内容简介:2019看雪纽盾KCTF晋级赛Q2经过十四天的激烈比拼,于昨日正午12点整正式宣告结束。攻破难题时战士们豪情万丈,意气风发,未能攻破也不要灰心,我们一起来看下第一题的题目解析,积蓄力量,再接再厉!本次比赛我们特意为大家设置了一个故事背景:
2019看雪纽盾KCTF晋级赛Q2经过十四天的激烈比拼,于昨日正午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的,限于篇幅,我们不做深入探究。
看雪CTF晋级赛Q2 精彩回顾
- End -
公众号ID:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com
戳原文,查看更多精彩writeup!
以上所述就是小编给大家介绍的《看雪.纽盾 KCTF 2019 Q2 | 第一题点评及解题思路》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 小记一类ctf密码题解题思路
- WSDM Cup 2019 自然语言推理任务获奖解题思路
- 并发题的解题思路以及 Go 语言调度器工作原理
- 算法和编程面试题精选TOP50!(附代码+解题思路+答案)
- 看雪.纽盾 KCTF 2019 Q2 | 第三题点评及解题思路
- 看雪.纽盾 KCTF 2019 Q2 | 第二题点评及解题思路
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。