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://flags
の enable-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
test
と je
の箇所で、不成立にさせて処理を飛ばす。
今回は 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()
からも呼ばれているので、芋づる式にこちらも特定できる
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
^^