I am doing an exercise for a class to hook some system calls on a running kernel using a linux kernel module and using my new_sys_call() in place of the old one. I am developing on CentOS 7 and using a stock kernel-3.10.0-862.3.2. I was able to successfully hook execve and I can access parameter values but I cannot seem to access the rename syscall parameter values. I realize this is probably not a practical real world approach but I am trying to learn more about kernel development and how system calls work.
Here's an example of the hooking method definitions:
/*
Original Syscall Prototype
*/
asmlinkage long (*orig_sys_chdir_fn)(const char __user *filename);
/*
new syscall
*/
asmlinkage long new_sys_chdir(const char __user *filename) {
// do stuff
return orig_sys_chdir_fn(filename);
}
We obtain the stub chdir address with this code:
orig_stub_chdir_addr = ((unsigned long *)(sys_call_table_addr))[__NR_chdir];
Thread 357 hit Breakpoint 3, new_sys_rename (oldname=0xffffff9c <error: Cannot access memory at address 0xffffff9c>,
newname=0xffffff9c <error: Cannot access memory at address 0xffffff9c>) at /home/ulys/syshooks/kmod/sysrename.c:19
19 asmlinkage long new_sys_rename(const char __user *oldname, const char __user *newname) {
(gdb) info registers
rax 0xffffffff8122dbd0 -2128421936
rbx 0x0 0
rcx 0x7ffd0faf9480 140724866618496
rdx 0xffffff9c 4294967196
rsi 0xffffff9c 4294967196
rdi 0xffffff9c 4294967196
rbp 0xffff88004183bf48 0xffff88004183bf48
rsp 0xffff88004183bf40 0xffff88004183bf40
r8 0x0 0
r9 0x1 1
r10 0x7ffd0faf7320 140724866609952
r11 0x202 514
r12 0x0 0
r13 0x0 0
r14 0x0 0
r15 0x0 0
rip 0xffffffffc0540b20 0xffffffffc0540b20 <new_sys_rename>
eflags 0x10246 [ PF ZF IF RF ]
cs 0x10 16
ss 0x18 24
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0xb 11
(gdb) info stack
#0 new_sys_rename (oldname=0xffffff9c <error: Cannot access memory at address 0xffffff9c>,
newname=0xffffff9c <error: Cannot access memory at address 0xffffff9c>) at /home/ulys/syshooks/kmod/sysrename.c:19
#1 0xffffffff8122dbee in gather_surplus_pages (delta=-2123237509, h=0x0 <irq_stack_union>) at mm/hugetlb.c:1764
#2 hugetlb_acct_memory (h=0x0 <irq_stack_union>, delta=-2123237521) at mm/hugetlb.c:3149
#3 0xffffffff8171f82f in inet_netconf_fill_devconf (skb=0xffffffff8171f77b <inet_netconf_fill_devconf+123>,
ifindex=<optimized out>, devconf=<optimized out>, portid=<optimized out>, seq=<optimized out>, flags=<optimized out>,
type=<error reading variable: Cannot access memory at address 0x10>, event=80) at net/ipv4/devinet.c:1786
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
(gdb) x/s 0x7ffd0faf9480
0x7ffd0faf9480: "/tmp/test2"
You can see the bogus addresses at 0xffffff9c which cannot be read by copy_from_user or used by anything in the new_sys_rename function. You can see that the newname is in the register rcx but I can't locate oldname. I have noticed this on several different filename based syscalls such as chmod and chdir as well.
On chdir, I receive similar results except I can't find filename in any register.
Thread 304 hit Breakpoint 1, new_sys_chdir (
filename=0xffffff9c <error: Cannot access memory at address 0xffffff9c>)
at /home/ulys/syshooks/kmod/syschdir.c:17
17 asmlinkage long new_sys_chdir(const char __user *filename) {
(gdb) info registers
rax 0x0 0
rbx 0x0 0
rcx 0xffff880055d47f18 -131939955343592
rdx 0x3 3
rsi 0x3 3
rdi 0xffffff9c 4294967196
rbp 0xffff880055d47f48 0xffff880055d47f48
rsp 0xffff880055d47f10 0xffff880055d47f10
r8 0xc919d0 13179344
r9 0xcba2d0 13345488
r10 0x7f7147cfd030 140124512833584
r11 0x246 582
r12 0x3 3
r13 0xc8f320 13169440
r14 0x0 0
r15 0x0 0
rip 0xffffffffc0561000 0xffffffffc0561000 <new_sys_chdir>
eflags 0x10246 [ PF ZF IF RF ]
cs 0x10 16
ss 0x18 24
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0xb 11
(gdb) x/s 0xffff880055d47f18
0xffff880055d47f18: "o\367q\201\377\377\377\377{\367q\201\377\377\377\377\225\"", <incomplete sequence \356>
(gdb) x/s 0xc919d0
0xc919d0: " "
(gdb) x/s 0xc919d0
0xc919d0: " "
(gdb) x/s 0x7f7147cfd030
0x7f7147cfd030: "f\017s\372\005f\017t\321f\017\370\320fD\017\327\312\323\352A\323\351D)\312\017\205\v\004"
(gdb) info stack
#0 new_sys_chdir (filename=0xffffff9c <error: Cannot access memory at address 0xffffff9c>)
at /home/ulys/syshooks/kmod/syschdir.c:17
#1 0xffffffff81218b3e in move_page_tables (vma=<optimized out>, old_addr=3, new_vma=<optimized out>,
new_addr=18446744071586314095, len=<optimized out>, need_rmap_locks=<optimized out>) at mm/mremap.c:187
#2 0xffffffff8171f82f in inet_netconf_fill_devconf (skb=0xffffffff8171f77b <inet_netconf_fill_devconf+123>,
ifindex=<optimized out>, devconf=<optimized out>, portid=<optimized out>, seq=<optimized out>, flags=<optimized out>,
type=<error reading variable: Cannot access memory at address 0x10>, event=80) at net/ipv4/devinet.c:1786
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
It appears to work just fine on execve. Here you can see similar output but I have no problems accessing any of execve's filename or argv strings.
Thread 335 hit Breakpoint 2, new_sys_execve (filename=0x55c85e0d7af0 "/usr/libexec/postfix/pickup", argv=0x55c85e0d3d00,
envp=0x55c85e0d3d00) at /home/ulys/syshooks/kmod/sysexecve.c:21
21 const char __user * const __user * envp) {
(gdb) info registers
rax 0xffffffff8171fd80 -2123235968
rbx 0x0 0
rcx 0xffffffff 4294967295
rdx 0x55c85e0d3d00 94319059746048
rsi 0x55c85e0d3d00 94319059746048
rdi 0x55c85e0d7af0 94319059761904
rbp 0x0 0x0 <irq_stack_union>
rsp 0xffff88005323ff50 0xffff88005323ff50
r8 0x30 48
r9 0x0 0
r10 0xffffffff 4294967295
r11 0x206 518
r12 0x0 0
r13 0x0 0
r14 0x0 0
r15 0x0 0
rip 0xffffffffc053f880 0xffffffffc053f880 <new_sys_execve>
eflags 0x10282 [ SF IF RF ]
cs 0x10 16
ss 0x18 24
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0xb 11
(gdb) info stack
#0 new_sys_execve (filename=0x55c85e0d7af0 "/usr/libexec/postfix/pickup", argv=0x55c85e0d3d00, envp=0x55c85e0d3d00)
at /home/ulys/syshooks/kmod/sysexecve.c:21
#1 0xffffffff8171fdc8 in rtm_to_ifaddr (pprefered_lft=<synthetic pointer>, pvalid_lft=<synthetic pointer>,
nlh=0x0 <irq_stack_union>, net=0x0 <irq_stack_union>) at net/ipv4/devinet.c:801
#2 inet_rtm_newaddr (skb=0x0 <irq_stack_union>, nlh=0x0 <irq_stack_union>) at net/ipv4/devinet.c:854
Backtrace stopped: Cannot access memory at address 0x8
So why are some of these variables protected from kernel space? Where can they be found and is there another kernel function that can be called to get the values?
User contributions licensed under CC BY-SA 3.0