{
	"id": "8fed26a0-70d8-4ad3-8e17-87dd7d84e786",
	"created_at": "2026-04-06T00:11:23.830879Z",
	"updated_at": "2026-04-10T03:21:39.089236Z",
	"deleted_at": null,
	"sha1_hash": "45ceff58ae4f448d4ed34a89e404abf41935f45f",
	"title": "Deobfuscating DanaBot’s API Hashing",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 480346,
	"plain_text": "Deobfuscating DanaBot’s API Hashing\r\nPublished: 2020-07-12 · Archived: 2026-04-05 23:43:10 UTC\r\nYou probably already guessed it from the title’s name, API Hashing is used to obfuscate a binary in order to hide\r\nAPI names from static analysis tools, hindering a reverse engineer to understand the malware’s functionality.\r\nA first approach to get an idea of an executable’s functionalities is to more or less dive through the functions and\r\nlook out for API calls. If, for example a CreateFileW function is called in a specific subroutine, it probably\r\nmeans that cross references or the routine itself implement some file handling functionalities. This won’t be\r\npossible if API Hashing is used.\r\nInstead of calling the function directly, each API call has a corresponding checksum/hash. A hardcoded hash value\r\nmight be retrieved and for each library function a checksum is computed. If the computed value matches the hash\r\nvalue we compare it against, we found our target.\r\nAPI Hashing used by DanaBot\r\nhttps://malwareandstuff.com/deobfuscating-danabots-api-hashing/\r\nPage 1 of 7\n\nIn this case a reverse engineer needs to choose a different path to analyse the binary or deobfuscate it. This blog\r\narticle will cover how the DanaBot banking trojan implements API Hashing and possibly the easiest way on how\r\nthis can be defeated. The SHA256 of the binary I am dissecting here is added at the end of this blog post.\r\nDeep diving into DanaBot\r\nDanaBot itself is a banking trojan and has been around since atleast 2018 and was first discovered by ESET[1]. It\r\nis worth mentioning that it implements most of its functionalities in plugins, which are downloaded from the C2\r\nserver. I will focus on deobfuscating API Hashing in the first stage of DanaBot, a DLL which is dropped and\r\npersisted on the system, used to download further plugins.\r\nReversing the ResolvFuncHash routine\r\nAt the beginning of the function, the EAX register stores a pointer to the DOS header of the Dynamic Linked\r\nLibrary which, contains the function the binary wants to call. The corresponding hash of the yet unknown API\r\nfunction is stored in the EDX register. The routine also contains a pile of junk instructions, obfuscating the actual\r\nuse case for this function.\r\nThe hash is computed solely from the function name, so the first step is to get a pointer to all function names of\r\nthe target library. Each DLL contains a table with all exported functions, which are loaded into memory. This\r\nExport Directory is always the first entry in the Data Directory array. The PE file format and its headers contain\r\nenough information to reach this mentioned directory by parsing header structures:\r\nCycling through the PE headers to obtain the ExportDirectory and AddressOfNames\r\nIn the picture below, you can see an example of the mentioned junk instructions, as well as the critical block,\r\nwhich compares the computed hash with the checksum of the function we want to call. The routine iterates\r\nthrough all function names in the Export Directory and calculates the hash.\r\nThe loop breaks once the computed hash matches the value that is stored in the EDX register since the beginning\r\nof this routine.\r\nhttps://malwareandstuff.com/deobfuscating-danabots-api-hashing/\r\nPage 2 of 7\n\nGraph overview of obfuscated API Hashing function\r\nReversing the hashing algorithm\r\nThe hashing algorithm is fairly simple and nothing too complicated. Junk instructions and opaque predicates\r\ncomplicate the process of reversing this routine.\r\nThe algorithm takes the nth and the stringLength-n-1th char of the function name and stores them, as well as\r\ncapitalised versions into memory, resulting in a total of 4 characters. Each one of those characters is XOR'd with\r\nthe string length. Finally they are multiplied and the values are added up each time the loop is run and result in the\r\nhash value.\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\ndef get_hash(funcname):\r\nstrlen = len (funcname)\r\ni = 0\r\nhashv = 0x0\r\nwhile i \u003c strlen:\r\nif i = = (strlen - 1 ):\r\nch1 = funcname[ 0 ]\r\nelse :\r\nhttps://malwareandstuff.com/deobfuscating-danabots-api-hashing/\r\nPage 3 of 7\n\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\n25\r\n26\r\nch1 = funcname[strlen - 2 - i]\r\nch = funcname[i]\r\nuc_ch = ch.capitalize()\r\nuc_ch1 = ch1.capitalize()\r\nxor_ch = ord (ch) ^ strlen\r\nxor_uc_ch = ord (uc_ch) ^ strlen\r\nxor_ch1 = ord (ch1) ^ strlen\r\nxor_uc_ch1 = ord (uc_ch1) ^ strlen\r\nhashv + = ((xor_ch * xor_ch1) * xor_uc_ch)\r\nhashv = hashv ^ xor_uc_ch1\r\ni + = 1\r\nreturn hashv\r\nA python script for calculating the hash for a given function name is also uploaded on my github page[2] and free\r\nfor everyone to use. I’ve also uploaded a text file with hashes for exported functions of commonly used DLLs.\r\nDeobfuscation by Commenting\r\nSo now that we cracked the algorithm, we want to update our disassembly to know which hash value represents\r\nwhich function. As I’ve already mentioned, we want to focus on simplicity. The easiest way is to compute hash\r\nvalues for exported functions of commonly used DLLs and write them into a file.\r\nhttps://malwareandstuff.com/deobfuscating-danabots-api-hashing/\r\nPage 4 of 7\n\nGenerated hashes\r\nWith this file, we can write an IdaPython script to comment the library function name next to the Api Hashing\r\ncall. Luckily the Api Hashing function is always called with the same pattern:\r\nMove the wanted hash value into the EDX register\r\nMove a DWORD into EAX register\r\nFirst we retrieve all XRefs of the Api Hashing function. Each XRef will contain an address where the Api\r\nHashing function is called at, which means that in atleast the 5 previous instructions, we will find the mentioned\r\npattern. So we will fetch the previous instruction until we extract the wanted hash value, which is being pushed\r\ninto EDX . Finally we can use this immediate to extract the corresponding api function from the hash values we\r\nhave generated before and comment the function name next to the Xref address.\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\ndef add_comment(addr, hashv, api_table):\r\nhashv = hex ( int (hashv[: - 1 ], 16 ))\r\nkeys = api_table.keys()\r\nif hashv in keys:\r\napifunc = api_table[hashv]\r\nprint \"Found ApiFunction = %s. Adding comment.\" % (apifunc,)\r\nidc.MakeComm(addr, apifunc)\r\ncomment_added = True\r\nhttps://malwareandstuff.com/deobfuscating-danabots-api-hashing/\r\nPage 5 of 7\n\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\n25\r\n26\r\n27\r\n28\r\n29\r\n30\r\n31\r\n32\r\n33\r\n34\r\nelse :\r\nprint \"Api function for hash = %s not found\" % (hashv,)\r\ncomment_added = False\r\nreturn comment_added\r\ndef main():\r\nf = open (\r\n\"C:\\\\Users\\\\luffy\\\\Desktop\\\\Danabot\\\\05-07-2020\\\\Utils\\\\danabot_hash_table.txt\" ,\r\n\"r\" )\r\nlines = f.readlines()\r\nf.close()\r\napi_table = get_api_table(lines)\r\ni = 0\r\nii = 0\r\nfor xref in idautils.XrefsTo( 0x2f2858 ):\r\ni + = 1\r\ncurrentaddr = xref.frm\r\naddr_minus = currentaddr - 0x10\r\nwhile currentaddr \u003e = addr_minus:\r\ncurrentaddr = PrevHead(currentaddr)\r\nis_mov = GetMnem(currentaddr) = = \"mov\"\r\nif is_mov:\r\ndst_is_edx = GetOpnd(currentaddr, 0 ) = = \"edx\"\r\nif dst_is_edx:\r\nsrc = GetOpnd(currentaddr, 1 )\r\nif src.endswith( \"h\" ):\r\nadd_comment(xref.frm, src, api_table)\r\nii + = 1\r\nhttps://malwareandstuff.com/deobfuscating-danabots-api-hashing/\r\nPage 6 of 7\n\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\nprint \"Total xrefs found %d\" % (i,)\r\nprint \"Total api hash functions deobfuscated %d\" % (ii,)\r\nif __name__ = = '__main__' :\r\nmain()\r\nConclusion\r\nAs reverse engineers, we will probably continue to encounter Api Hashing in various different ways. I hope I was\r\nable to show you some quick \u0026 dirty method or give you at least some fundament on how to beat this obfuscation\r\ntechnique. I also hope that, the next time a blue team fellow has to analyse DanaBot, this article might become\r\nhandy to him and saves him some time reverse engineering this banking trojan.\r\nIoCs\r\nDropper = e444e98ee06dc0e26cae8aa57a0cddab7b050db22d3002bd2b0da47d4fd5d78c\r\nDLL = cde01a2eeb558545c57d5c71c75e9a3b70d71ea6bbeda790a0b871fcb1b76f49\r\nSource: https://malwareandstuff.com/deobfuscating-danabots-api-hashing/\r\nhttps://malwareandstuff.com/deobfuscating-danabots-api-hashing/\r\nPage 7 of 7\n\n5 6 while i \u003c strlen: if i = = (strlen - 1 ):\n7 ch1 = funcname[ 0 ]\n8 else :  \n   Page 3 of 7",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://malwareandstuff.com/deobfuscating-danabots-api-hashing/"
	],
	"report_names": [
		"deobfuscating-danabots-api-hashing"
	],
	"threat_actors": [],
	"ts_created_at": 1775434283,
	"ts_updated_at": 1775791299,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/45ceff58ae4f448d4ed34a89e404abf41935f45f.pdf",
		"text": "https://archive.orkl.eu/45ceff58ae4f448d4ed34a89e404abf41935f45f.txt",
		"img": "https://archive.orkl.eu/45ceff58ae4f448d4ed34a89e404abf41935f45f.jpg"
	}
}