首页
社区
课程
招聘
[原创]cpu异常浅析
2017-6-16 21:57 8304

[原创]cpu异常浅析

2017-6-16 21:57
8304

cpu内部产生的异常(软中断)可分为2:

 

1.陷阱,由代码执行int xx指令,指令执行成功后陷入内核,根据idt表中对应的段描述符,执行对应的中断处理函数,因为是int xx执行成功后才陷入的内核,中断处理函数中得到的异常触发地址为int xx的下一条指令的地址

 

2.故障,一条指令可以分解为多条微指令,如在执行div ecx,该指令被分为多条微指令,执行过程中,微指令会先判断操作数的值是否符合要求,如果此时ecx的值为0不符合要求,会产生除0故障(类似int 0指令的效果),陷入内核后,对于cpu来说,该故障已经被处理,

对于操作系统来说异常处理才刚刚开始,这里我们不谈操作系统的异常处理,此时该指令还没执行完毕,应该说执行失败,中断处理函数中得到的异常触发地址为该指令的地址

 

例子:触发一个故障

#include <stdio.h>

 

int main(int argc, char *argv[])

{

    _asm int 0x20;

    return 0;

}

在执行int 0x20过程中,微指令判断对应的门描述符是否有效,要陷入的函数权限是否符合要求,任意不满足则触发故障,指令执行失败。

0x20号中断在idt中的描述符为0000000000080000,描述符p位为0,描述符无效,该指令执行失败触发一个故障,故障产生于应用程序,对于操作系统来说是一个3环异常,所以产生如下效果

 

 

例子:触发一个陷阱一个故障

#include <stdio.h>

 

int main(int argc, char *argv[])

{

    _asm int 0x20;

    return 0;

}

依旧使用int 0x20,此时我们使用windbg修改idt表将0x20号的门描述符修改为对于cpu来说,3环程序可用的门描述符

0号门描述符的地址为0x80b95400

20 号门描述符的地址应为 0x80b95400 + 0x20*8 = 0x80b95500

修改为0000 ee 00 0008 0000,此时虽然中断处理函数的地址为00000000,但对于cpu来说是一个3环程序可用的门描述符

 


int 0x20执行成功后程序陷入0,并且试图去0地址执行代码,对于cpu来说陷阱已经处理完毕,windows0-0xffff地址为空指针区域,都不是一个合法区域,所以会产生一个访问冲突的0环异常,其对应一个故障,我们在程序的内核态中并没有注册过任何seh结构化异常处理函数,所以该异常将成为一个不可除去的异常,因为处于0环导致系统崩溃蓝屏

 

例子:触发两个故障

#include <stdio.h>

 

int main(int argc, char *argv[])

{

    _asm{

       xor ecx, ecx;

       div ecx

    }

    return 0;

}

该程序会产生一个除0的故障对应中断号为0.

门描述符为84038e0000088650这是一个0环才可用的门描述符,但是我们在3环下触发除0异常,可以使用到此门,这可能是cpu体供的一些特殊机制,对此我们不深究.

 

当跳转到该门的中断函数地址后,cpu视为该故障已被处理,正常情况下,将执行系统的异常处理机制,此时我们修改该门描述符为00008e0000080000,只修改了中断处理函数,第一个故障处理后cpu将处于0环模式并且试图在0地址执行代码之后流程和之前情况相同蓝屏

 

 

3.中止,一些文章中写到此类异常标志的最严重的错误, 诸如硬件错误,类异常总是无法精确地报告引起错误的指令的位置,一个比较典型的终止类异常是"双重故障"(中断号为8), 当发生一次异常之后, 处理器在转入该中断的处理程序时, 又发生了另外的异常

 

双重故障理解:

首先故障是在执行某条指令的过程中产生的,对于cpu来说,陷入内核跳转到该故障对应的中断处理函数地址,便认为该故障已经被处理,双重故障则是在此过程中又将产生新的故障,此时故障无法被处理,便产生一个双重故障,也就是说所有的故障全都因为一条指令的执行

 

例子:触发一个双重故障

#include <stdio.h>

 

int main(int argc, char *argv[])

{

    _asm{

       xor ecx, ecx;

       div ecx

    }

}

在执行div ecx过程中将产生一个除0故障,此时cpu对于此故障处理将执行一个int 0的操作,我们修改0 号中断的门符号,将其修改为一个无效的中断描述符此时将发生第二个故障,产生此故障的不是某条指令而是cpu本身的故障处理机制,此时便触发一个双重故障


修改0号中断的门描述符为一个无效的门描述符, 0000000000080000


 双重故障的中断号为8,同时修改8号门描述符,使其处理函数为KiTrap03,方便我们观察效果


 

程序运行触发8号中断,并且异常已无法精确地报告引起错误的指令的位置

 

 

 

此时我又做了一个有趣的小实验:

#include <stdio.h>

 

int main(int argc, char *argv[])

{

    _asm{

       xor ecx, ecx;

       div ecx

    }

}

双重故障产生后,cpu依旧会处理这个故障,执行一个int 8的操作,此时我们让int 8也产生一个故障会怎么样呢

 

按照原来的思路构建一个双重故障,修改0号终端的门描述符为无效

修改8号终端的门描述符为无效


很遗憾虚拟机直接重启了


实验大多是在我的推测基础上进行的,可能有些不严谨或细节的错误,希望大家发现可以给我指出,我对此非常感兴趣



[培训]《安卓高级研修班(网课)》月薪三万计划

收藏
点赞2
打赏
分享
打赏 + 1.00雪花
打赏次数 1 雪花 + 1.00
 
赞赏  CCkicker   +1.00 2017/07/12
最新回复 (13)
雪    币: 248
活跃值: (3704)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
luskyc 2017-6-17 01:04
2
0
最后是一个三重故障,三重故障没有对应的故障处理例程,如果发生这种故障,cpu会直接重启
雪    币: 370
活跃值: (51)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
布衣勇者 1 2017-6-17 08:04
3
0
yy虫子yy 最后是一个三重故障,三重故障没有对应的故障处理例程,如果发生这种故障,cpu会直接重启
如果命名的话,我感觉叫多重故障比较贴切一点
雪    币: 2576
活跃值: (437)
能力值: ( LV2,RANK:85 )
在线值:
发帖
回帖
粉丝
wyfe 2017-6-17 09:00
4
0
这个微软有公开的资料吗?
雪    币: 451
活跃值: (1742)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
我是哥布林 2017-6-17 10:13
5
0
我记得复现双重故障的一个方法就是在驱动中进行无限递归,导致rsp到达栈边界。
雪    币: 370
活跃值: (51)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
布衣勇者 1 2017-6-20 18:53
6
0
wyfe 这个微软有公开的资料吗?
微软有没有我不知道,intel的IA-32手册上肯定有
雪    币: 370
活跃值: (51)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
布衣勇者 1 2017-6-20 19:07
7
0
我是哥布林 我记得复现双重故障的一个方法就是在驱动中进行无限递归,导致rsp到达栈边界。
嗯嗯,系统栈的大小是很有限的,在写驱动的时候,很容易出现满栈的问题,导致发生页错误的异常,而上面有说到,对于cpu来说,操作系统通过陷阱门成功陷入内核态,便是一次成功的异常处理,这里我略过了一些细节,cpu在通过陷阱门陷入内核过程中,会在系统栈中压入一些异常信息,而系统栈已经达到边界,导致陷入内核态失败,引发双重故障,这个也是非常经典的问题,终于遇到明白人了
雪    币: 248
活跃值: (3704)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
luskyc 2017-6-27 16:10
8
0
布衣勇者 嗯嗯,系统栈的大小是很有限的,在写驱动的时候,很容易出现满栈的问题,导致发生页错误的异常,而上面有说到,对于cpu来说,操作系统通过陷阱门成功陷入内核态,便是一次成功的异常处理,这里我略过了一些细节, ...
引发双重故障也会压栈,但是系统栈满了,最后导致三重故障重启
雪    币: 2576
活跃值: (437)
能力值: ( LV2,RANK:85 )
在线值:
发帖
回帖
粉丝
wyfe 2017-7-11 19:08
9
0
布衣勇者 微软有没有我不知道,intel的IA-32手册上肯定有
多谢!
雪    币: 3825
活跃值: (5433)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
badboyl 2 2017-7-12 14:31
10
0
是否可以用来攻击QUEM虚拟类和云计算的系统
雪    币: 36
活跃值: (102)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wbqsohucom 2017-7-13 17:27
11
0
mark
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_vvacqsvs 2020-4-11 16:11
12
0
大神请教下,我们的linux系统宕机后,没有任何日志打印,该节点ping不通,ssh登录不了;只能通过按钮硬复位重启恢复;以你的经验,CPU的错误指令可以导致这个问题嘛?
雪    币: 624
活跃值: (3126)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
dx苹果的心愿 1 2020-4-11 16:32
13
0
转眼三年过去了,时间好快啊。
雪    币: 995
活跃值: (1514)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
WMBa0 2023-1-28 20:42
14
0
转眼,3年了啊
游客
登录 | 注册 方可回帖
返回