⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcpip_patcher.c

📁 Last change: 2008-02-03 This is the source code of KCeasy。
💻 C
📖 第 1 页 / 共 2 页
字号:
		IoStatus->Information = OutputBufferLength;

		break;
	
	case IOCTL_PATCHER_SET_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_SET_LIMIT\n"));
			IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
			break;	
		}

		/* supplied input buffer must contain our parameter struct */
		if ((InputBufferLength < sizeof (PATCHER_LIMIT_DATA)) ||
		    (InputBuffer == NULL))
		{
			PATCHER_DBG(("Wrong input buffer size for IOCTL_PATCHER_SET_LIMIT\n"));
			IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
			break;	
		}

		/* Get new limit requested by caller */
		LimitData = (PATCHER_LIMIT_DATA*) InputBuffer;
		RequestedLimit = LimitData->HalfOpenLimit;

		/* 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;
		
		/* Do some sanity checking on the requested limit */
		if (RequestedLimit < 10 || RequestedLimit > 16384)
		{
			PATCHER_LOG_0("Requested half open limit out of range (10,16384)\n");
			LimitData->ErrorCode = PATCHER_ERROR_FAILURE;
			IoStatus->Information = OutputBufferLength;
			break;
		}

		__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)
						{
							/* set new limit */
							*LimitAddress = RequestedLimit;

							/* return requested data */
							LimitData->HalfOpenLimit = *LimitAddress;
							LimitData->CurrentHalfOpen = *CurrentHalfOpenAddress;
							LimitData->ErrorCode = PATCHER_ERROR_SUCCESS;

							PATCHER_LOG_1("Successfully set half open connections limit to %d\n",
							              LimitData->HalfOpenLimit);
						}
						else
						{
							PATCHER_LOG_0("Address of limit or current half open not in data section\n");
						}
					}
				}
			}
		}
		__except(EXCEPTION_EXECUTE_HANDLER)
		{
			PATCHER_LOG_0("Caught exception during IOCTL_PATCHER_SET_LIMIT\n");
			LimitData->ErrorCode = PATCHER_ERROR_FAILURE; 
		}

		/* Make the IOManager copy everything */
		IoStatus->Information = OutputBufferLength;

		break;

	default:
		PATCHER_DBG(("Invalid PatcherDeviceControl parameter\n"));
		IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
		break;
	}

    return IoStatus->Status;
}

/*****************************************************************************/
/* The code patterns we look for to determine the address of the half-open
 * limit variable we need to patch. */

ULONG CodePos1CurrentOff = 11;
ULONG CodePos1LimitOff = 17;
BYTE CodePos1Data[] = "\x3D\x02\x00\xC0\xE9\x8E\x29\xFE\xFF\x56\xA1\x20\xFE\x04\x00\x3B\x05\x1C\xFE\x04\x00\x7D\x51\x8B\x45\xF8\xFF\x45\xF8\x83\xF8\x14\x73\x46";
BYTE CodePos1Mask[] = "\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\x00\x00\x00\x00\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF";
/*                                         ^^^^^^^^^^^^^^^^        ^^^^^^^^^^^^^^^^        ^^^^^^^^^^^^^^^^ */
/*                                         some jump offset        current halfopen         halfopen limit  */

ULONG CodePos2CurrentOff = 12;
ULONG CodePos2LimitOff = 18;
BYTE CodePos2Data[] = "\x8B\xCB\x88\x45\x0B\xFF\x15\x28\xEF\x04\x00\xA1\x20\xFE\x04\x00\x3B\x05\x1C\xFE\x04\x00\x0F\x8D\x07\x10\x02\x00\x33\xF6";
BYTE CodePos2Mask[] = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\x00\x00\x00\x00\xFF\xFF\x00\x00\x00\x00\xFF\xFF\x00\x00\x00\x00\xFF\xFF";
/*                                                 ^^^^^^^^^^^^^^^^    ^^^^^^^^^^^^^^^^        ^^^^^^^^^^^^^^^^        ^^^^^^^^^^^^^^^^ */
/*                                     KefAcquireSpinLockAtDpcLevel    current halfopen         halfopen limit         some jump offset */

ULONG CodePos3CurrentOff = 3;
BYTE CodePos3Data[] = "\x33\xC9\xB8\x20\xFE\x04\x00\x41\xF0\x0F\xC1\x08\xA1\x28\xFE\x04\x00\x33\xC9\x8D\x04\x85\xA0\x3C\x05\x00\x41\xF0\x0F\xC1\x08\xC3";
BYTE CodePos3Mask[] = "\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF";
/*                                 ^^^^^^^^^^^^^^^^                        ^^^^^^^^^^^^^^^^                    ^^^^^^^^^^^^^^^^ */
/*                                 current halfopen                          some offset                          some offset   */

/* 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)
{
	PCHAR Pos1, Pos2, Pos3;

	/* find all three code snippets */
	Pos1 = FindMemWithMask (CodeStart, CodeSize, CodePos1Data, CodePos1Mask,
	                        sizeof (CodePos1Data));
	if(Pos1 == NULL)
	{
		PATCHER_LOG_0("Code snippet 1 not found\n");
		return NULL;
	}
	PATCHER_LOG_1("Code snippet 1 found at %p\n", Pos1);
	PATCHER_LOG_2("Current half-open address: %p, Limit address: %p\n",
	              *((ULONG*)(Pos1 + CodePos1CurrentOff)),
	              *((ULONG*)(Pos1 + CodePos1LimitOff)));


	Pos2 = FindMemWithMask (CodeStart, CodeSize, CodePos2Data, CodePos2Mask,
	                        sizeof (CodePos2Data));
	if(Pos2 == NULL)
	{
		PATCHER_LOG_0("Code snippet 2 not found\n");
		return NULL;
	}
	PATCHER_LOG_1("Code snippet 2 found at %p\n", Pos2);
	PATCHER_LOG_2("Current half-open address: %p, Limit address: %p\n",
	              *((ULONG*)(Pos2 + CodePos2CurrentOff)),
	              *((ULONG*)(Pos2 + CodePos2LimitOff)));


	Pos3 = FindMemWithMask (CodeStart, CodeSize, CodePos3Data, CodePos3Mask,
	                        sizeof (CodePos3Data));
	if(Pos3 == NULL)
	{
		PATCHER_LOG_0("Code snippet 3 not found\n");
		return NULL;
	}
	PATCHER_LOG_1("Code snippet 3 found at %p\n", Pos3);
	PATCHER_LOG_1("Current half-open address: %p\n",
	              *((ULONG*)(Pos3 + CodePos3CurrentOff)));

	/* compare current half-open addresses */
	if (*((ULONG*)(Pos1 + CodePos1CurrentOff)) != *((ULONG*)(Pos2 + CodePos2CurrentOff)))
	{
		PATCHER_LOG_0("Addresses for current half-open don't match between snippet 1 and 2!\n");
		return NULL;
	}

	if (*((ULONG*)(Pos2 + CodePos2CurrentOff)) != *((ULONG*)(Pos3 + CodePos3CurrentOff)))
	{
		PATCHER_LOG_0("Addresses for current half-open don't match between snippet 2 and 3!\n");
		return NULL;
	}
	PATCHER_LOG_1("Current half-open connections: %u\n",
	              **((ULONG**)(Pos1 + CodePos1CurrentOff)));

	/* compare limit addresses */
	if (*((ULONG*)(Pos1 + CodePos1LimitOff)) != *((ULONG*)(Pos2 + CodePos2LimitOff)))
	{
		PATCHER_LOG_0("Addresses for half-open limit don't match between snippet 1 and 2!\n");
		return NULL;
	}
	PATCHER_LOG_1("Current half-open limit: %u\n",
	              **((ULONG**)(Pos1 + CodePos1LimitOff)));

	/* return addresses */
	if (CurrentHalfOpenAddress != NULL)
		*CurrentHalfOpenAddress = (ULONG*) *((ULONG*)(Pos1 + CodePos1CurrentOff));

	return (ULONG*) *((ULONG*)(Pos1 + CodePos1LimitOff));
}
/*****************************************************************************/

/* Returns base address of module (e.g. "tcpip.sys") */
PVOID FindModuleBase (const char *module, LOG_DATA *pLogData)
{ 
	SYSTEM_MODULE_INFORMATION *mods;
	NTSTATUS status;
	PCHAR buf = NULL;
	ULONG buf_size = 48*1024;
	ULONG len, i;

	if (module == NULL)
		return NULL;

	PATCHER_LOG_1("Looking for module '%s'\n", module);

	do 
	{
		if((buf = (PCHAR)ExAllocatePool(NonPagedPool,buf_size)) == NULL)
			return NULL;

		status = ZwQuerySystemInformation(SystemModuleInformation,buf,
		                                  buf_size,NULL);

		if(status == STATUS_INFO_LENGTH_MISMATCH)
        {		
			ExFreePool (buf);
            buf_size *= 2;

			if (buf_size > 512*1024)
			{
				PATCHER_LOG_0("Module buffer size exceeds 512 KB, aborting search.\n");
				return NULL;
			}
        }
        else if (!NT_SUCCESS(status))
        {
			ExFreePool (buf);
			PATCHER_LOG_1("ZwQuerySystemInformation failed with %X\n",
			              status);
			return NULL;
        }

	} while(status == STATUS_INFO_LENGTH_MISMATCH);


	len = *((ULONG *)buf);
	mods = (SYSTEM_MODULE_INFORMATION *)(buf + sizeof (ULONG));

	PATCHER_LOG_1("Retrieved %d modules\n", len);

	for(i = 0; i < len; i++)
	{
		if (_stricmp(mods[i].ImageName + mods[i].ModuleNameOffset, module) == 0)
		{ 
			PVOID Base = mods[i].Base;
				
			PATCHER_LOG_2("Found module '%s' at %p\n", module, Base);

			ExFreePool (buf);
			return Base; 
		}
	}

	PATCHER_LOG_1("Module '%s' not found in memory\n", module);

	ExFreePool (buf);
	return NULL;
}

/* Returns RVA and size of code and data sections */
BOOL FindPESections (PVOID ImageBase,
                     ULONG *CodeRVA, ULONG *CodeSize,
                     ULONG *DataRVA, ULONG *DataSize,
                     LOG_DATA *pLogData)
{
	PCHAR Base = (PCHAR)ImageBase;
	PIMAGE_DOS_HEADER DOSHdr;
	PIMAGE_NT_HEADERS32 NTHdr;
	PIMAGE_FILE_HEADER FileHdr;
    PIMAGE_OPTIONAL_HEADER32 OptHdr;
	PIMAGE_SECTION_HEADER SecHdr, CodeSecHdr = NULL, DataSecHdr = NULL;
	int i;

	if (Base == NULL)
		return FALSE;

	DOSHdr = (PIMAGE_DOS_HEADER)Base;

	if (DOSHdr->e_magic != 0x5A4D)
	{
		PATCHER_LOG_0("DOS header not found\n");
		return FALSE;
	}

	NTHdr = (PIMAGE_NT_HEADERS32) (Base + DOSHdr->e_lfanew);

	if (NTHdr->Signature != 0x00004550)
	{
		PATCHER_LOG_0("PE signature not found\n");
		return FALSE;
	}

	FileHdr = &NTHdr->FileHeader;

	if (FileHdr->Machine != 0x014C)
	{
		PATCHER_LOG_0("Not a i386 PE file\n");
		return FALSE;
	}

	if (FileHdr->SizeOfOptionalHeader != 0xE0)
	{
		PATCHER_LOG_0("Size of optional header is not 0xE0\n");
		return FALSE;
	}
	
	OptHdr = &NTHdr->OptionalHeader;

	if (OptHdr->Magic != 0x010B) /* 0x010B is 32bit executable image */
	{
		PATCHER_LOG_0("Wrong optional header magic\n");
		return FALSE;
	}

	if (OptHdr->NumberOfRvaAndSizes != 0x010) 
	{
		PATCHER_LOG_0("NumberOfRvaAndSizes not 16\n");
		return FALSE;
	}

	SecHdr = (PIMAGE_SECTION_HEADER)(((PCHAR)OptHdr) +
	         sizeof(IMAGE_OPTIONAL_HEADER32));

	/* find .text and .data sections */
	for (i = 0; i < FileHdr->NumberOfSections; i++)
	{
#if 0
		char buf[9];
		memcpy(buf, SecHdr[i].Name, 8);
		buf[8] = 0;
		PATCHER_LOG_1("Section: %s\n", buf);
#endif

		if (memcmp(SecHdr[i].Name, ".text\x00\x00\x00", 8) == 0)
			CodeSecHdr = SecHdr + i;

		if (memcmp(SecHdr[i].Name, ".data\x00\x00\x00", 8) == 0)
			DataSecHdr = SecHdr + i;
	}

	if (CodeSecHdr == NULL)
	{
		PATCHER_LOG_0(".text section not found in image\n");
		return FALSE;
	}

	if (DataSecHdr == NULL)
	{
		PATCHER_LOG_0(".data section not found in image\n");
		return FALSE;
	}

	if ((CodeSecHdr->Characteristics & 0x20) == 0) /* IMAGE_SCN_CNT_CODE */
	{
		PATCHER_LOG_0(".text section does not contain code\n");
		return FALSE;
	}

	if ((DataSecHdr->Characteristics & 0x20) != 0) /* IMAGE_SCN_CNT_CODE */
	{
		PATCHER_LOG_0(".data section contains code\n");
		return FALSE;
	}

	PATCHER_LOG_2("Code section found at RVA 0x%08X size 0x%08X\n",
		          CodeSecHdr->VirtualAddress, CodeSecHdr->Misc.VirtualSize);

	if (CodeRVA != NULL)
		*CodeRVA = CodeSecHdr->VirtualAddress;
	if (CodeSize != NULL)
		*CodeSize = CodeSecHdr->Misc.VirtualSize;

	PATCHER_LOG_2("Data section found at RVA 0x%08X size 0x%08X\n",
		          DataSecHdr->VirtualAddress, DataSecHdr->Misc.VirtualSize);

	if (DataRVA != NULL)
		*DataRVA = DataSecHdr->VirtualAddress;
	if (DataSize != NULL)
		*DataSize = DataSecHdr->Misc.VirtualSize;

	return TRUE;
}

/* Find needle with mask. */
PVOID FindMemWithMask (const PVOID Start, ULONG Size, const PCHAR NeedleData,
                       const PCHAR NeedleMask, ULONG NeedleSize)
{
	ULONG FirstData, FirstMask;
	PCHAR Haystack = Start;
	ULONG Left, i;

	if (!Start || !NeedleData || !NeedleMask || Size < NeedleSize ||
	    NeedleSize < sizeof (ULONG))
	{
		return NULL;
	}

	FirstMask = ((ULONG*)NeedleMask)[0];
	FirstData = ((ULONG*)NeedleData)[0] & FirstMask;
	Left = Size - NeedleSize;

	while (Left > 0)
	{
		/* quickly find potential position (hopefully first long isn't common) */
		while ((*((ULONG*)Haystack) & FirstMask) != FirstData)
		{
			Haystack++;
			Left--;
			if (Left == 0)
				return NULL;
		}

#if 0
		PATCHER_DBG(("Potential match found at %p\n", Haystack));
#endif

		/* compare entire needle */
		for (i = 0; i < NeedleSize; i++)
		{
			if ((Haystack[i] & NeedleMask[i]) != (NeedleData[i] & NeedleMask[i]))
				break;
		}

		if (i == NeedleSize)
			return Haystack;		

		Haystack++;
		Left--;
	}

	return NULL;
}
/*****************************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -