问题
Is there a way of finding the loaded kernel code inside the memory? I mean the bootloader loads the kernel and executes it. The kernel extracts itself and start to initialize the hardware and runs init. As I understand the kernel is saved and loaded from the (b)zImage from disk. This unchanged code I want to find inside the memory of the system and check it.
I have the following enhancement:
Create a sha256 hash of the loaded kernel code and compare it to a defined value to audit the security of the system. Therefore I load a module which tries to find the kernel code inside the memory and compute the sha256 sum out of that.
I tried to find the kernel code in memory like that:
static struct resource *adhoc_next_resource(struct resource *p, bool sibling_only)
{
if (sibling_only)
return p->sibling;
if (p->child)
return p->child;
while (!p->sibling && p->parent)
p = p->parent;
return p->sibling;
}
static struct resource *get_kernel_code (void) {
struct resource *kern_code = &iomem_resource;
while (kern_code && strcmp(kern_code->name ? kern_code->name : "","Kernel code") != 0) {
kern_code = adhoc_next_resource(kern_code, false);
}
return kern_code;
}
int init_module(void)
{
void *start,*end;
size_t length;
SHA256_CTX sha256;
u32 *hash;
struct resource *kern_code;
kern_code = get_kernel_code();
if ( IS_ERR(kern_code) )
return -EINVAL;
start = (void*)phys_to_virt(kern_code->start);
end = (void*)phys_to_virt(kern_code->end);
length = kern_code->end - kern_code->start;
printk("%s[%s]:%s address: %0*llx-%0*llx \n", MODULE_NAME, __FUNCTION__, kern_code->name ? kern_code->name : "", 4, start, 4, end );
printk("%s[%s]: length: %lu \n", MODULE_NAME, __FUNCTION__, length);
printk ( KERN_INFO "%s[%s]: Init sha256\n", MODULE_NAME, __FUNCTION__ );
sha256_init(&sha256);
printk ( KERN_INFO "%s[%s]: Give kernel code to sha256\n", MODULE_NAME, __FUNCTION__ );
sha256_update ( &sha256, start, length );
hash = kmalloc ( 4 * sizeof(u32), GFP_KERNEL );
printk ( KERN_INFO "%s[%s]: Finalize sha256\n", MODULE_NAME, __FUNCTION__ );
sha256_final ( &sha256, (BYTE*)hash );
printk ( KERN_INFO "%s[%s]: Hash value of kernel code: %x - %x - %x - %x \n", MODULE_NAME, __FUNCTION__, hash[0], hash[1], hash[2], hash[3] );
kfree(hash);
return 0;
}
But, I get every time a reboot was done a different sha256 sum.
- Please explain that what happens ? Something in the memory of the kernel code changed. But what can it be ?
- Is this concept will be worked ? Or is there not every time the same loaded code in the memory.
回答1:
I have found by myself an answer for this problem:
I have made some more research about memory location of the kernel and so on. I found that during runtime the kernel ".text" section (extracted bzImage) is not stored in the iomem_resource list. I have inspected the address range from the "kernel code" resource (see my previous posted code) and found that most of the bits are 0. Only very at the beginning and at the end there is some code. But this is not "kernel code" I didn't find an answer what the hack is this "kernel code" section. Maybe it has to be the ".text" section of the Kernel Image, but not on my system (ARM 32bit & yocto-linux 4.10.17 ).
The KASLR feature (info here) posted from Yasushi is not the problem for ARM 32bit arichtecture. I found inside the kernel defines that this feature is not enabled on this type of system. But it is a very interesting feature.
To get the kernel address of the ".text" section I use now the kallsysm functionality. This is a big list of all addresses and exported variables. There are two variables who define the start and end. I use the following code:
start = (void*)kallsyms_lookup_name("_stext"); end = (void*)kallsyms_lookup_name("_etext");
Note: Be carefull with virtual memory vs. physical memory location. Kallsysm output is virtual memory location. (Please correct me if I am wrong)
Finally: I get the same checksum for each boot for the same kernel code and I can go on finishing my audit module :-).
来源:https://stackoverflow.com/questions/49065537/linux-kernel-code-in-memory-check-with-sha256-sum