CTF題解四 逆向 順藤摸瓜(ISCC2017)

觀察:

1.首先在IDA中找到main函數:

這裏寫圖片描述

首先輸入字符串s,接着把字符串s作爲隨機數的種子。

調用sub_400796函數和sub_400937函數。

由於s未知,所以需要猜測s的哪部分作爲隨機數的種子。

2.觀察sub_400796函數:

該函數主要分爲兩部分,第一部分是對byte_6010C0進行賦值
這裏寫圖片描述

第二部分是利用byte_6010C0和byte_601070以及a1原來的值,求得a1第一次加密後的值

這裏寫圖片描述

所以,如果要求解a1原來的值,需要已知:

byte_6010C0(已知)、byte_601070(已知)、a1第一次加密後的值(未知,需要解密下一個函數才能得到)。

3.觀察sub_400937函數:

這裏寫圖片描述

_ctype_b_loc這裏爲判斷是否爲小寫字母。分析上一個函數,可以看出a1中所有的字母都滿足*__ctype_b_loc())[v4] & 0x200該條件。

所以src與a1相比,只是將字母的順序進行了調換

另外,由於a1的長度最小爲v8*v9 - v8,而src的長度爲v8*v9。所以a1中長度不夠的部分需要隨機生成

4.總結:

本題的求解順序爲:

1.猜測隨機數的種子。

2.根據題目中給出的字符串,對sub_400937函數中的加密過程進行解密。

3.將解密的結果代入sub_400796函數中,求得s的值。

求解:

1.猜測隨機數的種子:

猜測s的前四位爲”flag”,由於小端問題,轉換爲16進制後應該爲:

0x67616C66

2.sub_400937解密:

由於src的長度正好等於v8*v9.所以在編寫解密程序時,v9不用再加1了。

解密程序的主要工作就是行列的調換。

char a[] = "vfnlhthn__bneptls}xlragp{__vejblxpkfygz_wsktsgnv";
srand(0x67616C66);
int v7 = 0;
int v8 = rand() % 7 + 2;
int v9 = strlen(a) / v8;
for (int i = 0; i < v9; i++) {
    for (int j = 0; j < v8; j++) {
        printf("%c", a[j*v9 + i]);
    }
}

最後得到輸出爲:

vhex{bykfnpl_lgtn_tr_xzsl_lavp_ghbsgekwntn}pjfsv

不考慮後面幾位隨機生成的數字,可以得到a1爲:

vhex{bykfnpl_lgtn_tr_xzsl_lavp_ghbsgekwntn}

3.sub_400796解密:

首先編程求解出byte_6010C0,並找到byte_601070的值。

然後編程求解a1,主要方法就是窮搜。

char a[] = "qwertyuiopasdfghjklzxcvbnm";
char b[] = "abcdefghijklmnopqrstuvwxyzbcdefghijklmnopqrstuvwxyzacdefghijklmnopqrstuvwxyzabdefghijklmnopqrstuvwxyzabcefghijklmnopqrstuvwxyzabcdfghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdefhijklmnopqrstuvwxyzabcdefgijklmnopqrstuvwxyzabcdefghjklmnopqrstuvwxyzabcdefghiklmnopqrstuvwxyzabcdefghijlmnopqrstuvwxyzabcdefghijkmnopqrstuvwxyzabcdefghijklnopqrstuvwxyzabcdefghijklmopqrstuvwxyzabcdefghijklmnpqrstuvwxyzabcdefghijklmnoqrstuvwxyzabcdefghijklmnoprstuvwxyzabcdefghijklmnopqstuvwxyzabcdefghijklmnopqrtuvwxyzabcdefghijklmnopqrsuvwxyzabcdefghijklmnopqrstvwxyzabcdefghijklmnopqrstuwxyzabcdefghijklmnopqrstuvxyzabcdefghijklmnopqrstuvwyzabcdefghijklmnopqrstuvwxzabcdefghijklmnopqrstuvwxy";
char c[] = "vhex{bykfnpl_lgtn_tr_xzsl_lavp_ghbsgekwntn}";
int k = 0;
while (k < strlen(c)) {
    if(c[k]>96&&c[k]<123){
        for (int i = 97; i < 123; i++) {
            if (c[k] == b[26 * ((i - 97) % 26) + (a[k % 26] - 97) % 26]) {
                printf("%c", i);
                break;
            }
        }
    }
    else printf("%c", c[k]);
    k++;
}

運行程序得到flag:

flag{decrypt_game_is_very_very_interesting}

反思:

本題主要卡在兩個地方:

1.猜測隨機數的種子。

2.猜測&0x200的意義。

發佈了48 篇原創文章 · 獲贊 13 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章