Re常见简单密码
起码没有Crypto专项那么柜物。。。
文章目录
- Re常见简单密码
- 1. RC4算法
- 2. TEA算法
- 3. XTEA算法
- 4. XXTEA算法
- 5. DASCTF strangeprograme
- 参考
C语言stdint.h
提供如下类型
int8_t 八位有符号整数
uint8_t 八位无符号整数
int16_t
int32_t
int64_t 64为有符号整数c_char_p char类型指针
1. RC4算法
RC4加密算法流程剖析结合CTF逆向签到 栀花谢了春红
RC4是对称加密中特殊的流加密算法,操作如下:
- 密钥调度KSA,初始化一个S表,用种子密钥填充另一个256字节的K表,用K表对S表进行初始置换。
- 伪随机字节流(密钥流)生成,使用KSA生成的状态数组S来生成伪随机字节流
- 通过伪随机字节流,也就是密钥流来与明文流进行异或
import binasciidef KSA(key):""" Key Scheduling Algorithm (KSA) """key_length = len(key)S = list(range(256)) # 对S表线性填充,一个字节范围0-255j = 0for i in range(256): # 打乱S盒j = (j + S[i] + key[i % key_length]) % 256S[i], S[j] = S[j], S[i] # swapreturn Sdef PRGA(S):""" Pseudo-Random Generation Algorithm (PRGA) """# 伪随机数生成算法i = 0j = 0while True:i = (i + 1) % 256j = (j + S[i]) % 256S[i], S[j] = S[j], S[i] # swapK = S[(S[i] + S[j]) % 256]yield K #生成器函数def RC4(key, plaintext):""" RC4 encryption/decryption """key = [ord(c) for c in key]S = KSA(key)keystream = PRGA(S)result = []for char in plaintext:val = ("%02x" % (ord(char) ^ next(keystream))) # XOR and format as hexresult.append(val)return ''.join(result)def RC4_decrypt(key, ciphertext_hex):""" RC4 decryption """key = [ord(c) for c in key]S = KSA(key)keystream = PRGA(S)ciphertext_bytes = binascii.a2b_hex(ciphertext_hex) #16进制数据的字符串转包含二进制数据的字节字符串result = []for byte in ciphertext_bytes:val = chr(byte ^ next(keystream)) # XOR with keystream and convert to charresult.append(val)return ''.join(result)# 示例
key = 'woodpecker'
plaintext = "hello world!"
ciphertext = RC4(key, plaintext)
print(f"密文: {ciphertext}")#密文: 8f45c2f7528c3ae9624bb3a9
plaintext2=RC4_decrypt(key,ciphertext)
print("明文: %s"%(plaintext2))#明文: hello world!
2. TEA算法
Tiny Encryption Algorithm是一种分组密码算法,使用64位的明文分组和128位的密钥,通过不断增加的Delta(黄金分割率)值和Feistel结构进行加密,迭代次数一般为32轮。
C语言代码如下
#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;uint32_t delta=0x9e3779b9;uint32_t k0=k[0],k1=k[1],k2=k[2],k3=k[3];for(i=0;i<32;i++){sum+=delta;v0+=((v1<<4)+k0)^(v1+sum)^((v1>>5)+k1);v1+=((v0<<4)+k2)^(v0+sum)^((v0>>5)+k3);} 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; //这里的sum是0x9e3779b9*32后截取32位的结果,截取很重要。uint32_t delta=0x9e3779b9;uint32_t k0=k[0],k1=k[1],k2=k[2],k3=k[3];for (i=0;i<32;i++){v1-=((v0<<4)+k2)^(v0+sum)^((v0>>5)+k3);v0-=((v1<<4)+k0)^(v1+sum)^((v1>>5)+k1);sum-=delta;} v[0]=v0;v[1]=v1;
}int main()
{uint32_t v[2]={1,2},k[4]={2,2,3,4};printf("加密前的数据:%u %u\n",v[0],v[1]); //%u 以十进制形式输出无符号整数 encrypt(v,k);printf("加密后数据:%u %u\n",v[0],v[1]);decrypt(v,k);printf("解密后数据:%u %u\n",v[0],v[1]);return 0;
}
python代码如下
from ctypes import *def encrypt(v, k):v0 = c_uint32(v[0]) #明文左部分v1 = c_uint32(v[1])sum1 = c_uint32(0)delta = 0x9e3779b9for i in range(32):sum1.value += deltav0.value += ((v1.value << 4) + k[0]) ^ (v1.value + sum1.value) ^ ((v1.value >> 5) + k[1])v1.value += ((v0.value << 4) + k[2]) ^ (v0.value + sum1.value) ^ ((v0.value >> 5) + k[3])return v0.value, v1.valuedef decrypt(v, k):v0 = c_uint32(v[0])v1 = c_uint32(v[1])delta = 0x9e3779b9sum1 = c_uint32(delta * 32)for i in range(32):v1.value -= ((v0.value << 4) + k[2]) ^ (v0.value + sum1.value) ^ ((v0.value >> 5) + k[3])v0.value -= ((v1.value << 4) + k[0]) ^ (v1.value + sum1.value) ^ ((v1.value >> 5) + k[1])sum1.value -= deltareturn v0.value, v1.valueif __name__ == '__main__':a = [1, 2]k = [2, 2, 3, 4]print("加密前数据:", a)#8字节明文,16字节密钥,8字节密文res = encrypt(a, k)print("加密后的数据:", res)res = decrypt(res, k)print("解密后数据:", res)
3. XTEA算法
XTEA相较TEA增加了更多的密钥表,移位和异或操作,设计者是 Roger Needham, David Wheeler。
一般情况,明文8字节,密钥16字节,密文8字节
C语言代码
#include<stdio.h>
#include<stdint.h>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; //这里是加密轮数,自己设置 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;
}
python代码如下
from ctypes import *
def encrypt(v,k):v0=c_uint32(v[0])v1=c_uint32(v[1])sum1=c_uint32(0)delta=0x9e3779b9for i in range(32):v0.value+=(((v1.value<<4)^(v1.value>>5))+v1.value)^(sum1.value+k[sum1.value&3])sum1.value+=deltav1.value+=(((v0.value<<4)^(v0.value>>5))+v0.value)^(sum1.value+k[(sum1.value>>11)&3])return v0.value,v1.valuedef decrypt(v,k):v0=c_uint32(v[0])v1=c_uint32(v[1])delta=0x9e3779b9sum1=c_uint32(delta*32)for i in range(32):v1.value-=(((v0.value<<4)^(v0.value>>5))+v0.value)^(sum1.value+k[(sum1.value>>11)&3])sum1.value-=deltav0.value-=(((v1.value<<4)^(v1.value>>5))+v1.value)^(sum1.value+k[sum1.value&3])return v0.value,v1.valueif __name__=='__main__':a=[1,2]k=[2,2,3,4]print("加密前数据:",a)res=encrypt(a,k)print("加密后的数据:",res)res=decrypt(res,k)print("解密后数据:",res)
4. XXTEA算法
XXTEA,又称Corrected Block TEA,设计者是Roger Needham, David Wheeler。
XXTEA是一个非平衡Feistel网络分组密码,在可变长度块上运行,这些块是32位大小的任意倍数(最小64位)。
C语言代码
#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;
}
python代码
from ctypes import *def MX(z, y, sum1, k, p, e):return c_uint32(((z.value >> 5 ^ y.value << 2) + (y.value >> 3 ^ z.value << 4)) ^ ((sum1.value ^ y.value) + (k[(p & 3) ^ e.value] ^ z.value)))def btea(v, k, n, delta):if n > 1:sum1 = c_uint32(0)z = c_uint32(v[n - 1])rounds = 6 + 52 // ne = c_uint32(0)while rounds > 0:sum1.value += deltae.value = ((sum1.value >> 2) & 3) # e都要32位哦for p in range(n - 1):y = c_uint32(v[p + 1])# v[p]=c_uint32(v[p]+c_uint32((((z.value>>5^y.value<<2)+(y.value>>3^z.value<<4))^((sum1.value^y.value)+(k[(p&3)^e.value]^z.value)))).value).valuev[p] = c_uint32(v[p] + MX(z, y, sum1, k, p, e).value).valuez.value = v[p]y = c_uint32(v[0])# v[n-1]=c_uint32(v[n-1]+c_uint32((((z.value>>5^y.value<<2)+(y.value>>3^z.value<<4))^((sum1.value^y.value)+(k[((n-1)&3)^e.value]^z.value)))).value).valuev[n - 1] = c_uint32(v[n - 1] + MX(z, y, sum1, k, n - 1, e).value).valuez.value = v[n - 1]rounds -= 1else: #decoding partsum1 = c_uint32(0)n = -nrounds = 6 + 52 // nsum1.value = rounds * deltay = c_uint32(v[0])e = c_uint32(0)while rounds > 0:e.value = ((sum1.value >> 2) & 3) # e都要32位哦for p in range(n - 1, 0, -1):z = c_uint32(v[p - 1])# y[p]=c_uint32(v[p]-c_uint32((((z.value>>5^y.value<<2)+(y.value>>3^z.value<<4))^((sum1.value^y.value)+(k[(p&3)^e.value]^z.value)))).value).valuev[p] = c_uint32(v[p] - MX(z, y, sum1, k, p, e).value).valuey.value = v[p]z = c_uint32(v[n - 1])# v[n-1]=c_uint32(v[n-1]-c_uint32((((z.value>>5^y.value<<2)+(y.value>>3^z.value<<4))^((sum1.value^y.value)+(k[((n-1)&3)^e.value]^z.value)))).value).valuev[0] = c_uint32(v[0] - MX(z, y, sum1, k, 0, e).value).valuey.value = v[0]sum1.value -= deltarounds -= 1return vif __name__ == '__main__':v = [1, 2]k = [2, 2, 3, 4]delta = 0x9e3779b9n = 2"""n的绝对值表示v的长度,取正表示加密,取负表示解密v为要加密的数据是两个32位无符号整数k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位"""print("加密前数据:", v)res = btea(v, k, n, delta)print("加密后数据:", res)res = btea(v, k, -n, delta)print("解密后数据:", res)
5. DASCTF strangeprograme
彩笔虽然不懂,但复现一下总有好处的。
peid先查壳,发现.DASCTF
段。
shift+F12
查看字符串,跟踪Please input flag
,按X进行交叉引用找到sub_415560,应当是main函数。
跟踪aDasctfIAmFakeB,看到DASCTF{I',27h,'am Fake But Why Look Like real?}
ctrl+s
选择.DASCTF
数据段跳转到loc_41D000
,然后按x到sub_411064
,再按x找到sub_413D50
跟踪sub_4111BD->sub_414E30->sub_411046->sub_414B90,
据说是SMC动态代码加密。
听说memcmp的IAT表给改了,在main函数的memcmp处打断点
在IDA外启动程序,IDA以附加进程形式开启调试,输入DASCTF{I'am Fake But Why Look Like real?}
跟踪一波,来到DASCTF段
按p创建函数,按F5,就是memcmp真正的逻辑
__int64 __cdecl sub_41D250(char *Str)
{__int64 v1; // rax__int64 v3; // [esp-8h] [ebp-24Ch]int j; // [esp+D0h] [ebp-174h]size_t i; // [esp+F4h] [ebp-150h]char *v6; // [esp+100h] [ebp-144h]int v7; // [esp+124h] [ebp-120h] BYREFint v8; // [esp+128h] [ebp-11Ch]int v9; // [esp+12Ch] [ebp-118h]int v10; // [esp+130h] [ebp-114h]char v11[260]; // [esp+13Ch] [ebp-108h] BYREFint savedregs; // [esp+244h] [ebp+0h] BYREFsub_4114D8(&unk_4250F3);v11[0] = -7;v11[1] = 77;v11[2] = 43;v11[3] = -68;v11[4] = 19;v11[5] = -35;v11[6] = 19;v11[7] = 98;v11[8] = -55;v11[9] = -4;v11[10] = -1;v11[11] = -119;v11[12] = 125;v11[13] = 79;v11[14] = -55;v11[15] = 15;v11[16] = 99;v11[17] = 29;v11[18] = 109;v11[19] = 82;v11[20] = 80;v11[21] = -3;v11[22] = 65;v11[23] = -29;v11[24] = 51;v11[25] = 118;v11[26] = 40;v11[27] = -105;v11[28] = 56;v11[29] = 54;v11[30] = -7;v11[31] = 107;v11[32] = -112;v11[33] = 57;v11[34] = 20;v11[35] = -125;v11[36] = 44;v11[37] = -30;v11[38] = 44;v11[39] = 31;memset(&v11[40], 0, 216);v7 = 0;v8 = 0;v9 = 0;v10 = 0;if ( j_strlen(Str) == 40 ){v6 = Str + 4;v7 = *(_DWORD *)Str;v8 = *((_DWORD *)Str + 1);sub_411541(&v7, &unk_422100);//tea*(_DWORD *)Str = v7;*((_DWORD *)Str + 1) = v8;for ( i = 2; i < j_strlen(Str) >> 2; i += 2 )//>>2相当于除以4{sub_411541(&v7, &unk_422100);//tea*(_DWORD *)Str = v7;*(_DWORD *)v6 = v8;*(_DWORD *)&Str[4 * i] ^= *(_DWORD *)Str;*(_DWORD *)&Str[4 * i + 4] ^= *(_DWORD *)v6;}for ( j = 0; j < 40; ++j ){HIDWORD(v1) = j;if ( Str[j] != v11[j] )//加密后的str要跟v11一样{LODWORD(v1) = 1;goto LABEL_12;}}LODWORD(v1) = 0;}else{LODWORD(v1) = 1;}
LABEL_12:v3 = v1;sub_41130C((int)&savedregs, (int)&unk_41D5CC);return v3;
}
sub_411541->sub_41D6F0,是个魔改TEA算法
int __cdecl sub_41D6F0(unsigned int *a1, _DWORD *a2)
{int result; // eaxunsigned int i; // [esp+DCh] [ebp-2Ch]int v4; // [esp+E8h] [ebp-20h]unsigned int v5; // [esp+F4h] [ebp-14h]unsigned int v6; // [esp+100h] [ebp-8h]//识别一下,v6->v[0],v5->v[1],v4->sum,delta->1640531527//函数类型是voidsub_4114D8(&unk_4250F3);v6 = *a1;v5 = a1[1];v4 = 0;for ( i = 0; i < 0x10; ++i ){v6 += (a2[1] + (v5 >> 5)) ^ (v4 + v5) ^ (*a2 + 16 * v5);v5 += (a2[3] + (v6 >> 5)) ^ (v4 + v6) ^ (a2[2] + 16 * v6);v4 -= 1640531527;}*a1 = v6;result = 4;a1[1] = v5;return result;
}
还原逻辑如下:
def tea_enc(v,k):v0=v[0]v1=v[1]delta=1640531527sum=0for i in range(0x10):v0 += (k[1] + (v1 >> 5)) ^ (sum + v1) ^ (k[0] + 16 * v1)v1 += (k[3] + (v0 >> 5)) ^ (sum + v0) ^ (k[2] + 16 * v0)sum -= deltav[0]=v0v[1]=v1return v
写出魔改TEA的解密代码
def tea_dec(v,k):v0=v[0]v1=v[1]delta=c_uint64(0x61C88647)sum=c_uint32(0)for i in range(16):sum.value=sum.value-delta.valuefor i in range(16):sum.value += delta.valuev1.value -= (k[3].value + (v0.value >> 5)) ^ (sum.value + v0.value) ^ (k[2].value + 16 * v0.value)v0.value -= (k[1].value + (v1.value >> 5)) ^ (sum.value + v1.value) ^ (k[0].value + 16 * v1.value)v[0]=v0v[1]=v1return v
程序F8至memset(&v11[40], 0, 216);
后,查看v11
[0xBC2B4DF9, 0x6213DD13, 0x89FFFCC9, 0x0FC94F7D, 0x526D1D63, 0xE341FD50, 0x97287633, 0x6BF93638, 0x83143990, 0x1F2CE22C]
from ctypes import *
import binascii
import structk=[c_uint32(i) for i in [0x12345678, 0x09101112, 0x13141516, 0x15161718]]def tea_dec(v,k):v0=v[0]v1=v[1]delta=c_uint64(0x61C88647)sum=c_uint32(0)for i in range(16):sum.value=sum.value-delta.valuefor i in range(16):sum.value += delta.valuev1.value -= (k[3].value + (v0.value >> 5)) ^ (sum.value + v0.value) ^ (k[2].value + 16 * v0.value)v0.value -= (k[1].value + (v1.value >> 5)) ^ (sum.value + v1.value) ^ (k[0].value + 16 * v1.value)v[0]=v0v[1]=v1return vif __name__ == '__main__':v11=[0xBC2B4DF9, 0x6213DD13, 0x89FFFCC9, 0x0FC94F7D, 0x526D1D63, 0xE341FD50, 0x97287633, 0x6BF93638, 0x83143990, 0x1F2CE22C]for i in range(len(v11)):v11[i]=c_uint32(v11[i])for i in range(8,0,-2):v11[i + 1].value ^= v11[1].valuev11[i].value ^= v11[0].valuev11=tea_dec(v11, k)v11=tea_dec(v11, k)flag=[]for i in v11:for j in bytearray(binascii.a2b_hex(hex(i.value).replace("0x","")))[::-1]:#先转hex字符串,然后替换开头0x,然后转bytes,再转bytearray,调整一下顺序flag.append(chr(j))print("".join(flag))for i in v11:j=struct.pack('<I',i.value) #把int类型打包成小端序二进制字符串print(j.decode("utf-8"),end="")#DASCTF{I4TH0ok_I5S0ooFunny_Isnotit?????}
ps:使用lazyida注意,选中到最后一行的下一行,不然会缺数据,如下15
缺失变成00
参考
-
解析 TEA 加密算法(C语言、python): 沐一 · 林
-
CTF RE中的密码学 chillysome
-
DASCTF-Strangeprograme_ok _Nickname