NJUST CTF 2018 Writeup

NJUST CTF 2018 Writeup

Supernova, Nanjing University frostwing98,Trap,Arcadia

MISC1 簽到

by Arcadia

一路調戲ai之後(誤)可以得到一串base64編碼的字符串,在線解碼得到flag

MISC2 GIF

by frostwing98

下載到gif,發現是不斷閃爍的黑/白畫面,第一考慮是莫爾斯電碼。首先http://tu.sioe.cn/gj/fenjie/分解之。

發現間隔並不均勻,也不按照1:3:5的比例。因此考慮01串的可能性。

後來題目有調整,也分好了每一幀。

我們發現,總共有91個圖片,如果是ASCII,應該是8的倍數纔對。

我們應該知道,ASCII的可打印字符,高位始終不會大於7,也就是0111.因此最高位其實可以省略。爲此我們又發現,91=7×13,進一步驗證了這個猜想。

因此將13×7個bit,每7個一組,最高位加上0,就能夠構成flag的13個字符。


MISC3 code

by Arcadia

純編程題,利用在線文字識別工具獲取圖片中的每個數字,存放在文件中,用算法模擬貪吃蛇移動路線,用輾轉相除法計算最大公約數跟最小公倍數,最後得到flag。

C++代碼:

#include <iostream>
#include <fstream> 
#include <string>
#include <cmath>

using namespace std;

int gcd(int a,int b){ return a%b==0?b:gcd(b,a%b);}

int main()
{
    int x=0,y=0;
    int p,q;
    int sum=25*25-1,value=0,temp,ans;
    int state=1;
    ifstream input;
    int map[25][25];
    bool flag[25][25]={0};
    input.open("data.txt",ios::in);
    for (int i=0;i<25;i++)
        for (int j=0;j<25;j++)
            input>>map[i][j];
    input.close();
    p=0;q=1;
    ans=value=map[0][0];
    flag[0][0]=1;
    while (1)
    {

        if (x+p<0 || x+p>=25 || y+q<0 || y+q>=25 || flag[x+p][y+q]) state=(state+1)%4;
        switch(state)
        {
            case 0:p=-1; q=0; break;
            case 1:p=0; q=1; break;
            case 2:p=1; q=0; break;
            case 3:p=0; q=-1; break;
        }
        x+=p; y+=q;
        if (flag[x][y]) break;
        cout<<x<<':'<<y<<' ';

        if (value>=map[x][y])
        {
            temp=gcd(value,map[x][y]);
            ans-=temp;
        }
        else
        {
            temp=gcd(map[x][y],value);
            ans+=value/temp*map[x][y];
        }
        value=map[x][y];
        flag[x][y]=1;
        sum--;
    }
    cout<<ans;
    return 0;
}

運行截圖:

Crypto1 Classical Enc

by frostwing98

題幹:

Ld hsrakwusyaxr, y hoyjjlhyo hlaxes lj y kraewv hlaxes kxyk zyj tjei xljkwslhyoor gtk dwz xyj vyooed, vws kxe pwjk aysk,ldkw iljtje. Ld hwdksyjk kw pwiesd hsrakwusyaxlh youwslkxpj, pwjk hoyjjlhyohlaxesj hyd ge asyhklhyoor hwpatkei ydi jwofei gr xydi. Xwzefes,WFKT|vGkciP5kK2i5pInblVJ~ kxer yse yojw tjtyoor fesr jlpaoe kw gseym zlkxpwiesd kehxdwowur. Kxe kesp ldhotiej kxe jlpaoe jrjkepj tjei jldhe Useem ydiSwpyd klpej, kxe eoygwsyke Sedyljjydhe hlaxesj, Zwsoi Zys LL hsrakwusyaxr jthxyj kxe Edlupy pyhxlde ydi gerwdi. Y btlhm gswzd vwq ntpa wfes kxe oycr iwu.

這一道題的確挺“經典加密”的……

首先明眼人一看便知,這個y,多次出現在逗號之前,可能是“a”。於是考慮凱撒密碼及其衍生移位密碼的可能性。

失敗……

後來hint1出現。迅速聯想到詞頻分析。https://quipqiup.com/在這個網站在線進行解密。

陰險的是,其實最後一句話已經給出了答案。A quick brown fox jumpover the lazy dog.是一個著名的句子,因爲它不重複的包含了26個字母,可以作爲解碼的密碼錶。

於是順利解出flag所在的句子

OVTU|fBtzdM5tT2d5mDjqiFS~

因爲|與~的間隔與{與}的間隔同爲2,因此這裏纔是凱撒,offset爲1.

decode結果爲NUST{eAsy_cL4sS1c4l_CiphER

Crypto2 XOR

by Arcadia

觀察代碼,發現是進行了5次異或下一位的運算之後得到結果,通過xor的運算規則能推導出第一個字符是由第1,2,5,6個原字符異或而成,第二個是2,3,6,7……以此類推,因爲已知flag格式,前5個字符爲“NUST{”,故可通過遞推得到後面的字符。

代碼及運行結果:

RE1 Base64Encode

by Arcadia

這題修改了base64的編碼表,並給出了經過編碼後的flag值,利用base64編碼的原理,將4位的base64編碼通過編碼表對應到3個字符上,即可獲得flag。

首先可以在IDA中直接看到編碼後的flag值:

然後在base64dncode函數中可以發現一個數組,存放着編碼信息:

然後編個代碼decode就搞定了:

RE2 Maze Game

by Trap

​ 這道re比較簡單,用IDA反編譯很方便,既沒有刪節頭又沒有加殼,可以說是非常良心了。

這裏要注意的只有三個地方,第一處是輸入的字符串必須爲22個(這也是讓人容易掉進陷阱的地方,你構造的路徑必須是正好22步),第二處是迷宮的驗證,第三處是生成flag。

Maze_verify如下:

可以看出,就像走迷宮一樣用wsad移動,只是這裏的上下是相反的,可以先構造再替換字符。然後如果在某一步裏面出了邊界或者迷宮地圖上不是1,也不算。看看迷宮的地圖:

結合上面的v3 v2的判斷條件,容易聯想到是8*8的迷宮,大概長這個樣:

Payload爲wwdwdsssddddwwwaawwddw

Pwn1 babystack

by Arcadia

利用棧可執行,將shellcode插在返回地址之後,返回到給出的棧地址,利用jmp指令跳轉到shellcode所在地址執行,拿到權限,cat flag得到flag

直接通過gets的函數漏洞修改返回地址爲之前泄露的字符地址:

指向棧上的jmp彙編代碼:

跳轉執行shellcode:

就可以進入服務器獲取flag了:

Web1 PHP Audit

by Trap

開始的狀態是這樣的:

這裏提示我們輸入兩個參數key1和key2,其中,key1是一個文件名,將其打開後與“Hello hacker!”一致。容易想到PHP協議流 data://text/plain;base64,SGVsbG8gaGFja2VyIQ==,這裏的第二個參數是“Hello hacker!”經過base64編碼後的結果,於是就得到第二部分:

這裏要求一個經過MD5以後的字符串要大於66666*66666,這裏的結果不能以字母開頭,不能以0e和1e開頭,我在MD5網上隨便試了一些,得到一個字符串vwer , 其32位MD5爲4e32e71b2e1aaa761a3c27eff3f7c257,PHP會將其識別爲4^32。

整理一下是這樣的:

過k3需要用到intval的一個漏洞:他不能識別除了數字和字母e以外的字符,遇到了就會停止。(小數點、負號等除外)因此這裏用十六進制編碼666 =0x29a,可以讓intval的輸出不等於666,而在字符串與666比較時,會被看做16進制數轉化成666.這樣就來到了k4

經過與主辦方交流,預期解似乎是665.999999 intval會將小數點截斷,然後比較的時候會四捨五入(?)

接下來到了這道題最詭異的部分了。關於k4的取值,理論上只要傳給intval的值超過臨界值214743647,那麼將會溢出,返回一個負數。這樣我們可以構造一個k4=2147483647的payload。這個payload在我的機子上測試通過(php version 5.6.25, 服務器version 5.6.28)但就是拿不到flag。然後,如果你在後面瘋狂地加0,你會發現仍然沒有flag……

​ 經過我的不嚴謹的測試,我發現,服務器端是否溢出只跟位數有關而與大小無關。最後我們構造了一個21位的payload 214748364900000000000 拿到的flag。但經過我的測試,發現只要是21位,不管是什麼數都可以拿到flag。但往下減位數,比如20 19 18 17位都不行。而往上找呢?只有24 36位可以用。各位有興趣可以去嘗試一下服務器的這個神奇的設定。

​ 最終payload:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章