首页 > 其他分享 >DESLearn-nepctf-cat

DESLearn-nepctf-cat

时间:2022-11-16 20:22:06浏览次数:50  
标签:DESLearn temp esp int cat ++ ebp bitset nepctf

des一些算法特征

每次加密八个字节

一些算法特征常量

初始置换表

            58, 50, 42, 34, 26, 18, 10, 2,
			60, 52, 44, 36, 28, 20, 12, 4,
			62, 54, 46, 38, 30, 22, 14, 6,
			64, 56, 48, 40, 32, 24, 16, 8,
			57, 49, 41, 33, 25, 17, 9,  1,
			59, 51, 43, 35, 27, 19, 11, 3,
			61, 53, 45, 37, 29, 21, 13, 5,
			63, 55, 47, 39, 31, 23, 15, 7

还有左移位数表

 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 

nepctf-Stupid_orange_cat

这题网上wp好像很少

如果直接动调的话

image-20220929103836270

这时候可以得出

应该是在这个函数

_scrt_common_main_seh

利用

initterm

这个函数在对于全局变量初始化的时候被加了一些反调试

继续单步跟

image-20220929104000392

可以来到这个地方

发现

image-20220929104550821

在sleep导致调试器超时

直接patch dword_EE65C0为0x20就行

后面会得到真正的key

52101314

再仔细看伪代码部分

int __cdecl main_0(int argc, const char **argv, const char **envp)
{
  char v4; // [esp-20h] [ebp-14D4h] BYREF
  int v5; // [esp-1Ch] [ebp-14D0h]
  int v6; // [esp-18h] [ebp-14CCh]
  int v7; // [esp-14h] [ebp-14C8h]
  int v8; // [esp-10h] [ebp-14C4h]
  int v9; // [esp-Ch] [ebp-14C0h]
  int v10; // [esp-8h] [ebp-14BCh]
  char v11; // [esp-4h] [ebp-14B8h]
  char v12; // [esp+0h] [ebp-14B4h]
  int v13; // [esp+14h] [ebp-14A0h]
  char *v14; // [esp+20h] [ebp-1494h]
  char *v15; // [esp+2Ch] [ebp-1488h]
  int j; // [esp+638h] [ebp-E7Ch]
  int i; // [esp+644h] [ebp-E70h]
  char v18[20]; // [esp+650h] [ebp-E64h] BYREF
  char Str[60]; // [esp+664h] [ebp-E50h] BYREF
  char v20[20]; // [esp+6A0h] [ebp-E14h] BYREF
  int v21; // [esp+6B4h] [ebp-E00h]
  int v22[889]; // [esp+6C0h] [ebp-DF4h] BYREF
  int v23; // [esp+14B0h] [ebp-4h]

  __CheckForDebuggerJustMyCode(&unk_EEB03D);
  init_Struct(v22);
  v23 = 0;
  sub_D455CC((int)&byte_EA3788, v12);
  sub_D442E9("%s", Str);
  word_EE65CC = sub_D4A9A0();
  v21 = 18;
  word_EE65D0 = *(&word_EE4000 + 18);
  dword_EE65C4 = (unsigned __int16)word_EE65CC | ((unsigned __int16)word_EE65D0 << 16);
  if ( j__strlen(Str) != 32 )
  {
    sub_D455CC((int)"Length is Wrong!!\n", v12);
    j___loaddll(0);
  }
  sub_D4A685((int)v20, "%x", dword_EE65C4);
  v15 = &v4;
  sub_D450D6(&v4, v20);                         // key=52101314
  sub_D49032(v4, v5, v6, v7, v8, v9, v10);
  for ( i = 0; i < 4; ++i )
  {
    for ( j = 0; j < 8; ++j )
      v18[j] = Str[8 * i + j];
    v14 = &v4;
    sub_D450D6(&v4, v18);
    sub_D44CF8(v22, v4, v5, v6, v7, v8, v9, v10);
    sub_D452CF(v22);
    if ( !i )
      sub_D46170(v22);
    if ( i == 1 )
      sub_D44109(v22);
    if ( i == 2 )
      sub_D478BD(v22);
    if ( i == 3 )
      sub_D47C3C(v22);
  }
  sub_D455CC((int)&unk_EA37B4, v11);
  sub_D455CC((int)&unk_EA37DC, v11);
  j__system("pause");
  v13 = 0;
  v23 = -1;
  sub_D48B6E(v22);
  return v13;
}

发现在sub_D46170函数中对a.txt进行了读取和比较

看了下a.txt的密文 多次动调尝试输入流和输出流的不同

这里会有很多函数嵌套,但也能看到会调用一些左移位数表,加上是每八个字节和八个字节的key进行比较,中间key还转换为hex和bin,

应该是无魔改des

搞出解密脚本,删删改改

#include "DES.h"
#include<bitset>
#include<fstream>

using namespace std;

DES::DES()
{
}


DES::~DES()
{
}

bitset<32> DES::F(bitset<32> R, bitset<48> k) {
	//E盒扩展
	bitset<48> expandR;
	for (int i = 0; i < 48; i++)
		expandR[47 - i] = R[32 - E[i]];  //expandR[i] = R[E[i] - 1];
	//异或
	expandR = expandR ^ k;
	//S盒代替
	bitset<32> output;
	int x = 0;
	for (int i = 0; i < 48; i = i + 6)
	{
		int row = expandR[i] * 2 + expandR[i + 5];
		int col = expandR[i + 1] * 8 + expandR[i + 2] * 4 + expandR[i + 3] * 2 + expandR[i + 4];
		int num = S_BOX[i / 6][row][col];
		bitset<4> temp(num);
		output[x + 3] = temp[0];
		output[x + 2] = temp[1];
		output[x + 1] = temp[2];
		output[x] = temp[3];
		x += 4;
	}
	//P盒置换
	bitset<32> tmp = output;
	for (int i = 0; i < 32; i++)
		output[i] = tmp[P[i] - 1];

	return output;
}
//左移函数
bitset<28> DES::leftshift(bitset<28> k, int shift) {
	bitset<28> temp = k;
	if (shift == 1)
	{
		for (int i = 0; i < 27; i++)
		{
			if (i - shift < 0)
				k[i - shift + 28] = temp[i];
			else
				k[i] = temp[i + shift];
		}
	}
	if (shift == 2)
	{
		for (int i = 0; i < 26; i++)
		{
			if (i - shift < 0)
				k[i - shift + 28] = temp[i];
			else
				k[i] = temp[i + shift];
		}
	}
	return k;
}

void DES::generateKeys() {
	bitset<56> real_key;
	bitset<28> left;
	bitset<28> right;
	bitset<48> compressKey;

	//首先经过选择置换PC-1,将初始密钥的8bit奇偶校验位去掉
	//并重新编排
	for (int i = 0; i < 56; i++)
		real_key[i] = key[PC_1[i] - 1];

	for (int round = 0; round < 16; round++)
	{
		for (int i = 0; i < 28; i++)
			left[i] = real_key[i];
		for (int i = 28; i < 56; i++)
			right[i - 28] = real_key[i];
		//左移
		left = leftshift(left, shiftBits[round]);
		right = leftshift(right, shiftBits[round]);
		//连接,置换选择PC-2做重排,进行压缩
		for (int i = 0; i < 28; i++)
			real_key[i] = left[i];
		for (int i = 28; i < 56; i++)
			real_key[i] = right[i - 28];
		for (int i = 0; i < 48; i++)
		{
			int m = PC_2[i];
			compressKey[i] = real_key[m - 1];
		}

		subkey[round] = compressKey;
	}

}


// 工具函数:将char字符数组转为二进制
bitset<64> DES::char_to_bit(const char s[8]) {
	bitset<64> bits;
	int x = 0;
	for (int i = 0; i < 8; i++)
	{
		int num = int(s[i]);
		bitset<8> temp(num);
		for (int j = 7; j >= 0; j--)
		{
			bits[x + j] = temp[7 - j];
		}
		x += 8;
	}
	/*for (int i = 0; i<8; ++i)
		for (int j = 0; j<8; ++j)
			bits[i * 8 + j] = ((s[i] >> j) & 1);
			*/
	return bits;
}
//工具函数:进行二进制逆向转换
bitset<64> DES::change(bitset<64> temp) {
	bitset<64> bits;
	bitset<8> n;
	for (int i = 0; i < 64; i = i + 8)
	{
		for (int j = 0; j < 8; j++)
		{
			bits[i + j] = temp[i + 7 - j];
		}
	}
	return bits;
}

bitset<64> DES::DES_encryp(bitset<64>& plain) {
	bitset<64> cipher;
	bitset<64> currentBits;
	bitset<32> left;
	bitset<32> right;
	bitset<32> newLeft;
	//初始置换IP
	for (int i = 0; i < 64; i++)
		currentBits[i] = plain[IP[i] - 1];//

	for (int i = 0; i < 32; i++)
		left[i] = currentBits[i];
	for (int i = 32; i < 64; i++)
		right[i - 32] = currentBits[i];
	//进入16轮轮变换
	for (int round = 0; round < 16; round++)
	{
		newLeft = right;
		right = left ^ F(right, subkey[round]);
		left = newLeft;
	}
	//合并
	for (int i = 0; i < 32; i++)
		cipher[i] = right[i];
	for (int i = 32; i < 64; i++)
		cipher[i] = left[i - 32];
	//逆初始化置换
	currentBits = cipher;
	for (int i = 0; i < 64; i++)
		cipher[i] = currentBits[IP_1[i] - 1];

	return cipher;
}

bitset<64> DES::DES_decrypt(bitset<64>& cipher) {
	bitset<64> plain;
	bitset<64> currentBits;
	bitset<32> left;
	bitset<32> right;
	bitset<32> newLeft;
	//置换IP
	for (int i = 0; i < 64; i++)
		currentBits[i] = cipher[IP[i] - 1];

	for (int i = 0; i < 32; i++)
		left[i] = currentBits[i];
	for (int i = 32; i < 64; i++)
		right[i - 32] = currentBits[i];
	//进入16轮迭代(子密钥逆序应用)
	for (int round = 0; round < 16; round++)
	{
		newLeft = right;
		right = left ^ F(right, subkey[15 - round]);
		left = newLeft;
	}
	//合并
	for (int i = 0; i < 32; i++)
		plain[i] = right[i];
	for (int i = 32; i < 64; i++)
		plain[i] = left[i - 32];
	//逆初始化置换
	currentBits = plain;
	for (int i = 0; i < 64; i++)
		plain[i] = currentBits[IP_1[i] - 1];

	return plain;
}


void DES::show_encryp() {
	bitset<64> plain = char_to_bit(s.c_str());
	key = char_to_bit(k.c_str());
	// 生成16个子密钥
	generateKeys();
	// 密文写入 a.txt
	bitset<64> cipher = DES_encryp(plain);
	fstream file1;
	file1.open("D://r.txt", ios::binary | ios::out);
	file1.write((char*)&cipher, sizeof(cipher));
	file1.close();
}


void DES::show_decrypt() {
	bitset<64> temp;
	key = char_to_bit(k.c_str());
	generateKeys();
	fstream file2;
	file2.open("E://CTF//cat (1)//nepctf//d.txt", ios::binary | ios::in); 
	file2.read((char*)&temp, sizeof(temp));
	file2.close();

	bitset<64> temp_plain = DES_decrypt(temp);
	bitset<64> temp_1 = change(temp_plain);

	file2.open("E://Vstudio2019Project//NepctfCat//Debug//a.txt", ios::binary | ios::out);
	file2.write((char*)&temp_1, sizeof(temp_1));
	file2.close();
}

int main() {
	DES C;
	string s = "flag{123";
	string k = "52101314"; 
	C.get_s(s);
	C.get_key(k);
	//nepctf{ben_ju_mao_is_so_stupid!}
	C.show_encryp();
	C.show_decrypt();
}

效验了一些输出流

image-20220929112515532

nepctf{ben_ju_mao_is_so_stupid!}

标签:DESLearn,temp,esp,int,cat,++,ebp,bitset,nepctf
From: https://www.cnblogs.com/Chis42/p/16897389.html

相关文章