

Full RELRO가 적용되어있기 때문에 got에 쓰기권한이 없으므로 버퍼 오버플로우 공격으로 인한 return address를 가젯으로 덮는 그런 공격은 못한다.
해당문제는 리눅스 18.04, libc-2.27.so 기준으로 작성되었기 때문에 hook overwrite 기법으로 풀 것이다.
free함수의 free_hook 함수를 system함수의 주소로 덮는다면 free함수를 실행하면 system함수가 실행이 될 것이고 free('/bin/sh')는 system('/bin/sh')이 될 것이다.
코드를 살펴보면 stack의 부분을 읽을 수 있고, 특정 주소가 참조하는 값을 바꿀 수 있으며, 특정 주소에 대해 free를 실행한다.

해당 부분에서 우리는 libc 베이스 주소를 구하고 이를 통해 system, __free_hook, /bin/sh의 주소를 구할 것이다.

우선 main함수는 라이브러리 함수인 libc_start_call_main 함수가 호출하므로 main함수의 return address에는 libc_start_main + x로 돌아갈 주소가 적혀있을 것이다. 해당 주소를 기반으로 libc 파일 내부의 main return address의 상대 주소를 찾아 빼게 된다면 우리는 libc 베이스 주소를 구할 수 있다.
그럼 우선 main함수의 returnaddress를 읽어야 하므로 gdb로 스택 프레임을 보면 다음과 같다.

rsp는 0x50만큼 빼지만 우리가 입력하는 buf 배열은 rbp-0x40위치에 존재하므로 0x40(canary 포함) + 0x08(SFP)를 덮으면 main 함수의 return address를 출력할 수 있다.
따라서 libc 베이스 주소를 구하는 코드는 다음과 같다.

여기서 main함수의 return address를 6바이트만 받아오는 이유는 libc의 주소가 6바이트기 떄문이다.
이렇게 main함수의 return address를 통해 libc 베이스 주소를 구했다면

해당 부분에서 __free_hook함수 가 가리키는 값을 system함수의 값으로 바꿔준다.

이후 free함수로 메모리를 해제할 주소를 '/bin/sh' 문자열의 주소로 입력하면 system('/bin/sh')가 실행이 되게 된다.


해당 hook overwrite는 신기하고 강력한 공격 기법이라고 생각하지만 리눅스 18.04, libc-2.27.so 이하 버전에서만 사용이 가능한 점이 상당히 아쉽다고 생각한다.
추가로 one_gadget이라는 가젯은 실행만 되면 쉘이 얻어지는 가젯으로

libc 파일을 기준으로 종류와, 제약사항을 볼 수 있다.
해당 문제에서는 0x4f432의 one-gadget이 유효하다. (왜인지는 모름)
그리고 해당 주소는 상대주소이므로 libc 베이스 주소에 더하여 사용하면 된다.
페이로드는 다음과 같다.

one-gadget의 수소로 0x131313르 보내는거는 그냥 64bit 기준 rdi에 0x131313을 넣는 것을 의미한다. 따라서 해당 값이 원가젯의 실행 여부와는 관련이 없어 보인다.

실행하면 쉘이 잘 얻어지는 것을 볼 수 있다.
'보안 > DreamHack' 카테고리의 다른 글
| Dreamhack hook (0) | 2024.10.28 |
|---|---|
| Dreamhack oneshot (0) | 2024.10.18 |
| Dreamhack basic_rop_x86 (0) | 2024.10.11 |
| Dreamhack basic_rop_x64 (0) | 2024.10.10 |
| Dreamhack Return Oriented Programming (0) | 2024.10.10 |