从零开始的RC4

从零开始的rc4

rc4作为流加密算法的一员还是经常用到的,直接贴上源码

void rc4_init(unsigned char*s,unsigned char*key, unsigned long Len){
int i=0,j=0;
char k[256]={0};
unsigned char tmp=0;
for(i=0;i<256;i++) {
    s[i]=i;//先用1-256初始化s盒
    k[i]=key[i%Len];//打乱密钥顺序
}
for(i=0;i<256;i++) {
    j=(j+s[i]+k[i])%256;
    tmp=s[i];
    s[i]=s[j];//交换s[i]和s[j]
    s[j]=tmp;
}}//搅乱s盒保证s盒的随机性与非线性

这部分主要根据用户的输入生成了s-box,先看第一个题目吧,可以轻松的找到密钥生成函数

123

可以看到这里的result就是搅乱后的s盒,至于密钥可以去内存里dump下,看下调用的函数的地址是401100,可以看到传递的第二个参数就是key,也就是SimpleCryptography

123

现在可以去看看加密函数,先贴上源码

void rc4_crypt(unsigned char*s,unsigned char*Data,unsigned long Len){
int i=0,j=0,t=0;
unsigned long k=0;
unsigned char tmp;
for(k=0;k<Len;k++)
{
    i=(i+1)%256;
    j=(j+s[i])%256;
    tmp=s[i];
    s[i]=s[j];//交换s[x]和s[y]
    s[j]=tmp;
    t=(s[i]+s[j])%256;
    Data[k]^=s[t];
}}

可以看到rc4就是异或加密,一旦生成的密钥流找到了,密文也就是明文几乎一摸一样

123

下面是本题的加密部分,加密结束之后和7C553E5F0EB4CCB977BF6BD960E0B968FB11CED2154B0EB5F73E51EE514D5A9C01A0C53AD038比较,也就是说上面那长串是密文

123

可以去看下生成的s盒

123

现在加密结束了,也有了密钥,等于说可以解出flag了,这里有两种方法,一种直接用源码解密,一种自己去内存里找到密钥流dump下来和密文异或下就行了

123

这一题还是比较简单的,一点都没有魔改算法,并且密文和密钥给的很明显,再看下面一题elf文件,也同样是rc4,打开发现是64位elf文件,一开始似乎有个奇怪的操作,先点进去给函数重命名下,其中有异或和加法,其中有一个函数不是很清楚,看下idaview,如果传入的是x的话,可以发现return的是x+(x+1)&7+16,继续向下看main函数

123

发现。。是以call寄存器的方式去调用函数的,还是动调下

123

先找到这个call的地址

123

可以动调时判断出这里取出了输入的username的前5位和admin比较,那么username可以知道是admin,v15顺便可以定义为memcmp函数

123

这里把输入的密码命名为pwd,发现最后是field_50和field_90相比较的,那么就继续向上找,j是循环次数,也就是pwd的下标,忽视前面的所有,归根到底还是一个异或,去动调下找到后面那个数组和比较的密文的就行了(一开始分析起来很麻烦,后来新建了结构体发现简单了很多,果然这个东西很重要)

123

先去看下在哪里可以找到密文和异或的数组,在伪代码窗口右击copy to a什么的就可以把注释和重命名复制到汇编窗口查看了,还是挺方便的,可以看到内存中此时的eax保存的是0x31也就是我输入的1的ascii码,底下一个call rbx应该就是调用的结构体里面的xor方法,这样一来异或的密钥就知道了

123

可以看到异或的第一个数据是d3

123

依次类推可以找到全部的密钥,为d3 e2 00 9c c5 b4 cc de 5d 35 8d 56 1a 9f91 90 26 f1 f1 ab

123

然后就是找密文了,在经过这0x13次循环异或之后就走到了判断的地方,直接看传入memcmp的两个参数就可以找到密文了。得到flag是Ea4y_A1l3ged_RC4_rE,但是说实话除了最后一步和rc4都是和密钥异或外,我并没能识别出rc4,如果有dalao可以指点下更好了,QQ858689519,这题就是在不知道密钥的情况下直接找出密钥流和密文解密,还是直接参考的,而且第一次自己新建结构体帮助分析,学习了