转自虾总
前段时间写的一段无聊代码,可能对大家有点用。用于在驱动里调用一些没有直接导出的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); }