📄 tcpip_patcher.c
字号:
/*
* This file is part of KCeasy (http://www.kceasy.com)
* Copyright (C) 2002-2005 Markus Kern <mkern@kceasy.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
/*****************************************************************************/
#define DRIVER_CODE
#include "tcpip_patcher.h"
#include <wdmsec.h> /* IoCreateDeviceSecure */
#include <ntstrsafe.h> /* RtlStringCbPrintfExA */
/*****************************************************************************/
/* Debugging/logging stuff */
typedef struct
{
LPSTR Buffer;
size_t Remaining;
} LOG_DATA;
#define LOG_0(fmt) \
RtlStringCbPrintfExA (pLogData->Buffer, pLogData->Remaining, \
&pLogData->Buffer, &pLogData->Remaining, \
0, fmt);
#define LOG_1(fmt,a1) \
RtlStringCbPrintfExA (pLogData->Buffer, pLogData->Remaining, \
&pLogData->Buffer, &pLogData->Remaining, \
0, fmt, a1);
#define LOG_2(fmt,a1,a2) \
RtlStringCbPrintfExA (pLogData->Buffer, pLogData->Remaining, \
&pLogData->Buffer, &pLogData->Remaining, \
0, fmt, a1, a2);
#if DBG
# define PATCHER_DBG(_x_) DbgPrint("TCPIP_PATCHER: "); DbgPrint _x_;
# define PATCHER_LOG_0(fmt) PATCHER_DBG((fmt)); LOG_0(fmt);
# define PATCHER_LOG_1(fmt,a1) PATCHER_DBG((fmt,a1)); LOG_1(fmt,a1);
# define PATCHER_LOG_2(fmt,a1,a2) PATCHER_DBG((fmt,a1,a2)); LOG_2(fmt,a1,a2);
#else
# define PATCHER_DBG(_x_)
# define PATCHER_LOG_0(fmt) LOG_0(fmt);
# define PATCHER_LOG_1(fmt,a1) LOG_1(fmt,a1);
# define PATCHER_LOG_2(fmt,a1,a2) LOG_2(fmt,a1,a2);
#endif
/*****************************************************************************/
/* PE file structs from around the web */
typedef UCHAR BYTE;
typedef USHORT WORD;
typedef ULONG DWORD;
typedef ULONG BOOL;
typedef struct _IMAGE_DOS_HEADER
{
WORD e_magic;
WORD e_cblp;
WORD e_cp;
WORD e_crlc;
WORD e_cparhdr;
WORD e_minalloc;
WORD e_maxalloc;
WORD e_ss;
WORD e_sp;
WORD e_csum;
WORD e_ip;
WORD e_cs;
WORD e_lfarlc;
WORD e_ovno;
WORD e_res[4];
WORD e_oemid;
WORD e_oeminfo;
WORD e_res2[10];
LONG e_lfanew;
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
typedef struct _IMAGE_FILE_HEADER
{
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
typedef struct _IMAGE_DATA_DIRECTORY
{
DWORD VirtualAddress;
DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
typedef struct _IMAGE_OPTIONAL_HEADER
{
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
DWORD BaseOfData;
DWORD ImageBase;
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
typedef struct _IMAGE_NT_HEADERS
{
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
#define IMAGE_SIZEOF_SHORT_NAME 8
typedef struct _IMAGE_SECTION_HEADER
{
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
union
{
DWORD PhysicalAddress;
DWORD VirtualSize;
} Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
/*****************************************************************************/
/* The kernel oracle */
typedef enum _SYSTEM_INFORMATION_CLASS
{
SystemModuleInformation = 11
} SYSTEM_INFORMATION_CLASS;
typedef struct _SYSTEM_MODULE_INFORMATION
{
ULONG Reserved[2];
PVOID Base;
ULONG Size;
ULONG Flags;
USHORT Index;
USHORT Unknown;
USHORT LoadCount;
USHORT ModuleNameOffset;
CHAR ImageName[256];
} SYSTEM_MODULE_INFORMATION,*PSYSTEM_MODULE_INFORMATION;
NTSYSAPI NTSTATUS NTAPI
ZwQuerySystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL);
/*****************************************************************************/
/* Various internal helpers */
/* Returns base address of module (e.g. "tcpip.sys") */
PVOID FindModuleBase (const char *module, LOG_DATA *pLogData);
/* Returns RVA and size of code and data sections */
BOOL FindPESections (PVOID ImageBase,
ULONG *CodeRVA, ULONG *CodeSize,
ULONG *DataRVA, ULONG *DataSize,
LOG_DATA *pLogData);
/* Returns address of DWORD containing half-open connections limit and
* optionally address of current half-open connections */
ULONG* FindLimitPosition (PVOID CodeStart, ULONG CodeSize,
ULONG **CurrentHalfOpenAddress, LOG_DATA *pLogData);
/* Find needle with mask */
PVOID FindMemWithMask (const PVOID Start, ULONG Size, const PCHAR NeedleData,
const PCHAR NeedleMask, ULONG NeedleSize);
/*****************************************************************************/
/* Driver control functions */
NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING registryPath);
VOID PatcherUnload (IN PDRIVER_OBJECT DriverObject);
NTSTATUS PatcherDispatch (IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS PatcherDeviceControl (IN PDEVICE_OBJECT pDeviceObject,
IN ULONG IoControlCode,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
OUT PIO_STATUS_BLOCK IoStatus);
/*****************************************************************************/
/* Driver loading/unloading/control */
NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
NTSTATUS status;
UNICODE_STRING unicodeDeviceName;
UNICODE_STRING unicodeDosDeviceName;
PDEVICE_OBJECT deviceObject;
UNREFERENCED_PARAMETER (RegistryPath);
PATCHER_DBG(("DriverEntry Enter\n"));
RtlInitUnicodeString (&unicodeDeviceName, PATCHER_DEVICE_PATH);
RtlInitUnicodeString (&unicodeDosDeviceName, PATCHER_DOS_DEVICE_PATH);
/* create device which only SYSTEM and Administrators can access */
status = IoCreateDeviceSecure (DriverObject,
0,
&unicodeDeviceName,
FILE_DEVICE_PATCHER,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&SDDL_DEVOBJ_SYS_ALL_ADM_ALL,
&PATCHER_DEVICE_GUID,
&deviceObject);
if (!NT_SUCCESS(status))
{
PATCHER_DBG(("IoCreateDeviceSecure() failed\n"));
return status;
}
status = IoCreateSymbolicLink (&unicodeDosDeviceName, &unicodeDeviceName);
if (!NT_SUCCESS(status))
{
PATCHER_DBG(("IoCreateSymbolicLink() failed\n"));
IoDeleteDevice(deviceObject);
return status;
}
DriverObject->MajorFunction[IRP_MJ_CREATE] =
DriverObject->MajorFunction[IRP_MJ_CLEANUP] =
DriverObject->MajorFunction[IRP_MJ_CLOSE] =
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PatcherDispatch;
DriverObject->DriverUnload = PatcherUnload;
PATCHER_DBG(("DriverEntry Exit\n"));
return STATUS_SUCCESS;
}
VOID PatcherUnload (IN PDRIVER_OBJECT DriverObject)
{
PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject;
UNICODE_STRING uniWin32NameString;
PATCHER_DBG(("PatcherUnload Enter\n"));
RtlInitUnicodeString (&uniWin32NameString,PATCHER_DOS_DEVICE_PATH);
IoDeleteSymbolicLink (&uniWin32NameString);
IoDeleteDevice (deviceObject);
PATCHER_DBG(("PatcherUnload Exit\n"));
return;
}
NTSTATUS PatcherDispatch (IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION irpStack;
NTSTATUS status = STATUS_SUCCESS;
PVOID InputBuffer;
PVOID OutputBuffer;
ULONG InputBufferLength;
ULONG OutputBufferLength;
ULONG IoControlCode;
irpStack = IoGetCurrentIrpStackLocation (Irp);
InputBuffer = Irp->AssociatedIrp.SystemBuffer;
InputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
OutputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
IoControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
switch (irpStack->MajorFunction) {
case IRP_MJ_CREATE:
PATCHER_DBG(("IRP_MJ_CREATE\n"));
Irp->IoStatus.Information = 0;
break;
case IRP_MJ_CLEANUP:
PATCHER_DBG(("IRP_MJ_CLEANUP\n"));
Irp->IoStatus.Information = 0;
break;
case IRP_MJ_CLOSE:
PATCHER_DBG(("IRP_MJ_CLOSE\n"));
Irp->IoStatus.Information = 0;
break;
case IRP_MJ_DEVICE_CONTROL:
PATCHER_DBG(("IRP_MJ_DEVICE_CONTROL\n"));
__try
{
status = PatcherDeviceControl (DeviceObject, IoControlCode,
InputBuffer, InputBufferLength,
OutputBuffer, OutputBufferLength,
&Irp->IoStatus);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
PATCHER_DBG (("Caught exception in PatcherDeviceControl\n"));
status = STATUS_DRIVER_INTERNAL_ERROR;
Irp->IoStatus.Information = 0;
}
break;
default:
PATCHER_DBG(("Invalid PatcherDispatch parameter\n"));
status = STATUS_INVALID_PARAMETER;
break;
}
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS PatcherDeviceControl (IN PDEVICE_OBJECT pDeviceObject,
IN ULONG IoControlCode,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
OUT PIO_STATUS_BLOCK IoStatus)
{
PATCHER_LIMIT_DATA *LimitData;
LOG_DATA LogData, *pLogData = &LogData;
ULONG RequestedLimit;
IoStatus->Status = STATUS_SUCCESS;
IoStatus->Information = 0;
switch (IoControlCode)
{
case IOCTL_PATCHER_GET_LIMIT:
/* supplied buffer must be big enough to contain our response */
if ((OutputBufferLength < sizeof (PATCHER_LIMIT_DATA)) ||
(OutputBuffer == NULL))
{
PATCHER_DBG(("Wrong output buffer size for IOCTL_PATCHER_GET_LIMIT\n"));
IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
break;
}
/* Prepare our result data */
LimitData = (PATCHER_LIMIT_DATA*) OutputBuffer;
LimitData->HalfOpenLimit = 0;
LimitData->CurrentHalfOpen = 0;
LimitData->ErrorCode = PATCHER_ERROR_FAILURE;
LogData.Buffer = LimitData->LogString;
LogData.Remaining = OutputBufferLength - sizeof(PATCHER_LIMIT_DATA);
if (LogData.Remaining > 0)
LogData.Buffer[0] = 0;
__try
{
PVOID TcpIpBase, DataStart, DataEnd;
ULONG CodeSecRVA, CodeSecSize;
ULONG DataSecRVA, DataSecSize;
ULONG *LimitAddress, *CurrentHalfOpenAddress;
TcpIpBase = FindModuleBase ("tcpip.sys", &LogData);
if (TcpIpBase != NULL)
{
if (FindPESections (TcpIpBase, &CodeSecRVA, &CodeSecSize,
&DataSecRVA, &DataSecSize, &LogData))
{
LimitAddress = FindLimitPosition (((PCHAR)TcpIpBase) + CodeSecRVA,
CodeSecSize,
&CurrentHalfOpenAddress,
&LogData);
if (LimitAddress != NULL && CurrentHalfOpenAddress != NULL)
{
/* addresses must be in data section */
DataStart = ((PCHAR)TcpIpBase) + DataSecRVA;
DataEnd = ((PCHAR)DataStart) + DataSecSize;
if ((PVOID)LimitAddress > DataStart &&
(PVOID)LimitAddress < DataEnd &&
(PVOID)CurrentHalfOpenAddress > DataStart &&
(PVOID)CurrentHalfOpenAddress < DataEnd)
{
/* return requested data */
LimitData->HalfOpenLimit = *LimitAddress;
LimitData->CurrentHalfOpen = *CurrentHalfOpenAddress;
LimitData->ErrorCode = PATCHER_ERROR_SUCCESS;
PATCHER_LOG_0("Successfully retrieved current half open connections and their limit\n");
}
else
{
PATCHER_LOG_0("Address of limit or current half open not in data section\n");
}
}
}
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
LimitData->ErrorCode = PATCHER_ERROR_FAILURE;
PATCHER_LOG_0("Caught exception during IOCTL_PATCHER_GET_LIMIT\n");
}
/* Make the IOManager copy everything */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -