2019看雪紐盾KCTF晉級賽Q2經過十四天的激烈比拼,於6月24日正午12點整正式宣告結束。
攻破難題時戰士們豪情萬丈,意氣風發,未能攻破也不要灰心,我們一起來看下第一題的題目解析,積蓄力量,再接再厲!
本次比賽我們特意為大家設定了一個故事背景:
時間快進到100年後的地球,一束耀眼的白光劃破長空,天空隨即被撕開一個猶如黑洞般深不見底的黑洞,一艘巨大的宇宙飛船從這黑洞中衝出來,懸浮在高空中,隨即來自外星球的宇宙大軍也開始源源不斷的湧入地球。
各個國家紛紛開啟防禦模式,拿出最強武器,對著來犯的外星人發起進攻。但顯然,人類的武器撐不了多久,人類最後一片淨土--紐西蘭,已經一片荒蕪,正在緩慢沉入海底。
留給人類的時間不多了。最好的方法是逃離地球。你需要藉助時間之輪,開啟進入另一個平行時空的入口,拯救人類於水火之中。
而啟動時間之輪,需要集齊9個能量寶石,方能開啟。快點行動起來吧!
題目簡介
北京地球上的人們還在沉睡,此時的地球早已沒有了996,每人每天只需要工作2~3小時,其餘都交給人工智慧,世界一片祥和。人們在這樣和平安逸的生活中逐漸放鬆警惕。以至於面對突如其來的外來入侵,毫無防備。
你作為海軍陸戰隊的一員,剛剛從與外星人對抗的一線撤離下來。手機信箱中突然出現了一封神祕來信,稱裡面含有時間之輪的祕密。但是必須成功解出這封信的密碼才能看到......
本題圍觀人數高達5282人,人氣頗高,攻破人數也達到了197人,為本次比賽開了個好彩頭!
攻破此題的戰隊排名一覽:
看雪CTF 評委 點評
這道題難度較低,作為一道簽到題被放在了第一題。其考察的內容是“異常(Exception)”的產生。
原理是:正確的flag可以觸發除0異常。程式邏輯本身並不複雜。也有隊伍採用窮舉的辦法完成此題。
解題思路
本題解題思路是將兩位小夥伴的解題思路整合而成的。
第一部分由jackandkx提供:
簽到題,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
第二部分由微笑明天提供:
簡單介紹一下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的,限於篇幅,我們不做深入探究。
主辦方
看雪學院(http://www.kanxue.com)是一個專注於PC、移動、智慧裝置安全研究及逆向工程的開發者社群!建立於2000年,歷經19年的發展,受到業內的廣泛認同,在行業中樹立了令人尊敬的專業形象。平臺為會員提供安全知識的線上課程教學,同時為企業提供智慧裝置安全相關產品和服務。
合作伙伴
上海紐盾科技股份有限公司成立於2009年,是一家以“網路安全”為主軸,以“科技源自生活,紐盾服務社會”為核心經營理念,以網路安全產品的研發、生產、銷售、售後服務與相關安全服務為一體的專業安全公司,致力於為數字化時代背景下的使用者提供安全產品、安全服務以及等級保護等安全解決方案。