首页 > 编程语言 >re | 逆向算法笔记

re | 逆向算法笔记

时间:2023-06-27 12:27:12浏览次数:62  
标签:逆向 加密 int unsigned puc char re 算法 key

凯撒算法

加密

for(i=0; i<strlen(passwd); i++)
{
    if(passwd[i] >= 'A' && passwd[i] <= 'Z')
    {
        passwd[i] = ((passwd[i]-'A')+move)%26+'A';
    }
    else if(passwd[i] >= 'a' && passwd[i] <= 'z')
    {
        passwd[i] = ((passwd[i]-'a')+move)%26+'a';
    }
}

解密

for(i=0; i<strlen(passwd); i++)
{
    if(passwd[i] >= 'A' && passwd[i] <= 'Z')
    {
        passwd[i] = ((passwd[i]-'A')+26-move)%26+'A';
    }
    else if(passwd[i] >= 'a' && passwd[i] <= 'z')
    {
        passwd[i] = ((passwd[i]-'a')+26-move)%26+'a';
    }
}

SM4算法

加密

  • 生成s盒

    • 特征是传入128位密钥(v2)

  • 19行异或的数也是sm4的一个特征值

  • 明文加密

    • input划分为4个4字节的值,赋给v5,v5数组按照往后递推的方式,由前4个单元生成后1个单元的值,最后逐个字节取v5[32]到v5[35]的值赋给out

  • sub_411700长这样,第一个v5单元的值和sub_41170函数异或,函数的参数为v5后三个单元和key的异或,最后计算的值再赋给第5个v5单元

解密

import sm4
key = sm4.SM4Key(b"where_are_u_now?")
print key.decrypt(sm4_encoded)

查表算法

加密

a="?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z"
index='PQHRSIDTUJVWKEBXYLZ[MF\]N^_OGCA'
b=[0]*31
for i in range(31):
    b[i]=a[ord(index[i])]

解密

b="?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z"
index='PQHRSIDTUJVWKEBXYLZ[MF\]N^_OGCA'
a=[0]*31
for i in range(31):
    a[ord(index[i])]=b[i]

二叉树算法

加密

typedef struct Node{
	DataType Data;
	struct Node *lchild, *rchild;
}BinTNode, *BiTree;

void Create_BinTree(BiTree *T)
{
	char ch;
	
	scanf("%c",&ch);
	if(ch=='#')
	{
		*T==NULL;
	//	return; 
	} 
	else
	{
		*T=(BinTNode*)malloc(sizeof(BinTNode)); 
		(*T)->Data=ch;
		printf("\n建立左子树\n");
		(*T)->lchild=NULL; 
		(*T)->rchild=NULL;
		Create_BinTree(  &((*T)->lchild ) );//建立左子树 
		printf("\n建立右子树\n");
		Create_BinTree(  &((*T)->rchild ) );//建立右子树 
	}
	return ;
}


void PostOrder_Traverase(BiTree T)//后序遍历 
{
	if(T==NULL)
	return ;
	else
	{
		PostOrder_Traverase(T->lchild);
		PostOrder_Traverase(T->rchild);	
		printf(" %c " , T->Data);
	}
} 

解密

# 二叉树的遍历本质上是一个位置映射,当做一个黑盒处理
# 输入'ABCDEFGHIJKLMNOPQRSTUVWXYZ',程序输出index字符串
# 利用index的位置映射关系来恢复待解密的字符串a

a="?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z"
index='PQHRSIDTUJVWKEBXYLZ[MF\]N^_OGCA'
b=[0]*31
for i in range(31):
    b[ord(index[i])-ord('A')]=a[i]

已知中序和后序,求先序

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

char post[] = "20f0Th{2tsIS_icArE}e7__w"; //后序遍历结果
char mid[] = "2f0t02T{hcsiI_SwA__r7Ee}"; //中序遍历结果

void f(int root,int start,int end)
{
    if(start > end)
        return ;
    int i = start;
    while(i < end && mid[i] != post[root])
        i++;   //定位根在中序的位置
    printf("%c",mid[i]);
    f(root - 1-(end - i),start,i - 1);  //递归处理左子树
    f(root-1,i + 1,end);  //递归处理右子树
}

int main()
{

    f(24,0,24);
    return 0;
}

满二叉树已知任一序,可以求任一序

循环左移/右移算法

正运算

  for ( i = 0; i < strlen(input); ++i )
  {
    if ( (i & 1) != 0 )                         // 奇数循环右移
      v1 = (input[i] >> 2) | (input[i] << 6);
    else                                        // 偶数循环左移
      v1 = (4 * input[i]) | (input[i] >> 6);
    input[i] = v1;
  }

逆运算

for i in range(0,len(result)):
    t = result[i]
    if i&1==0:   //偶数循环右移
        input[i]=(t&0x3)<<6|(t&0xfc)>>2   #低2位左移6位,高6位右移2位  相当于循环右移2位
    else:	//奇数循环左移
        input[i]=(t&0x3f)<<2|(t&0xc0)>>6  #低6位左移2位,高2位右移6位  相当于循环左移2位

base64

加密

  • 识别

  • 脚本

    import base64
    str='admin'
    bs64=base64.b64encode(str.encode('utf-8'))
    

解密

  • 识别

    void *__fastcall RxEncode(const char *input, int len)
    {
      void *result; // rax
      int sz; // [rsp+18h] [rbp-38h]
      signed int paddingSz; // [rsp+1Ch] [rbp-34h]
      int idx; // [rsp+20h] [rbp-30h]
      signed int v6; // [rsp+24h] [rbp-2Ch]
      int v7; // [rsp+28h] [rbp-28h]
      int v8; // [rsp+28h] [rbp-28h]
      signed int i; // [rsp+2Ch] [rbp-24h]
      _BYTE *v10; // [rsp+30h] [rbp-20h]
      void *s; // [rsp+38h] [rbp-18h]
    
      sz = 3 * (len / 4);
      paddingSz = 0;
      idx = 0;
      if ( input[len - 1] == '=' )
        paddingSz = 1;
      if ( input[len - 2] == '=' )
        ++paddingSz;
      if ( input[len - 3] == '=' )
        ++paddingSz;
      if ( paddingSz == 3 )
      {
        sz += 2;
      }
      else if ( paddingSz <= 3 )
      {
        if ( paddingSz == 2 )
        {
          sz += 3;
        }
        else if ( paddingSz <= 2 )
        {
          if ( paddingSz )
          {
            if ( paddingSz == 1 )
              sz += 4;
          }
          else
          {
            sz += 4;
          }
        }
      }
      s = malloc(sz);
      if ( s )
      {
        memset(s, 0, sz);
        v10 = s;
        while ( idx < len - paddingSz )
        {
          v6 = 0;
          v7 = 0;
          while ( v6 <= 3 && idx < len - paddingSz )
          {
            v7 = (v7 << 6) | (char)find_pos(input[idx]);
            ++v6;
            ++idx;
          }
          v8 = v7 << 6 * (4 - v6);
          for ( i = 0; i <= 2 && i != v6; ++i )
            *v10++ = v8 >> 8 * (2 - i);
        }
        *v10 = 0;
        result = s;
      }
      else
      {
        puts("No enough memory.");
        result = 0LL;
      }
      return result;
    }
    
  • 脚本

    import base64
    debs64=base64.b64decode(bs64)
    

换表的base64解密脚本

import base64
import string

str1 = "x2dtJEOmyjacxDemx2eczT5cVS9fVUGvWTuZWjuexjRqy24rV29q"

string1 = "ZYXABCDEFGHIJKLMNOPQRSTUVWzyxabcdefghijklmnopqrstuvw0123456789+/"
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

print (base64.b64decode(str1.translate(str.maketrans(string1,string2))))

base58

  strcpy(v23, "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
  v21 = 138 * strlen(v19) / 0x64;
  v14 = v21 + 1;
  v1 = 0;
  v22 = (_BYTE *)MEMORY[0x8114](v21 + 1);
  v2 = v22;
  sub_402C08(v22, 0, v14);
  v3 = v19;
  v20 = (int)(v19 + 1);
  if ( strlen(v19) )
  {
    v4 = &v2[v21];
    v18 = v4;
    while ( 1 )
    {
      v20 = ((char)*v4 << 8) + v3[v1];
      v5 = v20 / 58;
      *v4 = v20 % 58;
      if ( v5 )
      {
        do
        {
          v6 = (char)*--v4;
          v7 = (v6 << 8) + v5;
          v20 = v7 / 58;
          *v4 = v7 % 58;
          v5 = v20;
        }
        while ( v20 );
        v4 = v18;
      }
      if ( ++v1 >= strlen(v19) )
        break;
      v3 = v19;
    }
    v2 = v22;
  }
  v8 = 0;
  if ( !*v2 )
  {
    do
      ++v8;
    while ( !v2[v8] );
  }
  v9 = v21;
  if ( v8 <= v21 )
  {
    v10 = v2 - (_BYTE *)v24;
    do
    {
      v11 = (char *)v24 + v8++;
      *v11 = v23[(char)v11[v10]];
    }
    while ( v8 <= v9 );
  }
  if ( !MEMORY[0x7C1A](v24, "56fkoP8KhwCf3v7CEz") )

tea系列算法

tea

  • TEA加密解密是以原文以8字节(64位bit)为一组,密钥16字节(128位bit)为一组,该算法加密轮次可变,作者建议为32轮,因为被加密的明文为64位,所以最终加密的结果也是64位

  • 实现

    #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;           /* set up */
        uint32_t delta=0x9e3779b9;                     /* a key schedule constant */
        uint32_t 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 (uint32_t* v, uint32_t* k) {
        uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i;  /* set up */
        uint32_t delta=0x9e3779b9;                     /* a key schedule constant */
        uint32_t 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;
    }
    

xtea

  • XTEA是TEA的升级版,增加了更多的密钥表,移位和异或操作

  • 实现

    #include <stdio.h>
    #include <stdint.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, 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;//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

  • 特点:原字符串长度可以不是4的倍数了

  • 实现

    #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;
    }
    
    
  • (链接)vs中导入头文件编译,可直接使用decode函数

RC4算法

  • RC4加密原理很简单,只需要一个KeyStream与明文进行异或即可,密钥流的长度和明文的长度是对应的。RC4算法的的主要代码还是在于如何生成秘钥流
  • 密钥流的生成由两部分组成:
    • KSA(the Key-Scheduling Algorithm)
    • PRGA(the Pseudo-Random Generation Algorithm)
  • 实现
#include<stdio.h>
#include<string.h>
 
#define SBOX_LEN 256
 
#define rc4_encrypt rc4_crypt
#define rc4_decrypt rc4_crypt
 
static inline void swap_uchar(unsigned char *puc_x, unsigned char *puc_y)
{
    *puc_x = *puc_x ^ *puc_y;
    *puc_y = *puc_x ^ *puc_y;
    *puc_x = *puc_x ^ *puc_y;
}
 
void hexdump(unsigned char *puc_data, int length)
{
    int i = 0;
 
    for (i = 0; i < length; i++) {
        printf("%02X", puc_data[i]);
        if (i && (i + 1) % 16 == 0) {
            putchar('\n');
        }
    }
    printf("\n");
}
 
/**
 * 利用Key生成S盒,伪随机数生成器
 * the Key-Scheduling Algorithm
 */
static void rc4_ksa(unsigned char *puc_sbox, unsigned char *puc_key, int key_length)
{
    int i = 0;
    int j = 0;
    char tmp[SBOX_LEN] = {0};
 
    for (i = 0; i < SBOX_LEN; i++) {
        puc_sbox[i] = i;
        tmp[i] = puc_key[i % key_length];
    }
 
    for (i = 0; i < SBOX_LEN; i++) {
        j = (j + puc_sbox[i] + tmp[i]) % SBOX_LEN;
        swap_uchar(&puc_sbox[i], &puc_sbox[j]); //交换puc_sbox[i]和puc_sbox[j]
    }
}
 
/**
 * 利用S盒生成密钥流
 * The pseudo-random generation algorithm(PRGA)
 */
static void rc4_prga(unsigned char *puc_sbox, unsigned char *puc_key_stream, unsigned long ul_data_length)
{
    int i = 0;
    int j = 0;
    int t = 0;
    unsigned long k = 0;
 
    for (k = 0; k < ul_data_length; k++) {
        i = (i + 1) % SBOX_LEN;
        j = (j + puc_sbox[i]) % SBOX_LEN;
        swap_uchar(&puc_sbox[i], &puc_sbox[j]);
        t = (puc_sbox[i] + puc_sbox[j]) % SBOX_LEN;
        /* 为了更清晰理解rc4算法流程,此处保存keystream,不直接进行XOR运算 */
        puc_key_stream[k] = puc_sbox[t];
    }
}
 
/* 加解密 */
void rc4_crypt(unsigned char *puc_data, unsigned char *puc_key_stream, unsigned long ul_data_length)
{
    unsigned long i = 0;
 
    /* 把PRGA算法放在加解密函数中可以不需要保存keystream */
    for (i = 0; i < ul_data_length; i++) {
        puc_data[i] ^= puc_key_stream[i];
    }
}
 
int main(int argc, char *argv[])
{
    unsigned char sbox[SBOX_LEN] = {0};
    char key[SBOX_LEN] = {"abcdefghijklmnopqrstuvwxyz"}; //秘钥内容随便定义
    char data[512] = "[email protected] lvfvr#9527";
    unsigned char puc_keystream[512] = {0};
    unsigned long ul_data_length = strlen(data);
 
    printf("key=%s, length=%d\n\n", key, strlen(key));
    printf("Raw data string:%s\n", data);
    printf("Raw data hex:\n");
    hexdump(data, ul_data_length);
 
    /* 生成S-box */
    rc4_ksa(sbox, (unsigned char *)key, strlen(key));
 
    /* 生成keystream并保存,S-box也会被更改 */
    rc4_prga(sbox, puc_keystream, ul_data_length);
 
    printf("S-box final status:\n");
    hexdump(sbox, sizeof(sbox));
 
    printf("key stream:\n");
    hexdump(puc_keystream, ul_data_length);
 
    /* 加密 */
    rc4_encrypt((unsigned char*)data, puc_keystream, ul_data_length);
 
    printf("cipher hexdump:\n");
    hexdump(data, ul_data_length);
 
    /* 解密 */
    rc4_decrypt((unsigned char*)data, puc_keystream, ul_data_length);
 
    printf("decypt data:%s\n", data);
 
    return 0;
}
  • 脚本
from Crypto.Cipher import ARC4
rc4 = ARC4.new(key)
print rc4.decrypt(encoded)

CRC算法

/*
**初始化crc表,生成32位大小的crc表
**也可以直接定义出crc表,直接查表,
**但总共有256个,看着眼花,用生成的比较方便,
**对0-255进行模2除法生成crc表.
*/
static void init_crc_table(void)
{
	unsigned int c;
	unsigned int i, j;
	
	for (i = 0; i < 256; i++) {
		c = (unsigned int)i;
		for (j = 0; j < 8; j++) {
			if (c & 1)
				c = 0xedb88320L ^ (c >> 1);
			else
				c = c >> 1;
		}
		crc_table[i] = c;
	}
}
 
/*计算buffer的crc校验码*/
static unsigned int crc32(unsigned int crc,unsigned char *buffer, unsigned int size)
{
	unsigned int i;
	for (i = 0; i < size; i++) {
		crc = crc_table[(crc ^ buffer[i]) & 0xff] ^ (crc >> 8);
	}
	return crc ;
}

MD5算法

特征值

void MD5Init (MD5_CTX *context)
{
   /*将当前的有效信息的长度设成0,这个很简单,还没有有效信息,长度当然是0了*/
  context->count[0] = context->count[1] = 0;
   /* Load magic initialization constants.*/
  /*初始化变量,算法要求这样 */
  context->state[0] = 0x67452301;
  context->state[1] = 0xefcdab89;
  context->state[2] = 0x98badcfe;
  context->state[3] = 0x10325476;
}

RSA算法

加密

  • 选取两个大素数p和q,为了获得最高安全性,设两数长度一样

  • 计算n=p*q,n称为模

  • 选取加密密钥e,其与φ(n)互素。如果选择的e值合适,RSA加解密的速度会加快。e的常用值为3、17、和65537(2^16+1)

  • 公钥为e和n,加密消息m时,将其看成一个大整数,并把它分成比n小的数据分组

    c[i] = m[i]^e mod n
    

解密

  • 计算欧拉函数:

    φ(n)=(p-1)(q-1)
    
  • 使用扩展欧几里德算法求出e模φ(n)的逆元d

    e*d mod φ(n) = 1
    
  • 密钥为d和n,解密密文c时,取每个加密后的分组c[i]

    m[i] = c[i]^d mod n
    

还原

  • 分解公钥得到e和n 链接
  • 分解n得到p和q 链接
  • 脚本
import gmpy2 
import rsa 
 
e = 65537
n = 86934482296048119190666062003494800588905656017203025617216654058378322103517
p = 285960468890451637935629440372639283459
q = 304008741604601924494328155975272418463

phin = (q-1)*(p-1)

d = gmpy2.invert(e, phin)

key = rsa.PrivateKey(n, e, int(d), p, q)

with open("G:\\output\\flag.txt", "rb+") as f:
    f = f.read()
    print(rsa.decrypt(f, key))

AES算法

原理

特征

  • 密文的长度必须是0x10字节的倍数

  • 秘钥的长度是 0x10 或0x18或0x20字节

  • T1-T4 静态数组数据用于加密数据,T5-T8 静态数组数据用于解密数据,其他静态数组用于初始化

模式

  • ECB

  • CBC

代码实现

#include <stdio.h>
#include <windows.h>

/*s盒矩阵:The AES Substitution Table*/// 256 位的密匙256 位支持长度为32 个字符
static const unsigned char sbox[256] = {
	0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,
	0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
	0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,
	0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
	0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,
	0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
	0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,
	0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
	0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,
	0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
	0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,
	0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
	0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,
	0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
	0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,
	0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
	0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,
	0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
	0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,
	0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
	0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,
	0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
	0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,
	0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
	0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,
	0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
	0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,
	0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
	0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,
	0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
	0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,
	0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16,
};
//逆向S 盒矩阵
static const unsigned char contrary_sbox[256] = {
	0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,
	0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb,
	0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,
	0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb,
	0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,
	0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e,
	0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,
	0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25,
	0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,
	0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92,
	0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,
	0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84,
	0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,
	0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06,
	0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,
	0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b,
	0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,
	0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73,
	0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,
	0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e,
	0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,
	0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b,
	0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,
	0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4,
	0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,
	0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f,
	0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,
	0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef,
	0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,
	0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61,
	0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,
	0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d,
};
/*轮常量表 The key schedule rcon table*/
static const unsigned char Rcon[10] = {
	0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1b,0x36 };

//辅助函数
/*有限域*2乘法 The x2time() function */
static unsigned char x2time(unsigned char x)
{
	if (x & 0x80)
	{
		return (((x << 1) ^ 0x1B) & 0xFF);
	}
	return x << 1;
}
/*有限域*3乘法 The x2time() function */
static unsigned char x3time(unsigned char x)
{
	return (x2time(x) ^ x);
}
/*有限域*4乘法 The x4time() function */
static unsigned char x4time(unsigned char x)
{
	return (x2time(x2time(x)));
}
/*有限域*8乘法 The x8time() function */
static unsigned char x8time(unsigned char x)
{
	return (x2time(x2time(x2time(x))));
}
/*有限域9乘法 The x9time() function */
static unsigned char x9time(unsigned char x)	//9:1001
{
	return (x8time(x) ^ x);
}
/*有限域*B乘法 The xBtime() function */
static unsigned char xBtime(unsigned char x)	//B:1011
{
	return (x8time(x) ^ x2time(x) ^ x);
}
/*有限域*D乘法 The xDtime() function */
static unsigned char xDtime(unsigned char x)	//D:1101
{
	return (x8time(x) ^ x4time(x) ^ x);
}
/*有限域*E乘法 The xEtime() function */
static unsigned char xEtime(unsigned char x)	//E:1110
{
	return (x8time(x) ^ x4time(x) ^ x2time(x));
}
/*第三类操作:列混合操作 MixColumns: Process the entire block*/
static void MixColumns(unsigned char *col)//列混合
{
	unsigned char tmp[4], xt[4];
	int i;
	for (i = 0; i<4; i++, col += 4)  //col代表一列的基地址,col+4:下一列的基地址
	{
		tmp[0] = x2time(col[0]) ^ x3time(col[1]) ^ col[2] ^ col[3];	//2 3 1 1
		tmp[1] = col[0] ^ x2time(col[1]) ^ x3time(col[2]) ^ col[3];	//1 2 3 1
		tmp[2] = col[0] ^ col[1] ^ x2time(col[2]) ^ x3time(col[3]);	//1 1 2 3
		tmp[3] = x3time(col[0]) ^ col[1] ^ col[2] ^ x2time(col[3]);	//3 1 1 2
//修改后的值 直接在原矩阵上修改
		col[0] = tmp[0];
		col[1] = tmp[1];
		col[2] = tmp[2];
		col[3] = tmp[3];
	}
}
//逆向列混淆
static void Contrary_MixColumns(unsigned char *col)
{
	unsigned char tmp[4];
	unsigned char xt2[4];//colx2
	unsigned char xt4[4];//colx4
	unsigned char xt8[4];//colx8
	int x;
	for (x = 0; x<4; x++, col += 4)
	{
		tmp[0] = xEtime(col[0]) ^ xBtime(col[1]) ^ xDtime(col[2]) ^ x9time(col[3]);
		tmp[1] = x9time(col[0]) ^ xEtime(col[1]) ^ xBtime(col[2]) ^ xDtime(col[3]);
		tmp[2] = xDtime(col[0]) ^ x9time(col[1]) ^ xEtime(col[2]) ^ xBtime(col[3]);
		tmp[3] = xBtime(col[0]) ^ xDtime(col[1]) ^ x9time(col[2]) ^ xEtime(col[3]);
		col[0] = tmp[0];
		col[1] = tmp[1];
		col[2] = tmp[2];
		col[3] = tmp[3];
	}
}
/*第二类操作:行移位:行左循环移位 ShiftRows:Shifts the entire block*/
static void ShiftRows(unsigned char *col)//正向行移位
{
	unsigned char t;
	t = col[1]; col[1] = col[5]; col[5] = col[9]; col[9] = col[13]; col[13] = t;
	t = col[2]; col[2] = col[10]; col[10] = t;
	t = col[6]; col[6] = col[14]; col[14] = t;
	t = col[15]; col[15] = col[11]; col[11] = col[7]; col[7] = col[3]; col[3] = t;
}
//逆向行移位
static void Contrary_ShiftRows(unsigned char *col)
{
	unsigned char t;
	t = col[13]; col[13] = col[9]; col[9] = col[5]; col[5] = col[1]; col[1] = t;
	t = col[2]; col[2] = col[10]; col[10] = t;
	t = col[6]; col[6] = col[14]; col[14] = t;
	t = col[3]; col[3] = col[7]; col[7] = col[11]; col[11] = col[15]; col[15] = t;
}
/*第一类操作:s盒字节代换替换 SubBytes*/
static void SubBytes(unsigned char *col)//字节代换
{
	int x;
	for (x = 0; x<16; x++)
	{
		col[x] = sbox[col[x]];
	}
}
//逆向字节代换
static void Contrary_SubBytes(unsigned char *col)
{
	int x;
	for (x = 0; x<16; x++)
	{
		col[x] = contrary_sbox[col[x]];
	}
}
/*第四类操作:轮密钥加 AddRoundKey*/
static void AddRoundKey(unsigned char *col, unsigned char *expansionkey, int round)//密匙加
{
	//扩展密钥:44*32bit =11*4* 4*8 =  16字节*11轮,每轮用16字节密钥
	//第0轮,只进行一次轮密钥加
	//第1-10轮,轮密钥加
	int x;
	for (x = 0; x<16; x++)	//每1轮操作:4*32bit密钥 = 16个字节密钥
	{
		col[x] ^= expansionkey[(round << 4) + x];
	}
}
/* AES加密总函数 10轮4类操作 Encrypt a single block with Nr Rounds(10,12,14)*/
void AesEncrypt(unsigned char *blk, unsigned char *expansionkey, int Nr)//加密一个区块
{
	//输入blk原文,直接在上面修改,输出blk密文
	//输入skey:
	//输入Nr = 10轮
	int round;
	//第1轮之前:轮密钥加
	AddRoundKey(blk, expansionkey, 0);
	//第1-9轮:4类操作:字节代换、行移位、列混合、轮密钥加
	for (round = 1; round <= (Nr - 1); round++)
	{
		SubBytes(blk);		//输入16字节数组,直接在原数组上修改
		ShiftRows(blk);		//输入16字节数组,直接在原数组上修改
		MixColumns(blk);	//输入16字节数组,直接在原数组上修改
		AddRoundKey(blk, expansionkey, round);
	}
	//第10轮:不进行列混合
	SubBytes(blk);
	ShiftRows(blk);
	AddRoundKey(blk, expansionkey, Nr);
}
//AES 解密总函数
void Contrary_AesEncrypt(unsigned char *blk, unsigned char *expansionkey, int Nr)
{
	int x;
	/* unsigned char *contrary_key=key;
	for(x=0;x<11;x++,key+=16)
	Contrary_MixColumns(key);*/
	AddRoundKey(blk, expansionkey, Nr);
	Contrary_ShiftRows(blk);
	Contrary_SubBytes(blk);
	for (x = (Nr - 1); x >= 1; x--)
	{
		AddRoundKey(blk, expansionkey, x);
		Contrary_MixColumns(blk);
		Contrary_ShiftRows(blk);
		Contrary_SubBytes(blk);
	}
	AddRoundKey(blk, expansionkey, 0);
}
/*//密钥编排,16字节--->44列32bit密钥生成--> 11组16字节:分别用于11轮 轮密钥加运算
Schedule a secret key for use.
*outkey[] must be 16*15 bytes in size
*Nk==number of 32 bit words in the key,e.g.,4,6,8
*Nr==number of rounds,e.g.,10,12,14
*/
void ScheduleKey(unsigned char *inkey, unsigned char *outkey, int Nk, int Nr)//安排一个保密密钥使用
{
	//inkey:初始16字节密钥key
	//outkey:11组*16字节扩展密钥expansionkey
	//Nk:4列
	//Nr:10轮round
	unsigned char temp[4], t;
	int x, i;
	/*copy the key*/
	//第0组:[0-3]直接拷贝
	for (i = 0; i<(4 * Nk); i++)
	{
		outkey[i] = inkey[i];
	}
	//第1-10组:[4-43]
	i = Nk;
	while (i<(4 * (Nr + 1))) //i=4~43 WORD 32bit的首字节地址,每一个4字节
	{//1次循环生成1个字节扩展密钥,4次循环生成一个WORD
	 //temp:4字节数组:代表一个WORD密钥
	 /*temp=w[i-1]*/
	 //i不是4的倍数的时候
	 //每个temp = 每个outkey32bit = 4字节
		for (x = 0; x<4; x++)
			temp[x] = outkey[(4 * (i - 1)) + x];	//i:32bit的首字节地址
													//i是4的倍数的时候
		if (i%Nk == 0)
		{
			/*字循环:循环左移1字节 RotWord()*/
			t = temp[0]; temp[0] = temp[1]; temp[1] = temp[2]; temp[2] = temp[3]; temp[3] = t;
			/*字节代换:SubWord()*/
			for (x = 0; x<4; x++)
			{
				temp[x] = sbox[temp[x]];
			}
			/*轮常量异或:Rcon[j]*/
			temp[0] ^= Rcon[(i / Nk) - 1];
		}
		/*w[i] = w[i-4]^w[i-1]*/
		for (x = 0; x<4; x++)
		{
			outkey[(4 * i) + x] = outkey[(4 * (i - Nk)) + x] ^ temp[x];
		}
		++i;
	}
}
int main(void) {
	/*
	pt:原文16字节-->密文
	key:原密钥16字节
	skey:密钥扩展44long
	sbox:s盒
	*/

	unsigned char pt[17], key[17];
	unsigned char expansionkey[15 * 16];
	int i;
	int j;
	printf("输入需要加密字符串: \n");//输入无格式的字符串字符个数不得少于六个!
	scanf("%s", pt);
	printf("输入加密密钥: \n");//输入加密钥匙密匙个数不得低于六个!
	scanf("%s", key);

	/*加密*/
	ScheduleKey(key, expansionkey, 4, 10);	//1、密钥扩展生成
	AesEncrypt(pt, expansionkey, 10);		//2、AES 加密
	printf("加密后的数据:  ");	//输出密码文件

	for (i = 0; i < 16; i++)
		printf("%02x ", pt[i]);
	printf("\n");

	/*解密*/
	Contrary_AesEncrypt(pt, expansionkey, 10);//AES 解密
	printf("解密后的数据: ");//将解密文件输出
	for (i = 0; i < 16; i++)
		printf("%c ", pt[i]);

	system("pause");
	return 0;
}

脚本还原

  • ECB
from Crypto.Cipher import AES

password = b'1234567812345678' #秘钥,b就是表示为bytes类型
text = b'abcdefghijklmnhi' #需要加密的内容,bytes类型
aes = AES.new(password,AES.MODE_ECB) #创建一个aes对象
# AES.MODE_ECB 表示模式是ECB模式
en_text = aes.encrypt(text) #加密明文
print("密文:",en_text) #加密明文,bytes类型
den_text = aes.decrypt(en_text) # 解密密文
print("明文:",den_text)
  • CBC
from Crypto.Cipher import AES
password = b'1234567812345678' #秘钥,b就是表示为bytes类型
iv = b'1234567812345678' # iv偏移量,bytes类型
text = b'abcdefghijklmnhi' #需要加密的内容,bytes类型
aes = AES.new(password,AES.MODE_CBC,iv) #创建一个aes对象
# AES.MODE_CBC 表示模式是CBC模式
en_text = aes.encrypt(text) 
print("密文:",en_text) #加密明文,bytes类型
aes = AES.new(password,AES.MODE_CBC,iv) #CBC模式下解密需要重新创建一个aes对象
den_text = aes.decrypt(en_text)
print("明文:",den_text)

DES算法

原理

特征

  • 密文的长度必须是0x08字节的倍数

  • 秘钥的长度必须是 0x08字节

脚本还原

import base64
from Crypto.Cipher import DES

encryptData = "xZWDZaKEhWNMCbiGYPBIlY3+arozO9zonwrYLiVL4njSez2RYM2WwsGnsnjCDnHs7N43aFvNE54noSadP9F8eEpvTs5QPG+KL0TDE/40nbU="
e = base64.b64decode(encryptData)
# 在C#中,字符串默认是Unicode字符串,所以转成字节数组,在每个字符字节后都要加一个"\x00"
keyiv = b"t\x00e\x00s\x00t\x00"

d = DES.new(keyiv, DES.MODE_CBC, keyiv)
print(d.decrypt(e).decode("utf-16"))

标签:逆向,加密,int,unsigned,puc,char,re,算法,key
From: https://www.cnblogs.com/z5onk0/p/17508358.html

相关文章

  • mac 使用 brew安装包报错 fatal: not in a git directory,Error: Command failed with
    在mac下使用brew安装包的时候,最后一行会报错:fatal:notinagitdirectoryError:Commandfailedwithexit128:git导致包安装不成功,解决办法:brew-v 绿色框就是提示你需要做的,输入gitconfig--global--addsafe.directory/opt/homebrew/Library/Taps/homeb......
  • mac 下使用 brew 安装包报错 error: Cannot install under Rosetta 2 in ARM default
    mac下使用brew安装包报错error:CannotinstallunderRosetta2inARMdefaultprefix(/opt/homebrew)!TorerununderARMuse:arch-arm64brewinstall...Toinstallunderx86_64,installHomebrewinto/usr/local. 解决:arch-arm64brewinstallxxx ......
  • redis-分布式锁样例
    redisTemplate:stringlockKey="product_101"stringclientID=UUID.randomUUID().toString()boolresult=redisTemplate.opsForValue().setIfAbsent(lockKey,clientID,10,TimeUnit.SECONDS)if(!result){return"error_code"}try{//业务逻辑......
  • Freertos学习06-任务堆栈
    一、前言在FreeRTOS中,每个任务都有自己的堆栈,用于存储任务执行期间使用的局部变量和函数调用。堆栈的大小在任务创建时指定,如果任务使用的堆栈空间超过了指定的大小,就会发生堆栈溢出错误。二、介绍1.堆栈分配xTaskCreate()为任务分配堆栈大小,但是需要注意的是,usStackDept......
  • re | 逆向刷题笔记
    IDAdump内存脚本importidcdefmain():begin=0xCD956000;#需对应修改size=0x2FB000##需对应修改list=[]foriinrange(size):byte_tmp=ida_bytes.get_byte(begin+i)list.append(byte_tmp)if(i+1)%0x10......
  • 将 SmartAssembly 与单文件可执行文件一起使用 (.NET Core 6)
    .NETCore6引入了创建单文件可执行文件的功能。这只允许分发一个应用程序文件,因为所有配置和依赖项都包含在二进制文件本身中。该功能为依赖项嵌入提供了一种本机方法,这在发布生成数百个程序集的独立应用程序时最有益。它可用于依赖于框架或自包含的应用程序,但在这两种情况下都......
  • 【Mybatis】常用的标签积累<sql>、<where>等
    一·常用标签组示例: 二、部分标签总结1.sql片段标签<sql>:通过该标签可定义能复用的sql语句片段,在执行sql语句标签中直接引用即可。这样既可以提高编码效率,还能有效简化代码,提高可读性,需要配置的属性:id="">>>表示需要改sql语句片段的唯一标识引用:通过<includerefid=""/......
  • iphone/ios14越狱安装screendump
    必须是ios14因为screendump经过大神修复后最新版本(作者起了个名字叫做screendumpfix14)只支持到ios14。点击这里查看大神原帖子。点击这里查看如何降级到ios14如果降级失败(至少我是这样据说是因为什么G值无法固定导致)gettingkeysfailedwitherror:14745615(failedt......
  • java springboot3 Property 'sqlSessionFactory' or 'sqlSessionTemplate' are requir
    老版本的mybatis-plus未适配springboot3解决办法:在pom.xml修改 mybatis-plus-boot-starter版本<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><vers......
  • 在.gitignore中如何写可以忽略掉无扩展名的Unix可执行文件
    我也遇到这个问题,自己多次尝试找到了解决方案。先把我的解答发出来:#忽略所有文件和目录(当前目录不能忽略)*#增加指定目录和下面所有目录!/dir1/!/dir1/**/!/dir2/!/dir2/**/#增加指定扩展名文件和Makefile文件!*.cpp!*.c!*.h!Makefile#忽略特殊文件,一般是......