{
	"id": "ff0ee0d4-d32a-4ad5-8b5e-fdacd6cd0ef8",
	"created_at": "2026-04-06T01:31:14.751602Z",
	"updated_at": "2026-04-10T03:37:08.921614Z",
	"deleted_at": null,
	"sha1_hash": "768f69a21bd15686fdbd34d868cfdcc85c0a06f2",
	"title": "AgentTesla Malware Analysis - How To Resolve API Hashes With Conditional Breakpoints",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 8633479,
	"plain_text": "AgentTesla Malware Analysis - How To Resolve API Hashes With\r\nConditional Breakpoints\r\nBy Matthew\r\nPublished: 2023-05-07 · Archived: 2026-04-06 00:43:29 UTC\r\nSummary\r\nThis article covers the Analysis of a multi-stage AgentTesla loader. The loader utilizes a Nullsoft package to drop\r\nan exe-based loader and multiple encrypted files. We'll follow the loader as it locates and decrypts the encrypted\r\nfiles, ultimately resulting in Shellcode which deploys AgentTesla malware.\r\nTopics Covered\r\nInitial Analysis of Nullsoft File\r\nExtraction of exe and encrypted files.\r\nStatic Analysis of exe using Ghidra.\r\nStatic Analysis of Shellcode Using Ghidra\r\nIdentification of Stack Strings\r\nIdentification of API hashing\r\nX32dbg for Decoding Individual hashed APIs\r\nx32dbg for Decoding API Hashes in Bulk\r\nSha256: 7512be2746137d9694e3ec3a83e8ab4c6e4d826798a04381de53d4c6973d519f\r\nLink:\r\nhttps://bazaar.abuse.ch/sample/7512be2746137d9694e3ec3a83e8ab4c6e4d826798a04381de53d4c6973d519f/\r\nPrimary Analysis\r\nAfter unpacking the initial .zip pw:infected - An .exe is obtained.\r\nUsing detect-it-easy , we can determine the file is packaged using the Nullsoft Scriptable Install System.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 1 of 61\n\nOur initial approach with any scriptable installer is to attempt to unzip the file. This is because most exe-based\r\ninstaller scripts are just a zip file with a small exe stub that unzips and executes the files.\r\nUnzipping the folder using 7-zip reveals four files. Including a randomly named cwlkewfbz.exe and a Nullsoft\r\nScript .nsi .\r\nOur initial assumption was that the .nsi script would execute the cwlkewfbz.exe file, so we decided to look\r\ninto the script to see if this was true.\r\nWe assumed the script would be text-based and viewable with a text editor. So we used Notepad++ to view it.\r\nThe initial parts (below) look like junk - but after a short scroll to line, a potential execution path and parameters\r\nof cwlkewfbz.exe can be observed.\r\nIt appears (lines 55,68) the cwlkewfbz.exe is intended to execute from the users %TEMP% folder with\r\npgkayd.aq file as a parameter.\r\nThis was interesting information and implied that the malware requires two \"pieces\" in order to\r\nfunction. In situations like this, generally the .exe is a loader, and the real malware is contained in an\r\nencrypted file passed as a parameter (in this case the pgkayd.aq )\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 2 of 61\n\nA review of the pgkayd.aq file using detect-it-easy revealed no recognized file formats, but the overall\r\nentropy was high. This suggested that pgkayd.aq might be encrypted or obfuscated.\r\nIf a strong encryption was used, then the entropy would be flat and generally higher (usually around 7.9\r\nfor good encryption). This suggested a low-effort 0r low-quality encryption may be used.\r\nWe reviewed the file for any plaintext strings that may indicate its purpose. But this revealed only seven strings.\r\nNone of which were helpful.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 3 of 61\n\nReviewing the other djdqvq.sra file within the folder, an extremely high (and flat) entropy is observed.\r\nThe high and flat entropy strongly suggests that djdqvq.sra is encrypted.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 4 of 61\n\nBack to cwlkewfbz.exe\r\nAfter a review of the djdqvq.sra and pgkayd.aq files revealed they were likely encrypted. We returned to the\r\ncwlkewfbz.exe file.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 5 of 61\n\nThis reveals a C/C++ file with no significant areas of entropy.\r\nThe lack of high entropy areas suggests that the file does not contain any embedded encrypted content.\r\nReviewing the imported functions reveals the usage of VirtualAlloc . This is a valuable function/API that we\r\ncan later set a breakpoint on to extract information about allocated memory.\r\nAlthough VirtualAlloc has legitimate uses and is not malicious on its own - it also a common API used\r\nby malware to allocate new memory regions. The purpose of these regions is often to store decrypted\r\npayloads and additional stages of malware.\r\nLastly, we used detect-it-easy to perform a string search on cwlkewfbz.exe . I had hoped that there might be\r\nstrings that could indicate the purpose or origin of the Malware.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 6 of 61\n\nSadly, the string search did not determine anything interesting, just a bunch of Windows and C++ library\r\nshenanigans.\r\nAnalyzing cwlkewfbz.exe - x32dbg\r\nWe decided to move beyond basic analysis. Our approach was to use x32dbg to monitor the previously noted\r\nusage of VirtualAlloc\r\nWe hoped that this might reveal an additional payload or decrypted content.\r\nWe opened the cwlkewfbz.exe file in x32dbg and allowed it to execute until the initial entry point.\r\nWe then created a breakpoint on VirtualAlloc with bp VirtualAlloc\r\nWe allowed the Malware to continue to execute.\r\nHowever - the VirtualAlloc breakpoint was never hit and the process was immediately terminated.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 7 of 61\n\nSince the breakpoint on VirtualAlloc was never triggered; we knew something must have happened between\r\nthe entry point and the Malware’s initial call to VirtualAlloc.\r\nThere are a few ways that this could be investigated\r\nExit Breakpoint - Can be used to view the function that triggered the process termination,\r\nGhidra - To locate paths to VirtualAlloc and diagnose any potential issues, anti-debugging or similar.\r\nStatic Analysis Using Ghidra\r\nAfter the initial breakpoint failed, we used Ghidra to gather more information about paths to VirtualAlloc.\r\nSince the breakpoint was not being hit at all - we wanted to use Ghidra to investigate any paths between the\r\nEntryPoint and VirtualAlloc .\r\nThere are two main features that I'll use to achieve this\r\nCross References (x-refs) - To see where a given resource (function, API, string, etc) is used within a program.\r\n(Essentially a ctrl+F for binary files)\r\nFunction Tree - A graphical representation of cross-references. Allows you to see which function calls a given\r\nresource and which function calls that function. And so on. Quite literally, a \"tree\" of function calls that enables\r\nyou to visualize paths of execution.\r\nUsing cross-references - We would be able to find out where VirtualAlloc is called within the program.\r\nUsing the Function Tree - This would allow me to view the path taken to get to VirtualAlloc and potentially\r\nidentify reasons why VirtualAlloc is not being triggered.\r\nHow to use cross-references in Ghidra\r\nTo locate cross references to VirtualAlloc - We first located VirtualAlloc within the Symbol tree of Ghidra.\r\nSymbol Tree → Imports → Kernel32.DLL → VirtualAlloc\r\n(You could browse through the symbols manually or use the filter to speed things up)\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 8 of 61\n\nwe then accessed cross-references by right-clicking on the VirtualAlloc symbol and selecting. Show References\r\nto .\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 9 of 61\n\nThis revealed the cross references. With only one function that calls VirtualAlloc - We clicked on this function\r\nto view its contents and establish context around the VirtualAlloc call.\r\n(The context/data reference can be ignored, this is not a function call)\r\nHere (below), the surrounding code and context are revealed.\r\nThis is the code that executes (39) the VirtualAlloc function. In this screenshot, we can see that the\r\nVirtualAlloc function is called (39), then _memcpy is used (47) to copy data into the buffer, then the buffer is\r\nxor'd ^ with a key (49).\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 10 of 61\n\nHere is a slightly better view with only the most relevant information visible.\r\nLine 39 - Call VirtualAlloc to create a memory buffer\r\nLine 47 - Copy some data into that buffer\r\nLine 49 - Use XOR ^ To decode the data in that buffer.\r\nLine 51 - Execute the buffer as code.\r\nFrom this, we can determine that the VirtualAlloc buffer is being used to store and execute some kind of code.\r\nThis is great - but why is the VirtualAlloc function never hit in the first place?\r\nFor this - we need to see what happens before VirtualAlloc .\r\nSince we have already located the relevant function - we can scroll up to see what happens before VirtualAlloc\r\nand determine why it might not be being hit.\r\nBelow we can see the contents before the VirtualAlloc call on Line 39.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 11 of 61\n\nThere's quite a bit happening - so here’s a breakdown. The first is an anti-debug/anti-emulation check using\r\ntimers.\r\nLines 14-19 - This is an anti-debug/emulation check to bypass sandboxes that patch the Sleep function with a\r\nvalue of 0.\r\nLine 14 - GetTickCount is used to check the number of milliseconds that have elapsed since the system was\r\nstarted.\r\nLine 15 - The Malware calls Sleep for 0x2be (702) milliseconds.\r\nLine 16 - GetTickCount is used again to determine how many milliseconds have elapsed since the system was\r\nstarted.\r\nLine 17 - If less than 700 milliseconds have passed, set a variable to 0 and don’t continue execution.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 12 of 61\n\nWindows Calculator (programmer mode) can convert the 0x2be into decimal to obtain 702 milliseconds.\r\nAlthough this anti-analysis check was interesting - we had a gut feeling that it wasn't the issue, so we didn’t\r\ninvestigate it further.\r\nIn lines 21-24 below - we can see the CreateFileA function is called.\r\nThis is used to open a file from disk (the first parameter, stored in param_3).\r\nWe wanted to know which file was being opened and whether the failure to open this file may be what is breaking\r\nthe malware execution.\r\nWe decided to use a debugger to monitor the first argument to CreateFileA\r\nWe did this by creating a breakpoint with bp CreateFileA and allowing the Malware to execute.\r\n(Above) - the breakpoint is immediately hit.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 13 of 61\n\n(Below) - Confirmation that the first argument lpFileName is the one containing the file name.\r\nSo we followed the first argument, which can be found on the right side of the debugger window.\r\nWe viewed the contents of the first argument [esp+4] using Follow in Dump\r\n(below) In the resulting dump window - We could see only junk and not a valid file name.\r\nWe then scrolled up slightly. This revealed the command line of the file being executed.\r\nNotably, the command line is empty after the cwlkewfbz.exe .\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 14 of 61\n\nWe suspected this was causing issues. So we allowed the function to execute and checked the return value to\r\ndetermine if an error was occurring, which may break the Malware.\r\nUnsurprisingly - the return value for CreateFileA is 0xffffffff (EAX in top right) - which indicates an error.\r\nThe call to CreateFileA is within a long series of if-else statements which ultimately execute the 2nd stage.\r\nIf any statements fail, the Malware sets Bvar3 to 0 and exits.\r\nLine 22 - Since the result of CreateFileA is an error 0xffffffff , the Malware will not continue to the next API\r\nof CreateFileMappingA.\r\nFixing the CreateFileA\r\nIt was now reasonably safe to assume that the CreateFileA error was causing the Malware to terminate before\r\nthe call to VirtualAlloc .\r\nTo fix this and continue execution - we needed to know which value was being expected in the call to\r\nCreateFileA\r\nOur previous analysis of the .nsi script reveals the file that should be in this command line. pgkayd.aq\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 15 of 61\n\nAnalysisatch the command line in x32dbg.\r\nWe can use x32dbg to modify the command line to the correct values that match the .nsi script.\r\nWithin x32dbg you can browse to File -\u003e Change Command Line\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 16 of 61\n\nAnd then crudely add the value pgkayd.aq from the .nsi script. (We found that the full path was not required)\r\nThe modified command line looked like this.\r\nAfter restarting the program, the first argument to CreateFileA now contains the correct file.\r\nContinuing execution - the breakpoint on VirtualAlloc is triggered successfully.\r\nWe now need to monitor the memory being allocated by VirtualAlloc. This can be done using a similar process\r\nthat we detailed in our Redline/Amadey Post.\r\nUsing this process - we can be alerted if any content is written to the newly created buffer.\r\nSet a breakpoint on VirtualAlloc\r\nUse Execute Until Return to obtain the return value (containing the address of the memory buffer)\r\nSet a hardware breakpoint on the buffer - This will trigger an alert when the buffer is accessed.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 17 of 61\n\nMonitor the \"alerts\" until the buffer contains something of interest.\r\nCreating a Hardware Breakpoint To Decode Malware\r\nTo create the Hardware breakpoint from VirtualAlloc - we can hit CTRL+F9 (Execute Until Return) and then\r\nFollow in Dump on the return value in EAX.\r\nWith the resulting memory contents in the dump window - we can select the first bytes and create a hardware\r\nbreakpoint.\r\nDump → Right Click → Breakpoint → Hardware Access → Byte\r\nThen continue execution\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 18 of 61\n\nOnce the hardware breakpoint has been set - We can allow the Malware to continue to execute.\r\nSoon - the hardware breakpoint is triggered and a single byte DB is written into the buffer. We can hit CTRL+F9\r\nto continue execution and allow the buffer to finish filling up.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 19 of 61\n\nThe buffer quickly fills up - but does not contain a MZ header (indicating an unpacked file). There are also no\r\nvisible strings within the dumped content.\r\nIn situations like this - we generally suspect one of two things\r\nThe “junk” is raw machine code (also referred to as shellcode), which often looks like junk.\r\nThe “junk” is not fully decoded yet - in which case we can continue to execute and trigger hardware\r\nbreakpoints until something of value appears.\r\nThe second option is useful - because the buffer needs to be accessed each time the buffer undergoes a round of\r\ndecoding - a process that will trigger a hardware breakpoint.\r\nValidating Potential Shellcode\r\nThe x32dbg Disassembler can be used to validate whether or not the bytes are shellcode.\r\nThis can be done by selecting the dump data and selecting Follow in Disassembler\r\nWe can see this in action below - note how the first disassembler bytes are DB A3 , which aligns with the\r\ncontents of the dump window.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 20 of 61\n\nIn this case - the disassembled content did not look like valid shellcode. (You can usually tell this by the presence\r\nof big red ??? )\r\nWe decided to continue execution.\r\nContinuing Analysis - Locating Shellcode\r\nSince the initial bytes did not appear to be shellcode or anything of value - we decided to continue execution.\r\nThis triggered another hardware breakpoint on the same bytes and location as before.\r\nIn the below screenshot - we can see EIP that an xor instruction triggered the breakpoint. This is a strong\r\nsuggestion that decoding is taking place.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 21 of 61\n\nWe then found that continuing execution did not have the intended result that we wanted. The data was decoded as\r\nexpected, but a hardware breakpoint was not triggered when the first byte was executed.\r\nHence - the resulting shellcode was able to execute without triggering a breakpoint.\r\nTo solve this - we went back to Ghidra and checked where the buffer was being executed.\r\nWe then manually set a breakpoint on this address (the one containing the CALL) so that we could obtain the\r\nbuffer just prior to it being executed.\r\nThis was only a few instructions after the second hardware breakpoint was triggered.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 22 of 61\n\n(TLDR: once you hit the second hardware breakpoint, the CALL address will already be in your\r\ndisassembly window, about 6 lines after EIP)\r\nAllowing the Malware to continue to execute until the CALL. We can see a new buffer in the dump window E9\r\n97 0f 00\r\nWe can validate that this is shellcode by using Follow in Disassembler to view the contents as disassembled\r\ncode.\r\nThis time there are no glaring red ??? or other shenanigans.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 23 of 61\n\nAt this point, you could allow the shellcode to execute. However, we will be analyzing the shellcode manually.\r\nContinuing execution at this point will trigger breakpoints on api’s that are shared between the\r\nshellcode and initial cwlkewfbz.exe which is still loaded into x32dbg. If you continue execution this\r\nway - you can generally continue to debug the shellcode as if it were a regular process. The drawback is\r\nthat you will not trigger breakpoints on any new api’s imported and/or executed by the shellcode.\r\nThis section was admittedly confusing. If you have gotten lost at any point, restart the process and set a\r\nHardware Breakpoint (Execute) on the return value from VirtualAlloc. This will take you straight to the\r\ncurrent point of analysis.\r\nHow to Save Shellcode Using X32dbg\r\nSince this is an education-focused post - we will instead be dumping the shellcode and analyzing it manually.\r\nYou can do the same by reaching the point where the shellcode is executed.\r\nThen selecting Follow in Memory Map and Dump Memory to File\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 24 of 61\n\nWe then saved the content as shellcode.bin\r\nHow to Manually Analyse the Shellcode\r\nAt this point, we loaded the shellcode.bin file into Ghidra for further analysis.\r\nSince this is shellcode - The architecture will need to be manually speAnalysiso that Ghidra can load it\r\nsuccessfully.\r\nFor the majority of Windows shellcode you will encounter. You can simply enter x86 into the filter. Then select a\r\nsize based on the architecture of process which initially loaded the shellcode.\r\nIn this case - the initial file cwlkewfbz.exe is LE (little endian) and 32-bit. This information can be obtained\r\nusing detect-it-easy.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 25 of 61\n\nAny option that is both little and 32-bit will be suitable.\r\nWe have generally found that the Compiler column makes no difference for shellcode. Only the Endian ,\r\nSize and Processor columns matter.\r\nOnce the options have been selected - you can click ok and continue (OK) with the file analysis.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 26 of 61\n\nOnce completed - Ghidra will proceed to decompile the code and it should look like this. Note how there are\r\nfunctions and annotations in both the decompiler and disassembler windows.\r\nHow to Force Disassembly of Shellcode With Ghidra\r\nIf there are no functions or annotations present in your shellcode, Ghidra failed to recognize the start of the code.\r\nYou can easily correct this by selecting the first byte, right-click and Disassemble .\r\nIf anything still looks funny or the decompiler window remains empty - Right-Click again and select Create\r\nFunction\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 27 of 61\n\nThe decompiler view should go from left to right in the screenshot below.\r\nOnce this is setup - You can click the one and only available function.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 28 of 61\n\nAnalysis of The Shellcode Using Ghidra\r\nThis reveals a function FUN_00000f9c that begins by initialising a bunch of stack variables which can largely be\r\nignored for now.\r\nScrolling down further, we can see some potential stack strings.\r\nIdentifying Stack Strings in Ghidra\r\nYou can generally suspect stack strings when you see lots of hex or decimal values being set on stack variables.\r\nSince null bytes are used to terminate each string - this is also a dead giveaway.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 29 of 61\n\nThese stack strings can be decoded in Ghidra by right-clicking on each value and selecting char.\r\nOnce the first stack string is decoded, we can see a value of djdqvq.sra . Which is the remaining file in our\r\nunzipped nullsoft folder.\r\nAfter this value - are a few more stack strings which we presume to be folder and file names for later use.\r\nIdentifying API Hashing in Shellcode\r\nImmediately following the stack strings - there is a suspicious function FUN_00000073 that is called repeatedly.\r\nEach call to FUN_00000073 contains the same first argument, as well as a second argument containing hash-like\r\nvalue.\r\nOn lines 111 and 113 - We can see that a returned result is executed as code. This is an extremely strong\r\nindicator that FUN_00000073 is an API hashing function.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 30 of 61\n\nBased on the above analysis - we have enough information to determine that the function performs api\r\nAnalysisand resolution. You could always manually inspect the function to determine the exact hashing type, but\r\nthis is a manual process for a future blog post.\r\nInstead - we will focus on a repeatable method to resolve unknown api hashes using a debugger. This method\r\nshould work regardless of the api hashing method used and does not rely on 3rd party scripts or an internet\r\nconnection.\r\nHow to Defeat API Hashes With A Debugger\r\nA debugger (x32dbg/x64dbg) can be used to monitor the input and output of the API-hashing function and easily\r\nobtain the decoded APIs and their corresponding hashes. This is primarily achieved using the logging feature of\r\nx64dbg.\r\nTo Do This\r\nLoad shellcode into a debugger using blobrunner\r\nSet Breakpoints on the api hashing function FUN_00000073\r\nOne breakpoint for the beginning (containing the hashed api name)\r\nOne breakpoint for the end (containing the resolved api)\r\nOnce working - convert the breakpoints into conditional breakpoints that log the interesting values.\r\nView the log window for hashes as well as decoded api’s\r\nHow to Load Shellcode Into a Debugger (x32dbg)\r\nSince shellcode can not be loaded directly into a debugger - We will use Blobrunner from OALabs.\r\nThe purpose of Blobrunner is to load the shellcode and provide a process that can be attached to using a\r\ndebugger.\r\nTo do this - you can download blobrunner from GitHub, copy it to the same directory as your shellcode, then open\r\na command line and run blobrunner.exe shellcode.bin\r\n(Make sure to place the blobrunner files in the same folder as your shellcode, and use the 32-bit version\r\nblobrunner.exe and not blobrunner64.exe )\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 31 of 61\n\nSuccessful execution will show a small window containing a base address 0x00860000 where the shellcode has\r\nbeen loaded into.\r\nNote that the base address will be different for each execution.\r\nOnce the base address 0x00860000 of the shellcode has been obtained- you can open x32dbg and attach it to\r\nBlobrunner\r\nAttaching to Blobrunner using X32dbg\r\nX32dbg can be used to attach to the blobrunner process containing shellcode.\r\nFile -\u003e Attach -\u003e Blobrunner.exe\r\nOnce attached - a breakpoint should be created on the base address containing the shellcode.\r\nIn this case - the address was 0x00860000\r\nThe command bp 0x00860000 will create the breakpoint.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 32 of 61\n\nAt this point - you can press any button in the Blobrunner command window and the shellcode breakpoint should\r\nbe triggered.\r\nSetting a Breakpoint on the API Hashing Function\r\nAt this point - A breakpoint should be set on the API hashing function FUN_00000073\r\nTo set the breakpoint - we can either\r\nSync the addresses between x32dbg and Ghidra (see our previous blog).\r\nSet a breakpoint on the base address + 0x73.\r\nThe easiest way to is to set a breakpoint on the base address 0x00860000 + 0x73\r\nAllowing the shellcode to execute the program - the breakpoint on the API hashing function 0x00860073 is\r\ntriggered.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 33 of 61\n\nAt the point where the breakpoint is triggered, we can see the first API hash of 0x7f91a078 contained in the\r\nsecond argument to 0x00860073\r\n(Note that x32dbg assumes 5 arguments by default, we can ignore args 3,4 and 5 as we know the\r\nfunction only takes two)\r\nThis first hash of 0x7f91a078 corresponds to the first call at 0x00000f45\r\nTo obtain the decoded API name - Execute Until Return and monitor the return value in EAX .\r\nThis reveals that the first hash of 0x7f91a078 corresponds to Kernel32.ExitProcess .\r\nAllowing the Malware to continue to execute - the API hashing function is triggered again. This time with a hash\r\nof 0x7fae6c34 .\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 34 of 61\n\nExecuting until return - we see that 0x7fae6c34 resolves to kernel32.VirtualAllocExNuma .\r\nIt is now worth noting that the decoded API hash resides in the return value EAX whenever EIP is at the end of\r\nthe API hashing function 0x008600c9 .\r\nif EIP == 0x008600c9 → then EAX == Decoded API name\r\nAt this point - A Ghidra database could be modified with the first two resolved api names.\r\nFor example - by converting Line 18 (above) the above to this (below)\r\nMarking up Ghidra is not a complicated process - but it is somewhat tedious and hence will be left as an exercise.\r\nHow to Automate API Hashing with A Debugger (x32dbg)\r\nAt this point, we now know a few key pieces of information\r\nThe exact location where the API resolving function starts \u003cbase\u003e + 0x73\r\nThe exact location containing the hashed API name (2nd arg, [esp+8] )\r\nThe exact location where the decoded API name can be found \u003cbase\u003e + 0xc9\r\nWe can now simply create breakpoints with log conditions to obtain the hashes and decoded values.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 35 of 61\n\nThis will require two primary conditional breakpoints.\r\n1. On the API hashing function \u003cbase\u003e + 0x73 - This is to log the hash\r\n2. On the End of the API hashing function \u003cbase\u003e + 0xc9 - To log the decoded value\r\nThis can be achieved by restarting blobrunner (Making sure to set breakpoints according to the new base address)\r\nAs well as setting a breakpoint on the new address of the API resolving function.\r\nBlobrunner can now be executed - Which will trigger a breakpoint on the start of the api resolving function\r\n\u003cbase\u003e + 0x73\r\nRemember the hashed value contained the second argument [esp+8] . This is the first value that should be\r\nlogged.,\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 36 of 61\n\nWe can go ahead and EDIT the breakpoint. Adding the following conditions.\r\nLog Text - Hash: 0x{x:[esp+8]} - This will log the hex value contained at [esp+8]\r\nHash: this is just generic text for readability\r\n0x prepend a 0x to each printed hex value\r\n{x:[esp+8]} - print the hex x representation of the value at [esp+8]\r\nCommand Text - run; - this will continue execution instead of pausing at the breakpoint.\r\nThe conditional breakpoint should look like the below screenshot.\r\nNow when the Malware executes - Hashed values will be printed to the Log Window.\r\nNext, we’ll add a second breakpoint to log the decoded values.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 37 of 61\n\nLet's now take it a step further and print the decoded API names.\r\nWe can do this by restarting the program and recreating the initial conditional breakpoint.\r\nA second conditional breakpoint will need to be created at the end of the API hashing function \u003cbase\u003e +0xc9 .\r\nOnce the end of the api hashing function \u003cbase\u003e + 0xc9 has been located - A second conditional breakpoint can\r\nbe created.\r\n(Remembering that we want to log the API name at EAX, but not the actual value of EAX). This can be done by\r\nusing {a:eax}\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 38 of 61\n\nThe syntax of {a:eax} can be obtained from the x64dbg documentation - this will print the address information\r\nwhich contains any relevant function names. (As per the x64dbg documentation)\r\nWe can use this to set the following conditional breakpoint at the return address \u003cbase\u003e + 0xc9 .\r\nNow when the Malware is executed - A list of hashes and their decoded values can be observed in the Log\r\nWindow.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 39 of 61\n\nThis information can be used to further markup a Ghidra database.\r\nAlternatively - You can start adding breakpoints on the future functionality of the Malware.\r\nEg Setting breakpoints on newly resolved API's ReadFile , VirtualAlloc etc.\r\nAuto-creating breakpoints on Hashed APIs\r\nAdditional breakpoints can be created manually eg bp ReadFile - but they can also be auto-created by\r\nmodifying the command text to bp eax; run;\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 40 of 61\n\nThe Malware will now automatically create and trigger breakpoints on any function that was resolved via api\r\nhashing.\r\nSince API hashing is generally used to hide suspicious imports - each new breakpoint should reveal something of\r\ninterest.\r\nHere are some short examples of information gathered from newly auto-created breakpoints.\r\nlStrCatW - which appeared to be creating a folder path containing the final djdqvq.sra file from the original\r\nNullsoft folder.\r\nHere is a copy of the original Nullsoft folder.\r\nHere are the two values being concatenated by lstrcatW - They combine to create C:\\\\\\\\users\\\\\\\\\r\n\u003cuser\u003e\\\\\\\\Appdata\\\\\\\\local\\\\\\\\temp\\\\\\\\djdqvq.sra\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 41 of 61\n\nThis would make a good hunting IOC if you discovered this malware sample in your environment.\r\nPathAppendW - Revealed an interesting path for an exe file. c:\\\\\\\\users\\\\\\\\\r\n\u003cuser\u003e\\\\\\\\appdata\\\\\\\\roaming\\\\\\\\eirbw\\\\\\\\gcluqa.exe\r\nAfter a few more API calls related to persistence (via run key) and the creation of that eirbw folder.\r\nAn attempt was made to open the djdqvq.sra file via CreateFileW\r\nTo keep the Malware happy and avoid patching memory - We copied the djdqvq.sra file to the\r\nc:\\\\\\\\users\\\\\\\\\u003cuser\u003e\\\\\\\\appdata\\\\\\\\local\\\\temp folder.\r\nThe Malware was then allowed to continue to execute - at which point it hit another call to VirtualAlloc .\r\nExecute Until Return was used obtain the resulting buffer in EAX , and then a hardware breakpoint was created\r\nto observe it’s contents.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 42 of 61\n\nThe ReadFile API is then triggered (via auto-created breakpoint) - and the contents of the djdqvq.sra file is\r\nloaded into memory in the buffer created by VirtualAlloc .\r\nHere we can see the djdqvq.sra contents in a hex editor.\r\nObserving the memory buffer reveals identical contents - confirming that this is djdqvq.sra\r\nThis data is likely encrypted - The Entropy graph is extremely high in detect-it-easy.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 43 of 61\n\nThe Malware was allowed to continue execution. This was in hopes that it would trigger another hardware\r\nbreakpoint during the decoding of the encrypted content.\r\nAfter continuing (and clicking continue through a few exceptions) - the first byte 49 is turned into a promising\r\n4D , the first half of an MZ 4D 5A header.\r\nThe Malware can be allowed to finish decoding using Execute Until Return .\r\nExecute Until Return will work, but can be slow. An alternative is to set a breakpoint on the next call\r\ninstruction after the triggering of the hardware breakpoint.\r\nIn this case, the next call was 2 instructions after the initial hardware breakpoint was triggered.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 44 of 61\n\nOnce this breakpoint was triggered - a full PE file could be observed in the memory buffer.\r\nThe PE File can be saved to disk using Follow in Memory map and Dump Memory To File .\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 45 of 61\n\nWe saved the file as unpacked.bin\r\nAnalysis of unpacked.bin\r\nThis unpacked.bin file was a 248KB PE - without any recognized packers or obfuscation.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 46 of 61\n\nBased on the entropy graph - there were no glaring signs of hidden encrypted files or content.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 47 of 61\n\nReviewing the imported functions - there was a suspicious reference to CLRCreateInstance . This is typical when\r\na file contains an embedded .NET payload.\r\nWe loaded the file into Ghidra and checked x-refs (cross-references) to CLRCreateInstance . The API was called\r\nonly once from the function FUN_00401000 .\r\nCLRCreateInstance is called only once from the function FUN_00401000 - which itself is only called once from\r\nFUN_0040147b .\r\nThe function FUN_0040147b that eventually calls CLRCreateInstance , is responsible for loading an embedded\r\nresource and passing it to the CLRCreateInstance function.\r\nBelow you can see references to FindResourceW and LoadResource - prior to calling the function which\r\ncontains CLRCreateInstance\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 48 of 61\n\nChecking the unpacked.bin file using resource hacker. An embedded pe file can be observed in the resource\r\nsection.\r\nSince this resource is not encrypted or obfuscated, there were no signs of embedded content in the Entropy Graph.\r\nSince the file was named resource 1 - We lazily saved the file as 1.bin .\r\nAnalysis of The Final Stage\r\nWe again used detect-it-easy - which revealed the file was a .NET based program.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 49 of 61\n\nThere are no significant areas of high entropy, but there is a large flat section that may contain something\r\ninteresting and/or badly obfuscated.\r\n1.bin was loaded into Dnspy for additional analysis.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 50 of 61\n\nDnspy revealed a lot of obfuscation and functions that were difficult to analyse,\r\nIt would be possible to analyse this obfuscation and manually rename each function, but that process is extremely\r\ntedious and time-consuming.\r\nInstead, We decided to use a tool called Garbageman. (Download Link Here)\r\nGarbageman is a tool that can run a .NET program, and automatically capture strings and byte arrays that were\r\ncreated in memory.\r\nTLDR: You can run .NET Malware and easily obtain strings, embedded payloads and (if you're lucky)\r\nC2 information.\r\nGarbageman can be downloaded from the release page and then transferred into an analysis machine.\r\nFrom here the release can be unzipped as a regular zip file.\r\n(Note that 7-zip failed to unzip on our analysis machine, but the built-in unzip tool worked just fine - right\r\nclick -\u003e open with -\u003e windows explorer to unzip with the regular windows zip handler.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 51 of 61\n\nThis will create a folder containing Garbageman.exe\r\nRunning Garbageman\r\nGarbageman can be run by directly executing the Garbageman.exe file.\r\nTo run a suspicious file using Garbageman, File -\u003e New -\u003e Execute\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 52 of 61\n\nThe full path to 1.bin will need to be specified in the executable option.\r\nMost of the remaining options can largely be run as default - with a few changes…\r\nIncrease the snapshots to 5\r\nSet the interval to 200ms .\r\nThis will create 5 snapshots - at 500ms, 700ms, 900ms, 1100ms and 1300ms.\r\nThe exact timings don’t matter - but it is ideal to get multiple snapshots from the first 1-2 seconds of execution.\r\nOnce this is set - you can select “Start”\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 53 of 61\n\nThis will run the tool and capture relevant snapshots. After which a menu like this will be presented.,\r\nThis admittedly looks confusing - but for the most part - only the bottom left corner is important.\r\nThe bottom left corner is what allows you to search and view content that was captured in the snapshots.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 54 of 61\n\nWe recommend the following options as a starting point.\r\nSnapshot = Any - Search all available snapshots\r\nType = Byte or String - Show only bytes or strings\r\nValue = Blank - Add additional filters later.\r\nOrder By = Address - This Groups similar content together (Change to size when looking for embedded\r\npayloads)\r\nLimit = 1000 (or infinite) - Display as much data as possible\r\nOrder = Asc - Start from the \"beginning\" of the file. (Setto Desc if hunting for large content)\r\nThe initial results are fairly benign, and there are lots of duplicates.\r\nBut there is an interesting User Agent Header and reference to apify.org.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 55 of 61\n\nand then a pretty interesting reference to a yandex email address. This is something pretty unique and specific and\r\nworth googling.\r\nIdentification of AgentTesla\r\nGoogling the email address contained in the dump - numerous references to Malware are immediately shown.\r\nThe first link is a triage report for AgentTesla. In an IR situation - this could be a good hint as to the malware\r\nfamily involved.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 56 of 61\n\nThe Triage report contains an extracted malware config - with values very similar to what was found in\r\nGarbageman.\r\n(The Malware also contains references to SMTP and port 587)\r\nAt this point some interesting information had been found, and it is ideal to try and hone in and establish more\r\ncontext.\r\nTo simplify the output and reduce duplicates. The search can be reduced to a single snapshot. (Any snapshot\r\ncontaining useful information can be used, and you should experiment with multiple snapshots)\r\nSnapshot 4 was used for this case.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 57 of 61\n\nWith duplicates removed - there are references to Discord, Webmail, Facebook, and Twitter.\r\nReviewing the second result from the previous Google search (Ahnsec Labs) - There is a suggestion that\r\nAgentTesla uses SMTP as a means of exfiltration and command and control.\r\nThis suggests that the discovered email address is the C2 of the file. The blog also suggests that the value ubd*\r\nfound alongside the email address, is actually the password to the smtp server.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 58 of 61\n\nAt this point in the analysis - We would have strong confidence that the sample was AgentTesla.\r\nFoAnalysisonal confirmation. We scrolled down until more interesting, unique, and attack-related strings could be\r\nfound.\r\nThis revealed some strings related to targeted applications.\r\nA quick Google search reveals numerous results (Including Splunk) for Agent Tesla malware.\r\nintext:\"iridium browser\" intext:amigo intext:brave intext:torch malware\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 59 of 61\n\nAt this point - We were happy to consider the Malware as AgentTesla. And the C2 information to be successfully\r\ndiscovered.\r\nConclusion\r\nThis post concludes. We intentionally tried to cover as many topics as possible to demonstrate useful analysis\r\ntechniques. Hopefully, you've learned something new.\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 60 of 61\n\nIf you enjoy these posts and want to support the creation of more. Consider signing up for the site.\r\nResources\r\nHardware Breakpoints - https://reverseengineering.stackexchange.com/questions/28045/what-is-hardware-breakpoint-and-when-we-need-to-use-it\r\nx64dbg Documentation -String Formatting -\r\nhttps://help.x64dbg.com/en/latest/introduction/Formatting.html\r\nGarbageMan - Download - https://github.com/WithSecureLabs/GarbageMan/\r\nGarbageMan - Website - https://labs.withsecure.com/tools/garbageman\r\nTriage Report - Agent Tesla - https://triage.hatching.io/230410-pf13hsba5w\r\nAhnsec Labs - Agent Tesla - https://asec.ahnlab.com/en/51274/\r\nSource: https://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nhttps://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/\r\nPage 61 of 61\n\nLine 16 - started. GetTickCount is used again to determine how many milliseconds have elapsed since the system was\nLine 17-If less than 700 milliseconds have passed, set a variable to 0 and don’t continue execution.\n    Page 12 of 61   \n\n  https://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/  \nThe decompiler view should go from left to right in the screenshot below.\nOnce this is setup-You can click the one and only available function.\n   Page 28 of 61\n\n  https://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/   \nOnce this breakpoint was triggered -a full PE file could be observed in the memory buffer.\nThe PE File can be saved to disk using Follow in Memory map and Dump Memory To File .\n   Page 45 of 61",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://embee-research.ghost.io/agenttesla-full-analysis-api-hashing/"
	],
	"report_names": [
		"agenttesla-full-analysis-api-hashing"
	],
	"threat_actors": [
		{
			"id": "0661a292-80f3-420b-9951-a50e03c831c0",
			"created_at": "2023-01-06T13:46:38.928796Z",
			"updated_at": "2026-04-10T02:00:03.148052Z",
			"deleted_at": null,
			"main_name": "IRIDIUM",
			"aliases": [],
			"source_name": "MISPGALAXY:IRIDIUM",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "8941e146-3e7f-4b4e-9b66-c2da052ee6df",
			"created_at": "2023-01-06T13:46:38.402513Z",
			"updated_at": "2026-04-10T02:00:02.959797Z",
			"deleted_at": null,
			"main_name": "Sandworm",
			"aliases": [
				"IRIDIUM",
				"Blue Echidna",
				"VOODOO BEAR",
				"FROZENBARENTS",
				"UAC-0113",
				"Seashell Blizzard",
				"UAC-0082",
				"APT44",
				"Quedagh",
				"TEMP.Noble",
				"IRON VIKING",
				"G0034",
				"ELECTRUM",
				"TeleBots"
			],
			"source_name": "MISPGALAXY:Sandworm",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "7bd810cb-d674-4763-86eb-2cc182d24ea0",
			"created_at": "2022-10-25T16:07:24.1537Z",
			"updated_at": "2026-04-10T02:00:04.883793Z",
			"deleted_at": null,
			"main_name": "Sandworm Team",
			"aliases": [
				"APT 44",
				"ATK 14",
				"BE2",
				"Blue Echidna",
				"CTG-7263",
				"FROZENBARENTS",
				"G0034",
				"Grey Tornado",
				"IRIDIUM",
				"Iron Viking",
				"Quedagh",
				"Razing Ursa",
				"Sandworm",
				"Sandworm Team",
				"Seashell Blizzard",
				"TEMP.Noble",
				"UAC-0082",
				"UAC-0113",
				"UAC-0125",
				"UAC-0133",
				"Voodoo Bear"
			],
			"source_name": "ETDA:Sandworm Team",
			"tools": [
				"AWFULSHRED",
				"ArguePatch",
				"BIASBOAT",
				"Black Energy",
				"BlackEnergy",
				"CaddyWiper",
				"Colibri Loader",
				"Cyclops Blink",
				"CyclopsBlink",
				"DCRat",
				"DarkCrystal RAT",
				"Fobushell",
				"GOSSIPFLOW",
				"Gcat",
				"IcyWell",
				"Industroyer2",
				"JaguarBlade",
				"JuicyPotato",
				"Kapeka",
				"KillDisk.NCX",
				"LOADGRIP",
				"LOLBAS",
				"LOLBins",
				"Living off the Land",
				"ORCSHRED",
				"P.A.S.",
				"PassKillDisk",
				"Pitvotnacci",
				"PsList",
				"QUEUESEED",
				"RansomBoggs",
				"RottenPotato",
				"SOLOSHRED",
				"SwiftSlicer",
				"VPNFilter",
				"Warzone",
				"Warzone RAT",
				"Weevly"
			],
			"source_id": "ETDA",
			"reports": null
		},
		{
			"id": "75455540-2f6e-467c-9225-8fe670e50c47",
			"created_at": "2022-10-25T16:07:23.740266Z",
			"updated_at": "2026-04-10T02:00:04.732992Z",
			"deleted_at": null,
			"main_name": "Iridium",
			"aliases": [],
			"source_name": "ETDA:Iridium",
			"tools": [
				"CHINACHOPPER",
				"China Chopper",
				"LazyCat",
				"Powerkatz",
				"SinoChopper",
				"reGeorg"
			],
			"source_id": "ETDA",
			"reports": null
		},
		{
			"id": "a66438a8-ebf6-4397-9ad5-ed07f93330aa",
			"created_at": "2022-10-25T16:47:55.919702Z",
			"updated_at": "2026-04-10T02:00:03.618194Z",
			"deleted_at": null,
			"main_name": "IRON VIKING",
			"aliases": [
				"APT44 ",
				"ATK14 ",
				"BlackEnergy Group",
				"Blue Echidna ",
				"CTG-7263 ",
				"ELECTRUM ",
				"FROZENBARENTS ",
				"Hades/OlympicDestroyer ",
				"IRIDIUM ",
				"Qudedagh ",
				"Sandworm Team ",
				"Seashell Blizzard ",
				"TEMP.Noble ",
				"Telebots ",
				"Voodoo Bear "
			],
			"source_name": "Secureworks:IRON VIKING",
			"tools": [
				"BadRabbit",
				"BlackEnergy",
				"GCat",
				"NotPetya",
				"PSCrypt",
				"TeleBot",
				"TeleDoor",
				"xData"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "b3e954e8-8bbb-46f3-84de-d6f12dc7e1a6",
			"created_at": "2022-10-25T15:50:23.339976Z",
			"updated_at": "2026-04-10T02:00:05.27483Z",
			"deleted_at": null,
			"main_name": "Sandworm Team",
			"aliases": [
				"Sandworm Team",
				"ELECTRUM",
				"Telebots",
				"IRON VIKING",
				"BlackEnergy (Group)",
				"Quedagh",
				"Voodoo Bear",
				"IRIDIUM",
				"Seashell Blizzard",
				"FROZENBARENTS",
				"APT44"
			],
			"source_name": "MITRE:Sandworm Team",
			"tools": [
				"Bad Rabbit",
				"Mimikatz",
				"Exaramel for Linux",
				"Exaramel for Windows",
				"GreyEnergy",
				"PsExec",
				"Prestige",
				"P.A.S. Webshell",
				"AcidPour",
				"VPNFilter",
				"Neo-reGeorg",
				"Cyclops Blink",
				"SDelete",
				"Kapeka",
				"AcidRain",
				"Industroyer",
				"Industroyer2",
				"BlackEnergy",
				"Cobalt Strike",
				"NotPetya",
				"KillDisk",
				"PoshC2",
				"Impacket",
				"Invoke-PSImage",
				"Olympic Destroyer"
			],
			"source_id": "MITRE",
			"reports": null
		}
	],
	"ts_created_at": 1775439074,
	"ts_updated_at": 1775792228,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/768f69a21bd15686fdbd34d868cfdcc85c0a06f2.pdf",
		"text": "https://archive.orkl.eu/768f69a21bd15686fdbd34d868cfdcc85c0a06f2.txt",
		"img": "https://archive.orkl.eu/768f69a21bd15686fdbd34d868cfdcc85c0a06f2.jpg"
	}
}