This page looks best with JavaScript enabled

GKCTF Re Writeup

 ·  ☕ 3 min read · 👀... views

不吃不喝莽了8小时,终于冲了个单榜第二,师傅们也太猛了吧QAQ
然后想问下出题人地址,没什么,只想慰问慰问(
Rank

Check_1n

这题直接输出flag是我没想到的,白费了很多时间在检查前面有没有坑。

IDA打开检查字符串发现一串奇怪的东西,瞒猜是密文,交叉引用走过去下断动调发现并没有触发断点。
Rank

从头跟了两遍发现开机密码检查在这里,成功得到开机密码“HelloWorld”
Rank

然后来到这个界面,当然是毫不犹豫选flag啦
Rank

得到fake flag

V2h5IGRvbid0IHlvdSB0cnkgdGhlIG1hZ2ljIGJyaWNrIGdhbWU=
Why don't you try the magic brick game

但是可以知道真flag在打砖块游戏里,进去看它跑完后直接就输出flag了
Rank

BabyDriver

看到这题瞬间就想到了一周前和 Bayerischen 师傅的对话

Q:师傅我看CTF里好像很少出现驱动逆向,下次我们是不是可以出两个驱动搞一下?

B:驱动很简单的呀,直接静态就行了

Q:那就算法搞复杂一点逼你动调啊。再搞点什么驱动级反调比如什么KdDisableDebugger,估计很有意思

B:那也太复杂了吧,又要搭虚拟机又要双机动调,想想就麻烦

然后这回真就搞了个KD反调的驱动出来…我这算不算搬起石头砸自己的脚눈_눈

不过还好,这题算法没那么复杂,静态也能做。函数很少,很快能找到关键函数sub_140001380。可以看到这个规则有点多,粗粗一看像是三维还是四维迷宫。然后我把迷宫输出看了一眼

****************
o.*..*......*..*
*.**...**.*.*.**
*.****.**.*.*.**
*...**....*.*.**
***..***.**.*..*
*.**.***.**.**.*
*.**.******.**.*
*.**....***.**.*
*.*****.***....*
*...***.********
**..***......#**
**.*************

可以看到,如果不管那两个标记位,就把它当作一个普通的二维迷宫,是可以且只有一条路径能走到终点的。然后抱着试试看的心态当二维迷宫来做真就出了。

这题还有个大坑点是键盘扫描码并非是ascii码,找个表对照一下,就可以写出正确的输入路径了

Windows键值对照表

右  0x26 L
左  0x24 J
上  0x17 I
下  0x25 K
正确路径输入:LKKK LLK LKKK LLLKKK LLLLLL

Chelly’s identity

这题体验就不错,一个简单的算法。流程大概就这样
Rank

然后这个简单算法就不多说了,就是按照输入的值对照box累计出一个值来对输入进行异或,比赛的时候为了省时间直接就上爆破了

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
ciper = [
    438, 1176, 1089, 377, 377, 1600, 924, 377, 1610, 924, 637, 639, 376, 566, 836, 830
]
box = [
    0x02, 0x03, 0x05, 0x07, 0x0B, 0x0D, 0x11, 0x13,  
    0x17, 0x1D, 0x1F, 0x25, 0x29, 0x2B, 0x2F, 
    0x35, 0x3B, 0x3D, 0x43, 0x47, 0x49, 0x4F, 0x53,  
    0x59, 0x61, 0x65, 0x67, 0x6B, 0x6D, 0x71, 0x7F
]
blast_box = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-@#{}"
flag = ""
for x in range(len(ciper)):
    for n in blast_box:
        v7 = 0;
        for i in box:
            if i < ord(n):
                v7 += i
            else:
                break
        if ord(n) ^ v7 == ciper[x]:
            flag += n
print(flag)

WannaReverse

这题真刺激,真就勒索病毒分析,路径追踪追出来近600个函数调用,人都审傻了。(还好最后还是拿了一血

动调+阅读Wanncry病毒分析报告可以知道程序的一个大致流程:随机生成一个AES密钥,用于加密文件,然后用内嵌RSA公钥加密生成的AES密钥,并将加密结果保存在被加密文件的文件头部。然后在clickme.exe中可以得到RSA私钥。那解密流程就很清楚了,把文件头的RSA加密结果拿出来用RSA私钥解密得到AES密钥"30776159143604297789676442413079",然后用这个密钥对该文件的剩下内容进行AES解密,模式为ECB(模式这里坑死我了),就可以得到flag

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from Crypto.Cipher import AES
from hashlib import md5

ciper = bytes([
    0x5C, 0xBC, 0xEA, 
    0x89, 0xBA, 0x2B, 0x18, 0x27, 0x79, 0x3F, 0x13, 0x0A, 0x8A, 
    0x97, 0xB4, 0x9B, 0xCD, 0x78, 0x9B, 0xD8, 0x35, 0x92, 0x05, 
    0x45, 0x4C, 0x22, 0xA5, 0x69, 0x37, 0xEB, 0x6E, 0x2B, 0x0E, 
    0xBD, 0x84, 0x0F, 0x91, 0x61, 0x38, 0xF6, 0xF1, 0xBA, 0x99, 
    0x19, 0x41, 0x72, 0x07, 0x91, 0xF0, 0x26, 0x68, 0x06, 0x61, 
    0x26, 0x5C, 0x20, 0x35, 0xDD, 0xCF, 0xFC, 0x77, 0x57, 0x54, 
    0x81, 0xF2, 0xF2, 0xE4, 0xAF, 0xBF, 0xA2, 0x1D, 0x29, 0xAE, 
    0x6C, 0x08, 0x3B, 0x76, 0x1B, 0x66, 0xB8, 0xFE, 0x72, 0xCB, 
    0xD6, 0x94, 0xC3, 0xD5, 0x6A, 0xE7, 0x0C, 0x7A, 0x28, 0xDC, 
    0xBC, 0xAC, 0x80
])
key = b"30776159143604297789676442413079"
aes = AES.new(key, AES.MODE_ECB)
c = aes.decrypt(ciper)

for i in c:
    print("%02X"%i, end = "")
print(c)
Share on

Qfrost
WRITTEN BY
Qfrost
CTFer, Anti-Cheater, LLVM Committer