Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
Tags
- dangling pointer
- 계산기
- frida-dump
- WinDBG
- kaslr
- ioploaddrivers
- patchelf
- Android
- kernel debug
- top chunk
- return to libraty
- SCP
- cmake
- ntwritefile
- elf 헤더
- windows
- libc.so
- house of force
- RAO
- libc-database
- brop
- pwndbg
- randtbl
- windows kernel
- fastbin
- HOS
- sgerrand
- PLT
- canary leak
- JOP
Archives
- Today
- Total
sh711 님의 블로그
House of Force - 1 본문
1. 개념
House of Force는 glibc의 malloc을 이용한 힙 오버플로우 공격 기법으로, top chunk(최상단 청크)를 제어하여 공격자가 원하는 메모리 주소를 할당할 수 있도록 조작하는 기법이다
tcache(Thread Cache) 도입
- glibc 2.26부터 tcache가 도입되어 작은 크기의 할당 요청은 tcache에서 처리됨.
- 즉, 일반적인 할당 요청이 top chunk를 직접 사용하지 않게 됨 → House of Force를 수행하기 어려움
- top chunk 확장 방식 개선
- malloc()을 호출할 때 top chunk를 확장하는 과정에서, 보안 체크가 추가됨.
- 예전 버전(glibc 2.23)에서는 top chunk의 크기를 과하게 키워도 제어가 가능했으나,
glibc 2.27에서는 heap 확장 요청이 일정 크기를 초과하면 mmap()을 사용하여 할당됨. - 즉, sbrk()가 아닌 mmap()을 통해 메모리를 할당하면 top chunk 조작이 어려워짐.
- malloc_consolidate() 함수에서 top chunk의 크기가 비정상적으로 크면 오류 처리됨.
- top chunk의 크기를 0xFFFFFFFFFFFFFFF처럼 큰 값으로 조작하는 것이 더 어려워짐.
2. 환경 세팅
Docker에서 ubuntu:18.04 버전 설치
근데 해당 버전에서 glibc가 2.27인데 이미 tcache가 도입된 후여서 glibc 버전을 낮춰야 했다
glibc-2.23 버전 소스코드 다운
wget https://ftp.gnu.org/gnu/libc/glibc-2.23
tar -xzvf glibc-2.23
cd glibc-2.23
mkdir build
cd build
../configure --prefix=/opt/glibc-2.23
make
make install
1. setenv.c [__unsetenv] 에러
setenv.c: In function ‘__unsetenv’:
setenv.c:279:6: error: suggest explicit braces to avoid ambiguous ‘else’ [-Werror=dangling-else]
if (ep != NULL)
^
cc1: all warnings being treated as errors
// /root/glibc-2.23/stdlib/setenv.c line 278
ep = __environ;
if (ep != NULL)
while (*ep != NULL)
if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
{
/* Found it. Remove this pointer by moving later ones back. */
char **dp = ep;
do
dp[0] = dp[1];
while (*dp++);
/* Continue the loop in case NAME appears again. */
else
++ep;
}
수정
ep = __environ;
if (ep != NULL) { // 수정
while (*ep != NULL)
if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
{
/* Found it. Remove this pointer by moving later ones back. */
char **dp = ep;
do
dp[0] = dp[1];
while (*dp++);
/* Continue the loop in case NAME appears again. */
} // 수정
else
++ep;
}
2. regexp.c [loc] 에러
// /root/glibc-2.23/misc/regexp.c line 33
char *loc1;
char *loc2;
compat_symbol (libc, loc1, loc1, GLIBC_2_0);
compat_symbol (libc, loc2, loc2, GLIBC_2_0);
/* Although we do not support the use we define this variable as well. */
char *locs;
수정
char *loc1 __attribute__ ((nocommon)); // 수정
char *loc2 __attribute__ ((nocommon)); // 수정
compat_symbol (libc, loc1, loc1, GLIBC_2_0);
compat_symbol (libc, loc2, loc2, GLIBC_2_0);
/* Although we do not support the use we define this variable as well. */
char *locs __attribute__ ((nocommon)); // 수정
3. e_pow.c [checkint] 에러

// /root/glibc-2.23/sysdeps/ieee754/dbl-64/e_pow.c line 467
if (k > 20)
{
if (n << (k - 20))
return 0; /* if not integer */
return (n << (k - 21)) ? -1 : 1;
}
if (n)
return 0; /*if not integer */
if (k == 20)
return (m & 1) ? -1 : 1;
if (m << (k + 12))
return 0;
return (m << (k + 11)) ? -1 : 1;
수정
if (k > 20)
{
if (n << (k - 20) != 0) // 수정
return 0; /* if not integer */
return (n << (k - 21) != 0) ? -1 : 1; // 수정
}
if (n)
return 0; /*if not integer */
if (k == 20)
return (m & 1) ? -1 : 1;
if (m << (k + 12) != 0) // 수정
return 0;
return (m << (k + 11) != 0) ? -1 : 1; // 수정
4. rpc_parse.c [get _prog_declaration] 에러

// /root/glibc-2.23/sunrpc/rpc_parse.c line 520
static void
get_prog_declaration (declaration * dec, defkind dkind, int num /* arg number */ )
{
token tok;
char name[10]; /* argument name */
수정
static void
get_prog_declaration (declaration * dec, defkind dkind, int num /* arg number */ )
{
token tok;
char name[MAXLINESIZE]; /* argument name */ //수정
5. nis_call.c [nis_server_cache_add] 에러

// /root/glibc-2.23/nis/nis_call.c line 681
loc = &nis_server_cache[0];
if (*loc != NULL)
for (i = 1; i < 16; ++i)
if (nis_server_cache[i] == NULL)
{
loc = &nis_server_cache[i];
break;
}
else if ((*loc)->uses > nis_server_cache[i]->uses
|| ((*loc)->uses == nis_server_cache[i]->uses
&& (*loc)->expires > nis_server_cache[i]->expires))
loc = &nis_server_cache[i];
old = *loc;
*loc = new;
수정
if (*loc != NULL) { // 수정
for (i = 1; i < 16; ++i)
if (nis_server_cache[i] == NULL)
{
loc = &nis_server_cache[i];
break;
}
else if ((*loc)->uses > nis_server_cache[i]->uses
|| ((*loc)->uses == nis_server_cache[i]->uses
&& (*loc)->expires > nis_server_cache[i]->expires))
loc = &nis_server_cache[i];
} // 수정
6. nisplus-alias.c [_nss_nisplus_getaliasbyname_r] 에러

// /root/glibc-2.23/nis/nss_nisplus/nisplus-alias.c line 300
char buf[strlen (name) + 9 + tablename_len];
int olderr = errno;
snprintf (buf, sizeof (buf), "[name=%s],%s", name, tablename_val);
수정
char buf[tablename_len + 9]; // 수정
int olderr = errno;
snprintf (buf, sizeof (buf), "[name=],%s", tablename_val); // 수정
7. make install
드디어 libc-2.23 파일을 얻게 되었다..

8. 테스트
기존 libc-2.27에서 free 시 tcache로 들어간다


glibc-2.23 라이브러리 및 링커 컴파일
gcc test.c -o test -Wl,--rpath=/opt/glibc-2.23/lib/libc-2.23.so -Wl,--dynamic-lin
ker=/opt/glibc-2.23/lib/ld-2.23.so

glibc-2.23에서 free 된 청크는 fastbin에 들어간다

'Study > Linux' 카테고리의 다른 글
Linux Kernel - 1 (0) | 2025.03.26 |
---|---|
srandom_r & random_r (1) | 2025.03.20 |
ELF 헤더 분석 (1) | 2025.03.06 |
Return to Library (0) | 2025.03.01 |
Stack Buffer Overflow & Stack Canary (0) | 2025.02.26 |