プロフィール

髭山髭人(ひげひと)

自分の書いた記事が、一人でも誰かの役に立てれば...
活動信条の一つとして「貴方のメモは、誰かのヒント」というのがあります。

このサイトについて

本家HP(packetroom.net)から切り離した いわゆる技術メモ用のブログで、無料レンタルサーバーにて運用しています。広告表示はその義務なのでご容赦。
XREA さんには長年お世話になっています

サ終した Qrunch (クランチ) と呼ばれる技術ブログサービスに掲載していた記事も含まれます

chrome.dll 改造メモ - LocationIconView や LocationBarView の特定

スキーム文字列の除去

GoogleChrome v89.0.4389.114

FF 50 08 84 C0 0F 85 30 01
↓
FF 50 08 84 C0 90 E9 30 01
               ^^ ^^

jne を jmp 化

GoogleChrome 88.0.4324.182 Official Build x64 および
Chromium 88.0.4324.0 Developer Build x64 時

FF 50 08 84 C0 74 07 31 F6
↓
FF 50 08 84 C0 90 90 31 F6
               ^^ ^^

ロケーションバーの横幅制限撤廃

v89.0.4389.114

一連の計算処理を省略 (je→jmp化)

0F 84 87 01 00 00 48 8B 07 48 8D 74 24 30
↓
90 E9 87 01 00 00 48 8B 07 48 8D 74 24 30
^^ ^^

v88.0.4324.182

ebp へ 実数 0 の強制代入

03 6C 24 28 01 D5 0F 48 E9
↓
03 6C 24 28 BD 00 00 00 00
            ^^ ^^ ^^ ^^ ^^

Chromium 88.0.4324.0 Developer Build x64

横幅に関する計算処理を 74のje から EBのjmp にすり替えて強制省略

BB 00 00 00 00 74 71 4C 8D 77 F0
↓
BB 00 00 00 00 EB 71 4C 8D 77 F0
               ^^

スキーム文字列情報に関する当該ソースメモ

当時 chrome://flagsenable-mark-http-as に相当していた処理です。
「保護されていない通信」の文言を消す設定ですね。
https://www.chromium.org/Home/chromium-security/marking-http-as-non-secure
特にグラブルユーザーの方なんかは、この設定が残っていた時代にココを切っていたはず..

https://cs.chromium.org/chromium/src/chrome/browser/ui/views/location_bar/location_icon_view.cc?l=130&gsn=ShowText https://chromium.googlesource.com/chromium/src/+/master/chrome/browser/ui/views/location_bar/location_icon_view.cc

↓ 昔控えていた時のソースメモ

bool LocationIconView::ShouldShowText() const {
  if (delegate_->IsEditingOrEmpty())
    return false;

  const auto* location_bar_model = delegate_->GetLocationBarModel();
  const GURL& url = location_bar_model->GetURL();
  if (url.SchemeIs(content::kChromeUIScheme) ||
      url.SchemeIs(extensions::kExtensionScheme) ||
      url.SchemeIs(url::kFileScheme)) {
    return true;
  }

  return !location_bar_model->GetSecureDisplayText().empty();
}

↓ 執筆時のソースメモ

bool LocationIconView::GetShowText() const {
  if (delegate_->IsEditingOrEmpty())
    return false;

  const auto* location_bar_model = delegate_->GetLocationBarModel();
  const GURL& url = location_bar_model->GetURL();
  if (url.SchemeIs(content::kChromeUIScheme) ||
      url.SchemeIs(extensions::kExtensionScheme) ||
      url.SchemeIs(url::kFileScheme) ||
      url.SchemeIs(dom_distiller::kDomDistillerScheme)) {
    return true;
  }

  return !location_bar_model->GetSecureDisplayText().empty();
}

この処理に false を必ず返させれば、「保護されていない通信」や「Chrome」(拡張機能のページ)などのスキーム文字列を、ブラウザのロケーションバー上に表示させない様にできる。 ( ※ ただし、アイコンの処理は別件 )

過去特定したバージョン時のメソッド名は ShouldShowText() だったのだが、いつからか GetShowText() に変更された模様

バイナリ上における LocationIconView:: 付近の特定

"chrome" "chrome-extension" "file"
の参照文字列が3つ近い位置に含まれている個所を探し出す。
いつからか "chrome-distiller" も含まれるようになった

各種候補が多すぎて、単純に参照文字列だけで検索すると物凄い量なんだけど、他にも参照となる足掛かりもあるので、絞っていけば特定しやすい。
以下は参照文字列内における当該箇所のスクリーンショット。
(GoogleChrome v88.0.4324.182 Chrome.dll)

バイナリバージョンにもよるけど、画像のスクロール箇所でおおよその目途が付くかも。

↓ 炙り出し用の参照文字列検索でつかう正規表現。コピペでどうぞ
"chrome"|"chrome-extension"|"file"|"chrome-distiller"|"ExtensionsToolbarMenu"

で、こちらの画像が全体における当該箇所。

content::kChromeUIScheme"chrome" 相当
extensions::kExtensionScheme"chrome-extension" 相当
url::kFileScheme"file" 相当
dom_distiller::kDomDistillerScheme"chrome-distiller" 相当

FF50 08     call qword ptr ds:[rax+8]
84C0        test al,al
74 07       je chrome.xxxxxxxxxxxxx
31F6        xor esi,esi
E9 1D010000 jmp chrome.xxxxxxxxxxxxx

testje の箇所で、不成立にさせて処理を飛ばす。
今回は je を 90で埋めて nop 化させ、test の結果が何であれ je で飛ばない様にした。

FF 50 08 84 C0 74 07 31 F6
↓
FF 50 08 84 C0 90 90 31 F6
               ^^ ^^

※ GoogleChrome 88.0.4324.182 Official Build x64 時の画像

芋づる式に LocationBarView を見つけ出す

今回特定した LocationIconView::GetShowText() は、
int LocationBarView::GetMinimumLeadingWidth() の中からも呼ばれている。

この為、ブレークポイント貼りつつ横幅を操作した時に停まった個所にて ret した呼び出し元を探れば、こっちも特定できる

https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/ui/views/location_bar/location_bar_view.cc;l=840 https://chromium.googlesource.com/chromium/src/+/master/chrome/browser/ui/views/location_bar/location_bar_view.cc

int LocationBarView::GetMinimumLeadingWidth() const {
  // If the keyword bubble is showing, the view can collapse completely.
  if (ShouldShowKeywordBubble())
    return 0;

  if (location_icon_view_->GetShowText()) // ←★ココで呼んでる
    return location_icon_view_->GetMinimumLabelTextWidth();

  return GetLayoutConstant(LOCATION_BAR_ELEMENT_PADDING) +
         location_icon_view_->GetMinimumSize().width();
}

更に int LocationBarView::GetMinimumLeadingWidth()
gfx::Size LocationBarView::GetMinimumSize() からも呼ばれているので、芋づる式にこちらも特定できる

https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/ui/views/location_bar/location_bar_view.cc;l=427

gfx::Size LocationBarView::GetMinimumSize() const {
  const int height = GetLayoutConstant(LOCATION_BAR_HEIGHT);
  if (!IsInitialized())
    return gfx::Size(0, height);
  const int inset_width = GetInsets().width();
  const int padding = GetLayoutConstant(LOCATION_BAR_ELEMENT_PADDING);
  const int leading_width = GetMinimumLeadingWidth(); // ←★ココで呼んでる
  const int omnibox_width = omnibox_view_->GetMinimumSize().width();
  const int trailing_width = GetMinimumTrailingWidth();

  int alt_width = leading_width + padding + trailing_width;
  int width = inset_width + std::max(omnibox_width, alt_width);
  return gfx::Size(width, height);
}

ちなみにこの LocationBarView::GetMinimumSize() は、Chromeにおける横幅制限値計算の一端を担っており、従来の横幅制限撤廃のバイナリ値同様に、ここを見つけ出すのが個人的な最終目標の一つでもあった

ロケーションバー内部の横幅制限を撤廃させる

GoogleChrome v88.0.4324.182

執筆時のバイナリでは ebp への代入を改竄

// 変更前
| 036C24 28        | add ebp,dword ptr ss:[rsp+28]     |
| 01D5             | add ebp,edx                       |書換
| 0F48E9           | cmovs ebp,ecx                     |書換
| 48:8B7424 38     | mov rsi,qword ptr ss:[rsp+38]     |
| 892E             | mov dword ptr ds:[rsi],ebp        |
| 8B4424 2C        | mov eax,dword ptr ss:[rsp+2C]     |
| 31C9             | xor ecx,ecx                       |
// 変更後
| 036C24 28        | add ebp,dword ptr ss:[rsp+28]     |
| BD 00000000      | mov ebp,0                         | 強制代入
| 48:8B7424 38     | mov rsi,qword ptr ss:[rsp+38]     |
| 892E             | mov dword ptr ds:[rsi],ebp        |
| 8B4424 2C        | mov eax,dword ptr ss:[rsp+2C]     |
| 31C9             | xor ecx,ecx                       |

RBP(ebp)に対して色々加算している箇所の一部(後半)を弄り、 実数 0 の強制代入とした。

03 6C 24 28 01 D5 0F 48 E9
↓
03 6C 24 28 BD 00 00 00 00
            ^^ ^^ ^^ ^^ ^^

ちなみにRBP(ebp)の最終的な値は、従来だと0xCD(205) だった (GoogleChrome 88.0.4324.182)

逆コンパイル式では、この構造体に入る gfx::Size 型でほぼ間違いない。

struct s0 {
    int32_t f0;
    int32_t f4;
};

Chromium 88.0.4324.0 Developer Build x64

アセンブラ処理がソースコード同様二段式で呼ばれている様で、ret を足掛かりに LocationBarView::GetMinimumLeadingWidth() を呼ぶ LocationBarView::GetMinimumSize() を探り、 横幅に関する計算処理を 74のje から EBのjmp にすり替えて強制省略する形をとった

※ 参考画像は省略

BB 00 00 00 00 74 71 4C 8D 77 F0
↓
BB 00 00 00 00 EB 71 4C 8D 77 F0
               ^^