简体   繁体   中英

Why is C# Marshalling Strings not Working with C++ DLL

I am having issues passing strings to a certain function in my external DLL. I would post an actual code snippet but it's kind of messy and might be hard to read. The following snippets are what my personal code boils down to.

C# File (UNICODE)

[DllImport("InjectDll.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern ulong FindProgramProcessId(string procName);
[DllImport("InjectDll.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern bool InjectIntoProcess(ulong procId, string Dll);
string ProcName = "random_test_game.exe";
string DllPath = @"C:\ProgramData\Hack\File.dll";
ulong procId = FindProgramProcessId(ProcName);
bool Injected = InjectIntoProcess(procId, DllPath);

C++ File (ANSI)

DllExport DWORD FindProgramProcessId(const char* procName)
{
    ...
}
DllExport bool InjectIntoProcess(DWORD procId, const char* Dll)
{
    if (Dll == nullptr)
    {
        MessageBox(NULL, "DLL", "EMPTY", MB_OK);
        return false;
    }
    ...
}

C++ Header File

#pragma once
#include <Windows.h>
#include <TlHelp32.h>
#include <string>
#ifdef EXPORT
#define DllExport __declspec(dllexport)
#else
#define DllExport __declspec(dllimport)
#endif
extern "C" DllExport DWORD FindProgramProcessId(const char* procName);
extern "C" DllExport bool InjectIntoProcess(DWORD procId, const char* Dll);

Referencing the snippets, the issue arising is that FindProgramProcessId will successfully pass a string, no problemo, but InjectIntoProcess will show const char* Dll as nullptr according to the "extra" code I put in that method.

Notice, I have tried passing an IntPtr in place of string and using Marshal.StringToHGlobalAnsi , and I still get the Dll == nullptr issue. It's breaking my code. More of the same info can be found here at my GuidedHacking thread.

The Win32 DWORD is a 32 bit integer, but the C# ulong is a 64 bit integer. The confusion stems from the fact that DWORD is an alias for unsigned long , but the C++ long isn't necessarily 64 bits (in fact, in MSVC, it's 32 bits; unsigned long long is the 64 bit unsigned integer).

Since you're using the cdecl calling convention, the caller is responsible for cleaning the stack (so no crash occurs), and arguments are passed right-to-left (so Dll ends up pointing somewhere in the middle of the value passed to procId , which probably contains zeroes). Or at least that's my guess, since we're in undefined behavior territory here.

You should declare the return value of FindProgramProcessId and the procId parameter of InjectIntoProcess as uint instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM