📄 functions.c
字号:
while(uiIndex < uiLength && bStringIsTerminated == FALSE)
{
if(pString[uiIndex] == '\0')
{
*pdwStringLength = uiIndex + 1; /* Include the total count we read, includes the NULL */
bStringIsTerminated = TRUE;
DbgPrint(" String Is Terminated!\r\n");
}
else
{
uiIndex++;
}
}
return bStringIsTerminated;
}
/**********************************************************************
*
* Example_HandleSampleIoctl_DirectInIo
*
* Sample IOCTL TO Handle Direct In I/O
*
*
**********************************************************************/
NTSTATUS Example_HandleSampleIoctl_DirectInIo(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp, UINT *pdwDataWritten)
{
NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
PCHAR pInputBuffer;
PCHAR pOutputBuffer;
UINT dwDataRead = 0, dwDataWritten = 0;
PCHAR pReturnData = "IOCTL - Direct In I/O From Kernel!";
UINT dwDataSize = sizeof("IOCTL - Direct In I/O From Kernel!");
DbgPrint("Example_HandleSampleIoctl_DirectInIo Called \r\n");
/*
* METHOD_IN_DIRECT
*
* Input Buffer = Irp->AssociatedIrp.SystemBuffer
* Ouput Buffer = Irp->MdlAddress
*
* Input Size = Parameters.DeviceIoControl.InputBufferLength
* Output Size = Parameters.DeviceIoControl.OutputBufferLength
*
* What's the difference between METHOD_IN_DIRECT && METHOD_OUT_DIRECT?
*
* This function is actually *WRONG*!!!! We are using the output buffer
* as an output buffer! The difference is that METHOD_IN_DIRECT creates
* an MDL for the outputbuffer with *READ* access so the user mode application
* can send large amounts of data to the driver for reading.
*
* METHOD_OUT_DIRECT creates an MDL for the outputbuffer with *WRITE* access so the user mode
* application can recieve large amounts of data from the driver!
*
* In both cases, the Input buffer is in the same place, the SystemBuffer. There is a lot
* of consfusion as people do think that the MdlAddress contains the input buffer and this
* is not true in either case.
*/
pOutputBuffer = NULL;
if(Irp->MdlAddress)
{
pOutputBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
}
pInputBuffer = Irp->AssociatedIrp.SystemBuffer;
if(pInputBuffer && pOutputBuffer)
{
/*
* We need to verify that the string is NULL terminated. Bad things can happen
* if we access memory not valid while in the Kernel.
*/
if(Example_IsStringTerminated(pInputBuffer, pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength, &dwDataRead))
{
DbgPrint("UserModeMessage = '%s'", pInputBuffer);
DbgPrint("%i >= %i", pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength, dwDataSize);
if(pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength >= dwDataSize)
{
/*
* We use "RtlCopyMemory" in the kernel instead of memcpy.
* RtlCopyMemory *IS* memcpy, however it's best to use the
* wrapper in case this changes in the future.
*/
RtlCopyMemory(pOutputBuffer, pReturnData, dwDataSize);
*pdwDataWritten = dwDataSize;
NtStatus = STATUS_SUCCESS;
}
else
{
*pdwDataWritten = dwDataSize;
NtStatus = STATUS_BUFFER_TOO_SMALL;
}
}
}
return NtStatus;
}
/**********************************************************************
*
* Example_IsStringTerminated
*
* Sample IOCTL TO Handle Direct Out I/O
*
*
**********************************************************************/
NTSTATUS Example_HandleSampleIoctl_DirectOutIo(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp, UINT *pdwDataWritten)
{
NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
PCHAR pInputBuffer;
PCHAR pOutputBuffer;
UINT dwDataRead = 0, dwDataWritten = 0;
PCHAR pReturnData = "IOCTL - Direct Out I/O From Kernel!";
UINT dwDataSize = sizeof("IOCTL - Direct Out I/O From Kernel!");
DbgPrint("Example_HandleSampleIoctl_DirectOutIo Called \r\n");
/*
* METHOD_OUT_DIRECT
*
* Input Buffer = Irp->AssociatedIrp.SystemBuffer
* Ouput Buffer = Irp->MdlAddress
*
* Input Size = Parameters.DeviceIoControl.InputBufferLength
* Output Size = Parameters.DeviceIoControl.OutputBufferLength
*
* What's the difference between METHOD_IN_DIRECT && METHOD_OUT_DIRECT?
*
* The function which we implemented METHOD_IN_DIRECT is actually *WRONG*!!!! We are using the output buffer
* as an output buffer! The difference is that METHOD_IN_DIRECT creates
* an MDL for the outputbuffer with *READ* access so the user mode application
* can send large amounts of data to the driver for reading.
*
* METHOD_OUT_DIRECT creates an MDL for the outputbuffer with *WRITE* access so the user mode
* application can recieve large amounts of data from the driver!
*
* In both cases, the Input buffer is in the same place, the SystemBuffer. There is a lot
* of consfusion as people do think that the MdlAddress contains the input buffer and this
* is not true in either case.
*/
pInputBuffer = Irp->AssociatedIrp.SystemBuffer;
pOutputBuffer = NULL;
if(Irp->MdlAddress)
{
pOutputBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
}
if(pInputBuffer && pOutputBuffer)
{
/*
* We need to verify that the string is NULL terminated. Bad things can happen
* if we access memory not valid while in the Kernel.
*/
if(Example_IsStringTerminated(pInputBuffer, pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength, &dwDataRead))
{
DbgPrint("UserModeMessage = '%s'", pInputBuffer);
DbgPrint("%i >= %i", pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength, dwDataSize);
if(pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength >= dwDataSize)
{
/*
* We use "RtlCopyMemory" in the kernel instead of memcpy.
* RtlCopyMemory *IS* memcpy, however it's best to use the
* wrapper in case this changes in the future.
*/
RtlCopyMemory(pOutputBuffer, pReturnData, dwDataSize);
*pdwDataWritten = dwDataSize;
NtStatus = STATUS_SUCCESS;
}
else
{
*pdwDataWritten = dwDataSize;
NtStatus = STATUS_BUFFER_TOO_SMALL;
}
}
}
return NtStatus;
}
/**********************************************************************
*
* Example_IsStringTerminated
*
* Sample IOCTL TO Handle Buffered I/O
*
*
**********************************************************************/
NTSTATUS Example_HandleSampleIoctl_BufferedIo(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp, UINT *pdwDataWritten)
{
NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
PCHAR pInputBuffer;
PCHAR pOutputBuffer;
UINT dwDataRead = 0, dwDataWritten = 0;
PCHAR pReturnData = "IOCTL - Buffered I/O From Kernel!";
UINT dwDataSize = sizeof("IOCTL - Buffered I/O From Kernel!");
DbgPrint("Example_HandleSampleIoctl_BufferedIo Called \r\n");
/*
* METHOD_BUFFERED
*
* Input Buffer = Irp->AssociatedIrp.SystemBuffer
* Ouput Buffer = Irp->AssociatedIrp.SystemBuffer
*
* Input Size = Parameters.DeviceIoControl.InputBufferLength
* Output Size = Parameters.DeviceIoControl.OutputBufferLength
*
* Since they both use the same location so the "buffer" allocated by the I/O
* manager is the size of the larger value (Output vs. Input)
*/
pInputBuffer = Irp->AssociatedIrp.SystemBuffer;
pOutputBuffer = Irp->AssociatedIrp.SystemBuffer;
if(pInputBuffer && pOutputBuffer)
{
/*
* We need to verify that the string is NULL terminated. Bad things can happen
* if we access memory not valid while in the Kernel.
*/
if(Example_IsStringTerminated(pInputBuffer, pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength, &dwDataRead))
{
DbgPrint("UserModeMessage = '%s'", pInputBuffer);
DbgPrint("%i >= %i", pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength, dwDataSize);
if(pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength >= dwDataSize)
{
/*
* We use "RtlCopyMemory" in the kernel instead of memcpy.
* RtlCopyMemory *IS* memcpy, however it's best to use the
* wrapper in case this changes in the future.
*/
RtlCopyMemory(pOutputBuffer, pReturnData, dwDataSize);
*pdwDataWritten = dwDataSize;
NtStatus = STATUS_SUCCESS;
}
else
{
*pdwDataWritten = dwDataSize;
NtStatus = STATUS_BUFFER_TOO_SMALL;
}
}
}
return NtStatus;
}
/**********************************************************************
*
* Example_IsStringTerminated
*
* Sample IOCTL TO Handle Neither I/O
*
*
**********************************************************************/
NTSTATUS Example_HandleSampleIoctl_NeitherIo(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp, UINT *pdwDataWritten)
{
NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
PCHAR pInputBuffer;
PCHAR pOutputBuffer;
UINT dwDataRead = 0, dwDataWritten = 0;
PCHAR pReturnData = "IOCTL - Neither I/O From Kernel!";
UINT dwDataSize = sizeof("IOCTL - Neither I/O From Kernel!");
DbgPrint("Example_HandleSampleIoctl_NeitherIo Called \r\n");
/*
* METHOD_NEITHER
*
* Input Buffer = Parameters.DeviceIoControl.Type3InputBuffer
* Ouput Buffer = Irp->UserBuffer
*
* Input Size = Parameters.DeviceIoControl.InputBufferLength
* Output Size = Parameters.DeviceIoControl.OutputBufferLength
*
*/
pInputBuffer = pIoStackIrp->Parameters.DeviceIoControl.Type3InputBuffer;
pOutputBuffer = Irp->UserBuffer;
if(pInputBuffer && pOutputBuffer)
{
/*
* We need this in an exception handler or else we could trap.
*/
__try {
ProbeForRead(pInputBuffer, pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength, TYPE_ALIGNMENT(char));
/*
* We need to verify that the string is NULL terminated. Bad things can happen
* if we access memory not valid while in the Kernel.
*/
if(Example_IsStringTerminated(pInputBuffer, pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength, &dwDataRead))
{
DbgPrint("UserModeMessage = '%s'", pInputBuffer);
ProbeForWrite(pOutputBuffer, pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength, TYPE_ALIGNMENT(char));
DbgPrint("%i >= %i", pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength, dwDataSize);
if(pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength >= dwDataSize)
{
/*
* We use "RtlCopyMemory" in the kernel instead of memcpy.
* RtlCopyMemory *IS* memcpy, however it's best to use the
* wrapper in case this changes in the future.
*/
RtlCopyMemory(pOutputBuffer, pReturnData, dwDataSize);
*pdwDataWritten = dwDataSize;
NtStatus = STATUS_SUCCESS;
}
else
{
*pdwDataWritten = dwDataSize;
NtStatus = STATUS_BUFFER_TOO_SMALL;
}
}
} __except( EXCEPTION_EXECUTE_HANDLER ) {
NtStatus = GetExceptionCode();
}
}
return NtStatus;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -