实现过写拷贝实现全局HOOK
前言:滴水的驱动过写拷贝实现全局HOOK的练习
实现代码:https://github.com/chibd2000/monitor-write-copy-messagebox
问题1
听大家都说一个进程的4GB的线性空间,其中相关的系统DLL的线性地址都是指向物理页中的系统DLL的,也就是说系统DLL只有一份,那为什么HOOK了一个进程中的user32.dll的Messagebox的地址,为什么还是不能实现全局的HOOK?
这里的话就是操作系统的原因了,"其中相关的系统DLL的线性地址都是指向物理页中的系统DLL的,也就是说系统DLL只有一份",这句话是对的,但是其中还有一些别的原因,操作系统还会干一些别的事。
什么是写保护和写拷贝
上面的问题就是由写拷贝的操作,其实系统DLL的内存属性就是所谓的写拷贝(writecopy),那么当对进程中的系统DLL进行写的时候,由于它是写拷贝的属性,它就会触发写保护的机制。
流程:
当你对A进程的系统DLL的内存进行HOOK修改的时候,因为当前内存属性为写拷贝类型,那么就会触发异常,所以当操作系统的异常处理处理接收到异常的时候,判断VAD中当前要写的内存是否是写拷贝属性,如果是的话操作系统会重新分配一段新的物理页(就是你要写的那一段物理页,并不是当前DLL整个物理页),然后将PTE所指向的地址改到新分配的物理页上,这样的操作流程过后,最终导致的就是只能HOOK当前A的进程,不能实现全局HOOK。
如何确定当前的PTE是写拷贝导致重新指向其他的物理页的?老师说PTE中有个保留位,其中有个位能表示这个PTE所指向的物理页是写拷贝产生的,具体没研究过
考察知识点
1、代码界面简单编写
2、代码实现加载驱动程序
3、0环-3环通信
4、HOOK
5、shellcode
6、保护模式
知识点(自己的理解,不知道对措)
1、写拷贝是VAD树里内存的一个属性,内存还可以是可读,可写,可读写
2、过写保护 相当于 绕过写拷贝
3、写拷贝和只读内存的区别?写拷贝如果异常,操作系统接收并且另外处理,只读内存操作系统接收返回0xC0000005
这个问题其实换句话来说其实如何才知道一个内存是写拷贝还是只读内存。当
实现思路(失败)
1、三环模拟驱动加载
2、三环遍历LDR_MODULE获取USER32.DLL的MessageBox函数线性地址
3、三环与零环通信,将MessageBox函数的线性地址发送
4、零环接收到三环的MessageBox函数线性地址的消息,读取该MessageBox函数的线性地址,然后对MessageBox函数的线性地址修改 PTE 和 PDE 的属性过写拷贝
5、零环申请非分页方式的物理页,然后对该地址进行写上相关的shellcode,ZwCreateFile ZwWriteFile ZwClose 全部都写成shellcode
6、零环对MessageBox函数的开头5个字节的函数进行inline hook,E8 CALL到新申请到的非分页方式的线性地址上
7、卸载驱动,将 MessageBox 前5字节改回如下所示
实现思路(成功)
最一开始的思路,有个地方会出现问题,也就是inline hook的时候,如果开头是JMP 高2G,但问题是你在三环无法跑到高2G进行执行,如果改对应高2G的HOOK函数的PDE和PTE也没用,因为改的也只是读写,没有可执行的属性啊,所以inline hook需要改成调用门版的inline hook,还需要先进行提权,然后再跳转到hook的函数再进行执行
1、三环模拟驱动加载
2、三环遍历LDR_MODULE获取USER32.DLL的MessageBox函数线性地址
3、三环与零环通信,将MessageBox函数的线性地址发送
4、零环接收到三环的MessageBox函数线性地址的消息,读取该MessageBox函数的线性地址,然后对MessageBox函数的线性地址修改 PTE 和 PDE 的属性过写拷贝
5、零环申请非分页方式的物理页,然后对该地址进行写上相关的shellcode,ZwCreateFile ZwWriteFile ZwClose 全部都写成shellcode
6、零环对MessageBox函数的开头5个字节的函数进行inline hook,E8 CALL到新申请到的非分页方式的线性地址上
5、零环定义一个相关的HOOK函数为了记录相关的MessageBox的参数,实现相关的ZwCreateFile ZwWriteFile ZwClose
6、零环定义一个中断门/调用门的入口函数,这个函数是跳到HOOK函数的跳板函数
6、inline hook messagebox的前2/5个字节,可以进行中断门提权,也可以进行调用门提权,跳转的地址为中断门/调用门的入口函数
7、卸载驱动,将 MessageBox 前2/5字节改回原来的即可
效果
HOOK效果如下,可以已经进行inline hook了
测试MessageBoxA
记录参数
取消HOOK效果如下,可以看到inline hook已经被抹除了