17_页面异常接管

页面异常捕获过滤:

原理:

在 IDT 表中的e 号 处理 是 页面异常处理; 如果 我们 hook 掉 这个回调函数;那么就能获得全部的页面异常;再通过 cr3 对比 捕获指定的 cr3 (进程)的信息;最后再共享的区域将数据输出;然后测试程序获取该自己的页面异常信息;

实验中 容易出现的错误:

在 c 的时候注意将使用的寄存器(这里是eax)先保存起来;注意 通过栈保存 eax的话注意 相关进入中断后和栈相关的数据,就会和esp 的相对偏移产生变化。

测试程序代码.c:

此程序 主要是 中断进入 内核;然后读取数据;看时候有新的和自己有关的异常页面信息;这样

// 9_页面异常.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。//?#include "pch.h"#include <stdio.h>#include<stdlib.h>#include<Windows.h>// 定义一些内核地址宏;用来保存当前程序相关数据(cr3)#define K_BOOL_READY   0x8003f3f0    // * 当前是否已经提交 cr3,变为准备接收异常状态#define K_ESP        0x8003f3f4    // esp     * 异常代码 #defineK_ESP_NEG4    0x8003f3f8    // esp - 4   * 异常地址 eip(产生异常的代码地址)#define K_TARGET_CR30x8003f3ec    // cr3       * 异常程序cr3#define K_CR2        0x8003f3e8    // cr2       * 异常地址(产生页面异常页中的虚拟地址)#define K_BOOL_NEW_EXPT 0x8003f3e4    // * 是否有新的异常??DWORD g_bReady = FALSE;DWORD g_bNewExpt = FALSE;?DWORD g_pEIP = 0;DWORD g_pExceptPvn = 0;DWORD g_iCr3 = 0;DWORD g_iErrCode = -1;?// 0x401040void __declspec(naked) IdtEntry(){__asm mov eax, ds:[K_BOOL_READY];__asm mov g_bReady, eax;__asm{    mov eax, cr3;    mov cr3, eax;}if (g_bReady != 1){

// 第一次运行还没有提交CR3数据:    __asm    {        mov eax, cr3;        mov ds : [K_TARGET_CR3], eax;        // 提交完成的标识。        mov eax, 0x1;        mov ds : [K_BOOL_READY], eax;        // 重置新异常信号;        mov eax, 0x0;        mov ds : [K_BOOL_NEW_EXPT], eax;        iretd;    }}else{    // 已经提交 cr3 开始接收异常数据:?    // ----* 检测是否有新的异常需要接收;    __asm mov eax, dword ptr ds : [K_BOOL_NEW_EXPT];    __asm mov g_bNewExpt, eax;    if (g_bNewExpt == 0x1)    {        // 如果 有新的异常        __asm        {            // 获取异常信息 --》 到本地全局,以便输出            mov eax, dword ptr ds : [K_ESP_NEG4];            mov g_pEIP, eax;            mov eax, dword ptr ds : [K_CR2];            mov g_pExceptPvn, eax;            mov eax, dword ptr ds : [K_TARGET_CR3];            mov g_iCr3, eax;            mov eax, dword ptr ds : [K_ESP];            mov g_iErrCode, eax;            // 接收之后 重置新异常信号;            mov eax, 0x0;            mov ds : [K_BOOL_NEW_EXPT], eax;        }

}?    __asm    {        mov eax, cr3;        mov cr3, eax;        iretd;    }}}??void _declspec(naked) go(){__asm{    int 0x20;    ret;}}??int main(){if ((DWORD)IdtEntry != 0x401040){    printf("Func addres is wrong !!");    Sleep(5000);    system("pause");    exit(-1);}while (1){    go();    //printf("%d\n", g_bNewExpt);    if (g_bNewExpt == 0x1)    {        printf("new error ***cr3: %p -- eip: %p -- errorcode:%p -- pfvn:%p\n", g_iCr3, g_pEIP, g_iErrCode, g_pExceptPvn);        g_bNewExpt = 0;    }?}?    }?

Hook IDT_E 回调函数 且 通过识别cr3 将相关信息过滤到 共识的共享数据区域 .c :

// 9_页面异常_过滤获取目标异常信息.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。//?#include "pch.h"#include<stdio.h>#include<stdlib.h>#include<Windows.h>?// 定义一些内核地址宏;用来保存当前程序相关数据(cr3)#define K_BOOL_READY   0x8003f3f0    // * 当前是否已经提交 cr3,变为准备接收异常状态#define K_ESP        0x8003f3f4    // esp     * 异常代码 #defineK_ESP_NEG4    0x8003f3f8    // esp - 4   * 异常地址 eip(产生异常的代码地址)#define K_TARGET_CR30x8003f3ec    // cr3       * 异常程序cr3#define K_CR2        0x8003f3e8    // cr2       * 异常地址(产生页面异常页中的虚拟地址)#define K_BOOL_NEW_EXPT 0x8003f3e4    // * 是否有新的异常?#define K_HOOK_IDT_E_CODE 0x8003F120      // * Hook 代码所在#define K_HOOK_IDT_E_SRCCODE 0x80541450   // * Hook目标 所在?DWORD g_bReady = FALSE;DWORD g_bNewExpt = FALSE;?DWORD g_pEIP = 0;DWORD g_pExceptPvn = 0;DWORD g_iCr3 = 0;DWORD g_iErrCode = -1;DWORD g_iCurCr3 = 0;??int  g_i = 0;DWORD g_p = 0;void  checkAndCap();// -- int0x20 -- 0x401040void __declspec(naked) HookIdt_0xe(){// hook __asm{    // 修改写保护 WP    //cli;//将处理器标志寄存器的中断标志位清0 ,不允许中断    mov eax, cr0    and eax, not 0x10000    mov cr0, eax?    mov eax, 0x0;    mov ds : [K_BOOL_READY], eax;?    // 原来的第一句 有7个字节;而我们push ret 只有6个字节 ;扩充到 7个字节 68 20 f1 03 80 C3 90;    // push 0x8003f120;    // ret    // nop     mov al, 0x68;    mov byte ptr ds : [K_HOOK_IDT_E_SRCCODE], al;    mov eax, 0x8003f120;    mov dword ptr ds : [K_HOOK_IDT_E_SRCCODE + 1], eax;    mov ax, 0x90c3;    mov word ptr ds : [K_HOOK_IDT_E_SRCCODE + 5], ax;?

mov eax, cr0    or eax, 0x10000    mov cr0, eax    //sti;//将中断恢复?}?g_i = 0;g_p = K_HOOK_IDT_E_CODE;?// 拷贝hook 代码带内核区for (; g_i < 128; g_i++){    *(BYTE*)(g_p + g_i) = *(byte*)((DWORD)checkAndCap + g_i);}?__asm{    iretd;}}??// 0x401040  -- void _declspec(naked) checkAndCap(){__asm{    push eax;    // 判断程序是否已经就位    mov eax, ds:[K_BOOL_READY];    cmp eax, 0x1;    jnz END;

// 如果 目标程序 已经提交cr3 那么 就可以开始捕获异常了;    mov eax,cr3;   // cr3不能用于比较的 参数    cmp eax, ds:[K_TARGET_CR3];    jnz END;?    // 来到这一步,表明是目标的异常?    mov eax, [esp + 8]; // 前面push  了一个 eax  我去 浪费时间··· esp + 0x4 --> esp+ 0x8;    mov ds : [K_ESP_NEG4], eax; // eip 异常地址    mov eax, cr2;    mov ds : [K_CR2], eax; // 异常读/写/访 的目标分页地址    mov eax, [esp+4];// esp-->esp +4  因为前面压入了 eax    mov ds : [K_ESP], eax; // 异常代码    // 给新的异常信号    mov eax, 0x1;    mov ds : [K_BOOL_NEW_EXPT], eax;

END:    pop eax;    mov  word ptr[esp + 2], 0 // 恢复 原来的执行    push 0x80541457;          // 返回之前hook 的下一句    ret}}?void _declspec(naked) go(){__asm{    int 0x20;    ret;}}int main(){if ((DWORD)HookIdt_0xe != 0x401040){    printf("HOOK出错了:%p", HookIdt_0xe);    Sleep(10000);    exit(-1);}if ((DWORD)checkAndCap != 0x4010c0){    printf("CHEC出错了:%p", checkAndCap);    Sleep(10000);    exit(-1);}go();system("pause");???}?

效果展示:

原文地址:https://www.cnblogs.com/leibso-cy/p/11719276.html

时间: 2024-08-30 16:29:50

17_页面异常接管的相关文章

liteos 异常接管(十五)

1 概述 1.1 基本概念 异常接管是操作系统对在运行期间发生异常的情况进行处理的一系列动作,譬如打印异常发生时当前函数调用栈信息. cpu现场信息.任务的堆栈情况等. 异常接管作为一种调测手段,可以在系统发生异常时提供给用户有用的异常信息,譬如异常的类型.发生异常时系统的状态等,方便用户定位分析问题. Huawei LiteOS的异常接管,在系统发生异常时的处理动作是显示异常发生时正在运行的任务信息(包括任务名.任务号.堆栈大小等),以及cpu现场等信息. R11:可以用作通用寄存器,在开启特

#65279字符导致页面异常的问题

刚刚处理了一个小问题,一个客户的网站文件中多出出现"#65279"字符,并且影响页面布局了,出现了空行的问题上网查找了一下资料,看到这篇博文从?#65279字符看dede模板页面编码问题 基本确定是字符编码不一致引起的问题,我采用的方法和博文中的方法不同,我使用样式将原始元素的top设置为-5px,其效果了,这是一种偷懒的方法,主要是因为页面引入的文件过多,并且整个站点大部分都受到影响,我任务直接用样式处理要优于重构整个站点的所有文件 PS:这个问题似乎只在php项目中出现过

idea+jsp+jstl c标签页面异常

先在Schema and DTDs配置C.tld文件 最后提示是少包 网上很多方法都说少jstl.jar 折腾了很久 其实还少standard.jar 解决方法 把这两个包分别加到项目依赖库,生成的tomcat的war文件(即web-inf文件)的lib目录下,还有tomcat自己的lib 原因 idea自身的问题,用tomact做服务器,会没有jstl支持,缺那两个包,那么只要把那两个包放到和他们有关的三个lib里面就好了

学习笔记17_网站异常和日志处理

*在clobal.asax中,写protected void Application_Error() { Respone.Redirect("Default.aspx");//发生错误能在此处添加到日志当中. } *日志类 public class log { public static Queue<string> logString = new Queue<string>(); static Log() { ThreadPool.QueueUserWorkIt

Extjs4 filefield上传后返回信息页面异常

Ext.override(Ext.form.Action.Submit,{ processResponse : function(response){ this.response = response; var data = response.responseText; if(data.indexOf('<pre>') != -1||data.indexOf('<PRE>') != -1) { response.responseText = data.substring(5, da

[php] 错误接管类

自己弄的一个错误接管类: <?php //---------------------------------- // Leephp 错误接管类 // 2017-07-06 // PengchongLee //---------------------------------- // error_reporting - 设置应该报告何种 PHP 错误 error_reporting(0); class Erro { public function __construct() { $this->i

asp.net中当服务器出错时显示指定的错误页面

http://blog.csdn.net/helloxiaoyu/article/details/2943537 此篇文章描述了当异常再ASP.NET中发生时怎样使用C#.NET代码去拦截和相应异常.ASP.NET在异常处理方面比传统的ASP更优越.在ASP.NET中,允许在应用程序的各个层面中处理异常.ASP.NET的新特性ASP.NET为捕获并处理异常提供了更多的便利.在传统的ASP程序中,我们用“On Error Resume Next”(或Jscript的Try-catch)来处理异常.

Linux内核源代码情景分析-内存管理之用户页面的换入

在下面几种情况下会发生,页面出错异常(也叫缺页中断): 1.相应的页面目录项或者页面表项为空,也就是该线性地址与物理地址的映射关系尚未建立,或者已经撤销. 2.相应的物理页面不在内存中. 本文讨论的就是这种情况. 3.指令中规定的访问方式与页面的权限不符,例如企图写一个"只读"的页面. 假设已经建立好了映射,但是页表项最后一位P为0,表示页面不在内存中:整个页表项如下图,offset表示页面在一个磁盘设备的位置,也就是磁盘设备的逻辑页面号:而type则是指该页面在哪一个磁盘设备中. 图

Linux 内核源代码情景分析 chap2 存储管理 --- 页面的定期换出

1. 目的 Linux 内核通过定期检查并且预先将若干页面换出, 实现减轻系统在缺页异常时候所产生的负担. 虽然, 无法避免需要临时寻找可以换出的页面, 但是, 可以减少这种事件发生的概率.Linux 内核中设置一个专门用来定期将页面换出的线程 kswapd. kswapd 相当于一个进程 有自己的进程控制块 task_struct 结构, 但是呢, 他没有自己独立的地址空间, 我们可以将它理解为是线程. 2. kswapd 例行路线 2.1 kswapd 建立 ================