一丶简介

纯属兴趣爱好.特来逆向玩玩.

PsSetLoadImageNotifyRoutine 是内核中用来监控模块加载.操作系统给我们提供的回调. 我们只需要填写对应的回调函数原型即可进行加监控.

既然可以进行监控.那么我们的回调函数存储在哪.这是个问题.所以特来逆向玩玩.

二丶逆向过程

首先我的思路是直接windbg 挂载win7. 然后找到对应的函数进行

uf 反汇编. 来静态查看. 如果那里有疑问则自己进行动态查看.

过程很快.因为逆向过 进程回调监控.所以这个也就很快了.慢慢学习经验.

1.逆向PsSetLoadImageNotifyRoutine


3f809b3 8bff mov edi,edi
83f809b5 55 push ebp
83f809b6 8bec mov ebp,esp
83f809b8 53 push ebx
83f809b9 56 push esi
83f809ba 57 push edi
83f809bb 33ff xor edi,edi
83f809bd 57 push edi 83f809be ff7508 push dword ptr [ebp+8] 参数1压栈: 参数1 = 我们设置的回调函数地址. 83f809c1 e8113d0200 call nt!ExAllocateCallBack (83fa46d7) 逆向一下ExAllocateCallBack
83f809c6 8bd8 mov ebx,eax
83f809c8 3bdf cmp ebx,edi
83f809ca 7425 je nt!PsSetLoadImageNotifyRoutine+0x3e (83f809f1) //内部会申请一个结构体内存.保存我们的函数指针 以及 参数 结果给eax. nt!PsSetLoadImageNotifyRoutine+0x19:
83f809cc be802bf583 mov esi,offset nt!PspLoadImageNotifyRoutine (83f52b80)//得出回调函数数组. nt!PsSetLoadImageNotifyRoutine+0x1e:
83f809d1 6a00 push 0 0
83f809d3 8bcb mov ecx,ebx ecx = 结构体指针
83f809d5 8bc6 mov eax,esi eax = 回调函数数组.
ExCompareExchangeCallBack(函数数组,结构体指针,0); 根据函数名可以得知 比较交换回调函数指针. 逆向志之 在下面观看.
83f809d7 e82a3d0200 call nt!ExCompareExchangeCallBack (83fa4706)
83f809dc 84c0 test al,al
83f809de 751d jne nt!PsSetLoadImageNotifyRoutine+0x4a (83f809fd) nt!PsSetLoadImageNotifyRoutine+0x2d:
83f809e0 83c704 add edi,4
83f809e3 83c604 add esi,4
83f809e6 83ff20 cmp edi,20h
83f809e9 72e6 jb nt!PsSetLoadImageNotifyRoutine+0x1e (83f809d1) nt!PsSetLoadImageNotifyRoutine+0x38:
83f809eb 53 push ebx
83f809ec e824b71000 call nt!SepFreeCapturedString (8408c115) nt!PsSetLoadImageNotifyRoutine+0x3e:
83f809f1 b89a0000c0 mov eax,0C000009Ah nt!PsSetLoadImageNotifyRoutine+0x43:
83f809f6 5f pop edi
83f809f7 5e pop esi
83f809f8 5b pop ebx
83f809f9 5d pop ebp
83f809fa c20400 ret 4 nt!PsSetLoadImageNotifyRoutine+0x4a:
83f809fd 33c9 xor ecx,ecx
83f809ff b8a02bf583 mov eax,offset nt!PspLoadImageNotifyRoutineCount (83f52ba0)
83f80a04 41 inc ecx
83f80a05 f00fc108 lock xadd dword ptr [eax],ecx
83f80a09 a1782bf583 mov eax,dword ptr [nt!PspNotifyEnableMask (83f52b78)]
83f80a0e a801 test al,1
83f80a10 750a jne nt!PsSetLoadImageNotifyRoutine+0x69 (83f80a1c) nt!PsSetLoadImageNotifyRoutine+0x5f:
83f80a12 b8782bf583 mov eax,offset nt!PspNotifyEnableMask (83f52b78)
83f80a17 f00fba2800 lock bts dword ptr [eax],0 nt!PsSetLoadImageNotifyRoutine+0x69:
83f80a1c 33c0 xor eax,eax
83f80a1e ebd6 jmp nt!PsSetLoadImageNotifyRoutine+0x43 (83f809f6)

通过逆向次函数.可以得出我们的回调函数数组. 以及我们申请的回调函数指针.

伪代码

{

    结构体指针 = ExAllocateCallBack(回调函数地址,0);
ExCompareExchangeCallBack(函数数组,结构体指针,0); 内部进行解密
}

关于上面的函数逆向.如下:

2.逆向 ExAllocateCallBack


3fa46d7 8bff mov edi,edi
83fa46d9 55 push ebp
83fa46da 8bec mov ebp,esp
83fa46dc 6843627262 push 62726243h
83fa46e1 6a0c push 0Ch
83fa46e3 6a01 push 1 83fa46e5 e81bc9f8ff call nt!ExAllocatePoolWithTag (83f31005) 申请内存 eax = ExAllocatePoolWithTag(1,0xC,62726243)
83fa46ea 85c0 test eax,eax 83fa46ec 740f je nt!ExAllocateCallBack+0x26 (83fa46fd) 83fa46ee 8b4d08 mov ecx,dword ptr [ebp+8] ecx = 参数1
83fa46f1 832000 and dword ptr [eax],0 struct->one = 0
83fa46f4 894804 mov dword ptr [eax+4],ecx struct->two = ecx[ebp + 8] ==> 参数二
83fa46f7 8b4d0c mov ecx,dword ptr [ebp+0Ch]
83fa46fa 894808 mov dword ptr [eax+8],ecx struct->Three = [eb[ + c] ==> 参数三
83fa46fd 5d pop ebp
83fa46fe c20800 ret 8

汇编代码很简单.通过下面进行赋值可以看做是一个结构体

逆向得知,ExAllocateCallBack其实是申请一块内存.

并且转化为一个结构进行赋值

例如下:

struct
{
ULONG UnKnow1;
ULONG UnKnow2;
ULONG UnKnow3;
}

但是根据传参得知. UnKnow2 == 我们的回调地址 Unknow3 ==> 我们的参数

然后查看Wrk源码.得出以下结构

typedef struct _EX_CALLBACK_ROUTINE_BLOCK {
EX_RUNDOWN_REF RundownProtect;
PEX_CALLBACK_FUNCTION Function;
PVOID Context;
} EX_CALLBACK_ROUTINE_BLOCK, *PEX_CALLBACK_ROUTINE_BLOCK;

3.逆向交换 解密函数 ExCompareExchangeCallBack


nt!ExCompareExchangeCallBack:
83fa4706 8bff mov edi,edi
83fa4708 55 push ebp
83fa4709 8bec mov ebp,esp 83fa470b 51 push ecx
83fa470c 51 push ecx
83fa470d 53 push ebx
83fa470e 56 push esi
83fa470f 57 push edi 83fa4710 8bf0 mov esi,eax eax ============> 回调函数数组 83fa4712 85c9 test ecx,ecx ecx = 结构体指针 83fa4714 7410 je nt!ExCompareExchangeCallBack+0x20 (83fa4726) nt!ExCompareExchangeCallBack+0x10:
83fa4716 6a08 push 8
83fa4718 5a pop edx
83fa4719 e87670efff call nt!ExAcquireRundownProtectionEx (83e9b794)
83fa471e 84c0 test al,al 83fa4720 0f84aa000000 je nt!ExCompareExchangeCallBack+0xca (83fa47d0) nt!ExCompareExchangeCallBack+0x20: 83fa4726 8b1e mov ebx,dword ptr [esi] ebx = 数组[0]
83fa4728 8bc3 mov eax,ebx eax = ebx 83fa472a eb1d jmp nt!ExCompareExchangeCallBack+0x43 (83fa4749) nt!ExCompareExchangeCallBack+0x26:
83fa472c 85c9 test ecx,ecx
83fa472e 7407 je nt!ExCompareExchangeCallBack+0x31 (83fa4737) nt!ExCompareExchangeCallBack+0x2a:
83fa4730 8bc1 mov eax,ecx
83fa4732 83c807 or eax,7
83fa4735 eb02 jmp nt!ExCompareExchangeCallBack+0x33 (83fa4739) nt!ExCompareExchangeCallBack+0x31:
83fa4737 33c0 xor eax,eax nt!ExCompareExchangeCallBack+0x33:
83fa4739 8bd0 mov edx,eax
83fa473b 8bfe mov edi,esi
83fa473d 8bc3 mov eax,ebx
83fa473f f00fb117 lock cmpxchg dword ptr [edi],edx
83fa4743 3bc3 cmp eax,ebx
83fa4745 740a je nt!ExCompareExchangeCallBack+0x4b (83fa4751) nt!ExCompareExchangeCallBack+0x41:
83fa4747 8bd8 mov ebx,eax =================================> nt!ExCompareExchangeCallBack+0x43:
83fa4749 334508 xor eax,dword ptr [ebp+8] 数组[0] ^ 0 = 自己本身
83fa474c 83f807 cmp eax,7
83fa474f 76db jbe nt!ExCompareExchangeCallBack+0x26 (83fa472c) //eax = 数组[0] 所以不走这个循环. nt!ExCompareExchangeCallBack+0x4b:
83fa4751 8bfb mov edi,ebx 开始解密 edi = ebx = 数组[0]
83fa4753 83e7f8 and edi,0FFFFFFF8h edi = 数组[0] & 0xFFFFFFF8 = 结构体指针. 至此已经解析完毕了.
83fa4756 3b7d08 cmp edi,dword ptr [ebp+8]
83fa4759 7569 jne nt!ExCompareExchangeCallBack+0xbe (83fa47c4) nt!ExCompareExchangeCallBack+0x55:
83fa475b 85ff test edi,edi
83fa475d 7461 je nt!ExCompareExchangeCallBack+0xba (83fa47c0) nt!ExCompareExchangeCallBack+0x59:
83fa475f 648b3524010000 mov esi,dword ptr fs:[124h]
83fa4766 66ff8e86000000 dec word ptr [esi+86h]
83fa476d 8745fc xchg eax,dword ptr [ebp-4]
83fa4770 8b0dd8c7f483 mov ecx,dword ptr [nt!ExpCallBackFlush (83f4c7d8)]
83fa4776 83e101 and ecx,1
83fa4779 8745f8 xchg eax,dword ptr [ebp-8]
83fa477c 85c9 test ecx,ecx
83fa477e 7414 je nt!ExCompareExchangeCallBack+0x8e (83fa4794) nt!ExCompareExchangeCallBack+0x7a:
83fa4780 b9d8c7f483 mov ecx,offset nt!ExpCallBackFlush (83f4c7d8)
83fa4785 e803e4efff call nt!ExfAcquirePushLockExclusive (83ea2b8d)
83fa478a b9d8c7f483 mov ecx,offset nt!ExpCallBackFlush (83f4c7d8)
83fa478f e81d10f8ff call nt!ExfReleasePushLockExclusive (83f257b1) nt!ExCompareExchangeCallBack+0x8e:
83fa4794 66ff8686000000 inc word ptr [esi+86h]
83fa479b 0fb78686000000 movzx eax,word ptr [esi+86h]
83fa47a2 6685c0 test ax,ax
83fa47a5 750c jne nt!ExCompareExchangeCallBack+0xad (83fa47b3) nt!ExCompareExchangeCallBack+0xa1:
83fa47a7 8d4640 lea eax,[esi+40h]
83fa47aa 3900 cmp dword ptr [eax],eax
83fa47ac 7405 je nt!ExCompareExchangeCallBack+0xad (83fa47b3) nt!ExCompareExchangeCallBack+0xa8:
83fa47ae e8e63ce9ff call nt!KiCheckForKernelApcDelivery (83e38499) nt!ExCompareExchangeCallBack+0xad:
83fa47b3 8bd3 mov edx,ebx
83fa47b5 83e207 and edx,7
83fa47b8 42 inc edx
83fa47b9 8bcf mov ecx,edi
83fa47bb e81718eaff call nt!ExReleaseRundownProtectionEx (83e45fd7) nt!ExCompareExchangeCallBack+0xba:
83fa47c0 b001 mov al,1
83fa47c2 eb0e jmp nt!ExCompareExchangeCallBack+0xcc (83fa47d2) nt!ExCompareExchangeCallBack+0xbe:
83fa47c4 85c9 test ecx,ecx
83fa47c6 7408 je nt!ExCompareExchangeCallBack+0xca (83fa47d0) nt!ExCompareExchangeCallBack+0xc2:
83fa47c8 6a08 push 8
83fa47ca 5a pop edx
83fa47cb e80718eaff call nt!ExReleaseRundownProtectionEx (83e45fd7) nt!ExCompareExchangeCallBack+0xca:
83fa47d0 32c0 xor al,al nt!ExCompareExchangeCallBack+0xcc:
83fa47d2 5f pop edi
83fa47d3 5e pop esi
83fa47d4 5b pop ebx
83fa47d5 c9 leave
83fa47d6 c20400 ret 4

逆向这个函数可以得知.最后我们的数组会与 0xFFFFFFF8 进行and操作.操作之后的结果就是我们上面 逆向ExAllocateCallBack

得出的结构体指针原型.

结构体->two 成员就是记录我们想要的回调函数地址.

三丶总结

1.通过逆向 ExAllocateCallBack 我们得出了结构体原型.以及我们的回调函数如何存储

typedef struct _EX_CALLBACK_ROUTINE_BLOCK {

EX_RUNDOWN_REF RundownProtect;

PEX_CALLBACK_FUNCTION Function;

PVOID Context;

} EX_CALLBACK_ROUTINE_BLOCK, *PEX_CALLBACK_ROUTINE_BLOCK;

2.通过逆向 ExCompareExchangeCallBack我们得知数组是如何解密的

PEX_CALLBACK_ROUTINE_BLOCK pRoutine = 数组[0] & 0xFFFFFFF8;

pRoutine->Function == 我们要寻找的回调函数

3.简介

从以前的逆向PsSetCreateProcessRoutine得知.他也是通过 & 0xFFFFFFFF8进行解密的.

win64的也有逆向出来. 界面的数值为 & 0xFFFFFFFFFFFFFFF0 进行解密的. 关于64的.后面继续发.

在64位下感觉数组解密应该用的都是 0xFFFFFFFFFFFFFFF0 进行解密的(win7 64)

x32下PsSetLoadImageNotifyRoutine的逆向的更多相关文章

  1. X64下MmIsAddressValid的逆向及内存寻址解析

    标 题: [原创]X64下MmIsAddressValid的逆向及内存寻址解析 作 者: 普通朋友 时 间: 2015-10-21,20:03:52 链 接: http://bbs.pediy.com ...

  2. x32下逆向 PsSetCreateProcessNotifyRoutine 进程钩子

    目录 一丶前言 二丶逆向过程 1.windbg挂载 win7 32位.定位到函数反汇编位置 2.逆向 PspSetCreateProcessNotifyRoutine 3.逆向 ExReference ...

  3. 在Intellij IDEA下通过Hibernate逆向生成实体类

    前言:在IDEA中,通过相关插件,可以利用Hibernate逆向生成数据表对应的实体类.具体操作及注意事项见本篇随笔. 1.创建一个基于maven的hibernate工程.并在工程中添夹hiberna ...

  4. x32下的DLL隐藏

    原理主要就是PEB 中模块断链. 这里整理下代码.原理可以看下另一篇我写的帖子. https://www.cnblogs.com/iBinary/p/9601860.html // dllmain.c ...

  5. eclipse下 hibernate逆向数据库操作示例!!

    做项目必然要先进行数据库表设计,然后根据数据库设计建立实体类(VO),这是理所当然的,但是到公司里做项目后,让我认识到,没有说既进行完数据库设计后还要再“自己”建立一变VO.意思是,在项目设计时,要么 ...

  6. eclipse从数据库逆向生成Hibernate实体类

    做项目必然要先进行数据库表设计,然后根据数据库设计建立实体类(VO),这是理所当然的,但是到公司里做项目后,让我认识到,没有说既进行完数据库设计后还要再“自己”建立一变VO.意思是,在项目设计时,要么 ...

  7. CrackMe005-下篇 | 逆向破解分析 | 160个CrackMe(视频+图文)深度解析系列

    作者:逆向驿站微信公众号:逆向驿站知乎:逆向驿站 CrackMe005,上篇说了具体方法,下篇来发逆向分析过程,看看老夫是如何得到上篇的具体方法的! 准备 [环境和工具] win7/xp虚拟机环境 C ...

  8. eclipse逆向生成hibernate的实体类(注解和配置文件)

    eclipse从数据库逆向生成Hibernate实体类(注解和配置文件) 分类: hibernate 数据库 java 2011-10-22 21:28 2915人阅读 评论(8) 收藏 举报 做项目 ...

  9. RTL2832U+R820T电视棒windows下安装sdr# 以及搭建ADS-B使用VirtualRadar看飞机的教程

    本文中提到的软件随后我会打包给出下载地址.这篇文章是我根据网上的教程和自己的经验修改的详细版本,为了方便入门新手.先来说说RTL2832U+R820T在windows下安装sdr#的方法.首先科普下s ...

随机推荐

  1. shell脚本开发基本规范

    当你的才华还撑不起你的野心的时候,你就应该静下心来学习.当你的能力还驾驭不了你的目标的时候,你就应该沉下心来历练.问问自己,想要怎样的人生. 欢迎加入 基础架构自动化运维:598432640,大数据S ...

  2. tar命令中的 -C 作用

    我用这个命令:tar zcvf chao.tar.gz /chao/*  打包文件的时候,在压缩包里把  /chao/这个路径也打包进去了. [root@yunwei-test chao]# ls / ...

  3. 【Mysql】索引简介

    本文口味:番茄炒蛋,预计阅读:10分钟. 博客又停更了两个月,在这期间,对人生和世界多了许多思考.在人生的不同阶段,会对生活和世界有着不一样的认知,而认知的改变也会直接反应在行为模式之中. 对于生活的 ...

  4. re正则

    #转义字符和原生字符 import re # # # 转义 # text = 'apple price is $299' # ret = re.search('\$\d+',text) # print ...

  5. scrapy基础知识之 Scrapy-Redis分布式策略:

    Scrapy-Redis分布式策略: 假设有四台电脑:Windows 10.Mac OS X.Ubuntu 16.04.CentOS 7.2,任意一台电脑都可以作为 Master端 或 Slaver端 ...

  6. 洛谷P1003 铺地毯 noip2011提高组day1T1

    洛谷P1003 铺地毯 noip2011提高组day1T1 洛谷原题 题目描述 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有 n ...

  7. django项目中遇到要实现定时任务

    django项目中遇到要实现定时任务,所以选用了简单易用的django-crontab插件. 1.安装 django-crontab pip install django-crontab 2.定时要执 ...

  8. Socket编程(C语言实现):bind()函数英文翻译

    本篇翻译的bind()函数,我参考的国外网站是: bind 朋友们可以自由转载我对英文的中文翻译,但是对于"作者注:"的描述,转载时请注明出处和作者,否则视为侵权. 下面是翻译的正 ...

  9. android_ratingBar

    主文件 package cn.com.sxp;import android.app.Activity;import android.os.Bundle;import android.util.Log; ...

  10. android_sdcard读写(三)

    这次来个稍微复杂点的. package cn.com.sxp;import android.app.Activity;import android.app.ProgressDialog;import ...