๐ก ์คํ ์ค๋ฒํ๋ก์ฐ์ ์คํ ๋ฒํผ ์ค๋ฒ ํ๋ก์ฐ์ ์ฐจ์ด์
์คํ ์์ญ์ ์คํ์ค์ ํฌ๊ธฐ๊ฐ ๋์ ์ผ๋ก ํ์ฅ๋ ์ ์๋ค. ๊ทธ๋ฌ๋ ํ์ ๋ ํฌ๊ธฐ์ ๋ฉ๋ชจ๋ฆฌ ์์์ ์คํ์ด ๋ฌดํํ ํ์ฅ๋ ์๋ ์๋ค. ์คํ ์ค๋ฒํ๋ก์ฐ(Stack Overflow)๋ ์คํ ์์ญ์ด ๋๋ฌด ๋ง์ด ํ์ฅ๋์ด ๋ฐ์ํ๋ ๋ฒ๊ทธ๋ฅผ ๋ปํ๋ค.
๋ฐ๋ฉด, ์คํ ๋ฒํผ ์ค๋ฒํ๋ก์ฐ๋ ์คํ์ ์์นํ ๋ฒํผ์ ๋ฒํผ์ ํฌ๊ธฐ๋ณด๋ค ๋ง์ ๋ฐ์ดํฐ๊ฐ ์ ๋ ฅ๋์ด ๋ฐ์ํ๋ ๋ฒ๊ทธ๋ฅผ ๋ปํ๋ค. ์ฉ์ด๊ฐ ๋น์ทํ์ฌ ํผ๋ํ๊ธฐ ์ฝ์ง๋ง, ์ด ๋์ ์ ํ ๋ค๋ฅธ ์๋ฏธ๋ฅผ ๊ฐ์ง๊ณ ์์ผ๋ฏ๋ก ์ฌ์ฉ์ ์ฃผ์ํด์ผ ํ๋ค.
์คํ ๋ฒํผ ์ค๋ฒํ๋ก์ฐ
(1) ๋ฒํผ ์ค๋ฒํ๋ก์ฐ
: ์คํ์ ๋ฒํผ์์ ๋ฐ์ํ๋ ์ค๋ฒํ๋ก์ฐ
โ ๋ฒํผ
- ๋ฐ์ดํฐ๊ฐ ๋ชฉ์ ์ง๋ก ์ด๋๋๊ธฐ ์ ์ ๋ณด๊ด๋๋ ์์ ์ ์ฅ์
- ๋ฐ์ดํฐ์ ์ฒ๋ฆฌ์๋๊ฐ ๋ค๋ฅธ ๋ ์ฅ์น๊ฐ ์์ ๋, ์ด ๋ ์ฌ์ด์ ์ค๊ฐ๋ ๋ฐ์ดํฐ๋ฅผ ์์๋ก ์ ์ฅํด ๋๋ ๊ฒ์ ์ผ์ข ์ ์์ถฉ ์์ฉ์ ํจ
- ๋ฒํผ๊ฐ ๊ฐ๋ ์ฐฐ ๋๊น์ง๋ ์ ์ค๋๋ ๋ฐ์ดํฐ ์์ด ํต์ ํ ์ ์์
- ๋น ๋ฅธ ์๋๋ก ์ด๋ํ๋ ๋ฐ์ดํฐ๊ฐ ์์ ์ ์ผ๋ก ๋ชฉ์ ์ง์ ๋๋ฌํ ์ ์๋๋ก ์์ถฉ ์์ฉ์ ํ๋ ๊ฒ์ด ๋ฒํผ์ ์ญํ
→ ํ๋์๋ ์ด๋ฌํ ์๋ฏธ๊ฐ ๋ง์ด ํฌ์๋์ด ๋ฐ์ดํฐ๊ฐ ์ ์ฅ๋ ์ ์๋ ๋ชจ๋ ๋จ์๋ฅผ ๋ฒํผ๋ผ๊ณ ๋ถ๋ฅด๊ธฐ๋ ํจ
โถ ์คํ์ ์๋ ์ง์ญ ๋ณ์๋ ‘์คํ ๋ฒํผ’, ํ์ ํ ๋น๋ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ 'ํ ๋ฒํผ'
โ ๋ฒํผ ์ค๋ฒํ๋ก์ฐ
๋ฌธ์ ๊ทธ๋๋ก ๋ฒํผ๊ฐ ๋์น๋ ๊ฒ์ ์๋ฏธํ๋ค. ๋ฒํผ๋ ์ ๊ฐ๊ธฐ ํฌ๊ธฐ๋ฅผ ๊ฐ์ง๊ณ ์์ผ๋ฏ๋ก ํน์ ์๋ฃํ ํฌ๊ธฐ์ ๋ฒํผ์ ํด๋น ์๋ฃํ๋ณด๋ค ๋ ํฐ ๋ฒํผ์ ํฌ๊ธฐ๊ฐ ๋ค์ด๊ฐ ๊ฒฝ์ฐ ๋ฒํผ๊ฐ ๋์น๋ ์ฆ, ์ค๋ฒํ๋ก์ฐ ํ์์ด ๋ฐ์ํ๋ค.
์ผ๋ฐ์ ์ผ๋ก ๋ฒํผ๋ ๋ฉ๋ชจ๋ฆฌ์์์ ์ฐ์ํด์ ํ ๋น๋์ด ์์ผ๋ฏ๋ก, ์ด๋ค ๋ฒํผ๋ ์ค๋ฒํ๋ก์ฐ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ ๋ค์ ์๋ ๋ฒํผ๋ค์ ๊ฐ์ด ์กฐ์๋ ์ํ์ด ์๋ค.
(2) ์ค์ ๋ฐ์ดํฐ ๋ณ์กฐ
๋ฒํผ ์ค๋ฒํ๋ก์ฐ๊ฐ ๋ฐ์ํ๋ ๋ฒํผ ๋ค์ ์ค์ํ ๋ฐ์ดํฐ๊ฐ ์๋ค๋ฉด, ํด๋น ๋ฐ์ดํฐ๊ฐ ๋ณ์กฐ๋จ์ผ๋ก์จ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค. ์๋ฅผ ๋ค์ด, ์ ๋ ฅ ๋ฐ์ดํฐ์์ ์ ์ฑ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์งํ์ฌ ๊ฒฝ๊ณ ํด์ฃผ๋ ํ๋ก๊ทธ๋จ์ด ์์ ๋, ์ ์ฑ์ ์กฐ๊ฑด์ด ๋ณ๊ฒฝ๋๋ฉด ์ ์ฑ ๋ฐ์ดํฐ์๋ ์๋์ด ์ธ๋ฆฌ์ง ์์ ์ ์์
โ ์คํ ๋ฒํผ ์ค๋ฒํ๋ก์ฐ ์์
// Name: sbof_auth.c // Compile: gcc -o sbof_auth sbof_auth.c -fno-stack-protector #include <stdio.h> #include <stdlib.h> #include <string.h> int check_auth(char *password) { int auth = 0; char temp[16]; strncpy(temp, password, strlen(password)); if(!strcmp(temp, "SECRET_PASSWORD")) auth = 1; return auth; } int main(int argc, char *argv[]) { if (argc != 2) { printf("Usage: ./sbof_auth ADMIN_PASSWORD\n"); exit(-1); } if (check_auth(argv[1])) printf("Hello Admin!\n"); else printf("Access Denied!\n"); }โ
๐ก sbof_auth.c ์์ ๋ถ์
1) main ํจ์
- argv[1]์ check_auth ํจ์์ ์ธ์๋ก ์ ๋ฌํ ํ ๋ฐํ ๊ฐ์ ๋ฐ์์ด
- ๋ฐํ ๊ฐ์ด 0์ด ์๋๋ผ๋ฉด "Hello Admin!"์, 0์ด๋ผ๋ฉด "Access Denied!"๋ผ๋ ๋ฌธ์์ด์ ์ถ๋ ฅ
2) check_auth ํจ์
- 16๋ฐ์ดํธ ํฌ๊ธฐ์ temp ๋ฒํผ์ ์ ๋ ฅ๋ฐ์ ํจ์ค์๋๋ฅผ ๋ณต์ฌํ ํ ์ด๋ฅผ "SECRET_PASSWORD" ๋ฌธ์์ด๊ณผ ๋น๊ต
- ๋ฌธ์์ด์ด ๊ฐ๋ค๋ฉด auth๋ฅผ 1๋ก ์ค์ ํ๊ณ ๋ฐํ
3) check_auth
- strncpy ํจ์๋ฅผ ํตํด temp๋ฒํผ๋ฅผ ๋ณต์ฌํ ๋, temp์ ํฌ๊ธฐ์ธ 16 ๋ฐ์ดํธ๊ฐ ์๋ ์ธ์๋ก ์ ๋ฌ๋ password์ ํฌ๊ธฐ๋งํผ ๋ณต์ฌ
- argv[1]์ 16 ๋ฐ์ดํธ๊ฐ ๋๋ ๋ฌธ์์ด์ ์ ๋ฌํ๋ฉด, ์ด๋ค์ด ๋ชจ๋ ๋ณต์ฌ๋์ด ์คํ ๋ฒํผ ์ค๋ฒํ๋ก์ฐ๊ฐ ๋ฐ์
4) auth
- auth๋ temp๋ฒํผ์ ๋ค์ ์กด์ฌํ๋ฏ๋ก, temp๋ฒํผ์ ์ค๋ฒํ๋ก์ฐ๋ฅผ ๋ฐ์์ํค๋ฉด auth์ ๊ฐ์ 0์ด ์๋ ์์์ ๊ฐ์ผ๋ก ๋ฐ๊ฟ ์ ์์
- ์ด ๊ฒฝ์ฐ, ์ค์ ์ธ์ฆ ์ฌ๋ถ์๋ ์๊ด์์ด mainํจ์์ if(check_auth(argv[1])) ๋ ํญ์ ์ฐธ์ด ๋จ
(3) ๋ฐ์ดํฐ ์ ์ถ
C์ธ์ด์์ ์ ์์ ์ธ ๋ฌธ์์ด์ ๋๋ฐ์ดํธ๋ก ์ข ๊ฒฐ๋๋ฉฐ, ํ์ค ๋ฌธ์์ด ์ถ๋ ฅ ํจ์๋ค์ ๋๋ฐ์ดํธ๋ฅผ ๋ฌธ์์ด์ ๋์ผ๋ก ์ธ์ํ๋ค. ๋ง์ฝ ์ด๋ค ๋ฒํผ์ ์ค๋ฒํ๋ก์ฐ๋ฅผ ๋ฐ์์์ผ์ ๋ค๋ฅธ ๋ฒํผ์์ ์ฌ์ด์ ์๋ ๋๋ฐ์ดํธ๋ฅผ ๋ชจ๋ ์ ๊ฑฐํ๋ฉด, ํด๋น ๋ฒํผ๋ฅผ ์ถ๋ ฅ์์ผ์ ๋ค๋ฅธ ๋ฒํผ์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ์ ์๋ค. ํ๋ํ ๋ฐ์ดํฐ๋ ๊ฐ์ข ๋ณดํธ๊ธฐ๋ฒ์ ์ฐํํ๋๋ฐ ์ฌ์ฉ๋ ์ ์์ผ๋ฉฐ, ํด๋น ๋ฐ์ดํฐ ์์ฒด๊ฐ ์ค์ํ ์ ๋ณด์ผ ์๋ ์๋ค.
โ ์คํ ๋ฒํผ ์ค๋ฒํ๋ก์ฐ ๋ฉ๋ชจ๋ฆฌ ๋ฆญ ์์
// Name: sbof_leak.c // Compile: gcc -o sbof_leak sbof_leak.c -fno-stack-protector #include <stdio.h> #include <string.h> #include <unistd.h> int main(void) { char secret[16] = "secret message"; char barrier[4] = {}; char name[8] = {}; memset(barrier, 0, 4); printf("Your name: "); read(0, name, 12); printf("Your name is %s.", name); }โ
์ ์์ ์ ๊ฒฝ์ฐ 8๋ฐ์ดํธ ํฌ๊ธฐ์ name ๋ฒํผ์ 12๋ฐ์ดํธ์ ์ ๋ ฅ์ ๋ฐ๋๋ค. ์ฝ๊ณ ์ ํ๋ ๋ฐ์ดํฐ์ธ secret๋ฒํผ์์ ์ฌ์ด์ barrier๋ผ๋ 4๋ฐ์ดํธ์ ๋ ๋ฐฐ์ด์ด ์กด์ฌํ๋๋ฐ, ์ค๋ฒํ๋ก์ฐ๋ฅผ ์ด์ฉํ์ฌ ๋ ๋ฐ์ดํธ๋ฅผ ๋ชจ๋ ๋ค๋ฅธ ๊ฐ์ผ๋ก ๋ณ๊ฒฝํ๋ฉด secret์ ์ฝ์ ์ ์๋ค.
(4) ์คํ ํ๋ฆ ์กฐ์
Calling Convention์ ํจ์๋ฅผ ํธ์ถํ ๋ ๋ฐํ ์ฃผ์๋ฅผ ์คํ์ ์๊ณ , ํจ์์์ ๋ฐํ๋ ๋ ์ด๋ฅผ ๊บผ๋ด์ด ์๋์ ์คํ ํ๋ฆ์ผ๋ก ๋์๊ฐ๋ค. ์ด๋ฅผ ๊ณต๊ฒฉ์์ ๊ด์ ์์ ๋ฐ๋ผ๋ณด๋ฉด, '์คํ ๋ฒํผ ์ค๋ฒํ๋ก์ฐ๋ก ๋ฐํ ์ฃผ์(Return Address)๋ฅผ ์กฐ์ํ๋ฉด ์ด๋ป๊ฒ ๋ ๊น'ํ๋ ๊ถ๊ธ์ฆ์ ๊ฐ์ ธ๋ณผ ์ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ค์ ๋ก, ํจ์์ ๋ฐํ ์ฃผ์๋ฅผ ์กฐ์ํ๋ฉด ํ๋ก์ธ์ค์ ์คํ ํ๋ฆ์ ๋ฐ๊ฟ ์ ์๋ค.
โ ์คํ ๋ฒํผ ์ค๋ฒํ๋ก์ฐ๋ฅผ ํตํ ๋ฐํ ์ฃผ์ ๋ฎ์ด์ฐ๊ธฐ
// Name: sbof_ret_overwrite.c // Compile: gcc -o sbof_ret_overwrite sbof_ret_overwrite.c -fno-stack-protector #include <stdio.h> #include <stdlib.h> int main(void) { char buf[8]; printf("Overwrite return address with 0x4141414141414141: "); gets(buf); return 0; }โ
์ ์์ ๋ฅผ ์คํํ์ฌ main ํจ์์ ๋ฐํ ์ฃผ์๋ฅผ 0x4141414141414141๋ก ๋ณ๊ฒฝํด๋ณด์ธ์. “Success!”๋ผ๋ ๋ฌธ์์ด์ด ์ถ๋ ฅ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ ๊ฒ์ด๋ค.
์ถ์ฒ : ๋๋ฆผํต ์์คํ ํดํน ๋ก๋๋งต (https://dreamhack.io/lecture/roadmaps/2)
'Security > System Hacking' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Return Address Overwrite (1) | 2024.09.15 |
---|---|
[Stack Buffer Overflow] Return Address Overwrite (3) | 2024.09.15 |
[Stack Buffer Overflow] Calling Convention (2) | 2024.09.15 |
[Dreamhack] pwn-library write-up (0) | 2024.09.15 |
[dreamhack] fho write-up (0) | 2024.09.15 |