Re常见简单密码
起码没有Crypto专项那么柜物。。。
C语言stdint.h
提供如下类型
int8_t 八位有符号整数
uint8_t 八位无符号整数
int16_t
int32_t
int64_t 64为有符号整数
c_char_p char类型指针
1. RC4算法
RC4是对称加密中特殊的流加密算法,操作如下:
- 密钥调度KSA,初始化一个S表,用种子密钥填充另一个256字节的K表,用K表对S表进行初始置换。
- 伪随机字节流(密钥流)生成,使用KSA生成的状态数组S来生成伪随机字节流
- 通过伪随机字节流,也就是密钥流来与明文流进行异或
import binascii
def KSA(key):
""" Key Scheduling Algorithm (KSA) """
key_length = len(key)
S = list(range(256)) # 对S表线性填充,一个字节范围0-255
j = 0
for i in range(256): # 打乱S盒
j = (j + S[i] + key[i % key_length]) % 256
S[i], S[j] = S[j], S[i] # swap
return S
def PRGA(S):
""" Pseudo-Random Generation Algorithm (PRGA) """
# 伪随机数生成算法
i = 0
j = 0
while True:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i] # swap
K = 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 hex
result.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 char
result.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 = 0x9e3779b9
for i in range(32):
sum1.value += delta
v0.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.value
def decrypt(v, k):
v0 = c_uint32(v[0])
v1 = c_uint32(v[1])
delta = 0x9e3779b9
sum1 = 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 -= delta
return v0.value, v1.value
if __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=0x9e3779b9
for i in range(32):
v0.value+=(((v1.value<<4)^(v1.value>>5))+v1.value)^(sum1.value+k[sum1.value&3])
sum1.value+=delta
v1.value+=(((v0.value<<4)^(v0.value>>5))+v0.value)^(sum1.value+k[(sum1.value>>11)&3])
return v0.value,v1.value
def decrypt(v,k):
v0=c_uint32(v[0])
v1=c_uint32(v[1])
delta=0x9e3779b9
sum1=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-=delta
v0.value-=(((v1.value<<4)^(v1.value>>5))+v1.value)^(sum1.value+k[sum1.value&3])
return v0.value,v1.value
if __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 // n
e = c_uint32(0)
while rounds > 0:
sum1.value += delta
e.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).value
v[p] = c_uint32(v[p] + MX(z, y, sum1, k, p, e).value).value
z.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).value
v[n - 1] = c_uint32(v[n - 1] + MX(z, y, sum1, k, n - 1, e).value).value
z.value = v[n - 1]
rounds -= 1
else: #decoding part
sum1 = c_uint32(0)
n = -n
rounds = 6 + 52 // n
sum1.value = rounds * delta
y = 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).value
v[p] = c_uint32(v[p] - MX(z, y, sum1, k, p, e).value).value
y.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).value
v[0] = c_uint32(v[0] - MX(z, y, sum1, k, 0, e).value).value
y.value = v[0]
sum1.value -= delta
rounds -= 1
return v
if __name__ == '__main__':
v = [1, 2]
k = [2, 2, 3, 4]
delta = 0x9e3779b9
n = 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] BYREF
int v8; // [esp+128h] [ebp-11Ch]
int v9; // [esp+12Ch] [ebp-118h]
int v10; // [esp+130h] [ebp-114h]
char v11[260]; // [esp+13Ch] [ebp-108h] BYREF
int savedregs; // [esp+244h] [ebp+0h] BYREF
sub_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; // eax
unsigned 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
//函数类型是void
sub_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=1640531527
sum=0
for 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 -= delta
v[0]=v0
v[1]=v1
return 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.value
for i in range(16):
sum.value += delta.value
v1.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]=v0
v[1]=v1
return v
程序F8至memset(&v11[40], 0, 216);
后,查看v11
[0xBC2B4DF9, 0x6213DD13, 0x89FFFCC9, 0x0FC94F7D, 0x526D1D63, 0xE341FD50, 0x97287633, 0x6BF93638, 0x83143990, 0x1F2CE22C]
from ctypes import *
import binascii
import struct
k=[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.value
for i in range(16):
sum.value += delta.value
v1.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]=v0
v[1]=v1
return v
if __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].value
v11[i].value ^= v11[0].value
v11=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