前言:熟悉的夜晚,记录一下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好奇妙,爬