[DreamHack] [Pwnable] Return to Shellcode

image.png

image.png

이것저것 걸려있긴 하다.

하지만, NX가 걸려있지 않은 것을 보아 Canary만 우회할 수 있다면 쉘코드를 실행시킬 수 있을 것 같다.

소스코드 분석해보겠다.

// Name: r2s.c
// Compile: gcc -o r2s r2s.c -zexecstack

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

void init() {
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);
}

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

  init();

  printf("Address of the buf: %p\\n", buf);
  printf("Distance between buf and $rbp: %ld\\n",
         (char*)__builtin_frame_address(0) - buf);

  printf("[1] Leak the canary\\n");
  printf("Input: ");
  fflush(stdout);

  read(0, buf, 0x100);
  printf("Your input is '%s'\\n", buf);

  puts("[2] Overwrite the return address");
  printf("Input: ");
  fflush(stdout);
  gets(buf);

  return 0;
}

image.png

0x60만큼 빈공간이 선언됐고, push rbp가 보이기 때문에,

[ 버퍼(0x60 bytes) ] [ 카나리(8) ] [ 저장된 RBP(8) ] [ 리턴주소(8) ]
^                    ^             ^                 ^
|                    |             |                 +-- buf의 시작 주소(또는 NOP 슬레드 중간)
|                    |             +-- 임의(더미)
|                    +-- 복원한 정확한 카나리 8바이트
+-- 여기 앞부분에 x64 쉘코드를 놓고, 남는 공간은 NOP(0x90)로 패딩

의 스택 구조를 가지고 있을 것이다.

여기서 canary의 위치는 rbp-0x8이고, canary의 마지막 값은 \\x00 이기 때문에 해당 값만 덮기 위해서 A*89을 준다.

image.png

체크해보면, 해당 값의 끝값이 A(41)로 덮혔고, 이 실행에선 canary의 값이 0x3b4db137e8db0a00 라고 볼 수 있다.

물론, canary의 값은 매번 바뀐다.

따라서, 한번의 익스 실행 과정에서 canary leak + bof까지 한번에 진행해야한다는 것을 알 수 있다.