3

First off we don't have ASLR and stack cookie, and assume we can't create our own files on this system

So I'm trying to execute a shellcode in this code, this is what i have done so far:

i have managed to overwrite the buffer and set the return address of function foo to function critical, but my problem is how to run a specific shellcode here? the execv will run the bin/sh but i can't replace the first argument with a shellcode and it won't work and I'm not sure if its even possible to run a shellcode with execv, and when i pass a shellcode to sh it doesn't work.

also i know the return to libc exploit but still don't know how to execute a shellcode with system()? is it even possible to pass a shellcode to it? or maybe i can use another function to just pass a shellcode to it?

And i assume we can run our own shellcode if we created our own shellcode file and replaced the sh path, but we don't have access to create files, we have to do it with this code only.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int bar(char *arg, char *out)
    {
      strcpy(out, arg);
      return 0;
    }

    int foo(char *arg)
    {
      char buffer1[100]="Test program.\n";
      char buffer2[100];
      bar(arg, buffer2);
      printf("%s",buffer1);
      return 0;
    }

    void critical()
    {
      char *msg[]={"/bin/sh",NULL};
      execv(msg[0],msg);
    }

    int main(int argc, char *argv[])
    {
      if (argc != 2)
      {
        fprintf(stderr, "prog_vuln2: argc != 2\n");
        exit(EXIT_FAILURE);
      }
      foo(argv[1]);
      return 0;
    }

2 Answers 2

4

First thing that comes to mind when you have non-executable stack is Return-oriented programming which, as the name implies, uses return to execute a code you want.
When using ROP, you will want to use the program's executable and dlls (or .so files for linux) and rely as little as you can on system dlls as they change with the OS version.
The idea is that you find a bunch of sequences of instrucitons. each one called a gadget. A gadget can set a register value by poping a value from the stack, moving a value or adding/subtracting a register, followed by ret (which means you can usually find them at the end of functions), causing them to return to the next value on the stack (where the return address is expected to be), creating a ROP Chain.

A simple example is when you want to execute a command using system.
you can (on a 64 bit OS) jump to a pop-return where the first value on the stack is your buffer address and the second value is the address of system, causing system to be called with your buffer as an argument in the correct register (rdi for linux, ecx for windows).
On a 32 bit os, the overflow is somewhat simpler. All you need is to oerride the return address to system and override the 4 bytes after it to be the address of you buffer. That will execute system with your buffer as the first parameter.

1

You are correct that you can't pass your shellcode to execv(), but that's not the idea. What you require is to change the return address from the call to foo() to point to critical(), so that execv() receives the path "/bin/sh" as the parameter. Normally, your shellcode would be the contents of critical() itself, and the return address would point to the buffer that holds the critical() function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.