在OS下写一个访问底层的程序
前言
我们知道,在UEFI Shell下,可以随意读写底层的寄存器,但是对OS来说是行不通的!因为基于安全性考虑,目前的OS都对上层的应用程序做了限制,所以上层是无法直接访问底层的。如果要进行访问,必须要经过一个中间层(驱动),这篇文章记录在Windows和Linux中,如何编写一个可以访问底层寄存器的程序。
既然访问底层需要驱动,那么是不是要自己写一个驱动呢?当然不是,这里不讨论驱动开发,而且开发驱动不是三言两语说得清的。
Windows
Windows系统微软在WinXP后加了RING级别限制,普通应用程序访问底层必须经过驱动,除非使用OS提供的API。
访问底层无非就是IO或memory操作,网络上有几个免费的驱动做好了这些接口。常见的有WinIO、Inpout32/Inpoutx64、Winring0等。前面两个没有驱动签名,只能在windows测试模式使用,而winring0是带签名的,所以可以直接拿来使用。
Winring0项目地址:https://github.com/QCute/WinRing0/releases
详细API的使用可仔细阅读manual.chm,下面举一个读取CMOS数据的例子。
Step1,下载WinRing0_1_3_0.zip并解压。
Step2,使用VS新建一个名称为Cmos的C++空项目,并添加一个Main.cpp文件,注意一定要cpp后缀,winring0是c++写的,这样才能以C++方式编译,语法可以用C语言的。
Step3,复制解压出来的文件
1) 复制WinRing0_1_3_0\source\dll\OlsApi.h 至 Main.cpp同目录并添加到VS项目中
2) 复制WinRing0_1_3_0_\release\WinRing0x64.lib至 Main.cpp同目录
Step4,复制以下代码,VS设置编译成x64:
#include <windows.h> #include <iostream> #include "OlsApi.h" using namespace std; #pragma comment(lib, "WinRing0x64.lib") int main(int argc, char ** argv) { int Data[256]; int Index; if (!InitializeOls()) { cout << "Init Error!" << endl; return 0; } for (Index = 0; Index <= 0xFF; Index++) { WriteIoPortByte(0x70, Index); Data[Index] = ReadIoPortByte(0x71); } for (Index = 0; Index <= 0xFF; Index++) { if (Index % 0x10 == 0 && Index > 0) { printf("\n\r"); } printf("%02X ", Data[Index]); } return 0; }
Step5,点击“生成”->生成Cmos。
Step6,找到生成的目录,管理员权限运行windows shell,运行Cmos.exe,会提示找不到WinRing0x64.dll。
Step7,将WinRing0_1_3_0_\release\WinRing0x64.dll和WinRing0_1_3_0_\release\WinRing0x64.sys复制到Cmos.exe目录下。
Step8,重做Step6,成功读取CMOS。
Linux
Linux下有两种方法可以访问,一是自己写驱动模块,二是通过操作OS下/dev/port或/dev/mem设备,这里记录的是第二种。Linux下的访问底层的方式与Windows有很大的差异,它是将底层数据映射到一个文件上的,读写端口就是读写文件,原理这里不多描述,有兴趣可网上搜索。
这里同样举一个读取CMOS的例子,没什么什么步骤,直接新建一个文件main.c并粘贴以下代码:
#include <stdint.h> #include <stdbool.h> #include <fcntl.h> #include <stdio.h> #include <unistd.h> static int fd; bool port_dev_init(void) { fd = open("/dev/port", O_RDWR); if (fd < 0) { return false; } return true; } void port_dev_exit(void) { close(fd); } uint8_t ioread8(uint16_t port) { uint8_t buf[2] = { 0 }; lseek(fd, port, SEEK_SET); read(fd, buf, 1); return buf[0]; } void iowrite8(uint16_t port, uint8_t data) { uint8_t buf[2] = { 0 }; lseek(fd, port, SEEK_SET); buf[0] = data; write(fd, buf, 1); } int main(uint64_t argc, uint8_t **argv) { uint8_t value; uint8_t index; if (!port_dev_init()) { printf("Init error!\n"); return 0; } for (index = 0; index <= 0xFF; index++) { if (index % 0x10 == 0 && index > 0) { printf("\n\r"); } iowrite8(0x70, index); value = ioread8(0x71); printf("%02X ", value); } port_dev_exit(); return 0; }
编译:gcc main.c -o main
运行:sudo ./main
附件
https://wwi.lanzoui.com/ik09Cm210af
版权声明:
作者:bin
链接:https://ay123.net/mystudy/945/
来源:爱影博客
文章版权归作者所有,未经允许请勿转载。
jnuer
bin@jnuer
test