逆向中的Tea加解密算法案例

前言:熟悉的夜晚,记录一下Tea的加解密方法,由于时间原因,这个不会太探究原理,只作为一个案例来写,主要是根据xman的一个pwn题,魔改Tea

算法原理

明文长度分组为64位(8字节),密钥长度为128位(16字节),明文和密钥进入32轮循环,得到最后的64位密文。其中magic number DELTA是由黄金分割点得到。 算法比较简单源码如下

#include<stdio.h>
#define DELTA 0x9e3779b9

void tea_encrypt(unsigned int* v, unsigned int* key) {
  unsigned int l = v[0], r = v[1], sum = 0;
  for (size_t i = 0; i < 32; i++) { //进行32次迭代加密,Tea算法作者的建议迭代次数
    l += (((r << 4) ^ (r >> 5)) + r) ^ (sum + key[sum & 3]);
    sum += DELTA; //累加Delta的值
    r += (((l << 4) ^ (l >> 5)) + l) ^ (sum + key[(sum >> 11) & 3]); //利用多次双位移和异或将明文与密钥扩散混乱,并将两个明文互相加密
  }
  v[0] = l;
  v[1] = r;
}

void tea_decrypt(unsigned int* v, unsigned int* key) {
  unsigned int l = v[0], r = v[1], sum = 0;
  sum = DELTA * 32; //32次迭代累加后delta的值
  for (size_t i = 0; i < 32; i++) {
    r -= (((l << 4) ^ (l >> 5)) + l) ^ (sum + key[(sum >> 11) & 3]);
    sum -= DELTA;
    l -= (((r << 4) ^ (r >> 5)) + r) ^ (sum + key[sum & 3]);
  }
  v[0] = l;
  v[1] = r;
}

int main(int argc, char const *argv[])
{
    unsigned int key[4]={0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f};
    unsigned int v1[2] = {0xaabbccdd,0x01234567};

    tea_encrypt(v1,key);
    printf("tea_encrypt:%x %x\n",v1[0],v1[1]);

    tea_decrypt(v1,key);
    printf("tea_decrypt:%x %x\n",v1[0],v1[1]);
    return 0;
}

xman 一个pwn题来具体简绍如何解密Tea

_BOOL8 __fastcall sub_11F0(_BYTE *a1)
{
  sub_1035((unsigned int *)a1);
  return *a1 == 0x1E
      && a1[1] == 0x19
      && a1[2] == 0x5D
      && a1[3] == 0x10
      && a1[4] == 0xC8
      && a1[5] == 0x70
      && a1[6] == 0xE8
      && a1[7] == 0x98;
}
__int64 __fastcall sub_1035(unsigned int *a1)
{
  __int64 result; // rax
  int i; // [rsp+1Ch] [rbp-3Ch]
  unsigned int v3; // [rsp+20h] [rbp-38h]
  unsigned int v4; // [rsp+24h] [rbp-34h]
  unsigned int v5; // [rsp+28h] [rbp-30h]
  int v6[6]; // [rsp+38h] [rbp-20h]
  unsigned __int64 v7; // [rsp+50h] [rbp-8h]

  v7 = __readfsqword(0x28u);
  v6[0] = 0x28371234;
  v6[1] = 0x19283543;
  v6[2] = 0x19384721;
  v6[3] = 0x98372612;
  v3 = *a1;
  v4 = a1[1];
  v5 = 0;
  for ( i = 0; i <= 31; ++i )
  {
    v3 += (((v4 >> 5) ^ (16 * v4)) + v4) ^ (v6[v5 & 3] + v5);
    v5 -= 0x61C88647;
    v4 += (((v3 >> 5) ^ (16 * v3)) + v3) ^ (v6[(v5 >> 11) & 3] + v5);
  }
  *a1 = v3;
  result = v4;
  a1[1] = v4;
  return result;
}

解密exp.c:

#include <stdio.h> 
#include <stdlib.h> 
unsigned int key[4]={0x28371234,0x19283543,0x19384721,0x98372612}; 
unsigned int firstChunk=0x105d191e; 
unsigned int secondChunk=0x98e870c8; //倒叙就可以拉
//unsigned int firstChunk=0x9a3df895;  
//unsigned int secondChunk=0xb2a32f77; 
int main() { 
	unsigned int sum = 0; 
	unsigned int v0 = firstChunk; 
	unsigned int v1 = secondChunk; 
	unsigned int delta = 0x14872109; //0x61C88647
	for (int j=0;j<=16;j++) { 
		sum += delta; 
	}
	for (int i = 0; i <= 16; i++) { 
		v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]); 
		sum -= delta; 
		v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]); 
	}
	printf("0x%x\n",v0); printf("0x%x\n",v1); 
}

//v4 += (((v3 >> 5) ^ (16 * v3)) + v3) ^ (v6[(v5 >> 11) & 3] + v5);   v4 = a1[1];

//v4 += (((v3 >> 5) ^ (16 * v3)) + v3) ^ (v6[(v5 >> 11) & 3] + v5);

Tea好奇妙,爬

上一篇:杭州电 1052 Tian Ji -- The Horse Racing(贪婪)


下一篇:C# 如何添加Word文本和图片超链接