I'm having some problems implementing an algorithm to read a foreign process' memory. Here is the main code:
System.Diagnostics.Process.EnterDebugMode();
IntPtr retValue = WinApi.OpenProcess((int)WinApi.OpenProcess_Access.VMRead | (int)WinApi.OpenProcess_Access.QueryInformation, 0, (uint)_proc.Id);
_procHandle = retValue;
WinApi.MEMORY_BASIC_INFORMATION[] mbia = getMemoryBasicInformation().Where(p => p.State == 0x1000).ToArray();
foreach (WinApi.MEMORY_BASIC_INFORMATION mbi in mbia) {
byte[] buffer = Read((IntPtr)mbi.BaseAddress, mbi.RegionSize);
foreach (IntPtr addr in ByteSearcher.FindInBuffer(buffer, toFind, (IntPtr)0, mbi.RegionSize, increment)) {
yield return addr;
}
}
Read() ... method
if (!WinApi.ReadProcessMemory(_procHandle, address, buffer, size, out numberBytesRead)) {
throw new MemoryReaderException(
string.Format(
"There was an error with ReadProcessMemory()\nGetLastError() = {0}",
WinApi.GetLastError()
));
}
Although generally it seems to work correctly, the problem is that for some memory values ReadProcessMemory is returning false, and GetLastError is returning 299. From what I've googled, it seems to happen on vista because some params of OpenProcess were updated. Anyone knows what this is about? And what values should I try? Notice that as they changed, I wouldn't want to know if it's VM_READ or so, I want to know exactly what the values are.
EDIT: maybe it has something to do with not calling VirtualProtect()/VirtualProtectEx()? as seen on this SO url: WriteProcessMemory/ReadProcessMemory fail
Edit2: That was it! ^^ That is the solution, calling to VirtualProtectEx() first and after ReadProcessMemory()!
C:\Debuggers>kd -z C:\Windows\notepad.exe
0:000> !error 0n299
Error code: (Win32) 0x12b (299) - Only part of a ReadProcessMemory
or WriteProcessMemory request was completed.
This means you tried to read a block that was partially unmapped addresses (i.e. if the app itself did this, it'd AV)
You store the handle to the newly opened process in a local variable (retValue), but you don't pass it to your getMemoryBasicInformation function, so I can only assume that it actually fetches information about the current process. I suspect you're really using your own process's address ranges as though they belong to the other process. Many of the address ranges will probably be the same between processes, so that error wouldn't be immediately apparent.
Related
I have the following code in a loop, reading the contents of a file and transferring it via USB to an external device.
The loop works fine on one device, but if I swap it out for a different device (same device type, different unit) it works fine, but on the last iteration of the loop, somehow the Serial Port gets jammed up or something, not allowing me to perform any Read actions without a Timeout exception being thrown.
I've verified there are bytes available to read in the buffer, yet it just times out.
Now since it's the same code executing again and again (hundreds if not thousands of times, depending on the file size) I don't see why it should act any differently on the last iteration.
I assume I am doing something wrong (even though the code works on another unit) yet this is still mind boggling to me. Any sort of help will be greatly appreciated.
Here's the code:
for(int i = 0; i < fileData.Length; i++)
{
sendBuffer.Add(fileData[i]);
if(sendBuffer.Count == 61)
{
var result = writeI2cWithoutRegister(0x40, sendBuffer.ToArray());
Thread.Sleep(50); // At least 50ms between write actions
sendBuffer.Clear();
}
}
public bool writeI2cWithoutRegister(int deviceAddress, byte[] data)
{
mainPort.WriteLine(""); // This sends a certain command for our external product.
Thread.Sleep(25); // Force at least 25ms between write and read actions.
bool success = false;
do
{
try
{
var msg = mainPort.ReadLine();
Thread.Sleep(50);
if (msg.Contains("Write") || msg.Contains("Error"))
success = false;
if (!bool.TryParse(msg, out success))
success = false;
}
catch
{
success = false;
Console.WriteLine("Read exception, trying again...");
counter++;
}
}
while (success == false);
return success;
}
The do-while was an attempt to perhaps retry again and again until it works, I end up in an infinite loop, it always throws an exception (on the last for loop iteration as mentioned before).
Code above 99.99% of the time works, but not for the last message, not quite sure what's going on here. SerialPort WriteLine function works, but ReadLine times out while there definitely is data in the In Buffer.
I've done some digging around and it turns out #MatthewWatson's lead helped me the most, so all credit goes to them.
I've modified my code to use the Base Stream and not using the high-level functions of the SerialPort class, and it seems to have solved my issues.
Hopefully this helps someone in the future.
I would like to retrieve information about all running processes that match a certain name pattern. I do that by using the following code I found online, which apparently is supposed to help with some privilige issues on Windows Vista and above. Sadly, that does not work for me. I am executing the following code as administrator.
The Natives.OpenProcess works fine the first time it is being called, but fails for every after call that by returning IntPtr.Zero and GetLastWin32Error() returns "Access Denied".
public static string GetExecutablePathAboveVista(int ProcessId)
{
var buffer = new StringBuilder(1024);
IntPtr hprocess = Natives.OpenProcess(ProcessAccessFlags.PROCESS_QUERY_LIMITED_INFORMATION, false, ProcessId);
if (hprocess != IntPtr.Zero)
{
try
{
int size = buffer.Capacity;
if (Natives.QueryFullProcessImageName(hprocess, 0, buffer, out size))
{
return buffer.ToString();
}
}
finally
{
Natives.CloseHandle(hprocess);
}
}
throw new Win32Exception(Marshal.GetLastWin32Error());
}
OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, ..) give you ERROR_ACCESS_DENIED when and only when you have no SE_DEBUG_PRIVILEGE enabled. so can be only 2 case: or before first call GetExecutablePathAboveVista you have enabled SE_DEBUG_PRIVILEGE in thread (if it have token) or process token. and before second/next calls you direct or faster of all indirect disable this privilege or impersonate thread with another token. or possible you say confuse processes - first time you open one process (id) and second time you try open another process (id) - not clear from your code.
I am executing the following code as administrator.
this is not enough. this mean only that in your process token exist SE_DEBUG_PRIVILEGE. (with default windows settings, however this can be changed) but you need that this privilege will be enabled in token, not just exist.
also
that match a certain name pattern
if you need only process name without full path - you already have it when you enumerate all running processes.
also exist undocumented SystemProcessIdInformation information class for ZwQuerySystemInformation - with it you can got full path of process without open it and have any privileges.
I wrote a class, that should provide basic interaction with NodeJS server. This class also includes TcpClient instance and works asynchronously (methods like BeginRead, BeginWrite, ...) so many functions takes callbacks (anonymous function using lambda expr.) as an argument. Problem starts in this scenario (I try to illustrate on a peace of code similar to original).
this._nodeJS.Send("DATA_TO_SEND", (Response) => {
Console.WriteLine(Response);
// Section1
this._nodeJS.Send("ANOTHER_DATA", (Response1) => {
Console.WriteLine(Response1);
});
});
Problem occurs in Section1. When it's commented out, program behaves as expected. Response is received a written to Console. When it's not commented out, it starts to behave very strange. Write to Console in Section1 doesn't work (in many cases) and, what is important, code below Console.WriteLine in this section is not executed, the "thread" just stops right before command. I tried to debug it, step by step, variables in Section1 are correctly set, and when I get to the next command, debugging just stops. Is there anything wrong with this approach? Is there some things I need to be aware of?
For better imagination here is my example. I connect to the NodeJS server, when it's done, I send a request and wait for response containing data, that are processed and again sent to the NodeJS server in next request (Section1). NodeJS give me final response and program works ... Thanks for any advice!
Finally, I figured out, what's goin' on. I know, I din't show my original code and instead used some kind of pseudo-code, but if someone is interested to know, problem, probably, was causing wrong conversion of received data. I have buffer of size 1024 and StringBuilder variable where the data was appended. So when I received the data, converted it this way: Encoding.UTF8.GetString(state.Buffer) - this is wrong, instead, I had to use Encoding.UTF8.GetString(state.Buffer, 0, bytesRead). I don't know how, but this part of code was causing troubles and stopping callback to execute.
Without knowing your implementation details, I would suspect that the second _nodeJS.Send(... call is being blocked by the response from the first Send call.
At a guess, your code does something like this (made up pseudocode!):
void Send(String data, Action<Response> callback)
{
_socket.BeginSend(Magic(data), r => {
callback.Invoke(r.ResponseData);
_socket.EndSend(r.Result); //you cannot call _socket.Send() again until you have done this!
});
}
Due to order of operations, it should be doing this:
void Send(String data, Action<Response> callback)
{
_socket.BeginSend(Magic(data), r => {
_socket.EndSend(r.Result);
callback.Invoke(r.ResponseData);
});
}
I have a question about remote threads.I've read Mike Stall's article present here: <Link>
I would like to create a remote thread that executes a delegate in another process, just like Mike Stall does. However, he declares the delegate in the target process, obtaining a memory address for it and then he creates the remote thread from another process using that address. The code of the target process CANNOT be modified.
So, I cannot use his example, unless I can allocate memory in the target process and then WriteProcessMemory() using my delegate.
I have tried using VirtualAllocEx() to allocate space in the target process but it always returns 0.
This is how it looks so far.
Console.WriteLine("Pid {0}:Started Child process", pid);
uint pidTarget= uint.Parse(args[0]);
IntPtr targetPid= new IntPtr(pidTarget);
// Create delegate I would like to call.
ThreadProc proc = new ThreadProc(MyThreadProc);
Console.WriteLine("Delegate created");
IntPtr fproc = Marshal.GetFunctionPointerForDelegate(proc);
Console.WriteLine("Fproc:"+fproc);
uint allocSize = 512;
Console.WriteLine("AllocSize:" + allocSize.ToString());
IntPtr hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pidParent);
Console.WriteLine("Process Opened: " + hProcess.ToString());
IntPtr allocatedPtr = VirtualAllocEx(targetPid, IntPtr.Zero, allocSize, AllocationType.Commit, MemoryProtection.ExecuteReadWrite);
Console.WriteLine("AllocatedPtr: " + allocatedPtr.ToString());
Now my questions are:
In the code above, why does VirtualAllocEx() not work? It has been imported using DLLImport from Kernel32. The allocatedPtr is always 0.
How can I calculate alloc size? Is there a way I can see how much space the delegate might need or should I just leave it as a large constant?
How do I call WriteMemory() after all of this to get my delegate in the other process?
Thank you in advance.
That blog post is of very questionable value. It is impossible to make this work in the general case. It only works because:
the CLR is known to be available
the address of the method to execute is known
it doesn't require injecting a DLL in the target process
Windows security is unlikely to stop this particular approach
Which it achieves by handing the client process everything it needs get that thread started. The far more typical usage of CreateRemoteThread is to do so when the target process does not cooperate. In other words, you don't have the CLR, you have to inject a DLL with the code, that code can't be managed, you have to deal with the DLL getting relocated and Windows will balk at all this.
Anyhoo, addressing your question: you don't check for any errors so you don't know what is going wrong. Make sure your [DllImport] declarations have SetLastError=true, check the return value for failure (IntPtr.Zero here) and use Marshal.GetLastWin32Error() to retrieve the error code.
I am using Nektra's Deviare to hook winsock's send method calls. My ideia is to learn to also send messages through the same socket than the original application. So what I'm doing is when i detect the first call to send message, I save the socket id(the first argument of the send function), so I can use it later.
So here is my code:
uint socket = 0;
[DllImport("Ws2_32.dll")]
private static extern int send(uint socket, string buf, int len, int flags);
void _proxy_OnFunctionCalled(DeviareTools.IProcess proc, DeviareParams.ICallInfo callInfo, Deviare.IRemoteCall rCall)
{
socket = (uint)callInfo.Params.get_Item(0).Value;
}
and later
int ret = send(socket, "ABC", 3, 0);
MessageBox.Show(ret.ToString());
This last messagebox is poping up always -1. Why should be it?
Thanks
edit: calling WSAGetLastError() returns 2. Which I do not know what it means, as it doesn't seem to appear on msdn.
Try doing
MessageBox.Show(socket.ToString());
as well and make sure your socket variable got set.
I believe error 2 is "file not found", which would suggest to me that you have an invalid socket id, but I could be wrong about that.
WinSock must be initialized, a Socket must be created, a connection must be made (unless your socket is a SOCK_DGRAM), so than you can send() anything.
Besides that, API functions are meant to work with data from (char *) pointers, ensure that it is happening. Maybe "ABC" is being declared as a WIDECHAR array, a String object or something not a (char *) buffer.
There's a full exemple of a basic socket connection here in MSDN: http://msdn.microsoft.com/en-us/library/ms737625(VS.85).aspx
It might a bit late but the problem is that you are trying to use a socket created in a different process.
Using Deviare you get a socket id from one process and you are trying to use it in your process. That doesn't work because socket ids are only valid in the process where they were created.