如何从编译二进制文件(.so)删除字符串 [英] How to remove strings from a compiled binary (.so)

查看:710
本文介绍了如何从编译二进制文件(.so)删除字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何从/ obfuscate编译的二进制文件中删除字符串?目标是避免有人读取里面的函数/方法的名称。

How do I remove strings from / obfuscate a compiled binary? The goal is to avoid having people read the names of the functions/methods inside.

这是一个动态库(.so)从Android的C ++代码编译NDK工具(包括GCC)

It is a dynamic library (.so) compiled from C++ code for Android with the NDK tools (includes GCC)

我使用 -O3 编译并且已经使用 arm-eabi -strip -g mylib.so 删除调试符号,但是当我执行 strings mylib.so 时,函数/方法的所有名称仍然

I compile with -O3 and already use arm-eabi-strip -g mylib.so to remove debugging symbols, but when I do strings mylib.so all the names of the functions/methods are still readable.

推荐答案

这些字符串位于动态符号表中,在运行时加载。 readelf -p .dynstr mylib.so 将显示这些条目。

These strings are in the dynamic symbol table, which is used when the library is loaded at runtime. readelf -p .dynstr mylib.so will show these entries.

strip -g 将删除调试符号,但不能从动态符号表中删除条目,因为这些可能在运行时需要。你的问题是,在动态符号表中有一些条目,这些条目永远不会从库外调用。除非你告诉它,编译器/链接器无法知道哪些函数构成外部API的一部分(因此需要动态符号表中的条目)以及哪些函数对于库是私有的(因此不需要条目动态符号表),因此它只为所有非静态函数创建动态符号表条目。

strip -g will remove debugging symbols, but it can't remove entries from the dynamic symbol table, as these may be needed at runtime. Your problem is that you have entries in the dynamic symbol table for functions which are never going to be called from outside your library. Unless you tell it, the compiler/linker has no way of knowing which functions form part of the external API (and therefore need entries in the dynamic symbol table) and which functions are private to your library (and so don't need entries in the dynamic symbol table), so it just creates dynamic symbol table entries for all non-static functions.

有两种主要方式可以通知编译器哪些函数是私有的

There are two main ways you can inform the compiler which functions are private.


  1. 标记私人函数 static 。显然,这只适用于在单个编译单元中只需要的函数,但对于某些库,这种技术可能就足够了。

  1. Mark the private functions static. Obviously, this only works for functions only needed within a single compilation unit, though for some libraries this technique might be sufficient.

使用gcc将功能标记为可见或隐藏。您有两个选项:或者将所有私有函数标记为隐藏,或者使用 -fvisibility = hidden 编译器选项将默认可见性更改为隐藏,并将所有公共函数标记为可见。后者可能是最好的选择,因为它意味着你不必担心不小心添加一个函数并忘记将它标记为隐藏。

Use the gcc "visibility" attribute to mark the functions as visible or hidden. You have two options: either mark all the private functions as hidden, or change the default visibility to hidden using the -fvisibility=hidden compiler option and mark all the public functions as visible. The latter is probably the best option for you, as it means that you don't have to worry about accidentally adding a function and forgetting to mark it as hidden.

如果你有一个函数:

int foo(int a, int b);

那么标记隐藏的语法是:

then the syntax for marking it hidden is:

int foo(int a, int b) __attribute__((visibility("hidden")));

,标记可见的语法是:

int foo(int a, int b) __attribute__((visibility("default")));

有关详细信息,请参阅此文档,这是有关此主题的一个很好的信息来源。

For further details, see this document, which is an excellent source of information on this subject.

这篇关于如何从编译二进制文件(.so)删除字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆