前言
刷题过程中碰到一道恶心了我半天的题,但归根到底还是自己菜。。。。。。
一、题目分析
程序拖入IDA,跟进main函数后发现如下内容:
两个函数一个比较,先看看第一个函数干了什么,跟进sub_400894:
利用给定的参数0xB7E1516、0x61C88647生成了一个数组,里面包含26个int型数,后面又和v4进行了相关运算,相当于用v4混淆掉刚才生成的数组
获取输入后执行了sub_4006FC:
![在这里插入图片描述](https://img-blog.csdnimg.cn/f76095cf8ba24f5a从v5中取前两个,与明文中取两个相加,然后循环12轮,每次从v5中取两个,和前面经过sub_400676函数的内容相加,sub_00676是一个移位的函数:
最后给出了v6加密后正确的值,只要我们的输入经过运算后能够和结果对上就行了,这里主要是考察对加密算法的理解,这个整个运算的过程就是一个RC5加密,答案就是解密就行了,但是这个题目魔改了一个地方,刚开始时候我并没有发现,而是按照标准的RC5进行解密,发现解出来的结果不对,以为是脚本的问题,或者数据输入格式的问题,但是经过后面认真比对代码,以及动态调试验证,发现加密函数里取子密钥的地方并不是按照标准RC5加密进行的,标准RC5加密是按顺序取,也就是说:
这个地方的索引会和轮数k保持一致,而本题是保持了和取明文的索引的一致,所以用标准的RC5解密脚本不行,需要在解密函数对应的这个地方进行对应的修改即可。
二、代码示例
1.引入库
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
int w=32;//字长 32bit 4字节
int r=12;//12;//加密轮数12
int b=16;//主密钥(字节为单位8bit)个数 这里有16个
int t=26;//2*r+2=12*2+2=26
int c=4; //主密钥个数*8/w = 16*8/32
typedef unsigned long int FOURBYTEINT;//四字节
typedef unsigned short int TWOBYTEINT;//2字节
typedef unsigned char BYTE;
void InitialKey(unsigned char* KeyK,int b);
void generateChildKey(unsigned char* KeyK,FOURBYTEINT* ChildKeyS);
void Encipher(FOURBYTEINT* In,FOURBYTEINT* Out,FOURBYTEINT* S);
void Decipher(FOURBYTEINT* In,FOURBYTEINT* Out,FOURBYTEINT* S);
#define NoOfData 4
/**2、循环移位函数
由于在生成子密钥,加密,解密过程中都要进行循环移位,故要首先定义循环以为函数。
* 循环左移和右移函数
* x : 被循环的数
* y : 将要循环的位数
*/
#define ROTL(x,y) (((x)<<(y&(w-1))) | ((x)>>(w-(y&(w-1)))))
#define ROTR(x,y) (((x)>>(y&(w-1))) | ((x)<<(w-(y&