{
	"id": "4a68b196-16da-4b57-931c-fe88f16e8991",
	"created_at": "2026-04-06T00:14:07.99146Z",
	"updated_at": "2026-04-10T03:21:40.613557Z",
	"deleted_at": null,
	"sha1_hash": "deb2e800ec3aeb975cc6efdbbdf685b3c8928a8b",
	"title": "New Ursnif Malware Variant – a Stunning Matryoshka (Матрёшка)",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 78197,
	"plain_text": "New Ursnif Malware Variant – a Stunning Matryoshka\r\n(Матрёшка)\r\nBy sharon\r\nPublished: 2019-01-30 · Archived: 2026-04-05 17:54:31 UTC\r\nUrsnif malware is an information stealing/banking Trojan that has been around since 2016 and continues to\r\nevolve. Its capabilities include stealing of:\r\nSystem information\r\nList of installed applications\r\nList of installed drivers\r\nList of running processes\r\nList of network devices\r\nExternal IP address\r\nEmail credentials (IMAP, POP3, SMTP)\r\nCookies\r\nCertificates\r\nScreen video captures (.AVI)\r\nFinancial information via webinjects\r\nRecently, a new variant of Ursnif malware emerged, targeting Italian users via a spam email campaign.\r\nthe Cyberbit Malware Research team investigated this new variant and discovered that it has a lot of encryption,\r\nobfuscation and compressions techniques. Some are well known, some are custom made for this new variant.\r\nThese techniques can be used to hide from anti-virus products – as they hide the real payload and its malicious\r\nAPI calls/strings.\r\nWe determined that this sample also performs process hollowing using direct system calls – a technique we\r\ncovered thoroughly in our last article. The direct system calls injection can be used to bypass user mode hooks in\r\ncases when the patch guard mechanism is present and SSDT hooks can’t be placed.\r\nThis article will focus on reverse engineering of the encryption, obfuscation and compression techniques in this\r\nsample. SHA256 of the sample analyzed here is\r\n81798ea125359ca4e618a5619cd856f95f3fb809f5f3022a42563bd3b627f2ca\r\nThe decryption phases are summed up in this table and the flow chart. Detailed descriptions follow below.\r\nPhase\r\nEncrypted\r\ncode/data\r\nlocation\r\nDestination of\r\ndecrypted\r\ndata\r\nDecrypted data\r\ncontent\r\nDecryption\r\nalgorithms used\r\nDecryption\r\nalgorithms \r\nlocation\r\nhttps://www.cyberbit.com/blog/endpoint-security/new-ursnif-malware-variant/\r\nPage 1 of 6\n\n1\r\n.rdata\r\nsection of\r\nmain\r\nmodule\r\nHeap\r\nDecryption algorithm\r\nno.2 and the algorithms\r\nat phase 2 (encrypted)\r\nDecryption\r\nalgorithm no.1\r\n.text section\r\nof main\r\nmodule\r\n2  Heap Stack\r\nDeobfuscation (Byte-Swapping) algorithm\r\nand decryption\r\nalgorithm no.3\r\nDecryption\r\nalgorithm no.2\r\nHeap\r\n3\r\n.rdata\r\nsection of\r\nmain\r\nmodule\r\nNew\r\nallocation by\r\nVirtualAlloc\r\n(Region 1)\r\nUrsnif main PE\r\ncompressed with\r\nLighty Compressor and\r\nXORed with 0x7B,\r\nCode for process\r\nhollowing with direct\r\nsystem calls\r\nDeobfuscation\r\n(Byte-Swapping)\r\nalgorithm and\r\ndecryption\r\nalgorithm no.3\r\nStack\r\n4 Region 1\r\nNew\r\nallocation by\r\nVirtualAlloc\r\n(Region 2)\r\nUrsnif main PE\r\nLighty Compressor\r\nDecompression\r\nAlgorithm and a\r\nXOR with 0x7B\r\nRegion 1\r\nUrsnif Malware Decryption Phases\r\nUrsnif Malware stages\r\nThe NX (Non-Executable) bit\r\nThe PE file structure contains a header called Optional header. In this header, there is a field called\r\nDllCharacteristics. One of the values of this field is IMAGE_DLLCHARACTERISTICS_ NX_COMPAT\r\n(0x0100), also known as the NX-bit.\r\nIf this value is set, the processor will not execute any code that resides in specific memory areas. This is done in\r\norder to prevent code being executed from a forbidden memory area, for example; The heap and the stack.\r\nIf the NX-bit is not set, code can be executed from these memory areas and buffer overflow attacks will be easier\r\nto implement on the targeted process.\r\nThe new variant of Ursnif was compiled with the NX-bit not set. We will see how it utilizes it to execute code\r\nfrom both the Heap and the Stack of its process.\r\nUrsnif Malware executable\r\nFigure 1 – A screenshot from CFF explorer shows that the NX-bit of Ursnif executable is not set\r\nhttps://www.cyberbit.com/blog/endpoint-security/new-ursnif-malware-variant/\r\nPage 2 of 6\n\nFirst layer of ursnif malware encryption\r\nUrsnif begins its first unpacking stage with a decryption function located at 0x406110. The encrypted code resides\r\nat the .rdata section of the main module of the process at address 0x429AA0 and its size is 1910 (0x776) bytes.\r\nUrsnif Malware 2\r\nFigure 2 – Part of the first decryption function. In line 286 you can see it is looping through all 1910 bytes of the\r\nencrypted code\r\nBecause the NX-bit of the image is off, code can be executed from the heap, even though it has Read-Write\r\nprotection. The decrypted code is placed on the heap. This what the code looks like before and after decryption:\r\nUrsnif Malware 3\r\nFigure 3 – The code before decryption (above) and after decryption. The decrypted code is placed on the heap\r\nThe decryption function is huge but after  reverse engineering, the decryption algorithm is only a few lines. Most\r\nof the instructions do not directly/indirectly affect the decryption. It can be written as the following pseudo code\r\n(This sample is a 32-bit image):\r\nfor (i = 0; i \u003c 1910; i++):\r\nx = (i + 0x7F) * (0xFFFFFF82) * (i + 1)\r\ny = sign_extend(enc[i]) + x\r\nz = lowest_byte(y)\r\nt = sign_extend(z)\r\ndec[i] = lowest_byte(not(t))\r\nDefinitions:\r\nenc, dec – The pointer to the encrypted/decrypted buffer.\r\nenc[i], dec[i] –  the byte located at the encrypted/decrypted buffer at location i.\r\nlowest_byte – the lowest byte (least significant byte) of the 32-bit DWORD.\r\nsign_extend – equivalent to the movsx assembly instruction.\r\nExplanation for sign_extend:\r\nif  z = 0x4E (01001110 in binary), the sign of z is its most significant bit –  0. It means that z is a positive number,\r\nso the rest of the bits of t will be filled with the sign of the byte (0), hence t = 0x0000004E.\r\nhttps://www.cyberbit.com/blog/endpoint-security/new-ursnif-malware-variant/\r\nPage 3 of 6\n\nIf z = 0xAE (10101110), the sign of z is its most significant bit –  1. It means that z is a negative number, so the\r\nrest of the bits of t will be filled with the sign of the byte (1), hence t = 0xFFFFFFAE (because 0xF = 1111 in\r\nbinary)\r\nnot – equivalent to the not assembly instruction – flipping all the bits (from 0 to 1 or vice versa)\r\nNote – the sign_extend function does not affect the result of the decryption because we look only on the least\r\nsignificant byte. It is noted here for the sake of accuracy.\r\nSecond layer of encryption\r\nThe code that was unpacked to the heap has two parts. The first part decrypts the 2nd part from the heap to the\r\nstack. The stack is another memory area from which code should not be executed, but since the NX-bit is off, the\r\nprocessor will execute it. You can see in figure 4 that part of the code on the heap isn’t actually code that makes\r\nsense – This is the 2nd part which is encrypted. Its size is 958 (0x3BE) bytes and has a rather simple decryption\r\nalgorithm:\r\nfor (i = 0; i \u003c 958; i++):\r\ndec[i] = lowest_byte(enc[i] – 0x11B599c)\r\nUrsnif Malware 4\r\nFigure 4 – Part of the decrypted code on the heap which is encrypted by itself\r\nUrsnif malware 5\r\nFigure 5 – The instructions inside the red rectangle performs the decryption. The last instruction on this figure\r\n(call eax), executes the decrypted code\r\nThird layer of encryption\r\nThe decrypted code on the stack looks for the address of kernel32.dll on the PEB, and then for the address of\r\nGetProcAddress from this module. Using GetProcAddress it fetches the VirtualAlloc address. You can see the\r\ncharacters ‘G’, ‘P’, and ‘A’ on the stack in figure 6. They are accustomed to looking for the address of\r\nGetProcAddress. Using VirtualAlloc it allocates a buffer of 74280 (0x12228) bytes. The buffer is filled with an\r\nencrypted code that lies in the .rdata section of the malware’s process at address 0x417873.\r\nUrsnif Malware 6\r\nFigure 6 – Fetching the address of the PEB. The letters ‘G’, ‘P’, and ‘A’ are later used to fetch the address of\r\nkernel32.GetProcAddress\r\nUrsnif Malware 7\r\nFigure 7 – VirtualAlloc letters on the stack and a call to GetProcAddress(VirtualAlloc)\r\nhttps://www.cyberbit.com/blog/endpoint-security/new-ursnif-malware-variant/\r\nPage 4 of 6\n\nThe code in the buffer is both obfuscated and encrypted. It first goes through deobfuscation using this byte-swapping algorithm:\r\nx = 0x12227 * 0x5B + 0x15\r\nfor (i = 74279; i \u003e= 0; i–):\r\ny = x\r\nremainder = y % 0x12228\r\ntemp = buf[remainder]\r\nx = x – 0x5B\r\nbuf[remainder] = buf[i]\r\nbuf[i] = temp\r\nUrsnif Malware 8\r\nFigure 8 – The byte-swapping (deobfuscation) algorithm\r\nAfter the deobfusction, the buffer goes through this decryption algorithm:\r\nfor (i = 0; i \u003c 74280; i++):\r\nx = (i + 1) XOR 0xBC XOR ( (i + 1) * 0xBC )\r\ny = lowest_byte(enc[i] – x)\r\ndec[i] = lowest_byte(y – ((i + 1) XOR 0xF5))\r\nUrsnif Malware 9\r\nFigure 9 – The decryption routine\r\nAfter this decryption, the code in the buffer is executed.\r\nLast layer – Compressed Ursnif PE \u0026 Process Hollowing Using System Calls\r\nThe code in the buffer continues the unpacking process. It allocates a new buffer of 41984 (0xA400) bytes. It\r\ndecompresses to this buffer the Ursnif PE (XORed with 0x7B) that lies within itself. The Ursnif PE is compressed\r\nusing a compressor called “Lighty Compressor” and its decompression algorithm can be seen in figure 10. When\r\nthe decompression finishes, the new buffer is XORed with 0x7B and finally we have in memory the last PE of\r\nUrsnif, with its .bss section.\r\nYou can read more about the “Lighty Compressor” here. For your convenience, I have copied here  .asm file from\r\nthe previous link for direct download. This .asm file decompresses a Lighty-Compressed file. You just need to fill\r\nhttps://www.cyberbit.com/blog/endpoint-security/new-ursnif-malware-variant/\r\nPage 5 of 6\n\nin the input file, output file name and the output file size (this is the size allocated by VirtualAlloc in the last\r\nexample). Compile it with FASM.\r\nThis final PE is injected using process hollowing via direct system calls, with the original file as the hollowed\r\nprocess. The malware functionality continues in the hollowed process.\r\nUrsnif Malware 10\r\nFigure 10 – Part of the Lighty Compressor decompression algorithm\r\nUrsnif Malware 11\r\nFigure 11 – In the upper box, you can see the XORing of the decompressed PE file. In the lower box you can see\r\nhow the buffer looks after XORing, the first two bytes were XORed and are now MZ – the PE magic\r\nAs most modern malware do and as we talked about in our previous article, this variant rears its head with the\r\ninfamous direct system calls injection method. It reads a copy of ntdll.dll from the disk in order to copy the system\r\ncall numbers, creates a suspended process of itself and injects the final unpacked main Ursnif PE into it by direct\r\nsystem calls. It does it in a way very similar to Trickbot and it also uses CRC32 for hashing Windows API\r\nfunctions’ names.\r\nHod Gavriel is a Malware Analyst at Cyberbit.\r\nWatch FREE webcast to learn How to Prevent the Next Financial Cyberattack with Next-Gen Technology\r\nSource: https://www.cyberbit.com/blog/endpoint-security/new-ursnif-malware-variant/\r\nhttps://www.cyberbit.com/blog/endpoint-security/new-ursnif-malware-variant/\r\nPage 6 of 6",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"ETDA",
		"Malpedia"
	],
	"references": [
		"https://www.cyberbit.com/blog/endpoint-security/new-ursnif-malware-variant/"
	],
	"report_names": [
		"new-ursnif-malware-variant"
	],
	"threat_actors": [],
	"ts_created_at": 1775434447,
	"ts_updated_at": 1775791300,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/deb2e800ec3aeb975cc6efdbbdf685b3c8928a8b.pdf",
		"text": "https://archive.orkl.eu/deb2e800ec3aeb975cc6efdbbdf685b3c8928a8b.txt",
		"img": "https://archive.orkl.eu/deb2e800ec3aeb975cc6efdbbdf685b3c8928a8b.jpg"
	}
}