pwnable.kr AEG 문제를 보던 중 푸는데에 ANGR을 사용해보면 좋을 것 같아 이 참에 찾아보았다.
구글링 등 예제 코드를 보고 내가 대충 작성한 코드는 다음과 같았는데
(문제 바이너리를 local 로 다운로드 받았다고 치고 시작)
mine.py
def main(): proj = angr.Project('newbin0', load_options={"auto_load_libs": False}) input_size = 0x60 argv1 = claripy.BVS("argv1",input_size * 8) init = proj.factory.entry_state(args=["./newbin0", argv1]) init.libc.buf_symbolic_bytes=input_size + 1 al = [0x947C86,0x947976,0x9478FB,0x947889,0x947809,0x94778C,0x94770C,0x94768C,0x947610,0x9475A8,0x94752B,0x9474A9,0x94742C,0x9473B3,0x947337,0x9472BB,0x94723B] for byte in argv1.chop(8): init.add_constraints(byte >= '0') init.add_constraints(byte <= 'Z') init.add_constraints(byte != '\x3a') init.add_constraints(byte != '\x3b') init.add_constraints(byte != '\x3c') init.add_constraints(byte != '\x3d') init.add_constraints(byte != '\x3e') init.add_constraints(byte != '\x3f') init.add_constraints(byte != '\x40') init_path = proj.factory.path(init) path_group = proj.factory.path_group(init) path_group.explore(find=FIND_ADDR, avoid=al) found = path_group.found[0] solution = found.state.se.any_str(argv1) return solution |
위와 같이 코드를 작성하고 실행할 경우 문제는 원하는 방향으로 풀리고 Hex 값을 return 해주지만 실행시간이 약 60초 걸렸다.
문제에서 주어진 시간은 10초로 angr 돌리는데에만 터무니없이 긴 시간이 걸렸음.
시간을 줄이기 위해 avoid 조건을 이용해 이것 저것 넣어봤는데 효과는 미비했다.
구글링 중 github에 aeg 문제풀이 코드가 나와있는 것을 찾았고 여기서 angr 부분만 참고했다.
(출처 : https://github.com/rot256/Wargames/blob/master/pwnable/aeg/attack.py)
원본 코드는 위 URL에서 확인할 수 있으며 밑에는 테스트에 필요한 코드만 추출, 조작함
attack.py
# Create symbolic buffer p = angr.Project(tar) buf = claripy.BVS("buf",48*8) start_state = p.factory.blank_state(addr=0x2233b96) start_state.memory.store(0x2436160, buf) # Setup a stack frame start_state.regs.rbp = start_state.regs.rsp start_state.regs.rsp = start_state.regs.rsp - 0x50 start_state.memory.store(start_state.regs.rsp, start_state.se.BVV(0, 8*0x32)) # Setup stepper pg = p.factory.path_group(start_state) def step_func(pg): pg.drop(filter_func = lambda path: path.addr == 0x2233bbd) pg.stash(filter_func = lambda path: path.addr == 0x4006e0, from_stash='active', to_stash='found') return pg pg.step(step_func = step_func, until = lambda pg: len(pg.found) > 0) f = pr.found[0] cert = f.state.se.any_str(buf) print cert.encode('hex') |
위 스크립트 실행 시 약 6-7s 정도 시간 소요로 답을 구할 수 있었다.
결국 차이점은
1) 적절한 바이너리의 start state 설정
2) avoid 조건
으로 필요한 연산만 하도록해 state를 줄여줄 수 있는 것으로 보인다.
조금 더 공부해봅시다.
'Pwnable.kr > Grotesque' 카테고리의 다른 글
[pwnable.kr] dos4fun - 444pt (5) | 2018.03.14 |
---|---|
[pwnable.kr] sudoku - 111pt (0) | 2018.02.19 |
[pwnable.kr] AEG - 550pt (0) | 2018.02.11 |
[pwnable.kr] maze - 150pt (0) | 2017.12.23 |