学习pwn2
脚本中gdb调试
之前不知道自己哪里有问题,现在懂怎么改了
from pwn import * |
第三行是关键点,之后在想gdb调试的地方添加gdb.attach语句即可
使用时,先提升终端的权限为root,再输入tmux,之后进入tmux的界面之后运行脚本即可
简化书写
uu64 = lambda x: u64(x.ljust(8, b'\x00')) |
沙盒检测
seccomp-tools dump ./pwn |
orw
shellcode='' |
可以发现,程序禁用了execve和execveat,不能直接get shell,需要通过orw
同时,程序也禁用了常规的open read write,需要我们找到他们的替代品
对于open,我们可以选择使用openat或者openat2(本题已禁用)
对于read,我们可以选择使用readv,preadv,preadv2(本题可用),pread64或者mmap(本题可用)
对于write,我们可以选择使用writev(本题可用),sendfile(本题可用,且能省略read)等
shellcode的时候利用这个,rop的时候不要用libc里面的open函数,而是pop rax 然后syscall(目前还不知道原理,猜测是libc内部的open函数其实不是sys_open,因为那个题只让用open read write,其他系统调用都禁用了)
mprotect
如果能够rop的话,可以尝试使用mprotect
mprotect之后,read,然后写入shellcode,然后返回shellcode地址
mprotect 函数用于设置一块内存的保护权限(将从 start 开始、长度为 len 的内存的保护属性修改为 prot 指定的值),函数原型如下所示:
#include <sys/mman.h> |
需要注意的是,指定的内存区间必须包含整个内存页(4K),起始地址 start 必须是一个内存页的起始地址,并且区间长度 len 必须是页大小的整数倍。
start必须与0x1000对齐。
当一个进程的内存访问行为违背了内存的保护属性,内核将发出 SIGSEGV(Segmentation fault,段错误)信号,并且终止该进程。
https://firmianay.gitbook.io/ctf-all-in-one/4_tips/4.11_mprotect
ROPgadget
ROPgadget --binary './libc.so.6' --multibr |grep 'syscall'|grep 'ret' |
注意–multibr这个参数,不然出不来syscall;ret这个
xchg edx, eax ;
交换edx eax的值,如果找不到pop edx 可以考虑这个片段
scanf(“%d”)
正常输入时,输入为范围在-2147483648~2147483647内的整数。
如果输入范围在-9223372036854775808~9223372036854775807内的整数,则会截断高位读取,此范围是long long int的范围。
如果输入范围在long long int范围之外,则统一将参数赋值为-1(0xFFFFFFFF)
如果输入为非数字,分为下列情况:
– (1) 如果输入仅有一个,则该输入无效,该值不变。
– (2) 如果输入有数字前缀(如12345abcd),则scanf仅会读取前面的数字,从第一个非数字开始,后面全部舍弃(12345)。
– (3) 如果输入有多个且使用一个scanf语句(如scanf(“%d, %d”, &a, &b))。输入第一个非数字后,后面的所有输入均为无效,前面的输入可以赋值。
– (4) 如果输入有多个且使用多个scanf语句(含循环,即一个scanf中仅有一个输入),则输入非数字时,如果输入的不是’+’或’-’,则后面紧跟的所有scanf均自动跳过,变为无效,不能输入。如果输入的是’+’或’-’,则会跳过当前输入,后面仍然可以进行输入。
摘抄自:https://blog.csdn.net/qq_54218833/article/details/121308367
改写got表
确认保护只有RELRO: Partial RELRO
如果是Full RELRO则GOT不可写(mprotect尝试一下?)
另外got表被程序填入正确地址前后都可以改写,填入之前可以往里面填入别的函数的plt地址,改写之后可以填入别的函数的真实地址
ret2csu
写文章的时候已经忘了,后面看还能补上不。
栈迁移
当栈溢出只能最多溢出到返回地址,则可以考虑栈迁移,基础的栈迁移看上面这个链接
一般来说题目不会基础
稍复杂的就是第一次ret到read的地址(main函数里输入的地址),然后在第二次read的时候读入rop,然后ret到leave_ret。
pwndbg调试忽略信号
handle SIGALRM nostop |
handle SIGALRM nostop
nostop:让调试器在接收到 SIGALRM 信号时不要停止程序。
noprint:不显示任何关于接收到信号的消息。
pass:允许信号传递给被调试的程序。










