看雪.紐盾 KCTF 2019 Q2 | 第一題點評及解題思路

Editor發表於2019-07-01

2019看雪紐盾KCTF晉級賽Q2經過十四天的激烈比拼,於6月24日正午12點整正式宣告結束。


攻破難題時戰士們豪情萬丈,意氣風發,未能攻破也不要灰心,我們一起來看下第一題的題目解析,積蓄力量,再接再厲!


本次比賽我們特意為大家設定了一個故事背景:

時間快進到100年後的地球,一束耀眼的白光劃破長空,天空隨即被撕開一個猶如黑洞般深不見底的黑洞,一艘巨大的宇宙飛船從這黑洞中衝出來,懸浮在高空中,隨即來自外星球的宇宙大軍也開始源源不斷的湧入地球。

各個國家紛紛開啟防禦模式,拿出最強武器,對著來犯的外星人發起進攻。但顯然,人類的武器撐不了多久,人類最後一片淨土--紐西蘭,已經一片荒蕪,正在緩慢沉入海底。

留給人類的時間不多了。最好的方法是逃離地球。你需要藉助時間之輪,開啟進入另一個平行時空的入口,拯救人類於水火之中。

而啟動時間之輪,需要集齊9個能量寶石,方能開啟。快點行動起來吧!


題目簡介

北京地球上的人們還在沉睡,此時的地球早已沒有了996,每人每天只需要工作2~3小時,其餘都交給人工智慧,世界一片祥和。人們在這樣和平安逸的生活中逐漸放鬆警惕。以至於面對突如其來的外來入侵,毫無防備。

你作為海軍陸戰隊的一員,剛剛從與外星人對抗的一線撤離下來。手機信箱中突然出現了一封神祕來信,稱裡面含有時間之輪的祕密。但是必須成功解出這封信的密碼才能看到......


看雪.紐盾 KCTF 2019 Q2 | 第一題點評及解題思路


本題圍觀人數高達5282人,人氣頗高,攻破人數也達到了197人,為本次比賽開了個好彩頭!

攻破此題的戰隊排名一覽:


看雪.紐盾 KCTF 2019 Q2 | 第一題點評及解題思路



看雪CTF 評委 點評

這道題難度較低,作為一道簽到題被放在了第一題。其考察的內容是“異常(Exception)”的產生。

原理是:正確的flag可以觸發除0異常。程式邏輯本身並不複雜。也有隊伍採用窮舉的辦法完成此題。


解題思路

本題解題思路是將兩位小夥伴的解題思路整合而成的。

第一部分由jackandkx提供:

看雪.紐盾 KCTF 2019 Q2 | 第一題點評及解題思路


簽到題,F5一下。

輸入長度為6,最後3位為353,前3位的和為149。


int __cdecl main(int argc, const char **argv, const char **envp)
{
int val; // esi
unsigned int v4; // kr00_4
unsigned int i; // ecx
unsigned __int8 input[6]; // [esp+10h] [ebp-3Ch]
CPPEH_RECORD ms_exc; // [esp+34h] [ebp-18h]

val = 0;
printf((int)"請輸入序列號:\n");
scanf("%s", input);
v4 = strlen((const char *)input);
if ( v4 < 7 && input[5] == '3' && input[4] == '5' && input[3] == '3' && input[2] + input[1] + input[0] == 149 )
{
i = 0;
if ( v4 )
{
do
val = input[i++] + 16 * val - 48;
while ( i < v4 );
}
ms_exc.registration.TryLevel = 0;
printf((int)"error!\n");
while ( 1 )
;
}
printf((int)"error\n");
return 0;
}


F5的程式碼不完整,直接看彙編。函式開頭設定異常處理函式:


.text:00401260 push ebp
.text:00401261 mov ebp, esp
.text:00401263 push 0FFFFFFFEh
.text:00401265 push offset stru_41CC98
.text:0040126A push offset __except_handler4
.text:0040126F mov eax, large fs:0
.text:00401275 push eax


處理函式顯示"success",所以需要產生異常。


.rdata:0041CC98 stru_41CC98 dd 0FFFFFFE4h ; GSCookieOffset
.rdata:0041CC98 ; DATA XREF: _main+5↑o
.rdata:0041CC98 dd 0 ; GSCookieXOROffset ; SEH scope table for function 401260
.rdata:0041CC98 dd 0FFFFFFB4h ; EHCookieOffset
.rdata:0041CC98 dd 0 ; EHCookieXOROffset
.rdata:0041CC98 dd 0FFFFFFFEh ; ScopeRecord.EnclosingLevel
.rdata:0041CC98 dd offset loc_401373 ; ScopeRecord.FilterFunc
.rdata:0041CC98 dd offset sucesss ; ScopeRecord.HandlerFunc


6位數字轉化為16進位制數:


.text:00401330 movzx eax, [ebp+ecx+input]
.text:00401335 shl esi, 4
.text:00401338 add esi, 0FFFFFFD0h
.text:0040133B add esi, eax
.text:0040133D inc ecx
.text:0040133E cmp ec


16進位制數與地址0x401353相減,作為除數,讓除數等於0就能產生異常。


.text:0040134E call loc_401354
.text:0040134E ; ---------------------------------------------------------------------------
.text:00401353 db 0EBh
.text:00401354 ; ---------------------------------------------------------------------------
.text:00401354
.text:00401354 loc_401354: ; CODE XREF: _main+EE↑j
.text:00401354 pop eax
.text:00401355 sub eax, 0
.text:00401358 sub esi, eax
.text:0040135A div esi


故key為401353

第二部分由微笑明天提供:


看雪.紐盾 KCTF 2019 Q2 | 第一題點評及解題思路


簡單介紹一下SEH。


參考加密與解密

1、功能


SEH實際包含兩個主要功能:結束處理(termination handling)和異常處理(exception handling)。

每當你建立一個try塊,它必須跟隨一個finally塊或一個except塊。一個try塊之後不能既有finally塊又有except塊。但可以在try-except塊中巢狀try-finally塊,反過來也可以。


__try,__finally關鍵字用來標出結束處理程式兩段程式碼的輪廓。


不管保護體(try塊)是如何退出的。不論你在保護體中使用return,還是goto,或者是longjump,結束處理程式(finally塊)都將被呼叫。在try使用__leave關鍵字會引起跳轉到try塊的結尾。


2、TIB結構

在使用者模式下,TIB(ThreadInformationBlock)位於TEB的頭部。而TEB是作業系統為了儲存每個執行緒的私有資料建立的,每個執行緒都有自己的TEB。


nt!_TEB
+0x000 NtTib : _NT_TIB
+0x01c EnvironmentPointer : Ptr32 Void


我們看一下TIB的結構


typedef struct _NT_TIB //sizeof 1ch
{
00h struct _EXCEPTION_REGISTRATION *ExceptionList; //SEH鏈入口
04h PVOID StackBase; //堆疊基址
08h PVOID StackLimit; //堆疊大小
0ch PVOID SubSystemTib;
union {
PVOID FiberData;
10h DWORD Version;
};
14h PVOID ArbitraryUserPointer;
18h struct _NT_TIB *Self; //本NT_TIB結構自身的線性地址
}NT_TIB;


我們看到,ExceptionList在TIB的頭部。而在X86下,TEB總是由fs:[0]指向的。


ExceptionList是一個連結串列的結構。畫了一個流程圖便於理解:


+---------+ +----------------+ +---------------+
| 發生異常 +--->+ TIB +----->+ Next +--+
| | | fs:[0] | +---------------+ | +------------------+
+---------+ +----------------+ | Handler +-------------->+ 異常處理函式 |
+---------------+ | | ... |
| | retn |
+----------+ +------------------+
|
+-------v-------+
| Next +--+
+---------------+ | +------------------+
| Handler +-------------->+ 異常處理函式 |
+---------------+ | | ... |
| | retn |
+----------+ +------------------+
|
+-------v-------+
| FFFFFFh |
+---------------+ +------------------+
| Handler +-------------->+ 異常處理函式 |
+---------------+ | ... |
| retn |
+------------------+


next是下一個鏈的地址。如果next的值是FFFFFFh,表示是連結串列的最後一個節點,該節點的回撥函式是系統設定的一個終結處理函式,所有無人值守的異常都會到達這裡。


異常處理函式可以是自定義的函式,系統有一個預設的函式,但我們可以自定義一個異常處理函式,讓它來處理。


但是得先安裝自定義函式才能使用。


我們可以寫一個異常處理的例子:


//Powered by HAPPY
#include <Windows.h>
#include <iostream>
int exception_memory_access_violation(LPEXCEPTION_POINTERS p_exinfo)
{
if (p_exinfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
{
return EXCEPTION_EXECUTE_HANDLER; //handle this exception
}
else return EXCEPTION_CONTINUE_SEARCH; //Do not handle this exception
}

int main()
{
char* mem = 0;
std::cout << "Hello World!\n";
__try {
*mem = 0; //throw exception
}
__except (exception_memory_access_violation(GetExceptionInformation())) //handler
{
puts("Memory error in except");
}
}


我們可以將其編譯後反彙編研究下except的程式碼以及是如何安裝SEH的,限於篇幅,我們不做深入探究。


看雪.紐盾 KCTF 2019 Q2 | 第一題點評及解題思路

主辦方

看雪.紐盾 KCTF 2019 Q2 | 第一題點評及解題思路


看雪學院(http://www.kanxue.com)是一個專注於PC、移動、智慧裝置安全研究及逆向工程的開發者社群!建立於2000年,歷經19年的發展,受到業內的廣泛認同,在行業中樹立了令人尊敬的專業形象。平臺為會員提供安全知識的線上課程教學,同時為企業提供智慧裝置安全相關產品和服務。


合作伙伴


看雪.紐盾 KCTF 2019 Q2 | 第一題點評及解題思路



看雪.紐盾 KCTF 2019 Q2 | 第一題點評及解題思路


上海紐盾科技股份有限公司成立於2009年,是一家以“網路安全”為主軸,以“科技源自生活,紐盾服務社會”為核心經營理念,以網路安全產品的研發、生產、銷售、售後服務與相關安全服務為一體的專業安全公司,致力於為數字化時代背景下的使用者提供安全產品、安全服務以及等級保護等安全解決方案。


相關文章