- Name - flareon2016challenge
- Category - Reverse Engineering
- Points - 4
- Description - n/a
- Binary - Download here
signed int flareon2016challenge_7()
{
byte_10007014[dword_10007010-- % 0x10u] -= 79;
return 16;
}
And flareon2016challenge_47() looks like this:
signed int flareon2016challenge_47()
{
char v0; // cl@1
v0 = __ROL1__(byte_10007014[dword_10007010 % 0x10u], 4);
byte_10007014[dword_10007010-- % 0x10u] = v0;
return 20;
}
If we chain the return values we get the following: 30 -> 15 -> 42 -> 18 -> ... -> 35 -> 1 -> 51. The only 2 exported functions which are not part of this chain are flareon2016challenge_49() and flareon2016challenge50(). These will come into play later. Lets see what happens when we call the functions in the chain using the C program below:
int main(int argc, char* argv[])
{
FARPROC func;
HINSTANCE dllHandle = LoadLibraryA("flareon2016challenge.dll");
if (dllHandle == NULL)
return 0;
// Start from function 30
int next_func = 30;
// Go through chain of functions
while (1)
{
printf("Calling function %d\r\n", next_func);
func = GetProcAddress(dllHandle, next_func);
next_func = func();
if (next_func == 51)
{
printf("Calling function %d\r\n", next_func);
func = GetProcAddress(dllHandle, next_func);
func();
break;
}
printf("Press Any Key to Continue\n");
getchar();
return 0;
}
The first thing we notice is the following:
The most important thing though happens in the function which is called at the end, namely flareon2016challenge_51():
int flareon2016challenge_51()
{
char v1; // [sp+0h] [bp-90h]@1
sub_10001530(16);
sub_10001000((int)&v1, (int)&unk_10007060, (int)&unk_10007060, 6672);
return printf(aPlayMeASongHav);
}
Each of the functions listed above operate on a buffer which, after our program ends, looks like this in memory:
Copy the bytes into a hex editor, construct the PE file locally and open it in IDA. The main function only has the following:
int __cdecl main(int argc, const char **argv, const char **envp)
{
Beep(0x1B8u, 0x1F4u);
Beep(0x1B8u, 0x1F4u);
Beep(0x1B8u, 0x1F4u);
Beep(0x15Du, 0x15Eu);
Beep(0x20Bu, 0x96u);
Beep(0x1B8u, 0x1F4u);
Beep(0x15Du, 0x15Eu);
Beep(0x20Bu, 0x96u);
Beep(0x1B8u, 0x3E8u);
Beep(0x293u, 0x1F4u);
Beep(0x293u, 0x1F4u);
Beep(0x293u, 0x1F4u);
Beep(0x2BAu, 0x15Eu);
Beep(0x20Bu, 0x96u);
Beep(0x19Fu, 0x1F4u);
Beep(0x15Du, 0x15Eu);
Beep(0x20Bu, 0x96u);
Beep(0x1B8u, 0x3E8u);
return 0;
}
Running the binary plays Darth Vader's theme. Interesting!
Let's look at flareon2016challenge_50():
int __cdecl flareon2016challenge_50(DWORD dwFreq, DWORD dwDuration)
{
int result; // eax@1
Beep(dwFreq, dwDuration);
byte_10007028[dword_10008DD4] -= dwFreq;
byte_10007028[dword_10008DD4] ^= dwDuration;
result = dword_10008DD4++ + 1;
if ( dword_10008DD4 == 18 )
result = flareon2016challenge_49();
return result;
}
The function accepts 2 variables: dwFreq and dwDuration, just like the Beep() function in the extracted PE. Let's feed these into this function using the following program:
int main(int argc, char* argv[])
{
FARPROC func;
HINSTANCE dllHandle = LoadLibraryA("flareon2016challenge.dll");
if (dllHandle == NULL)
return 0;
// call flareon2016challenge_50 18 times for Darth Vader song
func = GetProcAddress(dllHandle, 50);
func(440, 500);
func(440, 500);
func(440, 500);
func(349, 350);
func(523, 150);
func(440, 500);
func(349, 350);
func(523, 150);
func(440, 1000);
func(659, 500);
func(659, 500);
func(659, 500);
func(698, 350);
func(523, 150);
func(415, 500);
func(349, 350);
func(523, 150);
func(440, 1000);
printf("Press Any Key to Continue\n");
getchar();
return 0;
}
After Darth Vader's theme we get:
Command Prompt
C:\>solver.exe
f0ll0w_t3h_3xp0rts@flare-on.com
Press Any Key to Continue
_


No comments:
Post a Comment