之前1直认为1个工具只要会用就能够了,可是作为1名喜欢安全的渣渣来说,会用还远远不够,你还得了解它,欺骗它,改造它,提升它!
上1篇文章讲了如何脱掉peid0.94版本的壳
[调试原理]逆向peid_脱壳
这1篇文章对peid开始逆向分析它的原理。开始的时候,从最简单的分析起:如何判断程序有vc编译器编译的。
逆向工具:ollydbg,ida,winhex
分析对象:peid v0.94(完善脱壳后uppeid)
测试程序:TraceMe.exe
打开peid加载TraceMe.exe发现为Microsoft Visual C++ 6.0编写,所以直接打开ollydbg,查找字符串Microsoft Visual C,发现字符串
双机来到这个字符所在的地方
发现跳转来自的地方,往上寻觅,发现这个函数的起始部份
这里用IDA1样可以到达相同的效果
直接下断,然后用peid加载我们的测试程序TraceMe.exe,后F9,程序中断下来
单步运行,将分析的算法写在下面的代码中:
00438C26 |. 53 push ebx
00438C27 |. 55 push ebp
00438C28 |. 56 push esi
00438C29 |. 57 push edi ; 下面就是填充1个数组
00438C2A |. B0 72 mov al,0x72 ; "r"
00438C2C |. 884424 2F mov byte ptr ss:[esp+0x2F],al
00438C30 |. 884424 31 mov byte ptr ss:[esp+0x31],al
00438C34 |. 884424 34 mov byte ptr ss:[esp+0x34],al
00438C38 |. 884424 39 mov byte ptr ss:[esp+0x39],al
00438C3C |. 884424 3D mov byte ptr ss:[esp+0x3D],al
00438C40 |. B0 63 mov al,0x63
00438C42 |. 884424 40 mov byte ptr ss:[esp+0x40],al ; "c"
00438C46 |. 884424 41 mov byte ptr ss:[esp+0x41],al
00438C4A |. B0 73 mov al,0x73
00438C4C |. 884424 43 mov byte ptr ss:[esp+0x43],al ; "s"
00438C50 |. 884424 44 mov byte ptr ss:[esp+0x44],al
00438C54 |. B0 6C mov al,0x6C
00438C56 |. 884424 47 mov byte ptr ss:[esp+0x47],al ; "l"
00438C5A |. 884424 48 mov byte ptr ss:[esp+0x48],al
00438C5E |. 8BB424 A00400>mov esi,dword ptr ss:[esp+0x4A0]
00438C65 |. 8B46 0C mov eax,dword ptr ds:[esi+0xC] ; "PE"
00438C68 |. 8B56 18 mov edx,dword ptr ds:[esi+0x18] ; .text
00438C6B |. B1 6D mov cl,0x6D
00438C6D |. 884C24 36 mov byte ptr ss:[esp+0x36],cl ; "m"
00438C71 |. 884C24 3E mov byte ptr ss:[esp+0x3E],cl
00438C75 |. B3 41 mov bl,0x41 ; 'A'
00438C77 |. C64424 2C 7B mov byte ptr ss:[esp+0x2C],0x7B ; "g"
00438C7C |. C64424 2D 4F mov byte ptr ss:[esp+0x2D],0x4F
00438C81 |. C64424 2E 75 mov byte ptr ss:[esp+0x2E],0x75
00438C86 |. C64424 30 50 mov byte ptr ss:[esp+0x30],0x50
00438C8B |. C64424 32 6F mov byte ptr ss:[esp+0x32],0x6F
00438C90 |. C64424 33 67 mov byte ptr ss:[esp+0x33],0x67
00438C95 |. C64424 35 61 mov byte ptr ss:[esp+0x35],0x61
00438C9A |. C64424 37 44 mov byte ptr ss:[esp+0x37],0x44
00438C9F |. C64424 38 69 mov byte ptr ss:[esp+0x38],0x69
00438CA4 |. C64424 3A 7D mov byte ptr ss:[esp+0x3A],0x7D
00438CA9 |. C64424 3B 5C mov byte ptr ss:[esp+0x3B],0x5C
00438CAE |. 885C24 3C mov byte ptr ss:[esp+0x3C],bl
00438CB2 |. 885C24 3F mov byte ptr ss:[esp+0x3F],bl
00438CB6 |. C64424 42 65 mov byte ptr ss:[esp+0x42],0x65
00438CBB |. C64424 45 2E mov byte ptr ss:[esp+0x45],0x2E
00438CC0 |. C64424 46 64 mov byte ptr ss:[esp+0x46],0x64
00438CC5 |. C64424 18 4D mov byte ptr ss:[esp+0x18],0x4D
00438CCA |. C64424 19 53 mov byte ptr ss:[esp+0x19],0x53
00438CCF |. C64424 1A 43 mov byte ptr ss:[esp+0x1A],0x43
00438CD4 |. C64424 1B 46 mov byte ptr ss:[esp+0x1B],0x46
00438CD9 |. 0FB740 06 movzx eax,word ptr ds:[eax+0x6] ; PE后偏移6位置为块的数目
00438CDD |. 8D0C80 lea ecx,dword ptr ds:[eax+eax*4] ; 块数目*5=0x14
00438CE0 |. 8B6CCA E8 mov ebp,dword ptr ds:[edx+ecx*8-0x18] ; .text段地址+块数*40-0x18 = 1000(最后1个段大小)
00438CE4 |. 8D44CA D8 lea eax,dword ptr ds:[edx+ecx*8-0x28] ; 最后1个段地址(".rsrc"段地址)
00438CE8 |. 8B78 14 mov edi,dword ptr ds:[eax+0x14] ; 获得最后1个段(.rsrc)的偏移
00438CEB |. 8B46 04 mov eax,dword ptr ds:[esi+0x4] ; 最后1个节末尾偏移
00438CEE |. 03FD add edi,ebp
00438CF0 |. 8BAC24 9C0400>mov ebp,dword ptr ss:[esp+0x49C] ; 数组中某值
00438CF7 |. 8D8F 00390000 lea ecx,dword ptr ds:[edi+0x3900]
00438CFD |. 3BC1 cmp eax,ecx
00438CFF |. 73 1A jnb XupPEiD.00438D1B
00438D01 |. 8B55 20 mov edx,[arg.7] ; 取得程序rva
00438D04 |. 85D2 test edx,edx ; 判断是不是为0
00438D06 |. 74 13 je XupPEiD.00438D1B
00438D08 |. 8B4E 18 mov ecx,dword ptr ds:[esi+0x18] ; text段
00438D0B |. 8B79 14 mov edi,dword ptr ds:[ecx+0x14] ; text段在文件中的偏移
00438D0E |. 0379 10 add edi,dword ptr ds:[ecx+0x10] ; 偏移+text段在文件中的块大小=text末尾偏移
00438D11 |. 3BD7 cmp edx,edi
00438D13 |. 0F82 E4020000 jb upPEiD.00438FFD ; 跳(确保oep在text段中)(vc的1个特点)
在上面的代码中00438D01处我的注释是取得程序 RVA
00438D01 |. 8B55 20 mov edx,[arg.7] ; 取得程序rva
这个地方其实不是直接分析得到的,发现程序每次加载的时候arg.7的地址为00471018
右键数据窗口中跟随,记录地址,然后重新加载程序,在00471018地方下 内存访问断点,F9运行后加载TraceMe.exe,在下面的地方断下:
而直接在数据窗口中跟随,并没有发现任何头绪,往上回溯代码,发现最开始赋给eax的地方在这里:
数据窗口中跟随:
熟习pe结构的看A0130000那个地方是否是在IMAGE_NT_HEADERS部份中IMAGE_OPTIONAL_HEADER中偏移为16的位置,而这个位置对应的就是address of entrypoint,所以这个地方就应当是程序的RVA(OEP)
那末这个分析只是分析了部份判定vc的代码,那末在之前还会不会又判定呢?我们看看那在判定vc的时候的堆栈
右键跟随,发现回到刚刚赋给rva的代码空间,前面的代码段其实就是在将程序的偏移,基址送给这个函数,然后判断,下面的代码段主要就是将函数指针数组的下标存进1个数组,然后调用相干函数确认程序类型。
昨晚分析1般加载TraceMe的时候电脑卡死了,瞬间很是生气,就没有在进行分析了,有兴趣的大牛们可以进行分析指针数组那个地方
分析了1点,其他分析的思路也差不多和这个1样,大牛勿喷!