如何在 linux 内核中获取 ELF 二进制文件的哈希值?
How to take the hash of ELF binary in linux kernel?
我正在内核内部实现二进制证明。我正在使用 kernel_read_from_file()
函数读取文件。函数定义如下:
int kernel_read_file_from_path(const char *path, void **buf, loff_t *size,
loff_t max_size, enum kernel_read_file_id id)
函数正在buf
中存储文件内容。当我读取带有 .c
或 .h
扩展名的文件时,代码工作正常。但是对于 ELF 二进制文件:
Value stored in buf = ELF
我在这里错过了什么?我如何从内核中读取 ELF 二进制文件?
相关代码如下:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/file.h>
// #include "sha256.h"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Robert W. Oliver II");
MODULE_DESCRIPTION("A simple example Linux module.");
MODULE_VERSION("0.01");
static int __init lkm_example_init(void)
{
void *data;
loff_t size;
int ret;
char path1[50] = "/etc/bash.bashrc";
char path2[50] = "/bin/sh";
ret = kernel_read_file_from_path(path1, &data, &size, 0, READING_POLICY);
printk(KERN_INFO "Hello, World!\n");
printk(KERN_INFO "%lld\n", size);
printk(KERN_INFO "%s", (char*)data);
ret = kernel_read_file_from_path(path2, &data, &size, 0, READING_POLICY);
printk(KERN_INFO "%lld\n", size);
printk(KERN_INFO "%s", (char*)data);
// vfree(data);
return 0;
}
static void __exit lkm_example_exit(void)
{
printk(KERN_INFO "Goodbye, World!\n");
}
module_init(lkm_example_init);
module_exit(lkm_example_exit);
这是 Makefile:
# Save file as read_elf.c
obj-m += read_elf.o
# This line tells makefile that the given object files are part of module
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
What am I missing here? How can I read ELF binary from inside the kernel?
您忽略了 ELF 文件不是文本文件,而是二进制文件这一事实。但是,您试图将其打印为字符串(printk
中的 %s
说明符),它只会打印前几个字符并在第一个零字节 ([=12=]
) 处停止,认为它是字符串终止符。
事实证明,正如@Tsyvarev 在上面的评论中指出的那样,ELF 文件总是以字节 7f 45 4c 46
开头,在 ASCII 中是 ELF
(第一个字节 7f
不可打印)。这就是您阅读后在缓冲区中看到的内容。
如果你读完再看size
,你会发现它确实大于4,这意味着文件被正确读取了。尽管您可能仍想检查错误并确保阅读了 整个 文件。
我正在内核内部实现二进制证明。我正在使用 kernel_read_from_file()
函数读取文件。函数定义如下:
int kernel_read_file_from_path(const char *path, void **buf, loff_t *size,
loff_t max_size, enum kernel_read_file_id id)
函数正在buf
中存储文件内容。当我读取带有 .c
或 .h
扩展名的文件时,代码工作正常。但是对于 ELF 二进制文件:
Value stored in buf = ELF
我在这里错过了什么?我如何从内核中读取 ELF 二进制文件?
相关代码如下:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/file.h>
// #include "sha256.h"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Robert W. Oliver II");
MODULE_DESCRIPTION("A simple example Linux module.");
MODULE_VERSION("0.01");
static int __init lkm_example_init(void)
{
void *data;
loff_t size;
int ret;
char path1[50] = "/etc/bash.bashrc";
char path2[50] = "/bin/sh";
ret = kernel_read_file_from_path(path1, &data, &size, 0, READING_POLICY);
printk(KERN_INFO "Hello, World!\n");
printk(KERN_INFO "%lld\n", size);
printk(KERN_INFO "%s", (char*)data);
ret = kernel_read_file_from_path(path2, &data, &size, 0, READING_POLICY);
printk(KERN_INFO "%lld\n", size);
printk(KERN_INFO "%s", (char*)data);
// vfree(data);
return 0;
}
static void __exit lkm_example_exit(void)
{
printk(KERN_INFO "Goodbye, World!\n");
}
module_init(lkm_example_init);
module_exit(lkm_example_exit);
这是 Makefile:
# Save file as read_elf.c
obj-m += read_elf.o
# This line tells makefile that the given object files are part of module
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
What am I missing here? How can I read ELF binary from inside the kernel?
您忽略了 ELF 文件不是文本文件,而是二进制文件这一事实。但是,您试图将其打印为字符串(printk
中的 %s
说明符),它只会打印前几个字符并在第一个零字节 ([=12=]
) 处停止,认为它是字符串终止符。
事实证明,正如@Tsyvarev 在上面的评论中指出的那样,ELF 文件总是以字节 7f 45 4c 46
开头,在 ASCII 中是 ELF
(第一个字节 7f
不可打印)。这就是您阅读后在缓冲区中看到的内容。
如果你读完再看size
,你会发现它确实大于4,这意味着文件被正确读取了。尽管您可能仍想检查错误并确保阅读了 整个 文件。