Sample Info
0a66e8376fc6d9283e500c6e774dc0a109656fd457a0ce7dbf40419bc8d50936
Unpacking
The dll
is loaded at 0x400000
in x32dbg
.
We can set breakpoints at VirtualAlloc
and VirtualProtect
to catch any regions of memory where the desired payload will be unpacked to.
This method will show that VirtualAlloc
is called 3 times.
The first contains some encrypted or encoded data, and isn’t very useful to us.
The second call will allocate at x0dF0000
where a mangled PE
gets written to.
The third call is interesting because it comes from the PE file written to the second allocation.
This third allocation is made at 0x2BC0000
and also contains a PE
file, but its headers are not mangled like the first.
We can dump this one to take a look.
Alternatively, you can also go through the VirtualProtect
calls.
This PE
will be used to overwrite the running process.
After the last VirtualProtect
, you can dump the original process memory and you’ll have the same bin file.
At this point, I wasn’t sure if this was the last stage or not, so I continue in x32dbg
in case I ran into more VirtualAlloc
or HeapAlloc
but pretty soon realized this was the main module.
The sample will use local APC injection to run some threads to decrypt the config we want and a few other tasks.
For the sake of brevity I will skip pass that process, but if you wanted to repeat it, you could set a break point at the call to CreateThread
(0x402020
), and once you get there, change the EIP
to point to the thread payload, which should be 0x401b7f
.
After locating the code that was decrypting the config data in .bss
, I was able to continue the reversing process in Binary Ninja.
Reversing Decryption Routine
The decryption process is pretty straightforward from here.
First, a base of 0 is established.
Then the key is subtracted from this base.
Then this new value (base - key
) is added with the dword
of data being decrypted.
Then the decrypted data is written to a buffer.
This loop will happen a max of 0x400
times, or until the data grabbed is 0.
The pseudo code could be understood as:
|
|
Key generation
Figuring out the key is a bit more tricky.
Stepping through x32dbg
I was able to figure out the formula to be:
|
|
Some int is a value picked up from calling NtQuerySystemInformation
and grabbing a dword
from it.
The value itself doesn’t matter, because that value is divided by 0x13
and only the remainder is used, and then two values, the NTSTATUS
return value and 1, are added to it.
STATUS_SUCCESS
is defined as 0x0
, so as long as NtQuerySystemInformation
succeeds, we are only really adding 1 to our remainder.
Hence the possible values of this mystery integer are 1 - 0x14.
Final Script
Through a little brute force, you can figure out that the secret value is supposed to be 18.
Here’s the final script I used, its meant to be ran with Binja
.
|
|