Skip to main content
Lazarus Using Leaked Hacking Team Tooling

Lazarus Using Leaked Hacking Team Tooling

Lazarus Malware RE CTI North Korea

Why make malware when Hacking Team can do it for you - Lazarus (probably)


About a week ago, I made this absolute banger of a tweet to tease this blog post.

On 12/09/2022, the following crypto themed CHM file was submitted to VirusTotal by a South Korean user. This got me all excited because it SCREAMS Lazarus. ZScaler did a lovely writeup1 on a very similar campaign in April.

Fig 1: VirusTotal submission

Technical Analysis

Stage 1: Dropper

We start off with a Compiled HTML Help (CHM) file, which is essentially a way of showing HTML natively on the desktop. Since CHM files are just archives, they can be decompiled(?) using 7-Zip allowing us to view the bundled content. If the victim opens wallet.chm they will see the following article about Bitcoin ( translated):

Fig 2: Opened CHM File

After extracting the bundled content we can see a number of files, the most important being: page_1.html and the src directory.


The content displayed in Fig: 1 is actually just a rendered version of page_1.html, and like any other HTML file, it can execute JavaScript. At the end of page_1.html we find some packed JS:

Fig 4: Packed JavaScript in CHM file

This specific JS packer has been noted in a number of NK attributed samples, and is trivial to unpack. Instead of returning the decoded function you can simply print the unpacked result.

Fig 5: Unpacking JS using the console

And after beautifying:

Fig 6: Beautified unpacked JS

The function jmpof09fds() gets the location of the CHM file on disk to prepare for writing the next stage. The variable jdeDc05a is just a URL encoded script which after being decoded is a shortcut for decompiling wallet.chm to expose hkcmds.exe to disk:

Fig 7: Beautified payload

Following the JS pictured in Fig: 4, there is some more code to execute the file hkcmds.exe that was included in the bundle.

Fig 8: Other shortcut created

At this point, we’re done with the CHM file as all the prep work for stage two has been completed. We can now move onto analyzing hkcmds.exe.

Stage 2: hkcmds.exe

Throwing the binary into DetectItEasy shows it is a C/C++ binary with no packing (🥵). No extra steps necessary and we can continue on to our analysis in IDA.

Fig 9: DIE output for hkcmds.exe

IDA helpfully identifies WinMain for us, so we start there. The first thing that jumps out is a number of obfuscated strings that are being fed into sub_4018A0().

Fig 10: WinMain decompilation

Examining the rest of the strings in the binary, we notice that there are tons of similarly obufscated strings. Just like the ones we saw above, they are all referenced by sub_4018A0. During a quick debug, we can see that sub_4018A0, miraculously returns a normal WinAPI function call! Interestingly, there are a lot similarities among the lines which means that it is probably some simple debofuscation happening.


For kicks, I threw a few of the strings into Google and was met with this… and all the mappings of obfuscated function calls. thanks bestie!! 🥰 Making use of Hacking Team implants like a good APT should.

Fig 11: obfuscated_calls.h

This was a great find as the repo contains source for the binary we were about to reverse! In terms of the function obfucsation, it ends up just shifting all the characters by -1. It would be a fair assumption to make that the binary we are reversing is just the RCS (remote control system) in this repo but there are some inconsistencies.

To make the process a little easier, I wrote a quick deobfuscation script to fix up the function calls in IDA.

import idc
import idautils
import idaapi

def deobfuscate(obfuscated) -> str:
    return "".join([chr(ord(i)-1) for i in str(obfuscated)])

def iterate_strings(start_addr, end_addr):
    for i in idautils.Strings():
        # Check if the string is within the specified range
        if i.ea >= start_addr and i.ea + i.length <= end_addr:
            # Get the string content
            print(f"String at {hex(i.ea)}: {deobfuscate(i)}")
            idaapi.patch_bytes(i.ea, bytes(deobfuscate(i), 'utf-8'))

def main():
    start_addr = 0x00411A68 # Start address of obfuscation strings
    end_addr = 0x0041322E   # End address of obfuscation strings

    iterate_strings(start_addr, end_addr)


In terms of similarities, the function sub_401260 which is passed to the new thread in WinMain bears resemblence to PollClipBoard in HM_ClipBoard.h. Accounting for some structural weirdness in the decompilation, these two share a very similar strcuture. With a large loop that GetsClipboardData and then batches it to send off.

Fig 12: Clipboard capture decompilation

Fig 13: Source for PollClipBoard

WinMain doesn’t have any comparable code in the Hacking Team repo, so my assumption is that hkcmds.exe is some modified or newer version. There are also some obvious mismatches like no entry for CreateThread in obfuscated_calls.h but uses of it in hkcmds.exe. I’m going to continue analysis on this sample further, but it is interesting to see the use of Hacking Team tools by possible nation state actors.


The case for attributing this malware to Lazarus or some other North Korean actor is fairly strong. Taking into consideration the locality of the submitter, the content of the document, the use of a CHM file for delivery, utilizing leaked tooling, and Akamai for infrastructure hosting; all line up with previous reports on recent Lazarus activity.

This is the first post like this I’ve done in a while so if you have any feedback I’d love to hear it! Feel free to hit me up on any of my linked socials (Discord: birch#9901). Thanks for reading!



File Name SHA256
wallet.chm 96f144e71068bc98c5e73d396738d22a948d3a5e2d20ba618b5a0a758c0a7a89
hkcmds.exe 442769ddce07457c55fa2eb61b145f6ad91cc1155fc2124b275e0acaf4029e2c