bad_python
看樣子是pyc文件損壞了。利用工具打開,發現是MAGIC壞了。搜下也沒有頭緒。
攻防世界-難度1- bad_python - _rainyday - 博客園
python Magic Number對照表以及pyc修復方法 - iPlayForSG - 博客園
看WP才知道36已經提示了pyc版本了。參考第二個文章,除了魔法數字還有8字節的額外信息。
但是我填充之后還是bad magic,再看看WP咋說的。原來代表文件大小的地方還不能為0.也就是第12個字節。
我們只需要修復一下就可以了。 媽的,用FF也不行,看來必須中規中矩才行。用E5成功了。、
?識別出是XTEA加密,寫出解密即可。后期我這又出問題了,這一步就不搞了吧
ereere
左邊沒有main了,依據start必定會出現main函數,一個個點找到了疑似main的函數。
base64換表+RC4。思路同攻防世界RE_ereere_攻防世界ereere-CSDN博客
用cyberchef解決的
easyEZbaby_app
定位到關鍵代碼。主要看checkpass和checkUsername函數
首先是username,密碼是zhishixuebao的MD5,以2為步長取。結果是:7afc4fcefc616ebd
pass則是如下。長度顯然是15位,注意算法要求是char數組=0,說明賦值等式右邊值是0(也就是48)。寫出Python代碼即可。
a=''
for i in range(15):a+=chr(((255 - i) + 2) - 98-48)
print(a)
toddler_regs?
導入pdb文件,放進IDA分析。
持續跟蹤,首先看到stage1,要求參數必須是要求的值,只能動調修改這個參數。
但是看起來沒啥用啊,看看stage2.
發現stage1的用處了,他會把黃框部分設置為23.我們直接找到這個對應的值即可。注意team是個字符串數組,我們導出來看看,直接在C里面運行吧。
第一個team輸出了:0Int
第二個代碼和上面一樣,結果是:nTJnU
組合起來就是flag{0Int_1s_n1c3_but_nTJnU_is_we1rd}
上面顯然是錯誤的,可能會遇到這個地方剛好是\0直接截斷。保險的做法是先定義好數組大小(如char[512][10],再直接去掉&運行即可)
exp:
也可以動調做,我電腦不知為何運行不起來這個軟件,只能靜態分析了。
easyre-xctf
看題目簡介估計有殼。是UPX原版殼,官方工具就可以脫殼了。
但并沒有明顯的算法,只在字符部分看到了疑似flag的后半段。雙擊這里有一個符號名part2。
動調看看有沒有提示,拿拿數據。
在內存發現了疑似的部分
根據其地址定位到函數,這就是第一個flag。函數名字有個part1,對應著part2.兩個16進制轉換為字符后就是part1.
七分靠猜,這里有運氣成分,正常來說估計得搜part1了。
CatFly(還沒有寫出來)
看主函數很復雜。慢慢來看吧。
運行出來是個這,輸入的東西會在左下角顯示。那么main函數有的部分就可以不看了。
看到一個提示:
要記住逃逸密碼??
難道是迷宮,分析這部分,\x1Bxxx是終端轉義啊,看著是打印圖形用的。
百思不得姐,還是看看WP吧。
re學習(29)攻防世界-CatFly(復原反匯編)_攻防世界catfly-CSDN博客
粗略瀏覽下發現沒有我想要的,不過突然想到可以給main函數拷貝到VC,刪去已知功能的函數再仔細分析看看。
暫時跳過,下次再看。
IgniteMe
跟進到主函數。
首先str長度需要大于4.
先來一個循環把str循環復制給v7。后兩個if判斷意思是大寫轉小寫,小寫轉大寫。
最關鍵的在后院嗎,str2我們已經知道了,這就是目標。byte我們也知道,目標就是求v7。接下來的sub_4013c0跟進一下。
?是一個表達式,相當于v7^0x55+72.那就很明顯了,寫出對應exp:
str2='GONDPHyGjPEKruv{{pj]X@rF'
byte=[ 0x0D, 0x13, 0x17, 0x11, 0x02, 0x01, 0x20, 0x1D, 0x0C, 0x02, 0x19, 0x2F, 0x17, 0x2B, 0x24, 0x1F, 0x1E, 0x16, 0x09, 0x0F, 0x15, 0x27, 0x13, 0x26, 0x0A, 0x2F, 0x1E, 0x1A, 0x2D, 0x0C, 0x22, 0x04]
flag=''
#根據str2猜測長度是24
for i in range(24):flag+=chr(((byte[i]^ord(str2[i]))-72)^0x55)
print(flag)
print(flag.lower())
出來的flag都是大寫,不要忘記兩個if判斷是大寫轉小寫小寫轉大寫,因此再次轉為小寫即可
BABYRE
main函數看著很簡單
需要注意:在 C 語言中,(*judge)(s)
?這種語法表示通過函數指針調用函數。在 C 語言中,函數名本質上是指向函數代碼起始地址的指針。可以將這個地址存儲在一個函數指針變量中,然后通過該變量調用函數。
也就是說這是一段自修改代碼。judge是函數,需要解密這段judge。
先用AI生成(因為我不太會IDA python)一段解密的腳本在IDA運行,然后C--P加載為函數即可
import idautils
import idaapibase = 0x600b00# 處理182個字節(與原始代碼一致,0到181共182次)
for i in range(182):# 讀取原始字節original_byte = idaapi.get_byte(base + i)# 異或解密decrypted_byte = original_byte ^ 0xC# 寫入解密后的字節idaapi.patch_byte(base + i, decrypted_byte)# 標記為數據(這一行刪了就行)無用idaapi.create_data(base + i, FF_BYTE, 1, idaapi.BADADDR)print(f"已解密 {base:X} 開始的182個字節")
再次從main函數進入judge即可了。?直接點進去judge好像部分代碼還是錯誤,重新從main進去就好了。
這個加密邏輯就很明顯了。
a='fmcd\x7Fk7d;V`;np'
flag=''
for i in range(len(a)):flag+=chr(ord(a[i])^i)
print(flag)
parallel-comparator-200
這一題直接給了C代碼。有點意思。
注意到代碼的flag_len是20.
首先認識一個新函數
逐步分析,main函數調用了下圖的highly_.....函數。
跟進此函數。根據is_ok的判斷條件,著重關注此部分,說明result值是0.因為is_ok的條件為generated==just_a_string。
查找用到result的地方。注意到只有first_letter未知,user_string是我們的目標。
最后一行代碼實際上經過上文知識點鋪墊,調用了checking函數。
由于result==0,說明argument[0]+argument[1]嚴格相等于argument[2]。會循環20次這個checking函數(因為pthread_creat函數在for循環內部循環了20次)
0我們不知道,(起碼知道是某個小寫字母)2是目標,1知道了。而且2就等于1+0.但是這還不太夠啊,看看還有沒有其余條件,似乎沒了。
先嘗試寫一個爆破腳本試試。這里要注意,一定要多生成幾個flag,因為不同的frist_letter對應不同的flag,我們試著a~z都搞一遍。第一次沒想到這樣遍歷。而且代碼美觀不如豆包寫的,還得多寫多練。
、注意{}是占位符,可以寫任意的表達式。
a = [0, 9, -9, -1, 13, -13, -4, -11, -9, -1, -7, 6, -13, 13, 3, 9, -13, -11, 6, -7]# 嘗試所有可能的基準值b (97-122)
for base in range(97, 123):flag = []valid = Truefor i in a:char_code = base + iif 32 <= char_code <= 126:flag.append(chr(char_code))else:valid = Falsebreak # 這個基準值無效if valid:print(f"基準值 {chr(base)} ({base}): {''.join(flag)}")
發現flag?
很讓我開心的是我找到了大致思路!哈哈哈哈哈。只是腳本功底還比較薄弱。
secret-galaxy-300
注意到程序是打印了類似于星球的東西。
但是觀察函數發現其實并沒有完全打印出來,a1這個數組的部分內容并沒有完全用到,所以我打算動調拿一波數據看看。
動調看a1并沒發現明顯的字符串
攻防世界逆向高手題之secret-galaxy-300-CSDN博客
看了別人的wp,反思一下,還是思路錯了,這時候可以結合題目的提示,隱藏的星系,確實發現一個沒有被打印出來的星系,點擊ctrl+x查看交叉引用:
(而且我說為啥有三個代碼差不多的文件,原來對應不同平臺)
其實這里就可以看出來這估計就是flag了,這里偷了個懶,使用了AI。
# 定義各個星系名稱字符串
ngs_2366 = "NGS 2366"
andromeda = "Andromeda"
messier = "Messier"
sombrero = "Sombrero"
triangulum = "Triangulum"
dark_secret_gala = "DARK SECRET GALAXY"# 將各個星系名稱轉換為字符列表,方便按索引取值
galaxy_strings = {"ngs_2366": list(ngs_2366),"andromeda": list(andromeda),"messier": list(messier),"sombrero": list(sombrero),"triangulum": list(triangulum),"dark_secret_gala": list(dark_secret_gala)
}def build_result_string():"""構建結果字符串"""result_chars = [galaxy_strings["andromeda"][8],galaxy_strings["triangulum"][7],galaxy_strings["messier"][4],galaxy_strings["andromeda"][6],galaxy_strings["andromeda"][1],galaxy_strings["messier"][2],'_',galaxy_strings["andromeda"][8],galaxy_strings["andromeda"][3],galaxy_strings["sombrero"][5],'_',galaxy_strings["andromeda"][8],galaxy_strings["andromeda"][3],galaxy_strings["andromeda"][4],galaxy_strings["triangulum"][6],galaxy_strings["triangulum"][4],galaxy_strings["andromeda"][2],'_',galaxy_strings["triangulum"][6],galaxy_strings["messier"][3]]return ''.join(result_chars)# 直接構建并打印結果字符串
print("構建的結果字符串:", build_result_string())
其實直接動調很快
simple-check-100
打開也是三個文件,有了前面的經驗,這里面的代碼一定是一樣的
不如直接打開exe,動調起也方便
懷疑這部分的result就是最終的flag。
為了便于調試分析,我想使用動調的方法來做這道題。目前有兩個思路,一個是直接改匯編代碼,讓這個條件強制為真,另一個是利用check_key來找v8的值,但是很遺憾看代碼這個是v7地址對應的數組,估計不方便尋找和爆破。方便起見,先直接改匯編代碼看看。
好吧,這種思路看著不太行的樣子。OD出來的是亂碼。估計是GBK編碼不可以處理,這個估計不是GBK編碼,
需要注意用X32得用管理員模式,剛才我patch了估計就是沒管理員模式,他不認,IDA動調的patch估計沒有靜態的好使,patch了還是說wrong.
參考了攻防世界-simple-check-100_攻防世界 simple-check-100-CSDN博客看來這種動調還是找專業的調試器吧
我看人家都是用GDB動調的。linux估計不亂碼。
新學的調試指令:set $eax=1
這里需要注意在這里改:,估計箭頭跑到這里意思就是這個指令執行完畢了已經。
果不其然出來了flag。
接下來試試靜態分析
注意參數本來是字符,搞成了int,因此本來一字節,導致合并為4字節。
還要注意這是一個嵌套for循環。?
這借鑒了攻防世界 simple-check-100(非常好的一篇wp,日后還得多多觀看,受益匪淺)-CSDN博客
#include <stdio.h>
int main(int argc, char *argv[])
{unsigned char flag_data[] = {220, 23, 191, 91, 212, 10, 210, 27, 125, 218,167, 149, 181, 50, 16, 246, 28, 101, 83, 83,103, 186, 234, 110, 120, 34, 114, 211};char v7[] = {84, -56, 126, -29, 100, -57, 22, -102, -51, 17,101, 50, 45, -29, -45, 67, -110, -87, -99, -46,-26, 109, 44, -45, -74, -67, -2, 106};unsigned int v2;unsigned char *v3;// v11 = -478230444;// v12 = -1709783196;// v13 = 845484493;// v14 = 1137959725;// v15 = -761419374;// v16 = -752063002;// v17 = -74;// v18 = -67;// v19 = -2;// v20 = 106;// 方法一:類比寫for (int i = 0; i <= 6; ++i){v2 = ((v7[4 * i] & 0x000000FF) + ((v7[4 * i + 1] & 0x000000FF) << 8) + ((v7[4 * i + 2] & 0x000000FF) << 16) + ((v7[4 * i + 3] & 0x000000FF) << 24)) ^ 0xDEADBEEF;v3 = (unsigned char *)&v2;for (int j = 3; j >= 0; --j){printf("%c", *(v3 + j) ^ flag_data[4 * i + j]);}}// 方法二:按位異或,小端字節序,低位在低地址// for (int i = 0; i <= 6; ++i) {// printf("%c", v7[4 * i + 3] ^ 0xDE ^ flag_data[4 * i + 3]);// printf("%c", v7[4 * i + 2] ^ 0xAD ^ flag_data[4 * i + 2]);// printf("%c", v7[4 * i + 1] ^ 0xBE ^ flag_data[4 * i + 1]);// printf("%c", v7[4 * i] ^ 0xEF ^ flag_data[4 * i]);// }return 0;
}
代碼分析:
v2
?的計算邏輯這行代碼的核心是?將 4 個有符號字節組合成一個 32 位無符號整數,然后與?
0xDEADBEEF
?進行異或運算。讓我逐步拆解這個過程:1. 為什么需要?
& 0x000000FF
?
v7
?是一個?有符號字符數組(char v7[]
),其中的負數(如?-56
)在內存中以補碼形式存儲(例如?-56
?的補碼是?0xC8
,即十進制的?200
)。問題:當將有符號數擴展為更大的類型(如?
int
)時,符號位會被保留。例如:
v7[1]
?的值是?-56
(二進制?0xC8
),如果直接轉換為?int
,會變成?0xFFFFFFC8
(因為符號位擴展)。這會導致后續的位運算(如?
<< 8
)結果錯誤。解決方法:通過?
& 0xFF
?將其截斷為無符號字節:
-56 & 0xFF
?→?0xC8
(十進制?200
),確保高 24 位為?0
。2. 為什么要進行位移操作(
<< 8
,?<< 16
,?<< 24
)?這是?小端序(Little Endian)字節組合?的過程:
假設有 4 個字節?
b0, b1, b2, b3
,對應的索引為?4*i
?到?4*i+3
。在小端序中,低字節存放在低地址,高字節存放在高地址。因此,組合成 32 位整數的公式是:
plaintext
value = b0 + (b1 << 8) + (b2 << 16) + (b3 << 24)
示例:
假設?v7[4*i]
?到?v7[4*i+3]
?的值為?[84, -56, 126, -29]
(即?[0x54, 0xC8, 0x7E, 0xE3]
):
v7[4*i] & 0xFF
?→?0x54
(低字節)
v7[4*i+1] & 0xFF
?→?0xC8
v7[4*i+2] & 0xFF
?→?0x7E
v7[4*i+3] & 0xFF
?→?0xE3
(高字節)組合后的值:
0xE37EC854
(注意字節順序顛倒,符合小端序)。
主要是因為將字符指針弄成整數的,再加上端序轉換,搞得很麻煩。?
re1-100
開局這些都是反調試
函數功能與原理
管道概念:管道是一種進程間通信(IPC,Inter - Process Communication)機制,用于在具有親緣關系(如父子進程)的進程間傳遞數據。它本質上是一個特殊的文件,遵循先進先出(FIFO)原則。
函數作用:在許多編程語言和系統(如 C、C++ 等基于 POSIX 標準的系統編程中),
pipe
?函數用于創建一個匿名管道。pipe
?函數通常接受一個包含兩個文件描述符的數組作為參數(這里?pParentWrite
?應該是數組首地址),其中一個文件描述符用于讀取管道數據(通常是數組的第一個元素,記為?fd[0]
),另一個用于向管道寫入數據(通常是數組的第二個元素,記為?fd[1]
- 成功時:返回?0。
- 失敗時:返回?-1,并設置?
errno
?來指示具體錯誤類型。
由此我們已經知道pparentread/pparentwrite都是什么意思。
這個代碼大概意思就是判斷輸入的是不是完整。根據我的判斷。?