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;
}
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////

  

posted @ 2018-10-09 21:11  develon  阅读(1227)  评论(0编辑  收藏  举报