angr进阶(5)内存操作
angr也可以将符号写在内存里,控制内存中的值,结合任意位置开始有奇效,但就是慢sym-write
1 p = angr.Project('./issue', load_options={"auto_load_libs": False}) 2 state = p.factory.entry_state(add_options={angr.options.SYMBOLIC_WRITE_ADDRESSES}) 3 u = claripy.BVS("u", 8) 4 state.memory.store(0x804a021, u)
因为最近好像要开始0ctf了,再分析一道0ctf的题目,0ctf_trace
这个题目两个文件,一个.bin的看起来像是二进制文件,其中trace是MIPS指令集。上万行,头大。
首先通过grep jal可以得到所调用的所有函数的起始地址,接着grep jr r31得到函数的结束地址
trace中总共三个函数,有一个函数运行了100多次,虽然每个函数还是很长就是了
然后分析函数得到Flag的地址,程序首先对常量字符初始化了,然后加上了一串未知字符串,就是flag
1 #!/usr/bin/env python2 2 3 from __future__ import print_function 4 import struct 5 import angr 6 7 MAIN_START = 0x4009d4 8 MAIN_END = 0x00400c18 9 10 FLAG_LOCATION = 0x400D80 11 FLAG_PTR_LOCATION = 0x410EA0 12 13 def load_trace(): 14 res = [] 15 delay_slots = set() 16 with open("./trace_8339a701aae26588966ad9efa0815a0a.log") as f: 17 for line in f: 18 if line.startswith('[INFO]'): 19 addr = int(line[6:6+8], 16) 20 21 res.append(addr) 22 23 if ("move r1, r1" in line): 24 delay_slots.add(addr) 25 26 return res, delay_slots 27 28 def main(): 29 trace_log, delay_slots = load_trace() 30 31 project = angr.Project("./data.bin", load_options={ 32 'main_opts': { 33 'backend': 'blob', 34 'base_addr': 0x400770, 35 'arch': 'mipsel', 36 }, 37 }) 38 39 state = project.factory.blank_state(addr=MAIN_START) 40 state.memory.store(FLAG_LOCATION, state.solver.BVS("flag", 8*32)) 41 state.memory.store(FLAG_PTR_LOCATION, struct.pack("<I", FLAG_LOCATION)) 42 43 sm = project.factory.simulation_manager(state) 44 choices = [state] 45 46 print("Tracing...") 47 for i, addr in enumerate(trace_log): 48 if addr in delay_slots: 49 continue 50 51 for s in choices: 52 if s.addr == addr: 53 break 54 55 else: 56 raise ValueError("couldn't advance to %08x, line %d" % (addr, i+1)) 57 58 if s.addr == MAIN_END: 59 break 60 61 if s.addr + 4 in delay_slots: 62 choices = project.factory.successors(s, num_inst=2).successors 63 else: 64 choices = project.factory.successors(s, num_inst=1).successors 65 66 state = s 67 68 print("Running solver...") 69 70 solution = state.solver.eval(state.memory.load(FLAG_LOCATION, 32), cast_to=bytes).rstrip(b'\0').decode('ascii') 71 print("The flag is", solution) 72 73 return solution 74 75 def test(): 76 assert main() == "0ctf{tr135m1k5l96551s9l5r}" 77 78 if __name__ == "__main__": 79 main()