30 Sep 2018

September update of unpackers

Last few months have been... extra busy. I survived HDD crash, participated in Flare-On reversing contest (and finished 4th!), had quite fun projects at work - but all that is a matter of another story. Today I want to share with you a long-overdue update for unpackers.

Enigma Virtual Box unpacker

  • Added support for Enigma Virtual Box v8.10, v8.20, v9.00 and v9.10.
  • Unpacker now restores file attributes and date/time. Be careful, unpacked files might have attributes "read only", "hidden", etc.!
  • Added validation of extracted folder/file names to prevent directory traversal attacks. It was on my todo list for a long time and all the media-craziness around Zip Slip finally forced me to do something about it.
  • Fixed warning message about TLS directory. Mea culpa.

Molebox Virtualization Studio unpacker

  • Fixed error "VFSDecrypt: failed to find STELPACK signature" on some data files;
  • Fixed error "SPack catalog not found or invalid. vfsrootsize=00000000" on some EXE files;
  • Fixed out-of-memory error when unpacking huge data files;
  • Loads possible filenames from mole_dictionary.txt;

How to use mole_dictionary.txt

If you have a file which uses "hide files" feature of Molebox VS, it only stores hash of the filename - original filenames are not stored anywhere. But if you have a good idea what the filename might be, you can add it to mole_dictionary.txt and my unpacker will use that for intelligent guessing.
Read More

15 May 2018

Unity3D, Mono and invalid PE files

Some time ago, Reoto asked a very nice question on Black Storm forum:

Can someone fix the .dll (.net) pe header to MS DOS?
How can I do that?
If you know about protecting .net files for Android, please help me.
I have another question.
Can I fix dnspy to resolve .dll pe header isn't .net?

Obviously, English is not author's first language but it seemed like an interesting problem, so I decided to look into it.

Here is one of the files in question: https://mega.nz/#!0g4VHaIR!KmpQirte4_3lv8MSxyjETiufjFGb-CITpFGrXwxSgGY

TL;DR: Mono loader used by Unity3D accepts invalid PE files. It can be used to break most .NET decompilers. dnlib and tools based on dnlib (dnSpy, de4dot) were updated on 20-Apr-2018 but the rest of the tools still can't handle such files.
Read More

05 Sep 2017

MSDN is sometimes wrong

While reversing a certain executable, I needed to figure out what data it sends over SSL/TLS. It's not using standard WinHttp functions but custom Schannel/SSPI implementation that's similar to CURL.

One of the steps in the process is to obtain SecurityFunctionTable using code like this:

And then you can use the obtained SECURITY_FUNCTION_TABLE to call different SSPI functions.

Sure, InitSecurityInterface and the SECURITY_FUNCTION_TABLE structure are described on MSDN (just the start of structure is shown for brevity):

So, I added the corresponding structure definition to IDA and tried to analyze the calls. It made no sense whatsoever.

What's happening here?

After some head scratching, I searched WDK for SECURITY_FUNCTION_TABLE definition. And here it is:

I wonder where the Reserved1 field has gone... wink

Fix the structure definition in IDA and magically all the calls make perfect sense:

Morale of the story - MSDN is great for quick reference but having a full Windows SDK/WDK installed is priceless.

Morale #2 - always carefully check IDA standard structures. Apparently, IDA doesn't have SECURITY_FUNCTION_TABLE defined - but it does have proper definition for SecurityFunctionTable.

26 Jan 2017

Abusing Microsoft-signed executables

This morning I noticed an article from Cylance named "Graftor Variant Leveraging Signed Microsoft Executable". It's a nice article, so I can really recommend you read it.

TL;DR version: Graftor authors are using DLL hijacking in SrcTool.exe to load their own dbghelp.dll. If antimalware solution trusts executable that's signed by Microsoft (most of them do!) and doesn't check all the DLLs it loads, malicious code will not be detected.

Other vulnerable files

I decided to look for other Microsoft-signed files that could be abused in a similar manner. One quick search for EXE files in folder C:\Program Files (x86)\Windows Kits that also contain string dbghelp.dll and here's the result:

  • agestore.exe
  • cdb.exe
  • dbh.exe
  • kd.exe
  • mftrace.exe
  • ntkd.exe
  • ntsd.exe
  • srctool.exe
  • symchk.exe*
  • symstore.exe
  • tlist.exe
  • tracefmt.exe
  • tracepdb.exe

*symchk.exe also requires SymbolCheck.dll.

All these files are statically linked to dbghelp.dll and therefore vulnerable to DLL hijacking. agestore.exe, mftrace.exe, srctool.exe, symstore.exe, tlist.exe, tracefmt.exe and tracepdb.exe are the best targets - if you don't pass any command-line to them, they load dbghelp.dll but don't call any of its APIs and therefore will not crash.

Demo time

Here's a small fake dbghelp.dll you can use for testing: https://www.mediafire.com/?yx677bhxtyc13pu

Place it in the folder with vulnerable EXE lies and run the EXE. If a "DLL Hijacking" messagebox shows up, the EXE is vulnerable. smile Something like this:

Have fun and keep it safe!

27 Sep 2016

Why I’m not using x64dbg

x64dbg is (probably) the most user-friendly x64 debugger right now. It's pretty, it's open-source and it usually works. But I find it very hard to switch from WinDbg to x64dbg for several reasons. Some of them are purely emotional (don't worry, I'm not going to bore you to death explaining those) but most of them are technical and related to the way x64dbg is being developed.

So, here goes slightly exaggerated but still serious list of my grievances. smile

Insane system requirements

Both DNSpy and x64dbg suffer from this disease. They love to use the "latest and greatest" of technologies, meaning Visual Studio 2017, .NET 4.6 and what not. That's perfectly fine when you're writing normal software. But debugger is not a normal software.

If I have a customer with a software crashing on his production servers, I can't tell him "You need to install Windows 7 SP2 and 3 different VS redistributables and reboot your machine twice just for me to run my debugger". No, I really can't.

Debugger must run on any and all systems out-of-the box. Olly does that. WinDbg does that. And it wouldn't be hard to link x64bdg with static VS runtime libs and target WinXP while using all the modern goodies. But for some reason it's not done that way.

Updated 30-Sep-2016: Mr. eXoDia let me know that now x64dbg is distributed together with the necessary runtime DLLs. We can remove this grievance off of my list. Hooray! smile

Uncertain direction and feature bloat

Antoine de Saint Exupery said:

Perfection is finally attained not when there is no longer anything to add, but when there is no longer anything to take away

These are really wise words and Olly is designed that way. It does all the basic stuff and has stable SDK that enables plugin authors to implement all the extras.

On the contrary, Mr. eXoDia is adding features left and right and the direction of x64dbg development looks more like this:
BrownianMovement

For example, why does a debugger need 3 (yes, three!) different assembler engines?
assemble

Want another example? Let's just look at the latest weekly digest.. How about this:

... change to the info box. Basically the pointer values in the instruction were not resolved (so if the instruction contained qword ptr ds:[rsp+30] it would not show the value of rsp+30). Personally this is quite useless

Yes, Mr. eXoDia, you're right. It is useless for everyone but few people.

And how about:

The commands plugload and plugunload have been added. This is useful for plugin developers who want to test plugins without having to restart x64dbg all the time.

How many people in the entire world will actually benefit from that? 5? 10?

So, why add such bloat? Once you add something, that something must be maintained. And it's very hard to remove stuff later, as it might break something else. So, please don't..

Broken features

When I am on a job and need to debug something, last thing I want to spend my time on, is fighting with debugger bugs. And my customers certainly don't want to pay me for doing that.

Oleh Yuschuk got it exactly right with the OllyDbg. There were few releases - but they were properly tested and rock solid. From what I can see, x64dbg is going the other way:
compiles_ship_it

Frequent commits like "Fixed search for constant references", "Fixed intermodular calls in module", "Fixed FS/GS memory branch destinations" is not something you want to see in any software, let alone a debugger.

Well, it wouldn't matter much, if there was some known-stable version I could put in my tool collection and use it anytime anywhere. But no, Mr. eXoDia thinks that "No more excuses to not update every day!" is a way to go. Instead of using tried-and-tested version, I should use a probably buggy and unstable one? Dafuq?

Conclusion

So, those are my 3 biggest complaints about x64dbg. I'd love to love x64dbg. I'd love to use x64dbg for everything. But right now I just can't.

How about you?

01 Aug 2016

Breaking B0rken ElGamal KeygenMe, part 2

In part 1 of the tutorial, I explained how badly initialized PRNG causes a serious problems and allows us to find the private key. In this part of tutorial, I'll show how to use another weakness in crackme to find private key without using bruteforce.

Looking deeper in the keygenme

If you analyze serial check in more details, you'll notice part of code that processes blacklisted names and keys:

It looks like we have 2 blacklisted names & corresponding serials. We can quickly patch crackme and verify that these names and serials really work.

But did you also notice that those serials look a lot alike? That's weird.. Let's take a closer look at them:

First part of the serial is exactly the same! Let's go back to ElGamal basics and think a bit.

Revisiting ElGamal signing algorithm

I'm sure you already remember the algorithm from my previous blog post. But here it is again.. smile

To sign a message M, one would:

  • Make a hash of message, H(M). In this crackme, it's SHA1 of the username
  • Generate a random number K where K<P-1
  • Calculate R=G^K (mod P)
  • Calculate S=(H(M)-RX)*K^(-1) (mod P-1)
  • The signature will be the pair C(R,S).

So, in our case, R is always the same. G and P are hardcoded in the crackme. That means.. K is always the same. And that doesn't sound right! smile

Quick look in Wikipedia confirms that it's a really bad idea:

The signer must be careful to choose a different k uniformly at random for each signature and to be certain that k, or even partial information about k, is not leaked. Otherwise, an attacker may be able to deduce the secret key x with reduced difficulty, perhaps enough to allow a practical attack. In particular, if two messages are sent using the same value of k and the same key, then an attacker can compute x directly.[1]

The problem of reusing k and the attack itself is explained in Stinson's "Cryptography Theory And Practice", pages 290-291. Unfortunately, normal person has no chance to understand that "explanation".

Few Google searches later I found 2 writeups from Boston Key Party CTF 2015 which were slightly better:

So, let's try to get something useful out of them.

Reused K and recovering private key

As I said earlier, cryptography is a dark magic - if you don't spend years studying it, you can't understand it. So, I just took the code from those CTF writeups and added few more comments to it. And no, I still don't know why it works. smile

Conclusion

Wise man once said:

Knowledge is of two kinds. We know a subject ourselves, or we know where we can find information upon it.

You don't need to be a crypto wizard to solve crackmes - you just need to know where to find the necessary information. But if you're implementing cryptography in your software, better ask someone who understands those things.

Have fun!

22 Jul 2016

Breaking B0rken ElGamal KeygenMe by SmilingWolf

Some weeks ago I found a nice keygenme on URET forum. The description looked interesting enough:

Yet another company is making wild claims! Your mission: prove that people shouldn't trust companies promoting "revolutionary" crypto algos. Keygen this son of a crypto nightmare and write a DETAILED tutorial!

Rules:
1) The only acceptable solution is a keygen
2) No patching of course

It was not solved for few weeks, so I decided to take a look at it. smile

Crash-course in ElGamal signature scheme

I hate cryptography. It's complex, it's confusing and unless you're prepared to study this field for years, you can't really understand why stuff works this or that way.

So, here's a short version, just enough to solve this keygenme. It's based on the explanation in InfoSec Institute's tutorial.

Key generation

  • Generate a random prime number P with chosen length.
  • Generate two random numbers, G and X, with G<P and X<P.
  • Calculate Y=G^X mod P.
  • Public key consists of 3 numbers: (P, G and Y), Private key is X.

All 3 numbers of public key are hardcoded in keygenme and are 256 bits long. We can find them in disassembly:

Private key X is.. well, private. smile Without it we can't generate correct keys for a name of our choice. So, the challenge would be to recover the private key somehow.

Signing

To sign a message M, one would:

  • Make a hash of message, H(M). In this crackme, it's SHA1 of the username
  • Generate a random number K where K<P-1
  • Calculate R=G^K (mod P)
  • Calculate S=(H(M)-RX)*K^(-1) (mod P-1)
  • The signature will be the pair C(R,S).

Verification

To verify a given pair C(R,S), one would:

  • Compute V1=G^M (mod P)
  • Compute V2=Y^R * R^S (mod P)
  • If V1==V2, the signature is valid

Breaking ElGamal

Strength of ElGamal algorithm lies in the Discrete Logarithm Problem (DLP). What it means is that easy to calculate Y=G^X mod P, but it's bloody hard to find out X, if you know P, G and Y.

In the InfoSec Institute's tutorial the author is using figugegl's DLPTool to solve the problem for 128-bit integers. However, it's not even possible to enter 256-bit integers in that tool. And the rest of the suggested tools can't handle such large integers either.

So, we must find another way to break the keygenme. After all, it's called "B0rken ElGamal", so there must be a weakness somewhere!

Inside the keygenme

The keygenme itself is an application that generates ElGamal keys. It would be logical to assume that SmilingWolf used this same application to generate keys for the keygenme. So, let's examine the application and see how ElGamal is implemented in it.

I'll skip the boring "unpack modified UPX part", as it's been explained dozens of times already.

So, here's the relevant code for key generation:

Looks legit, right? smile Well, not so fast.

Random numbers don't just magically appear out of thin air. They are generated using random number generators. If the generators are flawed, the numbers are not really random. You can read a lot about such attacks on Wikipedia.

So, let's examine random number generator used in this keygenme.

If you search for those constants, you'll see that it's a very standard PRNG which is not great but supposed to be reliable enough. You could bruteforce all 2^32 possibilities but it will take a long time. Another dead end?

Well, not really. Any PRNG must be initialized somehow, see random_seed variable above. So, let's see how SmilingWolf is initializing his PRNG..

Hmm, that's weird. Normally PRNG is initialized using rdtsc instruction or something even less predictable than that. And what exactly is arg_0? It's a handle of the DialogBox - not random at all!

Finally, we've found a reason why this ElGamal implementation is broken! smile

Bruteforcing the private key

Now that we know the weakness, we can write a bruteforcer that will go through all possibilities of random seeds and generate all possible ElGamal keys. Once we generate a key that has the same P, G and Y as in the keygenme, we will also know the correct private key X. But generating all these numbers is a slow process!

Let's look back at the code and see what we can optimize.

1) We don't need to generate all the numbers. It's enough if we find correct P - the rest of numbers will match automatically. So, let's remove the rest of the code.

2) First 32 bits of 256 bit integer will almost certainly not change when searching for nearest prime. Therefore, we could get rid of bigint_find_nearest_prime call which is the slowest piece of code. This means we won't be looking for number FE6D5B4400B30374A403F88CFBA3642435FB269AEC2BE5C8C2F331545EF37AB3, but any number starting with FE6D5B44...

3) Multiplication by 2. Another unnecessary step. Let's just divide P by 2 and look for that number. Instead of looking for FE6D5B44..., we'll look for 7F36ADA2...

4) Copying bigints. Unnecessary.

There's not much left, I'm satisfied.

Now, how to bruteforce random seed? It's a window handle. Window handles are always even. Also, they consist of 2 parts, high word and low word. Low word is the actual handle. It is almost never higher than 0x2000. High word is the "uniquifier" - just a counter. It's usually quite small - on my PC it's never larger than 0x800.

Taking all these assumptions into account, my pseudo-code for bruteforcer would look like this:

I implemented the bruteforcer in MASM32 with 95% of code ripped from keygenme and let it run. In less than 2 hours I had one (of the several possible) seed:

Once we know X, implementing keygen is a child's play. Again, lots of ripped code and small UI around it. Problem solved!

Keygen for download: https://mega.nz/#!JtgVUDwb!xs3SgCDK3t5h3MabOfoNsDFYCj1mpHcI7GbQT-K1_RE

Further reading

InfoSec Institute's tutorial about ElGamal: http://resources.infosecinstitute.com/breaking-software-protection-elgamal-signature-scheme/
Interactive webpage showing how ElGamal works with small numbers: https://asecuritysite.com/encryption/elgamal

Final thoughts

As SmilingWolf told me after solving his keygenme - there is another way how to break this keygenme. There's one more thing broken in this implementation that makes generating keys really easy. smile So, if you're interested, try to figure out what is it and how to abuse it.

08 Jun 2016

What’s wrong with this file – ASLR is tricky!

I love magic tricks. My absolute favorites are "there's nothing up my sleeve" kind of tricks. You can look at the equipment, you can examine magicians outfit, everything seems fine - yet the rabbit magically appears and disappears.

Here's a similar reversing challenge for you: https://www.mediafire.com/?38evlc6gmyieskn

This EXE file contains relocations. It has all the necessary necessary flags in PE header. And it gets ASLR support in Windows 10, as you can see in picture:
win10_has_aslr
But on Windows 7/8.1 this poor executable will be always loaded at it's preferred imagebase 0x400000, and doesn't get ASLR support:
win7_no_aslr
Can you figure out what's so special about it? smile

I will provide the correct answer in one week. Or you can provide your opinions in comments. Extra respect awarded for detailed answers and explaining how you figured that out. Extra extra respect if you knew the answer even before looking at the executable. smile