Using out parameters of a native DLL from C# - c#

I need to be using the following function from a native dll (WNSMP32.dll) in my C# code.
SNMPAPI_STATUS SnmpStartupEx( _Out_ smiLPUINT32 nMajorVersion,...);
//Considering just one for purpose of discussion
For this, I have the dllimport declaration as
[DllImport("wsnmp32.dll")] internal static extern
Status SnmpStartupEx(out IntPtr majorVersion, ...);
//Considering just one for purpose of discussion
I am using the function as
IntPtr majorVersion = Marshal.AllocHGlobal(sizeof(UINT32))
status = SnmpStartupEx(out majorVersion, out minVersion,
out level, out translateMode, out retransmitMode )
After the allocation of memory, I am printing the values of the IntPtr.
<<<DEBUG OUTPUT>>> IntPtr Value = 112235522816
However after the call to the , I find that the IntPtr is changing!
<<<DEBUG OUTPUT>>> IntPtr after calling SnmpStartupEx
<<<DEBUG OUTPUT>>> IntPtr Value = 111669149698
Should I be allocating memory through Marshal.AllocHGlobal before the call?
Is it valid for the IntPtr's address to change after the call?

Try:
[DllImport("wsnmp32.dll")]
internal static extern Status SnmpStartupEx(out UInt32 majorVersion,
out UInt32 minorVersion,
out UInt32 level,
out UInt32 translateMode,
out UInt32 retransmitMode);
Every out parameter is actually a pointer to a variable which the function overwrites. You don't want to write out IntPtr unless the native code has a double-pointer.
You could do all of that yourself with AllocHGlobal and a normal (pass-by-value, not out) IntPtr parameter... but why go to all that trouble when the compiler can do it for you (and the compiler will be faster, since it will take the address of local variables on the stack instead of allocating buffer space dynamically and then copying)?

Related

Random AccessViolationException in multithread simulation when using LoadLibrary to P/Invoke methods

I have an application in C# that simulates multiple mathematical models written in C++ in parallel(each model in a thread). Each model has 4 methods : Init, Run, Free and Save. Each method is dynamically loaded using LoadLibrary from kernel32. Using the LoadLibray method, we load the DLL and then using GetProcAddress we get the 4 main methods. The application has Play/Pause/Stop.
When we Play the simulation for the first time, there's no problem in the simulation but, if we Stop and Play again, after a couple of seconds, the program throws AccessViolationException in the Run method of a RANDOM model. There's no pattern, which makes me belive that problem lies in the P/Invoke operation. Look at the following example :
//The C++ Dll.
extern "C" __stdcall void Init(const char* name, int size, void* buffer, void** memory);
extern "C" __stdcall void Run(int in_size, int out_size, void* in_buffer, void* out_buffer, void** memory);
extern "C" __stdcall void Free(void** memory);
extern "C" __stdcall void Save(int size, void* buffer, void** memory);
// after the P/Invoke Dll and Marshal.GetDelegateForFunctionPointer method (in C# code)
ModelInit(string name, int size, IntPtr buffer, ref IntPtr memory);
ModelRun(int in_size, int out_size, IntPtr in_buffer, IntPtr out_buffer, ref IntPtr memory); // <---- THE EXCEPTION IS THROWN HERE
ModelFree(ref IntPtr memory);
ModelSave(int size, IntPtr buffer, ref IntPtr memory);
I have no idea how to debug this, i've already tried to make c++/cli wrapper to avoid P/Invoke, but some DLLs has third-party libraries that were built in /MTd option, and the C++/CLI is incompatible.

After calling the Windows function ReadFile(), where does the actual file data get stored?

I'm using the Windows API function ReadFile() to read system metafiles. But what I'm confused about is how to actually process the data that is returned from that function. I'm assuming that it's stored in the lpBuffer parameter, and that I somehow need to decode the contents of that buffer in order to interpret the actual data.
I'm running Windows 10 and am using C# to make interop calls.
Here's my wrapper:
[DllImport("kernel32", CharSet = CharSet.Auto)]
public static extern bool ReadFile(SafeFileHandle hFile, IntPtr lpBuffer, uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, ref NativeOverlapped lpOverlapped);
And here's my call:
NativeMethods.ReadFile(_volumeHandle, (IntPtr)buffer, (uint)len, out read, ref overlapped)
//do something with the buffer???
The data contained in the buffer after the call is a pointer to an int - which is what I expected - but where is the actual file data?
You need to supply the buffer. See https://learn.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-readfile

SetConsoleActiveScreenBuffer does not display screen buffer

I am currently trying to write a console application in C# with two screen buffers, which should be swapped back and forth (much like VSync on a modern GPU). Since the System.Console class does not provide a way to switch buffers, I had to P/Invoke several methods from kernel32.dll.
This is my current code, grossly simplified:
static void Main(string[] args)
{
IntPtr oldBuffer = GetStdHandle(-11); //Gets the handle for the default console buffer
IntPtr newBuffer = CreateConsoleScreenBuffer(0, 0x00000001, IntPtr.Zero, 1, 0); //Creates a new console buffer
/* Write data to newBuffer */
SetConsoleActiveScreenBuffer(newBuffer);
}
The following things occured:
The screen remains empty, even though it should be displaying newBuffer
When written to oldBuffer instead of newBuffer, the data appears immediately. Thus, my way of writing into the buffer should be correct.
Upon calling SetConsoleActiveScreenBuffer(newBuffer), the error code is now 6, which means invalid handle. This is strange, as the handle is not -1, which the documentation discribes as invalid.
I should note that I very rarely worked with the Win32 API directly and have very little understanding of common Win32-related problems. I would appreciate any sort of help.
As IInspectable points out in the comments, you're setting dwDesiredAccess to zero. That gives you a handle with no access permissions. There are some edge cases where such a handle is useful, but this isn't one of them.
The only slight oddity is that you're getting "invalid handle" rather than "access denied". I'm guessing you're running Windows 7, so the handle is a user-mode object (a "pseudohandle") rather than a kernel handle.
At any rate, you need to set dwDesiredAccess to GENERIC_READ | GENERIC_WRITE as shown in the sample code.
Also, as Hans pointed out in the comments, the declaration on pinvoke.net was incorrect, specifying the last argument as a four-byte integer rather than a pointer-sized integer. I believe the correct declaration is
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateConsoleScreenBuffer(
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwFlags,
IntPtr lpScreenBufferData
);

Call a function from an injected DLL

First off I would like to say, that I am not trying to hack a game. I am actually employed by the company whose process I am trying to inject. :)
I would like to know how to call a function from an already injected DLL.
So, I have successfully injected and loaded my DLL in the target using CreateRemoteThread(). Below you can see a snippet of the injection:
private static bool Inject(Process pToBeInjected, string sDllPath,out string sError, out IntPtr hwnd, out IntPtr hLibModule)
{
IntPtr zeroPtr = (IntPtr)0;
hLibModule = zeroPtr;
IntPtr hProcess = NativeUtils.OpenProcess(
(0x2 | 0x8 | 0x10 | 0x20 | 0x400), //create thread, query info, operation ,write, and read
1,
(uint)pToBeInjected.Id);
hwnd = hProcess;
IntPtr loadLibH = NativeUtils.GetProcAddress( NativeUtils.GetModuleHandle("kernel32.dll"),"LoadLibraryA");
IntPtr dllAddress = NativeUtils.VirtualAllocEx(
hProcess,
(IntPtr)null,
(IntPtr)sDllPath.Length, //520 bytes should be enough
(uint)NativeUtils.AllocationType.Commit |
(uint)NativeUtils.AllocationType.Reserve,
(uint)NativeUtils.MemoryProtection.ExecuteReadWrite);
byte[] bytes = CalcBytes(sDllPath);
IntPtr ipTmp = IntPtr.Zero;
NativeUtils.WriteProcessMemory(
hProcess,
dllAddress,
bytes,
(uint)bytes.Length,
out ipTmp);
IntPtr hThread = NativeUtils.CreateRemoteThread(
hProcess,
(IntPtr)null,
(IntPtr)0,
loadLibH, //handle to LoabLibrary function
dllAddress,//Address of the dll in remote process
0,
(IntPtr)null);
uint retV= NativeUtils.WaitForSingleObject(hThread, NativeUtils.INFINITE_WAIT);
bool exitR = NativeUtils.GetExitCodeThread(hThread, out hLibModule);
return true;
}
Note: Error checking and freeing resources were removed for brevity, but rest assured I check all the pointers and free my resources.
After the function above exits, I have a non-zero module handle to my DLL returned by LoadLibrary through hLibModule, meaning that the DLL was loaded correctly.
My DLL is a C# class library meant to show a message box (for testing). I have tried testing the function and the message box pops up. It looks like this:
public class Class1
{
public static void ThreadFunc(IntPtr param )
{
IntPtr libPtr = LoadLibrary("user32.dll");
MessageBox(IntPtr.Zero, "I'm ALIVE!!!!", "InjectedDll", 0);
}
[DllImport("kernel32", SetLastError = true)]
public static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern int MessageBox(IntPtr hWnd, String text, String caption, int options);
}
I compile it from Visual Studio and the DLL appears in the Debug folder. I then pass the full path of my DLL to the injector.
After injection into the target process, I don't know how to call my ThreadFunc from the injected DLL, so it never executes.
I cannot use GetProcAddress(hLibModule,"ThreadFunc") since I am out of process, so the answer must lie into calling CreateRemoteThread() somehow. Also, I have read that DllMain is no longer allowed for .NET DLLs, so I cannot get any free execution that way either.
Does anyone have any idea how to call a function from an injected DLL?
Thank you in advance.
Well, you already got a thread running inside that process. You make it do something boring, it only loads a DLL. This works completely by accident, LoadLibrary just happens to have to correct function signature.
It can do much more. That however better be unmanaged code, just like LoadLibrary(), you cannot count on any managed code running properly. That takes a heckofalot more work, you have to load and initialize the CLR and tell it to load and execute the assembly you want to run. And no, you cannot load the CLR in DllMain().
Keywords to look for are CorBindToRuntimeEx() and ICLRRuntimeHost::ExecuteInAppDomain(). This is gritty stuff to get going but I've seen it done. COM and C++ skills and generous helpings of luck required.

C# string to long pointer

I am working with an application in C# that need to send a message to a C++ application.
I imported
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(
int hWnd, // handle to destination window
uint Msg, // message
IntPtr wParam, // first message parameter
IntPtr lParam // second message parameter
);
but now, my problem is that I need to passe string to wParam and lParam. I tried unsafe code, but it seems string just doesnt work like the rest of variables. How can I achieve that? Thanks.
The declaration is wrong, the wParam and lParam arguments are IntPtr, not long.
There is a complication because you are trying to send strings. What matters if the target window is Unicode enabled or not. There are two versions of SendMessage, SendMessageA() and SendMessageW(). The former needs to be used if the program is dated and uses 8-bit character strings rather than UTF-16 encoded strings.
You can find out by using Spy++. Use the finder tool to select the window of the application. In the General property tab, you'll see "Window proc". It will say (Unicode) if the window is Unicode enabled. If you don't see it then the strings have to be translated to 8-bit characters.
To generate the string pointers you need to pass, you can use Marshal.StringToHGlobalAnsi or StringToHGlobalUni (respectively 8-bit and Unicode). You can however play a trick to let the P/Invoke marshaller translate the string for you. Saves you the hassle of having to free the strings after the call. For the Ansi version, you can declare the API function like this:
[DllImport("user32.dll", CharSet = CharSet.Ansi, EntryPoint = "SendMessageA", ExactSpelling = true)]
private static extern IntPtr SendMessageStrings(IntPtr hWnd, int msg, string wParam, string lParam);
And the Unicode version like this:
[DllImport("user32.dll", CharSet = CharSet.Unicode, EntryPoint = "SendMessageW", ExactSpelling = true)]
private static extern IntPtr SendMessageStrings(IntPtr hWnd, int msg, string wParam, string lParam);
One final note: this will not work as-is if the window belongs to another application, you'll crash it. The pointer values you pass are only valid in your own process, not in the C++ process. To work around that, you have to allocate memory in the target process so that the pointer is valid. That requires OpenProcess to get a handle to the process, VirtualAllocEx() to allocate memory in the target process, big enough to store the string, WriteProcessMemory to write the string. Now you can call SendMessage(), use a version that is declared with IntPtr for the wParam and lParam arguments, pass the value you got from VirtualAllocEx. Next use VirtualFreeEx() to release the memory and CloseHandle to clean up. Or keep the memory around for the next time if you do this often.
Quite a lot of P/Invoke to get wrong there. Not to mention security issues, WriteProcessMemory requires admin privileges, UAC elevation is required.
Passing the address of the string would involve unsafe code,
since Win32 API calls expect addresses (in a C/C++ native envrion). What windows message are you sending that requires a string in wParam or lParam?
We ended up using "WmCpyDta_d.dll" to deal with all that.

Categories

Resources