强网杯-Just RE-3DES逆向分析

强网杯just re

z3求解

题目流程很简单,查找字符串找到主函数

int __cdecl main(int argc, const char **argv, const char **envp)
{
  unsigned int *v3; // edi
  signed int v4; // eax
  _BYTE *v5; // edx
  int v6; // eax
  int result; // eax
  char v8; // [esp+4h] [ebp-68h]
  int savedregs; // [esp+6Ch] [ebp+0h]

  puts("      #                        ######         ");
  puts("      # #    #  ####  #####    #     # ###### ");
  puts("      # #    # #        #      #     # #      ");
  puts("      # #    #  ####    #      ######  #####  ");
  puts("#     # #    #      #   #      #   #   #      ");
  puts("#     # #    # #    #   #      #    #  #      ");
  puts(" #####   ####   ####    #      #     # ###### ");
  sub_401CE0("%s", &v8);
  v4 = sub_401610((int)&v8, (int)&savedregs);
  if ( v4 && (sub_4018A0(v4, v5, v3), v6) )
  {
    puts("congrats!");
    sub_401CA0("flag{%.26s}\n\n", &v8);
    result = 0;
  }
  else
  {
    puts("sorry..");
    result = 0;
  }
  return result;
}

程序首先执行401610函数且不能返回0。进入该函数

signed int __usercall sub_401610@<eax>(int a1@<ecx>, int a2@<ebp>)
{
  int v2; // edi
  unsigned int v3; // eax
  int v4; // esi
  char input; // dh
  unsigned __int8 v6; // dl
  int v7; // eax
  signed int v8; // ecx
  __m128i v9; // xmm5
  char v10; // dl
  unsigned __int8 v11; // dh
  unsigned __int8 v12; // cl
  char v13; // ch
  unsigned __int8 v14; // ch
  char v15; // dl
  unsigned __int8 v16; // dh
  signed int v17; // esi
  __m128i v18; // xmm0
  __m128i v19; // xmm0
  signed int v20; // esi
  __m128i v21; // xmm4
  signed int v22; // ecx
  unsigned __int64 v23; // rax
  HANDLE v24; // eax
  unsigned __int64 v26; // [esp-54h] [ebp-60h]
  __m128i v27; // [esp-20h] [ebp-2Ch]
  int v28; // [esp-8h] [ebp-14h]
  unsigned __int8 v29; // [esp-2h] [ebp-Eh]
  unsigned __int8 v30; // [esp-1h] [ebp-Dh]
  int v31; // [esp+0h] [ebp-Ch]
  int v32; // [esp+4h] [ebp-8h]
  int retaddr; // [esp+Ch] [ebp+0h]

  v31 = a2;
  v32 = retaddr;
  v2 = a1;
  v26 = __rdtsc();
  v3 = 0;
  v4 = 0;
  while ( 1 )
  {
    input = *(_BYTE *)(v4 + a1);
    if ( input >= 0x30 && input <= 0x39 )
    {
      v6 = input - 0x41;
      goto LABEL_6;
    }
    v6 = input - 0x41;
    if ( (unsigned __int8)(input - 0x41) > 0x19u )
      break;
LABEL_6:
    v3 *= 0x10;                                 // 左移4位
    if ( (unsigned __int8)(input - 0x30) <= 9u )
    {
      v7 = v3 - 0x30;
LABEL_10:
      v3 = input + v7;
      goto LABEL_11;
    }
    if ( v6 <= 0x19u )
    {
      v7 = v3 - 0x37;
      goto LABEL_10;
    }
LABEL_11:
    if ( ++v4 >= 8 )
    {
      v8 = 1;
      goto LABEL_14;
    }
  }
  v8 = 0;
LABEL_14:
  v9 = _mm_shuffle_epi32(_mm_cvtsi32_si128(v3), 0);
  if ( !v8 )
    return 0;
  v10 = *(_BYTE *)(v2 + 8);
  v11 = 0;
  if ( v10 >= 0x30 && v10 <= 0x39 )
  {
    v12 = v10 - 0x41;
    v30 = v10 - 0x41;
    goto LABEL_19;
  }
  v12 = v10 - 0x41;
  v30 = v10 - 0x41;
  if ( (unsigned __int8)(v10 - 0x41) > 0x19u )
  {
LABEL_34:
    v17 = 0;
    goto LABEL_35;
  }
LABEL_19:
  v13 = *(_BYTE *)(v2 + 9);
  v29 = v12;
  if ( v13 < 0x30 )
  {
    v12 = v29;
  }
  else if ( v13 <= 0x39 )
  {
    v14 = v13 - 0x41;
    goto LABEL_24;
  }
  v14 = v13 - 0x41;
  v30 = v12;
  if ( v14 > 0x19u )
    goto LABEL_34;
LABEL_24:
  if ( (unsigned __int8)(v10 - 0x30) > 9u )
  {
    if ( v30 > 0x19u )
      v15 = 0;
    else
      v15 = 0x10 * (v10 - 7);
  }
  else
  {
    v15 = 0x10 * v10;
  }
  v16 = *(_BYTE *)(v2 + 9) - 0x30;
  if ( v16 > 9u )
  {
    if ( v14 <= 0x19u )
    {
      v17 = 1;
      v11 = v15 + *(_BYTE *)(v2 + 9) - 0x37;
      goto LABEL_35;
    }
    v16 = 0;
  }
  v11 = v15 + v16;
  v17 = 1;
LABEL_35:
  v18 = _mm_cvtsi32_si128((char)v11);
  v19 = _mm_unpacklo_epi8(v18, v18);
  v27 = _mm_shuffle_epi32(_mm_unpacklo_epi16(v19, v19), 0);
  if ( !v17 )
    return 0;
  v20 = 0;
  if ( dword_4053C4 >= 2 )
  {
    v20 = 16;
    v21 = _mm_mullo_epi32(_mm_cvtepu8_epi32(_mm_cvtsi32_si128(v27.m128i_u32[0])), (__m128i)xmmword_404380);
    xmmword_405018 = (__int128)_mm_xor_si128(
                                 _mm_add_epi32((__m128i)xmmword_404340, v9),
                                 _mm_add_epi32(v21, (__m128i)xmmword_405018));
    xmmword_405028 = (__int128)_mm_xor_si128(
                                 _mm_add_epi32(_mm_add_epi32((__m128i)xmmword_404350, (__m128i)xmmword_404340), v9),
                                 _mm_add_epi32(v21, (__m128i)xmmword_405028));
    xmmword_405038 = (__int128)_mm_xor_si128(
                                 _mm_add_epi32(_mm_add_epi32((__m128i)xmmword_404360, (__m128i)xmmword_404340), v9),
                                 _mm_add_epi32(v21, (__m128i)xmmword_405038));
    xmmword_405048 = (__int128)_mm_xor_si128(
                                 _mm_add_epi32(_mm_add_epi32((__m128i)xmmword_404370, (__m128i)xmmword_404340), v9),
                                 _mm_add_epi32(v21, (__m128i)xmmword_405048));
  }
  do
  {
    *((_DWORD *)&xmmword_405018 + v20) = (v20 + v3) ^ (16843009 * v11 + *((_DWORD *)&xmmword_405018 + v20));
    ++v20;
  }
  while ( v20 < 24 );
  v22 = 0;
  do
  {
    JUMPOUT(*((_BYTE *)&xmmword_405018 + v22), *((_BYTE *)&loc_404148 + v22), &unk_40188E);
    ++v22;
  }
  while ( v22 < 96 );
  v28 = 0;
  v23 = __rdtsc();
  if ( HIDWORD(v23) > HIDWORD(v26) || (v28 = v23 - v26, (unsigned int)(v23 - v26) >= 0xFFFFFF) )
    MEMORY[0] = 0;
  v24 = GetCurrentProcess();
  WriteProcessMemory(v24, sub_4018A0, &xmmword_405018, 0x60u, 0);
  return 1;
}

函数很长,先粗略分析一下,首先输入字符不能大于’Z’否则直接返回0,有减去’A’和’0’,左移4位的操作,还有大写字母减去37,循环8次,感觉像前8位字符变成十六进制数字组合起来

继续向下看,之后取第九位和第十位字符,进行了与上方类似的操作。我们调试一下验证结果。

测试字符为ABCD123491

在这里插入图片描述

前8位果然如此,再接着往下走,寄存器出现了EDX=9190

在这里插入图片描述

再继续往下运算于是便涉及到SSE了。。。XMM寄存器看不了在OD中,但是在x32_dbg中能够看,先不管他继续向下运行。运行到一处循环。

在这里插入图片描述

看一下这个循环.大致表达式子如下 假设测试字符1234567891,i表计数循环,从0开始

扫描二维码关注公众号,回复: 8910294 查看本文章

(0x12345678+0x10+i)^(91*1010101+ds:[405058+4 *i])将计算的结果给405058+4 * i

而下方循环正是判断405058处地址与404188处地址是否相等,正好形成了一个方程组的格局

可以利用Z3求解,但是比赛时试着用z3求解异或好像用不了。。。于是便写了一个暴力程序跑了一下,第一个跑出的结果便是正确的

#include<windows.h>
#include<iostream>
using namespace std;
int main()
{
	for (int i = 0x10000000; i <= (unsigned int)0xffffffff; i++)
	{
		for (int j = 0; j <= 0x100; j++)
		{

			if (((i + 0x10) ^ (j * 0x1010101 + 0x1e47913f)) == 0x24448840)
			{

				if (((i + 0x11) ^ (j * 0x1010101 + 0x1e87963c)) == 0x24848d4c)
				{

					printf("x=%x  y=%x \n", i, j);
				}
			}
		}
	}
	printf("finish!");
	system("pause");
	return 0;
}

赛后也正好借机会学习一下z3的异或使用方法

from z3 import *
a=[0x1e47913f,0x1e87963c,0xfa0b0acd,0x035b0958,0xf5e74cf4,0xfa1261dc,0x854b2f05,0xf852ed82]
b=[0x24448840,0x24848d4c,0x000001fc,0x0f50006a,0x1c244411,0x000f58e8,0x8d406a00,0x02482484]
solver=z3.Solver()
x=BitVec('x',32)
y=BitVec('y',32)
for i in range(8):
    solver.add(((a[i]+y*0x1010101)^(i+0x10+x))==b[i])
solver.add(x>0)
solver.add(y>0,y<0xff)
if (solver.check()==z3.sat):
    print(solver.model())
else:
    print("unsat")

在这里插入图片描述
得到结果转换16进制前10个字符为1324220819

之后第一个函数调试是还是不过卡在了rdstc这里(获得程序或者一段代码运行的时间),应该是对抗调试用的,把函数内的断点全部清除掉,顺利返回1.

来到下一个函数,4018A0,发现IDA和OD处的二进制码不一样,IDA不能F5查看反汇编。其实是在上一个函数通过WriteProcessMemory将机器码写入了进去,来到4018A0使用OD将其dump出来。

IDA便得以在4018A0处F5观察程序逻辑

3DES分析

函数内部比较长,我们直接查找与我们输入有关的函数

v1 = *(_OWORD *)(input + 10);
  v17 = 0;
  input_1 = v1;

首先取后10位作为input1

v3=strlen(&input1)  
memcpy(&Dst, &input_1, v3);
  v4 = 8 * (v3 / 8) + 8;
  memset(&Dst + v3, (char)(8 - v3 % 8), 8 - v3 % 8);

之后将10位以后的数据复制给DST,并且在DST之后分配内存 长度为8-v3%8分配内容也为8-v3%8,且v4中是以strlen/8说明长度最好为8的整数,继续向下走

if ( v4 > 0 )
  {
    v5 = 0;
    do
    {
      v6 = (unsigned __int8)*(&v33 + v5);
      v7 = (unsigned __int8)*(&v34 + v5);
      v21 = ((unsigned __int8)*(&v32 + v5) << 24) | ((unsigned __int8)*(&v31 + v5) << 16) | ((unsigned __int8)*(&v30 + v5) << 8) | (unsigned __int8)*(&Dst + v5);
      v22 = (v7 << 8) | v6 | (((unsigned __int8)*(&v35 + v5) | ((unsigned __int8)v36[v5] << 8)) << 16);
      sub_401500((int)&v20, (unsigned int *)&v21, (int)&v19, (int)&v18);
      v8 = v21;
      *(&v37 + v5) = v21;
      *(&v38 + v5) = BYTE1(v8);
      *(&v39 + v5) = BYTE2(v8);
      *(&v40 + v5) = HIBYTE(v8);
      HIWORD(v8) = HIWORD(v22);
      v9 = BYTE1(v22);
      *(&v41 + v5) = v22;
      *(&v42 + v5) = v9;
      *(&v43 + v5) = BYTE2(v8);
      v44[v5] = HIBYTE(v8);
      v5 += 8;
    }
    while ( v5 < v4 );
  }

看一下这个循环次数,是由长度的8的倍数所决定

v21以由前4个字符逆序拼接而成,V22由后4个字符逆序拼接而成,之后执行401500

进入4015000函数

ip置换

v4 = a2;                                      // 前4个字符
  v5 = (*a2 ^ (a2[1] >> 4)) & 0xF0F0F0F;
  v6 = v5 ^ *a2;
  v7 = 16 * v5 ^ a2[1];
  v8 = (unsigned __int16)(v7 ^ ((v5 ^ *a2) >> 16));
  v9 = v8 ^ v7;
  v10 = (v8 << 16) ^ v6;
  v11 = (v10 ^ (v9 >> 2)) & 0x33333333;
  v12 = v11 ^ v10;
  v13 = 4 * v11 ^ v9;
  v14 = (v13 ^ (v12 >> 8)) & 0xFF00FF;
  v15 = v14 ^ v13;
  v16 = (v14 << 8) ^ v12;
  *a2 = v16 ^ (v16 ^ (v15 >> 1)) & 0x55555555;
  a2[1] = v15 ^ 2 * ((v16 ^ (v15 >> 1)) & 0x55555555);
  sub_401250(a1, a2, 1);
  sub_401250(a3, v4, 0);
  sub_401250(a4, v4, 1);
  v17 = (*v4 ^ (v4[1] >> 1)) & 0x55555555;
  v18 = v17 ^ *v4;
  v19 = 2 * v17 ^ v4[1];
  v20 = (v19 ^ ((v17 ^ *v4) >> 8)) & 0xFF00FF;
  v21 = v20 ^ v19;
  v22 = (v20 << 8) ^ v18;
  v23 = (v22 ^ (v21 >> 2)) & 0x33333333;
  v24 = v23 ^ v22;
  v25 = 4 * v23 ^ v21;
  v26 = (unsigned __int16)(v25 ^ HIWORD(v24));
  v27 = v26 ^ v25;
  v28 = (v26 << 16) ^ v24;
  result = v28 ^ (v28 ^ (v27 >> 4)) & 0xF0F0F0F;
  *v4 = result;
  v4[1] = v27 ^ 16 * ((v28 ^ (v27 >> 4)) & 0xF0F0F0F);
  return result;
}

后4个字符右移4位之后异或上前4个字符再与上0xf0f0f0f…后面一堆运算到402050直接黑盒吧

测试输入的12345678

变为00FF016600FF1EAA (验证一下)

是IP置换。

继续往下走 进入第一个401250函数参数2为IP置换的前8个值

v3 = (*a2 >> 29) + 8 * *a2;
  v4 = (a2[1] >> 29) + 8 * a2[1];
  if ( a3 )
  {
    v5 = a1 + 8;
    v15 = 8;
    v17 = (_DWORD *)(a1 + 8);
    do
    {
      v6 = v3 ^ *(_DWORD *)(v5 - 8);
      v7 = ((v3 ^ *(_DWORD *)(v5 - 4)) >> 4) + ((v3 ^ *(_DWORD *)(v5 - 4)) << 28);
      v4 ^= dword_403748[v6 >> 26] ^ dword_403848[v7 >> 26] ^ dword_403148[(unsigned __int8)v6 >> 2] ^ dword_403348[(unsigned __int16)v6 >> 10] ^ dword_403548[(v6 >> 18) & 0x3F] ^ dword_403248[(v7 >> 2) & 0x3F] ^ dword_403448[(v7 >> 10) & 0x3F] ^ dword_403648[(v7 >> 18) & 0x3F];
      v8 = ((v4 ^ v17[1]) >> 4) + ((v4 ^ v17[1]) << 28);
      v3 ^= dword_403748[(v4 ^ *v17) >> 26] ^ dword_403848[v8 >> 26] ^ dword_403148[((v4 ^ *v17) >> 2) & 0x3F] ^ dword_403348[(unsigned __int8)((unsigned __int16)(v4 ^ *(_WORD *)v17) >> 8) >> 2] ^ dword_403548[((v4 ^ *v17) >> 18) & 0x3F] ^ dword_403248[(v8 >> 2) & 0x3F] ^ dword_403448[(v8 >> 10) & 0x3F] ^ dword_403648[(v8 >> 18) & 0x3F];
      v5 = (int)(v17 + 4);
      v9 = v15-- == 1;
      v17 += 4;
    }
    while ( !v9 );
  }

IP置换后的前32位移位之后赋值给v3 后32位也同理赋值给v4

v3=4 5 6 7 8 9 …32 1 2 3 (数字表示位数)

之后再与一串字符异或赋值给v6

与一串字符串异或后进行移位,移位之后赋值给v7

此时v7=32 1 2 3 4 5 6 7 8 9…31(数字表示位数)

之后从一个8个表中取值,看一下这8个下标分别是(数字表示位数)

32,1,2,3,4,5,

4,5,6,7,8,9,

8,9,10,11,12,13,

12,13,14,15,16,17,

16,17,18,19,20,21,

20,21,22,23,24,25,

24,25,26,27,28,29,

28,29,30,31,32,1

有点像DES的扩展密钥的下标但是区别在于,v6和v7是由不一样的数据异或而成

看一下这8个数组里的值

/* nibble 8 */

​ 0x02080800L, 0x00080000L, 0x02000002L, 0x02080802L,
​ 0x02000000L, 0x00080802L, 0x00080002L, 0x02000002L,
​ 0x00080802L, 0x02080800L, 0x02080000L, 0x00000802L,
​ 0x02000802L, 0x02000000L, 0x00000000L, 0x00080002L,
​ 0x00080000L, 0x00000002L, 0x02000800L, 0x00080800L,
​ 0x02080802L, 0x02080000L, 0x00000802L, 0x02000800L,
​ 0x00000002L, 0x00000800L, 0x00080800L, 0x02080002L,
​ 0x00000800L, 0x02000802L, 0x02080002L, 0x00000000L,
​ 0x00000000L, 0x02080802L, 0x02000800L, 0x00080002L,
​ 0x02080800L, 0x00080000L, 0x00000802L, 0x02000800L,
​ 0x02080002L, 0x00000800L, 0x00080800L, 0x02000002L,
​ 0x00080802L, 0x00000002L, 0x02000002L, 0x02080000L,
​ 0x02080802L, 0x00080800L, 0x02080000L, 0x02000802L,
​ 0x02000000L, 0x00000802L, 0x00080002L, 0x00000000L,
​ 0x00080000L, 0x02000000L, 0x02000802L, 0x02080800L,
​ 0x00000002L, 0x02080002L, 0x00000800L, 0x00080802L,
​ /* nibble 1 /
​ 0x40108010L, 0x00000000L, 0x00108000L, 0x40100000L,
​ 0x40000010L, 0x00008010L, 0x40008000L, 0x00108000L,
​ 0x00008000L, 0x40100010L, 0x00000010L, 0x40008000L,
​ 0x00100010L, 0x40108000L, 0x40100000L, 0x00000010L,
​ 0x00100000L, 0x40008010L, 0x40100010L, 0x00008000L,
​ 0x00108010L, 0x40000000L, 0x00000000L, 0x00100010L,
​ 0x40008010L, 0x00108010L, 0x40108000L, 0x40000010L,
​ 0x40000000L, 0x00100000L, 0x00008010L, 0x40108010L,
​ 0x00100010L, 0x40108000L, 0x40008000L, 0x00108010L,
​ 0x40108010L, 0x00100010L, 0x40000010L, 0x00000000L,
​ 0x40000000L, 0x00008010L, 0x00100000L, 0x40100010L,
​ 0x00008000L, 0x40000000L, 0x00108010L, 0x40008010L,
​ 0x40108000L, 0x00008000L, 0x00000000L, 0x40000010L,
​ 0x00000010L, 0x40108010L, 0x00108000L, 0x40100000L,
​ 0x40100010L, 0x00100000L, 0x00008010L, 0x40008000L,
​ 0x40008010L, 0x00000010L, 0x40100000L, 0x00108000L,
​ },{
​ /
nibble 2 /
​ 0x04000001L, 0x04040100L, 0x00000100L, 0x04000101L,
​ 0x00040001L, 0x04000000L, 0x04000101L, 0x00040100L,
​ 0x04000100L, 0x00040000L, 0x04040000L, 0x00000001L,
​ 0x04040101L, 0x00000101L, 0x00000001L, 0x04040001L,
​ 0x00000000L, 0x00040001L, 0x04040100L, 0x00000100L,
​ 0x00000101L, 0x04040101L, 0x00040000L, 0x04000001L,
​ 0x04040001L, 0x04000100L, 0x00040101L, 0x04040000L,
​ 0x00040100L, 0x00000000L, 0x04000000L, 0x00040101L,
​ 0x04040100L, 0x00000100L, 0x00000001L, 0x00040000L,
​ 0x00000101L, 0x00040001L, 0x04040000L, 0x04000101L,
​ 0x00000000L, 0x04040100L, 0x00040100L, 0x04040001L,
​ 0x00040001L, 0x04000000L, 0x04040101L, 0x00000001L,
​ 0x00040101L, 0x04000001L, 0x04000000L, 0x04040101L,
​ 0x00040000L, 0x04000100L, 0x04000101L, 0x00040100L,
​ 0x04000100L, 0x00000000L, 0x04040001L, 0x00000101L,
​ 0x04000001L, 0x00040101L, 0x00000100L, 0x04040000L,
​ },{
​ /
nibble 3 /
​ 0x00401008L, 0x10001000L, 0x00000008L, 0x10401008L,
​ 0x00000000L, 0x10400000L, 0x10001008L, 0x00400008L,
​ 0x10401000L, 0x10000008L, 0x10000000L, 0x00001008L,
​ 0x10000008L, 0x00401008L, 0x00400000L, 0x10000000L,
​ 0x10400008L, 0x00401000L, 0x00001000L, 0x00000008L,
​ 0x00401000L, 0x10001008L, 0x10400000L, 0x00001000L,
​ 0x00001008L, 0x00000000L, 0x00400008L, 0x10401000L,
​ 0x10001000L, 0x10400008L, 0x10401008L, 0x00400000L,
​ 0x10400008L, 0x00001008L, 0x00400000L, 0x10000008L,
​ 0x00401000L, 0x10001000L, 0x00000008L, 0x10400000L,
​ 0x10001008L, 0x00000000L, 0x00001000L, 0x00400008L,
​ 0x00000000L, 0x10400008L, 0x10401000L, 0x00001000L,
​ 0x10000000L, 0x10401008L, 0x00401008L, 0x00400000L,
​ 0x10401008L, 0x00000008L, 0x10001000L, 0x00401008L,
​ 0x00400008L, 0x00401000L, 0x10400000L, 0x10001008L,
​ 0x00001008L, 0x10000000L, 0x10000008L, 0x10401000L,
​ },{
​ /
nibble 4 /
​ 0x08000000L, 0x00010000L, 0x00000400L, 0x08010420L,
​ 0x08010020L, 0x08000400L, 0x00010420L, 0x08010000L,
​ 0x00010000L, 0x00000020L, 0x08000020L, 0x00010400L,
​ 0x08000420L, 0x08010020L, 0x08010400L, 0x00000000L,
​ 0x00010400L, 0x08000000L, 0x00010020L, 0x00000420L,
​ 0x08000400L, 0x00010420L, 0x00000000L, 0x08000020L,
​ 0x00000020L, 0x08000420L, 0x08010420L, 0x00010020L,
​ 0x08010000L, 0x00000400L, 0x00000420L, 0x08010400L,
​ 0x08010400L, 0x08000420L, 0x00010020L, 0x08010000L,
​ 0x00010000L, 0x00000020L, 0x08000020L, 0x08000400L,
​ 0x08000000L, 0x00010400L, 0x08010420L, 0x00000000L,
​ 0x00010420L, 0x08000000L, 0x00000400L, 0x00010020L,
​ 0x08000420L, 0x00000400L, 0x00000000L, 0x08010420L,
​ 0x08010020L, 0x08010400L, 0x00000420L, 0x00010000L,
​ 0x00010400L, 0x08010020L, 0x08000400L, 0x00000420L,
​ 0x00000020L, 0x00010420L, 0x08010000L, 0x08000020L,
​ },{
​ /
nibble 5 /
​ 0x80000040L, 0x00200040L, 0x00000000L, 0x80202000L,
​ 0x00200040L, 0x00002000L, 0x80002040L, 0x00200000L,
​ 0x00002040L, 0x80202040L, 0x00202000L, 0x80000000L,
​ 0x80002000L, 0x80000040L, 0x80200000L, 0x00202040L,
​ 0x00200000L, 0x80002040L, 0x80200040L, 0x00000000L,
​ 0x00002000L, 0x00000040L, 0x80202000L, 0x80200040L,
​ 0x80202040L, 0x80200000L, 0x80000000L, 0x00002040L,
​ 0x00000040L, 0x00202000L, 0x00202040L, 0x80002000L,
​ 0x00002040L, 0x80000000L, 0x80002000L, 0x00202040L,
​ 0x80202000L, 0x00200040L, 0x00000000L, 0x80002000L,
​ 0x80000000L, 0x00002000L, 0x80200040L, 0x00200000L,
​ 0x00200040L, 0x80202040L, 0x00202000L, 0x00000040L,
​ 0x80202040L, 0x00202000L, 0x00200000L, 0x80002040L,
​ 0x80000040L, 0x80200000L, 0x00202040L, 0x00000000L,
​ 0x00002000L, 0x80000040L, 0x80002040L, 0x80202000L,
​ 0x80200000L, 0x00002040L, 0x00000040L, 0x80200040L,
​ },{
​ /
nibble 6 /
​ 0x00004000L, 0x00000200L, 0x01000200L, 0x01000004L,
​ 0x01004204L, 0x00004004L, 0x00004200L, 0x00000000L,
​ 0x01000000L, 0x01000204L, 0x00000204L, 0x01004000L,
​ 0x00000004L, 0x01004200L, 0x01004000L, 0x00000204L,
​ 0x01000204L, 0x00004000L, 0x00004004L, 0x01004204L,
​ 0x00000000L, 0x01000200L, 0x01000004L, 0x00004200L,
​ 0x01004004L, 0x00004204L, 0x01004200L, 0x00000004L,
​ 0x00004204L, 0x01004004L, 0x00000200L, 0x01000000L,
​ 0x00004204L, 0x01004000L, 0x01004004L, 0x00000204L,
​ 0x00004000L, 0x00000200L, 0x01000000L, 0x01004004L,
​ 0x01000204L, 0x00004204L, 0x00004200L, 0x00000000L,
​ 0x00000200L, 0x01000004L, 0x00000004L, 0x01000200L,
​ 0x00000000L, 0x01000204L, 0x01000200L, 0x00004200L,
​ 0x00000204L, 0x00004000L, 0x01004204L, 0x01000000L,
​ 0x01004200L, 0x00000004L, 0x00004004L, 0x01004204L,
​ 0x01000004L, 0x01004200L, 0x01004000L, 0x00004004L,
​ },{
​ /
nibble 7 */
​ 0x20800080L, 0x20820000L, 0x00020080L, 0x00000000L,
​ 0x20020000L, 0x00800080L, 0x20800000L, 0x20820080L,
​ 0x00000080L, 0x20000000L, 0x00820000L, 0x00020080L,
​ 0x00820080L, 0x20020080L, 0x20000080L, 0x20800000L,
​ 0x00020000L, 0x00820080L, 0x00800080L, 0x20020000L,
​ 0x20820080L, 0x20000080L, 0x00000000L, 0x00820000L,
​ 0x20000000L, 0x00800000L, 0x20020080L, 0x20800080L,
​ 0x00800000L, 0x00020000L, 0x20820000L, 0x00000080L,
​ 0x00800000L, 0x00020000L, 0x20000080L, 0x20820080L,
​ 0x00020080L, 0x20000000L, 0x00000000L, 0x00820000L,
​ 0x20800080L, 0x20020080L, 0x20020000L, 0x00800080L,
​ 0x20820000L, 0x00000080L, 0x00800080L, 0x20020000L,
​ 0x20820080L, 0x00800000L, 0x20800000L, 0x20000080L,
​ 0x00820000L, 0x00020080L, 0x20020080L, 0x20800000L,
​ 0x00000080L, 0x20820000L, 0x00820080L, 0x00000000L,
​ 0x20000000L, 0x20800080L, 0x00020000L, 0x00820080L

和一般的DES盒也不同,将8个DES盒中取出的数据相互异或,最后再与ip置换后32位异或,

之后ip置换后32位异或后的数据重复上述步骤。一共循环16次

*a2 = (v4 >> 3) + (v4 << 29);
  result = (v3 >> 3) + (v3 << 29);
  a2[1] = result;
  return result;

最后将一开始移位的数据进行还原,并返回。

进入第二个401250函数,参数2为第一次加密之后的结果

 v3 = (*a2 >> 29) + 8 * *a2;
 v4 = (a2[1] >> 29) + 8 * a2[1];

else
  {
    v10 = a1 + 112;
    v16 = 8;
    v18 = (_DWORD *)(a1 + 112);
    do
    {
      v11 = v3 ^ *(_DWORD *)(v10 + 8);
      v12 = ((v3 ^ *(_DWORD *)(v10 + 12)) >> 4) + ((v3 ^ *(_DWORD *)(v10 + 12)) << 28);
      v4 ^= dword_403748[v11 >> 26] ^ dword_403848[v12 >> 26] ^ dword_403148[(unsigned __int8)v11 >> 2] ^ dword_403348[(unsigned __int16)v11 >> 10] ^ dword_403548[(v11 >> 18) & 0x3F] ^ dword_403248[(v12 >> 2) & 0x3F] ^ dword_403448[(v12 >> 10) & 0x3F] ^ dword_403648[(v12 >> 18) & 0x3F];
      v13 = ((v4 ^ v18[1]) >> 4) + ((v4 ^ v18[1]) << 28);
      v3 ^= dword_403748[(v4 ^ *v18) >> 26] ^ dword_403848[v13 >> 26] ^ dword_403148[((v4 ^ *v18) >> 2) & 0x3F] ^ dword_403348[(unsigned __int8)((unsigned __int16)(v4 ^ *(_WORD *)v18) >> 8) >> 2] ^ dword_403548[((v4 ^ *v18) >> 18) & 0x3F] ^ dword_403248[(v13 >> 2) & 0x3F] ^ dword_403448[(v13 >> 10) & 0x3F] ^ dword_403648[(v13 >> 18) & 0x3F];
      v10 = (int)(v18 - 4);
      v9 = v16-- == 1;
      v18 -= 4;
    }

由于第三个参数为0执行else部分,else部分和上半部分差不多唯一的区别是密钥取值从后往前取的,而DES的解密部分也恰好是如此

最后又执行了一次401250函数,又是一次加密,参数是上一轮解密之后的结果。

三次执行完之后,又是一堆操作

v17 = (*v4 ^ (v4[1] >> 1)) & 0x55555555;
  v18 = v17 ^ *v4;
  v19 = 2 * v17 ^ v4[1];
  v20 = (v19 ^ ((v17 ^ *v4) >> 8)) & 0xFF00FF;
  v21 = v20 ^ v19;
  v22 = (v20 << 8) ^ v18;
  v23 = (v22 ^ (v21 >> 2)) & 0x33333333;
  v24 = v23 ^ v22;
  v25 = 4 * v23 ^ v21;
  v26 = (unsigned __int16)(v25 ^ HIWORD(v24));
  v27 = v26 ^ v25;
  v28 = (v26 << 16) ^ v24;
  result = v28 ^ (v28 ^ (v27 >> 4)) & 0xF0F0F0F;
  *v4 = result;
  v4[1] = v27 ^ 16 * ((v28 ^ (v27 >> 4)) & 0xF0F0F0F);
  return result;

和初始的IP处理的数字是反过来的应该是FP直接黑盒验证一下

初始数字

17810530018c6fdf

置换后

31050683159D85ed

密钥处理

是FP。这样3DES的操作就完成了,但是还缺少密钥前面又3个401000函数,以第一个401000函数为例去观察一下

v24 = a2;
  v2 = (a1[3] << 24) | (a1[2] << 16) | (a1[1] << 8) | *a1;
  v3 = (*((unsigned __int16 *)a1 + 3) << 16) | (a1[5] << 8) | a1[4];
  v4 = (v2 ^ (v3 >> 4)) & 0xF0F0F0F;
  v5 = (v4 ^ v2 ^ ((v4 ^ v2) << 18)) & 0xCCCC0000 ^ (((v4 ^ v2 ^ ((v4 ^ v2) << 18)) & 0xCCCC0000) >> 18) ^ v4 ^ v2;
  v6 = (16 * v4 ^ v3 ^ ((16 * v4 ^ v3) << 18)) & 0xCCCC0000 ^ (((16 * v4 ^ v3 ^ ((16 * v4 ^ v3) << 18)) & 0xCCCC0000) >> 18) ^ 16 * v4 ^ v3;
  v7 = (v5 ^ (v6 >> 1)) & 0x55555555;
  v8 = v7 ^ v5;
  v9 = 2 * v7 ^ v6;
  v10 = (v9 ^ (v8 >> 8)) & 0xFF00FF;
  v11 = v10 ^ v9;
  v12 = (v10 << 8) ^ v8;
  v13 = (v12 ^ (v11 >> 1)) & 0x55555555;
  v14 = v13 ^ v12;
  v15 = (2 * v13 ^ v11) & 0xFF00 | ((unsigned __int8)(2 * v13 ^ v11) << 16) | ((v14 & 0xF000000F | ((2 * v13 ^ v11) >> 12) & 0xFF0) >> 4);
  v16 = (char *)&unk_403108;
  result = v14 & 0xFFFFFFF;
  v23 = (char *)&unk_403108;
  do
  {
    if ( *(_DWORD *)v16 )
    {
      v18 = (result << 26) | (result >> 2);
      v19 = v15 << 26;
      v20 = v15 >> 2;
    }
    else
    {
      v18 = (result << 27) | (result >> 1);
      v19 = v15 << 27;
      v20 = v15 >> 1;
    }
    result = v18 & 0xFFFFFFF;
    v15 = (v19 | v20) & 0xFFFFFFF;
    v21 = dword_403948[result & 0x3F] | dword_403A48[(result & 0xC0 | (result >> 1) & 0xF00) >> 6] | dword_403B48[((result >> 1) & 0x60000 | result & 0x1E000) >> 13] | dword_403C48[(result & 0x100000 | ((result & 0xC00000 | (result >> 1) & 0x7000000) >> 1)) >> 20];
    v22 = dword_403D48[v15 & 0x3F] | dword_403F48[(v15 >> 15) & 0x3F] | dword_404048[(v15 & 0x1E00000 | (v15 >> 1) & 0x6000000) >> 21] | dword_403E48[(v15 & 0x180 | (v15 >> 1) & 0x1E00) >> 7];
    *v24 = (((v22 << 16) | (unsigned int)(unsigned __int16)v21) >> 30) + 4 * ((v22 << 16) | (unsigned __int16)v21);
    v24[1] = ((v22 & 0xFFFF0000 | (v21 >> 16)) >> 26) + ((v22 & 0xFFFF0000 | (v21 >> 16)) << 6);
    v16 = v23 + 4;
    v24 += 2;
    v23 = v16;
  }
  while ( (signed int)v16 < (signed int)dword_403148 );
  return result;
}

参数a1是字符串AFSAFCEDAFSAFCEDYCXCXACNDFKDCQXC和一串空地址

但是实际操作的只有前8个字符AFSAFCED

操作完毕之后将值赋值给19FD98,而此处正是与之前ip置换移位后异或的数据地址

此处还发现了8个数组

 0x00000000L,0x00000010L,0x20000000L,0x20000010L,
 0x00010000L,0x00010010L,0x20010000L,0x20010010L,
 0x00000800L,0x00000810L,0x20000800L,0x20000810L,
 0x00010800L,0x00010810L,0x20010800L,0x20010810L,
 0x00000020L,0x00000030L,0x20000020L,0x20000030L,
 0x00010020L,0x00010030L,0x20010020L,0x20010030L,
 0x00000820L,0x00000830L,0x20000820L,0x20000830L,
 0x00010820L,0x00010830L,0x20010820L,0x20010830L,
 0x00080000L,0x00080010L,0x20080000L,0x20080010L,
 0x00090000L,0x00090010L,0x20090000L,0x20090010L,
 0x00080800L,0x00080810L,0x20080800L,0x20080810L,
 0x00090800L,0x00090810L,0x20090800L,0x20090810L,
 0x00080020L,0x00080030L,0x20080020L,0x20080030L,
 0x00090020L,0x00090030L,0x20090020L,0x20090030L,
 0x00080820L,0x00080830L,0x20080820L,0x20080830L,
 0x00090820L,0x00090830L,0x20090820L,0x20090830L,
 },{
 /* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */
 0x00000000L,0x02000000L,0x00002000L,0x02002000L,
 0x00200000L,0x02200000L,0x00202000L,0x02202000L,
 0x00000004L,0x02000004L,0x00002004L,0x02002004L,
 0x00200004L,0x02200004L,0x00202004L,0x02202004L,
 0x00000400L,0x02000400L,0x00002400L,0x02002400L,
 0x00200400L,0x02200400L,0x00202400L,0x02202400L,
 0x00000404L,0x02000404L,0x00002404L,0x02002404L,
 0x00200404L,0x02200404L,0x00202404L,0x02202404L,
 0x10000000L,0x12000000L,0x10002000L,0x12002000L,
 0x10200000L,0x12200000L,0x10202000L,0x12202000L,
 0x10000004L,0x12000004L,0x10002004L,0x12002004L,
 0x10200004L,0x12200004L,0x10202004L,0x12202004L,
 0x10000400L,0x12000400L,0x10002400L,0x12002400L,
 0x10200400L,0x12200400L,0x10202400L,0x12202400L,
 0x10000404L,0x12000404L,0x10002404L,0x12002404L,
 0x10200404L,0x12200404L,0x10202404L,0x12202404L,
 },{
 /* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */
 0x00000000L,0x00000001L,0x00040000L,0x00040001L,
 0x01000000L,0x01000001L,0x01040000L,0x01040001L,
 0x00000002L,0x00000003L,0x00040002L,0x00040003L,
 0x01000002L,0x01000003L,0x01040002L,0x01040003L,
 0x00000200L,0x00000201L,0x00040200L,0x00040201L,
 0x01000200L,0x01000201L,0x01040200L,0x01040201L,
 0x00000202L,0x00000203L,0x00040202L,0x00040203L,
 0x01000202L,0x01000203L,0x01040202L,0x01040203L,
 0x08000000L,0x08000001L,0x08040000L,0x08040001L,
 0x09000000L,0x09000001L,0x09040000L,0x09040001L,
 0x08000002L,0x08000003L,0x08040002L,0x08040003L,
 0x09000002L,0x09000003L,0x09040002L,0x09040003L,
 0x08000200L,0x08000201L,0x08040200L,0x08040201L,
 0x09000200L,0x09000201L,0x09040200L,0x09040201L,
 0x08000202L,0x08000203L,0x08040202L,0x08040203L,
 0x09000202L,0x09000203L,0x09040202L,0x09040203L,
 },{
 /* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */
 0x00000000L,0x00100000L,0x00000100L,0x00100100L,
 0x00000008L,0x00100008L,0x00000108L,0x00100108L,
 0x00001000L,0x00101000L,0x00001100L,0x00101100L,
 0x00001008L,0x00101008L,0x00001108L,0x00101108L,
 0x04000000L,0x04100000L,0x04000100L,0x04100100L,
 0x04000008L,0x04100008L,0x04000108L,0x04100108L,
 0x04001000L,0x04101000L,0x04001100L,0x04101100L,
 0x04001008L,0x04101008L,0x04001108L,0x04101108L,
 0x00020000L,0x00120000L,0x00020100L,0x00120100L,
 0x00020008L,0x00120008L,0x00020108L,0x00120108L,
 0x00021000L,0x00121000L,0x00021100L,0x00121100L,
 0x00021008L,0x00121008L,0x00021108L,0x00121108L,
 0x04020000L,0x04120000L,0x04020100L,0x04120100L,
 0x04020008L,0x04120008L,0x04020108L,0x04120108L,
 0x04021000L,0x04121000L,0x04021100L,0x04121100L,
 0x04021008L,0x04121008L,0x04021108L,0x04121108L,
 },{
 /* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */
 0x00000000L,0x10000000L,0x00010000L,0x10010000L,
 0x00000004L,0x10000004L,0x00010004L,0x10010004L,
 0x20000000L,0x30000000L,0x20010000L,0x30010000L,
 0x20000004L,0x30000004L,0x20010004L,0x30010004L,
 0x00100000L,0x10100000L,0x00110000L,0x10110000L,
 0x00100004L,0x10100004L,0x00110004L,0x10110004L,
 0x20100000L,0x30100000L,0x20110000L,0x30110000L,
 0x20100004L,0x30100004L,0x20110004L,0x30110004L,
 0x00001000L,0x10001000L,0x00011000L,0x10011000L,
 0x00001004L,0x10001004L,0x00011004L,0x10011004L,
 0x20001000L,0x30001000L,0x20011000L,0x30011000L,
 0x20001004L,0x30001004L,0x20011004L,0x30011004L,
 0x00101000L,0x10101000L,0x00111000L,0x10111000L,
 0x00101004L,0x10101004L,0x00111004L,0x10111004L,
 0x20101000L,0x30101000L,0x20111000L,0x30111000L,
 0x20101004L,0x30101004L,0x20111004L,0x30111004L,
 },{
 /* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */
 0x00000000L,0x08000000L,0x00000008L,0x08000008L,
 0x00000400L,0x08000400L,0x00000408L,0x08000408L,
 0x00020000L,0x08020000L,0x00020008L,0x08020008L,
 0x00020400L,0x08020400L,0x00020408L,0x08020408L,
 0x00000001L,0x08000001L,0x00000009L,0x08000009L,
 0x00000401L,0x08000401L,0x00000409L,0x08000409L,
 0x00020001L,0x08020001L,0x00020009L,0x08020009L,
 0x00020401L,0x08020401L,0x00020409L,0x08020409L,
 0x02000000L,0x0A000000L,0x02000008L,0x0A000008L,
 0x02000400L,0x0A000400L,0x02000408L,0x0A000408L,
 0x02020000L,0x0A020000L,0x02020008L,0x0A020008L,
 0x02020400L,0x0A020400L,0x02020408L,0x0A020408L,
 0x02000001L,0x0A000001L,0x02000009L,0x0A000009L,
 0x02000401L,0x0A000401L,0x02000409L,0x0A000409L,
 0x02020001L,0x0A020001L,0x02020009L,0x0A020009L,
 0x02020401L,0x0A020401L,0x02020409L,0x0A020409L,
 },{
 /* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */
 0x00000000L,0x00000100L,0x00080000L,0x00080100L,
 0x01000000L,0x01000100L,0x01080000L,0x01080100L,
 0x00000010L,0x00000110L,0x00080010L,0x00080110L,
 0x01000010L,0x01000110L,0x01080010L,0x01080110L,
 0x00200000L,0x00200100L,0x00280000L,0x00280100L,
 0x01200000L,0x01200100L,0x01280000L,0x01280100L,
 0x00200010L,0x00200110L,0x00280010L,0x00280110L,
 0x01200010L,0x01200110L,0x01280010L,0x01280110L,
 0x00000200L,0x00000300L,0x00080200L,0x00080300L,
 0x01000200L,0x01000300L,0x01080200L,0x01080300L,
 0x00000210L,0x00000310L,0x00080210L,0x00080310L,
 0x01000210L,0x01000310L,0x01080210L,0x01080310L,
 0x00200200L,0x00200300L,0x00280200L,0x00280300L,
 0x01200200L,0x01200300L,0x01280200L,0x01280300L,
 0x00200210L,0x00200310L,0x00280210L,0x00280310L,
 0x01200210L,0x01200310L,0x01280210L,0x01280310L,
 },{
 /* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */
 0x00000000L,0x04000000L,0x00040000L,0x04040000L,
 0x00000002L,0x04000002L,0x00040002L,0x04040002L,
 0x00002000L,0x04002000L,0x00042000L,0x04042000L,
 0x00002002L,0x04002002L,0x00042002L,0x04042002L,
 0x00000020L,0x04000020L,0x00040020L,0x04040020L,
 0x00000022L,0x04000022L,0x00040022L,0x04040022L,
 0x00002020L,0x04002020L,0x00042020L,0x04042020L,
 0x00002022L,0x04002022L,0x00042022L,0x04042022L,
 0x00000800L,0x04000800L,0x00040800L,0x04040800L,
 0x00000802L,0x04000802L,0x00040802L,0x04040802L,
 0x00002800L,0x04002800L,0x00042800L,0x04042800L,
 0x00002802L,0x04002802L,0x00042802L,0x04042802L,
 0x00000820L,0x04000820L,0x00040820L,0x04040820L,
 0x00000822L,0x04000822L,0x00040822L,0x04040822L,
 0x00002820L,0x04002820L,0x00042820L,0x04042820L,
 0x00002822L,0x04002822L,0x00042822L,0x04042822L,
 }};

为DES_skb,是openssl库中加密DES所用到的矩阵,上方那个矩阵也是

下面两个401000函数的处理的数据分别为

YCXCXACN

DFKDCQXC

得到了3个密钥,正好用于做3des的密钥

最后再看一下比较结果为

‘\x50\x7c\xa9\xe6\x87\x09\xce\xfa\x20\xd5\x0d\xcf\x90\xbb\x97\x6c’

于是我们拿去解密

解密

代码如下

from Crypto.Cipher import DES
s = '\x50\x7C\xA9\xE6\x87\x09\xCE\xFA\x20\xD5\x0D\xCF\x90\xBB\x97\x6C'
des0 = DES.new('AFSAFCED', DES.MODE_ECB)
des1 = DES.new('YCXCXACN', DES.MODE_ECB)
des2 = DES.new('DFKDCQXC', DES.MODE_ECB)
flag += des0.decrypt(des1.encrypt(des2.decrypt(s)))
print flag

得到结果

0dcc509a6f75849b

发布了49 篇原创文章 · 获赞 14 · 访问量 6934

猜你喜欢

转载自blog.csdn.net/qq_39268483/article/details/90739154