简体   繁体   English

使反向工程成为C共享库的提示更加困难

[英]Tips to make reverse engineering a C shared library more difficult

I am interested in precautionary measures you could take to make reverse engineering a C shared library more difficult 我对您可以采取的预防措施感兴趣,以使逆向工程C共享库变得更加困难

It seems that it is impossible to prevent entirely but you can take steps that might make it take longer and therefore be less attractive/more costly to do 似乎不可能完全阻止,但你可以采取可能需要更长时间的步骤,因此不那么有吸引力/成本更高

Things like code obfuscation, compiler optimisation options compiler debug flags etc. (I would be specifically interested in the gcc compiler) 代码混淆,编译器优化选项编译器调试标志等等(我会特别感兴趣的是gcc编译器)

Also interested in any thoughts on the relative difficulty of reverse engineering a ~5KLOC C shared library (.so size of ~200kb) in terms of $ or man hours etc. 对于以$或工时等方式逆向工程~5KLOC C共享库(.so大小~200kb)的相对难度的任何想法也感兴趣。

Those are some tricks that I know of: 这些是我所知道的一些技巧:

  • Use strip with the --strip-unneeded option to remove all symbols except the ones that are needed for relocation (since we're talking about a shared library): 使用strip--strip-unneeded选项删除,只是需要搬迁(因为我们正在谈论的共享库)中的那些所有符号:

    strip --strip-unneeded libmylib.so

  • Link with the standard libc statically , this results in a bigger library/binary which means more code to go through and also obfuscation since it will be more difficult to separate your functions from the library functions: 静态链接标准libc,这会产生更大的库/二进制文件,这意味着需要更多的代码进行处理以及混淆,因为将函数与库函数分开会更加困难:

    gcc -static ...

  • Force the compiler to inline small functions, this embeds small functions in your code instead of calling them, so it makes it almost impossible to distinguish between your code and the standard library code. 强制编译器内联小函数,这会在代码中嵌入小函数而不是调用它们,因此几乎不可能区分代码和标准库代码。

Having said that, I must add that I've had a binary that used the above measures and I was able to reverse engineer it in a few hours, I started by rebuilding the symtab if you're curious, and I'm no reverse engineering guru. 话虽如此,我必须补充一点,我有一个使用上述措施的二进制文件,我能够在几个小时内对其进行逆向工程,如果你很好奇,我就会重建symtab ,并且我没有反向工程大师。

- No need of code obfuscation (as in C# or Java). - 无需代码混淆(如在C#或Java中)。

The name of your internal variables and functions do not exist in the object code. 目标代码中不存在内部变量和函数的名称。

However the name of your exported functions will still appear in clear in the shared object file. 但是,导出函数的名称仍将以明文形式显示在共享对象文件中。 This sounds reasonable. 这听起来很合理。

- Better to use gcc optimization flags -O2 or -O3 . - 最好使用gcc优化标志-O2-O3

Using compiler optimization, object code can largely differ from source code. 使用编译器优化,目标代码可能与源代码有很大不同。 It is actually very difficult to go back to the original C source code. 实际上很难回到原始的C源代码。

However it is always possible to revert engineer at the assembly level. 但是,始终可以在装配级别恢复工程师。 Usually, not all your program is valuable. 通常,并非所有程序都有价值。 It will be easier to reverse engineer the interesting portion in assembly rather than the whole program in C. 在装配中对有趣部分进行逆向工程更容易,而不是C中的整个程序。

The problem with most common anti-reversing techniques is that they are well-known and there are tools to overcome them. 最常见的防反转技术的问题在于它们是众所周知的并且存在克服它们的工具。 Of course, stripping symbols and obfuscation, is a must have, but this is just about hiding names/symbols. 当然,剥离符号和混淆是必须的,但这只是隐藏名称/符号。

If you want to make the job for reversers even harder, invent some code manipulation yourself. 如果你想让反向器的工作更加困难,那就自己发明一些代码操作。 It can be something really easy, like using a custom calling convention, but this will make all the disassemblers fail to recognize starts and ends of functions. 它可以是非常简单的东西,比如使用自定义调用约定,但这会使所有反汇编程序无法识别函数的开始和结束。

These kinds of simple tricks will be quite effective, because there won't be an already-made tool to revert the code to the original. 这些简单的技巧将非常有效,因为没有一个已经制作的工具可以将代码恢复为原始代码。 You see, for almost every commercial packer or encrypter, there is already a one-click-unpacker. 你看,对于几乎所有商业包装商或加密器,已经有一个单击解包器。

Not that much. 没有那么多。 Once you've stripped debug symbols and obfuscated all internal symbols (not external ones because the clients of the library need a symbol to link to), theres not much you can do. 一旦剥离了调试符号并对所有内部符号进行了模糊处理(而不是外部符号,因为库的客户端需要一个符号链接),那么你可以做的就不多了。 Assembly disassembly is very easy because of the 1-1 mapping of instructions to opcodes. 由于1-1指令到操作码的映射,装配反汇编非常容易。 On this other hand, it is very difficult to understand compiler generated assembly code, as it is full of bizarre optimizations and efficiency tricks. 另一方面,很难理解编译器生成的汇编代码,因为它充满了奇怪的优化和效率技巧。

On that note, turning GCC up to highest optimization is probably one of the best obfuscation tricks you can use. 在这方面,将GCC转换为最高优化可能是您可以使用的最好的混淆技巧之一。

Considering modern computing power, the disassembly itself won't take that long, and at that point it takes a human to decipher it. 考虑到现代计算能力,拆卸本身不需要那么长时间,并且在这一点上需要人来解读它。

Just curious though: What is so important to not have reverse engineered? 但是好奇的是:没有逆向工程有什么重要意义? The encryption and security that keeps things like financial data safe are mostly open source. 保证财务数据安全的加密和安全性大多是开源的。 Or is this a proprietary software protection thing? 或者这是一个专有的软件保护的东西?

Mix your code with switch/case obfuscation (make it nonlinear). 将代码与开关/案例混淆混合(使其成为非线性)。

Use C++ templates to encrypt variables/strings at the compilation time. 使用C ++模板在编译时加密变量/字符串。 It's possible to encapsulate integer types in double type to make the reversing a little bit harder. 可以在double类型中封装整数类型,以使反转更加困难。

Insert assembly obfuscation macros between the real code (jmp x, db 0E8h, x: etc.) 在实际代码(jmp x,db 0E8h,x:等)之间插入程序集混淆宏

Use BOOST ;) it really makes reverse engineering a pain the the ... ;) 使用BOOST;)它确实使逆向工程变得痛苦......;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM