首先不要误会,这几道题不是因为简单而放在零碎中。
思维混乱的出题人
下载:http://pan.baidu.com/s/1i57edOp 密码:61z7
说句实话,我做完后感觉这题的确有些混乱,我尽量简单的说。
先随便跑跑,发现随便输入最后会显示What do you his mother's want to do!
,OD载入,查找字符串,发现3个比较可疑的字符串tutushigecaiji
,aGN0ZntpdF9pc19ub3RfZmxhZyF9
和What do you his mother's want to do!
,第一个字符串让我感觉到了出题者和土土某种微妙的关系。动态调试后可知0x013E2B70是一个gets之类获取用户输入的函数,不是重点,略过。
比较微妙的是,当我们f8小心单步后可以发现:
当我们执行完CALL 0x13E1070后,字符串hctf{it_is_not_flag!}
出现在了我们的堆栈区,所以我用IDA看了一下这个CALL,发现0x61(‘=’)这个字节:
理所当然的想到了base64,拿aGN0ZntpdF9pc19ub3RfZmxhZyF9
进行base64解密得到了我们看到的字符串hctf{it_is_not_flag!}
,合理推测flag应该是由某个base64字串解密得到。
回头看一下,我们现在还有一个字符串没有用到:tutushigecaiji
,我们总不能把出题人想的这么坏,写个和题目无关的字符串只为了吐槽一下土土吧?我们到字符串的附近下断,动态跟踪一下,发现此处:
程序在循环利用写在0x0059F6E4出的字节码进行某种解密,我们就在跳转的前面轻轻摁一下f4,发现此时数据窗口出现了两个可疑字符串:
我们把它拼起来,得到aGN0ZntJdF8xc190aDNfZmxhRyF9
,base64解密一下得到flag:hctf{It_1s_th3_flaG!}
easy-shell
下载:http://pan.baidu.com/s/1i5OEU5v 密码:6x5w
首先扫下壳:
正如文件的名字,是个vmp壳,说真的我挺害怕这个壳的。
前排提醒:此处调试用的OD不能是原版OD,你可以使用网上各大论坛改的OD,比如52pojie,学破解,飘云阁等等。调试时需要Strong OD,FKVMP,忽略异常等。(你应该需要在XP上调试)
OD载入,先如下设置:
在此时的代码处右键选择FKVMP>>start,点击OD上方的L按钮,找到retn:
记录retn的地址:0x00571903
接着在OD上下断点:bp VirtualProtect
,按f9运行,观察堆栈区:
直到NewProtect = READONLY:
此时alt+B,断点界面取消或禁用断点,然后alt+M,对text段下内存访问断点:
f9一下,取消text段的访问断点,来到这里:
掏出我们之前记录下的retn地址:ctrl+G转到然后f2下断:
f9一下,取消retn的断点,再对text段下内存访问断点,f9一下,来到了我们的oep:
(此时我们可以对oep下硬件执行断点,方便下次调试,不用再重复之前那些动作)
我们现在可以用lordpe dump一下镜像,虽然IAT没有修复,但是IDA还是能分析部分的。
ida载入,找到关键函数:
1 | int sub_401000() |
忽略中间的n多细节,我们只看两段:
1 | do |
结合OD动态调试,我们发现,函数是将写在0x0012ff48处的数据做byte = (byte - 3) ^ '3'
变换:
然后和写在0x0012FF2C处的数据一位一位比较,如果相同则输出’cool‘:
由此用py写出反函数:
1 | enc = [0x56,0x53,0x42,0x50,0x4B,0x5F,0x56,0x6F,0x65,0x7F,0x61,0x6F,0x0D,0x7C,0x71,0x6F,0x63,0x7F,0x6F,0x63,0x79,0x0D,0x7C,0x62,0x49] |
得flag:hctf{oh_YOU_ARE_SO_SMART}
后话:如果你知道vs编译出来的程序的用户函数一般都从data段最前面开始,而且你有成功猜到这道题的主函数在0x401000处的话,这道题会简单很多:首先下一个退出断点:BP ExitProcess,运行后断下,ctrl+G来到401000,发现代码完整,接着在数据窗口ctrl+G来到401000,对401000下硬件执行断点,重新载入,f9运行,程序成功断在401000处,然后和上面一样,很快就解得了flag。
coder
下载:http://pan.baidu.com/s/1c1ZyuM8 密码:mugh
一开始,我是打算用正常的做re题的方法来解的,先跑跑,逆代码,分析,写反函数之类的来解,但我失败了,大概是水平不够。但我们依然有方法解题。
惯例扔到ida里,在main函数的加密函数中有如下一段:
1 | printf("encrypt ok, your key is ", buf); |
由此我们知道,key1为5位,key2为10位,加密过程可以大致表示为:enc[i] ^= key3[i%10]
,其中key3为10位,key3[i] = key1[i%5] ^ key2[i]
。
但我们现在不知道sub_401766函数是做什么的,起初我怀疑这个函数会对key做某种变换,导致每一轮加密用的key都不一样(满足某种函数关系),我试着分析了一下,但关系实在不好找,以为要GG,但我们打开flag.mp4文件,看到文件尾部为:
非常整齐,十个一组,所以我的顾虑打消了,key3应该是不会改变的。
flag的格式为mp4,这个条件我们不能漏下,我随便打开了我硬盘上的几个mp4文件,发现前八个字节都是相同的,为dec1 = [0x00,0x00,0x00,0x20,0x66,0x74,0x79,0x70]
:
而加密后的文件头8个字节为:enc1 = [0xFC,0x3E,0x96,0x1E,0xFE,0xDC,0xD9,0x32]
我们将两者进行异或,得到xor1 = [0xFC,0x3E,0x96,0x3E,0x98,0xA8,0xA0,0x42]
如果没有猜错,文件的结尾出应该是一串相同的字符,就像我手头的这个文件一样:
那么我们用python脚本:
1 | file_end = [0x3e,0x96,0x06,0x98,0xa8,0xa0,0x42,0x34,0x8a,0xfc,0x3e,0x96,0x06,0x98,0xa8,0xa0,0x42,0x34,0x8a,0xfc] |
观察输出有如下一段:
1 | ==== |
这就验证了我们的猜想,只是flag.mp4的文件头的第4字节和我手头的MP4文件不同。根据file_end,从而我们得到了真正的key3 = [0xFC,0x3E,0x96,0x06,0x98,0xA8,0xA0,0x42,0x34,0x8a]
我们利用key3对flag.mp4进行解密:
1 | key3 = [0xFC,0x3E,0x96,0x06,0x98,0xA8,0xA0,0x42,0x34,0x8a] |
打开解密后的视频:
嗯,flag:hctf{L0ng_CSS_Seems_SHORT!}
奇怪的代码
下载:http://pan.baidu.com/s/1nvjruXV 密码:3y72
题目描述:
部分思路来自:https://github.com/xoreaxeaxeax/movfuscator ,但比这个要简单的多
首先看了上面那和github的网站,是一个混淆器,可以生成只含有mov指令的程序,作者是这样说的:
The M/o/Vfuscator (short ‘o’, sounds like “mobfuscator”) compiles programs into “mov” instructions, and only “mov” instructions. Arithmetic, comparisons, jumps, function calls, and everything else a program needs are all performed through mov operations; there is no self-modifying code, no transport-triggered calculation, and no other form of non-mov cheating.
The basic effects of the process can be seen in overview, which illustates compiling a simple prime number function with gcc and the M/o/Vfuscator.
而这题只有一个函数是被混淆的。
首先ida载入,大致分析完了程序的流程:
main函数:
make_arr()生成数组:
check校验函数:
其中最主要的就是check函数了。
首先分析出了4种array里的数据所满足的关系:
arr1[x] = (x/256)^(x%256)
arr2[x] = x
arr3[x] = 256*x
arr4[x] = 4*x
由此可用python写出解密函数(不想仔细分析了,直接爆破):
1 | def arr1(n): |
得到flag:hgame{is_it_intersting_to_moov?}