vendredi 7 novembre 2014

Self Decryption Code (Static Decryption)

That's a two years old article that i have just found in my HD, and then i thought to share it with you yet again.

Before you start reading this article you must have some basic assembly knowledge, so if your skills are a little rusty, here are some good resources you can use to learn from:

There are plenty of articles in the Internet about what we are going to see today, but not the way i'm going to show it to you ;) but first Why the need to encrypt your application's source code? Maybe from being Reversed?! Maybe you already know about it and maybe you don't, however let me give you a little idea about what Software Reverse Engineering is, it's simply opening a program inside a tool called debugger(such as OllyDebugger, SoftICE, Immunity Debugger...) to make it's features fully working after they've been restricted only for the ones who buy it, it could be also for competitive purposes, etc...

So let's assume you have made an application and you want to protect some sensitive areas in your code (license key verification routine for example) from being reversed?, then you'll have to use an extension (example: compressor, protector, cryptor, etc...) which uses an extra protected/crypted code that jumps in a secure way to the original code, but that will only delay RE, because everything is just Crackable :) it could also be used to confuse antivirus engines from identifying malicious behaviors. So today we are going to concentrate on the code encryption part only, because there are numerous methods of Anti-RE. and we just don't want to get wasted :)

As the title says what we are going to see today is called a "Self Decryption Code" so what is this? this means the software decrypts a part of itself at runtime, which requires a decrypter stub inside the software and an encrypted code. There are many encryption methods such as XOR, RC4, Blowfish, Tea, etc..., some are static(with a static decryption key) and some are Dynamic (changes everytime) and there are many other methods..

But today we are going to see the Static Decryption method which is honestly easy to reverse. but that only depends on how you want it to be. And we want to protect that little part where the calculation and verification happens! let's see how to do that.

We will try to encrypt the following code by using the XOR encryption with a key.

We're going to encrypt the following part of our code :

00401054   5A                            POP EDX
00401055   B8 DEC00000           MOV EAX,0C0DE
0040105A   BB A5BB0000          MOV EBX,0BBA5
0040105F   2BC3                       SUB EAX,EBX
00401061   3BD0                       CMP EDX,EAX
first of all let's do that mainly

we are gonna use a 1 byte key i have chosen: 41(h)

as you might already know every instruction starts with a number that is called an OpCode that determines the nature of that instruction, example: in the x86 family 0x6A correspond to the PUSH instruction, and so on :) so what we are going to do is to encrypt each opcode with the key we've chosen:

5A   xor  41  =  1B
B8   xor  41  =  F9
DE  xor  41  =  9F
3B  xor  41  =  7A
D0  xor  41  =  91

which will give us the following encrypted code:

1B F9 9F 81 41 41 FA E4 FA 41 41 6A 82 7A 91

but in assembly (WinASM precisely) it has to be like this:

EncData            db 01Bh, 0F9h, 09Fh, 081h, 041h, 041h, 0FAh, 0E4h, 0FAh
                          db 041h, 041h, 06Ah, 082h, 07Ah, 091h


now comes the implementation part, so let's make our decryption algorithm:

        Decrypt:                                                              ; Start of decryption algorithm
            mov edx,offset EncryptedPart                                        ; edx is used as a pointer to the address where we will put our decrypted code
            invoke VirtualProtect,edx,15,PAGE_EXECUTE_READWRITE,addr oldProt    ; we use this function to give us permission to execute, read and write visit for more..
            mov esi, offset EncryptedPart                                       ; starting address of the place where we will put our decrypted code (Code Cave)
            mov edi, offset EncData                                             ; edi = our encrypted code
            mov ecx, 15                                                         ; ecx is used here as a counter
            xor eax, eax                                                        ; eax = 0
            DecryptionLoop:                                                     ; start of decryption routine
                mov al, byte ptr [edi]                                            ; al = edi+1 byte
                xor al,41h                                                        ; here is where the magic happens :)
                mov byte ptr [esi], al                                            ; move al to esi (remember it? it's the address)
                inc esi                                                           ; increament esi (esi+1)
                inc edi                                                           ; increament edi (edi+1)
            loop DecryptionLoop                                                 ; until ecx = 0
            jmp EncryptedPart                                                   ; jump to our encrypted routine

that was just the decryption algorithm, now we're going to set a place for the decrypted code to take action:

remember that we did not encrypt the whole code.. 

        invoke GetDlgItemInt,hWin,1001,addr szCode,NULL
        mov edx,eax
        push edx
        jmp Decrypt
            jnz @WRONG
            invoke SetDlgItemText,hWin,1001,addr Correct
            @WRONG: invoke SetDlgItemText,hWin,1001,addr Wrong

in the above code we get a typed integer and had put it in edx and then jump to the decryption algorithm where those 15 NOP's (because we had encrypted 15 bytes) are going to be replaced by, and if everything goes well you will either get a Wrong or Correct message.

As a conclusion, i must say that the example given above is the most easiest thing a reverser could encounter, but there are many ways of making your decryption code much more harder and complicated, but remember that nothing is impossible especially in this domain ;) and hopefully i cover more of this in my future posts.

Hope this was a useful article.
Now i will let you with your imagination.

Attachement : Exemple[Self_Decryption_Code].rar