https://dreamhack.io/wargame/challenges/29
basic_rop_x64
Description이 문제는 서버에서 작동하고 있는 서비스(basic_rop_x64)의 바이너리와 소스 코드가 주어집니다.Return Oriented Programming 공격 기법을 통해 셸을 획득한 후, "flag" 파일을 읽으세요."flag" 파일의
dreamhack.io
오늘은 드림핵의 basic_rop_x64 write up을 작성해보겠습니다.
이 문제도 이름처럼 rop와 관련된 문제입니다.

문제에 libc.so.6을 포함한 5개파일이 제공됩니다.
먼저 보호 기법을 확인해보겠습니다.

지금까지 풀었던 문제와 다르게 Canary가 없고, NX만 활성화 된 상태입니다.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void alarm_handler() {
puts("TIME OUT");
exit(-1);
}
void initialize() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
signal(SIGALRM, alarm_handler);
alarm(30);
}
int main(int argc, char *argv[]) {
char buf[0x40] = {};
initialize();
read(0, buf, 0x400);
write(1, buf, sizeof(buf));
return 0;
}
소스코드는 다음과 같은데 alarm_handler랑 initialize는 워게임 편의를 위해 제공 되는 함수라 사실 아래 소스코드만 보시면 될 것 같습니다.
int main(int argc, char *argv[]) {
char buf[0x40] = {};
read(0, buf, 0x400);
write(1, buf, sizeof(buf));
return 0;
}
이젠 딱 봐도 버퍼 오버플로우가 발생하는 코드라는 건 쉽게 알 수 있습니다.
NX가 있어 셸코드를 실행시키는게 불가능하므로 ROP를 사용하여 system("/bin/sh")를 실행하는 것을 목표로 하겠습니다.
버퍼는 0x40 = 64바이트만큼 입력을 저장하고 패딩 0x8을 더하면 buf가 할당된 바이트에서 72바이트를 입력하면 RET값을 원하는 값으로 설정할 수 있습니다.
이제 system함수 주소를 계산해야합니다.
저희가 여태까지 했던 것 처럼, 라이브러리의 Base 주소를 구하면 Base주소 + system함수의 offset을 통해 system 함수의 주소를 구할 수 있습니다.
소스코드에서 선언된 read함수의 GOT 값을 읽으면 system함수의 주소를 구할수 있습니다.
다음으로 /bin/sh라는 문자열을 찾아야하는데, 해당 문자열은 대부분의 경우 libc.so.6안에 매핑되어있다고 합니다.
이것도 동일하게 Base주소 + 문자열 오프셋으로 주소를 구해야합니다.

p = remote("host",port)
e = ELF("./basic_rop_x64")
libc = ELF("./libc.so.6")
read_plt = e.plt["read"]
read_got = e.got["read"]
write_plt = e.plt["write"]
write_got = e.got["write"]
main = e.symbols["main"]
read_offset = libc.symbols["read"]
system_offset = libc.symbols["system"]
sh = list(libc.search(b"/bin/sh"))[0]
이렇게 기본 세팅만 해줬습니다.
plt주소를 gdb에서 찾고 직접 숫자로 넣어도 상관없는데, 일단 이게 더 편한것 같아 이렇게 넣었습니다.
이제 가젯들도 찾아주겠습니다.
ROPgadget --binary ./basic_rop_x64 --re "pop rdi"

ROPgadget --binary ./basic_rop_x64 --re "pop rsi"

ROPgadget --binary ./basic_rop_x64 --re "ret"

이제 페이로드를 작성해보겠습니다.
먼저 버퍼 크기 + 패딩해서 A * 48 만큼 보내야합니다.
다음 return to main을 위해 main 주소를 추가해줍니다.
다음 payload를 send한 뒤 write로 인해 출력되는 A * 0x40을 recv해준 뒤 출력되는 문자열을 저장합니다.
해당 read값에 담겨있는 주소를 바탕으로 system함수의 주소와 binsh문자열의 주소를 담습니다.
다음으로 다시 main으로 돌아왔으니 payload를 다시 작성해서 system("/bin/sh")를 호출해주면 완성됩니다
서버에 연결하면 다음과 같이 flag를 획득 할 수 있습니다!

다음은 익스플로잇 전문입니다.
저번에 풀었던 rop보다는 카나리가 없으니 체감은 훨~씬 쉬운거같은데 그래도 아직 익숙하지가 않아 너무 어려운 것 같습니다..
복습을 열심히 해야겠네요 ㅜ
읽어주셔서 감사합니다.
'문제 풀이 > Write-up' 카테고리의 다른 글
| [Write-up]SECCON 2022 Quals babyfile write-up - 2 (0) | 2025.12.30 |
|---|---|
| [Write-up]SECCON 2022 Quals babyfile write-up - 1 (2) | 2025.12.23 |
| [Pwnable] FSOP - 2 (House of orange write-up) (2) | 2025.11.28 |
| [Write-up] Captain-Hook Write up (frida Hooking ③) (3) | 2025.07.14 |