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的用法: