调试原理-逆向peid-判定vc

以前一直认为一个工具只要会用就可以了,可是作为一名喜欢安全的渣渣来讲,会用还远远不够,你还得了解它,欺骗它,改造它,提升它!

上一篇文章讲了如何脱掉peid0.94版本的壳

[调试原理]逆向peid_脱壳

这一篇文章对peid开始逆向分析它的原理。开始的时候,从最简单的分析起:如何判断程序有vc编译器编译的。

逆向工具:ollydbg,ida,winhex

分析对象:peid v0.94(完美脱壳后uppeid)

测试程序:TraceMe.exe



打开peid加载TraceMe.exe发现为Microsoft Visual C++ 6.0编写,所以直接打开ollydbg,查找字符串Microsoft Visual C,发现字符串

双机来到这个字符所在的地方

发现跳转来自的地方,往上寻找,发现这个函数的起始部分

这里用IDA一样可以达到相同的效果

直接下断,然后用peid加载我们的测试程序TraceMe.exe,后F9,程序中断下来

单步运行,将分析的算法写在下面的代码中:

00438C26  |.  53            push ebx
00438C27  |.  55            push ebp
00438C28  |.  56            push esi
00438C29  |.  57            push edi                                 ;  下面就是填充一个数组
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(最后一个段大小)
00438CE4  |.  8D44CA D8     lea eax,dword ptr ds:[edx+ecx*8-0x28]    ;  最后一个段地址(".rsrc"段地址)
00438CE8  |.  8B78 14       mov edi,dword ptr ds:[eax+0x14]          ;  获取最后一个段(.rsrc)的偏移
00438CEB  |.  8B46 04       mov eax,dword ptr ds:[esi+0x4]           ;  最后一个节末尾偏移
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的一个特征)

在上面的代码中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的代码空间,前面的代码段其实就是在将程序的偏移,基址送给这个函数,然后判断,下面的代码段主要就是将函数指针数组的下标存进一个数组,然后调用相关函数确认程序类型。

昨晚分析一般加载TraceMe的时候电脑卡死了,瞬间很是生气,就没有在进行分析了,有兴趣的大牛们可以进行分析指针数组那个地方

分析了一点,其他分析的思路也差不多和这个一样,大牛勿喷!

时间: 2024-12-28 16:12:10

调试原理-逆向peid-判定vc的相关文章

【系统篇】从int 3探索Windows应用程序调试原理

探索调试器下断点的原理 在Windows上做开发的程序猿们都知道,x86架构处理器有一条特殊的指令——int 3,也就是机器码0xCC,用于调试所用,当程序执行到int 3的时候会中断到调试器,如果程序不处于调试状态则会弹出一个错误信息,之后程序就结束.使用VC开发程序时,在Debug版本的程序中,编译器会向函数栈帧中填充大量的0xCC,用于调试使用.因此,经常我们的程序发生缓冲区溢出时,会看到大量的“烫烫烫…”,这是因为“烫”的编码正是两个0xCC. 那么?为什么int 3可以让程序中断到调试

gdb调试原理及qemu中的gdbserver

(一)gdb调试原理 此部分转自:https://blog.csdn.net/u012658346/article/details/51159971     https://www.cnblogs.com/xsln/p/ptrace.html gdb调试的原理是基于ptrace系统调用,ptrace()系统调用提供了一个方法,该方法使一个程序(追踪者)可以观察和控制另外一个程序(被追踪者)的执行,并检查和改变被追踪者的内存及寄存器.它主要用于实现断点调试和追踪系统调用. 当被追踪时,被追踪线程在

ARM JTAG 调试原理

OPEN-JTAG 开发小组 1 前言 这篇文章主要介绍 ARM JTAG 调试的基本原理. 基本的内容包括了 TAP (TEST ACCESS PORT) 和 BOUNDARY-SCAN ARCHITECTURE 的介绍, 在此基础上,结合 ARM7TDMI 详细 介绍了的 JTAG 调试原理. 这篇文章主要是总结了前段时间的一些心得体会,希望对想了解 ARM JTAG 调试的网友们 有所帮助. 我个人对 ARM JTAG 的理解还不是很透彻,在文章中,难免会有偏失和不准确的地 方, 希望精通

.NET应用程序调试—原理、工具、方法

阅读目录: 1.背景介绍 2.基本原理(Windows调试工具箱..NET调试扩展SOS.DLL.SOSEX.DLL) 2.1.Windows调试工具箱 2.2..NET调试扩展包,SOS.DLL.SOSEX.DLL 2.3.调试系统的基本流程及架构(.NETDAC概念.mscordacwks.dll) 2.4.VisualStudio中集成扩展调试(更加细粒度的调试程序) 3.调试程序类型(客户端程序.服务端程序) 4.调试方式及场景 4.1.本机调试(Attach Process,调试器启动

从NDK在非Root手机上的调试原理探讨Android的安全机制(转载)

从NDK在非Root手机上的调试原理探讨Android的安全机制 最近都在忙着研究Android的安全攻防技术,好长一段时间没有写博客了,准备回归老本行中--Read the funcking android source code.这两天在看NDK文档的时候,看到一句话"Native debugging ... does not require root or privileged access, aslong as your application is debuggable".咦

从NDK在非Root手机上的调试原理探讨Android的安全机制

最近都在忙着研究Android的安全攻防技术,好长一段时间没有写博客了,准备回归老本行中--Read the funcking android source code.这两天在看NDK文档的时候,看到一句话"Native debugging ... does not require root or privileged access, aslong as your application is debuggable".咦,NDK调试不就是通过ptrace来实现调试的么?在非Root的手

GDB调试原理——ptrace系统调用

本文由霸气的菠萝原创,转载请注明出处:http://www.cnblogs.com/xsln/p/ptrace.html 全部关于gdb的文章索引请点这里 引子: gdb基本上大家都在用,你有没有想过它的实现原理是什么?为什么它可以控制程序执行.中断.访问内存甚至直接使程序流程改变? 在使用gdb调试程序时,程序的进程状态是”T”,但又似乎并非接到了SIGSTOP信号,那么这个”T”是什么呢? 追根溯源,我们今天来研究一下Linux下这个强大的系统调用:ptrace() 首先,linux的进程状

xdebug远程调试原理分析

xdebug可以控制PHP程序的执行,这意味着xdebug可以在任何时候暂停或者恢复正在运行的PHP程序.当PHP程序被暂停的时候,xdebug可以获取到程序的有关 信息,比如变量的值等.xdebug也可以修改一个变量的值,然后再恢复暂停的程序,让其继续运行. xdebug配合IDE执行 可视化调试的流程 (类似于VisualStudio单步调试)被称为“远程调试”,是因为调试时有一个Server(xdebug)和一个Client(IDE),所以在调试的时候,被调试的PHP程序和调试PHP程序的

TLS (Thread Local Storage)反调试原理

TLS的特别之处在于使得程序的入口点EP不是第一条执行的指令,所以常常用于反调试检测之中. 用一个已经开启的TLS的程序来做说明. 数据结构 TLS存在于PE文件格式之中.IMAGE_DATA_DIRECTORY DataDirectory[9] 存放了TLS目录的地址. winNT.h [F12 可得到定义位置] #define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory 同其他目录表数组一样,也是8字节结构 (VA+Size) typedef s