[Reverse]2022弱口令安全招新赛 tea

题目下载地址:tea

数据处理

数据处理分析

做这道题的时候是第一次深入接触tea加密,tea加密后的数据按理来说都应该是32位的大数,而我在查找数据的时候犯了一个很严重的错误:

file

将图中的数据分开来去tea解密,显然这是错误的。
我们不难发现在tea算法中我们需要有一个delta值如图v4所示
file
我们发现其中的delta值是8位的16进制也就是32位的数据,那么我们就需要手动将str2里面的数据进行还原为8位数据

小端序处理

在我处理这段数据的时候,我又犯了一个很严重的错误(直接按照顺序合并),程序是小端序储存的,所以我们需要反过来合并,例如
0xAA 0xBB 0xCC 0xDD
我们合并成32位数据就是
0xDDCCBBAA
这就是小端序储存
当然我们可以手动一个个将程序还原,显然太麻烦了,我选择使用算法,算法关键代码如下:

int kk[32] =
{
  46,162,154,93,216,119,117,77,224,124,80,69,114,165,248,93,109,14,98,20,102,95,216,91,138,93,196,200,116,32,253,101
};
    unsigned int F[8]={0};
    for(int i = 0 ; i < 32 ; i+=4 )
    {
        unsigned int wei = 0x1000000;
        for(int j = 3 ; j >= 0 ; j -- )
        {
            F[cd]+=kk[i+j]*wei;
            wei/=0x100;
        }
        cd++;
    }

处理过后F数组内储存的值就是我们按照小端序规则还原后的密文了。

tea算法

tea算法简介

TEA算法使用64位的明文分组和128位的密钥,它使用Feistel分组加密框架,需要进行 64 轮迭代,尽管作者认为 32 轮已经足够了。该算法使用了一个神秘常数δ作为倍数,它来源于黄金比率,以保证每一轮加密都不相同。但δ的精确值似乎并不重要,这里 TEA 把它定义为 δ=「(√5 – 1)231」(也就是程序中的 0×9E3779B9)

tea算法加密脚本

#include <stdio.h>
#include <stdint.h>
//加密函数
void encrypt(uint32_t* v, uint32_t* k)
{  
    uint32_t v0=v[0], v1=v[1], sum=0, i;           /* set up */  
    uint32_t delta=0x9e3779b9;                     /* a key schedule constant */  
    uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];   /* cache key */  
    for (i=0; i < 32; i++)
    {                       /* basic cycle start */
        sum += delta;
        v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
        v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
    }                                              /* end cycle */
    v[0]=v0; v[1]=v1;
}

int main()  
{  
    uint32_t v[2]={1,2},k[4]={2,2,3,4};
    // v为要加密的数据是两个32位无符号整数
    // k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
    printf("加密前原始数据:%u %u\n",v[0],v[1]);
    encrypt(v, k);
    printf("加密后的数据:%u %u\n",v[0],v[1]);
    return 0;
}

tea算法解密脚本

显然异或具有可逆性,我们只需要将加密脚本反过来写,就可以得到解密脚本

void decrypt(uint32_t* v, uint32_t* k)
{
    uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i;  /* set up */
    //sum的值为delta的值乘以加密的组数,作者推荐加密32次,这里也是32次,则我们就是乘以32
    uint32_t delta=0x9e3779b9;                     /* a key schedule constant */
    uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];   /* cache key */
    for (i=0; i<32; i++)
    {                           /* basic cycle start */  
        v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
        //v1与v0顺序互换+=改为-=然后逐次递减sum
        v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
        sum -= delta;
    }                                             /* end cycle */
    v[0]=v0; v[1]=v1;
} 

正经题解:

file

看到主函数的关键函数段,输入的v9赋值给了Destination数组然后对Destination数组两两一组进行加密,显然由于程序将我们输入的字符储存为了32位数据,每位数据占用了4个字节,所以对应的Destination就是我们输入的前四个字符,和后四个字符,因此我们解密的后序需要将它再次分开。
进入::k可以看到
file

1,2,3,4便是我们的密钥
然后我们进入encrypt函数:
file

解密脚本如何构造在上文的tea分析中已经提及
我的解密思想如下:

void decrypt(unsigned int *a1,int *a2)
{
//  char *result; // rax
    int i; // [rsp+10h] [rbp-10h]
    unsigned int v4;
    v4=0xa6768e00;// [rsp+14h] [rbp-Ch]
    unsigned int v5; // [rsp+18h] [rbp-8h]
    unsigned int v6; // [rsp+1Ch] [rbp-4h]

    v6 = *a1;
    v5 = a1[1];
    for ( i = 0; i <= 31; ++i )
    {
        v5 -= (v6 + v4) ^ (a2[2] + 16 * v6) ^ ((v6 >> 5) + a2[3]);
        v6 -= (v5 + v4) ^ (a2[0] + 16 * v5) ^ ((v5 >> 5) + a2[1]);
        v4 -= 0xD33B470;    
    }
    *a1 = v6;
    a1[1] = v5;
}

接下来就可以构造我们的解题代码了,str2的处理方式在上文小端序的介绍中已经提及
这里要注意的就是
我们在解密完成后会获得8组32位的大数,我们需要将它们按照小端序的规则分开再进行格式化字符串输出,我的输出思想如下:

    for(int i = 0 ; i < 8 ; i ++ )
    {
        unsigned temp = flag[i];//flag[i]为tea解密后留下的8组32位大数据
        for(int j = 0 ; j < 4 ; j++ )
        {
            int tmp = temp%0x100;
            temp/=0x100;
            printf("%c",tmp);
        }
    }

最后就可以直接构造脚本了

EXP

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<string>
#include<cstring>
#include<list>
#include<stdlib.h>
#include<windows.h>
using namespace std;
typedef int status;
typedef int selemtype;

int kk[32] =
{
  46,162,154,93,216,119,117,77,224,124,80,69,114,165,248,93,109,14,98,20,102,95,216,91,138,93,196,200,116,32,253,101
};
int a2[4]={1, 2, 3, 4};
void decrypt(unsigned int *a1,int *a2)
{
//  char *result; // rax
    int i; // [rsp+10h] [rbp-10h]
    unsigned int v4;
    v4=0xa6768e00;// [rsp+14h] [rbp-Ch]
    unsigned int v5; // [rsp+18h] [rbp-8h]
    unsigned int v6; // [rsp+1Ch] [rbp-4h]

    v6 = *a1;
    v5 = a1[1];
    for ( i = 0; i <= 31; ++i )
    {
        v5 -= (v6 + v4) ^ (a2[2] + 16 * v6) ^ ((v6 >> 5) + a2[3]);
        v6 -= (v5 + v4) ^ (a2[0] + 16 * v5) ^ ((v5 >> 5) + a2[1]);
        v4 -= 0xD33B470;    
    }
    *a1 = v6;
    a1[1] = v5;
}
int main()
{
    unsigned int flag[8],F[8]={0};
    int cd = 0;
    for(int i = 0 ; i < 32 ; i ++ )
    {
        printf("%X ",kk[i]);
    }
    cout<<endl;
    for(int i = 0 ; i < 32 ; i+=4 )
    {
        unsigned int wei = 0x1000000;
        for(int j = 3 ; j >= 0 ; j -- )
        {
            F[cd]+=kk[i+j]*wei;
            wei/=0x100;
        }
        cd++;
    }
    for(int i = 0 ; i < 8 ; i ++ )
    {
        printf("0x%X",F[i]);
        if(i!=7)    cout<<",";
    }

    cout<<endl;
    for(int i = 0 ; i<  8 ; i +=2 )
    {
        unsigned int tmp[2];
        tmp[0]=F[i];
        tmp[1]=F[i+1];
        decrypt(tmp,a2);
        flag[i]=tmp[0];
        flag[i+1]=tmp[1];
    }
    cout<<endl;
    for(int i = 0 ; i < 8 ; i ++ )
    {
        unsigned temp = flag[i];
        for(int j = 0 ; j < 4 ; j++ )
        {
            int tmp = temp%0x100;
            temp/=0x100;
            printf("%c",tmp);
        }
    }
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇