Re常见简单密码

Re常见简单密码

起码没有Crypto专项那么柜物。。。

C语言stdint.h提供如下类型

int8_t 八位有符号整数
uint8_t 八位无符号整数
int16_t
int32_t
int64_t 64为有符号整数

c_char_p char类型指针

1. RC4算法

RC4加密算法流程剖析结合CTF逆向签到 栀花谢了春红

RC4是对称加密中特殊的流加密算法,操作如下:

  1. 密钥调度KSA,初始化一个S表,用种子密钥填充另一个256字节的K表,用K表对S表进行初始置换。
  2. 伪随机字节流(密钥流)生成,使用KSA生成的状态数组S来生成伪随机字节流
  3. 通过伪随机字节流,也就是密钥流来与明文流进行异或
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

在这里插入图片描述

参考

  1. 解析 TEA 加密算法(C语言、python): 沐一 · 林

  2. CTF RE中的密码学 chillysome

  3. DASCTF-Strangeprograme_ok _Nickname

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值