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