看雪.纽盾 KCTF 2019 Q2 | 第一题点评及解题思路

栏目: 数据库 · 发布时间: 5年前

内容简介:2019看雪纽盾KCTF晋级赛Q2经过十四天的激烈比拼,于昨日正午12点整正式宣告结束。攻破难题时战士们豪情万丈,意气风发,未能攻破也不要灰心,我们一起来看下第一题的题目解析,积蓄力量,再接再厉!本次比赛我们特意为大家设置了一个故事背景:

2019看雪纽盾KCTF晋级赛Q2经过十四天的激烈比拼,于昨日正午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的,限于篇幅,我们不做深入探究。

看雪CTF晋级赛Q2 精彩回顾

- End -

看雪.纽盾 KCTF 2019 Q2 | 第一题点评及解题思路

看雪.纽盾 KCTF 2019 Q2 | 第一题点评及解题思路

公众号ID:ikanxue

官方微博:看雪安全

商务合作:wsc@kanxue.com

看雪.纽盾 KCTF 2019 Q2 | 第一题点评及解题思路

戳原文,查看更多精彩writeup!


以上所述就是小编给大家介绍的《看雪.纽盾 KCTF 2019 Q2 | 第一题点评及解题思路》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

程序员的数学

程序员的数学

结城浩 / 管杰 / 人民邮电出版社 / 2012-10 / 49.00元

如果数学不好,是否可以成为一名程序员呢?答案是肯定的。 本书最适合:数学糟糕但又想学习编程的你。 没有晦涩的公式,只有好玩的数学题。 帮你掌握编程所需的“数学思维”。 日文版已重印14次! 编程的基础是计算机科学,而计算机科学的基础是数学。因此,学习数学有助于巩固编程的基础,写出更健壮的程序。 本书面向程序员介绍了编程中常用的数学知识,借以培养初级程序员的数学思维。读......一起来看看 《程序员的数学》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具