August August - 3 months ago 11
C Question

Shellcode testing gone wrong

Hey I'm using a bit of code most of you are familiar with. It basically takes an array of characters and casts it as a function pointer. With this code you can theoretically test any shellcode's functionality with it, and it would be a very valuable program for my work, if it would behave... I'm doing this on Windows XP SP3, and am using MinGW's gcc to compile and gdb to debug the damn thing.

Here's what I've got...

unsigned char code[] =
"\x90\x90\x90\x90\x90\x90\x90\x90";
main()
{
printf("Code length = %i...\n",sizeof(code)-1);
int (*ret)()=(int(*)())code;
ret();
}


So I decided to use nops as the "shellcode" because it's easy on the eye and brain and would probably work no matter what. Unfortunately it doesn't.

When I compile and run the program I get...

An unhandled win32 exception occurred in horsefile.exe[3612].


...and when I run it in gdb I get...

Program received signal SIGSEV, Segmentation fault.
0x00409000 in code()


...where 0x00409000 is the entry point address of the shellcode function ret().

I've turned off DEP, as I thought casting the character array, which I thought was on the stack (probably in .data section in reality), and that there was no executing code on the stack (the casting treating the character array data as code on the stack). So I turned DEP off and it's still misbehaving.

Any thoughts? Remember, I'm using the MinGW compiler/debugger suite for Windows on Windows XP SP3.

EDIT -
unsigned char code[]
instead of
char *code[]
... still doesn't work...
EDIT - Added the
ret (\xc3)
at the end of the "shellcode", still no joy...

Answer

Your shell code contains nops, a 0x00 opcode and no further known contents. I can see 2 reasons for this to fail:

  • The operating system might not let you run code from the segment into which string literals are stored.
  • The sequence of operations does not end with a RET opcode, so you end up running some random unknown opcodes...

Try changing code to unsigned char const code[] = "\x90\x90\x90\x90\x90\x90\x90\x90\xC3";

Alternately, you can try and define code locally in the main() function:

int main(void) {
    unsigned char code[] = "\x90\x90\x90\x90\x90\x90\x90\xC3";

    printf("Code at %p, length = %i\n", (void*)code, (int)sizeof(code)-1);
    int (*ret)() = (int(*)())code;
    ret();
}

Neither approach is guaranteed to work, because the location where the compiler stores the code array may not be executable.

Comments