180125 逆向-安恒杯18-01-Re

1625-5 王子昂 总结《2018年1月25日》 【连续第482天总结】
A. 安恒杯18年1月逆向WP
B.
比赛的时候在冬令营,当天比较忙所以没来得及做。。
现在复现一下-0-可惜只有这一题是逆向
拖入64位IDA反编译,main函数倒是摆在面前,然而有一千多行的伪代码。。。OTZ
在linux中运行,发现有一句提示输入Show me the right key and I will give you the flag.
就用它来做突破点吧
Shift+F12查找,定位到main函数中的cout处
然而反编译状态下是没有显示的
180125 逆向-安恒杯18-01-Re
文章图片

往下读,发现调用cin接受了输入,然后通过c1函数来判断其长度

_BOOL8 __fastcall c1(__int64 a1) { return std::__cxx11::basic_string,std::allocator>::size(a1) != 8; }

很明显c1函数的参数就是input内容了,跟着它往下走
【180125 逆向-安恒杯18-01-Re】绕过一段跟input无关的操作,下面调用了[]的切片操作依次取得8个字符
180125 逆向-安恒杯18-01-Re
文章图片

第一个字符通过c2来判断,里面是一些很简单的加减异或操作,易反推出第一个字符为chr(30) = #
还以为接下来都是这么简单的内容,结果往下继续一走就懵逼了
180125 逆向-安恒杯18-01-Re
文章图片

WTF???
这么复杂拿头去跟哦
往后每个字符都要来这么一趟,真是要命
不过这里有个很关键的点:每个字符
也就是说,该程序对flag的8个字符都是独立判断、逐个校验的,彼此没有影响
那就可以逐位爆破了,穷举空间只有8*97,很轻松
因为程序在linux中,所以可以直接用pintool来跑
找到之前的脚本,修正几个点
1. 长度:由于本程序只在校验输入长度为8以后才继续,因此这里需要对爆破字符串添加padding来补足长度
2. 终止标识:错误没有字符提示,正确可能会有个”Congratulation”,但未知怎么读入。在已知flag长度的情况下,可以直接长度作为标识
python2脚本:
#-*- coding:utf-8 -*- import popen2,stringINFILE = "test" CMD = "/root/pin/pin -t /root/pin/source/tools/ManualExamples/obj-intel64/inscount1.so -- /root/ctf/anheng/18-1/re <" + INFILE choices = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$%&'()*+,-./:; <=>?@[\]^_`{|}~"#自定义爆破字典顺序,将数字和小写字母提前可以使得速度快一些~def execlCommand(command): global f fin,fout = popen2.popen2(command) result1 = fin.readline()#获取程序自带打印信息,wrong或者correct print result1 # if(result1 != 'Input : Wrong\n'):#输出Correct时终止循环 #f = 0 result2 = fin.readline()#等待子进程结束,结果输出完成 fin.close()def writefile(data): fi = open(INFILE,'w') fi.write(data) fi.close()def pad(data, n, padding): return data + padding * (n - len(data))flag = '' # flag = '#7Ff@(24' f = 1 while(f): l = 0#初始化计数器 for i in choices: key = flag + i#测试字符串 print ">",key writefile(pad(key, 8, '0')) execlCommand(CMD) fi = open('./inscount.out', 'r') # 管道写入较慢,读不到内容时继续尝试读 while(1): try: n = int(fi.read().split(' ')[1], 10) break except IndexError: continue fi.close() print n if(n-l > 30 and l):#如果两次运行指令差别过大,说明字符正确 flag += i if(len(flag)==8): f = 0 break else: l = n print flag

一会儿就能跑出来
#7Ff@(24
C. 明日计划
看安恒杯的讲解视频~

    推荐阅读