Giter Club home page Giter Club logo

monks's People

Contributors

alexandernst avatar dandare100 avatar milabs avatar nache avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

monks's Issues

Academic project

Clearly indicate in the README that this module, while it could be used to actually do something productive, it's an academic project.

Use stub funcitons for the un/hook process

The current hook method will block the module's unloading till the last sleeping process issues a call to all the syscalls it used at some point of it's execution. Using stubs should fix the situation, as per comments in #17 .

Use NETLINK for kernel-user communication

NETLINK is the one efficient way to do the kernel-user communication while sending event information from the kernel. Don't use dmesg for that purposes as it slows system's performance at high load.

Readme: Activation

First of all: Thanks a lot. Pretty much what I just needed.

The Readme should be changed to:

echo 1 > /proc/procmon
echo 0 > /proc/procmon

for starting and stopping

Make kmod optional

fca2039 introduced some help code to load/unload/start/stop procmon's kernel module from the viewer itself. That code uses kmod (or libkmod).

That set of libraries/tools weren't present until very recent distro versions. In Ubuntu's case, that's 13.04.

Procmon's viewer should be patched in a way so that it's able to compile it even if kmod/libkmod is not availabe. If those aren't available, some menu options should be disabled.

Create wiki

Create wiki with details about:

  • - How Monks works. (create some gifs?)
  • - How new syscalls are hooked. (detailed instructions and sample code)
  • - How UI works.
  • - TODO list.

rmmod procmon.ko BUG?

for(; iter < __stop_syscalls; ++iter){
    procmon_info("Unloading syscall %s\n", iter->name);
    if(iter->counter && atomic_read(iter->counter) > 0){ 
        return 0;
    }else if(iter->counter && atomic_read(iter->counter) == 0){ 
        del(iter->counter);
    }   
}  

running it some time (one hour or more);
then rmmod it, You will found the syslog Increases indefinitely.

Check before hijack-ing

Check each sys_call before hijack-ing it, maybe something else hijack-ed it, in which case bad things will happen)

Rename procmon to avoid conflicts with MS

Microsoft has a similar tool with a similar name for Windows. Before the final release, you might want to find another name, otherwise MS will probably force you to. :)

Inserting of kernel module fails

[673032.890669] [monks] ================
[673032.890672] [monks] Starting monks
[673032.890921] [monks] Acquired NETLINK socket (29)
[673032.890929] [monks] Found syscall_table addr at 0xffffffff81a001c0
[673032.890944] [monks] syscall_table is NULL, quitting...
[673032.890947] sysctl table check failed: monks//syscalls No proc_handler
[673032.890952] sysctl table check failed: monks//syscalls bogus .mode 0555
[673032.890956] CPU: 4 PID: 95734 Comm: insmod Tainted: G OEL 4.4.0-70-generic #91-Ubuntu
[673032.890958] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/02/2015
[673032.890961] 0000000000000286 00000000205d0186 ffff880151c2fba0 ffffffff813f82b3
[673032.890963] ffffffff81e899a0 ffff880100cc9000 ffff880151c2fc00 ffffffff81288bea
[673032.890965] 0000000000000000 ffffffff811ed213 ffffffffc07e6180 0000000000000000
[673032.890967] Call Trace:
[673032.890983] [] dump_stack+0x63/0x90
[673032.890993] [] __register_sysctl_table+0x29a/0x570
[673032.891005] [] ? kmem_cache_alloc_trace+0x183/0x1f0
[673032.891008] [] __register_sysctl_paths+0x1cd/0x1f0
[673032.891010] [] ? 0xffffffffc0760000
[673032.891012] [] register_sysctl_table+0x1f/0x30
[673032.891017] [] register_monks_controls+0x53/0x70 [monks]
[673032.891021] [] hook_init+0x71/0x1000 [monks]
[673032.891028] [] do_one_initcall+0xb3/0x200
[673032.891031] [] ? kmem_cache_alloc_trace+0x183/0x1f0
[673032.891037] [] do_init_module+0x5f/0x1cf
[673032.891043] [] load_module+0x166f/0x1c10
[673032.891046] [] ? __symbol_put+0x60/0x60
[673032.891051] [] ? kernel_read+0x50/0x80
[673032.891054] [] SYSC_finit_module+0xb4/0xe0
[673032.891056] [] SyS_finit_module+0xe/0x10
[673032.891066] [] entry_SYSCALL_64_fastpath+0x16/0x71
[673032.891068] [monks] Error creating fs control interface in /proc/sys/monks/

Multi-viewer support

By suggestions in #19, think about if Procmon should have the possibility to support multiple client/viewers.

Logging to file

Procmon should be abe to log all the data to a file. Maybe something like:

-L - Log everything to a file.
-l - Log just what's visible after applying all the filters to a file.

Detect which process(es) is(are) blocking procmon's unload

When a hijacked syscall is called, it should store the PID of the process which called it, and when it's done, it should remove that PID.
This way we'll be able to tell which process(es) is(are) blocking procmon's unloading process.

EDIT: Depends on #31

Stop sending empty messages to kernel module

Right now net_init() sends an empty message to the kernel module so the module can know to which PID it should send messages. Replace this with something like the autonegotiation port (sysctl).

This will make the code a little bit cleaner.

Up/down keys are buggy

Moving up/down in the list of hijacked syscalls is kind of buggy. It won't re-render, it won't go up/down and then it will skip a few lines at once, etc...

Move from NetLink to Mmap

I'd like to move away from the entire NetLink madness to mmap. I think procmon will gain in both speed and stability.

Anyways, I have been looking at the link you gave me ( http://people.ee.ethz.ch/~arkeller/linux/kernel_user_space_howto.html#ss8.1 ) here http://stackoverflow.com/questions/19233717/sharing-or-sending-data-from-lkm-to-userland and it seems as I'll have to face two big problems.

The first one is how to notify userland that there is more data availabe. I kept reading the link and I found I could use http://people.ee.ethz.ch/~arkeller/linux/kernel_user_space_howto.html#ss6.1 to notify userland when it should read more data.

But then, here it goes the second big problem: mmap is just writing to a buffer, like a file. Right now I'm saving and sending each message (containing name of program, pid, operation, details, etc... the syscall_info struct) like a piece of data, encoded and decoded with the de/serialize.c files. Each message looks like:

(size_t msg_size)(char msg_data)

So it's really easy to just read the msg_size from there, and then read that size and cast it to a syscall_info struct.

The problem is that I won't be able to do the same thing when I'm doing mmap, as everything will be written continuosly.
Or will I?

Anyways, I'm open to any suggestions about this @milabs :)

Check if syscall table is faked

Procmon should check if the syscall table is already patched by something else (or even by a remaining stub from procmon itself, as of #31). If the syscall table is patched, procmon should do nothing.

syscalls blacklist

It's impossible to hook several system calls by just replacing correspinding sys_call_table values. So, we need to blacklist that numbers which can be found by the command:

cat /proc/kallsyms | grep -e 'T stub'

My x86_64 system shows the result:

0000000000000000 T stub_clone
0000000000000000 T stub_fork
0000000000000000 T stub_vfork
0000000000000000 T stub_sigaltstack
0000000000000000 T stub_iopl
0000000000000000 T stub_execve
0000000000000000 T stub_rt_sigreturn
0000000000000000 T stub32_rt_sigreturn
0000000000000000 T stub32_sigreturn
0000000000000000 T stub32_sigaltstack
0000000000000000 T stub32_execve
0000000000000000 T stub32_fork
0000000000000000 T stub32_clone
0000000000000000 T stub32_vfork
0000000000000000 T stub32_iopl
  1. What's about x86_32?
  2. Do we needed to find the proper way to handling these are syscalls?

Free NETLINK slot number autonegotiation

Kernel has about 32 available netlink slots. Some of them may be used by another modules. I'll suggest to iterate all the slots from the last to the first and try to register netlink socket for each number. First number that passed can be exported by proc or sysctl for our application. What do you think?

Clear 32/86/64 mess

All over the code there are things like ia32 (referring to 32 emulation), 32 (referring to x86) and <nothing> (referring to x86 or x64). I'd really like to clear all this mess before v0.1

Data get's invalidated

Currently the real syscall is ran and then the fake syscall is ran. In the time between the real and the fake syscalls execution, data can get invalidated. A good example of that is the __NR_read / __NR_write interceptors and the __NR_close interceptor.

The first two can get the path of the fd, while the third one can't because the fd doesn't exist anymore by the time the fake syscall is called.

@milabs Any idea how to trick that? It seems hard :/

Remove (UN)HOOK macros, simplifying code

I'm trying to remove the (UN)HOOK macros and instead hook/unhook all the syscalls iterating over a section with the relevant data.

I made a patch that should work, but it's failing for some strange reason.

This is the patch:

diff --git a/procmon_kmodule/hookfns.c b/procmon_kmodule/hookfns.c
index 2984afd..5faec86 100644
--- a/procmon_kmodule/hookfns.c
+++ b/procmon_kmodule/hookfns.c
@@ -10,13 +10,25 @@
 asm(".section .counters, \"aw\""); //set section allocatable and writable

 void hook_calls(void){
+
+   counter_info_t *iter;
+
    if(get_sct() && set_sct_rw()){

-/* __NR_read / __NR32_read */
-       HOOK(read);
-#ifdef __NR32_read
-       HOOK_IA32(read);
-#endif
+       iter = __start_counters;
+       for(; iter < __stop_counters; ++iter){
+           DEBUG(KERN_INFO "ITER DIR %p\n", iter);
+           if(iter->is32){
+               DEBUG(KERN_INFO "HOOK_IA32 %s\n", iter->name);
+               iter->rf = (void *)ia32_sys_call_table[iter->__NR_];
+               ia32_sys_call_table[iter->__NR_] = (void *)iter->ff;
+           }else{
+               DEBUG(KERN_INFO "HOOK %s\n", iter->name);
+               iter->rf = (void *)sys_call_table[iter->__NR_];
+               sys_call_table[iter->__NR_] = (void *)iter->ff;
+
+           }
+       }

        set_sct_ro();
    }
@@ -33,13 +45,21 @@ void hook_calls(void){
 \*****************************************************************************/

 void unhook_calls(void){
+
+   counter_info_t *iter;
+
    if(get_sct() && set_sct_rw()){

-/* __NR_read / __NR_read32 */
-       UNHOOK(read);
-#ifdef __NR32_read
-       UNHOOK_IA32(read);
-#endif
+       iter = __start_counters;
+       for(; iter < __stop_counters; ++iter){
+           if(iter->is32){
+               DEBUG(KERN_INFO "UNHOOK_IA32 %s\n", iter->name);
+               ia32_sys_call_table[iter->__NR_] = (void *)iter->rf;
+           }else{
+               DEBUG(KERN_INFO "UNHOOK %s\n", iter->name);
+               sys_call_table[iter->__NR_] = (void *)iter->rf;
+           }
+       }

        set_sct_ro();
    }
diff --git a/procmon_kmodule/hookfns.h b/procmon_kmodule/hookfns.h
index 79c4ecb..d61dadc 100644
--- a/procmon_kmodule/hookfns.h
+++ b/procmon_kmodule/hookfns.h
@@ -6,6 +6,10 @@
 typedef struct counter_info {
    atomic_t counter;
    char *name;
+   int is32;
+   int __NR_;
+   void *ff;
+   void *rf;
 } __attribute__((packed)) counter_info_t;

 extern counter_info_t __start_counters[];
@@ -19,20 +23,14 @@ extern counter_info_t __stop_counters[];
 | hooked_sys_##F = FAKE FUNCTION as in the function which we'll be using to fake __NR_##F |
 \*****************************************************************************************/

-#define HOOK(F)                                                    \
-   DEBUG(KERN_INFO "HOOK __NR_" #F "\n");                      \
-   real_sys_##F = (void *)sys_call_table[__NR_##F];            \
-   sys_call_table[__NR_##F] = (void *)hooked_sys_##F;
-
-#define UNHOOK(F)                                              \
-   DEBUG(KERN_INFO "UNHOOK __NR_" #F "\n");                    \
-   sys_call_table[__NR_##F] = (void *)real_sys_##F;
-
 #define REGISTER_SYSCALL(F)                                        \
    static counter_info_t __counter_info___NR_##F               \
-   __attribute((unused, section(".counters"))) = {             \
+   __attribute((section(".counters"))) = {                     \
        .counter = ATOMIC_INIT(0),                              \
        .name = "__NR_" #F,                                     \
+       .is32 = 0,                                              \
+       .__NR_ = __NR_##F,                                      \
+       .ff = hooked_sys_##F,                                   \
    };

 #define __INCR(F)  \
@@ -43,20 +41,14 @@ extern counter_info_t __stop_counters[];

 #ifdef CONFIG_IA32_EMULATION

-#define HOOK_IA32(F)                                           \
-   DEBUG(KERN_INFO "HOOK_IA32 __NR32_" #F "\n");               \
-   real_sys32_##F = (void *)ia32_sys_call_table[__NR32_##F];   \
-   ia32_sys_call_table[__NR32_##F] = (void *)hooked_sys32_##F;
-
-#define UNHOOK_IA32(F)                                         \
-   DEBUG(KERN_INFO "UNHOOK_IA32 __NR32_" #F "\n");             \
-   ia32_sys_call_table[__NR32_##F] = (void *)real_sys32_##F;
-
 #define REGISTER_SYSCALL32(F)                                  \
    static counter_info_t __counter_info___NR32_##F             \
-   __attribute((unused, section(".counters"))) = {             \
+   __attribute((section(".counters"))) = {                     \
        .counter = ATOMIC_INIT(0),                              \
-       .name = "__NR32_" #F "_32",                             \
+       .name = "__NR32_" #F,                                   \
+       .is32 = 1,                                              \
+       .__NR_ = __NR32_##F,                                    \
+       .ff = hooked_sys32_##F,                                 \
    };

 #define __INCR32(F)    \

It seems that the loop iterates 3 times but there are only 2 structs saved in the section. I have noticed that if I remove the __NR_ element from the struct, the loop iterates only 2 times.

@milabs Any ideas?

Anti-rootkit

The way Procmon works makes it possible to use it as a rootkit detector. It shouldn't be hard to implement it, so why not?
Some discussion about this occurred in #37

Make filtering possible in the module side

Filtering data in the module instead of in the client will be faster (as no data will be sent anywhere, copied, pushed, etc...).

Probably the best way is to create some kind of macro and a sysctl interface for each hijacked syscall. Example: sysctl procmon.read=1 or sysctl procmon.write32=0

Kernel freezes when calling hook/unhook

Repeated calls on hook and unhook cause a kernel (at all levels) freeze. Machine gets completely frozen and the only way to gain access back to it is to restart physically the machine.

Add support for filters.

Add support for filtering all messages based on name, path, pid, etc...

Main features are:

  • Starts with
  • Ends with
  • Contains
  • Does not contain
  • Is equal
  • Is not equal

Maybe we're missing messages

Check if the number of intercepted and sent syscalls from the module is equal to the number of messages that the viewer received.
I think the viewer is missing something.

Adding hooks for other system calls

I just spent some time trying to figure out how to also hook the write system call. I did not manage to do it. Do you plan to provide some generic functions/macros to hook any kind of system call? I could keep trying implementing this, but maybe you are already up to it..

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.