208. 手工page walk

手动page work

  1. p /x cr3

    我们只能使用线性地址

    找到DriverInitianize的页框, 即找到DriverInitianize的函数地址

  2. 找到pgd表的线性地址

    线性地址空间的布局: 物理内存的直接映射:物理地址加上偏移(0xffff8800_0000000)就等于物理地址对应的线性地址

  3. 看断点处的反汇编

    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.
  4. 看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, 这是调试器的断点标记.

    猜想是否内核模块代码所在页框不可写, 因此接下来就是找到该页框, 查看该页框的属性

  5. 查看cr3寄存器的值

    1
    2
    (gdb) p /x cr3
    $8 = 0x138bca000

    pgd的物理地址: 0x138bca000

    线性地址: 0xffff8801 38bca000

  6. 查看DriverInitialize的线性地址

    1
    2
    (gdb) p DriverInitialize
    $9 = {int (void)} 0xffffffffa02c9217 <DriverInitialize>

    线性地址: 0xffffffffa02c9217

  7. pgd表

    1. index: 0b1,1111,1111 = 0x1ff

    2. 偏移量: $index \times 8$

      1
      2
      (gdb) p /x 0x1ff * 8
      $12 = 0xff8
    3. 存储pud表物理基地址的内存的线性地址: 0xffff8801 38bca000+0xff8 = 0xffff8801 38bcaff8

    4. 0xffff8801 38bcaff8存储的值

      1
      2
      (gdb) x /8xb 0xffff880138bcaff8
      0xffff880138bcaff8: 0x67 0x10 0xc1 0x01 0x00 0x00 0x00 0x00

      即: 0x01c11067

    5. 获得的信息如下

      • pud的物理基地址: 0x01c11000
      • R/W: 1
      • P: 1
  8. pud表

    1. index: 0b111111110 = 0x1fe

    2. offset:

      1
      2
      (gdb) p /x 0b111111110 * 8
      $16 = 0xff0
    3. 索引项的线性地址: 0xffff8800 01c11000+0xff0 = 0xffff8800 01c11ff0

    4. 0xffff8800 01c11ff0 存储的值:

      1
      2
      (gdb) x /8xb 0xffff880001c11ff0
      0xffff880001c11ff0: 0x63 0x20 0xc1 0x01 0x00 0x00 0x00 0x00

      即: 0x01c12063

    5. 获得的信息如下

      • pmd的物理基地址: 0x01c12000
      • R/W: 1
      • P: 1
  9. pmd表

    1. index: 0b1 0000 0001 = 0x101

    2. offset: 0x808

    3. 索引项的线性地址: 0xffff8800 01c12000 + 0x808 = 0xffff8800 01c12808

    4. 0xffff880001c12808存储的值

      1
      2
      (gdb) x /8xb 0xffff880001c12808
      0xffff880001c12808: 0x67 0xb0 0xb8 0xb4 0x00 0x00 0x00 0x00

      即: 0xb4b8b067

    5. 获得的信息如下

      • pt的物理基地址: 0xb4b8b000
      • R/W: 1
      • P: 1
  10. pt表

    1. index: 0b0 1100 1001 = 0x0c9

    2. offset: 0x0c9 * 8 = 0x648

    3. 索引项线性地址: 0xffff8800 b4b8b000 + 0x648 = 0xffff8800 b4b8b648

    4. 0xffff8800 b4b8b648存储的值

      1
      2
      (gdb) x /8xb 0xffff8800b4b8b648
      0xffff8800b4b8b648: 0x61 0x91 0xfa 0x35 0x01 0x00 0x00 0x00

      即: 0x0135fa9161

    5. 获得的信息如下

      • pt的物理基地址: 0x0135fa9000
      • R/W: 0 (只可读不可写)
      • P: 1
  11. 修改pt表的 R/W 值

    1. 修改为可读可写: set {unsigned char}0xffff8800b4b8b648=0x63

    2. 查看是否修改成功

      1
      2
      (gdb) x /8xb 0xffff8800b4b8b648
      0xffff8800b4b8b648: 0x63 0x91 0xfa 0x35 0x01 0x00 0x00 0x00
  12. 修改int3处的机器码

    1. 查看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处的机器码

    2. 0xffffffffa02c9230机器码

      1
      2
      (gdb) x /8xb 0xffffffffa02c9230
      0xffffffffa02c9230 <DriverInitialize+25>: 0xe8 0x3d 0xad 0xde 0xe0 0x0f 0x20 0xd8

      知: callq 的机器码为 0xe8

    3. 修改int3处的机器码 0xe8

      1
      (gdb) set {unsigned char}0xffffffffa02c923c=0xe8
    4. 查看是否修改成功

      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.
  13. 继续运行

    1
    2
    (gdb) c
    Continuing.

全部命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
root@ubuntu14:/home/qeuroal/Documents/kernel/linux-3.13# gdb ./vmlinux
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.3) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./vmlinux...done.
(gdb) set serial baud 115200
(gdb) target remote /dev/ttyS1
Remote debugging using /dev/ttyS1
kgdb_breakpoint () at kernel/debug/debug_core.c:1042
1042 wmb(); /* Sync point after breakpoint */
(gdb) l
1037 void kgdb_breakpoint(void)
1038 {
1039 atomic_inc(&kgdb_setting_breakpoint);
1040 wmb(); /* Sync point before breakpoint */
1041 arch_kgdb_breakpoint();
1042 wmb(); /* Sync point after breakpoint */
1043 atomic_dec(&kgdb_setting_breakpoint);
1044 }
1045 EXPORT_SYMBOL_GPL(kgdb_breakpoint);
1046
(gdb) b do_init_module
Breakpoint 1 at 0xffffffff810d4ed7: file kernel/module.c, line 3013.
(gdb) c
Continuing.
[New Thread 1835]
[Switching to Thread 1835]

Breakpoint 1, do_init_module (mod=mod@entry=0xffffffffa02a50e0) at kernel/module.c:3013
3013 {
(gdb) c
Continuing.
[New Thread 1859]
[Switching to Thread 1859]

Breakpoint 1, do_init_module (mod=mod@entry=0xffffffffa02cb0e0) at kernel/module.c:3013
3013 {
(gdb) p mod->sect_attrs->attrs[1]->name
$1 = 0xffff8800bb806de0 ".text"
(gdb) p /x mod->sect_attrs->attrs[1]->address
$2 = 0xffffffffa02c9000
(gdb) p mod->sect_attrs->attrs[4]->name
$3 = 0xffff8800bb806db0 ".data"
(gdb) p /x mod->sect_attrs->attrs[4]->address
$4 = 0xffffffffa02cb000
(gdb) p mod->sect_attrs->attrs[6]->name
$5 = 0xffff8800bb806df8 ".bss"
(gdb) p /x mod->sect_attrs->attrs[6]->address
$6 = 0xffffffffa02cb340
(gdb) add-symbol-file /home/qeuroal/Documents/code/4/4.1/PrintModule.ko 0xffffffffa02c9000 -s .data 0xffffffffa02cb000 -s .bss 0xffffffffa02cb340
add symbol table from file "/home/qeuroal/Documents/code/4/4.1/PrintModule.ko" at
.text_addr = 0xffffffffa02c9000
.data_addr = 0xffffffffa02cb000
.bss_addr = 0xffffffffa02cb340
(y or n) y
Reading symbols from /home/qeuroal/Documents/code/4/4.1/PrintModule.ko...done.
(gdb) l Driver
Function "Driver" not defined.
(gdb) l DriverInitialize
81
82 unregister_chrdev_region(gslDriverParameters.uiDeviceNumber, 1);
83 }
84
85 static int DriverInitialize(void)
86 {
87 unsigned long cr3;
88
89 DEBUG_PRINT(DEVICE_NAME " Initialize\n");
90
(gdb)
91 asm volatile("mov %%cr3, %0\n\t" : "=r" (cr3), "=m" (__force_order));
92
93 return InitalizeCharDevice();
94 }
95
96 static void DriverUninitialize(void)
97 {
98 DEBUG_PRINT(DEVICE_NAME " Uninitialize\n");
99
100 UninitialCharDevice();
(gdb)
101 }
102
103 module_init(DriverInitialize);
104 module_exit(DriverUninitialize);
(gdb) b 93
Breakpoint 2 at 0xffffffffa02c923c: file /home/qeuroal/Documents/code/4/4.1/DriverMain.c, line 93.
(gdb) c
Continuing.

Breakpoint 2, DriverInitialize () at /home/qeuroal/Documents/code/4/4.1/DriverMain.c:93
93 return InitalizeCharDevice();
(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.
(gdb) x /8xb 0xffffffffa02c923c

0xffffffffa02c923c <DriverInitialize+37>: 0xcc 0xef 0xfd 0xff 0xff 0xc9 0xc3 0x0f
(gdb)
0xffffffffa02c9244 <DriverUninitialize+1>: 0x1f 0x44 0x00 0x00 0x55 0x48 0x89 0xe5
(gdb) x /8xb 0xffffffffa02c923d
0xffffffffa02c923d <DriverInitialize+38>: 0xef 0xfd 0xff 0xff 0xc9 0xc3 0x0f 0x1f
(gdb) x /8xb 0xffffffffa02c923c
0xffffffffa02c923c <DriverInitialize+37>: 0xcc 0xef 0xfd 0xff 0xff 0xc9 0xc3 0x0f
(gdb) p cr3
$7 = 5246853120
(gdb) p /x cr3
$8 = 0x138bca000
(gdb) p DriverInitialize
$9 = {int (void)} 0xffffffffa02c9217 <DriverInitialize>
(gdb) p /x cr3
$10 = 0x138bca000
(gdb) p /x PAGE_OFFSET
No symbol "PAGE_OFFSET" in current context.
(gdb) p DriverInitialize
$11 = {int (void)} 0xffffffffa02c9217 <DriverInitialize>
(gdb) p /x 0x1ff * 8
$12 = 0xff8
(gdb) p /x 0x1ff*8
$13 = 0xff8
(gdb) x /8xb 0xffff880138bcaff8
0xffff880138bcaff8: 0x67 0x10 0xc1 0x01 0x00 0x00 0x00 0x00
(gdb) p /x 0x1fe * 8
$14 = 0xff0
(gdb) p /x 0xffff880001c11000+0xff0
$17 = 0xffff880001c11ff0
(gdb) x /8xb 0xffff880001c11ff0
0xffff880001c11ff0: 0x63 0x20 0xc1 0x01 0x00 0x00 0x00 0x00
(gdb) x /8xb 0xffff880001c12808
0xffff880001c12808: 0x67 0xb0 0xb8 0xb4 0x00 0x00 0x00 0x00
(gdb) p /x 0x0c9
$18 = 0xc9
(gdb) p /x 0x0c9 * 8
$19 = 0x648
(gdb) x /8xb 0xffff8800b4b8b648
0xffff8800b4b8b648: 0x61 0x91 0xfa 0x35 0x01 0x00 0x00 0x00
(gdb) set {unsigned char}0xffff8800b4b8b648=0x63
(gdb) x /8xb 0xffff8800b4b8b648
0xffff8800b4b8b648: 0x63 0x91 0xfa 0x35 0x01 0x00 0x00 0x00
(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.
(gdb) x /8xb 0xffffffffa02c9230
0xffffffffa02c9230 <DriverInitialize+25>: 0xe8 0x3d 0xad 0xde 0xe0 0x0f 0x20 0xd8
(gdb) set {unsigned char}0xffffffffa02c923c=0xe8
(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.
(gdb) c
Continuing.