2018安恒杯一月赛 Reverse WP
程序员文章站
2022-05-15 11:51:19
...
前言
第一次接触C++的程序,确实把我给绕晕了,很多基本的输入输入和函数都没有掌握,也就很难去分析了。这里学习了一波,记录一下。
分析
程序打开有2M多,几千行代码。emmm。从该字符串入手,
C++反汇编之后的函数,我们可能看不懂,但是IDA都给我们注释了,了解过C++的同学应该知道cout,cin,endl,<<<
之类的代码,F5反汇编查看, is_len_8
中进行了长度的判断。这时我们只需关注程序对我们的输入做了什么改变即可,因此可以忽略其中的大部分代码。
后面进行了切片操作,每次取一个字符,其中对第一个字符进行了简单的异或判断。但是对于后面的字符则做了很复杂的操作。
这代码想动态跟一遍很困难,不是已知的算法,如果要完全将其逆出来,难度可想而知,但是幸运的是,程序中是对每个字符进行判断。这样一来就可以采用逐字节**的方式,将正确的结果试出来!这里需要使用pintools,这个框架也学习了!
注意到正确的结果和错误的结果返回的结果不同,编写脚本如下。
我这里的脚本和参考的脚本一样,我觉得写的挺好的,有想法的可以用subprocess实现一下。理解了就OK。
#-*- coding:utf-8 -*-
import popen2,string
INFILE = "test"
CMD = "/root/pin-3.6-gcc-linux/pin -t /root/pin-3.6-gcc-linux/source/tools/ManualExamples/obj-intel64/inscount1.so -- /root/5a3397463481e <" + INFILE
choices = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$%&'()*+,-./:;<=>aaa@qq.com[\]^_`{|}~"#自定义**字典顺序,将数字和小写字母提前可以使得速度快一些~
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 = '#aaa@qq.com(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
总结
主要还是学习了一些逆向的方法和技巧,抓住输入和输出,看程序到底做了哪些变化,接着就是分析算法,或者寻找其它的思路。
上一篇: MYSQL 堆叠注入详解
下一篇: Sql注入基本原理