RE学习7.16-17

[HDCTF 2023]买了些什么呢

是一个经典的算法题吧
物品的重量和价值为:

| 物品编号 | 重量 | 价值 |

| 1 | 2 | 8 |
| 2 | 5 | 1 |
| 3 | 10 | 5 |
| 4 | 9 | 9 |
| 5 | 3 | 5 |
| 6 | 6 | 6 |
| 7 | 2 | 8 |
| 8 | 2 | 2 |
| 9 | 6 | 3 |
| 10 | 8 | 7 |
| 11 | 2 | 5 |
| 12 | 3 | 4 |
| 13 | 3 | 3 |
| 14 | 2 | 7 |
| 15 | 9 | 6 |
| 16 | 8 | 7 |
| 17 | 2 | 9 |
| 18 | 10 | 3 |
| 19 | 8 | 10 |
| 20 | 6 | 5 |
| 21 | 4 | 2 |
| 22 | 3 | 4 |
| 23 | 4 | 5 |
| 24 | 2 | 2 |
| 25 | 4 | 9 |
| 26 | 8 | 5 |
| 27 | 3 | 8 |
| 28 | 8 | 10 |
| 29 | 4 | 2 |
| 30 | 10 | 9 |
| 31 | 7 | 6 |
| 32 | 1 | 3 |
| 33 | 9 | 7 |
| 34 | 1 | 3 |
| 35 | 5 | 9 |
| 36 | 7 | 6 |
| 37 | 1 | 10 |
| 38 | 1 | 1 |
| 39 | 7 | 2 |
| 40 | 4 | 9 |

HDCTF淘宝店今天开业啦,你来到了淘宝店看到了琳琅满目的商品,这么多商品你都想要,怎么办鸭??
不知道要咋办惹,你只的背包只有50的容量,但你想买到价值最高的商品
你必须在50的容量内买到价值最大的商品
商品的编号从小到大排列即为flag
注意!每个商品只能拿一次!!
请输入你选择的物品编号
在这里插入图片描述
在这里插入图片描述

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<string>
#include<cstring>
#include<list>
#include<stdlib.h>
using namespace std;

int dp[500][500];
// int fact,just need dp[n+1][W+1]
int __cdecl knapsack(int W, int* wt, int* val, int n)
{
    int j_0; // [esp+0h] [ebp-10h]
    int i_0; // [esp+4h] [ebp-Ch]
    int j; // [esp+8h] [ebp-8h]
    int i; // [esp+Ch] [ebp-4h]
    // first initialize dp
    for (i = 0; i <= n; ++i)
    {
        for (j = 0; j <= W; ++j)
            dp[i][j] = 0;
    }
    // two circulations to read each object and bag capacity
    for (i_0 = 1; i_0 <= n; ++i_0)
    {
        for (j_0 = 1; j_0 <= W; ++j_0)
        {
            if (j_0 < wt[i_0 - 1]) //j_0 :current bag capacity
            {
                dp[i_0][j_0] = dp[i_0 - 1][j_0];
            }
            else   // consider whether put current object
            {
                dp[i_0][j_0] = dp[i_0 - 1][j_0];
                if (dp[i_0 - 1][j_0 - wt[i_0 - 1]] + val[i_0 - 1] > dp[i_0][j_0])
                    dp[i_0][j_0] = val[i_0 - 1] + dp[i_0 - 1][j_0 - wt[i_0 - 1]];
            }
        }
    }
    return 0;
}
int main()
{
    int W = 50;  // capacity
    int n = 40;  // objext numbers
    int wt[0xA0];// weight
    int val[0xA0];//value
    srand(1);
    for (int i = 0; i < n; i++)
    {
        wt[i] = rand() % 10 + 1;
        val[i] = rand() % 10 + 1;
        printf("|    %d    |   %d   |   %d   |\n", i + 1, wt[i], val[i]);
    }
    knapsack(W, wt, val, n);
    cout << "动态规划数组为: " << endl;
    for (int i = 0; i <= n; i++)
    {
        for (int j = 0; j <= W; j++)
        {
            cout << dp[i][j] << " ";
        }
        cout << endl;
    }
    vector<int> indices; //store indexs
    int w = W;           //ues to track bag residue capacity
    // 逆向追溯,右下角向左上角
    for (int i = n; i > 0 && w > 0; i--)
    {
        if (dp[i][w] != dp[i - 1][w])
        {   //choose (i-1)object  
            indices.push_back(i - 1);
            w -= wt[i - 1];
        }
    }
    cout << "选择的物品的下标为: ";
    for (int i = indices.size() - 1; i >= 0; i--)
    {
        cout << indices[i] << " ";
    }
}//HDCTF{0 4 6 10 11 13 16 18 21 22 24 26 31 33 34 36 39}

有点复杂,哈哈哈。
也有师傅是把所有价值大于重量的物品挑出来,相加和调试出来的check进行比较,然后再据此剔出或者加上一些物品。
简直tql都。 0.0

[羊城杯 2023]CSGO

在这里插入图片描述
不能输入?肯定是有一个反调试
在这里插入图片描述
ida不能正常运行
根据字符串找到这里,看不了
在这里插入图片描述
ghidra比之稍稍好看一点,0.0
go语言的一般都是动调了,
调完就是一个变表的base64,再找出密文就行了
但是确实要多学学调试的了

[WUSTCTF 2020]funnyre

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第一种就i是用 ida python (一些函数识别不了)

def _add(cipher, k):
  return [(each - k) & 0xff for each in cipher]  # &0xff 防止 byte 溢出造成错误
# &0xff ensure result in range(255),return a list
def _xor(cipher, k):
  return [each ^ k for each in cipher]

def _not(cipher):
  return [~each for each in cipher]

cipher = [0xD9, 0x2C, 0x27, 0xD6, 0xD8, 0x2A, 0xDA, 0x2D, 0xD7, 0x2C, 0xDC, 0xE1, 0xDB, 0x2C, 0xD9, 0xDD, 0x27, 0x2D,
          0x2A, 0xDC, 0xDB, 0x2C, 0xE1, 0x29, 0xDA, 0xDA, 0x2C, 0xDA, 0x2A, 0xD9, 0x29, 0x2A]
end = 0x401DA9
start = 0x400605
i = PrevHead(end)  # i 为end的前一条指令的地址
while i > start:
  if GetMnem(i) == 'xor' and GetOpnd(i, 0) == "byte ptr [rdx+rax+5]":
    k = int(GetOpnd(i, 1).rstrip('h'), 16)
    cipher = _xor(cipher, k)
  if GetMnem(i) == 'add' and GetOpnd(i, 0) == "byte ptr [rdx+rax+5]":
    k = int(GetOpnd(i, 1).rstrip('h'), 16)
    cipher = _add(cipher, k)
  if GetMnem(i) == 'not' and GetOpnd(i, 0) == "byte ptr [rdx+rax+5]":
    cipher = _not(cipher)
  i = PrevHead(i)

print(''.join(chr(i) for i in cipher))
# PrevHead(addr)用于获取指定地址之前一条指令的起始地址
# GetMnem(addr) 获取地址i处的操作指令
# GetOpnd(addr, n)获取某地址处的操作数(第一个参数是地址,第二个是操作数索引)

还有就是直接暴力破解(tql)

dt = [0xd9, 0x2c, 0x27, 0xd6, 0xd8, 0x2a, 0xda, 0x2d, 0xd7, 0x2c, 0xdc, 0xe1, 0xdb, 0x2c, 0xd9, 0xdd, 0x27, 0x2d, 0x2a, 0xdc, 0xdb, 0x2c, 0xe1, 0x29, 0xda, 0xda, 0x2c, 0xda, 0x2a, 0xd9, 0x29, 0x2a]

def kaisa(xx, kk):
    return [(x+kk) & 0xFF for x in xx]
def xor(xx, kk):
    return [x ^ kk for x in xx]
def check(xx):
    for x in xx:
        if x < ord('0') or (x > ord('9') and x < ord('a')) or x > ord('f'):
            return False
    return True

if __name__ == '__main__':
    for k1 in range(0x100):
        tt = kaisa(dt, k1)
        for k2 in range(0x100):
            tt2 = xor(tt, k2)
            if check(tt2):
                print(bytes(tt2))
                print(k1, k2)

主要我不知道怎么确定就是十六进制字符 0.0 换成A-F 就不行了,跑出很多结果

还有就是 angr (之前用都跑不出来就不太想用了)
这个可以跑出来,不过没有输入,需要自己用 claripy 将变量存到内存中

[HNCTF 2022 WEEK3]Help_Me!

又是一个01背包题,什么情况下不猝死?选几门课?
在这里插入图片描述
所以分析是可选的有20门课,要不超过200压力

values = [26,59,30,19,66,85,94,8,3,44,5,1,41,82,76,1,12,81,73,32,0]
weights = [71,34,82,23,1,88,12,57,10,68,5,33,37,69,98,24,26,83,16,26,0]
capacity = 200

def package(weights,values,capacity):
    n=len(weights)
    dp=[[0]*(capacity+1) for _ in range(n+1)]
    for i in range(1,n+1):   #先遍历每一个物品
        for w in range(capacity+1): #可能的背包容量
            if weights[i-1]<=w:
                dp[i][w]=max(dp[i-1][w],dp[i-1][w-weights[i-1]]+values[i-1])
            else:
                dp[i][w]=dp[i-1][w] #
    # 回溯最优解
    number=[]
    # 从动态规划表右下角开始回溯
    i,w=n,capacity
    while i>0 and w>0:
        if dp[i][w]!=dp[i-1][w]:  #是,选择了第i-1物品
            number.append(i-1)
            w-=weights[i-1]
        i-=1
    return dp[n][capacity],number #返回给定容量下获得最大价值

max_value,number=package(weights,values,capacity)
print(max_value)
print(number[::-1])
452
[1, 4, 6, 10, 12, 13, 18, 19]

抛石机

在这里插入图片描述

在这里插入图片描述
小端序:
较低地址的字节存储在较低地址,较高地址的字节存储在较高地址
但提取数据时应该 45 4A F1 3F

#include <stdio.h>

int main() {
	//*&qwordA > *&qwordB - 0.001
	//*&qwordC > *&qwordD - 0.001
	//v4 = 149.2 * *&qwordA + *&qwordA * -27.6 * *&qwordA - 129.0;
	//v3 = 149.2 * *&qwordB + *&qwordB * -27.6 * *&qwordB - 129.0;
	//v2 = *&qwordC * -39.6 * *&qwordC + 59.2 * *&qwordC + 37.8;
	//v1 = *&qwordD * -39.6 * *&qwordD + 59.2 * *&qwordD + 37.8;
	   /*   v4 <= -0.00003
		|| v4 >= 0.00003
		|| v3 <= -0.00003
		|| v3 >= 0.00003
		|| v2 <= -0.00002
		|| v2 >= 0.00002
		|| v1 <= -0.00003
		|| v1 >= 0.00003;*/
	unsigned long long i;
	unsigned long long tmp;
	double key;
	double v4, v2, v1;
	for (i = 0; i < 0xffffffff; i++) {
		tmp = i << 32;  //取qword 4-7位
		key = *(double*)(&tmp);
		v4 = 149.2 * key + key * -27.6 * key - 129.0;
		if ((v4 > -0.00003) && (v4 < 0.00003)) {
			printf("v4:%p  %lf\n", i, v4);
		}
		v2 = key * -39.6 * key + 59.2 * key + 37.8;
		if ((v2 > -0.00002) && (v2 < 0.00002)) {
			printf("v2:%p  %lf\n", i, v2);
		}
		v1 = key * -39.6 * key + 59.2 * key + 37.8;
		if ((v1 > -0.00003) && (v1 < 0.00003)) {
			printf("v1:%p  %lf\n", i, v1);
		}
	}
	return 0;
}
//v4:000000003FF14A45 - 0.000015     *
//v1 : 000000003FFFA458 - 0.000029   *
//v4 : 0000000040114CF8 - 0.000006(v3)*
//v1 : 00000000BFDEE41D  0.000026
//v2 : 00000000BFDEE41E  0.000002    *
//v1 : 00000000BFDEE41E  0.000002
//v1 : 00000000BFDEE41F - 0.000021
//printf("\nGetFlag!\nflag{454af13f-f84c-1140-1ee4-debf58a4ff3f} ");

[warmup]babyvxworks

vxe文件
在这里插入图片描述
考察花指令的,这个不容易看出,可以先按 D 变成数据
在这里插入图片描述
主要是这个花指令的去除还有函数尾部地址识别不正确的问题
也是搞了半天 0.0
得到了关键函数

int sub_3D0()
{
  int v0; // ebx
  int v1; // eax
  int v3; // [esp+0h] [ebp-D8h]
  const char *v4; // [esp+8h] [ebp-D0h]
  int v5; // [esp+14h] [ebp-C4h]
  int v6; // [esp+18h] [ebp-C0h]
  int v7; // [esp+1Ch] [ebp-BCh]
  int v8[2]; // [esp+20h] [ebp-B8h] BYREF
  char v9[52]; // [esp+28h] [ebp-B0h] BYREF
  char v10[124]; // [esp+5Ch] [ebp-7Ch] BYREF

  sub_32B0(v9, 0, 48);
  sub_32B0(v10, 0, 120);
  v8[0] = 0;
  sub_2BF0(v8, v9, 48);
  sub_2BF0(v8, v10, 120);
  v6 = 0;
  qmemcpy(v9, dword_126F8, 0x30u);
  sub_32D0("Plz Input Flag: ");
  sub_33C0("%s", v9);
  *(_DWORD *)sub_2450(21, v10, v3) = 188;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 10;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 187;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 193;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 213;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 134;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 127;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 10;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 201;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 185;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 81;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 78;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 136;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 10;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 130;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 185;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 49;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 141;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 10;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 253;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 201;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 199;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 127;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 185;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 17;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 78;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 185;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 232;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 141;
  *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 21, v10) = 87;
  v5 = sub_34C0(v9);
  v0 = 0;
  if ( v5 <= 0 )
    goto LABEL_7;
  do
  {
    v1 = sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 24, v9);
    ((void (__cdecl *)(int))loc_330)(v1);
    v7 = *(unsigned __int8 *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 26, v9);
    if ( *(_DWORD *)sub_2450("C:/WindRiver/workspace/helloworld/helloworld.c", 26, v10) == v7 )
      ++v6;
    ++v0;
  }
  while ( v0 < v5 );
  if ( v6 == 30 )
    v4 = (_BYTE *)&loc_8BE;
  else
LABEL_7:
    v4 = "Try Again";
  sub_3350(v4);
  sub_2930(v8);
  return 0;
}

一般函数汇编开头

push ebp
mov ebp , esp

也不用搞清楚每步在干嘛,找到对flag操作的地方就行了

总结

有花指令和函数结束判断错误的,先解决函数尾部地址的问题,反汇编一般有点问题,结合汇编看,也可以调试

splend

之前写过,不过没怎么弄清楚,再来写一遍
首先就是一个 strtok 函数,截取字符串
然后有两个 SMC 之前一直不知道怎么搞的,第一个是用动调搞出来了(也可以写脚本)
在这里插入图片描述
加上 OD 动调
也要注意程序的流程图,去瞅瞅
在这里插入图片描述
对于 flag2 ida 确实不好调试了
在这里插入图片描述
上 OD
OD和XDug地址和ida都不一样,不过可以用相对偏移(OD)RVA
在这里插入图片描述
然后下面有一个

cmp cl , bl

cl 就是正确的加密后的flag2,把data(eax)数组提取下来,根据下标就可以求出flag2 ,
哈哈哈,虽然搞了半天,但是把他搞明白还是非常开心的

BabyMaze

在这里插入图片描述
这好像就是师傅所说的python花了,我之前不清楚,都是直接转头去pycdc,(偷笑),额,这次不行
在这里插入图片描述
网站也不行
在这里插入图片描述
烦,我下的附件是坏的,其他人是好的,靠,不对啊,附件一样的,难道是python版本的问题?
算了,记一下方法先
1.查看字节码
2.找到花指令
3.知道指令对于机器码(十六进制)在010中删除
4.先用原来co_code找到位置然后修改减去花指令条数 * 3

import marshal, dis
f = open("D:\ctf附件2\BabyMaze.pyc", "rb").read()
code = marshal.loads(f[16:]) #这边从16位开始取因为是python3 python2从8位开始取
dis.dis(code) # get 字节码
# co_code
len(code.co_code)

在这里插入图片描述

时空飞行

首先不能慌,一点一点慢慢看
不知道的函数可以动调或者百度
在这里插入图片描述

在这里插入图片描述
可以看出它们是按照大端序存储的,因为在大端序中,最高有效字节 34h 在最低的地址 000000000060FD20 处,不太理解为什么34h是最高???
在这里插入图片描述
在这里插入图片描述
有i点糊,应该是 +4 啊??
逻辑左移,右移

#include <stdio.h>												

/**
 *	作用: 参数 x 左移参数 n 位
 */
#define SHL(x, n) ( ((x) & 0xFFFFFFFF) << n )

 /**
  *	作用: 参数 x 逻辑左移参数 n 位
  */
#define ROTL(x, n) ( SHL((x), n) | ((x) >> (32 - n)) )

  /**
   *	密钥用常量
   */
static const unsigned long FK[4] = { 0xa3b1bac6,0x56aa3350,0x677d9197,0xb27022dc };

/**
 *	密钥用常量
 */
static const unsigned long CK[32] =
{
0x00070e15,0x1c232a31,0x383f464d,0x545b6269,
0x70777e85,0x8c939aa1,0xa8afb6bd,0xc4cbd2d9,
0xe0e7eef5,0xfc030a11,0x181f262d,0x343b4249,
0x50575e65,0x6c737a81,0x888f969d,0xa4abb2b9,
0xc0c7ced5,0xdce3eaf1,0xf8ff060d,0x141b2229,
0x30373e45,0x4c535a61,0x686f767d,0x848b9299,
0xa0a7aeb5,0xbcc3cad1,0xd8dfe6ed,0xf4fb0209,
0x10171e25,0x2c333a41,0x484f565d,0x646b7279
};

unsigned int CalcRoundKey(unsigned int ka);

int main(void)
{
	unsigned int t[36];
	unsigned int k[] = { 0xFD07C452, 0xEC90A488, 0x68D33CD1, 0x96F64587 };
	int i, j;

	for (i = 32; i < 36; i++)
	{
		t[i] = k[i - 32];
		printf("0x%X, ", t[i]);
	}
	printf("\n");
	for (i = 35; i >= 4; i--)
		t[i - 4] = t[i] ^ (CalcRoundKey(t[i - 3] ^ t[i - 2] ^ t[i - 1] ^ CK[i - 4]));

	for (i = 0; i < 4; i++)
	{
		printf("0x%X, ", t[i] ^ FK[i]);
		t[i] ^= FK[i];
	}
	printf("\n");
	printf("Date:");
	unsigned char* p = (unsigned char*)t;
	for (i = 1; i <= 2; i++)
		for (j = 1; j <= 4; j++)
			printf("%c", p[i * 4 - j]);

	return 0;
}

unsigned int CalcRoundKey(unsigned int ka)
{
	unsigned int retval = 0;
	retval = ka ^ (ROTL(ka, 13) ^ ROTL(ka, 23));
	return retval;
}

得到日期(我自己写的输出乱码就烦死,结果明明一样靠)

后面的解法差不多,就是分析完,然后逆回去
中间师傅说有一步要用到DFS回溯还是什么,不然有很多分叉
后面的就慢慢逆吧 00000000000
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

#include <stdio.h>

static const int Rcon[10] =
{
	0x01000000, 0x02000000,
	0x04000000, 0x08000000,
	0x10000000, 0x20000000,
	0x40000000, 0x80000000,
	0x1b000000, 0x36000000
};

int GetIntFromChar(char c);
int GetWordFromStr(char* str);
int MergeArrayToInt(int array[4]);
void SplitIntToArray(int num, int array[4]);
void LeftLoop4Int(int array[4], int step);
int T(int num, int round);

void DFS(unsigned char* flag, int deep);

unsigned char flags[30][24];				//已经控制数据在30个以内 你们多设点也可以 
unsigned int enc[24] = { 0x25, 0x15, 0xDF, 0xA2, 0xC0, 0x93, 0xAD, 0x14, 0x46, 0xC5, 0xF, 0x2E, 0x9A, 0xEB, 0x30, 0xF8, 0x20, 0xE9, 0xCB, 0x88, 0xC6, 0xBE, 0x8D, 0xE3 };
int x;

int main(void)
{
	int i, j, c;
	unsigned int t[66];

	unsigned char flag[24];
	flag[23] = 0xE3;
	DFS(flag, 23); //找到所有可能性放到flags 

	unsigned int* pi = (unsigned int*)flags; //已无符号整形来访问 宽度为24 于4字节访问一次 所以为6 
	//	for ( i = 0; i < 30 * 6; i++ )
	//	{
	//		printf("0x%X, ", pi[i]);
	//		if ( (i + 1) % 6 == 0 )
	//			printf("\n");
	//	}

	for (c = 0; c <= 30 * 6; c += 6)
	{
		for (i = 60; i < 66; i++)	//填好数据 
			t[i] = pi[c + i - 60];
		for (i = 59, j = 9; i >= 0; i--)	//利用等式逆回去 
		{
			if (i % 6 == 0)
			{
				t[i] = t[i + 6] ^ T(t[i + 5], j);
				j--;
			}
			else
				t[i] = t[i + 6] ^ t[i + 5];
			//			printf("t[%d] = 0x%X, ",i, t[i]);
		}
		unsigned char* p = (unsigned char*)t;
		for (i = 0; i < 24; i += 4)
			printf("%c%c%c%c", p[i + 3], p[i + 2], p[i + 1], p[i]);//注意小端序 
		printf("\n");
	}

	return 0;
}

void DFS(unsigned char* flag, int deep)
{
	int i;
	if (deep == 0)
	{
		for (i = 0; i < 24; i++)
		{
			flags[x][i] = flag[i];
			//			printf("0x%X, ", flag[i]);
		}
		x++;
		//		puts("\n");
	}
	else
	{
		for (i = 0; i < 0xFF; i++)
		{
			if (((i ^ 0x41) ^ (i % 0x12 + flag[deep] + 0x05)) == enc[deep - 1])
			{
				flag[deep - 1] = i;
				//				printf("0x%X, ", flag[deep - 1]);
				DFS(flag, deep - 1);
			}
		}
	}

}

int GetIntFromChar(char c)
{
	int result = (int)c;

	return result & 0x000000FF;
}

int GetWordFromStr(char* str)
{
	int one = GetIntFromChar(str[0]);
	one = one << 24;

	int two = GetIntFromChar(str[1]);
	two = two << 16;

	int three = GetIntFromChar(str[2]);
	three = three << 8;

	int four = GetIntFromChar(str[3]);

	return one | two | three | four;
}

int MergeArrayToInt(int array[4])
{
	int one = array[0] << 24;
	int two = array[1] << 16;
	int three = array[2] << 8;
	int four = array[3];

	return one | two | three | four;
}

void SplitIntToArray(int num, int array[4])
{
	int one = num >> 24;
	array[0] = one & 0x000000FF;

	int two = num >> 16;
	array[1] = two & 0x000000FF;

	int three = num >> 8;
	array[2] = three & 0x000000FF;

	array[3] = num & 0x000000FF;
}

void LeftLoop4Int(int array[4], int step)
{
	int tmp[4];
	int i;

	for (i = 0; i < 4; i++)
		tmp[i] = array[i];

	int index = step;
	for (i = 0; i < 4; i++)
	{
		array[i] = tmp[index];
		index++;
		index = index % 4;
	}
}

int T(int num, int round)
{
	int NumArray[4];

	SplitIntToArray(num, NumArray);

	LeftLoop4Int(NumArray, 1);

	int result = MergeArrayToInt(NumArray);

	return result ^ Rcon[round];
}

对照敲了一遍,还是遇到了很多问题,端序,功能函数的实现,逻辑的推理,太棒了!!!。

总结一下:

先大致分析,能逆,好逆的就慢慢一步步逆回去,不然就考虑爆破什么的
还有要注意端序
以及这有两个输入的题目,后面一个输入中的一些变量(看似是定值)可能被一些函数修改了,注意分析。
太累了 0.0

还有一个 Sm4 和 AES 的密钥扩展,啊~还有好多加密还是要手打

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值