免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 14030 | 回复: 6

查找X86_64下内核代码段物理地址的方法 [复制链接]

论坛徽章:
0
发表于 2009-12-31 06:23 |显示全部楼层
查找X86_64下内核代码段物理地址的方法

一.        目标: 我想找出X86_64 LINUX 2.6.18的内核代码段的物理地址. 找出这个地址有什么用呢? 一般人是用不到的. 不过如果你知道什么是DMA ATTACK. 同时又想用这个方法来攻击X86_64 LINUX的话, 你也许就会用到内核的物理地址了.

二.        方法:

错误的方法:

在最开始的时候, 我一下子就想到了内核里面提供的VIRT_TO_PHYS函数. 看它的名字,就是把虚拟地址转成物理地址的. 同时,内核代码段的虚拟地址很容易获得,直接 grep _text  System 就可以了.

但是当我按照上面的思路写了一个kernel module之后,发现得到的地址明显不对. 因为得到的物理地址已经超过了我机器上已经插的内存条的总量. 后来仔细看了下VIRT_TO_PHYS的说明,发现它只是对KMALLOC() 分配的内存有效. 不过在X86-32 体系下, 它好像是可以用在内核代码段上的了 .

不管怎么说,此路不通. 那么只好用其他办法了.  在大概20多天的时间里,我一直没找到好的方法, 直到今天偶然看到了ZX_WING 大侠的这篇文章: http://linux.chinaunix.net/bbs/thread-1032711-1-1.html
(btw:同时要感谢把这篇文章顶起来的兄弟)


正确的方法:


看了ZX_WING老大的LINKER SCRIPT一文之后, 你就会发现, 内核加载的物理地址是在LINKER SCRIPT里面指定的. 那么接下来就是看这个SCRIPT了.

首先找X86_64的连接文件, 在2.6.32里面的时候,X86 32 和64的已经合并成一个文件了. 不过在我用的2.6.18里面还是分开的2个文件. 他的位置在ARCH/KERNEL/X86_64 (或者X86)/下面.

下面是其中的一小段:
http://lxr.linux.no/#linux+v2.6. ... ernel/vmlinux.lds.S
SECTIONS
  17{
  18  . = __START_KERNEL;
  19  phys_startup_64 = startup_64 - LOAD_OFFSET;
  20  _text = .;                    /* Text and read-only data */
  21  .text :  AT(ADDR(.text) - LOAD_OFFSET) {

明显用到了宏__START_KERNEL, 那么就把它相关的找出来吧. 分散在几个.H文件里面, 如下:
#define __PHYSICAL_START        CONFIG_PHYSICAL_START

#define __START_KERNEL          (__START_KERNEL_map + __PHYSICAL_START)

#define __START_KERNEL_map      0xffffffff80000000UL

#define LOAD_OFFSET __START_KERNEL_map

关于CONFIG_PHYSICAL_START的说明如下:

http://lxr.linux.no/#linux+v2.6.18/arch/x86_64/Kconfig#L493
config PHYSICAL_START
494        hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP)
495        default "0x1000000" if CRASH_DUMP
496        default "0x200000"
497        help
498          This gives the physical address where the kernel is loaded. Normally
499          for regular kernels this value is 0x200000 (2MB). But in the case
500          of kexec on panic the fail safe kernel needs to run at a different
501          address than the panic-ed kernel.


从上面可以看出PHYSICAL_START 的默认地址是 0X200000. 同时KERNEL 代码的起始虚拟地址是0XFFFFFFFF80000000. 那么这2个地址对应的内容应该是一样的. 只不过前者是物理地址,后者是虚拟地址.

最后, 装个X86_64的QEMU虚拟机验证下(我用的是QEMU版本是0.11.91,老的版本,比如0.9.x, 0.10等好像支持的不好, 我总是装不上X86_64版本的CENTOS 5.1).
按ALT+CTL+2, 切换到QEMU MONITOR, 然后输入下面2个命令:
x /10x 0xffffffff80000000
xp /10x 0x200000

发现内容是一样的. 证明前面的推理完全正确.

不过还是有个地方不太明白:
从下面三行来看:
. = __START_KERNEL;
phys_startup_64 = startup_64 - LOAD_OFFSET;
_text = .;         

_text的其实地址似乎应该是__START_KERNEL, 也就是0XFFFFFFFF80000000+0X200000 = 0XFFFFFFFF80200000. 但是我用GREP _TEXT SYMBOL 得到的结果是0XFFFFFFFF80000000. 没有用到PHYSICAL_START. 不知道为什么会这样? 哪位可以解释下? 多谢

[ 本帖最后由 accessory 于 2009-12-31 06:26 编辑 ]

评分

参与人数 1可用积分 +30 收起 理由
Godbach + 30 精品文章

查看全部评分

论坛徽章:
0
发表于 2010-01-01 11:29 |显示全部楼层
呵呵 研究一下去

论坛徽章:
0
发表于 2010-07-12 16:40 |显示全部楼层
[root@localhost boot]# grep "\b_text\b" System.map-2.6.18-128.el5
ffffffff80000000 A _text
[root@localhost boot]# grep "\b_text\b" System.map-2.6.33
ffffffff81000000 T _text
[root@localhost boot]# grep "\b_text\b" System.map-2.6.30.10
ffffffff80200000 T _text
回复 1# accessory


    这个是我的结果,貌似不同内核版本的都不一样?

论坛徽章:
0
发表于 2010-07-12 22:49 |显示全部楼层
有可能. 即使是X86-32, 不同的机器便宜出来的内核地址也可能不一样.

论坛徽章:
0
发表于 2010-11-10 01:26 |显示全部楼层
按ALT+CTL+2, 切换到QEMU MONITOR, 然后输入下面2个命令:
x /10x 0xffffffff80000000
xp /10x 0x200000


在linux终端下,如何查看这两个地址的内容呢?
貌似在linux下无法直接访问物理地址的呀

论坛徽章:
0
发表于 2010-11-10 01:27 |显示全部楼层
在这个帖子中的图片我这边都打不开,不知哪位朋友那可以打开?能否帮忙转载过来下

论坛徽章:
0
发表于 2014-06-19 23:18 |显示全部楼层
mark,后续研究
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

DTCC2020中国数据库技术大会 限时8.5折

【架构革新 高效可控】2020年6月4日~6日第十一届中国数据库技术大会将在北京隆重召开。

大会设置2大主会场,20+技术专场,将邀请超百位行业专家,重点围绕数据架构、AI与大数据、传统企业数据库实践和国产开源数据库等内容展开分享和探讨,为广大数据领域从业人士提供一场年度盛会和交流平台。

http://dtcc.it168.com


大会官网>>
  

北京盛拓优讯信息技术有限公司. 版权所有 16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122
中国互联网协会会员  联系我们:huangweiwei@it168.com
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP