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处
然而反编译状态下是没有显示的

这里写图片描述

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

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

很明显c1函数的参数就是input内容了,跟着它往下走

绕过一段跟input无关的操作,下面调用了[]的切片操作依次取得8个字符
这里写图片描述
第一个字符通过c2来判断,里面是一些很简单的加减异或操作,易反推出第一个字符为chr(30) = #

还以为接下来都是这么简单的内容,结果往下继续一走就懵逼了

这里写图片描述

WTF???
这么复杂拿头去跟哦
往后每个字符都要来这么一趟,真是要命

不过这里有个很关键的点:每个字符

也就是说,该程序对flag的8个字符都是独立判断、逐个校验的,彼此没有影响

那就可以逐位爆破了,穷举空间只有8*97,很轻松
因为程序在linux中,所以可以直接用pintool来跑
找到之前的脚本,修正几个点
1. 长度:由于本程序只在校验输入长度为8以后才继续,因此这里需要对爆破字符串添加padding来补足长度
2. 终止标识:错误没有字符提示,正确可能会有个”Congratulation”,但未知怎么读入。在已知flag长度的情况下,可以直接长度作为标识

python2脚本:

#-*- coding:utf-8 -*-
import popen2,string

INFILE = "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. 明日计划
看安恒杯的讲解视频~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值