C# output string to aircrack-ng - c#

I'm doing some tests related to information security, and I came across the following situation, I apologize if I'm posting this in the wrong place, any problems let me know and I'll fix it!
Researching about cracking WIFI passwords, I found the aircrack-ng suite of applications, and, after some time of study, I managed to complete the mission of finding the wifi password of my house xD
without further ado, below I detail my problem:
aircrack-ng manages to receive the password to be tested by parameter, my question is:
How to pass this parameter from a C# console application
I tried several ways but without success.
In my last attempt, out of desperation I used the sendmessage function, available in the user32.dll library of windows.
Obs: I'm using the compiled aircrack binaries for windows, available at the link:
aircrack-ng for windows
class Program
{
public const Int32 WM_COPYDATA = 0x4A;
[DllImport("user32.dll")]
static extern long SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern IntPtr FindWindow(string classname, string windowname);
public static IntPtr IntPtrAlloc<T>(T param)
{
IntPtr retval = Marshal.AllocHGlobal(Marshal.SizeOf(param));
Marshal.StructureToPtr(param, retval, false);
return (retval);
}
public static void IntPtrFree(IntPtr preAllocated)
{
if (IntPtr.Zero == preAllocated) throw (new Exception("Go Home"));
Marshal.FreeHGlobal(preAllocated); preAllocated = IntPtr.Zero;
}
public struct COPYDATASTRUCT
{
public IntPtr dwData;
public int cbData;
[MarshalAs(UnmanagedType.LPStr)]
public string lpData;
}
static void Main()
{
string msg = "123456";
var cds = new COPYDATASTRUCT
{
dwData = new IntPtr(3),
cbData = msg.Length + 1,
lpData = msg
};
IntPtr hWnd = FindWindow("ConsoleWindowClass", #"C:\WINDOWS\system32\cmd.exe aircrack-ng");
IntPtr cdsBuffer = IntPtrAlloc(cds);
SendMessage(hWnd, WM_COPYDATA, IntPtr.Zero, cdsBuffer);
}
}
There is an application that currently does this, it's called crunch, it's basically a word generator. And can send this parameter to aircrack using the following command from the console:
crunch 8 8 0123456789 | aircrack-ng -a 2 my-handshake-capture.cap -b my-router-mac-addres -w -
where the last - is replaced in aircrack, by the parameter coming from crunch.
I searched about it in Crunch project available on github, but it's written on c language, and is more complexity for me. Can anyone help me? Thank you very much in advance!

I followed advice at this link: How to write to the stdin of another app?
and I got the horizon I needed!
Well, in the end, the code to work was basically like this:
public static void WriteWord(string word)
{
using (System.Diagnostics.Process airNgProcess = new System.Diagnostics.Process())
{
airNgProcess.StartInfo.FileName = #"D:\aircrack-ng-1.6-win\bin\aircrack-ng.exe";
airNgProcess.StartInfo.Arguments = "francos.cap -b 38:BC:01:D1:A2:64 -w -";
airNgProcess.StartInfo.UseShellExecute = false;
airNgProcess.StartInfo.RedirectStandardInput = true;
airNgProcess.StartInfo.RedirectStandardOutput = true;
airNgProcess.StartInfo.WorkingDirectory = #"D:\aircrack-ng-1.6-win\bin";
airNgProcess.Start();
StreamWriter airNgWriter = airNgProcess.StandardInput;
StreamReader airNgReader = airNgProcess.StandardOutput;
airNgWriter.WriteLine(word);
airNgWriter.Close();
airNgProcess.WaitForExit();
String airNgOutput = airNgReader.ReadToEnd();
Console.WriteLine($"Testing Key: {word}");
if (airNgOutput.IndexOf("KEY FOUND!") > -1)
{
Console.WriteLine($"Wifi password is: {word}");
}
}
}
In the real world, it has no applicability, because, with the junction of the C# application with aircrack-ng, the number of attempts per second has been greatly reduced, it is around 8 thousand attempts per second. This I my computer with a core i9, and 32Gb of memory.
However, by way of study and learning, for me it was very good

Related

WindowsAccessBridge for Java Automation using C#

I try to automate an java application using WindowsAccessBridge.dll.
I can get the window handle but calling the function isJavaWindow(System.IntPtr hWnd) always return false
Please find my code below:
static void Main()
{
System.Int32 vmID = 0;
System.Int64 _acParent = 0;
string WndName = "GLOBUS EDU";
string ClassName = "SunAwtFrame";
Windows_run();
System.IntPtr hWnd = System.IntPtr.Zero;
hWnd = (System.IntPtr)FindWindow(ClassName, WndName);
bool Found = isJavaWindow(hWnd);
if (!Found) { throw new System.Exception("ERROR: Unable to find window by classname " + ClassName + " and " + WndName + "!"); }
System.Console.WriteLine("Application is finished. Press ENTER to exit...");
System.Console.ReadKey();
}
Interop:
[return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)]
[System.Runtime.InteropServices.DllImport("WindowsAccessBridge-64.dll", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl)]
private extern static bool getAccessibleContextFromHWNDFct(System.IntPtr hwnd, out System.Int32 vmID, out System.Int32 _acParent);
private static bool getAccesibleContextFromHWND(System.IntPtr hWnd, out System.Int32 vmID, out System.Int64 acParent)
{
System.Int32 ac = -1;
bool retVal = false;
getAccessibleContextFromHWNDFct(hWnd, out vmID, out ac);
acParent = ac;
return retVal;
}
[System.Runtime.InteropServices.DllImport("WindowsAccessBridge-64.dll", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl)]
private extern static bool getAccessibleContextInfo(int vmID, System.IntPtr ac, out AccessibleContextInfo textInfo);
[System.Runtime.InteropServices.DllImport("WindowsAccessBridge-64.dll", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl, ThrowOnUnmappableChar = true, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
private extern static void Windows_run();
[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
private static extern System.IntPtr FindWindow(string lpClassName, string lpWindowName);
[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
private static extern System.IntPtr FindWindowByCaptionFct(System.IntPtr ZeroOnly, string lpWindowName);
private static System.IntPtr FindWindowByCaption(string WindowTitle) { return FindWindowByCaptionFct(System.IntPtr.Zero, WindowTitle); }
[System.Runtime.InteropServices.DllImport("WindowsAccessBridge-64.dll", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl, ThrowOnUnmappableChar = true, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
private extern static System.Boolean isJavaWindow(System.IntPtr hwnd);
The function FindWindowis working perfect and I'm getting the window handle also Spy++ shows me. The classname is SunAwtFrameas Spy++ says.
My Java applications runs in 64 bit but I tried all the Libraries (-32, -64) and also switched in the VS Configuration Manager from x86 to x64 and back.
The AccessBridge itself is working well - Java-Monkey-64.exe can spy my running java application.
Does anybody has an idea, why this is not working?
Regards,
Jan
I have been fighting with your problem in few days.
i created a program that enumerate window that is java application(of course write on console application), and catch same problem like yours.
then, i rewrite it on WPF application,enumerate all window, then recognize that: besides the normal window, i see a strange window named: "java access bridge", and the problem is clearly:
the Windows_run function need to have an active windows message pump.
another way, you must putting it on the constructor of a WPF application or something same that.
if (result != FALSE) {
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
shutdownAccessBridge();
}
code in Java Monkey application.
After create a hidden window, it performs a PostMessage with a registered message. The JVM side of the access bridge responds to this message, and posts back another message to the window that was created. As such, they communicate by that way.
and more, you only can call JAB functions after the message pump can process messages.
that is reason why the java monkey need to use call back for it's business.
Pass null for class name as in the below code:
IntPtr hWnd = FindWindow(null, "GLOBUS EDU"); //cast to IntPtr is redundant
bool Found = isJavaWindow(hWnd);
Reference is here on Pinvoke documentation, and it works for me!

Evaluate if drive is in use

I'd like to evaluate wether a drive is in use (if I'm not mistaken this means that some read/write stuff is happening with the drive) using C#. I wouldn't mind for a solution using bash scripts or similiar either, as I could use them in a C# application. I already found a question regarding bash scripts here, but couldn't solve my problem with the answers given.
I considered to use the DriveInfo class already, however it didn't seem to have anything useful for me. I wondered wether I could use the IsReady property from DriveInfo, because I guessed that it wouldn't be ready while it is read/written, but this attempt seems rather botchy to me.
However I still tried it:
private static bool IsDriveInUse ()
{
var drive = DriveInfo.GetDrives ().FirstOrDefault(info => info.Name.StartsWith(DRIVE_LETTER.ToString()));
return drive != null && !drive.IsReady;
}
But it didn't work (it returned false while I played music from my drive).
An optimal solution for me would be a function that tells me wether the drive was in use in a specific span of time (let's stick to the name IsDriveInUse). That means that if the time was for example 60 seconds, IsDriveInUse should return true if 5 seconds before the function call content from the drive was read and false if there was no read/write action in the passed 60 seconds.
EDIT To specify what exactly I mean by in use, I'll try to explain what I'm trying to do. I am writing a tool, which automatically spins down my hard drive, when it's been idle or when I press a keyboard shortcut. I managed to spin it down programmatically (even though either the windows integrated tool nor other tools I found were able to do that, but that's another problem). However, it now spins down the hard drive every minute, regardless of wether it's currently in use or not. That means, if I play music from my hard drive, it's still spinned down, just to spin up directly after it, which doesn't decrease noise development.
I hope this clarified the matter.
EDIT I now tried using the FSCTL_LOCK_VOLUME control code (I couldn't find a value for IOCTL_DISK_PERFORMANCE), but it still returned false for IsDriveInUse() while I was playing music. Furthermore it caused windows to directly spin the drive up again as I spinned it down (probably because the releasing made Windows think that something was using the drive). This is what I tried:
public class DriveManager
{
public const int FSCTL_LOCK_VOLUME = 0x00090018;
public const int FSCTL_UNLOCK_VOLUME = 0x0009001c;
[DllImport ("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CreateFile (
string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes,
uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);
[return: MarshalAs (UnmanagedType.Bool)]
[DllImport ("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool DeviceIoControl (
[In] SafeFileHandle hDevice,
[In] int dwIoControlCode, [In] IntPtr lpInBuffer,
[In] int nInBufferSize, [Out] IntPtr lpOutBuffer,
[In] int nOutBufferSize, out int lpBytesReturned,
[In] IntPtr lpOverlapped);
public static SafeFileHandle CreateFileR (string device)
{
string str = device.EndsWith (#"\") ? device.Substring (0, device.Length - 1) : device;
return new SafeFileHandle (
CreateFile (#"\\.\" + str, WinntConst.GENERIC_READ, WinntConst.FILE_SHARE_READ, IntPtr.Zero,
WinntConst.OPEN_EXISTING, WinntConst.FILE_ATTRIBUTE_NORMAL, IntPtr.Zero), true);
}
internal class WinntConst
{
// Fields
internal static uint FILE_ATTRIBUTE_NORMAL = 0x80;
internal static uint FILE_SHARE_READ = 1;
internal static uint GENERIC_READ = 0x80000000;
internal static uint OPEN_EXISTING = 3;
}
public static bool IsDriveInUse (string deviceName)
{
var handle = CreateFileR (deviceName);
var buffer = Marshal.AllocHGlobal (sizeof (int));
try
{
return
DeviceIoControl (handle,
FSCTL_LOCK_VOLUME,
IntPtr.Zero,
0,
buffer,
sizeof(int),
out var bytesReturned,
IntPtr.Zero
);
}
finally
{
var sessionId = Marshal.ReadInt32 (buffer);
Marshal.FreeHGlobal (buffer);
handle.Close ();
}
}
And the implementation:
private static bool IsDriveInUse () => DriveManager.IsDriveInUse ($#"{DRIVE_LETTER}:\");
Maybe it helps to see the part in which I'm spinning the disc down as well (I used Smartmontools for this):
internal static class Program
{
private const string PROGRAM_PATH = #"External\smartctl.exe";
private const string ARGUMENTS_SHUTDOWN = #"-s standby,now {0}:";
private const char DRIVE_LETTER = 'd';
public static void Main (string [] args)
{
InitializeHotKey ();
Console.WriteLine ("Hotkey registered!");
while (true)
{
Thread.Sleep (60000);
if (!IsDriveInUse ())
ShutDownDrive (true);
}
}
private static bool IsDriveInUse () => DriveManager.IsDriveInUse ($#"{DRIVE_LETTER}:\");
private static void InitializeHotKey ()
{
HotKeyManager.RegisterHotKey (Keys.D, KeyModifiers.Alt | KeyModifiers.Control);
HotKeyManager.HotKeyPressed += HotKeyPressed;
}
private static void HotKeyPressed (object sender, HotKeyEventArgs hotKeyEventArgs) => ShutDownDrive (true);
private static void ShutDownDrive (bool withDialog = false)
{
Process process;
(process = new Process
{
StartInfo = new ProcessStartInfo
{
WindowStyle = ProcessWindowStyle.Hidden,
FileName = PROGRAM_PATH,
Arguments = string.Format (ARGUMENTS_SHUTDOWN, DRIVE_LETTER)
}
}).Start ();
process.WaitForExit ();
process.Close ();
if (withDialog)
Console.WriteLine ("Drive shut down!");
}
}
Perhaps you could use the Windows Performance Counter relevant to your drive ?
"Disk Read/sec" seems quite relevant for what youhave in mind.
In .Net, the counters are available via System.Diagnostics.PerformanceCounter
see there :
https://msdn.microsoft.com/en-us/library/system.diagnostics.performancecounter(v=vs.110).aspx

When did SECURITY_ATTRIBUTES change and why?

I have some code that uses P/Invoke to launch a process and capture the standard output. (The story of why we did this using P/Invoke instead of System.Diagnostics.Process is long and convoluted; suffice it to say it's a requirement.) It's been working in production under heavy load for nearly a year, and the tests that exercise it have always passed.
This morning though I ran the tests, and they failed. I can't be certain when I last ran the tests prior to this morning (5/15/2014), but I believe it was 4/24/2014. The tests passed then, but failed this morning. I was getting the "PInvokeStackImbalance" error message, so I did some research, and eventually realized the signature of one of the structs used by the extern method (CreatePipe in this instance) was incorrect. I changed it, and the tests started passing again.
I'm happy to have found the fix, but I'm concerned about deployment. Why did the signature of the struct change? I haven't upgraded my OS or anything - I was running Windows 7 x64 on 4/24, and I'm still running it now. (The deployment environment is Windows Server 2012.) I've installed (and uninstalled) a few apps since then, but they've been light-weight 3rd-party tools, not Microsoft or system components. I assume a Windows Update hotfix is responsible, but I can't figure out which one.
To be clear, in my own code, all I changed was this:
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public UInt32 nLength;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
}
to this:
[StructLayout(LayoutKind.Sequential)]
internal class SECURITY_ATTRIBUTES
{
public int nLength = 12;
public IntPtr lpSecurityDescriptor = IntPtr.Zero;
public bool bInheritHandle;
}
I need to be sure that the change I made to get the code working on my machine isn't going to break the app when I deploy to production. Does anyone know how to identify what necessitated the change and how to determine whether the production environment does or does not require it?
EDIT:
Here is the code that opens the pipe for the standard output:
private PipeInfo CreatePipe()
{
PipeInfo pipeInfo = new PipeInfo();
SafeFileHandle safeFileHandle = null;
try
{
Native.SECURITY_ATTRIBUTES pipeAttributes = new Native.SECURITY_ATTRIBUTES();
pipeAttributes.bInheritHandle = true;
if (!Native.CreatePipe(out safeFileHandle, out pipeInfo.ChildHandle, pipeAttributes, 0) || safeFileHandle.IsInvalid || pipeInfo.ChildHandle.IsInvalid)
{
throw new Win32Exception();
}
if (!Native.DuplicateHandle(new HandleRef(this, Native.GetCurrentProcess()), safeFileHandle, new HandleRef(this, Native.GetCurrentProcess()), out pipeInfo.ParentHandle, 0, false, 2))
{
throw new Win32Exception();
}
}
finally
{
if (safeFileHandle != null && !safeFileHandle.IsInvalid)
{
safeFileHandle.Close();
}
}
return pipeInfo;
}
I can't exactly take credit for this code, I largely lifted it from the .NET Reference Source
Just to be clear on timeline:
May 2013 - write the CreatePipe code with the first version of SECURITY_ATTRIBUTES
June 2013 - deploy; code has been running successfully ever since
April 2014 - without any changes being made, code starts throwing stack imbalance error
May 2014 - I change to the second version of SECURITY_ATTRIBUTES and the error goes away
We encountered this problem on x64 and this post was the top result in our search. We were using the magic 12 for nLength just like your solution which we got from the C# source for process: https://referencesource.microsoft.com/#System/services/monitoring/system/diagnosticts/Process.cs
[StructLayout(LayoutKind.Sequential)]
internal class SECURITY_ATTRIBUTES {
#if !SILVERLIGHT
// We don't support ACL's on Silverlight nor on CoreSystem builds in our API's.
// But, we need P/Invokes to occasionally take these as parameters. We can pass null.
public int nLength = 12;
public SafeLocalMemHandle lpSecurityDescriptor = new SafeLocalMemHandle(IntPtr.Zero, false);
public bool bInheritHandle = false;
#endif // !SILVERLIGHT
}
It turns out CreatePipe expects a pointer, from the docs:
lpPipeAttributes
A pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. If lpPipeAttributes is NULL, the handle cannot be inherited.
The solution is detailed in this stackoverflow post. It works for both x86 and x64. Our code is below based on that stack overflow post and the process source (with using DWORD = System.UInt32; at the top).
internal static class NativeMethods
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CreatePipe(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe,
IntPtr lpPipeAttributes, int nSize);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern bool DuplicateHandle(IntPtr hSourceProcessHandle, SafeHandle hSourceHandle,
IntPtr hTargetProcess, out SafeFileHandle targetHandle, int dwDesiredAccess,
bool bInheritHandle, int dwOptions);
[StructLayout(LayoutKind.Sequential)]
public struct PIPE_SECURITY_ATTRIBUTES
{
public DWORD nLength;
public IntPtr lpSecurityDescriptor;
[MarshalAs(UnmanagedType.Bool)]
public bool bInheritHandle;
}
public static void CreatePipe(out SafeFileHandle parentHandle, out SafeFileHandle childHandle, bool parentInputs)
{
PIPE_SECURITY_ATTRIBUTES lpPipeAttributes = new PIPE_SECURITY_ATTRIBUTES();
lpPipeAttributes.nLength = (DWORD)Marshal.SizeOf(lpPipeAttributes);
lpPipeAttributes.bInheritHandle = true;
lpPipeAttributes.lpSecurityDescriptor = IntPtr.Zero;
IntPtr attr = Marshal.AllocHGlobal(Marshal.SizeOf(lpPipeAttributes));
Marshal.StructureToPtr(lpPipeAttributes, attr, true);
SafeFileHandle hWritePipe = null;
try
{
if (parentInputs)
CreatePipeWithSecurityAttributes(out childHandle, out hWritePipe, attr, 0);
else
CreatePipeWithSecurityAttributes(out hWritePipe, out childHandle, attr, 0);
if (!DuplicateHandle(GetCurrentProcess(), hWritePipe, GetCurrentProcess(), out parentHandle, 0, false, 2))
throw new Exception();
}
finally
{
if ((hWritePipe != null) && !hWritePipe.IsInvalid)
{
hWritePipe.Close();
}
}
}
public static void CreatePipeWithSecurityAttributes(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe,
IntPtr lpPipeAttributes, int nSize)
{
hReadPipe = null;
if ((!CreatePipe(out hReadPipe, out hWritePipe, lpPipeAttributes, nSize) || hReadPipe.IsInvalid) || hWritePipe.IsInvalid)
throw new Exception();
}
}

Convert String to IntPtr, and Back Again

I'm trying to use the RegisteredWindowMessage API function to send text from one application to another, and I have the following code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace Common
{
public static class RegisteredMsg
{
private const string MyMessage = "9C7EDA65363F4fdaAF32";
private static IntPtr m_targetWindow = new IntPtr(0xFFFF);
private static object m_object = new object();
private static HandleRef m_handleRef;
private static HandleRef m_handleRef;
public static uint RegisteredMessage
{
get { return m_regMsg; }
private set
{
m_regMsg = RegisterWindowMessage(SynchroMessage);
}
}
//-----------------------------------------------------------------
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
static extern bool PostMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
//-----------------------------------------------------------------
[DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
static extern uint RegisterWindowMessage(string lpString);
//-----------------------------------------------------------------
static RegisteredMsg()
{
m_handleRef = new HandleRef(m_object, m_targetWindow);
}
//-----------------------------------------------------------------
public static void PostUpdateMsg(string text)
{
IntPtr lpData = Marshal.StringToHGlobalAuto(text);
IntPtr lpLength = new IntPtr(text.Length);
if (!PostMessage(m_handleRef, RegisteredMessage, lpData, lpLength))
{
throw new Exception("Could not post message.");
}
}
//-----------------------------------------------------------------
public static string GetMessageText(Message msg)
{
string text = "";
int length = msg.LParam.ToInt32();
text = Marshal.PtrToStringAuto(msg.WParam, length);
Marshal.FreeHGlobal(msg.WParam);
return text;
}
}
}
Posting the message works find, but when the receiving application calls GetMessageText, the string contains "\0\0\0\0" (which is NOT what the sending application sent).
I'm calling it like this:
RegisteredMsg.PostUpdateMsg("test");
and receiving it like this:
protected override void WndProc(ref Message msg)
{
base.WndProc(ref msg);
if (Convert.ToUInt32(msg.Msg) == RegisteredMsg.RegisteredMessage)
{
string text = RegisteredMsg.GetMessageText(msg);
}
}
EDIT #0
I also tried it this way, and all of the bytes in the received array are '\0':
//-------------------------------------------------------------------------
public static void PostUpdateMsg(string text)
{
byte[] array = StringToByteArray(text);
IntPtr lpData = Marshal.AllocHGlobal(array.Length);
Marshal.Copy(array, 0, lpData, array.Length);
IntPtr lpLength = new IntPtr(text.Length);
if (!PostMessage(m_handleRef, RegisteredMessage, lpData, lpLength))
{
throw new Exception("Could not post message.");
}
}
//-------------------------------------------------------------------------public static string GetMessageText(Message msg)
{
string text = "";
int length = msg.LParam.ToInt32();
byte[] array = new byte[length];
Marshal.Copy(msg.WParam, array, 0, length);
text = RegisteredMsg.ByteArrayToString(array);
return text;
}
EDIT #1
I also called this method from PostUpdateMessage, just to make sure what I was sending was what I thought I was sending:
private static void TestIntPtr(IntPtr ptr, int length)
{
string text = "";
byte[] array = new byte[length];
Marshal.Copy(ptr, array, 0, length);
text = ByteArrayToString(array); // <<------------
}
When the indicated line is executed, the text variablle is indeed = "test", so I'm doing it right on the sending side. It looks like the memory is getting cleared before it gets to the receiving application.
EDIT #2
I also tried making the IntPtr (pointing to the string I want to send) global to its parent class to make sure it would live long enough to be viable at the other end. No joy there, either.
EDIT #3
I also reverted back to using the StringToHGlobalAuto, and ran the "is it still okay in the sending app" test (see Edit #1 above), and that test proved that the way I was building the IntPtr was fine as well.
This cannot work by design. A pointer is only valid in the process that created it. Every process gets its own chunk of virtual memory. Retrieving the pointed-to memory content requires ReadProcessMemory(). Or you can allocate memory in the target process with VirtualAllocEx() and write to it with WriteProcessMemory(). Windows supports the WM_COPYDATA message to take care of this for you.
This is all rather low-level and painful. There are much better IPC mechanisms available. The ones that work well in .NET are sockets, pipes, WCF.
The PostMessage() manual states;
The system only does marshalling for system messages (those in the
range 0 to (WM_USER-1)). To send other messages (those >= WM_USER) to
another process, you must do custom marshalling.
As far as I understand, you're sending a pointer allocated on the local unmanaged heap and a length to a separate process, where the pointer points to something entirely different. The data is not passed along.
For simplicity (ie to avoid custom marshaling), you may want to use WM_COPYDATA instead to pass data between applications.
I think the problem lies in the message passing mechanism itself.
You're copying some data to a pointer (that's pointing to a memory block in the first process) and send this pointer to another application/process.
When you take the pointer in the other process, the memory location it points to is a block of memory in the other process and it will not contain whatever you've copied there in process 1.
If you want to send anything longer than a pair of ints with windows messages, you should look at WM_COPYDATA - this message is doing exactly what you want.

Programmatically install Certificate Revocation List (CRL)

I need to download and install about 50 CRLs once a week and install them on several Windows servers. Downloading is the easy part, is there a way I could script the CRL import process?
Here is my final source (slightly scrubbed for the public) - but should work. I won't change the accepted answer, but I do hope this helps (as does upvoting the question and answers!).
Note: This will import both a CRL or a regular certificate into the LOCAL MACHINE Trusted Root store. Changing the below CERT_SYSTEM_STORE_LOCAL_MACHINE to CERT_SYSTEM_STORE_CURRENT_USER in the call CertOpenStore will change it to work for the Current User store.
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace ConsoleApplication2
{
class Program
{
public struct CRYPTUI_WIZ_IMPORT_SRC_INFO
{
public Int32 dwSize;
public Int32 dwSubjectChoice;
[MarshalAs(UnmanagedType.LPWStr)]public String pwszFileName;
public Int32 dwFlags;
[MarshalAs(UnmanagedType.LPWStr)]public String pwszPassword;
}
[DllImport("CryptUI.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern Boolean CryptUIWizImport(
Int32 dwFlags,
IntPtr hwndParent,
IntPtr pwszWizardTitle,
ref CRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc,
IntPtr hDestCertStore
);
[DllImport("CRYPT32.DLL", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CertOpenStore(
int storeProvider,
int encodingType,
IntPtr hcryptProv,
int flags,
String pvPara
);
public const Int32 CRYPTUI_WIZ_IMPORT_SUBJECT_FILE = 1;
public const Int32 CRYPT_EXPORTABLE = 0x00000001;
public const Int32 CRYPT_USER_PROTECTED = 0x00000002;
public const Int32 CRYPTUI_WIZ_NO_UI = 0x0001;
private static int CERT_STORE_PROV_SYSTEM = 10;
private static int CERT_SYSTEM_STORE_CURRENT_USER = (1 << 16);
private static int CERT_SYSTEM_STORE_LOCAL_MACHINE = (2 << 16);
static void Main(string[] args)
{
if (args.Length != 1)
{
Console.WriteLine("Usage: certimp.exe list.crl");
Environment.ExitCode = 1;
}
else
{
IntPtr hLocalCertStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
IntPtr.Zero,
CERT_SYSTEM_STORE_LOCAL_MACHINE,
"ROOT"
);
CRYPTUI_WIZ_IMPORT_SRC_INFO importSrc = new CRYPTUI_WIZ_IMPORT_SRC_INFO();
importSrc.dwSize = Marshal.SizeOf(importSrc);
importSrc.dwSubjectChoice = CRYPTUI_WIZ_IMPORT_SUBJECT_FILE;
importSrc.pwszFileName = args[0];
importSrc.pwszPassword = null;
importSrc.dwFlags = CRYPT_EXPORTABLE | CRYPT_USER_PROTECTED;
if (!CryptUIWizImport(
CRYPTUI_WIZ_NO_UI,
IntPtr.Zero,
IntPtr.Zero,
ref importSrc,
hLocalCertStore
))
{
Console.WriteLine("CryptUIWizImport error " + Marshal.GetLastWin32Error());
Environment.ExitCode = -1;
}
}
}
}
}
I don't know a way to do it via script.
Can you write C code? If I understand what you want to do, you will use the CryptUiWizImport function, and the CRYPTUI_WIZ_IMPORT_SRC_INFO structure.
Here's a sample of code that installs a Cert; the corresponding CRL import is similar.
Addendum:
This post points out that Win32 APIs (such as CryptUiWizImport) are not directly accessible from PowerShell, and then describes a possible workaround: from within the PowerShell script, dynamically generate and compile C# code that does the P/Invoke stuff, and then run the resulting assembly. This would allow you to do the CryptUiWizImport strictly from a powershell script, although it would be a pretty exotic one.
Hm. Is there any reason not to use the certutil.exe utility? I can import a Certificate Revocation List into the appropriate store by running the following command:
certutil -addstore CA <FileName>.crl
In Powershell there is a Cert: provider which represents the certificate store. Manipulating it is done via the standard cmdlets so you might be able to integrate a revocation list there somewhere. I just don't know enough about how Windows handles certificates to be of any further help here.
We have to use only Win32 Apis to do this. There is no firstclass C# system APIs to do this. Refer https://stackoverflow.com/a/67814697/3671594

Categories