From: Willy Denoyette [MVP] on

"SQACSharp" <lsdisciples(a)hotmail.com> wrote in message
news:1162691474.481310.78130(a)h54g2000cwb.googlegroups.com...
| Your help is really appreciated Willy since i'm trying to do this since
| almost a week :(
|
| Ok i try to understand how to use the openProcess, VirtualAllocEx,
| ReadProcessMemory and VirtualFreeEx to solve my problem but i'm not
| sure exactly how i'm suppose to use the ReadProcessMemory to retreive
| the controlname returned by my sendmessage API call..This is what it
| look like after spending 3-4 more hours on that :
|
| System.Diagnostics.Process.Start("\"C:\\MyApplication.exe\"", "");
| int hwnd = 0;
| IntPtr hwndChild = IntPtr.Zero;
| hwnd = FindWindow(null, "Login");
| hwndChild = FindWindowEx((IntPtr)hwnd, IntPtr.Zero, "TEdit", "");
| SetControlText((int)hwndChild, WM_SETTEXT, 0, "MyPassword!");
|
| // The following is my nightmare to get the controlname....still not
| working :(
| System.Diagnostics.Process[] processes;
| processes = System.Diagnostics.Process.GetProcesses();
| uint ProcessId;
| IntPtr hProcess = IntPtr.Zero;
| const uint PROCESS_ALL_ACCESS = (uint)(0x000F0000L | 0x00100000L |
| 0xFFF);
| foreach (System.Diagnostics.Process instance in processes)
| {
| if (instance.ProcessName == "MyApplication")
| {
| ProcessId = (uint)instance.Id;
| hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0,
| (uint)instance.Id);
| }
| }
| if (hProcess == IntPtr.Zero)
| throw new ApplicationException("Failed to access process");
| const int dwBufferSize = 1024;
| const uint MEM_COMMIT = 0x1000;
| const uint MEM_RELEASE = 0x8000;
| const uint PAGE_READWRITE = 0x04;
| IntPtr lpRemoteBuffer = IntPtr.Zero;
| IntPtr lpLocalBuffer = IntPtr.Zero;
| IntPtr threadId = IntPtr.Zero;
| lpLocalBuffer = Marshal.AllocHGlobal(dwBufferSize);
| lpRemoteBuffer = VirtualAllocEx(hProcess, IntPtr.Zero, dwBufferSize,
| MEM_COMMIT, PAGE_READWRITE);
| if (lpRemoteBuffer == IntPtr.Zero)
| throw new SystemException("Failed to allocate memory in remote
| process");
| Int32 SendMsg;
| SendMsg = RegisterWindowMessage("WM_GETCONTROLNAME");
| long ReturnMsg;
| IntPtr ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(IntPtr)));
| Marshal.WriteIntPtr(ptr, IntPtr.Zero);
| MessageBox.Show(SendMsg.ToString());
| ReturnMsg = SendMessage((int)hwndChild, SendMsg, 65536,
| lpRemoteBuffer);
| bool bSuccess;
| bSuccess = ReadProcessMemory(hProcess, lpRemoteBuffer, lpLocalBuffer,
| dwBufferSize,IntPtr.Zero);
| if (!bSuccess)
| throw new SystemException("Failed to read from process memory");
| string retval;
| retval = Marshal.PtrToStringAnsi(lpRemoteBuffer);
| MessageBox.Show(retval); //This is not working....how I'm suppose to
| read the string value returned by my sendmessage???
|
|

-OpenProcess should not expect to have PROCESS_ALL_ACCESS access privs. (you
shouldn't even expect to have any privilege at all), specify only the
minimum required which is PROCESS_VM_OPERATION, PROCESS_VM_REA and
PROCESS_VM_WRITE.

const short PROCESS_VM_OPERATION = 0x8;
const short PROCESS_VM_READ = 0x10;
const short PROCESS_VM_WRITE = 0x20;

- VirtualAllocEx must allocate the same buffer size as passed with
SendMessage, that is - 65536, which is the minimum that should be
allocated.
- You don't need a native heap allocated local buffer (lpLocalBuffer ),
point is that you allocate memory in the target process and read from there
using ReadProcessMemory specifying a (local) byte[] as destination.
...
uint bufferSize = 65536;
byte[] bytearray = new byte[buffSize];
...
ReadProcessMemory(...., lpRemoteBuffer, bytearray, bufferSize,...);

- The byte[] can be converted to a string using the appropriate GetString
method of the Encoding class. Note that using VirtualAllocEx requires a
Unicode based Windows OS (NT4 and higher), so you can use something like:

string s = Encoding.Default.GetString(bytearray).TrimEnd('0');
to convert the byte[] to string.

As a genera remark, you should take care passing machine independent IntPtr
arguments in SendMessage. That means tha you should declare the size
argument as an IntPtr and pass it "new IntPtr(65536)" as value. The same is
valid for the handle argument. So your declarartion should look something
like:

... SendMessage(IntPtr handle, uint msg, IntPtr wParam, IntPtr
lParam);

or better use a SafeHandle for your handle parameters...


Same remark for your other API declarations.

And finally, don't forget to call VirtualFreeEx and to check the return
values !!!!

Willy.











From: SQACSharp on
OK, I modify the code according to all your comments.

Now I have a compiling error that prevent me to try the code with the
modification :

Error 1 - The best overloaded method match for
'TestWinAPI.MainForm.ReadProcessMemory(System.IntPtr, System.IntPtr,
System.IntPtr, int, System.IntPtr)' has some invalid

Error 2 - Argument '3': cannot convert from 'byte[]' to 'System.IntPtr'


Here is line of the error ::

bSuccess = ReadProcessMemory(hProcess, lpRemoteBuffer, ***ERROR***
bytearray, (int)bufferSize, NumRead);

Here is the code that use the bytearray :
//--------------------------
const int dwBufferSize = 65536;
uint bufferSize = 65536;
byte[] bytearray = new byte[bufferSize];

//....blablabla

IntPtr lpRemoteBuffer = IntPtr.Zero;
lpRemoteBuffer = VirtualAllocEx(hProcess, IntPtr.Zero, dwBufferSize,
MEM_COMMIT, PAGE_READWRITE);

//....blablabla

ReturnMsg = SendMessage((IntPtr)hwndChild, SendMsg, SizePtr, NumRead);

bSuccess = ReadProcessMemory(hProcess, lpRemoteBuffer, bytearray,
(int)bufferSize, NumRead);
//--------------------------


Any idea about how to convert from 'byte[]' to 'System.IntPtr ????

Thanks again for your time

Michel

From: Willy Denoyette [MVP] on
See inline...

Willy.

"SQACSharp" <lsdisciples(a)hotmail.com> wrote in message
news:1162749951.848994.55550(a)b28g2000cwb.googlegroups.com...
| OK, I modify the code according to all your comments.
|
| Now I have a compiling error that prevent me to try the code with the
| modification :
|
| Error 1 - The best overloaded method match for
| 'TestWinAPI.MainForm.ReadProcessMemory(System.IntPtr, System.IntPtr,
| System.IntPtr, int, System.IntPtr)' has some invalid
|
| Error 2 - Argument '3': cannot convert from 'byte[]' to 'System.IntPtr'
|
|
You need to declare the argument as a byte[] not an IntPtr, something like
this:

static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr
lpBaseAddress,
[Out] byte [] lpBuffer, UIntPtr nSize, IntPtr
lpNumberOfBytesRead);


| Here is line of the error ::
|
| bSuccess = ReadProcessMemory(hProcess, lpRemoteBuffer, ***ERROR***
| bytearray, (int)bufferSize, NumRead);
|
| Here is the code that use the bytearray :
| //--------------------------
| const int dwBufferSize = 65536;
| uint bufferSize = 65536;
| byte[] bytearray = new byte[bufferSize];
|

No need to define the size a second time.
const int dwBufferSize = 65536;
byte[] bytearray = new byte[dwBufferSize ];


| //....blablabla
|
| IntPtr lpRemoteBuffer = IntPtr.Zero;
| lpRemoteBuffer = VirtualAllocEx(hProcess, IntPtr.Zero, dwBufferSize,
| MEM_COMMIT, PAGE_READWRITE);
|
| //....blablabla
|
| ReturnMsg = SendMessage((IntPtr)hwndChild, SendMsg, SizePtr, NumRead);
|
| bSuccess = ReadProcessMemory(hProcess, lpRemoteBuffer, bytearray,
| (int)bufferSize, NumRead);
| //--------------------------
|
|
| Any idea about how to convert from 'byte[]' to 'System.IntPtr ????
|
| Thanks again for your time
|
| Michel
|


From: SQACSharp on
I change ReturnMsg to a IntPointer
IntPtr ReturnMsg = IntPtr.Zero;

Here is the missing declaration for SendMessage :
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr handle, uint msg, IntPtr
wParam, IntPtr
lParam);

But it still return 0 for and 0 bytes read....



Michel

From: SQACSharp on
the function RegisterWindowMessage("WM_GETCONTROLNAME");
return 49589..... If I call RegisterWindowMessage("WM_BLABLABLA"); it
also return 49589 ??????

Is this return value is a kind of non found return value????
Are you sure I can use registerWindowMessage to get the int value of
const "WM_GETCONTROLNAME" ???


System.UInt32 SendMsg;
SendMsg = RegisterWindowMessage("WM_GETCONTROLNAME");
MessageBox.Show(SendMsg.ToString());