本文共 3952 字,大约阅读时间需要 13 分钟。
scanf
里面会认为+123
还是123
, 即+
可以用来绕过某些栈中的canary
;scanf
可以触发malloc_consolidate
释放堆到unsortedbin
;当我们在写exp的时候有些需要去复制粘贴某些函数在plt表,got表的地址,或者找ROP的地址,有些时候复制粘贴不方便且不方便阅读,这样时候我们就可以用pwntools中提供的一些函数;
以32位程序的exp为例:ROPgadget:0x0804872f : pop ebp ; ret0x0804872c : pop ebx ; pop esi ; pop edi ; pop ebp ; ret0x0804843d : pop ebx ; ret0x0804872e : pop edi ; pop ebp ; ret0x0804872d : pop esi ; pop edi ; pop ebp ; ret0x08048426 : ret0x0804857e : ret 0xeac1
在exp中的0x0804843d,可以这样代替:
p32(rop.search(8).address)
proc = '文件路径'elf = ELF(proc)rop = ROP(elf)
找到gets函数在plt表中的位置,并将一段字符串写入bss段中:
p32(elf.plt['gets']) + 'aaaa' + p32(elf.bss()+0x100)p.sendline("要写入的字符串")
获得puts函数在got表中的地址:
p32(elf.got['puts'])
在exp中附加gdb调试exp:
context.log_level = 'debug'#context.terminal = ['deepin-terminal', '-x', 'sh' ,'-c']#deepin系统要加这句if args.G: gdb.attach(p)
当带G参数运行exp时(python exp.py G
),就会把gdb附加进去了;
格式化字符串常用函数 fmtstr_payload:
fmtstr_payload(num,{x_addr:str_addr})
num相当于%n$x中的n,表示第几个数,x_addr表示要修改的值的地址,str_addr表示需要修改成的值; 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 (关闭 / 部分开启 / 完全开启)
遇到程序当中有alarm时可以:
1. 直接vim程序,修改alarm为isnan可以patch掉alarm函数;2. 或者sed -i s/alarm/isnan/g ./pwn1
执行int 0x80可执行对应的系统调用:
查找int 0x80:ROPgadget --binary ./file_name --only "int 0x80"ROPgadget --binary ./file_name --opcode cd80c3
比如对于系统调用: execve("/bin/sh",NULL,NULL)
64位系统调用 :
mov rdi,xxxx; // '/bin/sh'字符串的地址 mov rax,59; //execve的系统调用号 mov rsi,0; mov rdx,0 syscall
Linux x64的传参方式:
它不同于x86的栈传参,它是优先6个寄存器传参,依次是RDI,RSI,RDX,RCX,R8,R9
,然后多余的参数才传进栈内,所以在进行ROP,找gadget的时候注意先从rdi开始传参数,然后再是RSI,RDX,RCX,R8,R9,最后才是栈上面的; int 80和syscenter采用的同样的传参顺序:eax,ebx,ecx,edx
;
rdi,rsi,rdx,r10,r9,r8
; p.shutdown('send')
:用于关闭读写通道,相当于Ctrl+c
结束while循环; 知道libc.so找函数的偏移的方法:
libc = ELF('./libc.so')system_offset = libc.symbols['system']binsh_offset = next(libc.search('/bin/sh'))
替换libc.so:
export LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libproxychains.so.4"
p = process(["file_name"],env={ "LD_PRELOAD":"./libc_name"})
在线查libc版本:
https://libc.blukat.me/
gdb查看堆的快表:
p/x main_arena.fastbinsY
堆的其他查看:
p *(mchunkprt) 0x602010find_fake_fast // 用于查找fake fastbin
exit退出的函数通过修改<_rtld_global+3848>
位置可以修改rip;
_dl_fini
的地址可以找到_rtld_global
,它一个结构体;) one_gadget
可以通过realloc_hook(one)
和__malloc_hook(__GI___libc_realloc+n)
来调整:
realloc_hook
设置为选择好的one_gadget
,将malloc_hook
设置为realloc
函数开头某一push寄存器处; push和pop的次数是一致的,若push次数减少则会压低堆栈,改变栈环境; IDA下载:
http://fuckilfakp5d6a5t.onion.pet/
pwn异构环境搭建:
qemu
:sudo apt-get install qemu-user
通过qemu模拟arm/mips环境,进而用gdb-multiarch进行调试;
gdb-multiarch
:sudo apt-get install gdb-multiarch
以mips为例:
apt-cache search "libc6" | grep mips
然后运行apt install +库名就可以安装; qemu-mipsel -L /usr/mipsel-linux-gnu/ ./add
用file命令查看文件信息,然后根据文件的类型选择qemu-的类型;qemu-的类型:
sir@sir-PC:~/desktop$ qemu-qemu-aarch64 qemu-i386 qemu-mipsel qemu-ppc64abi32 qemu-sparcqemu-aarch64_be qemu-m68k qemu-mipsn32 qemu-ppc64le qemu-sparc32plusqemu-alpha qemu-microblaze qemu-mipsn32el qemu-riscv32 qemu-sparc64qemu-arm qemu-microblazeel qemu-nios2 qemu-riscv64 qemu-tilegxqemu-armeb qemu-mips qemu-or1k qemu-s390x qemu-x86_64qemu-cris qemu-mips64 qemu-ppc qemu-sh4 qemu-xtensaqemu-hppa qemu-mips64el qemu-ppc64 qemu-sh4eb qemu-xtensaeb
-g
参数指定端口:qemu-mipsel -g 1234 -L /usr/mipsel-linux-gnu/ ./add
然后启动gdb-multiarch进行调试,先指定架构,再使用remote功能指定端口:
pwndbg> set architecture mipspwndbg> target remote localhost:1234
转载地址:http://vmlhn.baihongyu.com/