【问题标题】:Handling syscall via ASM code通过 ASM 代码处理系统调用
【发布时间】:2013-12-19 18:32:03
【问题描述】:

我正在用这段代码替换/挂钩__NR_read sysall(它被编译并作为操作码保存在内核模块的可执行内存中)

push rbp;
mov rbp, rsp;
sub rsp, 64; //8 bytes for rax content + 48 bytes for 6 args + 8 bytes for syscall result

mov [rsp], rax;
mov [rsp - 8], rdi;
mov [rsp - 16], rsi;
mov [rsp - 24], rdx;
mov [rsp - 32], r10;
mov [rsp - 40], r8;
mov [rsp - 48], r9;

mov rax, &atomic_inc;
mov rdi, &iter->counter;
call rax;

mov rax, [rsp];
mov rdi, [rsp - 8];
mov rsi, [rsp - 16];
mov rdx, [rsp - 24];
mov r10, [rsp - 32];
mov r8, [rsp - 40];
mov r9, [rsp - 48];
syscall;

mov [rsp - 56], rax;

mov rax, &iter->fake_syscall_function; //<-- this is inside the kernel module
mov rdi, [rsp - 8];
mov rsi, [rsp - 16];
mov rdx, [rsp - 24];
mov rcx, [rsp - 32];
mov r8, [rsp - 40];
mov r9, [rsp - 48];
call rax;

mov rax, &atomic_dec;
mov rdi, &iter->counter;
call rax;

mov rax, [rsp - 56];

mov rsp, rbp;
pop rbp;
ret;

现在,它假装在做什么:

  1. 保存系统调用参数
  2. 使用指向包含 atomit_t 数据的内存的参数调用 atomic_inc
  3. 调用真正的系统调用
  4. 保存返回值
  5. 使用之前保存的参数调用挂钩的系统调用(这用于监视系统调用,也就是调用它的参数)
  6. 调用 atomic_dec
  7. 将调用结果返回给真正的系统调用(将其放在 rax 中)

编译操作码并在运行时修补函数的地址(伪造的系统调用、atomic_int 和 atomic_dec)。 在运行时打补丁后,操作码如下所示:

554889e54883ec404889042448897c24f848897424f048895424e84c895424e04c894424d84c894c24d048b860621fa0ffffffff48bf000433250088ffffffd0488b0424488b7c24f8488b7424f0488b5424e84c8b5424e04c8b4424d84c8b4c24d00f0548894424c848b8f0701fa0ffffffff488b7c24f8488b7424f0488b5424e8488b4c24e04c8b4424d84c8b4c24d0ffd048b870621fa0ffffffff48bf000433250088ffffffd0488b4424c84889ec5dc3

我正在使用http://www.onlinedisassembler.com/odaweb/ 检查一切是否正确,但无论如何,我尝试进行这些更改的虚拟机崩溃了。

我的问题是:您能发现我的代码有什么问题吗? (因为我无法提供有关该错误的更多详细信息,因为我自己无法获得这些信息)。

问候

【问题讨论】:

  • 尝试用 C 语言编写它,以便在尝试用汇编语言编写它之前考虑你正在尝试做的事情的流程......记住你不能只用代码覆盖内存大小不同。

标签: linux assembly linux-kernel x86-64 kernel-module


【解决方案1】:

ODA 告诉我this

.data:0x0000005d    4c8b4c24d0  mov    r9,QWORD PTR [rsp-0x30]
.data:0x00000062    0f05    syscall
.data:0x00000064    48894424c8  mov    QWORD PTR [rsp-0x38],rax

那么,什么是 SYSCALL ???

您的意思可能是系统调用处理例程的 CALL(例如sys_read)。所以,这种情况下一定是call sys_read...

【讨论】:

  • 但我正在尝试调用真正的__NR_read 函数,这是一个内核系统调用。并且根据 ASM 调用约定,应该通过将系统调用号放在 rax 中然后调用 syscall(在 x64 中)来调用系统调用
  • 如果您已经用您的代码替换了系统调用例程,这将不起作用。系统调用指令在已经处于内核模式时无效,否则您的代码只会调用自身,从而导致无限循环。
  • 不要使用基于RSP的堆栈寻址,使用RBP,因为你使用mov rbp, rsp命令设置它......
  • 另外,你需要保存/恢复 rdi,rsi,rdx,rcx,r8,r9 而不是 r10 而不是 rcx
  • @alexandernst x86_64 调用约定假定它必须是 RDI,RSI,RDX,RCX,R8,R9。
猜你喜欢
  • 2014-01-14
  • 1970-01-01
  • 1970-01-01
  • 2019-04-05
  • 1970-01-01
  • 2021-04-29
  • 1970-01-01
  • 2019-08-04
  • 2017-03-22
相关资源
最近更新 更多