首页
社区
课程
招聘
[原创]自己动手,制作inline hook扫描工具
发表于: 2012-2-27 11:52 31678

[原创]自己动手,制作inline hook扫描工具

2012-2-27 11:52
31678
function CheckKernelInlineHook(parameter:Pointer):DWORD;stdcall;
var
  hDevice         : THandle;
  i               : DWORD;
  pModuleListBuf  : Pointer;
  dwBufSize       : DWORD;
  dw              : DWORD;
  tempStrStr            : string;
begin
  Result:=0;

  // 打开驱动层的设备对象
  hDevice:=OpenDevice(DEVICE_SYMBOLIC_NAMR);
  if hDevice = 0 then Exit;

  i:=0;
  pModuleListBuf:=nil;

  // 获得模块信息列表
  while True do
  begin
    dwBufSize:=(200 + i*5) * SizeOf(TLdrDataTableEntry);
    pModuleListBuf:=AllocMem(dwBufSize);
    if pModuleListBuf = nil then
    begin
      CloseHandle(hDevice);
      Exit;
    end;

    if not DeviceIoControl(hDevice, IOCTL_GET_MODULE_LIST_INFO, nil, 0, pModuleListBuf, dwBufSize, dw, nil) then
    begin
      if GetLastError = ERROR_INSUFFICIENT_BUFFER then
      begin
        Inc(i);
        FreeMem(pModuleListBuf);
        Continue;
      end
      else
      begin
        FreeMem(pModuleListBuf);
        CloseHandle(hDevice);
        Exit;
      end;
    end;

    Break;
  end;
  CloseHandle(hDevice);


  // 得到模块数量
  dw:=dw div SizeOf(TLdrDataTableEntry);

  // 扫描以下指定驱动模块
  FindDestModule(pModuleListBuf, 'ntoskrnl.exe', dw);
  FindDestModule(pModuleListBuf, 'win32k.sys', dw);
  FindDestModule(pModuleListBuf, 'hal.dll', dw);
  FindDestModule(pModuleListBuf, 'kdcom.dll', dw);
  FindDestModule(pModuleListBuf, 'partmgr.sys', dw);
  FindDestModule(pModuleListBuf, 'ndis.sys', dw);
  //FindDestModule(pModuleListBuf, 'tcpip.sys', dw);


  FreeMem(pModuleListBuf);

  // 界面回显
  tempStr:='All done';
  SendMessage(MainForm.Handle, MSG_THREAD_STATUS, Integer(@tempStr[1]), 0);

  Result:=1;
end;
_LDR_DATA_TABLE_ENTRY = packed record
  InLoadOrderLinks          : TListEntry;
  InMemoryOrderLinks        : TListEntry;
  InInitializationOrderLinks: TListEntry;
  DllBase                   : Pointer;
  EntryPoint                : Pointer;
  SizeOfImage               : DWORD;
  FullDllName               : UNICODE_STRING;
  BaseDllName               : UNICODE_STRING;
  Flags                     : DWORD;
  LoadCount                 : Word;
  TlsIndex                  : Word;
  //HashLinks                 : TListEntry;
  SectionPointer            : Pointer;
  CheckSum                  : DWORD;
  //TimeDateStamp             : DWORD;
  LoadedImports             : Pointer;
  EntryPointActivationContext  : Pointer;
  PatchInformation          : Pointer;

  //自定义
  FullName                  : array [0..255] of Char;
  BaseName                  : array [0..63] of Char;

end;
TLDR_DATA_TABLE_ENTRY = _LDR_DATA_TABLE_ENTRY;
PLDR_DATA_TABLE_ENTRY = ^_LDR_DATA_TABLE_ENTRY;
TLdrDataTableEntry    = _LDR_DATA_TABLE_ENTRY;
PLdrDataTableEntry    = ^_LDR_DATA_TABLE_ENTRY;
function FindDestModule(pModuleListBuf:Pointer; DestModuleName:string; ModuleCount:DWORD):Boolean;
var
  pTableEntry     : PLdrDataTableEntry;
  i               : DWORD;
  scanInfo        : TScanHookInfo;
  ShortName       : string;
  SystemPath      : string;
  FullPath        : string;
begin
  Result:=False;

  // 得到系统路径,确保以路径分隔符结尾
  SystemPath:=IncludeTrailingBackslash(GetSystemPath());
  
  // 遍历由驱动传回的模块列表,找到指定basename的项
  pTableEntry:=PLdrDataTableEntry(pModuleListBuf);
  for i := 0 to ModuleCount - 1 do
  begin
    if SameText(string(pTableEntry.BaseName), DestModuleName) then
    begin
    // 找到指定的BaseName之后跟系统路径组合一下
      ShortName:=ExtractFileName(string(pTableEntry.FullName));
      FullPath:=SystemPath + ShortName;
      Break;
    end;

    Inc(pTableEntry);
  end;

  // 如果文件不在系统路径下,可能在drivers路径下,如果不在这两个路径中就忽略掉
  if not FileExists(FullPath) then FullPath:=SystemPath + 'drivers\' + ShortName;
  if not FileExists(FullPath) then Exit;

  // 填充主要结构
  InitModuleInfo(@scanInfo, ShortName, FullPath, DWORD(pTableEntry.DllBase), KernelMode);
  
  // 正式开始检测
  Result:=CheckInlineHook(@scanInfo);
end;
type
TScanMode = (KernelMode, UserMode);                 //扫描内核还是用户空间
THookType = (InlineHook, IATHook);                  //Hook 类型

type                                                //扫描到的hook 返回结果
THookBytes = packed record
  OriData       : array [0..49] of Byte;                  //原始数据
  CurData       : array [0..49] of Byte;                  //当前数据
  Len           : DWORD;                                  //长度
  Address       : DWORD;                                  //起始地址
  HookType      : THookType;                              //Hook 类型
end;
PHookBytes = ^THookBytes;

type
TScanHookInfo = packed record                      //包含当前扫描的模块信息
  ModuleName    : array [0..63] of Char;           //模块名称
  ModulePath    : array [0..MAX_PATH - 1] of Char; //模块路径
  SectionName   : array [0..15] of Char;           //节区名称
  ModuleBase    : DWORD;                           //模块的加载基址
  MapModuleBase : DWORD;                           //模块的映射基址
  Mode          : TScanMode;                       //当前扫描模式
  ProcessId     : DWORD;                           //用户模式下有效
  SectionHeader : PImageSectionHeader;             //当前扫描的节区

  SourceAddress : DWORD;                           //进行对比时的地址A
  DestAddress   : DWORD;                           //进行对比时的地址B
  CompareSize   : DWORD;                           //对比大小

  HookData      : THookBytes;
end;
PScanHookInfo = ^TScanHookInfo;
procedure InitModuleInfo(scanInfo:PScanHookInfo; ModuleName:string; ModulePath:string; ModuleBase:DWORD; Mode:TScanMode; ProcId:DWORD = $FFFFFFFF);
begin
  ZeroMemory(scanInfo, SizeOf(TScanHookInfo));
  MoveMemory(@scanInfo.ModuleName, PChar(ModuleName), Length(ModuleName)*sizeof(Char));
  MoveMemory(@scanInfo.ModulePath, PChar(ModulePath), Length(ModulePath)*sizeof(Char));
  scanInfo.ModuleBase:=ModuleBase;
  scanInfo.Mode:=Mode;
  if ProcId <> $FFFFFFFF then
    scanInfo.ProcessId:=ProcId;
end;
function CheckInlineHook(scanInfo:PScanHookInfo):Boolean;
var
  MapModuleBase     :DWORD;
  tempStr           :string;
  tempFile          :string;

  label lbExit1;
begin
  Result:=False;

  // 用户界面回显
  tempStr:=Format('[%s]准备初始化',[string(scanInfo.ModuleName)]);
  SendMessage(MainForm.Handle, MSG_THREAD_STATUS, Integer(@tempStr[1]), 0);


  // 在这里,我将原文件拷贝到了临时目录再进行映射
  tempFile:=CopyFileToTempDirectory(scanInfo.ModulePath);
  if not FileExists(tempFile) then Exit;
  
  
  // 映射模块
  MapModuleBase:=DWORD(MapFileWriteAble(tempFile));
  if MapModuleBase = 0 then
  begin
    tempStr:=Format('[%s]映射模块发生错误',[string(scanInfo.ModuleName)]);
    SendMessage(MainForm.Handle, MSG_THREAD_ERROR, Integer(@tempStr[1]), 0);
    Exit;
  end;

  
  // 用户界面回显
  tempStr:=Format('[%s]初始化完毕,重定向数据...',[string(scanInfo.ModuleName)]);
  SendMessage(MainForm.Handle, MSG_THREAD_STATUS, Integer(@tempStr[1]), 0);
  
  
  // 重定向模块
  if not RelocSpecialModule(MapModuleBase, scanInfo.ModuleBase) then
  begin
    tempStr:=Format('[%s]重定向模块时发生错误',[string(scanInfo.ModuleName)]);
    SendMessage(MainForm.Handle, MSG_THREAD_ERROR, Integer(@tempStr[1]), 0);
    goto lbExit1;
  end;
  
  // 填充结构
  scanInfo.MapModuleBase  :=MapModuleBase;
  
  
  // 首先检测IATHook
  case scanInfo.Mode of
    KernelMode:
    begin
      CheckSpecialModuleIATHookKernel(scanInfo);
    end;

    UserMode:
    begin
      //CheckSpecialModuleIATHookUser(scanInfo);
    end;
  end;
  
  // 扫描.text PAGE节区
  ScanSection('.text', scaninfo);
  ScanSection('PAGE', scaninfo);

  Result:=True;
  
lbExit1:
  if MapModuleBase <> 0 then UnMapFile(PBYTE(MapModuleBase));
  DeleteFile(tempFile);
end;

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 6
支持
分享
最新回复 (37)
雪    币: 601
活跃值: (256)
能力值: ( LV11,RANK:190 )
在线值:
发帖
回帖
粉丝
2
招租,谢谢分享
2012-2-27 12:03
0
雪    币: 96
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
同上,楼主乃牛人。
2012-2-27 12:44
0
雪    币: 415
活跃值: (34)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
4
强大的delphi,强大的thisis.
2012-2-27 14:54
0
雪    币: 2314
活跃值: (2205)
能力值: (RANK:400 )
在线值:
发帖
回帖
粉丝
5
解析符号文件吧,哈哈。
2012-2-27 16:04
0
雪    币: 890
活跃值: (55)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
6
谢谢楼主,先收藏了,有时间在看
2012-2-27 18:14
0
雪    币: 602
活跃值: (45)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
强烈支持 Delphi 备注
2012-2-27 18:30
0
雪    币: 292
活跃值: (153)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
8
果断收藏~  Hook 好玩。
2012-2-27 20:05
0
雪    币: 585
活跃值: (573)
能力值: ( LV13,RANK:290 )
在线值:
发帖
回帖
粉丝
9
MmIsAddressValidEx是MmIsAddressValid的扩展版本,是一个很好的用来取代MmIsAddressValid的函数,可以在这里找到
http://bbs.pediy.com/showthread.php?t=109819

我们知道如果一个驱动中某个页面从没有被访问的时候系统可能不会对这个页面进行映射,
而我们在读取一块内存的时候通常都使用MmIsAddressValid来首先验证一下地址的有效性,
这样问题就来了,当使用MmIsAddressValid对一块没有被映射的有效内存进行判断的时候MmIsAddressValid会FALSE,
而实际上这内存是有效的,只不过还没有被映射而已,这样就会造成误判了
而使用MmIsAddressValidEx则不需要有这个顾虑,只要返回的不是VCS_INVALID,都是有效的内存地址,可以直接访问。。

曾经MmIsAddressValid这个函数把我坑惨了,,
2012-2-27 20:26
0
雪    币: 233
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
好东西啊,谢谢分享
2012-2-27 20:50
0
雪    币: 101
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
太强大了,望尘莫及
2012-2-27 21:09
0
雪    币: 589
活跃值: (119)
能力值: ( LV11,RANK:190 )
在线值:
发帖
回帖
粉丝
12
回帖学习
2012-2-27 21:55
0
雪    币: 274
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
楼主很强大呀,谢谢分享
2012-2-28 09:34
0
雪    币: 206
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
楼主写的好高深,就好比行业密码一样,外行看不出来~!!!
2012-2-28 11:09
0
雪    币: 417
活跃值: (143)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
好文,谢谢楼主分享
2012-2-29 13:08
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
我来了,支持楼主
虽然还是什么都看不懂,但是我在努力学
为了不再疏远大家,我来了
求楼主当老师QQ785150915
2012-2-29 22:09
0
雪    币: 322
活跃值: (113)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
谢谢楼主,先收藏了,有时间在看!!!
2012-3-1 10:04
0
雪    币: 220
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
不错 ( ^_^ )不错嘛
2012-3-2 01:32
0
雪    币: 15
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
19
楼上如真牛人啊
2012-3-2 15:18
0
雪    币: 265
活跃值: (84)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
看得出来,楼主真的是潜心研究技术的行家里手
2012-3-5 20:08
0
雪    币: 270
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
找了很长时间了额,终于看到了,感谢楼主分享,而且还是D的,更给力。
2012-3-6 10:03
0
雪    币: 231
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
相当给力的代码
2012-3-6 10:37
0
雪    币: 1040
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
很给力的D吖,好少见到看雪上,用D写的精华贴!
2012-3-6 16:47
0
雪    币: 0
活跃值: (954)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
24
C/C++ 能做的事情 pascal 依然可以胜任。
2012-3-7 08:32
0
雪    币: 428
活跃值: (33)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
看不懂的好文章~
2012-3-8 19:16
0
游客
登录 | 注册 方可回帖
返回
//