# pwndbg调试工具使用教程

### **C++ 进程内存空间分布** <a href="#c-jin-cheng-nei-cun-kong-jian-fen-bu" id="c-jin-cheng-nei-cun-kong-jian-fen-bu"></a>

内存可以分为以下几段：

> * **文本段**：包含实际要执行的代码（机器指令）和常量。它通常是共享的，多个实例之间共享文本段。文本段是不可修改的。
> * **初始化数据段**：包含程序已经初始化的全局变量，.data。
> * **未初始化数据段**：包含程序未初始化的全局变量，.bbs。该段中的变量在执行之前初始化为0或NULL。
> * **栈**：由系统管理，由高地址向低地址扩展。
> * **堆**：动态内存，由用户管理。通过malloc/alloc/realloc、new/new\[]申请空间，通过free、delete/delete\[]释放所申请的空间。由低地址向高地址扩展。

![process\_mem\_lay](https://dongwenhu.github.io//img/process_mem_lay.png)

### 内存布局

![](/files/-ME1H_YmK3zPI1lwCLrr)

进程地址空间从低地址开始依次是代码段(Text)、数据段(Data)、BSS段、堆、内存映射段(mmap)、栈。

![](/files/-ME1HMAuymhJCOZLAUk3)

&#x20;**\[ 注意：BSS段 和 data段的区别是 ，如果一个全局变量没有被初始化（或被初始化为0），那么他就存放在bss段；如果一个全局变量被初始化为非0，那么他就被存放在data段。]**

在进程被载入内存中时，基本上被分裂成许多小的节（section）。我们比较关注的是6个主要的节：&#x20;

（1） .text 节&#x20;

（2）.data 节&#x20;

（3）.bss 节&#x20;

（4） 堆节&#x20;

（5） 栈节&#x20;

（6）环境/参数节 环境/参数节（environment/arguments section）用来存储系统环境变量的一份复制文件， 进程在运行时可能需要。

例如，运行中的进程，可以通过环境变量来访问路径、shell 名称、主机名等信息。 该节是可写的，因此在格式串（format string）和缓冲区溢出（buffer overflow）攻击中都可以使用该节。 另外，命令行参数也保持在该区域中。

### pwndbg调试命令

程序的调试过程主要有：单步执行，跳入函数，跳出函数，设置断点，设置观察点，查看变量。

GDB主要可以做4大类事（加上一些其他的辅助工作），以帮助用户在程序运行过程中发现bug。

* 启动您的程序，并列出可能会影响它运行的一些信息
* 使您的程序在特定条件下停止下来
* 当程序停下来的时候，检查发生了什么
* 对程序做出相应的调整，这样您就能尝试纠正一个错误并继续发现其它错误

#### 基本命令包括以下几个：

* 1.输入gdb或者gdb-multiarch program进行本地调试
* 2.如果是本地程序的话，可以输入entry或者start进入第一条指令
  * entry
    * 如果是本地调试有main函数，则可以输入main直接进入main函数
      * main
* 3.如果调试的程序有源代码，则输入n执行的时候是按照源代码一行一行执行的；
  * 如果没有源代码，则输入ni来按照汇编语言执行一条条指令
  * 如果指令是调用了函数，则可以通过si进入调用内部
* 4.输入p 函数名可以打印出函数地址，然后使用nearpc 地址即可显示此函数的反汇编代码
  * p scanf
  * nearpc 0x7ffff7a777f0
  * p/x：以16进制显示变量值
  * p/d：10进制显示
  * p/o：8进制显示
* 5.下断点，如果有符号，可以直接使用b 函数名下断点，如果没有，则需要使用b \*address的方式下断点
  * b read/b recv
  * b \*0x40062b
  * 通过
    * bl列出所有断点&#x20;
    * bc清除断点&#x20;
    * bd临时禁用断点&#x20;
    * be启用断点
* 6.下完断点之后需要执行到断点，从头开始运行输入r命令，继续运行输入c
* 7.通过stack命令可以查看栈的数据
  * stack 0x20 \[0x20为查看的长度]
* 8.输入context可以重新刷新一下之前的调试界面
* 9.可以通过hexdump查看栈的地址的内容
  * hexdump 0x7fffffffe3b8
  * x/s 0x7fffffffe3b8
* 10.通过nextcall可以直接进行下一次调用
* 11.vmmap可以查看内存布局
* 12.可以使用p $eax查看寄存器的值，也可以使用i r eax查看
* 13.如果使用的调试器为peda：
  * pattern create 200
  * pattern offset 0xaddr
* 14.如果遇到栈溢出需要查看偏移量：
  * cyclic 200生成200字节的长度数据
  * cyclic -l 覆盖的前四个字母：cyclic -l jaab,输出即为偏移量

### IDA和OD快捷键

#### IDA

* y修改变量为类型加值
* n单纯修改变量
* G跳转到指定地址
* X查看交叉引用
* shift+F12查找字符串
* 数组和
* 空格切换图形和文本视图
* shift+e查看data段初始化的全局变量及静态变量

#### OD

* F2下断点
* F4运行到选中指令
* F8步过
* F7单步执行
* 数据窗口跟随
* 智能搜索可以查找的字符串更全
* od的基址与ida可能不一样
* &#x20;在看[Shark恒 破解教程](http://www.52pojie.cn/thread-200439-1-1.html) 时，有很多吾友对教程中按键的含义不懂，我发一个常用的快捷键列表，希望对新手有点帮助。\
  打开一个新的可执行程序 (F3)\
  重新运行当前调试的程序 (Ctrl+F2)\
  当前调试的程序 (Alt+F2)\
  运行选定的程序进行调试 (F9)\
  暂时停止被调试程序的执行 (F12)\
  单步进入被调试程序的 Call 中 (F7)\
  步过被调试程序的 Call (F8)\
  跟入被调试程序的 Call 中 (Ctrl+F11)\
  跟踪时跳过被调试程序的 Call (Ctrl+F12)\
  执行直到返回 (Ctrl+F9)\
  显示记录窗口 (Alt+L)\
  显示模块窗口 (Alt+E)\
  显示内存窗口 (Alt+M)\
  显示 CPU 窗口 (Alt+C)\
  显示补丁窗口 (Ctrl+P)\
  显示呼叫堆栈 (Alt+K)\
  显示断点窗口 (Alt+B)\
  打开调试选项窗口 (Alt+O)

### 二进制一些基础知识

代码测试：

```c
#include <stdio.h>


int add(int x, int y)
{
        int sum;
        sum = x+y;
        return sum;
}

int main()
{
        int p = add(3, 4);
        printf("%d\n",p);
        return 0;
}

```

```c
gcc -g -m32 learn_stack.c -o learn_stack_32
```

* 栈从内存高地址向低地址生长，调用执行函数的时候：首先将被调用函数参数按照从右向左的顺序依次入栈，之后的流程为：
  * 1.将call指令的下一条地址入栈，即被调用函数的返回地址入栈；
  * 2.main函数的栈底地址入栈，即ebp入栈；mov ebp,esp;使得ebp指向新的栈顶；
  * 3.之后被调用函数的局部变量入栈，执行到leave ret指令的时候：mov esp,ebp;pop ebp;，相当于恢复ebp原来的值，esp指向原来的位置，ret直接将pop esp;mov eip,esp;
* plt与got
  * PLT:CODE
  * GOT:ADDRESS
  * PROGRAM CALL --> PLT --> GOT -->LIBC
* 64位传参：rdi,rsi,rdx...       rdi, rsi, rdx, rcx, r8, r9,栈
  * 当参数少于7个时， 参数从左到右放入寄存器: rdi, rsi, rdx, rcx, r8, r9
  * 当参数为7个以上时， 前 6 个与前面一样， 但后面的依次从 “右向左” 放入栈中，即和32位汇编一样。
* POP rdi; ret// 通过*pop*为*rdi*赋值,再通过*ret*指令跳转到我们希望的地方
* ret：sp增加一个内存单元栈顶数据出栈赋值给ip寄存器


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://functfan.gitbook.io/gewuzz/lou-dong-wa-jue-1/lou-dong-wa-jue/wu-lian-wang-lou-dong-wa-jue-ji-shu/pwndbg-shi-yong-jiao-cheng.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
