LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1655|回复: 6

求助:关于获取系统调用发生时程序若干信息的问题

[复制链接]
发表于 2006-1-27 23:41:01 | 显示全部楼层 |阅读模式
本人因为论文需要刚刚学习内核不久,需要设计一个内核模块,通过此模块获得系统调用发生时若干相关信息。包括:进行系统调用的进程标示、系统调用号、系统调用参数、该系统调用发生时的指令指针、系统调用发生时进程内函数调用的情况。
对2.6.10的内核,参考别人的代码,通过修改int0x80和sysenter发生时(对int0x80修改IDT的中断地址,对sysenter修改SYSENTER_EIP_MSR)的处理函数,在原本的处理函数前加入了handle。
目前分析的结果如下:
进程标示---通过task_struct获得
系统调用号---eax
参数---ebx、ecx、edx、esi、edi
发生系统调用时的指令指针----eip??
进程内函数调用情况----ret包含在进程的用户空间栈中,通过mm_struct还是ss?
但是有如下问题:
1。此模块获得的eip是否是系统调用发生时的ip?如果不是,如何获得?
2。用户空间栈中包含的信息除了ret还有参数,局部变量等等,如何能获得此时栈中所有的ret,以此来获得进程函数调用关系?
3。通过什么获得用户空间栈地址?ss是否在陷入内核空间时指向了进程内核栈?

btw:看到别的论文中有了实验结果,却不知道如何实现,只知道方法可行,请各位帮帮忙。
发表于 2006-1-28 15:59:01 | 显示全部楼层
Post by nighthuman

1。此模块获得的eip是否是系统调用发生时的ip?如果不是,如何获得?
2。用户空间栈中包含的信息除了ret还有参数,局部变量等等,如何能获得此时栈中所有的ret,以此来获得进程函数调用关系?
3。通过什么获得用户空间栈地址?ss是否在陷入内核空间时指向了进程内核栈?

在内核系统调用时可用 (struct pt_regs *pt) 参数获取用户态的寄存器参数,如问题1的答案就是 pt->eip ,还有 pt->ss, pt->esp 中是用户态的栈区,使用 copy_from_user 复制过来就可以分析用户栈的内容,诸如此类,

这两天我在外面上网,手上没有可用的内核,部分有误请见谅。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-1-28 19:59:46 | 显示全部楼层

关于系统调用继续问题

谢谢!我查了一下,不过又有了几个问题:
1)struct pt_regs *pt直接放在处理函数的参数里就可以用pt.eip、pt.esp等吗?
2)这个结构在陷入内核以后由谁初始化?
3)通过ss和esp,获得用户空间栈以后,如何得到所有的ret列表还是不知道怎么办。
4)sysenter时用户态的EIP和ESP什么时候压入内核栈的?在处理函数之前如何访问压入
栈的用户态EIP和ESP等等?
5)copy_from_user的参数size,如何转换pt.esp使其能作为参数size?
回复 支持 反对

使用道具 举报

发表于 2006-2-10 16:30:57 | 显示全部楼层
lu wei wrote:
> 1)struct pt_regs *pt直接放在处理函数的参数里就可以用pt.eip、pt.esp等吗?不需要初始化?
系统调用是由 int 0x80 进入内核空间,安装的中断处理器是 system_call (arch/i386/kernel/entry.S),此汇编函数中的宏段落 SAVE_ALL 将所有用户空间寄存器值压入内核栈上,后续的 call *sys_call_table(,%eax,4) 过程中,内核栈上的参数排列刚好与 struct pt_regs 形成一致,于是所有真正的系统调用函数(sys_ 形状的函数)都可以认为栈上有一个 struct pt_regs

  1. /* from arch/i386/kernel/entry.S */
  2. #define SAVE_ALL \
  3.         cld; \
  4.         pushl %es; \
  5.         pushl %ds; \
  6.         pushl %eax; \
  7.         pushl %ebp; \
  8.         pushl %edi; \
  9.         pushl %esi; \
  10.         pushl %edx; \
  11.         pushl %ecx; \
  12.         pushl %ebx; \
  13.         movl $(__USER_DS), %edx; \
  14.         movl %edx, %ds; \
  15.         movl %edx, %es;
  16. ...
  17.         # system call handler stub
  18. ENTRY(system_call)
  19.         pushl %eax                      # save orig_eax
  20.         SAVE_ALL
  21.         GET_THREAD_INFO(%ebp)
  22.                                         # system call tracing in operation / emulation
  23.         /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
  24.         testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
  25.         jnz syscall_trace_entry
  26.         cmpl $(nr_syscalls), %eax
  27.         jae syscall_badsys
  28. syscall_call:
  29.         call *sys_call_table(,%eax,4)
  30.         movl %eax,EAX(%esp)             # store the return value
  31. syscall_exit:
  32.         cli                             # make sure we don't miss an interrupt
  33.                                         # setting need_resched or sigpending
  34.                                         # between sampling and the iret
  35.         movl TI_flags(%ebp), %ecx
  36.         testw $_TIF_ALLWORK_MASK, %cx   # current->work
  37.         jne syscall_exit_work

  38. restore_all:
  39.         movl EFLAGS(%esp), %eax         # mix EFLAGS, SS and CS
  40.         # Warning: OLDSS(%esp) contains the wrong/random values if we
  41.         # are returning to the kernel.
  42.         # See comments in process.c:copy_thread() for details.
  43.         movb OLDSS(%esp), %ah
  44.         movb CS(%esp), %al
  45.         andl $(VM_MASK | (4 << 8) | 3), %eax
  46.         cmpl $((4 << 8) | 3), %eax
  47.         je ldt_ss                       # returning to user-space with LDT SS
  48. restore_nocheck:
  49.         RESTORE_REGS
  50.         addl $4, %esp
  51. 1:      iret
  52. ...

  53. /* from include/asm-i386/ptrace.h */
  54. struct pt_regs {
  55.         long ebx;
  56.         long ecx;
  57.         long edx;
  58.         long esi;
  59.         long edi;
  60.         long ebp;
  61.         long eax;
  62.         int  xds;
  63.         int  xes;
  64.         long orig_eax;
  65.         long eip;
  66.         int  xcs;
  67.         long eflags;
  68.         long esp;
  69.         int  xss;
  70. };
复制代码


> 2)2.6内核中,使用sysenter的系统调用,用户态的EIP和ESP什么时候压入内核栈的?如何访问压入栈的用户态EIP和ESP等等?
用户态的 eip esp 是由 Intel 硬件特性压入内核栈的, Intel 出版的四本书上写过当中断,调用或是任务门等引起跨特权级的指令转移时,从低级到高级的转移过程中,硬件依次压入栈:ss, esp, eflags, cs, ip, 而普通的 far call 只压入 cs, eip,用户态EIP和ESP等等同样从 struct pt_regs 访问。

  1. /* from arch/i386/kernel/entry.S */
  2.         # sysenter call handler stub
  3. ENTRY(sysenter_entry)
  4.         movl TSS_sysenter_esp0(%esp),%esp
  5. sysenter_past_esp:
  6.         sti
  7.         pushl $(__USER_DS)
  8.         pushl %ebp
  9.         pushfl
  10.         pushl $(__USER_CS)
  11.         pushl $SYSENTER_RETURN
复制代码


> 3)copy_from_user拷贝栈的时候,起始地址和结束地址是什么(x86中好像不是ss —>ss+sp)?
copy_from_user 时只知道起始地址是 esp ,结束地址就要从栈上已取得的数据去分析了,一般来说用户态程序进入 main 函数,再进入系统调用,用户态栈上至少有几十个 Bytes 的内容,可以先 copy 一段,然后根据已 copy 的内容去分析离栈顶大概还有多远,当然也可
回复 支持 反对

使用道具 举报

发表于 2006-12-26 17:04:29 | 显示全部楼层

请教

第一次登录论坛,请大家多多指教,我有一问题,如果在linux下劫获了某一函数所调用的一系统调用,如何获得此系统调用的返回地址
回复 支持 反对

使用道具 举报

发表于 2006-12-26 17:09:35 | 显示全部楼层
请问你是如何在内核中实现劫获系统调用时,读取到此时的eip,我想我和你看的论文很相近啊,可是我不知道是怎么实现的
回复 支持 反对

使用道具 举报

发表于 2006-12-26 17:13:49 | 显示全部楼层
麻烦哪位高人能支点一下,不胜感激
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表