XOR 加密
XOR 是一个神奇的运算符, 观察它的真值表, 很容易得到以下结论:
假设现有 a , b 变量, 则
a ^ 0 == a
a ^ 0xff == ~a (取反加1等于作为补码的a的真值的相反数的补码, 比如0xff 取反加1 为 -1 的相反数 1 的补码 0x1, 0x0 取反加1 等于 0 的相反数 0 的补码, XOR 和相反数挂钩了!)
a ^ a == 0
XOR 满足交换律和结合律
a ^ b == b ^ a
a ^ b ^ a == b ^ (a ^ a) == b ^ 0 == b
这样一来, 可以使用一个中间变量 b , 使得 a ^ b 的值可以复原为 a , 这不正符合动态加密的需求吗?
说这些很无聊, 观察以下程序:
请问输出是什么? 抱歉, 我选择死亡!
问尼玛啊, 直接 Run 后观察不就好了?
如果你的程序有这种类似的提示, 那么很抱歉, 你将带给黑客极其重要的线索, 他只需简单地一调试, 关键代码就被定位到啦!
比如使用x64dbg定位字符串
剩下的先不说了, 我们写一个加密的程序吧?
这样一来, 可以在代码中使用混淆的数据了, 注意把解密函数和密钥隐藏起来哦.
/** *加密神器 *对 long 和字符串进行 XOR 加密 */ #include <stdio.h> #include <stdlib.h> #include <locale.h> #include <tchar.h> #include <string.h> unsigned int key; // 打印Usage void printUsage(); // initializing void init(); // encry int encry(void *source, unsigned char key, unsigned short length); // get the hex type string char *catX(const char *source, unsigned short length); // decode char *decode(const char *source, unsigned char key); void *ndecode(const void *source, unsigned char key, unsigned short length); /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// int main(int argc, const char **argv) { init(); if (argc != 4) { $Return: printUsage(); return 0; } if (sscanf(argv[3], "%x", &key) != 1) { wprintf(L"key是一个 8 bit 十六进制数, 请检查!\n"); return 1; } if (strcmp(argv[1], "-s") == 0) { // eg: encry -s "支付失败!" 33 // 用户选择的是字符串加密 int length = strlen(argv[2]); wprintf(L"加密字符串 \"%S\" , 共 %d 个字节.\n", argv[2], length); char *str = (char *) malloc(length + 1); if (str == NULL) return 2; if (strncpy(str, argv[2], length+1) == NULL){ return 1; } if (encry(str, key, length) != 0) return 1; wprintf(L"加密后显示为(key-0x%X):\n" L"\"%S\"", key, (const char *)str); puts(""); wprintf(L"加密前后的 ASCII 字串形式:\n" "\"%S\"\n" "\"%S\"\n", catX(argv[2], length), catX(str, length)); char *deco = decode(str, key); wprintf(L"尝试解码:\n" "\"%S\"", deco); free(str); free(deco); } else if (strcmp(argv[1], "-n") == 0) { // 用户选择的是 long 加密 long n = 0; if (sscanf(argv[2], "%ld", &n) != 1) { wprintf(L"请检查输入!\n"); return 1; } wprintf(L"加密整数 %ld :\n", n); encry(&n, key, sizeof(n)); printf("0x%lX\n", n); wprintf(L"尝试解密:\n%ld\n", *(long *)ndecode(&n, key, sizeof(n))); } else { goto $Return; } return 0; } void init() { // 本地化相关 setlocale(LC_CTYPE, ""); } void printUsage() { printf("%S", L"Usage:\n" "\t encry -s <要加密的字符串> <key>\n" "\t encry -n <要加密的整数> <key>\n"); } int encry(void *source, unsigned char key, unsigned short length) { if (source == NULL) { printf("NULL Pointer Exception\n"); return -1; } int i = 0; for (; i < length; i ++ ) { ((unsigned char *) source)[i] ^= key; } return 0; } char * catX(const char *source, unsigned short length) { if (source == NULL) { return NULL; } int n = 4 * length, i = 0; char *str = (char *) malloc(n + 1); *str = '\0'; for (; i < length; i ++ ) { unsigned char byte = source[i]; char tmp[5] = { 0 }; tmp[0] = '\\'; tmp[1] = 'x'; sprintf(&tmp[2], "%x", byte); strcat(str, tmp); } return str; } char * decode(const char *source, unsigned char key) { if (source == NULL) { printf("NULL Pointer Exception\n"); return NULL; } int length = strlen(source); char *str = (char *) malloc(length + 1); strncpy(str, source, length + 1); while (*str != '\0') { *str++ ^= key; } return str - length; } void * ndecode(const void *source, unsigned char key, unsigned short length) { if (source == NULL) return NULL; void *data = malloc(length); memcpy(data, source, length); int i = 0; for (; i < length; i ++ ) { ((char *) data)[i] ^= key; } return data; } /////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////