Enforce Data Execution Prevention (DEP) in C# app - c#

I have a C# app thats going to run with admin privileges. I want to force DEP for it. Either set DEP On for the process or kill the app if DEP is disabled.
But I've failed in both.
My code is:
private static void CheckDEP()
{
var dep = SetProcessDEPPolicy(3);
var handle = Process.GetCurrentProcess().Handle;
var res = GetProcessDEPPolicy(handle, out var flags, out var permanent);
}
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool SetProcessDEPPolicy(uint dwFlags);
[DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
static extern bool GetProcessDEPPolicy(IntPtr hProcess, out uint lpFlags, out bool lpPermanent);
Calling the function SetProcessDEPPolicy(3) always fails with error 50 (documentation says that it should return this error only when it's called from 64bit process, but this is not the case).
And I probably have some bug in GetProcessDEPPolicy, because the call fails with error 87 (parameter is incorrect). Maybe the Handle is wrong?

So, the solution is to change the build configuration in Configuration Manager from AnyCPU to x86. Now both methods work as expected.
The errors are the same for AnyCPU as for x64 (where DEP is enforced by default and these methods should return the mentioned errors).

Related

LoadLibrary in C# shows annoying error dialog using GetErrorLast

I have a little project, where I want to bulk load some libraries referenced in the registry to read some resources. I get stuck on loading the library C:\Windows\System32\mmsys.cpl, which seems to have errors. The error itself is not the problem, but I want to prevent showing any native error dialog. I just want to redirect the exception in the native code to a exception of the managed code. I have tested this with .Net Framework 4.8 and .Net Core 3.1 as well as LoadLibrary and LoadLibraryEx in Kernel32 without any success. I have tested other *.cpl libraries and they are loading fine.
Expected:
Loading this library causes an exception thrown in the managed code - no error dialog is shown.
Actual:
Loading this library shows this annoying dialog as well as throwing the exception in the managed code.
[System.Runtime.InteropServices.DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)]
private static extern System.IntPtr LoadLibrary(string lpFileName);
private static void Main(string[] args)
{
var resource = #"C:\Windows\System32\mmsys.cpl";
// var resource = #"C:\Windows\System32\timedate.cpl";
var lib = LoadLibrary(resource);
if (lib == System.IntPtr.Zero)
{
var errorCode = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
throw new System.SystemException($"System failed to load library '{resource}' with error {errorCode}");
}
}
The error dialog:
Update:
This snippet is now working for me:
[System.Runtime.InteropServices.DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)]
private static extern System.IntPtr LoadLibrary(string lpFileName);
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern ErrorModes SetErrorMode(ErrorModes uMode);
[System.Flags]
public enum ErrorModes : uint
{
SYSTEM_DEFAULT = 0x0,
SEM_FAILCRITICALERRORS = 0x0001,
SEM_NOALIGNMENTFAULTEXCEPT = 0x0004,
SEM_NOGPFAULTERRORBOX = 0x0002,
SEM_NOOPENFILEERRORBOX = 0x8000
}
private static void Main(string[] args)
{
SetErrorMode(ErrorModes.SEM_FAILCRITICALERRORS);
var resource = #"C:\Windows\System32\mmsys.cpl";
// var resource = #"C:\Windows\System32\timedate.cpl";
var lib = LoadLibrary(resource);
if (lib == System.IntPtr.Zero)
{
var errorCode = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
throw new System.SystemException($"System failed to load library '{resource}' with error {errorCode}");
}
}
You need to call first SetErrorMode with SEM_NOOPENFILEERRORBOX (0x8000).
See the Remarks section in the documentation for details:
To enable or disable error messages displayed by the loader during DLL loads, use the SetErrorMode function.

Any reliable method that provides info about file redirection?

All the C# methods to access a file, e.g. FileInfo(), FileVersionInfo.GetVersionInfo(), FileStream(), etc can be misleading when run in WOW64 mode, i.e. the app is compiled as x86 but run on x64. You can have totally different files with the same name in \Windows\System32\ and \Windows\SysWOW64\, or have no file in \Windows\System32\, but when your code tries to access it in \Windows\System32\ then the file copy in \Windows\SysWOW64\ will be used with no indication that the redirection took place. Is there any method that would indicate such redirection, for any reason (WOW64 or other)? The brute force is to check for WOW64 execution and check the path for \Windows\System32\
but I would prefer the system handle it for me. Also there could be some other special cases.
You can disable file system redirection with Wow64DisableWow64FsRedirection
For example =>
bool bWow64 = false;
IsWow64Process(Process.GetCurrentProcess().Handle, out bWow64);
if (bWow64)
{
IntPtr OldValue = IntPtr.Zero;
bool bRet = Wow64DisableWow64FsRedirection(out OldValue);
}
With :
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool IsWow64Process(IntPtr hProcess, out bool Wow64Process);
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool Wow64DisableWow64FsRedirection(out IntPtr OldValue);

Windows has triggered a breakpoint due to corruption in heap or dlls loaded

I have a C++ file with some exported functions which I am calling in C#. One of the functions is this:
char segexpc[MAX_SEG_LEN];
extern "C" QUERYSEGMENTATION_API char* fnsegc2Exported()
{
return segexpc2;
}
Somewhere in the program, I am also doing this thing:
if(cr1==1)
{
strcpy(segexpc, seg);
}
In my C# program, I am invoking the above by the followign way:
[DllImport("QuerySegmentation.dll", EntryPoint = "fnsegcExported", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern StringBuilder fnsegcExported();
this.stringbuildervar = fnsegcExported();
Previously, I was not getting any error, but now suddenly I have started getting this error, when I debug in visual studio.
Windows has triggered a breakpoint in SampleAppGUI.exe.
This may be due to a corruption of the heap, which indicates a bug in SampleAppGUI.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while SampleAppGUI.exe has focus.
This error appears only at the end just before it has to display the window. I have not pressed any F12 key key and neither is any breakpoint set here, but I am not sure why the error is occuring and breaking at this point. this.stringbuildervar = fnsegcExported();
When I press on continue, the window appears with the correct output.
What would happen if you changed your external declaration from
[DllImport("QuerySegmentation.dll", EntryPoint = "fnsegcExported", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern StringBuilder fnsegcExported();
to
[DllImport("QuerySegmentation.dll", EntryPoint = "fnsegcExported", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern string fnsegcExported();
And then called it in the following way:
this.stringbuildervar = new StringBuilder(fnsegcExported());
string seems the more appropriate type. Or better yet use the Marshal class to marshal your unmanaged char* return into a managed string.
[DllImport("QuerySegmentation.dll", EntryPoint = "fnsegcExported", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern IntPtr fnsegcExported();
string managedStr = Marshal.PtrToStringAnsi(fnsegcExported);
this.stringbuildervar = new StringBuilder(managedStr);
The reason why you see the error on this line is that it is the last stack frame for which you have debug information.
Fortunately, in your case, there is very little code on the C++ side. Make sure that segexpc contains a zero terminated string.
I suspect that because the default capacity of the string builder is 16, you may not be able to return longer strings in this fashion. Maybe you want to return just strings.
I also wonder whether your C++ string has to be non-Unicode. That will hurt performance upon every conversion.

Disable Suspend in Window CE

I have a system that requires the application to always be running.
I have set all of the registry settings in [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power\Timeouts] to 0 (which I am told should disable the timeout).
The system is still suspending, we are running on Windows CE 6.0 R3 in Full Power Management mode.
Like in AAT's answer, you have to trigger reload event. Working implementation below:
private static void DoAutoResetEvent()
{
string eventString = "PowerManager/ReloadActivityTimeouts";
IntPtr newHandle = CreateEvent(IntPtr.Zero, false, false, eventString);
EventModify(newHandle, (int)EventFlags.EVENT_SET);
CloseHandle(newHandle);
}
private enum EventFlags
{
EVENT_PULSE = 1,
EVENT_RESET = 2,
EVENT_SET = 3
}
[DllImport("coredll.dll", SetLastError = true)]
private static extern IntPtr CreateEvent(IntPtr lpEventAttributes, bool bManualReset, bool bInitialState, string lpName);
[DllImport("coredll")]
static extern bool EventModify(IntPtr hEvent, int func);
[DllImport("coredll.dll", SetLastError = true)]
private static extern bool CloseHandle(IntPtr hObject);
After you make any changes to the Control\Power\Timeouts registry entries you need to kick a special event so that the system knows to reload the timeout settings. It is a named event called PowerManager/ReloadActivityTimeouts so you need a snippet like
HANDLE hEvent = CreateEvent(NULL,
FALSE,
FALSE,
_T("PowerManager/ReloadActivityTimeouts"));
if(hEvent != NULL)
{
SetEvent(hEvent);
CloseHandle(hEvent);
}
(That is verbatim from our Win CE application which sets up and turns off timeouts according to the users' wishes.)
Another method which works equally well, but may be considered a hack is to periodically output a fake keypress. This function can be used:
keybd_event(VKEY_F24, 0, KEYEVENTF_KEYUP, 0);
If you output a non-existant key such as VKEY_F24 and use the keyup code, that will keep the system awake and be ignored by the running applications. Depending on your system's default timeout, this may need to be done once every 30 seconds.

Get the handle and write to the console that launched our process

How could I write to the standard output of some already open console?
I find the console I need with this piece of code:
IntPtr ptr = GetForegroundWindow();
int u;
GetWindowThreadProcessId(ptr, out u);
Process process = Process.GetProcessById(u);
The problem is how to get the standard output handle pointer (stdHandle) of this process.
I would then want something like:
SafeFileHandle safeFileHandle = new SafeFileHandle(stdHandle, true);
FileStream fileStream = new FileStream(safeFileHandle, FileAccess.Write);
Encoding encoding = Encoding.ASCII;
StreamWriter standardOutput = new StreamWriter(fileStream, encoding);
standardOutput.AutoFlush = true;
Console.SetOut(standardOutput);
Code in C++ using windows API is OK - I can use pInvoke.
Effectively what I would like is to write text to an already open console window not spawned by my process (and it is the one that was in foreground when launching my process through command line - but my process is a WinApp so the console does not attach the std).
Can the standard output be redirected after the process has been created?
PS: I read about some COM file that can be used to do this, so this means that there is a programmatic way ...
Thanks!
I finally figured out how to attach transparently to a console if it is the foreground window while launching the windows app.
Don't ask me why STD_ERROR_HANDLE must be passed instead of STD_OUTPUT_HANDLE, but it simply works, probably because the standard error can be shared.
N.B.: the console can accept user input while displaying you app messages inside, but it is a bit confusing to use it while the stderr is outputting from you app.
With this snippet of code if you launch you app from a console window with at least one parameter it will attach Console.Write to it, and if you launch the app with the parameter /debug then it will attach even the Debug.Write to the console.
Call Cleanup() before exiting you app to free the console and send an Enter keypress to release the last line so the console is usable as before starting the app.
PS. You cannto use output redirection with this method ie.: yourapp.exe > file.txt because
you will get an empty file. And dont even try myapp.exe > file.txt 2>&1 because you will crash the app (redirecting error to output means we are trying to attach to a nonshared buffer).
Here is the code:
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
[DllImport("kernel32.dll",
EntryPoint = "GetStdHandle",
SetLastError = true,
CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32", SetLastError = true)]
static extern bool AttachConsole(uint dwProcessId);
[DllImport("kernel32.dll",
EntryPoint = "AllocConsole",
SetLastError = true,
CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern int AllocConsole();
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern bool FreeConsole();
private const int STD_OUTPUT_HANDLE = -11;
private const int STD_ERROR_HANDLE = -12;
private static bool _consoleAttached = false;
private static IntPtr consoleWindow;
[STAThread]
static void Main()
{
args = new List<string>(Environment.GetCommandLineArgs());
int prId;
consoleWindow = GetForegroundWindow();
GetWindowThreadProcessId(consoleWindow, out prId);
Process process = Process.GetProcessById(prId);
if (args.Count > 1 && process.ProcessName == "cmd")
{
if (AttachConsole((uint)prId)) {
_consoleAttached = true;
IntPtr stdHandle = GetStdHandle(STD_ERROR_HANDLE); // must be error dunno why
SafeFileHandle safeFileHandle = new SafeFileHandle(stdHandle, true);
FileStream fileStream = new FileStream(safeFileHandle, FileAccess.Write);
Encoding encoding = Encoding.ASCII;
StreamWriter standardOutput = new StreamWriter(fileStream, encoding);
standardOutput.AutoFlush = true;
Console.SetOut(standardOutput);
if (args.Contains("/debug")) Debug.Listeners.Add(new TextWriterTraceListener(Console.Out));
Console.WriteLine(Application.ProductName + " was launched from a console window and will redirect output to it.");
}
}
// ... do whatever, use console.writeline or debug.writeline
// if you started the app with /debug from a console
Cleanup();
}
private static void Cleanup() {
try
{
if (_consoleAttached)
{
SetForegroundWindow(consoleWindow);
SendKeys.SendWait("{ENTER}");
FreeConsole();
}
}
}
If the intention is to write to the parent console, if any, you can use the AttachConsole function with the ATTACH_PARENT_PROCESS argument. (see msdn attachconsole)
ATTACH_PARENT_PROCESS (DWORD)-1 : Use the console of the parent of the current process
And if you do need to check the parent process, you might use the CreateToolhelp32Snapshot and get the parent process thru the th32ParentProcessID member of the PROCESSENTRY32 structure.
If you just want to write to the console that's used by some other app, then you can use the following - you'll need to use P/Invoke to do the first step:
AttachConsole(pid) to attach to that console - if your process is already associated with a console, you'll have to FreeConsole first, since a process can be associated with only one console at a time.
Now that you're attached, get the console output handle using CreateFile("CONOUT$", GENERIC_WRITE, FILE_SHARE_WRITE, ... ) - might be able to do this part in managed code.
Now that you've got the HANDLE, wrap it up in managed code - this part you already know.
Having said that, even though you can do this, it's not necessarily a good idea to do so. There's nothing to stop the original process from writing to the console while you are doing likewise, and the output from both getting mixed-up, depending on how the processes are doing buffering. If you want to do something like notify the user of something regardless of which window is active, there may be a better way of doing that.
A system process is uniquely identified on the system by its process identifier. Like many Windows resources, a process is also identified by its handle, which might not be unique on the computer. A handle is the generic term for an identifier of a resource. The operating system persists the process handle, which is accessed through the Process.Handle property of the Process component, even when the process has exited. Thus, you can get the process's administrative information, such as the Process.ExitCode (usually either zero for success or a nonzero error code) and the Process.ExitTime. Handles are an extremely valuable resource, so leaking handles is more virulent than leaking memory.
This is not the exact answer to ur questions , but it helps u to understand the basic thing actually.

Categories