如何将字符串中包含的地址分配给 C 中的指针

问题描述 投票:0回答:1

我目前正在尝试开发一个 Linux Ubuntu 内核模块(作为我任务的一部分),它基本上是在地址上安装一个观察点,指定为模块的字符串参数 *(char )

目前,我正处于将该地址分配给所需指针的阶段,但是......每次我尝试通过递增或添加该地址的值来完成此操作(之前从hex转换为decimalint) ),我根本无法正确分配这个地址。我知道存在手动分配,但这不是我被告知要做的。请帮助我至少找到一些方法来将精确地址安装到指针,而无需对其进行硬编码。

顺便说一下,由于某种原因,每次我重新启动机器时,地址都会改变。

我的代码:

char *address = NULL;
volatile void *zero_address = 0;
volatile long long unsigned int actual_address;

**...**

if(starts_with(address, "0x"))
{
    actual_address = simple_strtoul(address + 2, NULL, 16);
} else {
    actual_address = simple_strtoul(address, NULL, 16);
}
printk(KERN_INFO "Address in int = %llu", actual_address);   
for (volatile long long unsigned int i = 0; i < actual_address; i++, zero_address++);
// zero_address = zero_address + actual_address;
printk(KERN_INFO "Address converted = %p", zero_address);
write_attributes.bp_addr = (long long unsigned int) zero_address;

程序完整代码:

#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO, KERN_ALERT */
#include <linux/init.h>   /* Needed for the macros */
#include <linux/stat.h>
#include <linux/moduleparam.h> /* Needed for module_param */
#include <linux/perf_event.h>
#include <linux/hw_breakpoint.h>
#include <linux/version.h>

#include <linux/string.h>
#include <linux/math.h>

//https://tldp.org/LDP/lkmpg/2.6/lkmpg.pdf
//https://stackoverflow.com/questions/19725900/watch-a-variable-memory-address-change-in-linux-kernel-and-print-stack-trace
//https://github.com/xcellerator/linux_kernel_hacking/issues/3


#define DRIVER_AUTHOR "Denys Berezniuk"
#define DRIVER_DESC   "Test Driver"

/*
 * On Linux kernels 5.7+, kallsyms_lookup_name() is no longer exported,
 * so we have to use kprobes to get the address.
 * Full credit to @f0lg0 for the idea.
 */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,7,0)
#define KPROBE_LOOKUP 1
#include <linux/kprobes.h>
static struct kprobe kp = {
    .symbol_name = "kallsyms_lookup_name"
};
unsigned long int *kallsyms_lookup_name_custom(const char *);
#endif

MODULE_LICENSE("GPL");
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);

struct perf_event * __percpu *write_watchpoint;
struct perf_event * __percpu *read_watchpoint;
char *address = NULL;
volatile void *zero_address = 0;
volatile long long unsigned int actual_address;

struct perf_event_attr write_attributes;
struct perf_event_attr read_attributes;
module_param(address, charp, /*0000*/ S_IRUGO /*| S_IWUGO*/);

MODULE_PARM_DESC(address, "Address to place a Watchpoint on");

static void write_handler(struct perf_event *bp, struct perf_sample_data *data, struct pt_regs *regs)
{
    //printk(KERN_INFO "%s value is changed\n", address);
    //dump_stack();
    //printk(KERN_INFO "Dump stack from write_handler\n");
}

bool starts_with(const char *a, const char *b)
{
   if(strncmp(a, b, strlen(b)) == 0) return 1;
   return 0;
}
    
int __init initialize_driver(void)
{
    #ifdef KPROBE_LOOKUP
        /*register_kprobe(&kp);
        kallsyms_lookup_name_custom = (unsigned long int (*)(const char *)) kp.addr;
        unregister_kprobe(&kp);*/
        typedef unsigned long (*kallsyms_lookup_name_t)(const char *name);
        kallsyms_lookup_name_t kallsyms_lookup_name;
        register_kprobe(&kp);
        kallsyms_lookup_name = (kallsyms_lookup_name_t) kp.addr;
        unregister_kprobe(&kp);
    #endif

    printk(KERN_ALERT "Driver loaded\nAddress is: '%s'\n", address);
    hw_breakpoint_init(&write_attributes);
    //write_attributes.bp_addr = kallsyms_lookup_name(address);
    if(starts_with(address, "0x"))
    {
        actual_address = simple_strtoul(address + 2, NULL, 16);
    } else {
        actual_address = simple_strtoul(address, NULL, 16);
    }
    printk(KERN_INFO "Address in int = %llu", actual_address);   
    for (volatile long long unsigned int i = 0; i < actual_address; i++, zero_address++);
    // zero_address = zero_address + actual_address;
    printk(KERN_INFO "Address converted = %p", zero_address);
    write_attributes.bp_addr = (long long unsigned int) zero_address;
    write_attributes.bp_len = HW_BREAKPOINT_LEN_1;
    write_attributes.bp_type = HW_BREAKPOINT_W; //| HW_BREAKPOINT_R;
    write_watchpoint = register_wide_hw_breakpoint(&write_attributes, (perf_overflow_handler_t) write_handler, NULL);
    if(IS_ERR((void __force *) write_watchpoint))
    {
        int result = PTR_ERR((void __force *) write_watchpoint);
        printk(KERN_ALERT "Watchpoint registration failed\n");
        return result;
    }
    printk(KERN_INFO "HW Watchpoint (Breakpoint) for %s write installed (0x%p)\n", address, (void*)write_attributes.bp_addr);
    return 0;
}

void __exit driver_removal(void)
{
    printk(KERN_ALERT "Driver removed.\n");
}

module_init(initialize_driver);
module_exit(driver_removal);

我一直将指针保持为类型 (void *),但是,它并没有真正的帮助。我还尝试使用 kallsyms_lookup_name 函数来完成此任务(需要额外的代码才能在 kerner v.5 之后使用它),但它也没有帮助,仅返回 0x0 的地址。

c pointers kernel kernel-module memory-address
1个回答
0
投票

据我了解,您正在尝试将字符串地址“0x1233232”分配给指针,我编写了这个简单的代码,但由于我在用户模式下测试它,所以我无法随机分配一个地址进行测试,所以我分配了它并将其转换为字符串,然后将其从字符串转换为指针

char str_addr[100];//where we are going to store the address as a string
int i = malloc(4);//allocating 4 bytes
snprintf(str_addr,sizeof(str_addr),"%p",&i);//converting the address of i to a string 
printf("allocated address string: %s\n",str_addr);

int *p = (int *)str_addr;//casting the string address to a pointer
printf("pointed address:%s\n",  p);

我很确定你测试了同样的东西,也许问题出在 char 数组上,所以检查它是否以 ' ' 结尾

© www.soinside.com 2019 - 2024. All rights reserved.