首页
论坛
课程
招聘
汇编ring3下实现HOOK API[原创]
2006-7-12 18:39 29591

汇编ring3下实现HOOK API[原创]

2006-7-12 18:39
29591
汇编ring3下实现HOOK API(二次修改版)

【文章标题】汇编ring3下实现HOOK API
【文章作者】nohacks(非安全,hacker0058)
【作者主页】hacker0058.ys168.com
【文章出处】看雪论坛(bbs.pediy.com)

===========================[ 汇编ring3下实现HOOK API ]=======================

                                                 Author: nohacks
                                                 Emil: kker.cn@163.com
                                                 Version: 1.1
                                                 Date: 7.18.2006
                                                

=====[ 1. 内容 ]=============================================

1. 内容
2. 介绍
  2.1 什么叫Hook API?
  2.2 API Hook的应用介绍
  2.3 API Hook的原则
3. 挂钩方法
  3.1 改写IAT导入表法
  3.2 改写内存地址JMP法
4. 汇编实现
  4.1. 代码
  4.2. 分析
5. 结束语

=====[ 2. 介绍 ]================================================

   这篇文章是有关在OS Windows下挂钩API函数的方法。所有例子都在基于NT技术的Windows版本NT4.0

及以上有效(Windows NT 4.0, Windows 2000, Windows XP)。可能在其它Windows系统也会有效。

   你应该比较熟悉Windows下的进程、汇编器、和一些API函数,才能明白这篇文章里的内容。

=====[2.1 什么叫Hook API?]=================================
   
   所谓Hook就是钩子的意思,而API是指Windows开放给程序员的编程接口,使得在用户级别下可

以对操作系统进行控制,也就是一般的应用程序都需要调用API来完成某些功能,Hook API的意思

就是在这些应用程序调用真正的系统API前可以先被截获,从而进行一些处理再调用真正的API来完

成功能。

====[2.2 API Hook的应用介绍]=================================
   
   API Hook技术应用广泛,常用于屏幕取词,网络防火墙,病毒木马,加壳软件,串口红外通讯,游戏外

挂,internet通信等领域API HOOK的中文意思就是钩住API,对API进行预处理,先执行我们的函数,例

如我们用API Hook技术挂接ExitWindowsEx API函数,使关机失效,挂接ZwOpenProcess函数(如:老王的

EncryptPE),隐藏进程等等......

====[2.3 API Hook的原则]=====================================
   
   HOOK API有一个原则,这个原则就是:被HOOK的API的原有功能不能受到任何影响。就象医生救人,

如果把病人身体里的病毒杀死了,病人也死了,那么这个“救人”就没有任何意义了。如果你HOOK API

之后,你的目的达到了,但API的原有功能失效了,这样不是HOOK,而是REPLACE,操作系统的正常功能

就会受到影响,甚至会崩溃。

====[ 3. 挂钩方法 ]==============================================

总的来说,常用的挂钩API方法有以下两种:

3.1 改写IAT导入表法

   修改可执行文件的IAT表(即输入表)因为在该表中记录了所有调用API的函数地址,则只需将这些

地址改为自己函数的地址即可,但是这样有一个局限,因为有的程序会加壳,这样会隐藏真实的IAT表

,从而使该方法失效。

3.2 改写内存地址JMP法

    直接跳转,改变API函数的入口或出口的几个字节,使程序跳转到自己的函数,该方法不受程序加壳

的限制。这种技术,说起来也不复杂,就是改变程序流程的技术。在CPU的指令里,有几条指令可以改变

程序的流程:JMP,CALL,INT,RET,RETF,IRET等指令。理论上只要改变API入口和出口的任何机器码

,都可以HOOK,下面我就说说常用的改写API入口点的方法:
   
    因为工作在Ring3模式下,我们不能直接修改物理内存,只能一个一个打开修改,但具体的方法又分成

好几种,我给大家介绍几种操作思路:

  <1>首先改写API首字节,要实现原API的功能需要调用API时先还原被修改的字节,然后再调用原API,调

用完后再改回来,这样实现有点麻烦,但最简单,从理论上说有漏HOOK的可能,因为我们先还原了API,如果

在这之前程序调用了API,就有可能逃过HOOK的可能!

  (2)把被覆盖的汇编代码保存起来,在替代函数里模拟被被覆盖的功能,然后调用原函数(原地址+被覆

盖长度).但这样会产生一个问题,不同的汇编指令长度是不一样的(比如说我们写入的JMP指令占用5个字

节,而我们写入的这5个字节占用的位置不一定正好是一个或多个完整的指令,有可能需要保存7个字节,

才不能打乱程序原有的功能,需要编写一个庞大的判断体系来判断指令长度,网上已经有这样的汇编程序

(Z0MBiE写的LDE32),非常的复杂!

  (3)把被HOOK的函数备份一下,调用时在替代函数里调用备份函数.为了避免麻烦,可以直接备份整个

DLL缺点就是太牺牲内存,一般不推荐使用这种方法!

=====[ 4. 汇编实现 ]==============================================

本文就是建立在第2种方法之上的!本着先易后难的原则,今天我们先来说说它的第1种操作思路.
  
  我们拿API函数ExitWindowsEx来说明,下面是我在OD里拦下的ExitWindowsEx原入口部分

     77D59E2D            $  8BFF          mov edi,edi  
     77D59E2F            .  55            push ebp
     77D59E30            .  8BEC          mov ebp,esp
     77D59E32            .  83EC 18       sub esp,18
      ......

  如果我们把ExitWindowsEx的入口点改为下面的,会出现什么情况?

    77D59E2D               B8 00400000   mov eax,4000
    77D59E32               FFE0          jmp eax
    ......

  我们可想而知,程序执行到77D59E32处就会改变流程跳到00400000的地方

  如果我们的00400000处是这样的子程:

=======================
MyAPI proc  bs:DWORD  ,dwReserved:DWORD  ;和ExitWindowsEx一样带2个参数                 

;做你想做的事

......

;这里放API入口点改回原机器码的代码

;如果你是备份的整个DLL,就直接调用备份API,不用改来改去了,不会有漏勾API的可能!

invoke ExitWindowsEx,bs,dwReserved
                          
;这里放HOOK API的代码
       
.endif

mov eax,TRUE

ret
=======================

   这里的MyAPI是和ExitWindowsEx参数一样的的子程,因为程序是在API的入口部分跳转的,根据

stdcall约定(参数数据从右向左依次压栈,恢复堆栈的工作交由被调用者),此时堆栈还没有恢复,我们

在子程里取出的参数数据依然有效,我们可以在这里执行自己的代码,你可以决定是否继续按原参数或改

变参数后再调用原API,也可以什么都不做,当然在调用之前,我们要先还原我们修改过的API(可以事先用

API函数ReadProcessMemory读出原API的前几个字节备份之),调用完后再改回来继续HOOK API,不过这种

方法有漏API的可能(原因前面已经说了),你如果觉得这个方法不妥,因为一般系统DLL都不大,你可以备

份整个DLL.

下面我就列出ring3下HOOK API的几个步骤:

1.得到要挂勾API的入口点

2.修改API的入口点所在页的页面保护为可读写模式

3.用ReadProcessMemory读出API的入口点开始的几字节备份

4.用WriteProcessMemory修改API的入口点象这样的形式:
  
  mov eax,4000
  
  jmp eax

其中的4000要用和原API参数一样的子程序地址代替

  在这个子程序里我们决定用什么参数再调用原API,不过调用之前要用备份的前8字节改回来

调用之后在挂勾,如此反复.

=====[ 4.1. 代码 ]==============================================

  前面所讲的是本进程挂勾,我们要挂勾所有进程,可以用全局勾子,需要单独的一个DLL,我们可

以在DLL的DLL_PROCESS_ATTACH事件里来HOOK API

=================================hookdll.dll==========================
.486
.model flat,stdcall   ;参数的传递约定是stdcall(从右到左,恢复堆栈的工作交由被调用者)
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib

HOOKAPI struct
a  byte ?
PMyapi DWORD ?   
d BYTE ?  
e BYTE ?
HOOKAPI ends

;子程序声明
WriteApi proto :DWORD ,:DWORD,:DWORD,:DWORD
MyAPI proto  :DWORD  ,:DWORD
GetApi proto  :DWORD,:DWORD

;已初始化数据
.data
hInstance dd 0
WProcess dd 0
hacker HOOKAPI <>
CommandLine LPSTR ?

Papi1 DWORD ?
Myapi1 DWORD ?
ApiBak1 db 10 dup(?)
DllName1  db "user32.dll",0      
ApiName1  db "ExitWindowsEx",0
mdb db "下面的程序想关闭计算机,要保持阻止吗?",0

;未初始化数据

.data?
hHook dd ?
hWnd dd ?

;程序代码段

.code

DllEntry proc hInst:HINSTANCE, reason:DWORD, reserved1:DWORD
   
  
.if reason==DLL_PROCESS_ATTACH     ;当DLL加载时产生此事件
        push hInst
        pop hInstance

invoke GetCommandLine   
mov CommandLine,eax                                         ;取程序命令行

;初始化

mov hacker.a,0B8h     ;mov eax,
;mov hacker.d PMyapi  ;0x000000
mov hacker.d,0FFh     ;jmp
mov hacker.e, 0E0h    ;eax

invoke   GetCurrentProcess                                   ;取进程伪句柄

mov WProcess ,eax
   
invoke GetApi,addr DllName1,addr ApiName1                    ;取API地址
  
mov Papi1,eax                                               ;保存API地址

invoke ReadProcessMemory,WProcess,Papi1,addr ApiBak1,8,NULL  ;备份原API的前8字节

mov hacker.PMyapi,offset MyAPI   ;0x0000,这里设置替代API的函数地址

invoke WriteApi,WProcess,Papi1, addr hacker ,size HOOKAPI    ;HOOK API

.endif

.if  reason==DLL_PROCESS_DETACH

invoke WriteApi,WProcess,Papi1, addr ApiBak1 ,8               ;还原API

.endif

mov  eax,TRUE
    ret
DllEntry Endp

GetMsgProc proc nCode:DWORD,wParam:DWORD,lParam:DWORD
    invoke CallNextHookEx,hHook,nCode,wParam,lParam
     mov eax,TRUE
     
      ret
GetMsgProc endp

InstallHook proc
   
    invoke SetWindowsHookEx,WH_GETMESSAGE,addr GetMsgProc,hInstance,NULL
    mov hHook,eax
    ret
InstallHook endp

UninstallHook proc
    invoke UnhookWindowsHookEx,hHook
   invoke WriteApi,WProcess,Papi1, addr ApiBak1 ,8
  ret
UninstallHook endp

GetApi proc DllNameAddress:DWORD,ApiNameAddress:DWORD

invoke  GetModuleHandle,DllNameAddress     ;取DLL模块句柄
   
  .if eax==NULL
  
  invoke LoadLibrary ,DllNameAddress    ;加载DLL
  
   .endif
  
invoke GetProcAddress,eax,ApiNameAddress  ;取API地址
   

mov eax,eax
       
ret

GetApi endp

;============================下面是核心部分=========================

WriteApi proc Process:DWORD ,Papi:DWORD,Ptype:DWORD,Psize:DWORD

LOCAL mbi:MEMORY_BASIC_INFORMATION
LOCAL msize:DWORD

;返回页面虚拟信息
invoke VirtualQueryEx,Process, Papi,addr mbi,SIZEOF MEMORY_BASIC_INFORMATION

;修改为可读写模式

invoke VirtualProtectEx,Process, mbi.BaseAddress,8h,PAGE_EXECUTE_READWRITE,addr

mbi.Protect

;开始写内存

invoke  WriteProcessMemory,Process, Papi, Ptype,Psize ,NULL

PUSH eax

;改回只读模式

invoke VirtualProtectEx,Process,mbi.BaseAddress,8h,PAGE_EXECUTE_READ,addr mbi.Protect

pop eax

ret

WriteApi endp

;替代的API,参数要和原来一样

MyAPI proc  bs:DWORD  ,dwReserved:DWORD                     

invoke MessageBox, NULL,  CommandLine, addr mdb, MB_YESNO      ;弹出信息框选择是否阻止

.if eax==7                                                   ;如果选择否

invoke WriteApi,WProcess,Papi1, addr ApiBak1 ,8              ;先还原API

invoke ExitWindowsEx,bs,dwReserved                           ;再调用API

invoke WriteApi,WProcess,Papi1, addr hacker ,sizeof HOOKAPI  ;调用完后再改回来
       
.endif

mov eax,TRUE
ret

MyAPI endp

End DllEntry

===============================hookdll.def=============================

LIBRARY hookdll
EXPORTS InstallHook
EXPORTS UninstallHook

=====[ 4.2. 分析 ]==============================================

HOOKAPI struct
a  byte ?
PMyapi DWORD ?   
d BYTE ?  
e BYTE ?
HOOKAPI ends

   为了便于理解和使用,我定义了一个结构:这个结构有4个成员,第一个成员a,是个字节型,我用来放

0B8h(mov eax),PMyapi一个整数型,用来放我们的替代API函数的地址(0X000),第3个和第4个成员我分别

用来放JMP和EAX(jmp eax)那么连起来就是 mov,0X0000 ; jmp eax  

.if reason==DLL_PROCESS_ATTACH     
        push hInst
        pop hInstance

invoke GetCommandLine   
mov CommandLine,eax                                         

;初始化

mov hacker.a,0B8h     ;mov eax,
;mov hacker.d PMyapi  ;0x0000
mov hacker.d,0FFh     ;jmp
mov hacker.e, 0E0h    ;eax

invoke   GetCurrentProcess                                   

mov WProcess ,eax

  当DLL加载时,我们先保存模块句柄,读取程序命令行,然后初始化HOOKAPI结构,写入我们要写到内存的

指令(PMyapi以后写入)并调用GetCurrentProcess取出进程伪句柄方便以后写内存.

invoke GetApi,addr DllName1,addr ApiName1                    
  
mov Papi1,eax                                               

invoke ReadProcessMemory,WProcess,Papi1,addr ApiBak1,8,NULL  

mov hacker.PMyapi,offset MyAPI   ;0x0000   

invoke WriteApi,WProcess,Papi1, addr hacker ,size HOOKAPI    ;HOOK API

  接下来用子程GetApi取出要挂勾API的入口点,并用ReadProcessMemory读出入口点8字节备份之,写入
PMyapi调用子程WriteApi改写API的入口点,这个子程我不准备详细说了,它非常的简单,无非就是几个

API的调用.它的核心就是通过WriteProcessMemory改写内存.

.if  reason==DLL_PROCESS_DETACH

invoke WriteApi,WProcess,Papi1, addr ApiBak1 ,8               

.endif

mov  eax,TRUE
    ret

   如果这个DLL被卸载了,那么那个在DLL里的替代函数(MyAPI)将是无效的,如果这个时候程序再调用这

个API,将出现非法操作,因此在DLL卸载前,我们必须还原API.

   总结一下,现在只要程序加载这个DLL,这个程序的ExitWindowsEx就会被我们勾住,接下来要怎样才能

让所有的程序都加载这个DLL呢?这就需要安装全局勾子:

  InstallHook proc
   
      invoke SetWindowsHookEx,WH_GETMESSAGE,addr GetMsgProc,hInstance,NULL
   
      invoke WriteApi,WProcess,Papi1, addr hacker ,sizeof HOOKAPI

      mov hHook,eax
     ret
  InstallHook endp

   通过SetWindowsHookEx安装勾子,最后一个参数可以决定该钩子是局部的还是系统范围的。如果该值

为NULL,那么该钩子将被解释成系统范围内的,那它就可以监控所有的进程及它们的线程。

如果该函数调用成功的话,将在eax中返回钩子的句柄,否则返回NULL。我们必须保存该句柄,因为后

面我们还要它来卸载钩子,可以看出,我们创建的Hook类型是WH_CALLWNDPROC类型,该类型的Hook在进程

与系统一通信时就会被加载到进程空间,从而调用dll的初始化函数完成真正的Hook,值得一提的是:因

为要调用SetWindowsHookEx来安装钩子,我们GUI程序的这个DLL不会被

UnhookWidowHookEx卸载,也就只有一次DLL_PROCESS_ATTACH事件,因此这里再要

HOOK API一次!

我们回头来看看钩子回调函数:

  GetMsgProc proc nCode:DWORD,wParam:DWORD,lParam:DWORD
      invoke CallNextHookEx,hHook,nCode,wParam,lParam
       mov eax,TRUE
     
       ret
  GetMsgProc endp

   可以看到这里只是调用CallNextHookEx将消息交给Hook链中下一个环节处理,因为这里API函数
SetWindowsHookEx的唯一作用就是让进程加载我们的dll。

  UninstallHook proc
     invoke UnhookWindowsHookEx,hHook
     invoke WriteApi,WProcess,Papi1, addr ApiBak1 ,8
   ret
  UninstallHook endp

要卸载一个钩子时调用UnhookWidowHookEx函数,该函数仅有一个参数,就是欲卸载的钩子的句柄。钩

子卸载后我们也要还原我们GUI程序的API.

  LIBRARY hookdll
  EXPORTS InstallHook
  EXPORTS UninstallHook

   我们公开DLL里的InstallHook和UninstallHook函数,方便程序调用,这样我们只要在另外的程序中调

用InstallHook便可安装全局勾子,勾住所有程序中的API:ExitWindowsEx,执行我们自定的子程!

如果不需要了,可以调用UninstallHook卸载全局勾子.

   请注意:对于远程钩子,钩子函数必须放到DLL中,它们将从DLL中映射到其它的进程空间中去。当

WINDOWS映射DLL到其它的进程空间中去时,不会把数据段也进行映射。简言之,所有的进程仅共享DLL

的代码,至于数据段,每一个进程都将有其单独的拷贝。这是一个很容易被忽视的问题。您可能想当然

的以为,在DLL中保存的值可以在所有映射该DLL的进程之间共享。在通常情况下,由于每一个映射该

DLL的进程都有自己的数据段,所以在大多数的情况下您的程序运行得都不错。但是钩子函数却不是如

此。对于钩子函数来说,要求DLL的数据段对所有的进程也必须相同。这样您就必须把数据段设成共享

的:

一般来说, 目标文件有三个段, 分别是 text/data/bss 段.

.text 段放置代码, 是只读且可运行段

.data 段放置静态数据, 这些数据会被放置入 exe 文件. 这个段是可读写, 但是不能运行的.

.bss 段放置动态数据, 这些数据不被放入 exe 文件, 在exe文件被加载入内存后才分配的空间.

你可以通过在链接开关中指定段的属性来实现:

/SECTION:name,[E][R][W][S][D][K][L]

[X]

其中S表示共享,已初期化的段名是.data,未初始化的段名是.bss。假如您想要写一个包含钩子函数的

DLL,而且想使它的未初始化的数据段在所有进程间共享,您必须这么做:

link /section:.bss[S]  /DLL  /SUBSYSTEM:WINDOWS ..........

否则,您的全局勾子将不能正常工作!

=====[ 5. 结束语 ]================================================

    我欢迎任何人提出更多的这里没有提到的挂钩方法,我肯定那会有很多。同样欢迎补充我介绍得不

是很详细的方法。也可以把我懒得写的其它方法完成,把源代码发给我。这篇文档的目的是演示挂钩技

术的细节,我希望我做到了。
   
============================[ End ]========================

    水平有限,欢迎大家指出错漏之处。QQ:23453161 Email:kker.cn@163.com

    例子源程序(MASM+RadASM和Windows XP2系统下编译通过):

2021 KCTF 秋季赛 防守篇-征题倒计时(11月14日截止)!

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (22)
雪    币: 2170
活跃值: 活跃值 (31)
能力值: (RANK:410 )
在线值:
发帖
回帖
粉丝
小虾 活跃值 10 2006-7-12 18:48
2
0
你现在应该可以上传附件了。
雪    币: 578
活跃值: 活跃值 (31)
能力值: ( LV9,RANK:780 )
在线值:
发帖
回帖
粉丝
非安全 活跃值 17 2006-7-12 18:56
3
0
最初由 小虾 发布
你现在应该可以上传附件了。


恩,可以上传了,谢谢小虾版主
雪    币: 341
活跃值: 活跃值 (88)
能力值: ( LV9,RANK:690 )
在线值:
发帖
回帖
粉丝
winndy 活跃值 17 2006-7-12 19:06
4
0
很好好
和SND的 SUB Z3R0写的《HookInLinePatching》里的方法差不多
雪    币: 454
活跃值: 活跃值 (16)
能力值: ( LV12,RANK:660 )
在线值:
发帖
回帖
粉丝
prince 活跃值 16 2006-7-12 19:08
5
0
不错,支持!
雪    币: 2071
活跃值: 活跃值 (14)
能力值: (RANK:170 )
在线值:
发帖
回帖
粉丝
Aker 活跃值 4 2006-7-13 06:54
6
0
怎么附件下不了啊
雪    币: 578
活跃值: 活跃值 (31)
能力值: ( LV9,RANK:780 )
在线值:
发帖
回帖
粉丝
非安全 活跃值 17 2006-7-13 18:04
7
0
最初由 Aker 发布
怎么附件下不了啊


可以下啊
雪    币: 205
活跃值: 活跃值 (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
okdodo 活跃值 2 2006-7-21 14:19
8
0
很详细  谢谢分享   
雪    币: 111
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
无奈无赖 活跃值 2006-8-31 14:04
9
0
收藏,最近打算学习一下这方面的知识。

想请教一下,如果我不用dll,而且只对某一特写的进程的API进行hook,能够达到吗?那又该如何实现?
雪    币: 578
活跃值: 活跃值 (31)
能力值: ( LV9,RANK:780 )
在线值:
发帖
回帖
粉丝
非安全 活跃值 17 2006-8-31 14:50
10
0
最初由 无奈无赖 发布
收藏,最近打算学习一下这方面的知识。

想请教一下,如果我不用dll,而且只对某一特写的进程的API进行hook,能够达到吗?那又该如何实现?


可以的,在需要挂勾的进程内申请一空间,把新API函数用字节写到这个空间
(当然,你需要对汇编非常熟),然后再修改原API,办法同上
雪    币: 111
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
无奈无赖 活跃值 2006-8-31 17:15
11
0
我是这样子想的,我使用CreateProcess以挂起状态创建一个我们需要的进程,这样子我们就对这个进程的所有内存空间拥有全部权限,那接下来我是用否就可以先完成API HOOK,然后再恢复进程的运行呢?

不知道 这样子是否可行。程序的流程应该怎么样安排?
CreateProcess以挂起状态创建一个进程
GetProcAddress取API地址
ReadProcessMemory 备份API开头的数据
VirtualQueryEx返回虚拟页面的信息并保存
VirtualProtectEx改写虚拟页面信息
WriteProcessMemory向API头部写入新的代码
VirtualProtectEx恢复虚拟页面信息

在WriteProcessMemory这里,我的替代API在我的这个启动器(姑且这么叫吧,就是用CreateProcess创建进程的这个程序)内,不知道这样是否能行得通。
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yxt 活跃值 2006-9-6 13:56
12
0
如何备份函数呢?希望楼主讲下这个。
雪    币: 578
活跃值: 活跃值 (31)
能力值: ( LV9,RANK:780 )
在线值:
发帖
回帖
粉丝
非安全 活跃值 17 2006-9-9 17:36
13
0
最初由 无奈无赖 发布
我是这样子想的,我使用CreateProcess以挂起状态创建一个我们需要的进程,这样子我们就对这个进程的所有内存空间拥有全部权限,那接下来我是用否就可以先完成API HOOK,然后再恢复进程的运行呢?

不知道 这样子是否可行。程序的流程应该怎么样安排?
CreateProcess以挂起状态创建一个进程
GetProcAddress取API地址
........


替代API在启动器里,CreateProcess挂起的进程是否可以共享这段代码呢?

我没有试过,所以不能下结论!

不过我知道另外一个方法,应该是可行的:

用OpenProcess打开进程,获得最大权限

用下面的代码(易代码,COPY过来的,换成汇编应该不难吧):
============================

.子程序 模块_提升进程权限, 逻辑型, 公开
.参数 目标进程, 整数型, 可空
.参数 权限类别, 文本型, 可空

.局部变量 hdlProcessHandle, 整数型
.局部变量 hdlTokenHandle, 整数型
.局部变量 tmpLuid, LuID
.局部变量 tkp, TOKEN_PRIVILEGES
.局部变量 tkpNewButIgnored, TOKEN_PRIVILEGES

.判断开始 (是否为空 (目标进程))
    hdlProcessHandle = API_取当前进程伪句柄 ()
.否则
    hdlProcessHandle = 目标进程

API_OpenProcessToken (hdlProcessHandle, 40, hdlTokenHandle)
API_LookupPrivilegeValue (“”, 权限类别, tmpLuid)
tkp.PrivilegeCount = 1
tkp.lowpart = tmpLuid.lowpart
tkp.highpart = tmpLuid.highpart
tkp.Attributes = 2
返回 (API_AdjustTokenPrivileges (hdlTokenHandle, 0, tkp, 28, tkpNewButIgnored, 0))

===============================

权限类别 :SE_BACKUP_NAME,SE_RESTORE_NAME,SE_SHUTDOWN_NAME(关机),SE_DEBUG_NAME(调试

============================================================

这样就可以打开几乎所有非内核的程序,然后用VirtualAllocEx在这个进程内

申请一快内存空间,用WriteProcessMemory把替代API的子程序的所有字节数据写

到申请的内存空间,然后用本文的方法即可,只不过把替代地址换成申请的空间地

址即可,另外可能一些数据也可以启动器写入后再进行修改

难点就是要把子程序用字节数据写出来,其实也不是很难,有OD这样的调试器在,没有什么办不成的
雪    币: 578
活跃值: 活跃值 (31)
能力值: ( LV9,RANK:780 )
在线值:
发帖
回帖
粉丝
非安全 活跃值 17 2006-9-9 17:45
14
0
最初由 yxt 发布
如何备份函数呢?希望楼主讲下这个。


我是这样的,备份函数所在的整个DLL
psapi.dll里的GetModuleInformation可以取得模块信息

DLL的基地址,大小等都可以取得

ReadProcessMemory读出整个DLL数据

用VirtualAllocEx申请内存空间,WriteProcessMemory写入

备份API地址=备份空间地址 + 原函数地址 - 原DLL基地址
雪    币: 111
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
无奈无赖 活跃值 2006-10-3 03:43
15
0
国庆放假了终天有时间来学习下了.

将楼主的代码改了下,用来HOOK MessageBoxA,结果却是有些能够HOOK成功,有些又不行...明明程序里用的是MessageBoxA却无法成功HOOK.真是有点奇怪,不知道错在哪里.楼主有空的帮我看看,压缩包里test.exe是罗云彬书中第一个编译的例子,我把其中的代码改为调用MessageBoxA来显示对话框,却不能成功HOOK.其它进程,如winrar的消息框就能HOOK.怪事怪事,不知道是为什么.

好像是有窗口的程序就能HOOK成功,没有窗口的就不能HOOK成功,照理说,WH_GETMESSAGE钩子只要程序一创建就应该能够成功安装钩子的啊.

节省论坛空间,不上传附件.下载地下:
http://www.bsqing.com/hookdll.rar
雪    币: 301
活跃值: 活跃值 (35)
能力值: ( LV13,RANK:330 )
在线值:
发帖
回帖
粉丝
HSQ 活跃值 8 2006-10-3 04:52
16
0
不错,支持!
雪    币: 661
活跃值: 活跃值 (620)
能力值: ( LV9,RANK:190 )
在线值:
发帖
回帖
粉丝
qyc 活跃值 4 2006-11-17 23:42
17
0
认真学习 超过 kanxue
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
tongshi 活跃值 2006-11-19 12:53
18
0
<1>首先改写API首字节,要实现原API的功能需要调用API时先还原被修改的字节,然后再调用原API,调用完后再改回来,

这段文字我读的怎么这么别扭?究竟要表达哪种意思?请再说清楚点。
雪    币: 149
活跃值: 活跃值 (10)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
warshon 活跃值 6 2006-11-22 15:50
19
0
不错,支持一下
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
duchuan 活跃值 2006-11-23 12:31
20
0
顶啊,希望好好学习一下。
雪    币: 450
活跃值: 活跃值 (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cnnets 活跃值 2006-11-23 23:45
21
0
E语言??
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
baqiang 活跃值 2006-11-24 09:48
22
0
好东西  收藏了

楼主,我想要一些汇编不复杂实现ring0的方法 有办法吗
雪    币: 209
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
我爱软件 活跃值 2006-11-30 21:18
23
0
强,学习了.谢谢分享!!!
游客
登录 | 注册 方可回帖
返回