I'm trying to create a script where upon running, I can use the Double-Click to trigger a Screenshot. I was thinking maybe I could trigger the WindowsKey + Alt + PrintScreen (this is Xbox's Gamebar Screenshot) in Powershell?
Then I saw this post, and this is exactly what I need to trigger the 3 keys combination, but upon trying no screenshot has been acquired or maybe the "Alt" key was not recognized?
Multiple key press simultaneously for Windows logo key + Alt + PrtScn in powershell?
So maybe, can anyone tell me if it's really possible to do these 3 key combinations? And also, is Double-Click possible? since I can't see any references getting a double-click.
EDIT:
I almost passed out when I realize the solution for Windows+Alt+PrtSc.
I changed the word constant from the ::keydown("Alt") and changed it to "LMenu" and it works!
https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
This is working just what I like, the only problem is the Double-Click
$source = #"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace KeyboardSend
{
public class KeyboardSend
{
[DllImport("user32.dll")]
public static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
private const int KEYEVENTF_EXTENDEDKEY = 1;
private const int KEYEVENTF_KEYUP = 2;
public static void KeyDown(Keys vKey)
{
keybd_event((byte)vKey, 0, KEYEVENTF_EXTENDEDKEY, 0);
}
public static void KeyUp(Keys vKey)
{
keybd_event((byte)vKey, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
}
}
}
"#
# Call the Virtual Key Codes/ Is there a virtual key code for Double-Click?
$LeftClick = '0x01' # Leftclick
# Records the Left Click
$signatureClick=#'
[DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);
'#
Add-Type -memberDefinition $signatureClick -name Mouse -namespace PsOneApi
Do {
If ([PsOneApi.Keyboard]::GetAsyncKeyState($LeftClick) -eq -32767) {
Add-Type -TypeDefinition $source -ReferencedAssemblies "System.Windows.Forms"
[KeyboardSend.KeyboardSend]::KeyDown("LWin")
[KeyboardSend.KeyboardSend]::KeyDown("LMenu")
[KeyboardSend.KeyboardSend]::KeyDown("PrintScreen")
[KeyboardSend.KeyboardSend]::KeyUp("PrintScreen")
[KeyboardSend.KeyboardSend]::KeyUp("LMenu")
[KeyboardSend.KeyboardSend]::KeyUp("LWin")
Start-Sleep -Seconds 1.5
Write-Host "`nScreen has been captured via Click!" -ForegroundColor Red
}
} While($True)
Related
I have the following powershell code to dump the process memory from a given process. In this case, cmd.exe.
It opens the given process with PROCESS_ALL_ACCESS and uses VirtualQueryEx to list all the memory regions. For each memory region it finds, it calls ReadProcessMemory and writes the bytes read to a file.
$typeDefinition = #"
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
public static partial class MemApi
{
[StructLayout(LayoutKind.Sequential)]
public struct MEMORY_BASIC_INFORMATION64
{
public ulong BaseAddress;
public ulong AllocationBase;
public int AllocationProtect;
public int __alignment1;
public ulong RegionSize;
public int State;
public int Protect;
public int Type;
public int __alignment2;
}
[Flags]
public enum ProcessAccessFlags : uint
{
VM_READ = 0x00000010,
PROCESS_ALL_ACCESS = 0x001F0FFF
}
[DllImport("kernel32.dll")]
public static extern uint GetLastError();
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr OpenProcess(
ProcessAccessFlags dwAccess,
[MarshalAs(UnmanagedType.Bool)]
bool bInheritHandle,
int dwProcId
);
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
public static extern int VirtualQueryEx(
IntPtr hProc,
IntPtr lpAddr,
out MEMORY_BASIC_INFORMATION64 lpBuf,
int dwLen
);
public static List<MEMORY_BASIC_INFORMATION64> ListMemoryRegions(
IntPtr hProc
)
{
long maxAddr = 0x00007FFFFFFFFFFF;
long addr = 0;
List<MEMORY_BASIC_INFORMATION64> regions = new List<MEMORY_BASIC_INFORMATION64>();
do
{
MEMORY_BASIC_INFORMATION64 m;
int result = VirtualQueryEx(hProc, (IntPtr)addr, out m, (int)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION64)));
if (addr == (long)m.BaseAddress + (long)m.RegionSize)
break;
addr = (long)m.BaseAddress + (long)m.RegionSize;
regions.Add(m);
} while (addr <= maxAddr);
return regions;
}
[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern Boolean ReadProcessMemory(
IntPtr hProc,
IntPtr lpBaseAddr,
byte[] lpBuf,
UInt32 nSize,
ref UInt32 lpNBytes
);
}
"#
Add-Type -TypeDefinition $typeDefinition -Language CSharp
$cmd = Get-Process -Name cmd
$handle = [MemApi]::OpenProcess(0x1F0FFF, $false, $cmd.Id)
$regions = [MemApi]::ListMemoryRegions($handle)
$fileStream = [System.IO.File]::OpenWrite("$env:TEMP\cmd.DMP")
Write-Host "$($regions.Count) memory segments have been found"
for ($i = 0; $i -lt $regions.Count; $i++)
{
Write-Host "Exporting memory region $("{0:d4}/{1:d4}" -f $i, ($regions.Count + 1)) ($("0x{0:X16} - 0x{1:X16}" -f $regions[$i].BaseAddress, ($regions[$i].BaseAddress + $regions[$i].RegionSize)))..."
try
{
$read = 0
$buff = New-Object byte[] $regions[$i].RegionSize
if ([MemApi]::ReadProcessMemory($handle, [System.IntPtr]::new($regions[$i].BaseAddress), $buff, $buff.Length, [ref]$read) -eq $true)
{
$fileStream.Write($buff, 0, $buff.Length)
}
} catch { } finally { }
}
$fileStream.Close()
I would like to avoid using dbghelp.dll to do this, but is there a way I can create a MiniDump file out of this raw memory? Would I need to change the code at all or is there an external tool that can convert this?
I've tried to take a look into the MiniDumpWriteDump function to see if I can replicate it at all but I've had no luck.
I've also tried volatility's raw2dmp function, but this has not worked unfortunately.
Apologies if this is completely on the wrong tracks!
Any help would be much appreciated - Merry Christmas!
I'm trying to pull folder icons for a listview in a winform. I'm using [Drawing.Icon]::ExtractAssociatedIcon for file icons, but it doesn't work on folders.
I found this question here on stack which said to use SHGetStockIconInfo, but I can't wrap my head around how to load this function and use it in Powershell (I have no C programming experience). I managed to pull this from the linked question, but I'm stuck:
Add-Type -NameSpace WinAPI -Name DefaultIcons -MemberDefinition #'
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SHSTOCKICONINFO {
public uint cbSize;
public IntPtr hIcon;
public int iSysIconIndex;
public int iIcon;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szPath;
}
[DllImport("shell32.dll")]
public static extern int SHGetStockIconInfo(uint siid, uint uFlags, ref SHSTOCKICONINFO psii);
[DllImport("user32.dll")]
public static extern bool DestroyIcon(IntPtr handle);
private const uint SHSIID_FOLDER = 0x3;
private const uint SHGSI_ICON = 0x100;
private const uint SHGSI_LARGEICON = 0x0;
private const uint SHGSI_SMALLICON = 0x1;
'#
This runs without error, but that's as far as I can get and I don't fully understand what's going on.
I know I need to call the function SHGetStockIconInfo with three parameters:
uint to identify what icon I want
uint flag for the size of icon I want
a reference to a SHSTOCKICONINFO structure
The question I got all this from includes a GetStockIcon function definition, but I keep getting errors trying to include it saying The type or namespace name 'Icon' could not be found (are you missing a using directive or an assembly reference?)
With a few adjustments I got the code from that C# question to work under both PowerShell 5.1 and 7.2.6.
$refAsm = if( $PSVersionTable.PSVersion.Major -le 5 ) {'System.Drawing'} else {'System.Drawing.Common'}
Add-Type -ReferencedAssemblies $refAsm -TypeDefinition #'
using System;
using System.Runtime.InteropServices;
using System.Drawing;
public static class DefaultIcons
{
public static Icon GetStockIcon(uint type, uint size)
{
var info = new SHSTOCKICONINFO();
info.cbSize = (uint)Marshal.SizeOf(info);
SHGetStockIconInfo(type, SHGSI_ICON | size, ref info);
var icon = (Icon)Icon.FromHandle(info.hIcon).Clone(); // Get a copy that does not use the original handle
DestroyIcon(info.hIcon); // Clean up native icon to prevent resource leak
return icon;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SHSTOCKICONINFO
{
public uint cbSize;
public IntPtr hIcon;
public int iSysIconIndex;
public int iIcon;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szPath;
}
[DllImport("shell32.dll")]
public static extern int SHGetStockIconInfo(uint siid, uint uFlags, ref SHSTOCKICONINFO psii);
[DllImport("user32.dll")]
public static extern bool DestroyIcon(IntPtr handle);
public const uint SHSIID_FOLDER = 0x3;
public const uint SHGSI_ICON = 0x100;
public const uint SHGSI_LARGEICON = 0x0;
public const uint SHGSI_SMALLICON = 0x1;
}
'#
Use it like this:
$folderIconLarge = [DefaultIcons]::GetStockIcon( [DefaultIcons]::SHSIID_FOLDER, [DefaultIcons]::SHGSI_LARGEICON )
$folderIconSmall = [DefaultIcons]::GetStockIcon( [DefaultIcons]::SHSIID_FOLDER, [DefaultIcons]::SHGSI_SMALLICON )
I need to disable the Close button (the little X) for a script I wrote that has exit functionality that needs to be run (triggered via CTRL-C) and I want to remove the ability for users to bypass that by X'ing out of the window.
Function _Disable-X {
#Calling user32.dll methods for Windows and Menus
$MethodsCall = '
[DllImport("user32.dll")] public static extern long GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("user32.dll")] public static extern bool EnableMenuItem(long hMenuItem, long wIDEnableItem, long wEnable);
[DllImport("user32.dll")] public static extern long SetWindowLongPtr(long hWnd, long nIndex, long dwNewLong);
[DllImport("user32.dll")] public static extern bool EnableWindow(long hWnd, int bEnable);
'
$SC_CLOSE = 0xF060
$MF_DISABLED = 0x00000002L
#Create a new namespace for the Methods to be able to call them
Add-Type -MemberDefinition $MethodsCall -name NativeMethods -namespace Win32
$PSWindow = Get-Process -Pid $PID
$hwnd = $PSWindow.MainWindowHandle
#Get System menu of windows handled
$hMenu = [Win32.NativeMethods]::GetSystemMenu($hwnd, 0)
#Disable X Button
[Win32.NativeMethods]::EnableMenuItem($hMenu, $SC_CLOSE, $MF_DISABLED) | Out-Null
}
_Disable-X
Credit: https://www.makak.ch/disable-close-button-in-powershell-window/
i am trying to make a screen viewer.
i have an C# server side that works good and i have C# client side that works good.
this is my C# client side code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Drawing.Imaging;
using System.Runtime.Serialization.Formatters.Binary;
namespace WindowsFormsApp24
{
public partial class Form1 : Form
{
private readonly TcpClient client = new TcpClient();
private NetworkStream mainStream;
private int portNumber;
private static Image GrabDesktop()
{
Rectangle bound = Screen.PrimaryScreen.Bounds;
Bitmap screenshot = new Bitmap(bound.Width, bound.Height, PixelFormat.Format32bppArgb);
Graphics graphics = Graphics.FromImage(screenshot);
graphics.CopyFromScreen(bound.X, bound.Y, 0, 0, bound.Size, CopyPixelOperation.SourceCopy);
return screenshot;
}
private void SendDesktopImage()
{
BinaryFormatter binFormatter = new BinaryFormatter();
mainStream = client.GetStream();
binFormatter.Serialize(mainStream, GrabDesktop());
}
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
portNumber = 443;
try
{
string ip = "192.168.1.55";
client.Connect(ip, portNumber);
}
catch
{
}
timer1.Start();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void btnConnect_Click(object sender, EventArgs e)
{
}
private void timer1_Tick(object sender, EventArgs e)
{
SendDesktopImage();
}
}
}
The thing i am trying to do, is to switch the client side from C# to powershell.
is that possible? i am searching for ideas on google for along time, I would be happy
to hear what you have to say.. many thanks.
C# and Powershell are both using some version of the Dot Net runtime so the same objects and properties should be available in both, just by a different syntax. The process for converting between the two is basically this:
First you need to load the required assemblies into powershell with Add-Type. You will require several assemblies such as System.Net, System.Drawing and System.Windows.Forms to get access to the Objects in your code. (this is essentially the same as adding references to a C# project). Example: Add-Type -AssemblyName System.Drawing; would load everything inside System.Drawing.dll
Next you need to convert the syntax from C# to powershell line by line:
Example
private readonly TcpClient client = new TcpClient();
Would become:
[System.Net.Sockets.TcpClient] $client = New-Object System.Net.Sockets.TcpClient
Mostly this process will be simplification and expanding names. Above [System.Net.Sockets.TcpClient] is the fully qualified type - ie the long form name of the C# Class (visible on the tooltips in Visual Studio). New-Object is equivalent to new
Assuming you just want the screenshot to be taken and sent each time the script is executed you dont need to worry about writing classes or functions in powershell you can just convert each functional line of c# into powershell in a text file saved with .ps1 extension.
In powershell I'm using [System.Windows.Forms.SendKeys] to send keystrokes. However I'm having trouble emulating the windows key. Since it isn't one of the keys I found in the list in the docs:
https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.sendkeys?view=netcore-3.1
In this post I saw that they were emulating the windows keys using ctrl+esc however this doesn't seem to work.
Sending Windows key using SendKeys
Any idea how to accomplish this?
Try this solution. It has press down window key so that you can send combination key along with that.
**for me Win + Right Arrow key worked but shift doesn't have any effect on my machine. It might work for you.
$source = #"
using System;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace KeySends
{
public class KeySend
{
[DllImport("user32.dll")]
public static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
private const int KEYEVENTF_EXTENDEDKEY = 1;
private const int KEYEVENTF_KEYUP = 2;
public static void KeyDown(Keys vKey)
{
keybd_event((byte)vKey, 0, KEYEVENTF_EXTENDEDKEY, 0);
}
public static void KeyUp(Keys vKey)
{
keybd_event((byte)vKey, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
}
}
}
"#
Add-Type -TypeDefinition $source -ReferencedAssemblies "System.Windows.Forms"
Function WinKey ($Key)
{
[KeySends.KeySend]::KeyDown("LWin")
[KeySends.KeySend]::KeyDown("ShiftKey")
[KeySends.KeySend]::KeyDown("$Key")
[KeySends.KeySend]::KeyUp("LWin")
[KeySends.KeySend]::KeyUp("ShiftKey")
}
WinKey({Right})
.NET System.Windows.Forms Keys list