Hgame2020 Week2

Hgame2020 Week2

二月 01, 2020

logo

Hgame2020 Week2 新人(Akira)

这周也勉强AK了WM

Web

0x01 Cosmos的博客后台

打开网站发现没什么特别的,想到去年的php伪协议php://filter/read=convert.base64-encode/resource=index.php就试了一下,读出了index.php login.php admin.php的源码

image-20200128094633389

赌一把他debug没关

image-20200128094856506

image-20200128094830488

image-20200128094949506

因为弱比较所以直接用另一个md5值为0eXXXX的字符串绕过,成功登进后台

image-20200128095208688

image-20200128095317082

得知插入图片函数返回的是文件流的base64

直接尝试http://localhost/flag却是404,询问Annevi得知题目中的根目录指服务器根目录==

于是我们改用file://localhost//flag

image-20200128100052179

0x02 Cosmos的留言板-1

题目提示是数据库,手注了半天没什么收获突然想起可以用神器sqlmap

image-20200128195256212

直接注失败,发现题目把空格吞了,加上参数--tamper=space2comment

image-20200128195436135

检测到是MySQL

image-20200128195555654

只有一个库并且找到了注入点

使用命令 python sqlmap.py -u http://139.199.182.61/index.php?id=1 --tamper=space2comment --dump-all 直接转储数据库所有表项

image-20200128200010214

0x03 Cosmos的新语言

image-20200128121721727

看出有个mycode,这是mycode的执行结果

image-20200128123139467

访问/mycode,发现了加密方式

刷新几次之后发现mycode会刷新且🍆在群里说是5s一次

上周刚学的py写了个爬虫

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

#ROT13_Table
upperdict = {'A': 'N', 'B': 'O', 'C': 'P', 'D': 'Q', 'E': 'R', 'F': 'S', 'G': 'T',
'H': 'U', 'I': 'V', 'J': 'W', 'K': 'X', 'L': 'Y', 'M': 'Z', 'N': 'A',
'O': 'B', 'P': 'C', 'Q': 'D', 'R': 'E', 'S': 'F', 'T': 'G', 'U': 'H',
'V': 'I', 'W': 'J', 'X': 'K', 'Y': 'L', 'Z': 'M'}

lowerdict = {'a': 'n', 'b': 'o', 'c': 'p', 'd': 'q', 'e': 'r', 'f': 's', 'g': 't',
'h': 'u', 'i': 'v', 'j': 'w', 'k': 'x', 'l': 'y', 'm': 'z', 'n': 'a',
'o': 'b', 'p': 'c', 'q': 'd', 'r': 'e', 's': 'f', 't': 'g', 'u': 'h',
'v': 'i', 'w': 'j', 'x': 'k', 'y': 'l', 'z': 'm'}

def rot13(src):
dst = []
for ch in src:
if ch in lowerdict:
dst.append(lowerdict[ch])
elif ch in upperdict:
dst.append(upperdict[ch])
else:
dst.append(ch)
return ''.join(dst)

def decrypt(src):
dst = []
for i in src:
dst.append(chr(ord(i)-1))
return ''.join(dst)

url1 = 'http://7392403296.php.hgame.n3ko.co/'
url2 = 'http://7392403296.php.hgame.n3ko.co/mycode'

key = html.unescape(requests.get(url1).text.split('<br>')[-2][1:])
mycode = (requests.get(url2).text.split('\n')[8][5:-30]).split('(')
print (key)
print (mycode)

for i in mycode:
if i == 'str_rot13':
key = rot13(key)
elif i == 'encrypt':
key = decrypt(key)
elif i == 'base64_encode':
key = base64.b64decode(key).decode()
elif i == 'strrev':
key = key[::-1]
print (key)
res = requests.post(url1,data={'token':key})
print(res.text.split('<br>')[-1].split('\n')[-3])

image-20200128123832138

0x04 Cosmos的聊天室

直接点击右上角的flag

image-20200129162407279

同时burp显示

image-20200129162553777

说明我们要找到管理员的token

联想到给的学习资料

image-20200129162750754

直接复制粘贴(试了下XSS平台没成于是上了自己的机子,不行

不懂为什么用了闭合标签的反尖括号无返回,所以直接用 / 结束了

image-20200129171241826

于是模仿XSS平台对onerror=后面进行html实体编码后再urlencode

image-20200129171754947

刷新页面后,在我机子的web服务器log里找到了访问记录

image-20200129164904032

说明刷新时成功执行了页面上的脚本把我的token传了过来

百度抄了一个撞md5的脚本,撞出code后提交,让后台管理员运行脚本

我原来理解错了,我以为是输验证码后下一次输入传进bot

image-20200129165614277

得到管理员的token

image-20200129170216766

burp用管理员token访问/flag得到flag

Reverse

0x01 unpack

根据hint得知上了upx,于是跟教程手脱upx

image-20200126104124527

下断

image-20200126104739677

跟到OEP并用百度到的脚本dump

image-20200126105016010

测试可以运行

image-20200126105138416

搜索字符串Wrong input找到主函数发现判断逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
int main()
{
unsigned char key[] =
{
104, 104, 99, 112, 105, 128, 91, 117, 120, 73,
109, 118, 117, 123, 117, 110, 65, 132, 113, 101,
68, 130, 74, 133, 140, 130, 125, 122, 130, 77,
144, 126, 146, 84, 152, 136, 150, 152, 87, 149,
143, 166};//用IDA从byte_6CA0A0处导出的数组
for (int i = 0; i <= 41; i++)
putchar(key[i] - i);
return 0;
}
//打印flag

image-20200126105545336

0x03 babyPy

百度现学现卖py字节码,得到加密函数大概长这样

1
2
3
4
5
6
7
8
def encrypt(OOo):
O0O = OOo[None:None:-1]
O0o = list(O0O)
for O0 in range (1,len(O0o)):
Oo = O0o[O0-1] ^ O0o[O0]
O0o[O0] = Oo
O = bytes(O0o)
return O.hex()

虽然运行后提示不能str ^ str分析得知解密代码应该是这样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
int main()
{
int key[] = { 0x7d, 0x03, 0x7d, 0x04, 0x57,
0x17, 0x72, 0x2d, 0x62, 0x11,
0x4e, 0x6a, 0x5b, 0x04, 0x4f,
0x2c, 0x18, 0x4c, 0x3f, 0x44,
0x21, 0x4c, 0x2d, 0x4a, 0x22};//把题目里的输出便乘bytes
for (int i = 24; i >= 1; i--)
key[i] = key[i-1] ^ key[i];
for (int i = 24; i >= 0; i--)
putchar(key[i]);
return 0;
}

image-20200126173405601

Crypto

0x01 Verification_code

我爱签到题

image-202001261113166104位,直接爆破

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import string, random
from hashlib import sha256

table = ''.join(string.ascii_letters+string.digits)
tail = 'ORJNRW14IaEbB5ND'
res = 'e75027e00538dbf0f2de79d78467d3d9926695de7ed5639e7ae02df511d9a602'

print(table)
for i in table:
for j in table:
for k in table:
for l in table:
buf = i+j+k+l
if sha256((buf+tail).encode()).hexdigest() == res:
print (buf)

image-20200126111229624

The secret code?可以从题目的py里找到

image-20200126111425073

0x02 Remainder

原来中国剩余定理又叫孙子定理笑了半天

阅读代码得以下同余方程
$$
\begin{cases}
m\equiv k_1 (mod \ p)\
m\equiv k_2 (mod \ q)\
m\equiv k_3 (mod \ r)
\end{cases}
$$
其中 k1,k2,k3 分别为 prime为 p,q,r 时的输出

计算msg:

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
from Crypto.Util import number
import gmpy2

p = 94598296305713376652540411631949434301396235111673372738276754654188267010805522542068004453137678598891335408170277601381944584279339362056579262308427544671688614923839794522671378559276784734758727213070403838632286280473450086762286706863922968723202830398266220533885129175502142533600559292388005914561
q = 150088216417404963893679242888992998793257903343994792697939121738029477790454833496600101388493792476973514786401036309378542808470513073408894727406158296404360452232777491992630316999043165374635001806841520490997788796152678742544032835808854339130676283497122770901196468323977265095016407164510827505883
r = 145897736096689096151704740327665176308625097484116713780050311198775607465862066406830851710261868913835866335107146242979359964945125214420821146670919741118254402096944139483988745450480989706524191669371208210272907563936516990473246615375022630708213486725809819360033470468293100926616729742277729705727
k1 = 78430786011650521224561924814843614294806974988599591058915520397518526296422791089692107488534157589856611229978068659970976374971658909987299759719533519358232180721480719635602515525942678988896727128884803638257227848176298172896155463813264206982505797613067215182849559356336015634543181806296355552543
k2 = 49576356423474222188205187306884167620746479677590121213791093908977295803476203510001060180959190917276817541142411523867555147201992480220531431019627681572335103200586388519695931348304970651875582413052411224818844160945410884130575771617919149619341762325633301313732947264125576866033934018462843559419
k3 = 48131077962649497833189292637861442767562147447040134411078884485513840553188185954383330236190253388937785530658279768620213062244053151614962893628946343595642513870766877810534480536737200302699539396810545420021054225204683428522820350356470883574463849146422150244304147618195613796399010492125383322922
e = 65537

M = p*q*r
M1 = q*r
M2 = p*r
M3 = p*q
t1 = gmpy2.invert(M1, p)
t2 = gmpy2.invert(M2, q)
t3 = gmpy2.invert(M3, r)
n = p*q*r
c = (k1*t1*M1 + k2*t2*M2 + k3*t3*M3) % n
#利用中国剩余定理得到m^e,并用p*q*r做n当RSA算密文
d = gmpy2.invert(e, (p-1)*(q-1)*(r-1))
m = pow(c, d, n)
#算出d和明文

msg = number.long_to_bytes(m)
print (msg)
#此处打印出结果为msgstr的二进制值
msgstr = '\n1hAyuFoOUCamGW9BP7pGKCG81iSEnwAOM8x\n********** DO NOT GUESS ME ********\nhg In number theory, \nam the Chinese \ne{ remainder theorem \nCr states that if one\nT_ knows the \nw0 remainders of the \nNt Euclidean division\n+6 of an integer n \nOt by several \nh3 integers, then \nR_ YOU CAN FIND THE \nmE FLAG, ;D\n!! \n!} \n********** USE YOUR BRAIN *********\ncbl8KukOPUvpoe1LCpBchXHJTgmDknbFE2z\n'
print (msgstr)
#打印出来后发现flag藏在中间几行的前两位,用以下操作拼接起来
msgstr = msgstr.split('\n')[3:-3]
for substr in msgstr:
print (substr[:2], end='')
print('\n')

#验算
m2 = number.bytes_to_long(msg)
print (pow(m2,e,p))
print('\n')
print (pow(m2,e,q))
print('\n')
print (pow(m2,e,r))

image-20200128231930051

Misc

0x01 Cosmos的午餐

又是流量分析,这次上了TLS,在首选项里里加上ssl_log.log就可以正常分析了

image-20200129185818830

人肉扫了几遍只发现了4张没用的图片,在ObjectNotFound的提醒下发现自己想错了

image-20200129190118741

导出http对象列表按大小排序,找到了一个比其他大的上传到AWS的条目

image-20200129190348751

binwalk扫一遍发现是zip,顺手用binwalk解压得到Outguess with key.jpg

image-20200129190348751

C老板的理想午餐
从CTF-Wiki得知`outgutess`是一个隐写软件,从hint得知备注里有密码

image-20200129190837108

image-20200129190903682

得到一个网址

image-20200129190949190

打开链接下载得一个压缩包,里面有一张二维码

image-20200129191038325

扫码得到flag

image-20200129191233008

0x02 所见即为假

真的都是假的

打开压缩包发现有密码,根据题目猜到是伪加密

image-20200126112222489

image-20200126112156490

全局加密位无加密,文件加密位显示已加密,改09 0000 00后来发现用7zip就没这么多事儿了

FLAG_IN_THE_PICTURE

成功解压斯哈斯哈

CTF-Wiki得知压缩包注释的F5 key是指图片隐写软件F5 steganography的密码,下载后解压这张图

真·in the picture

得到一个txt文件,内容是

1
526172211A0701003392B5E50A01050600050101808000B9527AEA2402030BA70004A70020CB5BDC2D80000008666C61672E7478740A03029A9D6C65DFCED5016867616D657B343038375E7A236D737733344552746E46557971704B556B32646D4C505736307D1D77565103050400

很像一堆Hex字节,粘到WinHex里

image-20200126113049671

甚至不用改rar就得到了flag

0x03 地球上最后的夜晚

解压得到Last Evenings on Earth.7zNo password.pdf

询问ObjectNotFound得知原来No password指的是外层压缩包

image-20200128144912212

用PDF隐写软件wbStego4.3open解压出隐写数据得到压缩包密码

image-20200128145117817

解压得到Last Evenings on Earth.docx

打开docx没有发现什么特别的,用7zip打开对比正常的docx,发现多了一个secret.xml

image-20200128145426617

打开得到flag

image-20200128145556697

0x04 玩玩条码

解压得到7zipPasswordHere.mp4Code128.7zJPNPostCode.png

mp4是蹦蹦蹦主线第五章5-8的CG别问我为什么查这个看了一下没什么特别的

JPNPostCode倒是很直接,没找到解码的东西,看看维基百科的说明:

组成

客户条形码的字符由五个宽度为5的黑线组成。但是,起始码/停止码由宽度为3的长条和半长条(底部)组成。显示字母时,将它们组合为控制代码+数字(A为CC1 + 0)。黑线由四种类型组成:长条,半长条(顶部),半长条(底部)和定时条,其长宽比为3:2:2:1。字符由宽度为1的白线分隔。

然后去日本邮政官网下了个条码生成器

image-20200129233125419

根据维基用头解得1087627,打开cb.htm输进去验证

image-20200129194531699

好的,接下来就是视频了

一看就是视频隐写,但是如果直接搜视频隐写的话:

image-20200129233457517

很少有CTF相关的文章,在ObjectNotFound学长的提醒下最终咕狗到一个VirtualDub插件

image-20200129234701130

跟教程装完插件用JPNPostCode做密码处理完视频后得到一个忘记调码率所以有10G大的avi和7z密码

image-20200129235107507

解压得到code128.png

image-20200129235107507

扫码得flag

image-20200129235420297

所以视频是什么条码啊kora(

总结

这周题目难度骤增,但也学到了很多东西,py应该也逐渐会用了轮子也越装越多。好多地方理解错的,卡着的都亏学长(姐)们的耐心指导。要学的东西好多,学院的任务也没完成==,希望下周别爆零吧,也要开始肝学院的任务了(逃

来吃个柚子,图文无关(