« VC向网页注入脚本VC程序查错之序言 »

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);
}

  • quote 1.dd
  • GetDllFunctionIndex、GetSystemFunctionAddrW等函数呢?
    langouster 于 2010-9-2 23:00:40 回复
    补上了
  • 2010-9-2 16:02:58 回复该留言

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

日历

最新评论及回复

最近发表

Powered By Z-Blog 2.0 bate Build Theme by toboku

Copyright langouster. Some Rights Reserved.   苏ICP备06046736号