在【Day 27】Cmd 指令很乱,主办单位要不要管一下 (上) - Cmd 指令混淆我们说明了指令混淆的用处与侦测方法,也介绍一些指令混淆的技巧,这篇要继续介绍更多混淆的技巧。
括弧中的指令会被当作是一组指令,无意义的括弧可以用来混淆指令,以下举个例子。
# cmd /c ( (powershell))
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
这个混淆技巧可以绕过动态侦测,如下图 Sysmon 日志。
,
、;
在指令中可以取代空白作为指令参数之间的分割字元,它们可以任意被插入在参数之间需要空白的地方,以下用 netstat
举例。
# cmd;;,,/c,;netstat
Active Connections
这个混淆技巧可以绕过动态侦测,如下图 Sysmon 日志。
call
在 Cmd 指令中用来执行另一段指令,虽然它本身不是用来做混淆的,但是却可以让混淆的行为更低调。首先看看下面的例子,可以观察到例子中用 &&
串接两个指令,第一个设定环境变数,第二个印出环境变数。然而在没有 call
或 cmd /c
的情况下,直接 echo
不会把环境变数转成设定的值,因为同个 Cmd.exe Session 不会自动转换环境变数。
# cmd /c "set test=net&&echo %test%"
%test%
# cmd /c "set test=net&&call echo %test%"
net
# cmd /c "set test=net&&cmd /c echo %test%"
net
call
和 cmd /c
都会转换环境变数,但是两者的差别在於 call
不会产生 Child Process;而 cmd /c
会。因此使用 call
会比 cmd /c
更低调。
与 For Loop Value Extraction 不同,For-Loop Encoding 不会使用 Tokens、Delims 的方式拼凑出指令,而是直接写 For 回圈把需要的字元从环境变数的目标 Index 取出。
首先先来看看指令中 For 的用法,以下的例子会把 (0 1 2 3)
照顺序印出来。
# cmd /c "for %a in (0 1 2 3) do echo %a"
# echo 0
0
# echo 1
1
# echo 2
2
# echo 3
3
也可以在 For 回圈後加入条件判断,以下例子判断如果目前回圈跑到的值为 a
就印出 haha
。
# cmd /c "for %a in (0 1 2 a) do if %a==a (call echo haha) else (call echo %a)"
# if 0 == a (call echo haha ) else (call echo 0 )
0
# if 1 == a (call echo haha ) else (call echo 1 )
1
# if 2 == a (call echo haha ) else (call echo 2 )
2
# if 3 == a (call echo haha ) else (call echo 3 )
3
# if a == a (call echo haha ) else (call echo a )
haha
以上的 For 回圈使用方法再配上前面环境变数的混淆技巧,就可以做到把指令混淆的效果。以下例子最终会执行 netstat /ano
。先设两个环境变数 final
、unique
,final
会存放最终要执行的指令,一开始是空的。接着回圈的每一轮都会从 unique
取出一个字元并添加在 final
後面。最後会判断目前回圈跑到的 Index 是否为 a
,是的话就 call %final%
执行指令。
# cmd /c "set final= &&set unique=nets /ao&&for %a in (0 1 2 3 2 6 2 4 5 6 0 7 a) do if %a==a (call %final%) else (call set final=%final%%unique:~%a,1%)
# if 0 == a (call %final% ) else (call set final=%final%%unique:~0,1% )
# if 1 == a (call %final% ) else (call set final=%final%%unique:~1,1% )
# if 2 == a (call %final% ) else (call set final=%final%%unique:~2,1% )
# if 3 == a (call %final% ) else (call set final=%final%%unique:~3,1% )
# if 2 == a (call %final% ) else (call set final=%final%%unique:~2,1% )
# if 6 == a (call %final% ) else (call set final=%final%%unique:~6,1% )
# if 2 == a (call %final% ) else (call set final=%final%%unique:~2,1% )
# if 4 == a (call %final% ) else (call set final=%final%%unique:~4,1% )
# if 5 == a (call %final% ) else (call set final=%final%%unique:~5,1% )
# if 6 == a (call %final% ) else (call set final=%final%%unique:~6,1% )
# if 0 == a (call %final% ) else (call set final=%final%%unique:~0,1% )
# if 7 == a (call %final% ) else (call set final=%final%%unique:~7,1% )
# if a == a (call %final% ) else (call set final=%final%%unique:~a,1% )
Active Connections
这个混淆技巧可以绕过动态侦测,如下图 Sysmon 日志。
这个混淆技巧也是使用 For 回圈,不过参数中会使用 /L
,用法有点像 Python 的 in range()
,使用者可以自己定义回圈的范围。以下例子使用 For 回圈从 3 开始,每次减 1,直到 0 为止,每次回圈都会印出目前的数字。
# cmd /c "for /L %a in (3 -1 0) do echo %a"
# echo 3
3
# echo 2
2
# echo 1
1
# echo 0
0
知道 for /L
的使用方法之後,直接看看它用来混淆的例子。我们设一个环境变数 rev
存 netstat /ano
的反转字串,然後用 For 回圈从最後一个字元开始往回一一添加在环境变数 final
後。当回圈跑到 0 时就执行 %final%
。
# cmd /c "set final= &&set rev=ona/ tatsten&&for /l %a in (11 -1 0) do call set final=%final%%rev:~%a,1%&&if %a==0 call %final%
# call set final=%final%%rev:~11,1% && if 11 == 0 call %final%
# call set final=%final%%rev:~10,1% && if 10 == 0 call %final%
# call set final=%final%%rev:~9,1% && if 9 == 0 call %final%
# call set final=%final%%rev:~8,1% && if 8 == 0 call %final%
# call set final=%final%%rev:~7,1% && if 7 == 0 call %final%
# call set final=%final%%rev:~6,1% && if 6 == 0 call %final%
# call set final=%final%%rev:~5,1% && if 5 == 0 call %final%
# call set final=%final%%rev:~4,1% && if 4 == 0 call %final%
# call set final=%final%%rev:~3,1% && if 3 == 0 call %final%
# call set final=%final%%rev:~2,1% && if 2 == 0 call %final%
# call set final=%final%%rev:~1,1% && if 1 == 0 call %final%
# call set final=%final%%rev:~0,1% && if 0 == 0 call %final%
Active Connections
上面这个例子已经让人眼花撩乱了,不过还可以更混淆一点。for /L
後面接的范围每次不一定只能递减 1,可以递减任意值。所以原本的环境变数 rev
是放 netstat /ano
的反转字串,现在可以在指令之间塞入混淆用的字元。以下例子把原本的 rev
字串的每个字元之间插入 X
,并把 for /L
的递减值改为 2。
# cmd /c "set final= &&set rev=oXnXaX/X XtXaXtXsXtXeXn&&for /l %a in (22 -2 0) do call set final=%final%%rev:~%a,1%&&if %a==0 call %final%
# call set final=%final%%rev:~22,1% && if 22 == 0 call %final%
# call set final=%final%%rev:~20,1% && if 20 == 0 call %final%
# call set final=%final%%rev:~18,1% && if 18 == 0 call %final%
# call set final=%final%%rev:~16,1% && if 16 == 0 call %final%
# call set final=%final%%rev:~14,1% && if 14 == 0 call %final%
# call set final=%final%%rev:~12,1% && if 12 == 0 call %final%
# call set final=%final%%rev:~10,1% && if 10 == 0 call %final%
# call set final=%final%%rev:~8,1% && if 8 == 0 call %final%
# call set final=%final%%rev:~6,1% && if 6 == 0 call %final%
# call set final=%final%%rev:~4,1% && if 4 == 0 call %final%
# call set final=%final%%rev:~2,1% && if 2 == 0 call %final%
# call set final=%final%%rev:~0,1% && if 0 == 0 call %final%
Active Connections
这个混淆技巧可以绕过动态侦测,如下图 Sysmon 日志。
全名为 Fin-Style Encoding,因为 APT 组织 FIN7 的使用而得名。原理其实就是把指令的其中几个字元替换掉,之後再改回来而已。先看看基本的字串取代方法,下面例子把 zXzX
的 X
改成 e
,变成 zeze
。
# cmd /c "set a=zXzX&&call echo %a:X=e%
zeze
混淆指令也差不多,以下例子把原本的 netstat /ano
一开始先设成 neXsXaX /ano
,之後再把 X
改成 t
。
# cmd /c "set cmd1=neXsXaX /ano&&call set cmd2=%cmd1:X=t%&&call %cmd2%"
Active Connections
这个混淆技巧可以绕过动态侦测,如下图 Sysmon 日志。
<<: [Day - 28] - 运用Spring MockMvc 迈向自动化测试之路
>>: [Lesson28] Kotlin - Generics
若确认自己想去的公司会考 live coding,那总得练习。 就算不会,我个人认为多写一点也是好事...
今天继续使用者登入的部分. 登入资料验证 当接收到表单送来的资讯之後, 首先我们要针对资料作验证. ...
直线 在上一篇章我们学会提取点击时的位置,本篇章也会用到相同的 function,我们先将他移出。 ...
在上一篇:用HTML、CSS、JS打造个人网站 (1),讲解了开发网页的前置作业,以及 Heade...
※ 今天的内容 一、清单表格:QTable、QMarkupTable 二、弹出视窗:QDialog、...