pwn一些工具使用
ROPgadget
-查找gadget
地址
获取程序中gadget
的地址,这个程序可以是可执行程序也可以是libc
文件
gadget
:程序本身或者libc
中存在的一些汇编指令,比如pop ebx
,pop eax
等,每一条指令对应着一段地址,那么将这些gadget
地址部署到栈中,在esp
指针指向该gadget
地址的时候发现这个地址里面是一条指令而不是一个数据,那么esp
就会将该地址弹给ip
指针,ip
指针会执行该地址内存放的汇编指令
示例:
查找变量地址:ROPgadget --binary 程序名 --string 'global_max_fast’
查找指令地址:ROPgadget --binary 程序名 --only 'nop’
查找pop寄存器:ROPgadget --binary 程序名 --only 'pop|ret' | grep 'rdx’
查找字符:ROPgadget --binary 程序名 --string "/bin/sh”
生成ropchain
:ROPgadget --binary 程序名 --ropchain
,适用于静态编译的题目
其他:ROPgadget --help
grep
筛选 | 将前面一部分结果传递给后面部门,可以串联多个使用
区分rop
和shellcode
:
*RSP 0x7fffffffde38 —▸ 0x7ffff7df9083 (__libc_start_main+243) ◂— mov edi, eax *RIP 0x5555555555c2 (main) ◂— endbr64 ──────────────────────────────────────────────────[ DISASM / x86-64 / set emulate on ]─────────────────────────────────────────────────── ► 0x5555555555c2 <main> endbr64 0x5555555555c6 <main+4> push rbp 0x5555555555c7 <main+5> mov rbp, rsp 0x5555555555ca <main+8> sub rsp, 0x10 0x5555555555ce <main+12> mov rax, qword ptr fs:[0x28] 0x5555555555d7 <main+21> mov qword ptr [rbp - 8], rax 0x5555555555db <main+25> xor eax, eax 0x5555555555dd <main+27> mov eax, 0 0x5555555555e2 <main+32> call init <init> 0x5555555555e7 <main+37> mov eax, 0 0x5555555555ec <main+42> call menu <menu>
seccomp-tools
-沙箱工具
$ seccomp-tools dump ./pwn line CODE JT JF K 0000: 0x20 0x00 0x00 0x00000004 A = arch 0001: 0x15 0x00 0x05 0xc000003e if (A != ARCH_X86_64) goto 0007 0002: 0x20 0x00 0x00 0x00000000 A = sys_number 0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005 0004: 0x15 0x00 0x02 0xffffffff if (A != 0xffffffff) goto 0007 0005: 0x15 0x01 0x00 0x0000003b if (A == execve) goto 0007 0006: 0x06 0x00 0x00 0x7fff0000 return ALLOW 0007: 0x06 0x00 0x00 0x00000000 return KILL
patchelf
-更换libc
和ld
GCC编译的四个阶段 原创 · 预处理(Pre-Processing) · 编译(compiling) · 汇编(Assembling) · 链接(Linking)
patchelf --set-interpreter ld文件 ./pwn
patchelf --replace-needed 原本可执行文件的libc文件 需要替换的libc文件 ./pwn
查找原本的libc文件/确认是否修改成功:
ldd aladdin linux-vdso.so.1 (0x00007ffc0f7b0000) libc.so.6 => /lib/x86_64-linux-gnu/**libc.so.6 (0x00007f0d64c06000)#libc** /lib64/ld-linux-x86-64.so.2 (0x00007f0d64e13000)#ld
查看libc版本:
strings libc.so.6 | grep GNU GNU C Library (Ubuntu GLIBC 2.35-0ubuntu3.4) stable release version 2.35. Compiled by GNU CC version 11.4.0.
glibc-all-in-one
-下载libc
和对应的ld
题目给出的libc
和ld
很多时候是没有调试符号的,不利于调试,还有时候只给了libc
没给ld
,此时只能自己找对应的libc
和ld
第一次运行时sudo python3 update_list
更新列表
cat list / old_list
查看glibc-all-in-one
里有的libc
,再用./download / ./download_old + 文件名
下载
如果工具里没有可以先update
,没有就去ubuntu
官网找
one_gadget
-查找libc
中直接getshell
的gadget
one_gadget libc文件
获取更多gadget
:one_gadget -l2 l
ibc文件
调试
直接调试程序:gdb 文件名
调试exp
:需要调试的地方之前加dbg()
指令:
r
:开始
ni/si/c
:执行 ni不跟进,si跟进,c执行到下一个断点/程序结束
b 函数名/*地址/*$rebase(偏移)
code
watch 地址 / 变量
内存断点,改变时断
x 按十六进制格式显示变量。 d 按十进制格式显示变量。(dec) u 按十进制格式显示无符号整型。(unsigned dec) o 按八进制格式显示变量。(oct) t 按二进制格式显示变量。 a 按十六进制格式显示变量。 i 指令地址格式。 (instruction)查看指定区域汇编指令 c 按字符格式显示变量。(char) f 按浮点数格式显示变量。(float) s 显示地址对应的字符串 (string) u: 表示一个地址单元的长度 b表示单字节, h表示双字节, w表示四字节, g表示八字节
修改数据指令set:
set $rdi=0x10
//把rdi寄存器的值变为0x10set *(0x123456)=0x10
//0x123456地址的值变为0x10,注意带星号set args “abc” “def” “gh“
//给参数123赋值set args “python -c ‘print
“1234\x7f\xde”’” //使用python给参数赋值不可见字符
分布
registers
寄存器窗口 disasm
汇编代码窗口 stack
栈 backtrace
栈回溯窗口
快捷键:
ctrl + r 历史命令回滚
ctrl + b 切换tmux左右
ctrl + d 退出gdb