0

情况 - 我正在使用第三方堆栈。我有第三方的源代码。这段代码非常笨拙,并且存在很多与缓冲区溢出相关的问题。

我的解决方案——为了追查这个问题,我重写了现有的函数,如 sprintf 和 memcpy 来检查是否存在缓冲区溢出。

到目前为止,这是我为覆盖 malloc 和 sprintf 所做的工作。

#define memcpy my_memcpy
void * my_memcpy(void *s1, const void *s2, size_t n)
    {
      void *(*libc_memcpy)(void*,const void*,size_t) = dlsym(RTLD_NEXT, "memcpy");

      return libc_memcpy(s1,s2,n);
    }

接下来,我使用了 sprintf -

#define sprintf  mysprintf

int mysprintf(char *str, const char *format, ...)
{
  va_list args;
  va_start(args, format);
  vsprintf(str,format, args);
  va_end(args);
  return 0;

}

我的问题 - 我希望在缓冲区 - 目标容量较小时打印覆盖的函数,然后我们正在写入它。

我需要解决方案,它适用于堆栈分配的内存,如 char buff[5]; 和 char *buff = (char *) malloc(5);

因此,假设当我们对字符串大小为 6 字节的 buff 执行 memcpy 时,覆盖的 memcpy 应该会抛出错误。同样,当我们 sprintf 时,被覆盖的 sprintf 应该会抛出错误。主要问题是 sprintf。我想使用 snprintf 而不是 sprintf。很难查看每一段代码并更改为 snprintf。所以,我在这里要做的是用我的版本覆盖 sprintf 并在内部调用 snprintf,我将在其中根据 arg 的大小计算“n”。另外,我将比较 n 是否小于缓冲区大小。瓶颈是如何根据传递的指针找到缓冲区的大小。

4

1 回答 1

1

好吧,您能做的最好的事情就是在其他地方跟踪通过您自己的 malloc 副本分配的所有块的所需大小,然后让您的 memcpy 和 sprintf 副本测试指针是否来自该特殊分配函数,并且那么如果大小是兼容的。

您基本上有两种构建这样一个系统的方法:

  • 您的 malloc 添加2 * sizeof(int)到所需的大小,将签名放在第一个 int 中,然后将所需的大小 int 放在第二个中,然后返回一个指针。然后 memcpy 和 sprintf 控制这*(((int *) p) - 2)是签名,然后在*(((int *) p) - 1). 限制:签名可能在内存中的错误位置给出误报,并且无论如何在非专门分配的指针上这样做会调用未定义的行为,因为您可以访问数组外部。但是实现起来很简单
  • 您构建一个数据结构(一种哈希)来存储分配的指针及其大小。然后 memcpy 和 sprintf 在该数据结构中查找它们的指针。这里没有未定义的行为,但您必须在 C 中实现正确的数据结构

无论如何,这两种解决方案都有一个共同的缺陷:您只测试直接分配内存的缓冲区溢出 - 如果您分配 char 的 2D 数组并且在对第一个元素以外的元素执行 sprintf 时发生缓冲区溢出,您将不会检测到它。如果您测试指针是否在分配块的开始 - 结束范围内,则第二种解决方案可以,但它会更昂贵。而且您无法控制堆栈分配的内存,也无法控制静态缓冲区。

于 2015-09-28T08:20:20.840 回答