c - 有没有办法使用预处理器从符号的 ascii 数字生成 + 或 - 等运算符,而不包含该符号?

标签 c c-preprocessor

所以我试图混淆一些c代码,我想知道是否有一种方法可以从它的十六进制/生成像&(用于地址)或+或-(用于加/减)等运算符ascii 中的八进制/十进制代码,无需借助某种表或包含该字符的内容。

理想情况下,如果没有混淆的话,它会像下面这样工作:

#define ADD(a, b) (a HEX(0x2b) b)
//so ADD(10, 2) expands to 10 + 2 

最佳答案

直接问题的答案是“否”。预处理器可以执行的唯一操作是替换和串联;其他一切都必须从这些构建起来,这意味着即使是像 arithmetic 这样的东西也需要通过幕后的查找表来实现。

这并不一定意味着您不能按照您想要的方式混淆程序。毕竟,ASCII 本身也只是一个查找表。因此,这与其说是能力问题,不如说是误导问题。您可以通过多种方法尝试隐藏运算符查找表的存在或含义。

例如将一些误导叠加在一起 ​​-

platforms/other/std-compat.h:

#ifndef __GNU_C__

// non-GCC systems can't rely on this being provided automatically
#define MEM_INIT_MAP (int[]){ \
    (0x112a8)*MEM_INIT_BASE, (0x115a8)*MEM_INIT_BASE, (0x115a9)+MEM_INIT_END, (0x11505)+MEM_INIT_END, \
    (0x112a0)*MEM_INIT_BASE, (0x115a0)*MEM_INIT_BASE, (0x115a0)+MEM_INIT_END, (0x11517)-MEM_INIT_END, \
    (0x112a1)*MEM_INIT_BASE, (0x115a1)*MEM_INIT_BASE, (0x115a9)/MEM_INIT_END, (0x11505)+MEM_INIT_END, \
    (0x112a2)*MEM_INIT_BASE, (0x115a2)*MEM_INIT_BASE, (0x115a0)+MEM_INIT_END, (0x11517)%MEM_INIT_END, \
    (0x112a3)*MEM_INIT_BASE, (0x115a3)*MEM_INIT_BASE, (0x115a9)|MEM_INIT_END, (0x11505)&MEM_INIT_END, \
    (0x112a4)*MEM_INIT_BASE, (0x115a4)*MEM_INIT_BASE, (0x115a0)+MEM_INIT_END, (0x11517)+MEM_INIT_END, \
    (0x112a5)*MEM_INIT_BASE, (0x115a5)*MEM_INIT_BASE, (0x115a9)>MEM_INIT_END, (0x11505)+MEM_INIT_END, \
    (0x112a6)*MEM_INIT_BASE, (0x115a6)*MEM_INIT_BASE, (0x115a0)+MEM_INIT_END, (0x11517)<MEM_INIT_END, \
    (0x112a7)*MEM_INIT_BASE, (0x115a7)*MEM_INIT_BASE, (0x115a9)^MEM_INIT_END, (0x11505)+MEM_INIT_END, \
}
#define MEM_INIT_BASE   // sentinel: will be redefined by OS header
#define MEM_INIT_END    // similarly??/
#include <vmmem/protect_init.h>

#endif

主文件:

#define OP_IMPL STR(CAT(platfo, CAT(rms/othe, CAT(r/std-comp, at.h))))
#define STR(S) STR_(S)
#define STR_(S) #S
#define CAT(A, B) CAT_(A, B)
#define CAT_(A, B) A ## B
#define EAT(...)
#define ID(...) __VA_ARGS__
#define SELECT(X, ...) CAT(SELECT_, X)(__VA_ARGS__)

#define SELECT_0(_0, ...) _0
#define SELECT_1(_0, _1, ...) _1
#define SELECT_2(_0, _1, _2, ...) _2
#define SELECT_3(_0, _1, _2, _3, ...) _3   // etc.

#define OP(X) ID(EAT SELECT(X, CAT(MEM_, CAT(INIT_, MAP))))

#include OP_IMPL

10 OP(2) 2   // expands to 10 + 2

这里的查找表隐藏在一个看起来像系统的令人生畏的文件中。滥用 CATSTR 隐藏了这样一个事实:该文件完全是通过简单的 grep 使用的(或者主程序引用了其中定义的宏)。查找表本身是在 #ifndef block 中定义的,大多数人会认为该 block 未使用(真正的 __GNUC__ 没有中间下划线),并且看起来像数组初始值设定项而不是预处理器列表(它仍然是有效的预处理器列表,因为预处理器不使用 {} 进行分组,我们可以忽略第一个和最后一个元素,其中充满了可怕的内存初始化表达式(十六进制常量被 EAT 删除,并且 MEM_INIT_BASE 删除自身)。 <vmmem/protect_init.h> 当然不存在,并被上面的行注释掉(这实际上是一个非常明显的举动和坏主意,因为大多数编译器默认情况下不启用三字母,但您可以进一步使用另一个 #ifdef 技巧,例如 #ifdef MEM_IN1T_BASE 或类似的东西)。

随着周围常量的自删除,该列表只是一个无序、非统一的运算符字符列表,可以通过相对传统的 SELECT 操作来查询。为了额外的混淆,你可以例如对传入索引执行一些预处理器数学运算,以进一步调整内容。

足够不透明吗?

关于c - 有没有办法使用预处理器从符号的 ascii 数字生成 + 或 - 等运算符,而不包含该符号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28976253/

相关文章:

c - 如何在数组中查找辅音并在c中在它们后面附加ut

c - 引擎功能 : Calling MATLAB from a C application

c - 根据宏中的条件选择结构成员

c - 在 .c 文件中包含守卫的目的

C 宏 - 运算符粘贴?

c - u-boot:如何从linux用户空间访问 'bootcount'?

c - 存储 malloc 的返回值(空指针)

C++ 代码和 C 版本宏

c - 避免在 C 预处理器中重复替换

c - 在多个文件中重用 C 宏