脱壳-PECompact v1.66

    xiaoxiao2021-03-26  35

    前言

    在练习脱壳. 这个壳特点: * 在OEP处少代码, 需要自己在OEP处补齐. 少的代码在OEP之前都能看到. 这是所谓的偷代码. * 在OEP处脱壳后, ImpRec找不到IAT. 需要自己搜索指令来找到IAT项.

    记录

    查壳

    Detect It Easy => Borland Delphi(-)[-] PEID => 什么都没找到 * RDG => PECompact v1.66

    查找OEP

    用ESP定律

    004C3550 50 push eax 004C3551 68 30ED4800 push 0048ED30 004C3556 C2 0400 retn 4 0048ED30 55 push ebp 0048ED31 90 nop 0048ED32 8BEC mov ebp, esp 0048ED34 90 nop 0048ED35 B9 07000000 mov ecx, 7 0048ED3A 90 nop 0048ED3B 6A 00 push 0 0048ED3D 6A 00 push 0 0048ED3F 90 nop 0048ED40 90 nop 0048ED41 49 dec ecx 0048ED42 ^ E9 8EFCFFFF jmp 0048E9D5 0048E9C7 0000 add byte ptr [eax], al 0048E9C9 0000 add byte ptr [eax], al 0048E9CB 0000 add byte ptr [eax], al 0048E9CD 0000 add byte ptr [eax], al 0048E9CF 006A 00 add byte ptr [edx], ch 0048E9D2 6A 00 push 0 0048E9D4 49 dec ecx 0048E9D5 ^ 75 F9 jnz short 0048E9D0 ; 跳到这里来了, 如果这里作为OEP要将前面的代码补上

    输入新OEP代码

    Address Size Owner Section Contains Type Access Initial Mapped as 00400000 00001000 NfoViewe PE header Imag R RWE 00401000 000A2000 NfoViewe XtreaM code Imag R RWE 004A3000 00023000 NfoViewe .rsrc SFX,data,res Imag R RWE 004C6000 00001000 NfoViewe .rsrc imports Imag R RWE 0048xxxx在代码段(XtreaM) 004Cxxxx在其他段(.rsrc) 必须将004C3550开始的3句话搬到代码段 如果从0048E9C7作为OEP, 正好留了8个字节. 看看将前面欠的语句搬过来, 是否8个字节是否能放下. 试过了,放不下. 0048E9D5下面也放着代码没空隙. 0048ED30~0048ED42中间还空着5个字节. 004C3550 主要语句就是push eax, 那就将 004C3550的push eax搬到0048ED30.重新组织一下, 将多余的nop去掉, 空间就够了 重新运行程序, 当运行到0048ED30时, 直接将旧代码抹掉, 键入新代码, 然后脱壳. 将 0048ED30 作为OEP, 将0048ED30~0048ED42填充为NOP, 再输入下面的新代码 0048ED30 新的代码为: push eax push ebp mov ebp, esp mov ecx, 7 push 0 push 0 dec ecx jmp 0048E9D5 新代码码好了 0048ED30 50 push eax ; 0048ed30 new OEP 0048ED31 55 push ebp 0048ED32 8BEC mov ebp, esp 0048ED34 B9 07000000 mov ecx, 7 0048ED39 6A 00 push 0 0048ED3B 6A 00 push 0 0048ED3D 49 dec ecx 0048ED3E ^ E9 92FCFFFF jmp 0048E9D5 0048ED43 90 nop 0048ED44 90 nop 0048ED45 90 nop 0048ED46 90 nop ; 原来的语句结尾, 可以看出空间足够.

    脱壳

    在0048ED30处, 用ollyDump脱2个版本(不勾选RebuildImport, 勾选RebuildImport) 直接运行脱壳后的2个版本,都是报错的.

    修复IAT

    ImpREC , 输入OEP = 0008ED30, Click “AutoSearch”.

    --------------------------- Found something! --------------------------- Found address which may be in the Original IAT. Try 'Get Import'. (If it is not correct, try RVA: 00001000 Size:000A2000) --------------------------- 确定 ---------------------------

    RVA = 00092018 SIZE = 00000004 去看一下IAT. =>00492018, 都是0, 说明ImpREC没找到IAT.

    手工查找IAT

    调用API时, 一般都是 call xx

    00402BF0 E8 17E6FFFF call 0040120C ; jmp to kernel32.CloseHandle

    调用到的API处再跳到IAT表项内容

    0040120C - FF25 0C324900 jmp dword ptr [49320C] ; kernel32.CloseHandle

    代码段为00401000开始 从00401000开始, 2进制字符串搜索 FF25 搜到了IAT项

    004011F9 . 54 49 6E 74 6>ascii "TInterfacedObjec" 00401209 . 74 ascii "t" 0040120A 8BC0 mov eax, eax 0040120C $- FF25 0C324900 jmp dword ptr [49320C] ; kernel32.CloseHandle 00401212 8BC0 mov eax, eax 00401214 $- FF25 08324900 jmp dword ptr [493208] ; kernel32.CreateFileA 0040121A 8BC0 mov eax, eax 0040121C $- FF25 04324900 jmp dword ptr [493204] ; kernel32.GetFileType 00401388 $- FF25 84314900 jmp dword ptr [493184] ; kernel32.LocalAlloc 0040138E 8BC0 mov eax, eax 00401390 $- FF25 80314900 jmp dword ptr [493180] ; kernel32.LocalFree 00401396 8BC0 mov eax, eax 00401398 $- FF25 7C314900 jmp dword ptr [49317C] ; kernel32.VirtualAlloc 0040139E 8BC0 mov eax, eax 004013A0 $- FF25 78314900 jmp dword ptr [493178] ; kernel32.VirtualFree 004013A6 8BC0 mov eax, eax 004013A8 $- FF25 74314900 jmp dword ptr [493174] ; kernel32.InitializeCriticalSection 004013AE 8BC0 mov eax, eax 004013B0 $- FF25 70314900 jmp dword ptr [493170] ; ntdll.RtlEnterCriticalSection 004013B6 8BC0 mov eax, eax 004013B8 $- FF25 6C314900 jmp dword ptr [49316C] ; ntdll.RtlLeaveCriticalSection 004013BE 8BC0 mov eax, eax 004013C0 $- FF25 68314900 jmp dword ptr [493168] ; ntdll.RtlDeleteCriticalSection 004036BC $- FF25 14324900 jmp dword ptr [493214] ; user32.GetKeyboardType 00481C74 $- FF25 50384900 jmp dword ptr [493850] ; UpdSyste.ShowUpdateDialog

    用插件”Analyze This”分析一下.连续搜索FF25(CTRL+L), 看到最后一个CAll地址为004036BC

    统计IAT范围

    第一个Call为 jmp dword ptr [49320C], IAT地址49320C 最后一个Call为 jmp dword ptr [493850], IAT地址为493850 查看IAT地址, 已经找到正确的IAT了

    0049320C 7C809BD7 kernel32.CloseHandle 00493210 00000000 00493214 77D311DB user32.GetKeyboardType 00493218 77D2C908 user32.LoadStringA 0049321C 77D507EA user32.MessageBoxA 00493220 77D2C8B0 user32.CharNextA 00493224 00000000 00493228 77DA7AAB advapi32.RegQueryValueExA 0049322C 77DA7842 advapi32.RegOpenKeyExA 00493230 77DA6C17 advapi32.RegCloseKey 00493234 00000000 00493238 770F4880 oleaut32.SysFreeString 0049323C 770FA3EC oleaut32.SysReAllocStringLen

    向ImpREC填入IAT搜索参数 OEP = 0008ED30 IAT RVA = 0009320C // IAT开始地址为0049320C IAT SIZE = 00000644 // 493850 - 49320C click “Get Imports”

    得到的IAT列表正确

    IAT修复

    点击”Fix Dump”, 对ollyDump脱壳出的2个版本进行IAT修复.

    测试

    测试时, 2个程序都报错:应用初始化失败

    --------------------------- od_dump1_.exe - 应用程序错误 --------------------------- 应用程序正常初始化(0xc000007b)失败。请单击“确定”,终止应用程序。 --------------------------- 确定 ---------------------------

    重建PE

    对ImpRec修复过的2个版本, 用LordPE重建PE, 设置导入表修复选项.

    经过PE重建后, 2个版本中有一个正常运行了. 这个版本是用OllyDump不带引入表重建的版本.

    备注

    算IAT size时, 弄小了, 前面还有一些(取到一个IAT后, 在Memory窗口前后翻一下, 确定一下RVA和size, 范围弄大点都没关系, 可以在ImpREC中将无效的IAT剪掉). 调整IAT Info RVA and Size后, ImpREC fix. 运行修复完的版本,确实2个都不能运行. 但是经过PETools重建PE后, 2个都可以正常运行了. 不像IAT Info RVA and Size弄小时, PE重建后, 只有一个版本能正常运行.

    转载请注明原文地址: https://ju.6miu.com/read-650130.html

    最新回复(0)