移除 API Hook

Servlet的历史与规范 一、Servlet历史 1. Servlet的由来 背景 上世纪90年代,随着Internet和浏览器的飞速发展,基于浏览器的B/S模式随之火爆发展起来。 最初,用户使用浏览器向WEB服务器发送的请求都是请求静态的资源,比如html、css等。 但是可以想象:根据用户请求的不同动态的处理并返回资源是理所当然必须的要求。 CGI 必须要满足上述需求,所以CGI(Common Gat... 阅读详情
=========================
原文
=========================
对付API-splicing的一种简单方法 [PSI_H] By: greatdong

对于拦截API函数通常使用一种叫splicing的方法。此法的本质就是用JMP指令替换函数起始处的5个字节,将控制权传递给拦截程序。这种技术广泛应用于个人防火墙中,以防木马程序将自己的代码注入到其它可访问网络进程的地址空间中。然而,木马程序作者们可以采用不同的技术来穿透防火墙。比如说很流行的防火墙Agnitum Outpost的第三版就可以轻松绕过(详见MS-REM的文章《使用inject绕过防火墙》)。然而设计者们已经对自己的劳动结晶施以了巫术,Outpost 4.0已经能可靠地(?)对付这种方法了。但是如果这种保护绕不过去,那为什么不试着把它拿下呢?

首先脑子里想到的是,使用LoadLibrary/GetProcAddress函数来获取被拦截函数的原始代码,之后用它在内存里替换掉以前的代码,这样就摘掉了对函数的HOOK。因为调用LoadLibrary将返回指向已加载模块的指针,所以必须将文件拷贝并加载此拷贝。下面的代码去除了对ZwWriteVirtualMemory函数的拦截:

程序代码 程序代码

   // 将NTDLL.DLL文件拷入TEMP文件夹

       char szTemp[MAX_PATH];

       GetTempPath(MAX_PATH, szTemp);

       strcat(szTemp, "ntdll2.dll");

       CopyFile("C:/Windows/System32/ntdll.dll", szTemp, TRUE);
       
       // 取得指向原始函数的指针
   HMODULE hMod = LoadLibrary(szTemp);
       void* ptr_orig = GetProcAddress(hMod, "ZwWriteVirtualMemory");    
       
       // 取得指向当前函数的指针
       void* ptr_new = GetProcAddress (LoadLibrary("ntdll.dll"), "ZwWriteVirtualMemory");
       
       // 设置内存访问权限
       DWORD dwOldProtect;
       VirtualProtect(ptr_new, 10, PAGE_EXECUTE_READWRITE, &dwOldProtect);

       // 替换函数的前10个(为保险起见)字节
       memcpy(ptr_new, ptr_orig, 10);
       
       FreeLibrary(hMod);
       DeleteFile(szTemp);
此后,为了在其它进程地址空间中执行自己的代码,可以使用经典的CreateRemoteThread。顺便说一句,Outpost对这个函数也进行了拦截,但是,在别的进程里创建线程是绝对可以的。

尽管这里给出的摘除HOOK的方法完全奏效,但需要加载新的dll模块,这可能会引起防火墙的暴怒。我所认为的更为优雅的办法就是只需从文件中读取所需要的字节。下面这个函数的代码恢复了API的原始的起始部分。

[Copy to clipboard] [ - ]CODE:
   bool RemoveFWHook(char* szDllPath, char* szFuncName) // szDllPath为DLL的完整路径 !
   {
       // 取得指向函数的指针
       HMODULE lpBase = LoadLibrary(szDllPath);
       LPVOID lpFunc = GetProcAddress(lpBase, szFuncName);
       if(!lpFunc)
           return false;
       // 取得RVA
       DWORD dwRVA = (DWORD)lpFunc-(DWORD)lpBase;

       // 将文件映射入内存
       HANDLE hFile = CreateFile(szDllPath,GENERIC_READ, FILE_SHARE_READ,
                           NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, NULL);
       if(INVALID_HANDLE_VALUE == hFile)
           return false;

       DWORD dwSize = GetFileSize(hFile, NULL);

       HANDLE hMapFile = CreateFileMapping(hFile, NULL, PAGE_READONLY|SEC_IMAGE, 0, dwSize, NULL);

       LPVOID lpBaseMap = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, dwSize);
       
   // 指向当前函数的指针
       LPVOID lpRealFunc = (LPVOID)((DWORD)lpBaseMap+dwRVA);

       // 修改访问权限并拷贝
       DWORD dwOldProtect;
       BOOL bRes=true;
       if(VirtualProtect(lpFunc, 10, PAGE_EXECUTE_READWRITE, &dwOldProtect))
       {
           memcpy(lpFunc, lpRealFunc, 10);
       }else{
           bRes=false;
       }

       UnmapViewOfFile(lpBaseMap);

       CloseHandle(hMapFile);
       CloseHandle(hFile);

       return bRes;

}

注意CreateFileMapping函数的调用,参数SEC_IMAGE指明了文件将作为可执行文件映射入内存,这就使我们能够找到PE首部并计算文件偏移量。然而,以上示例是有缺陷的——用户可以禁止读取系统文件,除此之外,软件设计者还可以patch磁盘文件(尽管可能性很小)。对付的方法还是有的,可以基址作为标志函数起始的label。例如,在所有我研究过的Windows XP(SP0-SP2、RU和MUI)里,ZwWriteVirtualMemory起始处都是字节:

   B8 15 01 00 00 

其对应的汇编助记符为

   mov  eax, 00000115

为了识别label,无需在磁盘文件上做手脚,因为ntdll.dll在distribution里是不设防的。当然使用静态label并不能保证相容性,但这是防范拦截的最好办法。

使用上面所讲的技术可以达到十分通用的效果——比如防范调试器。比如说,我们的应用程序从注册表读取lisense键值,而且我们不想此举被黑客监视。为了恢复函数的原始代码以处理注册表,我们将断点(opcode为0xCC)做掉。老实说,如果黑客在函数的尾部施此伎俩,而我们只恢复起始部分,这还真就不灵了。所以,最好一下恢复整个code section。


Anti-anti-splicing

要想对付类似的anti-splicing的方法,developers可以对ZwProtectVirtualMemory函数进行处理。拦截了这个函数就能控制对内存访问参数的修改,我们也就因此而不能向所需的地址里进行写入。然而,如果建立了前面提到的函数起始基址的话,还是有办法对付的。

本文的配套程序是向Internet Explorer注入shellcode的例子。

[C] PSI_H

董岩 译
http://greatdong.blog.edu.cn



=========================
由于偷懒,所有变量都没有声明。
=========================

程序代码 程序代码

Private Declare Function VirtualProtect _
               Lib "kernel32.dll" (ByRef lpAddress As Any, _
                                   ByVal dwSize As Long, _
                                   ByVal flNewProtect As Long, _
                                   ByRef lpflOldProtect As Long) As Long
Private Declare Function MapViewOfFile _
               Lib "kernel32.dll" (ByVal hFileMappingObject As Long, _
                                   ByVal dwDesiredAccess As Long, _
                                   ByVal dwFileOffsetHigh As Long, _
                                   ByVal dwFileOffsetLow As Long, _
                                   ByVal dwNumberOfBytesToMap As Long) As Long
Private Declare Sub CopyMemory _
               Lib "kernel32.dll" _
               Alias "RtlMoveMemory" (ByRef Destination As Any, _
                                      ByRef Source As Any, _
                                      ByVal Length As Long)
Private Declare Function CloseHandle _
               Lib "kernel32.dll" (ByVal hObject As Long) As Long
Private Declare Function UnmapViewOfFile _
               Lib "kernel32.dll" (ByRef lpBaseAddress As Any) As Long
Private Declare Function GetProcAddress _
               Lib "kernel32.dll" (ByVal hModule As Long, _
                                   ByVal lpProcName As String) As Long
Private Declare Function LoadLibrary _
               Lib "kernel32.dll" _
               Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function CreateFile _
               Lib "kernel32.dll" _
               Alias "CreateFileA" (ByVal lpFileName As String, _
                                    ByVal dwDesiredAccess As Long, _
                                    ByVal dwShareMode As Long, _
                                    ByRef lpSecurityAttributes As Long, _
                                    ByVal dwCreationDisposition As Long, _
                                    ByVal dwFlagsAndAttributes As Long, _
                                    ByVal hTemplateFile As Long) As Long
Private Declare Function CreateFileMapping _
               Lib "kernel32.dll" _
               Alias "CreateFileMappingA" (ByVal hFile As Long, _
                                           ByRef lpFileMappigAttributes As Long, _
                                           ByVal flProtect As Long, _
                                           ByVal dwMaximumSizeHigh As Long, _
                                           ByVal dwMaximumSizeLow As Long, _
                                           ByVal lpName As String) As Long
Private Declare Function GetFileSize _
               Lib "kernel32.dll" (ByVal hFile As Long, _
                                   ByRef lpFileSizeHigh As Long) As Long
Private Type SECURITY_ATTRIBUTES
   nLength As Long
   lpSecurityDescriptor As Long
   bInheritHandle As Long
End Type
Private Const FILE_ATTRIBUTE_NORMAL As Long = &H80
Private Const SECTION_MAP_READ As Long = &H4
Private Const FILE_MAP_READ As Long = SECTION_MAP_READ
Private Const FILE_SHARE_READ As Long = &H1
Private Const GENERIC_READ As Long = &H80000000
Private Const OPEN_EXISTING As Long = 3
Private Const PAGE_EXECUTE_READWRITE As Long = &H40
Private Const PAGE_READONLY As Long = &H2
Private Const SEC_IMAGE As Long = &H1000000
Private Const INVALID_HANDLE_VALUE As Long = -1
Private Declare Function OpenProcess _
               Lib "kernel32.dll" (ByVal dwDesiredAccess As Long, _
                                   ByVal bInheritHandle As Long, _
                                   ByVal dwProcessId As Long) As Long
Private Const PROCESS_ALL_ACCESS As Long = (&HFFF)

Public Function RemoveFWHook(szDllPath As String, _
                            szFuncName As String) As Boolean   ' szDllPath为DLL的完整路径!
   ' 取得指向函数的指针
   lpBase = LoadLibrary(szDllPath)
   lpFunc = GetProcAddress(lpBase, szFuncName)

   If lpFunc = 0 Then RemoveFWHook = False
   ' 取得RVA
   dwRVA = lpFunc - lpBase
   ' 将文件映射入内存
   hFile = CreateFile(szDllPath, GENERIC_READ, FILE_SHARE_READ, ByVal 0&, _
           OPEN_EXISTING, 0, 0)

   If hFile = INVALID_HANDLE_VALUE Then
       RemoveFWHook = False
       Exit Function
   End If

   dwSize = GetFileSize(hFile, 0)
   hMapFile = CreateFileMapping(hFile, 0, PAGE_READONLY or SEC_IMAGE, 0, dwSize, _
           vbNullString)
   lpBaseMap = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, dwSize)
   ' 指向当前函数的指针
   lpRealFunc = lpBaseMap + dwRVA
   ' 修改访问权限并拷贝
   bRes = True

   If (VirtualProtect(lpFunc, 10, PAGE_EXECUTE_READWRITE, dwOldProtect)) Then
       CopyMemory lpFunc, lpRealFunc, 10
   Else
       bRes = False
   End If

   UnmapViewOfFile (lpBaseMap)
   CloseHandle (hMapFile)
   CloseHandle (hFile)
   RemoveFWHook = bRes
End Function


这个函数的使用很简单,传一个 DLL 名字和一个函数名字即可。
注意,VB中的函数名不等于实际的函数名。一般实际函数名都会有 A 或者 W 后缀来区分 ANSI 和 Unicode 版本的 API。
例如
程序代码 程序代码

Public Declare Function LoadLibrary _
               Lib "kernel32.dll" _
               Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long

实际函数名在 Alias 关键字后面,也就是 LoadLibraryA。如果没有这个关键字,那说明使用的就是实际名字。

示例:
程序代码 程序代码

MessageBox 0, RemoveFWHook(Environ$("SystemRoot") & "/System32/user32.dll", "MessageBoxA"), "Hello!", MB_OK

这样就移除了对 MwssageBoxA 的挂钩,同时调用此函数弹出一个对话框。

此方法对修改 IAT 的 Hook 无效。绕过这种钩子的方法是 GetProcAddress 或者 LoadLibrary + GetModuleHandle。 
 
可以安全摘除钩子的minhook源代码 对minhook进行改进,可以对同一函数进行多次挂钩,可以按任意顺序摘除钩子,而不影响其他钩子的运行,不影响被挂钩程序的稳定性。 立即下载

相关推荐

Vue3+Element Plus:构建现代化后台管理系统的核心布局实践

本文详细介绍了使用Vue3和Element Plus构建现代化后台管理系统的核心布局实践。从开发环境搭建到核心布局设计,再到动态菜单与路由集成,提供了完整的解决方案和优化技巧。特别适合需要快速开发高效、响应式后台系统的开发者,通过实战案例展示了如何提升开发效率和系统性能。

weixin_28309723的博客 458

对付API-splicing的一种简单方法

 对于拦截API函数通常使用一种叫splicing的方法。此法的本质就是用JMP指令替换函数起始处的5个字节,将控制权传递给拦截程序。这种技术广泛应用于个人防火墙中,以防木马程序将自己的代码注入到其它可访问网络进程的地址空间中。然而,木马程序作者们可以采用不同的技术来穿透防火墙。比如说很流行的防火墙Agnitum Outpost的第三版就可以轻松绕过(详见MS-REM的文章《使用inject绕过防

1038

opencode 完全指南:终端AI编程助手的安装、模型配置与实战

在AI编程助手快速迭代的当下,开发者对终端环境下的自动化编码需求愈发强烈。以自然语言驱动代码修改、命令执行与测试验证,已成为提升工程效率的重要方向。这类工具普遍遵循模型无关的设计原则,通过兼容OpenAI格式的接口接入多种大模型,并借助多会话管理、Skills、Memory等机制实现可审查、可干预的闭环流程。从安装配置到日常使用,再到apihub网关与免费模型的接入,终端AI助手在代码审查、跨文件重构、浏览器自动化验证等场景中展现出独特价值。本文聚焦opencode这一开源CLI工具,详细拆解其核心定位、模

weixin_33868027的博客 417

API 钩子获取窗口的关闭消息

这里我们通过 拦截通用处理函数 DefWindowProc 并过滤 SC_CLOSE 消息实现拦截窗口人为关闭操作,并弹出问询是否关闭的对话框,从而防止窗口被立即关闭。(如果不是编译好的程序,可以直接在窗口的回调函数中直接处理这条消息)

溡漪幽博客 894

AD20/Altium designer——如何进行DRC检查、冲突的错误如何改正

对于一个画完的PCB,我们常常需要进行DRC检查,确保板子的电器连接及制作工艺在设定规则的范围内,本篇将介绍如何对PCB进行后期DRC检查处理,确保电路板出现不必要错误。 1.DRC检查入口 2.DRC设置 3.错误分析 对于错误的内容,依据个人实际情况不同,其出现的原因都是因为与设计规则中的设定标准冲突,这里按遇到的错误进行修改讲解,其他错误同理。 4.常见错误分析及解决方法 (1) 解决方法:将未连接网络连接(...

嵌入式创客工坊的博客 5万+

【项目案例】前后端分离项目 【Web图书管理系统 】SpringBoot + Vue + Element UI + Mysql

Web图书管理系统

激流丶的博客 5397

python api框架 hook_5 分钟读懂Python 中的 Hook 钩子函数

1. 什么是Hook经常会听到钩子函数(hook function)这个概念,最近在看目标检测开源框架mmdetection,里面也出现大量Hook的编程方式,那到底什么是hook?hook的作用是什么?what is hook ?钩子hook,顾名思义,可以理解是一个挂钩,作用是有需要的时候挂一个东西上去。具体的解释是:钩子函数是把我们自己实现的hook函数在某一时刻挂接到目标挂载点上。hook...

weixin_39686353的博客 856

I2C通信——时序图

本文用逻辑分析仪抓取主机I2C通信的时序图,抓取的过程是读某个寄存器的值。

weixin_43772611的博客 7353

Hook技术之API拦截(API Hook)

Inline Hook就是修改

bobopeng 3万+

由JavaScript版迷宫游戏引出Java版迷宫地图生成器

Java案例:迷宫地图生成器 一、引入问题 本期18软件1班网页脚本实训项目是完成一个JavaScript版迷宫游戏。 迷宫地图是如何生成的呢?很简单,将一个正方形区域等分为若干行与若干列,比如25行25列,这样就有625个单元格,用一个二维数组map[25][25]就可以保存625个单元格信息,map[i][j] = 1表示该单元格要绘制砖,而map[i][j] = 0表示该单元格不绘制砖。 ...

howard2005的专栏 1472

FPGA工程师面试试题集锦11~20

时钟抖动是指芯片的某一个给定点上时钟周期发生暂时性变化,也就是说时钟周期在不同的周期上可能加长或缩短。它是一个平均值为0的平均变量。

FPGA/MATLAB学习教程/源码/项目合作开发 678

简述API HOOK技术及原理

我们观察内核代码的时候,很多时候一些函数调用都初始化的时候设置成回调函数的,例如上一个例子读取文件目录,那么proc有自己独有的读取目录处理函数,相对于的ext4、ceph、hpfs等等文件系统都有自己的处理函数,那么getdents的时候如何能调用到正确的处理函数呢?而在应用程序建立套接字的时候选择了v4还是v6,都是同一个系统调用(sys_socket),只是传入的参数是不一样的,那么内核根据传参的差异,灵活的选择使用不同函数来初始化套接字,不同的函数又使用各自对应的结构体来初始化后续的调用函数。

bing1564的博客 3309

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

我未翻译完的一段 Servlet 3.1 API 规范之“部署描述符”

 //---------------------------------------------------------------------------------------------////-- 原本是响应某童鞋的号召才翻译此文的,不过今天打开草稿箱正准备继续翻译时,       ---////-- 发现开涛童鞋已经发布了,后续内容翻译建议大家参考开涛童鞋的文章吧!          ...

咖啡代码-周庆芳 120

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Servlet规范之部署描述符

Servlet规范之部署描述符

有问题的请私信或关注v【技术印记】留言 755

servlet3.1规范翻译:第14章 部署描述符

第14章 部署描述符 本章指定的Java™Servlet规范3.0版要求Web容器支持部署描述符。部署描述符表达了应用开发人员、应用集成人员和Web应用部署人员之间的元素和配置信息。 对于JavaServlet 2.4和以后的版本,部署描述符在XML模式文档中定义。 为了向后兼容到2.2版本的API编写的应用程序,Web容器也需要支持2.2版本的部署描述符。为了向后兼容2.3版本的API编写

痴人说梦 4067

java web开发之 servlet3.1规范翻译-部署描述文件(14)

部署描述文件 本章指定的Java™Servlet规范3.0版要求Web容器支持部署描述文件。部署描述文件表达了应用开发人员、应用集成人员和Web应用部署人员之间的元素和配置信息。 对于Java Servlet 2.4和以后的版本,部署描述文件在XML模式文档中定义。 为了向后兼容到2.2版本的API编写的应用程序,Web容器也需要支持2.2版本的部署描述文件。为了向后兼容2...

xiaoliuliu2050的专栏 982

servlet3.1规范翻译:前言

应朋友之邀(博客地址:http://jinnianshilongnian.iteye.com/),一起翻译servlet3.1规范,本人不才,英语水平有限,勉强而为之。翻译过程中有很多地方把握不准确,现将各章翻译情况贴出来(很多章节是朋友翻译,为方便阅读,全部贴出来,特此声明),希望大家指出来,一起学习。英文版的规范可到本人发布的资源中下载,也可到规范网站自行下载(http://jcp.org/e

痴人说梦 2193

Servlet3.1API 学习合集

历时两个月完成servlet 3.1学习和翻译,希望对您有帮助,以下是文章汇总 1、Servlet3.1API 学习合集 1、Servlet3.1规范(第一篇) 2、Servlet接口(第二篇) 3、Servlet 请求(第三篇) 4、ServletContext接口(第四篇) 5、Servlet Response(第五篇) 6、Servlet 过滤器 (第六篇) 7、Servlet的Session(第七篇) 8、Servlet注解和可插拔性(第八篇) 9、Servlet请求分发(第九篇) 10、Ser.

往前的娘娘 316

java web开发之 servlet3.1规范翻译-概览(2)

Servlet3.1(JSR340)规范目前处于早期草案阶段,目标是在Java EE 7或更高平台。Servlet3.0(JSR 315)已经包含在Java EE 6平台。具体请参考本规范网站:http://jcp.org/en/jsr/detail?id=340 概览 1.1什么是Servlet? Servlet是基于Java技术的web组件,容器托管的,用于生成动态内容。像...

xiaoliuliu2050的专栏 199

java 可插拔注解_servlet3.1规范翻译:第8章 注解和可插拔性

servlet3.1规范翻译:第8章 注解和可插拔性 .这是Servlet3.0的新特性之一:这是Servlet3.0的新特性之一:通过Annotation(注解)配置Servlet之前版本的Servlet配置是需要在web.xml中配置:?servlet>? servlet-name>?servler-class>?load-on-startup>?init-para...

weixin_31464715的博客 230

Servlet规范之概览

Servlet规范之预览

有问题的请私信或关注v【技术印记】留言 586

Servlet规范之安全

Servlet规范之安全

有问题的请私信或关注v【技术印记】留言 1107

Servlet3.1规范翻译——前言

      Servlet3.1(JSR340)规范目前处于早期草案阶段,目标是在Java EE 7或更高平台。 Servlet3.0(JSR 315)已经包含在Java EE 6平台。具体请参考本规范网站:http://jcp.org/en/jsr/detail?id=340   前言 此文档是Java Servlet规范,版本:3.1。此文档描述了Java Servlet API...

jinnianshilongnian的专栏 225

Servlet3.1规范翻译——概览 (转)

Servlet3.1规范翻译——概览 (转自:http://jinnianshilongnian.iteye.com/blog/1722087)   Servlet3.1(JSR340)规范目前处于早期草案阶段,目标是在Java EE 7或更高平台。 Servlet3.0(JSR 315)已经包含在Java EE 6平台。具体请参考本规范网站:http://jcp.org/en/jsr/

wakata随记 981

Servlet规范之过滤器Filter

Servlet规范之过滤器Filter

有问题的请私信或关注v【技术印记】留言 1027
上一篇: 一段搜索EPROCESS来列进程的代码
下一篇: 熊猫烧香病毒主要代码分析
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值