Under the hood: Yoda’s Crypter 1.3

Yoda’s Crypter (yC) was released 2004, but never seemed to gain popularity amongst malware writers. But still, it isn’t uncommon to run into a sample protected by it. yC utilizes a polymorphic stub to hide better, but the packer can be easily fingerprinted.

I switched on every possible option in the packer, and packed a testfile with it. I’ll try to go through all the options and display them in the code. At the same time, we’ll walk through the unpacking process.

Here’s a screenshot of the options available when packing a file with yC:

yC Options

When we take look at the entrypoint, there’s a small stub that looks like this:

yC Entrypoint

At location 0040B092 starts the polymorphic part of the code:

yC Polymorphic stub

The stub always starts with the command lods, and ends with stosb. Once the loop is done, rest of the loader part is visible. When you use breakpoints remember to use hardware breakpoints to make bypassing CRC checks easier.

Next, a check is made whether the binary is running under Windows NT:

yC Checking for Windows NT

Next, we come to a CRC checking:

yC CRC checking

The checksum function itself is trivial and looks like this:

yC Checksum Function

The value of the CRC will be saved in the eax register, and stored into memory for later use. Next, the loader will install a SEH-frame, and does a check to see whether SoftIce is present:

yC Checks For SoftIce Presence

If you want to avoid unnecessary hassle and the whole SoftIce check, make sure that the je command is taken from offset 0040B115 to 0040B15F. Since the memory address used in the test dword ptr ds:[edx], 1 is a DWORD used for ProtectionFlags, you can bypass a lot of hassle by zeroing out the DWORD from memory. This will effectively bypass all the protection checks in the loader code :)

Next, the loader will load and resolve the necessary imports, and after that it’ll perform a jump to the next stage using a push/ret trick:

yC Pushing The Return Address To Stack And “Returning” To It

The next stage starts with checking whether to use anti-dumping or not:

yC AntiDumping

To bypass this, make sure that the jump from offset 0040B2C0 to 0040B2FD is taken. After this, the loader will mark the PE header as writable.

yC Fixing The Headers

After fixing the PE Header access the loader will check whether to perform a CRC check. To around that nuisance, make sure that the jump from offset 0040B33F to 0040B42E is taken.

What follows next is the final decryption:

yC Final Decryption

Set a breakpoint at the retn command, and press F9 to run the target. What follows now is the final stage. First, the jump to OEP is prepared:

yC Preparing For OEP Jump

A check is made to see whether there is a TLS table present:

yC Checking The TLS table

Depending on the malware you’re unpacking there might or might not be a TLS table present. In both cases, just trace through the code until you hit the mov edx, ebp at offset 0040B59B.

Then the loader checks whether the CRCs were calculated. If they were, and they don’t match, it’ll exit quietly. If you bypassed the CRC as was instructed above, the loader will process forward. A check is made to see whether API redirection was toggled on the options when the binary was packed:

yC Checks For Api Redirection

Make sure the jump at offset 0040B5D3 is taken. The loader will start resolving the imports.

I hope you zeroed out the ProtectionFlags up in the beginning, cause we’ll skip some hassle :)

When the import loading starts at offset 0040B62F, trace into the function a few times:

yC Resolving The Imports

The CALL seen in the above is a small decryption loop to get the cleartext import name. Afterwards, the loader will do an obfuscated jump using the push/ret trick. Trace into the ret, and you’ll see this:

yC How To Skip Import Loading

To fasten things up, we’ll set a breakpoint at the memory address used in the jump command. So, in the above sample, set a breakpoint at address 0040B7C8. Then press F9 to run to target:

yC Checking Whether To Wipe The Headers

The loader will check the ProtectionFlags whether to wipe the header to make dumping harder. If you zeroed the ProtectionFlags, you’ll run past this cleanly. Next, loader will check it’s own CRC. The ProtectionFlags don’t affect this, so I hope you used hardware breakpoints.

yC Checking Loader CRC

The CALL in the above is the GetChecksum method that was seen in the above. Whatever you decide to do, make sure you get to the command at offset 0040B82F. Next part will decrypt the jump code to the OEP:

yC Decrypting Jump Code

Set a breakpoint at 0040B855, and run to it. Once more, an obfuscated jump is made using the push/ret trick. Singlestep into the ret and you’ll land on a IsDebuggerPresent test:

yC IsDebuggerPresent Call

So, one way or the other, make your way to the mov edx, ebp at offset 0040B890. What follows next is a check on the ProtectionFlags to see whether to do an check for SoftIce.

yC Final Check

If you cleared the flags in the beginning you’ll skip right pass this nicely, otherwise navigate through the check manually. After the jump there’s yet another obfuscated jump. This phase will zero out the loader code and data:

yC Cleaning Up The Loader Code

While the cleaning is done, the loader gets ready to cause an exception:

yC Going For SEH

As you can see, the code installs an exception handler, and jumps to the zeroed out code which will cause an access violation. This will transfer the execution to the SEH structure that was just installed:

yC Final SEH

The SEH will make EIP point to the OEP. Trace through the SEH, and trace over the ntdll.dll code until you go into ZwContinue. You’ll land right on the OEP, and can dump the malware. Have fun and enjoy :)

Leave a Reply

You must be logged in to post a comment.

If you want to comment on this article please send e-mail
to authors(_at_)teamfurry.com or go to the forums.


InspectorWordpress has prevented 2 attacks.