【问题标题】:Kernel Development : Hooking Execve And Printing char *const argv[]内核开发:挂钩执行和打印 char *const argv[]
【发布时间】:2020-07-02 09:19:05
【问题描述】:

我正在尝试 HookExecve 并打印参数。我可以很好地打印文件名。如何在内核模式下打印 char *const argv[] 的参数?我需要能够获取它们的数量并能够打印它们。

所以如果我运行 ls -lah 。我应该在 argv ["ls", "-lah"] 中看到;我可以在用户空间中执行此操作,但是所有将信息从用户空间复制到内核空间的尝试似乎都会导致崩溃。

    char CharBuffer [255] = {'\0'};
    char Argz       [255] = {'\0'};

    asmlinkage int (*origional_execve)(const char *filename, char *const argv[], char *const envp[]);
    asmlinkage int HookExecve(const char *filename, char *const argv[], char *const envp[]) {
       unsigned int len     = sizeof(CharBuffer) / sizeof(CharBuffer[0]);
       unsigned int Argzlen = sizeof(Argz)       / sizeof(Argz[0]);

        copy_from_user(&CharBuffer , filename , len );
        //copy_from_user(Argz , argv[0] , sizeof(argv[0]) );     
        //strncpy_from_user(Argz, argv[0], len ); // Might break stuff
        printk( KERN_INFO "Executable Name %s \n", CharBuffer  );
        memset(CharBuffer, 0 , len);

      return (*origional_execve)(filename, argv, envp);
    }

【问题讨论】:

  • 请发布您希望代码执行的操作。
  • 我不确定我是否清楚,但我正在挂接 Linux 中的 execve 调用。我只想打印 argv 字符串。

标签: c unix linux-kernel hook rootkit


【解决方案1】:

sizeof(CharBuffer) / sizeof(CharBuffer[0])

。这只是sizeof(char*)/sizeof(char)

sizeof(Argz) / sizeof(Argz[0])

。这正好等于sizeof(char**)/sizeof(char*)

sizeof 是否为您提供数组中元素的数量。 sizeof 返回底层类型的大小。

要获取字符串的长度(即找到终止零字符之前的字符数),请使用strlenstrlen 返回 size_t 类型,sizeof 也是如此。

argv 数组以 sentinel value NULL 结尾。要打印char **argv 数组的内容,请迭代直到找到空值:

for (char *i = argv; *i != NULL; ++i) {
    printf("%s\n", *i);
}

或:

for (size_t i = 0; argv[i] != NULL; ++i) {
    printf("%s\n", argv[i]);
}

char 字符缓冲区 [255] = {'\0'}; &CharBuffer

虽然等于值,但&CharBuffer不是char*类型。 &CharBuffer 的类型为 char (*)[255] - 它是一个指向 255 个字符的数组的指针。启用编译器警告并解决它们 - 在内核中不要犯错误。只需使用CharBuffer 转换为char* 输入strcpy-likeish 函数。

你似乎有点想要:

char char_buffer[255] = {0};
// Note: Do not name variables similar, especially globals.
// The argc <-> argz <-> argv differ only in one char.
// and 2d array to hold arguments strings
char argz[255][255] = {0};
// the count of arguments
size_t argc = 0;

asmlinkage int (*origional_execve)(const char *filename, char *const argv[], char *const envp[]);
asmlinkage int HookExecve(const char *filename, char *const argv[], char *const envp[]) {

    if (strlen_user(filename) + 1 > sizeof(char_buffer)) {
         // TODO: no memory for filename
         return -1;
    }
    copy_from_user(char_buffer, filename, strlen_user(filename) + 1);

    size_t i = 0;
    for (i = 0; argv[i] != 0; ++i) {

         // note: argz has type `char (*)[255][255]`
         // so: sizeof(argz) = 255 * 255 * sizeof(char)
         // *argz has type `char (*)[255]`
         // so: sizeof(*argz) = 255 * 255 * sizeof(char)
         // so: sizeof(argz)/sizeof(*argz) = 255
         // This would NOT work if `argz` would be a `char**`...
         // if (i > sizeof(argz)/sizeof(*argz)) {
         // but there is ARRAY_SIZE macro that does the same
         if (i > ARRAY_SIZE(argz)) {
              // TODO: not enough indexes
              return -1;
         }

         // sizeof(argz[i]) = sizeof(char(*)[255]) = 
         //                 = 255 * sizeof(char) = 255
         if (strlen_user(argv[i]) + 1 > sizeof(argz[i])) {
              // TODO: no memory to copy
              return -1;
         }
         copy_from_user(argz[i], argv[i], strlen_user(argv[i]) + 1);
    }
    argc = i;

    printk( KERN_INFO "Executable Name %s \n", char_buffer);
    for (size_t i = 0; i < argc; ++i) {
        printk( KERN_INFO "arg[i] = %s\n", argz[i]);            
    }

    return (*origional_execve)(filename, argv, envp);
}

我没有测试代码,很可能它包含许多错误。更好地处理错误并且只使用动态分配并处理分配错误也会更好。

【讨论】:

  • Strlen 在参数上使用时由于某种原因会导致崩溃。我需要弄清楚如何使用这个严格的内核。
  • 您好,我认为链接已失效?
  • 对来自用户的缓冲区执行strlen_user
  • 这是我想发布的您想要发布的链接。 fsl.cs.sunysb.edu/kernel-api/re250.html
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-24
  • 2013-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-30
  • 2012-01-29
相关资源
最近更新 更多