The sample works for both x86 and x64 Windows environments. In x64 Windows, drivers had to be signed before they could be loaded and executed. NotMyFault was actually signed a driver that was signed by Sysinternals. This driver was considered legit and would be loaded by Windows x64.
However, the sample could not load drivers directly as it had only MEDIUM integrity. The User Access Control (UAC) would prompt users to ask for permission to load and install the driver. To bypass UAC the sample executed the following 4 steps.
- Write a modified cryptbase.dll into the temp directory.
- Pack the modified cryptbase.dll into cryptbase.msu using makecab.exe
- Extract cryptbase.msu into C:\Windows\system32\sysprep using wusa.exe
- Execute C:\Windows\systems32\sysprep\sysprep.exe using command promp
As a result of the UAC bypass technique, the modified cryptbase.dll was used to execute the sample again with HIGH integrity to load and install the NotMyFault driver.
Next, I would document how cryptbase.dll was modified and then trace the modified code to execute the sample with HIGH integrity.
The sample would have to decode a blob of codes required to overwrite into cryptbase.dll
A loop to locate the .rsrc section in the cryptbase.dll was executed.
The strings and function addresses required were also written into cryptbase.dll.
The Address of Entry Point (AOE) was also updated to point to the start of the .rsrc section.
Finally the checksum was also calculated and updated into the PE header of cryptbase.dll
The following is the PE header of the original cryptbase.dll note its AOE.
Next is the modified cryptbase.dll with a different AOE.
After looking at how cryptbase.dll was modified. Let us trace how the modified cryptbase.dll was used to load and install the NotMyFault driver. Do note that the cryptbase.dll was loaded by sysprep.exe. I used the x64dbg debugger to debug sysprep.exe in Windows x64.
Inside the DLL entry point of cryptbase.dll is a loop to locate the virtual address of the .rsrc section.
Next a indirect call was made to the CreateThread function to start a new thread.
Finally, inside the new thread the CreateProcess function was called. The function created a new process using the sample path and an argument of "2"
Now the sample runs at HIGH integrity and it is ready to do some really nasty stuff!
In the next and final post of the series on analysing Rovnix dropper. I will copy how the NotMyFault driver was load and executed. I will also document how the Bootkit is inserted.