Recently, TechHelpList uploaded a Hancitor Word document to VirusBay, along with an overview of the sites it reached out to, the C2 servers, and the payloads that were dropped by said document. As it seems Hancitor is quite popular for downloading the Pony and ZeusPanda malware (what is it with animals and malware?), I decided to examine the file to figure out the program flow and capabilities.
MD5 of Document: 00955c1db30ddc172086a061ab158f00
Upon opening the malicious document, we are met with an image stating that we have a new fax message, and that we can only view the message if we click Enable Editing and Enable Content. Interestingly enough, upon clicking said buttons, we still can’t view the fax message. Well I didn’t even want to view it anyway. A few seconds after we have activated the macros, Word exits suddenly, leaving the impression that Word has crashed. As you can probably guess, Word didn’t crash and is in fact a ploy used by the malware to remain undetected whilst it extracts a packaged executable and replaces the malicious document with a clean version, to prevent several instances of Hancitor running.
Taking a look at the macros, you’ll notice the default Document_Open() subroutine which executes first – but there is also a Document_Close() subroutine that executes when the program is closed, which calls the subroutine closee(). Before we get to that, let’s have a look at the Open routine.
So from just looking at it, Document_Open() is responsible for calling 3 other macro subroutines; kfs(), sdfsdf() and Module1.killo(). So let’s see what each function does.
Looking at the macro, it seems like kfs() is junk code, as it is simply moving the page down by 14, moving it right by 24, uses the backspace once and then copying something, which doesn’t cause much of an affect.
After a while of scouring through macros and the document, I noticed something. When we take a closer look at the malicious document, you can see a very small, but noticeable yellow dot.
We can click on this and actually make it larger, resulting in this image:
This icon will all make sense when we look at the next subroutine, sdfsdf(). At the start of this sub, the macro changes directory to the %TEMP% directory. From there, a Scripting.FileSystemObject is created, and used to copy the contents of 5C.pif to UserForm2.TextBox1.Text, and 6.pif. It then returns. It seems like sdfsdf() is responsible for extracting the malicious, due to the fact that upon interacting with the .pif icon inside the document, a shortcut file is created inside the %TEMP% folder, even if you haven’t clicked enable macro’s. This vanishes upon closing the document, so it seems to be a temporary file created by the document, hence why sdfsdf() copies the contents to another file, rather than executing 5C.pif – although I don’t know much about Packaged Shell Objects in Word, so I could be wrong. Furthermore, copying the data to UserForm2.TextBox1.Text from 5C.pif results in creating 6.exe, inside the %TEMP% directory – 6.exe and 6.pif are the exact same files, just different file extensions.
This got me thinking – if a .PIF is embedded inside the document, how can we extract it properly? How can we find where this file is? Then I remembered a little tool called hexedit and CFF Explorer. I executed hexedit on my host machine to see if I could locate the embedded file via examining the hex code. As .PIF files are executed the same way as an executable file, I searched for “MZ“, even though legitimate .PIF files apparently do not contain the magic number. Sure enough, I was able to locate the embedded file, just underneath an interesting file path, possibly from the attackers machine:
So now we have located the file, which can be confirmed as an executable file, we can extract it using CFF Explorer, or another hex viewer/dumping tool.
Simply finding the MZ header and right click, choosing Begin Of Block, and then travelling to the very end of the executable (after the file information) and right click, choosing End Of Block. From there, right click again and choose Copy -> Into New File. An error with this method is you may end up with a different file hash as you copied 1 more 00 than the original file, but this doesn’t seem to affect the overall execution of the program.
Now that we have extracted the executable for further analysis, let’s get back to the macros and check out the final sub, Module1.killo(). Simply put, killo() is responsible for saving the clean version of the Word document – without the macro’s. To do this it saves it in an XML document format, thus removing all macros in the file. Finally, killo() kills the application, causing the appearance of a crash. It may seem like the macros have finished executing and nothing really happened, in which case you have forgotten about Document_Close() and closee().
So as mentioned before, the Document_Close() executes closee(), and then the program finally exits, therefore the main function to focus on is closee(). First off, the macro is utilizing a WMI query to view the list of current running processes:
SELECT * FROM Win32_Process
From there, a for loop is executed which iterates over each process in the list, denoted as x. For each process, the process name is compared to both bdagent.exe and PSUAMain.exe. These may sound like malicious files downloaded by the malware, to prevent several instances running, however when we run a quick Google search, it turns out bdagent.exe is linked to BitDefender, and PSUAMain.exe is linked to Panda Security. So it seems the malware is checking for only two AV programs and running a different execution method for each. If bdagent.exe is running, the macro creates %TEMP%\1.hta and stores the handle in #1. When you see Print #1, the macro is in fact writing to 1.hta, rather than displaying strings. From there, the macro is Base64 decoding an encoded string (using DecodeBase64()), converting it to a unicode string, and then writing it to 1.hta. This occurs twice, and then the file is closed. Finally, a WScript.Shell object is used to move into the %TEMP% directory and execute 1.hta silently, to which the macro exits.
Anyway, moving back to the macro, if a process name matches PSUAMain.exe, another 2 strings are decoded and used to form a shell command, executed by the Shell at the start of the line. Once decoded, we get this command:
cmd.exe /c ping localhost -n 100 && %TEMP%\6.exe
The ping command seems to be used to delay the execution of 6.exe, which is executed after ping exits. After executing cmd.exe, the macro exits as well.
Finally, if no process names matched bdagent.exe or PSUAMain.exe, the for loop ends, and then a Shell command is executed, made up of 3 base64 encoded strings. Upon decoding, we get this:
cmd.exe /c ping localhost -n 100 && %TEMP%\6.pif
So, if no matches are found, 6.pif is executed, instead of 6.exe or 1.hta. I am not sure exactly why this is the case, I’m sure there is some reasoning behind it, but I have yet to find any. Once the final payload is executed, the final macro ends, leaving only 6.exe or 6.pif running – bringing this part of the analysis to an end. Unlike the other posts I have done on Downloaders or Droppers, I have actually analyzed the dropped file in this case, and just need to write up part 2, so expect that soon!
Enjoy my blog posts and wish to support me? Feel free to fund my caffeine addiction!
Stay updated on new course releases and related InfoSec content