13. 工程的组织和防破解
问题起因:别的文件定义了宏或函数等,我们现在想利用这些已经写好的代码,如果直接#include "xxx.cpp",会重复定义。因此需要定义一些规范,方便管理以及避免编译错误。
规范:
1.任何产生处理器行为(编译为二进制代码)的代码,都在.c .pp这些源码文件中定义。
2.不产生处理器行为的代码,以及各种函数声明,函数定义和宏定义等,都在.h这类头文件中定义。
3.尽量设计宏名不重复的代码。
注意:
1.文件内多次定义同一个宏时,编译报错,#undef后,最后一次定义生效。
2.宏定义不出文件,跨文件访问宏时,此宏不存在。
3.包含文件后,形成多次定义同一个宏的,#undef后,最后一次定义生效。
4.重复定义或重复包含的后果是,要么编译不通过,报告重复定义错误,要么按最后一次的定义生成代码。
防止重复包含的方法:
在.h文件中加入以下代码:
#ifndef MYHEAD_H
#define MYHEAD_H
// 代码...
#endif // !MYHEAD_H
为了防止MYHEAD_H重复定义,可以使用guidgen.exe生成GUID:
#ifndef MYHEAD_H_1E0D1E03_4133_42E0_8ED9_ABA28FDEC638
#define MYHEAD_H_1E0D1E03_4133_42E0_8ED9_ABA28FDEC638
// 代码...
#endif // !MYHEAD_H_1E0D1E03_4133_42E0_8ED9_ABA28FDEC638
也可以使用:
#pragma once
// 代码...
宏是双刃剑,既能大大提高程序的可读性和可移植性,又能大大降低程序的可读性和可移植性,切勿滥用。
一个加密的程序可以简单表示如下:
- trueData是要保护的关键数据,先用不可加密算法算出checkValue。
- trueData和key一起加密为encryptData。
- 黑色部分是提供给用户的程序,要求用户输入key,或者从用户输入的账号密码算出对应的key,再解密encryptData,得到decryptData。
- 如果输入的key正确,就得到了trueData,如果输入的key错误,得到错误解密的data。不能直接和trueData比较,否则内存就会出现明文。因此计算出decryptData的checkValue,和正确的checkValue比较,相等则输出decryptData,也就是trueData,否则输出error。
- 即使攻击者更改了关键跳转,得到的还是错误解密的data,能用的方法只有穷举了。