1. Generally, encryption is shelling.
We often consider how to encrypt an executable file to ensure security?
Generally, shells are used. The working principle of the shelling tool is to encrypt and convert the code and data of executable files and store them as data. The generated target file entry code is the anti-tracking code prepared by the shelling software. After a long period of anti-tracking code, the code and Data Segment of the original executable file will be restored, and then jump to the original entrance to continue running. The disadvantage of this is that, no matter how powerful your encryption is and the anti-tracking code is too powerful, all data will be restored in the memory as long as it runs. You just need to dump the memory image and disassemble it. Even some tools can directly Save the dump memory image as an executable file. In this way, the encryption will fail completely.
It is not safe to simply shell it, as we all know. We generally call the simple shelling method "compression shell ". So now the shelling software has done more work on the basis of the above "compressed shell", such:
* Prevent dump of memory. This is actually impossible. Because Windows is not a security system, how can you avoid dump of memory? Once there was a shell, I used a variety of methods, dump was not successful. However, we finally found a method to successfully dump it. I was amazed at the fact that dump had so many methods that it was hard to prevent.
* Modify the file entry code. Generally, software is compiled using several commonly used compilers. If the shelling software knows what compiler you are using (which is easy to compile), destroy the entry code and replace it with another functional code. In this way, the dump code is more difficult to find the correct entry, and it is much less likely to be directly stored as an EXE. But it will still be decompiled.
* There are also shell software that supports encryption of one or more key functions. Even virtual machines are used. However, they can only focus on encrypting a few functions and cannot encrypt all functions. There are also many requirements for this function. As you can imagine. If you write a function using a sink, you may not be able to find the function end address without ret. How can this function be encrypted?
Although shell software can use the above technologies to prevent tracking, analysis, and restoration, I think they still don't get rid of the central idea of "shell. The above technologies are just some small episodes made under the premise of "shell. It is still insecure.
Ii. distorted compilation ideas
A metaphor. Shell protection is like a baby on your desk. To protect it, you have a wire mesh around the perimeter of the house. As long as someone breaks through the wire mesh and enters your room, you can see the baby on the desk at a glance. Of course, this is not safe.
The idea of key function encryption is like a wire mesh around the perimeter of my house. I also put the baby in the safe. If someone breaks through the wire mesh and enters the room, they can see the safe at a glance. Although the coffee box won't be opened easily, what if he moves the coffee box slowly? This is not safe enough.
The safest thing is to enter the room, but nothing can be found. No goals. This is the biggest headache.
The current compilers are all pursuing efficient code execution. The code mode remains unchanged. Experienced programmers look at the disassembly code as simple as the source code, there is no secret. If we have a compiler, its compilation goal is not to be efficient, but to prevent being read, that would be nice! I have C ++ source code. I can understand it. Once compiled, no one wants to understand what I want to do through disassembly, or it is difficult. Unfortunately, such a compiler does not yet exist.
What if we compile such a compiler ourselves? Unrealistic. The workload is too heavy. Even finding an open-source C ++ compiler is not enough.
An encrypted compiler does not work. Once the EXE is generated by compiling the connection, it can only be shelled. Is there no way? I came up with an idea: encrypt and compile the intermediate file OBJ, output the ASM file, compile it into OBJ with ML, and then link it!
This method has several advantages:
* The OBJ file format is relatively simple. It is not as heavy as processing C ++ source files.
* The OBJ file contains many source file information, such as the symbol name, code, data, and label. Easy encryption. Many of the information is lost in the LINK process. So it is very inconvenient to process LINK after it is EXE.
* This is a brand new idea! Encryption of code is not limited to shelling, but encryption of every function and every instruction. There is no clear compilation at a glance.
* You can easily set the encryption intensity. You can perform lightweight encryption on some codes as needed, while focusing on encryption on other codes.
* Nested encryption is supported. Several encryption transformations are repeatedly used to expand the code without restrictions.
* Because the OBJ file is encrypted, both DLL and EXE can be encrypted smoothly. The driver can also be based on this idea. Our encryption software is coming soon! We call it twist converter 1.0 for now
Iii. distorted Converter
With the idea, start coding. Originally, the OBJ file format was documented and the project progress should be fast. I did not expect that there is still a lot of content to consider. Every time it is said that this is the last problem, it will be okay if it is solved, but it will always be postponed. I wrote about half a year ago and later.
Major technical problems:
* The assembler ML puts all the code in one segment. This is not acceptable. CL is usually a function segment.
* The assembler ML cannot generate COMDAT segments. Although it supports COMMON in the document, adding this keyword is ineffective.
* The assembler ML does not support WEAKEXTERN.
* The Compiler ML only supports the dreultlib drectve keyword. Other export, include, and other keywords are not supported. In short, many of the OBJ compiled by CL attributes cannot be generated by ML. Microsoft's masm should have been upgraded.
There are also some problems:
* The code and data cannot be clearly separated. The data segment must be data, but it may not be code or data in the code segment. In this case, if you try to disassemble it, an error will occur.
*????? In any case, these problems are solved one by one (don't ask me how to do it ).
The following code distortion methods are used:
* Use JMP to disrupt the code. This is not a new trick, but it still works.
* Use JMP to wrap multiple functions together. In this way, the analysts cannot find where the function starts and ends.
* Change call. The attacker is extremely sensitive to call, which makes it impossible to find a call.
For example, I can change call sub1:
Mov eax, offset sub1 + 3
Push offset @ 1 sub eax, 3
Jmp eax
@ 1:
* Get rid of ret. The attacker is extremely sensitive to ret, so that he cannot find a ret. For example, I can write ret:
Push ecx
Mov ecx, [esp + 4]
Add esp, 8
Jmp ecx
* Conditional jump. Conditional hops are extremely sensitive commands. For example, we can set the following:
Cmp reg1, reg2
Jge L_DST
Rochelle next: writing:
Push eax
Mov eax, reg1
Sub eax, reg2
Shr eax, 1fh
Neg eax
And eax, L2-L1
Add eax, L1
Jmp eax L1:
Pop eax
Jmp L_DST
L2:
Pop eax
Rochelle next:
Now, can you understand what it means:
Push offset @ L-offset L_3 + 23 h
Jmp L_1
L_2:
Jz L_3
Ret 4
L_3:
Add dword ptr [esp + 4], offset L_3-23 h
Add esp, 4
RetL_1:
Call L_2
...
Call and ret appear here, but they are not the expected ones. The call here does not mean that you have found a function call. The ret here does not mean the end of a function.
* Use a stack instead of a register. For example:
Mov eax, dword ptr [ECX + 0AD8h]
PUSH EAX
Mov ecx, dword ptr [EAX] can be written:
PUSH EAX
PUSH ECX
Mov eax, dword ptr [ESP]
Add eax, 0AD8h
Mov eax, dword ptr [EAX]
Mov dword ptr [ESP + 04 h], EAX
Push dword ptr [ESP + 04 h]
Mov eax, dword ptr [ESP]
Mov dword ptr [ESP + 08 h], EAX
Mov eax, dword ptr [ESP]
Mov eax, dword ptr [EAX]
Mov dword ptr [ESP + 04 h], EAX
Mov eax, dword ptr [ESP]
Mov ecx, dword ptr [ESP + 04 h]
Add esp, 08 h
Can you understand it? Obviously, this transformation cannot be reversed. There is no way to know which register it used.
*...... You can also come up with a lot of ways to distort the transformation. There is only one method to simplify the traditional mode. There are infinite ways to simplify the traditional mode. There are also some features:
* In C, use # pragma code_seg (". code $ curve_NoChange") to indicate that the subsequent code is not encrypted. Because sometimes some code contains a lot of loops, encryption will seriously affect the efficiency.
* In the C language, use # pragma code_seg (". code $ curve_Max") to indicate that the subsequent code focuses on encryption. For example, it is related to the registration algorithm.
Now I call the twist converter Version 1.0, which is very stable. I used the keystore to process all the Libs of the vc6database file, and then used the lib.exe tool to write it back to the LIB file. We now have an encrypted library. If you use this library to LINK your software, it is difficult for analysts to find out which is printf and which is strcpy from the assembly, and IDA cannot identify the library function of the MFC static LINK. You can encrypt all the VC6 databases without making any mistakes. I believe it is strong and stable.
Using it to encrypt a shared software, No one writes a registration machine. It is unimaginable to read a large number of transformed codes. But some people are still violent. I really admire him. I will continue to enrich the encryption methods so that all the attackers will give up.
The current distortion converter only supports the COFF format OBJ used by VC6. Next, analyze the OBJ format of VS2005 and support it as soon as possible.
There are several points:
* This software is not released for the moment and is only used by itself. If you want to encrypt your code, you can send the OBJ file to me for encryption. To prevent all software from using this encryption, we can eat IDA :(
* Currently, only the OBJ format of VC6 is supported, that is, COFF. The next step is to support the OBJ format of VS2005. In VS2005, the debug compiling OBJ is COFF, but the release compiling OBJ does not know the format, and no information can be found. Can someone help solve this problem? Thank you.
We use the registration code 12345678 with the username 33333333 error as an example to disconnect it at 40147E. We can see that the program calculates our registration code as a hexadecimal 12 12 12 12 AF and continues later, at 40180A, calculate our registration code as 15 16 17 18 B6 B7 B8 B9. Then, in 405310, our user name was converted into 31 32 33 34 35 36 37 38.
So far, in the stack, convert our user name and registration code into the stack address 12FF18.
False registration code part: 32 12 12 12 AF 15 16 17 18 B6 B7 B8 B9 1D 1E 1F 20 BE