从具有此代码段的模块代码中,我尝试更改CS寄存器的值:
asm("pushq %rax"); asm("mov $0x10,%rax"); asm("mov %rax,%cs"); asm("popq %rax");
实际上,CS寄存器包含段选择器- $0x10
,也是内核宏返回的该值__KERNEL_CS
。我想做的是用完全相同的值重写CS寄存器。不幸的是,我遇到了错误,没有摘要,则没有错误。
Aug 1 20:26:37 myhost kernel: [ 2905.693297] invalid opcode: 0000 [#1] SMP Aug 1 20:26:37 myhost kernel: [ 2905.694223] CPU: 0 PID: 7140 Comm: insmod Tainted: P OE 4.4.0-148-generic #174~14.04.1-Ubuntu Aug 1 20:26:37 myhost kernel: [ 2905.694362] task: ffff88007a0edb00 ti: ffff880068c54000 task.ti: ffff880068c54000 Aug 1 20:26:37 myhost kernel: [ 2905.694420] RIP: 0010:[] [ ] hello_init+0x44/0xe0 [hello_module] Aug 1 20:26:37 myhost kernel: [ 2905.694497] RSP: 0018:ffff880068c57ca0 EFLAGS: 00010282 Aug 1 20:26:37 myhost kernel: [ 2905.694540] RAX: 0000000000000010 RBX: ffffffff81e15080 RCX: 0000000000005768 Aug 1 20:26:37 myhost kernel: [ 2905.694595] RDX: 000000000000b1e4 RSI: 0000000000000246 RDI: 0000000000000246 Aug 1 20:26:37 myhost kernel: [ 2905.694649] RBP: ffff880068c57cc0 R08: 3231203a657a6973 R09: 6461202c66373a37 Aug 1 20:26:37 myhost kernel: [ 2905.694703] R10: 203a737365726464 R11: 0000000000000363 R12: ffff8800b7e7e980 Aug 1 20:26:37 myhost kernel: [ 2905.694757] R13: 0000000000000000 R14: ffffffffc114e0d0 R15: ffff880068c57eb0 Aug 1 20:26:37 myhost kernel: [ 2905.694813] FS: 00007f8c1c36b740(0000) GS:ffff88013fa00000(0000) knlGS:0000000000000000 Aug 1 20:26:37 myhost kernel: [ 2905.694875] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 Aug 1 20:26:37 myhost kernel: [ 2905.694920] CR2: 00005575a6b20248 CR3: 0000000075efc000 CR4: 0000000000060670 Aug 1 20:26:37 myhost kernel: [ 2905.694975] Stack: Aug 1 20:26:37 myhost kernel: [ 2905.694995] 0000000000000000 007f000081e15080 ffff88013fa0c000 ffffffff81e15080 Aug 1 20:26:37 myhost kernel: [ 2905.695065] ffff880068c57d38 ffffffff8100216f ffff880068c57eb0 ffff880068c57d10 Aug 1 20:26:37 myhost kernel: [ 2905.695133] 0000000000000246 0000000000000002 ffffffff811eab7f ffff88013b003c00 Aug 1 20:26:37 myhost kernel: [ 2905.695201] Call Trace: Aug 1 20:26:37 myhost kernel: [ 2905.695230] [ ] do_one_initcall+0xcf/0x200 Aug 1 20:26:37 myhost kernel: [ 2905.695281] [ ] ? kmem_cache_alloc_trace+0x1af/0x220 Aug 1 20:26:37 myhost kernel: [ 2905.695338] [ ] ? do_init_module+0x27/0x1d2 Aug 1 20:26:37 myhost kernel: [ 2905.695387] [ ] do_init_module+0x60/0x1d2 Aug 1 20:26:37 myhost kernel: [ 2905.695432] [ ] load_module+0x145d/0x1b50 Aug 1 20:26:37 myhost kernel: [ 2905.695480] [ ] ? __symbol_put+0x40/0x40 Aug 1 20:26:37 myhost kernel: [ 2905.695528] [ ] ? kernel_read+0x41/0x60 Aug 1 20:26:37 myhost kernel: [ 2905.695574] [ ] SYSC_finit_module+0x7e/0xa0 Aug 1 20:26:37 myhost kernel: [ 2905.695620] [ ] SyS_finit_module+0xe/0x10 Aug 1 20:26:37 myhost kernel: [ 2905.697884] [ ] entry_SYSCALL_64_fastpath+0x22/0xcb Aug 1 20:26:37 myhost kernel: [ 2905.700094] Code: eb 03 c0 0f 01 45 ee 0f b7 75 ee 48 8b 4d f0 48 c7 c7 9d f0 14 c1 31 c0 89 f2 e8 73 eb 03 c0 8c 5d ec 41 55 49 c7 c5 10 00 00 00 <49> 8e cd 41 5d 8c 4d ea 0f b7 55 ec 0f b7 75 ea 48 c7 c7 b8 f0 Aug 1 20:26:37 myhost kernel: [ 2905.704976] RIP [ ] hello_init+0x44/0xe0 [hello_module] Aug 1 20:26:37 myhost kernel: [ 2905.707358] RSP Aug 1 20:26:37 myhost kernel: [ 2905.719667] ---[ end trace 48f04fe6e7ff0ed6 ]---
用R13
寄存器更新
Aug 1 21:05:25 myhost kernel: [ 146.818158] invalid opcode: 0000 [#1] SMP Aug 1 21:05:25 myhost kernel: [ 146.818699] CPU: 1 PID: 5108 Comm: insmod Tainted: P OE 4.4.0-148-generic #174~14.04.1-Ubuntu Aug 1 21:05:25 myhost kernel: [ 146.818778] task: ffff880097a45b00 ti: ffff880085d58000 task.ti: ffff880085d58000 Aug 1 21:05:25 myhost kernel: [ 146.818810] RIP: 0010:[] [ ] hello_init+0x44/0xe0 [hello_module] Aug 1 21:05:25 myhost kernel: [ 146.818854] RSP: 0018:ffff880085d5bca0 EFLAGS: 00010282 Aug 1 21:05:25 myhost kernel: [ 146.818880] RAX: 000000000000001f RBX: ffffffff81e15080 RCX: 0000000000002298 Aug 1 21:05:25 myhost kernel: [ 146.818911] RDX: 00000000000051a2 RSI: 0000000000000246 RDI: 0000000000000246 Aug 1 21:05:25 myhost kernel: [ 146.818942] RBP: ffff880085d5bcc0 R08: 3231203a657a6973 R09: 6461202c66373a37 Aug 1 21:05:25 myhost kernel: [ 146.818973] R10: 203a737365726464 R11: 0000000000000353 R12: ffff880085cc0b60 Aug 1 21:05:25 myhost kernel: [ 146.819004] R13: 0000000000000010 R14: ffffffffc109e0d0 R15: ffff880085d5beb0 Aug 1 21:05:25 myhost kernel: [ 146.819037] FS: 00007fd564d44740(0000) GS:ffff88013fa40000(0000) knlGS:0000000000000000 Aug 1 21:05:25 myhost kernel: [ 146.819072] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 Aug 1 21:05:25 myhost kernel: [ 146.819097] CR2: 0000558a2aa16248 CR3: 0000000085d5c000 CR4: 0000000000060670 Aug 1 21:05:25 myhost kernel: [ 146.819128] Stack: Aug 1 21:05:25 myhost kernel: [ 146.819139] 0000000000000000 007f000081e15080 ffff88013fa4c000 ffffffff81e15080 Aug 1 21:05:25 myhost kernel: [ 146.819178] ffff880085d5bd38 ffffffff8100216f ffff880085d5beb0 ffff880085d5bd10 Aug 1 21:05:25 myhost kernel: [ 146.819217] 0000000000000246 0000000000000002 ffffffff811eab7f ffff88013b003c00 Aug 1 21:05:25 myhost kernel: [ 146.819255] Call Trace: Aug 1 21:05:25 myhost kernel: [ 146.819273] [ ] do_one_initcall+0xcf/0x200 Aug 1 21:05:25 myhost kernel: [ 146.819301] [ ] ? kmem_cache_alloc_trace+0x1af/0x220 Aug 1 21:05:25 myhost kernel: [ 146.819332] [ ] ? do_init_module+0x27/0x1d2 Aug 1 21:05:25 myhost kernel: [ 146.819359] [ ] do_init_module+0x60/0x1d2 Aug 1 21:05:25 myhost kernel: [ 146.819385] [ ] load_module+0x145d/0x1b50 Aug 1 21:05:25 myhost kernel: [ 146.819412] [ ] ? __symbol_put+0x40/0x40 Aug 1 21:05:25 myhost kernel: [ 146.819440] [ ] ? kernel_read+0x41/0x60 Aug 1 21:05:25 myhost kernel: [ 146.819466] [ ] SYSC_finit_module+0x7e/0xa0 Aug 1 21:05:25 myhost kernel: [ 146.819492] [ ] SyS_finit_module+0xe/0x10 Aug 1 21:05:25 myhost kernel: [ 146.820820] [ ] entry_SYSCALL_64_fastpath+0x22/0xcb Aug 1 21:05:25 myhost kernel: [ 146.822117] Code: eb 0e c0 0f 01 45 ee 0f b7 75 ee 48 8b 4d f0 48 c7 c7 9d f0 09 c1 31 c0 89 f2 e8 73 eb 0e c0 8c 5d ec 41 55 49 c7 c5 10 00 00 00 <49> 8e cd 41 5d 8c 4d ea 0f b7 55 ec 0f b7 75 ea 48 c7 c7 b8 f0 Aug 1 21:05:25 myhost kernel: [ 146.824981] RIP [ ] hello_init+0x44/0xe0 [hello_module] Aug 1 21:05:25 myhost kernel: [ 146.826376] RSP Aug 1 21:05:25 myhost kernel: [ 146.833469] ---[ end trace 6525f2f63d2f58dd ]---
Renat.. 7
没有mov
要写入的指令cs
。根据英特尔®64和IA-32架构软件开发人员手册,MOV规范:
MOV指令不能用于加载CS寄存器。尝试这样做会导致无效的操作码异常(#UD)。
您需要进行很大的改变cs
,检查5.8章的限制以进行改变cs
。
没有mov
要写入的指令cs
。根据英特尔®64和IA-32架构软件开发人员手册,MOV规范:
MOV指令不能用于加载CS寄存器。尝试这样做会导致无效的操作码异常(#UD)。
您需要进行很大的改变cs
,检查5.8章的限制以进行改变cs
。
您不能使用选择器直接加载CSMOV
。您将需要使用RETFQ
或IRETQ
指令来更改CS并转到64位偏移量。从指令集参考中:
MOV指令不能用于加载CS寄存器。尝试这样做会导致无效的操作码异常(#UD)。要加载CS寄存器,请使用far JMP,CALL或RET指令。
您将获得#UD(无效的操作码),这就是模块崩溃的原因。
在64位代码中,没有FAR CALL或FAR JMP将选择器和64位偏移量作为操作数(立即值),因为没有ptr16:64
变体。
在32位模式下,您可能已经完成了,ljmpl $0x10, $offset
但是在64位代码中,您必须使用替代项1,例如RETFQ(如果需要特权级别更改,则使用IRETQ)。您可以使用如下代码:
asm ("push %[sel]\n\t" "push $1f\n\t" "retfq\n\t" "1:" : : [sel]"i"(__KERNEL_CS));
如果要在问题中使用基本的内联汇编,则需要将连续ASM
语句放入一个语句中。允许编译器在您的各个ASM
语句之间生成代码,这不是您想要的。基本ASM
版本为:
asm ("push $0x10\n\t" "push $1f\n\t" "retfq\n\t" "1:");
重要的是要注意,您需要重写RETF
为Q
uadword大小,因为RETF
64位代码中的默认值假定返回的地址为32位,并且我们要指定要返回的地址为64位地址。从英特尔文档中RET
:
在64位模式下,此指令的默认操作大小为堆栈地址大小,即64位。这适用于近期收益,而不是远期收益;far返回的默认操作大小为32位。
该代码通过将选择器推到堆栈2上,然后1:
将指令的偏移量(标签)推入堆栈,将FAR JMP模拟为下一条指令retfq
。retfq
将弹出偏移量和选择器,并将控制转移到恰好是下一条指令的那个地址。
1可以创建一个长度为10个字节的变量,其中包括一个用于跳转的偏移量的QWORD和一个用于选择器的WORD。然后,您可以使用JMP m16:64
jump变体。要JMP m16:m64
使用AT&T语法在GCC内联汇编中编码,您可以执行以下操作:
asm ("push %[sel]\n\t" "push $1f\n\t" "rex.W ljmp *(%%rsp)\n\t" "1:add $16, %%rsp\n\t" : : [sel]"i"(__KERNEL_CS));
该代码16:64
在堆栈上构建(选择器:偏移)指针,并通过RSP对它执行间接FAR JMP 。该16:64
地址指向FAR JMP之后的指令。的rex.W
前缀促进FAR JMP,使得指针被解码与一个64位的偏移量,而不是32位的偏移量。然后清理堆栈,从堆栈中删除指针。
我不知道更改CS的上下文或原因,但是如果经常发生代码被调用的情况,那么您可能希望16:64
在代码本身中发出指针。在以下例子中的16:64
指针被存储在FAR JMP指令之后,指令跳转到处于标签2:
(后的16:64
指针):
asm ("rex.W ljmp *1f\n\t" /* The pointer is being stored with the code. The jump will be to the label after the pointer itself at label '2:'. */ "1: .quad 2f\n\t" " .word %c[sel]\n\t" "2:\n\t" : : [sel]"i"(__KERNEL_CS));
2 Linux内核本身没有红色区域,因此可以安全地通过内联汇编将信息直接压入堆栈。在用户模式代码中,您必须调整RSP以避免破坏RSP正下方的128个字节。