I open a file in C# with FileStream, and I got the file handle number with this line:
IntPtr file_handle = fs.SafeFileHandle.DangerousGetHandle();
Now I want to pass this handle to C++ code and use this handle value to access the file. Is this possible? How to open a file with merely a file handle in C++?
Thanks.
Update
I use C# to P/Invoke into a C++ Win32 DLL(not a COM DLL). I open the file in C# as FileStream, and pass the handle to the C++. Here is some of my code in the C++ DLL:
extern "C" __declspec(dllexport)void read_file(HANDLE file_handle)
{
char buffer[64];
::printf("\nfile = %d\n",file_handle);
if(::ReadFile(file_handle,buffer,32,NULL,NULL))
{
for(int i=0;i<32;i++)
cout<<buffer[i]<<endl;
}
else
cout<<"error"<<endl;
}
And here is my C# code:
[DllImport("...",EntryPoint = "read_file", CharSet = CharSet.Auto)]
public static extern void read_file(IntPtr file_handle_arg);
But I get this error:
Unhandled Exception: System.AccessViolationException: Attempted to read or write
protected memory. This is often an indication that other memory is corrupt.
Thanks.
You can use win32 calls, the same way the filestream/file constructors do (via p/invoke).
Cracking it open in .NET Reflector, it looks like it is using this function:
[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern SafeFileHandle CreateFile(
string lpFileName,
int dwDesiredAccess,
FileShare dwShareMode,
SECURITY_ATTRIBUTES securityAttrs,
FileMode dwCreationDisposition,
int dwFlagsAndAttributes,
IntPtr hTemplateFile);
Here is an official reference:
http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx
This is just to open the file, though, as you asked when you said:
How to open a file with merely a file handle in C++
If you want to read an already open file, you might have more trouble. I'm not sure. You might be able to use this function:
[DllImport("kernel32.dll", SetLastError=true)]
internal static extern unsafe int ReadFile(
SafeFileHandle handle,
byte* bytes,
int numBytesToRead,
IntPtr numBytesRead_mustBeZero,
NativeOverlapped* overlapped
);
http://msdn.microsoft.com/en-us/library/aa365467(v=VS.85).aspx
That entirely depends -- but it's unlikely that you will be able to do this. I'm assuming that your C# code and C++ code are running in different processes -- if you're in the same process you should just be able to marshall over the IntPtr over as a HANDLE.
The problem is that file handles are specific to a process -- you won't be able to use that handle in another process.
That said, you're probably better off:
Passing the name of the file to the C++ code and opening it there
Passing the data actually contained whithin the file to the C++ and dealing with it there.
If the C++ code is C++/CLI, then don't bother with the handle at all. Just pass the FileStream object directly to your C++ code.
If the C++ is native code, then you can use the file handle anywhere you'd normally use a Windows HANDLE value for files, such as ReadFile and WriteFile. You wouldn't use the handle to open a file because it's already open. If you want another copy of the handle, or if you want to give the handle to another process, then use DuplicateHandle. If you need to the value with POSIX-like functions like _read and _write, then call _open_osfhandle to get a file descriptor. You can wrap the file descriptor into a C FILE* stream with _fdopen.
Turns out the title isn't really what the OP was after.
But if someone ever really needs to do this (say: Re-opening a file with different permissions), you can probably use a combination of GetFileInformationByHandle to get the File ID and OpenFileById.
FWIW.
Related
I'm creating a .NET application for a client that performs I/O with one of their third-party systems. As they regularly change the password of this system, I should retrieve it dynamically by calling a native DLL that they provide in a dedicated directory (not besides my EXE file).
However, I have trouble loading the DLL dynamically using LoadLibraryEx. The weird thing is that I can call the library using the DllImportAttribute.
This is what I have done so far:
According to this SO answer, I use the following code (in a constructor) to try to load the DLL dynamically:
public PasswordProvider(string dllPath)
{
if (!File.Exists(dllPath))
throw new FileNotFoundException($"The DLL \"{dllPath}\" does not exist.");
_dllHandle = NativeMethods.LoadLibraryEx(dllPath, IntPtr.Zero, LoadLibraryFlags.None);
if (_dllHandle == IntPtr.Zero)
throw CreateWin32Exception($"Could not load DLL from \"{dllPath}\".");
var procedureHandle = NativeMethods.GetProcAddress(_dllHandle, GetPasswordEntryPoint);
if (procedureHandle == IntPtr.Zero)
throw CreateWin32Exception("Could not retrieve GetPassword function from DLL.");
_getPassword = Marshal.GetDelegateForFunctionPointer<GetPasswordDelegate>(procedureHandle);
}
When LoadLibraryEx is called, the resulting handle is null, the error code is 126 which usually means that the DLL or one of its dependencies could not be found.
When I call LoadLibraryEx with DoNotResolveDllReferences, then I get a working handle but afterwards, I cannot call GetProcAddress (error code 127) - I suspect that I have to fully load the DLL for this.
When I open the native DLL in Dependencies (which essentially is Dependency Walker for Win10), I can clearly see that one of the statically linked DLLs is missing
However, if I copy the DLL besides my EXE file and use the DllImportAttribute, I can call into the DLL
[DllImport(DllPath, EntryPoint = GetPasswordEntryPoint, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]
private static extern long GetPassword(long systemId, string user, byte[] password);
How is this possible? I thought that the mechanism behind DllImportAttribute uses LoadLibary internally, too. Where does my code differ? Am I missing something obvious?
Just some notes:
I can't just use DllImportAttribute as I cannot specify searching in a dedicated directory this way (the DLL must lie beside my EXE file or in a common Windows location for this to work).
I also tried LoadLibrary instead of LoadLibraryEx but with the same results.
EDIT after Simons comment:
NativeMethods is defined as followed:
private static class NativeMethods
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr LoadLibrary(string dllName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr LoadLibraryEx(string dllFileName, IntPtr reservedNull, LoadLibraryFlags flags);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetProcAddress(IntPtr moduleHandle, string procedureName);
[DllImport("kernel32.dll")]
public static extern bool FreeLibrary(IntPtr moduleHandle);
}
[Flags]
private enum LoadLibraryFlags : uint
{
None = 0,
DoNotResolveDllReferences = 0x00000001,
LoadIgnoreCodeAuthorizationLevel = 0x00000010,
LoadLibraryAsDatafile = 0x00000002,
LoadLibraryAsDatafileExclusive = 0x00000040,
LoadLibraryAsImageResource = 0x00000020,
LoadLibrarySearchApplicationDir = 0x00000200,
LoadLibrarySearchDefaultDirs = 0x00001000,
LoadLibrarySearchDllLoadDir = 0x00000100,
LoadLibrarySearchSystem32 = 0x00000800,
LoadLibrarySearchUserDirs = 0x00000400,
LoadWithAlteredSearchPath = 0x00000008
}
EDIT after Hans Passant's comment:
The overall goal is the ability to replace / update the native DLL while my application (a Windows Service) is running. I detect a file change and then reload the DLL. I am not quite sure if this is possible with DllImportAttribute without restarting the service.
And I should be more specific on the actual problem: I couldn't load the native DLL using LoadLibraryEx, no matter if it was placed next to my EXE, or in another random folder, or in SysWow64. Why does it work with DllImportAttribute? I'm pretty sure that the missing FastMM subdependency DLL is not present on my system (neither next to the actual DLL, nor in any Windows directory).
It's because the DLL search order path. In windows when application try to load a DLL the underlying system automatically search some path for the DLL ,So let's pretend Windows's DLL search path looks something like this:
A) . <-- current working directory of the executable, highest priority, first check
B) \Windows
C) \Windows\system32
D) \Windows\syswow64 <-- lowest priority, last check
You can read more about the underlying mechanism in this Microsoft documentation.
Search for DLL which your main DLL has dependency to it and find where it store on system, add the directory of it to DLL search path of Windows using AddDllDirectory or SetDllDirectory.
If the dll already loaded into memory by any of running process Windows automatically use it instead of searching, so you can load FastMM DLL into memory using LoadLibrary manually and then try to load the main DLL and it should solve the problem too.
#HansPassant and #David Heffernan are right: I actually tried to load two different versions of the DLL (one of them had the FastMM subdependency, one did not). Thanks for your help and sorry for the inconvenience.
I want use a DLL (developed in C++) in WinDev application , my DLL works fine with C# code and i can call any method in there , however with Windev i can successfuly load the DLL using :
hInst = LoadDLL("MyDLL.DLL")
but when i want invoke a method this way :
CallDLL32("MyDLL", "GetCode", data, res1, res2)
i got an error "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
the method signature that i want call is like this way :
string GetCode([IN] byte[] Data, [OUT] string res1, [OUT] string res2)
This post in french suggest that you prefix the strings with & because it need to be pass by reference, it should probably looks like :
CallDLL32("MyDLL", "GetCode", &data, &res1, &res2)
Though I don't know how it works with an array of bytes.
You can call Directely: API function
API("USER32", "SendMessageA", hWnd, wMsg, lParam1, lParam2)
documentation: https://doc.windev.com/en-US/?3014005
I'm rewording this question since I understand a bit more now. Originally, what I had was too vague. I've discovered that I'm being routed by something called "Code Access Security." This is old-hat to everyone reading this, I'm sure, but not to me.
The application is very large so in a nutshell I have two assemblies. One is a utilities assembly with various "tools" used throughout the program. The other is calling upon these tools in order to function.
In the utilities assembly, there are many functions that are PInvoked but the one giving me grief is: SetupDiGetDeviceInterfaceDetail() (see here). My function prototype looks like this:
[DllImport("SetupApi.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return : MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetDeviceInterfaceDetail(
SafeHandleZeroOrMinusOneIsInvalid deviceInfoSet,
ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
IntPtr deviceInterfaceDetailData,
uint deviceInterfaceDetailDataSize,
IntPtr requiredSize,
IntPtr deviceInfoData);
In the assembly which uses this function, I'm using the two step process outlined in the remarks in order to gain the understanding of how much space I need to store the DevicePath which is in the SP_DEVICE_INTERFACE_DETAIL_DATA structure (see here). For example:
string GetDevicePath(SafeHandleSeroOrMinusOneIsInvalid hList, SP_DEVICE_INTERFACE_DATA infoSet)
{
IntPtr pReqSize = Marshal.AllocHGlobal(4);
Marshal.WriteInt32(pReqSize, 0);
uint reqSize;
// get the size needed
PInvoke.SetupDiGetDeviceInterfaceDetail(hList,
ref infoSet,
IntPtr.Zero,
0,
pReqSize,
IntPtr.Zero);
reqSize = (uint)Marshal.ReadInt32(pReqSize, 0);
IntPtr pDevInfoDetail = Marshal.AllocHGlobal((int)reqSize + 4); // +4 for cbSize
// call again, this time getting the actual data wanted
PInvoke.SetupDiGetDeviceInterfaceDetail(hList,
ref infoSet,
pDevInfoDetail,
reqSize,
IntPtr.Zero,
IntPtr.Zero);
string path;
// work .NET magic to read from unmanaged memory the path string and assign it
// to the above variable. Deallocate both unmanaged memory blocks.
return path;
}
The most frustrating thing is, these assemblies are used by two different programs. One is a GUI using the Visual Studio Isolated Shell. The other is simply a command line program. When the GUI is running, the above code is called and executes as expected. In the command line tool however, they fail (as described in the MSDN reference for this Setup API function) with some data about what happened. At this point, I'm able only to recover a portion of the data that is returned.
This is what comes back from the runtime:
stem.Security.PartialTrustVisibilityLevel, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
I know this has something to do with Code Access Security but I'm not at all sure how to fix. Using some suggestions that I've found thus far I've tried this attribute to the assembly (I placed it before the namespace block of code):
[assembly: AllowPartiallyTrustedCallers]
But this caused other compilation problems.
Please, anything would be most helpful and greatly appreciated.
Andy
Unfortunately, the problem isn't yet fixed. However, the problem appears to have nothing to do with Code Access Security as I first thought. I was being thrown a red herring. I stepped my way through the code using the memory window in Visual Studio and noticed that these strings were in memory before calling the Setup API function to fill them. Occasionally, I would get a different block of memory with different contents too, I just usually ended up with the contents I pasted.
The problem actually appears to have something to do with the 64 vs. 32 bit environments (at least, that's my theory at this point).
However, this question isn't the actual problem so I'm "answering" it to close it.
I'm trying to run an executable directly from a byte[] representation of this executable as a resource in C#.
So basically i want to run a byte[] of an PE directly without touching the harddisk.
The code I'm using for this used to work but it doesn't anymore.
The code creates a process with a frozen main thread, changes the whole process data and finally resumes it so it runs the byte[] of the PE. But it seems like the process dies if the thread is resumed, i don't really know whats wrong.
So here is the code in a pastebin because its too long for here i guess...
http://pastebin.com/18hfFvHm
EDIT:
I want to run non-managed code !
Any PE File ...
Here is some code to execute native code (inside a byte array). Note that it is not exactly what you are asking for (it's not a PE file bytes, but a native procedure bytes ie. in assembly language)
using System;
using System.Runtime.InteropServices;
namespace Native
{
class Program
{
private const UInt32 MEM_COMMIT = 0x1000;
private const UInt32 PAGE_EXECUTE_READWRITE = 0x40;
private const UInt32 MEM_RELEASE = 0x8000;
[DllImport("kernel32")] private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr, UInt32 size, UInt32 flAllocationType, UInt32 flProtect);
[DllImport("kernel32")] private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, UInt32 dwFreeType);
[DllImport("kernel32")]
private static extern IntPtr CreateThread(
UInt32 lpThreadAttributes,
UInt32 dwStackSize,
UInt32 lpStartAddress,
IntPtr param,
UInt32 dwCreationFlags,
ref UInt32 lpThreadId
);
[DllImport("kernel32")] private static extern bool CloseHandle(IntPtr handle);
[DllImport("kernel32")] private static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
static void Main(string[] args)
{
byte[] nativecode = new byte[] { /* here your native bytes */ };
UInt32 funcAddr = VirtualAlloc(0, (UInt32)nativecode.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
Marshal.Copy(nativecode, 0, (IntPtr)(funcAddr), nativecode.Length);
IntPtr hThread = IntPtr.Zero;
UInt32 threadId = 0;
hThread = CreateThread(0, 0, funcAddr, IntPtr.Zero, 0, ref threadId);
WaitForSingleObject(hThread, 0xFFFFFFFF);
CloseHandle(hThread);
VirtualFree((IntPtr)funcAddr, 0, MEM_RELEASE);
}
}
}
This code may help:
Dynamic Process Forking of Portable Executable by Vrillon / Venus:
http://forum.gamedeception.net/threads/16557-Process-Forking-Running-Process-From-Memory
Leaving this here for everyone.
USE RUNPE
Look it up, works great :) I suggest self inject.
i found that sample, hope it will be useful for you.
http://www.cyberhackers.mybbnew.com/showthread.php?tid=178
I haven't tried this, so it's purely specutive, but I believe you want to load in into the AppDomain:
byte[] myAssm = ...
AppDomain.CurrentDomain.Load(myAssm);
AppDomain.CurrentDomain.ExecuteAssemblyByName(nameOfMyAssm);
I'm not sure if this will be much help, but here is where I answer running straight x86/x64 assembly opcodes from a C# program.
I believe your problem is that you are asking for a security hole.
To run any PE, you are asking -- "Let my secure/managed .NET app run an insecure/unmanaged app -- In a way which bypasses normal security".
Let's say I run you application (which I assume is secure). I've not given it permission to write to sensitive folder; it can't overrun buffers; it can't touch my win32 mode code. You then build, byte-by-byte, a malicious application in a byts[], and launch that. Where does Windows step in to ask me if I want to let this happen? And what does that warning say ? "Is that array of bytes from a trusted source?"
In theory, if you are running full trust, there is nothing stopping you from doing CreateProcess on rundll32.exe, unmapping rundll32.exe, and performing the initial EXE load yourself.
The way I'd go about it is inject a thread into the target process that does the work in an unmanaged way. Yes, this means piles of relocatable assembly.
The general idea is to call LdrUnloadModule to get rid of rundll32.exe, call LdrLoadModule to load the EXE, fixup the load chain to indicate it was loaded first, then restart the main thread.
Good luck to you.
Repost of Load an EXE file and run it from memory
Not tested but looks like to be the only way to do this (2nd answer)
I have a window to use for editing. The editor should load a dll (which I have full control of) in response to the user's selection to know how to display the information visually.
(They're dll's, as a user will not necessarily want or need every single display model, and also allow new ones to be added without messing around with the main project)
They will all simply be stored in a subdirectory (for now anyway)
I'm pretty sure I can enumerate the available dlls but I need to do 2 more things that I'm not sure on
1) Some way to get metadata from\on the dll, so I can build the lists of possible display selections...
2) Load the selected dll, and unload it as necessary
Any suggestions would be greatly appreciated.
If you are using raw dll's and not .NET assemblies then here are some handy P/Invokes for you:
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private static extern void SetDllDirectory(string lpPathName);
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
privatestatic extern int GetModuleFileName(IntPtr module, [Out] StringBuilder fileName, int size);
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private static bool FreeLibrary(IntPtr module);
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
Note that SetDllDirectory may need some protection as it is not available on all versions of windows (Windows 2000, in particular doesn't have it).
And in use:
SetDllDirectory(candidateFolder);
IntPtr dllHandle = LoadLibrary(dllName);
if (dllHandle != IntPtr.Zero)
{
_dllHandle = dllHandle;
_location = candidateFolder;
_fullPath = Path.Combine(candidateFolder, dllName);
IntPtr p = GetProcAddress(_dllHandle, procName);
if (p == IntPtr.Zero)
throw new ArgumentException("procName");
SomeDelegateType d = (SomeDelegateType)Marshal.GetDelegateForFunctionPointer(p, typeof(SomeDelegateType));
d(/* args */);
}
otherwise, you will be using Assembly methods. Looking at assembly level attributes or object level attributes is a good way to get extra information, although if what you want is a plug-in system, you should use a plug-in system, like the Managed Add-In Framework at CodePlex. See also this SO question and answer.
Take a look at the Castle Windsor framework. It is designed to handle all of your requirements including DLL unloading. It's also free and open source.
I don't know if changing how your program works is an option, but, you could use dependency injection for this, as long as they adhere to a certain interface.
The user selects, you dynamically set class to be loaded, and then just get an instance of the class.
I am not dealing with the unloading, I am just thinking about how you could possibly get classes, and since plinth already gave links to the functions for actually handling the dll, I think I will just end here.
For a native module, the simplest way to get "metadata" would be to define some C-exported (non-name-mangled) functions that return the information you want. At their simplest, these would return pointers to static data within the modules, e.g.:
extern "C" const char* GetModuleDescription();
...
const char* GetModuleDescription() { return "Dummy Module"; }
You would then load each ".dll" file in the directory using LoadLibrary, load and call your known exports from it using GetProcAddress. If you can't load a file or find the exports, then it's not a valid plugin module, so skip it.
Once you're done with a module, you can call FreeLibrary. Windows will then unload the module from your address space.
OK, I;ve figured out I need to use a second AppDomain, load the dll into that, and then I can unload the AppDomain as required.
string SignalSystemDLLPath = AppDomain.CurrentDomain.BaseDirectory + MyApp.Properties.Resources.SystemModuleFolder;
AppDomainSetup info = new AppDomainSetup();
info.ApplicationBase = DLLPath;
DLLDomain = AppDomain.CreateDomain("EditorDomain", null, info);
DLLPath is set to the subdir that holds the dll's.
I then foreach on all the dll's to get the AssemblyName, then later
I use
DLLDomain.Load(SelectedAssemblyName)
to load the DLL. I keep getting FileNotFound exceptions though.
After much googling I've decided its to much work at the moment, and I can refactor it later If I really need to do it...
Thank you for your replies though!
Found out how to do this very easy using MEF, simply use a DirectoryCatalog pointed at your plugin dir, and as long as you have matching [Export]s and [Import]s it works great.