- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在做一个项目,我必须在 OSX (10.10.5) 上 Hook 80%-90% 的系统调用函数。我正在从内核扩展中执行此操作。因为我必须(取消) Hook 许多函数,所以我想将原始内核函数存储到一个函数指针数组中,这样我就可以快速查找数组以便在取消 Hook 时恢复原始函数。
int (*kern_open)(struct proc *, struct open_args *, int *);
int mon_open(struct proc *p, struct open_args *uap, int *retval) {
kern_open = sysent[SYS_open].sy_call;
sysent[SYS_open].sy_call = mon_open;
这是可行的,kern_open 函数用于存储在系统调用时调用的原始内核函数。 mon_open 是我的 Hook 函数。
我想要实现的是以下内容;这样在脱钩时,我就可以遍历 KernSysCall 数组并恢复函数。
// global array of function pointers that all have the same func def.
static int (*KernSysCall[SYS_MAXSYSCALL])(struct proc *, struct args *, int *);
KernSysCall[SYS_open] = sysent[SYS_open].sy_call;
sysent[SYS_open].sy_call = mon_open;
正在恢复:sysent[SYS_open].sy_call = KernSysCall[SYS_open];
但是,将原始内核函数存储在函数指针数组中会导致内核 panic 。由于 error: KDP_REATTACH failed
错误,我还无法附加 lldb。我希望有人知道导致内核 panic 的原因。
以下是内核崩溃的日志。
Anonymous UUID: 052D64D2-A43C-99F8-D221-B591991E54AF
Wed Nov 11 12:55:06 2015
*** Panic Report ***
panic(cpu 0 caller 0xffffff80093f0024): Kernel trap at 0x0000000000000000, type 14=page fault, registers:
CR0: 0x0000000080010033, CR2: 0x0000000000000000, CR3: 0x00000000769bb018, CR4: 0x00000000001606e0
RAX: 0x0000000000000000, RBX: 0xffffff80115e3fc0, RCX: 0x0000000000000001, RDX: 0xffffff80115e3fc0
RSP: 0xffffff8068dabaf8, RBP: 0xffffff8068dabf50, RSI: 0xffffff80115e3f80, RDI: 0xffffff8010059cf0
R8: 0xffffff7f8afaccdf, R9: 0xffffff8009ae2a18, R10: 0xffffff8009939740, R11: 0x0000000000000000
R12: 0xffffff8010059cf0, R13: 0x0000000000000005, R14: 0xffffff80115e3f80, R15: 0xffffff801188b480
RFL: 0x0000000000010282, RIP: 0x0000000000000000, CS: 0x0000000000000008, SS: 0x0000000000000010
Fault CR2: 0x0000000000000000, Error code: 0x0000000000000010, Fault CPU: 0x0 VMM
Backtrace (CPU 0), Frame : Return Address
0xffffff8068dab790 : 0xffffff80092e4ed1 mach_kernel : _panic + 0xd1
0xffffff8068dab810 : 0xffffff80093f0024 mach_kernel : _kernel_trap + 0x664
0xffffff8068dab9e0 : 0xffffff800940de53 mach_kernel : trap_from_kernel + 0x26
0xffffff8068daba00 : 0x0
0xffffff8068dabf50 : 0xffffff800982c0c1 mach_kernel : _unix_syscall64 + 0x2f1
0xffffff8068dabfb0 : 0xffffff800940e656 mach_kernel : _hndl_unix_scall64 + 0x16
BSD process name corresponding to current thread: xpcproxy
Boot args: debug=0x14e kext-dev-mode=1 -v keepsyms=1 kmem=1
Mac OS version:
14F27
Kernel version:
Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 PDT 2015; root:xnu-2782.40.9~1/DEVELOPMENT_X86_64
Kernel UUID: C75BDFDD-9F27-3694-BB80-73CF991C13D8
Kernel slide: 0x0000000009000000
Kernel text base: 0xffffff8009200000
__HIB text base: 0xffffff8009100000
System model name: VMware7,1 (Mac-66F35F19FE2A0D05)
System uptime in nanoseconds: 251264993940
last loaded kext at 249789197520: my.kext 1 (addr 0xffffff7f8afa9000, size 57344)
last unloaded kext at 116769666233: com.apple.driver.AppleFileSystemDriver 3.0.1 (addr 0xffffff7f8aed3000, size 16384)
loaded kexts:
my.kext 1
[more kexts here]
在请求中,mon_open()的代码:
int
mon_open(struct proc *p, struct open_args *uap, int *r) {
int error;
char processname[MAXCOMLEN+1];
char intercepted_path[MAXPATHLEN];
pid_t pid = proc_pid(p);
proc_name(pid, processname, sizeof(processname));
size_t dummy = 0;
error = copyinstr((void *)uap->path, (void *)intercepted_path, MAXPATHLEN, &dummy);
if (!error) {
printf("[MYKEXT] open called with path: %s, PID: %d, processname: %s\n", intercepted_path, pid, processname);
}
return kern_open(p, uap, r);
}
非常感谢您!
最佳答案
panic 日志中的 0x0 行表示正在调用 NULL 函数指针(在这种情况下更有可能),或者您破坏了堆栈并用 NULL 覆盖了返回指针。你确定你不是在“恢复”你一开始就没有 Hook 的系统调用吗?
要让 lldb 与虚拟机一起工作,要求取决于不同的虚拟化环境。使用 VMWare Fusion 它应该可以正常工作,假设您使用的是“仅主机网络”或桥接模式。上次我尝试使用 VirtualBox 时,它只适用于 Virtio 网络设备,而我根本无法在 Parallels 上使用它,但那是几年前的事了。
请注意,如果您将串行端口添加到您的 VM,写入文本文件,您可以使用 kprintf()
登录到该文件 - 这可能对您有帮助,因为您可以打印出您的指针 Hook 和脱钩时的值。
关于c - 将 SYSCALL 函数存储在函数指针数组中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33646125/
我刚接触 C 语言几周,所以对它还很陌生。 我见过这样的事情 * (variable-name) = -* (variable-name) 在讲义中,但它到底会做什么?它会否定所指向的值吗? 最佳答案
我有一个指向内存地址的void 指针。然后,我做 int 指针 = void 指针 float 指针 = void 指针 然后,取消引用它们以获取值。 { int x = 25; vo
我正在与计算机控制的泵进行一些串行端口通信,我用来通信的 createfile 函数需要将 com 端口名称解析为 wchar_t 指针。 我也在使用 QT 创建一个表单并获取 com 端口名称作为
#include "stdio.h" #include "malloc.h" int main() { char*x=(char*)malloc(1024); *(x+2)=3; --
#include #include main() { int an_int; void *void_pointer = &an_int; double *double_ptr = void
对于每个时间步长,我都有一个二维矩阵 a[ix][iz],ix 从 0 到 nx-1 和 iz 从 0 到 nz-1。 为了组装所有时间步长的矩阵,我定义了一个长度为 nx*nz*nt 的 3D 指针
我有一个函数,它接受一个指向 char ** 的指针并用字符串填充它(我猜是一个字符串数组)。 *list_of_strings* 在函数内部分配内存。 char * *list_of_strings
我试图了解当涉及到字符和字符串时,内存分配是如何工作的。 我知道声明的数组的名称就像指向数组第一个元素的指针,但该数组将驻留在内存的堆栈中。 另一方面,当我们想要使用内存堆时,我们使用 malloc,
我有一个 C 语言的 .DLL 文件。该 DLL 中所有函数所需的主要结构具有以下形式。 typedef struct { char *snsAccessID; char *
我得到了以下数组: let arr = [ { children: [ { children: [], current: tru
#include int main(void) { int i; int *ptr = (int *) malloc(5 * sizeof(int)); for (i=0;
我正在编写一个程序,它接受一个三位数整数并将其分成两个整数。 224 将变为 220 和 4。 114 将变为 110 和 4。 基本上,您可以使用模数来完成。我写了我认为应该工作的东西,编译器一直说
好吧,我对 C++ 很陌生,我确定这个问题已经在某个地方得到了回答,而且也很简单,但我似乎找不到答案.... 我有一个自定义数组类,我将其用作练习来尝试了解其工作原理,其定义如下: 标题: class
1) this 指针与其他指针有何不同?据我了解,指针指向堆中的内存。如果有指向它们的指针,这是否意味着对象总是在堆中构造? 2)我们可以在 move 构造函数或 move 赋值中窃取this指针吗?
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: C : pointer to struct in the struct definition 在我的初学者类
我有两个指向指针的结构指针 typedef struct Square { ... ... }Square; Square **s1; //Representing 2D array of say,
变量在内存中是如何定位的?我有这个代码 int w=1; int x=1; int y=1; int z=1; int main(int argc, char** argv) { printf
#include #include main() { char *q[]={"black","white","red"}; printf("%s",*q+3); getch()
我在“C”类中有以下函数 class C { template void Func1(int x); template void Func2(int x); }; template void
我在64位linux下使用c++,编译器(g++)也是64位的。当我打印某个变量的地址时,例如一个整数,它应该打印一个 64 位整数,但实际上它打印了一个 48 位整数。 int i; cout <<
我是一名优秀的程序员,十分优秀!