Decode shikata ga nai with binary ninja — part 1
An introduction to shikata ga nai and write a simple script using binary ninja to decode shikata ga nai
Shikata ga nai (japanese for “it can’t be helped”) is a encoder that come with metasploit to encode your payload. It use old FPU instructions to get calculate the address and advance xor decryption scheme to decrypt the payload.
Shikata ga nai encode
The algorithm for shikata ga nai is quite simple but effecient. The algorithm can be divide into two phase, the initalising phase and the decoding phase
For the initalising phase, it can be run in any order, so shikata ga nai encode randomise the process to make analyser harder to write a static decoder. Under no specific order these are:
- Intialise the key and store it to a register
- Get the EIP using the FPU instruction.
- Get the counter of how many dword it need to decode
- Sometime the position get to plus 0x4 at first
The way shikata ga nai get the EIP from the FPU instrction is by the following:
<some random FPU instuction>
fnstenv [esp-0xc]
pop <reg>
The idea is fnstenv gets the informations of the last FPU instruction which was executed and push it to the stack. In those informations, specifically offset 0xc from old top of the stack is EIP of the last FPU that was executed. If you want to know more about fstenv then this answer from stackoverflow had done a great job at it.
After the initialising phase is done, it start the decode process:
- From the EIP of the FPU instruction that it execute, calculate the location of the next instruction and xor the dword with the current key
- Calculate the next key by adding the previous key with the dword of the decoded bytes
Another example without add 0x4 at first
But why do you need to do it statically you can just throw at the debugger and set the breakpiont before the loop and let it break there right.
Well yeah but let me tell you this, FPU instructions is buggy as hell on the modern day processor. For example my amd ryzen won’t give the right result from fnstenv instruction, it always return 0 to stack so the decode scheme fail. I also find the same issue on github: FIP divergence on Zen · Issue #2698 · rr-debugger/rr · GitHub. So yeah stop using shikata ga nai to encode for fudge sake.
So that’s the reason why the idea of decoding shikata ga nai statically come to my mind.
There are 2 steps you need to do to decode shikata ga nai. The first step is to get the initialise components.
The first step is to get the intialise components:
- The initalise key
- The position that it is going to decode
- The number of DWORDs(counter) it is going to decode
The counter is mostly store in the cx register using 1 instruction and can be easily get with ease.
But the initialise key and position is store in many random registers (eax, ebx, edx, esi, edi) and the position of it is also random as we have talk earlier.
The second step, after we have get all the components, the next step is to write a script to emulate the decode process.
In the next section, I will be using binary ninja to emulate the decode process in step two. I want to do second step first because it is easy and it is a great introduction to write a quick script using binary ninja python api.
Decode Shikata Ga Nai with binary ninja
Binary ninja is a great alternative for ida pro, it is affordable with just $299 so i don’t have to sell my soul and my kidney to buy it. The reason i change from ghidra to binary ninja because binary ninja come with a great python api to read and modify the assembly easily.
To emulate the shikata ga nai decode process, the first step is to get the bytes that we need to decode and then write back. With binary ninja, the process of writing and reading can be done easily with commands bv.read(address, len)
, the address to start reading and the len is number of bytes to read
And write back the bytes with bv.write(address, bytes)
, the bytes argument is the bytes that you are going to write at address.
To xor the byte you can use normal xor operation but here, i will be using transform module which come with binary ninja. Transform module is great because for normal xor operation you need to do a for loop to xor from the most significant bit to the least significant bit (from left to right), but with transform module you can do that in one command. The transform module also come with other type of transform like AES, RC4, …(for more you can read the doc).
To use xor transform module with a key, we do:
xor_transform = Transform['XOR']
dec_bytes = xor_transform.decode(enc_bytes, {'key': bytes_key})
Here the key and enc_bytes
is in type bytes, the transform will decrypt enc_bytes
by xor each block of enc_bytes
to bytes_key
and return back to the result to dec_bytes
.
The final code for step 2 is:
To get the script to binary ninja, you can copy paste it into the console and run or install snippet editor plugin, store the script in the snippet editor and run. After that you can use the function decrypt. Here we will take for example the sample that use shikataganai: VirusTotal — File — 0bbd75112062602c9cbbf081273b370cff6946decf7a81af6cb8f809c0f395fc (you can get the sample for free at malshare).
Here i will skip the analyse process and just demonstrate the shikata ga nai decode part. Go to address 0x1001e0ac by press g and type 0x1001e0ac and then press p to create function there. You will see something like this
Here the key is 0xbdfad26d, the counter is 0x5397 and the position that it is going to decode 0x1001e0c7.
In your python console paste the function in and run
decrypt(0x1001e0c7, 0xbdfad26d, 0x5397)
Now the update version of the graph look like this
Congratualation, you just deobfuscate a round of shikata ga nai, now do the same 6–9 times for most shikata ga nai consist of 6-9 rounds like this.
With that, we have learned how to write a quick and easy binary script to the emulate the decryption process with binary ninja. In the next post, i will show you using that script, we will write a plugin to automate the get components process by emulation with unicorn engine and decrypt shikata ga nai.
Part 2: https://medium.com/@acheron2302/decode-shikata-ga-nai-with-binary-ninja-part-2-19cea990ea4b
Reference
Shikata-Ga-Nai encoder (marcosvalle.github.io)
assembly — FSTENV? Can barely find any info about this instruction — Stack Overflow