Ring0上調用未導出Zw函數通用函數

轉自蝦總
前段時間寫的一段無聊代碼,可能對大家有點用。用於在驅動裏調用一些沒有直接導出的Zw函數,如ZwProtectVirtualMemory。在此感謝alpha提供思路。

BOOLEAN CallZwFunction(CONST CHAR *FunctionName,PVOID pCallRet,ULONG ArgNum,...)
{
	char *vl;
	BOOLEAN retval = FALSE;
	ULONG FunctionIndex;
	ULONG CallRet;
	ULONG Argv[20],temp;
	LONG i;
	ULONG FunctionAddr;
	BYTE Sign[]="\xb8\x44\x00\x00\x00";
	BYTE *p;

	FunctionIndex = GetDllFunctionIndex(FunctionName);
	if(!FunctionIndex || FunctionIndex==-1)
		goto END;

	FunctionAddr = 0;
	*(ULONG *)(Sign+1)=FunctionIndex;
	p=(BYTE *)GetSystemFunctionAddrW(L"ZwAccessCheckAndAuditAlarm");
	for(i=0;i<0x2000;i++)
	{
		if(memcmp(p+i,Sign,5)==0)
		{
			FunctionAddr=(ULONG)p+i;
			break;
		}
	}
	if(!FunctionAddr)
		goto END;

	va_start(vl, ArgNum);
	memcpy(Argv,vl,sizeof(ULONG)*ArgNum);
	va_end(vl);

	for(i=ArgNum-1;i>=0;i--)
	{
		temp=Argv[i];
		__asm
		{
			push temp;
		}
	}
	__asm
	{
		mov eax,FunctionAddr;
		call eax;
		mov CallRet,eax;
	}
	*(ULONG *)pCallRet = CallRet;
	retval = TRUE;

END:
	return retval;
}

調用示例代碼如下:
CallZwFunction("ZwProtectVirtualMemory",&status,5,(HANDLE)-1,&Addr2,&size,PAGE_EXECUTE_READWRITE,&old);

此函數中使用到兩個函數,這兩個函數相信很多人都有,但我還是貼一下這兩個函數的代碼吧
ULONG GetDllFunctionIndex(char* lpFunctionName)
{
	HANDLE  hSection, hFile, hMod;
	IMAGE_DOS_HEADER* dosheader;
	IMAGE_OPTIONAL_HEADER* opthdr;
	IMAGE_EXPORT_DIRECTORY* pExportTable;
	ULONG* arrayOfFunctionAddresses;
	ULONG* arrayOfFunctionNames;
	USHORT* arrayOfFunctionOrdinals;
	ULONG functionOrdinal;
	ULONG Base, x, functionAddress;
	char* functionName;
	STRING ntFunctionName, ntFunctionNameSearch;
	PVOID BaseAddress = NULL;
	SIZE_T size=0;
	OBJECT_ATTRIBUTES oa;// = {sizeof oa, 0, pDllName, OBJ_CASE_INSENSITIVE};
	IO_STATUS_BLOCK iosb;
	NTSTATUS status;
	ULONG uIndex=-1;
	UNICODE_STRING pDllName;


	RtlInitUnicodeString(&pDllName,L"\\SystemRoot\\system32\\ntdll.dll");
	InitializeObjectAttributes ( &oa, &pDllName, OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE, NULL, NULL);

	status=ZwOpenFile(&hFile, FILE_EXECUTE | SYNCHRONIZE, &oa, &iosb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT);
	if(status!=STATUS_SUCCESS)
	{
		//FILE_SUPERSEDED
		KdPrint(("ZwOpenFile Error:0x%x,0x%x",status,iosb.Information));
		return 0;
	}
	oa.ObjectName = 0;
	status=ZwCreateSection(&hSection, SECTION_ALL_ACCESS, &oa, 0,PAGE_EXECUTE, 0x01000000, hFile);
	if(status!=STATUS_SUCCESS)
	{
		KdPrint(("ZwCreateSection Error"));
		ZwClose(hFile);
		return 0;
	}
	ZwMapViewOfSection(hSection, NtCurrentProcess(), &BaseAddress, 0, 1000, 0, &size, (SECTION_INHERIT)1, MEM_TOP_DOWN, PAGE_READWRITE);
	ZwClose(hFile);

	hMod = BaseAddress;
	dosheader = (IMAGE_DOS_HEADER *)hMod;
	opthdr =(IMAGE_OPTIONAL_HEADER *) ((BYTE*)hMod+dosheader->e_lfanew+24);
	pExportTable =(IMAGE_EXPORT_DIRECTORY*)((BYTE*) hMod + opthdr->DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT]. VirtualAddress);
	// now we can get the exported functions, but note we convert from RVA to address
	arrayOfFunctionAddresses = (ULONG*)( (BYTE*)hMod + pExportTable->AddressOfFunctions);
	arrayOfFunctionNames = (ULONG*)( (BYTE*)hMod + pExportTable->AddressOfNames);
	arrayOfFunctionOrdinals = (USHORT*)( (BYTE*)hMod + pExportTable->AddressOfNameOrdinals);
	Base = pExportTable->Base;

	RtlInitString(&ntFunctionNameSearch, lpFunctionName);
	for(x = 0; x < pExportTable->NumberOfFunctions; x++)
	{
		functionName = (char*)( (BYTE*)hMod + arrayOfFunctionNames[x]);
		RtlInitString(&ntFunctionName, functionName);
		functionOrdinal = arrayOfFunctionOrdinals[x] + Base - 1; // always need to add base, -1 as array counts from 0
		// this is the funny bit.  you would expect the function pointer to simply be arrayOfFunctionAddresses[x]...
		// oh no... thats too simple.  it is actually arrayOfFunctionAddresses[functionOrdinal]!!

		//KdPrint(("0x%x\t0x%x \n",x,functionOrdinal));
		functionAddress = (ULONG)( (BYTE*)hMod + arrayOfFunctionAddresses[functionOrdinal]);
		if (RtlCompareString(&ntFunctionName, &ntFunctionNameSearch, TRUE) == 0)
		{
			//INT3
			uIndex=*(PULONG)((PUCHAR)functionAddress+1);
			break;
			//return functionAddress;
		}
	}

	ZwClose(hSection);
	ZwUnmapViewOfSection(NtCurrentProcess(),BaseAddress);
	return uIndex;
}

PVOID GetSystemFunctionAddrW(CONST WCHAR *FunctionName)
{
	UNICODE_STRING uniFunctionName;

	RtlInitUnicodeString(&uniFunctionName,FunctionName);
	return MmGetSystemRoutineAddress(&uniFunctionName);
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章