208. 手工page walk
手动page work
p /x cr3
我们只能使用线性地址
找到DriverInitianize的页框, 即找到DriverInitianize的函数地址
找到pgd表的线性地址
线性地址空间的布局: 物理内存的直接映射:物理地址加上偏移(0xffff8800_0000000)就等于物理地址对应的线性地址
看断点处的反汇编
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18(gdb) disassemble
Dump of assembler code for function DriverInitialize:
0xffffffffa02c9217 <+0>: nopl 0x0(%rax,%rax,1)
0xffffffffa02c921c <+5>: push %rbp
0xffffffffa02c921d <+6>: mov %rsp,%rbp
0xffffffffa02c9220 <+9>: sub $0x8,%rsp
0xffffffffa02c9224 <+13>: mov $0xffffffffa02ca0e3,%rdi
0xffffffffa02c922b <+20>: mov $0x0,%eax
0xffffffffa02c9230 <+25>: callq 0xffffffff810b3f72 <printk>
0xffffffffa02c9235 <+30>: mov %cr3,%rax
0xffffffffa02c9238 <+33>: mov %rax,-0x8(%rbp)
=> 0xffffffffa02c923c <+37>: int3
0xffffffffa02c923d <+38>: out %eax,(%dx)
0xffffffffa02c923e <+39>: std
0xffffffffa02c923f <+40>: (bad)
0xffffffffa02c9240 <+41>: dec %ecx
0xffffffffa02c9242 <+43>: retq
End of assembler dump.看int3是什么
1
2
3
4(gdb) x /8xb 0xffffffffa02c923c
0xffffffffa02c923c <DriverInitialize+37>: 0xcc 0xef 0xfd 0xff 0xff 0xc9 0xc3 0x0f
(gdb) x /8xb 0xffffffffa02c923d
0xffffffffa02c923d <DriverInitialize+38>: 0xef 0xfd 0xff 0xff 0xc9 0xc3 0x0f 0x1f可知int3对应的机器码为
0xcc
, 这是调试器的断点标记.猜想是否内核模块代码所在页框不可写, 因此接下来就是找到该页框, 查看该页框的属性
查看cr3寄存器的值
1
2(gdb) p /x cr3
$8 = 0x138bca000pgd的物理地址:
0x138bca000
线性地址:
0xffff8801 38bca000
查看
DriverInitialize
的线性地址1
2(gdb) p DriverInitialize
$9 = {int (void)} 0xffffffffa02c9217 <DriverInitialize>线性地址:
0xffffffffa02c9217
pgd表
index:
0b1,1111,1111
=0x1ff
偏移量: $index \times 8$
1
2(gdb) p /x 0x1ff * 8
$12 = 0xff8存储pud表物理基地址的内存的线性地址:
0xffff8801 38bca000+0xff8 = 0xffff8801 38bcaff8
0xffff8801 38bcaff8
存储的值1
2(gdb) x /8xb 0xffff880138bcaff8
0xffff880138bcaff8: 0x67 0x10 0xc1 0x01 0x00 0x00 0x00 0x00即:
0x01c11067
获得的信息如下
- pud的物理基地址:
0x01c11000
- R/W: 1
- P: 1
- pud的物理基地址:
pud表
index:
0b111111110 = 0x1fe
offset:
1
2(gdb) p /x 0b111111110 * 8
$16 = 0xff0索引项的线性地址:
0xffff8800 01c11000+0xff0 = 0xffff8800 01c11ff0
0xffff8800 01c11ff0
存储的值:1
2(gdb) x /8xb 0xffff880001c11ff0
0xffff880001c11ff0: 0x63 0x20 0xc1 0x01 0x00 0x00 0x00 0x00即:
0x01c12063
获得的信息如下
- pmd的物理基地址:
0x01c12000
- R/W: 1
- P: 1
- pmd的物理基地址:
pmd表
index:
0b1 0000 0001 = 0x101
offset:
0x808
索引项的线性地址:
0xffff8800 01c12000 + 0x808 = 0xffff8800 01c12808
0xffff880001c12808
存储的值1
2(gdb) x /8xb 0xffff880001c12808
0xffff880001c12808: 0x67 0xb0 0xb8 0xb4 0x00 0x00 0x00 0x00即:
0xb4b8b067
获得的信息如下
- pt的物理基地址:
0xb4b8b000
- R/W: 1
- P: 1
- pt的物理基地址:
pt表
index:
0b0 1100 1001 = 0x0c9
offset:
0x0c9 * 8 = 0x648
索引项线性地址:
0xffff8800 b4b8b000 + 0x648 = 0xffff8800 b4b8b648
0xffff8800 b4b8b648
存储的值1
2(gdb) x /8xb 0xffff8800b4b8b648
0xffff8800b4b8b648: 0x61 0x91 0xfa 0x35 0x01 0x00 0x00 0x00即:
0x0135fa9161
获得的信息如下
- pt的物理基地址:
0x0135fa9000
- R/W: 0 (只可读不可写)
- P: 1
- pt的物理基地址:
修改pt表的 R/W 值
修改为可读可写:
set {unsigned char}0xffff8800b4b8b648=0x63
查看是否修改成功
1
2(gdb) x /8xb 0xffff8800b4b8b648
0xffff8800b4b8b648: 0x63 0x91 0xfa 0x35 0x01 0x00 0x00 0x00
修改int3处的机器码
查看call的机器码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19(gdb) disassemble
Dump of assembler code for function DriverInitialize:
0xffffffffa02c9217 <+0>: nopl 0x0(%rax,%rax,1)
0xffffffffa02c921c <+5>: push %rbp
0xffffffffa02c921d <+6>: mov %rsp,%rbp
0xffffffffa02c9220 <+9>: sub $0x8,%rsp
0xffffffffa02c9224 <+13>: mov $0xffffffffa02ca0e3,%rdi
0xffffffffa02c922b <+20>: mov $0x0,%eax
0xffffffffa02c9230 <+25>: callq 0xffffffff810b3f72 <printk>
0xffffffffa02c9235 <+30>: mov %cr3,%rax
0xffffffffa02c9238 <+33>: mov %rax,-0x8(%rbp)
=> 0xffffffffa02c923c <+37>: int3
0xffffffffa02c923d <+38>: out %eax,(%dx)
0xffffffffa02c923e <+39>: std
0xffffffffa02c923f <+40>: (bad)
0xffffffffa02c9240 <+41>: dec %ecx
0xffffffffa02c9242 <+43>: retq
End of assembler dump.根据
0xffffffffa02c9230 <+25>: callq 0xffffffff810b3f72 <printk>
查看0xffffffffa02c9230
处的机器码0xffffffffa02c9230
机器码1
2(gdb) x /8xb 0xffffffffa02c9230
0xffffffffa02c9230 <DriverInitialize+25>: 0xe8 0x3d 0xad 0xde 0xe0 0x0f 0x20 0xd8知:
callq
的机器码为0xe8
修改int3处的机器码
0xe8
1
(gdb) set {unsigned char}0xffffffffa02c923c=0xe8
查看是否修改成功
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15(gdb) disassemble
Dump of assembler code for function DriverInitialize:
0xffffffffa02c9217 <+0>: nopl 0x0(%rax,%rax,1)
0xffffffffa02c921c <+5>: push %rbp
0xffffffffa02c921d <+6>: mov %rsp,%rbp
0xffffffffa02c9220 <+9>: sub $0x8,%rsp
0xffffffffa02c9224 <+13>: mov $0xffffffffa02ca0e3,%rdi
0xffffffffa02c922b <+20>: mov $0x0,%eax
0xffffffffa02c9230 <+25>: callq 0xffffffff810b3f72 <printk>
0xffffffffa02c9235 <+30>: mov %cr3,%rax
0xffffffffa02c9238 <+33>: mov %rax,-0x8(%rbp)
=> 0xffffffffa02c923c <+37>: callq 0xffffffffa02c9030 <InitalizeCharDevice>
0xffffffffa02c9241 <+42>: leaveq
0xffffffffa02c9242 <+43>: retq
End of assembler dump.
继续运行
1
2(gdb) c
Continuing.
全部命令
1 | root@ubuntu14:/home/qeuroal/Documents/kernel/linux-3.13# gdb ./vmlinux |