20 Jul 2017

Fix Backspace in Google Chrome

I've written about my fight with Google Chrome updates and broken features in the past. This time let's talk about the brain-dead decision to disable Backspace.

This was their rationale for the change:

We have UseCounters showing that 0.04% of page views navigate back via the backspace button and 0.005% of page views are after a form interaction. The latter are often cases where the user loses data. Years of user complaints have been enough that we think it's the right choice to change this given the degree of pain users feel by losing their data and because every platform
has another keyboard combination that navigates back.

So, just because 50 persons out of each 1'000'000 are f*king idiots, all the others have to suffer? Makes no sense to me.

To prove my point, let's look at the simple Google search: "Google Chrome backspace". It gives 238'000+ results. First few results are: "Backspace to go Back - Chrome Web Store", "Go Back With Backspace - Chrome Web Store", "Back to Backspace - Chrome Web Store", "How to restore the backspace key as a keyboard shortcut to go back in ...", "So where's the Chrome flag to RE-ENABLE BACKSPACE going back a...".

Apparently, I'm not the only one who is hurt by this change.

Hidden BackspaceGoesBack feature

When the change was first introduced in Google Chrome, developers also created a hidden feature that you could set and make Backspace work as it used to. To use it, you just need to launch chrome.exe with a command-line like this:

But in commit 0fe1505a this feature was removed as well.

If you enter the commit number in Chromium Find Releases tool, you'll see that in went out in public in v61.0.3116.0. Another check in Chrome Channel Releases tool will tell you that as of this moment the change is already out for both Canary and Dev channels, and will hit Beta and Stable channels in next months:

So, let's fix this issue for good! And by "fixing it" I don't mean some stupid JavaScript-based Chrome extension (which doesn't work when JavaScript is disabled and in hundreds of other cases..), I mean a proper fix in the code.

Patching Google Chrome again

If you've read my previous post, you know the drill. Set the symbol path, load chrome.dll in IDA, get yourself some coffee and wait. Wait a lot. And after 20-30 minutes you'll be able to start working.

This is the commit that's causing our headaches: commit 0fe1505a and the corresponding place in disassembly of Chrome 58:

What a mess!

Luckily for us, compiler decided to emit nice switch table in version v61.0.3153.2:

To make Backspace work as intended, we can simply overwrite 2 entries in jump table.

Mission accomplished! smile

In the next part of this blog series, I'll show you how to make this patch more user friendly and a few ways how to automate the patching (so that you can receive automatic Google Chrome updates, if you wish).

Till next time!
kao.

03 May 2016

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! smile

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... smile

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!

21 Aug 2015

Dancing pigs – or how I won my fight with Google Chrome updates

I think removing NPAPI support from Google Chrome was a really stupid decision from Google. Sure, Java and some other plugins were buggy and vulnerable. But there is a huge group of users that need to have NPAPI for perfectly legit reasons. Certain banks use NPAPI plugins for 2-factor authentication. Certain countries have made their digital government and signatures based on NPAPI plugins. And the list goes on.

I have my reasons too. If I have to run older version of Chrome for that, I will do so - and no amount of nagging will change my mind.

That’s a well known fact in security circles, named "dancing pigs":

If J. Random Websurfer clicks on a button that promises dancing pigs on his computer monitor, and instead gets a hortatory message describing the potential dangers of the applet — he's going to choose dancing pigs over computer security any day

Unfortunately pointy-haired managers at Google fail to understand this simple truth. Or they just don't give a crap.

Hello, I am AutoUpdate, I just broke your computer

Imagine my reaction one day when my NPAPI plugin suddenly stopped working. It just wouldn't load. It turned out that Google Chrome was silently updated by Google Update. It broke my plugin in the process and - officially - there is no way of going back.

What do you think I did next?

That's right - I disabled Google Update from services, patched GoogleUpdate.exe to terminate immediately and restored previous version of Google Chrome from the backup. Dancing pigs, remember?

Your Google Chrome is out-of-date

It worked well for few months. But this week, Chrome started nagging me again.
chrome_nag1
Quick Google search lead me to this answer: you need to disable Chrome updates using Google's administrative templates.

Let's ignore the fact that the described approach works only for XP (for Windows 7 you need to use ADMX templates which you need to copy manually to %systemroot%\PolicyDefinitions) and now there are like 4 places related to Google Chrome updates in the policies.

So, I set the policies and it seemed to work. For a day.

Your Google Chrome is still out-of-date

Imagine my joy the next day when I saw yet-another-nagscreen. Like this:
chrome_nag2

No, I don't need that update. Really!

I can close the nag, but 10 minutes later it will pop up again. And it looks like the only way to get rid of the nag is to patch chrome.dll. I really didn't want to do that but dumb decisions by Google managers are forcing my hand here.

Reversing Google Chrome

Since Chrome is more or less open-source, you can easily find the nagware message:

From here, we can find which dialog is responsible for the nag:

From there we can find NOTIFICATION_OUTDATED_INSTALL which comes from UpgradeDetector. And finally we arrive at CheckForUpgrade() procedure:

This is what I want to patch! But how?

You could load Chrome DLL in IDA and try to find the offending call on your own. But I'm willing to bet that it will take you hours, if not days. Well, PDB symbols to the rescue!

Symbols for Chrome are stored at https://chromium-browser-symsrv.commondatastorage.googleapis.com and you will need to add that path to your _NT_SYMBOL_PATH. Something like this:

_NT_SYMBOL_PATH is a very complex beast, you can do all sorts of things with it. If you want a more detailed explanation how it works, I suggest that you read Symbols the Microsoft Way.

After that, you can load chrome.dll in IDA, wait until IDA downloads 850MB of symbols, and drink a coffee or two while IDA is analyzing the file. After that it's all walk in the park. This is the place:

And one retn instruction makes my day so much better..

Final words

Unfortunately for me, this world is changing. You are no more the sole owner of your devices, all the big corporations want to make all the decisions for you.

Luckily for me, it is still possible to achieve a lot using a disassembler and debugger. And reverse engineering for interoperability purposes is completely legal in EU. smile

Have fun!

31 Jan 2015

Improved CFF Explorer

CFF Explorer is another invaluable tool for .NET reversers. Unfortunately it is closed-source and is not actively maintained anymore.

One of the most annoying problems is that it cannot correctly process .NET metadata in some assemblies protected by ConfuserEx (and few other protectors).
CFF shows garbage
As you can see, Module data make no sense and Methods also look weird.

Cause of the problem

The problem is caused by obscure and undocumented field in Metadata Table Stream. DNLib is one of the very few tools/libraries that properly supports it:

This extraData field is causing us troubles.. Oh, well, it's time to fix it! smile

Solution

Since CFF Explorer is closed-source, I had to reverse-engineer parts of it. Then I created a small code cave and added extra code that checks flag value and skips over extraData field, if necessary. If you're interested how exactly it was done, check address 004689CC and added code at 00589800.

CFF works fine
Much better, isn't it?

Download link for patched EXE: Please get latest version from this post