P/Invoke problems with basic CRT functions (i.e., putchar, puts) - c#

I've noticed something very strange. I was trying to call the CRT function "putchar", and was unable to get it to work. So I double-checked that I wasn't missing something, and I copied the code directly from the P/Invoke tutorial on MSDN to see if it worked.
http://msdn.microsoft.com/en-us/library/aa288468%28VS.71%29.aspx
You'll notice that they import "puts".
So I tested the exact code copied from MSDN. It didn't work! So now I got frustrated. I've never had this problem before.
Then I just so happened to run WITHOUT debugging (hit ctrl+f5), and it worked! I tested other functions which output to the console too, and none of them work when debugging but all work when not debugging.
I then wrote a simple C dll which exports a function called "PrintChar(char c)". When I call that function from C#, it works even if I'm debugging or not, without any problems.
What is the deal with this?

The Visual Studio hosting process is capable of redirecting console output to the Output window. How exactly it manages to do this is not documented at all, but it gets in the way here. It intercepts the WriteFile() call that generates the output of puts().
Project + Properties, Debug tab, untick "Enable the Visual Studio hosting process". On that same page, enabling unmanaged debugging also fixes the problem.

It's a bad example, using the C-Runtime Library DLL to call puts. Keep reading the tutorial as there is good info there, but try making Win32 API calls instead.
Here is a better introduction to p/invoke: http://msdn.microsoft.com/en-us/magazine/cc164123.aspx
It's old, but the information is still good.
Edited
My explaination was wrong.
I went looking for a correct explaination and I discovered that the C-Runtime puts method and the .NET Framework Console.Write method differ in how they write to the console (Console.Write works where the p/invoke to puts does not). I thought maybe the answer was in there, so I whipped up this demonstration:
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
class Program
{
public static void Main()
{
int written;
string outputString = "Hello, World!\r\n";
byte[] outputBytes = Encoding.Default.GetBytes(outputString);
//
// This is the way the C-Runtime Library method puts does it
IntPtr conOutHandle = CreateFile("CONOUT$", 0x40000000, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
WriteConsole(conOutHandle, outputBytes, outputString.Length, out written, IntPtr.Zero);
//
// This is the way Console.Write does it
IntPtr stdOutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
WriteFile(stdOutputHandle, outputBytes, outputBytes.Length, out written, IntPtr.Zero);
// Pause if running under debugger
if (Debugger.IsAttached)
{
Console.Write("Press any key to continue . . . ");
Console.ReadKey();
}
}
const int STD_OUTPUT_HANDLE = -11;
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll", SetLastError = true)]
static extern int WriteFile(IntPtr handle, [In] byte[] bytes, int numBytesToWrite, out int numBytesWritten, IntPtr mustBeZero);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr CreateFile(string lpFileName, int dwDesiredAccess, FileShare dwShareMode, IntPtr securityAttrs, FileMode dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
static extern bool WriteConsole(IntPtr hConsoleOutput, [In] byte[] lpBuffer, int nNumberOfCharsToWrite, out int lpNumberOfCharsWritten, IntPtr mustBeZero);
}
Both of those successfully output under the debugger, even with the hosting process enabled. So that is a dead end.
I wanted to share it in case it leads someone else to figuring out why it happens -- Hans?

Related

Using an unmanaged DLL with C#

I'm using a Silicon Labs VCP (CP2105) under Windows (7/8/10) and I am trying to obtain some info from it using the Silicon Labs runtime DLL - which is unmanaged.
This is my implementation:
[DllImport("CP210xRuntime.dll")]
private static extern Int32 CP210xRT_GetDeviceProductString(IntPtr handle, IntPtr bfPtr, ref uint len, bool convert);
public static Int32 GetProduct(IntPtr handle)
{
var buff = new char[100];
GCHandle hnd = GCHandle.Alloc(buff);
IntPtr bfPtr = (IntPtr)hnd;
uint bytesRead = 0;
var r = CP210xRT_GetDeviceProductString(handle, bfPtr, ref bytesRead, true);
hnd.Free();
return r;
}
I am getting the device handle for the ports using:
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateFile(
string FileName,
uint DesiredAccess,
uint ShareMode,
IntPtr SecurityAttributes,
uint CreationDisposition,
uint FlagsAndAttributes,
IntPtr hTemplateFile
);
When I run this it works - of sorts, that is to say the return value is 0 which, according to the Silicon Labs docs, indicates all is well, and I have confirmed this by using a handle to another device and I got 3 back, which confirms invalid handle.
The bytesRead ref value is also ammended as expected to 36 which is what the length of the product name should be. But the buff array never fills with any data (just to be sure I have written values to each element as well but they dont change). If I leave the program running the whole thing throws an exception:
Managed Debugging Assistant 'FatalExecutionEngineError' has detected a problem in********
Additional information: The runtime has encountered a fatal error. The address of the error was at 0x70338780, on thread 0x1f5c. The error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.
This is also the program does, if I comment out the line where I call the function from the dll - the program does not fail.
I'm not massively familar with invoke unmanged code using C# so if someone could help me out with where I am going wrong / point me in the right direction I would be most grateful!
This is from the Silicon Labs Docs:
CP210x_STATUS CP210xRT_GetDeviceProductString(HANDLE cyHandle, 
LPVOID lpProduct, LPBYTE lpbLength, BOOL bConvertToASCII = TRUE)

Writing a lite-weight libVLC wrapper. Need help (Newish to P/Invoke)

I'm writing a super-simple ultra-lite weight .Net wrapper for the LibVLC media library since the only things I need access to are the ability to play, pause and stop media files. I've posted a couple of questions on this and gotten some answers but unfortunately I'm just left with more questions.
We'll start from the top and work down.
The documentation first states I have to initialize VLC with a call to the function with this specification:
libvlc_instance_t* libvlc_new (int argc, const char *const *argv)
for which I have the defined the following method:
[DllImport("libvlc", EntryPoint = "libvlc_new",
CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr NewCore(int argc, IntPtr argv);
And I'm calling the function like this:
private IntPtr Instance;
this.Instance = DGLibVLC.NewCore(0, IntPtr.Zero);
I have tried it several different ways. Initially I did not know about the CallingConvention which was leading to an unbalanced stack which brought me here in the first place. That issue was resolved and the method has gone through several iterations, none of which have proved successful, by which I mean IntPtr is always 0 after the method call. I've tried it like it is above, with the second argument being String[] argc, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr)] string[],
I've tried having it return to a Long (which actually resulted in the Long having a value in it), but nothing so far has worked correctly.
Does anyone know the correct way to call this function from the LibVLC DLL Library?
EDIT: On a suggestion I tried calling the error message function of the library:
Specification:
const char* libvlc_errmsg (void)
Implementation:
[DllImport("libvlc", EntryPoint = "libvlc_errmsg",
CallingConvention = CallingConvention.Cdcel)]
public static extern string GetLastError();
Call:
Console.WriteLine(DGLibVLC.GetLastError());
Result:
Null
The documentation states it will return Null if there is no error. This must indicate that the initial function call NewCore was working correctly but something is still going wrong somehow.
To be cover all bases I checked that the DLLs match the documentation, they do. 2.0.6.0. The documentation I am referencing is here.
EDIT: I can confirm there is no error. When using an initialized to zero long variable to store the result of NewCore I can see it returning something. What I am doing wrong here is where I am trying to store the pointer being returned by the unmanaged function that returns the pointer to the object. How do I store the pointer to the opaque structure reference being passed back?
It doesn't have anything to do with the way you call the function. You cannot get anywhere when you get IntPtr.Zero back from libvlc_new(). It means "there was an error". You'll need to focus on error reporting first, call libvlc_errmsg() to try to get a description for the problem.
So after much looking around and asking questions I've come full circle.
I looked deeply into LibVLC.Net and found how they were importing the DLL functions and adapted what they did to my own wrapper and it worked.
To summarize:
There are some Win32 API functions declared in the code at the start:
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetDllDirectory(string lpPathName);
[DllImport("kernel32", SetLastError = true)]
private static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool FreeLibrary(IntPtr hModule);
that handle providing a handle to a dll and setting a directory search path.
I don't know exactly what it all means but when you initialize the LibVLC.Net library (the primary object) it loads pretty much EVERY function like so:
m_libvlc_media_player_new = (libvlc_media_player_new_signature)LoadDelegate<libvlc_media_player_new_signature>("libvlc_media_player_new");
That delegate is defined here like so:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate IntPtr libvlc_media_player_new_signature(IntPtr p_instance);
//==========================================================================
private readonly libvlc_media_player_new_signature m_libvlc_media_player_new;
//==========================================================================
public IntPtr libvlc_media_player_new(IntPtr p_instance)
{
VerifyAccess();
return m_libvlc_media_player_new(p_instance);
}
And it has a public function that calls the delegate once defined.
I simply stripped down the function that defines the library instance and imported only the functionality I needed.
Thanks very much to everyone who was so patient in helping me along. I likely wouldn't have been able to come to a solution without your help.
EDIT: Okay so it wasn't that. It was the location of the LibVLC Plugin Directory. So it was something stupid -.-;

MoveFileWithProgress throws "The system cannot move the file to a different disk drive" – why?

I have:
[SuppressUnmanagedCodeSecurity]
[DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool MoveFileWithProgress(
string lpExistingFileName, string lpNewFileName,
CopyProgressRoutine lpProgressRoutine,
int dwFlags);
public enum MoveFileOptions
{
MOVEFILE_COPY_ALLOWED = 0x2
}
And calling it with:
if (!MoveFileWithProgress(source.FullName, destination.FullName, cpr, (int)options)) {
throw new IOException(new Win32Exception().Message);
}
Where: options is MoveFileOptions.MOVEFILE_COPY_ALLOWED
It works fine when moving in the hard drive. But when I try moving to a Flash-drive, I get: The system cannot move the file to a different disk drive.
Why?
Your DllImport is incorrect. Your function has only 4 parameters, but the real function has 5. Presumably what is happening is that MOVEFILE_COPY_ALLOWED is being passed to lpData and is ignored. The dwFlags parameter is just whatever happens to be sitting on the stack.
Fixing your p/invoke will probably solve the problem. Also, dwFlags should be unsigned.
[DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool MoveFileWithProgress(
string lpExistingFileName,
string lpNewFileName,
CopyProgressRoutine lpProgressRoutine,
IntPtr lpData,
uint dwFlags
);
With this correct you need to decide what to pass to lpData. Since you appear not to be using it at the moment, it doesn't really matter and IntPtr.Zero seems the obvious choice.
From this Microsoft | Technet page, it says:
The file cannot be moved to a different disk drive at the same time you rename it using the Rename command.
Try renaming the file before moving it.
Are you perhaps moving a directory?
According to the documentation for MoveFileWithProgress at MSDN (emphasis added):
When moving a file, lpNewFileName can be on a different file system or volume. If lpNewFileName is on another drive, you must set the MOVEFILE_COPY_ALLOWED flag in dwFlags.
When moving a directory, lpExistingFileName and lpNewFileName must be on the same drive.

LoadLibrary call from MVC application running in IIS

I'm having trouble executing this line of code in my MVC application:
IntPtr hModule = LoadLibrary(BondProbeSettings.AssemblyFilePath);
The problem is that hModule is always 0.
If I run the same code with the same value for BondProbeSettings.AssemblyFilePath but from a console application instead of the MVC app hModule is non-zero.
Are there any security issues I need to consider?
The signature for LoadLibrary is:
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
static extern IntPtr LoadLibrary(string lpFileName);
Change the declaration to:
[DllImport("kernel32.dll", CharSet = CharSet.Auto), SetLastError = true)]
static extern IntPtr LoadLibrary(string lpFileName);
And your code to:
IntPtr hModule = LoadLibrary(BondProbeSettings.AssemblyFilePath);
if (hModule == IntPtr.Zero) throw new System.ComponentModel.Win32Exception();
Now you'll know why it doesn't work.
Yep you need to run the site assembly in full trust. I haven't configured this myself but I reckon you need:
to GAC the dll (meaning it has to be strongnamed)
to perhaps configure the application pool in IIS (assuming IIS) to allow full trust (?)
I'm on linux so I can't really help you with screenshots right now

Running executable from memory

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)

Categories