DLL Reversing - Writeup
Hello all, I am going to give a detailed write-up about how to reach flag in “DLL Reversing” challenge which was presented at CTF Fatec Ourinhos 2018 2nd edition.
Challenge Information
Name: DLL Reversing
Download: Link
Initial Analysis
During the initial analysis, we need to determine which type of file this DLL fit. If it is C++ code, we should use a Debugger (like OllyDbg, x64dbg) to debug it, if it’s a C# code, then it would be a .NET executable, which means we can decompile it to see source-code, which is always better for reversing!
Determining file type
Using “file” command, we are able to get that kind of information very quickly:
[root:~] file DLLReversing.dll
DLLReversing.dll: PE32 executable (DLL) (console) Intel 80386 Mono/.Net assembly, for MS Windows
So it is a .NET assembly, which lead us to know that we are able to decompile it. We can use ILSpy, a .NET decompiler, to get our DLL source-code.
Reading source-code, we identify a Shellcode class. And it calls the following functions from Windows API:
- OpenProcess
- VirtualAllocEx
- VirtualProtectEx
- WriteProcessMemory
- CreateRemoteThread
Which means it is obviously injecting shellcode to a remote process. We can confirm that by reading the public function named Exec.
It decrypts an array of numbers using XOR on key 0x31 (49 decimal) and convert them to bytes - our shellcode in original format - and them searches for a process to open, then allocate memory, change memory permissions, write shellcode to remote process and finally creating a remote thread and pointing it to the begginning of shellcode.
We already know what the DLL is for, we must now execute it!
Solving the challenge (Method 1)
There is two good ways of solving this challenge. One of them, and most easy, is to execute shellcode. We can use powershell for that.
You can see that we loaded the DLL in-memory and also that we are able to access Shellcode.Exec function directly from PowerShell terminal. Let’s spawn a 32-bit Notepad and try to execute the Exec function.
This is by far the most easy solution. There is an alternate solution by reversing the shellcode to get flag.
Solving the Challenge (Method 2)
The shellcode in string (ASCII) format is the following:
Çëô;|$(uáZ$ ëf KZ ë èD$ aÃ)ÔåÂhN ìRèÿÿÿE »~Øâs $Rèÿÿÿhll Ah32.dhuser0Û\$
æVÿU ÂP»¨¢M¼ $Rè_ÿÿÿhoxX hageBhMess1Û\$
ãhe}X hl3nghChalhion_hjecthL_Inhr_DLh0th3hf{4nhwgct1ÉL$&á1ÒRSQRÿÐ1ÀPÿU
You can look the flag in there, but to get it you will need to understand assembly.
Assembly pushes the string to the top of the stack before calling MessageBox, so we can just “simulate” how assembly would work to get the flag back.
Assembly code flag:
hl3nghChalhion_hjecthL_Inhr_DLh0th3hf{4nhwgct
The “h” character is the PUSH assembly instruction, so we need to remove it every 4 bytes (because of 32-bit architecture), leading us to:
l3ngChalion_jectL_Inr_DL0th3f{4nwgct
Now we pop 4 bytes from right to left.
wgct
f{4n
0th3
r_DL
L_In
ject
ion_
Chal
l3ng
e}
Which leads us to the flag:
wgctf{4n0th3r_DLL_Injection_Chall3nge}