wodeao 发表于 2015-2-13 21:41:21

在HS下可读写内存的驱动

#include<ntddk.h>
/*
初学驱动  参读堕落天才ssdt hook 对抗inline hook
哪里有错或者有比这个还简单的方法还请大神指点一下 好让我从中得到启发 thx
                                              By Bleach=darkmax
*/
typedef unsigned char BYTE;




typedef struct _SYSTEM_MODULE_INFORMATION {
    ULONG reserved;
    PVOID Base;
    ULONG Size;
    ULONG Flags;
    USHORT Index;
    USHORT Unknown;
    USHORT LoadCount;
    USHORT ModuleNameOffset;            
    CHAR ImageName;  
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;  // ZwQuerySystemInformation需要的数据结构

NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation(
  ULONG num,
  PVOID SystemInformation,
  ULONG SystemInformationLength,
  PULONG ReturnLength
);



typedef struct _SERVICE_DESCRIPTOR_TABLE
{
  PVOID   ServiceTableBase;
  PULONG  ServiceCounterTableBase;
  ULONG   NumberOfService;
  ULONG   ParamTableBase;
}SERVICE_DESCRIPTOR_TABLE,*PSERVICE_DESCRIPTOR_TABLE; //由于KeServiceDescriptorTable只有一项,这里就简单点了
extern PSERVICE_DESCRIPTOR_TABLE    KeServiceDescriptorTable;//KeServiceDescriptorTable为导出函数

/////////////////////////////////////
VOID Hook();
VOID Unhook();
VOID OnUnload(IN PDRIVER_OBJECT DriverObject);
//////////////////////////////////////
ULONG JmpAddress;//跳转到NtOpenProcess里的地址
ULONG JmpAddress1;
ULONG JmpAddress2;
ULONG OldServiceAddress;//原来NtOpenProcess的服务地址
ULONG OldServiceAddress1;
ULONG OldServiceAddress2;
BYTE dthq={0};
BYTE hqdt={0};
BYTE dthq1={0};
BYTE hqdt1={0};
BYTE dthq2={0};
BYTE hqdt2={0};

PVOID newop=0;
PVOID newop1=0;
PVOID newop2=0;
PVOID newop3=0;
PVOID newop4=0;
PVOID newop5=0;

ULONG getid=0;


PVOID GetFuncAddress()
{
    ULONG size,index;
    PULONG buf;
    ULONG i;
    PSYSTEM_MODULE_INFORMATION module;
    PVOID driverAddress = 0;
    ULONG ntosknlBase;
    ULONG ntosknlEnd;
    ULONG curAddr;
    NTSTATUS status;
    ULONG k;
    ULONG retAddr;
    ULONG code_1 = 0x00a16480, code_2 = 0x50000000, code_3 = 0x1024448b,
          code_4 = 0x10246c89;  //定义特征码,通过Windbg的dd来找

    ZwQuerySystemInformation(11,&size,0,&size);  // 第一个参数其实是个enum,11 - SystemModuleInformation,为了保持简洁,我可耻的没放出定义。
    buf = (PULONG) ExAllocatePool(PagedPool,size);
    if(buf == NULL)
        return NULL;
    status = ZwQuerySystemInformation(11,buf,size,0); // 上一次调用得到大小,此次得到数据。
    if(!NT_SUCCESS(status))
    {
        return NULL;
    }
    module = (PSYSTEM_MODULE_INFORMATION)((PULONG)buf + 1);
    ntosknlEnd = (ULONG)module->Base + (ULONG)module->Size;
    ntosknlBase = (ULONG)module->Base;    //ntosknl的基地址
    curAddr = ntosknlBase;
    ExFreePool(buf);
    for(i = curAddr; i<=ntosknlEnd; i++) //从头开始搜,当然,如果知道未导出函数前一个函数和后一个函数的信息,就可以减小范围,详见pediy的sysnap的方法。
    {

        if( (*((ULONG*)i)) == code_1      &&
            (*((ULONG*)(i+4)) == code_2) &&
            (*((ULONG*)(i+8)) == code_3) &&
            (*((ULONG*)(i+12)) == code_4) )
            {
                retAddr = i;
                //DbgPrint("Target Found! Address: 0x%08x\n",retAddr);
                return retAddr;
            }
    }
}
//////////////////////////////////////

__declspec(naked) NTSTATUS __stdcall MyNtOpenProcess(PHANDLE ProcessHandle,
               ACCESS_MASK DesiredAccess,
               POBJECT_ATTRIBUTES ObjectAttributes,
               PCLIENT_ID ClientId)
{
// DbgPrint("NtOpenProcess() called");
  
__asm
{
   push
   push
   call
   jmp    
}
}
///////////////////////////////////////////////////
__declspec(naked) NTSTATUS __stdcall MyNtReadVirtualMemory(  
  IN HANDLE               ProcessHandle,
  IN PVOID                BaseAddress,
  OUT PVOID               Buffer,
  IN ULONG                NumberOfBytesToRead,
  OUT PULONG              NumberOfBytesReaded OPTIONAL)
{
   __asm{
   push
   push
   call
     jmp    
        }  
}
//===================================================
__declspec(naked) NTSTATUS __stdcall MyNtWriteVirtualMemory(
  IN HANDLE               ProcessHandle,
  IN PVOID                BaseAddress,
  IN PVOID                Buffer,
  IN ULONG                BufferLength,
  OUT PULONG              ReturnLength OPTIONAL)
{
   __asm{
   push
   push
   call
   jmp
        }

}
//////////////////////////////////////////////
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
  DriverObject->DriverUnload = OnUnload;
  DbgPrint("Unhooker load");
  Hook();
  return STATUS_SUCCESS;
}
/////////////////////////////////////////////////////
VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
  DbgPrint("Unhooker unload!");
  Unhook();
}
/////////////////////////////////////////////////////
VOID Hook()
{
  ULONG  Address,Address1,Address2;

  Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x7A * 4;//0x7A为NtOpenProcess服务ID
  Address1 = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0xBA * 4;
  Address2 = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x115 * 4;
  DbgPrint("Address:0x%08X",Address);

  OldServiceAddress = *(ULONG*)Address;//保存原来NtOpenProcess的地址
  OldServiceAddress1 = *(ULONG*)Address1;//保存原来NtOpenProcess的地址
  OldServiceAddress2 = *(ULONG*)Address2;//保存原来NtOpenProcess的地址  

newop=(ULONG)NtOpenProcess+1;
newop1=(ULONG)NtOpenProcess+6;

newop2=OldServiceAddress1+1;
newop3=OldServiceAddress1+3;

newop4=OldServiceAddress2+1;
newop5=OldServiceAddress2+3;

memcpy(dthq,newop,sizeof(dthq));
memcpy(hqdt,newop1,sizeof(hqdt));

memcpy(dthq1,newop2,sizeof(dthq1));
memcpy(hqdt1,newop3,sizeof(hqdt1));

memcpy(dthq2,newop4,sizeof(dthq2));
memcpy(hqdt2,newop5,sizeof(hqdt2));

getid=(ULONG)GetFuncAddress()-4;

JmpAddress = (ULONG)NtOpenProcess + 15; //跳转到NtOpenProcess函数头+15的地方,这样在其前面写的JMP都失效了
  JmpAddress1 = OldServiceAddress1 + 12; //跳转到NtOpenProcess函数头+15的地方,这样在其前面写的JMP都失效了
  JmpAddress2 = OldServiceAddress2 + 12; //跳转到NtOpenProcess函数头+15的地方,这样在其前面写的JMP都失效了
  DbgPrint("JmpAddress:0x%08X",JmpAddress);
    
  __asm{//去掉内存保护
    cli
    mov  eax,cr0
    and  eax,not 10000h
    mov  cr0,eax
  }

  *((ULONG*)Address) = (ULONG)MyNtOpenProcess;//HOOK SSDT
  *((ULONG*)Address1) = (ULONG)MyNtReadVirtualMemory;//HOOK SSDT
  *((ULONG*)Address2) = (ULONG)MyNtWriteVirtualMemory;
  __asm{//恢复内存保护  
    mov  eax,cr0
    or   eax,10000h
    mov  cr0,eax
    sti
  }
}
//////////////////////////////////////////////////////
VOID Unhook()
{
ULONG  Address,Address1,Address2;
  Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x7A * 4;
  Address1 = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0xBA * 4;
Address2 = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x115 * 4;

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

*((ULONG*)Address) = (ULONG)OldServiceAddress;//还原SSDT
*((ULONG*)Address1) = (ULONG)OldServiceAddress1;
*((ULONG*)Address2) = (ULONG)OldServiceAddress2;

  __asm{  
         mov  eax,cr0
    or   eax,10000h
    mov  cr0,eax
    sti
  }

  DbgPrint("Unhook");
}


juanzi 发表于 2015-3-6 01:46:21

锄禾日当午,发帖真辛苦。谁知坛中餐,帖帖皆辛苦!

______唯你懂我訫 发表于 2015-4-19 16:15:10

顶,楼主v5

fzjiaoliu 发表于 2015-4-19 16:15:43

谢谢楼主分享,支持 海论坛

zeng83122 发表于 2015-5-28 21:03:22

必须顶一个啊

zeng83122 发表于 2015-5-28 21:03:40

顶顶顶顶大大的等等等等等等等等等等等等

俊俊 发表于 2015-10-31 15:37:03

{:lol:}{:lol:}{:lol:}{:lol:}{:lol:}

西门 发表于 2017-8-14 20:59:57

学习{:lol:}{:lol:}
页: [1]
查看完整版本: 在HS下可读写内存的驱动