Software decryption technology research
---- Windows PE file Shell
Decrypt the executable of the plus shell to decrypt the executable of the plus shell by setting hook, dynamically tracking the stack.
Of course, to decrypt, at least first ---- get a "genuine" software that is encrypted.
Then ---- Write simple debugger.
Just intercept the loadLibray / getModuleHandle / GetProcadDress, perform the record library file name, Procedure name in these three hooks. Press the ImportTable structure to fake an ImportTable and store additional information.
Generate a hook function body for each import function, which acquires the return address from the stack (that is, the address of the next instruction to call the CALL instruction of the function), the previous instruction of the return address (ie call The CALL directive of this function is decoded, which is generally as follows:
Call jump_thunk
Call [tunk_fun]
Call REG; in this form, first ignore this form
Call [REG]; for simple, ignore this form first
Call [REG THUNK_OFFSET]; for simple, ignore this form first
Other wonderful strange forms are completely ignored, such as
Push Offset Ret_Address
Push fun_address
RET
RET_ADDRESS:
or:
Push Offset Ret_Address
JMP Fun_Address
RET_ADDRESS:
The key difficulties are here, it is likely to have problems here because the reverse decoding may decode an address error (not this situation). If these problems are ignored, this is ok.
The previous instruction of the return address is called the CALL instruction of the function, which is called Caller_ENTRY.
The BIN Code of the Caller_Entry command is: OP XXXXXXXX, where xxxxxxx is the steering address. What do our hook code do?
1. Read Caller_ENTRY and some bin code near it and write our CRACK file, for future analysis, of course XXXXXXXX will be recorded.
2. Since dynamic automatic tracking is not possible to track all wherever the import function is called, it can be tracked to a call to at least one Import Function. So change XXXXXXXX (ie, jump_thunk or fun_thunk) may not be practical, then only ----
3. For JUMP JUMP_THUNK, we walk to Jump_thunk, which is generally "call [fun_thunk]" form.
4. Write Fun_thunk into our CRACK file to use it for further analysis.
5. In this process we need users to use all the operation paths of "this genuine software" (such as point file> storage / saving, editing> copy / paste ...
6. Users click the "Traverse End" button of Debugger to come out of the entire pe image DUMP.
Then, click Debugger 's "Analysis & Crack" to analyze the CRACK files we generated.
The main operation in the analysis process is:
1. Modify the memory from DUMP, mainly PE Header and section Table.
2. Go to Fun_thunk, change [FUN_THUNK] to our hook address. The shelling software is characterized by only one thing: other shelling software is an importaddressTable or ImportNameTable, which is a way to get residual IMPORTADDRESSTABLE or IMPORTNAMETABLE.
The software is a actual Thunk address from the program's run and constructs ImportTable itself.
In fact, everything is very simple!
postscript:
I have a "software encryption technology and realization" as a graduation papers a year, and I have almost abandoned the encryption research because of my work.
Not long ago, there was a friend and said: "You will encrypt, how do you know if you can't be cracked by others?" So old and short-lived, even dream: Can I make others can't crack? I want to go, I can't find a complete policy. Finally, I finally thought of: "Address Encryption" method, i.e., when IMPORTFunction is encrypted, call IMPORTFUNCITON, first decrypt the address and then jump to ImportFunciton, the implementation is as follows:
Write a hook code, fill the address in the IMPORTADDRESSTABLE to the address of the hook code, so there is a copy of the hook code with each ImportAddresStableEntry, which decrypts the encrypted address and then jumps. The hook code makes it unable to get any addressFunction from PE Image.
I think it is perfect for this method, but I shortly I thought of cracking methods, that is, described herein.
So, very fast, I found another way to deal with this crack ----
Starting with Hookcode, encrypt the return address (ie, the call_entry), then create a new StackFrame to the called function (ie, the importfunction), and copy the parameters previously passed to the new StackFrame. Then call the ImportFuncion.
However, this method also has problems - I don't actually know a few parameters in the modulated function.
So when I created a StackFrame for it, I can only build the StackFrame enough to accommodate the most parameter function ---- If I assume that it has at least 100 parameters, so this will waste more stacking area, fortunately There will be no recursive calls, otherwise the stack is likely to overflow. This problem is temporarily resolved.
However, another problem has occurred ---- When the modulo is returned, I don't know if it skips a few parameters (ImportFunction is generally stdcall, the responsibility of skipping the parameter area is completed by the adjuster). That is, after the modulation is returned, the value of the ESP is different from the call before the call.
Fortunately, the function call does not change the value of ESI, EDI, EBX, EBP. I just use the registers in this, such as EBP, then use the ESP before calling the call (of course, put it into the stack, after recovery) . Then call the importfunction. After it returns, paramsize = (STACKFRAMESIZE - (EBP - ESP)) is the size of the parameter area skipped by the adjuster.
However, there is a problem: How do you return this moment? I have to skip the parameter area! If I can generate an instruction RET paramsize ---- (Paramsize must be an immediate number), it can be.
But there is a problem ---- such code is not re-revenue!
No way? Of course, this code can complete the functionality of RET Paramsize: Add ESP, Paramsize
JMP [ESP - Paramsize]; at this moment, the return address has been decrypted.
Everything OK!!
This encryption method, soliciting crack!!