6.3 调试器

1.调试器提供了非常多的便利和优点。比如运行,暂停,步进,一个进程;设置断点;操作寄存器和内存;捕捉内部异常,这些底层操作的细节,正是我这章要详细探讨的。

===============================================

2.当我们很难得到源代码的时候,开发者,逆向工程师, Hacker 就会应用黑盒调试跟
踪目标程序。黑盒调试中,被测试的软件对黑客来说是不透明的,唯一能看到的就是反汇编代码。

===========================

3.黑盒测试分成两种不同的模式:用户模式和内核模式.用户模式的权限是最低的。
当你运行“运算器(cacl.exe)”的时候,就会产生一个用户级别的进程;对这个进程的调试
就是用户模式调试。核心模式的权限是最高的。这里运行着操作系统内核,驱动程序,底层组件。

====================

4.下面的这些用户模式的调试器大家应该再熟悉不过了:WinDbg(微软生产),OllyDbg(一个免费的调试器作者是Oleh Yuschuk)。当你在Linux 下调试程序的时候,就需要使用标准的GNU 调试器(gdb)

       比如安装钩子函数,以及其他的专门为Hacker 和逆向工程师专门定制的各种功能。在这方面出现了两个新的具有代表性的作品分别是PyDbg (byPedram Amini)和Immunity
Debugger (from Immunity, Inc.)。

       PyDbg 是一个纯Python 实现的调试器,让黑客能够用Python 语言全面的控制一个进程,实现自动化调试。Immunity 调试器则是一个会让你眼前一亮的调试器,界面相当的友好,类似OllyDbg,但是拥有更强大的功能以及更多的Python 调试库。

=======================

5.CPU 的寄存器能够对少量的数据进行快速的存取访问。在x86 指令集里,一个CPU 有
八个通用寄存器:EAX, EDX, ECX, ESI, EDI, EBP, ESP 和EBX。

(1)EAX 寄存器也叫做累加寄存器,用于加减;

    前面我们说了,函数的返回值也是存储在EAX 寄存器里。这一点很重要,因为通过返
回的EAX 里的值我们可以判断函数是执行成功与否,或者得到确切返回值。

(2)EDX 寄存器也叫做数据寄存器。用于乘法和除法

(3)ECX 寄存器,也叫做计数寄存器,简单理解就是用于循环操作时是由大减到小的)。

counter = 0
while counter < 10:
print "Loop number: %d" % counter
counter += 1
_______________________________________________________________________
如果你把这代码转化成汇编代码,你会看到第一轮的时候ECX 将等于10,第二轮
的时候等于9,如此反复知道ECX 减少到0。这很容易让人困惑,因为这和Python 的循环刚好代码相反,但是只要记得ECX 是向下计算的就行了。

(4)ESI 寄存器是源操作数指针,存储着输入的数据流的位置

(5)EDI 寄存器是目的操作数指针,存储了计算结果存储的位置。

(6)(7)ESP 和EBP 分别是栈指针和基指针。这两个寄存器共同负责函数的调用和栈的操作。当一个函数被调用的时候,函数需要的参数被陆续压进栈内最后函数的返回地址也被压进。ESP 指着栈顶,也就是返回地址。EBP 则指着栈的底端。有时候,编译器能够做出优化,释放EBP,使其不再用于栈的操作,只作为普通的寄存器使用。

(8)EBX 是唯一一个没有特殊用途的寄存器。它能够作为额外的数据储存器。

(9)还有一个需要提及的寄存器就是EIP。这个寄存器总是指向马上要执行的指令。当CPU执行一个程序的成千上万的代码的时候,EIP 会实时的指向当前CPU 马上要执行到的位置。

======================================================

6.栈

ESP 负责跟踪栈顶,EBP 负责跟踪栈底。栈从内存的高地址像低地址增长。让我们用前面编写的函数my_sock()作为例子讲解栈是如何工作的。

Function Call in C
_____________________________________________________________________
int my_socks(color_one, color_two, color_three);
_____________________________________________________________________


把我们的my_socks()函数扩展一点,让我们假定函数被调用后做的第一件事就是
申请一个字符串数组,将参数color_one 复制到数组里。代码应该像这样:
____________________________________________________________________
int my_socks(color_one, color_)
{
char stinky_sock_color_on[10];
...
}

函数将在棧里申请stinky_sock_color_on 变量的空间,以便在栈里调用(当然会随着函
数的执行完毕而释放,不过在函数内部访问时,效率会高很多)。申请成功以后,堆栈的结构将像图2-2 看到的这样。




“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值