Let’s say something good about Google Chrome

kao

In my previous post I criticized Google's decision to disable NPAPI plugin technology. I still think it was a bad decision. But today let's talk about a change that should be an improvement for virtually all users.

Chrome will begin pausing many Flash ads by default to improve performance for users. This change is scheduled to start rolling out on September 1, 2015.

Source: https://plus.google.com/+GoogleAds/posts/2PmwKinJ7nj

Say what? Is Google going against ads? 😎 Well, not really. HTML5 ads are apparently OK. But those obnoxious Flash-based ads will become click-to-play.

The setting in question is located in Settings->Advanced->Content Settings->Plugins:
chrome_plugin_settings
It has been present in Chrome for several months already. So, I'm guessing that Google will be only pushing out some configuration change, or change the default value for new installations. Who knows, as Google is not giving us any details at this point..

Google's ad detection algorithm might need some improvements and there might be some other side-effects but overall I think it's a great change! Good job Google, you made my day better! πŸ™‚

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

kao

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:

      
        Chrome could not update itself to the latest version, so you are missing out on awesome new features and security fixes. You need to update Chrome.
      

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

void OutdatedUpgradeBubbleView::Init() {
  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
  accept_button_ = new views::LabelButton(
      this, l10n_util::GetStringUTF16(
          auto_update_enabled_ ? IDS_REINSTALL_APP : IDS_REENABLE_UPDATES));
  accept_button_->SetStyle(views::Button::STYLE_BUTTON);
  accept_button_->SetIsDefault(true);
  accept_button_->SetFontList(rb.GetFontList(ui::ResourceBundle::BoldFont));
  elevation_icon_setter_.reset(new ElevationIconSetter(
      accept_button_,
      base::Bind(&OutdatedUpgradeBubbleView::SizeToContents,
                 base::Unretained(this))));

  later_button_ = new views::LabelButton(
      this, l10n_util::GetStringUTF16(IDS_LATER));
  later_button_->SetStyle(views::Button::STYLE_BUTTON);

  views::Label* title_label = new views::Label(
      l10n_util::GetStringUTF16(IDS_UPGRADE_BUBBLE_TITLE));
  title_label->SetFontList(rb.GetFontList(ui::ResourceBundle::MediumFont));
  title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);

  views::Label* text_label = new views::Label(l10n_util::GetStringUTF16(
      auto_update_enabled_ ? IDS_UPGRADE_BUBBLE_TEXT
                           : IDS_UPGRADE_BUBBLE_REENABLE_TEXT));

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

void UpgradeDetectorImpl::CheckForUpgrade() {
  // Interrupt any (unlikely) unfinished execution of DetectUpgradeTask, or at
  // least prevent the callback from being executed, because we will potentially
  // call it from within DetectOutdatedInstall() or will post
  // DetectUpgradeTask again below anyway.
  weak_factory_.InvalidateWeakPtrs();

  // No need to look for upgrades if the install is outdated.
  if (DetectOutdatedInstall())
    return;

  // We use FILE as the thread to run the upgrade detection code on all
  // platforms. For Linux, this is because we don't want to block the UI thread
  // while launching a background process and reading its output; on the Mac and
  // on Windows checking for an upgrade requires reading a file.
  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
                          base::Bind(&UpgradeDetectorImpl::DetectUpgradeTask,
                                     weak_factory_.GetWeakPtr()));
}

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:

set _NT_SYMBOL_PATH=SRV*F:\Symbols*https://msdl.microsoft.com/download/symbols;SRV*F:\Symbols*https://chromium-browser-symsrv.commondatastorage.googleapis.com

_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:

.02CF3BDF: 55                             push         ebp
.02CF3BE0: 8BEC                           mov          ebp,esp
.02CF3BE2: 83EC20                         sub          esp,020 ;' '
.02CF3BE5: 8365FC00                       and          d,[ebp][-4],0
.02CF3BE9: 56                             push         esi
.02CF3BEA: 8BF1                           mov          esi,ecx
.02CF3BEC: 57                             push         edi
.02CF3BED: 8DBE10010000                   lea          edi,[esi][000000110]

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. πŸ™‚

Have fun!