Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
BlackLotus-analysis-stage2-bootkit-rootkit-stage — Z2A-BlackLotus チャレンジ ステージ2 ブートキット/ルートキット解析 | Kitploit
ツール/GitHubGitHub/spiralbl0ck/blacklotus-analysis-stage2-bootkit-rootkit-stage
静的分析動的分析 (サンドボックス)リバースエンジニアリングデバッガマルウェア分析バイナリ解析学習と教育ファームウェア解析
GitHub
spiralbl0ck/blacklotus-analysis-stage2-bootkit-rootkit-stage

BlackLotus-analysis-stage2-bootkit-rootkit-stage

Z2A-BlackLotus チャレンジ ステージ2 ブートキット/ルートキット解析

リポジトリを見る
17543年前未レビュー

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

BlackLotus-analysis-stage2-bootkit-rootkit-stage

BlackLotus ステージ2 ブートキット-ルートキット解析

この神がかった代物に踏み込む前に(信じてくれ、これは神の御心なしには誰にも成し得ない神がかった代物だ(少なくとも私の意見では))、ブートキットファイルのハッシュをここに示す

1

まず最初に、これが正常なシステムの見え方だ

1
2
``` C:\Windows\system32>BCDEdit

Windows Boot Manager

identifier {bootmgr} device partition=\Device\HarddiskVolume9 path \EFI\MICROSOFT\BOOT\BOOTMGFW.EFI description Windows Boot Manager locale en-US inherit {globalsettings} default {current} resumeobject {3f80ecd0-df10-11ed-bafc-80a84b2564bb} displayorder {current} toolsdisplayorder {memdiag} timeout 30

Windows Boot Loader

``` So how do we set up a breakpoint in order to debug the bootkit? Well that's we we compiled the ovmf image as debug rather than release. If you specifically start qemu with that command you'll have qemu run and debug messages will be logged in a file called debug.log , which looks like this ```

identifier {current} device partition=C: path \Windows\system32\winload.efi description Windows 10 locale en-US inherit {bootloadersettings} recoverysequence {3f80ecd2-df10-11ed-bafc-80a84b2564bb} displaymessageoverride Recovery recoveryenabled Yes isolatedcontext Yes allowedinmemorysettings 0x15000075 osdevice partition=C: systemroot \Windows resumeobject {3f80ecd0-df10-11ed-bafc-80a84b2564bb} nx OptIn bootmenupolicy Standard

root@kitploit:~
さて、私の分析では、自分のマシンに感染させることはできなかったので、先ほど参照したアジアの研究者のブログ記事の例を使います。これは感染したものがどのように見えるべきかの例です。```
    // Windows Boot Manager
    // --------------------
    // identifier              {9dea862c-5cdd-4e70-acc1-f32b344d4795}
    // description             Windows Boot Manager
    // locale                  en-US
    // inherit                 {7ea2e1ac-2e61-4728-aaa3-896d9d0a9f0e}
    // bootdebug               Yes
    // displayorder            {57e1b615-0355-11ec-abb0-005056c00008}
    // timeout                 30

    // Windows Boot Loader
    // -------------------
    // identifier              {57e1b615-0355-11ec-abb0-005056c00008}
    // device                  boot
    // path                    \system32\hvloader.efi
    // description             Hoy la disco se flota
    // locale                  en-US
    // inherit                 {6efb52bf-1766-41db-a6b3-0ee5eff72bd7}
    // truncatememory          0x10000000
    // avoidlowmemory          0x1000
    // nointegritychecks       Yes
    // testsigning             Yes
    // isolatedcontext         Yes
    // osdevice                boot
    // systemroot              \
    // ems                     Yes

=============================================================================

=============================================================================

始める前に、そもそもEFIモジュールを解析するための環境をどのようにセットアップするのでしょうか? これは @MaverickMusic__ のおかげです。彼との議論の中で、彼は私にこれを渡してくれました( https://zhuanlan-zhihu-com.translate.goog/p/343293521?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=en-GB )。さて、私はそこにある手順を完全には従いませんでした。ここに、環境を立ち上げるために私が実際に行ったことを正確に示します:

-最初にedk2をインストールしました(https://github.com/tianocore/tianocore.github.io/wiki/Windows-systems)

-次に、ovmfをリリースではなくデバッグとして構成しました(これは後で役立ちます)。コマンドは次のとおりです build -a X64 -t VS2019 -b DEBUG -p OvmfPkg/OvmfPkgX64.dsc

-第三に、windbgを構成する必要がありました。これをいったいどうやってやったのか? 私はこのリンクからすべてをダウンロードしました(git clone https://github.com/microsoft/WinDbg-Samples)。それからExdiGdbSrv.slnをコンパイルしました。その後、私はこのリンク(https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/setting-up-qemu-kernel-mode-debugging-using-exdi)にあるすべての手順を、`Use regsvr32 to register the DLL in an Administrator command prompt. と書かれている箇所から、PS>.\Start-ExdiDebugger.ps1 -ExdiTarget "QEMU" -GdbPort 1234 -Architecture x64 -ExdiDropPath "C:\path\to\built\exdi\files"まで実行しました。混乱するのは分かっていますが、すべての手順を説明するビデオを必ず作るので、どうか辛抱強く待ってください! よし、これでデバッグ用の環境が整いました。では、いったいどうやってコードをデバッグするのでしょうか? そこでqemuを起動します。私の場合、次のコマンドを実行して起動しましたqemu-system-x86_64.exe -L . -bios OVMF.fd -hdd dos.img -debugcon file:debug.log -global isa-debugcon.iobase=0x402`。qemuコマンドを実行すると、すぐにqemuのviewメニューからcompat_monitor0を選択しました。そうすると、次のように表示されるはずです。

また、これを選択した後、gdbserverと入力して、gdbデバッグのリモートインスタンスを起動します。これにwindbgを使って、次のコマンドでアタッチします .\Start-ExdiDebugger.ps1 -ExdiTarget "QEMU" -GdbPort 1234 -Architecture x64。接続すると、次のように表示されます。

1
1

さて、この出力を解釈しましょう。私たちのケースでは、唯一関連する行は EntryPoint=0x000062C9A8C で、これはブートキットを実行する際の優先ロードアドレスのようなものです。具体的には、このブートキットでは 0x62C4A8C または 0x62C9A8C の間で変動します。これで IDA でプログラムをリベースして、通常の作業を進めることができます :) 。ブログの残りもお楽しみください!

=============================================================================

元の winload.efi と blacklotus がドロップした winload.efi を BinDiff で比較する

1
2
3
4

いくつかの類似点も見られますが、相違点もあります。ただ、役立つものは何もありません。とにかく....

=============================================================================

よし、では始めましょう。

1
1

よし、それでは解析を始めましょう。まず、呼び出される関数があることがわかります。それが何なのか? うーん

1
2

別の関数も登場。そうでもない...。何か見覚えのあるものがありませんか?

1
2
3

4

5

まだ何もない???

問題ない、今度こそ

1
2

同じデマングル関数だ! やあ、旧友よ :)))

しかし、return (*(a1 + 88))(v2, &unk_62CEABC, 3i64); はどうでしょうか? 正直、静的な視点だけでは何と言えばいいのかわかりません。デバッガーを使って理解してみましょう :))

文字列をデマングルすると、次のようになります。

1

次に、call 命令に到達すると

1

そして情報は得られません.... 素晴らしい。でも、なぜでしょうか? それは、デバッグシンボルを取得するための .pdb ファイルがないからです。まあ、少なくとも ida はここで役に立ちます。つまり、「grand」関数は入力として SystemTable->RuntimeServices を受け取ります。これは EFI_SYSTEM_TABLE 型です。これを調べると、EFI Runtime Services Table へのポインタ。 です。Google で検索すると多くのドキュメントが見つかりますが、重要なドキュメントの1つが https://uefi.org/sites/default/files/resources/UEFI\_Spec\_2\_1\_D.pdf です。そこには次のように書かれています。

1

つまり、多数のポインタを持つ構造体ですね。でも、もっとズームインしてみましょう。

まず最初に、VbsPolicyDisable をデマングルします。Google で検索すると、ESET の分析がヒットし、この変数は起動中に Windows OS ローダーによって評価され、定義されている場合、HVCI や Credential Guard などの VBS のコア機能は初期化されません。 とあります。つまり、この変数は起動レベルの現在の「セキュリティ」を担っています。次に、その変数を引数に取る関数があります。

1

したがって、これはその変数の状態を何らかの形で変更する関数であると結論付けることができます。これを実行できる可能性のある関数は何でしょうか? EFI_SYSTEM_TABLE には、それを行う関数が1つだけあります。EFI_SET_VARIABLE の SetVariable です。

つまり、この関数は単純に VbsPolicyDisable を受け取り、それを設定します。``` db 77h ; w .data:0000000180005034 db 59h ; Y .data:0000000180005035 db 3 .data:0000000180005036 db 32h ; 2 .data:0000000180005037 db 4Dh ; M .data:0000000180005038 db 0BDh ; ½ .data:0000000180005039 db 60h ; ` .data:000000018000503A db 28h ; ( .data:000000018000503B db 0F4h ; ô .data:000000018000503C db 0E7h ; ç .data:000000018000503D db 8Fh .data:000000018000503E db 78h ; x .data:000000018000503F db 4Bh ; K.

root@kitploit:~
さて、これらのバイトに何か重要な意味はあるのでしょうか? はい、あります。もし偶然にも blacklotus 解析の第一部を読んだことがあるなら、私がアジアの研究者の仕事を参照したのを覚えているでしょう。その研究者は、ドロップされたブートキットも解析してくれていました。ぜひ確認してみてください(https://www.cnblogs.com/DirWang/p/17294545.html#autoid-3-2-1)。彼の解析の中で、彼は親切にもその情報を提供してくれました。彼が指し示しているのは https://github.com/Mattiwatti/EfiGuard/blob/master/EfiGuardDxe/PatchWinload.c です。そこには似たような行があります。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/33c755aa460f5bdc338c75f3f5e1322c731123299d59c43dcdf2be3b72d1276c.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/144b057568871a60a32e477ed1ae7e8d7090778a67b7fc24222f0f58fe44afc1.png" alt=""><figcaption></figcaption></figure>

</div>

これには特定の理由があるのでしょうか? 正直なところ、私はブートキットを解析するのは初めてなので分かりません。この分野で私より経験がある方がいらっしゃいましたら、教えていただくか、このドキュメントを編集するPR/プルリクエストを作ってください :)

\=============================================================================

さて次は、運が良く、IDA の擬似コードがアセンブリと似ています。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/7457c9d8beb807556618728c7aba102109a472ef2f990f35ec344038fafc4cd5.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/e11c4b4e4260f7a91e6dc08bcabb7c3ac420dcee346b1bf9dff02835342f7837.png" alt=""><figcaption></figcaption></figure>

</div>

ここで起きているのは、おそらく EFI\_SYSTEM\_TABLE の通常の初期化です。つまり、ブートプロセスを継続するプロセスを初期化しているのだと思います。そして、PatchBootManager という関数呼び出しがあります。

PatchBootManager

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/66c49bf5b64655af7e0edfe384ad715912c02fbeea1ac1313e4f65479ab58f80.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/7a1dc3ac7c01cbd4cfd9b3ec614c357895210e4f03ae5d58000e6b047f84eb96.png" alt=""><figcaption></figcaption></figure>

</div>

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/3fc22a51052c24c9e436ace83a1672ce88bf25fb11103b32d0143fa0ab4d7216.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/22c7869b067f26c6469e4baffcd4226535c47e82d4baaf7fa8e27820915b1580.png" alt=""><figcaption></figcaption></figure>

</div>

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/38cf7697523141faa68a59b52abd2a1ca14d0d9053f1e6960052a5093e3a94bb.png" alt="3">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/505a3fd02b96bcb823bf108ee03a8a1204827852260c1e8ce3902638237259b3.png" alt=""><figcaption></figcaption></figure>

</div>

そして擬似コードから

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/9c8482f0faa4d4de5f8643acc4276ebbbfc57386e9b00a4057793b5c67b1bf3b.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/c44de61b9f089fd8972bcc8567110bc2d58c21e5465a7b4f14fc7beaefee30a3.png" alt=""><figcaption></figcaption></figure>

</div>

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/6809c28e881b3626d73a476cd31631891539f6a7b71cf276619f9cd2244d83e9.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/c8cd4870cd0488e57cde3448ba01fdd44063f266516d8530731f42e6ccc5be78.png" alt=""><figcaption></figcaption></figure>

</div>

では、最初の関数呼び出しは HandleProtocol です。このコードは何をしているのでしょうか? 幸運にも、Google で簡単に検索するとこれが見つかります(https://tianocore-docs.github.io/edk2-ModuleWriteGuide/draft/5\_uefi\_drivers/54\_communication\_between\_uefi\_drivers.html)。それによると、`プロトコルを取得` するものです。かっこいいけど、これだけではあまり意味が分かりません。わかってるよ、みんな。つまり、これは他の UEFI ドライバーが使う通信情報メソッドを取得しているのです。さらに掘り下げると、2番目のパラメータはこれです。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/703c3f52bd8c3d10eaf046fc801cbc60ca7a62e9162d67a6ba63caf4c9e9038d.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/9d41aacaed9c15391beb8b1b62739572bf7f873508938ade770610eec371a17c.png" alt=""><figcaption></figcaption></figure>

</div>

その特定のバイト列を検索すると、これが見つかります。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/f4a8ed3b81486c8481c0f8894175f9d7390ddf62f9974ba025aad9827dea119e.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/882b5116cfd08886c3dac510443fb77c9aa31781eb234208ec81fdf313544c29.png" alt=""><figcaption></figcaption></figure>

</div>

では、EFI\_LOADED\_IMAGE\_PROTOCOL\_GUID は一体何をするのでしょうか? (https://uefi.org/specs/UEFI/2.10/09\_Protocols\_EFI\_Loaded\_Image.html) からの引用だと、`任意のイメージハンドルに対して使用でき、ロードされたイメージに関する情報を取得できます。` とあります。どんな情報? \`\`\`このセクションでは、EFI\_LOADED\_IMAGE\_PROTOCOL と EFI\_LOADED\_IMAGE\_DEVICE\_PATH\_PROTOCOL を定義します。これらのプロトコルはそれぞれ、メモリにロードされたイメージを記述し、EFI Boot Service LoadImage() を通じて PE/COFF イメージがロードされたときに使われたデバイスパスを指定します。これらの記述には、イメージがロードされたソース、メモリ内でのイメージの現在の場所、イメージ用に割り当てられたメモリの種類、およびイメージが呼び出されたときに渡されたパラメータが含まれます。\`\`\`\`

つまり、このケースではブートキットに関する情報を取得しています。ここで問題が1つ。デバッグシンボルがないため、関数の結果をあまり詳しく調べることができません :/ しかし、推測はできます。私は、構造体(前の関数呼び出しの結果)が rbx に入っていると推測しています。

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/b8f744ecd9fd4be572a1e2d191b06231559eca2b32aeaa981a399eec7f3ee710.png" alt=""><figcaption></figcaption></figure>

次に、文字列のデマングルを呼び出します。

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/1fdc75d2dc9221250e6d46692770ad5240f7a0d6cda9cc5634749b327fc8c146.png" alt=""><figcaption></figcaption></figure>

これにより次が得られます。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/e073b265ff13675b755ec8413554bec74ab4eae57dd002b25694632eb43cbc8e.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/3654bb54071386cd020c43ed4a35fae40aec386897a0ca26a27b58b8e1a91c95.png" alt=""><figcaption></figcaption></figure>

</div>

そして次にこれを呼び出します。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/c433aa63cddd2ecfb5ce0fd57a6774ad35b1c1ed4ee71e7cecb566cc861d2b80.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/6834be566cdd81f2410ec7d4ee97936d14a27017a723371eea3046b8590609f4.png" alt=""><figcaption></figcaption></figure>

</div>

\=============================================================================

sub\_180002B14

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/483f2b789c0fa6fe9378ba324f8e349bc72cbb45e540bbc2355ef55acaf1b6b4.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/d84d79115facbc0f9ff7afe06d70a18555e7d94bc196f6f9d0ff6b5cfd40408a.png" alt=""><figcaption></figcaption></figure>

</div>

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/19e2366fddab99fa3aa4375b8306475ee31d3bf9a3c3737efeeb4d627868404e.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/6c808c76821c756eca776cf6290482f6f9829167f539bf31b2ad82b3de0af829.png" alt=""><figcaption></figcaption></figure>

</div>

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/ad0d06238e39e4ba1decb2f1305510a8375822b13ae9148d91e267d14762eb3b.png" alt="3">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/0e45e9ae64c3fbd8a61ffdf60ec2e532529d8cab6cfc7786fa2c91824233d347.png" alt=""><figcaption></figcaption></figure>

</div>

そして擬似コード

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/c14b1eacbe8eef4155c4148b66fa95f93bbd9e6fc81e5ca80f1ddc5b2b9a7a16.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/b7c452865661d95b79886a48a455eba663c2e3915e0a81ad16dc7ddd8c2c0189.png" alt=""><figcaption></figcaption></figure>

</div>

なるほど、if までの部分はすべて自明です。では if はどうでしょう? ここでも unk\_180005010 をパラメータにして呼び出しをしています。これもバイト配列です。さらに調べると、次のようになっています。

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/c3bb66f35a4e559ae793ba590fc0c342bdde1e1c9765e144cb450a809009655d.png" alt=""><figcaption></figcaption></figure>

では、最初のバイト列をもう一度調べて簡単に検索すると、これ(https://github.com/theopolis/uefi-firmware-parser/blob/master/uefi\_firmware/guids/efiguids\_ami.py)に出くわします。より正確には、この `'EFI_DEVICE_PATH_PROTOCOL_GUID': [0x09576e91, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b]` です。

UEFI の仕様ページをもう一度見ると、`任意のデバイスハンドルに対して使用でき、物理デバイスまたは論理デバイスに関する一般的なパス/位置情報を取得できます。` とあります。さらに、`デバイスパスは、ハンドルが指すデバイスの場所を記述します。` のような記述もあります。OK、もう少しスクロールすると、\_EFI\_DEVICE\_PATH\_PROTOCOL という関数が見えます。結論として、これは EFI\_DEVICE\_PATH\_PROTOCOL\_GUID に関係していることが分かります。しかし、私たちの関数は型が EFI\_BOOT\_SERVICES です。では、EFI\_BOOT\_SERVICES にプロトコルを扱うような関数はあるのでしょうか? あります。https://www.intel.com/content/dam/doc/product-specification/efi-v1-10-specification.pdf のセクション4.4を調べると、次のようになっています。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/918a0a5184849cbb87454df44c5ffa5e5fa586f223213287f6c7fbe737a0fbc8.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/fab94604327fe596d9eeb68368efcf0afc721ef7bfcdc07a8977392b4309238c.png" alt=""><figcaption></figcaption></figure>

</div>

より正確には、おなじみの関数(HandleProtocol)があります。クール。

次に、今度は私たちにとって未知の関数呼び出しがあります。その引数を見てみましょう。引数は2つ、次に渡された文字列の長さ(Unicode)、そして変数へのポインタです。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/39e0d1d9baabff8d95da7109294db94f9fc4409a6ede34d37ece9662fb73651d.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/e116e90f20a09d48f21a981e7d24c49f7474ea9ac6007b6fa41973300af4e83d.png" alt=""><figcaption></figcaption></figure>

</div>

これをデバッガで調べると

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/f412c3bf83f60da9213f4c29b39350c925a0aa6411c42de52d7fa4530c5bc3fe.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/5285bf4d5e52dbbef857e46e8738c3ba6e7f6cda87f9b67a4965b23cc70aba0e.png" alt=""><figcaption></figcaption></figure>

</div>

奇妙なことに、rcx には AllocatePool というデバッグ文字列があり、それは関数呼び出しの後に現れます。したがって、これはおそらく AllocatePool への呼び出しだと考えられます。面白いことに、仕様を調べると boot\_services にも AllocatePool へのポインタがあり、この仮説がさらに強くなります。

では、十分な領域を確保できた場合(>= 0 のチェックは確保が成功したかどうかを確認するためです。EFI\_OUT\_OF\_RESOURCES が次のように実装されているなら

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/bf08cd5dd33ad9ca16ff4e6a44a4cbfd51cd1f8b0300d9b6b44984c4306fcb6e.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/c28af9995294473937be13a6094de90cb57a688c83727617ca9f667c2705d7cd.png" alt=""><figcaption></figcaption></figure>

</div>

次のように仮定するのが安全です。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/3741ef8be2dc989f601d26568907381f1847d29c0bf514add76485b0f0fef4b6.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/cdfc6ccb296659fc8156d4bfba6d777da8b2792e4af56677d0f0d57695932216.png" alt=""><figcaption></figcaption></figure>

</div>

は確保成功に使われるということです)

興味深い事実として、確保後のバッファはゼロではなく、次のようなバイトが含まれています。これについて詳しい方がいらっしゃいましたら、このドキュメントを編集するPRリクエストを作ってください。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/e4b15da615e07faa4965d864435bf4deec0e01270f9d1ac1134fb5b20ad46892.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/b229a700b321040fc8978f4f0f489a058381795c128d27dbcfbcfff5f9ffd3b2.png" alt=""><figcaption></figcaption></figure>

</div>

とにかく、最終的に memcpy を呼び出し、呼び出し後のバッファは次のようになります。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/28e61d8725687245e9a9dae7e467929ac15d5a81e33178262f0ce886a3c4555c.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/f161ab0441b14d71dbade9fc3acebbd12b1453de5d53b77b09af98c0cf0ac6d6.png" alt=""><figcaption></figcaption></figure>

</div>

次に、いくつかのバイトを追加して、バッファが次のようになるようにします。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/80906384a49ef1d6eaea9667cb962459c27feb8e9deac857491a248be5443a4f.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/7c703952c72c154d156603c457a00013305c48519ddee808925c32a62499135f.png" alt=""><figcaption></figcaption></figure>

</div>

そして、FileDevicePath\_call という関数を呼び出します。これは大体次のようなものです。&#x20;

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/66c77ae12715ee6d982ba2cfb769ba6a650f52ce56d7bae54e3bd93686695f02.png" alt=""><figcaption></figcaption></figure>

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/5f7e06800ec3eecb9559d1592b8a76868038c0cbb64744e5c928b65d189ef183.png" alt=""><figcaption></figcaption></figure>

これは次のように変換されます。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/2b36492bb7dd46a7139c27de61371b59adac5bfbec989bbb542b58d34ce7982d.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/361e2b338c676b99393f7baa48e970ba886894f579065a4468fe113841c0783b.png" alt=""><figcaption></figcaption></figure>

</div>

でも、説明がないと意味が分からないので…。

まず、strlen のカスタム実装がありますが、役に立たないので解説はしません :) ただし、結果はこちらです。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/03a0aabe9f7c87f42b7e64bb284d74738ecdc81134136cfec68c70084644c3ea.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/823c30bd0a6a8c1d750ef1dfb0bce5be67a13a96de12e53b3e46b2226a1c2be1.png" alt=""><figcaption></figcaption></figure>

</div>

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/5dd4684c37f3129c8234cd69574bb6371b4bef72ff7e027199b7900134cdd101.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/118ee749874a6b08d40286821735190f67af45ca8d4573fc94aee3a2cea04af2.png" alt=""><figcaption></figcaption></figure>

</div>

len(of(str)+"\x00" から32文字と、関数呼び出しの前に追加された最後の4バイト 0x4FF7F

次に、アジアの研究者のブログ記事から私も使った PxepDevicePathInstanceCount を呼び出します。これは単純な strlen で、各文字を数えてカウンタを持つだけです。以下で見られます。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/130931a6676f0519da2b50a9762955b7581e7102434e587236137b216cc62ead.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/ce1a6ad93452a8092d2fb71ffd6418df78c32fc8cdf4fb99133924cc9037f12e.png" alt=""><figcaption></figcaption></figure>

</div>

そう、pop rbx があり、呼び出し後には rbx=0x48 となっています。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/4c2eabdd91ec40fc82c100e67579d729def9e74c6bfd000fff287bc9c10b0f38.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/818bb3c8398d4a53c0260d9310d4d192cfa5b65a404348df5516c94fa3d8dcaa.png" alt=""><figcaption></figcaption></figure>

</div>

その後、同じ文字列に対して再び strlen を呼び出します。これはおそらく、次の行、正確には `v6 + v4 * v5;` で v4\*v5 を行うためで、Unicode 文字列を扱う何らかの方法だと思います。

とにかく、その後、以前に出会った gEfiBootServices + 64 を使って再度メモリを確保します。これは AllocatePool に解決されました。

ここでも素晴らしいものが見られます。それは

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/26d19e06bd335f1267946a5da2542cf3eb9f2965fab788d0bcf720d7e3c08d37.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/225c92cbe9a5e72214cb279e61ad5fcbaef0a243db835b67fce5ff7ef74e7c86.png" alt=""><figcaption></figcaption></figure>

</div>

このメモリブロックには afafafaf というパターンが含まれているという事実です。

次に何が起こるかというと、メインループの実行後に、次のような2つのバッファが得られます。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/35f257d96c752ac436e81778da5f37c28bfcb79fc5614f3ea8e099888cc011c3.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/b9c706cc28161a6e7274c5cabc895bedc1279728b3ed7c11084cb6cb38dbf9e3.png" alt=""><figcaption></figcaption></figure>

</div>

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/52477a3825650e47112a5e619a098c74e7e0de778ebfeda5682e5b49d48f3923.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/762a6dd3897f3b630ce1d0faa371e58ed9b2bce755bb8edd54f958aab7c3b69b.png" alt=""><figcaption></figcaption></figure>

</div>

本当に言うと、私たちが関心があるのは最初のバッファだけです。それが返されるからです。つまり、これはデバイスパスをコピーして、バッファから不要なゴミをクリアしているだけだと考えられます。:))

これが終わったら、この場合のデバイスパスがすでに初期化されているかどうかを確認します。初期化されていなければプールを解放し、前述の関数から返されたクリーンなバッファを返します。

この関数を終える前に、もう1つ興味深い事実を指摘しておきたいと思います。メモリ上での bootservice テーブルの見た目はこれです :) 仕様によると、先頭ヘッダもこんな感じです。将来の作業をする人がダンプの中に BOOTSERVF という文字列を見つけたときのために、ここに残しておくと面白いかもしれないと思っただけです。これは間違いなく bootservice テーブルです。

\=============================================================================

さて、次は何が起こるのでしょうか ??? winload.efi ファイルを見つけられるかどうかを確認し、メモリにロードします。これが擬似コードです :)

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/b59f211cb997e5ad783cbb6421833c23bea4ef4f7f21743577cd8aba4656ad2f.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/a96f7410f6bd6f7e207b76dff36a411f3c17a3f40dcb1a9433d5292b46f775e2.png" alt=""><figcaption></figcaption></figure>

</div>

そして、メモリ上ではこのように見えます。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/e3ee7b08fdc84433a08e60c7065c74692fb3a4e26eb81def063b662aa5229558.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/445d40332ba97516eebf129d17c56a38e28688858515d787ebf90a99580daa51.png" alt=""><figcaption></figcaption></figure>

</div>

rax とは何でしょうか? rax はイメージへのハンドルです :) 最初はメモリ領域だと思っていた私のように愚かにならないでください :)

では、さらに進む前に、winload.efi が一体何なのかを簡単に説明させてください。つまり、`コンピュータの発展に伴い、従来の BIOS ブートは時代遅れとなり、UEFI ブートに関するセキュリティ上の対立が始まりました。下のフローチャートからわかるように、UEFI には MBR や VBR はもはや存在しませんが、UEFI 自体が bootmgr のロードを担当しており、これはより安全で高速であることも意味します。`

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/d2443977ce3d56790e424fd6236d1d0594db283caa9357ed4e6abb9b8b30b8ed.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/1259e1f45b2d2bb8edcb12609e057d089f7c1dcf907677973d799049c58bee4a.png" alt=""><figcaption></figcaption></figure>

</div>

では、通常のWindows PCはどう起動するのでしょうか? BDSの後、SPIに格納されたUEFIファームウェアコードの作業が完了すると、UEFIファームウェアのブートマネージャーはまずNVRAMのUEFI変数を照会してESPを見つけ、OS固有のブートマネージャー bootmgfw.efi を見つけて、そのエントリ関数(DXEドライバー)を呼び出します。

この関数はまず EfiInitCreateInputParametersEx 関数を呼び出します。これは主に、EfiEntry パラメータを bootmgfw.efi が期待するパラメータ形式に変換するために使われます。

次に、Windows Boot Manager のエントリポイント BmMain 関数が呼び出されます。

この関数では、BmFwInitializeBootDirectoryPath が呼び出され、スタートアップアプリケーション(BootDirectory)のパス(\EFI\Microsoft\Boot)を初期化します。

その後、BootMgr はシステムのブート構成データ(BCD)を読み取ります。複数のブートオプションがある場合は、BmDisplayGetBootMenuStatus を呼び出してブートメニューを表示します。

次に、BmpLaunchBootEntry 関数を呼び出してアプリケーション(winload.efi)を起動します。

もちろん、bootmgfw.efi はそれだけでなく、ブートポリシーの検証、コード整合性、セキュアブートコンポーネントの初期化なども行うので、ここでは詳しく説明しません。

Windows Boot Manager (BootMgr) の最終段階では、BmpLaunchBootEntry 関数が以前の BCD 値に従って正しいブートエントリを選択します。フルボリューム暗号化(BitLocker)が有効な場合、システムパーティションが最初に復号化され、その後制御を winload.efi に移すことができます。

次に、BmTransferExecution 関数が呼び出され、スタートアップオプションがチェックされ、実行フローが BlImgStartBootApplication 関数に渡されます。

次に、BlImgStartBootApplication 関数は ImgFwStartBootApplication 関数を呼び出し、最終的に ImgArchStartBootApplication 関数を呼び出します。その中で winload.efi のメモリ保護モードが初期化され、BlpArchTransferTo64BitApplication 関数が呼び出されます。BlpArchTransferTo64BitApplication は Archpx64TransferTo64BitApplicationAsm 関数を呼び出し、最終的に制御を winload.efi に渡します。

この関数は新しい GDT と IDT を有効にし、完全に制御を winload.efi に渡します。この時点で、BootMgr はその使命を完了し、Winload が動作を開始します。 - これを扱っている中国のWebサイトからの引用はここまでです(詳細はこちらを参照してください https://bbs.kanxue.com/thread-268267.htm )そしてそこから、winload.efi がその役割を果たし、Windows をロードして、カーネルに制御を渡す前に、もう少しハードウェアの作業を行います。

さて、この種の簡単な説明の後、先ほど述べたように

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/65537ae888c278e8e487029f93d909fb1e4699069699cf1b7d5ad8fa1f9e0d69.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/3b00c68a215f4568fca5d672ea6f892fecf9809e671c68795c067d2660fa3f1f.png" alt=""><figcaption></figcaption></figure>

</div>

次に、メモリへのロードが成功したかどうかをさらに確認し、それから ati\_analysis\_rdtsc\_aia\_cu\_4e1f という関数を実行します。この関数は、この分析の最初の部分を既に読んでいれば、おなじみのはずです。

さて、面白い話として、その関数の分析に失敗して検出されたと仮定しましょう。sub\_180002A08 がどのように見えるか見てみましょう。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/4eb3ae379ab937e19e6a699339d992b2a5fd1fcb33202ca67355f62a5b1203b4.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/a4b252df16a31b5bf165d2a500ebe3c54ad5dad3c58cf9fe88a8a1da11ed6b63.png" alt=""><figcaption></figcaption></figure>

</div>

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/dd594955a663274e25603804c348b516ca22755886b2732ef81dc8e1e0177544.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/6fba01328584e8abb254912b81b048e8dcf80bda6d3eadc11573a52a5e84dd15.png" alt=""><figcaption></figcaption></figure>

</div>

再び gEfiSystemTable + 64 が登場しますが、今回は型が異なるため、実際には何かは分かりません。今回は bootservices 型ではなく efisystemtable 型です。その後、memcpy と、さらに 3 つの不明な関数呼び出しがあります。ここで、ループが始まるまで実行すると、

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/20e0db7308860023b613310ea14e0880529a588540d9dabac2218b52dc93cefb.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/b8f498165a4016c19d8d5797517680fc32dea241d343b38fcc613620270d58dd.png" alt=""><figcaption></figcaption></figure>

</div>

そして、memcpy の直前のパラメータを調べると、

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/21f546fbfb10a39e0e603186c8c505a3ae0679e8c7bad40f31643022f9ebfbcd.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/2ef8c97938b8f961abf92c03937ca15d5a48cd03eb58a0169891559fad27dde5.png" alt=""><figcaption></figcaption></figure>

</div>

そして、QEMU の出力イメージを調べると、次のようになります。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/e4325617bfda31fb45f7920d0d1d977103fd6b85260e590fc7cfdca1efacb787.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/04e29142b4cf543a6e5b8f55de2c27d1f3f0034707a6d19e2b1ea45b8251e899.png" alt=""><figcaption></figcaption></figure>

</div>

なるほど。では、これを整理しましょう。正直なところ私もここで混乱しているので、再び Asian の研究ブログ記事を参照します。

彼のブログによると、この 2 つの関数は実際には...```
ConOut->ClearScreen(ConOut);
ConOut->OutputString(ConOut, String);

OK、でも conOut って一体何? さらに彼は、conout は EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL 型であり、ConOut = gEfiSystemTable->ConOut; で取得されると言っている。 OK、それでコード上ではこれが何を意味するのか??

OK、それでは掘り下げてみよう。

定義

1

そして GUID

2

さて、私はこれを最初に解析したとき、efisystemtable と bootservices のデータ型を混同して、これは実際には allocatepool だと思っていたため、デバッガで実際にキャプチャするのをうっかり忘れてしまった。

さて、これらの関数は何をするのか?

ClearScreen は説明不要だろうし、OutputString も同様だ。どうして研究者はその変数が EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL 型だと結論づけられたのか? おそらくデバッガで GUID のバイトを見たからだろう。

では、最後の関数はどうだろう?

彼のブログ記事では、最後の関数は gEfiBootServices->Stall だと言っている? それでこれは一体何をするのか? UEFI 仕様によると The Stall() function stalls execution on the processor for at least the requested number of microseconds. Execution of the processor is not yielded for the duration of the stall.

つまり基本的に CPU をフリーズさせる。どれくらいの間? 0x1C9C380 秒。聞かれれば、とんでもなく長い時間だ。そしてこれもまた無限ループの中に置かれているので、もうおしまいだ :)))

そして、デバッガではこんなふうに表示される。

1

さて、メイン関数の続きに戻ろう。

1

bootmgfrw.efi(ここでは実際の Windows ブートローダーである winload.efi)の読み込みに成功したら、sub_180002538 を呼び出す。

============================================================================= sub_180002538

グラフの視点から

1

アセンブリの視点から

2
3
4
5
6

何か心当たりはある? いや、まあ少し待てば分かるはずだ。その間に擬似コードの視点を見てみよう。

1
2

EXE のパース処理が見える :) 前のパート(part1)とどれだけ同じかは分からないけど、見てみよう :)

では、メモリ上のバイナリ(bootmgfrw.efi)を古典的な MZ ヘッダ(0x5A4D)と比較している。次のとおりだ。

1
1

OK、次はもう一つの定番チェックとして、PE ヘッダが見つかるかどうかを確認している。

1

いいね。次に sub_1800024C4() を呼び出す。これはこんな感じだ。

1
2

いいね。ここで起きているのは、メモリ内の特定の値を探し、見つかったらそれらを返すということだ。エミュレーションについては sub_180002538.py.py を参照してほしい。

とにかく、ここに sub_180002464 がある。

1

sub_1800024C4 の実行に成功したら、より大きな関数に戻り、さらにいくつかのチェックを実行する。いいね、これらを整理してみよう。

1

OK、さらに rax+0xe にある値を 0x64 と比較している。ふむ、面白い。rax+0xe を調べてみよう。

1

この特定のチェックに特別な理由はあるのか? 正直、分からない。もしかしたらあるのかもしれない。もし知っているなら、プルリクエストを送ってこの文書を編集してほしい。

さらにいくつか加算を行い、それから比較をしている。

1

ここで少し立ち止まって、この記事で迷ったときにいつも参照していた元ネタをもう一度参照したい。彼のブログでは、値を比較する関数を RtlpImageDirectoryEntryToDataEx と改名していた。検索しても結果は得られないが、彼の命名に十分近いものとして RtlImageDirectoryEntryToData がある。これは基本的に次のことを行う。Given the base address of a kernel module and the index of an entry in the data directory, RtlImageDirectoryEntryToData() returns the virtual address and the size of the directory entry(https://codemachine.com/articles/top\_ten\_kernel\_apis.html) 今回の場合、我々は EFI/UEFI アプリ上にいるので、ここで見える 50 はルートパーティションのサイズ(バイトか MB かは分からない)であり、rax にあるそのアドレスはディレクトリ内のエントリだと考えることができる。

先に進む前に、もう一つ説明すべき興味深い詳細がある。彼の研究では、RtlImageDirectoryEntryToData の出力を次の構造体に変換している。``` typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY { union { struct { DWORD NameOffset : 31; DWORD NameIsString : 1; }; DWORD Name; WORD Id; }; union { DWORD OffsetToData; struct { DWORD OffsetToDirectory : 31; DWORD DataIsDirectory : 1; }; }; } IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;

root@kitploit:~
さて、この構造は一体何だ?

まあ、その構造について少し検索すると、ここ(http://www.brokenthorn.com/Resources/OSDevPE.html)にたどり着く。そこにはこう書かれている: `Parsing resources is a bit more complex then the other directory types, however. Like the other sections, there is a base IMAGE_RESOURCE_DIRECTORY structure that can be obtained from the DataDirectory member of the optional header: blah blah` そしてさらにこうもある。 ```This structure doesnt have much of any interesting fields, except the last three.

If you have worked with Win32 resources, you might know that resources can be idenitified by ID or name. Two of the members in this structure will let us know the number of these entries, and the total amount of entries (NumberOfNamedEntries + NumberOfIdEntries), which is useful in looping through all of the entries. As you can probably guess, the entries are in the DirectoryEntries array. DirectoryEntries consists of an array of IMAGE\_RESOURCE\_DIRECTORY\_ENTRY structures, which follow the format:```

つまり、基本的にこれは内部でいろいろと解析するために使われるもので、私たちがリソースを持つディレクトリを扱っているという文脈なら意味が通じる。いいね。

もっと見せて!

で、次は

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/137d3d2aebf0db9501f550b09baddf01c3e50bf703ca8d13386a7185a567f19a.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/045c3a8a2bab306f516cdc7e9a59954e3c1ff16efe4189273c50f54b9e84f3e6.png" alt=""><figcaption></figcaption></figure>

</div>

これがやってるのは、基本的にディレクトリ内のすべてのリソースを反復処理して、文字列型かどうかをチェックするってことだ。

正直、なぜ彼がそんなことをするのか分からない。間違ってたらごめん、間違ってなかったら万歳!

次

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/a57c5815ee8b5498fed6d8dde92f48b9fc2bdfd2d4f4e231796ba96e5e28bea9.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/bd4513fdf1f8f165fc404b8462d6bc36644de4937e42d560d54f1a5f1c0e8799.png" alt=""><figcaption></figcaption></figure>

</div>

で、ここで何が起きているかというと、いくつかのオフセットを加算して、中国人研究者が言うところの「2番目のリソーステーブル」にたどり着く。見ての通りだ。

それから同じ処理を繰り返して、いくつかのオフセットを取得する。

そして同じ処理を繰り返す。今回は型が VS\_VERSION\_INFO かどうかをチェックする。

で、VS\_VERSION\_INFO って一体何だ? まあ、マイクロソフト(https://learn.microsoft.com/en-us/windows/win32/menurc/versioninfo-resource)は「`Defines a version-information resource`」と言っている。つまり、おそらく bootmgfrw.ef のバージョンを示しているだけだと思う。

そして最後に、VS\_VERSION\_INFO が見つかったら、同じアルゴリズムを繰り返す。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/4f00ecf2c2c9b32b2d25fcbf3c62e9bb45679df1390a085371f5166a70d67933.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/facd25069491b5d7826500e4f2c04cafe213191075012ddb4c1fa9a8bc97c4c5.png" alt=""><figcaption></figcaption></figure>

</div>

今回はひねりがあって、そのひねりとはビルドIDを返すということだ :) 見ての通りね。

では結論として、ここでは実際に何が起きたのか? 中国人研究者が使った名前(GetPeFileVersionInfo\_BuildNumber\_)から判断すると、実際にはブートローダーのビルド番号を取得していると結論づけられる。最初の画像からもわかるように。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/b28007dda110fc31d53233931ff077ac42fc81146d803b91999069e204020a4d.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/d19f1311c2ee242ced63da8334db384929ada3acae147009becc0dbf34d2b7fb.png" alt=""><figcaption></figcaption></figure>

</div>

ここでは、ロードされたブートローダーがメモリ内にあるのが見える。

2枚目の画像では、これが見える。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/2000f17c51ccc65267b46ac2c1d191bd033b3bc6e6b655973423dbbd8a1fc77e.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/7c47fe45fe4b422618a400f2c26c28cd33fea9416f2b24086a2c852d08f1614b.png" alt=""><figcaption></figcaption></figure>

</div>

rcx に入っている整数値。これはビルド番号か PE ファイルバージョンのどちらかだろう。

そして3枚目の画像。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/41729b1d4a4701480d64f058f421cd2ad8a8b9b871bf17675fd7b537cec3dd85.png" alt="3">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/d2b17725eeb9af2336d725be9c556565fba221fd2a3517912c942f411f9ed33b.png" alt=""><figcaption></figcaption></figure>

</div>

ebx が rax に移されるので、ビルド番号だろうと推測できる :)

この関数について最後に一言。すごいエンジニアリングだ。

=============================================================================

さあ、次のチャレンジだ :) 前のステージの出力に基づいて、v10 に sub\_180001D80 か sub\_180001D48 をセットする。見ての通り。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/33581031e03f29b5997d46b708c467bfd49ce58625e99381dd28c109cadae7d3.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/6647119081cffb664dcca365392271398b2572ee04c24a0456141f33cbaaeecf.png" alt=""><figcaption></figcaption></figure>

</div>

そして今回の場合、v10=sub\_180001D80 だ。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/2af043a1449f6bf10e2925f06697438716976d24a1539a61ab42c4301c4a8435.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/0769d4dff6e1da51acaf9c5bac3a9a9b4b446aae9d7c593e7e54d865ec13c2ea.png" alt=""><figcaption></figcaption></figure>

</div>

=============================================================================

それから、ブートローダーマネージャーとあのバイト配列の間で strcmp を行う。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/59164794afc69304133f0a4c008b9e4755671e8d57bd8dc4ea5a2b2e6ae54164.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/03b00f7c18ff7db73dfd5253f02d6966955e38732fa7d1cfb4840366c17355a1.png" alt=""><figcaption></figcaption></figure>

</div>

ちょっとだけここで止まりたいんだが、察しの通り、中国人研究者のブログ記事で面白いものを見つけたんだ。彼はそのバイト配列を SigImgArchStartBootApplication と呼んでいた。で、SigImgArchStartBootApplication は一体何なのか、誰のものなのか、そしてなぜそんな名前が付けられているのか(migos)。google(gulugulu)で SigImgArchStartBootApplication を検索しても、何も出てこない。今の状況ではWindowsのブートローダーマネージャーを使っているので、IDAで開いてみよう。C:\Windows\Boot\EFI に行き、IDAでバイナリを開いて SigImgArchStartBootApplication を検索しても何もない。ImgArchStartBootApplication を検索すると、これが出てくる。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/1ad42d5236e8ca4da08688fe3d4c72e6b3de01fdce633a1bdaa870de421cdc40.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/d6e211aa12b37dfba0244d48516a08703248484c070f8d7ffcf0a28f08e8a833.png" alt=""><figcaption></figcaption></figure>

</div>

で、ImgArchStartBootApplication .... これは一体何してるんだ!? まあ、えっと...これは `@_xeroxz` からパクるよ(彼のフォローをしてないなら何やってんだ、彼の作品をフォローしろよ....)。基本的に彼の記事によると、`bootmgfw.ImgArchStartBootApplication between windows versions 2004-1709 is invoked to start winload.efi` らしい。彼の画像(https://guidedhacking.com/threads/hyper-v-hacking-framework-works-on-every-version-of-windows-10-2004-1511-amd-intel.16251/)からもわかる。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/4967559cb05e49785841a2dc216e13fc0b94fe8be8f17d9bceaf1914722156ff.jpg" alt="1603213912596">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/4967559cb05e49785841a2dc216e13fc0b94fe8be8f17d9bceaf1914722156ff.jpg" alt=""><figcaption></figcaption></figure>

</div>

それでも不明確なら、ある記事()にはこうある。`ImgArchStartBootApplication to catch the moment when the Windows OS loader (winload.efi) is loaded in the memory but still has not been executed`(https://rustrepo.com/repo/rusty-bootkit--uefi-bootkit-in-rust)

いいね。で、strcmp は ImgArchStartBootApplication と何の関係があるんだ? まあ、IDAをもっと詳しく見てみよう。すぐに答えが明らかになる。ブートローダーのコードでバイト列 41 b8 09 を検索すると、すぐに犯人に出会う。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/91050c01f95eb88488cbc575c21af7f453228eeb13c665b94d415eecf5682a55.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/7239d85f2dc9e220a2eab80f79b5db9705285a17c074f85958c041d122bfaf8e.png" alt=""><figcaption></figcaption></figure>

</div>

そして、メモリ内のブートローダーのイメージバイトがバイト列のシグネチャと一致した場合、sub\_180002398 を実行する。

そして、見ての通り、パターンを見つけて、eax でバイト列があるメモリゾーンを返し、安全に sub\_180002398 の実行に進む。

=============================================================================

sub\_180002398

"アセンブリの視点"

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/5aa624d92161499019e7ce6597bf46853c59ba89d37fec483a8ac7ee168ddbeb.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/afbf940a1eb535d73dce744606cc63c568c2b447c9cf85034c422a8e900859f4.png" alt=""><figcaption></figcaption></figure>

</div>

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/6468513a220946bbccfab53328c056a620755e1fe94ad3e36d8c8958ed777794.png" alt=""><figcaption></figcaption></figure>

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/c5c36e7c29f1cdea6f42d55d7605ad3c2044d66397c867c221da6c0bf74f8d6a.png" alt=""><figcaption></figcaption></figure>

"擬似コードの視点"

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/5b1d8a264dad55f34a0cc958a2f4a26014a31987af5b66754e754589ea085097.png" alt="3">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/1d3db7165e0f71a3fa76862ba8afb3869f821f59db6fc5a5c5e99d5002ecfba1.png" alt=""><figcaption></figcaption></figure>

</div>

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/ae65504884fa2881cb50af2f88e846a0ad029c9431ee6296b28993de8f2e4a0d.png" alt=""><figcaption></figcaption></figure>

で、これは何をしているのか? 正直に言うと、いくつかの計算と加算・減算をしているだけで、大したことはしていない。なぜなら、あまり面白くないからだ。私たちが興味があるのは、関数から戻った後に何が起こるかだ。rax を見てみよう。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/4eae862955421b2b1629c120bb09970714cf085e9255590d6cfa36a77bbc69e9.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/43917bf46096449ad92172baa282fd3e70ec0bec67fec2bbf2a276285d878b52.png" alt=""><figcaption></figcaption></figure>

</div>

よし、いいね。でもまだ理解できない。まあ、rax = 0x5eec108 で、それは 0x48c48b48 を指している。で、それがどうした? 正直、私も君と同じくらい困惑したので、もう一度中国人のブログに戻ったんだ。その研究者が説明しているのは、こういうことだ:ImgArchStartBootApplication 関数の先頭に戻る。しかし、彼はどうやってこれを思いついたんだ? まあ、前述の通り、rax =\
0x48c48b48 で、booloadermnfr.efi を調べると、これが見える。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/2dbe283fa0b0dd9cf837e79f1f42eaeb6dcd61252e76979c0a4af3cf2f68e8d8.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/624e1927cac5a0011d6fabea0f2ce4740b8dfd14102509656d6e5c0395a9c08d.png" alt=""><figcaption></figcaption></figure>

</div>

これは 0x5eec108 にあるバイト列とまったく同じだ。よし、今のはかっこいい :)

この動作をエミュレートしようとした私の失敗作は、sub\_180002398.py を参照してほしい :)

=============================================================================

いいね、次は?

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/432ad1832fa35743bc5676f7f8362ad9e2043e17387121136a1f6dfe1bdf16f1.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/aab798c5c80621b1c367ea6eecfff0d7caf9ecc368ae2fe2e947538e4f0e2b0c.png" alt=""><figcaption></figcaption></figure>

</div>

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/f04ebd9c650ddadb5553e4f2c43c72af8a5ccbef372a4dbdc811600e9583b0c9.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/3411e1620450739ea98f6db634346748487377106547324591b148cefe358df2.png" alt=""><figcaption></figcaption></figure>

</div>

次に起こるのは RaiseTPL だ。で、これは何をするのか? 現在実行中のタスクの優先度を上げて、以前の優先度レベルを返す。私たちの場合、最高の実行特権で実行されることになる。

次に、私が patch\_something と呼んでいるものを呼び出す。こんな感じだ。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/0a31b0c154406b340e9bb044c4211afd6494bcac6ec197c99a10a6d0effb6a31.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/3fcff1b34a5d9af3cdd70e4dac1188abd3edd13e74d11e4f0bba5d667d4f53a1.png" alt=""><figcaption></figcaption></figure>

</div>

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/c2f9bb8ca36961def04d4a3111a7d4213bb219949d13094b525a1a906ab788f7.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/accdd93e3428b9b03132eafceda3ec5e1cfda742a978f1cd7f2c6bcf1904ceaa.png" alt=""><figcaption></figcaption></figure>

</div>

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/e0f6c806d296e47269b9908ceab7b90954bbd219d3d9c13462ebee8344f854f3.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/1ed164077989d04273ae3b40ec6daf7cf9b93ec42d917533b1e9758525231b7b.png" alt=""><figcaption></figcaption></figure>

</div>

静的分析から、これはいわゆるフッキングだとわかる。 :) 基本的に、ImgArchStartBootApplication のバイトを書き換えて sub\_180001D80 を指すようにし、ImgArchStartBootApplication の元の関数を byte\_180015C78 に保存する。

見ての通り、正確に sub\_180001D80 に変更されている。

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/6c48bf4c9126a9a1466493aed943113cc27b4bbf9f7d68cdd251d0e14303ad8a.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/633d84a62c16dba91229fe6bb73ed0318719fc06f63f7f2a9d19adba0d0e8cfe.png" alt=""><figcaption></figcaption></figure>

</div>

次に特権をリセットし、そこから制御を boomgrfw.efi に渡す :)

というわけで、これで正式に分析の前半が完了だ :) 次のパートでは、sub\_180001D80 と boomgrfw.efi(今回の場合は winload.efi)のさらなるデバッグ方法を学ぶ。だから、第二部の分析のための環境の準備方法を学ぶまで、じっと待っていてほしい。

=============================================================================

さあ、分析の後半だ.... boomgrfw.efi をどうデバッグすればいいのか?
ツールをダウンロード