[CTF] to see snow CTF first question Rangers

Download title, the initial judgment from the icon is an MFC program, the other no good-looking, double-click directly dragged into the virtual machine running facie display.

Double-click program displays an input box that prompts passwod, and verification.

First, nothing input, direct verification, the program prompts pop output string: "Please enter pass!".

The free to enter pass, the output window prompt string is playing: "Wrong Come on!!", And the program exits.

From the above information we guess:

1, if the correct pass, and when the program should fail, like pop, and tips related strings, we can start from the search for the error or correct prompt string, you can also start from the pop API.

2, since the program requires user input, then we get a string of API control from input controls to start, either.

3, if the program is a MFC program, and user input validation need to click a button, we can start from MFC OD search button event code.

4, enter the pass error, the program will exit, exit off the search function or API, the code then backtracking.

With more than four cracks idea, we can open the IDA to begin the analysis.

After the completion of IDA analysis code shortcut keys Shift + F12 to view the string.

Double-click on suspicious strings, look at the code cross-reference.

F5 to see pseudo-code.

 1 int __thiscall sub_401890(CWnd *this)
 2 {
 3   struct CString *v1; 
 4   CWnd *v2; 
 5   int v3; 
 6   int result; 
 7   int v5[26]; 
 8   int i;
 9   char *Str; 
10   CWnd *v8; 
11 
12   v8 = this;
13   v1 = (CWnd *)((char *)this + 100);
14   v2 = CWnd::GetDlgItem(this, 1002);
15   CWnd::GetWindowTextA(v2, v1);
16   v3 = sub_401A30((char *)v8 + 100);
17   Str = CString::GetBuffer((CWnd *)((char *)v8 + 100), v3);
18   if ( strlen(Str) )
19   {
20     for ( i = 0; Str[i]; ++i )
21     {
22       if ( Str[i] > 57 || Str[i] < 48 )
23       {
24         if ( Str[i] > 122 || Str[i] < 97 )
25         {
26           if ( Str[i] > 90 || Str[i] < 65 )
27             sub_4017B0();
28           else
29             v5[i] = Str[i] - 29;
30         }
31         else
32         {
33           v5[i] = Str[i] - 87;
34         }
35       }
36       else
37       {
38         v5[i] = Str[i] - 48;
39       }
40     }
41     result = sub_4017F0(v5);
42   }
43   else
44   {
45     result = CWnd::MessageBoxA(v8, "请输入pass!", 0, 0);
46   }
47   return result;
48 }

第15、17行代码将用户输入的pass保存到Str。

第18行代码使用strlen函数检测pass长度,如果为空,则第45行代码弹窗提示重新输入。

第22、24、26行代码通过循环比较来判断pass每个字符是否在0-9,a-z,A-Z范围之间。通过IDA快捷键“R”可以将比较数值转换为字符显示。

第29、33、38行代码则对不同范围内的字符进行减法操作:

0-9:Str[i] -= 48

a-z:Str[i] -= 87

A-Z:Str[i] -= 29

第41行程序将处理后的pass交由“sub_4017F0”函数进行验证处理。

 1 int __cdecl sub_4017F0(int a1)
 2 {
 3   int result; 
 4   char Str1[28]; 
 5   int v3; 
 6   int v4; 
 7 
 8   v4 = 0;
 9   v3 = 0;
10   while ( *(_DWORD *)(a1 + 4 * v4) < 62 && *(_DWORD *)(a1 + 4 * v4) >= 0 )
11   {
12     Str1[v4] = aAbcdefghiabcde[*(_DWORD *)(a1 + 4 * v4)];
13     ++v4;
14   }
15   Str1[v4] = 0;
16   if ( !strcmp(Str1, "KanXueCTF2019JustForhappy") )
17     result = sub_401770();
18   else
19     result = sub_4017B0();
20   return result;
21 }

第10行代码循环遍历pass字符,判断pass[i]是否>=0并且<62。

第12行代码如果以上条件满足,程序将pass[i]的值当做下标索引来获取“aAbcdefghiabcde”字符数组对应索引位置的字符,保存到Str1。

第16行代码使用“strcmp”函数比较Str1是否等于“KanXueCTF2019JustForhappy”字符串,如果等于则调用第17行函数,否则调用第19行函数。

第17行代码:pass正确!

第19行代码:pass错误!

假设:

字符串1 = "KanXueCTF2019JustForhappy"。

字符串2 = "abcdefghiABCDEFGHIJKLMNjklmn0123456789opqrstuvwxyzOPQR"。

通过以上分析我们知道,正确的pass在经过一系列减法操作后,最终应该等于字符串1。

而字符串1是通过字符串2得到的。所以通过反向思维,我们首先获取字符串1每个字符在字符串2中的下标索引。

然后根据每一个索引值的范围加上不同的数,最终就是输入时正确的pass!

 

Guess you like

Origin www.cnblogs.com/SunsetR/p/11240124.html