驱动 进程回调中修改导入表插入DLL (只做了一点儿修正不算原创)

来源:互联网 发布:机顶盒禁止安装软件 编辑:程序博客网 时间:2024/06/05 19:56


//虽然现在对很多程序的注入都一点儿问题 ,不过一般的程序还是能注入的 最好建议使用zwCreateThreadEX来注入 好处你懂的= =我修正了判断EXE名字 因为 直接用PsGetImageFileNmae 会获取名字不完整因为某结构中只保存了16 char的 内容 不同系统 还不一样= = 所有就用这个 还有就是 卸载驱动会蓝屏= =因为 系统在回调数组中找到了指向我们这里回调函数的指针 却无法调用 所以蓝屏= =因为回调中已经在 上下文  只需要 keattachstack....
//通用WIN8.1-WIN8-WIN7-WINXP#include <ntifs.h>
#include <windef.h>
// 进程名
NTKERNELAPI
UCHAR *
PsGetProcessImageFileName(
        __in PEPROCESS Process
        );


typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
 WORD   e_magic;                     // Magic number
 WORD   e_cblp;                      // Bytes on last page of file
 WORD   e_cp;                        // Pages in file
 WORD   e_crlc;                      // Relocations
 WORD   e_cparhdr;                   // Size of header in paragraphs
 WORD   e_minalloc;                  // Minimum extra paragraphs needed
 WORD   e_maxalloc;                  // Maximum extra paragraphs needed
 WORD   e_ss;                        // Initial (relative) SS value
 WORD   e_sp;                        // Initial SP value
 WORD   e_csum;                      // Checksum
 WORD   e_ip;                        // Initial IP value
 WORD   e_cs;                        // Initial (relative) CS value
 WORD   e_lfarlc;                    // File address of relocation table
 WORD   e_ovno;                      // Overlay number
 WORD   e_res[4];                    // Reserved words
 WORD   e_oemid;                     // OEM identifier (for e_oeminfo)
 WORD   e_oeminfo;                   // OEM information; e_oemid specific
 WORD   e_res2[10];                  // Reserved words
 LONG   e_lfanew;                    // File address of new exe header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

typedef struct _IMAGE_DATA_DIRECTORY {
 DWORD   VirtualAddress;
 DWORD   Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

typedef struct _IMAGE_OPTIONAL_HEADER {
 //
 // Standard fields.
 //

 WORD    Magic;
 BYTE    MajorLinkerVersion;
 BYTE    MinorLinkerVersion;
 DWORD   SizeOfCode;
 DWORD   SizeOfInitializedData;
 DWORD   SizeOfUninitializedData;
 DWORD   AddressOfEntryPoint;
 DWORD   BaseOfCode;
 DWORD   BaseOfData;

 //
 // NT additional fields.
 //

 DWORD   ImageBase;
 DWORD   SectionAlignment;
 DWORD   FileAlignment;
 WORD    MajorOperatingSystemVersion;
 WORD    MinorOperatingSystemVersion;
 WORD    MajorImageVersion;
 WORD    MinorImageVersion;
 WORD    MajorSubsystemVersion;
 WORD    MinorSubsystemVersion;
 DWORD   Win32VersionValue;
 DWORD   SizeOfImage;
 DWORD   SizeOfHeaders;
 DWORD   CheckSum;
 WORD    Subsystem;
 WORD    DllCharacteristics;
 DWORD   SizeOfStackReserve;
 DWORD   SizeOfStackCommit;
 DWORD   SizeOfHeapReserve;
 DWORD   SizeOfHeapCommit;
 DWORD   LoaderFlags;
 DWORD   NumberOfRvaAndSizes;
 IMAGE_DATA_DIRECTORY DataDirectory[16];
} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;


typedef struct _IMAGE_FILE_HEADER {
 WORD    Machine;
 WORD    NumberOfSections;
 DWORD   TimeDateStamp;
 DWORD   PointerToSymbolTable;
 DWORD   NumberOfSymbols;
 WORD    SizeOfOptionalHeader;
 WORD    Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

typedef struct _IMAGE_NT_HEADERS {
 DWORD Signature;

 IMAGE_FILE_HEADER FileHeader;
 IMAGE_OPTIONAL_HEADER OptionalHeader; // 0x18
} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;

// 输入表
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
 union {
  DWORD   Characteristics;            // 0 for terminating null import descriptor
  DWORD   OriginalFirstThunk;         // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
 };
 DWORD   TimeDateStamp;                  // 0 if not bound,
 // -1 if bound, and real date\time stamp
 //     in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
 // O.W. date/time stamp of DLL bound to (Old BIND)

 DWORD   ForwarderChain;                 // -1 if no forwarders
 DWORD   Name;
 DWORD   FirstThunk;                     // RVA to IAT (if bound this IAT has actual addresses)
} IMAGE_IMPORT_DESCRIPTOR;
typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;

typedef struct _IMAGE_IMPORT_BY_NAME {

 WORD    Hint;

 BYTE    Name[1];

} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;


typedef struct _IMAGE_THUNK_DATA {

 union {

  PDWORD                 Function;

  PIMAGE_IMPORT_BY_NAME  AddressOfData;

 } u1;

} IMAGE_THUNK_DATA, *PIMAGE_THUNK_DATA;


PIMAGE_IMPORT_DESCRIPTOR g_psaveDes = NULL;
PVOID g_eprocess = NULL;
ULONG g_ulPid = 0;
 

ULONG ulBaseImage;
ULONG oldCr0;

PIMAGE_DOS_HEADER pDos;
PIMAGE_NT_HEADERS pHeader;
PIMAGE_IMPORT_DESCRIPTOR  pImportDesc;

PVOID lpBuffer = NULL;
PVOID lpDllName = NULL;
PVOID lpExportApi = NULL;
PVOID lpTemp = NULL;
PVOID lpTemp2=NULL;

VOID Start (
   IN PUNICODE_STRING  FullImageName,
   IN HANDLE  ProcessId, // where image is mapped
   IN PIMAGE_INFO  ImageInfo
   )
{

 NTSTATUS ntStatus;
 PIMAGE_IMPORT_DESCRIPTOR pImportNew;

 HANDLE hProcessHandle;
 int nImportDllCount = 0;

 int size;


 // PID改变时,可以说明已经注入DLL了。
 if(g_ulPid != (ULONG)ProcessId && g_ulPid != 0 && g_psaveDes != NULL)
 {
  KAPC_STATE apcState;
  BOOLEAN bAttached = FALSE;

  //_asm int 3;

  if(g_psaveDes!= NULL)
  {
   if(PsGetCurrentProcess() != g_eprocess) {
    KeStackAttachProcess((PRKPROCESS)g_eprocess, &apcState);
    bAttached = TRUE;
   }

   //
   __asm {
    cli;
    mov eax, cr0;
    mov oldCr0, eax;
    and eax, not 10000h;
    mov cr0, eax
   }

   // 改导出表
   pHeader->OptionalHeader.DataDirectory[1].Size -= sizeof(IMAGE_IMPORT_DESCRIPTOR);
   pHeader->OptionalHeader.DataDirectory[1].VirtualAddress = (ULONG)g_psaveDes - ulBaseImage;

   __asm {
    mov eax, oldCr0;
    mov cr0, eax;
    sti;
   }
   g_psaveDes = NULL;

   if(bAttached)
    KeUnstackDetachProcess(&apcState);


  }
 
  return ;
 }
 // 注入进程没退出。
 if(g_eprocess != NULL)
  return;
 KdPrint((PsGetProcessImageFileName(PsGetCurrentProcess())));
  if(wcsstr(FullImageName->Buffer,L"calc.exe")!=NULL)
 {
  //_asm int 3;
  g_eprocess = PsGetCurrentProcess();

  g_ulPid = (ULONG )ProcessId;
 
   ulBaseImage = (ULONG)ImageInfo->ImageBase;// 进程基地址

  pDos =(PIMAGE_DOS_HEADER) ulBaseImage;
  pHeader = (PIMAGE_NT_HEADERS)(ulBaseImage+(ULONG)pDos->e_lfanew);
  pImportDesc  = (PIMAGE_IMPORT_DESCRIPTOR)((ULONG)pHeader->OptionalHeader.DataDirectory[1].VirtualAddress + ulBaseImage);

 

  // 导入DLL个数  
  nImportDllCount = pHeader->OptionalHeader.DataDirectory[1].Size / sizeof(IMAGE_IMPORT_DESCRIPTOR);

  // 把原始值保存。
  g_psaveDes = pImportDesc;


  ntStatus = ObOpenObjectByPointer(g_eprocess, OBJ_KERNEL_HANDLE, NULL, 0x008, //PROCESS_VM_OPERATION
   NULL, KernelMode, &hProcessHandle);

  if(!NT_SUCCESS(ntStatus)) 
   return ;
  //             加上一个自己的结构。
  size = sizeof(IMAGE_IMPORT_DESCRIPTOR) * (nImportDllCount + 1);

  //  分配导入表
  ntStatus = ZwAllocateVirtualMemory(hProcessHandle, &lpBuffer, 0, &size,
   MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  if(!NT_SUCCESS(ntStatus)) {
   ZwClose(hProcessHandle);
   return ;
  }
  RtlZeroMemory(lpBuffer,sizeof(IMAGE_IMPORT_DESCRIPTOR) * (nImportDllCount + 1));

  size = 20;
  // 分配当前进程空间。
  ntStatus = ZwAllocateVirtualMemory(hProcessHandle, &lpDllName, 0, &size,
   MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  if(!NT_SUCCESS(ntStatus)) {

   ZwClose(hProcessHandle);
   return ;
  }
  RtlZeroMemory(lpDllName,20);


  /* 分配导出函数的进程地址空间。
   注意这里是分配高位地址的。如分配低位地址,得到PIMAGE_IMPORT_BY_NAME结构的地址会以,如ff等开头的负数地址,
   这样,系统就会默认按序号查找API地址,会弹出找不到序号的框框。

  */
  size = 20;
  ntStatus = ZwAllocateVirtualMemory(hProcessHandle, &lpExportApi, 0, &size,
   MEM_COMMIT|MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE);
  if(!NT_SUCCESS(ntStatus)) {

   ZwClose(hProcessHandle);
   return ;
  }
  RtlZeroMemory(lpExportApi,20);

  // 分配当前进程空间。
  size = 20;
  ntStatus = ZwAllocateVirtualMemory(hProcessHandle, &lpTemp, 0, &size,
   MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  if(!NT_SUCCESS(ntStatus)) {

   ZwClose(hProcessHandle);
   return ;
  }
  RtlZeroMemory(lpTemp,20);

  // 分配当前进程空间。
  size = 20;
  ntStatus = ZwAllocateVirtualMemory(hProcessHandle, &lpTemp2, 0, &size,
   MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  if(!NT_SUCCESS(ntStatus)) {

   ZwClose(hProcessHandle);
   return ;
  }
  RtlZeroMemory(lpTemp2,20);


  pImportNew = lpBuffer;

  // 把原来数据保存好。
  RtlCopyMemory(pImportNew+1, pImportDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR) * nImportDllCount );


  // 构造自己的DLL    IMAGE_IMPORT_DESCRIPTOR结构
  {
   IMAGE_IMPORT_DESCRIPTOR Add_ImportDesc;
   PULONG ulAddress;
   ULONG oldCr0;
   ULONG Func;
   PIMAGE_IMPORT_BY_NAME ptmp;
   IMAGE_THUNK_DATA *pThunkData=(PIMAGE_THUNK_DATA)lpTemp2;


   //_asm int 3;
   //
   // ThunkData结构的地址
   //
   ptmp = (PIMAGE_IMPORT_BY_NAME)lpExportApi;
   ptmp->Hint=0;
   // 至少要一个导出API
   RtlCopyMemory(ptmp->Name,"ExportedFunction",18);

   *(PULONG)lpTemp =(DWORD)ptmp-ulBaseImage;
   pThunkData->u1.AddressOfData =(DWORD)ptmp-ulBaseImage;
   //pThunkData[1].u1.AddressOfData = 0;//导出函数截断
   Add_ImportDesc.Characteristics = (DWORD)pThunkData-ulBaseImage;

   Add_ImportDesc.TimeDateStamp = 0;
   Add_ImportDesc.ForwarderChain = 0;

   //
   // DLL名字的RVA
   //  
   RtlCopyMemory(lpDllName,"q.dll",20);
   Add_ImportDesc.Name = (DWORD)lpDllName-ulBaseImage;
   Add_ImportDesc.FirstThunk = Add_ImportDesc.Characteristics;


   RtlCopyMemory(pImportNew, &Add_ImportDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR));


   __asm {
    cli;
    mov eax, cr0;
    mov oldCr0, eax;
    and eax, not 10000h;
    mov cr0, eax
   }

   // 改导出表
   pHeader->OptionalHeader.DataDirectory[1].Size += sizeof(IMAGE_IMPORT_DESCRIPTOR);
   pHeader->OptionalHeader.DataDirectory[1].VirtualAddress = (ULONG)pImportNew - ulBaseImage;


   __asm {
    mov eax, oldCr0;
    mov cr0, eax;
    sti;
   }

  }
  ZwClose(hProcessHandle);
  hProcessHandle = NULL;
 }
}


VOID ProcessExitRoutine (
         IN HANDLE  ParentId,
         IN HANDLE  ProcessId,
         IN BOOLEAN  Create
         )
{
 PVOID eprocess = NULL;
 NTSTATUS ntStatus;
 
 ntStatus = PsLookupProcessByProcessId(ProcessId, (PEPROCESS*)&eprocess);
 if(!NT_SUCCESS(ntStatus))
  return;

 if(!Create)
 {
 
  if(eprocess == g_eprocess)
  {
   //_asm int 3;

   if(g_psaveDes != NULL )
   {
    __asm {
     cli;
     mov eax, cr0;
     mov oldCr0, eax;
     and eax, not 10000h;
     mov cr0, eax
    }

    // 改导出表
    pHeader->OptionalHeader.DataDirectory[1].Size -= sizeof(IMAGE_IMPORT_DESCRIPTOR);
    pHeader->OptionalHeader.DataDirectory[1].VirtualAddress = (ULONG)g_psaveDes - ulBaseImage;

    __asm {
     mov eax, oldCr0;
     mov cr0, eax;
     sti;
    }
    g_psaveDes = NULL;

   }
   // 标志注入进程已经关闭了。
   g_eprocess = NULL;
  }

 }

 ObDereferenceObject(eprocess);
}
 
void DriverUnload(PDRIVER_OBJECT obj){

 PsRemoveLoadImageNotifyRoutine(Start);
 PsSetCreateProcessNotifyRoutine(ProcessExitRoutine, TRUE);
}

NTSTATUS  DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
 
 PsSetLoadImageNotifyRoutine(Start);

  PsSetCreateProcessNotifyRoutine(ProcessExitRoutine, FALSE);
 DriverObject->DriverUnload=DriverUnload;
 return STATUS_SUCCESS;

}

0 0
原创粉丝点击