提问人:Denis Berezniuk 提问时间:8/13/2023 更新时间:8/13/2023 访问量:86
如何在 C 中将包含在字符串中的 Address 分配给指针
How to assign an Address, contained inside a string, to a pointer in C
问:
我目前正在尝试开发一个 Linux Ubuntu 内核模块(作为我任务的一部分),它基本上是在地址上安装一个观察点,指定为模块的字符串参数 *(char)。
目前,我正处于将此地址分配给所需指针的阶段,但是......每次我尝试通过递增或添加此地址的值(以前从十六进制转换为十进制转换为 int)来执行此操作时,我根本无法正确分配此地址。我知道存在手动分配,但这不是我被告知要做的。请帮我找到至少一些方法来安装指针的确切地址,而无需对其进行硬编码。
顺便说一句,由于某种原因,每次重新启动计算机时,地址都会更改。
我的代码:
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地址。
答:
-1赞
X0rw
8/13/2023
#1
据我了解,您正在尝试将字符串地址“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 数组上,所以请检查它是否以“\0”结尾
评论
volatiles
volatile
unsigned char *address = (char *)0; address += simple_strtoul(.....)