Baidu Netdisk has been collected. If you need to review it, you can view it in the folder [CTF question bank collection]
Just run it first
This is a crackme type question, a competition question on the Snow CTF. Use OD to analyze it.
I first used IDA analysis. After analyzing it for a long time, I couldn’t find anything. Then I searched online and found it. I directly raised the flag and solved my urgent problem. Haha, I looked at wp afterwards and found out. In order to find the real solution, we should still summarize it. After all, some questions cannot be found...
Question: Why use OD instead of IDA?
OD can dynamically track the variable change process. OD disassembly code can be colored to make it more eye-catching. Crackme type questions
→The first choice for dynamic tune
IDA can see the data structure and even disassemble it into C code, which is helpful to grasp the overall structure.
→The first choice for quiet tone
Run the program in OD and find that the message box appears after running the function at address 00401494. It can be seen that this is the key function. F2 sets the breakpoint and F7 follows up.
In the process of following this function, Windows GUI - message loop and messages will occur. You can refer to this article.
Windows GUI -- Message Loop and Message_gui Message Loop_My Blog with a Fish Pond at Home-CSDN Blog
It seems that you have to type something to get out of the loop, then set a breakpoint, run F9 and enter characters to get out of the loop.
Where to place a breakpoint? If you set a breakpoint here, as shown below,
After running, an error will be reported directly because the assembly instruction retn is used to end the current process and return to the previous calling process.
So you have to set a breakpoint at the earliest instruction next to this assembly instruction.
After successfully running at the breakpoint, the next step is the key code of disassembly:
CPU Disasm
地址 十六进制数据 指令 注释 标签
00401225 . 83F8 04 CMP EAX,4
00401228 . 59 POP ECX
00401229 . 0F85 A0000000 JNE 004012CF strlen()函数
0040122F . 6A 30 PUSH 30
00401231 . 59 POP ECX
00401232 . 384D E4 CMP BYTE PTR SS:[EBP-1C],CL 判断key第1个字符是否为“0”
00401235 . 0F84 94000000 JE 004012CF
0040123B . 384D E5 CMP BYTE PTR SS:[EBP-1B],CL 判断key第2个字符是否为“0”
0040123E . 0F84 8B000000 JE 004012CF
00401244 . 384D E6 CMP BYTE PTR SS:[EBP-1A],CL 判断key第3个字符是否为“0”
00401247 . 0F84 82000000 JE 004012CF
0040124D . 384D E7 CMP BYTE PTR SS:[EBP-19],CL 判断key第4个字符是否为“0”
00401250 . 74 7D JE SHORT 004012CF
00401252 . 807D E4 31 CMP BYTE PTR SS:[EBP-1C],31 判断key第1个字符是否等于“1”,不等于则直接跳转弹出“error”
00401256 . 75 77 JNE SHORT 004012CF
00401258 . 807D E5 35 CMP BYTE PTR SS:[EBP-1B],35 判断key第2个字符是否等于“5”,不等于则直接跳转弹出“error”
0040125C . 75 71 JNE SHORT 004012CF
0040125E . 74 03 JE SHORT 00401263 花指令
00401260 . 75 01 JNE SHORT 00401263
00401262 E8 DB E8 CHAR 'è'
00401263 > 66:B8 0800 MOV AX,8
00401267 . 66:35 0700 XOR AX,0007
0040126B . 0FBE45 E6 MOVSX EAX,BYTE PTR SS:[EBP-1A] 取输入key的第3位数
0040126F . 2BC1 SUB EAX,ECX 减去0x30,得到a
00401271 . 8945 FC MOV DWORD PTR SS:[EBP-4],EAX 把得到的值保存在[ebp-0x4]中
00401274 . 0FBE45 E4 MOVSX EAX,BYTE PTR SS:[EBP-1C] 取输入key的第1位值“1”
00401278 . DB45 FC FILD DWORD PTR SS:[EBP-4] 把[ebp-0x4]中保存的值压入到ST(0)中
0040127B . 2BC1 SUB EAX,ECX 0x31减去0x30,则为1
0040127D . 8945 FC MOV DWORD PTR SS:[EBP-4],EAX 把得到的值1保存在[ebp-0x4]中
00401280 . 0FBE45 E5 MOVSX EAX,BYTE PTR SS:[EBP-1B] 取输入key的第2位值“5”
00401284 . DB45 FC FILD DWORD PTR SS:[EBP-4] 把[ebp-0x4]中保存的值1压入到ST(0)中
00401287 . 2BC1 SUB EAX,ECX 0x35减去0x30,则为5
00401289 . 8945 FC MOV DWORD PTR SS:[EBP-4],EAX 把得到的值5保存在[ebp-0x4]中
0040128C . DA75 FC FIDIV DWORD PTR SS:[EBP-4] st(0)中的值1除以[ebp-0x4]中的值5,得到0.2保存到st(0)中
0040128F . 0FBE45 E7 MOVSX EAX,BYTE PTR SS:[EBP-19] 取输入key的第4位值
00401293 . 2BC1 SUB EAX,ECX 减去0x30,得到b
00401295 . 8945 FC MOV DWORD PTR SS:[EBP-4],EAX 把得到的值b保存在[ebp-0x4]中
00401298 . DEE9 FSUBP ST(1),ST st(1)-st并保存在st(0)中,即(a-0.2)
0040129A . DA4D FC FIMUL DWORD PTR SS:[EBP-4] st(0)乘以[ebp-0x4] 中保存的值b,结果保存在st(0)中
0040129D . D80D 1C714000 FMUL DWORD PTR DS:[40711C] 数据段ds:[0x40711C]值为16,这里则是st(0)乘以16
004012A3 . D95D FC FSTP DWORD PTR SS:[EBP-4] 把上面得到值保存在[ebp-0x4]中
004012A6 . 74 03 JE SHORT 004012AB
004012A8 . 75 01 JNE SHORT 004012AB
004012AA E8 DB E8 CHAR 'è'
004012AB /> 66:B8 0800 MOV AX,8
004012AF |. 66:35 0700 XOR AX,0007
004012B3 |. D945 FC FLD DWORD PTR SS:[EBP-4] 取出[ebp-0x4]中保存的值
004012B6 |. D81D 18714000 FCOMP DWORD PTR DS:[407118] 得出的值与384比较是否相等
004012BC |. 6A 00 PUSH 0
004012BE |. 68 78804000 PUSH OFFSET 00408078 ASCII "CrackMe 2017 CTF"
004012C3 |. DFE0 FSTSW AX
004012C5 |. 9E SAHF
004012C6 |. 75 0E JNE SHORT 004012D6
004012C8 |. 68 5C804000 PUSH OFFSET 0040805C ASCII "Registration successful !"
004012CD \. EB 0C JMP SHORT 004012DB
004012CF /> 6A 00 PUSH 0
004012D1 |. 68 48804000 PUSH OFFSET 00408048 ASCII "CrackMe 2017 CTF v2"
004012D6 |> 68 40804000 PUSH OFFSET 00408040 ASCII "error !"
0x01 determines the length of the input value
You can see the part of the value we passed in after input, and use strlen to get whether its length is 4. If it is not 4, it will jump directly to 004012CF.
Now it can be determined that the length of key is 4
0x02 Verify the value of the first 2 digits of the key
Here we verify whether the key values are all string "0". If another 4-digit key is "0", jump directly to the "error" pop-up box.
Then continue to verify the value of the first 2 digits of the key string, that is, the first 2 digits of the given string are "15".
If the value of the first 2 digits of the key is not "15", jump directly to the "error" pop-up frame
Here we get the value of the first 2 keys as "15"
0x03 Analysis Algorithm
Here's how it works:
1. Take the hexadecimal value of the third digit in the key, and then subtract 0x30. Here, the value is assumed to be a
2. Take the hexadecimal value of the first bit in the key as "1", which is 0x31, and then subtract 0x30, 0x31-0x30 =1
3. Take the hexadecimal value of "5" in the second digit of the key, which is 0x35, then subtract 0x30, 0x31-0x30 =5, and then divide 1 by 5 to get the floating point number 0.2
4. Take the hexadecimal value of the 4th digit in the key, and then subtract 0x30. Here, the value is assumed to be b
5. Then the result of multiplying (a-0.2)*b by 16 is c
6. Determine whether c and 384 are equal. If they are equal, Registration successful!, if they are not the same, then "error"
formula: (a-0.2)*b*16 = 384 Solve a and b
0x04 Write an algorithm script
Based on the above analysis, I wrote a simple script and ran out two results: "151N" and "1555"
for i in range(126):
for j in range(126):
if(((i-48)-0.2)*(j-48) == 24):
print(i)
print(j)
print("15"+"%s"%(chr(i))+"%s"%(chr(j)))
print("------")