分类

类型:
不限 游戏开发 计算机程序开发 Android开发 网站开发 笔记总结 其他
评分:
不限 10 9 8 7 6 5 4 3 2 1
原创:
不限
年份:
不限 2018 2019

技术文章列表

  • 磁盘盘符隐藏并访问隐藏磁盘的文件数据 精华

    背景之前,帮一个小伙伴开发了一个程序,这个程序就是对磁盘盘符进行隐藏与显示。也就是说,我们打开资源管理器,在资源管理器中隐藏指定磁盘,不显示在界面上。而且,我们还可以使用程序对这个隐藏后的磁盘文件数据进行读写。
    这个程序的实现原理,主要是删除和创建卷加载点实现来实现的。其中,我们给出两种方法来创建隐藏磁盘,分别是使用WIN32 API 函数 DefineDosDeivce 以及 SetVolumeMountPoint 来实现。现在,我就把实现过程整理成文档,分享给大家。
    函数介绍QueryDosDevice 函数
    获取有关MS-DOS设备名称的信息。 该功能可以获得特定MS-DOS设备名称的当前映射。 该功能还可以获取所有现有MS-DOS设备名称的列表。
    函数声明
    DWORD WINAPI QueryDosDevice( _In_opt_ LPCTSTR lpDeviceName, _Out_ LPTSTR lpTargetPath, _In_ DWORD ucchMax);
    参数

    lpDeviceName [in,optional]指定查询目标的MS-DOS设备名称字符串。设备名称不能有尾随的反斜杠;例如,使用“C:”,而不是“C:\”。此参数可以为NULL。在这种情况下,QueryDosDevice功能将将所有现有的MS-DOS设备名称的列表存储到lpTargetPath指向的缓冲区中。lpTargetPath [out]指向将接收查询结果的缓冲区的指针。该函数用一个或多个以null结尾的字符串填充此缓冲区。最后以空值终止的字符串后跟一个额外的NULL。如果lpDeviceName不为NULL,则该函数将检索有关由lpDeviceName指定的特定MS-DOS设备的信息。存储在缓冲区中的第一个以null结尾的字符串是设备的当前映射。其他以null结尾的字符串表示设备的未删除的先前映射。如果lpDeviceName为NULL,则该函数将检索所有现有MS-DOS设备名称的列表。存储在缓冲区中的每个以null结尾的字符串都是现有MS-DOS设备的名称,例如\ Device \ HarddiskVolume1或\ Device \ Floppy0。ucchMax [in]lpTargetPath指向的缓冲区中可以存储的最大TCHAR数。
    返回值

    如果函数成功,则返回值是存储在lpTargetPath指向的缓冲区中的TCHAR数。如果函数失败,返回值为零。 要获取扩展错误信息,请调用GetLastError。如果缓冲区太小,则该函数失败,最后一个错误代码为ERROR_INSUFFICIENT_BUFFER。

    DefineDosDevice 函数
    定义,重新定义或删除MS-DOS设备名称。
    函数声明
    BOOL WINAPI DefineDosDevice( _In_ DWORD dwFlags, _In_ LPCTSTR lpDeviceName, _In_opt_ LPCTSTR lpTargetPath);
    参数

    dwFlags [in]DefineDosDevice功能的可控方面。 此参数可以是以下值中的一个或多个:



    VALUE
    MEANING




    DDD_EXACT_MATCH_ON_REMOVE
    如果此值与DDD_REMOVE_DEFINITION一起指定,则该函数将使用完全匹配来确定要删除的映射。 使用此值可确保不删除未定义的内容


    DDD_NO_BROADCAST_SYSTEM
    不要广播WM_SETTINGCHANGE消息。 默认情况下,该消息被广播以通知shell和应用程序的更改


    DDD_RAW_TARGET_PATH
    使用lpTargetPath字符串。 否则,它将从MS-DOS路径转换为路径


    DDD_REMOVE_DEFINITION
    删除指定设备的指定定义。 要确定要删除的定义,该函数将会遍历设备的映射列表,查找与此设备关联的每个映射的前缀的lpTargetPath的匹配。 匹配的第一个映射是删除的映射,然后该函数返回。如果lpTargetPath为NULL或指向NULL字符串的指针,则该函数将删除与设备关联的第一个映射,并弹出最近推送的映射。 如果没有什么可以弹出,设备名称将被删除。如果未指定此值,则由lpTargetPath参数指向的字符串将成为此设备的新映射。




    lpDeviceName [in]指向MS-DOS设备名称字符串的指针,指定功能正在定义,重新定义或删除的设备。 设备名称字符串不得有冒号作为最后一个字符,除非正在定义,重新定义或删除驱动器号。 例如,驱动器C将是字符串“C:”。 在任何情况下都不允许使用尾部反斜杠(“\”)。
    lpTargetPath [in]指向将实现此设备的路径字符串的指针。 字符串是一个MS-DOS路径字符串,除非指定了DDD_RAW_TARGET_PATH标志,在这种情况下,此字符串是一个路径字符串。

    返回值

    如果函数成功,则返回值不为零。如果函数失败,返回值为零。 要获取扩展错误信息,请调用GetLastError。

    DeleteVolumeMountPoint 函数
    删除驱动器号或安装的文件夹。
    函数声明
    BOOL WINAPI DeleteVolumeMountPoint( _In_ LPCTSTR lpszVolumeMountPoint);
    参数

    lpszVolumeMountPoint [in]要删除的驱动器号或安装的文件夹。 需要尾随的反斜杠,例如“X:\”或“Y:\ MountX \”。
    返回值

    如果函数成功,则返回值不为零。如果函数失败,返回值为零。 要获取扩展错误信息,请调用GetLastError。

    GetVolumeNameForVolumeMountPoint 函数
    检索与指定卷装入点(驱动器盘符,卷GUID路径或已装载文件夹)相关联的卷的卷GUID路径。
    函数声明
    BOOL WINAPI GetVolumeNameForVolumeMountPoint( _In_ LPCTSTR lpszVolumeMountPoint, _Out_ LPTSTR lpszVolumeName, _In_ DWORD cchBufferLength);
    参数

    lpszVolumeMountPoint [in]指向包含已安装文件夹路径(例如“Y:\ MountX \”)或驱动器盘符(例如“X:\”)的字符串的指针。 字符串必须以尾部反斜杠(’\’)结尾。lpszVolumeName [out]指向接收卷GUID路径的字符串的指针。 此路径的格式为“\?\ Volume {GUID} \”,其中GUID是用于标识卷的GUID。 如果该卷存在多个卷GUID路径,则仅返回安装管理器缓存中的第一个卷。cchBufferLength [in]输出缓冲区的长度,在TCHAR中。 缓冲区容纳最大容量GUID路径的合理大小为50个字符。
    返回值

    如果函数成功,则返回值不为零。如果函数失败,返回值为零。 要获取扩展错误信息,请调用GetLastError。

    SetVolumeMountPoint 函数
    将卷与驱动器号或另一卷上的目录相关联。
    函数声明
    BOOL WINAPI SetVolumeMountPoint( _In_ LPCTSTR lpszVolumeMountPoint, _In_ LPCTSTR lpszVolumeName);
    参数

    lpszVolumeMountPoint [in]与卷关联的用户模式路径。 这可能是驱动器号(例如“X:\”)或其他卷上的目录(例如“Y:\ MountX \”)。 字符串必须以尾部反斜杠(’\’)结尾。lpszVolumeName [in]卷的卷GUID路径。 此字符串的格式必须为“\?\ Volume {GUID} \”,其中GUID是用于标识卷的GUID。 “\?\”关闭路径解析,并作为路径的一部分被忽略,如命名卷所述。
    返回值

    如果函数成功,则返回值不为零。如果函数失败,返回值为零。 要获取扩展错误信息,请调用GetLastError。如果lpszVolumeMountPoint参数包含已安装文件夹的路径,即使目录为空,GetLastError返回ERROR_DIR_NOT_EMPTY。

    实现原理在资源管理器中隐藏磁盘显示的原理就是:把磁盘对应的卷加载点删除,这样,磁盘就没有相应的驱动器号了,就不会在资源管理器中显示。对于删除卷加载点,我们可以使用 DeleteVolumeMountPoint 函数实现。
    在资源管理器中还原回隐藏的磁盘,原理就是:重新创建磁盘的卷加载点,并未磁盘分配一个驱动器号。但是,在创建卷加载点之前,也就是在删除卷加载点之前,我们就要使用 GetVolumeNameForVolumeMountPoint 获取卷加载点对应的卷名。因为,当我们使用 SetVolumeMountPoint 函数的时候,需要用到卷名,为相应的卷名创建卷加载点,分配驱动器号。
    创建隐藏盘符,方便我们程序访问的原理是:我们为删除卷加载点的磁盘,分配一个非字母的的驱动器号,这样,磁盘在资源管理器中是不显示的。但是,我们的程序可以通过这个非字母的盘符,正常访问盘符里的文件数据,和正常的字母盘符一样访问。在此,创建一个非字母的磁盘设备,我们可以有两种实现方式,均可以达到上述所说的效果:

    使用 DefineDosDevice 函数来实现,在使用 DefineDosDevice 之前,就需要获取磁盘对应的 Dos 路径,也就是说, 在删除卷加载点之前,先调用 QueryDosDevice 函数获取磁盘对应的 Dos 路径。之后,再使用 DefineDosDevice 函数将 Dos 路径对应的磁盘创建一个非字母驱动器的路径。
    使用 SetVolumeMountPoint 函数来实现,在使用 SetVolumeMountPoint 之前,需要通过 GetVolumeNameForVolumeMountPoint 函数来获取磁盘对应的卷名。后来,我们通过 SetVolumeMountPoint 为卷名对应的磁盘分配一个非字母驱动器号的卷加载点。

    编码实现删除卷加载点,隐藏盘符// 隐藏磁卷加载点, 实现磁盘隐藏BOOL HideValume(char *pszDriver){ BOOL bRet = ::DeleteVolumeMountPoint(pszDriver); if (FALSE == bRet) { ShowError("DeleteVolumeMountPoint"); return FALSE; } return TRUE;}
    获取磁盘对应的卷名// 获取磁盘对应的卷名::GetVolumeNameForVolumeMountPoint("E:\\", szVolumeName, MAX_PATH);
    设置卷加载点,显示磁盘// 显示卷加载点, 恢复磁盘显示BOOL ShowValume(char *pszDriver, char *pszVolumeName){ /* 注意在使用SetVolumeMountPoint的时候,挂载点目录必须存在,而且必须为空目录,否则程序会运行失败 */ while (ERROR_DIR_NOT_EMPTY == ::SetVolumeMountPoint(pszDriver, pszVolumeName)) { // 更改加载盘符 pszDriver[0]++; } return TRUE;}
    使用 DefineDosDevice 创建隐藏磁盘// 创建隐藏盘符BOOL CreateHideVolume(char *lpszDosPath){ // 创建隐藏盘符,对于非字母盘符,在"我的电脑"里是不可见的,只有程序可以访问 if (::DefineDosDevice(DDD_RAW_TARGET_PATH, MY_HIDEN_DRIVER, lpszDosPath)) { return TRUE; } return FALSE;}
    删除隐藏磁盘路径// 删除 1:DeleteHideVolume(szDosPath);// 删除 2:HideValume("2:\\");
    程序测试我们在 main 函数中,调用上述封装好的函数进行测试。首先,我们先获取将要隐藏磁盘对应的卷名以及 Dos 路径。然后,我们开始删除卷加载点,实现磁盘的隐藏。接着,我们使用 DefineDosDeivce 的方法创建一个非字母驱动器路径 1:,并拷贝 520.exe 文件到非字符驱动器路径的根目录下 1:\ ,测试非字母路径能否正常访问。然后,我们使用 SetVolumeMountPoint 创建一个非字母的驱动器 2:\,并拷贝 520.exe 文件到非字符驱动器路径的根目录下 2:\ ,测试非字母路径能否正常访问。最后,我们便删除上述两种方法创建的非字母驱动器号路径,并恢复正确的磁盘路径,显示磁盘。
    int _tmain(int argc, _TCHAR* argv[]){ char szVolumeName[MAX_PATH] = { 0 }; char szDosPath[MAX_PATH] = { 0 }; // 获取磁盘对应的卷名 ::GetVolumeNameForVolumeMountPoint("E:\\", szVolumeName, MAX_PATH); // 获取磁盘路径对应的Dos路径 ::QueryDosDevice("E:", szDosPath, MAX_PATH); // 删除卷加载点来实现磁盘隐藏 HideValume("E:\\"); system("pause"); // 使用 DefineDosDevice 创建一个非字母驱动器号的磁盘路径 1: CreateHideVolume(szDosPath); system("pause"); // 复制文件到隐藏磁盘 if (FALSE == ::CopyFile("520.exe", "1:\\520__111111.exe", FALSE)) { printf("copy file error[%d].\n", ::GetLastError()); } printf("copy file ok.\n"); system("pause"); // 使用 SetVolumeMountPoint 创建一个非字母驱动器号的磁盘路径 2: ShowValume("2:\\", szVolumeName); system("pause"); // 复制文件到隐藏磁盘 if (FALSE == ::CopyFile("520.exe", "2:\\520_22222222.exe", FALSE)) { printf("copy file error[%d].\n", ::GetLastError()); } printf("copy file ok.\n"); system("pause"); // 删除 1: DeleteHideVolume(szDosPath); // 删除 2: HideValume("2:\\"); // 恢复正确磁盘路径 ShowValume("E:\\", szVolumeName); system("pause"); return 0;}
    我们以管理员权限运行程序,测试结果正确:


    总结要注意的是,程序是需要管理员或者管理员以上权限才可以正常执行。同时,也需要理解上述的两种方法实现的对隐藏磁盘数据文件的读写。理解 DefineDosDevice 和 SetVolumeMountPoint 函数的参数含义以及具体的使用方法。
    参考参考自《Windows黑客编程技术详解》一书
    2 留言 2018-12-19 21:17:03 奖励20点积分
  • 基于WinInet的HTTPS文件上传实现 精华

    背景之前写过基于WinInet的HTTPS文件下载功能的小程序了,那就顺便把HTTPS文件上传也一并写了吧,这样知识才算是比较完整了。相对于文件下载来说,文件上传过程原理也都差不多,只要注意些区别就好了。
    现在,把基于WinInet的HTTPS文件上传功能小程序的开发过程分享给大家,方便大家的参考。
    前期准备前期需要本地搭建一个测试环境,本文搭建的是一个本地的HTTPS的ASP网站,同时,使用asp写了一个接收上传数据存储为文件的小程序test1.asp。
    搭建HTTPS传输的ASP服务器,可以参考本站上写的 “使用Windows7旗舰版64位来搭建本地HTTPS测试的ASP服务器” 这一篇文章,里面详细介绍了搭建过程和注意事项。同时,也可以参考 “修改ASP网站的文件传输大小的默认限制并对限制大小进行探索” 这一篇文章,介绍的是更改ASP网站上传的文件大小的限制。
    搭建测试环境的原因,就是为了测试,才能知道文件有没有成功上传到服务器上。当然,有条件的,也可以自己在公网上搭建服务器,这样测试会更加真实。
    主要函数介绍介绍HTTPS上传文件使用到的主要的WinInet库中的API函数。
    1. InternetOpen介绍
    函数声明
    HINTERNET InternetOpen(In LPCTSTR lpszAgent,In DWORD dwAccessType,In LPCTSTR lpszProxyName,In LPCTSTR lpszProxyBypass,In DWORD dwFlags);
    参数lpszAgent指向一个空结束的字符串,该字符串指定调用WinInet函数的应用程序或实体的名称。使用此名称作为用户代理的HTTP协议。dwAccessType指定访问类型,参数可以是下列值之一:



    Value
    Meaning




    INTERNET_OPEN_TYPE_DIRECT
    使用直接连接网络


    INTERNET_OPEN_TYPE_PRECONFIG
    获取代理或直接从注册表中的配置,使用代理连接网络


    INTERNETOPEN_TYPE_PRECONFIG WITH_NO_AUTOPROXY
    获取代理或直接从注册表中的配置,并防止启动Microsoft JScript或Internet设置(INS)文件的使用


    INTERNET_OPEN_TYPE_PROXY
    通过代理的请求,除非代理旁路列表中提供的名称解析绕过代理,在这种情况下,该功能的使用



    lpszProxyName指针指向一个空结束的字符串,该字符串指定的代理服务器的名称,不要使用空字符串;如果dwAccessType未设置为INTERNET_OPEN_TYPE_PROXY,则此参数应该设置为NULL。
    lpszProxyBypass指向一个空结束的字符串,该字符串指定的可选列表的主机名或IP地址。如果dwAccessType未设置为INTERNET_OPEN_TYPE_PROXY的 ,参数省略则为NULL。
    dwFlags参数可以是下列值的组合:



    VALUE
    MEANING




    INTERNET_FLAG_ASYNC
    使异步请求处理的后裔从这个函数返回的句柄


    INTERNET_FLAG_FROM_CACHE
    不进行网络请求,从缓存返回的所有实体,如果请求的项目不在缓存中,则返回一个合适的错误,如ERROR_FILE_NOT_FOUND


    INTERNET_FLAG_OFFLINE
    不进行网络请求,从缓存返回的所有实体,如果请求的项目不在缓存中,则返回一个合适的错误,如ERROR_FILE_NOT_FOUND



    返回值成功:返回一个有效的句柄,该句柄将由应用程序传递给接下来的WinInet函数。失败:返回NULL。

    2. InternetConnect介绍
    函数声明
    HINTERNET WINAPI InternetConnect( HINTERNET hInternet, LPCTSTR lpszServerName, INTERNET_PORT nServerPort, LPCTSTR lpszUserName, LPCTSTR lpszPassword, DWORD dwService, DWORD dwFlags, DWORD dwContext);
    参数说明hInternet:由InternetOpen返回的句柄。lpszServerName:连接的ip或者主机名nServerPort:连接的端口。lpszUserName:用户名,如无置NULL。lpszPassword:密码,如无置NULL。dwService:使用的服务类型,可以使用以下

    INTERNET_SERVICE_FTP = 1:连接到一个 FTP 服务器上INTERNET_SERVICE_GOPHER = 2INTERNET_SERVICE_HTTP = 3:连接到一个 HTTP 服务器上
    dwFlags:文档传输形式及缓存标记。一般置0。dwContext:当使用回叫信号时, 用来识别应用程序的前后关系。返回值成功返回非0。如果返回0。要InternetCloseHandle释放这个句柄。

    3. HttpOpenRequest介绍
    函数声明
    HINTERNET HttpOpenRequest( _In_ HINTERNET hConnect, _In_ LPCTSTR lpszVerb, _In_ LPCTSTR lpszObjectName, _In_ LPCTSTR lpszVersion, _In_ LPCTSTR lpszReferer, _In_ LPCTSTR *lplpszAcceptTypes, _In_ DWORD dwFlags, _In_ DWORD_PTR dwContext);
    参数
    hConnect:由InternetConnect返回的句柄。
    lpszVerb:一个指向某个包含在请求中要用的动词的字符串指针。如果为NULL,则使用“GET”。
    lpszObjectName:一个指向某个包含特殊动词的目标对象的字符串的指针。通常为文件名称、可执行模块或者查找标识符。
    lpszVersion:一个指向以null结尾的字符串的指针,该字符串包含在请求中使用的HTTP版本,Internet Explorer中的设置将覆盖该参数中指定的值。如果此参数为NULL,则该函数使用1.1或1.0的HTTP版本,这取决于Internet Explorer设置的值。
    lpszReferer:一个指向指定了包含着所需的URL (pstrObjectName)的文档地址(URL)的指针。如果为NULL,则不指定HTTP头。
    lplpszAcceptTypes:一个指向某空终止符的字符串的指针,该字符串表示客户接受的内容类型。如果该字符串为NULL,服务器认为客户接受“text/*”类型的文档 (也就是说,只有纯文本文档,并且不是图片或其它二进制文件)。内容类型与CGI变量CONTENT_TYPE相同,该变量确定了要查询的含有相关信息的数据的类型,如HTTP POST和PUT。
    dwFlags:dwFlags的值可以是下面一个或者多个。



    价值
    说明




    INTERNET_FLAG_DONT_CACHE
    不缓存的数据,在本地或在任何网关。 相同的首选值INTERNET_FLAG_NO_CACHE_WRITE。


    INTERNET_FLAG_EXISTING_CONNECT
    如果可能的话,重用现有的连接到每个服务器请求新的请求而产生的InternetOpenUrl创建一个新的会话。 这个标志是有用的,只有对FTP连接,因为FTP是唯一的协议,通常在同一会议执行多个操作。 在Win 32 API的缓存一个单一的Internet连接句柄为每个HINTERNET处理产生的InternetOpen。


    INTERNET_FLAG -超链接
    强制重载如果没有到期的时间也没有最后修改时间从服务器在决定是否加载该项目从网络返回。


    INTERNET_FLAG_IGNORE_CERT_CN_INVALID
    禁用的Win32上网功能的SSL /厘为基础的打击是从给定的请求服务器返回的主机名称证书检查。 Win32的上网功能用来对付证书由匹配主机名和HTTP请求一个简单的通配符规则比较简单的检查。


    INTERNET_FLAG_IGNORE_CERT_DATE_INVALID
    禁用的Win32上网功能的SSL /厘为基础的HTTP请求适当的日期,证书的有效性检查。


    INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP
    禁用的Win32上网功能能够探测到这种特殊类型的重定向。 当使用此标志,透明的Win32上网功能允许对HTTP重定向的URL从HTTPS。


    INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS
    禁用的Win32上网功能能够探测到这种特殊类型的重定向。 当使用此标志,透明的Win32上网功能允许从HTTP重定向到HTTPS网址。


    INTERNET_FLAG_KEEP_CONNECTION
    使用保持活动语义,如果有的话,给HTTP请求连接。 这个标志是必需的微软网络(MSN),NT LAN管理器(NTLM)和其他类型的身份验证。


    INTERNET_FLAG_MAKE_PERSISTENT
    不再支持。


    INTERNET_FLAG_MUST_CACHE_REQUEST
    导致一个临时文件如果要创建的文件不能被缓存。 相同的首选值INTERNET_FLAG_NEED_FILE。


    INTERNET_FLAG_NEED_FILE
    导致一个临时文件如果要创建的文件不能被缓存。


    INTERNET_FLAG_NO_AUTH
    不尝试HTTP请求身份验证自动。


    INTERNET_FLAG_NO_AUTO_REDIRECT
    不自动处理HTTP请求重定向只。


    INTERNET_FLAG_NO_CACHE_WRITE
    不缓存的数据,在本地或在任何网关。


    INTERNET_FLAG_NO_COOKIES
    不会自动添加Cookie标头的请求,并不会自动添加返回的Cookie的HTTP请求的Cookie数据库。


    INTERNET_FLAG_NO_UI
    禁用cookie的对话框。


    INTERNET_FLAG_PASSIVE
    使用被动FTP语义FTP文件和目录。


    INTERNET_FLAG_RAW_DATA
    返回一个数据WIN32_FIND_DATA结构时,FTP目录检索信息。 如果这个标志,或者未指定代理的电话是通过一个CERN,InternetOpenUrl返回的HTML版本的目录。


    INTERNET_FLAG_PRAGMA_NOCACHE
    强制要求被解决的原始服务器,即使在代理缓存的副本存在。


    INTERNET_FLAG_READ_PREFETCH
    该标志目前已停用。


    INTERNET_FLAG_RELOAD
    从导线获取数据,即使是一个本地缓存。


    INTERNET_FLAG_RESYNCHRONIZE
    重整HTTP资源,如果资源已被修改自上一次被下载。 所有的FTP资源增值。


    INTERNET_FLAG_SECURE
    请确保在使用SSL或PCT线交易。 此标志仅适用于HTTP请求。



    dwContext:OpenRequest操作的上下文标识符。

    4. WinHttpAddRequestHeaders介绍
    函数声明
    BOOL WINAPI WinHttpAddRequestHeaders( In HINTERNET hRequest, In LPCWSTR pwszHeaders, In DWORD dwHeadersLength, In DWORD dwModifiers);
    作用
    添加一个HTTP的请求头域。
    参数

    hRequest [in]一个HINTERNET句柄通过调用WinHttpOpenRequest返回。pwszHeaders [in]请求的头域字符串,每个头域(多个头域以)使用回车换行(\r\n)结束dwHeadersLength [in]无符号长整型变量,指向pwszHeaders的长度,如果该参数为(ulong)-1L时,自动以”/0”结束来计算pwszHeaders的长度。dwModifiers [in]头域的修改模式。包括如下值:WINHTTP_ADDREQ_FLAG_ADD 添加一个头域,如果头域存在时值将被新添加的值替换。与WINHTTP_ADDREQ_FLAG_REPLAC一起使用WINHTTP_ADDREQ_FLAG_ADD_IF_NEW 添加一个不存在头域,如果该头域存在则返回一个错误。WINHTTP_ADDREQ_FLAG_COALESCE 将同名的头域进行合并。WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA 合并同名的头域,值使用逗号隔开。WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON 合并同名的头域,值使用分号隔开。WINHTTP_ADDREQ_FLAG_REPLACE 替换和删除一个头域,如果值为空,则删除,否则被替换。
    返回值
    返回值为假时,使用GetLastError来得到错误信息。err code:ERROR_WINHTTP_INCORRECT_HANDLE_STATE 请求不能被执行,因为句柄的状态不正确ERROR_WINHTTP_INCORRECT_HANDLE_TYPE 请求的句柄类型不正确ERROR_WINHTTP_INTERNAL_ERROR 内部错误ERROR_NOT_ENOUGH_MEMORY 没有足够的内存来完成操作。

    5. InternetWriteFile介绍
    函数声明
    BOOL InternetWriteFile( __in HINTERNET hFile,__out LPVOID lpBuffer,__in DWORD dwNumberOfBytesToRead,__out LPDWORD lpdwNumberOfBytesRead);
    参数

    hFile[in]
    由InternetOpenUrl,FtpOpenFile, 或HttpOpenRequest函数返回的句柄.
    lpBuffer[out]
    缓冲器指针
    dwNumberOfBytesToRead[in]
    欲写入数据的字节量。
    lpdwNumberOfBytesRead[out]
    接收写入字节量的变量。该函数在做任何工作或错误检查之前都设置该值为零

    返回值成功:返回TRUE,失败,返回FALSE

    程序设计原理该部分讲解下程序设计的原理以及实现的流程,让大家有个宏观的认识。原理是:

    首先,使用 InternetCrackUrl 函数分解URL,从URL中提取网站的域名、路径以及URL的附加信息等。关于 InternetCrackUrl 分解URL的介绍和实现,可以参考 “URL分解之InternetCrackUrl” 这篇文章
    使用 InternetOpen 建立会话,获取会话句柄
    使用 InternetConnect 与网站建立连接,获取连接句柄
    设置HTTPS的访问标志,使用 HttpOpenRequest 打开HTTP的“POST”请求
    构造请求信息头字符串,并使用 HttpAddRequestHeaders 附加请求信息头
    使用 HttpSendRequestEx发送访问请求,同时根据出错返回的错误码,来判断是否设置忽略未知的证书颁发机构,以确保能正常访问HTTPS网站
    使用 InternetWriteFile 上传数据
    数据上传完毕之后,使用 HttpEndRequest 函数结束请求
    关闭句柄,释放资源

    其中,需要注意的是第 5 步,这一步是与HTTPS文件下载不同的地方,这一步需要构造请求信息头,所以构造请求信息头的字符串的时候,一定要严格按照协议格式去构造。例如回车换行、空格之类的。
    编程实现1. 导入WinInet库#include <WinInet.h>#pragma comment(lib, "WinInet.lib")
    2. HTTPS文件上传编程实现// 数据上传// 输入:上传数据的URL路径、上传数据内容、上传数据内容长度BOOL Https_Upload(char *pszUploadUrl, BYTE *pUploadData, DWORD dwUploadDataSize){ // INTERNET_SCHEME_HTTPS、INTERNET_SCHEME_HTTP、INTERNET_SCHEME_FTP等 char szScheme[MAX_PATH] = { 0 }; char szHostName[MAX_PATH] = { 0 }; char szUserName[MAX_PATH] = { 0 }; char szPassword[MAX_PATH] = { 0 }; char szUrlPath[MAX_PATH] = { 0 }; char szExtraInfo[MAX_PATH] = { 0 }; ::RtlZeroMemory(szScheme, MAX_PATH); ::RtlZeroMemory(szHostName, MAX_PATH); ::RtlZeroMemory(szUserName, MAX_PATH); ::RtlZeroMemory(szPassword, MAX_PATH); ::RtlZeroMemory(szUrlPath, MAX_PATH); ::RtlZeroMemory(szExtraInfo, MAX_PATH); // 分解URL if (FALSE == Https_UrlCrack(pszUploadUrl, szScheme, szHostName, szUserName, szPassword, szUrlPath, szExtraInfo, MAX_PATH)) { return FALSE; } // 数据上传 HINTERNET hInternet = NULL; HINTERNET hConnect = NULL; HINTERNET hRequest = NULL; DWORD dwOpenRequestFlags = 0; BOOL bRet = FALSE; DWORD dwRet = 0; unsigned char *pResponseHeaderIInfo = NULL; DWORD dwResponseHeaderIInfoSize = 2048; BYTE *pBuf = NULL; DWORD dwBufSize = 64 * 1024; BYTE *pResponseBodyData = NULL; DWORD dwResponseBodyDataSize = 0; DWORD dwOffset = 0; do { // 建立会话 hInternet = ::InternetOpen("WinInetPost/0.1", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); if (NULL == hInternet) { Https_ShowError("InternetOpen"); break; } // 建立连接 hConnect = ::InternetConnect(hInternet, szHostName, INTERNET_DEFAULT_HTTPS_PORT, szUserName, szPassword, INTERNET_SERVICE_HTTP, 0, 0); if (NULL == hConnect) { Https_ShowError("InternetConnect"); break; } // 打开并发送HTTP请求 dwOpenRequestFlags = INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP | INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_NO_AUTH | INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_NO_UI | // HTTPS SETTING INTERNET_FLAG_SECURE | INTERNET_FLAG_IGNORE_CERT_CN_INVALID | INTERNET_FLAG_RELOAD; if (0 < ::lstrlen(szExtraInfo)) { // 注意此处的连接 ::lstrcat(szUrlPath, szExtraInfo); } hRequest = ::HttpOpenRequest(hConnect, "POST", szUrlPath, NULL, NULL, NULL, dwOpenRequestFlags, 0); if (NULL == hRequest) { Https_ShowError("HttpOpenRequest"); break; } // 附加 请求头(可以写也可以不写, 不写的话直接发送数据也可以, 主要是看服务端和客户端的数据传输约定; 批量发送的时候要用到) char szBoundary[] = "-------------MyUploadBoundary"; // 数据边界 char szRequestHeaders[MAX_PATH] = { 0 }; ::RtlZeroMemory(szRequestHeaders, MAX_PATH); ::wsprintf(szRequestHeaders, // 构造 请求头数据信息 "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/xaml+xml,*/*\r\n" "Accept-Encoding: gzip, deflate\r\n" "Accept-Language: zh-cn\r\n" "Content-Type: multipart/form-data; boundary=%s\r\n" "Cache-Control: no-cache\r\n\r\n", szBoundary); bRet = ::HttpAddRequestHeaders(hRequest, szRequestHeaders, ::lstrlen(szRequestHeaders), HTTP_ADDREQ_FLAG_ADD); if (FALSE == bRet) { Https_ShowError("HttpAddRequestHeaders"); break; } // 构造将要发送的数据包格式 // 1. 文件数据前缀(可选) char szPreData[1024] = { 0 }; int iPostValue = 7758; char szUploadFileName[] = "C:\\User\\DemonGan.txt"; ::RtlZeroMemory(szPreData, 1024); ::wsprintf(szPreData, "--%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n%d\r\n" "--%s\r\nContent-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n" // 二进制数据流 --> (jpg || jpeg file)"Content-Type: image/pjpeg\r\n\r\n" --> // (gif file)"Content-Type: image/gif\r\n\r\n" --> (png file)"Content-Type: image/x-png\r\n\r\n" "Content-Type: application/octet-stream\r\n\r\n", szBoundary, "MyValue", iPostValue, szBoundary, "MyUploadFileName", szUploadFileName); // 2. 上传主体内容数据(可以是多个文件数据, 但是要用 szBoundary 分开) // ----> pUploadData // 3.结束后缀(可选) char szSufData[1024] = { 0 }; ::RtlZeroMemory(szSufData, 1024); ::wsprintf(szSufData, "\r\n--%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n%s\r\n--%s--", szBoundary, "MyUploadOver", "OVER", szBoundary); // 计算数据包的大小 = 前缀数据包大小 + 主体数据大小 + 后缀数据包大小 // 并 发送请求, 告诉服务器传输数据的总大小 DWORD dwPostDataSize = ::lstrlen(szPreData) + dwUploadDataSize + ::lstrlen(szSufData); // DWORD dwPostDataSize = dwUploadDataSize; INTERNET_BUFFERS internetBuffers = { 0 }; ::RtlZeroMemory(&internetBuffers, sizeof(internetBuffers)); internetBuffers.dwStructSize = sizeof(internetBuffers); internetBuffers.dwBufferTotal = dwPostDataSize; bRet = ::HttpSendRequestEx(hRequest, &internetBuffers, NULL, 0, 0); if (FALSE == bRet) { if (ERROR_INTERNET_INVALID_CA == ::GetLastError()) { DWORD dwFlags = 0; DWORD dwBufferSize = sizeof(dwFlags); // 获取INTERNET_OPTION_SECURITY_FLAGS标志 bRet = ::InternetQueryOption(hRequest, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, &dwBufferSize); if (bRet) { // 设置INTERNET_OPTION_SECURITY_FLAGS标志 // 忽略未知的证书颁发机构 dwFlags = dwFlags | SECURITY_FLAG_IGNORE_UNKNOWN_CA; bRet = ::InternetSetOption(hRequest, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof(dwFlags)); if (bRet) { // 再次发送请求 bRet = ::HttpSendRequestEx(hRequest, &internetBuffers, NULL, 0, 0); if (FALSE == bRet) { Https_ShowError("HttpSendRequestEx"); break; } } else { Https_ShowError("InternetSetOption"); break; } } else { Https_ShowError("InternetQueryOption"); break; } } else { Https_ShowError("HttpSendRequestEx"); break; } } // 发送数据 // 发送前缀数据(可选) bRet = ::InternetWriteFile(hRequest, szPreData, ::lstrlen(szPreData), &dwRet); if (FALSE == bRet) { Https_ShowError("InternetWriteFile1"); break; } // 发送主体内容数据 bRet = ::InternetWriteFile(hRequest, pUploadData, dwUploadDataSize, &dwRet); if (FALSE == bRet) { Https_ShowError("InternetWriteFile2"); break; } // 发送后缀数据(可选) bRet = ::InternetWriteFile(hRequest, szSufData, ::lstrlen(szSufData), &dwRet); if (FALSE == bRet) { Https_ShowError("InternetWriteFile3"); break; } // 发送完毕, 结束请求 bRet = ::HttpEndRequest(hRequest, NULL, 0, 0); if (FALSE == bRet) { Https_ShowError("HttpEndRequest"); break; } // 接收来自服务器响应的数据 // 接收响应的报文信息头(Get Response Header) pResponseHeaderIInfo = new unsigned char[dwResponseHeaderIInfoSize]; if (NULL == pResponseHeaderIInfo) { break; } ::RtlZeroMemory(pResponseHeaderIInfo, dwResponseHeaderIInfoSize); bRet = ::HttpQueryInfo(hRequest, HTTP_QUERY_RAW_HEADERS_CRLF, pResponseHeaderIInfo, &dwResponseHeaderIInfoSize, NULL); if (FALSE == bRet) { Https_ShowError("HttpQueryInfo"); break; }#ifdef _DEBUG printf("[HTTPS_Upload_ResponseHeaderIInfo]\n\n%s\n\n", pResponseHeaderIInfo);#endif // 从 中字段 "Content-Length: "(注意有个空格) 获取数据长度 bRet = Https_GetContentLength((char *)pResponseHeaderIInfo, &dwResponseBodyDataSize); if (FALSE == bRet) { break; } // 接收报文主体内容(Get Response Body) pBuf = new BYTE[dwBufSize]; if (NULL == pBuf) { break; } pResponseBodyData = new BYTE[dwResponseBodyDataSize]; if (NULL == pResponseBodyData) { break; } ::RtlZeroMemory(pResponseBodyData, dwResponseBodyDataSize); do { ::RtlZeroMemory(pBuf, dwBufSize); bRet = ::InternetReadFile(hRequest, pBuf, dwBufSize, &dwRet); if (FALSE == bRet) { Https_ShowError("InternetReadFile"); break; } ::RtlCopyMemory((pResponseBodyData + dwOffset), pBuf, dwRet); dwOffset = dwOffset + dwRet; } while (dwResponseBodyDataSize > dwOffset); } while (FALSE); // 关闭 释放 if (NULL != pResponseBodyData) { delete[]pResponseBodyData; pResponseBodyData = NULL; } if (NULL != pBuf) { delete[]pBuf; pBuf = NULL; } if (NULL != pResponseHeaderIInfo) { delete[]pResponseHeaderIInfo; pResponseHeaderIInfo = NULL; } if (NULL != hRequest) { ::InternetCloseHandle(hRequest); hRequest = NULL; } if (NULL != hConnect) { ::InternetCloseHandle(hConnect); hConnect = NULL; } if (NULL != hInternet) { ::InternetCloseHandle(hInternet); hInternet = NULL; } return bRet;}
    3. ASP接收文件程序mytest1.asp<%'ASP文件接收程序dim file,obj,fsofile = Trim(Request("file"))If file = "" Then Response.Write "上传错误文件名未指定": Response.EndSet obj = Server.CreateObject("Adodb.Stream")With obj.Type = 1.Mode = 3.Open.Write Request.BinaryRead(Request.TotalBytes).Position = 0.SaveToFile Server.Mappath(file), 2.CloseEnd WithSet obj = NothingSet fso = CreateObject("Scripting.FileSystemObject")If fso.FileExists(Server.Mappath(file)) ThenResponse.Write "上传成功"ElseResponse.Write "上传失败"End IfSet fso = Nothing%>
    程序测试在main函数中,调用上述封装好的函数,上传文件进行测试。
    main函数为:
    int _tmain(int argc, _TCHAR* argv[]){ char szHttpsUploadUrl[] = "https://192.168.28.137/mytest1.asp?file=520.zip"; char szHttpsUploadFileName[] = "C:\\Users\\Desktop\\520.zip"; BYTE *pHttpsUploadData = NULL; DWORD dwHttpsUploadDataSize = 0; DWORD dwRets = 0; // 打开文件 HANDLE hFiles = ::CreateFile(szHttpsUploadFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL); if (INVALID_HANDLE_VALUE == hFiles) { return 1; } // 获取文件大小 dwHttpsUploadDataSize = ::GetFileSize(hFiles, NULL); // 读取文件数据 pHttpsUploadData = new BYTE[dwHttpsUploadDataSize]; ::ReadFile(hFiles, pHttpsUploadData, dwHttpsUploadDataSize, &dwRets, NULL); dwHttpsUploadDataSize = dwRets; // 上传数据 if (FALSE == Https_Upload(szHttpsUploadUrl, pHttpsUploadData, dwHttpsUploadDataSize)) { return 2; } // 释放内存 delete []pHttpsUploadData; pHttpsUploadData = NULL; ::CloseHandle(hFiles); system("pause"); return 0;}
    测试结果:
    根据传输返回的Response Header可知,数据上传成功。

    查看ASP服务器目录,成功获取17795KB大小的“mmyyyytestupload1”文件。

    总结相对与HTTPS的文件下载,HTTPS文件上传需要注意两点。一是要注意HttpOpenRequest 中要打开“POST”请求;二是在构造请求头信息的时候,一定要严格按照协议格式去写,具体格式可以到网上搜索。
    参考参考自《Windows黑客编程技术详解》一书
    2 留言 2018-12-21 08:58:16 奖励25点积分
  • 枚举并删除系统上ObRegisterCallbacks回调

    背景我们学习内核 Rootkit 编程,那么肯定会接触到各种无 HOOK 回调函数的设置,这些回调函数都是官方为我们做好的接口,我们直接调用就好。这些回调使用方便,运行在底层,功能强大,而且非常稳定。很多杀软、游戏保护等就是设置这些回调,实现对计算机的监控的。
    既然可以设置回调,自然也可以删除回调。如果是自己程序设置的回调,当然可以很容易删除。但是,我们要做的是要枚举系统上存在的回调,不管是不是自己程序创建的,然后,并对这些回调进行删除,使其失效。
    本文要介绍的是枚举并删除系统上 ObRegisterCallbacks 回调,支持 32 位和 64 位、Win7 到 Win10 全平台系统。现在,我把实现的过程和原理整理成文档,分享给大家。
    实现原理我们注册的对象回调,会存储在一个表头为 CallbackList 的双向链表里,它存储着系统里所有 ObRegisterCallbacks 对象回调操作前回调函数地址、操作后回调函数地址和对象回调句柄的信息。
    经过使用 WinDbg 逆向,总结得出 CallbackList 双向链表指向的数据结构为:
    #pragma pack(1)typedef struct _OB_CALLBACK{ LIST_ENTRY ListEntry; ULONGLONG Unknown; HANDLE ObHandle; PVOID ObTypeAddr; PVOID PreCall; PVOID PostCall;}OB_CALLBACK, *POB_CALLBACK;#pragma pack()
    经过分析,无论 32 位或 64 位平台,成员 Unknown 数据类型是 8 字节,而不是PVOID!分析方法为,使用 WinDbg 的命令 dd CallbackList(0x9A485632), 获取 CallbackList 双向链表地址及其附近的数据,与使用 ObRegisterCallback 设置的回调信息比对,比对设置的回调地址、句柄等, 从而确定。
    ListEntry 中存储着下一个或者上一个 OB_CALLBACK 结构体指针的信息,我们通过遍历这个双向链表,就可以枚举出 ObRegisterCallbacks 对象回调函数地址和句柄的信息。
    CallbackList 地址的获取CallbackList 的地址,可以直接从对象类型中获取。如果要获取进程对象回调函数的双向链表信息,可以从 *PsProcessType 中获取;如果要获取线程对象回调函数的双向链表信息,可以从 *PsThreadType 中获取。
    其中,进程对象类型 *PsProcessType 和线程对象类型 *PsThreadType 的数据结构类型为 POBJECT_TYPE,那么数据结构定义为:
    typedef struct _OBJECT_TYPE{ LIST_ENTRY TypeList; // _LIST_ENTRY UNICODE_STRING Name; // _UNICODE_STRING PVOID DefaultObject; // Ptr64 Void UCHAR Index; // UChar ULONG TotalNumberOfObjects; // Uint4B ULONG TotalNumberOfHandles; // Uint4B ULONG HighWaterNumberOfObjects; // Uint4B ULONG HighWaterNumberOfHandles; // Uint4B OBJECT_TYPE_INITIALIZER TypeInfo; // _OBJECT_TYPE_INITIALIZER EX_PUSH_LOCK TypeLock; // _EX_PUSH_LOCK ULONG Key; // Uint4B LIST_ENTRY CallbackList; // _LIST_ENTRY}OBJECT_TYPE, *POBJECT_TYPE;
    其中,OBJECT_TYPE_INITIALIZER 数据结构类型的定义为:
    typedef struct _OBJECT_TYPE_INITIALIZER{ USHORT Length; // Uint2B UCHAR ObjectTypeFlags; // UChar ULONG ObjectTypeCode; // Uint4B ULONG InvalidAttributes; // Uint4B GENERIC_MAPPING GenericMapping; // _GENERIC_MAPPING ULONG ValidAccessMask; // Uint4B ULONG RetainAccess; // Uint4B POOL_TYPE PoolType; // _POOL_TYPE ULONG DefaultPagedPoolCharge; // Uint4B ULONG DefaultNonPagedPoolCharge; // Uint4B PVOID DumpProcedure; // Ptr64 void PVOID OpenProcedure; // Ptr64 long PVOID CloseProcedure; // Ptr64 void PVOID DeleteProcedure; // Ptr64 void PVOID ParseProcedure; // Ptr64 long PVOID SecurityProcedure; // Ptr64 long PVOID QueryNameProcedure; // Ptr64 long PVOID OkayToCloseProcedure; // Ptr64 unsigned char#if (NTDDI_VERSION >= NTDDI_WINBLUE) // Win8.1 ULONG WaitObjectFlagMask; // Uint4B USHORT WaitObjectFlagOffset; // Uint2B USHORT WaitObjectPointerOffset; // Uint2B#endif}OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;
    其中,进程对象类型 *PsProcessType 和线程对象类型 *PsThreadType 系统已经在头文件 wdm.h 中为我们导入:
    // #include <wdm.h>extern POBJECT_TYPE *CmKeyObjectType;extern POBJECT_TYPE *IoFileObjectType;extern POBJECT_TYPE *ExEventObjectType;extern POBJECT_TYPE *ExSemaphoreObjectType;extern POBJECT_TYPE *TmTransactionManagerObjectType;extern POBJECT_TYPE *TmResourceManagerObjectType;extern POBJECT_TYPE *TmEnlistmentObjectType;extern POBJECT_TYPE *TmTransactionObjectType;extern POBJECT_TYPE *PsProcessType;extern POBJECT_TYPE *PsThreadType;extern POBJECT_TYPE *SeTokenObjectType;
    所以,可直接从 *PsProcessType、 *PsThreadType 等对象类型 POBJECT_TYPE 中获取对应类型的 CallbackList 双向链表的地址。注意,不同的对象类型,都有一个属于自己类型的 CallbackList 双向链表。
    我们只要对 CallbackList 双向链表进行遍历,就可以获取对应对象类型的回调信息。
    获取进程对象类型 *PsProcessType 的 CallbackList 地址代码为:
    ((POBJECT_TYPE)(*PsProcessType))->CallbackList;
    获取线程对象类型 *PsThreadType 的 CallbackList 地址代码为:
    ((POBJECT_TYPE)(*PsThreadType))->CallbackList;
    删除回调我们可以通过上述介绍的方法,枚举系统中的回调函数。那么,要删除回调函数可以有 3 种方式:

    可以直接调用 ObUnRegisterCallbacks 函数,传入回调句柄,即可删除回调
    修改 CallbackList 双向链表中的数据,使其指向我们自己定义的空回调函数地址。这样,当触发回调函数的时候,执行的是我们自己的空回调函数
    修改回调函数的前几字节内存数据,写入直接返回指令 RET,不进行任何操作

    编码实现获取进程对象类型回调// 获取进程对象类型回调BOOLEAN EnumProcessObCallback(){ POB_CALLBACK pObCallback = NULL; // 直接获取 CallbackList 链表 LIST_ENTRY CallbackList = ((POBJECT_TYPE)(*PsProcessType))->CallbackList; // 开始遍历 pObCallback = (POB_CALLBACK)CallbackList.Flink; do { if (FALSE == MmIsAddressValid(pObCallback)) { break; } if (NULL != pObCallback->ObHandle) { // 显示 DbgPrint("[PsProcessType]pObCallback->ObHandle = 0x%p\n", pObCallback->ObHandle); DbgPrint("[PsProcessType]pObCallback->PreCall = 0x%p\n", pObCallback->PreCall); DbgPrint("[PsProcessType]pObCallback->PostCall = 0x%p\n", pObCallback->PostCall); } // 获取下一链表信息 pObCallback = (POB_CALLBACK)pObCallback->ListEntry.Flink; } while (CallbackList.Flink != (PLIST_ENTRY)pObCallback); return TRUE;}
    获取线程对象类型回调// 获取线程对象类型回调BOOLEAN EnumThreadObCallback(){ POB_CALLBACK pObCallback = NULL; // 直接获取 CallbackList 链表 LIST_ENTRY CallbackList = ((POBJECT_TYPE)(*PsThreadType))->CallbackList; // 开始遍历 pObCallback = (POB_CALLBACK)CallbackList.Flink; do { if (FALSE == MmIsAddressValid(pObCallback)) { break; } if (NULL != pObCallback->ObHandle) { // 显示 DbgPrint("[PsThreadype]pObCallback->ObHandle = 0x%p\n", pObCallback->ObHandle); DbgPrint("[PsThreadType]pObCallback->PreCall = 0x%p\n", pObCallback->PreCall); DbgPrint("[PsThreadType]pObCallback->PostCall = 0x%p\n", pObCallback->PostCall); } // 获取下一链表信息 pObCallback = (POB_CALLBACK)pObCallback->ListEntry.Flink; } while (CallbackList.Flink != (PLIST_ENTRY)pObCallback); return TRUE;}
    移除回调// 移除回调NTSTATUS RemoveObCallback(PVOID RegistrationHandle){ ObUnRegisterCallbacks(RegistrationHandle); return STATUS_SUCCESS;}
    程序测试在 Win7 32 位系统下,驱动程序正常执行:

    在 Win8.1 32 位系统下,驱动程序正常执行:

    在 Win10 32 位系统下,驱动程序正常执行:

    在 Win7 64 位系统下,驱动程序正常执行:

    在 Win8.1 64 位系统下,驱动程序正常执行:

    在 Win10 64 位系统下,驱动程序正常执行:

    总结要理解清楚获取 CallbackList 双向链表地址的流程,其中,不同系统的数据结构定义是不同的,要注意区分。大家也不用记忆这些特征码,如果需要用到,可以随时使用 WinDbg 来进行逆向查看就好。
    删除回调常用就有 3 种方式,自己根据需要选择一种使用即可。
    参考参考自《Windows黑客编程技术详解》一书
    1 留言 2019-03-29 14:19:44 奖励10点积分
  • 基于Skin++库实现的换肤功能

    背景之前自己经常使用MFC来开发一些界面程序,这些程序大都是自己练手用的。但,也会有极个别是帮别人开发,给别人使用。当你辛苦做出来的作品拿出去给别人用的时候,你总想让自己的作品给人留下深刻印象,无论是从功能,还是用程序界面上。
    对于,我们使用 VC6.0 或者 VS2008、VS2010等以上版本开发出来的界面程序,界面通常都是千篇一律,非常质朴的。所以,自己就像用最简单的方式去修改下界面,因为界面虽说重要,但也并不是说不可或缺的,所以自己不想花费太多的精力在界面上。
    后来,经过搜索查找,还真让我找到一个不错的、方便易用的界面修改方法,即使用 Skin++界面库 来实现。Skin++ 属于第二代的外挂式的界面库,提供了Skin Builder 工具将所有控件的资源全部设计成为一个独立的文件,便于在应用程序外部独立地进行增删改操作,采用Hook与子类化技术来实现应用程序的自动换肤。
    现在,本文就基于 Skin++界面库 实现给 VC 或 VS 开发的界面程序更换皮肤。把实现的过程整理成文档,分享给大家。
    实现过程程序要使用到的 Skin++库 文件包括:SkinPPWTL.h、SkinPPWTL.lib、skinppwtl.dll 以及 48个 .ssk 的皮肤文件。
    首先,我们需要把 Skin++ 库文件加载到程序里,做法如下:

    把 SkinPPWTL.h 头文件以及 SkinPPWTL.lib 库文件拷贝到我们的项目工程目录下面,然后在程序声明头文件并加载库文件:
    #include <afxcmn.h>#include <Windows.h>#include "skin\\SkinPPWTL.h"#pragma comment(lib, "skin\\SkinPPWTL.lib")
    然后,我们编译下程序,看看有没有错误提示。若出现类似这样的错误提示: “… _CRT_SECURE_NO_WARNINGS …”,则在 项目属性 —> C/C++ —> 预处理器 —> 预处理器定义 中添加 “__CRT_SECURE_NO_WARNINGS” 这个预定义即可。

    经过上面两步操作,就可以正确地把 Skin++ 库文件加载到程序中了。
    接下来,我们就直接调用 skinppLoadSkin 函数加载 .ssk 格式的皮肤库就可以了。但是要注意调用 skinppLoadSkin 函数的地方,一定要在界面实现出来之前的初始化操作里就开始调用,不能再界面显示出来后调用,否则会出问题。对于 MFC 程序和 Windows应用程序,它们调用 skinppLoadSkin 函数加载界面库文件的地方可以是:

    对于 MFC 程序,可以是在 CxxxAPP::InitInstance() 初始化函数的开头调用,也可以是在 CxxxDlg::OnInitDialog() 主窗口类初始化函数里调用。
    对于 Windows 应用程序,可以是在 WinMain 函数的开头调用,也可以是在窗口消息处理过程函数中的 WM_INITDIALOG 消息中加载。

    调用 skinppLoadSkin 函数加载界面库文件的代码如下所示:
    // 加载皮肤::skinppLoadSkin("skins\\XP-Home.ssk");
    要更换皮肤,只需要更改上面加载的 .ssk 库文件就好,本文有 48 个 .ssk 文件,所以,可以实现 48 种换肤。
    最后,我们编译链接生成可执行文件,在运行程序之前,只需要按照上面库文件 .ssk 的路径放置库文件,同时还需要把 skinppwtl.dll 动态链接库放在和可执行程序同一目录下,就可以正常运行程序了。
    程序测试按照上面的方法,我们分别创建了一个 MFC 程序和 Windows应用程序 来进行测试,程序成功更换皮肤。


    总结对于 Skin++界面库使用比较简单,主要在窗口初始化的时候,就对界面库初始化,并加载界面库就好,剩下的,不需要我们去理会,我们只需要正常开发我们的程序功能就好。
    2 留言 2018-11-29 09:23:21 奖励10点积分
  • 设置VS编译选项使程序不需要带DLL在任意Windows系统上正常运行

    背景初学编程的时候,那时使用的开发环境是VC6.0。使用VC6.0编译的控制台程序或者是DLL,直接编译出来就可以在其他平台上运行或是调用,不需要额外加载运行库DLL等等。使用VC6.0编译出来的MFC程序,编译的时候设置下在静态库中使用MFC,即将MFC所需的DLL组件静态编译到程序里,这样程序在任一平台上运行,也不需要额外附加MFC所需的DLL文件。
    后来,由于跟随大流,VC6.0慢慢地就很少使用,转而使用VS2010、VS2012、VS2013、VS2015,甚至现在VS2017也有了。使用VS系统的开发环境,功能方面确实比较全面,提升开发效率。但是,伴随着VC6.0一些习以为常的习惯,例如编译的设置等,都悄无声息地都露着区别。所以,本文就是教你在使用VS系列开发环境的时候,怎么设置编译选项,使得生成出来的程序可以直接在其他电脑上运行,就像VC6.0一样,不需要额外DLL文件。
    步骤1. 针对VS上编译控制台程序和DLL程序的编译设置之所以把控制台和DLL程序的编译设置放在一起,是因为它们的设置都已一样的。现在,我们以VS2013开发环境为例,想大家描述一下操作步骤。
    在打开项目工程之后,右击项目工程,选中并点击“属性”,打开属性页。

    1> 设置兼容XP在“平台工具集”里选择“Visual Studio 2013 - Windows XP (v120xp)”,即带有“Windows XP (v120xp)”字样的选项,这表示程序兼容XP系统,可以正常在XP系统下运行。

    2> 静态编译运行库接着上面操作,点击左侧“C/C++”前面的三角形标号,展开选项;然后,点击“代码生成”选项,便可以在右侧的页面看到“运行库”的默认值是“MDd”。如果此时,你的项目是Debug模式的,则选择“MTd”,若是Release模式的,则选择“MT”。其中MT是“Multithread, Static Version”的缩写,即多线程静态版本;d是“Debug”的缩写,即Debug模式。

    根据上面两步操作:设置XP兼容和静态编译运行库,这样编译出来的控制台程序和DLL程序就能直接在Windows系统上直接加载运行了。
    2. 针对VS上编译MFC程序的编译设置对于MFC程序,除了上面两步操作之外。(注意:除了上面两步操作之外,也就是说,MFC程序的编译也要进行上面两项的操作。)还需要额外做一步操作,就是在“MFC的使用”选项中设置“在静态库中使用MFC”。这样,VS开发环境就会把MFC所需的DLL文件都静态编译到程序里,这样,生成的文件也自然会变大。但是,这样程序就可以直接在其他Windows计算机上运行了,而不需要额外加在其他文件。

    总结上述,罗列了控制体程序、DLL程序以及MFC程序在VS系列开发环境的编译设置,大家按照以上操作,就可以编译出更加便于使用的程序出来。
    参考参考自《Windows黑客编程技术详解》一书
    2 留言 2018-12-27 10:55:47 奖励5点积分
  • 使用Windows7旗舰版64位来搭建本地HTTPS测试的ASP服务器

    背景近期写的一个小程序里面,需要用到HTTPS协议来传输数据到指定的HTTPS服务器上面。上传数据的客户端使用WININET库开发完成,但是需要搭建本地测试环境,来测试程序能够成功发送数据到HTTPS的服务器上面。所以,从网上查询了一些相关资料,把环境给成功搭建起来了。现在,想把自己搭建HTTPS测试环境的过程,也分享给大家。
    步骤参考本站上的 《使用Windows7旗舰版64位来搭建ASP服务器环境》 一文来配置ASP服务器,我们是在此ASP服务器上进行配置的。
    按上面参考文章步骤成功安装ASP服务器后,打开“Internet 信息服务(IIS)管理器”,在“功能视图”中选中并双击打开“服务器证书”。

    进入“服务器证书”页面后,点击右侧的“创建自签名证书…”。

    接着,任意新创建的自签名证书设置一个名称,如:“MyHttpsTest”。输入完毕后,点击“确定”。

    接着选中ASP服务器网站,然后,点击右侧的“绑定…”。

    在“网站绑定”窗口中,点击“添加(A)…”。

    在“添加网站绑定窗口”中,“类型(T)”选择“https”,“IP地址(I)”选择服务器的IP地址,“SSL证书()S”选择刚刚创建的自签名证书“MyHttpsTest”,接着点击“确定”。

    这样,便可以成功为网站设置了自签名证书,可以在浏览器中输入:https://192.168.28.137 进行测试。网站可以正常打开,在浏览器中,https有一条红色的斜杠,而且提示“网站的安全证书不受信任”,那是因为我们使用的是自签名证书,并非权威机构颁发的证书,所以会有此提示,不过这不影响到我们使用的HTTPS数据传输。

    总结步骤比较简单,仔细跟着操作应该不会有什么问题。
    2 留言 2018-12-26 08:53:55 奖励5点积分
  • python数据分析(3)——数据特征分析(下)

    1. 周期性分析周期性分析是探索某个变量是否随这时间的变化而呈现出某种周期变化趋势。
    时间尺度较长的有年度性、季节性;较短的有月度、周度性;甚至更短的天、小时。
    2. 贡献度(帕累托)分析20/80定律,同样的投入放在不同的地方会产生不同的效益。
    例如对于一个公司,80%的利润常常来源于20%的产品,其余80%产品只产生了20%利润。
    帕累托图用双直角坐标系表示,左边纵坐标表示频数,右边纵坐标表示频率,折线表示累积频率,横坐标表示影响的各项因素,按影响程度的大小(即出现频数多少)从左到右排列,通过对帕累托图的观察分析,可以抓住影响的主要因素,从而优先解决主要问题。
    数据为catering_dish_profit.xls
    代码为
    #-*- coding: utf-8 -*-#菜品盈利数据 帕累托图from __future__ import print_functionimport pandas as pd#初始化参数dish_profit = 'catering_dish_profit.xls' #餐饮菜品盈利数据data = pd.read_excel(dish_profit, index_col = u'菜品名')data = data[u'盈利'].copy()data.sort_values(ascending=False)import matplotlib.pyplot as plt #导入图像库plt.rcParams['font.sans-serif'] = ['SimHei'] #用来正常显示中文标签plt.rcParams['axes.unicode_minus'] = False #用来正常显示负号plt.figure()data.plot(kind='bar')plt.ylabel(u'盈利(元)')p = 1.0*data.cumsum()/data.sum()p.plot(color = 'r', secondary_y = True, style = '-o',linewidth = 2)plt.annotate(format(p[6], '.4%'), xy = (6, p[6]), xytext=(6*0.9, p[6]*0.9), arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2")) #添加注释,即85%处的标记。这里包括了指定箭头样式。plt.ylabel(u'盈利(比例)')plt.show()

    3. 相关性分析3.1 直接绘制散点图判断两个变量是否具有线性相关关系的最最直观的方法是直接绘制散点图。

    3.2 绘制散点图矩阵需要同时考察多个变量间的相关关系,使用散点图矩阵。
    代码是
    # Seaborn visualization libraryimport seaborn as sns# Create the default pairplotsns.pairplot(df)

    3.3 计算相关系数3.3.1 Pearson相关系数
    3.3.2 Spearman秩相关系数
    3.3.3 判定系数
    #-*- coding: utf-8 -*-#餐饮销量数据相关性分析from __future__ import print_functionimport pandas as pdcatering_sale = 'catering_sale_all.xls' #餐饮数据,含有其他属性data = pd.read_excel(catering_sale, index_col = u'日期') #读取数据,指定“日期”列为索引列

    data.corr() #相关系数矩阵,即给出了任意两款菜式之间的相关系数data.corr()[u’百合酱蒸凤爪’] #只显示“百合酱蒸凤爪”与其他菜式的相关系数data[u’百合酱蒸凤爪’].corr(data[u’翡翠蒸香茜饺’]) #计算“百合酱蒸凤爪”与“翡翠蒸香茜饺”的相关系数

    2 留言 2018-12-23 19:21:06 奖励20点积分
  • 【Cocos Creator实战教程(8)】——UI组件(2)ProgressBar 组件 精华

    1. 知识点讲解ProgressBar(进度条)经常被用于在游戏中显示某个操作的进度,在节点上添加 ProgressBar 组件,然后给该组件关联一个 Bar Sprite 就可以在场景中控制 Bar Sprite 来显示进度了。

    点击 属性检查器 下面的添加组件按钮,然后从添加 UI 组件中选择ProgressBar,即可添加 ProgressBar 组件到节点上。
    1.1 ProgressBar 属性


    属性
    功能说明




    Bar Sprite
    进度条渲染所需要的 Sprite 组件,可以通过拖拽一个带有 Sprite组件的节点到该属性上来建立关联。


    Mode
    支持 HORIZONTAL(水平)、VERTICAL(垂直)和 FILLED(填充)三种模式,可以通过配合 reverse 属性来改变起始方向。


    Total Length
    当进度条为 100%时 Bar Sprite 的总长度/总宽度。在 FILLED 模式下 Total Length 表示取 Bar Sprite 总显示范围的百分比,取值范围从 0 ~ 1。


    Progress
    浮点,取值范围是 0~1,不允许输入之外的数值。


    Reverse
    布尔值,默认的填充方向是从左至右/从下到上,开启后变成从右到左/从上到下。



    1.2 详细说明添加 ProgressBar 组件之后,通过从 层级管理器 中拖拽一个带有Sprite组件的节点到 Bar Sprite属性上,此时便可以通过拖动 progress 滑块来控制进度条的显示了。
    Bar Sprite 可以是自身节点,子节点,或者任何一个带有Sprite组件的节点。另外,Bar Sprite 可以自由选择 Simple、Sliced 和 Filled 渲染模式。
    进度条的模式选择 FILLED 的情况下,Bar Sprite 的 Type 也需要设置为 FILLED,否则会报警告。
    2. 步骤创建新的ProgressScene,创建ProgressBar控件名为progressBarView,然后在progressBarView上添加脚本文件ProgressBarScript。
    创建脚本文件,当然我们在创建脚本文件的时候,需要自定义properties属性来让脚本这个类来接收UI控件并关联
    cc.Class({ extends: cc.Component, // 脚本自定义的属性,当前自定义的属性会在属性检查中查看到 properties: { speed: 1, progressBarView: { type: cc.ProgressBar, default: null } }, //当我们将脚本添加到节点 `node`上面的时候 onLoad: function () { this._ping = true; this.progressBarView.progress = 0; }, //如果该组件启用,则每帧调用 update //dt:Number the delta time in seconds it took to complete the last frame update: function (dt) { this._updateProgressBar(this.progressBarView, dt); }, _updateProgressBar: function(progressBar, dt){ var progress = progressBar.progress; if(progress < 1.0 && this._ping){ progress += dt * this.speed; } else { progress -= dt * this.speed; this._ping = progress <= 0; } progressBar.progress = progress; }});
    当我们在写完这些的时候,将脚本文件添加到节点上面,拖拽创建的控件ProgressBarView到我的属性progressBarView上,这样程序就会发现进度条在走。

    3. 总结在现实中,我们可能需要从服务器预加载资源,这时就需要进度条来表示进度。比如使用cc.loader加载资源,同时监控加载进度,之后再用update显示。
    本资源部分素材来源于网络。
    1 留言 2018-11-28 14:54:25 奖励10点积分
  • 为程序创建任务栏右下角托盘图标 精华

    背景我们用过很多应用程序,无论是功能复杂的大程序还是功能单一的小程序,大都会在计算机右下角显示一个图盘图标,然后我们可以直接把窗口关掉,通过点击托盘图标来控制程序的执行操作或显示窗口。使得程序使用起来比较便捷,不用显示程序主窗口就能完成一些操作,增强了程序的用户体验。
    本文要讲解的正是为程序添加这样的一个右下角托盘,并实现显示程序主窗口、退出程序等功能。本文分别在MFC程序和Windows应用程序中进行演示,其实,原理步骤都是相同的,只是为了方便大家理解,所以MFC程序和Windows程序都各写一个来演示。
    现在,我就把程序实现的过程整理成文档,分享给大家。
    函数介绍Shell_NotifyIcon 函数
    主要用于向任务栏的状态栏发送一个消息。
    函数声明
    BOOL Shell_NotifyIcon( DWORD dwMessage, PNOTIFYICONDATA lpdata);
    参数

    dwMessage为输入参数,传递发送的消息,表明要执行的操作。可选的值如下:NIM_ADD向托盘区域添加一个图标。此时第二个参数lpdata指向的NOTIFYICONDATA结构体中的hWnd和uID成员用来标示这个图标,以便以后再次使用Shell_NotifyIcon对此图标操作。NIM_DELETE删除托盘区域的一个图标。此时第二个参数lpdata指向的NOTIFYICONDATA结构体中的hWnd和uID成员用来标示需要被删除的这个图标。NIM_MODIFY修改托盘区域的一个图标。此时第二个参数lpdata指向的NOTIFYICONDATA结构体中的hWnd和uID成员用来标示需要被修改的这个图标。NIM_SETFOCUSVersion 5.0. 设置焦点。比如当用户操作托盘图标弹出菜单,而有按下ESC键将菜单消除后,程序应该使用此消息来将焦点设置到托盘图标上。NIM_SETVERSIONVersion 5.0. 设置任务栏按照第二个参数lpdata指向的NOTIFYICONDATA结构体中的uVersion成员指定的版本号来工作。此消息可以允许用户设置是否使用基于Windows2000的version 5.0的风格。uVersion的缺省值为0,默认指明了使用原始Windows 95图标消息风格。具体这两者的区别请参考msdn中的Shell_NotifyIcon函数说明的Remarks。lpdata为输入参数,是指向NOTIFYICONDATA结构体的指针,结构体内容用来配合第一个参数wMessage进行图标操作。
    返回值

    如果图标操作成功返回TRUE,否则返回FALSE。

    NOTIFYICONDATA 结构体
    结构体声明
    typedef struct _NOTIFYICONDATA { DWORD cbSize; HWND hWnd; UINT uID; UINT uFlags; UINT uCallbackMessage; HICON hIcon; TCHAR szTip[64]; DWORD dwState; DWORD dwStateMask; TCHAR szInfo[256]; union { UINT uTimeout; UINT uVersion; }; TCHAR szInfoTitle[64]; DWORD dwInfoFlags; GUID guidItem;} NOTIFYICONDATA, *PNOTIFYICONDATA;
    成员

    cbSize:结构体的大小,以字节为单位。hWnd:窗口的句柄。窗口用来接收与托盘图标相关的消息。Shell_NotifyIcon函数调用时,hWnd和uID成员用来标示具体要操作的图标。uID:应用程序定义的任务栏图标的标识符。Shell_NotifyIcon函数调用时,hWnd和uID成员用来标示具体要操作的图标。通过将多次调用,你可以使用不同的uID将多个图标关联到一个窗口。hWnd。uFlags:此成员表明具体哪些其他成员为合法数据(即哪些成员起作用)。此成员可以为以下值的组合:NIF_ICON:hIcon成员起作用。NIF_MESSAGE:uCallbackMessage成员起作用。NIF_TIP:szTip成员起作用。NIF_STATE:dwState和dwStateMask成员起作用。NIF_INFO:使用气球提示代替普通的工具提示框。szInfo, uTimeout, szInfoTitle和dwInfoFlags成员起作用。NIF_GUID:保留。uCallbackMessage:应用程序定义的消息标示。当托盘图标区域发生鼠标事件或者使用键盘选择或激活图标时,系统将使用此标示向由hWnd成员标示的窗口发送消息。消息响应函数的wParam参数标示了消息事件发生的任务栏图标,lParam参数根据事件的不同,包含了鼠标或键盘的具体消息,例如当鼠标指针移过托盘图标时,lParam将为WM_MOUSEMOVE。hIcon:增加、修改或删除的图标的句柄。注意,windows不同版本对于图标有不同要求。Windows XP可支持32位。szTip:指向一个以\0结束的字符串的指针。字符串的内容为标准工具提示的信息。包含最后的\0字符,szTip最多含有64个字符。对于Version 5.0 和以后版本,szTip最多含有128个字符(包含最后的\0字符)。dwState:Version 5.0,图标的状态,有两个可选值,如下:NIS_HIDDEN:图标隐藏NIS_SHAREDICON:图标共享dwStateMask:Version 5.0. 指明dwState成员的那些位可以被设置或者访问。比如设置此成员为NIS_HIDDEN,将导致只有hidden状态可以被获取。szInfo:Version 5.0. 指向一个以\0结束的字符串的指针。字符串的内容为气球提示内容。最多含有255个字符。如果要移除已经存在的气球提示信息,设置uFlags成员为NIF_INFO,同时将szInfo设为空。uTimeout:和uVersion成员为联合体。uTimeout表示气球提示超时的时间,单位为毫秒,此时间后气球提示将消失。系统默认气球提示的超时时间最小值为10秒,最大值为30秒。如果设置的uTimeout的值小于10将设置最小值,如果大于30将设置最大值。将超时时间分为最大最小两种,是因为解决不同图标的气球提示同时弹出的问题,详细内容请参考MSDN中NOTIFYICONDATA结构体说明的remarks。uVersion:Version 5.0. 和uTimeout成员为联合体。用来设置使用Windows 95 还是 Windows 2000风格的图标消息接口。szInfoTitle:Version 5.0. 指向一个以\0结束的字符串的指针。字符串的内容为气球提示的标题。此标题出现在气球提示框的上部,最多含有63个字符。dwInfoFlags:Version 5.0. 设置此成员用来给气球提示框增加一个图标。增加的图标出现在气球提示标题的左侧,注意如果szInfoTitle成员设为空字符串,则图标也不会显示。guidItem:Version 6.0. 保留。

    实现过程无论是对MFC程序还是Windows应用程序,实现的步骤和原理都是一样的。
    1. 设置 NOTIFYICONDATA首先,我们需要对托盘图标结构体 NOTIFYICONDATA 进行设置,设置的内容,就是我们想要托盘图标显示的内容。我们主要是对 NOTIFYICONDATA 的cbSize、hWnd、uID、uFlags、uCallbackMessage、hIcon以及szTip成员进行设置。
    其中,cbSize表示 NOTIFYICONDATA 结构体的大小;hWnd表示和托盘图标相关联的程序窗体的句柄,这个值需要被指定,因为窗口用来接收与托盘图标相关的消息;uID表示应用程序定义的任务栏图标的标识符,可以使用不同的uID将多个图标关联到一个窗口;uFlags表示哪些结构体成员起作用,NIF_ICON则hIcon成员起作用,NIF_MESSAGE则uCallbackMessage成员起作用,NIF_TIP则szTip成员起作用,所以下面我们还需要对hIcon、uCallbackMessage以及szTip成员赋值;hIcon表示托盘显示的图标句柄;uCallbackMessage表示托盘的消息类型;szTip表示托盘的提示信息。
    NOTIFYICONDATA notifyIconData = {0};::RtlZeroMemory(&notifyIconData, sizeof(notifyIconData));notifyIconData.cbSize = sizeof(NOTIFYICONDATA);notifyIconData.hWnd = hWnd;notifyIconData.uID = IDI_ICON1;notifyIconData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;notifyIconData.uCallbackMessage = WM_MYTASK;notifyIconData.hIcon = ::LoadIcon(::GetModuleHandle(NULL), (LPCSTR)IDI_ICON1);::lstrcpy(notifyIconData.szTip, "This Is A Notify Tip.");
    2. 增加托盘显示然后,我们开始调用 Shell_NotifyIcon 函数按照上面 NOTIFYICONDATA 设置新增托盘。其中,NIM_ADD表示向托盘区域添加一个图标。notifyIconData就是上面设置的 NOTIFYICONDATA 结构体变量。
    // 增加托盘::Shell_NotifyIcon(NIM_ADD, &notifyIconData);
    3. 托盘消息处理函数经过上面两步操作,我们就可以成功为程序在窗口右下角增加一个托盘图标显示。但是,我们还需要让托盘图标对一些操作做出响应,而不是只是显示而已。例如,我们鼠标右击托盘图标的时候,显示菜单栏。
    根据上面对 NOTIFYICONDATA 结构体成员 uCallbackMessage 介绍中知道 ,当托盘图标区域发生鼠标事件或者使用键盘选择或激活图标时,系统将使用此标示向由hWnd成员标示的窗口发送消息。消息响应函数的wParam参数标示了消息事件发生的任务栏图标,lParam参数根据事件的不同,包含了鼠标或键盘的具体消息,例如当鼠标指针移过托盘图标时,lParam将为WM_MOUSEMOVE。所以,我们要响应鼠标右键的操作,需要判断 lParam 是否为 WM_RBUTTONUP ,若是,弹出菜单,否则忽略操作。
    switch (lParam){// 鼠标右键弹起时case WM_RBUTTONUP: { // 弹出菜单 PopupMyMenu(); break;}default: break;}
    就这样,菜单弹出来后,我们直接响应菜单选项的消息响应函数,在对应的选项里执行相应的操作就好。
    为程序添加托盘显示的原理就是上面 3 个步骤,剩下来的就是编码实现了。
    编码实现Windows应用程序实现首先我们把对NOTIFYICONDATA结构体的设置以及添加托盘图标的操作代码都放在程序初始化WM_INITDIALOG操作里。
    然后,我们就开始在窗口消息过程函数中添加托盘消息类型WM_MYTASK,并对实现托盘消息处理响应函数。这样,在右击托盘的时候,就可以显示菜单栏了。
    窗口消息过程函数BOOL CALLBACK ProgMainDlg(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam){ if (WM_INITDIALOG == uiMsg) { // 设置托盘显示 SetNotifyIcon(hWnd); } else if (WM_CLOSE == uiMsg) { // 隐藏窗口 ::ShowWindow(hWnd, SW_HIDE); } else if (WM_MYTASK == uiMsg) { // 处理操作托盘的消息 OnTaskMsg(hWnd, wParam, lParam); } else if (WM_COMMAND == uiMsg) { if (ID_EXIT == wParam) { // 托盘菜单 退出 ::EndDialog(hWnd, NULL); } else if (ID_SHOW == wParam) { // 托盘菜单 显示主窗口 ::ShowWindow(hWnd, SW_SHOW); } } return FALSE;}
    设置托盘显示// 设置托盘显示void SetNotifyIcon(HWND hWnd){ NOTIFYICONDATA notifyIconData = {0}; ::RtlZeroMemory(&notifyIconData, sizeof(notifyIconData)); notifyIconData.cbSize = sizeof(NOTIFYICONDATA); notifyIconData.hWnd = hWnd; notifyIconData.uID = IDI_ICON1; notifyIconData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; notifyIconData.uCallbackMessage = WM_MYTASK; notifyIconData.hIcon = ::LoadIcon(::GetModuleHandle(NULL), (LPCSTR)IDI_ICON1); ::lstrcpy(notifyIconData.szTip, "This Is A Notify Tip."); // 增加托盘 ::Shell_NotifyIcon(NIM_ADD, &notifyIconData);}
    托盘消息处理函数// 处理操作托盘的消息LRESULT OnTaskMsg(HWND hWnd, WPARAM wParam, LPARAM lParam){ switch (lParam) { // 鼠标右键弹起时,弹出菜单 case WM_RBUTTONUP: { // 弹出菜单 PopupMyMenu(hWnd); break; } default: break; } return 0;}
    弹出菜单栏// 弹出菜单栏void PopupMyMenu(HWND hWnd){ POINT p; ::GetCursorPos(&p); HMENU hMenu = ::LoadMenu(::GetModuleHandle(NULL), (LPCSTR)IDR_MENU1); HMENU hSubMenu = ::GetSubMenu(hMenu, 0); ::TrackPopupMenu(hSubMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON, p.x, p.y, 0, hWnd, NULL); ::DestroyMenu(hSubMenu);}
    MFC程序实现和上面的Windows应用程序一样,首先我们把对NOTIFYICONDATA结构体的设置以及添加托盘图标的操作代码都放在程序初始化,对于MFC来说,初始化消息响应函数是主对话框类的OnInitDialog函数。我们把托盘设置这部分代码,放在函数OnInitDialog中即可。
    然后,我们开始对为自定义消息类型 WM_MYTASK 创建自定义消息响应函数 OnTaskMsg。创建自定义消息响应函数操作如下:

    声明消息类型 WM_MYTASK。
    #define WM_MYTASK (WM_USER + 100)
    声明消息响应函数,函数名称可以任意,但是返回值类型和参数类型是固定的。
    // 托盘消息处理函数 LRESULT OnTaskMsg(WPARAM wParam, LPARAM lParam);
    在主对话框的窗口消息响应列表中,为上述自定义的消息类型和消息响应函数进行关联。
    BEGIN_MESSAGE_MAP(CNotifyIcon_MFC_TestDlg, CDialogEx) … …(省略) ON_MESSAGE(WM_MYTASK, OnTaskMsg) END_MESSAGE_MAP()

    这样,我们就可以直接定义响应函数OnTaskMsg就可以了。
    接下来的操作和代码,基本上和Windows应用程序中的代码是一样的,所以,就给出代码了。若有什么问题,可以直接参考本文对应的程序代码即可。
    程序测试我们直接运行程序,便可以看到窗口右下角有托盘图标显示,然后我们鼠标右击图标,便成功弹出菜单栏,点击菜单栏选项,成功实现相应的操作。

    总结这个程序原理上不是很复杂,但是实现上面,由于Windows应用程序和MFC程序框架上不同,所以,要注意它们的区别,特别是MFC的自定义消息响应函数。
    参考参考自《Windows黑客编程技术详解》一书
    2 留言 2018-11-07 11:23:55 奖励10点积分
  • 枚举并删除系统上PsSetLoadImageNotifyRoutine回调

    背景我们学习内核 Rootkit 编程,那么肯定会接触到各种无 HOOK 回调函数的设置,这些回调函数都是官方为我们做好的接口,我们直接调用就好。这些回调使用方便,运行在底层,功能强大,而且非常稳定。很多杀软、游戏保护等就是设置这些回调,实现对计算机的监控的。
    既然可以设置回调,自然也可以删除回调。如果是自己程序设置的回调,当然可以很容易删除。但是,我们要做的是要枚举系统上存在的回调,不管是不是自己程序创建的,然后,并对这些回调进行删除,使其失效。
    本文要介绍的是枚举并删除系统上 PsSetLoadImageNotifyRoutine 回调,支持 32 位和 64 位、Win7 到 Win10 全平台系统。现在,我把实现的过程和原理整理成文档,分享给大家。
    实现原理我们注册的模块加载回调,会存储在一个名为 PspLoadImageNotifyRoutine 的数组里。 PspLoadImageNotifyRoutine 可以理解成一个 PVOID 数组,它存储着系统里所有 PsSetLoadImageNotifyRoutine 模块加载回调函数地址的加密地址。PspLoadImageNotifyRoutine 数组里的数据是加密的,要经过解密操作才可以获取正确的数据。
    PspLoadImageNotifyRoutine 数组地址的获取我们借助 WinDbg 帮助我们逆向 PsSetLoadImageNotifyRoutine 内核函数,下面是 Win10 64 位系统上 PsSetLoadImageNotifyRoutine 函数的逆向代码:
    nt!PsSetLoadImageNotifyRoutine+0x36:fffff803`0a53d30a 488d0d6f0adfff lea rcx,[nt!PspLoadImageNotifyRoutine (fffff803`0a32dd80)]fffff803`0a53d311 4533c0 xor r8d,r8d
    由上面的代码,我们可以通过在内核函数 PsSetLoadImageNotifyRoutine 中扫描内存特征码,在 32 位系统下,可以直接定位得到数组 PspLoadImageNotifyRoutine 的地址;在 64 位下,可以获取数组 PspLoadImageNotifyRoutine 的偏移,从而根据偏移计算出地址。但是,特征码在不同系统上也会不同,下面是我使用 WinDbg 逆向各个版本系统上的函数,总结的特征码:




    Win7
    win8.1
    win10




    32 位
    BE
    BB
    BF


    64 位
    488D0D
    488D0D
    488D0D



    总的来说,我们直接通过扫描 PsSetLoadImageNotifyRoutine 函数内存,就可获取 PspLoadImageNotifyRoutine 地址了。其中,特征码的确定就变得至关重要。
    PspLoadImageNotifyRoutine 里数据的解密我们上面说,PspLoadImageNotifyRoutine 里的数据是加密的,在 64 位系统和 32 位系统上的加密方式是不相同的,自然解密方式也不同。现在,我们分别介绍 32 位系统和 64 位系统下的解密方式。
    对于 32 位系统来说:PspLoadImageNotifyRoutine 是一个 4 字节无符号类型的数组,数组大小最大为 8。我们使用 PspLoadImageNotifyRoutine[i] 表示数组中的值,那么,32 位系统下的解密方式为:

    首先,数组的值 PspLoadImageNotifyRoutine[i] 位运算“与” 0xFFFFFFF8。然后,“与”运算之后的结果值再加上 4,结果就是一个存储着回调函数地址的地址。
    对于 64 位系统来说:PspLoadImageNotifyRoutine 是一个 8 字节无符号类型的数组,数组大小最大为 64。我们使用 PspLoadImageNotifyRoutine[i] 表示数组中的值,那么,64 位系统下的解密方式为:
    数组的值 PspLoadImageNotifyRoutine[i] 位运算“与” 0xFFFFFFFFFFFFFFF8,结果就是一个存储着回调函数地址的地址。
    删除回调我们可以通过上述介绍的方法,枚举系统中的回调函数。那么,要删除回调函数可以有 3 种方式:

    可以直接调用 PsRemoveLoadImageNotifyRoutine 函数,传入回调函数地址,即可删除回调。修改 PspLoadImageNotifyRoutine 数组中的数据,使其指向我们自己定义的空回调函数地址。这样,当触发回调函数的时候,执行的是我们自己的空回调函数。修改回调函数的前几字节内存数据,写入直接返回指令 RET,不进行任何操作。
    编码实现遍历回调// 遍历回调BOOLEAN EnumNotifyRoutine(){ ULONG i = 0; PVOID pPspLoadImageNotifyRoutineAddress = NULL; PVOID pNotifyRoutineAddress = NULL; // 获取 PspLoadImageNotifyRoutine 数组地址 pPspLoadImageNotifyRoutineAddress = GetPspLoadImageNotifyRoutine(); if (NULL == pPspLoadImageNotifyRoutineAddress) { DbgPrint("GetPspLoadImageNotifyRoutine Error!\n"); return FALSE; } DbgPrint("pPspLoadImageNotifyRoutineAddress=0x%p\n", pPspLoadImageNotifyRoutineAddress); // 获取回调地址并解密#ifdef _WIN64 for (i = 0; i < 64; i++) { pNotifyRoutineAddress = *(PVOID *)((PUCHAR)pPspLoadImageNotifyRoutineAddress + sizeof(PVOID) * i); pNotifyRoutineAddress = (PVOID)((ULONG64)pNotifyRoutineAddress & 0xfffffffffffffff8); if (MmIsAddressValid(pNotifyRoutineAddress)) { pNotifyRoutineAddress = *(PVOID *)pNotifyRoutineAddress; DbgPrint("[%d]ullNotifyRoutine=0x%p\n", i, pNotifyRoutineAddress); } }#else for (i = 0; i < 8; i++) { pNotifyRoutineAddress = *(PVOID *)((PUCHAR)pPspLoadImageNotifyRoutineAddress + sizeof(PVOID) * i); pNotifyRoutineAddress = (PVOID)((ULONG)pNotifyRoutineAddress & 0xfffffff8); if (MmIsAddressValid(pNotifyRoutineAddress)) { pNotifyRoutineAddress = *(PVOID *)((PUCHAR)pNotifyRoutineAddress + 4); DbgPrint("[%d]ullNotifyRoutine=0x%p\n", i, pNotifyRoutineAddress); } }#endif return TRUE;}
    移除回调// 移除回调NTSTATUS RemoveNotifyRoutine(PVOID pNotifyRoutineAddress){ NTSTATUS status = PsRemoveLoadImageNotifyRoutine((PLOAD_IMAGE_NOTIFY_ROUTINE)pNotifyRoutineAddress); if (!NT_SUCCESS(status)) { ShowError("PsRemoveLoadImageNotifyRoutine", status); } return status;}
    获取 PspLoadImageNotifyRoutine 数组地址// 获取 PspLoadImageNotifyRoutine 数组地址PVOID GetPspLoadImageNotifyRoutine(){ PVOID pPspLoadImageNotifyRoutineAddress = NULL; RTL_OSVERSIONINFOW osInfo = { 0 }; UCHAR pSpecialData[50] = { 0 }; ULONG ulSpecialDataSize = 0; // 获取系统版本信息, 判断系统版本 RtlGetVersion(&osInfo); if (6 == osInfo.dwMajorVersion) { if (1 == osInfo.dwMinorVersion) { // Win7#ifdef _WIN64 // 64 位 // 488D0D pSpecialData[0] = 0x48; pSpecialData[1] = 0x8D; pSpecialData[2] = 0x0D; ulSpecialDataSize = 3;#else // 32 位 // BE pSpecialData[0] = 0xBE; ulSpecialDataSize = 1;#endif } else if (2 == osInfo.dwMinorVersion) { // Win8#ifdef _WIN64 // 64 位#else // 32 位#endif } else if (3 == osInfo.dwMinorVersion) { // Win8.1#ifdef _WIN64 // 64 位 // 488D0D pSpecialData[0] = 0x48; pSpecialData[1] = 0x8D; pSpecialData[2] = 0x0D; ulSpecialDataSize = 3;#else // 32 位 // BB pSpecialData[0] = 0xBB; ulSpecialDataSize = 1;#endif } } else if (10 == osInfo.dwMajorVersion) { // Win10#ifdef _WIN64 // 64 位 // 488D0D pSpecialData[0] = 0x48; pSpecialData[1] = 0x8D; pSpecialData[2] = 0x0D; ulSpecialDataSize = 3;#else // 32 位 // BF pSpecialData[0] = 0xBF; ulSpecialDataSize = 1;#endif } // 根据特征码获取地址 pPspLoadImageNotifyRoutineAddress = SearchPspLoadImageNotifyRoutine(pSpecialData, ulSpecialDataSize); return pPspLoadImageNotifyRoutineAddress;}
    根据特征码获取 PspLoadImageNotifyRoutine 数组地址// 获取 PspLoadImageNotifyRoutine 数组地址PVOID GetPspLoadImageNotifyRoutine(){ PVOID pPspLoadImageNotifyRoutineAddress = NULL; RTL_OSVERSIONINFOW osInfo = { 0 }; UCHAR pSpecialData[50] = { 0 }; ULONG ulSpecialDataSize = 0; // 获取系统版本信息, 判断系统版本 RtlGetVersion(&osInfo); if (6 == osInfo.dwMajorVersion) { if (1 == osInfo.dwMinorVersion) { // Win7#ifdef _WIN64 // 64 位 // 488D0D pSpecialData[0] = 0x48; pSpecialData[1] = 0x8D; pSpecialData[2] = 0x0D; ulSpecialDataSize = 3;#else // 32 位 // BE pSpecialData[0] = 0xBE; ulSpecialDataSize = 1;#endif } else if (2 == osInfo.dwMinorVersion) { // Win8#ifdef _WIN64 // 64 位#else // 32 位#endif } else if (3 == osInfo.dwMinorVersion) { // Win8.1#ifdef _WIN64 // 64 位 // 488D0D pSpecialData[0] = 0x48; pSpecialData[1] = 0x8D; pSpecialData[2] = 0x0D; ulSpecialDataSize = 3;#else // 32 位 // BB pSpecialData[0] = 0xBB; ulSpecialDataSize = 1;#endif } } else if (10 == osInfo.dwMajorVersion) { // Win10#ifdef _WIN64 // 64 位 // 488D0D pSpecialData[0] = 0x48; pSpecialData[1] = 0x8D; pSpecialData[2] = 0x0D; ulSpecialDataSize = 3;#else // 32 位 // BF pSpecialData[0] = 0xBF; ulSpecialDataSize = 1;#endif } // 根据特征码获取地址 pPspLoadImageNotifyRoutineAddress = SearchPspLoadImageNotifyRoutine(pSpecialData, ulSpecialDataSize); return pPspLoadImageNotifyRoutineAddress;}// 根据特征码获取 PspLoadImageNotifyRoutine 数组地址PVOID SearchPspLoadImageNotifyRoutine(PUCHAR pSpecialData, ULONG ulSpecialDataSize){ UNICODE_STRING ustrFuncName; PVOID pAddress = NULL; LONG lOffset = 0; PVOID pPsSetLoadImageNotifyRoutine = NULL; PVOID pPspLoadImageNotifyRoutine = NULL; // 先获取 PsSetLoadImageNotifyRoutine 函数地址 RtlInitUnicodeString(&ustrFuncName, L"PsSetLoadImageNotifyRoutine"); pPsSetLoadImageNotifyRoutine = MmGetSystemRoutineAddress(&ustrFuncName); if (NULL == pPsSetLoadImageNotifyRoutine) { ShowError("MmGetSystemRoutineAddress", 0); return pPspLoadImageNotifyRoutine; } // 然后, 查找 PspSetCreateProcessNotifyRoutine 函数地址 pAddress = SearchMemory(pPsSetLoadImageNotifyRoutine, (PVOID)((PUCHAR)pPsSetLoadImageNotifyRoutine + 0xFF), pSpecialData, ulSpecialDataSize); if (NULL == pAddress) { ShowError("SearchMemory", 0); return pPspLoadImageNotifyRoutine; } // 获取地址#ifdef _WIN64 // 64 位先获取偏移, 再计算地址 lOffset = *(PLONG)pAddress; pPspLoadImageNotifyRoutine = (PVOID)((PUCHAR)pAddress + sizeof(LONG) + lOffset);#else // 32 位直接获取地址 pPspLoadImageNotifyRoutine = *(PVOID *)pAddress;#endif return pPspLoadImageNotifyRoutine;}
    指定内存区域的特征码扫描// 指定内存区域的特征码扫描PVOID SearchMemory(PVOID pStartAddress, PVOID pEndAddress, PUCHAR pMemoryData, ULONG ulMemoryDataSize){ PVOID pAddress = NULL; PUCHAR i = NULL; ULONG m = 0; // 扫描内存 for (i = (PUCHAR)pStartAddress; i < (PUCHAR)pEndAddress; i++) { // 判断特征码 for (m = 0; m < ulMemoryDataSize; m++) { if (*(PUCHAR)(i + m) != pMemoryData[m]) { break; } } // 判断是否找到符合特征码的地址 if (m >= ulMemoryDataSize) { // 找到特征码位置, 获取紧接着特征码的下一地址 pAddress = (PVOID)(i + ulMemoryDataSize); break; } } return pAddress;}
    程序测试在 Win7 32 位系统下,驱动程序正常执行:

    在 Win8.1 32 位系统下,驱动程序正常执行:

    在 Win10 32 位系统下,驱动程序正常执行:

    在 Win7 64 位系统下,驱动程序正常执行:

    在 Win8.1 64 位系统下,驱动程序正常执行:

    在 Win10 64 位系统下,驱动程序正常执行:

    总结要理解清楚获取 PspLoadImageNotifyRoutine 地址的流程,其中,不同系统的内存特征码是不同的,要注意区分。大家也不用记忆这些特征码,如果需要用到,可以随时使用 WinDbg 来进行逆向查看就好。
    而且,不同位数系统中,对 PspLoadImageNotifyRoutine 数组中的值解密方式也不相同,这个需要区分开来。
    删除回调常用就有 3 种方式,自己根据需要选择一种使用即可。
    参考参考自《Windows黑客编程技术详解》一书
    附录Win7 32 位 PsSetLoadImageNotifyRoutinelkd> uf PsSetLoadImageNotifyRoutinent!PsSetLoadImageNotifyRoutine:83f819cb 8bff mov edi,edi83f819cd 55 push ebp83f819ce 8bec mov ebp,esp83f819d0 53 push ebx83f819d1 56 push esi83f819d2 57 push edi83f819d3 33ff xor edi,edi83f819d5 57 push edi83f819d6 ff7508 push dword ptr [ebp+8]83f819d9 e83b3c0200 call nt!ExAllocateCallBack (83fa5619)83f819de 8bd8 mov ebx,eax83f819e0 3bdf cmp ebx,edi83f819e2 7428 je nt!PsSetLoadImageNotifyRoutine+0x41 (83f81a0c)nt!PsSetLoadImageNotifyRoutine+0x19:83f819e4 bea030f583 mov esi,offset nt!PspLoadImageNotifyRoutine (83f530a0)nt!PsSetLoadImageNotifyRoutine+0x1e:83f819e9 6a00 push 083f819eb 8bcb mov ecx,ebx83f819ed 8bc6 mov eax,esi83f819ef e8543c0200 call nt!ExCompareExchangeCallBack (83fa5648)83f819f4 84c0 test al,al83f819f6 7520 jne nt!PsSetLoadImageNotifyRoutine+0x4d (83f81a18)nt!PsSetLoadImageNotifyRoutine+0x2d:83f819f8 83c704 add edi,483f819fb 83c604 add esi,483f819fe 81ff00010000 cmp edi,100h83f81a04 72e3 jb nt!PsSetLoadImageNotifyRoutine+0x1e (83f819e9)nt!PsSetLoadImageNotifyRoutine+0x3b:83f81a06 53 push ebx83f81a07 e8ffc81000 call nt!AlpcpFreeBuffer (8408e30b)nt!PsSetLoadImageNotifyRoutine+0x41:83f81a0c b89a0000c0 mov eax,0C000009Ahnt!PsSetLoadImageNotifyRoutine+0x46:83f81a11 5f pop edi83f81a12 5e pop esi83f81a13 5b pop ebx83f81a14 5d pop ebp83f81a15 c20400 ret 4nt!PsSetLoadImageNotifyRoutine+0x4d:83f81a18 33c9 xor ecx,ecx83f81a1a b8a031f583 mov eax,offset nt!PspLoadImageNotifyRoutineCount (83f531a0)83f81a1f 41 inc ecx83f81a20 f00fc108 lock xadd dword ptr [eax],ecx83f81a24 a19830f583 mov eax,dword ptr [nt!PspNotifyEnableMask (83f53098)]83f81a29 a801 test al,183f81a2b 750a jne nt!PsSetLoadImageNotifyRoutine+0x6c (83f81a37)nt!PsSetLoadImageNotifyRoutine+0x62:83f81a2d b89830f583 mov eax,offset nt!PspNotifyEnableMask (83f53098)83f81a32 f00fba2800 lock bts dword ptr [eax],0nt!PsSetLoadImageNotifyRoutine+0x6c:83f81a37 33c0 xor eax,eax83f81a39 ebd6 jmp nt!PsSetLoadImageNotifyRoutine+0x46 (83f81a11)
    Win7 64 位 PsSetLoadImageNotifyRoutinelkd> uf PsSetLoadImageNotifyRoutinent!PsSetLoadImageNotifyRoutine:fffff800`0428db60 48895c2408 mov qword ptr [rsp+8],rbxfffff800`0428db65 57 push rdifffff800`0428db66 4883ec20 sub rsp,20hfffff800`0428db6a 33d2 xor edx,edxfffff800`0428db6c e8efaffeff call nt!ExAllocateCallBack (fffff800`04278b60)fffff800`0428db71 488bf8 mov rdi,raxfffff800`0428db74 4885c0 test rax,raxfffff800`0428db77 7507 jne nt!PsSetLoadImageNotifyRoutine+0x20 (fffff800`0428db80)nt!PsSetLoadImageNotifyRoutine+0x19:fffff800`0428db79 b89a0000c0 mov eax,0C000009Ahfffff800`0428db7e eb4a jmp nt!PsSetLoadImageNotifyRoutine+0x6a (fffff800`0428dbca)nt!PsSetLoadImageNotifyRoutine+0x20:fffff800`0428db80 33db xor ebx,ebxnt!PsSetLoadImageNotifyRoutine+0x22:fffff800`0428db82 488d0d7799d9ff lea rcx,[nt!PspLoadImageNotifyRoutine (fffff800`04027500)]fffff800`0428db89 4533c0 xor r8d,r8dfffff800`0428db8c 488bd7 mov rdx,rdifffff800`0428db8f 488d0cd9 lea rcx,[rcx+rbx*8]fffff800`0428db93 e8b814f8ff call nt!ExCompareExchangeCallBack (fffff800`0420f050)fffff800`0428db98 84c0 test al,alfffff800`0428db9a 7511 jne nt!PsSetLoadImageNotifyRoutine+0x4d (fffff800`0428dbad)nt!PsSetLoadImageNotifyRoutine+0x3c:fffff800`0428db9c ffc3 inc ebxfffff800`0428db9e 83fb08 cmp ebx,8fffff800`0428dba1 72df jb nt!PsSetLoadImageNotifyRoutine+0x22 (fffff800`0428db82)nt!PsSetLoadImageNotifyRoutine+0x43:fffff800`0428dba3 488bcf mov rcx,rdifffff800`0428dba6 e8a5defeff call nt!IopDeallocateApc (fffff800`0427ba50)fffff800`0428dbab ebcc jmp nt!PsSetLoadImageNotifyRoutine+0x19 (fffff800`0428db79)nt!PsSetLoadImageNotifyRoutine+0x4d:fffff800`0428dbad f083058b99d9ff01 lock add dword ptr [nt!PspLoadImageNotifyRoutineCount (fffff800`04027540)],1fffff800`0428dbb5 8b052599d9ff mov eax,dword ptr [nt!PspNotifyEnableMask (fffff800`040274e0)]fffff800`0428dbbb a801 test al,1fffff800`0428dbbd 7509 jne nt!PsSetLoadImageNotifyRoutine+0x68 (fffff800`0428dbc8)nt!PsSetLoadImageNotifyRoutine+0x5f:fffff800`0428dbbf f00fba2d1899d9ff00 lock bts dword ptr [nt!PspNotifyEnableMask (fffff800`040274e0)],0nt!PsSetLoadImageNotifyRoutine+0x68:fffff800`0428dbc8 33c0 xor eax,eaxnt!PsSetLoadImageNotifyRoutine+0x6a:fffff800`0428dbca 488b5c2430 mov rbx,qword ptr [rsp+30h]fffff800`0428dbcf 4883c420 add rsp,20hfffff800`0428dbd3 5f pop rdifffff800`0428dbd4 c3 ret
    Win8.1 32 位 PsSetLoadImageNotifyRoutinelkd> uf PsSetLoadImageNotifyRoutine nt!PsSetLoadImageNotifyRoutine:8116e59e 8bff mov edi,edi8116e5a0 55 push ebp8116e5a1 8bec mov ebp,esp8116e5a3 8b4d08 mov ecx,dword ptr [ebp+8]8116e5a6 33d2 xor edx,edx8116e5a8 56 push esi8116e5a9 e8a4030000 call nt!ExAllocateCallBack (8116e952)8116e5ae 8bf0 mov esi,eax8116e5b0 85f6 test esi,esi8116e5b2 7444 je nt!PsSetLoadImageNotifyRoutine+0x5a (8116e5f8)nt!PsSetLoadImageNotifyRoutine+0x16:8116e5b4 53 push ebx8116e5b5 57 push edi8116e5b6 bba8640181 mov ebx,offset nt!PspLoadImageNotifyRoutine (810164a8)8116e5bb 33ff xor edi,edint!PsSetLoadImageNotifyRoutine+0x1f:8116e5bd 6a00 push 08116e5bf 8bd6 mov edx,esi8116e5c1 8bcb mov ecx,ebx8116e5c3 e89027d9ff call nt!ExCompareExchangeCallBack (80f00d58)8116e5c8 84c0 test al,al8116e5ca 0f84bc030a00 je nt! ?? ::NNGAKEGL::`string'+0x70322 (8120e98c)nt!PsSetLoadImageNotifyRoutine+0x32:8116e5d0 33c0 xor eax,eax8116e5d2 b9486c2f81 mov ecx,offset nt!PspLoadImageNotifyRoutineCount (812f6c48)8116e5d7 40 inc eax8116e5d8 f00fc101 lock xadd dword ptr [ecx],eax8116e5dc a1446c2f81 mov eax,dword ptr [nt!PspNotifyEnableMask (812f6c44)]8116e5e1 a801 test al,18116e5e3 750a jne nt!PsSetLoadImageNotifyRoutine+0x51 (8116e5ef)nt!PsSetLoadImageNotifyRoutine+0x47:8116e5e5 b8446c2f81 mov eax,offset nt!PspNotifyEnableMask (812f6c44)8116e5ea f00fba2800 lock bts dword ptr [eax],0nt!PsSetLoadImageNotifyRoutine+0x51:8116e5ef 33c0 xor eax,eaxnt!PsSetLoadImageNotifyRoutine+0x53:8116e5f1 5f pop edi8116e5f2 5b pop ebxnt!PsSetLoadImageNotifyRoutine+0x55:8116e5f3 5e pop esi8116e5f4 5d pop ebp8116e5f5 c20400 ret 4nt!PsSetLoadImageNotifyRoutine+0x5a:8116e5f8 b89a0000c0 mov eax,0C000009Ah8116e5fd ebf4 jmp nt!PsSetLoadImageNotifyRoutine+0x55 (8116e5f3)nt! ?? ::NNGAKEGL::`string'+0x70322:8120e98c 83c704 add edi,48120e98f 83c304 add ebx,48120e992 83ff20 cmp edi,20h8120e995 0f8222fcf5ff jb nt!PsSetLoadImageNotifyRoutine+0x1f (8116e5bd)nt! ?? ::NNGAKEGL::`string'+0x70331:8120e99b 8bce mov ecx,esi8120e99d e8e0fbe8ff call nt!ExFreeCallBack (8109e582)8120e9a2 b89a0000c0 mov eax,0C000009Ah8120e9a7 e945fcf5ff jmp nt!PsSetLoadImageNotifyRoutine+0x53 (8116e5f1)
    Win8.1 64 位 PsSetLoadImageNotifyRoutinelkd> uf PsSetLoadImageNotifyRoutinent!PsSetLoadImageNotifyRoutine:fffff803`107a0c88 48895c2408 mov qword ptr [rsp+8],rbxfffff803`107a0c8d 57 push rdifffff803`107a0c8e 4883ec20 sub rsp,20hfffff803`107a0c92 33d2 xor edx,edxfffff803`107a0c94 e81750fdff call nt!ExAllocateCallBack (fffff803`10775cb0)fffff803`107a0c99 488bf8 mov rdi,raxfffff803`107a0c9c 4885c0 test rax,raxfffff803`107a0c9f 0f847b560900 je nt! ?? ::NNGAKEGL::`string'+0x87720 (fffff803`10836320)nt!PsSetLoadImageNotifyRoutine+0x1d:fffff803`107a0ca5 33db xor ebx,ebxnt!PsSetLoadImageNotifyRoutine+0x1f:fffff803`107a0ca7 488d0d12ffdbff lea rcx,[nt!PspLoadImageNotifyRoutine (fffff803`10560bc0)]fffff803`107a0cae 4533c0 xor r8d,r8dfffff803`107a0cb1 488bd7 mov rdx,rdifffff803`107a0cb4 488d0cd9 lea rcx,[rcx+rbx*8]fffff803`107a0cb8 e8e307c1ff call nt!ExCompareExchangeCallBack (fffff803`103b14a0)fffff803`107a0cbd 84c0 test al,alfffff803`107a0cbf 7427 je nt!PsSetLoadImageNotifyRoutine+0x60 (fffff803`107a0ce8)nt!PsSetLoadImageNotifyRoutine+0x39:fffff803`107a0cc1 f0ff0584a91800 lock inc dword ptr [nt!PspLoadImageNotifyRoutineCount (fffff803`1092b64c)]fffff803`107a0cc8 8b054ea41800 mov eax,dword ptr [nt!PspNotifyEnableMask (fffff803`1092b11c)]fffff803`107a0cce a801 test al,1fffff803`107a0cd0 7509 jne nt!PsSetLoadImageNotifyRoutine+0x53 (fffff803`107a0cdb)nt!PsSetLoadImageNotifyRoutine+0x4a:fffff803`107a0cd2 f00fba2d41a4180000 lock bts dword ptr [nt!PspNotifyEnableMask (fffff803`1092b11c)],0nt!PsSetLoadImageNotifyRoutine+0x53:fffff803`107a0cdb 33c0 xor eax,eaxnt!PsSetLoadImageNotifyRoutine+0x55:fffff803`107a0cdd 488b5c2430 mov rbx,qword ptr [rsp+30h]fffff803`107a0ce2 4883c420 add rsp,20hfffff803`107a0ce6 5f pop rdifffff803`107a0ce7 c3 retnt!PsSetLoadImageNotifyRoutine+0x60:fffff803`107a0ce8 ffc3 inc ebxfffff803`107a0cea 83fb08 cmp ebx,8fffff803`107a0ced 72b8 jb nt!PsSetLoadImageNotifyRoutine+0x1f (fffff803`107a0ca7)nt!PsSetLoadImageNotifyRoutine+0x67:fffff803`107a0cef e922560900 jmp nt! ?? ::NNGAKEGL::`string'+0x87716 (fffff803`10836316)nt! ?? ::NNGAKEGL::`string'+0x87716:fffff803`10836316 33d2 xor edx,edxfffff803`10836318 488bcf mov rcx,rdifffff803`1083631b e800fbcdff call nt!ExFreePoolWithTag (fffff803`10515e20)nt! ?? ::NNGAKEGL::`string'+0x87720:fffff803`10836320 b89a0000c0 mov eax,0C000009Ahfffff803`10836325 e9b3a9f6ff jmp nt!PsSetLoadImageNotifyRoutine+0x55 (fffff803`107a0cdd)
    Win10 32 位 PsSetLoadImageNotifyRoutinekd> uf PsSetLoadImageNotifyRoutinent!PsSetLoadImageNotifyRoutine:81e1c7e6 8bff mov edi,edi81e1c7e8 55 push ebp81e1c7e9 8bec mov ebp,esp81e1c7eb 83ec30 sub esp,30h81e1c7ee a1948bc981 mov eax,dword ptr [nt!__security_cookie (81c98b94)]81e1c7f3 33c5 xor eax,ebp81e1c7f5 8945fc mov dword ptr [ebp-4],eax81e1c7f8 8b4508 mov eax,dword ptr [ebp+8]81e1c7fb 33d2 xor edx,edx81e1c7fd 53 push ebx81e1c7fe 56 push esi81e1c7ff 8bc8 mov ecx,eax81e1c801 8945d0 mov dword ptr [ebp-30h],eax81e1c804 e8b7020000 call nt!ExAllocateCallBack (81e1cac0)81e1c809 8bd8 mov ebx,eax81e1c80b 85db test ebx,ebx81e1c80d 0f84711d0a00 je nt! ?? ::NNGAKEGL::`string'+0x69b78 (81ebe584)nt!PsSetLoadImageNotifyRoutine+0x2d:81e1c813 57 push edi81e1c814 bf30dacb81 mov edi,offset nt!PspLoadImageNotifyRoutine (81cbda30)81e1c819 33f6 xor esi,esint!PsSetLoadImageNotifyRoutine+0x35:81e1c81b 6a00 push 081e1c81d 8bd3 mov edx,ebx81e1c81f 8bcf mov ecx,edi81e1c821 e8ae1fd6ff call nt!ExCompareExchangeCallBack (81b7e7d4)81e1c826 84c0 test al,al81e1c828 0f848a000000 je nt!PsSetLoadImageNotifyRoutine+0xd2 (81e1c8b8)nt!PsSetLoadImageNotifyRoutine+0x48:81e1c82e f0ff05c8bdff81 lock inc dword ptr [nt!PspLoadImageNotifyRoutineCount (81ffbdc8)]81e1c835 a1c4bdff81 mov eax,dword ptr [nt!PspNotifyEnableMask (81ffbdc4)]81e1c83a a801 test al,181e1c83c 750a jne nt!PsSetLoadImageNotifyRoutine+0x62 (81e1c848)nt!PsSetLoadImageNotifyRoutine+0x58:81e1c83e b8c4bdff81 mov eax,offset nt!PspNotifyEnableMask (81ffbdc4)81e1c843 f00fba2800 lock bts dword ptr [eax],0nt!PsSetLoadImageNotifyRoutine+0x62:81e1c848 33f6 xor esi,esint!PsSetLoadImageNotifyRoutine+0x64:81e1c84a 5f pop edint!PsSetLoadImageNotifyRoutine+0x65:81e1c84b 8b45d0 mov eax,dword ptr [ebp-30h]81e1c84e 8b0d7842ca81 mov ecx,dword ptr [nt!EtwApiCallsProvRegHandle (81ca4278)]81e1c854 8b157c42ca81 mov edx,dword ptr [nt!EtwApiCallsProvRegHandle+0x4 (81ca427c)]81e1c85a 8945d8 mov dword ptr [ebp-28h],eax81e1c85d 8bc1 mov eax,ecx81e1c85f 0bc2 or eax,edx81e1c861 8975d4 mov dword ptr [ebp-2Ch],esi81e1c864 743e je nt!PsSetLoadImageNotifyRoutine+0xbe (81e1c8a4)nt!PsSetLoadImageNotifyRoutine+0x80:81e1c866 8365e000 and dword ptr [ebp-20h],081e1c86a 8d45d8 lea eax,[ebp-28h]81e1c86d 8365e800 and dword ptr [ebp-18h],081e1c871 8365f000 and dword ptr [ebp-10h],081e1c875 8365f800 and dword ptr [ebp-8],081e1c879 8945dc mov dword ptr [ebp-24h],eax81e1c87c 8d45d4 lea eax,[ebp-2Ch]81e1c87f 8945ec mov dword ptr [ebp-14h],eax81e1c882 8d45dc lea eax,[ebp-24h]81e1c885 50 push eax81e1c886 6a02 push 281e1c888 6a00 push 081e1c88a 6800c9a681 push offset nt!KERNEL_AUDIT_API_PSSETLOADIMAGENOTIFYROUTINE (81a6c900)81e1c88f 52 push edx81e1c890 51 push ecx81e1c891 c745e404000000 mov dword ptr [ebp-1Ch],481e1c898 c745f404000000 mov dword ptr [ebp-0Ch],481e1c89f e82ce6c9ff call nt!EtwWrite (81abaed0)nt!PsSetLoadImageNotifyRoutine+0xbe:81e1c8a4 8b4dfc mov ecx,dword ptr [ebp-4]81e1c8a7 8bc6 mov eax,esi81e1c8a9 5e pop esi81e1c8aa 33cd xor ecx,ebp81e1c8ac 5b pop ebx81e1c8ad e86669d8ff call nt!__security_check_cookie (81ba3218)81e1c8b2 8be5 mov esp,ebp81e1c8b4 5d pop ebp81e1c8b5 c20400 ret 4nt!PsSetLoadImageNotifyRoutine+0xd2:81e1c8b8 83c604 add esi,481e1c8bb 83c704 add edi,481e1c8be 81fe00010000 cmp esi,100h81e1c8c4 0f8251ffffff jb nt!PsSetLoadImageNotifyRoutine+0x35 (81e1c81b)nt!PsSetLoadImageNotifyRoutine+0xe4:81e1c8ca e9bf1c0a00 jmp nt! ?? ::NNGAKEGL::`string'+0x69b82 (81ebe58e)nt! ?? ::NNGAKEGL::`string'+0x69b78:81ebe584 be9a0000c0 mov esi,0C000009Ah81ebe589 e9bde2f5ff jmp nt!PsSetLoadImageNotifyRoutine+0x65 (81e1c84b)nt! ?? ::NNGAKEGL::`string'+0x69b82:81ebe58e 6a00 push 081ebe590 53 push ebx81ebe591 e88a3addff call nt!ExFreePoolWithTag (81c92020)81ebe596 be9a0000c0 mov esi,0C000009Ah81ebe59b e9aae2f5ff jmp nt!PsSetLoadImageNotifyRoutine+0x64 (81e1c84a)
    Win10 64 位 PsSetLoadImageNotifyRoutinekd> uf PsSetLoadImageNotifyRoutinent!PsSetLoadImageNotifyRoutine:fffff800`a09a42d4 48895c2410 mov qword ptr [rsp+10h],rbxfffff800`a09a42d9 4889742418 mov qword ptr [rsp+18h],rsifffff800`a09a42de 57 push rdifffff800`a09a42df 4883ec70 sub rsp,70hfffff800`a09a42e3 488b056e9ddaff mov rax,qword ptr [nt!_security_cookie (fffff800`a074e058)]fffff800`a09a42ea 4833c4 xor rax,rspfffff800`a09a42ed 4889442460 mov qword ptr [rsp+60h],raxfffff800`a09a42f2 33d2 xor edx,edxfffff800`a09a42f4 488bf1 mov rsi,rcxfffff800`a09a42f7 e814030000 call nt!ExAllocateCallBack (fffff800`a09a4610)fffff800`a09a42fc 488bf8 mov rdi,raxfffff800`a09a42ff 4885c0 test rax,raxfffff800`a09a4302 0f8452790900 je nt! ?? ::NNGAKEGL::`string'+0x674ca (fffff800`a0a3bc5a)nt!PsSetLoadImageNotifyRoutine+0x34:fffff800`a09a4308 33db xor ebx,ebxnt!PsSetLoadImageNotifyRoutine+0x36:fffff800`a09a430a 488d0d6f0adfff lea rcx,[nt!PspLoadImageNotifyRoutine (fffff800`a0794d80)]fffff800`a09a4311 4533c0 xor r8d,r8dfffff800`a09a4314 488d0cd9 lea rcx,[rcx+rbx*8]fffff800`a09a4318 488bd7 mov rdx,rdifffff800`a09a431b e870ecbfff call nt!ExCompareExchangeCallBack (fffff800`a05a2f90)fffff800`a09a4320 84c0 test al,alfffff800`a09a4322 0f849f000000 je nt!PsSetLoadImageNotifyRoutine+0xf3 (fffff800`a09a43c7)nt!PsSetLoadImageNotifyRoutine+0x54:fffff800`a09a4328 f0ff05a94a1d00 lock inc dword ptr [nt!PspLoadImageNotifyRoutineCount (fffff800`a0b78dd8)]fffff800`a09a432f 8b0503471d00 mov eax,dword ptr [nt!PspNotifyEnableMask (fffff800`a0b78a38)]fffff800`a09a4335 a801 test al,1fffff800`a09a4337 7509 jne nt!PsSetLoadImageNotifyRoutine+0x6e (fffff800`a09a4342)nt!PsSetLoadImageNotifyRoutine+0x65:fffff800`a09a4339 f00fba2df6461d0000 lock bts dword ptr [nt!PspNotifyEnableMask (fffff800`a0b78a38)],0nt!PsSetLoadImageNotifyRoutine+0x6e:fffff800`a09a4342 33db xor ebx,ebxnt!PsSetLoadImageNotifyRoutine+0x70:fffff800`a09a4344 488b0d75e9daff mov rcx,qword ptr [nt!EtwApiCallsProvRegHandle (fffff800`a0752cc0)]fffff800`a09a434b 895c2430 mov dword ptr [rsp+30h],ebxfffff800`a09a434f 4889742438 mov qword ptr [rsp+38h],rsifffff800`a09a4354 4885c9 test rcx,rcxfffff800`a09a4357 744d je nt!PsSetLoadImageNotifyRoutine+0xd2 (fffff800`a09a43a6)nt!PsSetLoadImageNotifyRoutine+0x85:fffff800`a09a4359 8364244c00 and dword ptr [rsp+4Ch],0fffff800`a09a435e 488d442438 lea rax,[rsp+38h]fffff800`a09a4363 8364245c00 and dword ptr [rsp+5Ch],0fffff800`a09a4368 488d151902d1ff lea rdx,[nt!KERNEL_AUDIT_API_PSSETLOADIMAGENOTIFYROUTINE (fffff800`a06b4588)]fffff800`a09a436f 4889442440 mov qword ptr [rsp+40h],raxfffff800`a09a4374 41b902000000 mov r9d,2fffff800`a09a437a 488d442430 lea rax,[rsp+30h]fffff800`a09a437f c744244808000000 mov dword ptr [rsp+48h],8fffff800`a09a4387 4889442450 mov qword ptr [rsp+50h],raxfffff800`a09a438c 4533c0 xor r8d,r8dfffff800`a09a438f 488d442440 lea rax,[rsp+40h]fffff800`a09a4394 c744245804000000 mov dword ptr [rsp+58h],4fffff800`a09a439c 4889442420 mov qword ptr [rsp+20h],raxfffff800`a09a43a1 e8daafb5ff call nt!EtwWrite (fffff800`a04ff380)nt!PsSetLoadImageNotifyRoutine+0xd2:fffff800`a09a43a6 8bc3 mov eax,ebxfffff800`a09a43a8 488b4c2460 mov rcx,qword ptr [rsp+60h]fffff800`a09a43ad 4833cc xor rcx,rspfffff800`a09a43b0 e80bb4c0ff call nt!_security_check_cookie (fffff800`a05af7c0)fffff800`a09a43b5 4c8d5c2470 lea r11,[rsp+70h]fffff800`a09a43ba 498b5b18 mov rbx,qword ptr [r11+18h]fffff800`a09a43be 498b7320 mov rsi,qword ptr [r11+20h]fffff800`a09a43c2 498be3 mov rsp,r11fffff800`a09a43c5 5f pop rdifffff800`a09a43c6 c3 retnt!PsSetLoadImageNotifyRoutine+0xf3:fffff800`a09a43c7 ffc3 inc ebxfffff800`a09a43c9 83fb40 cmp ebx,40hfffff800`a09a43cc 0f8238ffffff jb nt!PsSetLoadImageNotifyRoutine+0x36 (fffff800`a09a430a)nt!PsSetLoadImageNotifyRoutine+0xfe:fffff800`a09a43d2 e979780900 jmp nt! ?? ::NNGAKEGL::`string'+0x674c0 (fffff800`a0a3bc50)nt! ?? ::NNGAKEGL::`string'+0x674c0:fffff800`a0a3bc50 33d2 xor edx,edxfffff800`a0a3bc52 488bcf mov rcx,rdifffff800`a0a3bc55 e8a623c7ff call nt!ExFreePoolWithTag (fffff800`a06ae000)nt! ?? ::NNGAKEGL::`string'+0x674ca:fffff800`a0a3bc5a bb9a0000c0 mov ebx,0C000009Ahfffff800`a0a3bc5f e9e086f6ff jmp nt!PsSetLoadImageNotifyRoutine+0x70 (fffff800`a09a4344)
    1 留言 2019-03-23 20:19:06 奖励10点积分
  • 枚举并删除系统上PsSetCreateProcessNotifyRoutine回调

    背景我们学习内核 Rootkit 编程,那么肯定会接触到各种无 HOOK 回调函数的设置,这些回调函数都是官方为我们做好的接口,我们直接调用就好。这些回调使用方便,运行在底层,功能强大,而且非常稳定。很多杀软、游戏保护等就是设置这些回调,实现对计算机的监控的。
    既然可以设置回调,自然也可以删除回调。如果是自己程序设置的回调,当然可以很容易删除。但是,我们要做的是要枚举系统上存在的回调,不管是不是自己程序创建的,然后,并对这些回调进行删除,使其失效。
    本文要介绍的是枚举并删除系统上 PsSetCreateProcessNotifyRoutine 回调,支持 32 位和 64 位、Win7 到 Win10 全平台系统。现在,我把实现的过程和原理整理成文档,分享给大家。
    实现原理我们注册的进程回调,会存储在一个名为 PspCreateProcessNotifyRoutine 的数组里。 PspCreateProcessNotifyRoutine 可以理解成一个 PVOID 数组,它存储着系统里所有 PsSetCreateProcessNotifyRoutine 进程回调函数地址的加密地址。PspCreateProcessNotifyRoutine数组里的数据是加密的,要经过解密操作才可以获取正确的数据。
    PspCreateProcessNotifyRoutine 数组地址的获取首先,我们需要获取 PspCreateProcessNotifyRoutine 的地址。我们可以借助 WinDbg 帮助我们进行内核调试,下面是我们借助 WinDbg 逆向 Win10 x64 内核函数 PspSetCreateProcessNotifyRoutine 的代码:
    nt!PspSetCreateProcessNotifyRoutine+0x4c:fffff801`54b3b57c 33ff xor edi,edifffff801`54b3b57e 4c8d3dfb0bdfff lea r15,[nt!PspCreateProcessNotifyRoutine (fffff801`5492c180)]
    我们从上面发现,函数中会调用到 PspCreateProcessNotifyRoutine 的地址。所以,在 64 位系统中,我们可以通过扫描内存特征码,从而获取数组PspCreateProcessNotifyRoutine 的 4 字节偏移,再计算出它的地址。在 32 位系统中,通过扫描内存特征码,就可以直接获取 PspCreateProcessNotifyRoutine 的地址了。注意的是:不同系统上,特征码也会不同。下面是我们总结的特征码:




    Win7
    win8.1
    win10




    32 位
    C7450C
    B8
    BB


    64 位
    4C8D35
    4C8D3D
    4C8D3D



    其中,内核函数 PspSetCreateProcessNotifyRoutine 并不是导出函数,所以不能直接获取它的函数地址。使用WinDbg 逆向 PsSetCreateProcessNotifyRoutine 函数的代码如下(Win10 x64 系统):
    nt!PsSetCreateProcessNotifyRoutine:fffff800`042cb3c0 4533c0 xor r8d,r8dfffff800`042cb3c3 e9e8fdffff jmp nt!PspSetCreateProcessNotifyRoutine (fffff800`042cb1b0)
    我们从上面代码发现,内核函数 PsSetCreateProcessNotifyRoutine 里会调用到内核函数 PspSetCreateProcessNotifyRoutine。所以,在 32 位和 64 位系统中,我们可以通过扫描内存特征码,从而获取 PspSetCreateProcessNotifyRoutine 的 4 字节偏移,再计算出它的地址。注意的是:不同系统上,特征码也会不同。下面是我们总结的特征码:




    Win7
    win8.1
    win10




    32 位
    E8
    E8
    E8


    64 位
    E9
    E9
    E9



    要就是说,获取 PspCreateProcessNotifyRoutine 地址可以分成两步:

    首先,通过扫描特征码,从 PsSetCreateProcessNotifyRoutine 函数中获取 PspSetCreateProcessNotifyRoutine 函数的地址
    然后,通过扫描特征码,从 PspSetCreateProcessNotifyRoutine 函数中获取 PspCreateProcessNotifyRoutine 数组的地址

    那么,特征码的确定就变得至关重要了。
    PspCreateProcessNotifyRoutine 里数据的解密我们上面说,PspCreateProcessNotifyRoutine 里的数据是加密的,在 64 位系统和 32 位系统上的加密方式是不相同的,自然解密方式也不同。现在,我们分别介绍 32 位系统和 64 位系统下的解密方式。
    对于 32 位系统来说:PspCreateProcessNotifyRoutine 是一个 4 字节无符号类型的数组,数组大小最大为 8。我们使用 PspCreateProcessNotifyRoutine[i] 表示数组中的值,那么,32 位系统下的解密方式为:

    首先,数组的值 PspCreateProcessNotifyRoutine[i] 位运算“与” 0xFFFFFFF8
    然后,“与”运算之后的结果值再加上 4,结果就是一个存储着回调函数地址的地址

    对于 64 位系统来说:PspCreateProcessNotifyRoutine 是一个 8 字节无符号类型的数组,数组大小最大为 64。我们使用 PspCreateProcessNotifyRoutine[i] 表示数组中的值,那么,64 位系统下的解密方式为:
    数组的值 PspCreateProcessNotifyRoutine[i] 位运算“与” 0xFFFFFFFFFFFFFFF8,结果就是一个存储着回调函数地址的地址。
    删除回调我们可以通过上述介绍的方法,枚举系统中的回调函数。那么,要删除回调函数可以有 3 种方式:

    可以直接调用 PsSetCreateProcessNotifyRoutine 函数,传入回调函数地址,并设置删除回调函数标志为 TRUE,即可删除回调
    修改 PspCreateProcessNotifyRoutine 数组中的数据,使其指向我们自己定义的空回调函数地址。这样,当触发回调函数的时候,执行的是我们自己的空回调函数
    修改回调函数的前几字节内存数据,写入直接返回指令 RET,不进行任何操作

    编码实现遍历回调// 遍历回调BOOLEAN EnumNotifyRoutine(){ ULONG i = 0; PVOID pPspCreateProcessNotifyRoutineAddress = NULL; PVOID pNotifyRoutineAddress = NULL; // 获取 PspCreateProcessNotifyRoutine 数组地址 pPspCreateProcessNotifyRoutineAddress = GetPspCreateProcessNotifyRoutine(); if (NULL == pPspCreateProcessNotifyRoutineAddress) { DbgPrint("GetPspCreateProcessNotifyRoutine Error!\n"); return FALSE; } DbgPrint("pPspCreateProcessNotifyRoutineAddress=0x%p\n", pPspCreateProcessNotifyRoutineAddress); // 获取回调地址并解密#ifdef _WIN64 for (i = 0; i < 64; i++) { pNotifyRoutineAddress = *(PVOID *)((PUCHAR)pPspCreateProcessNotifyRoutineAddress + sizeof(PVOID) * i); pNotifyRoutineAddress = (PVOID)((ULONG64)pNotifyRoutineAddress & 0xfffffffffffffff8); if (MmIsAddressValid(pNotifyRoutineAddress)) { pNotifyRoutineAddress = *(PVOID *)pNotifyRoutineAddress; DbgPrint("[%d]ullNotifyRoutine=0x%p\n", i, pNotifyRoutineAddress); } }#else for (i = 0; i < 8; i++) { pNotifyRoutineAddress = *(PVOID *)((PUCHAR)pPspCreateProcessNotifyRoutineAddress + sizeof(PVOID) * i); pNotifyRoutineAddress = (PVOID)((ULONG)pNotifyRoutineAddress & 0xfffffff8); if (MmIsAddressValid(pNotifyRoutineAddress)) { pNotifyRoutineAddress = *(PVOID *)((PUCHAR)pNotifyRoutineAddress + 4); DbgPrint("[%d]ullNotifyRoutine=0x%p\n", i, pNotifyRoutineAddress); } }#endif return TRUE;}
    移除回调// 移除回调NTSTATUS RemoveNotifyRoutine(PVOID pNotifyRoutineAddress){ NTSTATUS status = PsSetCreateProcessNotifyRoutine((PCREATE_PROCESS_NOTIFY_ROUTINE)pNotifyRoutineAddress, TRUE); if (!NT_SUCCESS(status)) { ShowError("PsSetCreateProcessNotifyRoutine", status); } return status;}
    获取 PspCreateProcessNotifyRoutine 数组地址// 获取 PspCreateProcessNotifyRoutine 数组地址PVOID GetPspCreateProcessNotifyRoutine(){ PVOID pPspCreateProcessNotifyRoutineAddress = NULL; RTL_OSVERSIONINFOW osInfo = { 0 }; UCHAR pFirstSpecialData[50] = { 0 }; ULONG ulFirstSpecialDataSize = 0; UCHAR pSecondSpecialData[50] = { 0 }; ULONG ulSecondSpecialDataSize = 0; // 获取系统版本信息, 判断系统版本 RtlGetVersion(&osInfo); if (6 == osInfo.dwMajorVersion) { if (1 == osInfo.dwMinorVersion) { // Win7#ifdef _WIN64 // 64 位 // E9 pFirstSpecialData[0] = 0xE9; ulFirstSpecialDataSize = 1; // 4C8D35 pSecondSpecialData[0] = 0x4C; pSecondSpecialData[1] = 0x8D; pSecondSpecialData[2] = 0x35; ulSecondSpecialDataSize = 3;#else // 32 位 // E8 pFirstSpecialData[0] = 0xE8; ulFirstSpecialDataSize = 1; // C7450C pSecondSpecialData[0] = 0xC7; pSecondSpecialData[1] = 0x45; pSecondSpecialData[2] = 0x0C; ulSecondSpecialDataSize = 3;#endif } else if (2 == osInfo.dwMinorVersion) { // Win8#ifdef _WIN64 // 64 位#else // 32 位#endif } else if (3 == osInfo.dwMinorVersion) { // Win8.1#ifdef _WIN64 // 64 位 // E9 pFirstSpecialData[0] = 0xE9; ulFirstSpecialDataSize = 1; // 4C8D3D pSecondSpecialData[0] = 0x4C; pSecondSpecialData[1] = 0x8D; pSecondSpecialData[2] = 0x3D; ulSecondSpecialDataSize = 3;#else // 32 位 // E8 pFirstSpecialData[0] = 0xE8; ulFirstSpecialDataSize = 1; // B8 pSecondSpecialData[0] = 0xB8; ulSecondSpecialDataSize = 1;#endif } } else if (10 == osInfo.dwMajorVersion) { // Win10#ifdef _WIN64 // 64 位 // E9 pFirstSpecialData[0] = 0xE9; ulFirstSpecialDataSize = 1; // 4C8D3D pSecondSpecialData[0] = 0x4C; pSecondSpecialData[1] = 0x8D; pSecondSpecialData[2] = 0x3D; ulSecondSpecialDataSize = 3;#else // 32 位 // E8 pFirstSpecialData[0] = 0xE8; ulFirstSpecialDataSize = 1; // BB pSecondSpecialData[0] = 0xBB; ulSecondSpecialDataSize = 1;#endif } // 根据特征码获取地址 pPspCreateProcessNotifyRoutineAddress = SearchPspCreateProcessNotifyRoutine(pFirstSpecialData, ulFirstSpecialDataSize, pSecondSpecialData, ulSecondSpecialDataSize); return pPspCreateProcessNotifyRoutineAddress;}
    根据特征码获取 PspCreateProcessNotifyRoutine 数组地址// 根据特征码获取 PspCreateProcessNotifyRoutine 数组地址PVOID SearchPspCreateProcessNotifyRoutine(PUCHAR pFirstSpecialData, ULONG ulFirstSpecialDataSize, PUCHAR pSecondSpecialData, ULONG ulSecondSpecialDataSize){ UNICODE_STRING ustrFuncName; PVOID pAddress = NULL; LONG lOffset = 0; PVOID pPsSetCteateProcessNotifyRoutine = NULL; PVOID pPspSetCreateProcessNotifyRoutineAddress = NULL; PVOID pPspCreateProcessNotifyRoutineAddress = NULL; // 先获取 PsSetCreateProcessNotifyRoutine 函数地址 RtlInitUnicodeString(&ustrFuncName, L"PsSetCreateProcessNotifyRoutine"); pPsSetCteateProcessNotifyRoutine = MmGetSystemRoutineAddress(&ustrFuncName); if (NULL == pPsSetCteateProcessNotifyRoutine) { ShowError("MmGetSystemRoutineAddress", 0); return pPspCreateProcessNotifyRoutineAddress; } // 然后, 查找 PspSetCreateProcessNotifyRoutine 函数地址 pAddress = SearchMemory(pPsSetCteateProcessNotifyRoutine, (PVOID)((PUCHAR)pPsSetCteateProcessNotifyRoutine + 0xFF), pFirstSpecialData, ulFirstSpecialDataSize); if (NULL == pAddress) { ShowError("SearchMemory1", 0); return pPspCreateProcessNotifyRoutineAddress; } // 获取偏移数据, 并计算地址 lOffset = *(PLONG)pAddress; pPspSetCreateProcessNotifyRoutineAddress = (PVOID)((PUCHAR)pAddress + sizeof(LONG) + lOffset); // 最后, 查找 PspCreateProcessNotifyRoutine 地址 pAddress = SearchMemory(pPspSetCreateProcessNotifyRoutineAddress, (PVOID)((PUCHAR)pPspSetCreateProcessNotifyRoutineAddress + 0xFF), pSecondSpecialData, ulSecondSpecialDataSize); if (NULL == pAddress) { ShowError("SearchMemory2", 0); return pPspCreateProcessNotifyRoutineAddress; } // 获取地址#ifdef _WIN64 // 64 位先获取偏移, 再计算地址 lOffset = *(PLONG)pAddress; pPspCreateProcessNotifyRoutineAddress = (PVOID)((PUCHAR)pAddress + sizeof(LONG) + lOffset);#else // 32 位直接获取地址 pPspCreateProcessNotifyRoutineAddress = *(PVOID *)pAddress;#endif return pPspCreateProcessNotifyRoutineAddress;}
    指定内存区域的特征码扫描// 指定内存区域的特征码扫描PVOID SearchMemory(PVOID pStartAddress, PVOID pEndAddress, PUCHAR pMemoryData, ULONG ulMemoryDataSize){ PVOID pAddress = NULL; PUCHAR i = NULL; ULONG m = 0; // 扫描内存 for (i = (PUCHAR)pStartAddress; i < (PUCHAR)pEndAddress; i++) { // 判断特征码 for (m = 0; m < ulMemoryDataSize; m++) { if (*(PUCHAR)(i + m) != pMemoryData[m]) { break; } } // 判断是否找到符合特征码的地址 if (m >= ulMemoryDataSize) { // 找到特征码位置, 获取紧接着特征码的下一地址 pAddress = (PVOID)(i + ulMemoryDataSize); break; } } return pAddress;}
    程序测试在 Win7 32 位系统下,驱动程序正常执行:

    在 Win8.1 32 位系统下,驱动程序正常执行:

    在 Win10 32 位系统下,驱动程序正常执行:

    在 Win7 64 位系统下,驱动程序正常执行:

    在 Win8.1 64 位系统下,驱动程序正常执行:

    在 Win10 64 位系统下,驱动程序正常执行:

    总结要理解清楚获取 PspCreateProcessNotifyRoutine 地址的流程,其中,不同系统的内存特征码是不同的,要注意区分。大家也不用记忆这些特征码,如果需要用到,可以随时使用 WinDbg 来进行逆向查看就好。
    而且,不同位数系统中,对 PspCreateProcessNotifyRoutine 数组中的值解密方式也不相同,这个需要区分开来。
    删除回调常用就有 3 种方式,自己根据需要选择一种使用即可。
    参考参考自《Windows黑客编程技术详解》一书
    附录Win7 32 位 PspSetCreateProcessNotifyRoutinelkd> uf PspSetCreateProcessNotifyRoutinent!PspSetCreateProcessNotifyRoutine:83fa573b 8bff mov edi,edi83fa573d 55 push ebp83fa573e 8bec mov ebp,esp83fa5740 807d0c00 cmp byte ptr [ebp+0Ch],083fa5744 53 push ebx83fa5745 56 push esi83fa5746 57 push edi83fa5747 0f84fa000000 je nt!PspSetCreateProcessNotifyRoutine+0x10a (83fa5847)nt!PspSetCreateProcessNotifyRoutine+0x12:83fa574d 648b3524010000 mov esi,dword ptr fs:[124h]83fa5754 66ff8e84000000 dec word ptr [esi+84h]83fa575b 33db xor ebx,ebx83fa575d c7450ce032f583 mov dword ptr [ebp+0Ch],offset nt!PspCreateProcessNotifyRoutine (83f532e0)nt!PspSetCreateProcessNotifyRoutine+0x29:83fa5764 ff750c push dword ptr [ebp+0Ch]83fa5767 e894bb0d00 call nt!ExReferenceCallBackBlock (84081300)83fa576c 8bf8 mov edi,eax83fa576e 85ff test edi,edi83fa5770 7439 je nt!PspSetCreateProcessNotifyRoutine+0x6e (83fa57ab)nt!PspSetCreateProcessNotifyRoutine+0x37:83fa5772 8b4f08 mov ecx,dword ptr [edi+8]83fa5775 e8e31ef2ff call nt!ExGetCallBackBlockRoutine (83ec765d)83fa577a 3b4508 cmp eax,dword ptr [ebp+8]83fa577d 7522 jne nt!PspSetCreateProcessNotifyRoutine+0x64 (83fa57a1)nt!PspSetCreateProcessNotifyRoutine+0x44:83fa577f 85c9 test ecx,ecx83fa5781 7509 jne nt!PspSetCreateProcessNotifyRoutine+0x4f (83fa578c)nt!PspSetCreateProcessNotifyRoutine+0x48:83fa5783 384d10 cmp byte ptr [ebp+10h],cl83fa5786 7519 jne nt!PspSetCreateProcessNotifyRoutine+0x64 (83fa57a1)nt!PspSetCreateProcessNotifyRoutine+0x4d:83fa5788 eb08 jmp nt!PspSetCreateProcessNotifyRoutine+0x55 (83fa5792)nt!PspSetCreateProcessNotifyRoutine+0x4f:83fa578c 807d1000 cmp byte ptr [ebp+10h],083fa5790 740f je nt!PspSetCreateProcessNotifyRoutine+0x64 (83fa57a1)nt!PspSetCreateProcessNotifyRoutine+0x55:83fa5792 8b450c mov eax,dword ptr [ebp+0Ch]83fa5795 57 push edi83fa5796 33c9 xor ecx,ecx83fa5798 e8abfeffff call nt!ExCompareExchangeCallBack (83fa5648)83fa579d 84c0 test al,al83fa579f 7547 jne nt!PspSetCreateProcessNotifyRoutine+0xab (83fa57e8)nt!PspSetCreateProcessNotifyRoutine+0x64:83fa57a1 8b450c mov eax,dword ptr [ebp+0Ch]83fa57a4 8bcf mov ecx,edi83fa57a6 e889bc0d00 call nt!ExDereferenceCallBackBlock (84081434)nt!PspSetCreateProcessNotifyRoutine+0x6e:83fa57ab 83450c04 add dword ptr [ebp+0Ch],483fa57af 43 inc ebx83fa57b0 83fb40 cmp ebx,40h83fa57b3 72af jb nt!PspSetCreateProcessNotifyRoutine+0x29 (83fa5764)nt!PspSetCreateProcessNotifyRoutine+0x78:83fa57b5 66ff8684000000 inc word ptr [esi+84h]83fa57bc 0fb78684000000 movzx eax,word ptr [esi+84h]83fa57c3 6685c0 test ax,ax83fa57c6 7516 jne nt!PspSetCreateProcessNotifyRoutine+0xa1 (83fa57de)nt!PspSetCreateProcessNotifyRoutine+0x8b:83fa57c8 8d4640 lea eax,[esi+40h]83fa57cb 3900 cmp dword ptr [eax],eax83fa57cd 740f je nt!PspSetCreateProcessNotifyRoutine+0xa1 (83fa57de)nt!PspSetCreateProcessNotifyRoutine+0x92:83fa57cf 6683be8600000000 cmp word ptr [esi+86h],083fa57d7 7505 jne nt!PspSetCreateProcessNotifyRoutine+0xa1 (83fa57de)nt!PspSetCreateProcessNotifyRoutine+0x9c:83fa57d9 e8a714e9ff call nt!KiCheckForKernelApcDelivery (83e36c85)nt!PspSetCreateProcessNotifyRoutine+0xa1:83fa57de b87a0000c0 mov eax,0C000007Ah83fa57e3 e9c5000000 jmp nt!PspSetCreateProcessNotifyRoutine+0x170 (83fa58ad)nt!PspSetCreateProcessNotifyRoutine+0xab:83fa57e8 83c9ff or ecx,0FFFFFFFFh83fa57eb 807d1000 cmp byte ptr [ebp+10h],083fa57ef b8e433f583 mov eax,offset nt!PspCreateProcessNotifyRoutineCount (83f533e4)83fa57f4 7405 je nt!PspSetCreateProcessNotifyRoutine+0xbe (83fa57fb)nt!PspSetCreateProcessNotifyRoutine+0xb9:83fa57f6 b8e033f583 mov eax,offset nt!PspCreateProcessNotifyRoutineExCount (83f533e0)nt!PspSetCreateProcessNotifyRoutine+0xbe:83fa57fb f00fc108 lock xadd dword ptr [eax],ecx83fa57ff 8d049de032f583 lea eax,nt!PspCreateProcessNotifyRoutine (83f532e0)[ebx*4]83fa5806 8bcf mov ecx,edi83fa5808 e827bc0d00 call nt!ExDereferenceCallBackBlock (84081434)83fa580d 66ff8684000000 inc word ptr [esi+84h]83fa5814 0fb78684000000 movzx eax,word ptr [esi+84h]83fa581b 6685c0 test ax,ax83fa581e 7516 jne nt!PspSetCreateProcessNotifyRoutine+0xf9 (83fa5836)nt!PspSetCreateProcessNotifyRoutine+0xe3:83fa5820 8d4640 lea eax,[esi+40h]83fa5823 3900 cmp dword ptr [eax],eax83fa5825 740f je nt!PspSetCreateProcessNotifyRoutine+0xf9 (83fa5836)nt!PspSetCreateProcessNotifyRoutine+0xea:83fa5827 6683be8600000000 cmp word ptr [esi+86h],083fa582f 7505 jne nt!PspSetCreateProcessNotifyRoutine+0xf9 (83fa5836)nt!PspSetCreateProcessNotifyRoutine+0xf4:83fa5831 e84f14e9ff call nt!KiCheckForKernelApcDelivery (83e36c85)nt!PspSetCreateProcessNotifyRoutine+0xf9:83fa5836 8bcf mov ecx,edi83fa5838 e83a251700 call nt!ExWaitForCallBacks (84117d77)83fa583d 57 push edi83fa583e e8c88a0e00 call nt!AlpcpFreeBuffer (8408e30b)nt!PspSetCreateProcessNotifyRoutine+0x106:83fa5843 33c0 xor eax,eax83fa5845 eb66 jmp nt!PspSetCreateProcessNotifyRoutine+0x170 (83fa58ad)nt!PspSetCreateProcessNotifyRoutine+0x10a:83fa5847 807d1000 cmp byte ptr [ebp+10h],083fa584b 7413 je nt!PspSetCreateProcessNotifyRoutine+0x123 (83fa5860)nt!PspSetCreateProcessNotifyRoutine+0x110:83fa584d ff7508 push dword ptr [ebp+8]83fa5850 e82bb0fdff call nt!MmVerifyCallbackFunction (83f80880)83fa5855 85c0 test eax,eax83fa5857 7507 jne nt!PspSetCreateProcessNotifyRoutine+0x123 (83fa5860)nt!PspSetCreateProcessNotifyRoutine+0x11c:83fa5859 b8220000c0 mov eax,0C0000022h83fa585e eb4d jmp nt!PspSetCreateProcessNotifyRoutine+0x170 (83fa58ad)nt!PspSetCreateProcessNotifyRoutine+0x123:83fa5860 33c0 xor eax,eax83fa5862 384510 cmp byte ptr [ebp+10h],al83fa5865 0f95c0 setne al83fa5868 50 push eax83fa5869 ff7508 push dword ptr [ebp+8]83fa586c e8a8fdffff call nt!ExAllocateCallBack (83fa5619)83fa5871 8bd8 mov ebx,eax83fa5873 85db test ebx,ebx83fa5875 7507 jne nt!PspSetCreateProcessNotifyRoutine+0x141 (83fa587e)nt!PspSetCreateProcessNotifyRoutine+0x13a:83fa5877 b89a0000c0 mov eax,0C000009Ah83fa587c eb2f jmp nt!PspSetCreateProcessNotifyRoutine+0x170 (83fa58ad)nt!PspSetCreateProcessNotifyRoutine+0x141:83fa587e bee032f583 mov esi,offset nt!PspCreateProcessNotifyRoutine (83f532e0)83fa5883 33ff xor edi,edint!PspSetCreateProcessNotifyRoutine+0x148:83fa5885 6a00 push 083fa5887 8bcb mov ecx,ebx83fa5889 8bc6 mov eax,esi83fa588b e8b8fdffff call nt!ExCompareExchangeCallBack (83fa5648)83fa5890 84c0 test al,al83fa5892 7520 jne nt!PspSetCreateProcessNotifyRoutine+0x177 (83fa58b4)nt!PspSetCreateProcessNotifyRoutine+0x157:83fa5894 83c704 add edi,483fa5897 83c604 add esi,483fa589a 81ff00010000 cmp edi,100h83fa58a0 72e3 jb nt!PspSetCreateProcessNotifyRoutine+0x148 (83fa5885)nt!PspSetCreateProcessNotifyRoutine+0x165:83fa58a2 53 push ebx83fa58a3 e8638a0e00 call nt!AlpcpFreeBuffer (8408e30b)83fa58a8 b80d0000c0 mov eax,0C000000Dhnt!PspSetCreateProcessNotifyRoutine+0x170:83fa58ad 5f pop edi83fa58ae 5e pop esi83fa58af 5b pop ebx83fa58b0 5d pop ebp83fa58b1 c20c00 ret 0Chnt!PspSetCreateProcessNotifyRoutine+0x177:83fa58b4 33c9 xor ecx,ecx83fa58b6 41 inc ecx83fa58b7 807d1000 cmp byte ptr [ebp+10h],083fa58bb 7525 jne nt!PspSetCreateProcessNotifyRoutine+0x1a5 (83fa58e2)nt!PspSetCreateProcessNotifyRoutine+0x180:83fa58bd b8e433f583 mov eax,offset nt!PspCreateProcessNotifyRoutineCount (83f533e4)83fa58c2 f00fc108 lock xadd dword ptr [eax],ecx83fa58c6 a19830f583 mov eax,dword ptr [nt!PspNotifyEnableMask (83f53098)]83fa58cb a802 test al,283fa58cd 0f8570ffffff jne nt!PspSetCreateProcessNotifyRoutine+0x106 (83fa5843)nt!PspSetCreateProcessNotifyRoutine+0x196:83fa58d3 b89830f583 mov eax,offset nt!PspNotifyEnableMask (83f53098)83fa58d8 f00fba2801 lock bts dword ptr [eax],183fa58dd e961ffffff jmp nt!PspSetCreateProcessNotifyRoutine+0x106 (83fa5843)nt!PspSetCreateProcessNotifyRoutine+0x1a5:83fa58e2 b8e033f583 mov eax,offset nt!PspCreateProcessNotifyRoutineExCount (83f533e0)83fa58e7 f00fc108 lock xadd dword ptr [eax],ecx83fa58eb a19830f583 mov eax,dword ptr [nt!PspNotifyEnableMask (83f53098)]83fa58f0 a804 test al,483fa58f2 0f854bffffff jne nt!PspSetCreateProcessNotifyRoutine+0x106 (83fa5843)nt!PspSetCreateProcessNotifyRoutine+0x1bb:83fa58f8 b89830f583 mov eax,offset nt!PspNotifyEnableMask (83f53098)83fa58fd f00fba2802 lock bts dword ptr [eax],283fa5902 e93cffffff jmp nt!PspSetCreateProcessNotifyRoutine+0x106 (83fa5843)
    Win7 64 位 PspSetCreateProcessNotifyRoutinelkd> uf PspSetCreateProcessNotifyRoutinent!PspSetCreateProcessNotifyRoutine:fffff800`042be1b0 48895c2408 mov qword ptr [rsp+8],rbxfffff800`042be1b5 48896c2410 mov qword ptr [rsp+10h],rbpfffff800`042be1ba 4889742418 mov qword ptr [rsp+18h],rsifffff800`042be1bf 57 push rdifffff800`042be1c0 4154 push r12fffff800`042be1c2 4155 push r13fffff800`042be1c4 4156 push r14fffff800`042be1c6 4157 push r15fffff800`042be1c8 4883ec20 sub rsp,20hfffff800`042be1cc 4533e4 xor r12d,r12dfffff800`042be1cf 418ae8 mov bpl,r8bfffff800`042be1d2 4c8be9 mov r13,rcxfffff800`042be1d5 418d5c2401 lea ebx,[r12+1]fffff800`042be1da 413ad4 cmp dl,r12bfffff800`042be1dd 0f840e010000 je nt!PspSetCreateProcessNotifyRoutine+0x141 (fffff800`042be2f1)nt!PspSetCreateProcessNotifyRoutine+0x33:fffff800`042be1e3 65488b3c2588010000 mov rdi,qword ptr gs:[188h]fffff800`042be1ec 83c8ff or eax,0FFFFFFFFhfffff800`042be1ef 660187c4010000 add word ptr [rdi+1C4h],axfffff800`042be1f6 4c8d358395d6ff lea r14,[nt!PspCreateProcessNotifyRoutine (fffff800`04027780)]nt!PspSetCreateProcessNotifyRoutine+0x4d:fffff800`042be1fd 418bc4 mov eax,r12dfffff800`042be200 4d8d3cc6 lea r15,[r14+rax*8]fffff800`042be204 498bcf mov rcx,r15fffff800`042be207 e8f4ecedff call nt!ExReferenceCallBackBlock (fffff800`0419cf00)fffff800`042be20c 33d2 xor edx,edxfffff800`042be20e 488bf0 mov rsi,raxfffff800`042be211 483bc2 cmp rax,rdxfffff800`042be214 743d je nt!PspSetCreateProcessNotifyRoutine+0xa3 (fffff800`042be253)nt!PspSetCreateProcessNotifyRoutine+0x66:fffff800`042be216 488bc8 mov rcx,raxfffff800`042be219 e89eb4c0ff call nt!ExGetCallBackBlockRoutine (fffff800`03ec96bc)fffff800`042be21e 493bc5 cmp rax,r13fffff800`042be221 7523 jne nt!PspSetCreateProcessNotifyRoutine+0x96 (fffff800`042be246)nt!PspSetCreateProcessNotifyRoutine+0x73:fffff800`042be223 48395110 cmp qword ptr [rcx+10h],rdxfffff800`042be227 7507 jne nt!PspSetCreateProcessNotifyRoutine+0x80 (fffff800`042be230)nt!PspSetCreateProcessNotifyRoutine+0x79:fffff800`042be229 403aea cmp bpl,dlfffff800`042be22c 7407 je nt!PspSetCreateProcessNotifyRoutine+0x85 (fffff800`042be235)nt!PspSetCreateProcessNotifyRoutine+0x7e:fffff800`042be22e eb16 jmp nt!PspSetCreateProcessNotifyRoutine+0x96 (fffff800`042be246)nt!PspSetCreateProcessNotifyRoutine+0x80:fffff800`042be230 403aea cmp bpl,dlfffff800`042be233 7411 je nt!PspSetCreateProcessNotifyRoutine+0x96 (fffff800`042be246)nt!PspSetCreateProcessNotifyRoutine+0x85:fffff800`042be235 4c8bc6 mov r8,rsifffff800`042be238 498bcf mov rcx,r15fffff800`042be23b e8100ef5ff call nt!ExCompareExchangeCallBack (fffff800`0420f050)fffff800`042be240 33c9 xor ecx,ecxfffff800`042be242 3ac1 cmp al,clfffff800`042be244 7540 jne nt!PspSetCreateProcessNotifyRoutine+0xd6 (fffff800`042be286)nt!PspSetCreateProcessNotifyRoutine+0x96:fffff800`042be246 488bd6 mov rdx,rsifffff800`042be249 498bcf mov rcx,r15fffff800`042be24c e8bb2eeeff call nt!ExDereferenceCallBackBlock (fffff800`041a110c)fffff800`042be251 33d2 xor edx,edxnt!PspSetCreateProcessNotifyRoutine+0xa3:fffff800`042be253 4403e3 add r12d,ebxfffff800`042be256 4183fc40 cmp r12d,40hfffff800`042be25a 72a1 jb nt!PspSetCreateProcessNotifyRoutine+0x4d (fffff800`042be1fd)nt!PspSetCreateProcessNotifyRoutine+0xac:fffff800`042be25c 66019fc4010000 add word ptr [rdi+1C4h],bxfffff800`042be263 7517 jne nt!PspSetCreateProcessNotifyRoutine+0xcc (fffff800`042be27c)nt!PspSetCreateProcessNotifyRoutine+0xb5:fffff800`042be265 488d4750 lea rax,[rdi+50h]fffff800`042be269 483900 cmp qword ptr [rax],raxfffff800`042be26c 740e je nt!PspSetCreateProcessNotifyRoutine+0xcc (fffff800`042be27c)nt!PspSetCreateProcessNotifyRoutine+0xbe:fffff800`042be26e 663997c6010000 cmp word ptr [rdi+1C6h],dxfffff800`042be275 7505 jne nt!PspSetCreateProcessNotifyRoutine+0xcc (fffff800`042be27c)nt!PspSetCreateProcessNotifyRoutine+0xc7:fffff800`042be277 e834f5b6ff call nt!KiCheckForKernelApcDelivery (fffff800`03e2d7b0)nt!PspSetCreateProcessNotifyRoutine+0xcc:fffff800`042be27c b87a0000c0 mov eax,0C000007Ahfffff800`042be281 e916010000 jmp nt!PspSetCreateProcessNotifyRoutine+0x1ec (fffff800`042be39c)nt!PspSetCreateProcessNotifyRoutine+0xd6:fffff800`042be286 403ae9 cmp bpl,clfffff800`042be289 750a jne nt!PspSetCreateProcessNotifyRoutine+0xe5 (fffff800`042be295)nt!PspSetCreateProcessNotifyRoutine+0xdb:fffff800`042be28b f08305f196d6ffff lock add dword ptr [nt!PspCreateProcessNotifyRoutineCount (fffff800`04027984)],0FFFFFFFFhfffff800`042be293 eb08 jmp nt!PspSetCreateProcessNotifyRoutine+0xed (fffff800`042be29d)nt!PspSetCreateProcessNotifyRoutine+0xe5:fffff800`042be295 f08305e396d6ffff lock add dword ptr [nt!PspCreateProcessNotifyRoutineExCount (fffff800`04027980)],0FFFFFFFFhnt!PspSetCreateProcessNotifyRoutine+0xed:fffff800`042be29d 418bc4 mov eax,r12dfffff800`042be2a0 488bd6 mov rdx,rsifffff800`042be2a3 498d0cc6 lea rcx,[r14+rax*8]fffff800`042be2a7 e8602eeeff call nt!ExDereferenceCallBackBlock (fffff800`041a110c)fffff800`042be2ac 66019fc4010000 add word ptr [rdi+1C4h],bxfffff800`042be2b3 7519 jne nt!PspSetCreateProcessNotifyRoutine+0x11e (fffff800`042be2ce)nt!PspSetCreateProcessNotifyRoutine+0x105:fffff800`042be2b5 488d4750 lea rax,[rdi+50h]fffff800`042be2b9 483900 cmp qword ptr [rax],raxfffff800`042be2bc 7410 je nt!PspSetCreateProcessNotifyRoutine+0x11e (fffff800`042be2ce)nt!PspSetCreateProcessNotifyRoutine+0x10e:fffff800`042be2be 33c0 xor eax,eaxfffff800`042be2c0 663987c6010000 cmp word ptr [rdi+1C6h],axfffff800`042be2c7 7505 jne nt!PspSetCreateProcessNotifyRoutine+0x11e (fffff800`042be2ce)nt!PspSetCreateProcessNotifyRoutine+0x119:fffff800`042be2c9 e8e2f4b6ff call nt!KiCheckForKernelApcDelivery (fffff800`03e2d7b0)nt!PspSetCreateProcessNotifyRoutine+0x11e:fffff800`042be2ce 33c0 xor eax,eaxfffff800`042be2d0 f0480fb11e lock cmpxchg qword ptr [rsi],rbxfffff800`042be2d5 740d je nt!PspSetCreateProcessNotifyRoutine+0x134 (fffff800`042be2e4)nt!PspSetCreateProcessNotifyRoutine+0x127:fffff800`042be2d7 483bc3 cmp rax,rbxfffff800`042be2da 7408 je nt!PspSetCreateProcessNotifyRoutine+0x134 (fffff800`042be2e4)nt!PspSetCreateProcessNotifyRoutine+0x12c:fffff800`042be2dc 488bce mov rcx,rsifffff800`042be2df e86cd4b9ff call nt!ExfWaitForRundownProtectionRelease (fffff800`03e5b750)nt!PspSetCreateProcessNotifyRoutine+0x134:fffff800`042be2e4 488bce mov rcx,rsifffff800`042be2e7 e864d7fbff call nt!IopDeallocateApc (fffff800`0427ba50)fffff800`042be2ec e9a9000000 jmp nt!PspSetCreateProcessNotifyRoutine+0x1ea (fffff800`042be39a)nt!PspSetCreateProcessNotifyRoutine+0x141:fffff800`042be2f1 413aec cmp bpl,r12bfffff800`042be2f4 7419 je nt!PspSetCreateProcessNotifyRoutine+0x15f (fffff800`042be30f)nt!PspSetCreateProcessNotifyRoutine+0x146:fffff800`042be2f6 e8b51dfbff call nt!MmVerifyCallbackFunction (fffff800`042700b0)fffff800`042be2fb 413bc4 cmp eax,r12dfffff800`042be2fe 750a jne nt!PspSetCreateProcessNotifyRoutine+0x15a (fffff800`042be30a)nt!PspSetCreateProcessNotifyRoutine+0x150:fffff800`042be300 b8220000c0 mov eax,0C0000022hfffff800`042be305 e992000000 jmp nt!PspSetCreateProcessNotifyRoutine+0x1ec (fffff800`042be39c)nt!PspSetCreateProcessNotifyRoutine+0x15a:fffff800`042be30a 488bd3 mov rdx,rbxfffff800`042be30d eb03 jmp nt!PspSetCreateProcessNotifyRoutine+0x162 (fffff800`042be312)nt!PspSetCreateProcessNotifyRoutine+0x15f:fffff800`042be30f 498bd4 mov rdx,r12nt!PspSetCreateProcessNotifyRoutine+0x162:fffff800`042be312 498bcd mov rcx,r13fffff800`042be315 e846a8fbff call nt!ExAllocateCallBack (fffff800`04278b60)fffff800`042be31a 488bf0 mov rsi,raxfffff800`042be31d 493bc4 cmp rax,r12fffff800`042be320 7507 jne nt!PspSetCreateProcessNotifyRoutine+0x179 (fffff800`042be329)nt!PspSetCreateProcessNotifyRoutine+0x172:fffff800`042be322 b89a0000c0 mov eax,0C000009Ahfffff800`042be327 eb73 jmp nt!PspSetCreateProcessNotifyRoutine+0x1ec (fffff800`042be39c)nt!PspSetCreateProcessNotifyRoutine+0x179:fffff800`042be329 418bfc mov edi,r12dfffff800`042be32c 4c8d354d94d6ff lea r14,[nt!PspCreateProcessNotifyRoutine (fffff800`04027780)]nt!PspSetCreateProcessNotifyRoutine+0x183:fffff800`042be333 8bc7 mov eax,edifffff800`042be335 4533c0 xor r8d,r8dfffff800`042be338 488bd6 mov rdx,rsifffff800`042be33b 498d0cc6 lea rcx,[r14+rax*8]fffff800`042be33f e80c0df5ff call nt!ExCompareExchangeCallBack (fffff800`0420f050)fffff800`042be344 413ac4 cmp al,r12bfffff800`042be347 7516 jne nt!PspSetCreateProcessNotifyRoutine+0x1af (fffff800`042be35f)nt!PspSetCreateProcessNotifyRoutine+0x199:fffff800`042be349 03fb add edi,ebxfffff800`042be34b 83ff40 cmp edi,40hfffff800`042be34e 72e3 jb nt!PspSetCreateProcessNotifyRoutine+0x183 (fffff800`042be333)nt!PspSetCreateProcessNotifyRoutine+0x1a0:fffff800`042be350 488bce mov rcx,rsifffff800`042be353 e8f8d6fbff call nt!IopDeallocateApc (fffff800`0427ba50)fffff800`042be358 b80d0000c0 mov eax,0C000000Dhfffff800`042be35d eb3d jmp nt!PspSetCreateProcessNotifyRoutine+0x1ec (fffff800`042be39c)nt!PspSetCreateProcessNotifyRoutine+0x1af:fffff800`042be35f 413aec cmp bpl,r12bfffff800`042be362 751c jne nt!PspSetCreateProcessNotifyRoutine+0x1d0 (fffff800`042be380)nt!PspSetCreateProcessNotifyRoutine+0x1b4:fffff800`042be364 f0011d1996d6ff lock add dword ptr [nt!PspCreateProcessNotifyRoutineCount (fffff800`04027984)],ebxfffff800`042be36b 8b056f91d6ff mov eax,dword ptr [nt!PspNotifyEnableMask (fffff800`040274e0)]fffff800`042be371 a802 test al,2fffff800`042be373 7525 jne nt!PspSetCreateProcessNotifyRoutine+0x1ea (fffff800`042be39a)nt!PspSetCreateProcessNotifyRoutine+0x1c5:fffff800`042be375 f00fba2d6291d6ff01 lock bts dword ptr [nt!PspNotifyEnableMask (fffff800`040274e0)],1fffff800`042be37e eb1a jmp nt!PspSetCreateProcessNotifyRoutine+0x1ea (fffff800`042be39a)nt!PspSetCreateProcessNotifyRoutine+0x1d0:fffff800`042be380 f0011df995d6ff lock add dword ptr [nt!PspCreateProcessNotifyRoutineExCount (fffff800`04027980)],ebxfffff800`042be387 8b055391d6ff mov eax,dword ptr [nt!PspNotifyEnableMask (fffff800`040274e0)]fffff800`042be38d a804 test al,4fffff800`042be38f 7509 jne nt!PspSetCreateProcessNotifyRoutine+0x1ea (fffff800`042be39a)nt!PspSetCreateProcessNotifyRoutine+0x1e1:fffff800`042be391 f00fba2d4691d6ff02 lock bts dword ptr [nt!PspNotifyEnableMask (fffff800`040274e0)],2nt!PspSetCreateProcessNotifyRoutine+0x1ea:fffff800`042be39a 33c0 xor eax,eaxnt!PspSetCreateProcessNotifyRoutine+0x1ec:fffff800`042be39c 488b5c2450 mov rbx,qword ptr [rsp+50h]fffff800`042be3a1 488b6c2458 mov rbp,qword ptr [rsp+58h]fffff800`042be3a6 488b742460 mov rsi,qword ptr [rsp+60h]fffff800`042be3ab 4883c420 add rsp,20hfffff800`042be3af 415f pop r15fffff800`042be3b1 415e pop r14fffff800`042be3b3 415d pop r13fffff800`042be3b5 415c pop r12fffff800`042be3b7 5f pop rdifffff800`042be3b8 c3 ret
    Win8.1 32 位 PspSetCreateProcessNotifyRoutinelkd> uf PspSetCreateProcessNotifyRoutinent!PspSetCreateProcessNotifyRoutine:819b987e 8bff mov edi,edi819b9880 55 push ebp819b9881 8bec mov ebp,esp819b9883 83ec10 sub esp,10h819b9886 53 push ebx819b9887 8bd9 mov ebx,ecx819b9889 895df4 mov dword ptr [ebp-0Ch],ebx819b988c 56 push esi819b988d 57 push edi819b988e 84d2 test dl,dl819b9890 0f8567020a00 jne nt! ?? ::NNGAKEGL::`string'+0x70493 (81a59afd)nt!PspSetCreateProcessNotifyRoutine+0x18:819b9896 33f6 xor esi,esi819b9898 33ff xor edi,edi819b989a 46 inc esi819b989b 385508 cmp byte ptr [ebp+8],dl819b989e 756e jne nt!PspSetCreateProcessNotifyRoutine+0x90 (819b990e)nt!PspSetCreateProcessNotifyRoutine+0x22:819b98a0 8bd7 mov edx,edint!PspSetCreateProcessNotifyRoutine+0x24:819b98a2 8bcb mov ecx,ebx819b98a4 e8a9000000 call nt!ExAllocateCallBack (819b9952)819b98a9 8bc8 mov ecx,eax819b98ab 894dfc mov dword ptr [ebp-4],ecx819b98ae 85c9 test ecx,ecx819b98b0 0f846b030a00 je nt! ?? ::NNGAKEGL::`string'+0x705b7 (81a59c21)nt!PspSetCreateProcessNotifyRoutine+0x38:819b98b6 b8c8158681 mov eax,offset nt!PspCreateProcessNotifyRoutine (818615c8)819b98bb 8bdf mov ebx,edi819b98bd 8945f8 mov dword ptr [ebp-8],eaxnt!PspSetCreateProcessNotifyRoutine+0x42:819b98c0 8bd1 mov edx,ecx819b98c2 8bc8 mov ecx,eax819b98c4 57 push edi819b98c5 e88e24d9ff call nt!ExCompareExchangeCallBack (8174bd58)819b98ca 84c0 test al,al819b98cc 751c jne nt!PspSetCreateProcessNotifyRoutine+0x6c (819b98ea)nt!PspSetCreateProcessNotifyRoutine+0x50:819b98ce 8b45f8 mov eax,dword ptr [ebp-8]819b98d1 83c304 add ebx,4819b98d4 8b4dfc mov ecx,dword ptr [ebp-4]819b98d7 83c004 add eax,4819b98da 8945f8 mov dword ptr [ebp-8],eax819b98dd 81fb00010000 cmp ebx,100h819b98e3 72db jb nt!PspSetCreateProcessNotifyRoutine+0x42 (819b98c0)nt!PspSetCreateProcessNotifyRoutine+0x67:819b98e5 e941030a00 jmp nt! ?? ::NNGAKEGL::`string'+0x705c1 (81a59c2b)nt!PspSetCreateProcessNotifyRoutine+0x6c:819b98ea 807d0800 cmp byte ptr [ebp+8],0819b98ee 752b jne nt!PspSetCreateProcessNotifyRoutine+0x9d (819b991b)nt!PspSetCreateProcessNotifyRoutine+0x72:819b98f0 b8541cb481 mov eax,offset nt!PspCreateProcessNotifyRoutineCount (81b41c54)819b98f5 f00fc130 lock xadd dword ptr [eax],esi819b98f9 46 inc esi819b98fa a1441cb481 mov eax,dword ptr [nt!PspNotifyEnableMask (81b41c44)]819b98ff a802 test al,2819b9901 7437 je nt!PspSetCreateProcessNotifyRoutine+0xbc (819b993a)nt!PspSetCreateProcessNotifyRoutine+0x85:819b9903 33c0 xor eax,eaxnt!PspSetCreateProcessNotifyRoutine+0x87:819b9905 5f pop edi819b9906 5e pop esi819b9907 5b pop ebx819b9908 8be5 mov esp,ebp819b990a 5d pop ebp819b990b c20400 ret 4nt!PspSetCreateProcessNotifyRoutine+0x90:819b990e e86d000000 call nt!MmVerifyCallbackFunction (819b9980)819b9913 85c0 test eax,eax819b9915 742f je nt!PspSetCreateProcessNotifyRoutine+0xc8 (819b9946)nt!PspSetCreateProcessNotifyRoutine+0x99:819b9917 8bd6 mov edx,esi819b9919 eb87 jmp nt!PspSetCreateProcessNotifyRoutine+0x24 (819b98a2)nt!PspSetCreateProcessNotifyRoutine+0x9d:819b991b b8501cb481 mov eax,offset nt!PspCreateProcessNotifyRoutineExCount (81b41c50)819b9920 f00fc130 lock xadd dword ptr [eax],esi819b9924 46 inc esi819b9925 a1441cb481 mov eax,dword ptr [nt!PspNotifyEnableMask (81b41c44)]819b992a a804 test al,4819b992c 75d5 jne nt!PspSetCreateProcessNotifyRoutine+0x85 (819b9903)nt!PspSetCreateProcessNotifyRoutine+0xb0:819b992e b8441cb481 mov eax,offset nt!PspNotifyEnableMask (81b41c44)819b9933 f00fba2802 lock bts dword ptr [eax],2819b9938 ebc9 jmp nt!PspSetCreateProcessNotifyRoutine+0x85 (819b9903)nt!PspSetCreateProcessNotifyRoutine+0xbc:819b993a b8441cb481 mov eax,offset nt!PspNotifyEnableMask (81b41c44)819b993f f00fba2801 lock bts dword ptr [eax],1819b9944 ebbd jmp nt!PspSetCreateProcessNotifyRoutine+0x85 (819b9903)nt!PspSetCreateProcessNotifyRoutine+0xc8:819b9946 b8220000c0 mov eax,0C0000022h819b994b ebb8 jmp nt!PspSetCreateProcessNotifyRoutine+0x87 (819b9905)nt! ?? ::NNGAKEGL::`string'+0x70493:81a59afd 648b3524010000 mov esi,dword ptr fs:[124h]81a59b04 66ff8e3c010000 dec word ptr [esi+13Ch]81a59b0b 33ff xor edi,edi81a59b0d b8c8158681 mov eax,offset nt!PspCreateProcessNotifyRoutine (818615c8)81a59b12 897df8 mov dword ptr [ebp-8],edi81a59b15 8945fc mov dword ptr [ebp-4],eaxnt! ?? ::NNGAKEGL::`string'+0x704ae:81a59b18 8bc8 mov ecx,eax81a59b1a e85bb2c2ff call nt!ExReferenceCallBackBlock (81684d7a)81a59b1f 8bd8 mov ebx,eax81a59b21 85db test ebx,ebx81a59b23 7426 je nt! ?? ::NNGAKEGL::`string'+0x704e1 (81a59b4b)nt! ?? ::NNGAKEGL::`string'+0x704bb:81a59b25 8bcb mov ecx,ebx81a59b27 e86a67d1ff call nt!ExGetCallBackBlockContext (81770296)81a59b2c 8bd0 mov edx,eax81a59b2e e86d67d1ff call nt!ExGetCallBackBlockRoutine (817702a0)81a59b33 3b45f4 cmp eax,dword ptr [ebp-0Ch]81a59b36 7509 jne nt! ?? ::NNGAKEGL::`string'+0x704d7 (81a59b41)nt! ?? ::NNGAKEGL::`string'+0x704ce:81a59b38 85d2 test edx,edx81a59b3a 7557 jne nt! ?? ::NNGAKEGL::`string'+0x70529 (81a59b93)nt! ?? ::NNGAKEGL::`string'+0x704d2:81a59b3c 385508 cmp byte ptr [ebp+8],dl81a59b3f 7458 je nt! ?? ::NNGAKEGL::`string'+0x7052f (81a59b99)nt! ?? ::NNGAKEGL::`string'+0x704d7:81a59b41 8b4dfc mov ecx,dword ptr [ebp-4]81a59b44 8bd3 mov edx,ebx81a59b46 e8e7b1c2ff call nt!ExDereferenceCallBackBlock (81684d32)nt! ?? ::NNGAKEGL::`string'+0x704e1:81a59b4b 8b4df8 mov ecx,dword ptr [ebp-8]81a59b4e 8b45fc mov eax,dword ptr [ebp-4]81a59b51 41 inc ecx81a59b52 83c004 add eax,481a59b55 894df8 mov dword ptr [ebp-8],ecx81a59b58 8945fc mov dword ptr [ebp-4],eax81a59b5b 83f940 cmp ecx,40h81a59b5e 72b8 jb nt! ?? ::NNGAKEGL::`string'+0x704ae (81a59b18)nt! ?? ::NNGAKEGL::`string'+0x704f6:81a59b60 0fbf863c010000 movsx eax,word ptr [esi+13Ch]81a59b67 40 inc eax81a59b68 6689863c010000 mov word ptr [esi+13Ch],ax81a59b6f 6685c0 test ax,ax81a59b72 7515 jne nt! ?? ::NNGAKEGL::`string'+0x7051f (81a59b89)nt! ?? ::NNGAKEGL::`string'+0x7050a:81a59b74 8d4670 lea eax,[esi+70h]81a59b77 3900 cmp dword ptr [eax],eax81a59b79 740e je nt! ?? ::NNGAKEGL::`string'+0x7051f (81a59b89)nt! ?? ::NNGAKEGL::`string'+0x70511:81a59b7b 6639be3e010000 cmp word ptr [esi+13Eh],di81a59b82 7505 jne nt! ?? ::NNGAKEGL::`string'+0x7051f (81a59b89)nt! ?? ::NNGAKEGL::`string'+0x7051a:81a59b84 e8fb79c8ff call nt!KiCheckForKernelApcDelivery (816e1584)nt! ?? ::NNGAKEGL::`string'+0x7051f:81a59b89 b87a0000c0 mov eax,0C000007Ah81a59b8e e972fdf5ff jmp nt!PspSetCreateProcessNotifyRoutine+0x87 (819b9905)nt! ?? ::NNGAKEGL::`string'+0x70529:81a59b93 807d0800 cmp byte ptr [ebp+8],081a59b97 74a8 je nt! ?? ::NNGAKEGL::`string'+0x704d7 (81a59b41)nt! ?? ::NNGAKEGL::`string'+0x7052f:81a59b99 8b4dfc mov ecx,dword ptr [ebp-4]81a59b9c 33d2 xor edx,edx81a59b9e 53 push ebx81a59b9f e8b421cfff call nt!ExCompareExchangeCallBack (8174bd58)81a59ba4 84c0 test al,al81a59ba6 7499 je nt! ?? ::NNGAKEGL::`string'+0x704d7 (81a59b41)nt! ?? ::NNGAKEGL::`string'+0x7053e:81a59ba8 83c8ff or eax,0FFFFFFFFh81a59bab b9541cb481 mov ecx,offset nt!PspCreateProcessNotifyRoutineCount (81b41c54)81a59bb0 807d0800 cmp byte ptr [ebp+8],081a59bb4 7405 je nt! ?? ::NNGAKEGL::`string'+0x70551 (81a59bbb)nt! ?? ::NNGAKEGL::`string'+0x7054c:81a59bb6 b9501cb481 mov ecx,offset nt!PspCreateProcessNotifyRoutineExCount (81b41c50)nt! ?? ::NNGAKEGL::`string'+0x70551:81a59bbb f00fc101 lock xadd dword ptr [ecx],eax81a59bbf 8b45f8 mov eax,dword ptr [ebp-8]81a59bc2 8bd3 mov edx,ebx81a59bc4 8d0c85c8158681 lea ecx,nt!PspCreateProcessNotifyRoutine (818615c8)[eax*4]81a59bcb e862b1c2ff call nt!ExDereferenceCallBackBlock (81684d32)81a59bd0 0fbf863c010000 movsx eax,word ptr [esi+13Ch]81a59bd7 40 inc eax81a59bd8 6689863c010000 mov word ptr [esi+13Ch],ax81a59bdf 6685c0 test ax,ax81a59be2 7515 jne nt! ?? ::NNGAKEGL::`string'+0x7058f (81a59bf9)nt! ?? ::NNGAKEGL::`string'+0x7057a:81a59be4 8d4670 lea eax,[esi+70h]81a59be7 3900 cmp dword ptr [eax],eax81a59be9 740e je nt! ?? ::NNGAKEGL::`string'+0x7058f (81a59bf9)nt! ?? ::NNGAKEGL::`string'+0x70581:81a59beb 6639be3e010000 cmp word ptr [esi+13Eh],di81a59bf2 7505 jne nt! ?? ::NNGAKEGL::`string'+0x7058f (81a59bf9)nt! ?? ::NNGAKEGL::`string'+0x7058a:81a59bf4 e88b79c8ff call nt!KiCheckForKernelApcDelivery (816e1584)nt! ?? ::NNGAKEGL::`string'+0x7058f:81a59bf9 33f6 xor esi,esi81a59bfb 33c0 xor eax,eax81a59bfd 46 inc esi81a59bfe 8bce mov ecx,esi81a59c00 f00fb10b lock cmpxchg dword ptr [ebx],ecx81a59c04 85c0 test eax,eax81a59c06 740d je nt! ?? ::NNGAKEGL::`string'+0x705ab (81a59c15)nt! ?? ::NNGAKEGL::`string'+0x7059e:81a59c08 3bc6 cmp eax,esi81a59c0a 7409 je nt! ?? ::NNGAKEGL::`string'+0x705ab (81a59c15)nt! ?? ::NNGAKEGL::`string'+0x705a2:81a59c0c 8bd0 mov edx,eax81a59c0e 8bcb mov ecx,ebx81a59c10 e87d36ccff call nt!ExfWaitForRundownProtectionRelease (8171d292)nt! ?? ::NNGAKEGL::`string'+0x705ab:81a59c15 57 push edi81a59c16 53 push ebx81a59c17 e8f4a3ddff call nt!ExFreePoolWithTag (81834010)81a59c1c e9e2fcf5ff jmp nt!PspSetCreateProcessNotifyRoutine+0x85 (819b9903)nt! ?? ::NNGAKEGL::`string'+0x705b7:81a59c21 b89a0000c0 mov eax,0C000009Ah81a59c26 e9dafcf5ff jmp nt!PspSetCreateProcessNotifyRoutine+0x87 (819b9905)nt! ?? ::NNGAKEGL::`string'+0x705c1:81a59c2b 57 push edi81a59c2c ff75fc push dword ptr [ebp-4]81a59c2f e8dca3ddff call nt!ExFreePoolWithTag (81834010)81a59c34 b80d0000c0 mov eax,0C000000Dh81a59c39 e9c7fcf5ff jmp nt!PspSetCreateProcessNotifyRoutine+0x87 (819b9905)
    Win8.1 64 位 PspSetCreateProcessNotifyRoutinelkd> uf PspSetCreateProcessNotifyRoutineFlow analysis was incomplete, some code may be missingnt!PspSetCreateProcessNotifyRoutine:fffff803`10775bc4 48895c2408 mov qword ptr [rsp+8],rbxfffff803`10775bc9 48896c2410 mov qword ptr [rsp+10h],rbpfffff803`10775bce 4889742418 mov qword ptr [rsp+18h],rsifffff803`10775bd3 57 push rdifffff803`10775bd4 4154 push r12fffff803`10775bd6 4155 push r13fffff803`10775bd8 4156 push r14fffff803`10775bda 4157 push r15fffff803`10775bdc 4883ec20 sub rsp,20hfffff803`10775be0 4533f6 xor r14d,r14dfffff803`10775be3 418ae8 mov bpl,r8bfffff803`10775be6 4c8be1 mov r12,rcxfffff803`10775be9 418d7e01 lea edi,[r14+1]fffff803`10775bed 84d2 test dl,dlfffff803`10775bef 0f85c52e0b00 jne nt! ?? ::NNGAKEGL::`string'+0x79eba (fffff803`10828aba)nt!PspSetCreateProcessNotifyRoutine+0x31:fffff803`10775bf5 4584c0 test r8b,r8bfffff803`10775bf8 7577 jne nt!PspSetCreateProcessNotifyRoutine+0xad (fffff803`10775c71)nt!PspSetCreateProcessNotifyRoutine+0x36:fffff803`10775bfa 418bd6 mov edx,r14dnt!PspSetCreateProcessNotifyRoutine+0x39:fffff803`10775bfd 498bcc mov rcx,r12fffff803`10775c00 e8ab000000 call nt!ExAllocateCallBack (fffff803`10775cb0)fffff803`10775c05 488bf0 mov rsi,raxfffff803`10775c08 4885c0 test rax,raxfffff803`10775c0b 0f84ef2f0b00 je nt! ?? ::NNGAKEGL::`string'+0x7a000 (fffff803`10828c00)nt!PspSetCreateProcessNotifyRoutine+0x4d:fffff803`10775c11 418bde mov ebx,r14dfffff803`10775c14 4c8d3de5b1deff lea r15,[nt!PspCreateProcessNotifyRoutine (fffff803`10560e00)]nt!PspSetCreateProcessNotifyRoutine+0x57:fffff803`10775c1b 8bc3 mov eax,ebxfffff803`10775c1d 4533c0 xor r8d,r8dfffff803`10775c20 488bd6 mov rdx,rsifffff803`10775c23 498d0cc7 lea rcx,[r15+rax*8]fffff803`10775c27 e874b8c3ff call nt!ExCompareExchangeCallBack (fffff803`103b14a0)fffff803`10775c2c 84c0 test al,alfffff803`10775c2e 750c jne nt!PspSetCreateProcessNotifyRoutine+0x78 (fffff803`10775c3c)nt!PspSetCreateProcessNotifyRoutine+0x6c:fffff803`10775c30 03df add ebx,edifffff803`10775c32 83fb40 cmp ebx,40hfffff803`10775c35 72e4 jb nt!PspSetCreateProcessNotifyRoutine+0x57 (fffff803`10775c1b)nt!PspSetCreateProcessNotifyRoutine+0x73:fffff803`10775c37 e9ce2f0b00 jmp nt! ?? ::NNGAKEGL::`string'+0x7a00a (fffff803`10828c0a)nt!PspSetCreateProcessNotifyRoutine+0x78:fffff803`10775c3c 4084ed test bpl,bplfffff803`10775c3f 7545 jne nt!PspSetCreateProcessNotifyRoutine+0xc2 (fffff803`10775c86)nt!PspSetCreateProcessNotifyRoutine+0x7d:fffff803`10775c41 f0013d005a1b00 lock add dword ptr [nt!PspCreateProcessNotifyRoutineCount (fffff803`1092b648)],edifffff803`10775c48 8b05ce541b00 mov eax,dword ptr [nt!PspNotifyEnableMask (fffff803`1092b11c)]fffff803`10775c4e a802 test al,2fffff803`10775c50 7450 je nt!PspSetCreateProcessNotifyRoutine+0xde (fffff803`10775ca2)nt!PspSetCreateProcessNotifyRoutine+0x8e:fffff803`10775c52 33c0 xor eax,eaxfffff803`10775c54 488b5c2450 mov rbx,qword ptr [rsp+50h]fffff803`10775c59 488b6c2458 mov rbp,qword ptr [rsp+58h]fffff803`10775c5e 488b742460 mov rsi,qword ptr [rsp+60h]fffff803`10775c63 4883c420 add rsp,20hfffff803`10775c67 415f pop r15fffff803`10775c69 415e pop r14fffff803`10775c6b 415d pop r13fffff803`10775c6d 415c pop r12fffff803`10775c6f 5f pop rdifffff803`10775c70 c3 retnt!PspSetCreateProcessNotifyRoutine+0xad:fffff803`10775c71 e87e000000 call nt!MmVerifyCallbackFunction (fffff803`10775cf4)fffff803`10775c76 85c0 test eax,eaxfffff803`10775c78 0f84782f0b00 je nt! ?? ::NNGAKEGL::`string'+0x79ff6 (fffff803`10828bf6)nt!PspSetCreateProcessNotifyRoutine+0xba:fffff803`10775c7e 488bd7 mov rdx,rdifffff803`10775c81 e977ffffff jmp nt!PspSetCreateProcessNotifyRoutine+0x39 (fffff803`10775bfd)nt!PspSetCreateProcessNotifyRoutine+0xc2:fffff803`10775c86 f0013db7591b00 lock add dword ptr [nt!PspCreateProcessNotifyRoutineExCount (fffff803`1092b644)],edifffff803`10775c8d 8b0589541b00 mov eax,dword ptr [nt!PspNotifyEnableMask (fffff803`1092b11c)]fffff803`10775c93 a804 test al,4fffff803`10775c95 75bb jne nt!PspSetCreateProcessNotifyRoutine+0x8e (fffff803`10775c52)nt!PspSetCreateProcessNotifyRoutine+0xd3:fffff803`10775c97 f00fba2d7c541b0002 lock bts dword ptr [nt!PspNotifyEnableMask (fffff803`1092b11c)],2fffff803`10775ca0 ebb0 jmp nt!PspSetCreateProcessNotifyRoutine+0x8e (fffff803`10775c52)nt!PspSetCreateProcessNotifyRoutine+0xde:fffff803`10775ca2 f00fba2d71541b0001 lock bts dword ptr [nt!PspNotifyEnableMask (fffff803`1092b11c)],1fffff803`10775cab eba5 jmp nt!PspSetCreateProcessNotifyRoutine+0x8e (fffff803`10775c52)
    Win10 32 位 PspSetCreateProcessNotifyRoutinekd> uf PspSetCreateProcessNotifyRoutinent!PspSetCreateProcessNotifyRoutine:81e1c9fe 8bff mov edi,edi81e1ca00 55 push ebp81e1ca01 8bec mov ebp,esp81e1ca03 83ec10 sub esp,10h81e1ca06 53 push ebx81e1ca07 8bd9 mov ebx,ecx81e1ca09 895df4 mov dword ptr [ebp-0Ch],ebx81e1ca0c 56 push esi81e1ca0d 57 push edi81e1ca0e 84d2 test dl,dl81e1ca10 0f85d11b0a00 jne nt! ?? ::NNGAKEGL::`string'+0x69bdb (81ebe5e7)nt!PspSetCreateProcessNotifyRoutine+0x18:81e1ca16 33ff xor edi,edi81e1ca18 385508 cmp byte ptr [ebp+8],dl81e1ca1b 7560 jne nt!PspSetCreateProcessNotifyRoutine+0x7f (81e1ca7d)nt!PspSetCreateProcessNotifyRoutine+0x1f:81e1ca1d 8bd7 mov edx,edint!PspSetCreateProcessNotifyRoutine+0x21:81e1ca1f 8bcb mov ecx,ebx81e1ca21 e89a000000 call nt!ExAllocateCallBack (81e1cac0)81e1ca26 8945f8 mov dword ptr [ebp-8],eax81e1ca29 85c0 test eax,eax81e1ca2b 0f84d81c0a00 je nt! ?? ::NNGAKEGL::`string'+0x69cfd (81ebe709)nt!PspSetCreateProcessNotifyRoutine+0x33:81e1ca31 bb30dccb81 mov ebx,offset nt!PspCreateProcessNotifyRoutine (81cbdc30)81e1ca36 8bf7 mov esi,edint!PspSetCreateProcessNotifyRoutine+0x3a:81e1ca38 57 push edi81e1ca39 8bd0 mov edx,eax81e1ca3b 8bcb mov ecx,ebx81e1ca3d e8921dd6ff call nt!ExCompareExchangeCallBack (81b7e7d4)81e1ca42 84c0 test al,al81e1ca44 7516 jne nt!PspSetCreateProcessNotifyRoutine+0x5e (81e1ca5c)nt!PspSetCreateProcessNotifyRoutine+0x48:81e1ca46 8b45f8 mov eax,dword ptr [ebp-8]81e1ca49 83c604 add esi,481e1ca4c 83c304 add ebx,481e1ca4f 81fe00010000 cmp esi,100h81e1ca55 72e1 jb nt!PspSetCreateProcessNotifyRoutine+0x3a (81e1ca38)nt!PspSetCreateProcessNotifyRoutine+0x59:81e1ca57 e9b71c0a00 jmp nt! ?? ::NNGAKEGL::`string'+0x69d07 (81ebe713)nt!PspSetCreateProcessNotifyRoutine+0x5e:81e1ca5c 807d0800 cmp byte ptr [ebp+8],081e1ca60 7529 jne nt!PspSetCreateProcessNotifyRoutine+0x8d (81e1ca8b)nt!PspSetCreateProcessNotifyRoutine+0x64:81e1ca62 f0ff05d8bdff81 lock inc dword ptr [nt!PspCreateProcessNotifyRoutineCount (81ffbdd8)]81e1ca69 a1c4bdff81 mov eax,dword ptr [nt!PspNotifyEnableMask (81ffbdc4)]81e1ca6e a802 test al,281e1ca70 7435 je nt!PspSetCreateProcessNotifyRoutine+0xa9 (81e1caa7)nt!PspSetCreateProcessNotifyRoutine+0x74:81e1ca72 33c0 xor eax,eaxnt!PspSetCreateProcessNotifyRoutine+0x76:81e1ca74 5f pop edi81e1ca75 5e pop esi81e1ca76 5b pop ebx81e1ca77 8be5 mov esp,ebp81e1ca79 5d pop ebp81e1ca7a c20400 ret 4nt!PspSetCreateProcessNotifyRoutine+0x7f:81e1ca7d e86c000000 call nt!MmVerifyCallbackFunction (81e1caee)81e1ca82 85c0 test eax,eax81e1ca84 742d je nt!PspSetCreateProcessNotifyRoutine+0xb5 (81e1cab3)nt!PspSetCreateProcessNotifyRoutine+0x88:81e1ca86 33d2 xor edx,edx81e1ca88 42 inc edx81e1ca89 eb94 jmp nt!PspSetCreateProcessNotifyRoutine+0x21 (81e1ca1f)nt!PspSetCreateProcessNotifyRoutine+0x8d:81e1ca8b f0ff05d4bdff81 lock inc dword ptr [nt!PspCreateProcessNotifyRoutineExCount (81ffbdd4)]81e1ca92 a1c4bdff81 mov eax,dword ptr [nt!PspNotifyEnableMask (81ffbdc4)]81e1ca97 a804 test al,481e1ca99 75d7 jne nt!PspSetCreateProcessNotifyRoutine+0x74 (81e1ca72)nt!PspSetCreateProcessNotifyRoutine+0x9d:81e1ca9b b8c4bdff81 mov eax,offset nt!PspNotifyEnableMask (81ffbdc4)81e1caa0 f00fba2802 lock bts dword ptr [eax],281e1caa5 ebcb jmp nt!PspSetCreateProcessNotifyRoutine+0x74 (81e1ca72)nt!PspSetCreateProcessNotifyRoutine+0xa9:81e1caa7 b8c4bdff81 mov eax,offset nt!PspNotifyEnableMask (81ffbdc4)81e1caac f00fba2801 lock bts dword ptr [eax],181e1cab1 ebbf jmp nt!PspSetCreateProcessNotifyRoutine+0x74 (81e1ca72)nt!PspSetCreateProcessNotifyRoutine+0xb5:81e1cab3 b8220000c0 mov eax,0C0000022h81e1cab8 ebba jmp nt!PspSetCreateProcessNotifyRoutine+0x76 (81e1ca74)
    Win10 64 位 PspSetCreateProcessNotifyRoutinekd> uf PspSetCreateProcessNotifyRoutinent!PspSetCreateProcessNotifyRoutine:fffff800`a09a4530 48895c2408 mov qword ptr [rsp+8],rbxfffff800`a09a4535 48896c2410 mov qword ptr [rsp+10h],rbpfffff800`a09a453a 4889742418 mov qword ptr [rsp+18h],rsifffff800`a09a453f 57 push rdifffff800`a09a4540 4154 push r12fffff800`a09a4542 4155 push r13fffff800`a09a4544 4156 push r14fffff800`a09a4546 4157 push r15fffff800`a09a4548 4883ec20 sub rsp,20hfffff800`a09a454c 8ada mov bl,dlfffff800`a09a454e 8bf2 mov esi,edxfffff800`a09a4550 d0eb shr bl,1fffff800`a09a4552 4c8be1 mov r12,rcxfffff800`a09a4555 80e301 and bl,1fffff800`a09a4558 f6c201 test dl,1fffff800`a09a455b 0f8559770900 jne nt! ?? ::NNGAKEGL::`string'+0x6752a (fffff800`a0a3bcba)nt!PspSetCreateProcessNotifyRoutine+0x31:fffff800`a09a4561 84db test bl,blfffff800`a09a4563 7573 jne nt!PspSetCreateProcessNotifyRoutine+0xa8 (fffff800`a09a45d8)nt!PspSetCreateProcessNotifyRoutine+0x35:fffff800`a09a4565 488bd6 mov rdx,rsifffff800`a09a4568 498bcc mov rcx,r12fffff800`a09a456b e8a0000000 call nt!ExAllocateCallBack (fffff800`a09a4610)fffff800`a09a4570 488bf0 mov rsi,raxfffff800`a09a4573 4885c0 test rax,raxfffff800`a09a4576 0f8400780900 je nt! ?? ::NNGAKEGL::`string'+0x675ec (fffff800`a0a3bd7c)nt!PspSetCreateProcessNotifyRoutine+0x4c:fffff800`a09a457c 33ff xor edi,edifffff800`a09a457e 4c8d3dfb0bdfff lea r15,[nt!PspCreateProcessNotifyRoutine (fffff800`a0795180)]nt!PspSetCreateProcessNotifyRoutine+0x55:fffff800`a09a4585 498d0cff lea rcx,[r15+rdi*8]fffff800`a09a4589 4533c0 xor r8d,r8dfffff800`a09a458c 488bd6 mov rdx,rsifffff800`a09a458f e8fce9bfff call nt!ExCompareExchangeCallBack (fffff800`a05a2f90)fffff800`a09a4594 84c0 test al,alfffff800`a09a4596 750c jne nt!PspSetCreateProcessNotifyRoutine+0x74 (fffff800`a09a45a4)nt!PspSetCreateProcessNotifyRoutine+0x68:fffff800`a09a4598 ffc7 inc edifffff800`a09a459a 83ff40 cmp edi,40hfffff800`a09a459d 72e6 jb nt!PspSetCreateProcessNotifyRoutine+0x55 (fffff800`a09a4585)nt!PspSetCreateProcessNotifyRoutine+0x6f:fffff800`a09a459f e9e2770900 jmp nt! ?? ::NNGAKEGL::`string'+0x675f6 (fffff800`a0a3bd86)nt!PspSetCreateProcessNotifyRoutine+0x74:fffff800`a09a45a4 84db test bl,blfffff800`a09a45a6 7540 jne nt!PspSetCreateProcessNotifyRoutine+0xb8 (fffff800`a09a45e8)nt!PspSetCreateProcessNotifyRoutine+0x78:fffff800`a09a45a8 f0ff051d481d00 lock inc dword ptr [nt!PspCreateProcessNotifyRoutineCount (fffff800`a0b78dcc)]fffff800`a09a45af 8b0583441d00 mov eax,dword ptr [nt!PspNotifyEnableMask (fffff800`a0b78a38)]fffff800`a09a45b5 a802 test al,2fffff800`a09a45b7 744b je nt!PspSetCreateProcessNotifyRoutine+0xd4 (fffff800`a09a4604)nt!PspSetCreateProcessNotifyRoutine+0x89:fffff800`a09a45b9 33c0 xor eax,eaxnt!PspSetCreateProcessNotifyRoutine+0x8b:fffff800`a09a45bb 488b5c2450 mov rbx,qword ptr [rsp+50h]fffff800`a09a45c0 488b6c2458 mov rbp,qword ptr [rsp+58h]fffff800`a09a45c5 488b742460 mov rsi,qword ptr [rsp+60h]fffff800`a09a45ca 4883c420 add rsp,20hfffff800`a09a45ce 415f pop r15fffff800`a09a45d0 415e pop r14fffff800`a09a45d2 415d pop r13fffff800`a09a45d4 415c pop r12fffff800`a09a45d6 5f pop rdifffff800`a09a45d7 c3 retnt!PspSetCreateProcessNotifyRoutine+0xa8:fffff800`a09a45d8 e837020000 call nt!MmVerifyCallbackFunction (fffff800`a09a4814)fffff800`a09a45dd 85c0 test eax,eaxfffff800`a09a45df 7584 jne nt!PspSetCreateProcessNotifyRoutine+0x35 (fffff800`a09a4565)nt!PspSetCreateProcessNotifyRoutine+0xb1:fffff800`a09a45e1 b8220000c0 mov eax,0C0000022hfffff800`a09a45e6 ebd3 jmp nt!PspSetCreateProcessNotifyRoutine+0x8b (fffff800`a09a45bb)nt!PspSetCreateProcessNotifyRoutine+0xb8:fffff800`a09a45e8 f0ff05d9471d00 lock inc dword ptr [nt!PspCreateProcessNotifyRoutineExCount (fffff800`a0b78dc8)]fffff800`a09a45ef 8b0543441d00 mov eax,dword ptr [nt!PspNotifyEnableMask (fffff800`a0b78a38)]fffff800`a09a45f5 a804 test al,4fffff800`a09a45f7 75c0 jne nt!PspSetCreateProcessNotifyRoutine+0x89 (fffff800`a09a45b9)nt!PspSetCreateProcessNotifyRoutine+0xc9:fffff800`a09a45f9 f00fba2d36441d0002 lock bts dword ptr [nt!PspNotifyEnableMask (fffff800`a0b78a38)],2fffff800`a09a4602 ebb5 jmp nt!PspSetCreateProcessNotifyRoutine+0x89 (fffff800`a09a45b9)nt!PspSetCreateProcessNotifyRoutine+0xd4:fffff800`a09a4604 f00fba2d2b441d0001 lock bts dword ptr [nt!PspNotifyEnableMask (fffff800`a0b78a38)],1fffff800`a09a460d ebaa jmp nt!PspSetCreateProcessNotifyRoutine+0x89 (fffff800`a09a45b9)
    Win7 32 位 PsSetCreateProcessNotifyRoutinelkd> uf PsSetCreateProcessNotifyRoutinent!PsSetCreateProcessNotifyRoutine:83fa5720 8bff mov edi,edi83fa5722 55 push ebp83fa5723 8bec mov ebp,esp83fa5725 6a00 push 083fa5727 ff750c push dword ptr [ebp+0Ch]83fa572a ff7508 push dword ptr [ebp+8]83fa572d e809000000 call nt!PspSetCreateProcessNotifyRoutine (83fa573b)83fa5732 5d pop ebp83fa5733 c20800 ret 8
    Win7 64 位 PsSetCreateProcessNotifyRoutinelkd> u PsSetCreateProcessNotifyRoutinent!PsSetCreateProcessNotifyRoutine:fffff800`042be3c0 4533c0 xor r8d,r8dfffff800`042be3c3 e9e8fdffff jmp nt!PspSetCreateProcessNotifyRoutine (fffff800`042be1b0)
    Win8.1 32 位 PsSetCreateProcessNotifyRoutinelkd> uf PsSetCreateProcessNotifyRoutinent!PsSetCreateProcessNotifyRoutine:811617d2 8bff mov edi,edi811617d4 55 push ebp811617d5 8bec mov ebp,esp811617d7 8a550c mov dl,byte ptr [ebp+0Ch]811617da 8b4d08 mov ecx,dword ptr [ebp+8]811617dd 6a00 push 0811617df e89a000000 call nt!PspSetCreateProcessNotifyRoutine (8116187e)811617e4 5d pop ebp811617e5 c20800 ret 8
    Win8.1 64 位 PsSetCreateProcessNotifyRoutinelkd> u PsSetCreateProcessNotifyRoutinent!PsSetCreateProcessNotifyRoutine:fffff803`10775b00 4533c0 xor r8d,r8dfffff803`10775b03 e9bc000000 jmp nt!PspSetCreateProcessNotifyRoutine (fffff803`10775bc4)
    Win10 32 位 PsSetCreateProcessNotifyRoutinekd> uf PsSetCreateProcessNotifyRoutinent!PsSetCreateProcessNotifyRoutine:81e1c8d4 8bff mov edi,edi81e1c8d6 55 push ebp81e1c8d7 8bec mov ebp,esp81e1c8d9 8a550c mov dl,byte ptr [ebp+0Ch]81e1c8dc 8b4d08 mov ecx,dword ptr [ebp+8]81e1c8df 6a00 push 081e1c8e1 e818010000 call nt!PspSetCreateProcessNotifyRoutine (81e1c9fe)81e1c8e6 5d pop ebp81e1c8e7 c20800 ret 8
    Win10 64 位 PsSetCreateProcessNotifyRoutinekd> u PsSetCreateProcessNotifyRoutinent!PsSetCreateProcessNotifyRoutine:fffff800`a09a4460 33c0 xor eax,eaxfffff800`a09a4462 84d2 test dl,dlfffff800`a09a4464 448d4001 lea r8d,[rax+1]fffff800`a09a4468 410f45c0 cmovne eax,r8dfffff800`a09a446c 8bd0 mov edx,eaxfffff800`a09a446e e9bd000000 jmp nt!PspSetCreateProcessNotifyRoutine (fffff800`a09a4530)
    3 留言 2019-03-16 10:05:02 奖励12点积分
  • 两种方式实现DLL导出函数之dllexport与def文件导出

    背景我们开发DLL的时候,大部分都会导出函数。对于导出函数,常用的有两种方式,一种是使用 dllexport 关键字导出,另一种是使用 .def 文件导出。我个人比较喜欢用后一种方式导出函数,因为用起来比较省心、方便。
    现在,我就把这部分知识整理成文档,分享给大家。
    实现过程dllexport关键字方法这种方法就是在函数声明中加上 __declspec(dllexport) 关键字,同时也要加上 extern “C” 这个前缀,加上extern “C”后,会指示编译器这部分代码按C语言的进行编译,而不是C++的。
    那么, __declspec(dllexport) 关键字导出函数的代码如下所示:
    // 方法一 dllexportextern "C" __declspec(dllexport) BOOL MyExportFunc_dllexport(char *pszText, char *pszCaption){ ::MessageBox(NULL, pszText, pszCaption, MB_OK); return TRUE;}
    def文件方法def文件方法相对于上面介绍的 __declspec(dllexport) 要更简便,而且很容易理解使用。
    一般我们创建的DLL工程是没有 .def 这个文件的,需要我们创建并添加到项目工程中,添加方式如下:
    选中工程项目,右击选择“添加”,并选中“新建项”,在新建项中选择“Visual C++”下的“代码”中的“模块定义文件(.def)”文件,并输入文件名称,点击“添加”按钮,即可成功添加。

    添加成功后,我们在新建的 .def 模块定义文件中添加 “EXPORTS” 关键字段,这个表示DLL的导出函数位置。然后在 “EXPORTS” 字段下面添加要导出函数的名称即可。如下图,导出 “MyExportFunc_def” 这个函数。注意,只需写文件名即可。

    这样,对于要导出的函数,我们按正常编写的方式编写即可,不需要额外添加任何关键字,只需要把要导出的函数的函数名称放在“EXPORTS”字段下面就可以成功导出函数。
    // 方法一 def文件BOOL MyExportFunc_def(char *pszText, char *pszCaption){ ::MessageBox(NULL, pszText, pszCaption, MB_OK); return TRUE;}
    程序测试我们对上面的DLL工程项目进行编译链接,生成DLL文件。然后使用,“DEPENDS.EXE”工具查看新生成的DLL文件的导出函数。我们可以看到上述分别使用两种导出函数方法导出的导出函数均成功导出。

    总结对于上面两种导出方法来说,个人推荐 .def 模块定义文件 导出方式,要注意的是,要记得自己手动添加这个文件,并在文件中添加“EXPORTS”导出字段。
    2 留言 2018-11-07 11:03:06 奖励5点积分
  • 编程实现MFC程序窗口一运行立马隐藏 精华

    背景MFC程序在启动显示窗口之前,就已经做了很多关于界面初始化的操作。如果对WIN32 API函数较为熟悉的同学就会认为,让窗口隐藏,直接调用 ShowWindow 函数,将窗口设置为隐藏就可以了。是的,ShowWindow 函数可以隐藏窗口没错。但是,这个函数要成功实现的窗口隐藏有一个前提条件,就是窗口界面初始化已经完成,而且窗口界面你已经显示完全了。这时,再调用 ShowWindow 函数去隐藏窗口,这是可以的。
    但是,本文要实现的是,窗口程序一运行就已经开始隐藏的功能,而不是显示后隐藏。也就是说,在窗口界面初始化阶段,窗口界面还没有显示的时候,就已经开始隐藏界面了。这样的隐藏,使得程序运行无声无息。
    现在,我们把这个程序的实现过程整理成文档,分享给大家。
    函数介绍MoveWindow 函数
    改变指定窗口的位置和大小。对子窗口来说,位置和大小取决于父窗口客户区的左上角;对于Owned窗口,位置和大小取决于屏幕左上角。
    函数声明
    BOOL MoveWindow( HWND hWnd, int X, int Y, int nWidth, int nHeight, BOOL bRepaint );
    参数

    hWnd [in]窗口的句柄。X [in]窗口左侧的新位置。Y [in]窗口顶部的新位置。nWidth [in]窗口的新宽度。nHeight [in]窗口的新高度。bRepaint [in]指示窗口是否要重画。 如果此参数为TRUE,窗口将收到一条消息。 如果参数为FALSE,则不会发生任何重画。 这适用于客户端区域,非客户区域(包括标题栏和滚动条),父窗口的任何部分由于移动子窗口而被覆盖。
    返回值

    如果函数成功,则返回值不为零。如果函数失败,返回值为零。 要获取扩展错误信息,请调用GetLastError。

    GetWindowLong 函数
    获取有关指定窗口的信息。 函数也获得在额外窗口内存中指定偏移位地址的32位度整型值。
    函数声明
    LONG GetWindowLong( HWND hWnd, int nlndex );
    参数

    hWnd目标窗口的句柄。它可以是窗口句柄及间接给出的窗口所属的窗口类。
    nlndex需要获得的相关信息的类型。要获得任意其他值,指定下列值之一:




    VALUE
    MEANING




    GWL_EXSTYLE
    获得扩展窗口风格。


    GWL_HINSTANCE
    获得应用实例的句柄


    GWL_HWNDPARENT
    如果父窗口存在,获得父窗口句柄


    GWL_ID
    获得窗口标识


    GWL_STYLE
    获得窗口风格


    GWL_USERDATA
    获得与窗口有关的32位值。每一个窗口均有一个由创建该窗口的应用程序使用的32位值


    GWL_WNDPROC
    获得窗口过程的地址,或代表窗口过程的地址的句柄。必须使用CallWindowProc函数调用窗口过程



    hWnd参数为对话框句柄时,还可用下列值:



    VALUE
    MEANING




    DWL_DLGPROC
    获得对话框过程的地址,或一个代表对话框过程的地址的句柄。必须使用函数CallWindowProc来调用对话框过程


    DWL_MSGRESULT
    获得在对话框过程中一个消息处理的返回值


    DWL_USER
    获得应用程序私有的额外信息,例如一个句柄或指针



    返回值

    如果函数成功,返回值是所需的32位值;如果函数失败,返回值是0。若想获得更多错误信息请调用 GetLastError函数。

    SetWindowLong 函数
    用来改变指定窗口的属性.函数也将指定的一个32位值设置在窗口的额外存储空间的指定偏移位置。
    函数声明
    LONG SetWindowLong( HWND hWnd, // handle to window int nlndex, // offset of value to set LONG dwNewLong // new value);
    参数

    hWnd窗口句柄及间接给出的窗口所属的类。nlndex设置相关信息的类型。要获得任意其他值,指定下列值之一(和上面 GetWindowLong 函数的 nIndex 值相同)。dwNewLong指定的替换值。
    返回值

    如果函数成功,返回值是指定的32位整数的原来的值。如果函数失败,返回值为0。若想获得更多错误信息,请调用GetLastError函数。

    实现原理窗口移动到显示屏幕之外要设置程序窗口显示的位置和大小,我们可以直接调用 MoveWindow 函数,设置移动后窗口显示的位置坐标、窗口大小。这时,我们只需要将窗口大小都设为 0 ,位置坐标都设为-1000(屏幕位置坐标以屏幕左上角为起点),这样窗口就在屏幕之外显示了。
    隐藏任务栏程序图标其中,我们先来了解 GWL_EXSTYLE 窗口拓展属性中的两个值的含义,这是要理解隐藏任务栏比较关键的一步:
    一是 WS_EX_APPWINDOW,表示当窗口可见时,将一个顶层窗口放置到任务条上;
    二是 WS_EX_TOOLWINDOW,表示创建工具窗口,即窗口是一个游动的工具条。工具窗口的标题条比一般窗口的标题条短,并且窗口标题以小字体显示。工具窗口不在任务栏里显示,当用户按下alt+Tab键时工具窗口不在对话框里显示。如果工具窗口有一个系统菜单,它的图标也不会显示在标题栏里,但是,可以通过点击鼠标右键或Alt+Space来显示菜单。
    由上面 WS_EX_APPWINDOW 和 WS_EX_TOOLWINDOW 可知,我们要想实现任务栏程序的隐藏。那么,就要把 WS_EX_APPWINDOW 值去掉,然后再增加值 WS_EX_TOOLWINDOW。所以:

    首先调用 GetWindowLong 函数获取窗口 GWL_EXSTYLE 属性的值 dwOldStyle;
    然后,去掉 WS_EX_APPWINDOW 值,即
    dwOldStyle & (~WS_EX_APPWINDOW)
    接着,增加 WS_EX_APPWINDOW 值,即
    dwNewStyle = dwNewStyle | WS_EX_TOOLWINDOW;
    最后,调用 SetWindowLong 将新的 GWL_EXSTYLE 属性的值重新设置,这样就完成了。

    编码实现// 隐藏窗口void HideWindow(HWND hWnd){ // 把窗口移动到屏幕显示之外, 窗口大小都设为 0 ::MoveWindow(hWnd, -1000, -1000, 0, 0, FALSE); // 先获取原来窗口的拓展风格 DWORD dwOldStyle = ::GetWindowLong(hWnd, GWL_EXSTYLE); // 设置新属性, 隐藏任务栏程序图标 DWORD dwNewStyle = dwOldStyle & (~WS_EX_APPWINDOW); dwNewStyle = dwNewStyle | WS_EX_TOOLWINDOW; ::SetWindowLong(hWnd, GWL_EXSTYLE, dwNewStyle);}
    总结我们隐藏窗口的思路就两点:一是把窗口的显示位置坐标移到屏幕之外,这样窗口显示的时候,在屏幕之内是看不到的;二是把任务栏的程序图标隐藏,因为第一步操作会因为任务栏下的图标露出马脚,所以,必须隐藏任务栏中程序的图标。这样,就可以实现一运行程序,窗口就隐藏了。
    大家要注意,虽然窗口隐藏了,我们打开任务管理器还是会看到我们程序的进程的。所以,关于进程隐藏,就是另一个不同知识点了。
    参考参考自《Windows黑客编程技术详解》一书
    2 留言 2018-11-07 11:20:19 奖励15点积分
  • 使用TransparentBlt函数实现绘制透明位图

    背景在自己本科的时候,喜欢用 VC6.0 写一些小游戏来锻炼自己的编程水平。那些小游戏的游戏画面绘制都是使用Windows提供的GDI(图形设备接口)函数实现的,并没有调用现成的游戏引擎。所以,使得自己对GDI函数比较熟悉,能用它开发各式各样的小游戏。
    其中,那些小游戏都会用到的一个关键技术,便是透明位图的绘制。现在,我把之前自己开发小游戏时,绘制透明位图的方法总结一下,分别为大家介绍一下三种实现方法:一是使用 BitBlt 函数实现;二是使用 StretchBlt 函数实现;三是使用 TransparentBlt 函数实现。
    这三种方法,分别为其写一遍文档进行介绍,本文介绍的是 TransparentBlt 函数实现透明位图的绘制。
    函数介绍TransparentBlt 函数
    对指定的源设备环境中的矩形区域像素的颜色数据进行位块(bit_block)转换,并将结果置于目标设备环境。
    函数声明
    BOOL TransparentBlt( HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int hHeightDest, HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, UINT crTransparent );
    参数

    hdcDest:指定目标的句柄。nXOriginDest:指定目标矩形左上角的X轴坐标,坐标以逻辑单位表示。nYOriginDest:指定目标矩形左上角的Y轴坐标,坐标以逻辑单位表示。nnWidthDest:指定目标矩形的宽度。nHeightDest:指定目标矩形的高度。hdcSrc:源图的句柄。nXOriginSrc:指定源矩形(左上角)的X轴坐标,坐标以逻辑单位表示。nYOriginsrc:指定源矩形(左上角)的Y轴坐标,坐标以逻辑单位表示。nWidthSrc:指定源矩形的宽度。nHeightSrc:指定源矩形的高度。crTransparent:源位图中的RGB值当作透明颜色。(用RGB(0,0,0)也就是黑色不行)。
    返回值

    如果函数成功,那么返回TRUE;如果函数失败,则返回FALSE。

    什么是位图透明处理?至于如何使用 BitBlt 函数绘制位图,我在《BMP位图的绘制》这篇有讲过,当然这只是其中一种绘图方法而已,并不是唯一的。
    那我就先来介绍下,什么是透明位图的绘制。用下面的图片直观表示吧:
    如果我们有两张图片,一张是背景图:

    一张是人物图:

    现在,我想把人物绘制到背景图上,那么按照通常的方法就是,把人物的图片直接在背景图上显示就好,效果如下所示:

    大家可能会看到有些问题了吧,我们其实想要的是下面这张图片的效果:

    没错,所谓的透明位图的绘制就像上面图片表示出来的那样。就是我们只绘制图片特定的地方,而且形状都是不规则的,其他的不进行绘制。就对上上面的例子来说,就是把人物抠出来绘制,背景的蓝色不绘制,即背景像似透明一样,所以这便是位图的透明绘制。
    编程实现原理对于,TransparentBlt 函数来说,它的最后一个参数指定除黑色RGB(0, 0, 0)外的其它透明颜色。所谓的透明颜色是指,只要是指定RGB值的颜色,使用Transparent函数都不会绘制,只绘制其他非指定透明颜色RGB值的颜色。
    对于上面的例子来说,我们只要指定透明颜色RGB为蓝色(0, 0, 255),这样,就可以不绘制蓝色,而只绘制非蓝色部分的人物图像了。
    对于,为何指定了透明颜色,就可以实现透明处理,其本质的原理可以参考我写的《使用BitBlt函数实现绘制透明位图》和《使用StretchBlt函数实现绘制透明位图》这两篇文章中的透明原理的分析。Transparent 函数的实现,应该是调用 StretchBlt 函数去实现的。
    编码实现导入库文件#include <WinGDI.h>#pragma comment(lib, "Msimg32.lib")
    绘制背景位图BOOL PaintBmp(HWND hWnd){ // 获取窗口的客户区域的显示设备上下文环境的句柄 HDC hDC = ::GetDC(hWnd); // 创建一个与hDC兼容的内存设备上下文环境 HDC hBuf = ::CreateCompatibleDC(hDC); // 加载位图, 获取位图句柄 HBITMAP hBmp = (HBITMAP)::LoadImage(NULL, "image\\bg.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); // 选择位图句柄到hBuf中, 并获取返回的原来位图句柄 HBITMAP hOldBmp = (HBITMAP)::SelectObject(hBuf, hBmp); // 绘图 ::BitBlt(hDC, 0, 0, 764, 397, hBuf, 0, 0, SRCCOPY); // 还原位图对象 ::SelectObject(hBuf, hOldBmp); // 释放位图 ::DeleteObject(hBmp); // 释放兼容的内存设备上下文环境 ::DeleteDC(hBuf); // 释放设备上下文环境 ::ReleaseDC(hWnd, hDC); return TRUE;}
    绘制透明位图BOOL PaintTransparentBmp(HWND hWnd){ // 获取窗口的客户区域的显示设备上下文环境的句柄 HDC hDC = ::GetDC(hWnd); // 创建一个与hDC兼容的内存设备上下文环境 HDC hBuf = ::CreateCompatibleDC(hDC); // 加载位图, 获取位图句柄 HBITMAP hBmp = (HBITMAP)::LoadImage(NULL, "image\\1.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); // 选择位图句柄到hBuf中, 并获取返回的原来位图句柄 HBITMAP hOldBmp = (HBITMAP)::SelectObject(hBuf, hBmp); // 透明色为蓝色 绘制 ::TransparentBlt(hDC, 280, 210, 200, 200, hBuf, 0, 0, 101, 121, RGB(0, 0, 255)); // 还原位图对象 ::SelectObject(hBuf, hOldBmp); // 释放位图 ::DeleteObject(hBmp); // 释放兼容的内存设备上下文环境 ::DeleteDC(hBuf); // 释放设备上下文环境 ::ReleaseDC(hWnd, hDC); return TRUE;}
    程序测试调用上述封装好的函数,直接测试。人物位图成功背景透明绘制到背景图上。而且,人物还能成功拉伸绘制。

    总结使用 TransparentBlt 函数实现透明位图处理,应该是这三种实现方法中最为简单,也是最容易理解的。而且,使用起来还比较简洁灵活。
    参考参考自《Windows黑客编程技术详解》一书
    2 留言 2018-12-29 15:12:35 奖励5点积分
  • 【Cocos Creator实战教程(13)】——播放声音 精华

    1. 相关知识点1.1 使用 AudioSource 组件播放创建一个空节点,在这个空节点上,添加一个 其他组件 -> AudioSource在脚本上预设好 AudioSource,并且根据实际需求,完善脚本的对外接口,如下:
    cc.Class({ properties: { audioSource: { type: cc.AudioSource, default: null }, }, play: function () { this.audioSource.play(); }, pause: function () { this.audioSource.pause(); },});
    1.2 使用 AudioEngine 播放在脚本内定义一个 audioClip 资源对象,如下示例中 properties 对象内。直接使用 cc.audioEngine.play(audio, loop, volume); 播放。如下示例中 onLoad 中。
    cc.Class({ properties: { audio: { default: null, type: cc.AudioClip } }, onLoad: function () { this.current = cc.audioEngine.play(this.audio, false, 1); }, onDestroy: function () { cc.audioEngine.stop(this.current); }});
    AudioEngine 播放的时候,需要注意这里的传入的是一个完整的 AudioClip 对象(而不是 url)。 所以我们不建议在 play 接口内直接填写音频的 url 地址,而是希望大家先定义一个 AudioClip,然后在编辑器内将音频拖拽过来。
    2. 步骤播放声音有两种方式
    2.1 组件AudioSourceplay ( )播放音频剪辑。stop ( )停止当前音频剪辑。pause ( )暂停当前音频剪辑。resume ( )恢复播放。rewind ( )从头开始播放。
    2.2 声音系统//背景音乐,循环cc.audioEngine.playMusic(source);cc.audioEngine.stopMusic(source);//短音效cc.audioEngine.playEffect(source);cc.audioEngine.stopEffect(source);
    上面的第一种方法原生平台有很多Bug,所以我们的游戏都用的第二种方法播放声音
    3.总结加上音效,让游戏锦上添花
    本教程部分资源来源于网络。
    2 留言 2018-12-01 20:12:02 奖励25点积分
显示 75 到 90 ,共 15 条
eject