system hacking/dreamhack(드림핵)
uaf_overwrite
blackbearwow
2022. 4. 17. 17:14
이 문제는 답을 알려준 문제이다. 하지만 모르는 내용이 많이 나와 정리해보자.
// 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;
}; //size: 0x20
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;
}
}
}
소스파일을 보면 Human구조체, Robot구조체, custom으로 0x100이상의 메모리를 malloc 동적 할당한다.
알아야 할것:
heap에서 bin은 free된 청크들을 관리하는 것이다.
tcachebin, unsortedbin
0x410이하의 청크는 tcachebin에 할당된다.
0x410초과의 청크를 할당하고, 해제하면 unsortedbin에서 관리된다.
unsortedbin에서 첫번째 청크는 fd, bk가 항상 main_arena+alpha로 고정된다.(같은 libc라면)
main_arena는 항상 libc_base에서 같은 거리에 있다.
tcachebin은 topchunk와 인접해도 병합 대상이 아니다.
unsortedbin은 topchunk와 인접하면 병합 대상이다.
linux는 heap 할당을 first fit을 채택중이다. 참고: https://code1018.tistory.com/192
시나리오:
custom으로 0x500크기의 청크를 2번 할당하고 0번째 청크를 free한다.
custom에서 0x500크기의 청크를 할당하고 데이터는 한바이트만 전송한다.
heap는 first fit방식이므로, free된 청크의 자리에 할당된다.
main_arena+alpha값이 출력될거고, 해당값을 이용해 libc_base값을 구한다.
원가젯주소를 구하고 human->age에 넣는다.
robot_func()실행하면 원가젯 실행.