NAME: stackulator
CATEGORY: pwn
POINTS: 200
First pwn of the season! And the second pwn of my life!
Welcome to my first calculator!
What is your name?:
Aw man. What a polite calculator. What a shame we have to pummel it with malicious input.
undefined8 main(void)
{
int iVar1;
undefined8 uVar2;
long lVar3;
undefined8 *puVar4;
long in_FS_OFFSET;
undefined8 local_88 [8];
int local_48;
undefined8 local_44;
undefined8 local_3c;
undefined8 local_30;
undefined8 local_28;
char local_20 [16];
long local_10;
local_10 = *(long *)(in_FS_OFFSET + 0x28);
puVar4 = local_88;
for (lVar3 = 0xe; lVar3 != 0; lVar3 = lVar3 + -1) {
*puVar4 = 0;
puVar4 = puVar4 + 1;
}
local_44 = 0x6c2e636c61632f2e;
local_3c = 0x676f;
puts("Welcome to my first calculator!\n\nWhat is your name?:");
fgets((char *)local_88,99,stdin); // Reads 99 bytes to local_88
printf("\nHello %s",local_88);
if (local_48 == 1) { // This seems important
debug_menu(&local_44);
}
else {
...
OK, so we have an opportunity to write past the 64 bytes that are allocated to local_88. The following variable is local_48, which needs to be set to 1 to enter the debug menu. So if we send 64 bytes of gibberish, we can overwrite local_48. Appending 1 as a 4-byte little-endian integer gets us to the debug menu:
Select an option:
1) Receive a compliment
2) View log file
3) Get a random YouTube link
4) Show me an ASCII bee
This now gives us an option to read a file. More importantly, however, we can get a compliment:
You are good at making secure calculators
Goodbye!
Wrong!
void debug_menu(char *param_1)
{
...
if (local_40d == '2') {
puts("\nLog contents:");
local_40c = open(param_1,0);
read(local_40c,local_408,1000);
puts(local_408);
goto code_r0x00101396;
}
...
}
This reads a file that’s passed in by param_1. Which conveniently is just after the stuff you’ve overwritten. Now it is time to spend 20 minutes guessing the name of the flag. It’s not flag.txt or calc.log. 2 minutes after the challenge expires we will learn that the correct file is merely titled flag. I don’t know why I went so long without trying that. Appending that will get us the flag, so all is well!
Craft the exploit with a final payload of 64 bytes, the integer 1, and then “flag”, being sure to add a null terminator. Submitting this prints out the contents of a file named “flag”!