{
	"id": "e574c85a-3cd5-447c-9fcf-a6a183be99a1",
	"created_at": "2026-04-06T00:14:29.759116Z",
	"updated_at": "2026-04-10T13:12:21.846112Z",
	"deleted_at": null,
	"sha1_hash": "21e59cb4cf141d4547b8818a75d7f912c6d625c6",
	"title": "Pythons and Unicorns and Hancitor…Oh My! Decoding Binaries Through Emulation",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 3129732,
	"plain_text": "Pythons and Unicorns and Hancitor…Oh My! Decoding Binaries\r\nThrough Emulation\r\nBy Jeff White\r\nPublished: 2016-08-30 · Archived: 2026-04-05 13:23:09 UTC\r\nThis blog post is a continuation of my previous post, VB Dropper and Shellcode for Hancitor Reveal New\r\nTechniques Behind Uptick, where we analyzed a new Visual Basic (VB) macro dropper and the accompanying\r\nshellcode. In the last post, we left off with having successfully identified where the shellcode carved out and\r\ndecoded a binary from the Microsoft Word document.\r\nOften when analysts are faced with an embedded payload for which they want to write a decoder, they simply re-write the assembly algorithm in their language of choice and process the file. The complexity of these algorithms\r\nvaries when attempting to translate from machine code to a higher-level language. It can be quite frustrating at\r\ntimes, depending on the amount of coffee you’ve had and complexity of the algorithms.\r\nIn this post, I’ll show how we can use an attacker’s own decoding algorithm combined with CPU emulation to\r\ndecode or decrypt payloads fairly easily by simply reusing the assembly in front of us. Specifically, I’ll be\r\nfocusing on using the Unicorn Engine module in Python to run the attacker’s decoding functions within an\r\nemulated environment to extract our encoded payloads. Our end goal is to identify the command and control (C2)\r\nservers being used by the final Hancitor payload by running our Python script against the Microsoft Word\r\ndocument.\r\nNow, you may ask, why even worry about this to begin with? In the last post we just let the program run and the\r\npayload was written to disk for easy retrieval, so why bother? The main answer to that is bulk-analysis\r\nautomation. If we can write a program that we can point at a directory full of documents, then we can quickly\r\nextract embedded payloads for C2 extraction and parsing to form a more holistic view of what we’re dealing with.\r\nAn example of such bulk analysis was witnessed earlier this year in July when we looked at a large sample set of\r\nLuminosityLink malware samples.\r\nDecoding Routines\r\nAs a reminder, in the last blog post we were working with the following sample:\r\n03aef51be133425a0e5978ab2529890854ecf1b98a7cf8289c142a62de7acd1a\r\nWe’ll continue where we left off after identifying the decoding routine, as seen in figure 1. The function at\r\nloc_B92 added 0x3 to each byte and uses 0x13 to XOR the result. Once every byte in the embedded binary has\r\nbeen processed, it pushes the location of the embedded binary to the stack and calls function sub_827.\r\nhttps://researchcenter.paloaltonetworks.com/2016/08/unit42-pythons-and-unicorns-and-hancitoroh-my-decoding-binaries-through-emulation/\r\nPage 1 of 19\n\nFigure 1 Start of decoding routine\r\nWithout going too far into detail on the decoding routine, know that there are five parts to it, and that each one\r\nmanipulates the bytes in some way before the overall function ends and our payload is decoded.\r\nFigure 2 Proximity view of decoding functions in IDA\r\nWhat we’re effectively going to do is copy the bytes from sub_8A6, sub_827, sub_7E7, sub_7CA, and sub_7D7.\r\nThese are the core functions that handle all of the decoding. In addition to this, we’ll need our embedded payload,\r\nhttps://researchcenter.paloaltonetworks.com/2016/08/unit42-pythons-and-unicorns-and-hancitoroh-my-decoding-binaries-through-emulation/\r\nPage 2 of 19\n\nwhich can be located in the Word document through the magic header of “POLA” as discussed in the previous\r\nblog.\r\nOnce we have the copied bytes, we’ll setup our emulation environment, adjust our assembly, and run our own\r\nshellcode to retrieve the payload. In the context of this blog, I’m just going to refer to the x86 instructions as\r\nshellcode to keep things straightforward.\r\nStarting with offset 0xB92, we’ll copy the bytes for the two blocks, ending just after our call since the payload\r\nwill be decoded by that point.\r\nFigure 3 Decoding function and associated bytes\r\nNext we’ll copy the bytes from sub_827, which are all of the bytes from offset 0x827 to 0x8A5.\r\nFigure 4 Additional decoding functions and associated bytes\r\nLast, we’ll collect the bytes from the three smaller functions. If you note their location, you can see they are\r\ncontiguous. Keeping the bytes in order is convenient but not necessary. If they don’t line up, you’ll simply need to\r\nadjust the operands for the calls or jumps so that they go where they should.\r\nhttps://researchcenter.paloaltonetworks.com/2016/08/unit42-pythons-and-unicorns-and-hancitoroh-my-decoding-binaries-through-emulation/\r\nPage 3 of 19\n\nFigure 5 Additional decoding functions and associated bytes\r\nOnce all of the bytes have been saved, we can write them to a file and open it up in a disassembler to see what\r\nissues we need to correct, if any.\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n# sub_8A6\r\nsc = b'\\x8A\\x04\\x0F\\x04\\x03\\x34\\x13\\x88\\x04\\x0F\\x41\\x81\\xF9\\xAC\\x3A\\x01\\x\r\n00\\x72\\xED\\x57\\xE8\\x7C\\xFC\\xFF\\xFF\\x83\\x7D\\xFC\\x01'\r\n# sub_7CA\r\nsc += b'\\x6B\\xC0\\x06\\x99\\x83\\xE2\\x07\\x03\\xC2\\xC1\\xF8\\x03\\xC3'\r\n# sub_7D7\r\nsc +=\r\nb'\\x6B\\xC0\\x06\\x25\\x07\\x00\\x00\\x80\\x79\\x05\\x48\\x83\\xC8\\xF8\\x40\\xC3'\r\n\u003cem\u003e# sub_7E7\u003c/em\u003e\r\nsc +=\r\nb'\\x8D\\x48\\xBF\\x80\\xF9\\x19\\x77\\x07\\x0F\\xBE\\xC0\\x83\\xE8\\x41\\xC3\\x8D\\x\r\n48\\x9F\\x80\\xF9\\x19\\x77\\x07\\x0F\\xBE\\xC0\\x83\\xE8\\x47\\xC3\\x8D\\x48\\xD0\\x\r\n80xF9\\x09\\x77\\x07\\x0F\\xBE\\xC0\\x83\\xC0\\x04\\xC3\\x3C\\x2B\\x75\\x04\\x6A\\x\r\n3E\\x58\\xC3\\x3C\\x2F\\x75\\x04\\x6A\\x3F\\x58\\xC3\\x33\\xC0\\xC3'\r\n# sub_827\r\nsc +=\r\nhttps://researchcenter.paloaltonetworks.com/2016/08/unit42-pythons-and-unicorns-and-hancitoroh-my-decoding-binaries-through-emulation/\r\nPage 4 of 19\n\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24\r\nb'\\x55\\x8B\\xEC\\x51\\x51\\x8B\\x45\\x08\\x83\\x65\\xFC\\x00\\x89\\x45\\xF8\\x8A\\x\r\n00\\x84\\xC0\\x74\\x68\\x53\\x56\\x57\\xE8\\xA3\\xFF\\xFF\\xFF\\x8B\\xD8\\x8B\\x45\\x\r\nFC\\xE8\\x7C\\xFF\\xFF\\xFF\\x8B\\x4D\\xF8\\x8D\\x14\\x08\\x8B\\x45\\xFC\\xE8\\x7B\\x\r\nFF\\xFF\\xFF\\x8B\\xF8\\x8B\\xF0\\xF7\\xDE\\x8D\\x4E\\x08\\xB0\\x01\\xD2\\xE0\\xFE\\x\r\nC8\\xF6\\xD0\\x20\\x02\\x83\\xFF\\x03\\x7D\\x09\\x8D\\x4E\\x02\\xD2\\xE3\\x08\\x1A\\x\r\nEB\\x15\\x8D\\x4F\\xFE\\x8B\\xC3\\xD3\\xF8\\x8D\\x4E\\x0A\\xD2\\xE3\\x08\\x02\\xC6\\x\r\n42\\x01\\x00\\x08\\x5A\\x01\\xFF\\x45\\x08\\x8B\\x45\\x08\\x8A\\x00\\xFF\\x45\\xFC\\x\r\n84\\xC0\\x75\\x9E\\x5F\\x5E\\x5B\\xC9\\xC3'\r\nLooking at our shellcode, only one major issue appears, which is the initial call to the decoding function being at a\r\ndifferent address.\r\nFigure 6 Broken call within shellcode\r\nAs we want to call to our previous function sub_827, which is at the end of our shellcode, we can adjust this call\r\nto point to the start of that function. Looking at our code in a hex editor, the start of the function is exactly 97\r\nbytes (0x61) into our shellcode, so we can change the instruction 0xE87CFCFFFF to 0xE861000000.\r\nFigure 7 Correcting the previously broken call\r\nhttps://researchcenter.paloaltonetworks.com/2016/08/unit42-pythons-and-unicorns-and-hancitoroh-my-decoding-binaries-through-emulation/\r\nPage 5 of 19\n\nNext, we can validate our change worked as expected within the disassembler and that our functions are now all\r\ncorrectly linked.\r\nFigure 8 Validating correction of call\r\nEmbedded Payload\r\nWe know that our embedded payload address is located on the EDI register that gets pushed onto the stack\r\nthrough our previous dynamic analysis. For the initial validation of this method, we’ll go ahead and manually\r\ncopy the bytes, starting with the magic header of “POLA” and a size of 0x13AAAC bytes, to our Python script. At\r\nthe end of the blog, I’ll include a full script that will automatically extract this binary from the Word Document.\r\n# POLA 0x504F4C41\r\nencoded_binary =\r\nb'\\x50\\x4F\\x4C\\x41\\x08\\x00\\xFF\\xFF\\xAC\\x3A\\x01[truncated]’\r\nEnter the Unicorn\r\nAs we now have all of the data we need to decode the binary, the last step for this part is to build the emulation\r\nenvironment for our code to run on. To accomplish this, I’ll use the open-source Unicorn Engine.\r\nThe first thing we’ll want to do is assign the address space we’ll be working within, along with initializing\r\nUnicorn for the architecture we want to emulate (x86), and map some memory to use. Next we’ll write our\r\nshellcode and encoded binary to our memory space and initialize some values. Finally, we’ll output the decrypted\r\ndata to STDOUT.\r\n1\r\n2\r\n3\r\n4\r\n5\r\nADDRESS = 0x1000000\r\nmu = Uc(UC_ARCH_X86, UC_MODE_32)\r\nmu.mem_map(ADDRESS, 4 * 1024 * 1024)\r\n# Write code to memory\r\nmu.mem_write(ADDRESS, X86_CODE32)\r\nhttps://researchcenter.paloaltonetworks.com/2016/08/unit42-pythons-and-unicorns-and-hancitoroh-my-decoding-binaries-through-emulation/\r\nPage 6 of 19\n\n6\r\n7\r\n8\r\n9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n# Start of encoded data + offset to binary, pushed to Stack at\r\nstart\r\nmu.reg_write(UC_X86_REG_EDI, 0x10000F9 + 0x0C)\r\n# Initialize ECX counter to 0\r\nmu.reg_write(UC_X86_REG_ECX, 0x0)\r\n# Initialize Stack for functions\r\nmu.reg_write(UC_X86_REG_ESP, 0x1300000)\r\nprint \"Encrypt: %s\" % mu.mem_read(0x10000F9,150)\r\nmu.emu_start(ADDRESS, ADDRESS + len(X86_CODE32))\r\nprint \"Decrypt: %s\" % mu.mem_read(0x10000F9,150)\r\nFigure 9 Successful decoding\r\nSuccess! We can write that section of memory to a file and see what we have.\r\nf = open(\"demo.exe\", \"w\")\r\nf.write(mu.mem_read(0x10000F9 + 0x0C, 0x13AAC))\r\nf.close()\r\nhttps://researchcenter.paloaltonetworks.com/2016/08/unit42-pythons-and-unicorns-and-hancitoroh-my-decoding-binaries-through-emulation/\r\nPage 7 of 19\n\nFigure 10 Decoded binary properties\r\nUnfortunately we find ourselves with a packed binary that may have our actual Hancitor sample, so we’ll need to\r\ntry and decode yet another payload.\r\nAttack of the Binaries\r\nThis binary has a fair amount of functions and code, but very early on we see the binary lookup the address for the\r\nsame API we discussed in our earlier blog post, RtlMoveMemory(), and then copy what we presume is our\r\nencoded payload.\r\nhttps://researchcenter.paloaltonetworks.com/2016/08/unit42-pythons-and-unicorns-and-hancitoroh-my-decoding-binaries-through-emulation/\r\nPage 8 of 19\n\nFigure 11 RtlMoveMemory() being called\r\nFigure 12 Encoded payload\r\nContinuing to debug the program, just three instructions later it returns to what looks like our next decoding\r\nroutine.\r\nhttps://researchcenter.paloaltonetworks.com/2016/08/unit42-pythons-and-unicorns-and-hancitoroh-my-decoding-binaries-through-emulation/\r\nPage 9 of 19\n\nFigure 13 Decoding function\r\nLetting these blocks complete a few times validates we’re in the right spot, as we quickly identify the MZ\r\nexecutable header.\r\nFigure 14 Validation of decoding\r\nWe’ve now found the location of the encoded binary, due to RtlMoveMemory(), and the location of our function\r\nthat we need to emulate.\r\nFunction Copying\r\nAnalyzing this function, it’s much less complex than the last one, but takes a different approach of iterating over a\r\n12-byte key, located at 0x40743C in our example, and using it to XOR the encoded payload.\r\nFigure 15 12-byte XOR key\r\nWe’ll follow the same methodology as previous to add it into our program.\r\nhttps://researchcenter.paloaltonetworks.com/2016/08/unit42-pythons-and-unicorns-and-hancitoroh-my-decoding-binaries-through-emulation/\r\nPage 10 of 19\n\nStarting at loc_406442, we’ll copy all of the bytes for the three blocks in the picture below, which is the decoding\r\nloop.\r\nFigure 16 Decoding loop and associated bytes\r\nNext we’ll copy the XOR key and encoded payload into our script and build a test file so that it follows the\r\nfollowing order of operation:\r\nshellcode -\u003e key -\u003e payload\r\n# loc_406442\r\nsc =\r\nb'\\x85\\xC9\\x7C\\x29\\x8B\\x35\\x40\\x90\\x40\\x00\\xB8\\x67\\x66\\x66\\x66\\xF\r\n7\\xE9\\xC1\\xFA\\x02\\x8B\\xC2\\xC1\\xE8\\x1F\\x03\\xC2\\x8D\\x04\\x80\\x03\\xC0\r\n\\x8B\\xD1\\x2B\\xD0\\x8A\\x82\\x3C\\x74\\x40\\x00\\x30\\x04\\x0E\\x41\\x3B\\x0D\\\r\nx4C\\x90\\x40\\x00\\x72\\xCA'\r\n# XOR Key\r\nsc += b'\\x48\\x45\\x57\\x52\\x54\\x57\\x45\\x57\\x45\\x54\\x48\\x47'\r\nencoded_binary = b'\\x05\\x1F\\xC7\\x52\\x57\\x57\\x45\\x57[truncated]’\r\nLooking at the code in the disassembler, we can tell there are a few values we’ll have to prep before we can make\r\nthis code run in our emulated environment. Specifically, we’ll need to edit two MOV instructions and a CMP\r\nhttps://researchcenter.paloaltonetworks.com/2016/08/unit42-pythons-and-unicorns-and-hancitoroh-my-decoding-binaries-through-emulation/\r\nPage 11 of 19\n\ninstruction that reference locations that don’t exist in our code.\r\nBased on our dynamic analysis, we know that the lpBuffer is a pointer to the address of the encoded payload, so\r\nwe can change this instruction to move the starting location, where our payload will reside, into the ESI register.\r\nThe current instruction is referencing an address in the data segment that holds the address to the payload. We’ll\r\nreplace it with an immediate MOV instruction by changing 0x8B3540904000 to 0xBE42000190, where 0x100042\r\nis the start of our buffer. Since we changed the opcode, the length of our new instruction was one byte short and I\r\npadded it with a 0x90 – NOP to keep everything aligned.\r\nFigure 17 Change location of payload\r\nThe first MOV is for our encoded payload, the second MOV is for our XOR key. The second MOV uses a\r\ndifferent opcode that plays more favorably to our needs, so we’ll simply change the existing address to the\r\nlocation of the key by modifying 0x8A823C744000 to a value of 0x8A8236000001.\r\nFigure 18 Change location of the XOR key\r\nThe final item to change is the compare instruction. Based off dynamic analysis, we know it’s looking for the\r\nvalue 0x5000, so we’ll change the opcode to support an immediate operand and modify 0x3B0D4C904000 to a\r\nvalue of 0x81F900500000.\r\nFigure 19 Hard-set compare value\r\nEmulation\r\nTo set up our environment for this sample, the only value we need to worry about is EDX, which needs to be a\r\npointer to our encoded payload, and gets moved into the EAX register during the loop. Similar to before, we’ll\r\nsetup our address space, define the architecture, map memory, and configure some initial register values.\r\nhttps://researchcenter.paloaltonetworks.com/2016/08/unit42-pythons-and-unicorns-and-hancitoroh-my-decoding-binaries-through-emulation/\r\nPage 12 of 19\n\nADDRESS = 0x1000000\r\nmu = Uc(UC_ARCH_X86, UC_MODE_32)\r\nmu.mem_map(ADDRESS, 4 * 1024 * 1024)\r\n# Write code to memory\r\nmu.mem_write(ADDRESS, X86_CODE32)\r\n# Start of encoded data\r\nmu.reg_write(UC_X86_REG_EDX, 0x1000042)\r\n# Initialize ECX counter to 0\r\nmu.reg_write(UC_X86_REG_ECX, 0x0)\r\n# Initialize Stack for functions\r\nmu.reg_write(UC_X86_REG_ESP, 0x1300000)\r\nprint \"Encrypt: %s\" % mu.mem_read(0x1000042,250)\r\nmu.emu_start(ADDRESS, ADDRESS + len(X86_CODE32))\r\nprint \"Decrypt: %s\" % mu.mem_read(0x1000042,250)\r\nThis yields the following result:\r\nFigure 20 Decrypted payload after running Python script\r\nIf we take a look at this binary and peer at the strings, we can see that we’re finally at the end of the road.\r\nFigure 21 Hancitor C2 URLs, external IP check, and Google remote check\r\nhttps://researchcenter.paloaltonetworks.com/2016/08/unit42-pythons-and-unicorns-and-hancitoroh-my-decoding-binaries-through-emulation/\r\nPage 13 of 19\n\nTo recap the process:\r\nStarted with a Microsoft Word document\r\nExtracted base64 encoded shellcode\r\nExtracted encoded payload\r\nEmulated decoding function from shellcode to decode payload (binary)\r\nExtracted XOR key from new binary\r\nExtracted next encoded payload from new binary\r\nEmulated decoding function from new binary to decode Hancitor (binary)\r\nOur last step is to put everything together into a nice package that we can use to scan thousands of Microsoft Word\r\ndocuments containing Hancitor and identify all of the C2 communications. Here’s a link to the Hancitor decoder\r\nscript we created.\r\nFor the purpose of this test, I took a small sample set of 10,000 unique Microsoft Word documents that were first\r\nseen on August 15, 2016 and observed by Palo Alto Networks WildFire as creating a process with a name of\r\nhttps://researchcenter.paloaltonetworks.com/2016/08/unit42-pythons-and-unicorns-and-hancitoroh-my-decoding-binaries-through-emulation/\r\nPage 14 of 19\n\n“WinHost32.exe”. This, coupled with a few other criteria, gives me a corpus of testing samples that we know will\r\nbe Hancitor and that I can run this script against.\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24\r\n[+] FILE: fe23150ffec79eb11a0fed5e3726ca6738653c4f3b0f24dd9306f6460131b34c\r\n  #### PHASE 1 ####\r\n  [-] ADD:  0x3\r\n  [-] XOR:  0x13\r\n  [-] SIZE: 80556\r\n  [!] Success! Written to disk as\r\nfe23150ffec79eb11a0fed5e3726ca6738653c4f3b0f24dd9306f6460131b34c_S1.exe\r\n  #### PHASE 2 ####\r\n  [-] XOR:  HEWRTWEWETHG\r\n  [!] Success! Written to disk as\r\nfe23150ffec79eb11a0fed5e3726ca6738653c4f3b0f24dd9306f6460131b34c_S2.exe\r\n  ### PHASE 3 ###\r\n  [-] http://api.ipify.org\r\n  [-] http://google.com\r\n  [-] http://bettitotuld.com/ls3/gate.php\r\n  [-] http://tefaverrol.ru/ls3/gate.php\r\n  [-] http://eventtorshendint.ru/ls3/gate.php\r\n[+] FILE: fe7d4a583c1ae380eff25a11bda4f6d53b92d49a7a4d72c775b21488453bbc96\r\n  #### PHASE 1 ####\r\n  [-] ADD:  0x3\r\n  [-] XOR:  0x13\r\n  [-] SIZE: 80556\r\n  [!] Success! Written to disk as\r\nfe7d4a583c1ae380eff25a11bda4f6d53b92d49a7a4d72c775b21488453bbc96_S1.exe\r\n  #### PHASE 2 ####\r\nhttps://researchcenter.paloaltonetworks.com/2016/08/unit42-pythons-and-unicorns-and-hancitoroh-my-decoding-binaries-through-emulation/\r\nPage 15 of 19\n\n25\r\n26\r\n27\r\n28\r\n29\r\n30\r\n31\r\n32\r\n33\r\n34\r\n35\r\n36\r\n37\r\n38\r\n39\r\n40\r\n41\r\n42\r\n43\r\n44\r\n45\r\n46\r\n47\r\n48\r\n49\r\n50\r\n  [-] XOR:  HEWRTWEWETHG\r\n  [!] Success! Written to disk as\r\nfe7d4a583c1ae380eff25a11bda4f6d53b92d49a7a4d72c775b21488453bbc96_S2.exe\r\n  ### PHASE 3 ###\r\n  [-] http://api.ipify.org\r\n  [-] http://google.com\r\n  [-] http://bettitotuld.com/ls3/gate.php\r\n  [-] http://tefaverrol.ru/ls3/gate.php\r\n  [-] http://eventtorshendint.ru/ls3/gate.php\r\n[+] FILE: fea98cc92b142d8ec98be6134967eacf3f24d5e089b920d9abf37f372f85530d\r\n  #### PHASE 1 ####\r\n  [-] ADD:  0x3\r\n  [-] XOR:  0x14\r\n  [-] SIZE: 162992\r\n  [!] Success! Written to disk as\r\nfea98cc92b142d8ec98be6134967eacf3f24d5e089b920d9abf37f372f85530d_S1.exe\r\n  #### PHASE 2 ####\r\n  [-] XOR:  ð~ð~ð~\r\n  [!] Detected Nullsoft Installer! Shutting down.\r\n[+] FILE: feb58e18dd320229d41d5b5932c14d7f2a26465e3d1eec9f77de211dc629f973\r\n  #### PHASE 1 ####\r\n  [-] ADD:  0x3\r\n  [-] XOR:  0x13\r\n  [-] SIZE: 80556\r\n  [!] Success! Written to disk as\r\nfeb58e18dd320229d41d5b5932c14d7f2a26465e3d1eec9f77de211dc629f973_S1.exe\r\n  #### PHASE 2 ####\r\nhttps://researchcenter.paloaltonetworks.com/2016/08/unit42-pythons-and-unicorns-and-hancitoroh-my-decoding-binaries-through-emulation/\r\nPage 16 of 19\n\n51\r\n52\r\n53\r\n54\r\n  [-] XOR:  HEWRTWEWETHG\r\n  [!] Success! Written to disk as\r\nfeb58e18dd320229d41d5b5932c14d7f2a26465e3d1eec9f77de211dc629f973_S2.exe\r\n  ### PHASE 3 ###\r\n  [-] http://api.ipify.org\r\n  [-] http://google.com\r\n  [-] http://bettitotuld.com/ls3/gate.php\r\n  [-] http://tefaverrol.ru/ls3/gate.php\r\n  [-] http://eventtorshendint.ru/ls3/gate.php\r\nAnalysis\r\nThe results were fairly unimpressive, however you win some and you lose some. It still provides some interesting\r\nobservations.\r\nFor our sample set, there were only 3 C2 URLs across all 8,851 Hancitor payloads we successfully decoded:\r\nhxxp://bettitotuld[.]com/ls3/gate.php\r\nhxxp://tefaverrol[.]ru/ls3/gate.php\r\nhxxp://eventtorshendint[.]ru/ls3/gate.php\r\nLooking at the stage 1 payloads, we decoded 9,967, which is almost the entire set. Reviewing the metadata for the\r\nPE files, 8,851 exhibited the following characteristics, which are included in a YARA rule at the end of this\r\ndocument.\r\nCompanyName: 'SynapticosSoft, Corporation.'\r\nOriginalFilename: 'MpklYuere.exe'\r\nProductName: 'ngqlgdA'\r\nAdditionally, we identified three XOR keys being used in stage 1:\r\nhttps://researchcenter.paloaltonetworks.com/2016/08/unit42-pythons-and-unicorns-and-hancitoroh-my-decoding-binaries-through-emulation/\r\nPage 17 of 19\n\n13   [-] XOR:  0xe\r\n1103   [-] XOR:  0x14\r\n8851   [-] XOR:  0x13\r\nAfter correlating the data, each of the keys corresponded to a different stage 2 dropper and our script was designed\r\nto target and decoded the most heavily used. General observations for the other two decoders are that the one with\r\nkey 0xE uses the same XOR key for the second stage Hancitor payload “HEWRTWEWETHG” and would likely\r\nbe straightforward to add to the decoding script. The 1,103 other files with key 0x14 were identified as Nullsoft\r\nInstallers.\r\nFor the 8,851 that successfully decoded their stage 2 payload, I did not note any PE’s with any file information;\r\nhowever, a YARA rule is included which matches them all. The last thing I’ll mention regarding the stage 2 files is\r\nthe different file sizes.\r\n3   [-] SIZE: 114688\r\n10   [-] SIZE: 109912\r\n1103   [-] SIZE: 162992\r\n8851   [-] SIZE: 80556\r\nThis data is pulled from the variable in our shellcode and we can see that there is a slight file size variation in the\r\n13 that used the XOR key 0xE, which might imply slightly modified payloads.\r\nConclusion\r\nHopefully this was an educational demonstration using the extremely powerful Unicorn Engine to build a practical\r\nmalware decoder. These techniques can be applied to many different samples of malware and can free you up\r\nfrom the more tedious process of figuring out how to program a slew of bitwise interactions and focus more on\r\nanalysis and countermeasures.\r\nIndicators\r\nAt the following GitHub repository, you will find 3 YARA rules, listed below, which can be used to detect the\r\nvarious pieces described throughout these two blogs, and the script that was built throughout this blog for\r\ndecoding Hancitor.\r\nhancitor_dropper.yara – Detect Microsoft Word document dropper\r\nhancitor_stage1.yara – Detect first PE dropper\r\nhancitor_payload.yara – Detect Hancitor malware payload\r\nhttps://researchcenter.paloaltonetworks.com/2016/08/unit42-pythons-and-unicorns-and-hancitoroh-my-decoding-binaries-through-emulation/\r\nPage 18 of 19\n\nSource: https://researchcenter.paloaltonetworks.com/2016/08/unit42-pythons-and-unicorns-and-hancitoroh-my-decoding-binaries-through-emu\r\nlation/\r\nhttps://researchcenter.paloaltonetworks.com/2016/08/unit42-pythons-and-unicorns-and-hancitoroh-my-decoding-binaries-through-emulation/\r\nPage 19 of 19\n\nmanipulates the Figure 2 Proximity bytes in some view of way before decoding functions the overall in IDA function ends and our payload is decoded. \nWhat we’re effectively going to do is copy the bytes from sub_8A6, sub_827, sub_7E7, sub_7CA, and sub_7D7.\nThese are the core functions that handle all of the decoding. In addition to this, we’ll need our embedded payload,\n    Page 2 of 19",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://researchcenter.paloaltonetworks.com/2016/08/unit42-pythons-and-unicorns-and-hancitoroh-my-decoding-binaries-through-emulation/"
	],
	"report_names": [
		"unit42-pythons-and-unicorns-and-hancitoroh-my-decoding-binaries-through-emulation"
	],
	"threat_actors": [],
	"ts_created_at": 1775434469,
	"ts_updated_at": 1775826741,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/21e59cb4cf141d4547b8818a75d7f912c6d625c6.pdf",
		"text": "https://archive.orkl.eu/21e59cb4cf141d4547b8818a75d7f912c6d625c6.txt",
		"img": "https://archive.orkl.eu/21e59cb4cf141d4547b8818a75d7f912c6d625c6.jpg"
	}
}