How to retrieve the encryption program password
Recently, a friend told me that he forgot the password of the encryption program. There is a lot of important information in it. I hope I can help him retrieve the password. I thought I just clicked "forgot password", so I readily agreed, and then the next story happened.
0 × 01 Preface
When you get the encrypted file, it's a dumb. If it is not a networked program, it is a standalone exe, and there is no "forgot password" option at all. After you double-click it, the cold dialog box "please enter password" is displayed ", as a result, he habitually tried "artificial intelligence weak password cracking" (manually enter the password without authorization). After some tossing, he gave up his attempt. After a cold sweat on the back, I still had a hard scalp. Who made me readily promise others. At the same time, in order to challenge myself, I decided to reverse parse the program and completely "burst" the secret. Who made me a hacker, we still need to look for work by cultivating technologies...
0 × 02 Conjecture
After the user enters the password, the program will immediately determine whether the password is correct or not, so there is a "comparison key" in the file to determine the correctness of the password.
Comparison key formats:
1. plaintext of the password;
2. Hash Value of the password;
3. Generate a comparison key using the password and a specific feature value;
4. Generate a comparison key using the password and the original data to be encrypted;
5 ...................
0 × 03 Information Collection Step 1: Sample settings
Step 2: static file Analysis
Select sample 1 and use the UE search function to search for the password "123456". No result is found, which indicates that the password is not stored in plaintext.
Select sample 1 as the standard sample and use the binary comparison function of UE to compare the differences between sample 2, 3, and 4 and sample 1.
Open the encryption program with an empty content with UE, And the last line number is c9f0h. By comparing the above samples, you can determine that the encryption program stores ciphertext data by appending data at the end of the file, and further analyze the data to obtain the data storage format.
Step 3: IDA Static Analysis
Use IDA to load sample 1. A prompt box is displayed.
Click OK. The program is loaded successfully, but there is only one function in the function window. It can be seen that the program adds a shell to interfere with IDA reverse analysis.
Step 4: Shelling
To reduce interference during debugging and further clarify the program process, shelling is required. Use the shell detection artifact PEiD to determine the shell type. The results are as follows:
PEiD successfully detects that the shell name is PECompact 2.x-> Jeremy Collake. If it is an unknown shell, manual shelling is required. Download the corresponding shelling program based on the shell information to perform shelling for the four sample programs set up earlier.
After shelling, the program performs static IDA analysis. The function window can obtain all function information. The main program flowchart is as follows:
This dense branch made me feel cold again
Step 5: dynamic debugging
Use OD for dynamic debugging and analysis, mainly to analyze the password comparison process of the program.
1. Load sample 1 into OD and run F9 directly. At this point, a strange thing happened. The program prompts that the process has ended in the lower left corner of the OD when the password input box pops up. This means that the program has finished running. Why is the password box still there ?!!!
This determines that the program stops its own process after other working processes are created during running. Open the task manager and you can see that the following suspected processes are running. After Kill the process, the password box disappears, proving that the thread is a working thread in the password box.
2. Use the folder search function to search for the entire process and find the program storage directory corresponding to the process.
Open the corresponding folder and you can see many similar programs. These are the intermediate programs generated by notepad during the test.
3. Run these programs in a blank notepad with no content. The UE checks and confirms that these programs are the original programs in the notebook and do not contain any data.
Speculation:When notepad is running, it first releases the original program in the temp directory, and then creates a new process and runs the released program with parameters.
Proof:Use OD to view the list of functions called by the program and find the functions related to the process.
Right-click the CreateProcessA function of the kernel32 library and choose View reference from the shortcut menu ".
This function is called at 407BAE to create a new process and run the program at a breakpoint under 407BAE.
The program runs by adding parameters. Open cmd, enter the program path, and add parameters to run the program.
The program pop-up error window does not work properly. The pop-up password input box is displayed.
0 × 04 deep analysis
After obtaining the above basic information, the data storage format and running Loading Method of the encryption program are determined. The following uses the OD append process to directly debug the newly created process after running and sort out the password judgment process.
1. Additional programs
Double-click the running program, open OD-> file-> append, double-click the new process name, and append OD to debug it.
At this time, the new process is entered in the password box, so the OD will stay in the system function airspace, and the password box is unavailable. To track the password input process, you need to track debugging after entering the password. The Alt + F9 program runs automatically and remains in the user code segment. At this time, the password input box is activated. Enter the correct password and click OK. The program stays in the user code segment.
2. IDA assists in viewing program processes
After obtaining the Key address entered by the password, use IDA to load the program, and use F5 decompilation to view the pseudo code of the program.
In the While LOOP, you can see the 33rd behavior password input box. In the 37 rows, function 404648 is called to determine the password correctness, and 39 behavior "Invalid passphrase" Password error messages. Locate the OD to the call of the 404648 function. We can see that the returned value of the function eax determines the future branch direction. This value is the result generated after the correct password is determined.
Find the key to password determination, go to the 404648 function, view the generation process of the return value, and determine the key code.
Repe cmps byte ptr [esi], byte ptr [edi]
ESI is 12FE78, EDI is 3E3D99
The program compares the data of 0 to 20 bytes, and the two data are the first 0 to 20 bytes of the key in sample 1. After obtaining the entered password, the program will generate a 0*20 byte key after a series of encryption transformations and compare it with the key in the file to determine whether the entered password is correct.
3. encryption process
After determining the key position of a key, continue to trace up and look for the process of comparing the key generation. After some tracking, it is determined that function 407481 generates a function for the comparison key.
size_t __usercall sub_407481@(int a1@, void *a2, size_t a3){ int v3; // edi@1 size_t result; // eax@1 int v5; // ebx@1 size_t v6; // ebx@7 v3 = *(_DWORD *)a1 & 0x3F; result = a3 + *(_DWORD *)a1; v5 = 64 - v3; *(_DWORD *)a1 = result; if ( result < a3 ) ++*(_DWORD *)(a1 + 4); if ( v3 && a3 >= v5 ) { memcpy_0((void *)(v3 + a1 + 40), a2, 64 - v3); result = sub_404B4C(a1 + 40, a1); a3 -= v5; a2 = (char *)a2 + v5; v3 = 0; } if ( a3 >= 0x40 ) { v6 = a3 >> 6; do { result = sub_404B4C((int)a2, a1); a3 -= 64; a2 = (char *)a2 + 64; --v6; } while ( v6 ); } if ( a3 ) result = (size_t)memcpy_0((void *)(v3 + a1 + 40), a2, a3); return result;}
Use OD to break points at the 407481 Function
What !!!! When a function is executed, parameter 1 indicates the plaintext content and parameter 2 indicates the plaintext length. Previously, the program used the entered password to decrypt the ciphertext, and then sent the decrypted plaintext to function 407481 to generate a comparison key.
How the plain text is parsed. Analyze it later. First, continue to analyze how the 407481 function uses plaintext to generate a comparison key. After debugging, determine the function 404B4C as the key encryption function.
Because the function is very complex, we do not intend to conduct in-depth analysis on the encryption algorithm. We directly extract the assembly code of the function and use it as the embedded code of the c program.
The input of the 404B4C function is eax (the content to be encrypted, the length is 0 × 40 bytes), ecx (the location where the generated key is stored ), the key to which ecx points is stored in 0 × 28 bytes. the first 8 bytes hold the total length of the original plaintext, And the last 0 × 20 bytes store the generated key, the 0*20-byte key has an initial value.
407481 Functions
Input: Arg1: original plaintext address
Parameter Arg2: original plaintext Length
Output: the original plaintext length is displayed in the blue box.
The result is the key converted result in the red box.
The Green Box is the plain text content after dividing the plain text length by 0 × 40.
407481 process representation
The value of the parameter Arg2 is written in the blue box.
Count = Arg2/0x40; // The length of the plaintext divided by 0x40
data=Arg1;
While(count--)
{
Call 404B4C (data); // encrypt the 0x40 bytes of the plaintext each time.
data=data+0x40;
}
Call 40B240 (Arg2% 0x40, data); // write the rest of the plain text to the Green Box
After the above process is completed, the program calls the 407481 function again. The parameter is the key2 key in the original encrypted file and the length is 0 × 10 bytes.
407481 after the function is run, the key 0 × 10 bytes is appended to the end of the remaining plaintext.
The subsequent call 00407508 function calculates the comparison key of 0 × 20 bytes.
After analysis, the program mainly uses the data in the following regions to generate a comparison key.
Blue Box: original plaintext Length + Data Length appended to the end
Red box: Key
Green Box: remaining data
Summary and comparison of the key generation process:
1. initialize the red area and write the initial key
2. Read raw data of 0*40 bytes each time, encrypt and convert the key in the red area, and output the generated key to the red area;
3. fill the remaining raw data to reach the length of 0 × 40, and then perform another key transformation. The generated key is the key for comparison with the correct key.
After analysis, we found that the comparison key generation conditions can be obtained from the file data, but one condition is unknown now, that is, plaintext Data !!! We seem to be in an endless loop ..
0 × 05 ciphertext decryption
1. Conjecture: after obtaining the entered password, the program decrypts the ciphertext using the entered password and generates a comparison key using the decrypted ciphertext.
Proof: Continue tracing. Make sure that the call 0040854C function called at the 404A6F address is the decryption function. Parameter 1 is the ciphertext content, parameter 2 is the ciphertext length, and parameter 3 is the key2 key in the file.
The 40854C function also calls data in some unknown regions for decryption and transformation.
2. Conjecture: during initialization, the program generates data for these unknown regions.
Proof: re-run the program, stop at the program entry point, view the data area 41E340, it can be seen that the region is 0 × 00.
Set the memory write breakpoint in this data area and run the F9 command.
After confirming the location, use IDA to decompile the program. It can be clearly observed that the program writes data to six regions, 41B300, 41BB00, 41E340, 41EB40, 41C700, and 41CB00, by calling the 408FFB function, the length of each region is 0 × 100.
int sub_408FFB(){ int v0; // eax@1 int v1; // ecx@1 ………………………… v0 = 1; v1 = 0; do { v2 = 283 * (((unsigned int)v0 >> 7) & 1); *(int *)((char *)&dword_41CF00 + v1) = v0; v1 += 4; v0 = v2 ^ 2 * v0; }while ( (unsigned int)v1 < 0x28 ); v28 = 0; do { v3 = v28; LOBYTE(v2) = v28; v4 = sub_408F52(v1, v2); v5 = 2 * (v4 ^ 2 * (v4 ^ 2 * (v4 ^ 2 * v4))) ^ v4; v6 = (unsigned __int8)(v5 ^ BYTE1(v5) ^ 0x63); v7 = 2 * v6 ^ 283 * (v6 >> 7) | ((v6 | (v6 << 8)) << 8) | 452984832 * (v6 >> 7) ^ ((v6 ^ 2 * v6) << 24); …………………… v20 = 72448 * v17 ^ 72448 * v18 ^ 72448 * v19 ^ ((v14 ^ 8 * v14) << 8) | 18546688 * v17 ^ 18546688 * v15 ^ 18546688 * (((unsigned int)v14 >> 6) & 1) ^ 18546688 * v18 ^ 18546688 * v19 ^ ((v14 ^ 4 * v16) << 16) | 452984832 * ((unsigned int)v14 >> 7) ^ 452984832 * v17 ^ 452984832 * v18 ^ 452984832 * v19 ^ ((v14 ^ 2 * (v14 ^ 4 * v14)) << 24) | 283 * ((unsigned int)v14 >> 7) ^ 283 * v17 ^ 283 * v15 ^ 283 * (((unsigned int)v14 >> 6) & 1) ^ 283 * v18 ^ 283 * v19 ^ 2 * (v14 ^ 2 * v16); …………………… dword_41E340[v8] = v21; dword_41EB40[v8] = v24; dword_41C700[v8] = v1; dword_41CB00[v8] = v26; } while ( v28 < 0x100 ); dword_41FF58 = 1; return 0;}
0 × 06. decryption process
0 × 07. Postscript
Based on the above analysis, it can be determined that the encryption program does not store the password in the file, so the original password cannot be reversed Based on the encrypted data, instead, Dictionary attacks can only be used for brute force cracking Based on the password verification process analyzed above. This is also the reason why many encryption programs need to use dictionaries for brute force cracking. After the program is analyzed, it is time to write the program and combine the dictionary to "crack" the secret ......