他们会把做内核的人当成无所不能的,认为你们对反编译啥的都应该会。
俗话说的好,人要活成别人想要的样子嘛:
看下如何停止进程,让大家看到内存中到底是啥样子;
简单的print globalA当然能输出来变量globalA的地址以及这个地址中的值,但是如果这里是一个链表,能通过编程的方法把这里的数值给dump出来么,直接就dump函数么,两个思路吧,要么是代码中自己写一个函数供调用,要么是我自己写一个外挂程序去调用。
第一种方法:
第一种方法可以,借助gdb的call 功能,就能让程序去执行特定的调测函数,测试程序:call showNode(root)就可以了
https://github.com/honpey/codebox/blob/master/gdb/gdb_call.c
第二种方法:gdb能不能开一个外观呢?gdb自己写函数去调用
还是先从最简单的动态库开始,我先在动态库中作函数
#include <stdio.h>
int max(int a, int b) {
return (a>b)?a:b;
}
int min(int a, int b) {
return (a<b)?a:b;
}
void sayhello() {
printf("hello libso\n");
}
其中max和min函数都不依赖外部的函数,都是raw的,可以直接调用,此时甚至都不需要什么动态库,直接静态的就好,但是后面由于需要有sayhello,因此需要有plt的重定位的加持。
可以看到max函数位于.text段的这个位置(odjdump -d cal.so):0x00000000000006e0;min位于0x00000000000006f6
那么text段的偏移(readelf -S cal.so)是005e0,大小是13f,所以整个代码段的大小是[005e0, 0071f)这么大的位置
上面两个函数相互相互印证吧,我们看到0x6e0/6f6确实是位于[005e0, 0071f)这个区间内,那么案例说,我直接去执行这个地址就能得到max和min的结果, 试验成功,
步骤:
1) gdb gdb_call 22044
2) call open("cal.so", 2)
3) call mmap(0, 4096, 1|2|4, 1, 3, 0)
4) set $addr=$addr_base+0x6e0 //$addr_base= /proc/22044/maps得到
5) call $addr(1, 100) 就真的返回100了
这个倒是简单,对于动态加载的呢?
先看下反汇编的函数:
void sayhello() {
printf("hello libso\n");
}
------->
000000000000070c <sayhello>:
70c: 55 push %rbp
70d: 48 89 e5 mov %rsp,%rbp
710: 48 8d 3d 12 00 00 00 lea 0x12(%rip),%rdi # 729 <_fini+0x9>
717: e8 a4 fe ff ff callq 5c0 <puts@plt>
71c: 90 nop
71d: 5d pop %rbp
71e: c3 retq
编译其看到这里的5c0会咋整?
内容很多,下面一篇详细介绍吧