在上一篇文章https://bbs.kanxue.com/thread-287893.htm中通过 hook 了 svc 进行了监控,然后获取目标进程内存,利用 fp 寄存器实现了栈回溯。此时的栈回溯只有内存地址,还需要额外的辅助才能拿到 so 中对应的地址,在这篇文章中可以获取到 so 名称以及 so 的相对偏移。
根据 maps 文件的生成原理,可以在源码中查看到show_map_vmae32K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4S2J5k6h3k6S2L8X3c8J5L8$3W2V1i4K6u0W2j5$3!0E0i4K6u0r3j5h3&6V1M7X3!0A6k6o6p5K6i4K6u0V1y4g2)9J5k6e0p5H3i4K6u0V1L8s2c8K6i4K6u0r3M7#2)9K6c8Y4u0W2k6Y4y4Q4x3@1c8K6K9r3!0%4i4K6g2X3L8h3q4H3i4K6g2X3N6X3#2S2i4K6t1$3j5h3#2H3i4K6y4n7M7s2u0G2K9X3g2U0N6q4)9K6c8r3k6K6
他是通过struct vm_area_struct *vma 获取到 vm_file,然后使用seq_file_path函数获取到里面的路径字符串,seq_file_path 中调用了seq_path,下面是seq_path 的源码。
从这里看出其中的字符串主要是通过d_path 来取得。
那么根据这个流程我们可以自己实现一个,大概流程如下:
具体实现如下
这里要使用到的mm_struct 和vm_area_struct 结构体在 Apatch 中提供的头文件里没有,我们可以自己编写一个头文件
这个结构体可以从源码中复制过来,要注意对应内核版本,我的手机是 5.10 内核所以用的 5.10 版本。另外,这里可以截断一部分,只需要覆盖到我们需要用的成员偏移,能让编译器找到对应偏移即可。新的效果如下:
使用该内核模块拦截到的是所有的 svc,那么栈回溯中也会回溯所有调用到的。这里发现 dmesg 打出来的日志里有很多系统自身调用 svc 生成的,会干扰到我们查看日志。 此处考虑从 task 结构体中获取 cred 结构体,在 cred 结构体中会保存进程 uid,通过过滤 uid 可以知道是否是普通 app 的进程。
但是在实现的过程中,调用了get_task_cred 获取 cred 结构就会导致内核崩溃,下面是实现源码:
还请各位大佬指点一下
271 static void
272 show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
273 {
274 struct mm_struct *mm = vma->vm_mm;
275 struct file *file = vma->vm_file;
276 vm_flags_t flags = vma->vm_flags;
277 unsigned long ino = 0;
278 unsigned long long pgoff = 0;
279 unsigned long start, end;
280 dev_t dev = 0;
281 const char *name = NULL;
282
283 if (file) {
284 struct inode *inode = file_inode(vma->vm_file);
285 dev = inode->i_sb->s_dev;
286 ino = inode->i_ino;
287 pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT;
288 }
289
290 start = vma->vm_start;
291 end = vma->vm_end;
292 show_vma_header_prefix(m, start, end, flags, pgoff, dev, ino);
293
294 /*
295 * Print the dentry name for named mappings, and a
296 * special [heap] marker for the heap:
297 */
298 if (file) {
299 seq_pad(m, ' ');
300 seq_file_path(m, file, "\n");
301 goto done;
302 }
303
304 if (vma->vm_ops && vma->vm_ops->name) {
305 name = vma->vm_ops->name(vma);
306 if (name)
307 goto done;
308 }
309
310 name = arch_vma_name(vma);
311 if (!name) {
312 struct anon_vma_name *anon_name;
313
314 if (!mm) {
315 name = "[vdso]";
316 goto done;
317 }
318
319 if (vma->vm_start <= mm->brk &&
320 vma->vm_end >= mm->start_brk) {
321 name = "[heap]";
322 goto done;
323 }
324
325 if (is_stack(vma)) {
326 name = "[stack]";
327 goto done;
328 }
329
330 anon_name = anon_vma_name(vma);
331 if (anon_name) {
332 seq_pad(m, ' ');
333 seq_printf(m, "[anon:%s]", anon_name->name);
334 }
335 }
336
337 done:
338 if (name) {
339 seq_pad(m, ' ');
340 seq_puts(m, name);
341 }
342 seq_putc(m, '\n');
343 }
271 static void
272 show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
273 {
274 struct mm_struct *mm = vma->vm_mm;
275 struct file *file = vma->vm_file;
276 vm_flags_t flags = vma->vm_flags;
277 unsigned long ino = 0;
278 unsigned long long pgoff = 0;
279 unsigned long start, end;
280 dev_t dev = 0;
281 const char *name = NULL;
282
283 if (file) {
284 struct inode *inode = file_inode(vma->vm_file);
285 dev = inode->i_sb->s_dev;
286 ino = inode->i_ino;
287 pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT;
288 }
289
290 start = vma->vm_start;
291 end = vma->vm_end;
292 show_vma_header_prefix(m, start, end, flags, pgoff, dev, ino);
293
294 /*
295 * Print the dentry name for named mappings, and a
296 * special [heap] marker for the heap:
297 */
298 if (file) {
299 seq_pad(m, ' ');
300 seq_file_path(m, file, "\n");
301 goto done;
302 }
303
304 if (vma->vm_ops && vma->vm_ops->name) {
305 name = vma->vm_ops->name(vma);
306 if (name)
307 goto done;
308 }
309
310 name = arch_vma_name(vma);
311 if (!name) {
312 struct anon_vma_name *anon_name;
313
314 if (!mm) {
315 name = "[vdso]";
316 goto done;
317 }
318
319 if (vma->vm_start <= mm->brk &&
320 vma->vm_end >= mm->start_brk) {
321 name = "[heap]";
322 goto done;
323 }
324
325 if (is_stack(vma)) {
326 name = "[stack]";
327 goto done;
328 }
329
330 anon_name = anon_vma_name(vma);
331 if (anon_name) {
332 seq_pad(m, ' ');
333 seq_printf(m, "[anon:%s]", anon_name->name);
334 }
335 }
336
337 done:
338 if (name) {
339 seq_pad(m, ' ');
340 seq_puts(m, name);
341 }
342 seq_putc(m, '\n');
343 }
459 int seq_path(struct seq_file *m, const struct path *path, const char *esc)
460 {
461 char *buf;
462 size_t size = seq_get_buf(m, &buf);
463 int res = -1;
464
465 if (size) {
466 char *p = d_path(path, buf, size);
467 if (!IS_ERR(p)) {
468 char *end = mangle_path(buf, p, esc);
469 if (end)
470 res = end - buf;
471 }
472 }
473 seq_commit(m, res);
474
475 return res;
476 }
477 EXPORT_SYMBOL(seq_path);
459 int seq_path(struct seq_file *m, const struct path *path, const char *esc)
460 {
461 char *buf;
462 size_t size = seq_get_buf(m, &buf);
463 int res = -1;
464
465 if (size) {
466 char *p = d_path(path, buf, size);
467 if (!IS_ERR(p)) {
468 char *end = mangle_path(buf, p, esc);
469 if (end)
470 res = end - buf;
471 }
472 }
473 seq_commit(m, res);
474
475 return res;
476 }
477 EXPORT_SYMBOL(seq_path);
task_struct->mm_struct->vm_area_struct->vm_file
d_path(vm_file)
task_struct->mm_struct->vm_area_struct->vm_file
d_path(vm_file)
typedef char *(*d_path)(const struct path *path, char *buf, int buflen);
d_path d_path_func;
struct mm_struct{
struct vm_area_struct *mmap;
};
void show_vma(struct task_struct *task, pid_t pid, unsigned long addr){
struct mm_struct *mm;
struct vm_area_struct *vma;
mm = get_task_mm_func(task);
// pr_info(">>> VMA list for PID %d:\n", pid);
for (vma = mm->mmap; vma; vma = vma->vm_next) {
if(vma->vm_start <= addr && vma->vm_end >= addr){
char path[256] = {0};
if (vma->vm_file) {
char *tmp = d_path_func(&vma->vm_file->f_path, path, sizeof(path));
char *path = strrchr(tmp, '/');
if(path){
path++;
pr_info("VMA: %s+0x%lx pid: %d\n",
path, addr - vma->vm_start, pid);
}else{
pr_info("VMA: %s+0x%lx pid: %d\n",
tmp, addr - vma->vm_start, pid);
}
}
}
}
mmput_func(mm);
}
d_path_func = (typeof(d_path))kallsyms_lookup_name("d_path");
typedef char *(*d_path)(const struct path *path, char *buf, int buflen);
d_path d_path_func;
struct mm_struct{
struct vm_area_struct *mmap;
};
void show_vma(struct task_struct *task, pid_t pid, unsigned long addr){
struct mm_struct *mm;
struct vm_area_struct *vma;
mm = get_task_mm_func(task);
// pr_info(">>> VMA list for PID %d:\n", pid);
for (vma = mm->mmap; vma; vma = vma->vm_next) {
if(vma->vm_start <= addr && vma->vm_end >= addr){
char path[256] = {0};
if (vma->vm_file) {
char *tmp = d_path_func(&vma->vm_file->f_path, path, sizeof(path));
char *path = strrchr(tmp, '/');
if(path){
path++;
pr_info("VMA: %s+0x%lx pid: %d\n",
path, addr - vma->vm_start, pid);
}else{
pr_info("VMA: %s+0x%lx pid: %d\n",
tmp, addr - vma->vm_start, pid);
}
}
}
}
mmput_func(mm);
}
[培训]科锐软件逆向54期预科班、正式班开始火爆招生报名啦!!!