Linux下C语言的内存模式扫描
我正在寻找一种方法来扫描程序的内存中的特定模式。程序正在将我们的代码作为库加载(Linux下C语言的内存模式扫描,c,linux,gcc,memory,C,Linux,Gcc,Memory,我正在寻找一种方法来扫描程序的内存中的特定模式。程序正在将我们的代码作为库加载(.so) 以下是我的尝试: unsigned long FindPattern(char *pattern, char *mask) { void *address; unsigned long size, i; // NULL = We want the base address of the process we are loaded in address = dlo
.so
)
以下是我的尝试:
unsigned long FindPattern(char *pattern, char *mask)
{
void *address;
unsigned long size, i;
// NULL = We want the base address of the process we are loaded in
address = dlopen(NULL, 0); // Would be GetModuleHandle(NULL) on Windows
// The size of the program, would be GetModuleInformation.SizeOfImage on Windows
size = 0x128000; // Didn't find a way for Linux
for(i = 0; i < size; i++)
{
if(_compare((unsigned char *)(address + i), (unsigned char *)pattern, mask))
return (unsigned long)(address + i);
}
return 0;
}
int _compare(unsigned char *data, unsigned char *pattern, char *mask)
{
for(; *mask; ++mask, ++data, ++pattern)
{
if(*mask == 'x' && *data != *pattern) // Crashes here according to gdb
return 0;
}
return (*mask) == 0;
}
无符号长find模式(字符*模式,字符*掩码)
{
无效*地址;
无符号长尺寸,i;
//NULL=我们需要加载的进程的基址
address=dlopen(NULL,0);//将是Windows上的GetModuleHandle(NULL)
//程序的大小在Windows上为GetModuleInformation.SizeOfImage
size=0x128000;//找不到Linux的方法
对于(i=0;i
但所有这些都不起作用。从dlopen
开始,它不会返回我们加载的程序的正确基址。我也尝试过链接地图,如前所述。
我确实知道IDA和gdb的地址,这就是我知道dlopen
返回错误值的原因
在CentOS 6.5 64位上使用gcc-4.4.7。该程序是32位可执行二进制文件。
dlopen
返回库的句柄,而不是指向包含库的内存的指针
您需要使用dlsym
获取函数的地址
handle = dlopen(NULL, RTLD_LAZY);
address = dlsym(handle, "main");
现在你有一个地址可以看了
“main”可能不是最好的起点,但它在这里起到了示范作用。确保在程序的早期找到一个符号,以便进行完全搜索
作为奖励,加快搜索/比较循环:
// The size of the program, would be GetModuleInformation.SizeOfImage on Windows
size = 0x128000; // Didn't find a way for Linux
unsigned char* ptr = address;
while (1)
{
/* hmmm, gets complicated if we need to mask src char then compare pattern, I punted
* and just compared for first char of pattern. It's just an idea... */
ptr = memcmp(ptr, pattern[0], (size - ptr + address));
if (ptr==NULL)
break;
if (_compare(ptr, (unsigned char *)pattern, mask))
return ptr;
}
说明:“标志[…]中必须包含以下两个值之一”,然后将0
作为第二个参数传递给dlopen
。因此,您不能依赖于返回值。也许这是你的问题,但我不确定…不幸的是,我没有尝试过懒惰,空载,现在国旗;所有这些都失败了您希望扫描程序的代码或数据段吗?或者两者都有?程序控制的每一位内存?实际上只是程序的代码;汇编指令summ,memchr函数的长度参数可能应该是(size-ptr+address-strlen(pattern))
,因此我们不在缓冲区的末尾进行比较。(最好将strlen(pattern)放入一个变量中,以防止每次也重新评估strlen)根据显示的附加\u compare
代码,只要mask
的第一个字符是'x'
,我建议的加速比就可以正常工作。好极了谢谢你的建议。我尝试过dlsym和所有不同的入口点,但实际上没有任何效果;它总是返回0。当使用readelf-l
时,输出入口点
显示一个正确的地址,该地址几乎位于程序的最顶端。所以必须有一种方法来获取这个地址。“entry_point”的值存储在内存映像的第一个字节中,但是由于ASLR,我们不知道它在哪里。在没有ASLR的情况下,32位ELF从0x8048000开始,而64位ELF从0x400000开始,并且入口点作为4字节LE值位于偏移量0x18处。通常,如果您查找\u start
的值,您将非常接近主程序的开头。但是dlsym
为\u start
返回0,我的操作与您的帖子中的操作完全相同。有什么想法吗?同时,我将使用默认的ELF开始,谢谢。