Converting C# into Powershell with DllImport involved - c#

I've recently been working on a little side project to see if I can get a little memory editing to work with PowerShell. I put together a small script in C# that doesn't require administrative privileges and when ran, gives you max coins and diamonds in Hill Climb Racing.
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace HCRtest2
{
public class Programmmm
{
public static void Main()
{
[DllImport("kernel32.dll")]
static extern bool WriteProcessMemory(IntPtr hProcess, long lpBaseAddress, byte[] lpBuffer, uint nSize, out uint lpNumberOfBytesRead);
long BaseAddress;
IntPtr ProcessHandle;
Process process = Process.GetProcessesByName("HillClimbRacing")[0];
if (process.Handle.ToInt64() != 0L)
{
BaseAddress = process.MainModule.BaseAddress.ToInt64();
ProcessHandle = process.Handle;
uint num = 0U;
WriteProcessMemory(ProcessHandle, BaseAddress + 0x28CAD4, BitConverter.GetBytes(2147483647), 4U, out num);
WriteProcessMemory(ProcessHandle, BaseAddress + 0x28CAEC, BitConverter.GetBytes(2147483647), 4U, out num);
}
}
}
}
My challenge right now is to see if I can find a way to execute this code on my school laptop which doesn't have admin privileges or access to open unknown executables, but it does have access to PowerShell (nonadmin of course). I've been doing a lot of research but cant find a good way to port this script into PowerShell. If anyone has any good ideas please let me know because this is seriously getting on my nerves right now.

This website provides an answer on how to play c# within a powershell session.
$code = #"
using System;
namespace HelloWorld
{
public class Program
{
public static void Main(){
Console.WriteLine("Hello world!");
}
}
}
"#
Add-Type -TypeDefinition $code -Language CSharp
iex "[HelloWorld.Program]::Main()"

It's been a couple of months of on and off work, but I found out that everything has to be labeled as public and static, and along with that I was missing a method that was required to make sure the process would be properly opened, here's the working code that can be executed in Powershell.
$code = #"
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace HelloWorld
{
public class Program
{
public const int ProcessVMWrite = 0x0020;
public const int ProcessVMOperation = 0x0008;
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool WriteProcessMemory
(
IntPtr hProcess,
long lpBaseAddress,
byte[] lpBuffer,
int nSize,
out int lpNumberOfBytesRead
);
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess
(
int dwDesiredAccess,
bool bInheritHandle,
int dwProcessId
);
public static IntPtr Handle;
public static long BaseAddress;
public static void Main(){
Process process = Process.GetProcessesByName("HillClimbRacing")[0];
Handle = OpenProcess(ProcessVMOperation | ProcessVMWrite, false, process.Id);
BaseAddress = process.MainModule.BaseAddress.ToInt64();
int thingy = 0;
WriteProcessMemory(Handle, BaseAddress + 0x28CAD4L, BitConverter.GetBytes(2147483647), 4, out thingy);
WriteProcessMemory(Handle, BaseAddress + 0x28CAECL, BitConverter.GetBytes(2147483647), 4, out thingy);
}
}
}
"#
Add-Type -TypeDefinition $code -Language CSharp
iex "[HelloWorld.Program]::Main()"

Related

Why is SetThreadAffinityMask ignored?

Why is SetThreadAffinityMask ignored?
I'm trying to write a program that sets the Affinity of each process thread according to the value of IdealProcessor.
But SetThreadAffinityMask is ignored.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace ThreadAffinity
{
class Program
{
[DllImport("kernel32.dll")]
static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
[DllImport("kernel32.dll")]
static extern bool SetThreadAffinityMask(IntPtr hThread, IntPtr dwThreadAffinityMask);
[DllImport("kernel32.dll")]
static extern bool GetThreadIdealProcessorEx(IntPtr hThread, ref PROCESSOR_NUMBER lpIdealProcessor);
[DllImport("kernel32.dll")]
static extern bool CloseHandle(IntPtr hObject);
[StructLayout(LayoutKind.Sequential)]
public struct PROCESSOR_NUMBER
{
public ushort Group;
public byte Number;
public byte Reserved;
}
[Flags]
public enum ThreadAccess : int
{
TERMINATE = (0x0001),
SUSPEND_RESUME = (0x0002),
GET_CONTEXT = (0x0008),
SET_CONTEXT = (0x0010),
SET_INFORMATION = (0x0020),
QUERY_INFORMATION = (0x0040),
SET_THREAD_TOKEN = (0x0080),
IMPERSONATE = (0x0100),
DIRECT_IMPERSONATION = (0x0200),
THREAD_ALL_ACCESS = (0x1F03FF)
}
static void Main(string[] args)
{
Console.WriteLine("Enter process id:");
int processId = Convert.ToInt32(Console.ReadLine());
Process process = Process.GetProcessById(processId);
foreach (ProcessThread thread in process.Threads)
{
IntPtr hThread = OpenThread(ThreadAccess.QUERY_INFORMATION, false, (uint)thread.Id);
PROCESSOR_NUMBER processorNumber = new PROCESSOR_NUMBER();
GetThreadIdealProcessorEx(hThread, ref processorNumber);
Console.WriteLine("Thread {0} ideal processor is {1}", thread.Id, processorNumber.Number);
SetThreadAffinityMask(hThread, (IntPtr)(1 << processorNumber.Number));
CloseHandle(hThread);
}
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
}
I can't deny that with 99% probability I'm an idiot, that's why I came here to ask for your help.
upd1: The program properly detects idealprocessor, but doesn't set affinity to the thread.
As #RaymondChen said
Per documentation: This handle must have the THREAD_SET_INFORMATION or
THREAD_SET_LIMITED_INFORMATION access right and the
THREAD_QUERY_INFORMATION or THREAD_QUERY_LIMITED_INFORMATION access
right.

CertOpenStore "Memory" returns file not found

The code below used to work. I think it broke after some .NET Framework or Windows 10 upgrade, but not sure.
It opens a temporary certificate store for generating self-signed certificates.
using System;
using System.Runtime.InteropServices;
namespace MyTestApp
{
internal static class Program
{
public static void Main(string[] arguments)
{
var certStore = CertOpenStore(
"Memory", // sz_CERT_STORE_PROV_MEMORY
0,
IntPtr.Zero,
CERT_STORE_CREATE_NEW_FLAG,
IntPtr.Zero
);
if (certStore != IntPtr.Zero)
{
Console.WriteLine("Success!");
}
else
{
var error = Marshal.GetHRForLastWin32Error();
Console.WriteLine("Error: " + error.ToString("X"));
}
Console.ReadLine();
}
private const uint CERT_STORE_CREATE_NEW_FLAG = 0x00002000;
[DllImport("Crypt32.dll", SetLastError = true, CharSet=CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr CertOpenStore(
[MarshalAs(UnmanagedType.LPWStr)] string storeProvider,
uint messageAndCertificateEncodingType,
IntPtr cryptProvHandle,
uint flags,
IntPtr parameters
);
}
}
The output is:
Error: 80070002
Which is ERROR_FILE_NOT_FOUND. Tested on .NET 4.5 and 4.5.2.
What can I do to diagnose further or fix?

How to update the change time of a file from c#?

Files can have a change date. This date is not the same as the last modified date or the last access date. Change date is not visible through the UI or .NET API. There a two Win32 functions GetFileInformationByHandleEx for reading and SetFileInformationByHandle for writing file information.
I want to read out the change date, add some hours to it, and write the new date back as the change date of the file.
For now I have following code:
class Program
{
static void Main(string[] args)
{
using (var file = new FileStream(#"c:\path\to\file", FileMode.Open))
{
var fileInfo = new FILE_BASIC_INFO();
GetFileInformationByHandleEx(
file.Handle,
FILE_INFO_BY_HANDLE_CLASS.FileBasicInfo,
out fileInfo,
(uint)Marshal.SizeOf(fileInfo));
SetFileInformationByHandle(
file.Handle,
FILE_INFO_BY_HANDLE_CLASS.FileBasicInfo,
fileInfo,
(uint)Marshal.SizeOf(fileInfo));
}
}
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool GetFileInformationByHandleEx(
IntPtr hFile,
FILE_INFO_BY_HANDLE_CLASS infoClass,
out FILE_BASIC_INFO fileInfo,
uint dwBufferSize);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetFileInformationByHandle(
IntPtr hFile,
FILE_INFO_BY_HANDLE_CLASS infoClass,
FILE_BASIC_INFO fileInfo,
uint dwBufferSize);
private enum FILE_INFO_BY_HANDLE_CLASS
{
FileBasicInfo = 0
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct FILE_BASIC_INFO
{
public LARGE_INTEGER CreationTime;
public LARGE_INTEGER LastAccessTime;
public LARGE_INTEGER LastWriteTime;
public LARGE_INTEGER ChangeTime;
public uint FileAttributes;
}
[StructLayout(LayoutKind.Explicit, Size = 8)]
private struct LARGE_INTEGER
{
[FieldOffset(0)]
public Int64 QuadPart;
[FieldOffset(0)]
public UInt32 LowPart;
[FieldOffset(4)]
public Int32 HighPart;
}
}
I can read out the change date into that awful structure LARGE_INTEGER. What I want to have is a function which can convert that type into a System.DateTime and vice versa.
The second problem that I have is that the siganture of the SetFileInformationByHandle method is wrong. I get a PInvokeStackImbalance with this additional information:
Additional information: A call to PInvoke function 'Program::SetFileInformationByHandle' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.
Who can help me?
To answer the first part..On how to convert "that awful Large_Interger" to DateTime..
The below code snippet should help..
using (var file = new System.IO.FileStream(#"sample.log", System.IO.FileMode.Open))
{
var fileInfo = new FILE_BASIC_INFO();
GetFileInformationByHandleEx(
file.Handle,
FILE_INFO_BY_HANDLE_CLASS.FileBasicInfo,
out fileInfo,
(uint)System.Runtime.InteropServices.Marshal.SizeOf(fileInfo));
var changeTime = DateTime.FromFileTime(fileInfo.ChangeTime.QuadPart);
Console.WriteLine(changeTime);
System.TimeSpan changedForHowLong = DateTime.Now.Subtract(changeTime);
Console.WriteLine(changedForHowLong.Days);
}
I tested the above snippet it seems to work fine..
Let me try repro'ing the issue you faced with the PInvokeStackImbalance..
Take Care,
I found this signature on PInvoke
[DllImport("Kernel32.dll", SetLastError = true)]
private static extern bool SetFileInformationByHandle(
IntPtr hFile,
int FileInformationClass,
IntPtr lpFileInformation,
Int32 dwBufferSize);
Somehow this did not work. I had to change the type of the parameter lpFileInformation to FILE_BASIC_INFO to make it work.
This is the complete C# example called from PowerShell:
$fu = #"
using System;
using System.IO;
using System.Runtime.InteropServices;
public class FileUtility
{
private struct FILE_BASIC_INFO
{
[MarshalAs(UnmanagedType.I8)]
public Int64 CreationTime;
[MarshalAs(UnmanagedType.I8)]
public Int64 LastAccessTime;
[MarshalAs(UnmanagedType.I8)]
public Int64 LastWriteTime;
[MarshalAs(UnmanagedType.I8)]
public Int64 ChangeTime;
[MarshalAs(UnmanagedType.U4)]
public UInt32 FileAttributes;
}
[DllImport("Kernel32.dll", SetLastError = true)]
private static extern bool SetFileInformationByHandle(
IntPtr hFile,
int FileInformationClass,
FILE_BASIC_INFO lpFileInformation,
Int32 dwBufferSize);
public void SetFileChangeTime()
{
using (FileStream fs = new FileStream(#"c:\path\to\file", FileMode.Open))
{
FILE_BASIC_INFO fileInfo = new FILE_BASIC_INFO();
fileInfo.ChangeTime = 943044610000000;
SetFileInformationByHandle(
fs.Handle,
0, // the same as FILE_INFO_BY_HANDLE_CLASS.FileBasicInfo
fileInfo,
Marshal.SizeOf(fileInfo));
}
}
}
"#
Add-Type -TypeDefinition $fu -IgnoreWarnings
$f = New-Object -TypeName FileUtility
$f.SetFileChangeTime()
I have run the example with the other date properties since they are shown in the explorer and it worked.
Edit
This code does not run in debug mode within VS. As mentioned above it throws the exception. Running the EXE in the command line does not throw an exception. But the change date is not updated. However it works only in PowerShell. Strange.

C# How to use CallNtPowerInformation with Interop to get SYSTEM_POWER_INFORMATION

I am trying to write a small program that runs as a service and monitors if a user is active or not. If the user is idle (no mouse/keyboard) for an hour, then certain processes are killed. Got it working if run by a user by using the LASTINPUTINFO from user32.dll, but it won't work as a service. Looking further I ran across someone saying to call CallNtPowerInformation with SystemPowerInformation and examine the TimeRemaining member. I'd like to do this but have little experience with interop and was hoping to get a little help/example:
In C# I would import:
[DllImport("powrprof.dll", SetLastError = true)]
private static extern UInt32 CallNtPowerInformation(
Int32 InformationLevel,
IntPtr lpInputBuffer,
UInt32 nInputBufferSize,
IntPtr lpOutputBuffer,
UInt32 nOutputBufferSize
);
I believe then I would need to create a struct for SYSTEM_POWER_INFORMATION to handle the result?
Apologies for the n00bness
You can get the information you need like this:
using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class Program
{
const int SystemPowerInformation = 12;
const uint STATUS_SUCCESS = 0;
struct SYSTEM_POWER_INFORMATION
{
public uint MaxIdlenessAllowed;
public uint Idleness;
public uint TimeRemaining;
public byte CoolingMode;
}
[DllImport("powrprof.dll")]
static extern uint CallNtPowerInformation(
int InformationLevel,
IntPtr lpInputBuffer,
int nInputBufferSize,
out SYSTEM_POWER_INFORMATION spi,
int nOutputBufferSize
);
static void Main(string[] args)
{
SYSTEM_POWER_INFORMATION spi;
uint retval = CallNtPowerInformation(
SystemPowerInformation,
IntPtr.Zero,
0,
out spi,
Marshal.SizeOf(typeof(SYSTEM_POWER_INFORMATION))
);
if (retval == STATUS_SUCCESS)
Console.WriteLine(spi.TimeRemaining);
Console.ReadLine();
}
}
}
I cannot tell you whether or not this method will give you the information you need when run from a service.

C# Process Killing

I need to write a program in c# that would just start, kill one process\exe that it is supposed to kill and end itself.
The process I need to kill is another C# application so it is a local user process and I know the path to the exe.
Check out Process.GetProcessesByName and Process.Kill
// Get all instances of Notepad running on the local
// computer.
Process [] localByName = Process.GetProcessesByName("notepad");
foreach(Process p in localByName)
{
p.Kill();
}
First search all processes for the process you want to kill, than kill it.
Process[] runningProcesses = Process.GetProcesses();
foreach (Process process in runningProcesses)
{
// now check the modules of the process
foreach (ProcessModule module in process.Modules)
{
if (module.FileName.Equals("MyProcess.exe"))
{
process.Kill();
}
}
}
Killing processes by their name can be easily done in C# (as the other answers already showed perfectly). If you however want to kill processes based on the full path of the executable things get more tricky. One way to do that would be to use WMI, another way would be to use the Module32First Windows API function.
The sample below uses the latter approach. It first selects a subset of the running processes by their name and then queries each of these processes for their full executable path. Note that this path will be the actual path of the image being executed, which is not necessarily the executable that was launched (e.g. on x64 systems the actual path to calc.exe will be C:\Windows\SysWOW64\calc.exe even if the file C:\Windows\system32\calc.exe was started). All processes with a matching path are returned by GetProcessesByPath:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
class Program
{
static void Main(string[] args)
{
Process[] processList = GetProcessesByPath(#"C:\Program Files\MyCalculator\calc.exe");
foreach (var process in processList)
{
if (!process.HasExited)
process.Kill();
}
}
static Process[] GetProcessesByPath(string path)
{
List<Process> result = new List<Process>();
string processName = Path.GetFileNameWithoutExtension(path);
foreach (var process in Process.GetProcessesByName(processName))
{
ToolHelpHandle hModuleSnap = NativeMethods.CreateToolhelp32Snapshot(NativeMethods.SnapshotFlags.Module, (uint)process.Id);
if (!hModuleSnap.IsInvalid)
{
NativeMethods.MODULEENTRY32 me32 = new NativeMethods.MODULEENTRY32();
me32.dwSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(me32);
if (NativeMethods.Module32First(hModuleSnap, ref me32))
{
if (me32.szExePath == path)
{
result.Add(process);
}
}
hModuleSnap.Close();
}
}
return result.ToArray();
}
}
//
// The safe handle class is used to safely encapsulate win32 handles below
//
public class ToolHelpHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private ToolHelpHandle()
: base(true)
{
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
protected override bool ReleaseHandle()
{
return NativeMethods.CloseHandle(handle);
}
}
//
// The following p/invoke wrappers are used to get the list of process and modules
// running inside each process.
//
public class NativeMethods
{
[DllImport("kernel32.dll", SetLastError = true)]
static public extern bool CloseHandle(IntPtr hHandle);
[DllImport("kernel32.dll")]
static public extern bool Module32First(ToolHelpHandle hSnapshot, ref MODULEENTRY32 lpme);
[DllImport("kernel32.dll")]
static public extern bool Module32Next(ToolHelpHandle hSnapshot, ref MODULEENTRY32 lpme);
[DllImport("kernel32.dll")]
static public extern bool Process32First(ToolHelpHandle hSnapshot, ref PROCESSENTRY32 lppe);
[DllImport("kernel32.dll")]
static public extern bool Process32Next(ToolHelpHandle hSnapshot, ref PROCESSENTRY32 lppe);
[DllImport("kernel32.dll", SetLastError = true)]
static public extern ToolHelpHandle CreateToolhelp32Snapshot(SnapshotFlags dwFlags, uint th32ProcessID);
public const short INVALID_HANDLE_VALUE = -1;
[Flags]
public enum SnapshotFlags : uint
{
HeapList = 0x00000001,
Process = 0x00000002,
Thread = 0x00000004,
Module = 0x00000008,
Module32 = 0x00000010,
Inherit = 0x80000000,
All = 0x0000001F
}
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct PROCESSENTRY32
{
public uint dwSize;
public uint cntUsage;
public uint th32ProcessID;
public IntPtr th32DefaultHeapID;
public uint th32ModuleID;
public uint cntThreads;
public uint th32ParentProcessID;
public int pcPriClassBase;
public uint dwFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szExeFile;
};
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct MODULEENTRY32
{
public uint dwSize;
public uint th32ModuleID;
public uint th32ProcessID;
public uint GlblcntUsage;
public uint ProccntUsage;
IntPtr modBaseAddr;
public uint modBaseSize;
IntPtr hModule;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string szModule;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szExePath;
};
}
Some of the code is based on an article by Jason Zander which can be found here.
you can call the Process.Kill method
you can use the Process.GetProcesses to get all processes or Process.GetProcessByName or Process.GetProcessById so you can get the process to call Kill on.
Process[] processes = Process.GetProcesses();
foreach (Process pr in processes){
if (pr.ProcessName=="vfp")
if (pr.MainWindowTitle.Contains("test"))
pr.CloseMainWindow();
}`enter code here`
Here vfp is process name. and test is setup title name.
You can achieve it by using Process Class class but why would you want to kill another process?
Process class has Kill() method
I wanted to define my own list of applications to close so I made this based on some of the examples I've seen listed. It's simple and effective.
string[] Process_name_list = {"chrome","notepad"};
foreach (string Process_name in Process_name_list)
{
foreach (var process in Process.GetProcessesByName(Process_name))
{
process.Kill();
}
}

Categories

Resources