-
the
math.out
binary is sent to us -
After inputting a random pin, the program exits.
-
So let’s take a look at the source code in
ghidra
-
Below is the main function
undefined8 main(void)
{ int iVar1; int iVar2; int iVar3; int iVar4; int iVar5; int iVar6; int iVar7; int iVar8; basic_ostream *pbVar9; long in_FS_OFFSET; int local_28; int local_24; long local_20;
local_20 = *(long *)(in_FS_OFFSET + 0x28); iVar1 = tryharder(8); iVar2 = eadsvfbdgw(0xf); iVar3 = eadsvfbdgw(7); iVar3 = eadsvfbdgw(iVar3); iVar4 = eadsvfbdgw(8); iVar4 = eadsvfbdgw(iVar4); iVar5 = eadsvfbdgw(8); iVar5 = eadsvfbdgw(iVar5); iVar6 = asberwefreqw(4); iVar7 = asberwefreqw(1); iVar7 = asberwefreqw(iVar7); iVar7 = eadsvfbdgw(iVar7); iVar8 = eadsvfbdgw(5); iVar8 = eadsvfbdgw(iVar8); local_24 = tryharder(0xb); local_24 = local_24 + iVar1 + iVar2 + iVar3 + iVar4 + iVar5 + iVar6 + iVar7 + iVar8; local_24 = tryharder(local_24 + -1); pbVar9 = std::operator<<((basic_ostream *)std::cout,"Enter the pin for the flag here:"); std::basic_ostream<char,std::char_traits<char>>::operator<< ((basic_ostream<char,std::char_traits<char>> *)pbVar9, std::endl<char,std::char_traits<char>>); std::basic_istream<char,std::char_traits<char>>::operator>> ((basic_istream<char,std::char_traits<char>> *)std::cin,&local_28); if (local_24 == local_28) { pbVar9 = std::operator<<((basic_ostream *)std::cout,"ECSC{sha256(<your number>)}"); std::basic_ostream<char,std::char_traits<char>>::operator<< ((basic_ostream<char,std::char_traits<char>> *)pbVar9, std::endl<char,std::char_traits<char>>); } if (local_20 != *(long *)(in_FS_OFFSET + 0x28)) { /* WARNING: Subroutine does not return */ __stack_chk_fail(); } return 0;}
- Take a look at
iVar1
throughiVar8
after they’re declared. The initialization of these variables is being made by calling some functions.
/* asberwefreqw(int) */
int asberwefreqw(int param_1)
{ int iVar1;
if (param_1 < 2) { iVar1 = 1; } else { iVar1 = asberwefreqw(param_1 + -1); iVar1 = iVar1 * param_1; } return iVar1;}
/* eadsvfbdgw(int) */
int eadsvfbdgw(int param_1)
{ int iVar1; int iVar2;
if (1 < param_1) { iVar1 = eadsvfbdgw(param_1 + -1); iVar2 = eadsvfbdgw(param_1 + -2); param_1 = iVar2 + iVar1; } return param_1;}
/* ecscisfun(int) */
int ecscisfun(int param_1)
{ int iVar1;
if (param_1 < 2) { iVar1 = 1; } else { iVar1 = tryharder(param_1 + -1); iVar1 = iVar1 + param_1 * 2 + 0x539; } return iVar1;}
/* tryharder(int) */
int tryharder(int param_1)
{ int iVar1;
if (param_1 < 2) { iVar1 = 1; } else { iVar1 = ecscisfun(param_1 + -1); iVar1 = iVar1 + (param_1 + 200) * 2; } return iVar1;}
- Back to the main, let’s have a bit of understanding about what the code does
local_20 = *(long *)(in_FS_OFFSET + 0x28);
if (local_20 != *(long *)(in_FS_OFFSET + 0x28)){ /* WARNING: Subroutine does not return */ __stack_chk_fail();}
- this seems to be some sort of protection to make sure the heap integrity is not compromised ; it helps preventing vulnerabilities like buffer overflow, most probably.
iVar1 = tryharder(8); iVar2 = eadsvfbdgw(0xf); iVar3 = eadsvfbdgw(7); iVar3 = eadsvfbdgw(iVar3); iVar4 = eadsvfbdgw(8); iVar4 = eadsvfbdgw(iVar4); iVar5 = eadsvfbdgw(8); iVar5 = eadsvfbdgw(iVar5); iVar6 = asberwefreqw(4); iVar7 = asberwefreqw(1); iVar7 = asberwefreqw(iVar7); iVar7 = eadsvfbdgw(iVar7); iVar8 = eadsvfbdgw(5); iVar8 = eadsvfbdgw(iVar8); local_24 = tryharder(0xb); local_24 = local_24 + iVar1 + iVar2 + iVar3 + iVar4 + iVar5 + iVar6 + iVar7 + iVar8; local_24 = tryharder(local_24 + -1);
-
Here are the variables I was talking about in the beginning. To find the values, we must calculate each of them based on the argument value and what is each function doing.
-
Then, at the end, we need to get the value of
local_24
. -
This is then compared to
local_28
- this is the variable that is storing our input
if (local_24 == local_28) { pbVar9 = std::operator<<((basic_ostream *)std::cout,"ECSC{sha256(<your number>)}"); std::basic_ostream<char,std::char_traits<char>>::operator<< ((basic_ostream<char,std::char_traits<char>> *)pbVar9, std::endl<char,std::char_traits<char>>); }
-
if these 2 are equal, then the flag is outputted. kind of. we should convert the number in sha256, but you got the idea.
-
Since we already have the functions, let’s skip the input thing and make a quick c program to calculate
local_24
for us, based on the functions found in the ghidra decompilation.
#include <stdio.h>
int tryharder(int);int ecscisfun(int);int eadsvfbdgw(int);int asberwefreqw(int);
int main() { int iVar1, iVar2, iVar3, iVar4, iVar5, iVar6, iVar7, iVar8, local_24;
iVar1 = tryharder(8); iVar2 = eadsvfbdgw(0xf); iVar3 = eadsvfbdgw(7); iVar3 = eadsvfbdgw(iVar3); iVar4 = eadsvfbdgw(8); iVar4 = eadsvfbdgw(iVar4); iVar5 = eadsvfbdgw(8); iVar5 = eadsvfbdgw(iVar5); iVar6 = asberwefreqw(4); iVar7 = asberwefreqw(1); iVar7 = asberwefreqw(iVar7); iVar7 = eadsvfbdgw(iVar7); iVar8 = eadsvfbdgw(5); iVar8 = eadsvfbdgw(iVar8); local_24 = tryharder(0xb); local_24 = local_24 + iVar1 + iVar2 + iVar3 + iVar4 + iVar5 + iVar6 + iVar7 + iVar8; local_24 = tryharder(local_24 - 1);
printf("iVar1: %d\n", iVar1); printf("iVar2: %d\n", iVar2); printf("iVar3: %d\n", iVar3); printf("iVar4: %d\n", iVar4); printf("iVar5: %d\n", iVar5); printf("iVar6: %d\n", iVar6); printf("iVar7: %d\n", iVar7); printf("iVar8: %d\n", iVar8); printf("local_24: %d\n", local_24);
return 0;}
int tryharder(int param_1) { int iVar1;
if (param_1 < 2) { iVar1 = 1; } else { iVar1 = ecscisfun(param_1 - 1); iVar1 = iVar1 + (param_1 + 200) * 2; } return iVar1;}
int ecscisfun(int param_1) { int iVar1;
if (param_1 < 2) { iVar1 = 1; } else { iVar1 = tryharder(param_1 - 1); iVar1 = iVar1 + param_1 * 2 + 0x539; } return iVar1;}
int eadsvfbdgw(int param_1) { int iVar1, iVar2;
if (1 < param_1) { iVar1 = eadsvfbdgw(param_1 - 1); iVar2 = eadsvfbdgw(param_1 - 2); param_1 = iVar2 + iVar1; } return param_1;}
int asberwefreqw(int param_1) { int iVar1;
if (param_1 < 2) { iVar1 = 1; } else { iVar1 = asberwefreqw(param_1 - 1); iVar1 = iVar1 * param_1; } return iVar1;}
gcc -o FLAG solve.c
./FLAG
iVar1: 5682iVar2: 610iVar3: 233iVar4: 10946iVar5: 10946iVar6: 24iVar7: 1iVar8: 5local_24: 1{redacted}5
echo -n <local24_value> | sha256sum
- The flag is
ECSC{value_from_command_above}
.