1. 程式人生 > 實用技巧 >全國大學生資訊保安競賽—創新實踐能力賽初賽wp

全國大學生資訊保安競賽—創新實踐能力賽初賽wp

前兩天打了國賽的初賽,再次被自己菜哭555

MISC

簽到

the_best_ctf_game

下載下來附件拖入notepad++,看到有類似flag的字樣

再放到010editor裡

看到了頭和尾,直接一個個輸入拼起來就好了

flag{65902f26-0d6e-463f-bc63-2df733e47fbe}

WEB

easyphp

開啟環境看到顯示的原始碼

這段程式碼大體意思就是先建立一個子程序,然後建立成功後去進行程序控制,如果進城異常退出的話,就返回phpinfo,後面就是對傳參a進行過濾。

審計過後發現有個敏感函式call_user_func_array(),這個函式是回撥函式,並把一個數組引數作為回撥函式的引數。

在程式碼中還發現了會用正則過濾變數a,不能直接傳pcntl_wait()而使子程序終端

後來想到我們可以通過給a變數傳入call_user_func(),然後給b傳pcntl_wait()來繞過正則過濾從而得到phpinfo

Payload: ?a=call_user_func&b=pcntl_wait

可以得到phpinfo頁面,本來想通過phpinfo來看一下有沒有可利用的函式來getshell的,結果發現flag就在phpinfo中

easytrick

拿到題目發現是反序列化。目的是執行echo file_get_contents(“/flag”)語句。因此需要構造物件的兩個成員,trick1和trick2長度小於5,md5相等,但是兩者不相等。

由於在程式碼剛開始的部分有強制型別轉換

!==當判斷兩者型別不同後,就會直接返回True。因此只要傳入的trick1和trick2是同類型但不是String型別即可。

!=則會先轉換二者型別,因此需要使用傳入的引數在強制型別轉換為String後,再次轉換不能復原的型別。

實驗發現使用NAN(Not a Number)符合以上條件:

使用如下程式碼構造payload:

O:5:"trick":2:{s:6:"trick1";d:NAN;s:6:"trick2";d:NAN;}

傳入payload獲得最終結果:

rceme

打開發現有原始碼

將$_GET['a']的值傳入了parserIfLabel函式

經過資訊蒐集後發現本題程式碼為CVE-2019-9041漏洞的魔改題

傳入的a需要滿足次正則要求,即{if:}開頭,{end if}結尾

之後經過多層過濾後在{if:}的:與}之間的語句會被拼接到

而被執行,在經過多次本地除錯後發現形似?a={if:1)*要執行程式碼*if(1}{end if}的payload可以被成功拼接並執行

下一步表示繞過過濾函式danger_key()

發現過濾的很死,eval,assert以及回撥函式啥的都被ban了

想到用字串拼接來繞過,但是回撥函式被ban了,後查閱資料發現array_map()也能來掉用函式

後來構造payload ?a={if:1)array_map('sys'.'tem',['cat /flag']);if(1}{end if} 併成功的到flag

Reverse

Re_Z3

拖進IDA進行反編譯

找到main函式後進行反彙編出虛擬碼

可以整理出其中的邏輯,首先將unk_404020處的字串讀入Dst賦給Dst。然後讀取使用者42位的輸入。以七個字母為一組組成七元一次方程組,等式左側的部分即是Dst中的值。後續的方程引數都相同,僅僅是方程左側的數值不同。

這裡使用python的scipy庫解方程,exp如下:

import numpy as np

from scipy.linalg import solve

Dst=[
[0x4f17,0x9cf6,0x8ddb,0x8ea6,0x6929,0x9911,0x40a2],
[0x2f3e,0x62b6,0x4b82,0x486c,0x4002,0x52d7,0x2def],
[0x28dc,0x640d,0x528f,0x613b,0x4781,0x6b17,0x3237],
[0x2a93,0x615f,0x50be,0x598e,0x4656,0x5b31,0x313a],
[0x3010,0x67fe,0x4d5f,0x58db,0x3799,0x60a0,0x2750],
[0x3759,0x8953,0x7122,0x81f9,0x5524,0x8971,0x3a1d]]

a=np.array([[12,53,6,34,58,36,1],
[83,85,12,73,27,96,52],
[78,53,24,36,86,25,46],
[39,78,52,9,62,37,84],
[23,6,14,74,48,12,83],
[27,85,92,42,48,15,72],
[4,6,3,67,0,26,68]])

for i in Dst:
b=np.array(i)
x=solve(a,b)
for j in x:
print(chr(int(round(j))),end='')

執行得到最終答案:flag{7e171d43-63b9-4e18-990e-6e14c2afe648}

Hyperthreading

程式有反除錯,呼叫win下的IsDebuggerPresent,先使用IDA搜尋字串,找到debug欄位,檢視交叉引用,定位到反調函式進行patch,之後拖進Ollydbg,隨便輸入一個值,發現flag長度42位,驗證方式是逐字元對使用者輸入的字元做加密後進行對比。

找到關鍵cmp,位置在0x401306(基址401000),對cmp下的jnz進行patch,改為nop,並將0x40130F處的2Ah改成FFh,即去除對比後不成功的跳轉,並且將程式的flag對比操作次數從0x2a改為0xff。

之後拖入OLLYDBG 關鍵cmp處下斷。

輸入abcdefghijklmnopqrstuvwxyz1234567890-{}

按順序記錄cl的值,獲得一個每個字母對應十六進位制的對映表

通過字串定位方法發現sub_401270中的byte_402150即為加密的flag,逐位與使用者輸入對比。

根據前一步動態除錯patch後的程式獲得的abcdefghijklmnopqrstuvwxyz1234567890-{}對映表就可解出flag{a959951b076ca047840add7093583251ca92}

提交後發現不正確,觀察flag發現需要把0換為減號

最終flag為flag{a959951b-76ca-4784-add7-93583251ca92}

Crypto

bd

使用CTF-RSA-TOOLS 解出m

M轉為16進製為

666c61677b64333735323533382d393064302d633337332d636665662d3932343764336531363834387d

發現是16進位制的flag

兩個一組,寫指令碼解出flag{d3752538-90d0-c373-cfef-9247d3e16848}

PWN

babyjsc

根據題目嘗試連線:

可以根據報錯得知,題目環境使用python搭建,並使用input讀入

根據得到的原始碼也可以驗證這一點,因此可以使用input的漏洞,input()函式如果接收的是計算式,會執行得到結果。

此處嘗試根據該漏洞傳入程式碼執行,利用的os模組的system()方法執行系統命令 __import__('os').system('ls')。命令成功被執行,說明漏洞存在:

發現flag並不在根目錄,嘗試查詢flag:

找到flag位置讀取,得到最終結果: