前言
第一次 打国际赛
只能说 太有意思啦(难死我吧):sob: :sob: :sob:
首先对师傅们 及 我自己 说句
不管怎么样 我会好好努力学习的
:grin: :grin: :grin: :grin: :grin: :grin:
然后的话 不管怎么说都学到了一点东西
单拿题目来讲 队里师傅出了第一个CycleChaser
笔者呢 就对这道领悟的还算…
(我太菜辣 Orz Orz)
不瞎掰扯了 看题
有所错误, 望指正 诚心希望大家能指明是否有误
笔者万分感谢 (Orz)
CycleChaser
查壳 运行(不能运行)
拖入ida分析
思路
这就是 关键部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| v16 = malloc(0x4009uLL); // malloc分配0x4009空间来存放上面所作的操作 - 理解位初始化也可以 if ( !v16 ) { puts("Error."); exit(6); } if ( fread(v16, 1uLL, 0x4009uLL, stdin) != 0x4009 ) { puts("Error."); exit(7); } v17 = calloc(0x40uLL, 1uLL); // calloc分配64空间 作为true_flag for ( j = 0; j <= 0x2003F; ++j ) { if ( j > 0x1FFFF ) { v5 = *(_BYTE *)((j & 0x3F) + v15); // v5 为 下面异或key // v15 为 {}中间 - input } else { LOWORD(n_4) = rand() & 0x3FF; n_4 = (unsigned __int16)n_4; v5 = *((_BYTE *)v12 + (unsigned __int16)n_4);// v5是随机出来的 } if ( (unsigned __int8)step(v16, 0x4009LL) ) // step函数作为关键call *((_BYTE *)v17 + (j & 0x3F)) ^= v5; } for ( k = 0; k <= 0x3F; ++k ) printf("%0X ", *((unsigned __int8 *)v17 + k));// 输出true_flag - v17
|
好的 引用队内是师傅的思路就是
应该是用符号执行找到一个input使得可以在循环的前0x20000次中都让step返回0,再后续的0x3F次中都返回1
意思就是 说 下面那个 异或的 关键call
让true_flag ^ 1 = 不可控的数
而前面空间 ^ 0 = 可控的数(这个数本身)
example
1 2 3 4 5 6 7 8 9 10
| >>> a = 10 >>> a ^ 0 10 >>> a ^ 1 11 >>> b = 1 >>> b ^ 0 1 >>> b ^ 1 0
|
然后的话 我想用angr跑一下 试试
但笔者学到的都是皮毛
并没有什么结果
后面看师傅的angr 脚本 (只能看懂 我写不出来 Orz)
也没有跑出来结果 大概是 少加了什么约束条件吧
贴一下(以后仿写 嘿嘿)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| import angr, claripy import sys, time
def main(argv): path_to_binary = "cyclechaser" p = angr.Project(path_to_binary)
start_address = 0x4019D7 initial_state = p.factory.blank_state( addr = start_address, add_options = { angr.options.SYMBOL_FILL_UNCONSTRAINED_MEMORY, angr.options.SYMBOL_FILL_UNCONSTRAINED_REGISTERS } )
initial_state.regs.rbp = initial_state.regs.rsp initial_state.regs.rsp -= 0xF0 input_size = 0x4009 input = claripy.BVS('input', input_size * 8) pointer_to_input = initial_state.regs.rsp + 0x40 fake_heap_addr_input = 0x30000000 initial_state.memory.store(fake_heap_addr_input, input) initial_state.memory.store(pointer_to_input, fake_heap_addr_input)
flag_size = 64 out_size = 64 buf_size = 0x400 flag = claripy.BVV(0, flag_size * 8) out = claripy.BVV(0, out_size * 8) buf = claripy.BVV(0, buf_size * 8) fake_heap_addr_flag = 0x40000000 fake_heap_addr_out = 0x50000000 fake_heap_addr_buf = 0x60000000 pointer_to_flag = initial_state.regs.rsp + 0x38 pointer_to_out = initial_state.regs.rsp + 0x48 pointer_to_buf = initial_state.regs.rsp + 0x20 initial_state.memory.store(fake_heap_addr_flag, flag) initial_state.memory.store(fake_heap_addr_out, out) initial_state.memory.store(fake_heap_addr_buf, buf) initial_state.memory.store(pointer_to_flag, fake_heap_addr_flag) initial_state.memory.store(pointer_to_out, fake_heap_addr_out) initial_state.memory.store(pointer_to_buf, fake_heap_addr_buf)
def found(simgr): if simgr.found: solution_state = simgr.found[0] print('success') solution = solution_state.solver.eval(input, cast_to=bytes).decode() solution = ' '.join(map('{}'.format, [ solution])) print(solution) else: raise Exception('not solution')
find_addr = 0x4019E7 avoid_addr = [0x40192C, 0x401478, 0x401510]
simgr = p.factory.simulation_manager(initial_state) simgr.explore(find=find_addr, avoid=avoid_addr) found(simgr) if __name__ == '__main__': start = time.time()
main(sys.argv)
end = time.time() total = end - start print(total)
|
结果
然后 师傅写出来暴破的脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| from pwn import *
real_flag = bytearray([0] * 64) for n in range(64):
r = remote('3.123.91.129', 13339)
seed = r.recvline() print(seed)
r.sendline(b'\x00' * (0x4009 - n) + b'\x01' * n)
result = r.recvline() result = result.split(b' ') flag = bytearray(b'') for res in result: flag += bytes([int(res.decode(), 16)])
for i in range(len(flag)): if real_flag[i] == 0 and flag[i] != 0: real_flag[i] = flag[i]
print(flag)
print(real_flag)
|
比赛closed了 然后 就不贴flag了
需要的师傅自己去跑一下吧
总结
比赛挺好
好的 本文结束
感谢观看 Orz
Orz