BH01 - 500pts
Briefing
Download the file and find a way to get the flag. Contents: program
Challenge Files:
Solution
Inputting some random letters into the program prints some of the flag:
What is the magic word? djyawthvdbhgsajdghytwilhqypdoasgdbhwgdytqvdkbfuhgyabkhsj Flag: aLittLeObfuScatIo������uF?9�� Did you understand that?
However, the amount of the flag that is printed changes each time we run the program using the same input. There appears to be 4 different variations so a random number generator is involved. Using an input that consists of a single character seems to always produce the same output.
We can decompile the binary using Ghidra to see what the program does:
main
function:undefined8 FUN_00101209(void) { byte bVar1; byte bVar2; int iVar3; uint uVar4; time_t tVar5; long in_FS_OFFSET; uint local_90; time_t local_88; undefined4 local_7d; undefined local_79; undefined8 local_78; undefined8 local_70; undefined8 local_68; undefined8 local_60; undefined4 local_58; undefined8 local_48; undefined8 local_40; undefined8 local_38; undefined8 local_30; undefined8 local_28; undefined2 local_20; long local_10; local_10 = *(long *)(in_FS_OFFSET + 0x28); tVar5 = time(&local_88); srand((uint)tVar5); local_48 = 0; local_40 = 0; local_38 = 0; local_30 = 0; local_28 = 0; local_20 = 0; local_7d = 0x16120a05; local_79 = 0x18; puts("What is the magic word?"); fflush(stdout); fgets((char *)&local_48,0x28,stdin); local_78 = 0x103f4f6c803a05b6; local_70 = 0x9f2abbb5f5e62364; local_68 = 0x982b00094580efba; local_60 = 0x3f4675fb93f9dfb2; local_58 = 0x1afcba39; iVar3 = rand(); uVar4 = (int)*(char *)((long)&local_48 + (long)(int)*(char *)((long)&local_7d + (long)(iVar3 % 5)) ) - 0x5a; local_90 = 0; while (local_90 < uVar4) { bVar1 = ~*(byte *)((long)&local_78 + (ulong)local_90) + 0x2f; bVar2 = (byte)local_90; bVar1 = (~(~(0x57 - (~(bVar1 * -0x80 | bVar1 >> 1) - 0x33)) - 0x3f) ^ bVar2) + 0x4e ^ bVar2; bVar1 = ~((bVar1 * '\x02' | bVar1 >> 7) + 0x3d) ^ bVar2; bVar1 = ~(bVar1 << 3 | bVar1 >> 5); if ((int)uVar4 < 0) break; bVar1 = ~((bVar1 << 5 | bVar1 >> 3) - bVar2) - 0x17; bVar1 = ~((bVar1 * -0x80 | bVar1 >> 1) - bVar2); bVar1 = 0xad - ((bVar1 << 3 | bVar1 >> 5) + 0x3c); bVar1 = (bVar1 * ' ' | bVar1 >> 3) + bVar2; bVar1 = (bVar1 * '\b' | bVar1 >> 5) - bVar2; bVar1 = ~(bVar1 * -0x80 | bVar1 >> 1) ^ bVar2; bVar2 = (bVar1 * -0x40 | (byte)-bVar1 >> 2) - bVar2; bVar1 = ~(~(~(bVar2 * ' ' | bVar2 >> 3) ^ 0x45) - 8); *(byte *)((long)&local_78 + (ulong)local_90) = (0xd1 - ((bVar1 << 2 | bVar1 >> 6) ^ 0xef) ^ 0x65) - 0x3a; local_90 = local_90 + 1; } puts((char *)&local_78); puts("Did you understand that?"); if (local_10 == *(long *)(in_FS_OFFSET + 0x28)) { return 0; } /* WARNING: Subroutine does not return */ __stack_chk_fail(); }
The program picks a random byte from
local_7d
and uses that byte to index the user input to get a single characteruVar4
. Next, a loop runs that prints the flag character by character. However, it only iterates trough the loopuVar4 - 0x5a
times. Therefore, the letter that is selected from the input has to have an ascii code minus0x5a
(90) that is greater than the length of the flag.}
has a large ascii value. If we sent a lot of}
s into the program, it will print the flag:python -c "print('}'*50)" | ./program
. This is because the program selects a random character from our input, subtracts 90 from it, and then prints that many characters of the flag. So,125 - 90 = 35
which means the loop runs 35 times and successfully displays the 29 character flag. We cannot use just one}
because the program selects a random character from the input and it a character does not exist at the chosen index, it selects\x00
(a null byte).What is the magic word? }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} Flag: aLittLeObfuScatIonalCharActEr Did you understand that?
Flag
aLittLeObfuScatIonalCharActEr
Last updated
Was this helpful?