我想编写一些简单的防篡改机制,在运行时计算某些函数(或基本块)的校验和,并将其与固定的预计算值进行比较。如果校验和匹配,那么一切都很好;否则程序终止。
我可以在运行时轻松计算校验和,但我不知道如何计算固定值以进行比较。
我想我在编译后对二进制文件进行了一些后期处理,因为在编译时不可能知道校验和(对吧?)。
但是如何在二进制代码中找到与我的函数(或基本块)对应的代码点?我可以使用一些十六进制编辑器手动执行此操作,但我希望自动执行此过程。在预先计算了校验和后,我需要修改二进制文件以包含它 - 但这又要求能够在二进制文件中找到正确的位置。
对解决方案的任何建议?
答案 0 :(得分:0)
例如,您可以获得指向函数的指针并将其重新解释为uint8_t的数组。如果您不希望编译器在某个循环中使用该函数的内联副本,您也可以禁用特定函数的内联。
uint8_t* pMain = (uint8_t*)&main;
然后你必须尝试估计函数长度并计算校验和。
答案 1 :(得分:0)
如果您的代码包含多个文件,您可以遵循以下机制:
使用您希望将来检查的功能编译文件
找到已编译的文件(最可能是.o,.obj)函数位置 - 例如使用objdump或类似工具 - 它必须显示人类可读文本以及编译代码的十六进制代码
< / LI> 醇>示例:
objdump a.o -d --insn-width = 10
40064b: 48 89 e5 mov %rsp,%rbp
40064e: ff d0 callq *%rax
400650: 5d pop %rbp
400651: e9 7a ff ff ff jmpq 4005d0 <register_tm_clones>
0000000000400656 <calculate>:
400656: 55 push %rbp
400657: 48 89 e5 mov %rsp,%rbp
40065a: 89 7d ec mov %edi,-0x14(%rbp)
40065d: 48 89 75 e0 mov %rsi,-0x20(%rbp)
400661: 8b 05 f9 09 20 00 mov 0x2009f9(%rip),%eax # 601060 <magicCRC1>
400667: 89 c2 mov %eax,%edx
400669: 48 8b 45 e0 mov -0x20(%rbp),%rax
40066d: 89 10 mov %edx,(%rax)
40066f: 48 8b 45 e0 mov -0x20(%rbp),%rax
400673: 48 83 c0 04 add $0x4,%rax
400677: c7 00 01 00 00 00 movl $0x1,(%rax)
40067d: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
400684: eb 72 jmp 4006f8 <calculate+0xa2>
400686: 83 7d fc 01 cmpl $0x1,-0x4(%rbp)
40068a: 75 1c jne 4006a8 <calculate+0x52>
40068c: 8b 45 fc mov -0x4(%rbp),%eax
40068f: 48 98 cltq
所以在objdump函数的情况下,name会被&lt;包围&GT; - 以上计算函数的例子
编写脚本来解析它 - 你需要在地址和反汇编代码之间使用十六进制代码
计算你的CRC,哈希或任何你需要的东西
存储CRC以及块长度以便稍后在运行时解码它在一个文件中也将被编译 - 当然你需要知道映射什么变量/常量保持哪个函数CRC
链接所有文件
如果单个文件可用(完整的可执行文件),您可以: