{
	"id": "503a88c6-1d0d-424d-84e1-57a353f36f35",
	"created_at": "2026-04-06T00:10:16.38962Z",
	"updated_at": "2026-04-10T13:12:29.505348Z",
	"deleted_at": null,
	"sha1_hash": "9ce65abb88d932c5c4d45561719883c2938e3b8b",
	"title": "A Case of Vidar Infostealer - Part 1 (Unpacking)",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 971151,
	"plain_text": "A Case of Vidar Infostealer - Part 1 (Unpacking)\r\nPublished: 2022-03-27 · Archived: 2026-04-05 19:04:55 UTC\r\nHi, in this post, I’ll be unpacking and analyzing Vidar infostealer from my BSides Islamabad 2021 talk. Initial\r\nstage sample comes as .xll file which is Excel Add-in file extension. It allows third party applications to add extra\r\nfunctionality to Excel using Excel-DNA, a tool or library that is used to write .NET Excel add-ins. In this case, xll\r\nfile embeds malicious downloader dll which further drops packed Vidar infostealer executable on victim machine,\r\ninvestigating whole infection chain is out of scope for this post, however I’ll be digging deep the dropped\r\nexecutable (Packed Vidar) in Part1 of this blogpost and final infostealer payload in Part2.\r\nSHA256: 5cd0759c1e566b6e74ef3f29a49a34a08ded2dc44408fccd41b5a9845573a34c\r\nTechnical Analysis\r\nI usually start unpacking general malware packers/loaders by looking it first into basic static analysis tools, then\r\nopening it into IDA and taking a bird’s eye view of different sections for variables with possible encrypted strings,\r\nkeys, imports or other global variables containing important information, checking if it has any crypto signatures\r\nidentified and then start debugging it. After loading it into x64dbg, I first put breakpoint on memory allocation\r\nAPIs such as LocalAlloc, GlobalAlloc, VirtualAlloc and memory protection API: VirtualProtect, and hit run\r\nbutton to see if any of the breakpoints hits. If yes, then it is fairly simple to unpack it and extract next stage\r\npayload, otherwise it might require in-depth static and dynamic analysis. Let’s hit run button to see where it takes\r\nus next.\r\nShellcode Extraction\r\nHere we go, the first breakpoint hits in this case, is VirtualProtect, being called on a stack memory region of size\r\n0x28A to grant it Execute Read Write (0x40) protection, strange enough right!\r\nhttps://xer0xe9.github.io/A-Case-of-Vidar-Infostealer-Part-1-(-Unpacking-)/\r\nPage 1 of 12\n\nFigure1\r\nfirst few opcodes E9, 55, 8B in dumped data on stack correspond to jmp, push and mov instructions respectively,\r\nso it can be assumed it is shellcode being pushed on stack and then granted Execute protection to later execute it,\r\nIf I hit execute till return button on VirtualProtect and trace back from it into disassembler, I can see shellcode\r\nstored as stack strings right before VirtualProtect call and list of arguments are pushed as shown in the figure\r\nbelow\r\nhttps://xer0xe9.github.io/A-Case-of-Vidar-Infostealer-Part-1-(-Unpacking-)/\r\nPage 2 of 12\n\nfollowing few statements are preparing to execute shellcode on stack by retrieving a handle to a device context\r\n(DC) object and passing this handle to GrayStringA to execute shellcode from stack (ptr value in eax taken from\r\nFigure1)\r\nlet’s now start exploring the shellcode.\r\nDebugging shellcode to extract final payload\r\nAs soon as, GrayStringA executes, it hits on VirtualAlloc breakpoint set in the debugger, which is being called\r\nto reserver/commit 0xAA3CE size of memory with MEM_COMMIT | MEM_RESERVE (0x3000) memory\r\nallocation type\r\nreturning control from VirtualAlloc and stepping over one more time from ret, leads us to the shellcode, next few\r\nstatements after VirtualAlloc call are pushing pointer to newly created buffer, size of the buffer and the file handle\r\nfor currently loaded process on stack to call ReadFile\r\nhttps://xer0xe9.github.io/A-Case-of-Vidar-Infostealer-Part-1-(-Unpacking-)/\r\nPage 3 of 12\n\nwhich reads 0xAA3CE bytes of data from parent process image into the buffer, let’s say it buffer1\r\nfurther execution again hits at VirtualAlloc breakpoint, this time allocating 0x14F0 bytes of memory, I’ll now put\r\na write breakpoint in the memory region reserved/committed by second VirtualAlloc API call to see what and how\r\ndata gets dumped into second buffer, buffer2. Hitting Run button once more will break at instruction shown in the\r\nfigure below\r\nhttps://xer0xe9.github.io/A-Case-of-Vidar-Infostealer-Part-1-(-Unpacking-)/\r\nPage 4 of 12\n\nthis loop is copying 0x14F0 bytes of data from a certain offset of buffer1 into buffer2, next few statements are\r\nagaian calling VirtualAlloc to allocate another 0x350DE bytes of memory say buffer3, pushing returned buffer\r\naddress along with an offset from buffer1 on stack to copy 0x350DE bytes of data from buffer1 into buffer3\r\nloop in the following figure is decrypting data copied to buffer2, next push instruction is pushing the buffer3\r\npointer on stack as an argument of the routine being called from buffer2 address in edx which is supposed to\r\nprocess buffer3 contents\r\nhttps://xer0xe9.github.io/A-Case-of-Vidar-Infostealer-Part-1-(-Unpacking-)/\r\nPage 5 of 12\n\nfigure below is showing final buffer2 decrypted contents\r\nhttps://xer0xe9.github.io/A-Case-of-Vidar-Infostealer-Part-1-(-Unpacking-)/\r\nPage 6 of 12\n\nstepping into edx starts executing buffer2 contents, where it seems to push stack strings for kernel32.dll first and\r\nthen retrieves kernel32.dll handle by parsing PEB (Process Environment Block) structure\r\nretrieved kernel32.dll handle is passed to next call along with another argument with constant FF7F721A value, a\r\nquick Google search for this constant results in some public sandbox links but not clear what is this exactly about.\r\nLet’s dig into it further, stepping over this routine 0x0A4E results in GetModuleFileNameW API’s resolved\r\naddress from Kernel32.dll stored in eax which means this routine is meant to resolve hashed APIs\r\nhttps://xer0xe9.github.io/A-Case-of-Vidar-Infostealer-Part-1-(-Unpacking-)/\r\nPage 7 of 12\n\nsimilarly second call resolves 7F91A078 hash value to ExitProcess API, wrapper routine 0x0A4E iterates over\r\nlibrary exports and routine 0x097A is computing hash against input export name parameter. Shellcode seems to be\r\nusing a custom algorithm to hash API, computed hash value is retuned back into eax which is compared to the\r\ninput hash value stored at [ebp-4], if both hash values are equal, API is resolved and its address is stored in eax\r\nnext few instructions write some junk data on stack followed by pushing pointer to buffer3 and total size of\r\nbuffer3 contents (0x350C0) on stack and execute routine 0x0BE9 for decryption - this custom decryption scheme\r\nworks by processing each byte from buffer3 using repetitive neg, sub, add, sar, shl, not, or and xor set of\r\ninstructions with hard-coded values in multiple layers, intermediate result is stored in [ebp-1]\r\nhttps://xer0xe9.github.io/A-Case-of-Vidar-Infostealer-Part-1-(-Unpacking-)/\r\nPage 8 of 12\n\nand final value overwrites the corresponding buffer3 value at [eax] offset\r\nhttps://xer0xe9.github.io/A-Case-of-Vidar-Infostealer-Part-1-(-Unpacking-)/\r\nPage 9 of 12\n\nonce buffer3 contents are decrypted, it continues to resolve other important APIs in next routine 0x0FB6\r\nhttps://xer0xe9.github.io/A-Case-of-Vidar-Infostealer-Part-1-(-Unpacking-)/\r\nPage 10 of 12\n\nI wrote a simple POC python script for hashing algorithm implemented by decrypted shellcode which can be\r\nfound here\r\nafter all required APIs have been resolved, it proceeds to create a new process\r\nusing CreateProcessW in suspended mode\r\nhttps://xer0xe9.github.io/A-Case-of-Vidar-Infostealer-Part-1-(-Unpacking-)/\r\nPage 11 of 12\n\nand then final payload is injected into newly created process using SetThreadContext API, CONTEXT structure\r\nfor remote thread is set up with ContextFlag and required memory buffers and SetThreadContext API is called\r\nwith current thread handle and remote thread CONTEXT structure for code injection\r\nmain process terminates right after launching this process, we can now take a dump of this process to extract final\r\npayload.\r\nThat’s it for unpacking! see you soon in the next blogpost covering detailed analysis of Vidar infostealer.\r\nSource: https://xer0xe9.github.io/A-Case-of-Vidar-Infostealer-Part-1-(-Unpacking-)/\r\nhttps://xer0xe9.github.io/A-Case-of-Vidar-Infostealer-Part-1-(-Unpacking-)/\r\nPage 12 of 12",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://xer0xe9.github.io/A-Case-of-Vidar-Infostealer-Part-1-(-Unpacking-)/"
	],
	"report_names": [
		"A-Case-of-Vidar-Infostealer-Part-1-(-Unpacking-)"
	],
	"threat_actors": [],
	"ts_created_at": 1775434216,
	"ts_updated_at": 1775826749,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/9ce65abb88d932c5c4d45561719883c2938e3b8b.pdf",
		"text": "https://archive.orkl.eu/9ce65abb88d932c5c4d45561719883c2938e3b8b.txt",
		"img": "https://archive.orkl.eu/9ce65abb88d932c5c4d45561719883c2938e3b8b.jpg"
	}
}