您的位置:首页 > 其它

30天自制操作系统------保护操作系统

2017-07-14 08:50 197 查看
一、攻击(1)
使用C语言编写的应用程序擅自修改操作系统管理的内存,导致操作系统的功能出错。

void api_end(void);
void HariMain(void)
{
*((char*)0x00102600)=0;
api_end();
}

二、解决办法(1)
   为操作系统以及应用程序分配各自的段,互不影响。函数cmd_app(由C语言编写)为应用程序分配专用的段。
启动应用程序时,计算机的环境切换过程:操作系统——>应用程序——>操作系统。此部分为start_app函数(由汇编语言编写)完成。
应用程序很有可能会访问保存在操作系统段的API,但是应用程序和操作系统不在同一个段,所以需要进行环境切换:应用程序——>操作系统——>应用程序
 
以上部分并不能解决攻击(1)产生的问题。
在x86架构规范中,当应用程序试图破坏操作系统,或者试图违背操作系统的设置时,就会自动产生0x0d中断。也就是说以上攻击会产生0x0d中断,所以为了应对这种中断,我们需要编写0x0d中断函数,并且将其注册在IDT中。
0x0d中断函数应该给出提示信息,并且强制结束应用程序。
给出提示信息的工作可以通过调用INT 0x40来实现,而强制结束应用程序需要正确设置CS和EIP。具体的0x0d号中断服务例程如下:

_asm_inthandler0d:
STI
PUSH ES
PUSH DS
PUSHAD ;将寄存器的值保存到栈里

MOV AX,SS ;判断发生中断的环境
CMP AX,1*8
JNE .from_app

;操作系统中产生中断
MOV EAX,ESP
PUSH SS ;保存中断时的SS
PUSH EAX ;保存中断时的ESP
MOV AX,SS
MOV DS,AX
MOV ES,AX
CALL _inthandler0d

ADD ESP,8
POPAD
POP DS
POP ES
ADD ESP,4
IRETD

.from_app: ;当应用程序中发生中断
CLI
MOV EAX,1*8
MOV DS,AX ;将DS设为操作系统用
MOV ECX,[0xfe4] ;操作系统的ESP
ADD ECX,-8
MOV [ECX+4],SS ;保存中断时的SS
MOV [ECX],ESP ;保存中断时的ESP
MOV SS,AX
MOV ES,AX
MOV ESP,ECX
STI
CALL _inthandler0d
CLI
CMP EAX,0
JNE .kill
POP ECX
POP EAX
MOV SS,AX ;将SS设回应用程序用
MOV ESP,ECX ;将ESP设回应用程序用
POPAD
POP DS
POP ES
ADD ESP,4
IRETD

.kill: ;将应用程序强制结束
MOV EAX,1*8
MOV ES,AX
MOV SS,AX
MOV DS,AX
MOV FS,AX
MOV GS,AX
MOV ESP,[0xfe4] ;强制返回到start_app的ESP
STI ;切换完成后恢复中断请求
POPAD ;恢复事先保存的寄存器的值
RET
将应用程序强制结束的代码.kill部分,需要结合start_app函数来看。
asm_inthandler0d已经被注册在IDT中了,即在操作系统段中,当执行这段代码时,CS寄存器已经指向了OS段,若要强制结束应用程序,使得各个寄存器都指向OS段,就需要将其他的段寄存器指向OS段,为了正常返回到OS的环境中,还需要知道下一条指令的地址,才能保证操作系统的正常运行,所以需要首先获得操作系统栈顶的地址,然后才能获得正确的EIP。



    start_app函数保存在内存单元0xfe4处的ESP就是如上图所示的ESP,所以要想获得正确的EIP,应该先将8个寄存器的值弹出,然后用RET指令(执行POP
EIP的动作)使得程序返回到操作系统的环境中。


三、攻击(2)
   攻击(1)之所以可以对操作系统造成影响是因为应用程序擅自访问了操作系统管理的内存空间,我们通过给应用程序分配专用的段、编写相应的异常处理程序解决了这个问题。
但是因为我们是通过C函数cmd_app给应用程序分配专用的段的,而应用程序可以忽略操作系统的分配,自己通过汇编语言可以给各寄存器赋值,任意使用内存空间,这样的话很有可能会对操作系统造成破坏,例如如下应用程序,0x102600为操作系统管理的内存:
[INSTRSET "i486p"]
[BITS 32]
MOV EAX,1*8
MOV DS,AX
MOV BYTE [0x102600],0
MOV EDX,4
INT 0x40  

四、解决办法(2)
   
攻击(2)之所以会攻击到OS,是因为应用程序擅自向DS存入了OS用的段地址。
在段定义的地方,如果将访问权限加上0x60的话,就可以将段设置为应用程序用,当CS中的段地址为应用程序段地址时,CPU会认为“当前正在运行应用程序”,这时如果存入操作系统用的段地址就会产生0x0d号异常。
也就是说,只需要在cmd_app给应用程序分配专用的代码段和数据段时,将原本的访问权限加上0x60即可,这样一旦应用程序想要擅自向段寄存器中存入OS用的段地址,就会触发0x0d异常,使得应用程序强制结束。
 
如此一来,OS环境与应用程序环境就很明确的分割开来。但是根据x86的规则,是不允许操作系统CALL应用程序的,操作系统向应用程序用的段进行FAR-CALL也是被禁止的。
    那么操作系统如何启动应用程序呢?
此处我们使用了RETF指令,相当于执行POP EIP,POP
CS指令,只需要预先将应用程序的CS,EIP压栈,那么程序就可以启动应用程序。
为了保证在发生异常时可以正常返回到OS,需要记录OS的栈顶ESP,OS的ESP被保存在tss_esp0处。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  操作系统