- 論壇徽章:
- 0
|
查找X86_64下內(nèi)核代碼段物理地址的方法
一. 目標: 我想找出X86_64 LINUX 2.6.18的內(nèi)核代碼段的物理地址. 找出這個地址有什么用呢? 一般人是用不到的. 不過如果你知道什么是DMA ATTACK. 同時又想用這個方法來攻擊X86_64 LINUX的話, 你也許就會用到內(nèi)核的物理地址了.
二. 方法:
錯誤的方法:
在最開始的時候, 我一下子就想到了內(nèi)核里面提供的VIRT_TO_PHYS函數(shù). 看它的名字,就是把虛擬地址轉(zhuǎn)成物理地址的. 同時,內(nèi)核代碼段的虛擬地址很容易獲得,直接 grep _text System 就可以了.
但是當我按照上面的思路寫了一個kernel module之后,發(fā)現(xiàn)得到的地址明顯不對. 因為得到的物理地址已經(jīng)超過了我機器上已經(jīng)插的內(nèi)存條的總量. 后來仔細看了下VIRT_TO_PHYS的說明,發(fā)現(xiàn)它只是對KMALLOC() 分配的內(nèi)存有效. 不過在X86-32 體系下, 它好像是可以用在內(nèi)核代碼段上的了 .
不管怎么說,此路不通. 那么只好用其他辦法了. 在大概20多天的時間里,我一直沒找到好的方法, 直到今天偶然看到了ZX_WING 大俠的這篇文章: http://linux.chinaunix.net/bbs/thread-1032711-1-1.html
(btw:同時要感謝把這篇文章頂起來的兄弟)
正確的方法:
看了ZX_WING老大的LINKER SCRIPT一文之后, 你就會發(fā)現(xiàn), 內(nèi)核加載的物理地址是在LINKER SCRIPT里面指定的. 那么接下來就是看這個SCRIPT了.
首先找X86_64的連接文件, 在2.6.32里面的時候,X86 32 和64的已經(jīng)合并成一個文件了. 不過在我用的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, 那么就把它相關(guān)的找出來吧. 分散在幾個.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
關(guān)于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個地址對應(yīng)的內(nèi)容應(yīng)該是一樣的. 只不過前者是物理地址,后者是虛擬地址.
最后, 裝個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
發(fā)現(xiàn)內(nèi)容是一樣的. 證明前面的推理完全正確.
不過還是有個地方不太明白:
從下面三行來看:
. = __START_KERNEL;
phys_startup_64 = startup_64 - LOAD_OFFSET;
_text = .;
_text的其實地址似乎應(yīng)該是__START_KERNEL, 也就是0XFFFFFFFF80000000+0X200000 = 0XFFFFFFFF80200000. 但是我用GREP _TEXT SYMBOL 得到的結(jié)果是0XFFFFFFFF80000000. 沒有用到PHYSICAL_START. 不知道為什么會這樣? 哪位可以解釋下? 多謝
[ 本帖最后由 accessory 于 2009-12-31 06:26 編輯 ] |
評分
-
查看全部評分
|