小菜鸟还原VM的OEP笔记。有不对的地方请大牛斧正
本帖最后由 珈蓝夜雨 于 2012-8-15 13:39 编辑大家好,我是珈蓝夜雨
看了一蓑烟雨T牛(T牛的全名忘了……安啦,T牛人很好他不会计较这些的)的教程,然后根据自己的理解来弄的,做一个笔记留念。可能有的地方有错误和不严谨的地方,请大牛斧正
我将一个CM加了VMP的壳,然后用插件扒壳,扒壳后的程序此时是无法运行的
现在来还原OEP
首先找到一个和要还原的程序的编译语言是一样的版本的程序
我这个是CM是易语言的
首先先将我们找到的易语言的无壳程序的OEP用二进制字符复制下来,粘贴在脱壳程序的
入口处
下面红色的字体是我们要找到修改的地方。蓝色的字体是修改的值。绿色的字体是我对如何查找到修改值的一些注释
0045518D >/$55 push ebp
0045518E|.8BEC mov ebp,esp
00455190|.6A FF push -0x1
00455192|.68 E8CE4700 push DNF.0047CEE8 Push 0046E538
来到加壳程序的OEP处,将堆栈处的滚动条往下拉到最后,往上找。注意当找到的值一定要将最下面的值填到代码的前面一句,压入堆栈的值是先将前面值压入,后压入后面的值,所以前面先压入的值就在下面
00455197|.68 EC994500 push DNF.004599EC push 0044C46C
0045519C|.64:A1 0000000>mov eax,dword ptr fs:
004551A2|.50 push eax
004551A3|.64:8925 00000>mov dword ptr fs:,esp
004551AA|.83EC 58 sub esp,0x58
004551AD|.53 push ebx
004551AE|.56 push esi
004551AF|.57 push edi ;ntdll.7C930228
004551B0|.8965 E8 mov ,esp
004551B3|.FF15 58424700 call dword ptr ds:[<&KERNEL32.GetVersion>;kernel32.GetVersion CALLGetVersion
因为这里是直接CALL的函数,所以直接将他改为CALL同样的函数
004551B9|.33D2 xor edx,edx ;ntdll.KiFastSystemCallRet
004551BB|.8AD4 mov dl,ah
004551BD|.8915 48034B00 mov dword ptr ds:,edx ;
mov dword ptr ds:,edx
将加壳程序运行起来后,搜索二进制,记录地址
28 0A 00 00 01 05 00 00 05 00 00 00 01 00 00 00
数据的由来:
将无壳程序运行到下面的CALL处,也就是下文的004551E6处,然后在第一个MOV的那
句代码处选择数据框跟随内存地址,然后往上找三句(因为一共压入了四个地址),然后将
其二进制复制下来。其二进制的数据就是前面28 0A……什么的
下面是找到的数据,依次从下往上填写
数据:
00494DB400000A28
00494DB800000501
00494DBC00000005
00494DC000000001
004551C3|.8BC8 mov ecx,eax
004551C5|.81E1 FF000000 and ecx,0xFF
004551CB|.890D 44034B00 mov dword ptr ds:,ecx
mov dword ptr ds:,edx
004551D1|.C1E1 08 shl ecx,0x8
004551D4|.03CA add ecx,edx ;ntdll.KiFastSystemCallRet
004551D6|.890D 40034B00 mov dword ptr ds:,ecx
mov dword ptr ds:,edx
004551DC|.C1E8 10 shr eax,0x10
004551DF|.A3 3C034B00 mov dword ptr ds:,eax
mov dword ptr ds:,edx
004551E4|.6A 01 push 0x1
004551E6|.E8 9A470000 call DNF.00459985CALL 0044C405
在加壳程序中搜索
33 C0 6A 00 39 44 24 08 68 00 10 00 00 0F 94 C0 50
将找的地址修改在脱壳程序上
数据的由来:
在无壳程序里面进入这个对应的CALL,然后将前面的代码的二进制复制下来。复制的时候注意要将程序可能变动的数值的二进制用??代替。下面的CALL大多都是这样。后面就不提了
004551EB|.59 pop ecx ;kernel32.7C817077
004551EC|.85C0 test eax,eax
004551EE|.75 08 jnz short DNF.004551F8
004551F0|.6A 1C push 0x1C
004551F2|.E8 C3000000 call DNF.004552BAcall 00447D6A
在加壳程序中搜索
83 3D ?? ?? ?? ?? 01 75 05 E8 ?? ?? ?? ?? FF 74 24 04 E8 ?? ?? ?? ?? 59 68 FF 00 00
004551F7|.59 pop ecx ;kernel32.7C817077
004551F8|>E8 45450000 call DNF.00459742call 0044C1C2
在加壳程序中跟随表达式TlsAlloc下硬件断点,运行后返回,记录段首的值
这个CALL进去后会调用TlsAlloc这个函数,所以直接在这个函数下硬件断点,等程序停下后返回,然后将段首记录
004551FD|.85C0 test eax,eax
004551FF|.75 08 jnz short DNF.00455209
00455201|.6A 10 push 0x10
00455203|.E8 B2000000 call DNF.004552BAcall 00447D6A
这个和前面004551F2处的CALL一样,所以直接call 00447D6A
00455208|.59 pop ecx ;kernel32.7C817077
00455209|>33F6 xor esi,esi
0045520B|.8975 FC mov ,esi
0045520E|.E8 73430000 call DNF.00459586 CALL 0044C006
在加壳程序中搜索 55 8B EC 83 EC 48 53 56 57 68 80 04 00 00
记录地址
00455213|.FF15 70434700 call dword ptr ds:[<&KERNEL32.GetCommand>; [GetCommandLineA
直接修改为call GetCommandLineA
00455219|.A3 441A4B00 mov dword ptr ds:,eax
mov dword ptr ds:,eax
将加壳程序运行起来,搜索二进制
9? 23 16 00 ,记录下地址
0045521E|.E8 31420000 call DNF.00459454 call 0044BED4
加壳程序二进制搜索
51 51 A1 ?? ?? ?? ?? 53 55
00455223|.A3 08034B00 mov dword ptr ds:,eax
mov dword ptr ds:,eax
搜索call 0044BBCE(也就是下面的 第二个call)的二进制,来到这个CALL里面,找里面调用的地址,哪个调用次数最多,就记录下来
00455228|.E8 DA3F0000 call DNF.00459207CALL 0044BC87
加壳程序二进制搜索 55 8B EC 51 51 53 33 DB 39 1D ?? ?? ?? ?? 56 57
0045522D|.E8 1C3F0000 call DNF.0045914E call 0044BBCE
加壳程序搜索二进制53 33 DB 39 1D ?? ?? ?? ?? 56 57 75 05 E8 ?? ?? ?? ?? 8B 35 ?? ?? ?? ?? 33 FF
00455232|.E8 44300000 call DNF.0045827B call 0044ACFB
加壳程序搜索二进制A1 ?? ?? ?? ?? 85 C0 74 02 FF D0 68 ?? ?? ?? ?? 68 ?? ?? ?? ?? E8 ?? ?? ?? ?? 68 ?? ?? ?? ?? 68 ?? ?? ?? ?? E8 ?? ?? ?? ?? 83 C4 10
00455237|.8975 D0 mov ,esi
0045523A|.8D45 A4 lea eax,
0045523D|.50 push eax ; /pStartupinfo = NULL
0045523E|.FF15 FC414700 call dword ptr ds:[<&KERNEL32.GetStartup>; \GetStartupInfoA
直接修改为call GetStartupInfoA
00455244|.E8 AD3E0000 call DNF.004590F6 call 0044BB76
加壳程序搜素二进制83 3D ?? ?? ?? ?? 00 75 05 E8 ?? ?? ?? ?? 56 8B 35 ?? ?? ?? ?? 8A 06 3C 22 75 25
00455249|.8945 9C mov ,eax
0045524C|.F645 D0 01 test byte ptr ss:,0x1
00455250|.74 06 je short DNF.00455258
00455252|.0FB745 D4 movzx eax,word ptr ss:
00455256|.EB 03 jmp short DNF.0045525B
00455258|>6A 0A push 0xA
0045525A|.58 pop eax ;kernel32.7C817077
0045525B|>50 push eax
0045525C|.FF75 9C push
0045525F|.56 push esi
00455260|.56 push esi ; /pModule = FFFFFFFF ???
00455261|.FF15 60434700 call dword ptr ds:[<&KERNEL32.GetModuleH>; \GetModuleHandleA
直接修改为call GetModuleHandleA
00455267|.50 push eax
00455268|.E8 01DC0000 call DNF.00462E6E call 004558EE
加壳程序搜索二进制FF 74 24 10 FF 74 24 10 FF 74 24 10 FF 74 24 10 E8 ?? ?? ?? ??
0045526D|.8945 A0 mov ,eax
00455270|.50 push eax
00455271|.E8 32300000 call DNF.004582A8 call 0044AD28
二进制搜索二进制6A 00 6A 00 FF 74 24 0C E8 ?? ?? ?? ?? 83 C4 0C
00455276|.8B45 EC mov eax,
00455279|.8B08 mov ecx,dword ptr ds:
0045527B|.8B09 mov ecx,dword ptr ds: ;ntdll.7C92DCBA
0045527D|.894D 98 mov ,ecx
00455280|.50 push eax
00455281|.51 push ecx
00455282|.E8 F73C0000 call DNF.00458F7E call 0044B9FE
加壳程序二进制搜索 55 8B EC 51 53 56 E8 ?? ?? ?? ?? 8B F0 FF 76 50 FF 75 08
00455287|.59 pop ecx ;kernel32.7C817077
00455288|.59 pop ecx ;kernel32.7C817077
00455289\.C3 retn
还原结束
OEp的值是固定的
一般只需要修改几点Push Call的值与加载Api函数即可
支持将自己的分析所得与坛友分享交流 太深奥了。。。。。 貌似LZ不是小菜把。。 学习了 虽然还没开始接触VM
但是在各位前辈的帖子中已经了解了不少{:1_908:} 会还原OEP的都是大牛{:1_931:}T牛难道是Tortoiser大牛,正在看他的视频呢 鼎起来,晕晕的 支持一下。
页:
[1]
2