22 Jul

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. :)

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. :) 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? :) 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! :)

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. :) So, if you’re interested, try to figure out what is it and how to abuse it.

28 Jun

Bugs in Enigma Virtual Box

While working on a new version of my static EnigmaVB unpacker, I tried to generate test files to cover most of the Enigma Virtual Box features. In the process, I ran into quite a few bugs in Enigma Virtual Box v7.40.

So, here’s a short list:

Registry virtualization

1. Importing REG file with wrapped lines:

Data get truncated at the end of first line.

2. Importing REG file with entry type REG_NONE:

It gets virtualized as a string value “hex(0):”

File virtualization

1. If size of any embedded file > 4GB: creates invalid x86 executable;
2. If total size of all embedded files > 4GB: creates invalid x86 executable;
3. If size of main EXE > 2 GB: creates executable that seems to be valid but won’t run;
..and that’s only for x86 executables. I wonder how many more issue will surface when I start testing x64 executables. ;)

TLS callbacks

Since Enigma Virtual Box uses TLS callbacks to initialize its hooks and handlers, it will (accidentally?) break any executable that also uses TLS callbacks. However, it preserves TLS StartAddressOfRawData, EndAddressOfRawData and AddressofIndex fields. Very weird.. :)

Have fun (and remember to test your software properly)!

20 Jun

Six-factor authentication (it’s not)

Today I read an article in The Register called Tor torpedoed! Tesco Bank app won’t run with privacy tool installed.

It’s a fun read about Tesco’s Android banking app and how it refuses to run when Tor application is installed on your mobile. But what really caught my attention, is this comment to the article:

I did a count of my account with a certain bank and when I use a PC which does not store their funky cookies, I get 6 (yes really, 6) steps for authentication.

  • Initial Customer code
  • Security password as there is no cookie so PC is not recognised
  • pre-agreed image
  • pre-agreed phrase
  • Customer Number
  • Security code

and if I use a Windows PC it whinges that I don’t have cRapport which would ‘improve my security’
So 6-Factor security isn’t good enough and you want an extra package to help???????

Sir, if you ever read what a multi-factor authentication is, you wouldn’t be stating such nonsense. All six of the steps you mentioned are of the same factor – “something you know”. As such, they provide no additional security, as one keylogger/screengrabber will capture them all.

Why your bank insists on you jumping over so many redundant hoops, remains a mystery..

08 Jun

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? :)

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. :)

06 Jun

CFF bug in RVA2Offset

Yes, this is yet another post about bugs in CFF Explorer. So far I’ve described:

Today, I’ll describe an issue with CFF Explorer’s RVA2Offset function and provide a solution to the problem (patched executable).

And no, I really don’t hate CFF Explorer. In fact, it’s one of my favorite tools and I use it every day – that’s why I keep noticing more and more issues with it. ;)

Introduction

Here is an executable that demonstrates the bug: https://www.mediafire.com/?9ju0cfm36b32ys9

If you open it in CFF Explorer and try to check Import Directory. In this case, CFF will show that it’s empty.

cff_bug_empty_imports

That’s incorrect, import directory of this executable is present and valid. It contains 2 DLLs and 3 APIs:

actual_imports

In other executables, it can get stuck into eternal loop or – even worse – show incorrect data.

Also, CFF’s Address Converter feature is affected. In my demo executable, try convert RVA 0x2000 to file offset. It will return 0:

CFF_address_converter_bug

So, what’s happening here?

Background of the bug

To put it simply, bug is triggered when one section in executable has SizeOfRawData much larger than VirtualSize. In my crafted executable it looks like this:

CFF_cause_of_bug

Nitpickers corner: it’s actually more complicated. The exact condition is ALIGN_UP(sec.SizeOfRawData, pe.FileAlignment) > ALIGN_UP(sec.VirtualSize, pe.SectionAlignment). But who cares about those small details, anyway?

And the offending pseudo-code in CFF Explorer looks something like this:

Fixing the bug

Since I’m doing binary patches to CFF Explorer, I’m quite limited to what I can do and how. In the end, I chose the following pseudocode:

While it doesn’t look like much (and it doesn’t cover edge cases, for example, when PE file is truncated), in general it should work just fine.

Download link for fixed CFF Explorer: https://www.mediafire.com/?5eg1bs9a9bv39ge
It also includes all my previous fixes.

Conclusion

While writing this post, I noticed that PE viewer in ExeinfoPE v0.0.4.1 has very similar bug. And ProtectionID v6.6.6. And PETools 1.5 Xmas edition. And Stud_PE 2.1. And LordPE. And then I ran out of tools to test. :D

Obviously, I can’t fix them all. All I can say – use PE editing/viewing tools that actually work, for example, HIEW or IDA. And when you’re writing your own PE parser library, make sure you test it on weird executables.

Have fun and stay safe!

Further reading

03 Jun

Quickpost: addicted to meaningless jargon

This is a great article about one journalist’s experiences in the RISE conference.

“We visually organize your email and cloud-based content for ultra fast access,” says Kalpesh, reading from his promotional materials. “It’s visual storytelling with any type of content.”

Say what? What does this thingy do? I have no clue.

Apparently I’m not alone. Luckily, article author translated it to plain English:

Translation: Cubes is actually an app that pinpoints anything that’s not plain-Jane text in your email or Dropbox accounts (a photograph, an excel file, a YouTube video), takes snapshots of those things, and then bundles them together in a standalone app.

OK, now I get it. Thanks! :)

However, the sad thing is, it’s not just startups. If you’re working in a large company, you’ve probably seen these kinds of emails sent by your pointy-haired bosses. They are stuck in their bubbles talking about “disruption”, “alignment” and “engagement”. How about this:

To ensure synergies and alignment between the finance strategy and business needs, Mr.X will co-operate closely with all finance functional leads, including aligning closely with Mr.Y and his team to ensure the consistent dissemination of financial information.

No, I really don’t know why our company is going to pay $100k a year to this guy. Do you?

31 May

BTVStack.exe requesting access to Skype on every startup

Background

At home I’m using a desktop computer. It has ASUS motherboard with Atheros Bluetooth chip. I have all the drivers installed but I’m not using Bluetooth at all.

Problem

Some time ago I started getting these notifications every single time I started Windows:
btvstack_skype

btvstack.exe is requesting access to Skype. Only allow access to programs downloaded from a trusted source as they will be able to use information such as your Skype contacts and messages.

No matter what option I selected, it would ask me again on next reboot. Bloody hell!

If you google for the solution, you’ll notice that:

  1. It’s a quite common problem;
  2. Most common solution is to deny/allow access either using the dialog above, or Tools->Options->Advanced->Advanced Settings->Manage other programs’ access to Skype;
  3. Another solution for Windows 8+ is to deselect “Allow Bluetooth devices to send you PIM items such as business cards, calendar items, e-mail messages, and notes. ” in Bluetooth Control Panel applet;

Unfortunately, first solution was not working for me. And second solution is not feasible because there is no such option in Windows 7 Control Panel.

Solution

Since I don’t need Bluetooth but I don’t like to have broken drivers, I decided to disable just the offending DLL. From the elevated command-prompt I ran

and the problem has disappeared. Great success! :)

Hope this helps someone else too.

20 May

Beautiful code

After making quite a few unpackers and other RE-related tools, publishing sources for them and having to maintain and bugfix them, all I can say is: “Read this. Remember this. Worship this.

All code is born ugly.

It starts disorganized and inconsistent, with overlaps and redundancies and gaps.

We begin working it into an imperfect solution for an often poorly defined problem.

As we start building up like clay, a solution starts taking form. The feedback guides us in moving, removing and adding material. It allows us to add and remove details. We learn from our mistakes.

Thank you, Dennis, you made my day so much better.

16 May

Quickpost: application reversing becoming legal in USA?

Last Friday authors of Dotfuscator made quite an interesting blogpost, claiming that reverse engineering applications in USA is becoming a legal means for acquiring intellectual property, thanks to the Defend Trade Secrets Act of 2016.

I am not a lawyer, and such statements coming from authors of obfuscator should be taken with a grain of salt – but it’s an interesting read nevertheless. What’s your take on that?

03 May

CFF bugs in processing managed resources

Users on tuts4you quite often ask questions like “Can you identify which obfuscator was used”. When I was analyzing one such assembly, my CFF Explorer started to act erratically. New tabs would not open and on exit CFF Explorer crashed with access violation.
CFF acting up
That’s weird, I said to myself and decided to figure out what’s causing it.

Uninitialized buffers and unchecked return values

First bug is a classic. In pseudo-code it looks like this:

First issue is that nobody initialized ResourcesInfo structure, so all fields will initially contain random garbage. As soon as ReadResourceHeader fails to read or validate something, it returns, and lots of fields will still contain random garbage.

It wouldn’t be a big problem, if Daniel checked the return value of the function. But his code just continues processing even if the data initialization failed. And, to make matters worse, it just hides all exceptions by putting try-except handlers around most of the code. No wonder CFF is occasionally acting weird! :)

This bug is quite hard to demonstrate, as it needs to have few lucky coincidences in the uninitialized data. But I’m sure that a skilled person would convert it into arbitrary code execution in no time. Not me, though… :)

Buffer overflow

Second bug is also a classic. In pseudo-code it looks like this:

So, what’s wrong here? Daniel takes a fixed-size buffer and initializes it with all zeros (unlike previous case). Then he reads size of data (NameSize). And then he copies NameSize bytes into a fixed-size buffer – without checking if that’s gonna overflow or not.. Yikes!

Example file demonstrating this bug: https://www.mediafire.com/?x4idsa21toh0t36 (you need to click on Resource Editor -> .NET Resources to trigger the buggy code. Afterwards, CFF Explorer will start acting weird).

Solution

Just like in a previous case where I added support for ConfuserEx and undocumented fields, I had to make few binary patches to CFF Explorer.

Fixed exe file is here: Please get latest version from this post

Have fun and stay safe!