Crypto知识 S

Crypto知识 S

Hash

Hash是将任意长度的消息压缩成固定长度散列值的算法。常见的Hash加密算法有MD5,SHA系列等等。

由于Hash算法不可逆,所以想要获得原消息基本上是采取正向爆破的方法。方法有使用python脚本和Hashcat。

Hashcat

比如现在知道hash值是2d6c7ed3df6905dfeb89a99e7322eadd5482f1295679416bfe3e9cea1a63243d,消息是九位,前三位是ycF,sha256加密(-m 1400)。那么使用命令(-a 3掩码攻击):

.\hashcat.exe -a 3 -m 1400 --force 2d6c7ed3df6905dfeb89a99e7322eadd5482f1295679416bfe3e9cea1a63243d ycF?a?a?a?a?a?a

可以爆破原文为ycFm@5t3r。

008b35dc8300d2faaf3901301c5bcae7

python

import itertools
#import hmac
key = '2100'
dir = '1234567890'//爆破所用到的字典,这里猜全是数字
dir_list = itertools.product(dir, repeat=6)
for i in dir_list:
        data=i[0]+i[1]+i[2]+i[3]+i[4]+i[5]
        secrets=sha256((key+data).encode('utf-8')).hexdigest()
        if(secrets=='3a5137149f705e4da1bf6742e62c018e3f7a1784ceebcb0030656a2b42f50b6a'):
            print(data)
            break

识别

一般Py、Java、C#这些都有Hash相关库,直接看名字。

不过还有加盐哈希之类的,暂时还没遇到。

之前看到做Crypto的大佬听绿wyc做hash相关密码题,还有什么维纳攻击,真是可怕呀这群人.jpg

TEA家族

其实TEA算法的难点(对个人)不在于设计算法,毕竟加密那三步倒过来就是解密,而在于从IDA Pro里面提取正确的数据,编写exp的时候也要注意数据类型......感觉除了那种密码里面的TEA签到,每次做到TEA相关的都出问题。

TEA

img

#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;
}
 
//解密函数
void decrypt (uint32_t* v, uint32_t* k) {
    uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, 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 */
        v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
        v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
        sum -= delta;
    }                                              /* 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]);
    decrypt(v, k);
    printf("解密后的数据:%u %u\n",v[0],v[1]);
    return 0;
}

过程都好理解,但是解题过程中,会产生数据类型等等相关问题。TEA加密的单位是一个8bytes即64bits大小的整数,v[0],v[1]分别是32bits。然而我们通过IDA Pro获取到的往往是unsigned char类型的数组。因此我们在用C/C++编写exp的时候,应使用uint32_t*来对密文数组进行访问。例如Newstar 2024 week2 drink_tea的exp:

#include<stdio.h>
#include<stdint.h>
using namespace std;

void decrypt(uint32_t *v,uint32_t *k)
{
	uint32_t delta=2654435769;
    uint32_t v0=v[0],v1=v[1],sum=(32)*delta;
	for(int i=0;i<32;i++)
	{ 
    	v1 -= (k[3] + (v0 >> 5)) ^ (sum + v0) ^ (k[2] + 16 * v0);
	    v0 -= (k[1] + (v1 >> 5)) ^ (sum+ v1) ^ (*k + 16 * v1);
	    sum-=delta;	
	}	
	v[0]=v0;
	v[1]=v1;
}

int main()
{
	unsigned char key[]="WelcomeToNewStar";
	unsigned char enc[] =
    {
      0x78, 0x20, 0xF7, 0xB3, 0xC5, 0x42, 0xCE, 0xDA, 0x85, 0x59, 
      0x21, 0x1A, 0x26, 0x56, 0x5A, 0x59, 0x29, 0x02, 0x0D, 0xED, 
      0x07, 0xA8, 0xB9, 0xEE, 0x36, 0x59, 0x11, 0x87, 0xFD, 0x5C, 
      0x23, 0x24
    }; 
    uint32_t* k=(uint32_t*)key;
    uint32_t* v=(uint32_t*)enc;
    for(int i=0;i<8;i+=2)
    {
    	decrypt(v+i,k);
	}
	for(int i=0;i<32;i++)
	 printf("%c",enc[i]);
	return 0;
 } 
//flag{There_R_TEA_XTEA_and_XXTEA}

值得注意的有几点:

1.从21~28行可见key与enc是unsigned char类型的数组;

2.从29~30行可见,分别使用了k,v两个uint32_t类型的指针指向两个unsigned char数组的首地址。

3.循环时,v的地址变化是0,2,4,6,共有四组,这意味着enc数组中的32个字符被分为4组,每组8个作为一个64位整数进行加密。

XTEA

XTEA是TEA的加强版。

与TEA类似,XTEA加密中的重要数据有:密钥,δ,轮数等。

这里的密钥可以是128bits,256bits,512bits等等。而δ和轮数也一般是黄金分割率和32/64轮。

其实跟TEA没有太大区别,只是每轮加密算法稍微复杂一些,写exp的思路也没有变,就是照猫画虎倒着写:

#include <stdio.h>
#include <stdint.h>
 
/* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */
 
void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
    unsigned int i;
    uint32_t v0=v[0], v1=v[1], sum=0, delta=0x9E3779B9;
    for (i=0; i < num_rounds; i++) {
        v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
        sum += delta;
        v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
    }
    v[0]=v0; v[1]=v1;
}
 
void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
    unsigned int i;
    uint32_t v0=v[0], v1=v[1], delta=0x9E3779B9, sum=delta*num_rounds;
    for (i=0; i < num_rounds; i++) {
        v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
        sum -= delta;
        v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
    }
    v[0]=v0; v[1]=v1;
}
 
int main()
{
    uint32_t v[2]={1,2};
    uint32_t const k[4]={2,2,3,4};
    unsigned int r=32;//num_rounds建议取值为32
    // v为要加密的数据是两个32位无符号整数
    // k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
    printf("加密前原始数据:%u %u\n",v[0],v[1]);
    encipher(r, v, k);
    printf("加密后的数据:%u %u\n",v[0],v[1]);
    decipher(r, v, k);
    printf("解密后的数据:%u %u\n",v[0],v[1]);
    return 0;
}

XXTEA

进一步加强,key的长度可以不是4的倍数了。

#include <stdio.h>
#include <stdint.h>
#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))
 
void btea(uint32_t *v, int n, uint32_t const key[4])
{
    uint32_t y, z, sum;
    unsigned p, rounds, e;
    if (n > 1)            /* Coding Part */
    {
        rounds = 6 + 52/n;
        sum = 0;
        z = v[n-1];
        do
        {
            sum += DELTA;
            e = (sum >> 2) & 3;
            for (p=0; p<n-1; p++)
            {
                y = v[p+1];
                z = v[p] += MX;
            }
            y = v[0];
            z = v[n-1] += MX;
        }
        while (--rounds);
    }
    else if (n < -1)      /* Decoding Part */
    {
        n = -n;
        rounds = 6 + 52/n;
        sum = rounds*DELTA;
        y = v[0];
        do
        {
            e = (sum >> 2) & 3;
            for (p=n-1; p>0; p--)
            {
                z = v[p-1];
                y = v[p] -= MX;
            }
            z = v[n-1];
            y = v[0] -= MX;
            sum -= DELTA;
        }
        while (--rounds);
    }
}
int main()
{
    uint32_t v[2]= {1,2};
    uint32_t const k[4]= {2,2,3,4};
    int n= 2; //n的绝对值表示v的长度,取正表示加密,取负表示解密
    // v为要加密的数据是两个32位无符号整数
    // k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
    printf("加密前原始数据:%u %u\n",v[0],v[1]);
    btea(v, n, k);
    printf("加密后的数据:%u %u\n",v[0],v[1]);
    btea(v, -n, k);
    printf("解密后的数据:%u %u\n",v[0],v[1]);
    return 0;
}

改天贴几道XTEA和XXTEA的例题。

END

posted @ 2024-10-31 17:09  brs7  阅读(1)  评论(0编辑  收藏  举报