首页
社区
课程
招聘
[原创]使用ollvm编译Linux内核驱动模块.ko的正确方法、解决ollvm编译导致加载驱动报错“please compile with -fno-common”
发表于: 2021-4-18 00:48 19046

[原创]使用ollvm编译Linux内核驱动模块.ko的正确方法、解决ollvm编译导致加载驱动报错“please compile with -fno-common”

2021-4-18 00:48
19046

地址:[原创]开源一个Linux内核里进程内存管理模块源码

使用ollvm编译Linux内核驱动模块.ko的正确方法、解决ollvm编译导致加载驱动报错“please compile with -fno-common”

此问题很久之前就已解决了,库存了挺久了,是时候发布一下吧~

在编写好Linux内核驱动模块后,经过OLLVM混淆编译出来(这里我采用OLLVM9.0.1编译)。再加载进真机手机发现报错“please compile with -fno-common”(不要问我是如何Pass掉内核里验证,此问题不在此文章的讨论范围内)

可以确定的是这个错误,肯定是内核报出来的,不是我的驱动报的。随便下载一份Linux内核源码,很快就定位到了报错点在/kernel/module.c文件里

通过分析ELF结构可以得知COM的意思:

检查.ko文件的ELF头发现确实有一大堆的COM变量,而且规律可循,每有一个混淆函数,就会带有两个COM变量,分别为x、y。这里猜测是ollvm每混淆出来的一个函数,都需要附带两个4字节全局变量才可正常执行,这两个4字节变量叫x、y。

每让ollvm混淆一个函数,自己就在源文件新建两个4字节的变量后期替换掉ollvm编译后的两个COM,如
int fake_x=0,fake_y=0;

这里变量名我随便取,取xaa3和xaa6

可以发现,自己在源文件里面定义的变量,是没有COM这个标识的,反而变成了17,那就非常好办了,修改ELF头,替换掉OLLVM编译的COM变量指向,因为自己在源文件里定义的两个int变量并无任何用途,所有替换是没有问题的。

这里写一个小工具来替换COM变量:
GitHub

替换后的效果:

COM标志已消失。

尝试重新跑驱动:

拖进IDA,看看效果

下雨一样很壮观。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2021-4-18 00:52 被abcz316编辑 ,原因:
收藏
免费 6
支持
分享
最新回复 (9)
雪    币: 7103
活跃值: (9914)
能力值: ( LV17,RANK:797 )
在线值:
发帖
回帖
粉丝
2
用unicorn模拟运行,可以忽略平台接口的差异。因为unicorn可以完全忽略call指令及其它平台深度绑定的指令。
2021-4-20 13:14
0
雪    币: 16752
活跃值: (7281)
能力值: ( LV13,RANK:923 )
在线值:
发帖
回帖
粉丝
3
无名侠大佬说得很对,还有microcode 了解一下
2021-4-20 15:48
0
雪    币: 1109
活跃值: (3781)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
4
感觉配置一下 linker script 应该就可以了
2021-4-20 16:05
0
雪    币: 435
活跃值: (1397)
能力值: ( LV13,RANK:388 )
在线值:
发帖
回帖
粉丝
5
95dK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6G2j5X3k6#2M7$3y4S2N6r3!0J5i4K6u0V1L8r3I4$3L8g2)9J5c8X3!0T1k6Y4g2K6j5$3q4@1L8%4u0Q4x3V1k6T1L8r3!0T1i4K6u0r3L8r3I4$3L8g2)9J5k6o6c8Q4x3X3f1H3i4K6u0r3L8r3W2T1i4K6u0r3g2s2u0S2L8Y4y4X3L8%4u0E0M7#2)9J5c8V1!0T1k6Y4g2K6j5$3q4@1K9h3!0F1i4K6u0r3b7X3!0Y4N6i4y4o6L8$3&6@1M7X3!0D9c8X3I4G2N6#2)9J5k6h3y4H3M7q4)9J5x3@1H3#2x3e0f1`.

      GlobalVariable         * x = new GlobalVariable(M, Type::getInt32Ty(M.getContext()), false,
          GlobalValue::CommonLinkage, (Constant * )x1,
          *varX);
      GlobalVariable         * y = new GlobalVariable(M, Type::getInt32Ty(M.getContext()), false,
          GlobalValue::CommonLinkage, (Constant * )y1,
          *varY);

这里把xy的CommonLinkage改成其他LinkageType就行了
2021-4-20 17:27
1
雪    币: 402
活跃值: (2044)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
无名侠 用unicorn模拟运行,可以忽略平台接口的差异。因为unicorn可以完全忽略call指令及其它平台深度绑定的指令。

模拟?你如何拿到真机的内核内存数据?比如以小米10为例,应用层是不可能的(内核漏洞情况除外)。

最后于 2021-4-21 01:37 被abcz316编辑 ,原因:
2021-4-21 01:33
0
雪    币: 7103
活跃值: (9914)
能力值: ( LV17,RANK:797 )
在线值:
发帖
回帖
粉丝
7
abcz316 无名侠 用unicorn模拟运行,可以忽略平台接口的差异。因为unicorn可以完全忽略call指令及其它平台深度绑定的指令。 模拟?你如何拿到 ...
unicorn跑一下ollvm基本块关系,不需要内核数据也能跑
2021-4-21 18:45
0
雪    币: 144
活跃值: (335)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
mark
2021-4-21 20:28
0
雪    币: 5
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
9
大佬能留个联系方式吗?有偿,我账号无权限私信你
2022-2-21 06:40
0
雪    币: 156
活跃值: (1352)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
......
2023-4-28 20:14
0
游客
登录 | 注册 方可回帖
返回