3
votes

I'm replacing/hooking __NR_read sysall with this block of code (which is compiled and saved as opcode in an executable memory in a kernel module)

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;

Now, what this pretends to do:

  1. Save syscall arguments
  2. Call atomic_inc with an argument pointing to a memory that contains an atomit_t data
  3. Call the real syscall
  4. Save the returned value
  5. Call the hooked syscall with the arguments that were saved earlier (this is used to monitor the syscall,. aka, with what parameters it was called)
  6. Call atomic_dec
  7. Return the result from the call to the real syscall (placing it in rax)

The opcode is compiled and the addresses of the functions (the faked syscall, atomic_int and atomic_dec) are patched in run-time. After patching in run-time, the opcode looks like this:

554889e54883ec404889042448897c24f848897424f048895424e84c895424e04c894424d84c894c24d048b860621fa0ffffffff48bf000433250088ffffffd0488b0424488b7c24f8488b7424f0488b5424e84c8b5424e04c8b4424d84c8b4c24d00f0548894424c848b8f0701fa0ffffffff488b7c24f8488b7424f0488b5424e8488b4c24e04c8b4424d84c8b4c24d0ffd048b870621fa0ffffffff48bf000433250088ffffffd0488b4424c84889ec5dc3

I'm using http://www.onlinedisassembler.com/odaweb/ to check if everything is correct, which it is, but anyways, the virtualbox where I'm trying those changes crashes.

My question is: can you spot anything wrong with my code? (as I can't provide any further details about the error, as I can't get those myself).

Regards

1
Try writing this in C in order to think about the flow of what youare a trying to do, before you try writing it in assembly... And remember you can't just overwrite the memory with code of a different size. - Chris Stratton

1 Answers

3
votes

ODA shows me this:

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

So, what is the SYSCALL ??? 

Possibly, you mean the CALL for the system call handling routine (sys_read, for example). So, it must be call sys_read in that case...