└文章标题┐:ACPR2.0有趣发现 和 Stolen OEP修复
└破文作者┐:大菜一号
└破解对象┐:S-Recorder动画制作
└下载地址┐:附件
└对象大小┐:不知
└加壳方式┐:ACProtect V2.0 -> risco * Sign.By.fly *
└保护方式┐:ACProtect V2.0 -> risco * Sign.By.fly *
└编写语言┐:未知
└使用工具┐:od,REC,Lord PE
└破解平台┐:xp
└破解声明┐:`
----------------------------------------------------------------------------------
└破解过程┐:
此款壳,有压缩选项,反调试,反加载,oep抽取,RAS密钥等保护!
最近在玩一些个壳子,太难的就免了,因为介绍上写着这款壳“强度还不错”,所以我选了它,哈哈哈哈,这次不用hello world,因为似乎达不到此壳的最好保护效果,选中oep抽取选项加密,则运行出错!随便挑了一个程序,就用了S-Recorder这个动画制作软件!下面是将该软件加壳的选项截图
OD载入加壳程序!忽略所有异常,f9运行先,发现程序出现无法调试的异常,无法继续!用hide OD插件似乎没有什么用.碰碰运行,下断GetCurrentProcessId,f9运行,断下
7C809920 > 64:A1 18000000 mov eax, dword ptr fs:[18] <-断在这里
7C809926 8B40 20 mov eax, dword ptr [eax+20]
7C809929 C3 retn
用Lord PE找到OD的pID(进程标识),我这里找到的是73c,当然每次运行都不一样,则上面的代码,让其返回OD的pID,改为
7C809920 > B8 3C070000 mov eax, 73C
7C809925 90 nop
7C809926 90 nop
7C809927 90 nop
7C809928 90 nop
7C809929 C3 retn
假如 此时f9运行,程序已经没有无法继续的异常了!出现了此款壳未注册的nag对话框(我没注册这个壳) - -,这是一个好东西呀,后面再讲~
接下来可以下GetModuleHandle断点了,哈哈哈~f9运行,断下后.alt+m在代码节上下内存访问,f9运行,出现了壳未注册的nag对话框,证明壳已将执行完其自己身代码,点击确定!被内存断点拦下了
00411C54 ? A3 EC0F4300 mov dword ptr [430FEC], eax <-被断在这里,取消内存断点
00411C59 . E8 29010000 call 00411D87
00411C5E . 391D 90684200 cmp dword ptr [426890], ebx
00411C64 . 75 0C jnz short 00411C72
00411C66 . 68 841D4100 push 00411D84
00411C6B . FF15 7C934100 call dword ptr [41937C] ; msvcrt.__setusermatherr <-看来是个mfc程序
向上翻看:
00411BEE \. C3 retn
00411BEF 42 db 42 ; CHAR 'B' <-嘿嘿嘿嘿
00411BF0 82 db 82
00411BF1 28 db 28 ; CHAR '('
00411BF2 1C db 1C
00411BF3 E2 db E2
00411BF4 B8 db B8
00411BF5 A5 db A5
00411BF6 01 db 01
00411BF7 BB db BB
00411BF8 0C db 0C
00411BF9 DE db DE
00411BFA B9 db B9
00411BFB 97 db 97
00411BFC 9E db 9E
00411BFD 0D db 0D
00411BFE 09 db 09
00411BFF 21 db 21 ; CHAR '!'
00411C00 C1 db C1
00411C01 8A db 8A
00411C02 22 db 22 ; CHAR '"'
00411C03 32 db 32 ; CHAR '2'
00411C04 BD db BD
00411C05 8A db 8A
00411C06 EC db EC
00411C07 9D db 9D
00411C08 E8 db E8
00411C09 A8 db A8
00411C0A 80 db 80
00411C0B 00 db 00
00411C0C EA db EA
00411C0D F4 db F4
00411C0E 29 db 29 ; CHAR ')'
00411C0F 5A db 5A ; CHAR 'Z'
00411C10 05 db 05
00411C11 7C db 7C ; CHAR '|'
00411C12 A3 db A3
00411C13 95 db 95
00411C14 B8 db B8
00411C15 60 db 60 ; CHAR '`'
00411C16 57 db 57 ; CHAR 'W'
00411C17 27 db 27 ; CHAR '''
00411C18 39 db 39 ; CHAR '9'
00411C19 FD db FD
00411C1A B8 db B8
00411C1B 68 db 68 ; CHAR 'h'
00411C1C 63 db 63 ; CHAR 'c'
00411C1D C1 db C1
00411C1E 2E db 2E ; CHAR '.'
00411C1F 7C db 7C ; CHAR '|'
00411C20 3F db 3F ; CHAR '?'
00411C21 9D db 9D
00411C22 0F db 0F
00411C23 B0 db B0
00411C24 48 db 48 ; CHAR 'H'
00411C25 4F db 4F ; CHAR 'O'
00411C26 96 db 96
00411C27 C8 db C8
00411C28 E7 db E7
00411C29 D3 db D3
00411C2A F2 db F2
00411C2B A0 db A0
00411C2C . F7C4 C00B3083 test esp, 83300BC0
00411C32 . 92 xchg eax, edx
00411C33 . E7 CD out 0CD, eax
00411C35 . 60 pushad
00411C36 . 5F pop edi
00411C37 . C3 retn
00411C38 E3 db E3
00411C39 29 db 29 ; CHAR ')'
00411C3A F7 db F7
00411C3B 8D db 8D
00411C3C 1A db 1A
00411C3D C7 db C7
00411C3E DC db DC
00411C3F 2F db 2F ; CHAR '/'
00411C40 CF db CF
00411C41 E2 db E2
00411C42 . 0E push cs
00411C43 . 10E1 adc cl, ah
00411C45 . A9 B2D58A39 test eax, 398AD5B2
00411C4A . B8 E0263CC2 mov eax, C23C26E0
00411C4F . 67:C1C6 FE rol esi, 0FE
00411C53 . 22A3 EC0F4300 and ah, byte ptr [ebx+430FEC]
00411C59 . E8 29010000 call 00411D87
00411C5E . 391D 90684200 cmp dword ptr [426890], ebx
00411C64 . 75 0C jnz short 00411C72
00411C66 . 68 841D4100 push 00411D84
00411C6B . FF15 7C934100 call dword ptr [41937C] ; msvcrt.__setusermatherr
虽然这堆代码乱七八糟,不过可以确定的是,oep在00411bef,不管3121先dump出来再说,OD插件修改modify为11bef,dump出1.exe,当然此时程序无法运行。打开REC,选择这个带壳进程,oep为11bef,获得输入表信息,发现没有任何损坏指针,看来不用修复了!
修复被抽掉的oep
看语言特征,可以知道是mfc的程序,随手写一个标准的mfc程序,OD载入之,其入口代码和上面的代码对比
发现
00411C66 . 68 841D4100 push 00411D84
00411C6B . FF15 7C934100 call dword ptr [41937C] ; msvcrt.__setusermatherr
这两句以上的,都被抽掉了~一共是119字节
有人会问
00411C66 . 68 841D4100 push 00411D84,这句也不一样呀,这句是对下面那个call传参的,参数地址不是一定的~所以不用将其列在黑名单 -0-
好了,下面用od载入1.exe,把标准可用的mfc程序的前119个字节,在hex窗口中二进制粘贴过来~我找到的mfc程序的前119字节是下面这些:
00401C80 >55 8B EC 6A FF 68 B0 26 40 00 68 06 1E 40 00 64 U嬱jh?@.h@.d
00401C90 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 68 ?...Pd?....冹h
00401CA0 53 56 57 89 65 E8 33 DB 89 5D FC 6A 02 FF 15 B0 SVW塭?蹓]黬
00401CB0 21 40 00 59 83 0D 5C 31 40 00 FF 83 0D 60 31 40 !@.Y?\1@.?`1@
00401CC0 00 FF FF 15 AC 21 40 00 8B 0D 50 31 40 00 89 08 .?@.?P1@.?
00401CD0 FF 15 A8 21 40 00 8B 0D 4C 31 40 00 89 08 A1 A4 ?@.?L1@.?·
00401CE0 21 40 00 8B 00 A3 58 31 40 00 E8 16 01 00 00 39 !@.?1@.?..9
00401CF0 1D 70 30 40 00 75 0C p0@.u.
二进制粘贴进1.exe的前119字节处~得到下面的“可观”代码
00411BEF > 55 push ebp
00411BF0 8BEC mov ebp, esp
00411BF2 6A FF push -1
00411BF4 68 B0264000 push 004026B0
00411BF9 68 061E4000 push 00401E06
00411BFE 64:A1 0000000>mov eax, dword ptr fs:[0]
00411C04 50 push eax
00411C05 64:8925 00000>mov dword ptr fs:[0], esp
00411C0C 83EC 68 sub esp, 68
00411C0F 53 push ebx
00411C10 56 push esi
00411C11 57 push edi
00411C12 8965 E8 mov dword ptr [ebp-18], esp
00411C15 33DB xor ebx, ebx
00411C17 895D FC mov dword ptr [ebp-4], ebx
00411C1A 6A 02 push 2
00411C1C FF15 B0214000 call dword ptr [4021B0]
00411C22 59 pop ecx
00411C23 830D 5C314000>or dword ptr [40315C], FFFFFFFF
00411C2A 830D 60314000>or dword ptr [403160], FFFFFFFF
00411C31 FF15 AC214000 call dword ptr [4021AC]
00411C37 8B0D 50314000 mov ecx, dword ptr [403150]
00411C3D 8908 mov dword ptr [eax], ecx
00411C3F FF15 A8214000 call dword ptr [4021A8]
00411C45 8B0D 4C314000 mov ecx, dword ptr [40314C]
00411C4B 8908 mov dword ptr [eax], ecx
00411C4D A1 A4214000 mov eax, dword ptr [4021A4]
00411C52 8B00 mov eax, dword ptr [eax]
00411C54 A3 58314000 mov dword ptr [403158], eax
00411C59 E8 16010000 call 00411D74
00411C5E 391D 70304000 cmp dword ptr [403070], ebx
00411C64 75 0C jnz short 00411C72
00411C66 . 68 841D4100 push 00411D84
00411C6B . FF15 7C934100 call dword ptr [<&msvcrt.__setusermat>; msvcrt.__setusermatherr
先选中保存一下,此时的程序当然也是无法运行的,因为所粘贴的入口代码中有几个函数指针,地址和原程序是不对应的,况且不是启动函数相关,od都不能识别了!
要改的指针是
00411BEF > 55 push ebp
00411BF0 8BEC mov ebp, esp
00411BF2 6A FF push -1
00411BF4 68 B0264000 push 004026B0
00411BF9 68 061E4000 push 00401E06
00411BFE 64:A1 0000000>mov eax, dword ptr fs:[0]
00411C04 50 push eax
00411C05 64:8925 00000>mov dword ptr fs:[0], esp
00411C0C 83EC 68 sub esp, 68
00411C0F 53 push ebx
00411C10 56 push esi
00411C11 57 push edi
00411C12 8965 E8 mov dword ptr [ebp-18], esp
00411C15 33DB xor ebx, ebx
00411C17 895D FC mov dword ptr [ebp-4], ebx
00411C1A 6A 02 push 2
00411C1C FF15 B0214000 call dword ptr [4021B0] <-第一个
00411C22 59 pop ecx
00411C23 830D 5C314000>or dword ptr [40315C], FFFFFFFF
00411C2A 830D 60314000>or dword ptr [403160], FFFFFFFF
00411C31 FF15 AC214000 call dword ptr [4021AC] <-第二个
00411C37 8B0D 50314000 mov ecx, dword ptr [403150]
00411C3D 8908 mov dword ptr [eax], ecx
00411C3F FF15 A8214000 call dword ptr [4021A8] <-第三个
00411C45 8B0D 4C314000 mov ecx, dword ptr [40314C]
00411C4B 8908 mov dword ptr [eax], ecx
00411C4D A1 A4214000 mov eax, dword ptr [4021A4] <-第四个
00411C52 8B00 mov eax, dword ptr [eax]
00411C54 A3 58314000 mov dword ptr [403158], eax
00411C59 E8 16010000 call 00411D74 <-第五个
00411C5E 391D 70304000 cmp dword ptr [403070], ebx
00411C64 75 0C jnz short 00411C72
00411C66 . 68 841D4100 push 00411D84
00411C6B . FF15 7C934100 call dword ptr [<&msvcrt.__setusermat>; msvcrt.__setusermatherr
我们知道,函数都是调用系统模块的,所以,函数的绝对地址在系统加载模块后也是一个固定,不固定的话,我们也是可以完成修复!至少本次是固定,就够了~ - -
OD载入标准mfc程序,再载入上面所保存的1.exe
下面是标准mfc程序的一些入口代码:
00401C80 >/$ 55 push ebp
00401C81 |. 8BEC mov ebp, esp
00401C83 |. 6A FF push -1
00401C85 |. 68 B0264000 push 004026B0
00401C8A |. 68 061E4000 push <jmp.&MSVCRT._except_handler3> ; SE 处理程序安装
00401C8F |. 64:A1 0000000>mov eax, dword ptr fs:[0]
00401C95 |. 50 push eax
00401C96 |. 64:8925 00000>mov dword ptr fs:[0], esp
00401C9D |. 83EC 68 sub esp, 68
00401CA0 |. 53 push ebx
00401CA1 |. 56 push esi
00401CA2 |. 57 push edi
00401CA3 |. 8965 E8 mov dword ptr [ebp-18], esp
00401CA6 |. 33DB xor ebx, ebx
00401CA8 |. 895D FC mov dword ptr [ebp-4], ebx
00401CAB |. 6A 02 push 2
00401CAD |. FF15 B0214000 call dword ptr [<&MSVCRT.__set_app_ty>; msvcrt.__set_app_type
//这是我们要改的第一个,这是可用的mfc程序,则od会在后面注释识别函数("msvcrt.__set_app_type"),鼠标在上面点击一下,OD的信息窗口友好提示我们
ds:[004021B0]=77C0537C (msvcrt.__set_app_type) <-这个函数地址是77c0537c
windowTo.<模块入口点>+2D
这样就得到几个重要启动函数的地址了
00401CB3 |. 59 pop ecx
00401CB4 |. 830D 5C314000>or dword ptr [40315C], FFFFFFFF
00401CBB |. 830D 60314000>or dword ptr [403160], FFFFFFFF
00401CC2 |. FF15 AC214000 call dword ptr [<&MSVCRT.__p__fmode>] ; msvcrt.__p__fmode
//这个也是这样获得
00401CC8 |. 8B0D 50314000 mov ecx, dword ptr [403150]
00401CCE |. 8908 mov dword ptr [eax], ecx
00401CD0 |. FF15 A8214000 call dword ptr [<&MSVCRT.__p__commode>; msvcrt.__p__commode
//这个也是这样获得
00401CD6 |. 8B0D 4C314000 mov ecx, dword ptr [40314C]
00401CDC |. 8908 mov dword ptr [eax], ecx
00401CDE |. A1 A4214000 mov eax, dword ptr [<&MSVCRT._adjust>
//这个也是这样获得
00401CE3 |. 8B00 mov eax, dword ptr [eax]
00401CE5 |. A3 58314000 mov dword ptr [403158], eax
00401CEA |. E8 16010000 call 00401E05
//这个载入带壳程序,按照上述方法,执行这到,可获得为00411D87
00401CEF |. 391D 70304000 cmp dword ptr [403070], ebx
00401CF5 |. 75 0C jnz short 00401D03
00401CF7 |. 68 021E4000 push 00401E02
00401CFC |. FF15 A0214000 call dword ptr [<&MSVCRT.__setusermat>; msvcrt.__setusermatherr
下面是待修复的1.exe的入口代码,可以看到od都不能识别一些函数指针:
00411BEF >/$ 55 push ebp
00411BF0 |. 8BEC mov ebp, esp
00411BF2 |. 6A FF push -1
00411BF4 |. 68 B0264000 push 004026B0
00411BF9 |. 68 061E4000 push 00401E06 ; SE 处理程序安装
00411BFE |. 64:A1 0000000>mov eax, dword ptr fs:[0]
00411C04 |. 50 push eax
00411C05 |. 64:8925 00000>mov dword ptr fs:[0], esp
00411C0C |. 83EC 68 sub esp, 68
00411C0F |. 53 push ebx
00411C10 |. 56 push esi
00411C11 |. 57 push edi
00411C12 |. 8965 E8 mov dword ptr [ebp-18], esp
00411C15 |. 33DB xor ebx, ebx
00411C17 |. 895D FC mov dword ptr [ebp-4], ebx
00411C1A |. 6A 02 push 2
00411C1C |. FF15 B0214000 call dword ptr [4021B0]
//拿这个做例子,在上面获得对应函数地址是77c0537c,则,在OD的hex窗口中,先d一下41937c,找到IAT部份,再查找二进制字串7c 53 c0 77
我找到的是41938c,则上面的代码应该改为 call dword ptr[41938c],改了之后OD就能识别了
00411C22 |. 59 pop ecx
00411C23 |. 830D 5C314000>or dword ptr [40315C], FFFFFFFF
00411C2A |. 830D 60314000>or dword ptr [403160], FFFFFFFF
00411C31 |. FF15 AC214000 call dword ptr [4021AC]
//这个也是这样改
00411C37 |. 8B0D 50314000 mov ecx, dword ptr [403150]
00411C3D |. 8908 mov dword ptr [eax], ecx
00411C3F |. FF15 A8214000 call dword ptr [4021A8]
//这个也是这样改
00411C45 |. 8B0D 4C314000 mov ecx, dword ptr [40314C]
00411C4B |. 8908 mov dword ptr [eax], ecx
00411C4D |. A1 A4214000 mov eax, dword ptr [4021A4]
//这个也是这样改
00411C52 |. 8B00 mov eax, dword ptr [eax]
00411C54 |. A3 58314000 mov dword ptr [403158], eax
00411C59 E8 16010000 call 00411D74
//这个改为call 00411D87
00411C5E |. 391D 70304000 cmp dword ptr [403070], ebx
00411C64 |. 75 0C jnz short 00411C72
00411C66 |. 68 841D4100 push 00411D84
00411C6B |. FF15 7C934100 call dword ptr [<&msvcrt.__setusermat>; msvcrt.__setusermatherr
*******************************************
下面看一看这个壳的趣的问题
怎么个有趣法,嘿嘿,就在于它没有注册,加壳后会出现一个nag,而此nag代码位于壳中,执行到此nag,则壳已完成判断,证明此软件加的壳并没有注册~之后,将把主动权交还给原程序执行,可以通过这个来找oep,但是,上面我们看到的,oep被抽掉了,无法正确定位!所以,这个有趣的地方,也不能用在这里,就是加壳时选中“oep抽取”选项,此壳就不有趣了~哈哈哈哈~
再用加壳软件加一个S-Recorder.exe,记住,这里像不能选中"Oep抽取"选项,否则下文将是错误的!
加壳后,用Peid找到其oep,就是00411bef
OD载入加壳程序,f9运行,出现nag,壳就要把主动权交还给原程序了,此时的壳也没有抽掉oep,所以,ctrl+g到00411bef,看到oep完好无损,f2下断~点击nag中的确定,这样就到oep了~,再dump,当然,所有指针也是有效的,直接可以运行了~
还有更有趣的
其实我一开始是用hello world来接受加壳的,而且也没选中"oep抽取",因为hello world程序短小,oep上面就是MessageBox代码了~就像这样
00401000 /$ 6A 40 push 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00401002 |. 68 40604000 push 00406040 ; |Title = "Hello"
00401007 |. 68 30604000 push 00406030 ; |Text = "Hello world!"
0040100C |. 6A 00 push 0 ; |hOwner = NULL
0040100E |. FF15 9C504000 call dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA
00401014 |. 33C0 xor eax, eax
00401016 \. C2 1000 retn 10
00401019 90 nop
0040101A 90 nop
0040101B 90 nop
0040101C 90 nop
0040101D 90 nop
0040101E 90 nop
0040101F 90 nop
00401020 >/$ 55 push ebp
00401021 |. 8BEC mov ebp, esp
00401023 |. 6A FF push -1
00401025 |. 68 A8504000 push 004050A8
所以,f9运行,当壳到nag时,在od窗中已经出现上面的代码了~哈哈哈哈哈!MessageBox是hello world的精髓~
然后直接在00401020处f2下断,再点击nag的确定,就到oep了~
好了,本文也没有什么新的技术含量,就是这个有趣的地方,呵呵呵呵~
----------------------------------------------------------------------------------
└经验总结┐:
壳盲的经验还是不分享的好~
----------------------------------------------------------------------------------
└版权声明┐ 本文原创于看雪软件安全论坛, 转载请注明作者并保持文章的完整, 谢谢!
2007年9月23日 20:09
[课程]Android-CTF解题方法汇总!