介绍:
由孟加拉国第一次举办的为期27小时的夺旗战;
KnightCTF做起来二进制方向确实算签到题;
同时KnightCTF偏小众,但是个很好的新手训练平台,能很好的入门各个方向;
但同时KnightCTF有很多个扩展方向,不只是局限于web,re,crypto,pwn,misc;
还有数字取证(Digital Forensics),开源情报(OSINT),隐写(Steganography),网络(Networking),以及编程(Programming);
通过这些特殊的方向可以学习到很多有意思的知识;
比如隐写会把秘密写在图片里,或者图片的介绍里;网络会需要用到wireshark,由此还特别下载学习使用;开源情报则是灵活使用谷歌搜索以及其他的爬虫;
通过这次CTF的学习,可以发现很多奇怪的文件都可以转成zip来破解,有些甚至会套娃;
过程:
我和我的小队成员也在比赛的过程中互相帮助,揣测思路;尽管二进制很简单,我们能很快解决AK掉,但其他方向和奇怪的谜题也困扰着我们,比如misc的3D建模需要穿模找flag…等等;
一边学习一边讨论一边解题,针对新知识,解题确实让人头大,连续熬夜两天,每天都高强度地盯着屏幕,怕是这样久了头发都掉光;
为什么这么认真呢?因为这是矩阵战队第一次的CTF比赛,我们会团结起来,去拿到一切能拿到的分数,不会说二进制AK我就下班;
在这过程中,我们还误判了结束比赛的时间,导致排名往下掉了不少,最后也是凭着每个人的意志熬了过来;
最后也是成功的拿到了前100的名次得到证书;
虽然都不是什么难题,但确实让人开心;
接下来就是二进制系列的复现了;
Pwn:
whats_your_name
IDA和ROPgadget:
可以看到主函数很简单,gets输入v4会栈溢出,以便修改v5的值,执行system函数获取flag;
使用ROPgadget会发现有可以控制的寄存器,所以可以玩一点花的;
再使用cyclic命令找到溢出返回的长度;
用got表可以找到plt的偏移;
之前写过ret2libc,那就用那次的经历来写一次;
Exp:
1 | from pwn import * |
思路就是,直接去return,先调用gets函数,控制r15寄存器输入 ‘/bin/sh’ 到一段可修改的地址,返回后调用system,直接执行 system(‘/bin/sh’) ;
之后得到flag:KCTF{bAbY_bUfF3r_0v3Rf1Ow}
hackers_vault
IDA:
可以发现输入的v4是用%d(整数)格式输入的,之后还有一个运算,最后得出v5的值,如果v5 = 48,就能拿到flag;
其实就是一道非常简单的逆向题;
算法就是每一位数的和,所以只需要输入一串数字,这串数字加起来为48就好了(千万别管溢出!别管int的位数!)
然后就nc到服务器,输入数字得到flag:KCTF{b1NaRy_3xOpL0iTaT1On_r0cK5}
whats_your_name_two
IDA:
查看主函数,发现输入的内容s,会被复制到dest,看栈的结构,可以知道dest后面紧跟v6和v7;
主函数里判断,如果v7和v6满足条件值,就执行system获取flag;
则Exp:
1 | from pwn import * |
得到flag:KCTF{bUfF3r_0v3Rf1Ow_i5_fUn_r1Gh7}
偷懒不想玩return了;
Reverse:
The_Flag_Vault
IDA:
进入主函数看到会让输入字符串s2,然后和s1字符串比较,如果相同,就会输出flag;
输入s1后获得flag:KCTF{welc0me_t0_reverse_3ngineering}
the_encoder
IDA:
输入最大40个字符,然后这个for是在判断输入的长度,没什么实际的意义,不会改变输入的值;
之后就会把输入的字符的ascii码加上1337输出;
根据题里的内容,可以知道有如下的数据:
1 | 1412 1404 1421 1407 1460 1452 1386 1414 1449 1445 1388 1432 1388 1415 1436 1385 1405 1388 1451 1432 1386 1388 1388 1392 1462 |
所以思路就是:把每个数减去1337,再换成ascii;
代码:
1 |
|
运行后得到flag:KCTF{s1Mpl3_3Nc0D3r_1337}
BabyShark
这道题的文件是.jar,所以用jd-gui反编译;
可以找到这样两个关键字符串信息内容;
上面一张图的数据后面有等号,可以想到AES,base64加密,于是去尝试解密:
用base64解密解出flag:KCTF{7H15_W@5_345Y_R16H7?}
flag_checker
IDA:
这道题就是单纯的把输入的字符串v4经过两个for循环的运算之后给已有的v5字符串比较与否;
那么稍微改一下两个for里的算法,改成自己的逆运算,当然,第一个for的逆运算就是它自己,因为 x = -1 - y 就是 y = -1 - x;用v5的值算回v4就行了;
代码:
1 |
|
因为是复制的代码用,所以会比较乱,而且写的时候是v4来运算,但实际上输入的数据是v5的;
运行输入后得到flag:KCTF{aTbAsH_cIpHeR_wItH_sOmE_tWiSt}
Knight Vault
IDA:
输入v8,让v8经过for循环的运算,再用运算的数据和v7比较与否;
思路还是改写for循环的运算,使其逆向,把v7变回v8;
代码:
1 |
|
运行得到flag:4CTF{sO_yOu_gOt_mE_gOOd_jOOb_hApPy_hAc4iNg}
Droid Flag
这是个安卓APK,用jeb分析:
这是整个onCreate方法;
下方可以看到v1变量在添加flag样式的字符,并且使用getSx函数获取字符串;
如下是getSx系列:
它是用16进制下标在字符串里找对应id的字符串,那就进入字符串里寻找;
最后结果:
从字符串里看出,就这样输入貌似并不是flag,但是把字符反着输入,就可以拼接成单词了,比如s7代表的 D10RdNa ,反转输入就变为 aNdR01D -> android ;
最后通过这样的字符串拼接方法得到flag:KCTF{aNdR01D_s1MpL3_r3V3rS3}
Knight Switch Bank
IDA:
输入v5,进入while循环开始选择性的运算,最后还有一个while循环,结束后让运算过的v5与v6比较与否;
这个套路很像之前的 flag_checker 这道题;唯一不同的就是两个循环的样子变了一下;
第一个循环在选择输入的字符:如果是小(大)写字母的前13个,就加13;如果是小(大)写字母的后13个,就减13;如果不是字母,就减32;
第二个循环就是自加2;
跟之前一样,改写一下循环里的东西:
1 |
|
运行后得到flag:KCTF{So_YoU_ROT_iT_gOOd_jOOb}
总结
二进制方向要说没收获吧,其实还是有的,就比如安卓逆向和java逆向,当时看到的时候并不知道.getstring()函数是什么东西,更不知道其他点过去点过来的函数;都需要去网上查找学习才能弄懂;
因为简单,然后学习其他方向的内容,也是挺头大的,不过也同时收获很多知识;
比如密码学的RSA的简单了解和运用,web的SQL注入,misc 3D建模以及pacpng后缀文件的运用;
之后就是主打hgame了,在hgame结束的时候也会有这样类似的复盘发布的;