IDA分析:

长度不超过10,程序会把读入的字符串转成数字,我们需要找到一个不超过10位数的数字使得程序输出flag~

angr中需要hook这个strtol函数的原因:

angv[1]输入时是一个字符串。

程序处理时会用strtol函数,将字符串转为长整型,然后计算。

而如果angv[1]参数就是一个符号变量,再将符号变量传入strtol函数,进行求解时会出错。

添加限制条件:

flag前五个字符为:ASIS{

flag的剩余每一个字符都是0-f

#!/usr/bin/env python
# coding=utf-8

import angr

unconstrained_number = None

def strtol(state):
    global unconstrained_number
    unconstrained_number = state.solver.BVS('strtol', 64)
    state.regs.rax = unconstrained_number

def main():
    p = angr.Project("./fake")
    p.hook(0x4004a7, strtol, length = 5)
    state = p.factory.entry_state(args=['fake','123'])
    ex = p.surveyors.Explorer(find=(0x400450,), start = state)
    ex.run()
    found = ex.found[0]

    flag_addr = found.regs.rsp + 0x8
    found.add_constraints(found.memory.load(flag_addr, 5) == int("ASIS{".encode("hex"),16))
    for i in xrange(0, 32):
        op0 = found.memory.load(flag_addr + 5 + i, 1) >= ord('0')
        op1 = found.memory.load(flag_addr + 5 + i, 1) <= ord('9')
        op2 = found.memory.load(flag_addr + 5 + i, 1) >= ord('a')
        op3 = found.memory.load(flag_addr + 5 + i, 1) <= ord('f')
        found.add_constraints(
            found.solver.Or(
                found.solver.And(op0, op1),
                found.solver.And(op2, op3)
                )
            )
    found.add_constraints(found.memory.load(flag_addr + 5 + 32, 1) == ord('}'))
    flag = found.solver.eval(found.memory.load(flag_addr, 8 * 5))
    print 'Input Number:', found.solver.eval(unconstrained_number)
    print hex(flag)[2:-1].decode("hex").strip('\0')

if __name__ == '__main__':
    main()

这里主要是不太明白:这个32是怎么出来的,怎么会知道flag的长度是38位。从IDA里看到的是5个int64,应该是40位才对

另外找到了一种更好理解的方法:

https://github.com/p4-team/ctf/tree/master/2015-10-10-asisfin/re_150_fake#eng-version

用逆元思想

X * M === 'ASIS{...' (mod 2^64) <=> X === 'ASIS{...' * M^-1 (mod 2^64).

所以根据这个去暴力值即可

还学到了一种新姿势:

python fake.py > te.txt
cat te.txt | xargs -l ./fake

补充一个xargs的用法:

http://www.runoob.com/linux/linux-comm-xargs.html