【问题标题】:Why do constant names appear in compiled binaries/shared libraries?为什么常量名称出现在编译的二进制文件/共享库中?
【发布时间】:2020-07-28 23:15:01
【问题描述】:

我正在 CMake 中构建一个库,该库在私有标头中有一些常量。当我在Release 配置中编译时,例如-O3 -DNDEBUG 并在输出上运行strings,这些常量出现在输出中。这些常量的名称揭示了一些我希望尽可能隐藏的实现细节。

这是一个演示问题的最小项目示例:

private.h

#pragma once

const int MY_CONSTANT = 42;

lib.c

#include "private.h"

extern int get_mask(void)
{
  return MY_CONSTANT ^ 3;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.5)

project(dummylib)

add_library(mylib SHARED lib.c)

构建并显示字符串输出:

$ mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Release .. && cmake --build . --config Release -- VERBOSE=1 && strings libmylib.so | grep MY
MY_CONSTANT

是否有一些额外的开关可以用来隐藏这些信息?

【问题讨论】:

  • 尽管有名字,但这不是一个常数。没有static 关键字,它是一个全局变量。使用static 关键字,它是一个文件范围变量。无论哪种方式,它都是一个变量。如果您想要一个名称不会出现在输出文件中的常量,请使用#define
  • 我更正了 const 错误,实际库中所有这些都有 const 关键字。
  • @Mat 似乎 CMake Release 构建类型隐式处理了这个问题,但无论如何我一定会添加它!谢谢!

标签: c linux shared-libraries obfuscation elf


【解决方案1】:

MY_CONSTANT 是一个需要在内存中占有一席之地的变量。 C 的编译链接过程包括在将其链接到最终的 ELF 可执行文件之前创建一个中间目标文件。需要跟踪变量,并在链接的最后阶段分配其最终地址并重新定位引用。

为此,为使用名称引用MY_CONSTANT 的目标文件创建了一个符号表。默认情况下,链接器在创建最终可执行文件时不会丢弃它。

您可以通过运行strip --strip-unneeded ./a.out 手动删除此符号表。

请注意,这与用于在运行时链接的动态符号表无关。应用程序仍然可以链接和调用get_mask(void)

【讨论】:

    【解决方案2】:

    我刚刚想通了。当您在常量前面添加static 关键字时,您仍然可以从lib.c 和相关的源文件中访问该值,但它的名称不再出现在二进制文件的strings 转储中

    private.h

    #pragma once
    
    const int MY_CONSTANT = 42;
    

    结果:

    $ strings libmylib.so | grep MY
    MY_CONSTANT
    MY_CONSTANT
    

    使用static 关键字:

    private.h

    #pragma once 
    
    static const int MY_CONSTANT = 42;
    

    结果:

    $ strings libmylib.so | grep MY
    
    

    gcc 中,您还可以使用-g0 禁用调试符号

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-05
      相关资源
      最近更新 更多