I'm developing a little memory scanner for a specific application. When I select a process to scan, the first thing I want to do is to verify that the process is an instance that specific application... and to do this I must find a signature that can be anywhere inside its memory.
Here is my code:
[DllImport("Kernel32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern Boolean ReadProcessMemory([In] IntPtr processHandle, [In] IntPtr processAddress, [Out] Byte[] buffer, [In] UInt32 bytesToRead, [Out] out IntPtr bytesRead);
[DllImport("Kernel32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
internal static extern UInt32 VirtualQueryEx([In] IntPtr processHandle, [In, Optional] IntPtr processAddress, [Out] out MEMORY_BASIC_INFORMATION buffer, [In] UInt32 bufferSize);
internal struct MEMORY_BASIC_INFORMATION
{
public static UInt32 Size = (UInt32)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION));
public IntPtr BaseAddress;
public IntPtr AllocationBase;
public AllocationProtect AllocationProtect;
public IntPtr RegionSize;
public StateEnum State;
public AllocationProtect Protect;
public TypeEnum lType;
}
public void Open()
{
Byte[] toFind = new Byte[] { 31, 55, 78, 33, 00, 00, 00, 37 };
UInt32 address = 0;
do
{
MEMORY_BASIC_INFORMATION info = new MEMORY_BASIC_INFORMATION();
if (NativeMethods.VirtualQueryEx(m_Process.Handle, (IntPtr)address, out info, NativeMethods.MemoryBasicInformation.Size) == 0)
break;
Byte[] buffer = new Byte[(UInt32)info.RegionSize];
IntPtr bytesRead;
if (NativeMethods.ReadProcessMemory(m_Process.Handle, info.BaseAddress, buffer, (UInt32)buffer.Length, out bytesRead))
{
if (buffer.Contains(toFind)) // Extension Method
{
m_IsValid = true;
break;
}
}
if (address == (UInt32)info.BaseAddress + (UInt32)info.RegionSize)
break;
address = (UInt32)info.BaseAddress + (UInt32)info.RegionSize;
}
while (address <= 0x7fffffff);
}
The first problem that this method is never reaching completion and it looks like it's endlessly looping (yesterday I let it running for debug purposes for more than one hour without reaching the end). Checking for Marshal.GetLastWin32Error() inside my loop I noticed that sometimes I get an ERROR_PARTIAL_COPY (0x0000012B) after calling ReadProcessMemory... is it the possible cause?
Then I also have some questions:
1) Should I call OpenProcess before proceeding with the scan loop? I don't think so, right?
2) I would like to make my application both x32 and x64 compatible. What should I change inside my code to be sure it will properly work with both systems (address limit, value type of address, RegionSize cast, ...)?
3) While scanning the process memory in order to find my target byte array, should I check the current MEMORY_BASIC_INFORMATION's properties (AllocationProtect, State, Protect and/or lType) to see if I can skip ReadProcessMemory for the current region because it's not necessary or it can't be read?
4) Is there anything else I can do to optimize the speed of this methos, which is very important?
Oooooooook I solved it. The problem was the way I was trying to read it without using VirtualQueryEx and checking for the memory region protection!
Related
I read card SD like file. I use this method:
public static int ReadUSBDisk(ref byte[] buffer, int sector, string fileName)
{
ushort count = 10;
bool retValue;
int address = 512 * sector;
if (!IsUSBOpen())
hUSBDisk = OpenUSBDisk(fileName);
if ((int)hUSBDisk == -1)
return NISH_ERROR;
SetFilePointer(hUSBDisk, address
, 0,
EMoveMethod.Begin);
retValue = ReadFile(hUSBDisk, buffer, 512, ref count, IntPtr.Zero);
if (retValue)
return NISH_NO_ERROR;
else
return NISH_ERROR;
}
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool ReadFile(IntPtr handle,
byte[] buffer, ushort toRead, ref ushort read, IntPtr lpOverLapped);
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint SetFilePointer(
IntPtr hFile,
int lDistanceToMove,
int lpDistanceToMoveHigh,
EMoveMethod dwMoveMethod);
But I need to read from more space than the int. But change lDistanceToMove to long couses throw error:
A call to PInvoke '(className) :: SetFilePointer' has upset the
balance of the stack. Probable cause is a mismatch between the managed
PInvoke signature and the unmanaged target signature. Check that the
calling convention and signature parameters of the PInvoke function
match the unmanaged target signature.
Honestly, I don't know exactly how it works. Maybe someone can tell me if I can change it to read from long space in some way.
I'm to trying to call FreeLibraryAndExitThread externally in another process (using CreateRemoteThread) so that I can unload a module I loaded in externally through LoadLibrary.
I understand that whilst CreateRemoteThread takes 1 parameter, you can provide it with a struct of multiple arguments if you need more than one.
If have tried the following which did not unload the module. In fact it seemed to do nothing.
Note I have removed all error checking to keep this post simple and short
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr GetModuleHandle(string moduleName);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr GetProcAddress(IntPtr moduleHandle, string procName);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr VirtualAllocEx(IntPtr processHandle, IntPtr baseAddress, int size, int allocationType, int protection);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool WriteProcessMemory(IntPtr processHandle, IntPtr baseAddress, byte[] buffer, int size, int bytesWritten);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr CreateRemoteThread(IntPtr processHandle, IntPtr threadAttributes, int stackSize, IntPtr startAddress, IntPtr parameter, int creationFlags, int threadId);
private struct FreeLibraryAndExitThreadParameters
{
internal IntPtr ModuleAddress;
internal int ExitCode;
}
var process = Process.GetProcessesByName("notepad")[0];
var freeLibraryAndExitThreadAddress = GetProcAddress(GetModuleHandle("kernel32.dll"), "FreeLibraryAndExitThread");
// Get an instance of the module - dllName is the name of the module I am trying to unload
var module = process.Modules.Cast<ProcessModule>().SingleOrDefault(m => string.Equals(m.ModuleName, dllName, StringComparison.OrdinalIgnoreCase));
var freeLibraryAndExitThreadParameters = new FreeLibraryAndExitThreadParameters { ModuleAddress = module.BaseAddress, ExitCode = 0 };
// This code turns the struct into a byte array
var structureSize = Marshal.SizeOf(freeLibraryAndExitThreadParameters);
var structureBytes = new byte[structureSize];
var buffer = Marshal.AllocHGlobal(structureSize);
Marshal.StructureToPtr(freeLibraryAndExitThreadParameters, buffer, true);
Marshal.Copy(buffer, structureBytes, 0, structureSize);
Marshal.FreeHGlobal(buffer);
// Allocate memory in the remote process with commit and reserve allocation type and PageExecuteReadWrite permissions
var remoteAddress = VirtualAllocEx(process.Handle, IntPtr.Zero, structureSize, 0x01000 | 0x02000, 0x040);
// Write the structure into the remote process
WriteProcessMemory(process.Handle, remoteAddress, buffer, structureSize, 0);
// Finally call CreateRemoteThread to execute the function in the remote process
CreateRemoteThread(process.Handle, IntPtr.Zero, 0, freeLibraryAndExitThreadAddress, remoteAddress, 0, 0);
None of the pinvoke calls are actually failing and I can see that the bytes are being written into memory but nothing seems to happen after the remote thread is created - In my actual code I call WaitForSingleObject and the thread finishes its task also with no problem.
Can someone point out what I'm doing wrong and how I can fix this problem so that I can externally call FreeLibraryAndExitThread in a remote process?
It may be worth mentioning that I can use FreeLibrary with this method - it works fine(removing the struct as it only takes 1 parameter) but I specifically need to use FreeLibraryAndExitThread for the module I need to unload which is why I am not using the simpler FreeLibrary.
formally this is simply, all what we need
CreateRemoteThread(hProcess, 0, 0, (PTHREAD_START_ROUTINE)FreeLibraryAndExitThread, hmod, 0, 0)
where hmod is address of module in remote process. address of FreeLibraryAndExitThread can be take from current process kernel32!FreeLibraryAndExitThread - until kernel32.dll is loaded at the same base address in all processes.
that
DECLSPEC_NORETURN
VOID
WINAPI
FreeLibraryAndExitThread(
_In_ HMODULE hLibModule,
_In_ DWORD dwExitCode
);
take 2 parameters in concrete case no problem. as result of call - CreateRemoteThread(hProcess, 0, 0, (PTHREAD_START_ROUTINE)FreeLibraryAndExitThread, hmod, 0, 0) the FreeLibraryAndExitThread will be called via stdcall (WINAPI) calling convention with single parameter - hmod. the second parameter dwExitCode will be undefined in this case, but it not play any role - any return code of thread is ok. system not interpret this value. and because this concrete api never return - different in parameter count also not play role.
another question - for what, which sense unload module in remote process. and if module really will be unloaded (the FreeLibrary call only decrement module load count, so module not always will be unloaded during this call) and after this some code in remote process call code of unloading module - think not need explain what is be in this case
I've got a COM interface dll, and some documentation about the methods within the dll, however from what I can tell with the documentation, the method requires a custom struct be passed in as an out parameter, but the documentation doesn't provide any information about the struct itself.
The function I'm calling from c# is as follows:
API
UINT OpenRequest ([out] PHCOMS phComs,
[in] PCHAR pEndPointName,
[in] UINT fBlockingMode,
[in] UINT fOpenMode,
[in] UINT fDataType,
[in] HINSTANCE hInstance)
My issue is that PHCOMS is a type described in the documentation as:
The address of a variable of type HCOMS. The communications handle to be used by the other API calls, is returned in this variable. If an error occurs this will be NULL.
This function starts by allocating a comms handle (hComs), if
available, to the application. This handle is used for creating a new
connection object. The parameters of this function are assigned to the
relevant members. For this object, a pointer instance is created for
connecting to the interface, as well as the PC Headerpched
interface
I've had a look at various dll inspectors and other posts on SO but can't find anything that helps with how I can actually create a struct that's going to be validly accepted by the function.
I am also unsure if I'm misinterpreting what I need to do - is it possible that I just need to pass a standard handle through to the function or something similar? Is the PHComs type a non custom type that I just can't find info on in google?
Right now I'm attempting to call the function through c# using the DLLImport attribute over an extern function which seems to be ok except that the handle I get back is never valid, which I'm blindly (I've never done something like this before) trying to do like this
[DllImport("MyDll.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
public static extern uint OpenRequest(ref SafeProcessHandle hComs, string host, uint fBlockingMode, uint fOpenMode, uint fDataType, SafeProcessHandle hInstance);
static void Main(string[] args)
{
IntPtr h = new IntPtr();
var handle = new SafeProcessHandle(h, true);
uint test = 0;
test = OpenRequest(ref handle, "Host01", 0, 0, 0, handle);
handle.Dispose();
}
Any assistance on how to setup my test properly would help too since I'm blindly guessing about the IntPtr and use of whatever Safe*Handle Classes.
Edit
I've changed it to be like this following Hans' comment:
As you said, there are other methods that use that handle, for example the ConnectRequest added below.
Any suggestion as to what the HInstance parameter refers to? I doubt it's correct that I'm just passing the same handle/IntPtr in again?
The documentation says:
hInstance HINSTANCE Windows programs must pass their instance handle.
[DllImport("MyDll.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
public static extern uint OpenRequest(out IntPtr hComs, string host, uint fBlockingMode, uint fOpenMode, uint fDataType, IntPtr hInstance);
[DllImport("MyDll.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
public static extern uint ConnectRequest(IntPtr hComs, uint cTimeOut);
static void Main(string[] args)
{
IntPtr hComs = new IntPtr();
uint test_OpenRequest = 0;
test_OpenRequest = OpenRequest(out hComs, "Host01", 0, 0, 0, hComs);
}
Edit 2
[DllImport("WinCom32.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
public static extern uint OpenRequest(out IntPtr hComs, string host, uint fBlockingMode, uint fOpenMode, uint fDataType, IntPtr hInstance);
static void Main(string[] args)
{
IntPtr hComs = new IntPtr();
uint test_Request = 0;
string hostName = ConfigurationManager.AppSettings["HostName"];
IntPtr hInstance = Marshal.GetHINSTANCE(Assembly.GetEntryAssembly().GetModules()[0]);
test_Request = OpenRequest(out hComs, hostName, 0, 0, 1, hInstance);
Console.WriteLine("Request response value: " + test_Request.ToString());
}
There's a test application I can run that shows that this is supposed to work because it's able to connect to the host, so I've got to be doing something wrong.
I have several DLL files that are on my hard disk. A process on my server contains important file data that I want to log by allocating virtual memory inside the process. I don't have the source code of that process, so I need to reside to more extreem measures. I want it to start the DLL main function. The allocation of memory externally needs to be written in C# due to the fact I want to use it with WPF.
How can you excute your own source code in another process with C#?
In order to execute your own source code inside a process you need to virtually allocate memory for the process and write the path of your DLL inside that memory address you allocated. You will use that DLL path to catapult your dll inside the process using the exported function in kernel32.dll LoadLibraryW.
Each process on the windows platform has a specified memory size dedicated to that process. One of the reasons is for security, a process can’t read or write data to other processes. So in order to be able to write/inject your DLL you need to open a HANDLE. You can do this if you import the OpenProcess function from the kernel32.dll. What this briefly means is that you are using the windows api. Here is how you import the kernel32 DLL in C#
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr OpenProcess(
uint dwDesiredAccess,
int bInheritHandle,
uint dwProcessId
);
You can find the full documentation of the windows api in the holy bible
Now, you want to allocate memory to the process that you got a handle from by using the OpenProcess function. Use the VirtualAllocEx function, lets consult the MSDN
How hath thou allocated thou memory?
LPVOID WINAPI VirtualAllocEx(
_In_ HANDLE hProcess,
_In_opt_ LPVOID lpAddress,
_In_ SIZE_T dwSize,
_In_ DWORD flAllocationType,
_In_ DWORD flProtect
);
As we can see it takes 5 parameters. The HANDLE object that you collected earlier. An optional parameter that we won’t use. The size of your DLL that you can get if you convert your DLL into an array of bytes. The type of memory allocation, we want to both reserve and commit allocation so use (0x1000 | 0x2000) and last the protection for the allocated memory that we will put on write 0x40.
STEP 1 Allocate memory ✓
STEP 2 Write DLL path
STEP 3 use LoadLibraryW
The second step involves using WriteProcessMemory to simply write the dll path in memory. Convert String to array of bytes
byte[] bytes = Encoding.ASCII.GetBytes(DllPath);
Write that array of bytes on the memory you allocated with the windows api function WriteProcessMemory like so.
WriteProcessMemory(processHandle, allocatedMemory, bytes, (uint)bytes.Length, 0)
STEP 1 Allocate memory ✓
STEP 2 Write DLL path ✓
STEP 3 use LoadLibraryW
This will be a bit tricky to explain if you have no clue on what exported functions are so ill try to give you an abstract understanding.
When creating an application you need to import DLLs that windows provided in order to use some functionalities. For example, you want to send a HTTP request in your application. Even without you knowing you need to load windows ws2.dll (windows socket) library. The windows OS provided a handy function that will literally load a library called LoadLibraryW. Where can I find this fantastic function? Well no worries child, the kernel32.dll got you covered. All you need to do is find a pointer to the LoadLibraryW function. Again, show faith in the MSDN and it shall reward you.
FARPROC WINAPI GetProcAddress(
_In_ HMODULE hModule,
_In_ LPCSTR lpProcName
);
HMODULE WINAPI GetModuleHandle(
_In_opt_ LPCTSTR lpModuleName
);
You can read the documentation for more information. Simply put this will find your LoadLibraryW function inside kernel32.dll since it is an exported function.
IntPtr lpLLAddress = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryW");
STEP 1 Allocate memory ✓
STEP 2 Write DLL path ✓
STEP 3 use LoadLibraryW ✓
Start a remotethread inside your process that will simply execute your loadlibrary code
CreateRemoteThread(hndProc, (IntPtr)null, (IntPtr)null, lpLLAddress, lpAddress, 0, (IntPtr)null)
After that simply close the handle to the process and your dll should be ‘injected’ inside the process. At any rate if you still haven't figured it out or simply want a class that does it for you here is some source code
DLLinjector
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace dllInjectExample
{
public enum DllInjectionResult
{
DllNotFound,
GameProcessNotFound,
InjectionFailed,
Success
}
public static class DllInjector
{
static readonly IntPtr INTPTR_ZERO = (IntPtr)0;
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr OpenProcess(uint dwDesiredAccess, int bInheritHandle, uint dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
static extern int CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, IntPtr dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll", SetLastError = true)]
static extern int WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] buffer, uint size, int lpNumberOfBytesWritten);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttribute, IntPtr dwStackSize, IntPtr lpStartAddress,
IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
public static DllInjectionResult Inject(string sProcName, string sDllPath)
{
if (!File.Exists(sDllPath))
{
return DllInjectionResult.DllNotFound;
}
uint _procId = 0;
Process[] _procs = Process.GetProcesses();
for (int i = 0; i < _procs.Length; i++)
{
if (_procs[i].ProcessName == sProcName)
{
_procId = (uint)_procs[i].Id;
break;
}
}
if (_procId == 0)
{
return DllInjectionResult.GameProcessNotFound;
}
if (!bInject(_procId, sDllPath))
{
return DllInjectionResult.InjectionFailed;
}
return DllInjectionResult.Success;
}
private static bool bInject(uint pToBeInjected, string sDllPath)
{
IntPtr hndProc = OpenProcess((0x2 | 0x8 | 0x10 | 0x20 | 0x400), 1, pToBeInjected);
if (hndProc == INTPTR_ZERO)
{
return false;
}
IntPtr lpAddress = VirtualAllocEx(hndProc, (IntPtr)null, (IntPtr)sDllPath.Length, (0x1000 | 0x2000), 0X40);
if (lpAddress == INTPTR_ZERO)
{
return false;
}
byte[] bytes = Encoding.ASCII.GetBytes(sDllPath);
if (WriteProcessMemory(hndProc, lpAddress, bytes, (uint)bytes.Length, 0) == 0)
{
return false;
}
IntPtr lpLLAddress = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryW");
if (lpLLAddress == INTPTR_ZERO)
{
return false;
}
if (CreateRemoteThread(hndProc, (IntPtr)null, INTPTR_ZERO, lpLLAddress, lpAddress, 0, (IntPtr)null) == INTPTR_ZERO)
{
return false;
}
CloseHandle(hndProc);
return true;
}
}
}
Example injecting into csgo since I have no other idea why you would want to inject a dll?
if (Process.GetProcessesByName("csgo").Count() == 0)
{
Process Proc = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo(#"D:\Application\Steam\Steam.exe");
Proc.StartInfo = startInfo;
Proc.StartInfo.Arguments = "-applaunch 730";
Proc.StartInfo.UseShellExecute = false;
Proc.StartInfo.CreateNoWindow = false;
Proc.Start();
Thread.Sleep(15000);
}
while (Process.GetProcessesByName("csgo").Count() == 0)
{
}
var something = DllInjector.Inject("csgo", #"C:\Visual Studio 2015\Projects\XGame\Debug\XGamedll.dll");
I want to Inject Python Code into a process and It seems to be crashing my process when it injects. I do not get any errors on my own program but the target process stops working. The called unmanaged APIs have not given me any errors and seem to have carried out their execution properly.
[DllImport("kernel32")]
public static extern IntPtr CreateRemoteThread(IntPtr hProcess,IntPtr lpThreadAttributes,uint dwStackSize, IntPtr lpStartAddress,IntPtr lpParameter,uint dwCreationFlags, out uint lpThreadId);
[Flags]
enum ProcessAccessFlags : uint
{
All = 0x001F0FFF,
Terminate = 0x00000001,
CreateThread = 0x00000002,
VMOperation = 0x00000008,
VMRead = 0x00000010,
VMWrite = 0x00000020,
DupHandle = 0x00000040,
SetInformation = 0x00000200,
QueryInformation = 0x00000400,
Synchronize = 0x00100000
}
[DllImport("kernel32.dll")]
static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);
[Flags]
public enum AllocationType
{
Commit = 0x1000,
Reserve = 0x2000,
Decommit = 0x4000,
Release = 0x8000,
Reset = 0x80000,
Physical = 0x400000,
TopDown = 0x100000,
WriteWatch = 0x200000,
LargePages = 0x20000000,
VIRTUAL_MEM = (0x1000 | 0x2000)
}
[Flags]
public enum MemoryProtection
{
Execute = 0x10,
ExecuteRead = 0x20,
ExecuteReadWrite = 0x40,
ExecuteWriteCopy = 0x80,
NoAccess = 0x01,
ReadOnly = 0x02,
ReadWrite = 0x04,
WriteCopy = 0x08,
GuardModifierflag = 0x100,
NoCacheModifierflag = 0x200,
WriteCombineModifierflag = 0x400,
PAGE_EXECUTE_READWRITE = 0x00000040
}
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, AllocationType flAllocationType, MemoryProtection flProtect);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize, uint dwFreeType);
[DllImport("kernel32", SetLastError = true, ExactSpelling = true)]
internal static extern Int32 WaitForSingleObject( IntPtr handle,Int32 milliseconds);
[DllImport("kernel32.dll")]
public static extern Int32 CloseHandle(IntPtr hObject);
private void InjectCode(string shellcode = "print('Hello, World!')")
{
foreach (Process proc in Process.GetProcesses())
{
if (proc.ProcessName == "Toontown")
{
int shellcode_length = shellcode.Length;
IntPtr h_process = OpenProcess(ProcessAccessFlags.All, false, (int)proc.Id);
IntPtr shellcode_address = (IntPtr)VirtualAllocEx(h_process, (IntPtr)0, (uint)shellcode_length, AllocationType.VIRTUAL_MEM, MemoryProtection.PAGE_EXECUTE_READWRITE);
byte[] bytes = new byte[shellcode.Length * sizeof(char)];
Buffer.BlockCopy(shellcode.ToCharArray(), 0, bytes, 0, bytes.Length);
UIntPtr bytesout;
uint t_id;
bool Written = WriteProcessMemory(h_process, shellcode_address, bytes, (uint)shellcode_length, out bytesout);
IntPtr hThread = (IntPtr)CreateRemoteThread(h_process, (IntPtr)null, 0, (IntPtr)shellcode_length, (IntPtr)shellcode_address, 0, out t_id);
int Result = WaitForSingleObject(hThread, 10 * 1000);
if (Result == 0x00000080L || Result == 0x00000102L || Result == 0xFFFFFFFF)
{
if (hThread != null)
{
CloseHandle(hThread);
}
}
Thread.Sleep(1000);
VirtualFreeEx(h_process, shellcode_address, (UIntPtr)0, 0x8000);
if (hThread != null)
{
CloseHandle(hThread);
}
}
}
}
As you may see, I have saved the returned values of the unmanaged API into variables which I used to see if it was working or not, it seemed to be doing fine but it crashes the target process, logs haven't recorded any errors related to it.
Can managed programs inject into unmanaged processes? Am I casting wrong variable types? Is the shellcode translated into byte array incorrectly? Please let me know, thanks.
EDIT: It crashes at CreateRemoteThread
CreateRemoteThread creates a native thread in another process, the start address it receives must point to valid machine code or the thread will crash the process.
The scenario you describe is different, you want to instruct the Python interpreter of another process to execute some code. This can be done, but it is different and considerably more difficult.
Inject a native library into the other process which does two things:
setup the Python interpreter
setup some means of interprocess communication (IPC)
Use the IPC to send the Python code you want to execute to the other process and the code in the library you injected then executes that code using the Python interpreter.
You can find an example of how to inject a DLL into another process in this Codeproject article.
It looks like you are trying to run some arbitrary Python code from .net. Now you are trying to invoke the Python interpreter to actually do this.
The cons of doing this are:-
It is complicated as you found out.
Interprocess communication makes it even harder, as you move bytes across the boundary
Then you need to parse the information that you get from each side into something that makes sense (probably using some kind of XML)
Finally with all the above overhead its slow
Now one way around this is to invoke the python program directly within .net. Now I have never done so in my life AND I have never seen a python in my life (except maybe the type that hisses). Take a look at http://msdn.microsoft.com/en-us/library/ee461504.aspx, unfortunately it looks like they are storing the python in a file and invoking it there. However I am sure you can invoke code stored as a string.
The main disadvantage of using the DLR implementation of python is that you are relying on a third party to get the Python -> CLR translation correct. But I think IronPython is a microsoft sponsored open source project.
For more information see: http://ironpython.codeplex.com/