逆向初学者做题记录3.28
[ACTF新生賽2020]rome
查殼
ida打開,通過字符窗口(按shift+F12)找可疑字符
int func() {int result; // eaxint v1; // [esp+14h] [ebp-44h]int v2; // [esp+18h] [ebp-40h]int v3; // [esp+1Ch] [ebp-3Ch]int v4; // [esp+20h] [ebp-38h]unsigned __int8 v5; // [esp+24h] [ebp-34h]unsigned __int8 v6; // [esp+25h] [ebp-33h]unsigned __int8 v7; // [esp+26h] [ebp-32h]unsigned __int8 v8; // [esp+27h] [ebp-31h]unsigned __int8 v9; // [esp+28h] [ebp-30h]int v10; // [esp+29h] [ebp-2Fh]int v11; // [esp+2Dh] [ebp-2Bh]int v12; // [esp+31h] [ebp-27h]int v13; // [esp+35h] [ebp-23h]unsigned __int8 v14; // [esp+39h] [ebp-1Fh]char v15; // [esp+3Bh] [ebp-1Dh]char v16; // [esp+3Ch] [ebp-1Ch]char v17; // [esp+3Dh] [ebp-1Bh]char v18; // [esp+3Eh] [ebp-1Ah]char v19; // [esp+3Fh] [ebp-19h]char v20; // [esp+40h] [ebp-18h]char v21; // [esp+41h] [ebp-17h]char v22; // [esp+42h] [ebp-16h]char v23; // [esp+43h] [ebp-15h]char v24; // [esp+44h] [ebp-14h]char v25; // [esp+45h] [ebp-13h]char v26; // [esp+46h] [ebp-12h]char v27; // [esp+47h] [ebp-11h]char v28; // [esp+48h] [ebp-10h]char v29; // [esp+49h] [ebp-Fh]char v30; // [esp+4Ah] [ebp-Eh]char v31; // [esp+4Bh] [ebp-Dh]int i; // [esp+4Ch] [ebp-Ch]v15 = 81;v16 = 115;v17 = 119;v18 = 51;v19 = 115;v20 = 106;v21 = 95;v22 = 108;v23 = 122;v24 = 52;v25 = 95;v26 = 85;v27 = 106;v28 = 119;v29 = 64;v30 = 108;v31 = 0;printf("Please input:");scanf("%s", &v5);result = v5;if ( v5 == 65 ){result = v6;if ( v6 == 67 ){result = v7;if ( v7 == 84 ){result = v8;if ( v8 == 70 ){result = v9;if ( v9 == 123 ){result = v14;if ( v14 == 125 ){v1 = v10;v2 = v11;v3 = v12;v4 = v13;for ( i = 0; i <= 15; ++i ){if ( *((_BYTE *)&v1 + i) > 64 && *((_BYTE *)&v1 + i) <= 90 )// 對大寫的字母進(jìn)行下面的加密*((_BYTE *)&v1 + i) = (*((char *)&v1 + i) - 51) % 26 + 65;if ( *((_BYTE *)&v1 + i) > 96 && *((_BYTE *)&v1 + i) <= 122 )// 對小寫的字母進(jìn)行下面的加密*((_BYTE *)&v1 + i) = (*((char *)&v1 + i) - 79) % 26 + 97;}for ( i = 0; i <= 15; ++i ){result = (unsigned __int8)*(&v15 + i);if ( *((_BYTE *)&v1 + i) != (_BYTE)result )return result;}result = printf("You are correct!");}}}}}}return result; }在寫腳本的時候,一定要注意取余運(yùn)算,這個運(yùn)算在逆向的時候比較麻煩,比較好的方法是枚舉,
觀察這個取余運(yùn)算的數(shù),65(A的ASCII碼)、97(a的ASCII碼)、26,不難想到,實(shí)質(zhì)上就是對字母進(jìn)行偏移;然后再看51和79,都是26的倍數(shù)加或減1;也可以直接打開這個括號,再進(jìn)行運(yùn)算。那么這個取余運(yùn)算的作用也比較容易理解,下面是代碼:
decry = "Qsw3sj_lz4_Ujw@l" v = list(decry)for i in range(16):if ord(v[i])>64 and ord(v[i])<=90:v[i] = chr(ord(v[i])-65+51) if (ord(v[i])-65+51) > 64 else chr(ord(v[i])-65+26+51)if ord(v[i]) > 96 and ord(v[i]) <= 122:v[i] = chr(ord(v[i]) - 97 + 79) if (ord(v[i])-97+79) > 96 else chr(ord(v[i])-97+26+79)print("".join(v))flag{Cae3ar_th4_Gre@t}
[FlareOn4]login
下載有兩個文件,文本文件沒什么用,看網(wǎng)頁
源代碼里有用的是下面這段代碼
document.getElementById("prompt").onclick = function () {var flag = document.getElementById("flag").value;var rotFlag = flag.replace(/[a-zA-Z]/g, function(c){return String.fromCharCode((c <= "Z" ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26);});if ("PyvragFvqrYbtvafNerRnfl@syner-ba.pbz" == rotFlag) {alert("Correct flag!");} else {alert("Incorrect flag, rot again");}}replace的第一個參數(shù),/[a-zA-Z]/g??這部分是正則表達(dá)式,相關(guān)內(nèi)容可參考https://www.runoob.com/regexp/regexp-syntax.html
replace的第二個參數(shù),是一個函數(shù),也就是將輸入的字符串的所有字符,進(jìn)行這個函數(shù)的加密
加密后的字符串是"PyvragFvqrYbtvafNerRnfl@syner-ba.pbz"?
.charCodeAt(i) 方法是返回字符串的第i個字符的Unicode編碼(i從0算起)
.fromCharCode() 方法是將一個Unicode編碼轉(zhuǎn)換成對應(yīng)的字符
實(shí)質(zhì)上就是對字符串進(jìn)行偏移,偏移量為固定的13。。ROT13加密
flag{ClientSideLoginsAreEasy@flare-on.com}
CrackRTF
哈希
首先了解一下關(guān)于哈希(Hash):
哈希(Hash)是將任意長度的數(shù)據(jù)映射到固定長度的數(shù)據(jù)的過程,被映射后的數(shù)據(jù)稱為哈希值(Hash Value)。哈希函數(shù)是實(shí)現(xiàn)哈希的算法,它可以將輸入數(shù)據(jù)(也稱為消息)轉(zhuǎn)換為哈希值。哈希值具有以下特點(diǎn):
固定長度:無論輸入數(shù)據(jù)的大小,哈希值的長度都是固定的。
唯一性:哈希函數(shù)將不同的輸入數(shù)據(jù)映射到不同的哈希值,因此不同的輸入數(shù)據(jù)生成的哈希值是唯一的。
散列性:哈希函數(shù)應(yīng)該具有很高的散列性,即對于微小的輸入數(shù)據(jù)變化,生成的哈希值應(yīng)該有很大的差異,從而使哈希值更難以被預(yù)測或攻擊者更難以針對性地構(gòu)造相同的哈希值。
不可逆性:哈希函數(shù)應(yīng)該是單向的,即無法通過哈希值還原出原始數(shù)據(jù)。
哈希值在密碼學(xué)中廣泛應(yīng)用,例如數(shù)字簽名、消息認(rèn)證和數(shù)據(jù)完整性驗(yàn)證。在網(wǎng)絡(luò)安全中,哈希函數(shù)也被用于驗(yàn)證文件的完整性和防止篡改,例如文件校驗(yàn)和和數(shù)字指紋。
一些常用的哈希函數(shù)包括:MD5、SHA-1、SHA-2 和 SHA-3。需要注意的是,隨著計(jì)算機(jī)計(jì)算能力的不斷提高,一些早期的哈希函數(shù),如 MD5 和 SHA-1,已經(jīng)被認(rèn)為不再安全,建議使用更安全的哈希函數(shù)。
不同哈希函數(shù)簡介
MD5:輸出長度為128位的散列值。由于其輸出長度較短,MD5易于被暴力破解。因此,MD5已經(jīng)不再被推薦用于安全加密。
SHA-1:輸出長度為160位的散列值。SHA-1的安全性也被認(rèn)為不足,容易受到碰撞攻擊。因此,SHA-2和SHA-3等更強(qiáng)大的哈希函數(shù)已被推薦用于安全加密。
SHA-2:SHA-2系列包括SHA-224、SHA-256、SHA-384和SHA-512,分別輸出長度為224、256、384和512位的散列值。SHA-2相對于MD5和SHA-1更加安全,被廣泛使用于安全加密領(lǐng)域。
SHA-3:SHA-3是NIST于2012年發(fā)布的新一代哈希函數(shù)標(biāo)準(zhǔn)。SHA-3與SHA-2不同的是,它采用了基于置換的架構(gòu),具有更好的安全性和效率。
BLAKE2:BLAKE2是一種高速哈希函數(shù),輸出長度可以從1到512位不等。它比SHA-3和SHA-2更快,也被廣泛用于數(shù)據(jù)完整性校驗(yàn)和密碼學(xué)協(xié)議等領(lǐng)域。
這里的散列值相當(dāng)于一個字節(jié),下面是不同進(jìn)制的單個字符再計(jì)算機(jī)里所占內(nèi)存大小:
二進(jìn)制:每個二進(jìn)制字符(0或1)占據(jù)1比特位,8個二進(jìn)制字符組成一個字節(jié)。
八進(jìn)制:每個八進(jìn)制字符(0-7)占據(jù)3比特位,3個八進(jìn)制字符組成一個字節(jié)。
十進(jìn)制:每個十進(jìn)制字符(0-9)占據(jù)1個字節(jié)(8個比特位)。
十六進(jìn)制:每個十六進(jìn)制字符(0-9,A-F)占據(jù)4比特位,2個十六進(jìn)制字符組成一個字節(jié)。
題目
查殼,32位無殼,IDA32打開,找到main_0,有以下代碼
int __cdecl main_0() {DWORD v0; // eaxDWORD v1; // eaxCHAR String; // [esp+4Ch] [ebp-310h]int v4; // [esp+150h] [ebp-20Ch]CHAR String1; // [esp+154h] [ebp-208h]BYTE pbData; // [esp+258h] [ebp-104h]memset(&pbData, 0, 0x104u);memset(&String1, 0, 0x104u);v4 = 0;printf("pls input the first passwd(1): ");scanf("%s", &pbData);if ( strlen((const char *)&pbData) != 6 ){printf("Must be 6 characters!\n");ExitProcess(0);}v4 = atoi((const char *)&pbData);if ( v4 < 100000 )ExitProcess(0);strcat((char *)&pbData, "@DBApp");v0 = strlen((const char *)&pbData);sub_40100A(&pbData, v0, &String1);if ( !_strcmpi(&String1, "6E32D0943418C2C33385BC35A1470250DD8923A9") ){printf("continue...\n\n");printf("pls input the first passwd(2): ");memset(&String, 0, 0x104u);scanf("%s", &String);if ( strlen(&String) != 6 ){printf("Must be 6 characters!\n");ExitProcess(0);}strcat(&String, (const char *)&pbData);memset(&String1, 0, 0x104u);v1 = strlen(&String);sub_401019((BYTE *)&String, v1, &String1);if ( !_strcmpi("27019e688a4e62a649fd99cadaafdb4e", &String1) ){if ( !sub_40100F(&String) ){printf("Error!!\n");ExitProcess(0);}printf("bye ~~\n");}}return 0; }26行的一串,是40位數(shù)字,并且是16進(jìn)制,那么就是SHA-1加密了
要求兩位6位字符的passwd,先輸入第一段字符,在其后面加上@DBApp,再經(jīng)過sub_40100A加密;再輸入第二段字符,sub_401019加密,將其拼接在第一段字符的前面;然后整體再加密一次
這里的atoi()函數(shù)用于將字符串轉(zhuǎn)換成整型數(shù)
memset()函數(shù):void *memset(void *ptr, int value, size_t num),其中,ptr是指向內(nèi)存區(qū)域的指針,value是要設(shè)置的值,num是要設(shè)置的字節(jié)數(shù)。用于將指定內(nèi)存區(qū)域的每個字節(jié)都設(shè)置成指定的值。
其中,第一段和第二段加密后的字符給出了
那么先來爆破第一段:
import hashlibflag = "@DBApp"for i in range(100000, 1000000):s = str(i)+flagx = hashlib.sha1(s.encode())cnt = x.hexdigest()if "6e32d0943418c2c" in cnt:print(cnt)print(str(i)+flag)由于SHA-1哈希函數(shù)只接受字節(jié)序列作為輸入,所以需要.encode(),encode()默認(rèn)為UTF-8
結(jié)果123321@DBApp
第二次加密,給出的字符長度有變,是32位,可能是MD5加密,往后看,有個sub_40100F函數(shù),點(diǎn)進(jìn)去,看到這種字符串,這個函數(shù)肯定有用,看起來像從AAA這個文件取出什么東西
進(jìn)入這個函數(shù),是個異或運(yùn)算
這里附上一個工具Resource Hacker的官網(wǎng)http://www.angusj.com/resourcehacker/#download,這個工具可以直接查看文件中的資源。
文件.rtf的文件頭固定為{\rtf1\ansi\ansicpg936\deff0\......,取前六位{\rtf1。
所以{\rtf1與AAA中前六個數(shù)據(jù)異或就行了
結(jié)果~!3a@0
寫到這突然不知道接下來要干什么了,這道題對小白來說也算難的了吧
那就運(yùn)行一下exe,兩次輸入,最后發(fā)現(xiàn)dbapp.rtf,
flag{N0_M0re_Free_Bugs}
總結(jié)
以上是生活随笔為你收集整理的逆向初学者做题记录3.28的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 实现发送xml格式的请求
- 下一篇: [ICCV 2019] Few-Shot