NoobyProtect SE Demo 1.6.1.0 IAT加密初探
本帖最后由 yangjt 于 2009-8-15 12:15 编辑【文章标题】: NoobyProtect SE Demo 1.6.1.0 IAT加密初探
【文章作者】: yangjt
【作者邮箱】: yangjietao123@163.com
【作者QQ号】: 325002492
【下载地址】: 附件里
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
非常感谢这两天帮助过我的所有人……特别感谢下Nooby指点,还有HyperChem和Hmily的帮助
首先载入壳,Demo版可以来到VirtualProtect在那里的
E8 75FFFFFF call VirtualProtectEx处下断点,然后看堆栈,当堆栈变成这样的时候
0012FF48 FFFFFFFF|hProcess = FFFFFFFF
0012FF4C 00401000|Address = 复件_未?00401000
0012FF50 00004000|Size = 4000 (16384.)
0012FF54 00000040|NewProtect = PAGE_EXECUTE_READWRITE
0012FF58 0012FF84\pOldProtect = 0012FF84
再按一遍F9,这个时候代码段就已经解码了。然后取消断点,来到00401000段……因为我们的目的只是分析IAT,所以找到入口对我们来说并没有太多的作用,Ctrl+B搜索E8 ?? ?? 0A 00搜索不到就更改0A的值,增加或减少,对于这个程序是这个
可以来到这个地方:
004010C7 000D 0A00002A add byte ptr , cl
004010CD 8BEC mov ebp, esp
004010CF 83EC 44 sub esp, 44
004010D2 56 push esi
004010D3 E8 E3BE0A00 call 004ACFBB;这就是被加密的API调用,可以搜索到这里,直接Enter进入
004010D8^ 7D 8B jge short 00401065
004010DA F0:8A00 lock mov al, byte ptr [eax]
004010DD 3C 22 cmp al, 22
004010DF 75 1B jnz short 004010FC
004010E1 56 push esi
004010E2 E8 D6AF0A00 call 004AC0BD
;call来自004010D3:
004ACFBB 90 nop;直接在这里下断点,运行断下
004ACFBC 68 A448416D push 6D4148A4 ;IAT索引?后面用来储存所调用的API需要的地址
004ACFC1 9C pushfd
004ACFC2 814424 04 341DA>add dword ptr [esp+4], 74AB1D34 ;修改IAT索引为E1EC65D8
004ACEBA 60 pushad
004AC71C E8 00000000 call 004AC721
004AC721 58 pop eax
004AC722 81E8 79C386D7 sub eax, D786C379 ;貌似是GetModuleHandleA的定位
004AC644 ?E8 0D000000 call 004AC656
004AC649 .6B 65 72 6E 6>ascii "kernel32.dll",0
004AC656 FF90 CD8286D7 call dword ptr [eax+D78682CD] ; kernel32.GetModuleHandleA
004AC362 85C0 test eax, eax ; kernel32.7C800000
004AC364^ 0F84 0CFDFFFF je 004AC076 ;不成功?就得到自己的句柄……Nooby说是为了支持插件
004AC01A E8 10000000 call 004AC02F
004AC01F .47 65 74 43 6>ascii "GetCommandLineA",0 ;其实这里已经看到API的名字了……
004ABFF8 50 push eax ;下面的一坨代码是用来模拟GetProcAddress的…
004AC055 E8 B089F6FF call 00414A0A
00414A0A E8 F7A90600 call 0047F406
0047F406 50 push eax
0047F40C 9C pushfd
0047D183 E8 00000000 call 0047D188
0047D188 E9 902A0000 jmp 0047FC1D
0047FC1D 58 pop eax
0047FC8B 81E8 81A56389 sub eax, 8963A581
0047FC91 81C0 5AC66389 add eax, 8963C65A ;定位SEH异常处理流程
0047FC97 874424 04 xchg dword ptr [esp+4], eax ;充当SEH handler
0047FC9B 9D popfd
0047FC9C 64:FF35 0000000>push dword ptr fs:
0047FC25 64:8925 0000000>mov dword ptr fs:, esp ;建立异常处理
0047D161 CC int3 ;邪恶的CC 9D
0047D162 9D popfd ;Nooby说这里本来是用于猥琐OD的一个Bug,后来因为StrongOD,OD都不吃这套了
;异常类型,STATUS_BREAKPOINT
;到异常处理流程里看看去
0047F261 60 pushad;这里下int3断点
0047F262 8B45 08 mov eax, dword ptr [ebp+8] ;pEXCEPTION_RECORD
0047F265 EB 5F jmp short 0047F2C6 ;= =SEH处理过程也被猥琐了……
0047F2C6 8B4D 10 mov ecx, dword ptr [ebp+10] ;ecx:pContext
0047F270 8B00 mov eax, dword ptr [eax] ;eax = dwExceptionCode
0047F2D2 8061 18 F0 and byte ptr [ecx+18], 0F0 ;iDr7清零
0047F27B 80E8 03 sub al, 3
0047F2FC^\70 FA jo short 0047F2F8 ;这样可以用来判断异常类型,不是不处理,交给上一层SEH
0047F33F 8B99 C1000000 mov ebx, dword ptr [ecx+C1] ;ebx=Eflag+1
0047F450 80E3 01 and bl, 1 ;TF标志判断
0047F34A 3AC3 cmp al, bl ;猥琐单步用
0047F429^\0F85 C9FEFFFF jnz 0047F2F8 ;做个标记了……免得下次再走进去……
0047F3B8 8381 B8000000 0>add dword ptr [ecx+B8], 0D ;计算返回位置,加13个字节
0047F3BF 8B81 B8000000 mov eax, dword ptr [ecx+B8] ;返回点 = 0047D16E
0047F3C5 0FB600 movzx eax, byte ptr [eax] ;返回点的第一个字节
0047F3C8 81C0 9F109961 add eax, 6199109F
0047F391 81F8 6B119961 cmp eax, 6199116B ;判断是否是CC……跳转Demo里没有……
0047F3F0 61 popad
0047F3F1 C7C0 00000000 mov eax, 0 ;EXCEPTION_CONTINUE_EXECTION
0047F337 C2 1000 retn 10 ;安全返回……
;从0047F2FC跳出来的分支
;死亡谷……
0047F2F8 61 popad
0047F331 C7C0 FFFFFFFF mov eax, -1 ;EXCEPTION_CONTINUE_SEARCH
0047F337 C2 1000 retn 10
;返回后:
0047D16E /E9 5F220000 jmp 0047F3D2
0047F3D2 64:8F05 0000000>pop dword ptr fs: ; 解除异常处理,其实可以跑到这个地方下Int3 断点,这样不会被SEH里的检测猥琐
0047F3FC 8D6424 08 lea esp, dword ptr [esp+8] ;平衡堆栈
0047F45A 55 push ebp
0047F4FE 8BEC mov ebp, esp
0047F500 81EC 0C010000 sub esp, 10C
0047F506 53 push ebx
0047F507 8B5D 08 mov ebx, dword ptr [ebp+8] ;dll image base
0047F50A 85DB test ebx, ebx
0047F50C 56 push esi ;什么玩艺?
0047F4E1 57 push edi
0047F515 /74 1D je short 0047F534 ;不太可能出问题吧……
0047F738 8BCB mov ecx, ebx ;这里的代码猥琐程度终于降低了
0047F73A 33FF xor edi, edi
0047F73C E8 F2D2FCFF call 0044CA33;这里算是比较远的Call,跟进……
0047F741 8B48 7C mov ecx, dword ptr [eax+7C]
0047F744 8B70 78 mov esi, dword ptr [eax+78]
0047F747 03F3 add esi, ebx
0047F749 85C9 test ecx, ecx
;call 来自0047F73C:
0044CA33 50 push eax ; kernel32.7C800000
0044CA36 9C pushfd
00449DE3 E8 00000000 call 00449DE8
00449DE8 E9 BD2C0000 jmp 0044CAAA
0044CAAA 58 pop eax ; 复件_未?00449DE8
0044CAAB 81E8 6C21BA96 sub eax, 96BA216C
0044CAB1 81C0 C24CBA96 add eax, 96BA4CC2
0044CAB7 874424 04 xchg dword ptr [esp+4], eax
0044CABB 9D popfd
0044CABC 64:FF35 0000000>push dword ptr fs:
0044CB07 64:8925 0000000>mov dword ptr fs:, esp
00449C38 CC int3 ;这个壳考验的是人的耐心……
00449C39 9D popfd
;SEH
0044C93E 60 pushad
0044C9B8 8B45 08 mov eax, dword ptr [ebp+8]
0044C9BB 8B4D 10 mov ecx, dword ptr [ebp+10]
0044C9BE 8B00 mov eax, dword ptr [eax]
0044C9C0 8061 18 F0 and byte ptr [ecx+18], 0F0
0044C9C4 80E8 03 sub al, 3
0044C9C7^ 0F80 78FFFFFF jo 0044C945
;下面代码同上一个SEH……代码核心完全一样……只是猥琐程度不同……懒得分析了……
;返回
00449C3D /E9 BA2D0000 jmp 0044C9FC
0044CA56 64:8F05 0000000>pop dword ptr fs:
0044CA26 8D6424 04 lea esp, dword ptr [esp+4]
00413BC4 E8 3A1A0600 call 00475603
00413BC9 1ACA sbb cl, dl
00413BCB 53 push ebx
00413BCC C3 retn
;call来自00413BC4
;……接下来省略一些猥琐代码……= =还是老一套……
;返回到
00475062 /E9 2E050000 jmp 00475595
00475549 66:8139 4D5A cmp word ptr [ecx], 5A4D;终于到了激动人心的时刻……
004755B8^\74 B0 je short 0047556A ;是PE文件?
0047556A 8B41 3C mov eax, dword ptr [ecx+3C];e_lfanew
004755CD 03C1 add eax, ecx ;定位Signature PE
0047F741 8B48 7C mov ecx, dword ptr [eax+7C];size of Export Directory
0047F744 8B70 78 mov esi, dword ptr [eax+78];RVA of Export Directory
0047F747 03F3 add esi, ebx;VA of Export Directory
0047F749 85C9 test ecx, ecx;有导出表吗?
0047F6F2 894D F8 mov dword ptr [ebp-8], ecx;输出表大小保存
0047F6F5^\0F84 39FEFFFF je 0047F534;没有还扯什么……
0047F6FB 3BF3 cmp esi, ebx
0047F6BD^\0F86 71FEFFFF jbe 0047F534;导出表怎么会在PE头前面?
0047F713 8B55 0C mov edx, dword ptr [ebp+C];哪个API?EDX=API名称
0047F6CD 81FA 00000100 cmp edx, 10000;?
0047F762^\73 B4 jnb short 0047F718;堆栈怎么会用那么多?
0047F718 8B46 20 mov eax, dword ptr [esi+20];定位export name table
0047F7E0 8A0A mov cl, byte ptr [edx]
0047F84D 03C3 add eax, ebx;VA of export name table
0047F84F 80F9 40 cmp cl, 40;大于等于'@'?
0047F852 8945 FC mov dword ptr [ebp-4], eax
0047F855^ 7E 8E jle short 0047F7E5
0047F857 80F9 53 cmp cl, 53;大于等于'S'?
0047F85A^ 7E D1 jle short 0047F82D
0047F82D 217D 08 and dword ptr [ebp+8], edi;清零?
0047F880 397E 18 cmp dword ptr [esi+18], edi;NumberOfNames
0047F883^ 0F86 E6FEFFFF jbe 0047F76F;不能是是负数或者0
0047F860 8B4D 08 mov ecx, dword ptr [ebp+8];ecx=计数器
0047F958 8B0488 mov eax, dword ptr [eax+ecx*4]
0047F894 03C3 add eax, ebx;第N个export name
0047F896 E8 80D3FCFF call 0044CC1B;不是这个函数吗?
0047F89B 85C0 test eax, eax;返回1继续,返回0找到
0047F8B8 /74 1E je short 0047F8D8;是
0047F8BA |EB 6D jmp short 0047F929;下一个
0047F929 FF45 08 inc dword ptr [ebp+8]
0047F8FF 8B45 08 mov eax, dword ptr [ebp+8]
0047F938 3B46 18 cmp eax, dword ptr [esi+18]
0047F906^\72 83 jb short 0047F88B
0047F88B 8B55 0C mov edx, dword ptr [ebp+C]
0047F88E 8B45 FC mov eax, dword ptr [ebp-4]
0047F860 8B4D 08 mov ecx, dword ptr [ebp+8]
0047F958 8B0488 mov eax, dword ptr [eax+ecx*4]
0047F894 03C3 add eax, ebx
0047F896 E8 80D3FCFF call 0044CC1B
0047F89B 85C0 test eax, eax
;找到所需API的时候
0047F8D8 8B46 24 mov eax, dword ptr [esi+24];AddressOfNameOrdinals
0047F90B 8B4D 08 mov ecx, dword ptr [ebp+8]
0047F8E1 8D0448 lea eax, dword ptr [eax+ecx*2]
0047F9B7 0FB70418 movzx eax, word ptr [eax+ebx]
0047FB1F 8B4E 1C mov ecx, dword ptr [esi+1C];AddressOfFunctions
0047FB22 8D0481 lea eax, dword ptr [ecx+eax*4]
0047F7B6 8B3C18 mov edi, dword ptr [eax+ebx];RAV of func
0047FAA0 03FB add edi, ebx;VA
0047F76F 3BFE cmp edi, esi;这里的EDI就是需要的API ; kernel32.7C80262C
0047FAC9^\72 AF jb short 0047FA7A
0047FACB 8B45 F8 mov eax, dword ptr [ebp-8]
0047FACE 03F0 add esi, eax
0047FAD0 3BFE cmp edi, esi
0047FAD2^ 73 A6 jnb short 0047FA7A
0047FA7A 8BC7 mov eax, edi ; kernel32.GetCommandLineA
0047FC47 E8 51D7FCFF call 0044D39D;后面省略N多猥琐代码
0044D059 /E9 6C030000 jmp 0044D3CA
004149D0 E8 70A50600 call 0047EF45;继续猥琐
0047D104 /E9 6E1D0000 jmp 0047EE77
0047EF33 E8 57A0F9FF call 00418F8F;VM Check?
0047EF3C C3 retn;直接在这里下断点吧……
0047FC4C^\E9 46FFFFFF jmp 0047FB97
0047FB97 5F pop edi
0047FB98^ E9 E4FEFFFF jmp 0047FA81
0047FA81 5E pop esi
0047FA82 E9 5C010000 jmp 0047FBE3
0047FBE3 5B pop ebx
0047FBE4 C9 leave
0047FBE5 C2 0800 retn 8
;返回以后的最后一段代码……光明就在眼前了……
004AC05A^\EB A3 jmp short 004ABFFF
004ABFFF E8 00000000 call 004AC004
004AC004 EB 30 jmp short 004AC036
004AC036 59 pop ecx ; 复件_未?004AC004
004AC037 E9 56010000 jmp 004AC192
004AC192 81E9 04C04A00 sub ecx, 004AC004
004AC198 8981 BDCF4A00 mov dword ptr [ecx+4ACFBD], eax
004AC19E C781 C2CF4A00 F>mov dword ptr [ecx+4ACFC2], 82444FF
004AC1A8^ EB BF jmp short 004AC169
004AC169 66:C781 C6CF4A0>mov word ptr [ecx+4ACFC6], 0C39D
004AC088 0FB618 movzx ebx, byte ptr [eax] ;检测API开头的1个字节
004AC13E 81C3 58363566 add ebx, 66353658
004AC0E2 81FB 24373566 cmp ebx, 66353724 ;是CC吗?
004AC0E8 74 5C je short 004AC146 ;是就猥琐你
004AC0AC 894424 24 mov dword ptr [esp+24], eax ;不是就可以转到真正的API了……
004AC0B0 61 popad
004AC0B1 FF4424 08 inc dword ptr [esp+8];返回地址修正
004AC0B5 90 nop
004AC0B6 9D popfd
004AC0B7 C3 retn;光明了……
;啊!终于到站了……晕死我了……把我猥琐坏了……
004010D9 8BF0 mov esi, eax
004010DB 8A00 mov al, byte ptr [eax]
004010DD 3C 22 cmp al, 22
返回,IAT分析告一段落……有一些地方有些疑问…欢迎大家指正错误……
--------------------------------------------------------------------------------
【经验总结】
总结下:追踪NP的IAT加密的时候能用Int3断点尽量用……因为整个程序对硬件断点的猥琐很严格……
我一开始以为要用GetProcAddress的……后来发现其实GetProcAddress他是自己实现的……具体步骤就是找到需要Dll的导
出表,然后再挨个找……
写个脚本吧……自己太菜……写不出来……0047F76F每次停在这一行就可以得到地址了,至于调用地址可以读堆栈,修正下
就可以了……
跟以前版本相比的区别……
1.整个流程显得非常猥琐,Demo版本的不足也很容易看到……比较完了不给你跳……囧
2.自己实现了GetProcAddress,这期间没有调用系统API。
3.ZP和VMP的优点融合的非常融洽……搞得那个貌似VM_Check的函数进去直接跟晕了……所以这个函数的功能只是猜测……
具体作用等待Nooby作解析
4.那个貌似IAT索引的东西到底是什么?是为了后面函数返回所Push的一个随即值?程序里好像没有对他进行读取……等待
Nooby作解析
VM+乱续+SEH除了猥琐……还能怎么评价?
--------------------------------------------------------------------------------
【版权声明】: 转载请注明作者并保持文章的完整, 谢谢!
2009年08月15日 11:39:57 太强了,做我的师傅把 LZ很好很强大.. 毅力很足,搞完了问一句,累吗?:lol 毅力很足,搞完了问一句,累吗?:lol
Hmily 发表于 2009-8-15 16:29 http://www.52pojie.cn/images/common/back.gif
:lol 还行……有点累…… 你也太强悍了吧!厉害 毅力很足,搞完了问一句,累吗 楼主好问彩,膜拜加学习~ 注解寫得很不錯.
學習了 给你加分支持