REVERSE-COMPETITION-GeekChallenge2021
REVERSE-COMPETITION-GeekChallenge2021
- Re0
- 劉壯桌面美化大師
- 買Activity
- Re1
- 調試
- 珍惜生命
- new_language
- easypyc
- Brute_force
- win32
- wasm
- 猜拳
- have_a_tea
Re0
64位exe,ida打開,main函數中沒發現什么重要的邏輯
Shift+F12打開字符串窗口,直接找到flag明文
劉壯桌面美化大師
apk文件,jadx-gui打開,MainActivity中什么都沒有,于是查看與MainActivity在同一目錄下的其它類
在DesktopbeautifierConfigureActivityKt類里面找到一個好像和flag相關的方法loadTitlePref
loadTitlePref要獲取R.string.flag,我們跟過去發現只是一個整型,實際上是一個資源id
在android中,一個資源id和一個實際的資源綁定,而這個實際的資源在資源文件res中
于是在如下位置找到flag
買Activity
apk文件,加載了buyactivity庫,MainActivity大概作用是保存輸入到一個msgList里,沒什么大用,于是Msg和MsgAdapter這兩個類就不用看了
查看ExportedActivity這個類,發現可以直接在一個文本框打印flag
來到Decode類,從本地獲取一個字符串,然后對這個字符串順序異或16即為flag
這個時候可以直接用jeb調試smali,指定啟動ExportedActivity即可獲得flag
這里我們按照getDecodedFlag方法的邏輯計算flag
ida打開libbuyactivity.so,來到Java_com_sorrowrain_buyactivity_Decode_stringFromNative
可以看到兩個字符串和一些操作,下面的操作一時看不懂,直接將兩個字符串拼接,然后順序異或16
可以看到兩個字符串拼接順序異或16后,得到的字符串中含有"{}",說明這個字符串大概率就是flag,但是順序不對
看著像柵欄,直接用工具,欄數為2,得到flag
解柵欄前:
解柵欄后:
Re1
64位的exe,ida打開
主要的邏輯在main函數中,輸入的長度為44,輸入經標準base64變換后與0x40異或,最后與data比較
取出data的數據,寫逆腳本即可
調試
64位elf,反編譯main函數后就只有一個字符串拷貝
查看main函數的匯編代碼,在偏移0x144C處有一條jnz條件跳轉指令,如果[rbp+var_144]非零則跳轉到loc_1455,但是在偏移0x1382處給[rbp+var_144]賦值為0,所以ida反編譯到jnz就判定為不跳轉,進而jmp到loc_14A0即main函數結束處
我們看到loc_1455中偏移為0x146B處調用了sub_11C8函數,根據函數調用約定可知上面拷貝來的字符串作為參數傳入了sub_11C8函數進行處理
于是可以猜測出題人就是想通過上述不執行jnz條件跳轉的方式來隱藏flag
這里我們先去看一下sub_11C8函數,ida分析sub_11C8失敗,先在偏移0x11C8處右鍵->undefine
我們知道函數的開頭一般是push rbp,機器碼為0x55,于是在偏移0x11CD處,按c將數據轉為代碼,再按p創建函數,反編譯后得到
sub_11CD沒看懂什么邏輯,實際上也不需要看懂
出題人通過不執行sub_11CD的方式來隱藏flag,于是我們可以patch程序,將jnz改寫成jz,如圖
保存后,直接運行elf,即可得到flag
或者不patch程序,根據題目的提示,用ida遠程調試elf的時候,在執行jnz之前將零標志位的值修改為0即可將程序流引向執行sub_11CD,進而獲得flag
珍惜生命
.pyc文件,用uncompyle6來反編譯
輸入flag和key,flag長度為51,key長度為8
驗證key經過多元方程組運算后是否與"Syclover"相同,然后輸入的flag中{}中包含的內容與key做循環異或,結果與一個給定的flag元組比較,驗證輸入的flag是否正確
核心在求解key,用z3解多元方程組即可,需要注意兩個地方
1、用BitVec定義變量時需要是16位,筆者開始用8位,一直解不出來
2、此方程組多解,要用while s.check()==sat來輸出多組解,需要的是key的8個值都小于128的一組解
最后key與flag循環異或即可得到flag
flag = [113, 74, 71, 35, 29, 91, 29, 12, 114, 73, 60, 52, 69, 5, 113, 35, 95, 38, 20, 112, 95, 7, 74, 12, 102, 23, 7, 31, 87, 5, 113, 98, 85, 38, 16, 112, 29, 6, 30, 12, 65, 73, 83, 36, 12, 23] key=[0]*8 key[6] = 54 key[1] = 38 key[3] = 99 key[0] = 83 key[7] = 46 key[2] = 121 key[5] = 45 key[4] = 64 for i in range(len(flag)):flag[i]^=key[(i+1)%len(key)] print("SYC{"+"".join(chr(i) for i in flag)+"}") # SYC{W3$c0m3_T0_th3_py_w0r1d_@nd_z3_1s_s0000_g00d!!}new_language
32位.Net程序,dnSpy打開,來到Main
text為輸入,長度為38,將輸入作為下標從sbox中取值,保存到array中,然后array與已知的array2比較
取出sbox和array2,寫逆運算腳本即可得到flag
easypyc
python打包成的exe,用pyinstxtractor腳本解包
uncompyle6反編譯easypyc.pyc失敗,原因是解包后的easypyc.pyc文件魔數被破壞,需要修正正確
此為被破壞的easypyc.pyc文件
想要修正easypyc.pyc需要對照同目錄下的struct.pyc進行修正,如圖
此為修正后的easypyc.pyc文件
保存后再用uncompyle6反編譯
aaaaaaa和bbbbbbbbbb是魔改了一點的RC4,最后異或的時候多異或了一個102,解RC4的時候要加上,密鑰為"Geek2021"
ccccccccc對RC4加密后的密文進行異或運算,結果與tttttt比較
先逆ccccccccc解得正確的RC4密文
再解魔改RC4即可得到flag
#include<stdio.h> void rc4_init(unsigned char* s, unsigned char* key, unsigned long Len_k) {int i = 0, j = 0;char k[256] = { 0 };unsigned char tmp = 0;for (i = 0; i < 256; i++) {s[i] = i;k[i] = key[i % Len_k];}for (i = 0; i < 256; i++) {j = (j + s[i] + k[i]) % 256;tmp = s[i];s[i] = s[j];s[j] = tmp;} }/* RC4加解密函數 unsigned char* Data 加解密的數據 unsigned long Len_D 加解密數據的長度 unsigned char* key 密鑰 unsigned long Len_k 密鑰長度 */ void rc4_crypt(unsigned char* Data, unsigned long Len_D, unsigned char* key, unsigned long Len_k) //加解密 {unsigned char s[256];rc4_init(s, key, Len_k);int i = 0, j = 0, t = 0;unsigned long k = 0;unsigned char tmp;for (k = 0; k < Len_D; k++) {i = (i + 1) % 256;j = (j + s[i]) % 256;tmp = s[i];s[i] = s[j];s[j] = tmp;t = (s[i] + s[j]) % 256;Data[k] = Data[k] ^ s[t]^102; //這里加一個異或102} } void main() {//密鑰unsigned char key[] = "Geek2021";unsigned long key_len = sizeof(key) - 1;//密鑰//unsigned char key[] = {};//unsigned long key_len = sizeof(key);//密文unsigned char data[] = { 34, 87, 28, 210, 186, 225, 87, 69, 104, 210, 181, 143, 128, 51, 105, 175, 135, 170, 87, 83, 3, 64, 181, 140, 38, 18, 59, 220, 71, 155, 93, 161 };//解密rc4_crypt(data, sizeof(data), key, key_len);for (int i = 0; i < sizeof(data); i++){printf("%c", data[i]);}printf("\n");return; } //SYC{Just_a_Eeeeeeasy_Rc4_right?}Brute_force
64位exe,ida打開,go語言,左側函數窗找到main_main
要求運行時加參數,且參數的長度為24
進入main_unnamed630函數,第40行有一個main_encode函數,做了md5散列,返回十六進制摘要
直接在ida中調試一下,斷點下在main_unnamed630函數第49行調用runtime_memequal函數前
參數設置為一段長度為24的字符串,如圖
程序運行后在此處斷下
v15指向我們的輸入經main_encode函數處理返回的十六進制摘要,此時為"e2fc714c4727ee9395f324cd2e7f331f"
v19指向要去比較的長度為32的md5十六進制摘要,此時為"957a3926d4ff16d0d3bac4ed3044537b"
通過在線網站查詢到v15指向的字符串就是我們輸入的前四個字符"abcd"的md5十六進制摘要
那么這題的流程就是將長度為24的輸入分成6組,每組4個字符,對每組進行md5散列,返回散列值的十六進制摘要,與已知的長度為32的md5十六進制摘要比較,從而驗證輸入
每組4個字符,每個字符的ascii碼范圍為[48,128),可爆破,和題目名稱呼應
"957a3926d4ff16d0d3bac4ed3044537b"只是第1組要去比較的md5十六進制摘要,其他5組可通過調試得到
最后全部6組md5十六進制摘要和爆破腳本如下
win32
題目名為win32,實際是個64位的exe,upx脫殼,ida打開
題目描述中提到了base64,猜測可能是變表base64
交叉引用Str2來到sub_140011B80函數,主要邏輯在case 0x111處
輸入傳入sub_1400110F5函數處理,結果放入變量Str1中,與已知的Str2比較,驗證輸入
進入sub_1400110F5->sub_140011F90
sub_140011F90函數構造了一個表,和標準的base64表是一樣的,下面就是正常的base64算法
直接解Str2的base64即可得到flag
wasm
wasm逆向參考:一種Wasm逆向靜態分析方法
使用wasm2c將.wasm文件轉為.c文件,對.c文件用gcc只編譯不鏈接得到.o文件
ida分析.o文件,w2c_main->w2c_f11
大概的邏輯如下圖,判斷輸入的長度是否等于22,w2c_f10對輸入進行變換,w2c_f9對變換后的輸入進行比較驗證
進入w2c_f10函數,唯一的參數就是我們的輸入
看到循環體里有一個異或0x66的運算,結合題目文件名xorwasm,這個異或0x66的運算可能有很大作用
之前猜測w2c_f9是對變換后的輸入進行比較驗證的函數,但是跟進去分析并沒有找到最后要去比較的數據
參考博客里寫道,“對于wasm,所有的字符串會被存放在二進制文件的末尾,以此能獲取一些關鍵的信息”
而且在ida字符串窗口中也能找到一些明文字符串
在Hex View中找到這些明文字符串,可以看到在"infinity"這個有意義的單詞前正好有22個數據,猜測這些數據就是最后要去比較的數據
直接取出這22個數據,異或0x66后即可得到flag
猜拳
64位exe,加了upx殼,但是工具脫不掉殼
根據提示"API斷點"猜測可能是通過調試器對按鈕相關的API下斷點,程序停下來后修改寄存器的值,從而改變程序執行流,得到flag
程序直接扔進x64dbg,然后F9會被程序檢測到調試器從而結束進程
這時我們先運行程序,然后讓x64dbg去附加(attach)到運行中的程序
附加成功后,右鍵->搜索->所有模塊->字符串
可以發現一些明文字符串
雙擊字符串"Congratulations on getting the flag"(相當于ida中的交叉引用),找到引用該字符串的指令
我們看到該字符串的上方有一條"Sycl0v3r"的字符串,還有一條"call re.7FF7A77E13D8"的指令
多次調試發現,程序將"Sycl0v3r"作為密鑰傳入0x7FF7A77E13D8處的函數,對密文進行解密,返回flag
在上圖標紅處,即"00007FF7A77E1567"處,右鍵->設置新的運行點,將rip設置到此處
隨后F8單步步過,在"call re.7FF7A77E13D8"這條指令執行后即可得到flag
have_a_tea
64位ELF,start函數中存在SMC,在偏移0x1A2F處下斷點
啟動調試,程序斷下來后,F8來到偏移0x0870處
再多按幾次F8,來到偏移0x1361處
之后可以不用按F8,往下走,來到偏移0x14C6處,可以看到"db 55h"
我們知道"push rbp"的機器碼為0x55,于是這里就是一個函數的起始地址
在偏移0x14C6處按c,將數據轉成代碼,再按p創建函數,然后F5反編譯
sub_55C97B2014C6->sub_55C97B2012BD,可以看到程序正常運行時會打印的字符串
進入sub_55C97B2010B7函數,分析可知
程序對輸入進行CBC模式的TEA加密,已知iv和key,密文為res
筆者沒有CBC模式的TEA解密腳本,只能先對密文解TEA,然后按CBC模式加密思路來逆CBC
對密文解TEA:
按CBC模式加密思路來逆CBC
from Crypto.Util.number import long_to_bytes res=[0xc9fa3b95,0x7cfd0735,0x958c7c9f,0xc143b59e,0x61741e89,0xf47dcdc4,0xd6e2a1f2,0x6a38e9ad,0xc2c16feb,0x8c0ee999] iv=[0]*10 iv[0]=0x5f797274 iv[1]=0x64726168 for i in range(8):iv[i+2]=res[i] plain=[0x243a2b27,0x1d133211,0x8d945ac6,0x2393665c,0xfbbc14c5,0x9e22f9c1,0x3e1a2ff0,0xab1ca587,0xb883e88a,0x683ae9d0] flag="" for i in range(10):flag+=long_to_bytes(plain[i]^iv[i])[::-1] print(flag) # SYC{ySaySanDian_Zh0n_La_y1n_Cha_xIan}總結
以上是生活随笔為你收集整理的REVERSE-COMPETITION-GeekChallenge2021的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 法拉利告别内燃机
- 下一篇: 使用 hexo-git-backup 插