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!

63 thoughts on “Dancing pigs – or how I won my fight with Google Chrome updates

  1. Hi!

    Would it be possible to modify the maximum http requests with this as well?
    I know that Chrome has a thread pool

    1. Given enough time and effort anything can be achieved. The real question is - why do it? πŸ™‚

      You lose Chrome security updates. After some time Google main page will start nagging you. Then Google Web Store. And there are potential False Positive detections from antiviruses, etc, etc.

      I have a very specific use case and for me it was worth it. How about you?

      If you still want to do that, this seems to be the place: https://code.google.com/p/chromium/codesearch#chromium/src/net/socket/client_socket_pool_manager.cc&sq=package:chromium&type=cs&l=46

  2. Because on some complex websites Chrome just chokes hard. Firefox has 15 I think already. Chrome folks are so backward.

    I think auto patching could be done πŸ™‚

    1. Never happened to me. πŸ™‚ If it's a reasonably large public website exhibiting these issues, I'd bug website owners to use domain sharding and/or Chrome authors to change connection defaults.

      Automatic patcher should be possible but I haven't tried to implement it myself.

  3. Still, how do you actually patch an enum with Ida Pro? I've only patched logic so far. JNZ, JMP etc.

    1. It's not an enum, it's an array of integers.

      In my old chrome.dll (45.0.2414.0) it looks like this:

      .data:03968848 ; int * net::`anonymous namespace'::g_max_sockets_per_group
      .data:03968848 ?g_max_sockets_per_group@?A0x1ef593ee@net@@3PAHA dd 6
      .data:0396884C                 dd 30
      

      So, you just change number 6 to whatever you like. πŸ™‚

      EDIT 2x: properly formatting code in comments is hard.

  4. I found the hex string shown in your example: 55 8B EC 83 EC 20 83 65 FC 00 56 8B F1 57 8D BE 10 01 00 00. You said change it to RETN, which is hex C3, so I changed the ending from 8D BE 10 01 00 00 to C3 BE 10 01 00 00, but it doesn't seem to work. Chrome just crashes after a while.

    Could you tell me what to change? Thank you

    1. You should replace first byte of that sequence with retn instruction. So, in my example, it's address 02CF3BDF - and after patch it looks like this:

      .02CF3BDF: C3                             retn
      .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]
      
  5. Hi,

    I'm using Chrome 52 and i opened chrome.dll in IDA Pro but the strings are not there. Maybe because the version i use is newer and the dll has changed. I am new to this what i have to do? I really want to turn off that boring out-of-date popup. Thanks

    1. Most likely you did not set up symbols correctly. Please re-read that part of blog post and try again. πŸ™‚

      If it still doesn't work, please upload your chrome.dll to mega.co.nz or mediafire.com and send me the link. Ideally - with a step-by-step description of what you did and what didn't work as expected. I'll try to look at it and find out what's causing the issue.

  6. First thanks for your quick answer.

    You were right i did a mistake with the symbol path i forgot to change the drive letter from F to C. Looks like more strings appeared when i restarted IDA but still none of the ones you mentioned, i got these instead with similar names:

    02CF3BD0                 push    0
    02CF3BD2                 lea     eax, [ebp+var_48]
    02CF3BD5                 push    offset sub_2CF392B
    02CF3BDA                 push    eax
    02CF3BDB                 call    sub_1DC5C39
    02CF3BE0                 add     esp, 14h
    02CF3BE3                 push    eax
    02CF3BE4                 push    edi
    02CF3BE5                 push    ebx
    02CF3BE6                 lea     eax, [ebp+var_1C]
    02CF3BE9                 push    eax
    02CF3BEA                 mov     eax, [ebp+var_38]
    02CF3BED                 push    [ebp+var_40]
    02CF3BF0                 mov     ecx, [eax+90h]
    02CF3BF6                 call    dword ptr [esi+30h]
    02CF3BF9                 lea     ecx, [ebp+var_48]
    02CF3BFC                 call    sub_1C5E781

    Since i'm not experienced with this i decided like you said to upload chrome.dll to mediafire, here's the link: {link_removed}

    1. You still did something wrong with symbols. πŸ™‚ If you did it right, you'd be able to see the correct place in IDA:

      .031ECD7F ; void __thiscall UpgradeDetectorImpl::CheckForUpgrade(UpgradeDetectorImpl *this)
      .031ECD7F ?CheckForUpgrade@UpgradeDetectorImpl@@AAEXXZ proc near
      .031ECD7F 
      .031ECD7F this = ecx
      .031ECD7F 55              push    ebp
      .031ECD80 8BEC            mov     ebp, esp
      .031ECD82 83EC20          sub     esp, 20h
      .031ECD85 8365FC00        and     dword ptr [ebp-4], 0
      .031ECD89 56              push    esi
      .031ECD8A 8BF1            mov     esi, this
      .031ECD8C 57              push    edi
      .031ECD8D 8DBE10010000    lea     edi, [esi+110h]
      .031ECD93 8BCF            mov     this, edi
      .031ECD95 E8DF5AACFE      call    ?InvalidateWeakPtrs@?$WeakPtrFactory@VObjectWatcher@win@base@@@base@@QAEXXZ ; base::WeakPtrFactory::InvalidateWeakPtrs(void)
      .031ECD9A 8BCE            mov     this, esi
      .031ECD9C E860000000      call    ?DetectOutdatedInstall@UpgradeDetectorImpl@@AAE_NXZ ; UpgradeDetectorImpl::DetectOutdatedInstall(void)
      .031ECDA1 84C0            test    al, al
      .031ECDA3 7556            jnz     short loc_31ECDFB
  7. I give up with the symbols but i found the strings above:

    031ECD7F push ebp
    031ECD80 mov ebp, esp
    031ECD82 sub esp, 20h
    031ECD85 and [ebp+var_4], 0
    031ECD89 push esi
    031ECD8A mov esi, ecx
    031ECD8C push edi
    031ECD8D lea edi, [esi+110h]
    031ECD93 mov ecx, edi
    031ECD95 call sub_1CB2879
    031ECD9A mov ecx, esi
    031ECD9C call sub_31ECE01
    031ECDA1 test al, al
    031ECDA3 jnz short loc_31ECDFB

    So i only have to change the 1st line from 031ECD7F push ebp to 031ECD7F retn ? I am totally new with code editing how can i do that?

    A much easier solution would be that you do it and upload the modified file.

    Thank you again for your help.

    1. Due to possible legal issues, I cannot upload the modified file. So, you'll have to modify it yourself. πŸ˜‰

      In the snippet I posted above you can see the corresponding byte values. Use any hex editor to find them:

      55 8B EC 83 EC 20 83 65 FC 00 56 8B F1 57 8D BE 10 01 00 00

      Change the first byte from 55 to C3, save the modified file and enjoy!

      P.S. Always make a backup copy of file before modifying it! πŸ™‚

  8. It works! I replaced chrome.dll with the modified one and since then the out-of-date message never showed up again.

    I tried many solutions from a lot of sites but only this one worked for me, it's a shame we need to modify a file to get rid of that nagging popup.

    Btw, would it be possible using this method to remove the geolocation and bookmark icon from the url bar, and also the warning "This page is trying to load scripts from unauthenticated sources" ? They are useless for me but I would understand if you dont have time to deal with that.

    Anyway thank you again for your support i hope it will help other people too.

    1. As I said in an earlier comment, everything is possible.

      The method of locating icons in address bar would be similar to what I described in the post. But I'm not particularly interested in spending my time on that..

  9. Hi again!

    I decided to switch from 32 to 64 bits of Chrome and it appears that the chrome.dll is different. I looked for the string but i didn't find it, it must be different then. Can you help me find the one that match in the 64 bits version? Like last time i uploaded the file to Mediafire: {link_removed}

    Thank you

    1. This is the place you're looking for:

      .181C447B4 ; void __fastcall UpgradeDetectorImpl::CheckForUpgrade(UpgradeDetectorImpl *this)
      .181C447B4 ?CheckForUpgrade@UpgradeDetectorImpl@@AEAAXXZ proc near
      .181C447B4
      .181C447B4 48895C2410          mov     [rsp+arg_8], rbx
      .181C447B9 57                  push    rdi
      .181C447BA 4883EC70            sub     rsp, 70h
      .181C447BE 83A4248000000000    and     dword ptr [rsp+78h+result.flag_.ptr_], 0
      .181C447C6 488DB970010000      lea     rdi, [rcx+170h]
      .181C447CD 488BD9              mov     rbx, rcx
      .181C447D0 488BCF              mov     rcx, rdi        ; this
      .181C447D3 E8387C45FE          call    ?Invalidate@WeakReferenceOwner@internal@base@@QEAAXXZ ; base::internal::WeakReferenceOwner::Invalidate(void)
      .181C447D8 488BCB              mov     rcx, rbx        ; this
      .181C447DB E8B0000000          call    ?DetectOutdatedInstall@UpgradeDetectorImpl@@AEAA_NXZ ; UpgradeDetectorImpl::DetectOutdatedInstall(void)
      .181C447E0 84C0                test    al, al
      .181C447E2 0F8598000000        jnz     loc_181C44880
      

      and the bytes to search for:

      48 89 5C 24 10 57 48 83 EC 70 83 A4 24 80 00 00 00 00 48 8D B9 70 01 00 00

      I'm not using the 64-bit version, so I wasn't able to test it myself. Take care! πŸ™‚

      1. Hi,

        I forgot to say that it is also working for the 64 bits version of Chrome using the method of kao's last post.
        Be careful the chrome.dll file is different between 32 and 64 bits so it will only work for 64 bits. If you use 32 bits just read the first post to find the right sequence of bytes.
        Before any modification make a backup of the file then open it with a hex editor and change the first byte from 48 to C3 of the following sequence:
        48 89 5C 24 10 57 48 83 EC 70 83 A4 24 80 00 00 00 00 48 8D B9 70 01 00 00
        Save and enjoy no more out-of-date popup.
        I hope it will help many people using the 64 bits version.
        Finally thanks again kao for your help and for making this topic.

  10. Thanks for your help! I have a Vista Ultimate install which I'm not quite ready to part with - it still has security updates for several months, after all - and I only use Chrome on a few specific websites I trust, but it's a pain to have the popup coming up all the time and stealing focus.

  11. RidofChromepopup

    Kao. This is out of subject of your post (I'm very sorry) But I really need your help.

    In your previous post, I saw your instruction to block annoying Chrome "Out of Date" Popup.
    {hidden link}

    This thing is bugging me for 3 weeks, and because of this extremly annoying and stressful problem, I can't proceed my automating work at all. I'm in really urgent situation and every other methods including regedit, task manager, policy_template, even clicking 'update' in the popup didn't work for me.

    As you described in your post yeah, every methods around internet did never work. I can't tell how serious damage it is to me now. I can't proceed my project for 3 weeks because of this forceful stupid annoying Chrome policy.

    and what's even more serious, I absolutely have no idea how should I deal with the chrome.dll file. I downloaded IdaPro, and let it to reverse my Chrome.dll file but never could find the matching line as below (which was in your post)
    .02CF3BDF: C3 retn
    .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]

    I'm really so sorry bringing this non-related subject which you have done about 9 months ago, but it seems you're the only person who can solve my problem. I am really urgent and so very despondent.

    {details_removed}

    1. This post was not intended for real beginners. I never expected it to gain so much attention.. πŸ™‚

      Responded and (hopefully solved) via e-mail.

  12. Hello kao,

    Thanks for your post.

    I'd like to remove a reminder about an outdated OS from Chrome 49 the same way. But unfortunately, IdaPRO does not seem to download any symbol information, though I have set the PATH variable as you suggested. What am I doing wrong?

    1. Just verified on 32-bit Chrome 49.0.2623.112 and IDA 6.95 - it works just fine. Can you describe the exact steps you took, preferably with screenshots? I'll try to reproduce them and see what went wrong. My email is at the bottom of the page.

      OR:

      • If you have the same build of Chrome (MD5 of chrome.dll = 27da638454ae4cc566c8999a7e051c36), you can try my symbols from https://mega.nz/#!Z0o2gJpS!Er-8c5ovfLpYN-BlKO60142t3Lt8apOGOg5S8R3BRPk and load them manually in IDA File->Load File->PDB file
      • If you have a different build, please upload chrome.dll to mega.nz and I'll try to find symbols for you.
      1. I have build 110, but I heard the only difference between that 2 versions is the version of Pepper Flash DLL included. Anyway, thanks for the file, hope it will work!
        I have IDA Pro 6.8, but I run it on Win XP. Can it be the source of a problem? Or maybe that online source is now irrelevant? Is it updated as a new build of Chromium comes out? I looked through the XML located there, and I see dates about January 2013 and versions around 22-23. It is alright that it stays the same all this time?

      2. And another question, are PDB files included in the repository in some folder? If yes - I'll be able to find them myself for any needed version.

  13. Hi. I had been searching for a way to turn off/disable the "Chrome is out-of-date" message, and I found this post, which happened to be what I was looking for. I am a beginner at this, but I'm willing to do something complex. I'm just confused about where to put the editted chrome.dll file, since I downloaded mine to do the editting on. Thanks.

    1. Well, turns out IDA, the Windows version that I downloaded from hex-rays(dot)com won't work on my computer... Is there a version for Windows 7 32-bit? I really do hope to get rid of the annoying "Chrome out-of-date"/"Chrome cannot update" message from appearing (after managing to disable autoupdate by using the policy templates and the registry editor, deleting the "Update" folder, and disabling the update services)...

      1. IDA v7.0+ is (officially) 64-bit only. There was a 32-bit version available to allow porting of plugins but it's unsupported - and it was never leaked to public.

        I think you have 2 options. Either find older IDA 5.0 Free (google for idafree50.exe) or find pirated IDA 6.8 (google for ida 6.8 leaked). Both are quite easy to find.

        1. Oh, thanks. I managed to find and download the 6.8 version.
          (Next stop: editing the chrome.dll file I downloaded.).

          1. Oh, wait. What is the first thing I'm supposed to look for after opening the chrome.dll file in IDA? Also, where should the dll file be, if I downloaded my chrome version not from google?

  14. SIMPLE METHOD:

    1) With Chrome closed, Shift+Right click on your Chrome Shortcut.
    2) Click on Properties
    3) Add " --check-for-update-interval=604800" to the end of the Target field
    4) Apply and close Properties.

    Pic: {hidden link}

    604800 is seconds, 7 days.
    I have not tested if 604800 is the maximum number, but that's enough. Just restart Chrome every 7 days and you will not have that annoying arrow again.

    Credits for Dirk Gently.
    {hidden link}

  15. Hello. I somehow lost my IDA 6.8 file, so I downloaded the free 5.0 version. What should I do to start editing chrome.dll? (Speaking of chrome.dll, I downloaded it from online because I didn't have it, so where should the file be?)

    1. Oh, nevermind about where to put the .dll file. I found it in the right place. So, how do I use IDA to open and edit the file?

    1. IDA downloads symbols automatically, you just need to set up symbol path correctly.

      From the article:

      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

      You can read a bit more details in official page as well: https://www.chromium.org/developers/how-tos/debugging-on-windows#TOC-Symbol-server

          1. Cool.

            The chrome.dll file is so big, I let IDA run for about 6 hours and its still not finished... I'm not sure about running IDA and downloading the dll file over multiple days, so I'm trying to download it all on one day, but finding the day to do that isn't easy. (-.-);

          2. It depends on your computer and internet connection speed but - in general - it should not take more than few hours. 6 hours sounds crazy!

  16. Hi. I recently switched computers, so I'm using a windows 10 64-bit. Would version 5.0 work?

    1. I found a version 7.0 (the freeware version) from hex-rays, but it's missing a few dll files...

  17. Hello, I use Hex editor, can anyone tell me what code you need to find in the name and change the hex so that this information is not displayed?

    1. .text:0000000181C65526 ; private: void UpgradeDetectorImpl::CheckForUpgrade(void)
      .text:0000000181C65526 ?CheckForUpgrade@UpgradeDetectorImpl@@AEAAXXZ proc near
      .text:0000000181C65526                                         ; DATA XREF: UpgradeDetectorImpl::StartTimerForUpgradeCheck(void)+CA↑o
      .text:0000000181C65526                 push    r14
      .text:0000000181C65528                 push    rsi
      .text:0000000181C65529                 push    rdi
      .text:0000000181C6552A                 push    rbx
      .text:0000000181C6552B                 sub     rsp, 88h
      .text:0000000181C65532                 mov     rsi, rcx
      .text:0000000181C65535                 mov     rax, cs:__security_cookie
      .text:0000000181C6553C                 xor     rax, rsp
      .text:0000000181C6553F                 mov     [rsp+80h], rax
      .text:0000000181C65547                 lea     rdi, [rcx+210h]
      .text:0000000181C6554E                 mov     rcx, rdi
      .text:0000000181C65551                 call    ?Invalidate@WeakReferenceOwner@internal@base@@QEAAXXZ ; base::internal::WeakReferenceOwner::Invalidate(void)
      .text:0000000181C65556                 mov     rcx, rsi
      .text:0000000181C65559                 call    ?DetectOutdatedInstall@UpgradeDetectorImpl@@AEAA_NXZ ; UpgradeDetectorImpl::DetectOutdatedInstall(void)
      .text:0000000181C6555E                 test    al, al
      
      1. Awesome, you're almost there. πŸ™‚ You just need to find the same place in hex editor and patch it.

        1. what do i need to change now?
          now i have like this:

                            ; void __fastcall UpgradeDetectorImpl::CheckForUpgrade(UpgradeDetectorImpl *__hidden this)
                            ?CheckForUpgrade@UpgradeDetectorImpl@@AEAAXXZ proc near
          
                            result= base::Location ptr -80h
                            var_60= byte ptr -60h
                            var_58= xmmword ptr -58h
                            var_48= base::WeakPtr ptr -48h
                            var_38= base::internal::CallbackBase ptr -38h
                            var_30= byte ptr -30h
                            var_28= qword ptr -28h
          
          41 56             push    r14
          56                push    rsi
          57                push    rdi
          53                push    rbx
          48 81 EC 88 00 00+sub     rsp, 88h
          00
          48 89 CE          mov     rsi, rcx
          48 8B 05 84 BE 95+mov     rax, cs:__security_cookie
          01
          48 31 E0          xor     rax, rsp
          48 89 84 24 80 00+mov     [rsp+0A8h+var_28], rax
          00 00
          48 8D B9 10 02 00+lea     rdi, [rcx+210h]
          00
          48 89 F9          mov     rcx, rdi        ; this
          E8 8A 61 41 FE    call    ?Invalidate@WeakReferenceOwner@internal@base@@QEAAXXZ ; base::internal::WeakReferenceOwner::Invalidate(void)
          48 89 F1          mov     rcx, rsi
          E8 3E 02 00 00    call    ?DetectOutdatedInstall@UpgradeDetectorImpl@@AEAA_NXZ ; UpgradeDetectorImpl::DetectOutdatedInstall(void)
          84 C0             test    al, al
          0F 85 F5 00 00 00 jnz     loc_181C6565B
          
    1. .text:0000000181C6567A                   ; void __fastcall UpgradeDetectorImpl::StartUpgradeNotificationTimer(UpgradeDetectorImpl *__hidden this)
      .text:0000000181C6567A                   ?StartUpgradeNotificationTimer@UpgradeDetectorImpl@@AEAAXXZ proc near
      .text:0000000181C6567A                                                           ; CODE XREF: UpgradeDetectorImpl::UpgradeDetectorImpl(base::TickClock const *)+187↑p
      .text:0000000181C6567A                                                           ; UpgradeDetectorImpl::UpgradeDetectorImpl(base::TickClock const *)+36C↑p ...
      .text:0000000181C6567A
      .text:0000000181C6567A                   var_68          = qword ptr -68h
      .text:0000000181C6567A                   var_60          = byte ptr -60h
      .text:0000000181C6567A                   result          = base::Location ptr -50h
      .text:0000000181C6567A                   var_30          = byte ptr -30h
      .text:0000000181C6567A                   var_28          = qword ptr -28h
      .text:0000000181C6567A
      .text:0000000181C6567A 41 56                             push    r14
      .text:0000000181C6567C 56                                push    rsi
      .text:0000000181C6567D 57                                push    rdi
      .text:0000000181C6567E 53                                push    rbx
      .text:0000000181C6567F 48 83 EC 68                       sub     rsp, 68h
      .text:0000000181C65683 48 89 CE                          mov     rsi, rcx
      .text:0000000181C65686 48 8B 05 33 BD 95+                mov     rax, cs:__security_cookie
      .text:0000000181C65686 01
      .text:0000000181C6568D 48 31 E0                          xor     rax, rsp
      .text:0000000181C65690 48 89 44 24 60                    mov     [rsp+88h+var_28], rax
      .text:0000000181C65695 48 8D B9 70 01 00+                lea     rdi, [rcx+170h]
      .text:0000000181C65695 00
      .text:0000000181C6569C 48 89 F9                          mov     rcx, rdi
      .text:0000000181C6569F E8 7C 34 17 FF                    call    ?IsUploadSave@SaveCardBubbleControllerImpl@autofill@@UEBA_NXZ ; autofill::SaveCardBubbleControllerImpl::IsUploadSave(void)
      .text:0000000181C656A4 84 C0                             test    al, al
      .text:0000000181C656A6 0F 85 89 00 00 00                 jnz     loc_181C65735
      .text:0000000181C656AC 48 83 7E 38 00                    cmp     qword ptr [rsi+38h], 0
      .text:0000000181C656B1 75 19                             jnz     short loc_181C656CC
      .text:0000000181C656B3 48 8B 4E 08                       mov     rcx, [rsi+8]
      .text:0000000181C656B7 48 8B 01                          mov     rax, [rcx]
      .text:0000000181C656BA 48 8D 5C 24 58                    lea     rbx, [rsp+88h+var_30]
      .text:0000000181C656BF 48 89 DA                          mov     rdx, rbx
      .text:0000000181C656C2 FF 50 08                          call    qword ptr [rax+8]
      .text:0000000181C656C5 48 8B 03                          mov     rax, [rbx]
      .text:0000000181C656C8 48 89 46 38                       mov     [rsi+38h], rax
      
      1. It should be as simple as putting "retn" instruction (one byte - 0xC3) at the beginning of the method CheckForUpgrade (address 0x181C65526).

        I haven't tested it myself, so please make sure you have a backup copy of the DLL. πŸ™‚

        1. now i change HxD editor:

          41 56 56 57 53 48 83 EC 68 48 89 CE 48 8B 05 33 BD 95 01 48 31 E0
          

          is: 53> C3

          41 56 56 57 C3 48 83 EC 68 48 89 CE 48 8B 05 33 BD 95 01 48 31 E0
          

          I hope I did it right

          1. I noticed that I have the following problem after that time I google closes automatically instead or do you also have such a problem?

          2. You should change FIRST byte of the instruction. So, 41 -> C3...

            This is 6 years old article. I managed to find a workaround for the software which required old Chrome version and now I have enabled automatic updates again. But the method should still work.

  18. Thank you for sharing this. It helped me a lot. I didn't know that symbols for chrome.dll can be downloaded like that. However, starting from version 91.0.4472.77 (or probably even earlier) the correct function to be patched is "UpgradeDetector::NotifyUpgrade(void)" (replace the first byte of the function with C3).

  19. Thank you for this amazing article!

    I tried with what was the latest version of chrome, 126.0.6478.57. It found and downloaded the PDB file (~4.8GB) but when IDA tries to load the file it pops up an error, "chrome.dll failed to load pdb info"

    If I look in the output log it says "malformed PDB file"

    Even if I copy the http URL where it finds the file, download it manually (to skip having to wait for that 4.8GB on every new attempt), and put it in the same directory, and select it when opening, it still gives me errors:

    PDB: loading ...Chrome-bin\126.0.6478.57\chrome.dll.pdb
    PDB: File ...Chrome-bin\126.0.6478.57\chrome.dll.pdb is the malformed PDB file

    Do you have any advice?

    1. Hi JC,
      I encountered the same problem few weeks ago when I tried to play with Chrome again. The Chrome team is definitely doing something strange with their symbol files! πŸ™‚

      My solution was to use Dump_Syms tool from Mozilla - it was the only tool that would accept Chrome PDB file and produce any reasonable output in a reasonable time. I found the address I needed in the generated text file, but you could also make a script to import all symbols into IDA.

      1. Thank you, kao! Dump_Syms worked very! I saw something while searching for a solution talking about how pdb files with empty (missing?) functions can break IDA's ability to load them, with a note that such files can probably still be loaded/used by debuggers esp. windbg. If IDA is indeed the problem maybe they will upgrade their PDB parser in the future. But at least for now we have Dump_Syms! Thank you again! πŸ™‚

Leave a Reply

  • Be nice to me and everyone else.
  • If you are reporting a problem in my tool, please upload the file which causes the problem.
    I can`t help you without seeing the file.
  • Links in comments are visible only to me. Other visitors cannot see them.

6  +   =  15