[re]反推樹結構:2020網鼎杯朱雀組re tree wp

[re]反推樹結構:2020網鼎杯朱雀組re tree wp

這道題感覺出題人放了一波水,隱藏了一個輸出樹的函數,導致發現了這個函數之後難度大幅降低,當然沒有這個函數也可以解,但麻煩了很多!接下來分析題目:

題目分析

一道比較標準的逆向題,開局就輸flag,一點不多BB:
在這裏插入圖片描述
逆向分析一下,主邏輯比較簡單:
在這裏插入圖片描述
init裏面是初始化,先把a-z26個字母放在一個結構體數組裏:
在這裏插入圖片描述
然後用這個結構體數組生成了一個樹結構:

具體生成算法不用太仔細研究,我當時也是看了好久,後來發現跟這個並沒關係,後面介紹。

然後輸入flag,進入chkflag函數:
在這裏插入圖片描述
這裏將我們輸入的flag裏面的0-9,a-f也就是十六進制的數變成二進制,這也可以確定我們輸入的flag長度是“flag{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}”這麼長,42字節,並且由16進制數組成。然後將flag掐頭去尾去掉“flag{”和“}”還有“-”之後的十六進制數轉換成二進制數字符串。

接下來利用輸入flag轉換的二進制數和之前生成的二叉樹結構進行尋路,0就是左子節點,1就是右子節點:
在這裏插入圖片描述
把找到的東西和“zvzjyvosgnzkbjjjypjbjdvmsjjyvsjx”這個字符串進行比較,成功則通過。

解題

根據分析可知,這道題的關鍵是數結構,生成數結構的算法說實話還是比較複雜(雖然沒幾行),但從內存中直接分析又太麻煩,寫腳本把脫出來的內存分析出樹結構也比較麻煩。直到看到了有一個函數,靜靜的躺在函數列表,沒有被調用,很孤獨,很寂寞:
在這裏插入圖片描述
反編譯看一下:
在這裏插入圖片描述
這特麼不就是遍歷輸出樹結構嗎,但這個函數並沒有被調用:
在這裏插入圖片描述
但我們可以調用,將程序patch一下,將原本調用parse的地方patch成調用outtree:
在這裏插入圖片描述
patch成:
在這裏插入圖片描述
直接用patch裏的Assemble即可,然後把函數名替換一下就行,不用改機器碼:
在這裏插入圖片描述
然後執行一下:
在這裏插入圖片描述
輸出的內容:

50:left :48 ,right : 49
48:left :44 ,right : 45
44:left :38 ,right : 39
38:left :24 ,right : 33
24: char:y
33:left :1 ,right : 16
1: char:b
16: char:q
39:left :6 ,right : 5
6: char:g
5: char:f
45:left :9 ,right : 40
9: char:j
40:left :34 ,right : 35
34:left :22 ,right : 15
22: char:w
15: char:p
35:left :30 ,right : 10
30:left :23 ,right : 28
23: char:x
28:left :3 ,right : 8
3: char:d
8: char:i
10: char:k
49:left :46 ,right : 47
46:left :18 ,right : 41
18: char:s
41:left :25 ,right : 13
25: char:z
13: char:n
47:left :42 ,right : 43
42:left :36 ,right : 7
36:left :2 ,right : 31
2: char:c
31:left :19 ,right : 4
19: char:t
4: char:e
7: char:h
43:left :37 ,right : 21
37:left :14 ,right : 32
14: char:o
32:left :29 ,right : 12
29:left :11 ,right : 27
11: char:l
27:left :20 ,right : 26
20: char:u
26:left :17 ,right : 0
17: char:r
0: char:a
12: char:m
21: char:v

樹結構就是這麼個東西。

然後我們把每個字母的路線整理出來,還原一下就行了,但不用都整理。“zvzjyvosgnzkbjjjypjbjdvmsjjyvsjx”這個字符串中只有“zvjyosgnkbpdmx"這幾個字母,通過樹反推(手工就行)出路線是:

z:1010
v:1111
j:010
y:0000
o:11100
s:100
g:0010
n:1011
k:01111
b:00010
p:01101
d:0111010
m:111011
x:011100

鑑於有小同學細聊問我怎麼根據字母反推會二叉樹的路線,這裏簡單說一下,如果實在不會反着推這個路線,那就根據這個輸出結果把圖畫出來,大概是這樣的:
在這裏插入圖片描述
以途中的字母b作爲例子,從b觸發,往回走走到根就是路線,左子節點是0又子節點是1,所以b的路線就是00010。

然後寫個代碼復原一下flag:

tree={
"z":"1010",
"v":"1111",
"j":"010",
"y":"0000",
"o":"11100",
"s":"100",
"g":"0010",
"n":"1011",
"k":"01111",
"b":"00010",
"p":"01101",
"d":"0111010",
"m":"111011",
"x":"011100"}
result="zvzjyvosgnzkbjjjypjbjdvmsjjyvsjx"
flag=""
for i in result:
    flag+=tree[i]
flag1=""
i=0
while i<len(flag):
    flag1+=hex(int(flag[i:i+8],2))[2:]
    i+=8
print "flag{"+flag1[0:8]+'-'+flag1[8:12]+'-'+flag1[12:16]+'-'+flag1[16:20]+'-'+flag1[20:32]+'}'

在這裏插入圖片描述
然後成功:
在這裏插入圖片描述

附錄

修改的結構體(沒啥用):
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章