Encrypt code in exes (decrypt at runtime)
Right!
It creates an interesting problem though doesn't it. Assuming you have some key how do you get it in there to decrypt? You probably don't want one key unlocks all apps but it'd be an admin nightmare to have to manage all the exe's separately (compile for each customer?).
I know that this is not being brought up as foolproof or anything but perhaps if we put a few heads together on the design we can improve it a bit as the base idea looks good, just still a little hard to use in real life
It creates an interesting problem though doesn't it. Assuming you have some key how do you get it in there to decrypt? You probably don't want one key unlocks all apps but it'd be an admin nightmare to have to manage all the exe's separately (compile for each customer?).
I know that this is not being brought up as foolproof or anything but perhaps if we put a few heads together on the design we can improve it a bit as the base idea looks good, just still a little hard to use in real life
Paul Dwyer
“In nature, it’s not the strongest nor the most intelligent who survives. It’s the most adaptable to change” - Charles Darwin
“If you can't explain it to a six-year old you really don't understand it yourself.” - Albert Einstein
“In nature, it’s not the strongest nor the most intelligent who survives. It’s the most adaptable to change” - Charles Darwin
“If you can't explain it to a six-year old you really don't understand it yourself.” - Albert Einstein
- DoubleDutch
- Addict
- Posts: 3220
- Joined: Thu Aug 07, 2003 7:01 pm
- Location: United Kingdom
- Contact:

It's just to stop script kiddies! Don't for one moment think that you will ever be able to create something that will defeat the big boys.
https://deluxepixel.com <- My Business website
https://reportcomplete.com <- School end of term reports system
https://reportcomplete.com <- School end of term reports system
Yup, DoubleDutch is totally right. The idea looks good on the paper hehe. The main bad thing about this is that the code is decrypted at runtime. That means that all the code between the labels is going to be visible to the cracker's eyes. So they can come up with a sort of loader to give control to your exe and then patch directly in memory. This, however, implemented with a good encryption algo can protect your app for a limited time from usual byte-patching.
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
Major update (multi-label support, better encryption, masked labels by DoubleDutch):
Encryptor:
Test executable
Enjoy!
Encryptor:
Code: Select all
;By Inf0Byt3, 10OCT07
;
;Based on code by Rings/Pdwyer/Franky/Wayne Diamond
;Mods/Fixes/Improvements by DoubleDutch/Thefool
;
;Free to use, credits appreciated
;It would be nice to improve it if you have time and if you want to share the knowledge
;
;Now with multi-label support ;)
;Don't forget to enable Inline ASM
Structure Block
StartOffset.l
EndOffset.l
Length.l
EndStructure
Structure CharArray
char.c[0]
EndStructure
Global NewList Blocks.Block()
Procedure BZ_CompareMemory(*Src, *Dst, Len)
MOV esi, *Src
MOV edi, *Dst
MOV eax, Len
MOV ecx, eax
AND eax, 3
SHR ecx, 2
XOR ebx, ebx
REPE CMPSD
!JNE .not_eq
MOV ecx, eax
XOR ebx, ebx
REPE CMPSB
!JNE .not_eq
ProcedureReturn 1
!.not_eq:
ProcedureReturn 0
EndProcedure
Procedure XorWithKey (sText.l, LenText.l, sKey.l, LenKey.l)
XOR ecx, ecx
MOV esi, sText
MOV edi, sKey
MOV edx, LenText
MOV ebp, LenKey
ADD ebp, esi
xornextbyte:
MOV al, [esi]
MOV bl, [edi]
XOR al, bl
MOV [esi], al
INC ecx
INC esi
INC edi
CMP esi, ebp
JGE l_xorcomplete
CMP ecx, edx
JGE l_xornextround
JMP l_xornextbyte
xornextround:
XOR ecx, ecx
SUB edi, edx
JMP l_xornextbyte
xorcomplete:
EndProcedure
Procedure BinSearch(*Object.CharArray, ObjectLength.l, StartOffset.l, *String.CharArray, StringLength.l)
Dim SkipLength.l(255)
For i = 0 To 255
SkipLength(i) = StringLength + 1
Next
For i = 0 To StringLength -1
SkipLength(*String\char[i]) = StringLength - i
Next
CurrentOffset.l = StartOffset
MaxOffset.l = ObjectLength - StringLength
While CurrentOffset <= MaxOffset
If BZ_CompareMemory(*Object + CurrentOffset, *String, StringLength) = 1
FoundPos = CurrentOffset + 1
Break
EndIf
CurrentOffset + SkipLength(*Object\char[CurrentOffset + StringLength])
Wend
ProcedureReturn FoundPos
EndProcedure
Procedure Callback(Message.s)
Debug Message
ProcedureReturn 1
EndProcedure
Procedure EncryptExecutablePieces(File.s,*Callback)
BlockStr.s = Chr($eb)+Chr($06)+Chr($eb)+Chr($fc)+Chr($eb)+Chr($fa)+Chr($eb)+Chr($f8)
BlockEnd.s = Chr($eb)+Chr($04)+Chr($eb)+Chr($04)+Chr($eb)+Chr($fc)+Chr($eb)+Chr($fc)
EXE_Block_Key.s = "this is the enc key"
If FileSize(File) = 0 Or FileSize(File) = -1
CallFunctionFast(*Callback,"No file or empty file...")
ProcedureReturn 0
EndIf
FLRH = OpenFile(#PB_Any,File)
If IsFile(FLRH)
CallFunctionFast(*Callback,"Opened file...")
;Read the file in memory
TotalLength = Lof(FLRH)
*MainMem = AllocateMemory(TotalLength)
ReadData(FLRH,*MainMem,TotalLength)
;Now search for the blocks that need encryption
CallFunctionFast(*Callback,"Searching for blocks...")
While Pos <= TotalLength
EStart = BinSearch(*MainMem,TotalLength,Pos,@BlockStr,Len(BlockStr))
EEnd = BinSearch(*MainMem,TotalLength,Pos,@BlockEnd,Len(BlockEnd))
If EStart > 0 And EEnd > 0
AddElement(Blocks())
Blocks()\StartOffset = EStart+Len(BlockStr)-1
Blocks()\EndOffset = EEnd-1
Blocks()\Length = Blocks()\EndOffset-Blocks()\StartOffset
Else
Break
EndIf
Pos + (EEnd-Pos)
Wend
;Read and encrypt the data
If CountList(Blocks()) > 0
CallFunctionFast(*Callback,Str(CountList(Blocks()))+" block(s) were found.")
ForEach Blocks()
CallFunctionFast(*Callback,"Block start at offset: "+Str(Blocks()\StartOffset))
CallFunctionFast(*Callback,"Block end at offset: "+Str(Blocks()\EndOffset))
CallFunctionFast(*Callback,"Block length: "+Str(Blocks()\Length))
*MemArea = AllocateMemory(Blocks()\Length)
FileSeek(FLRH,Blocks()\StartOffset)
ReadData(FLRH,*MemArea,Blocks()\Length)
XorWithKey (*MemArea, Blocks()\Length, @EXE_Block_Key, Len(EXE_Block_Key))
FileSeek(FLRH,Blocks()\StartOffset)
WriteData(FLRH,*MemArea,Blocks()\Length)
CallFunctionFast(*Callback,"Block patched...")
FreeMemory(*MemArea)
Next
CallFunctionFast(*Callback,"")
Else
CallFunctionFast(*Callback,"No blocks found...")
EndIf
CallFunctionFast(*Callback,"Closing file...")
CloseFile(FLRH)
CallFunctionFast(*Callback,"Ready...")
Else
ProcedureReturn -1
EndIf
EndProcedure
EncryptExecutablePieces("C:\Test.exe",@Callback())
Code: Select all
;By Inf0Byt3, 10OCT07
;
;Based on code by Rings/Pdwyer/Franky/Wayne Diamond
;Mods/Fixes/Improvements by DoubleDutch/Thefool
;
;Free to use, credits appreciated
;It would be nice to improve it if you have time and if you want to share the knowledge
;
;Now with multi-label support ;)
;Don't forget to enable Inline ASM
Procedure XorWithKey (sText.l, LenText.l, sKey.l, LenKey.l)
XOR ecx, ecx
MOV esi, sText
MOV edi, sKey
MOV edx, LenText
MOV ebp, LenKey
ADD ebp, esi
xornextbyte:
MOV al, [esi]
MOV bl, [edi]
XOR al, bl
MOV [esi], al
INC ecx
INC esi
INC edi
CMP esi, ebp
JGE l_xorcomplete
CMP ecx, edx
JGE l_xornextround
JMP l_xornextbyte
xornextround:
XOR ecx, ecx
SUB edi, edx
JMP l_xornextbyte
xorcomplete:
EndProcedure
Procedure.l Scramble(StartAddress,Length)
EXE_Block_Key.s = "this is the enc key"
Mode = #PAGE_READWRITE
Result=VirtualProtect_(StartAddress,Length,Mode,@OrigMode)
XorWithKey (StartAddress,Length,@EXE_Block_Key,Len(EXE_Block_Key))
VirtualProtect_(StartAddress,Length,OrigMode,Mode)
ProcedureReturn 1
EndProcedure
;The code address
CStart = ?S1
CEnd = ?E1
CDiff = ?E1-?S1
Scramble(CStart,CDiff)
;Here's the protected code!
!_MarkBegin1 db $eb,$06,$eb,$fc,$eb,$fa,$eb,$f8
S1:
MessageRequester("","This code here is scrambled")
For t = 97 To 122
a$ + Chr(t)
Next
MessageRequester("","Result "+a$)
E1:
!_MarkEnd1 db $eb,$04,$eb,$04,$eb,$fc,$eb,$fc
;The protected code ends here
MessageRequester("","OUT MWAHAHAHAHAHAHAHAHAHAHA")
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
- DoubleDutch
- Addict
- Posts: 3220
- Joined: Thu Aug 07, 2003 7:01 pm
- Location: United Kingdom
- Contact:
Why do you have to implement a complex search when the whole search mask will fit in a quad?
That's why I made it 8 bytes long.
edit: I like the newer xor method though.
That's why I made it 8 bytes long.

edit: I like the newer xor method though.
Last edited by DoubleDutch on Tue Oct 16, 2007 3:25 pm, edited 1 time in total.
https://deluxepixel.com <- My Business website
https://reportcomplete.com <- School end of term reports system
https://reportcomplete.com <- School end of term reports system
- DoubleDutch
- Addict
- Posts: 3220
- Joined: Thu Aug 07, 2003 7:01 pm
- Location: United Kingdom
- Contact:
If you use the quad search from bit I posted then the code will get a lot shorter. 

https://deluxepixel.com <- My Business website
https://reportcomplete.com <- School end of term reports system
https://reportcomplete.com <- School end of term reports system
Re: Encrypt code in exes (decrypt at runtime)
Excuse me for bumping.
For one, are there any verifications that the above code (except for the xor-encryption) still works? It seems interesting.
Using the correction I've posted in http://www.purebasic.fr/english/viewtop ... 62#p321431 this could be a pretty nice way to scare off the little amateur with a hex editor. Combined with other methods it could get pretty good.
The corrected xor-encryption routine:
UPDATED CODE (Fred reminded me of register preservation):
For one, are there any verifications that the above code (except for the xor-encryption) still works? It seems interesting.
Using the correction I've posted in http://www.purebasic.fr/english/viewtop ... 62#p321431 this could be a pretty nice way to scare off the little amateur with a hex editor. Combined with other methods it could get pretty good.
The corrected xor-encryption routine:
UPDATED CODE (Fred reminded me of register preservation):
Code: Select all
Procedure XorWithKey (sText.l, LenText.l, sKey.l, LenKey.l)
PUSHA
MOV ebx, LenKey
MOV ecx, LenText
DEC ecx
MOV edi, sKey
MOV esi, sText
xornextbyte:
MOV eax, ecx
CDQ
DIV ebx
MOV al, [edx + edi]
XOR [ecx + esi], al
DEC ecx
JNS l_xornextbyte
POPA
EndProcedure
Re: Encrypt code in exes (decrypt at runtime)
Doesn't work with PB 4.51
Can you post a working version ?
Thanks
Can you post a working version ?
Thanks
- ultralazor
- Enthusiast
- Posts: 186
- Joined: Sun Jun 27, 2010 9:00 am
Re: Encrypt code in exes (decrypt at runtime)
A cracker will just use the stub to decrypt the blocks(which will stand out in most tools) and dump it.
If you want to do this proper just get PE pointer from 0x3C, then get entry point which is usually 4 bytes from that section, and insert stub there, and decrypt the entire code section. You can actually decrypt all sections from there, just make sure to change size offsets in header if you make them bigger, and make sure encrypted sections are writable.
How to improve it:
-RC5 encrypt resource section and realign if needed, also rename it
-VM with handler stub at OEP that decrypts VM entry points on the fly and creates timer threads on calls
-Have ring3 anti debugs inside VM
-VM handles all JMP, and CALL instructions
-use enduser labels for VM where blocks first goes through RC5 decryption then the VM which emulates JMP,CALL,CMP and more
-use many polymorphic functions
-insert garbage in VM blocks, code section(s) and a little in heaps
-implement some heap checksums
Also allow another label to insert some form of trigger. An make a VM scheme like a jump decrypts next one and encrypts self, and vm handles decrypted same way. Also some server auther where there is a keygen to decrypt the first VM handler or prompt and exit.
Armadillo is a joke BTW, they embed a DLL that actually helps the cracker bypass license. There is actually an up-to-date tool that does it for you. TheMida and SecurEngine and maybe VMProtect are the only ones that are remotely hard, and scripts exist for rebuilding latest versions with all options on..Securom and Starforce are just vm protectors with disc based crypt used on the VM.
You have to actually rebuild a PE protected with VM, crypter stubs you just run and dump. Skilled reversers will just publish scripts for rebuilding either way...this only hurts independent devs IMO cause it keeps the poor poor and the rich competing with the poor..economics
EDIT:All you have to do to defeat the latest code here is BP on unrecognized code in code section, step over it, then patch if needed and dump. A noob could do it in minutes with ollydbg. Also jump the stub, or wipe it and realign. Or even better inline patch it at runtime to use your own key :p
EDIT2:If anyone is interested in PB code that will VM+encrypt protect any EXE/DLL/SYS/SCR without having to write labels in the target code, then you can contact me; a solution for Linux and Mac ELF is also available with same features. I'm not interested in publishing one cause people don't want to pay license fees that cover the time developing it, and act like you lied when someone defeats it...
If you want to do this proper just get PE pointer from 0x3C, then get entry point which is usually 4 bytes from that section, and insert stub there, and decrypt the entire code section. You can actually decrypt all sections from there, just make sure to change size offsets in header if you make them bigger, and make sure encrypted sections are writable.
How to improve it:
-RC5 encrypt resource section and realign if needed, also rename it
-VM with handler stub at OEP that decrypts VM entry points on the fly and creates timer threads on calls
-Have ring3 anti debugs inside VM
-VM handles all JMP, and CALL instructions
-use enduser labels for VM where blocks first goes through RC5 decryption then the VM which emulates JMP,CALL,CMP and more
-use many polymorphic functions
-insert garbage in VM blocks, code section(s) and a little in heaps
-implement some heap checksums
Also allow another label to insert some form of trigger. An make a VM scheme like a jump decrypts next one and encrypts self, and vm handles decrypted same way. Also some server auther where there is a keygen to decrypt the first VM handler or prompt and exit.
Armadillo is a joke BTW, they embed a DLL that actually helps the cracker bypass license. There is actually an up-to-date tool that does it for you. TheMida and SecurEngine and maybe VMProtect are the only ones that are remotely hard, and scripts exist for rebuilding latest versions with all options on..Securom and Starforce are just vm protectors with disc based crypt used on the VM.
You have to actually rebuild a PE protected with VM, crypter stubs you just run and dump. Skilled reversers will just publish scripts for rebuilding either way...this only hurts independent devs IMO cause it keeps the poor poor and the rich competing with the poor..economics
EDIT:All you have to do to defeat the latest code here is BP on unrecognized code in code section, step over it, then patch if needed and dump. A noob could do it in minutes with ollydbg. Also jump the stub, or wipe it and realign. Or even better inline patch it at runtime to use your own key :p
EDIT2:If anyone is interested in PB code that will VM+encrypt protect any EXE/DLL/SYS/SCR without having to write labels in the target code, then you can contact me; a solution for Linux and Mac ELF is also available with same features. I'm not interested in publishing one cause people don't want to pay license fees that cover the time developing it, and act like you lied when someone defeats it...
so many ideas so little time..
Re:
Armadillo is TOO EASY TO GET OFFRook Zimbabwe wrote:Not to flog a dead pony or anything, BUT!!!
With some slight revision of this you could create a Armadillo like Software security system.

(I can break TEA/XTEA/XXTEA at seconds on the hardware "mate" somelike to "copacobana").
See ya... 

- ultralazor
- Enthusiast
- Posts: 186
- Joined: Sun Jun 27, 2010 9:00 am
Re: Re:
why keygen and do crypto when you can just do a loader, or inline their DLL and rebuild? The DLL method bypasses nano and everything else..the loader methods works on the latest still and is noob-easy xD4RESTER wrote:Armadillo is TOO EASY TO GET OFFRook Zimbabwe wrote:Not to flog a dead pony or anything, BUT!!!
With some slight revision of this you could create a Armadillo like Software security system.
![]()
(I can break TEA/XTEA/XXTEA at seconds on the hardware "mate" somelike to "copacobana").
If a protector isn't at least VM based with it's engine and keys encrypted using non-standard routines, then there are going to be very few people who can't defeat it with minimal effort and time..shareware level warez teams currently do any protector including dongle based inside a day, usually an hour with ones most 'skilled' people can't.
Only exception is some dongle ones that do isolated crypto properly, but these are rarely used..
methods shown here defeat themselves..breakpoint..jmp..done. PB compacts code around syscalls, making RCE even easier too.
so many ideas so little time..
Re: Encrypt code in exes (decrypt at runtime)
It is almost useless because you cannot encrypt functions.
Reason for that is because Fred is using macros to assemble ASM file ( macro MP6{
_Procedure6: ......... )
and after that he is calling macros at the end of ASM file so your code will end up like this:
And to achieve full encryption you need to put encryption routine in all procedures, also .data section is not encrypted so your key can be easily viewed from hex edit.
Reason for that is because Fred is using macros to assemble ASM file ( macro MP6{
_Procedure6: ......... )
and after that he is calling macros at the end of ASM file so your code will end up like this:
Code: Select all
; !_MarkEnd1 db $ea,$04,$ea,$04,$ea,$fc,$ea,$fc
_MarkEnd1 db $ea,$04,$ea,$04,$ea,$fc,$ea,$fc
;
_PB_EOP_NoValue:
PUSH dword 0
_PB_EOP:
CALL _PB_EndFunctions
PUSH dword [PB_MemoryBase]
CALL _HeapDestroy@4
CALL _ExitProcess@4
_PB_EndFunctions:
CALL _PB_FreeMemorys@0
CALL _PB_FreeLibraries@0
CALL _PB_FreeGadgets@0
CALL _PB_FreeWindows@0
CALL _PB_FreeImages@0
CALL _PB_EndAlphaImage@0
RET
;
MP4
MP72
MP14
MP16
MP18
MP50
MP52
MP56
MP58
MP8
MP78
MP80
MP82
MP86
MP102
MP88
MP104
MP70
MP106
MP90
MP108
MP92
MP94
MP112
MP54
MP64
MP74
MP110
MP76
MP84
MP100
MP96
MP98
MP68
MP128
MP130
MP134
MP132
MP62
MP60
MP116
MP124
MP122
MP120
MP126
MP114
MP118
MP66
MP136
MP146
MP154
MP138
MP162
MP2
MP164
MP0
Re: Encrypt code in exes (decrypt at runtime)
I wouldnt care about the key at all. Just wait for the procedure to decrypt itself and then dump it.MisterDr wrote: And to achieve full encryption you need to put encryption routine in all procedures, also .data section is not encrypted so your key can be easily viewed from hex edit.