pwn-note

gcc 编译的指令

  • NX:-z execstack / -z noexecstack (关闭 / 开启)
  • Canary:-fno-stack-protector /-fstack-protector / -fstack-protector-all (关闭 / 开启 / 全开启)
  • PIE:-no-pie / -pie (关闭 / 开启)
  • RELRO:-z norelro / -z lazy / -z now (关闭 / 部分开启 / 完全开启)

plt got

plt 是寻址用的->作用就是去 got 表寻找最后调用 libc 中的函数
got 可以理解为一个函数指针列表 函数一开始没调用时不是指向libc
指向一段init汇编

syscall和函数传参

arm 一般要具体情况具体分析
这里列举了常见的4种架构

  • x86

    • 返回值 : eax
    • syscall : int 0x80
    • syscall调用号: eax
    • syscall参数: ebx,ecx,edx,esi,edi,ebp
    • 函数参数: stack
  • x86_64

    • 返回值 : rax
    • syscall : syscall
    • syscall调用号: rax
    • syscall参数: rdi,rsi,rdx,r10,r8,r9
    • 函数参数: rdi,rsi,rdx,rcx,r8,r9,stack
  • arm32(aarch32)

    • 返回值 : r7
    • syscall : svc 0
    • syscall调用号: r7
    • syscall参数: r0,r1,r2,r3,stack
    • 函数参数: r0,r1,r2,r3,stack
  • arm64(aarch64)

    • 返回值 : x0
    • syscall : svc 0
    • syscall调用号: x8
    • syscall参数: x0,x1,x2,x3,x4,x5
    • 函数参数: x0,x1,x2,x3,x4,x5,x6,x7,stack

ps:

  • 这里注意Linux syscall函数^[int syscall(int syscall_id, ...);使用函数形式传递系统调用号,所以传递到第一个函数参数所对应的存储位置,接下来的几个参数往后推]
  • x寄存器=w寄存器
  • svc软中断=swi软中断

gdb 相关

转载自[https://www.cnblogs.com/murkuo/p/15965270.html]()稍有改动

基本指令

  • help 帮助
  • i info,查看一些信息,只输入 info 可以看可以接什么参数,下面几个比较常用

    • i b 常用,info break 查看所有断点信息(编号、断点位置)
    • i r 常用,info registers 查看各个寄存器当前的值
    • i f info function 查看所有函数名,需保留符号
  • show 和 info 类似,但是查看调试器的基本信息,如:

    • show args 查看参数
      rdi 常用,+寄存器名代表一个寄存器内的值,用在地址上直接相当与一个十六进制变量
  • backtrace 查看调用栈
  • q quit 退出,常用
  • vmmap 内存分配情况

执行指令

  • s 单步步入,遇到调用跟进函数中,相当于 step into,源码层面的一步

    • si 常用,同 s,汇编层面的一步
  • n 单步补过,遇到函数不跟进,相当于 step over,源码层面的一步

    • ni 常用,同 n,汇编层面的一步
  • c continue 常用,继续执行到断点,没断点就一直执行下去
  • r run 常用,重新开始执行
  • start 类似于 run,停在 main 函数的开始

断点指令

下普通断点指令 b(break):

  • b *(0x123456) 常用,给 0x123456 地址处的指令下断点
  • b *$rebase(0x123456) $rebase 在调试开 PIE 的程序的时候可以直接加上程序的随机地址
  • b func 常用,给函数 func 下断点

    • b file_name:func_name
  • b \*func+47 常用,给地址 func+47 处下断点
  • b file_name:15 给 file_name 的 15 行下断点,要有源码才行

    • b 15
  • b +0x10 在程序当前停住的位置下 0x10 的位置下断点,同样可以-0x10,就是前 0x10
  • break fun if $rdi==5 条件断点,rdi 值为 5 的时候才断

删除、禁用断点:

  • info breakpoints,i b 查看断点编号
  • delete 5,d 5常用,删除 5 号断点,直接 delete 不接数字删除所有
  • disable 5 常用,禁用 5 号断点
  • enable 5 启用 5 号断点
  • clear 清除下面的所有断点

内存断点指令 watch:

  • watch 0x123456 0x123456 地址的数据改变的时候会断
  • watch a 变量 a 改变的时候会断
  • info watchpoints 查看 watch 断点信息

捕获断点 catch:

  • catch syscall syscall 系统调用的时候断住
  • tcatch syscall syscall 系统调用的时候断住,只断一次
  • info breakpoints catch 的断点可以通过 i b 查看
    syscall 外还可以使用的有:

    1. throw: 抛出异常
    2. catch: 捕获异常
    3. exec: exec 被调用
    4. fork: fork 被调用
    5. vfork: vfork 被调用
    6. load: 加载动态库
    7. load libname: 加载名为 libname 的动态库
    8. unload: 卸载动态库
    9. unload libname: 卸载名为 libname 的动态库
    10. syscall [args]: 调用系统调用,args 可以指定系统调用号,或者系统名称

打印指令

查看内存指令 x:

  • x /nuf 0x123456 常用,x 指令的格式是:x 空格/nfu,nfu 代表三个参数

    • n 代表显示几个单元(而不是显示几个字节,后面的 u 表示一个单元多少个字节),放在/后面
    • u 代表一个单元几个字节,b(一个字节),h(2 字节),w(四字节),g(八字节)
    • f 代表显示数据的格式,f 和 u 的顺序可以互换,也可以只有一个或者不带 n,用的时候很灵活

      1. x 按十六进制格式显示变量。
      2. d 按十进制格式显示变量。
      3. u 按十六进制格式显示无符号整型。
      4. o 按八进制格式显示变量。
      5. t 按二进制格式显示变量。
      6. a 按十六进制格式显示变量。
      7. c 按字符格式显示变量。
      8. f 按浮点数格式显示变量。
      9. s 按字符串显示。
      10. b 按字符显示。
      11. i 显示汇编指令。
  • x /10gx 0x123456 常用,从 0x123456 开始每个单元八个字节,十六进制显示 10 个单元的数据
  • x /10xd $rdi 从 rdi 指向的地址向后打印 10 个单元,每个单元 4 字节的十进制数
  • x /10i 0x123456 常用,从 0x123456 处向后显示十条汇编指令

打印指令 p(print):

  • p func 打印函数 func 的地址,需要保留符号
  • p 0x10-0x08 计算 0x10-0x08 的结果
  • p &a 查看变量 a 的地址
  • p *(0x123456) 查看 0x123456 地址的值,注意和 x 指令的区别,x 指令查看地址的值不用星号
  • p $rdi 显示 rdi 寄存器的值,注意和 x 的区别,这只是显示 rdi 的值,而不是 rdi 指向的值
  • p *$rdi 显示 rdi 指向的值

打印汇编指令 disass(disassemble):

  • disass 0x123456 显示 0x123456 前后的汇编指令
  • x /10i 也可以使用 x 指令

打印源代码指令 list:

  • list 查看当前附近 10 行代码,要有源码,list 指令 pwn 题中几乎不用,但为了完整性还是简单举几个例子
  • list 38 查看 38 行附近 10 行代码
  • list 1,10 查看 1-10 行
  • list main 查看 main 函数开始 10 行

修改和查找指令

修改数据指令 set:

  • set $rdi=0x10 把 rdi 寄存器的值变为 0x10
  • set *0x123456=0x10 0x123456 地址的值变为 0x10,注意带星号
  • set args "abc" "def" "gh" 给参数 123 赋值
  • set args "python -c 'printf("1234\x7f\xde")'" 使用 python 给参数赋值不可见字符

查找数据:

  • search rdi 从当前位置向后查包含 rdi 的指令,返回若干
  • search -h 查看 search 帮助,我也不太长用这个指令
  • find "hello" 查找 hello 字符串,pwndbg 独有
  • ropgadget 查找 ropgadget,pwndbg 独有,没啥用,可以用其他工具

堆操作指令(pwndbg 插件独有)`

  • arena 显示 arena 的详细信息
  • arenas 显示所有 arena 的基本信息
  • arenainfo 好看的显示所有 arena 的信息
  • bins 常用,查看所有种类的堆块的链表情况
  • fastbins 单独查看 fastbins 的链表情况
  • largebins 同上,单独查看 largebins 的链表情况
  • smallbins 同上,单独查看 smallbins 的链表情况
  • unsortedbin 同上,单独查看 unsortedbin 链表情况
  • tcachebins 同上,单独查看 tcachebins 的链表情况
  • tcache 查看 tcache 详细信息
  • heap 数据结构的形式显示所有堆块,会显示一大堆
  • heapbase 查看堆起始地址
  • heapinfo heapinfoall 显示堆得信息,和 bins 的挺像的,没 bins 好用
  • parseheap 显示堆结构,很好用
  • tracemalloc 好用,会跟提示所有操作堆的地方

其他 pwndbg 插件独有指令

  • cyclic(cyc) 生成用来溢出的字符串,如

    • cyc -l aaaa/0x6161616161616161 返回溢出的 aaaa 溢出前有多少个字符
    • cyc 50 生成一个 50 长度的溢出字符串(根据不同平台不同)
  • $rebase 开启 PIE 的情况的地址偏移

    • b *$rebase(0x123456) 断住 PIE 状态下的二进制文件中 0x123456 的地方
    • codebase 打印 PIE 偏移,与 rebase 不同,这是打印,rebase 是使用
  • stack 查看栈
  • retaddr 打印包含返回地址的栈地址
  • canary 直接看 canary 的值
  • plt 查看 plt 表
  • got 查看 got 表
  • hexdump 像 IDA 那样显示数据,带字符串
最后修改:2023 年 10 月 11 日
如果觉得我的文章对你有用,请随意赞赏