jscriptpatch.cpp-IE漏洞补丁

本文介绍了一个针对 Internet Explorer 中 createTextRange 漏洞的安全修复程序。通过修改 JScript.dll 文件来实现对漏洞的有效修补,避免潜在的安全风险。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

// jscriptpatch.cpp
//==============================================================
// Patch for the IE createTextRange() vulnerability.
//
// Derek Soeder - eEye Digital Security - 03/24/2006


#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <stdio.h>



// TranslateRVAToRawPtr

PBYTE TranslateRVAToRawPtr(
	PBYTE			pbBase,
	DWORD			dwRVA)
{
	PIMAGE_NT_HEADERS	ppe;
	PIMAGE_SECTION_HEADER	psect;
	DWORD			dw;

	//----------------
	ppe   = (PIMAGE_NT_HEADERS)(pbBase + ((PIMAGE_DOS_HEADER)pbBase)->e_lfanew);
	psect = IMAGE_FIRST_SECTION(ppe);

	for (dw = ppe->FileHeader.NumberOfSections; dw != 0; dw--, psect++)
	{
		if (dwRVA >= psect->VirtualAddress && (dwRVA - psect->VirtualAddress) < psect->SizeOfRawData)
			return pbBase + (dwRVA - psect->VirtualAddress + psect->PointerToRawData);
	} //for(dw)

	return NULL;
} //TranslateRVAToRawPtr()



// CreateJScriptPatchDLL

BOOL CreateJScriptPatchDLL(
	char			*szOriginalDLL,
	char			*szPatchDLL)
{
	HMODULE			hmod;
	DWORD			cbmodsize;
	PIMAGE_NT_HEADERS	ppe;
	PIMAGE_SECTION_HEADER	psect;
	DWORD			dwsectnum;

	PDWORD			pdw;
	PVOID			pvend;
	DWORD			dw;

	DWORD			dwrva, dwrvadest;
	PBYTE			pb;
	LONG			lofs;
	DWORD			dwlen;
	BOOL			bebp;

	HANDLE			hfile;
	PBYTE			pbdest;
	DWORD			cb;
	DWORD			dwerr;

	//---------------- load the original DLL with virtual alignments and relocations applied
	hmod = LoadLibraryEx(szOriginalDLL, NULL, DONT_RESOLVE_DLL_REFERENCES);

	if (hmod == NULL)
		return FALSE;

	dwrva     = 0;
	dwrvadest = 0;

	//---------------- search for an executable section with sufficient unused space
	ppe = (PIMAGE_NT_HEADERS)(((PBYTE)hmod) + ((PIMAGE_DOS_HEADER)hmod)->e_lfanew);

	if (ppe->Signature != IMAGE_NT_SIGNATURE)
	{
		FreeLibrary(hmod);
		SetLastError(ERROR_INVALID_EXE_SIGNATURE);
		return FALSE;
	}

	psect = IMAGE_FIRST_SECTION(ppe);

	for (dwsectnum = 0; dwsectnum != ppe->FileHeader.NumberOfSections; dwsectnum++, psect++)
	{
		if ( (psect->Characteristics & (IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_DISCARDABLE|IMAGE_SCN_CNT_CODE)) !=
		     (IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_CNT_CODE) )
		{
			continue;
		}

		if ( ((psect->Misc.VirtualSize & 0x0FFF) != 0) && 
		     ((psect->Misc.VirtualSize & 0x0FFF) <= 0x1000 - 0x20) && // patch code will be <= 0x20 bytes
		     (psect->SizeOfRawData > psect->Misc.VirtualSize) &&
		     (psect->SizeOfRawData - psect->Misc.VirtualSize >= 0x20) )
		{
			dwrvadest = psect->VirtualAddress + psect->Misc.VirtualSize;
			break;
		}
	} //for(dwsectnum)

	if (dwsectnum == ppe->FileHeader.NumberOfSections)
	{
		FreeLibrary(hmod);
		SetLastError(-1);
		return FALSE;
	}

	//---------------- search image for 0x74-case switch table
	cbmodsize = ppe->OptionalHeader.SizeOfImage;

	pdw   = (PDWORD)hmod;
	pvend = pdw + (cbmodsize / 4) - /*0x74 /*IE 5.0 SP4 only has 0x72 cases*/0x72;

	for ( ; pdw != pvend; pdw = (PDWORD)((PBYTE)pdw + 1))
	{
		if (*pdw >= (DWORD)hmod && (*pdw - (DWORD)hmod) < cbmodsize)
		{
			for (dw = 1; dw != /*0x74*/0x72; dw++)
			{
				if (pdw[dw] < (DWORD)hmod || (pdw[dw] - (DWORD)hmod) > cbmodsize)
					break;
			}

			if ( dw == /*0x74*/0x72 &&		// overlapping cases are a "signature" for the switch table
			     pdw[0x00] == pdw[0x02] &&
			     pdw[0x00] == pdw[0x63] &&
			     pdw[0x00] == pdw[0x64] &&
			     pdw[0x01] == pdw[0x5A] &&
			     pdw[0x17] == pdw[0x1B] &&
			     pdw[0x5E] == pdw[0x5F] )
			{
				break;
			}
		}
	} //for(pdw)

	if (pdw == pvend)
	{
		FreeLibrary(hmod);
		SetLastError(-1);
		return FALSE;
	}

	//---------------- search case 0x23 code for VT_EMPTY assignment instruction
	pb = (PBYTE)(pdw[0x23]);

	lofs  = 0;
	dwlen = 0;
	bebp  = FALSE;

	for (dw = 0x40; dw != 0; dw--, pb++)
	{
		if (pb[0x00] != 0x66)				// 66h: operand size prefix ('vt' is a WORD-size field)
			continue;

		if (pb[0x01] == 0xC7)				// C7h/0: MOV mem, imm
		{
			switch (pb[0x02])
			{
			case 0x44:				// ModRM=44h: 8-bit offset, SIB
				if (pb[0x03] != 0x24 || pb[0x05] != 0 || pb[0x06] != 0) // SIB=24h: ESP
					continue;
				lofs  = (LONG)*(char*)(pb + 0x04);
				dwlen = 0x07;
				bebp  = FALSE;
				break;

			case 0x45:				// ModRM=45h: 8-bit offset, EBP
				if (pb[0x04] != 0 || pb[0x05] != 0)
					continue;
				lofs  = (LONG)*(char*)(pb + 0x03);
				dwlen = 0x06;
				bebp  = TRUE;
				break;

			case 0x84:				// ModRM=84h: 32-bit offset, SIB
				if (pb[0x03] != 0x24 || pb[0x08] != 0 || pb[0x09] != 0) // SIB=24h: ESP
					continue;
				lofs  = *(LONG*)(pb + 0x04);
				dwlen = 0x0A;
				bebp  = FALSE;
				break;

			case 0x85:				// ModRM=85h: 32-bit offset, EBP
				if (pb[0x07] != 0 || pb[0x08] != 0)
					continue;
				lofs  = *(LONG*)(pb + 0x03);
				dwlen = 0x09;
				bebp  = TRUE;
				break;

			default:
				continue;
			}
		}
		else if (pb[0x01] == 0x83)			// 83h/4: AND mem, simm8
		{
			switch (pb[0x02])
			{
			case 0x64:				// ModRM=64h: 8-bit offset, SIB
				if (pb[0x03] != 0x24 || pb[0x05] != 0) //SIB=24h: ESP
					continue;
				lofs  = (LONG)*(char*)(pb + 0x04);
				dwlen = 0x06;
				bebp  = FALSE;
				break;

			case 0x65:				// ModRM=65h: 8-bit offset, EBP
				if (pb[0x04] != 0)
					continue;
				lofs  = (LONG)*(char*)(pb + 0x03);
				dwlen = 0x05;
				bebp  = TRUE;
				break;

			case 0xA4:				// ModRM=A4h: 32-bit offset, SIB
				if (pb[0x03] != 0x24 || pb[0x08] != 0) // SIB=24h: ESP
					continue;
				lofs  = *(LONG*)(pb + 0x04);
				dwlen = 0x09;
				bebp  = FALSE;
				break;

			case 0xA5:				// ModRM=A5h: 32-bit offset, EBP
				if (pb[0x07] != 0)
					continue;
				lofs  = *(LONG*)(pb + 0x03);
				dwlen = 0x08;
				bebp  = TRUE;
				break;

			default:
				continue;
			}
		}
		else	continue;

		if ((lofs & 3) != 0)				// variable will always be DWORD-aligned on stack
			continue;

		if (bebp)
		{
			if (lofs > -0x04 || lofs < -0x800)	// EBP-relative must be negative
				continue;
		}
		else
		{
			if (lofs < 0 || lofs > 0x800)		// ESP-relative must be positive
				continue;
		}

		dwrva = (UINT_PTR)pb - (UINT_PTR)hmod;
		break;
	} //for(dw)

	FreeLibrary(hmod);

	if (dw == 0)
	{
		SetLastError(-1);
		return FALSE;
	}

	//---------------- read original JScript.dll into memory
	hfile = CreateFile(szOriginalDLL, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);

	if (hfile == INVALID_HANDLE_VALUE)
		return FALSE;

	cbmodsize = GetFileSize(hfile, NULL);

	if (cbmodsize == INVALID_FILE_SIZE)
	{
		dwerr = GetLastError();
		CloseHandle(hfile);
		SetLastError(dwerr);
		return FALSE;
	}

	pb = (PBYTE)LocalAlloc(LMEM_FIXED, cbmodsize);

	if (pb == NULL)
	{
		dwerr = GetLastError();
		CloseHandle(hfile);
		SetLastError(dwerr);
		return FALSE;
	}

	if (!ReadFile(hfile, pb, cbmodsize, &cb, NULL) || cb != cbmodsize)
	{
		dwerr = GetLastError();
		CloseHandle(hfile);
		LocalFree(pb);
		SetLastError(dwerr);
		return FALSE;
	}

	CloseHandle(hfile);

	//---------------- patch in-memory file and write it to patched DLL
	ppe   = (PIMAGE_NT_HEADERS)(pb + ((PIMAGE_DOS_HEADER)pb)->e_lfanew);
	psect = IMAGE_FIRST_SECTION(ppe);
	psect += dwsectnum;

	pbdest = TranslateRVAToRawPtr(pb, dwrvadest);

	psect->Misc.VirtualSize += 0x20;

	pbdest[0x00] = 0x60;					// PUSHAD
	pbdest[0x01] = 0x8D;					// LEA EDI, [{ESP,EBP}+ofs32]
	pbdest[0x02] = 0xBC;
	pbdest[0x03] = (bebp ? 0x25 : 0x24);
	*(LONG*)(pbdest + 0x04) = (bebp ? lofs : lofs + 0x20);	// (0x20 to compensate for PUSHAD effect on stack)
	pbdest[0x08] = 0x33;					// XOR EAX, EAX
	pbdest[0x09] = 0xC0;
	*(DWORD*)(pbdest + 0x0A) = 0xABABABAB;			// STOSD / STOSD / STOSD / STOSD
	pbdest[0x0E] = 0x61;					// POPAD
	pbdest[0x0F] = 0xE9;					// JMP rel32
	*(DWORD*)(pbdest + 0x10) = (dwrva + dwlen) - (dwrvadest + 0x14);

	pbdest = TranslateRVAToRawPtr(pb, dwrva);

	pbdest[0x00] = 0xE9;					// JMP rel32
	*(DWORD*)(pbdest + 0x01) = dwrvadest - (dwrva + 5);

	hfile = CreateFile(szPatchDLL, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

	if (hfile == INVALID_HANDLE_VALUE)
	{
		dwerr = GetLastError();
		LocalFree(pb);
		SetLastError(dwerr);
		return FALSE;
	}

	if (!WriteFile(hfile, pb, cbmodsize, &dw, NULL) || dw != cbmodsize)
	{
		dwerr = GetLastError();
		CloseHandle(hfile);
		LocalFree(pb);
		SetLastError(dwerr);
		return FALSE;
	}

	CloseHandle(hfile);

	LocalFree(pb);

	SetLastError(ERROR_SUCCESS);
	return TRUE;
} //CreateJScriptPatchDLL()



// WinMain

int WINAPI WinMain(
	IN HINSTANCE		hInstance,
	IN HINSTANCE		hPrevInstance,
	IN LPSTR		lpCmdLine,
	IN int			nShowCmd)
{
	char			szsystem32[MAX_PATH+8];
	char			szoriginal[MAX_PATH+40];
	char			szpatch[MAX_PATH+40];
	UINT			u;
	DWORD			dwerr;

	//----------------
	if ( lpCmdLine != NULL && ((strstr(lpCmdLine, "/?") != NULL) || (strstr(lpCmdLine, "-?") != NULL)) )
	{
		MessageBox(NULL, ":::/n"
		                 ":::  Microsoft Internet Explorer createTextRange patch/n"
		                 ":::  eEye Digital Security - www.eeye.com - 03/24/2006/n"
		                 ":::/n",
		           "eEye Digital Security", MB_OK);
		return -1;
	}

	//---------------- get %SystemRoot%/system32 path
	u = GetSystemDirectory(szsystem32, sizeof(szsystem32) - 1);

	if (u == 0 || u >= sizeof(szsystem32) - 1)
	{
		dwerr = GetLastError();
		return (dwerr == 0 ? ERROR_PATH_NOT_FOUND : (int)dwerr);
	}

	if (szsystem32[u-1] != '//')
	{
		szsystem32[u] = '//';
		szsystem32[u+1] = 0;
	}
	else	szsystem32[u] = 0;

	_snprintf(szoriginal, sizeof(szoriginal), "%sjscript.dll", szsystem32);
	szoriginal[sizeof(szoriginal)-1] = 0;

	_snprintf(szpatch,    sizeof(szpatch),    "%sjscript-eeye-patch20.dll", szsystem32);
	szpatch[sizeof(szpatch)-1] = 0;

	//---------------- create patched JScript.dll
	if (!CreateJScriptPatchDLL(szoriginal, szpatch))
	{
		dwerr = GetLastError();
		return (dwerr == 0 ? -1 : (int)dwerr);
	}

	return 0;
} //WinMain()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值