有没有一种方法可以使用预处理器从符号的 ascii 数字生成类似 + 或 - 的运算符,而不包括该符号?
Is there a way to use the preprocessor to generate an operator like + or - from ascii number for symbol, without including that symbol?
所以我试图混淆一些 C 代码,我想知道是否有办法生成类似 &(用于地址)或 + 或 -(用于 addition/subtraction)等运算符,来自它的 hex/octal/decimal ascii 代码,而不求助于某种 table 或包含字符的东西。
理想情况下,如果不进行混淆,它会像下面这样工作:
#define ADD(a, b) (a HEX(0x2b) b)
//so ADD(10, 2) expands to 10 + 2
直接问题的答案是"no"。预处理器可以执行的唯一操作完全是替换和连接;其他一切都必须从这些构建起来,这意味着即使像 arithmetic 这样的事情也需要通过在幕后查找 tables 来实现。
但这并不一定意味着您不能按照您想到的方式混淆程序。毕竟,ASCII 本身也只是一种查找 table。所以这不是能力的问题,而是误导的问题。有几种方法可以尝试隐藏运算符查找的存在或意义 table.
例如将一些误导叠加在一起-
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
这里的查找 table 隐藏在一个看起来很吓人的系统文件中。滥用 CAT
和 STR
隐藏了文件被简单 grep
使用的事实(或者主程序引用了其中定义的宏)。查找 table 本身是在一个 #ifndef
块中定义的,大多数人会认为该块未被使用(真正的 __GNUC__
没有中间下划线),并且看起来像一个数组初始化器而不是一个预处理器列表(它仍然是一个有效的预处理器列表,因为预处理器不使用 {}
进行分组,我们可以忽略第一个和最后一个元素)充满可怕的内存初始化表达式(十六进制常量被 EAT
,并且 MEM_INIT_BASE
会自行删除)。 <vmmem/protect_init.h>
当然不存在并被上面的行注释掉(这实际上是一个非常明显的举动和坏主意,因为大多数编译器默认情况下不启用三字母,但你可以使用另一个 #ifdef
进一步向下欺骗,例如 #ifdef MEM_IN1T_BASE
或类似的东西)。
随着周围常量的自动删除,该列表只是一个无序、非统一的运算符字符列表,可以通过相对常规的SELECT
操作进行查询。对于额外的混淆,你可以例如对传入的索引执行一些预处理器数学运算,以进一步调整内容。
够不透明吗?
所以我试图混淆一些 C 代码,我想知道是否有办法生成类似 &(用于地址)或 + 或 -(用于 addition/subtraction)等运算符,来自它的 hex/octal/decimal ascii 代码,而不求助于某种 table 或包含字符的东西。
理想情况下,如果不进行混淆,它会像下面这样工作:
#define ADD(a, b) (a HEX(0x2b) b)
//so ADD(10, 2) expands to 10 + 2
直接问题的答案是"no"。预处理器可以执行的唯一操作完全是替换和连接;其他一切都必须从这些构建起来,这意味着即使像 arithmetic 这样的事情也需要通过在幕后查找 tables 来实现。
但这并不一定意味着您不能按照您想到的方式混淆程序。毕竟,ASCII 本身也只是一种查找 table。所以这不是能力的问题,而是误导的问题。有几种方法可以尝试隐藏运算符查找的存在或意义 table.
例如将一些误导叠加在一起-
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
这里的查找 table 隐藏在一个看起来很吓人的系统文件中。滥用 CAT
和 STR
隐藏了文件被简单 grep
使用的事实(或者主程序引用了其中定义的宏)。查找 table 本身是在一个 #ifndef
块中定义的,大多数人会认为该块未被使用(真正的 __GNUC__
没有中间下划线),并且看起来像一个数组初始化器而不是一个预处理器列表(它仍然是一个有效的预处理器列表,因为预处理器不使用 {}
进行分组,我们可以忽略第一个和最后一个元素)充满可怕的内存初始化表达式(十六进制常量被 EAT
,并且 MEM_INIT_BASE
会自行删除)。 <vmmem/protect_init.h>
当然不存在并被上面的行注释掉(这实际上是一个非常明显的举动和坏主意,因为大多数编译器默认情况下不启用三字母,但你可以使用另一个 #ifdef
进一步向下欺骗,例如 #ifdef MEM_IN1T_BASE
或类似的东西)。
随着周围常量的自动删除,该列表只是一个无序、非统一的运算符字符列表,可以通过相对常规的SELECT
操作进行查询。对于额外的混淆,你可以例如对传入的索引执行一些预处理器数学运算,以进一步调整内容。
够不透明吗?