为什么常量名称出现在编译的二进制文件/共享库中?

问题描述 投票:1回答:2

我正在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

还有其他一些我可以用来隐藏此信息的开关吗?

c linux shared-libraries obfuscation elf
2个回答
2
投票

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

作为其产物,将为目标文件创建一个符号表,该符号表使用其名称引用MY_CONSTANT。默认情况下,在创建最终可执行文件时,链接程序不会将其丢弃。

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

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


0
投票

我只是想通了。当您在常量前面添加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禁用调试符号>

© www.soinside.com 2019 - 2024. All rights reserved.