1/10 Close Analysis of an Unusual HawkEye Sample govcert.ch/blog/analysis-of-an-unusual-hawkeye-sample/ GovCERT.ch Homepage GovCERT.ch Blog Blog Posts Recently published blog posts: 12.12.2021Zero-Day Exploit Targeting Popular Java Library Log4j 09.03.2021Exchange Vulnerability 2021 27.10.2020Cyber Security for the Healthcare Sector During Covid19 Blog Archive 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. https://www.govcert.ch/blog/analysis-of-an-unusual-hawkeye-sample/ https://www.govcert.ch/ https://www.govcert.ch/ https://www.govcert.ch/blog/ https://www.govcert.ch/blog/ https://www.govcert.ch/blog/zero-day-exploit-targeting-popular-java-library-log4j/ https://www.govcert.ch/blog/exchange-vulnerability-2021/ https://www.govcert.ch/blog/cyber-security-for-the-healthcare-sector-during-covid19/ https://www.govcert.ch/blog/ https://www.govcert.ch/blog/rss.xml 2/10 Close Close Whitepapers Whitepapers Recently published whitepapers: 23.09.2019Trickbot - An analysis of data collected from the botnet 03.03.2017Scripting IDA Debugger to Deobfuscate Nymaim 23.05.2016Technical Report about the Malware used in the Cyberespionage against RUAG Whitepapers RSS feed Subscribe to the whitepapers RSS feed to stay up to date and get notified about new whitepapers. Report an Incident 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) Alternative GovCERT.ch PGP Key (for older versions of PGP without Curve25519 support) GovCERT.ch SMIME https://www.govcert.ch/whitepapers/ https://www.govcert.ch/whitepapers/trickbot-an-analysis-of-data-collected-from-the-botnet/ https://www.govcert.ch/whitepapers/scripting-ida-debugger-to-deobfuscate-nymaim/ https://www.govcert.ch/whitepapers/apt-case-ruag-technical-report-govcert-ch/ https://www.govcert.ch/whitepapers/rss.xml https://www.govcert.ch/report/ https://www.govcert.ch/report/ https://www.govcert.ch/report/ https://www.govcert.ch/report/ https://www.govcert.ch/downloads/govcert.pgp https://www.govcert.ch/downloads/govcert_alternative.pgp https://www.govcert.ch/downloads/govcert_2021.crt 3/10 Statistics https://www.govcert.ch/statistics/ 4/10 Close Breadcrumbs Introduction Currently, we are observing HawkEye samples being distributed by large malspam waves. HawkEye 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 . Recently we observed an interesting obfuscation method in a HawkEye binary , 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 . Looking through the decompiled source code in dnSpy we find the method gate in the class Sinister . The Base32 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 . This value is a concatenated string consisting of the following nine static strings. 1 2 3 4 5 6 7 https://www.govcert.ch/blog/analysis-of-an-unusual-hawkeye-sample/assets/01_base32_dll.png 5/10 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 correct string. Update: According to our colleagues at FedPol/BKP the string is actually Urdu. Thanks for the hint, most appreciated. https://dotnetfiddle.net/ 6/10 ) 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. https://www.govcert.ch/blog/analysis-of-an-unusual-hawkeye-sample/assets/03_dotnet_fiddle.png 7/10 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. https://www.govcert.ch/blog/analysis-of-an-unusual-hawkeye-sample/assets/04_image_loop.png https://www.govcert.ch/blog/analysis-of-an-unusual-hawkeye-sample/assets/05_encrypted_image.png 8/10 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. https://www.govcert.ch/blog/analysis-of-an-unusual-hawkeye-sample/assets/06_array_decrypt.png 9/10 #!/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 . 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. 8 10/10 The detection rate of VirusTotal shows, that the “smuggling” technique is actually working. The initial malicious file is detected by only 17 AV engines (two weeks after the first upload). The decrypted PE file was detected by 34 engines right after upload. 4 9