Description
We were given a file : howtouse.
Resolution
We checked the type of the file:
$ file howtouse
howtouse: PE32 executable (DLL) (GUI) Intel 80386, for MS Windows
Ok. A DLL, let’s switch to Windows !
Well in fact…so boring !
Using a decompiler, we had the following code (I cut some parts):
#include <windows.h> #include <defs.h> signed int sub_6FAC1010(); signed int sub_6FAC1020(); signed int sub_6FAC1030(); int __cdecl fnhowtouse(int); ... signed int sub_6FAC1010() { return 97; } signed int sub_6FAC1020() { return 98; } int __cdecl fnhowtouse(int a1) { signed int (*v2)(); signed int (*v3)(); signed int (*v4)(); signed int (*v5)(); ... v2 = sub_6FAC1080; v3 = sub_6FAC1080; v11 = sub_6FAC1090; v14 = sub_6FAC1090; ... return (*(&v2 + a1))(); }
The most interesting part here is the fnhowtouse function.
Each integer variable is filled by a sub_XXXXXXXX function when running the code.
Below is a good example :
v2 = sub_6FAC1080;
calls the function:
signed int sub_6FAC1080() { return 77; }
so v2 = 77;
When calling all the functions:
v2 = sub_6FAC1080; 77 v3 = sub_6FAC1080; 77 v4 = sub_6FAC1070; 65 v5 = sub_6FAC1110; 123 v6 = sub_6FAC1060; 102 v7 = sub_6FAC1030; 99 v8 = sub_6FAC10E0; 55 v9 = sub_6FAC1040; 100 v10 = sub_6FAC1100; 57 v11 = sub_6FAC1090; 48 v12 = sub_6FAC1030; 99 v13 = sub_6FAC1010; 97 v14 = sub_6FAC1090; 48 v15 = sub_6FAC1090; 48 v16 = sub_6FAC10A0; 49 v17 = sub_6FAC1060; 102 v18 = sub_6FAC1030; 99 v19 = sub_6FAC10F0; 56 v20 = sub_6FAC10E0; 55 v21 = sub_6FAC10A0; 49 v22 = sub_6FAC10B0; 50 v23 = sub_6FAC10D0; 52 v24 = sub_6FAC1100; 57 v25 = sub_6FAC10E0; 55 v26 = sub_6FAC1040; 100 v27 = sub_6FAC10F0; 56 v28 = sub_6FAC10F0; 56 v29 = sub_6FAC1040; 100 v30 = sub_6FAC1100; 57 v31 = sub_6FAC1050; 101 v32 = sub_6FAC1050; 101 v33 = sub_6FAC10E0; 55 v34 = sub_6FAC1050; 101 v35 = sub_6FAC1060; 102 v36 = sub_6FAC1010; 97 v37 = sub_6FAC1100; 57 v38 = sub_6FAC1050; 101 v39 = sub_6FAC1100; 57 v40 = sub_6FAC1020; 98 v41 = sub_6FAC10C0; 51 v42 = sub_6FAC10B0; 50 v43 = sub_6FAC1050; 101 v44 = sub_6FAC1040; 100 v45 = sub_6FAC10F0; 56 v46 = sub_6FAC1120; 125
$ python
>>> s = '77 77 65 123 102 99 55 100 57 48 99 97 48 48 49 102 99 56 55 49 50 52 57 55 100 56 56 100 57 101 101 55 101 102 97 57 101 57 98 51 50 101 100 56 125' >>> print "".join([chr(int(c)) for c in s.split(' ')]) MMA{fc7d90ca001fc8712497d88d9ee7efa9e9b32ed8}
Flag is MMA{fc7d90ca001fc8712497d88d9ee7efa9e9b32ed8}
Hello. it was very difficult for me. Could i ask question? how to call the all functions and convert this numbers 77 77 65 123 102 99 55 100 57 48 99 97 48 48 49 102 99 56 55 49 50 52 57 55 100 56 56 100 57 101 101 55 101 102 97 57 101 57 98 51 50 101 100 56 125. please explain more and more?
Hello Tsuka 🙂
In fact you can simply parse the decompiled C code.
You don’t need to call the functions from outside.
1) Sort all the variables v2, v3, v4 etc.. as I did.
2) For each variable there’s a function called, which will return a value.
I’ll take another more detailed example, not in my cropped source code :
v22 = sub_6FAC10B0; //Here v22 = the variable, sub_6FAC10B0 is the function
If you search the function named sub_6FAC10B0 in your decompiled code, you’ll find :
signed int sub_6FAC10B0()
{
return 50;
}
The final value of the variable v22 will be 50.
3) The function returns an integer (notice the “signed int” before the name).
It’s not a binary value and there are no letters A-F, so it can only be a decimal form.
You have to take the value the 50 and convert it in ASCII which gives 2.
v22 = 2; //50 in decimal.
4) When you have all the numbers, pass theses to a converter from decimal to ASCII.
This is an explanation of my code in python :
– it splits the string with all the values you gave it
– for each number it converts it in an ASCII value
– prints the final ASCII string
I hope it will be easier to understand now 🙂
Thank you very Much.
Hello, I’m a beginner with CTFs, which compiler did you use? I was messing around with IDA Pro and I saw the same fnhowtouse but I never put the pieces together. Which compiler did you use?
Exactly what decompiler did you use? I’m a beginner and would like to have proper tools from the start. I used ret-dec and it didn’t give me the proper ascii.
We commonly use IDA Pro for reversing and decompiling. WtF did this challenge, but given his decompiling result, I would assume he used IDA.
(I’ll let him confirm though)
Yes I used IDA 🙂
You can also decompile the DLL with :
– Hopper
– the Capstone engine + a python decompiler script
– radeco
From IDA, how did you get the result to look so “readable”. Mine mostly came out with assembly commands.
You have to use the decompiler (and not just stay in disassembler mode) :
File / Produce file / Create C file…
If you haven’t all the returned int values in the file, you have to attach the DLL to rundll32.exe:
– Choose windbg as debugger
– Debugger / Process options…
– Application : rundll32.exe
As example:
– howtouse_without_windbg.txt
– howtouse_with_windbg.txt