# Analysis of an Unusual HawkEye Sample **govcert.ch/blog/analysis-of-an-unusual-hawkeye-sample/** ## GovCERT.ch [Homepage](https://www.govcert.ch/) [GovCERT.ch](https://www.govcert.ch/blog/) Blog ### Blog Posts Recently published blog posts: [12.12.2021Zero-Day Exploit Targeting Popular Java Library Log4j](https://www.govcert.ch/blog/zero-day-exploit-targeting-popular-java-library-log4j/) [09.03.2021Exchange Vulnerability 2021](https://www.govcert.ch/blog/exchange-vulnerability-2021/) [27.10.2020Cyber Security for the Healthcare Sector During Covid19](https://www.govcert.ch/blog/cyber-security-for-the-healthcare-sector-during-covid19/) ### Blog Archive Close Go to the blog archive and browse all previous blog posts we have published so far. ### RSS Feed Subscribe to the GovCERT.ch blog RSS feed to stay up to date and get notified about new blog posts. ----- Whitepapers ### Whitepapers Recently published whitepapers: [23.09.2019Trickbot - An analysis of data collected from the botnet](https://www.govcert.ch/whitepapers/trickbot-an-analysis-of-data-collected-from-the-botnet/) [03.03.2017Scripting IDA Debugger to Deobfuscate Nymaim](https://www.govcert.ch/whitepapers/scripting-ida-debugger-to-deobfuscate-nymaim/) 23.05.2016Technical Report about the Malware used in the Cyberespionage against RUAG ### Whitepapers RSS feed Close Subscribe to the whitepapers RSS feed to stay up to date and get notified about new whitepapers. [Report an Incident](https://www.govcert.ch/report/) Close ### Report an incident to NCSC Report an incident: incidents[at]govcert{dot}ch General inquiries: outreach[at]govcert{dot}ch ### Point of contact for CERTs and CSIRTs The following email address can be considered as point of contact for FIRST members and other CERTs/CSIRTs: incidents[at]govcert{dot}ch ### Encrypted Email GovCERT.ch [PGP-Key (preferred)](https://www.govcert.ch/downloads/govcert.pgp) Alternative GovCERT.ch PGP Key (for older versions of PGP without Curve25519 support) [GovCERT.ch SMIME](https://www.govcert.ch/downloads/govcert_2021.crt) ----- [Statistics](https://www.govcert.ch/statistics/) ----- Close ## Breadcrumbs Introduction Currently, we are observing HawkEye samples being distributed by large malspam waves. HawkEye1 is a keylogger which has been around quite a long time (since 2013) and has evolved since then and gained more functionality. There are several good blog posts about HawkEye in general 2 3 . Recently we observed an interesting obfuscation method in a HawkEye binary 4, which we are going to describe in this blog post. ## Extracting Base32 encoded DLL HawkEye is written in .NET and thus we can analyze it rather easily with the help of dnSpy .5 Looking through the decompiled source code in dnSpy we find the method ``` gate in the class Sinister . ``` The Base326 encoded strings are concatenated, then reversed and decoded. The output of the decoded string is a DLL written in .NET as well. We can easily decode the string using `rev and` `base32 on a Linux system or with the help` of similar tools. After decoding, the DLL is loaded and the property `iraq is set via reflection 7.` This value is a concatenated string consisting of the following nine static strings. ----- _Side note: The concatenated string used here is encoded with non-latin letters_ _(maybe Farsi, any feedback most welcome). Trying to concatenate the strings in_ _[a text editor did not really work, however, using dotnetfiddle.net revealed the](https://dotnetfiddle.net/)_ _correct string._ _Update: According to our colleagues at FedPol/BKP the string is_ _actually Urdu. Thanks for the hint, most appreciated._ ----- ) ## Extracting EXE file from embedded PNG After opening the DLL in `dnspy, we can examine the` `set_iraq method. The` only thing this method does is to pass the argument to the method ``` ArgueMents.e1 . ``` The method `e1 loads and starts another executable file (lines 34–36). In order` to analyze this executable, we need to know how it is loaded into the ``` rawAssembly array and how we can extract it. ``` ----- Line 30 instantiates a `Bitmap object with the value that was passed to the` ``` set_iraq method. Looking at the code of the method i10 we see, that the ``` image is loaded from the `ResourceManager of the main binary. The bitmap is a` PNG file, located in the resource section of the main executable. Next, the `Bitmap is passed to the method` `e5 . This method reads the width` and the height of the PNG. It then loops over the height (inner loop) and the width (outer loop) and stores the red, green and blue value of every pixel into a array and returns it. The alpha values as well as all pixels that are `r,g,b,a =` ``` (0,0,0,0) are omitted. ``` ----- The resulting array is then passed to the decryption method `e9 .` In this method, a new array is created which is 16 bytes smaller than the array containing the color values. Then, the image array is copied to the new array (the first 16 bytes are omitted). The first 16 bytes are in fact the key needed to decrypt the rest of the data using `XOR . There is a` `for loop, which will iterate` over every value in the smaller array and XORs the value with the corresponding value of the key. The decoded data is a PE file (exe), which is loaded into the memory. Finally the ``` EntryPoint of the File is called. ``` As the key is stored in the Image itself, we can write a small python script to decrypt this and similar images. ----- ``` #!/usr/bin/python3 from PIL import Image import argparse KEY_LENGTH = 16 def get_color_values(file_name): arr = bytearray() im = Image.open(file_name) w, h = im.size for i in range(w): for j in range(h): r, g, b, t = im.getpixel((i, j)) # ignore zero values if (r, g, b, t) != (0, 0, 0, 0): arr.extend([r, g, b]) return arr def process(input_file, output_file): arr = get_color_values(input_file) key = arr[:KEY_LENGTH] data = arr[KEY_LENGTH:] for i in range(len(data)): data[i] ^= key[i % KEY_LENGTH] with open(output_file, "wb") as o: o.write(data) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("input_file") parser.add_argument("output_file") args = parser.parse_args() process(args.input_file, args.output_file) ``` In this case, the resulting PE file is once again heavily obfuscated, the first stage is obfuscated with Babel Obfuscator .8 The final payload after several obfuscation rounds is HawkEye. ## Conclusion The obfuscation technique using a PNG file to store a PE file is neither new, nor very advanced. However we found it to be noteworthy nevertheless as we do not see it often. It could be an interesting way to bypass anti virus products, because the PE file is loaded directly into the memory, however in this case, the resulting HawkEye binary stores a copy of itself on the disk after the infection and therefore may be detected by AV products. ----- The detection rate of VirusTotal shows, that the smuggling technique is actually working. The initial malicious file 4 is detected by only 17 AV engines (two weeks after the first upload). The decrypted PE file9 was detected by 34 engines right after upload. -----