首页
社区
课程
招聘
[旧帖] [邀请码已发][原创]HOOK之获取内核函数地址(申请激请码) 0.00雪花
发表于: 2010-4-21 20:55 4058

[旧帖] [邀请码已发][原创]HOOK之获取内核函数地址(申请激请码) 0.00雪花

2010-4-21 20:55
4058
来到看雪,胆子都变小了,好多大牛,导致连贴子都不敢发。
今天为了求个激活码,斗胆献丑,希望版主大哥赏赐!

对与驱动编程中的入门,我说下这几天学习得问题。
我发现很多新手学驱动上来就是SSDT HOOK,inline hook,包括我自己。
但是对一些基础却一无所知,就比如获取函数地址,连地址都不知道怎么获取就HOOK,也太勉强了。
今天就讨论这获取函数地址。

内核函数有导出与未导出函数,
导出或未导出看ntoskrnl.exe导出表就晓得了。可以用导出表查看工具或PE文件工具查看。
也可以到DDK的帮助文档里查找,没有则说明未导出。如果有都会指出声明所在的头文件。

导出函数只要声明下就可以直接调用MmGetSystemRoutineAddress获取地址
当然就转换下类型也可得到。如:(ULONG)NtFunname...

导出与未导出函数声明都可查看下面的网站
http://undocumented.ntinternals.net/

未导出函数的地址获取会麻烦些。
首先了解下SSDT中的函数,如果SSDT中有,可以通过获取SSDT的地址加索引得到。
别告诉我SSDT地址都不知道怎么获取。

typedef struct _SYSTEM_SERVICE_TABLE
{
        unsigned int *ServiceTableBase;
        unsigned int *ServiceCounterTableBase;
        unsigned int NumberOfServices;
        unsigned char *ParamTableBase;
}
SYSTEM_SERVICE_TABLE,
*PSYSTEM_SERVICE_TABLE,
**PPSYSTEM_SERVICE_TABLE;

__declspec(dllimport) SYSTEM_SERVICE_TABLE KeServiceDescriptorTable;//得到SSDT地址

还不知道你可以用看雪刚推出的www.kanxue.con搜索去了。

#define SYSTEMSERVICE(ID)  KeServiceDescriptorTable.ServiceTableBase[ID]

加上这个宏就可以通过服务号得到函数地址了。

关于如何获取服务号可以从下面的页面查看
http://www.pediy.com/document/Windows_System_Call_Table/Windows_System_Call_Table.htm

大牛们也提供了通过ntdll.dll获取服务号的函数。(尾部贴出代码这里写下使用)
#define SYSCALL_INDEX(_Function) *(PULONG) ((PUCHAR)_Function+1)
用这个宏得到服务号。
原理:---------------------------------------------------------------------------------
lkd> u NtReadVirtualMemory
nt!NtReadVirtualMemory:
805b40bc 6a1c            push    1Ch
805b40be 68f0ae4d80      push    offset nt!MmClaimParameterAdjustDownTime+0x90 (804daef0)
805b40c3 e89888f8ff      call    nt!_SEH_prolog (8053c960)
805b40c8 64a124010000    mov     eax,dword ptr fs:[00000124h]
805b40ce 8bf8            mov     edi,eax

lkd> u ZwReadVirtualMemory
nt!ZwReadVirtualMemory:
80501b94 b8ba000000      mov     eax,0BAh        ;此处0BAh就是NtReadVirtualMemory的服务号
80501b99 8d542404        lea     edx,[esp+4]
80501b9d 9c              pushfd
80501b9e 6a08            push    8
80501ba0 e88c060400      call    nt!KiSystemService (80542231)
80501ba5 c21400          ret     14h
--------------------------------------------------------------------------------------
UNICODE_STRING dllName;
DWORD          functionAddress;
int            position;
RtlInitUnicodeString( &dllName, L"\\Device\\HarddiskVolume1\\Windows\\System32\\ntdll.dll" );
functionAddress = GetDllFunctionAddress("NtReadVirtualMemory", &dllName);
position = SYSCALL_INDEX(functionAddress);
//获取NtReadVirtualMemory的服务号完毕!
SYSTEMSERVICE(position);
就可得到地址。

SSDT中没有,可以再看看shadow ssdt。shadow ssdt中的函数是GUI函数。
对shadow ssdt不太了解的可以查看shadow ssdt 学习笔记一贴,写的比较详细。
http://bbs.pediy.com/showthread.php?t=56955

shadow ssdt与SSDT一样,都有它的索引表。我没找到,有的朋友可以共享份,先谢谢了。
我是通过XueTr工具查看的。小巧简洁的工具,挺强大。

前面的序号就是shadow ssdt中的索引了。注意shadow ssdt中的地址需要GUI线程上下文才有效。

未导出函数不在SSDT 或 shadow ssdt中那将是最麻烦的事了。
拿KiAttachProcess作例子。
我们知道有个KeAttachProcess是导出函数并且中间是调用了KiAttachProcess。
我们可以用windbg查看下KeAttachProcess
lkd> uf KeAttachProcess
nt!KeAttachProcess:
804f9afc 8bff            mov     edi,edi
804f9afe 55              push    ebp
804f9aff 8bec            mov     ebp,esp
804f9b01 56              push    esi
804f9b02 57              push    edi
804f9b03 64a124010000    mov     eax,dword ptr fs:[00000124h]
804f9b09 8b7d08          mov     edi,dword ptr [ebp+8]
804f9b0c 8bf0            mov     esi,eax
804f9b0e 397e44          cmp     dword ptr [esi+44h],edi
804f9b11 742f            je      nt!KeAttachProcess+0x46 (804f9b42)

nt!KeAttachProcess+0x17:
804f9b13 80be6501000000  cmp     byte ptr [esi+165h],0
804f9b1a 752c            jne     nt!KeAttachProcess+0x4c (804f9b48)

nt!KeAttachProcess+0x20:
804f9b1c 64a194090000    mov     eax,dword ptr fs:[00000994h]
804f9b22 85c0            test    eax,eax
804f9b24 7522            jne     nt!KeAttachProcess+0x4c (804f9b48)

nt!KeAttachProcess+0x2a:
804f9b26 33c9            xor     ecx,ecx
804f9b28 ff1588904d80    call    dword ptr [nt!_imp_KeAcquireQueuedSpinLockRaiseToSynch

(804d9088)]
804f9b2e 884508          mov     byte ptr [ebp+8],al
804f9b31 8d864c010000    lea     eax,[esi+14Ch]
804f9b37 50              push    eax
804f9b38 ff7508          push    dword ptr [ebp+8]
804f9b3b 57              push    edi
804f9b3c 56              push    esi
804f9b3d e890feffff      call    nt!KiAttachProcess (804f99d2) ;---------------------这行

nt!KeAttachProcess+0x46:
804f9b42 5f              pop     edi
804f9b43 5e              pop     esi
804f9b44 5d              pop     ebp
804f9b45 c20400          ret     4

好了,看下e890feffff      call    nt!KiAttachProcess (804f99d2)这里
调用了KiAttachProcess。我们就利用它来获取KiAttachProcess的地址。

ULONG Addres;
Addres = (ULONG)KeAttachProcess+0x42;        //经过计算call nt!KiAttachProcess的偏移量0x42
Addres = *(ULONG*)Addres;                //得到KiAttachProcess地址的偏移量
Addres = (ULONG)KeAttachProcess + 0x46 + Addres;//相加得到KiAttachProcess的地址

就是这样了。可以根据不同情况扩展。还有哪些方法希望大牛们可以指导指导。

/*************大牛提供的获取函数地址********/
DWORD GetDllFunctionAddress(char* lpFunctionName, PUNICODE_STRING pDllName)
{
  HANDLE hThread, hSection, hFile, hMod;
  SECTION_IMAGE_INFORMATION sii;
  IMAGE_DOS_HEADER* dosheader;
  IMAGE_OPTIONAL_HEADER* opthdr;
  IMAGE_EXPORT_DIRECTORY* pExportTable;
  DWORD* arrayOfFunctionAddresses;
  DWORD* arrayOfFunctionNames;
  WORD* arrayOfFunctionOrdinals;
  DWORD functionOrdinal;
  DWORD 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;
  
  ZwOpenFile(&hFile, FILE_EXECUTE | SYNCHRONIZE, &oa, &iosb, FILE_SHARE_READ,

FILE_SYNCHRONOUS_IO_NONALERT);
  
  oa.ObjectName = 0;
  
  ZwCreateSection(&hSection, SECTION_ALL_ACCESS, &oa, 0,PAGE_EXECUTE, SEC_IMAGE, hFile);
  
  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);
  
  arrayOfFunctionAddresses = (DWORD*)( (BYTE*)hMod + pExportTable->AddressOfFunctions);
  
  arrayOfFunctionNames = (DWORD*)( (BYTE*)hMod + pExportTable->AddressOfNames);
  
  arrayOfFunctionOrdinals = (WORD*)( (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;
    functionAddress = (DWORD)( (BYTE*)hMod + arrayOfFunctionAddresses[functionOrdinal]);
    if (RtlCompareString(&ntFunctionName, &ntFunctionNameSearch, TRUE) == 0)
    {
      ZwClose(hSection);
      return functionAddress;
    }
  }
  
  ZwClose(hSection);
  return 0;
}

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 0
支持
分享
最新回复 (31)
雪    币: 287
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
支持一下先!
2010-4-22 00:16
0
雪    币: 7067
活跃值: (4005)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
有用......
2010-4-22 08:44
0
雪    币: 266
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
记下了! 哈
2010-4-22 09:18
0
雪    币: 38
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
高手...俺是初学者,先记录下来,以后学到的时候好好参详参详,支持下!
2010-4-22 09:44
0
雪    币: 290
活跃值: (32)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
谢谢各位支持~~~~~
2010-4-22 16:52
0
雪    币: 5
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
强烈支持楼主
2010-4-22 18:00
0
雪    币: 290
活跃值: (32)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
谢谢楼上的支持。
走过路过不要错过,各位大哥大姐叔叔阿姨大妈大婶。看到帮忙顶下~~
还望版主能给个机会~~~
2010-4-23 12:48
0
雪    币: 90
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
不错,希望以后多多出这样的教程,谢谢分享了
2010-4-23 16:35
0
雪    币: 290
活跃值: (32)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
一定继续努力~~~~挖掘通用性最好的方法。
2010-4-24 13:31
0
雪    币: 138
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
Addres = (ULONG)KeAttachProcess + 0x46 + Addres;//相加得到KiAttachProcess的地址
这里的0x46是哪来的? 写错了吗?
2010-4-24 22:36
0
雪    币: 290
活跃值: (32)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
804f9b3c 56              push    esi
804f9b3d e890feffff      call    nt!KiAttachProcess (804f99d2) ;---------------------这行

nt!KeAttachProcess+0x46:
804f9b42 5f              pop     edi

我们得到的地址偏移是相对804f9b3d e890feffff      call    nt!KiAttachProcess (804f99d2) 这句语句结束的地址偏移,这句语句结束地址正好就是nt!KeAttachProcess+0x46。
2010-4-25 16:40
0
雪    币: 138
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
谢谢你的解答,不知道理解的对不对,
call    nt!KiAttachProcess (804f99d2)共5个字节,最后一个字节相对nt!KeAttachProcess偏移0x46,而KiAttachProcess的偏移是相对于这最后一个字节的,所以是0x46.
2010-4-26 15:10
0
雪    币: 290
活跃值: (32)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
对的。。。
2010-4-27 01:37
0
雪    币: 8149
活跃值: (2751)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
15
并非所有的导出函数都有文档..

引用导出但未文档的函数.

可以查一下原型.

然后前面直接加一个 NTKERNELAPI 即可.

无需MmXXX这样繁琐的找地址.

例如说 非常常用的那个ObReferenceObjectByName.

原型.
NTSTATUS
ObReferenceObjectByName (
    __in PUNICODE_STRING ObjectName,
    __in ULONG Attributes,
    __in_opt PACCESS_STATE AccessState,
    __in_opt ACCESS_MASK DesiredAccess,
    __in POBJECT_TYPE ObjectType,
    __in KPROCESSOR_MODE AccessMode,
    __inout_opt PVOID ParseContext,
    __out PVOID *Object
    )

引用的时候

直接
NTKERNELAPI
NTSTATUS
ObReferenceObjectByName (
    __in PUNICODE_STRING ObjectName,
    __in ULONG Attributes,
    __in_opt PACCESS_STATE AccessState,
    __in_opt ACCESS_MASK DesiredAccess,
    __in POBJECT_TYPE ObjectType,
    __in KPROCESSOR_MODE AccessMode,
    __inout_opt PVOID ParseContext,
    __out PVOID *Object
    )
即可.
2010-4-27 02:15
0
雪    币: 290
活跃值: (32)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
LS是对的,但有注意的地方。
引用sudami大牛原话。
Mm的作用是在ntos*的EAT中找到函数地址, 和自己在EAT中没什么区别, 唯一不同的是它是用二分查找法找的.

再者, 若直接调用导出函数,比如KeInsertQueueApc,是直接从你写的驱动的IAT中调用,而此时你的IAT可能被某些程序修改过,比如微点主动防御软件. 此时你的地址便是微点的fake_KeInsertQueueApc的地址; 而用MmGet*得到的函数地址是ntos*导出的地址, 若安全软件没有对ntos*进行EAT HOOK,那么取得的地址是正确的.
2010-4-27 18:29
0
雪    币: 28
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
不错。。正好需要!~~~~
2010-4-28 18:13
0
雪    币: 1731
活跃值: (22)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
看看随便顶下你!
2010-4-28 20:55
0
雪    币: 241
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
先收藏。。。。
2010-4-29 09:40
0
雪    币: 27
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
不知道delphi 对这个能不能对得上
2010-4-29 11:15
0
雪    币: 73
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
强呵,赞一个。
2010-4-29 15:40
0
雪    币: 9
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
好贴,学习了
2010-4-29 19:10
0
雪    币: 290
活跃值: (32)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
谢谢各位支持。。。。小生在此有礼了!
2010-4-30 20:44
0
雪    币: 28
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
函数有些结构找不到~~~
2010-5-2 21:30
0
雪    币: 33
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
正好有用,收藏了
多谢LZ
2010-5-2 21:34
0
游客
登录 | 注册 方可回帖
返回
//