{
	"id": "1490a636-654b-4e3b-8c82-a1ff559198c8",
	"created_at": "2026-04-06T00:06:45.20229Z",
	"updated_at": "2026-04-10T03:21:38.438074Z",
	"deleted_at": null,
	"sha1_hash": "a6cea6411ab8aeb9b154b5a8c91ac347cf6d2e22",
	"title": "Virus Bulletin :: Needle in a haystack",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 2208231,
	"plain_text": "Virus Bulletin :: Needle in a haystack\r\nBy Gabor SzappanosSophos, HungaryEditor: Helen Martin\r\nArchived: 2026-04-02 12:05:15 UTC\r\n2014-02-03\r\nAbstract\r\nSometimes what looks like a genuine MP3 encoder library, and even works as a functional encoder, actually hides\r\nmalicious code deep amongst a pile of clean code. Gabor Szappanos reveals the lengths to which one piece of\r\nmalware goes to hide its tracks.\r\nCopyright © 2014 Virus Bulletin\r\nMalware authors engaged in Advanced Persistent Threat (APT) operations put great effort into making sure their\r\ncreations live up to their name and achieve persistence over the course of months or years; in order to do so, the\r\nthreats must remain undetected by security products.\r\nThe authors try both to conceal the presence of the threats on infected systems and to hide their code from analysis\r\nand detection. Most crimeware authors achieve the latter by applying sophisticated execryptors and protectors to\r\ntheir code.\r\nOver the past year, however, we have spotted a different approach: malicious code is compiled into an open source\r\nlibrary, hidden among a large pile of clean library code, with only a single export pointing to the trojan\r\nfunctionality. The deployment and progression of this malware spans about two years now – however its\r\nversioning suggests that its development started longer ago than that.\r\nThis malware doesn’t take anything for granted: even common system tools like rundll32.exe and wscript.exe,\r\nwhich are present on all Windows systems, are carried with the installer and dropped when needed.\r\nThe malware goes to great lengths to cover its tracks. All of the string constants that could reveal the nature of the\r\nbackdoor are protected with strong encryption. Additionally, the backdoor itself is disguised as a legitimate MP3\r\nencoder library. In fact, it is a legitimate and functional MP3 library – and a bit more besides.\r\nExploited carrier workbook\r\nIn a handful of cases we have been able to identify the original exploited document that leads to the system\r\ninfection. At the time of finalizing this paper, three exploited workbooks have been found that install this threat.\r\nAll of them are protected Excel workbooks with the default password (for more details see [1]). In short: the\r\nworkbooks are password protected (that is, checked before opening). It is possible to leave the password field\r\nblank – in which case Excel encrypts the content using the default password: ‘VelvetSweatshop’. On the other\r\nhttps://www.virusbulletin.com/virusbulletin/2014/02/needle-haystack\r\nPage 1 of 16\n\nhand, if a workbook is protected with exactly this password, Excel assumes that there is no password, and opens\r\nthe document transparently. As a result, the document content is encrypted and hidden from normal analysis, but\r\nopening it will execute the shellcode without further prompting.\r\nThe workbooks exploit the CVE-2012-0158 vulnerability, which triggers the execution of shellcode within the\r\ndocument.\r\nAfter the workbooks are opened, the intended operation is to open a decoy workbook – a clean file that grabs the\r\nattention of the user while malicious activities proceed in the background. The themes of the decoys give us some\r\nidea as to the areas of interest of the target audience of this malware distribution.\r\nWorkbook 1\r\nFilename: 300 .xls (rough translation: ‘300 petitioners cosigned.xls’)\r\nFile size: 839756 bytes\r\nSHA1: 066998e20ad44bc5f1ca075a3fb33f1619dd6313\r\nMD5: 5c370923119f66e64a5f9accdd3d5fb\r\nThis does not display any decoy document, just closes the Excel window. Nevertheless, the shellcode execution\r\nproceeds.\r\nIf the file was opened, it would display a workbook with a list of names, gender, region and phone numbers of\r\nChinese individuals.\r\nhttps://www.virusbulletin.com/virusbulletin/2014/02/needle-haystack\r\nPage 2 of 16\n\nFigure 1. Decoy content for 066998e20ad44bc5f1ca075a3fb33f1619dd6313.\r\nWorkbook 2\r\nFilename: sample.xls\r\nFile size: 638912 bytes\r\nSHA1: e5e183e074d26416d7e6adfb14a80fce6d9b15c2\r\nMD5: 2066462274ed6f6a22d8275bd5b1da2b\r\nhttps://www.virusbulletin.com/virusbulletin/2014/02/needle-haystack\r\nPage 3 of 16\n\nFigure 2. Decoy content for e5e183e074d26416d7e6adfb14a80fce6d9b15c2.\r\nWorkbook 3\r\nFilename: LIST OF KEY OFFICIALS IN THE DND PROPER.xls\r\nFile size: 638912 bytes\r\nSHA1: d80b527df018ff46d5d93c44a2a276c03cd43928\r\nMD5: 80857a5541b5804895724c5d42abd48f\r\nThis decoy workbook contains information about key officials in the Philippines Department of National Defense\r\n(DND).\r\nhttps://www.virusbulletin.com/virusbulletin/2014/02/needle-haystack\r\nPage 4 of 16\n\nFigure 3. Decoy content for d80b527df018ff46d5d93c44a2a276c03cd43928.\r\nIn the rest of this article, unless specified otherwise, we refer to the operation resulting from infection via\r\nWorkbook 1 – but the overall operations (dropped filenames, registry keys, backdoor functions) are the same in\r\neach case.\r\nWhen mining our sample collection for related samples we were able to spot other examples – however, in these\r\ninstances the initial dropper was not available for our analysis, only the temporary dropper executables or the final\r\npayloads could be located. In these cases we don’t have complete information about the system infection, but it is\r\nsafe to assume that similar exploitation schemes were utilized.\r\nShellcode\r\nThe shellcode features an interesting anti-debugging trick that I have come across quite regularly in APT samples\r\nlately. Most of the Windows API functions are resolved and called normally, but some of the critical ones (such as\r\nWinExec and CreateFile) are not entered at the entry address (as stored in the kernel32.dll export table), but five\r\nbytes after it instead. These functions are responsible for the most critical operations of the code (dropping the\r\nhttps://www.virusbulletin.com/virusbulletin/2014/02/needle-haystack\r\nPage 5 of 16\n\npayload executable and executing it), which would reveal unusual activity in the scope of an ordinary Excel\r\nprocess.\r\nAs most tracers and debuggers would place the breakpoint or hijack function right at the entry of the API function,\r\nskipping the first few bytes is a good way to avoid API tracing and debugging.\r\nFigure 4. Anti-tracing trick.\r\n(Click here to view a larger version of Figure 4.)\r\nThe same happens with WriteFile and GlobalAlloc, but this time, depending on whether or not there is a call right\r\nat the entry of the function, the displacement will be either five or seven bytes.\r\nFigure 5. Anti-tracing hook initialization.\r\nhttps://www.virusbulletin.com/virusbulletin/2014/02/needle-haystack\r\nPage 6 of 16\n\nAs a result of the functions not being entered at their usual entry points, the first few instructions are missed. As\r\nthese are still essential for the stack management, the code is compensated within the shellcode, where a standard\r\nfunction prologue (stack frame creation push ebp, move ebp,esp) is executed.\r\nFor system functions compiled with standard compilers, the first few instructions are fixed on the entry point, but\r\nanything after that can’t be taken for granted. The shellcode can’t enter further than five or seven bytes into the\r\nAPI function, otherwise it could end up in the middle of a multi byte instruction, easily crashing the application.\r\nFigure 6. Anti-tracing used in practice.\r\nIn order to extract the embedded executable, the shellcode needs to find the carrier workbook. It does this using\r\nthe fact that, at the time of the exploitation, the workbook must remain open in Excel. The code enumerates all\r\npossible handles and tries to call GetFileSize on each of them. If the function fails, because the handle does not\r\nbelong to an open file (it could belong to many other objects such as directory, thread, event or registry key), or\r\nthe file size is smaller than the expected size of the workbook (minus the appended encrypted EXE), 1de10h\r\nbytes, it skips to the next handle value.\r\nNext, it reads four bytes from offset 0x1de00; the value found there should be equal to the size of the carrier\r\nworkbook (this time including the appended EXE).\r\nAt this position, in the appended content following the OLE2 document structure, a short header is stored that\r\ncontains the full carrier workbook size, the embedded EXE size and the embedded decoy workbook size. These\r\nvalues are used by the shellcode. The encrypted EXE content follows.\r\nOrganizing the code and structure in this manner makes the carrier/dropper workbook component and the dropped\r\npayload executable completely independent – it is possible to replace the payload with a new variant without\r\nchanging a bit in the carrier encrypted workbook.\r\nhttps://www.virusbulletin.com/virusbulletin/2014/02/needle-haystack\r\nPage 7 of 16\n\nFigure 7. Appended header and payload.\r\nOnce the hosting workbook is found, the code proceeds with decoding the embedded executable (using a one byte\r\nXOR algorithm with running key plus an additional one byte XOR with a fixed key), saving it to a file named\r\n‘Winword.exe’ in the %TEMP% directory, then executing it. At this point, the decoy workbook content is dropped\r\n(using the same algorithm: one byte XOR with running key plus one byte XOR with fixed key, only this key\r\ndiffers from the one used in decoding the EXE).\r\nTemporary dropper\r\nThis file is the dropper and installer for the final payload. It has an initial anti-debug layer.\r\nThe address of the GetVersion function is patched in the import table, to contain an internal function virtual\r\naddress instead of an imported function address, which is normally expected at that position. The code around the\r\nentry point uses the stored value to redirect execution:\r\nmov large fs:0, esp\r\nsub esp, 58h\r\npush ebx\r\npush esi\r\npush edi\r\nmov [ebp-18h], esp\r\ncall ds:dword_41A188\r\nThe execution actually goes to the address stored at dword_41A188, which is the memory location 00402440.\r\nThe program has only one export, LoadLibrary, thus when the operating system loads the program and resolves\r\nthe external dependencies, this value, stored within the import table region, remains intact. The trick completely\r\nfools IDA Pro, which can’t be convinced that the location is an internal position and not an external import. This\r\nmakes static analysis a bit more complicated. The necessary imported function addresses are later resolved\r\ndynamically by the initialization code of the dropper.\r\nhttps://www.virusbulletin.com/virusbulletin/2014/02/needle-haystack\r\nPage 8 of 16\n\nThe major procedures of the dropper program are not called directly; instead, the trojan builds a function pointer\r\ntable, and calls to procedures are performed via indexing into this table, as shown in Figure 8.\r\nFigure 8. Building the function pointer table.\r\nThe key procedures are identified by having the following instruction sequence near the prologue:\r\npush ebp\r\nmov ebp, esp\r\npush eax\r\nmov eax, 12547908h\r\npop eax\r\nThe value stored in the EAX register is a combination of two elements: 1254 is the marker; 7908 is the numeric\r\nID for the function.\r\nThe entry is located by searching backwards for the standard prologue:\r\npush ebp\r\nmov ebp, esp\r\nThe procedures are later invoked by calling indexes from the function pointer table (see Figure 9).\r\nhttps://www.virusbulletin.com/virusbulletin/2014/02/needle-haystack\r\nPage 9 of 16\n\nFigure 9. Using the function pointer table.\r\nWinword.exe normally drops three major components into the system:\r\n%PROGRAM FILES%\\Common Files\\ODBC\\AppMgmt.dll – the final payload (Windows DLL file)\r\n%PROGRAM FILES%\\Common Files\\DBEngin.EXE – a copy of rundll32.exe (a clean Windows system\r\nfile, used for executing the payload)\r\n%PROGRAM FILES%\\Common Files\\WUAUCTL.EXE – another rundll32.exe (a clean Windows system\r\nfile, used for executing the payload).\r\nAdditionally, two registry export files named jus*.tmp (with a random number added after jus) are dropped into\r\n%TEMP%. These are the old and new hives of the HKLM\\SYSTEM\\CurrentControlSet\\Services\\AppMgmt\r\nregistry location – a location at which the trojan registers itself in order to execute automatically upon each system\r\nboot. Saving the hives to a file makes it possible to modify the registry in one shot using RegRestoreKey.\r\nAlso dropped is a 301,445 byte long jus*.tmp file, which is a CAB archive containing the payload DLL.\r\nThe execution flow takes a different route if the presence of running security products is detected. The following\r\nprocess names are checked: KVMonXP.exe, RavMonD.exe, RsTray.exe, ccsvchst.exe, QQPCTray.exe,\r\nzhudongfangyu.exe, 360sd.exe, 360Tray.exe, zatray.exe, bdagent.exe, ksafetray.exe, kxetray.exe and avp.exe.\r\nHowever, not all of the security processes are checked at the same time – only a couple of selected ones are\r\nchecked before each major operation.\r\nAs an example, if zatray.exe, RsTray.exe or RavMonD.exe is running, then AppMgmt.dll is not dropped and\r\ninstead, the 400MB vbstdcomm.nls is created (the large size is due to an enormous amount of junk appended at\r\nthe end of the file). Finally, a VBScript file is created and executed with the help of a dropped copy of wscript.exe\r\n(both files are saved to the %TEMP% folder, as lgt*.tmp.vbs and lgt*.tmp.exe, respectively). An encrypted copy\r\nof Winword.exe is created in %CommonProgramFiles%\\ODBC\\odbc.txt, using a one byte XOR algorithm with\r\nhttps://www.virusbulletin.com/virusbulletin/2014/02/needle-haystack\r\nPage 10 of 16\n\nkey 0xCC. Vbstdcomm.nls, which serves as a backup installer, takes the encrypted copy of Winword.exe, decodes\r\nit and simply executes.\r\nThe dropper registers AppMgmt.dll as a service. This is not achieved by creating a new service entry, rather by\r\ntaking over the role of an already installed service, AppMgmt, redirecting the service DLL from the clean library\r\nto the dropped malware payload:\r\nHKLM\\SYSTEM\\CurrentControlSet\\Services\\AppMgmt\\Parameters: ServiceDll\r\n%SystemRoot%\\System32\\appmgmts.dll -\u003e C:\\Program Files\\Common Files\\ODBC\\AppMgmt.dll\r\nIn addition, the start up mode is changed from auto to demand in the location:\r\nHKLM\\SYSTEM\\CurrentControlSet\\Services\\AppMgmt: Start\r\nThen it changes the error control settings in the registry key\r\nHKLM\\SYSTEM\\CurrentControlSet\\Services\\AppMgmt:ErrorControl from normal (this would mean that if the\r\ndriver fails to load, the start up process proceeds, but a warning is displayed) to ignore (in this case if the driver\r\nfails to load, start up proceeds, and no warning is displayed). The change is designed to avoid raising suspicion,\r\nshould start up fail for any reason.\r\nFinally, it executes the dropped DLL by executing net start AppMgmt.\r\nPayload\r\nWe have identified five different versions of the final payload. Two of them were replicated from the exploited\r\nworkbooks detailed earlier; the other three were found when we were digging through our sample collection\r\nsearching for samples with similar characteristics.\r\nThe main characteristics of the five variants are summarized in Table 1 shown below (detailed descriptions of the\r\ncolumns are provided later in this section).\r\nhttps://www.virusbulletin.com/virusbulletin/2014/02/needle-haystack\r\nPage 11 of 16\n\n(Click here to view a larger version of Table 1.)\r\nThis DLL is built from the LAME MP3 encoder source [2]. The full library has been compiled, and in addition, a\r\ncouple of malicious exports have been added to the code: lame_set_out_sample and lame_get_out_sample.\r\nFigure 10. Additional malicious imports.\r\nNote that the names of the additional exports are strikingly similar to the legitimate exports,\r\nlame_set_out_samplerate and lame_get_out_samplerate, which are present in the LAME source – thus it is not\r\nvery obvious that the additional exports belong to something completely different.\r\nhttps://www.virusbulletin.com/virusbulletin/2014/02/needle-haystack\r\nPage 12 of 16\n\nOne of the extra exports, lame_get_out_sample, is missing from newer versions of the malware. However, the\r\nfunction that would invoke this export is still present in the code. Clearly, the code was not cleaned up properly\r\nwhen the export was removed.\r\nThe backdoor contains many encrypted strings, one of which serves as an internal version number. In Table 1 we\r\nlist the version numbers as they appear in the code. Collected information suggests that the most widely\r\ndistributed was version 2.3(UDP), making its rounds in the wild in early December 2012.\r\nTable 1 also lists the date when we first saw each particular backdoor variant – either arriving in our collection,\r\nreported in cloud look ups or seen elsewhere on the Internet. Additionally, the compilation date is listed, as taken\r\nfrom the PE header.\r\nAn interesting quirk comes from the usage of the LAME source: one of the original source functions, beVersion(),\r\ninserts the compilation date into the data section of the executable.\r\nFigure 11. Compilation date in code.\r\nThis provides an independent method of determining the creation date of the variant aside from the PE time\r\nstamp. There was no trick, however – the two dates matched in all cases.\r\nIt is notable that there is always a large gap between the compilation date and the date of the first observation of\r\neach variant. There are several possible reasons for this:\r\nSmall-scale targeted attacks don’t provide much telemetry information; the smaller the number of targets,\r\nthe slimmer our chances of finding out about their infection.\r\nThe trojan looks very similar to a real LAME encoder library; infected victims are reluctant to submit it for\r\nanalysis.\r\nThere may be an intentional delay (some sort of testing period) in the release process of the malware.\r\nhttps://www.virusbulletin.com/virusbulletin/2014/02/needle-haystack\r\nPage 13 of 16\n\nThe backdoor uses different approaches for handling C\u0026C communication. Earlier versions used the standard\r\nWindows socket communication functions (send, recv) to exchange data with the C\u0026C server. The newer versions\r\nlinked the UDT data transfer library (available from udt.sourceforge.net) for communication. The versioning of\r\nthe variants suggests that some time around March 2012, the code forked into a socket communication branch\r\n(TCP) and a UDT powered communication branch (UDP).\r\nThe backdoor features all the basic functionality that is expected from a piece of malware of its class. It is able to:\r\nCreate screenshots\r\nGet drive type (FAT, FAT32, NTFS, CDFS) and free space\r\nEnumerate files and directories and send the list to the server\r\nRename files\r\nCreate directories\r\nDelete files.\r\nThe last character of the ModuleFileName (without extension) is checked on execution: if it is not of one of the\r\nexpected values – ‘T’, ‘t’ (executed via net.exe), ‘R’, ‘r’, ‘N’, ‘n’ (executed via DBEngin.EXE), ‘2’ (rundll32.exe),\r\n‘L’ or ‘l’ – it builds and injects a simple piece of code to load AppMgmt.dll properly.\r\nFor this purpose, it creates a new suspended process (with command line: c:\\windows\\system32\\svchost.exe),\r\ncalls GetThreadContext on it, and gets EAX from the CONTEXT structure, using the fact that in the case of a\r\nsuspended process the EAX register always points to the entry point of the process. Then it writes the starter code\r\nto this entry point and resumes the thread. The suspended thread is not visible in the process list at that point. This\r\nway, the trojan can escape analysis, if not executed in a natural form, and still execute.\r\nConfiguration data is stored in a file named DbTrans.db, XOR encrypted with key 0x58.\r\nThe string constants (API names, DLL names, process names) are all stored in encrypted form using a strong\r\nencryption algorithm. The strings are stored aligned (Unicode strings to 0x90 bytes, ASCII strings to 0x38 bytes\r\nboundary), decrypted in eight byte chunks using the DES ECB algorithm, and referenced by IDs that index into\r\nthis name pool. The encrypted strings contain padding bytes at the end, where zeros are encoded.\r\nThe strings are decrypted on the fly before being used and filled with zeros after use. This way there are no visible\r\nstrings in the memory that would give away more information about the internals of the backdoor.\r\nThere are three nearly identical encryption functions (and accompanying encrypted string tables and encryption\r\nkeys) in all variants: one is for the Unicode strings, one for the ordinary ASCII constants, and a third one for the\r\nWindows API function names (also stored as ASCII strings) that are used in the code. We found that only the\r\nencryption keys were different for the three cases. The following key seeds remain the same throughout the\r\nvariants:\r\nFor ASCII strings: 82 C5 D3 59 2B 38 00 00\r\nhttps://www.virusbulletin.com/virusbulletin/2014/02/needle-haystack\r\nPage 14 of 16\n\nFor Unicode strings: 5E 97 CC 42 8E CD 00 00\r\nFor API function names: 5B 5F CB 8D E5 F5 00 00\r\nIn the last version, the two ASCII functions are merged into a single function.\r\nThe C\u0026C addresses are hard coded into the backdoor, and protected with a simple byte wise XOR (key:0x58)\r\nencryption. This is an interesting choice, given that all other string constants are protected with a string DES\r\nalgorithm – perhaps the server addresses are changed more frequently (indeed, there is a minimal overlap between\r\nthe different versions’ C\u0026C addresses) than the authors are comfortable with re-encrypting the strings – but no\r\nevidence was found for it in the few samples we have found.\r\nThe string constants of the code are referenced by IDs and decrypted on the fly. However, there are strings that are\r\nnever used in the code. These could belong to an earlier or internal version, and simply have not been cleaned up\r\nfrom the string pool, as illustrated in this example:\r\npush 9 ; ,lame_set_out_sample\r\ncall Get_String_A\r\npush 0Ah ; ,\r\ncall Get_String_A\r\npush 1Eh ; DBEngin.exe\r\ncall Get_String_A\r\npush 8 ; EXPL.EXE\r\npop eax\r\ncall Get_String_W\r\npush offset s_expl_exe\r\npush [ebp+var_254]\r\ncall StrCpyW\r\npush 8\r\npop eax\r\nxor ecx, ecx\r\ncall set_mem\r\npush ebx\r\npush 2\r\ncall CreateToolhelp32Snapshot\r\nSome of these strings could be internal configuration options for the development environment (I suspect these are\r\naccess details to an internal server):\r\nkazafei\r\n192.168.1.98\r\n80\r\nOther strings provide status information about the current operation of the backdoor:\r\nhttps://www.virusbulletin.com/virusbulletin/2014/02/needle-haystack\r\nPage 15 of 16\n\nClient RecvData Complete\r\nA File Search Task has start already !!!\r\nFile Search Task Success\r\nFile Search Task Failed, Please Check\r\nUpload Client Failed\r\nUpload Client Success\r\nDelete File Success\r\nDelete File Failed\r\nRename File Success\r\nRename File Failed\r\nCreate Folder Success\r\nCreate Folder Failed\r\nA few constants indicate undocumented or debug functionality:\r\nX:\\Windows\\System32\\rundll32.exe\r\nX:\\Windows\\msacm32.drv\r\nMagicMutex\r\nD:\\Resume.dll\r\nD:\\delete.dll\r\nD:\\delete2.dll\r\nConclusion\r\nWhen looking into APT attack scenarios, one has to be extra careful. Often we see that clean programs and\r\nlibraries are dropped onto systems to hide the operation of malicious applications [3]. But sometimes, what looks\r\nto be a genuine MP3 encoder library, and even works as a functional encoder, actually hides malicious additions\r\nburied deep in a large pile of clean code. One has to be very thorough when it comes to targeted attacks, and one\r\ncannot afford to make any assumptions.\r\nBibliography\r\nSource: https://www.virusbulletin.com/virusbulletin/2014/02/needle-haystack\r\nhttps://www.virusbulletin.com/virusbulletin/2014/02/needle-haystack\r\nPage 16 of 16\n\nencryption keys variants: were different for the three cases. The following key seeds remain the same throughout the\nFor ASCII strings: 82 C5 D3 59 2B 38 00 00 \n   Page 14 of 16",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MISPGALAXY",
		"MITRE",
		"Malpedia"
	],
	"references": [
		"https://www.virusbulletin.com/virusbulletin/2014/02/needle-haystack"
	],
	"report_names": [
		"needle-haystack"
	],
	"threat_actors": [],
	"ts_created_at": 1775434005,
	"ts_updated_at": 1775791298,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/a6cea6411ab8aeb9b154b5a8c91ac347cf6d2e22.pdf",
		"text": "https://archive.orkl.eu/a6cea6411ab8aeb9b154b5a8c91ac347cf6d2e22.txt",
		"img": "https://archive.orkl.eu/a6cea6411ab8aeb9b154b5a8c91ac347cf6d2e22.jpg"
	}
}