前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >同时作为exe,dll,shellcode运行,自解密自解压

同时作为exe,dll,shellcode运行,自解密自解压

作者头像
franket
发布2022-06-29 16:52:43
6170
发布2022-06-29 16:52:43
举报
文章被收录于专栏:技术杂记
代码语言:javascript
复制
//----------------------源码如下---------------------------------------------------------

;2012.08.28
;可同时作为exe,dll,shellcode等同时运行.
;自解密,自解压

.386
.model flat,stdcall
option casemap:none

.code
include windows.inc

;运行方式
XROLE_DLL_PROCESS_DETACH        equ	0
XROLE_DLL_PROCESS_ATTACH        equ	1
XROLE_DLL_THREAD_ATTACH         equ	2
XROLE_DLL_THREAD_DETACH         equ	3
XROLE_EXE                       equ	4
XROLE_SYS                       equ	5
XROLE_SHELLCODE                 equ	6
XROLE_RELOAD                    equ	7
	
;压缩类型
XCOMPRESS_FLAG                  equ	2

;API的 Hash
ROLHASH_RtlDecompressBuffer              equ 07B8h
ROLHASH_RtlGetCompressionWorkSpaceSize   equ 0A80h
ROLHASH_VirtualAlloc                     equ	0467h
ROLHASH_VirtualProtect                   equ 04B5h


;内部变量,在没有寄存器可用的时候使用
XINFO struct
	pOldCode 	DWORD,0
	pNewCode	DWORD,0
	dwRole		DWORD,0
	hSelfModule DWORD,0
XINFO ends

;
W2DW MACRO w1,w2
	EXITM <w2 SHL 16 + w1>
endm
	
;入口点
EntryPoint PROC	
	_hNtdll                  equ [ebp - 04h]
	_hKernel32               equ [ebp - 08h]
	_dwRole                  equ [ebp - 0Ch]
	_pCurOEP                 equ [ebp - 14h]
	_pCurModule              equ [ebp - 18h]
	_bKey                    equ [ebp - 1Ch]
	
	_dwCodeLen                        equ [ebp - 20h]
	_dwCompressLen                    equ [ebp - 24h]
	_dwCompressBufferWorkSpaceSize    equ [ebp - 28h]
	_dwCompressFragmentWorkSpaceSize  equ [ebp - 2Ch]

	_dwProtect                        equ [ebp - 30h]
	
	_pVirtualAlloc                    equ [ebp - 40h]
	_pVirtualProtect                  equ [ebp - 44h]
	_pRtlDecompressBuffer             equ [ebp - 48h]
	_pRtlGetCompressionWorkSpaceSize  equ [ebp - 4Ch]

	push ebp
	mov ebp,esp

	push ebx
	push ecx
	push edx
	push esi
	push edi
	
	add esp,-100h
	
	;让eax指向ebp
	mov esi,esp
	add esi,114h
	mov esi,[esi]
	
	;dll和exe都是这里是OEP入口点
	push [esi + 8h]		
	pop _pCurOEP
	
	;得到Rol解密的密钥
_Config_Before:
	call _StartCode
_Config:
	;----------------------------------------------------
	BYTE	1		;rol解码密钥
	WORD 	5h		;原始代码的长度
	WORD	5h		;压缩之后代码的长度
	;----------------------------------------------------

_StartCode:
	pop edx
	;int 3
	;add edx,_Config - _Config_Before				;跳过最开始的短跳
	movzx eax,BYTE PTR [edx]
	mov _bKey,eax
	

	
	;原始字节长度
	mov ax,WORD PTR [edx + 1]
	mov _dwCodeLen,eax
	
	;压缩后的长度
	mov ax,WORD PTR [edx + 3]
	mov _dwCompressLen,eax
	
	;判断执行类型
	;dll时,第一个参数 和父的[esi + 0Ch]相等
	mov eax,[ebp + 08h]
	test eax,eax
	je _RoleExe
	
	cmp eax,[esi + 0Ch]		;父参数
	jne _RoleExe
	
_RoleDll:
	;当前角色
	push [ebp + 0Ch]
	pop _dwRole
	
	xor edi,edi
	inc edi
	cmp _dwRole,edi
	je _RoleDllProcessAttach
	
	;如果不是XROLE_DLL_PROCESS_ATTACH,就直接返回1
_DirectRet:
	xor eax,eax
	inc eax
	add esp,100h
	pop edi
	pop esi
	pop edx
	pop ecx
	pop ebx
	pop ebp
	ret 0Ch
		
_RoleDllProcessAttach:
	;修正返回地址
	mov eax,[ebp + 4]
	mov [ebp + 0Ch],eax
	jmp _Work
	
_RoleExe:
	;角色
	push XROLE_EXE
	pop _dwRole
	
_Work:
	lea edi,_pRtlGetCompressionWorkSpaceSize
	push edi					;API的存储地址,从这里开始往高地址存放


	
	;搜索Kernel32
	xor eax,eax
	xor ecx,ecx
	mov al,18h
	assume fs:nothing
	mov esi,fs:[eax]
	mov esi,[esi+30h]	;esi = TEB
	mov esi,[esi+0Ch]	;esi = PEB
	mov esi,[esi+1Ch]	;esi = PEB_LDR_DATA
	push esi
_LdrLoop:
	mov edi,[esi+08h]	;edi= InInitOrder[X].base_address
	mov edx,[esi+20h]	;edx = InInitOrder[X].module_name
	mov esi,[esi]
	cmp [edx+18h],cl
	jne _LdrLoop
	pop esi
	
	mov esi,[esi+08h]
	mov _hNtdll,esi
	mov _hKernel32,edi
	
	pop edi				;取出edi ->API的存储位置
	
	;在栈上面构建Hash表	
_Stack_Begin:	;栈开始点
	push W2DW(ROLHASH_VirtualProtect,ROLHASH_VirtualAlloc)
	push W2DW(ROLHASH_RtlGetCompressionWorkSpaceSize,ROLHASH_RtlDecompressBuffer)
	
	mov esi,esp	;esi 指向 HashTable -> 原始esp - 4

	xor ecx,ecx		;得到0
_FindSomeApi:
	xor edx,edx
	push ebp	;保存ebp
	xor eax,eax
	lodsw
	push ecx
	
	cmp ecx,2
	je _FindKernel32Api
	jb _FindNtdllApi
	
	cmp ecx,4
	jb _FindKernel32Api

	add esp,10h	;还有8字节是pop ecx		pop ebp
	;反IDA
	xor eax,eax
	je _FindAllApiFinish		;所有的API都找到了
	db 0E7h,0E8h,0E9h
_FindNtdllApi:
	push eax
	mov ebp,_hNtdll
	jmp _FindApi
_FindKernel32Api:
	push eax
	mov ebp,_hKernel32
	jmp _FindApi
_FindApi:
	;ebp -> hModule,
	mov ebx,[ebp+3Ch]			;ebx =PE
	mov ebx,[ebp + ebx + 78h]	;ebx = 输出表 RVA
	add ebx,ebp					;ebx = 输出表
	mov ecx,[ebx + 20h]			;ecx= names table RVA
	add ecx,ebp					;ecx = names table
	push esi					;保存esi
_WalkNameTable:					;遍历导出表
	inc edx
	mov esi,[ecx + edx * 4]		;esi =API字符串
	add esi,ebp
_CalcHash:
	push ecx
	xor ecx,ecx
	xor eax,eax
_HashLoop:
	lodsb
	test al,al
	je _HashEnd
	rol cl,1
	add ecx,eax
	jmp _HashLoop
_HashEnd:
	mov eax,ecx
	pop ecx
	cmp eax,[esp+4]
	jne _WalkNameTable
_WalkNameFinish:
	pop esi			;恢复esi = Hash Table	
	pop eax			;修复堆栈
_FindApiFinish:
	mov ecx,[ebx + 24h]				;ecx = ordinals table RVA
	add ecx,ebp						;ecx = ordinals table
	movzx edx,WORD PTR [ecx + 2*edx];edx = ordinal number of function
	mov ecx,[ebx+1Ch]				;ecx = address table RVA
	add ecx,ebp						;ecx = address table
	mov eax,ebp
	add eax,[ecx + 4*edx]			;eax = adi addr
	stosd							;保存API地址
	pop ecx							;取出ecx
	inc ecx		;API+1
	pop ebp
	jmp _FindSomeApi
_FindAllApiFinish:
	;OK.到这里的时候,所要用的API全部都找到了
	
	;申请xInfo内存
	xor ebx,ebx
	xor ecx,ecx
	mov bl,40h
	mov ch,10h
	
	push ecx			;保存edx和ecx
	push edx		
	
	push ebx			;40h
	push ecx			;1000h
	mov ax,sizeof XINFO
	push eax
	push edx			;0
	call DWORD PTR _pVirtualAlloc
	mov edi,eax			;edi = XINFO地址
	
	pop edx				;取出edx和ecx
	pop ecx

	assume edi:PTR XINFO

		;分配新的代码的内存
		xor eax,eax
		push ebx	;40h
		push ecx	;1000h
		mov ax,_dwCodeLen
		push eax
		push edx	;0
		call DWORD PTR _pVirtualAlloc
	
		mov [edi].pNewCode,eax		;解密之后的code的地址
		
		push _dwRole				;角色
		pop [edi].dwRole
		
		;Reload之前的模块基址
		push _pCurOEP
		pop eax
		sub eax,1000h
		mov [edi].hSelfModule,eax	
		
		;获取解密之前的地址
		call _GetCodeAddr
		mov esi,eax			;esi = code起始地址
		mov [edi].pOldCode,eax
		
		;修改负载为可读可写可执行
		lea eax,_dwProtect
		push eax
		push 40h
		push _dwCompressLen
		push [edi].pOldCode
		call DWORD PTR _pVirtualProtect
		
		;开始解密
		push edi

		;压缩之后的长度
		movzx edx,WORD PTR _dwCompressLen
		mov ecx,_bKey
		
		;目的地址,在原地解密
		mov edi,[edi].pOldCode
				
	_DecodeLoop:
		lodsb
		rol al,cl
		stosb
		dec edx
		test edx,edx
		jne _DecodeLoop
_DecodeFinish:	
		pop edi		;rol解密完毕,取出edi
		
		;恢复代码段页属性
		lea eax,_dwProtect
		push eax
		push _dwProtect
		push _dwCompressLen
		push [edi].pOldCode
		call DWORD PTR _pVirtualProtect
		
		
		;分配WorkSpace
		push _dwCodeLen
		pop _dwCompressBufferWorkSpaceSize
		
		push 0
		pop _dwCompressFragmentWorkSpaceSize
		
		lea eax,_dwCompressFragmentWorkSpaceSize
		push eax
		lea eax,_dwCompressBufferWorkSpaceSize
		push eax
		push XCOMPRESS_FLAG
		call DWORD PTR _pRtlGetCompressionWorkSpaceSize
		
		lea eax,_dwCompressFragmentWorkSpaceSize
		push eax
		push _dwCompressLen
		push [edi].pOldCode
		push _dwCodeLen
		push [edi].pNewCode
		push XCOMPRESS_FLAG
		call DWORD PTR _pRtlDecompressBuffer
				
	assume edi:nothing
	
	mov eax,edi
	assume eax:PTR XINFO
	
		;恢复所有使用过的寄存器
		add esp,100h
		pop edi
		pop esi
		pop edx
		pop ecx
		pop ebx

		pop ebp
		
		cmp [eax].dwRole

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档