SSHCTF--RE--WP(自存)
SSHCTF復現
0x01 Check your IDA
知識點:IDA pro的基礎使用方法
做法:
把文件拖進ida,在functions windows欄control+F,搜索main函數。再對main函數點擊f5進入偽代碼窗口,直接可以得到flag

0x02 baby xor
知識點:異或運算
做法:
無殼,拖進ida,找到main函數,進入偽代碼窗口,審計代碼

雙擊變量byte_40B040,可以查看具體內容

可以看到aSshctfX0rKey的內容是
'sshctf&X0R_key';
byte_40B040的內容為
32h, 20h, 32h, 20h, 32h, 20h, 4Fh, 1, 4Dh, 27h, 12h, 0, 47h, 17h, 16h, 2Ch, 22h, 53h, 14h, 39h, 5, 2Bh, 7Dh, 26h, 25h, 0Eh, 28h, 1Bh, 4, 0, 0Eh, 3Ch, 23h, 3Ch, 6Bh, 2Ah, 47h, 24h, 28h, 19h, 4, 48h, 0Fh, 14h, 7, 13h
程序使用密鑰對當前字符進行異或操作,如果索引是偶數,再與0x12進行異或操作。
為了便于操作,讓kimi(?幫我們把上述內容轉化為對應的ASCII碼,則
sshctf&X0R_key=115, 115, 104, 99, 116, 102, 38, 88, 48, 82,95, 107, 101, 121
byte_40B040=50, 32, 50, 32, 50, 32, 79, 1, 77, 39,18, 0, 71, 23, 22, 44, 34, 83, 20, 57,5, 43, 125, 38, 37, 14, 40, 27, 4, 0,14, 60, 35, 60, 107, 42, 71, 36, 40, 25,4, 72, 15, 20, 7
用cpp復現,如下
int main() {
std::vector<int> arr = {
50, 32, 50, 32, 50, 32, 79, 1, 77, 39,
18, 0, 71, 23, 22, 44, 34, 83, 20, 57,
5, 43, 125, 38, 37, 14, 40, 27, 4, 0,
14, 60, 35, 60, 107, 42, 71, 36, 40, 25,
4, 72, 15, 20, 7
};
std::vector<int> Str = {
115, 115, 104, 99, 116, 102, 38, 88, 48, 82,
95, 107, 101, 121
};
for (size_t i = 0; i < arr.size(); ++i) {
if (i % 2 == 0) {
arr[i] ^= 0x12;
}
arr[i] ^= Str[i % Str.size()];
}
std::string result;
for (int a : arr) {
result += static_cast<char>(a);
}
std::cout << result << std::endl;
return 0;
}
運行即可拿到flag
SSHCTF{You_k0nw_X0r_1s_the_best_EZ_revers1ng}
0x03 baby crack
知識點:位移、位運算加密
無殼,直接拖ida,找到main,查看偽代碼

可看到變量str的開頭是SSHCTF,應該就是flag,且長度為38,繼續看看到了sub_401550函數,進去看看

函數通過種子0xDEADBEEF生成37個在0-254之間的固定隨機數。
v2 = *(unsigned __int8 *)(v7 + i)是讀取 v7 + i 地址處的一個字節值,并存儲在 v2 中
v3 = v2 >> (Str[v5 % strlen(Str)] % 8):計算 v2 右移 Str 中指定位置字符的值(模8)的結果,存儲在 v3 中
*(_BYTE *)(v7 + i) = ((_BYTE)v2 << (8 - Str[v5 % strlen(Str)] % 8)) | v3;:對 v2 進行左移操作,并將結果與 v3 進行或運算,然后將結果存儲回 v7 + i 地址處。
*(_BYTE *)(v7 + i) ^= *(_BYTE *)(i + 1i64 + v7);:對 v7 + i 地址處的字節值與 v7 + i + 1 地址處的字節值進行異或操作,并將結果存儲回 v7 + i 地址處。
if ( ((unsigned __int8)(v5 & *(_BYTE *)(v7 + i)) | ~(v5 | *(unsigned __int8 *)(v7 + i)) | 7) > 63 ):一坨條件判斷。
v4 = *(_BYTE *)(v7 + i);:將 v7 + i 地址處的字節值存儲在 v4 中。
*(_BYTE *)(v7 + i) = (i & 0x12 | Str[i % strlen(Str)]) & 0x3F ^ v4;:進行一系列的位運算,并將結果存儲回 v7 + i 地址處。
(能力有限,加密過程分析部分借助了ai)
反復讀n遍代碼,基本理解了加密過程(?真的嗎),準備逆一下試試
先用C生成種子0xDEADBEEF的隨機數列(模255)(注意 只能用C來生成)
int main() {
int i;
unsigned int seed = 0xDEADBEEF;
srand(seed);
for (i = 0; i < 37; ++i) {
int random_number = rand()%255;
printf(",%u",random_number);
}
return 0;
}
得到隨機數組:
232,90,117,135,98,176,175,24,8,123,84,245,112,135,139,71,23,72,4,144,110,181,55,140,156,151,75,136,53,253,7,32,95,73,116,219,63
再查看變量數據,得到:
aSshctfkey=SSHCTFkey
byte_40F040=201, 34, 74, 60, 108, 98, 249, 249, 111, 177,146, 73, 118, 241, 190, 203, 137, 113, 40, 169,115, 82, 249, 180, 94, 254, 243, 132, 199, 61,235, 137, 117, 190, 106, 61, 19, 125
數據齊全,開始寫python腳本(注釋里有重要語句的功能)
key = "SSHCTFkey"
flag = [201, 34, 74, 60, 108, 98, 249, 249, 111, 177,
146, 73, 118, 241, 190, 203, 137, 113, 40, 169,
115, 82, 249, 180, 94, 254, 243, 132, 199, 61,
235, 137, 117, 190, 106, 61, 19, 125]
len_a2 = len(a2)
a1 = flag
a2 = [ord(k) for k in key] ##這里沒見過,去查了知道是儲存字符的Unicode代碼點(與ascii碼值相等)
random = [232, 90, 117, 135, 98, 176, 175, 24, 8, 123,
84, 245, 112, 135, 139, 71, 23, 72, 4, 144,
110, 181, 55, 140, 156, 151, 75, 136, 53, 253,
7, 32, 95, 73, 116, 219, 63]
for i in reversed(range(37)): #python腳本中v3對應源碼v5;a1對應源碼*(v7 + i);xor_a1對應源碼v4;a2對應源碼str
v3 = random[i]
xor_a1 = a1[i] ^ (i & 0x12 | a2[i % len(a2)] & 0x3F) #這一步恢復的是(v7 + i) = (i & 0x12 | Str[i % strlen(Str)]) & 0x3F ^ v4中的v4
if ((v3 & xor_a1) | ~(v3 | xor_a1) | 7) > 63:
a1[i] = xor_a1 #這里逆向if ( (v5 & (v7 + i)) | ~(v5 | (v7 + i)) | 7) > 63 ):v4 = (v7 + i),恢復了*(v7+1)
#后面的逆向也是同理
a1[i] ^= a1[i + 1]
c = a2[v3 % len(a2)] % 8
a1[i] = (a1[i] >> (8 - c)) | (a1[i] << c)& 0xFF
print("".join([chr(a) for a in a1]))
運行腳本,得到flag
SSHCTF{N0w_y0u_Kn0w_B1twise_op3r@t0rs}
0x04 Let's go to learn Cry
知識點:aes加密,base64加密(補 自學了一些python基礎語法用來寫腳本 QAQ)
無殼,拖ida

可以獲取的信息: key=9e015a9f82d367bc
查看enc_flag變量
內容為KKN+NK5ZWN4xr4kM1+qq+2wJKUEEaiWmITgnvi2VaXfjscLoN2sbUObWbnc45pZr(看代碼 經過了base64編碼)
進入Cry_Encrypt函數,看到有一個變量名字是AesKey,大概率是aes加密

此處去了解一下python中的AES模塊
AES.new(key, AES.MODE_ECB):創建一個新的AES加密對象
aes.decrypt(ciphertext):使用AES對象來解密
嘗試用新鮮剛學一點的python寫腳本(?
然后在意想不到的地方坐牢了,先是pip2和pip3兼容出了點問題,然后pip install pycryptodome之后,在pycharm里還是沒有導入這個庫,費了點時間才搞好
總之最后的腳本:
from Cryptodome.Cipher import AES
import base64
key=b'9e015a9f82d367bc'
aes_decode_flag='KKN+NK5ZWN4xr4kM1+qq+2wJKUEEaiWmITgnvi2VaXfjscLoN2sbUObWbnc45pZr'
aesed_flag=base64.b64decode(aes_decode_flag)
aes_decode=AES.new(key,AES.MODE_ECB)
flag=aes_decode.decrypt(aesed_flag)
print(flag)
運行得到flag
SSHCTF{Crypt0_1n_R3v3rs3_1s_so000oo0_Imp0rt@nt!}
@"Pinguw"#116
Q1:怎么判斷aes的mode是ECB還是其他模式
Q2:我需不需要去看看crypto,感覺re題好多加密(所以聯想到了crypto>_<)
0x06 flower
知識點:花指令
無殼,拖進ida,main無法f5反編譯
對main按P(編輯為函數,將從光標位置開始的代碼識別為函數,IDA將自動分析)
查看報錯
.text:004010A2: The function has undefined instruction/data at the specified address.
Your request has been put in the autoanalysis queue.
雙擊跳到.text:004010A2
pic 7
jnz short near ptr byte_4010A2:如果上一條test的結果不為零,則跳轉到地址004010A2處的標簽byte_4010A2。由于byte_4010A2是一個數據定義(db 0C7h),這個跳轉通常不會執行任何有意義的操作,因此這條指令可能是一個花指令。
0x05 SMC
知識點:SMC,動態調試
無殼,拖進ida,進入main函數
pic
進入sub_140001280,發現了VirtualProtect,結合題目,應該是是smc問題,需要動態調試
(SMC指的是Self-Modifying Code,即自修改代碼。程序在運行時會修改自己的代碼或數據,這樣做可以阻止他人直接進行靜態分析。)
找到自加密的部分,發現sub_1400011C0的數據是一些奇怪的東西
pic 9
繼續讀sub_140001280,v2是VirtualProtect的結果,所以在return v2處設置斷點
debugger啟動(此處跑去學idebugger的用法)
從0x1400011C0選中到0x14000127E這整個一段。按u回到字節文本狀態,再回到這一段的開頭,按p重新編譯,f5拿到了正確的sub_1400011C0函數,
Q:沒太明白這里重編譯的原理是啥,大體流程是程序執行到斷點,然后對0x1400011C0到0x14000127E這一段--->文本--->編譯,為什么這樣就會編譯正確,但是之前不會捏(是因為這個時候還沒有自加密嗎?),以及為什么是選中0x1400011C0到0x14000127E這一段
pic 10
分析可以知道flag=str^0x23,寫腳本拿到flag
str=b'EOBDXZFP|V|GL|JW^'
print("".join([chr(i ^ 0x23) for i in str]))
#flag{yes_u_do_it}
0x06 maze
知識點:迷宮類型的題
無殼,拖入ida,
main-->sub_1257-->sub_13D3 (圖里自己改了變量名字方便理解)

語句if ( byte_4020[225 * dword_42C8 - 15 + 15 * dword_42CC + dword_42D0] == 1 ):
計算 byte_4020 數組的一個索引,并檢查該索引處的值是否為1。
如果該值是1,將該索引處的值改為3,將另一個索引處的值改為1。
如果該值不是1,檢查它是否為4,如果該值是4,函數返回 1LL(long long的1)。
如果dword_42CC為0,或者byte_4020數組中指定索引的值既不是1也不是4,函數返回 0LL。
可以猜測到,3是當前位置,1是路,4是重點,0是障礙物
查看數組byte_4020,shift+e,共有675個字符,里面有3個4,即為3個終點,所以是15*15的3個迷宮(迷宮要自己判斷,交給ai它會騙人,比如它告訴我迷宮一共有256個字符……)
第一個迷宮:
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 3 1 1 0 0 0 0 0 0
1 1 1 1 1 0 0 0 1 0 0 0 0 0 0
1 1 1 1 1 0 0 0 1 0 0 0 0 0 0
1 1 1 1 1 0 0 0 1 1 1 1 1 0 0
1 1 1 1 1 0 0 0 0 0 0 0 1 0 0
1 1 1 1 1 0 0 0 0 0 0 0 1 0 0
1 1 1 1 1 0 0 0 0 0 0 0 1 1 0
1 1 1 1 1 0 0 0 0 0 0 0 0 1 0
1 1 1 1 1 0 0 0 0 0 0 0 0 4 0
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
第二個迷宮:
1 1 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 0 3 1 1 1 1 1 0 0 0 0 0 0
1 1 0 1 1 0 0 0 1 0 0 0 0 0 0
1 1 0 0 0 0 0 0 1 0 0 0 0 0 0
1 1 0 1 1 0 0 0 1 1 1 1 1 0 0
1 1 0 1 1 0 0 0 0 0 0 0 1 0 0
1 1 0 1 1 0 0 0 0 0 0 0 1 0 0
1 1 0 1 1 0 0 0 0 0 1 1 1 1 0
1 1 0 1 1 0 0 0 0 0 1 0 0 1 0
1 1 0 1 1 0 0 0 0 0 1 0 0 0 0
1 1 0 1 1 1 1 1 1 0 1 0 1 1 0
1 1 0 1 1 1 1 1 1 1 1 1 1 1 0
1 1 0 0 0 0 0 0 0 0 0 0 0 4 0
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
第三個迷宮:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 3 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 1 1 1 0 0 0 0 0 0 0
0 0 0 1 1 1 0 1 0 0 0 0 0 0 0
0 0 0 0 1 0 0 1 0 0 0 0 0 0 0
0 1 1 0 1 0 0 1 0 0 0 0 0 0 0
0 0 1 1 1 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 1 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 4 0
得到了迷宮之后,應該確定輸入什么字符去控制這個迷宮走向,
在sub_1257中可以發現,條件判斷中v1的值分別為119,115,100,97,27,對應的ASCII字符分別為w、a、s、d和esc

那么上下左右分別對應w、s、a、d。
現在我們已經有了迷宮內容,走迷宮的方法,接下來手動解出迷宮即可。
1 : 'ddsssddddsssdss'
2 : 'dddddsssddddsssaassssddds'
3 : 'ddssddwddssssssdddssssdddss'
根據程序輸出內容"success! the flag is flag{md5(your input)}"可以知道flag需要經過md5加密
寫腳本拿flag
import hashlib
s1 = 'ddsssddddsssdss'
s2 = 'dddddsssddddsssaassssddds'
s3 = 'ddssddwddssssssdddssssdddss'
print('SSHCTF{' + hashlib.md5((s1+ s2 + s3).encode('utf-8')).hexdigest() + '}')

浙公網安備 33010602011771號