如何从一个编译的二进制字符串(的.so) [英] How to remove strings from a compiled binary (.so)

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

问题描述

我如何删除/混淆编译的二进制字符串?我们的目标是避免具有人阅读的内部的功能/方法的名称。

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.

这是(。所以)编译从C ++为Android code与NDK工具(包括GCC)

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

我编译 -O3 和已经使用 ARM-EABI-带-g mylib.so 删除调试符号,但是当我做的功能字符串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.

脱衣-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. 标记私人静态。显然,这仅适用于只需要在一个单一的编译单元的功能,但对于一些图书馆这种技术可能就足够了。

  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 =隐藏编译器选项更改默认可见性为隐藏和标记所有的公共职能为可见。后者可能是您的最佳选择,因为它意味着你不必担心意外增加一个功能,忘记将其标记为隐藏。

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")));

和语法标记是可见的是:

and the syntax for marking it visible is:

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天全站免登陆