强网杯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开始
(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