시작
안녕하세요 :D
오랜만에 포너블 라이트업입니다.
heap 문제들은 how2heap 공부 끝나고 풀어야 될 것 같아서.. 눈에 보이는 문제들만 빠르게 풀려고 해요.
babyfsb 시작해보죠!!
(구름ide에서 터미널 내용 복사가 안 되네요.. 캡쳐 도구로 찍었습니다 ㅠㅠ)
Write UP
main() 입니다.
버퍼 size에 맞게 read() 후 printf() 하는데, 인자를 rdi 하나만 전달하는 것 보니깐 fsb가 터질 것 같아요.
64bit 포맷스트링 시 페이로드를 어떻게 줘야 할 지는 You are silver
문제에서 했었죠? (https://powerco3e-lch.tistory.com/89)
레지스터 먼저 leak 후 스택 leak이었으니깐, %6$ln
이 스택의 첫 번째 8 bytes를 가리켰습니다.
처음에 생각한 것은 리턴 주소를 변조하는 방법이었어요.
노란색 부분이 리턴 주소인데, 여기(0x7ffc2cd76d28
)를 가리키는 영역을 찾아서 값을 덮어쓰면 될 줄 알았는데
..없더라구요. 때문에 특정 함수를 덮어야합니다.
main()을 보면 BOF가 터지는 것도 아니어서 특정 함수라고 해봤자 카나리를 검사하는 __stack_chk_fail()
뿐이에요.
얘는 plt, got가 없는 줄 알았는데..
libc에 이 함수도 있었습니다. 지금 보니깐 main()에 @plt가 붙어있네요 ㅋㅋㅋㅋ
이 녀석의 got값을 가젯의 주소로 돌려 주소를 leak하면 될 것 같습니다.
페이로드는 You are silver
때와 똑같아요. 가젯 주소 + %?$ln + AA.. 로 16 bytes를 맞춰주고 뒤에 got 주소를 쓰는거죠.
%4196236d + %8$ln + aa를 페이로드로 줬어요. 딱 맞게 들어갔네요 :D
이 뒤에 __stack_chk_fail@got 주소를 주면 %8$ln에 의해 가젯의 주소가 덮어쓰여질 것입니다.
이제 어떤 가젯을 줘야할까요? 바로 pop rdi; ret 가젯으로 돌려서 puts()를 호출하면 될까요?
rsp 레지스터의 위치를 직접 확인해보겠습니다.
%4196236d%8$ln을 주고 뒤에 __stack_chk_fail@got를 붙여서 실행했습니다.
현재 rsp는 0x7fff28f7a090
이네요.
__stack_chk_fail() 실행 후 rsp 입니다. 8 bytes 올라간 0x7fff28f7a088
이네요.
때문에 바로 pop rdi; ret 가젯을 주면 이상한 값이 pop 되기 때문에
pppp를 통해 rsp를 이동시킨 후 ret을 노란색 영역에 맞춰줘야 합니다.
fsb 페이로드 뒤에 값을 붙이면 노란색 영역부터 쓰이기 때문이에요.
결론적으로 페이로드는 %(ppppr 가젯 주소)d + %8$ln + “aa” + __stack_chk_fail@got + pr + puts@got + puts@plt + main() 이 되겠습니다.
마지막에 main()으로 돌리는 이유는 leak한 주소를 바탕으로 system(), “/bin/sh”의 주소를 딴 후
첫 번째 페이로드에서 puts@got 부분을 “/bin/sh”로, puts@plt 부분을 system()으로 바꿔주면 끝이겠네요.
코드입니다!!
긴 공백을 뛰어넘어서
플래그를 획득했습니다 :D
마무리
포너블 처음 할 때 제일 헷갈렸던 fsb인데, 이제야 뭔가 이해한 느낌입니다.
해당하는 값을 주소로 보고, 그 영역 안에다 출력한 바이트만큼 덮어쓴다라는 내용이.. 처음 할 땐 참 어려웠습니다 ㅠㅠ
64bit fsb는 더막막했었는데, 이젠 자신감이 조금 생기네요 ㅎㅎ
감사합니다 :D
'CTF_Write_UP > HackCTF' 카테고리의 다른 글
[HackCTF] j0n9hyun's secret (0) | 2019.11.22 |
---|---|
[HackCTF] Unexploitable_3, 4 (0) | 2019.11.16 |
[HackCTF] You are silver (0) | 2019.11.02 |
[HackCTF] World Best Encryption Tool (0) | 2019.10.22 |
[HackCTF] Register (0) | 2019.10.15 |