- Name - flareon2016challenge
- Category - Reverse Engineering
- Points - 4
- Description - n/a
- Binary - Download here
The binary for this challenge is a dll and hence we have to do some static analysis before we decide what to do next. The library exports functions flareon2016challenge_1() all the way up to flareon2016challenge_51(). Most of them perform actions on byte_10007014 buffer and return a value. For example flareon2016challenge_7() looks like this:
1 2 3 4 5 | signed int flareon2016challenge_7() { byte_10007014[dword_10007010-- % 0x10u] -= 79; return 16; } |
And flareon2016challenge_47() looks like this:
1 2 3 4 5 6 7 8 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 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():
1 2 3 4 5 6 7 8 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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():
1 2 3 4 5 6 7 8 9 10 11 12 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 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