Root Has Segfault Executing RDMSR Assembly Code - c

I would like to read msr 0x19a (IA32_CLOCK_MODULATIOn) directly from C code WITH root privilege. However, I get the following segfault error.
a.out[27843] general protection ip:40053b sp:7fffefc38020 error:0 in a.out[400000+1000]
Does anyone know whether this way of calling rdmsr is a viable option?
Thanks in advance!
#include <stdio.h>
#define __init
typedef unsigned uint32_t;
static int __init test3_init(void)
{
uint32_t hi,lo;
hi=0x0; lo=0x0;
asm volatile("mov $0x19a,%ecx");
asm volatile("rdmsr":"=a"(lo),"=d"(hi));
printf("exit_readmsr: hi=%08x lo=%08x\n",hi,lo);
return 0;
}
int main(void)
{
return test3_init();
}
BTW, the code is extract from this answer.

This instruction must be executed at privilege level 0. In other words, you must be inside the kernel.

Related

Run m-type instructions on RISC-V

Is it possible to run m-type instruction of RISC-V isa from userspace? I have to run misa instruction that provides cpu info from a userspace c program, but according to RISC-V documentation it's possible at machine privilege level. Is it completely impossible or is there a workaround?
I've already tried
#include <stdio.h>
static unsigned long cpuid()
{
unsigned long res;
__asm__ volatile ("csrr %0, misa" : "=r"(res));
return res;
}
int main() {
unsigned long mcpuid = cpuid();
printf("mcpuid: %lu", mcpuid);
return 0;
}
Running it on a RISC-V fedora I get Illegal instruction

LKM scheduling while atomic

I am developing a linux kernel module, which looks like this:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Me");
MODULE_DESCRIPTION("Something Something");
int checkSomething(void) {
int someCpuFeature = 0;
__asm__("mov $1, %eax");
__asm__("cpuid");
__asm__("mov %%ecx, %0" : "=r" (someCpuFeature));
if (someCpuFeature & 32) {
return 1;
}
return 0;
}
int __init init_module(void) {
if (!checkSomething()) {
printk(KERN_INFO "Exiting\n");
return 0;
} else {
printk(KERN_INFO "Continuing\n");
}
return 0;
}
static void __exit exit_module(void) {
printk(KERN_INFO "Unloading Module\n");
}
And when i loaded it, i tried to see it's output from dmesg.
but instead of only printing Exiting/Continuing, it also printed a call trace,
and said BUG: scheduling while atomic: insmod/24641/0x06100800.
I searched this bug and found that it has some connection to the scheduler and sleeping at places you shouldn't sleep in, but this is the only functionality of the code,
So i think it has something to do with the cpuid instruction, but i don't know exactly what it is.
any ideas?
Hm, considering the interrupts raised on my machine now, it would look like your assembler is incorrect.
Instead of writing this yourself, I'd recommend relying on the cpuid kernel module (and thus, reading /dev/cpu/NUMBER/cpuid after seeking to your level of interest), as that's future-proof external API. You can also look at /arch/x86/include/asm/processor.h, and use kernel functions like cpu_has to detect your feature. Don't reinvent the wheel – querying details of a CPU on an SMP machine is bound to be painful, and the poor kernel developers had to go through the pain to make this work themselves.

How to Compile a C program which contains 32bit asm into .o file?

Introduction
I'm following through the book "Learning Linux Binary Analysis". I have some experience working with 32 bit assembly and C (however still consider myself a novice). However I'm having trouble and confusion of how to compile a c program , which contains 32 bit assembly into an object file .o. So im guessing this is just a compilation issue on my part.
The Source code is for part of an example of code injection-based binary patching.
Source Code
#include <sys/syscall.h>
int _write (int fd, void *buf, int count)
{
long ret;
__asm__ __volatile__ ("pushl %%ebx\n\t"
"movl %%esi,%%ebx\n\t"
"int $0x80\n\t""popl %%ebx":"=a" (ret)
:"0" (SYS_write), "S" ((long) fd),
"c" ((long) buf), "d" ((long) count));
if (ret >= 0) {
return (int) ret;
}
return -1;
}
int evil_puts(void)
{
_write(1, "HAHA puts() has been hijacked!\n", 31);
}
The problem
I attempt to compile evil_puts.c into .o file. Which will then be used later for injection into another simple program.
gcc -c evil_puts.c
evil_puts.c: Assembler messages:
evil_puts.c:5: Error: invalid instruction suffix for `push'
evil_puts.c:8: Error: invalid instruction suffix for `pop'
I've received this before when working with 32 assembly with gas. And to solve this i put the '-32' flag when compiling and linking. Which i'm guessing is the problem? however not completely sure, and don't have an idea of how to compile it in 32 bit with C and gcc if that's the case?
I also attempted to change it to 64bit to see if it would work, by replacing 'l' of every command to 'q' and changing the registers to begin with 'r'. which seems to work. However the book uses 32 bit. So i wish to keep it that way. Any ideas? Sorry if this is a really basic question.
Also tried '-m32' but receive this:
fatal error: sys/syscall.h: No such file or directory
Use gcc -m32 -c evil_puts.c -o evil_puts.o
You're getting that error because you don't have the 32-bit libraries installed.
If using Ubuntu:
sudo apt-get install gcc-multilib
Knowledge specific to 32-bit x86 is of limited usefulness these days since basically everybody has switched to 64-bit (this is a good thing - 32-bit has a lot of register pressure and address space pressure).
Luckily, you don't actually need any asm for what you're doing. I've also made a couple sanity fixes:
#define _GNU_SOURCE
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h>
#define write_str(fd, s) my_write(fd, s, strlen(s))
static ssize_t my_write(int fd, const void *buf, size_t count)
{
return syscall(SYS_write, (long)fd, (long)buf, (long)count);
}
int puts(const char *s __attribute__((unused)))
{
write_str(STDOUT_FILENO, "HAHA puts() has been hijacked!\n");
return strlen(s) + 1;
}
I'm not sure exactly why you're avoiding write(2). But if you really need to avoid syscall(2) as well, it will still be far easier to implement that single function in assembly than write assembly everywhere.

System call interception in linux-kernel module (kernel 3.5)

I need to replace a standard system call (e.g. SYS_mkdir) with my own implementation.
As I read in some sources, including this question on Stackoverflow, the sys_call_table is not exported symbol since kernel version 2.6.
I tried the following code:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/unistd.h>
#include <asm/syscall.h>
int (*orig_mkdir)(const char *path);
....
int init_module(void)
{
orig_mkdir=sys_call_table[__NR_mkdir];
sys_call_table[__NR_mkdir]=own_mkdir;
printk("sys_mkdir replaced\n");
return(0);
}
....
Unfortunately I receive compiler error:
error: assignment of read-only location ‘sys_call_table[83]’
How can I replace the system call?
EDIT: Is there any solution without kernel patching?
this works for me.
See
Linux Kernel: System call hooking example
and
https://bbs.archlinux.org/viewtopic.php?id=139406
asmlinkage long (*ref_sys_open)(const char __user *filename, int flags, umode_t mode);
asmlinkage long new_sys_open(const char __user *filename, int flags, umode_t mode)
{
return ref_sys_open(filename, flags, mode);
}
static unsigned long **aquire_sys_call_table(void)
{
unsigned long int offset = PAGE_OFFSET;
unsigned long **sct;
while (offset < ULLONG_MAX) {
sct = (unsigned long **)offset;
if (sct[__NR_close] == (unsigned long *) sys_close)
return sct;
offset += sizeof(void *);
}
print("Getting syscall table failed. :(");
return NULL;
}
// Crazy copypasted asm stuff. Could use linux function as well...
// but this works and will work in the future they say.
static void disable_page_protection(void)
{
unsigned long value;
asm volatile("mov %%cr0, %0" : "=r" (value));
if(!(value & 0x00010000))
return;
asm volatile("mov %0, %%cr0" : : "r" (value & ~0x00010000));
}
static void enable_page_protection(void)
{
unsigned long value;
asm volatile("mov %%cr0, %0" : "=r" (value));
if((value & 0x00010000))
return;
asm volatile("mov %0, %%cr0" : : "r" (value | 0x00010000));
}
static int __init rootkit_start(void)
{
//Hide me
print("loaded");
if(!(sys_call_table = aquire_sys_call_table()))
return -1;
disable_page_protection();
{
ref_sys_open = (void *)sys_call_table[__NR_open];
sys_call_table[__NR_open] = (unsigned long *)new_sys_open;
}
enable_page_protection();
return 0;
}
static void __exit rootkit_end(void)
{
print("exiting");
if(!sys_call_table) {
return;
}
disable_page_protection();
{
sys_call_table[__NR_open] = (unsigned long *)ref_sys_open;
}
enable_page_protection();
}
Yes there is a solution without patching/rebuilding the kernel. Use the Kprobes infrastructure (or SystemTap).
This will allow you to place "probes" (functions) at any point(s) within the kernel, using a kernel module.
Doing similar stuff by modifying the sys_call_table is now prevented (it's read-only) & is considered a dirty hack! Kprobes/Jprobes/etc are a "clean" way to do so..Also, the documentation and samples provided in the kernel source tree is excellent (look under the kernel src tree- Documentation/kprobes.txt).
The problem is caused due to the fact that sys_call_table is read only. In order to avoid the error, before manipulating the sys_call_table, you have to make it writable as well. The kernel provides a function to achieve it. And that function is given as set_mem_rw().
Just add the below code snippet before manipulating the sys_call_table
set_mem_rw((long unsigned int)sys_call_table,1);
In the exit function of the kernel module,please do not forget to revert back the sys_call_table back to read only.It can be achieved as below.
set_mem_ro((long unsigned int)sys_call_table,1);
First, you need to determine the location of sys_call_table. See here.
Before writing into the just located system table, you have to make its memory pages writable. For that check here and if that doesn't work, try this.
Use LSM infrustructure.
Look at LSM hooks path_mkdir or inode_mkdir for details. One question that needs to be solved is how to register your own LSM module while the system don't allow it explicitly. See the answer for details here:
How can I implement my own hook function with LSM?

Assembly inline C for getchar without echo

I'm trying to use the assembly inline code in C with gcc, to use the interrupt 21 with ah = 07h to make a getchar without echo. This is my code(the main):
...
int main(int argc, char *argv[])
{
int t, x, y;
char input;
asm(
"movb $0x01, %%ah\n\t"
"int $0x21\n\t"
"movb %%al, %0"
: "=r" (input)
);
printf("Character: %c\n", input);
return 0;
}
...
But it doesn't work, it compiles successfully but it doesn't do anything.
First of all you mixed an AT&T syntax with DOS int. so here are answers for each platform:
1.DOS: http://msdn.microsoft.com/en-us/library/5f7adz6y(v=vs.71).aspx
__asm mov ah,01
__asm int 21
Now al contains the read byte. As explained in here.
If you want to pass al to the char input use the right offset to stack pointer esp - <the offset> to reach the address of input and set to it the read value by calling mov byte [esp-offset], al.
2.LINUX:
The way you write the assembly is AT&T style so please check this out.
static inline
unsigned read_cr0( void )
{
unsigned val;
asm volatile( "mov %%cr0, %0"
: "=r"(val) );
return val;
}
From the informations you give, it seems that you are programming on a platform different from DOS. Interrupt 21 only works on DOS. For linux, have a look at the libraries ncurses and readline for advanced terminal tricks. If you want to do something more low-level, you might also be interested in the ANSI escape sequences. They give you a way to interact with the terminal.
Instead of using inline assembler, which as others have pointed out is DOS-specific, why don't you just set your terminal to disable echo? See this answer to another question for details on how to do so.

Resources