unsafe C functions

strcmp()

int strcmp(const char *cs, const char *ct)
{
	unsigned char c1, c2;

	while (1) {
		c1 = *cs++;
		c2 = *ct++;
		if (c1 != c2)
			return c1 < c2 ? -1 : 1;
		if (!c1)
			break;
	}
	return 0;
}

Above is a strcmp implementation that is found herearrow-up-right. Simply put, it takes cs and ct, loops through the characters to compare them, and returns 0 if they are the same. The final if case leading to the break checks for a terminating NULL byte. We know that our input is only 6 characters long before it overflows to the flag variable, so I decided to change the flag variable to hold our input, including the NULL terminating byte.

Beating strcmp

By inputting strings that contain \0 e.g

we can beat strcmp by making it compare two strings of AAAAA\x00 and AAAAA\x00

strlen()

Breaking the for loop

The for-loop usage convention

where

  • Statement 1 is executed (one time) before the execution of the code block.

  • Statement 2 defines the condition for executing the code block.

  • Statement 3 is executed (every time) after the code block has been executed.

How does the for loop know when to stop?

Hence, the for loop stops when the condition *s is false. In C, the null character '\0' indicates the end of a string. Therefore, the loop will continue as long as the value *s is not equal to '\0'. When the loop encounters the null character, the condition *s will evaluate as false, and the loop will terminate. At this point, the pointer s will be pointing to the null character, and the string length can be calculated by subtracting the initial pointer str from s.

In the example of light, we are trying to trick the program to think our input is 22 bytes into thinking so that we can go into the memcpy function and overflow local_28 into the to_overwrite function from there

hence, to exploit the strlen function, we now have to give an input that:

  1. has a null terminator at the 22nd byte,

  2. are more than 22 bytes anyways, so it can overflow local_28 (or val, in the source code)

printf()

format string vulnerabilities affect all printf variants (listed below)

String formatters

parameter

%c

usage

formats a single character

parameter

%d

usage

formats an integer in decimal value

parameter

%f

usage

formats a float in decimal value

parameter

%s

usage

formats a string

parameter

%p

usage

formats a pointer to an address location

parameter

%n

usage

formats the number of bytes written

parameter

%x

usage

formats a hexadecimal value

take the following usage:

the usage of printf() here is unsafe

we can exploit it by passing an input of %p such as:

this will dump some memory values

Exploiting it

example 1 (reading from a string value in a variable)

we can get the program to print out the variable flag using this exploit script, which prints the first 100 values on the stack as a string using our beloved string format exploit.

on the ninth iteration, we get the flag, which means the flag is stored at %9$s in this case.

example 2 (reading from stack chunks)

by using the following exploit script, we can see where 'position 1' of the printf lands and calculate the location of flag

Cross referencing with the gdb's stack:

we can see that a match of 0x19ff554040is found at %6$p, and that the dummy flag of our own flag.txt is offset at 6,7, and 8 below the stack pointer, our flag is stored at %12$p , %13$p, and %14$p

the values are as follows: %12$p --> 0x6568747b67616c66--> to ascii: eht{galf

%13$p --> 0x73695f67616c665f--> to ascii: si_galf_

%14$p --> 0x7d2121657265685f --> to ascii: }!!ereh_

note: %12$p is the start of our flag string, so in the case of a real pwn challenge, juts play around till you find the flag at %>12$p

stringing the values together in reverse, we get this:

}!!ereh_si_galf_eht{galf

reversing it back,

flag{the_flag_is_here!!}

Last updated