Click here to Skip to main content
15,499,046 members

Comments by JudyL_MD (Top 9 by date)

JudyL_MD 6-May-22 9:10am View     CRLF
NOT SUCCESS. You need a working version of those IF statements. Once you get data with those IF statements, then you have success. Your driver must NOT assume that the provided buffers are the correct length. A correctly coded driver checks the length of the buffer and never writes more data than the length indicates. If you don't get anything with the IF statements, that means there is some logic error. Probably a disconnect between how long the driver thinks a ULONG is and how long VB.net thinks a ulong is. And my math may be off on the string length leaving space for the NULL - maybe a +1 instead of a -1. Don't know. That's the kind of thing I check with a debugger to make sure I got it right. You need to put debug statements in the driver to print out the two values it is comparing in the IF statements and see what is wrong. I can't help with this anymore since I can't run your app / driver pair of program. Time to debug and see what the driver is doing with those IF statements. I can't emphasize enough that you MUST validate the length of the buffer before you write data to it in a driver. This is driver 101 stuff. Did you read and understand the link Dave (radnor) gave you? Do so! https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/security-issues-for-i-o-control-codes Don't get rid of those IF statements - FIX them.
JudyL_MD 5-May-22 9:46am View    
LOL ... seriously though, based on the OP's initial "working" code, I think we can safely assume he is using METHOD_BUFFERED. In that case, no MDL mapping is needed and I added the needed length validation in my comments.
JudyL_MD 4-May-22 15:24pm View     CRLF
In general, I'm advocating splitting the retrieval of the PID and the path into two separate calls. I'd advise doing some studying on the different models of memory management used in unmanaged versus managed code. Drivers themselves are a very unique subset of unmanaged code and have their own restrictions and function calls. Now to specifics ... You asked about my comments. I've listed the big three below. 1) I'd create a new code to make it easy in the driver to tell the difference between the ulong and the string. The code is just a number ... You were asking if you should create another IOCTL for retrieving the path. Yes you should. Somewhere in your VB, you have IO_GET_CLIENT_PROCID defined; that value gets itself turned into the switch value SEND_TO_USER in the driver. Make a second such "ioctl code" such as IO_GET_CLIENT_PROCPATH, which you must support with a new case in the driver's switch, such as SEND_TO_USER_PATH. Your VB code then calls DeviceIoControl twice, once with each of the two IO control codes. "Just a number" refers to the code value itself -- it's just a UINT with a very specific format to its bits. 2) Your ulong VB code then needs to allocate an unmanaged buffer, call the driver using the pointer to the buffer as the output parameter, then retrieve the ulong value from the pointer The IOCTL handling function in a driver only takes one type as input and one type as output -- a pointer to a chunk of unmanaged memory. In your old code, VB.net hid those details from you. When you had "<out> ByRef OutBuffer As ULong" describing the OutBuffer parameter, VB created an unmanaged chunk of memory and got a pointer to it, copied the value of your ulong into that memory ... or more likely just locked the memory location of your ulong variable and got a pointer to the locked location ... then passed that pointer through to the DeviceIoControl function in Kernel32.DLL. To use DeviceIoControl properly, you're going to need to do that hidden stuff yourself. (I'm speaking C# pseudo-code here): IntPtr p = Marshall.AllocHGlobal (sizeof (ulong)) DeviceIoControl (hFile, IO_GET_CLIENT_PROCID, Nothing, 0, p, sizeof (ulong), Bytes_IO, Nothing) check return value from DeviceIoControl ulong value = Marshall.ReadInt64 (p); Marshall.FreeHGlobal (p); For the string case, you need to allocate a string of the max possible size and then use that in your call to the driver. I've got "* 2" below since you have unicode in the driver and that takes 2 bytes per character, and "+ 1" to leave room for the NULL terminator. numStringBytes = (MAX_STRING_SIZE + 1) * 2 IntPtr p = Marshall.AllocHGlobal (numStringBytes) DeviceIoControl (hFile, IO_GET_CLIENT_PROCPATH, Nothing, 0, p, numStringBytes, Bytes_IO, Nothing) check return value from DeviceIoControl string = Marshall.PtrToStringUni (p) Marshall.FreeHGlobal (p); 3) (Now the driver code) You'll need to revise your driver code to validate the length of the buffer against the length of a ulong sizeof (*buffer) is not the right way to either validate input length or set return length. Remember, the driver is pure C code. For the IO_GET_CLIENT_PROCID that already exists to retrieve the process ID, your switch case should be something like: case SEND_TO_USER: if (outLength == sizeof (ULONG)) { *((ULONG *) buffer) = ProcID; status = STATUS_SUCCESS; returnLength = sizeof(ULONG); } for your new ioctl code case SEND_TO_USER_PATH: if (outLength <= (myUnicodeString.Length / 2) - 1) // leave space for the NULL terminator { RtlFillMemory (buffer, nOutBufferSize, 0); RtlCopyBytes (buffer, myUnicodeString.buffer, myUnocdeString.Length * 2); status = STATUS_SUCCESS; returnLength = myUnocdeString.Length * 2; }
JudyL_MD 26-Oct-21 10:22am View     CRLF
I always set my C# and C to the environment on which the app will run. If you're actually using a 32-bit machine, yes use the x86 mode. If you're running on a 64-bit machine, set your C# to 64-bit (AnyCPU for the target and _uncheck_ Prefer 32-bit) and use x64 for your C code. If needed, I deliver two versions in my installer. I don't trust 32- to 64-bit thunking so I _always_ match my C code to my machine hardware. You're getting absolutely no indications why the C# processes are aborting? You may need to add your own logging to see where the problems are. Make sure your error checking is robust -- if it can error, even for the most obscure reasons, check those return codes! My only other thought is to check that your C routines are truly re-entrant. Good luck.
JudyL_MD 4-Jun-20 8:44am View    
In addition to what Patrice said ... the debugger in Android Studio is pretty good. Also, look in your LogCat output; find and click the tab along the bottom of Android Studio that says LogCat. There should be entries reporting what exception was thrown that crashed your app. Look for the lines in red (the default color for the ERROR output), and it will show you the call stack. It will even allow you to click on the line and take you right to that spot in the source code that generated the exception.