第一个jz向上为第一部分,要让程序输出 “success”的分析:

图片

输入读取:

  • 用户输入学生 ID 和密钥。这些输入通过 sub_3A1041 函数读取,该函数可能是封装了 scanf 或类似功能的自定义函数。

内存分配和键值处理:

  • 使用 malloc 分配内存,大小取决于 (var_38 - Block) / 8 * 12。这个计算涉及到一些变量,可能是基于输入的长度或者类似参数。
  • 输入的“键”被读取到分配的内存中。

数据处理和比较:

  • 代码执行了一系列的 xorshld 操作。这些操作在内存块中进行,可能是执行某种加密或数据转换。
  • 之后,内存区域的内容被与另一部分的内容进行比较。如果所有比较都相等 (jnz loc_3A7C15 未被执行),则继续执行。

循环处理:

  • xor 操作在一个循环中重复,这个循环基于一个计算得到的次数进行。循环的次数是 (var_38 - Block) / 8,同样可能基于输入长度。

成功条件:

  • 如果所有 xor 操作后的比较都相等,且没有跳转到 loc_3A7C15,则会执行到打印 “success” 的代码行。
  • 在打印 “success” 之前,还会检查 Block 指针是否非空,这可能是为了确认之前的操作或内存分配是否成功。

推测输入值 “2022141530151” 处理流程:

输入处理:

  • 首先,代码提示用户输入学生 ID,假设输入 “2022141530151”。这个 ID 被存储在一个由 lea eax, [ebp+Arglist]push eax 指向的缓冲区内,与格式字符串 "%13s" 一起被 sub_3A1041 使用,这个函数在进行进行字符串的读取。

内存分配:

  • 接下来代码进行内存分配,这部分涉及到 var_38Block 这两个变量。具体的大小计算是 (var_38 - Block) / 8 * 12,然后调用 malloc。通过查阅源码 ,发现var_38 大小为 0x38Block大小为0x3C 的初始值。这个大小计算可能基于你的输入长度或其他因素。

键值读取:

  • 然后程序再次提示输入,这次是输入“键”。这个键值也被读取并存储,用来进行后续的数据比较或加密/解密操作。

数据处理:

  • 程序执行一系列的 xorshld 指令,这些可能是对数据进行某种形式的处理。这个处理可能依赖于输入的“键”和“ID”的特定属性。

比较逻辑:

  • 处理后的数据被与一些预设值进行比较。所有这些比较都必须成功(即相等),程序流程才会继续向前。

成功输出:

  • 如果所有条件满足(即所有比较都通过),程序最终会输出 “success”。

观察到,loc_3A7BB1 对应着success输出,前面有 jz loc_3A7BB1 汇编能够跳转(EFLAGS 寄存器 的 PSW 标志为0则跳转),从此处切入。

Shift + F12查看字符串长度,锁定输入长度为 72 位,此时第一次 jz 之前 al 为 0x1 ,不会跳转到key error。

图片

假设输入 1*72,动调查看

图片

通过以上初步检查与分析,初步判定上述汇编代码为对我的输入进行一系列异或操作,形成密钥,并未涉及密钥的检查部分。

定位到cmp函数,打下断点,通过第一次检查后,第一次每次进行到(F9继续执行)

图片

时,为了通过每轮密钥检查,参考以下部分进行修改(F7单步执行):

图片

将 RSI 中(用户输入的值)修改为其将要比较的对象,即 RCX 中存储的值,每次用此方法进行检查绕过,最后将每次修改的内容(12位)拼接在一起,几位最终的密钥:

第一次:17FB6F0AA3BD

第二次:1EFB6F0AA3BD

第三次:7522B8C906D3

第四次:7C24B5A7CB3F

第五次:7D24B5A7CB3D

第六次:7824B5A7CB3D

即最后的 key 值为:17FB6F0AA3BD1EFB6F0AA3BD7522B8C906D37C24B5A7CB3F7D24B5A7CB3D7824B5A7CB3D

最后,取消所有断点,在打印success代码后打断电,观察结果:

图片

即为答案。

反汇编:

ida.exe进入该程序,快捷键F5,查看反汇编代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
int __cdecl main_0(int argc, const char **argv, const char **envp)  
{
 _DWORD *v3; // esi
 __int64 v4; // rax
 unsigned int v5; // ebx
 unsigned int v6; // eax
 _DWORD *v7; // edx
 unsigned int v8; // edi
 int v9; // ecx
 _DWORD *v10; // eax
 _DWORD *v11; // eax
 _DWORD *v12; // eax
 _DWORD *v13; // eax
 _BYTE *v14; // edx
 char v16; // [esp-10h] [ebp-80h]
 char v17; // [esp-4h] [ebp-74h]
 char v18; // [esp+0h] [ebp-70h]
 unsigned int v19; // [esp+10h] [ebp-60h]
 int v20; // [esp+24h] [ebp-4Ch]
 int v21; // [esp+28h] [ebp-48h]
 int v22; // [esp+2Ch] [ebp-44h]
 int v23; // [esp+30h] [ebp-40h]
 void *Block; // [esp+34h] [ebp-3Ch] BYREF
 int v25; // [esp+38h] [ebp-38h]
 int v26; // [esp+3Ch] [ebp-34h]
 int Buffer[4]; // [esp+40h] [ebp-30h] BYREF
 char Arglist[16]; // [esp+50h] [ebp-20h] BYREF
 int v29; // [esp+6Ch] [ebp-4h]

 sub_4010AA(&Block);
 v29 = 0;
 sub_401177("input the student id: ", v17);
 sub_401041("%13s", (char)Arglist);
 sub_401177("input the key: ", v16);
 v3 = malloc(12 * ((v25 - (int)Block) >> 3) + 1);
 sub_401041("%s", (char)v3);
 if ( !(unsigned __int8)sub_4015BE(v3, 12 * ((v25 - (int)Block) >> 3)) )
   goto LABEL_14;
 v4 = sub_401325(Arglist);
 v5 = v4;
 v6 = HIDWORD(v4);
 v7 = Block;
 v8 = 0;
 v19 = v6;
 if ( (v25 - (int)Block) >> 3 )
 {
   v23 = __PAIR64__(v6, v5) >> 31;
   v22 = __PAIR64__(v6, v5) >> 30;
   v21 = __PAIR64__(v6, v5) >> 29;
   v20 = __PAIR64__(v6, v5) >> 28;
   v9 = 2 * v5;
   while ( 1 )
   {
     v7[2 * v8] ^= v5;
     v7[2 * v8 + 1] ^= v6;
     v10 = Block;
     *((_DWORD *)Block + 2 * v8) ^= v9;
     v10[2 * v8 + 1] ^= v23;
     v11 = Block;
     *((_DWORD *)Block + 2 * v8) ^= 4 * v5;
     v11[2 * v8 + 1] ^= v22;
     v12 = Block;
     *((_DWORD *)Block + 2 * v8) ^= 8 * v5;
     v12[2 * v8 + 1] ^= v21;
     v13 = Block;
     *((_DWORD *)Block + 2 * v8) ^= 16 * v5;
     v13[2 * v8 + 1] ^= v20;
     sub_4015EB((char *)Buffer, "%012llX\n", *((_DWORD *)Block + 2 * v8));
     if ( Buffer[0] != *v3 || Buffer[1] != v3[1] || Buffer[2] != v3[2] )
       break;
     ++v8;
     v7 = Block;
     v3 += 3;
     v9 = 2 * v5;
     v6 = v19;
     if ( v8 >= (v25 - (int)Block) >> 3 )
       goto LABEL_8;
   }
LABEL_14:
   sub_401177("key error", v18);
   exit(0);
 }
LABEL_8:
 sub_401177("success", v18);
 v14 = Block;
 if ( Block )
 {
   if ( ((v26 - (_DWORD)Block) & 0xFFFFFFF8) >= 0x1000 )
   {
     v14 = (_BYTE *)*((_DWORD *)Block - 1);
     if ( (unsigned int)((_BYTE *)Block - v14 - 4) > 0x1F )
       invalid_parameter_noinfo_noreturn();
   }
   sub_4010D7(v14);
 }
 return 0;
}