I was hoping for this to be my last post about Osiris, but since the DLL (shtefans1.spe) is packed it would not be possible for me to cover reverse engineering in one piece.
As I mentioned earlier in Macros: Locky Osiris that shtefans1.spe is a DLL. How do we know that it’s a DLL? Well, since the malware author is calling it using rundll32.exe, it has to be a DLL. Also, we can load it up in Exeinfo PE and check that it is indeed a DLL file. Note that it also tells us that it is ‘Not packed’.
Assume that we proceed with this information and load it up in IDA Pro. IDA Pro recognizes it as a DLL file and loads it successfully. However, it is clear from the imports, exports and strings that there is not enough information for us to declare it as unpacked.
Image: Imports for shtefans1.spe
Image: Strings for shtefans1.spe
Image: Exports of shtefans1.spe
Now, allow me to digress for a moment and briefly explain how rundll32.exe works, which would clarify the reasoning behind my conclusion i.e., the DLL is packed.
rundll32.exe <dllname>,<entrypoint> [optional arguments]
Rundll32 allows users to load a particular sort of DLL. The DLL is loaded via LoadLibrary() and the function address is obtained via GetProcAddress() call. Comparing the above syntax with the one that was used by the malware author, we can conclude that the entrypoint function is ‘plan’. While above imports are loaded successfully we can safely assume that this DLL is loadable using rundll32.exe, but exports do not conform with the entry function (plan) that was called. This suggests that the shtefans1.spe would be unpacked during rundll32.exe runtime. Also, the strings that we have for this DLL look meaningless. If you want to learn more about rundll32.exe read: INFO: Windows Rundll and Rundll32 Interface. One more function that is generally used for unpacking malwares is VirtualAlloc() which can be found in the imports list.
Note that this utility also allows user to call functions exported by the loaded DLL but it does not unpack shtefans1.spe successfully. We could try getting deeper in rundll32.exe and loaddll.exe but analyzing them is probably topic for another blog post.
We can try loading rundll32.exe in OllyDbg with the required arguments (DLL and entrypoint function), but reverse engineering that would be a waste of time as we can unpack it faster using other methods. If the reader wants to try the method above, keep in mind that VirtualAlloc calls are used to allocate memory, which means the code is most likely going to be unpacked in the next few instructions. I request the reader to let me know how this method turns out.
The process that I am going to follow from here onwards works on the idea that the code gets unpacked eventually in the memory if executed. This means we would be nearly infecting the machine on which analysis is done. I would strongly suggest to try this out in an isolated environment on machines that could be restored back to the state before infection.
Open OllyDbg and be ready to attach to rundll32. Now execute rundll32.exe and load our DLL with ‘plan’ as entry point.
In order to attach OllyDbg to the running process rundll32.exe, start by selecting
File(Menu) > Attach…
Select the rundll32 process and click Attach button.
There is no need to panic about the ransomware encrypting files as once the DLL is loaded the process goes into Sleep for some time. After the process is attached OllyDbg will try to pause it as you can see from the bottom right corner of the window.
As seen in the above window the code control drops somewhere in ntdll module. You can try stepping through (F8) the code. Since I have already done it I will make it easier for the readers. Click Ctrl+G this will open the window for ‘Follow expression’. Enter address 10005016.
This will take us to the API call for Kernel32.Sleep. You can see above the Menu bar that we are back in shtefans1_spe module.
Since we want our control to stop here we will put a breakpoint in the next instruction. Press F2 on 0x1000501C.
Press F9 to continue code execution. It will pause again once it reaches 0x1000501C. This means the code has been unpacked in the memory and we can take a dump of it. This can be done using OllyDumpEx plugin which is provided in OllyDbg2.0
Select the shtefans1.spe dll. This will change the ‘Image Base’ to 0x10000000.
We can check the correctness by looking at the running instance in Process Hacker. As it is clear from below that the Base Address is 0x10000000 and size is ~176 KB
However we want the code to be dumped from where the control of program is currently i.e., EIP. Click Get EIP as OEP (Original Entry Point). This will change the Entry Point to 0x0000501C
Click Dump. The completion of dumping process is confirmed by Dump OK alert box. This shows us the location of the dumped DLL.
Since we dumped the process in the middle, the imports of this DLL requires fixing. We can use Scylla for this job.
Select the rundll32 process from the dropdown, then click Pick DLL. This will allow us to select the DLL for which we want the imports to be fixed.
Click ‘IAT Autosearch’ button. This will display a notification ‘IAT found’. This means that we were able to find the IAT for the running instance of the DLL. Then click ‘Get Imports’. You should be seeing all the imports that are found in the running DLL.
It’s time to fix the DLL that we dumped from OllyDbg. Click ‘Fix Dump’ and select the DLL.
This will build the imports and save it to the same location with suffix _SCY. We have unpacked the DLL successfully. We can now begin with the real reverse engineering of the Locky Osiris DLL.
Let’s put it to test in IDA Pro.
Voila! Here is the entry point function that is exported by this DLL which is expected by rundll32.exe.
We can now see the culprit imported functions that were used in encrypting files and network communication. Strings also make more sense.
In the next post we will be understanding the inner workings of this DLL. We will figure out the functions defined in the DLL and their utility.