Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux下C语言的内存模式扫描_C_Linux_Gcc_Memory - Fatal编程技术网

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开始,谢谢。