一、攻击(3)
破坏操作系统可以从内存上下手,使得操作系统无法正常工作。定时器对于操作系统也是非常重要的,因为很多中断都是依赖于定时器的,没有定时器,光标就不会闪烁,任务也无法切换,整个操作系统就好像瘫痪了一般。
所以我们可以通过修改定时器的中断频率来攻击操作系统,因为操作系统的中断频率=主频/中断周期,CPU的主频是不可修改的,所以我们可以通过修改中断周期来修改中断频率,将中断周期设的大一点,中断频率就会小一点,操作系统的反应速度就会变慢,也就能达到我们的攻击目的了。
设置中断频率的步骤
1、OUT(0x43,AL),AL=0x34
2、OUT(0x40,AL),AL=中断周期的低8位
3、OUT(0x40,AL),AL=中断周期的高8位
也就是说,我们需要通过汇编的OUT指令对相应的端口进行设置来设置中断频率。
但是当操作系统以应用程序运行时,执行IN指令和OUT指令都会产生一般保护异常,也就是说这种攻击方式行不通。
二、攻击(4)
既然不能修改定时器的中断频率,那么我们可以考虑让操作系统不再接收定时器中断,这样的话,键盘和鼠标中断会停止响应,任务切换也会停止。
我们可以在应用程序中执行CLI命令,然后执行HLT命令,这样一来电脑就死机了,也达到的攻击的目的。
但是当操作系统以应用程序模式运行时,执行CLI,STI,HLT这些指令都会产生异常。因为中断应该是由操作系统来管理的,应用程序不可以随便进行控制。
所以这种攻击方式也是行不通的。
操作系统环境中有一个io_cli函数,执行的动作就是CLI,是否可以在应用程序环境中通过FAR-CALL函数来调用这个函数呢?肯定不能。因为CPU规定除了设置好的地址以外,禁止应用程序CALL其他的地址。
三、数组越界
如下程序,很明显的有数组越界的问题,但是在我们自制的操作系统上是可以正常运行的,只不过只能显示abc,不能显示d。
void api_putchar(int c);
void api_end(void);
void HariMain(void)
{
char a[100];
a[10]='a';
api_putchar(a[10]);
a[102]='b';
api_putchar(a[102]);
a[103]='c';
api_putchar(a[103]);
a[144]='d';
api_putchar(a[144]);
api_end();
}
应用程序都会分配有一个栈空间,a这个数组是保存在栈中的,应该是产生了栈异常(中断号为0x0c),我们可以编写一个处理栈异常的函数并且将其注册到IDT中。
上面的程序中,出现了三次数组越界,但是a[102],a[103]的使用都没有产生中断,而a[144]的使用就触发了中断。这是因为a[102]、a[103]虽然超出了数组的边界,但却没有超出为应用程序分配的数据段的边界,因此虽然这是个Bug,但CPU也不会产生异常。CPU产生异常的目的并不是去发现Bug,而是为了保护操作系统。
四、强制结束应用程序
规定按下SHIFT+F1键时,强制结束应用程序。
应用程序是通过cmd_app函数启动的,应用程序执行完毕之后,也会返回到cmd_app中去。我们可以写一个强制结束应用程序的函数asm_end_app,当按下SHIFT+F1键后,就执行asm_end_app函数,然后返回到cmd_app中。
五、用C语言显示字符串
我们已经写好了显示字符串的API,主要是通过hrb_api调用,调用时首先传参,然后使用INT 0x40命令调用API。
我们可以使用汇编程序编写一个调用hrb_api的函数如api_putstr0,然后在C语言中调用api_putstr0,这样就省去了每次都要给API函数传参的麻烦。
在API函数中,显示字符串时需要字符串的首地址,若应用程序是通过bim2hrb生成的话,那么源程序还会链接obj文件,使得数据部分的地址就不是我们所认为的那样。
由bim2hrb生成的.hrb文件,开头的36个字节不是程序,而是存放了下列信息:
地址 |
信息内容 |
0x0000(DWORD) |
请求操作系统为应用程序准备的数据段的大小 |
0x0004(DWORD) |
“Hari”(.hrb文件的标志) |
0x0008(DWORD) |
数据段内预备空间的大小 |
0x000c(DWORD) |
ESP初值&数据部分传送目的地址 |
0x0010(DWORD) |
hrb文件内数据部分的大小 |
0x0014(DWORD) |
hrb文件内数据的起始地址 |
0x0018(DWORD) |
0xe9000000 |
0x001c(DWORD) |
应用程序入口地址-0x20 |
0x0020(DWORD) |
malloc空间起始地址 |
E9是JMP指令的机器码,跳转的偏移地址为应用程序入口地址-0x20,实际上这完成的是一次短转移。
当启动应用程序时,操作系统为应用程序分配了代码段和数据段,在启动应用程序时应该先将hrb文件中的数据复制到数据段再执行应用程序。
应用程序都有个入口地址,那么如何跳转到入口地址呢?根据上面的内存分布图可知“JMP 应用程序入口地址-0x20”的指令就可以跳转到应用程序入口,而0xe9000000在内存中的存放形式为“00 00 00 e9”,所以e9存放在0x1b处,
所以可以跳转到该地址执行应用程序。
这种方法仅限于由bim2hrb生成的hrb应用程序。
六、显示窗口/在窗口上显示文字
操作系统已经有了显示窗口以及显示文字的函数,可以在hrb_api中调用,只需要确定一下功能号并且正确传参即可实现显示窗口以及在窗口上显示文字的功能。