News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Preventing a code from being reverse engineered

Started by Subhadeep.Ghosh, June 02, 2007, 07:12:51 AM

Previous topic - Next topic

Subhadeep.Ghosh

Hello,

Some background: In our company we develop security based products (the details of which I won't be able to disclose). And the staff in my department are so paranoid about security that they want people reverse engineer the executable. So we came up with an idea of including an encrypted executable (the child) in another executable (the mother) and when required, the mother would decrypt the child in memory and execute it from there.

I wanted to know if this was feasible or not. And IF it was feasible and IF someone had the patience and willingness to give me an idea as to how it could be done, I would be really great full.

I've done a few small projects using MASM32 and I'm comfortable with the Win32 API as well.

After going through a few posts in this forum, I would expect a post like this one to be treated as a threat. However, as assurance I would like to say a few things - firstly, I used my company e-mail ID for registering to this forum. Secondly, I have a dedicated static IP for my terminal (which I'm using to compose this post). And lastly, I'm using my actual name as my login user name (unlike most of the subscribers of this forum). These three things should be enough to track me down if required.

Besides, I only wanted to know if it could be done or not - just YES or NO. If you wanted to help me further you could mail me at subhadeep.ghosh@unikensolutions.com (as I realize the dangers of discussing such topics in public).

If anyone has a better idea for preventing an executable from being reverse engineered, I would be happy to know.

I hope I don't get a hostile response for posting a topic such as this one. Thank you in advance.

Regards,
Subhadeep Ghosh

hutch--

Subhadeep,

Welcome on board, we have enough experience to know the difference between crackers and people who are trying to protect commercial software from easily being cracked so have no fear about that.

Without addressing techniques there is a general formula that says the more complex a protection is, the fewer people will succeed in breaking it and the more original and obscure a protection is in both design and implementation the fewer people will discover how its done but at best you buy time before someone if they have a good enough reason and enough skill will put in the work to find out how to break the protection scheme.

If your product line is subject to regular upgrades then you can make it more complicated for the would be cracker by varying the protection method from version to version while ensuring that the product line cannot be easily patched. Try and avoid protection methods that can be beaten by a key generator as they are easy to distribute and if it suits your product type, put the name of the customer into every version that is sold so they have reason NOT to share your software around.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

evlncrn8

Quote from: Subhadeep.Ghosh on June 02, 2007, 07:12:51 AM
Some background: In our company we develop security based products

erm, how can a compeny develop security based products that arent secure?

doing the parent->child launch in the way you described achieves nothing, armadillo and others
have done this for a while... doesnt work, any experienced cracker would crack it in seconds

the best way you can make it more secure would be to make a virtual machine, encode the
assembly code into vm code, and run it through the vm runtime...

again any experienced cracker can crack it, but it will take time... especially if you make the vm
versatile and 'different' (structs etc) each time you protect the executable...

puting the customer name in doesnt help either, as you have to handle the possibility they were
hacked and the exe 'stolen', that and crackers would probably find it, unless your code never
'touched' the area,  might be spottable though getting 2 exe's from different sources, and
comparing them... crackers are a resourceful bunch..

Subhadeep.Ghosh

Hello,

Thank you all for your replies.

I would like to add that the child executable is going change and is going to be encrypted/decrypted using a key whose lifespan is the lifespan of a single session.

Regards,
Subhadeep Ghosh

evlncrn8

you're going to encrypt/decrypt parts of the child runtime?
breakpoinging on readprocessmemory/writeprocessmemory will catch that
so again, not exactly good...
runtime keys, great, except they aren't gaining u any security..

like how about i code a tool to 'probe' the memory areas in the child that
you've protected, so that u deprotect / decrypt them, i catch and grab
and do the whole thing in a loop... in a matter of seconds i've got a clean exe..

Subhadeep.Ghosh

Hi evlncrn8,

You've certainly got a point. Now, what I present in this reply is a pure correlation of how the 32 bits x86 family of processors work and the API functionality which Microsoft Windows provide.

From whatever little I know about the 32bit x86 family of processors, I know that the processor provides at-least three modes in which a code segment could be created. They are the execute mode, the execute and read only mode and the execute, read and write mode. As far as I know, if a section of the virtual memory is marked just executable, then it cannot be read as a block of data, it can only be executed by the processor. The Win32 API provides a VirtualProtect function call, which (I think) could be used to change the status of a memory block to just execution mode (by using the PAGE_EXECUTE flag). In this case, if a ReadProcessMemory actually tries to read the "protected" memory location, the processor throws an exception.

Now exception handling and unloading the protected module during hibernation are other areas which are beyond the scope of this reply. So I'll stop at this point.

Regards,
Subhadeep Ghosh

hutch--

I have kept up with this line of responses and while I know where Evil is coming from, also note that the cracking scene has a tendency to project what it prefers rather than what works the best. With a protection system more is better than less but smart is better than dumb and the more obscure and original you get the more work they have to do to first find how its done then work out how to break it on a regular basis.

From the production end if you know what you are doing you can wind up the level of complexity which increases the workload at the other end. Your target is not an unbreakable protection system, its a system that takes long enough to break to not be viable. If you match this method with a unique binary for every version you build you just pass an increased level of complexity to the opponent.

This is in fact not all that hard to achieve, alter the order of your code on every build and your binary image changes on every build. Try and avoid well understood protection methods, make the opponent have to manually look through very large volumes of code to find a large number of bits and pieces. The better end of crackers are often highly skilled and resourceful but so are experienced programmers and the advantage lies with the programmer in terms of generating complexity.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Subhadeep.Ghosh

Hello,

Thank you Hutch for your response. After coding for a while and in the process of trying to find out a solution to this very problem, I realized that "dynamics" is the only solution. You (and even evlncrn8) are right, I cannot make the product fully crack-proof. The most I could do it to make it difficult for a cracker to crack the code.

In fact we were faced with a similar problem in the mathematical domain where we were trying to find a mathematical algorithm which couldn't be cracked. Only to realize the fact that such an algorithm cannot exist. Even the most fundamental algorithm such as the Diffie-Hellman algorithm, around which most of the other algorithms are based, can only increase the complexity and nothing more.

I greatly appreciate the help that I've received from this forum.

Regards,
Subhadeep Ghosh.

AkinforASM

Although I'm a newbie, I would like to answer that.

Actually there are commercial solutions for that problem. One of them is Armadillo, which I have no affiliation at all.

When you enable the protection, there are two processes with the same name. When you kill one of them, the other one is also killed automatically. (I believe the designer did set up a messaging mechanism between two processes.)

When you attach a debugger to one of the processes, you can step a few instructions and process is killed. The other process which is actual application cannot be attached by a debugger.

If you start the application through a debugger it gives a warning that the application cannot be started from a debugger.

If you use a kernel mode debugger (like SoftIce ???), it even does not allow running of the process.

I don't know inner workings of the system they use but they use some sort of certificates.

HTH and Regards.

ecube

note that no software protection is 100% secure, if an experienced reverse engineer wants it bad enough he'll get your original code. The idea is to frustrate the attacker to the point of giving up. You can accomplish this with many ways, anti-debug,anti-dumpers,self modifying code, encryption/compression,import table removing, adding lot of confusing possibly poly/metamorphic code to the protected app(i'm talking 100's of kilobytes), entry point obfuscation and the new popular thing out right now that I find really interesting is creating a virtual machine http://www.oreans.com/codevirtualizer.php shows an example of it :D

evlncrn8

also, try to make your routines as less generic as possible ie: not just one global handler to encrypt/decrypt mem
make many copies, change code about in them etc etc..

and dont overuse anything you design, as it'll 'stick out' in a disassembly...

main recommendations would be

1. code obfuscation
2. minor anti debug stuff - dont stick it all in one place, scatter the checks...
3. if you need to communicate between 2 processes, use memory mapping, network, windows messaging and so on
4. the more variation you use, the harder the cracker has to work
5. if your product is cracked, try and analyse how it was cracked, and close that hole
6. think about using virtual machines in your code, your code will run slower, but the vm will have to be reverse engineered... so critical code could be vm'd

just a few things you should keep in mind, a fundamental problem with copy protection is the operating system api.. there are only so many ways to do things (memory allocation, file access and so on), so if the cracker knows the api's to watch, then the cracking phase is quicker... and yes, nothing is 100% secure, but using nothing is definately not a good idea.

Quote
As far as I know, if a section of the virtual memory is marked just executable, then it cannot be read as a block of data, it can only be executed by the processor. The Win32 API provides a VirtualProtect function call, which (I think) could be used to change the status of a memory block to just execution mode (by using the PAGE_EXECUTE flag). In this case, if a ReadProcessMemory actually tries to read the "protected" memory location, the processor throws an exception.

virtualprotect - memory block as read/write - reads fine, writes fine, excecution is 50/50 (dep wont allow it)
virtualprotect - memory block as write - writes fine, read causes exception, execution - no go
virtualprotect - memory block as execute - reads fine (think so anyway) and can execute (to execute it has to be readable anyway)
virtualprotect - memory block as read/write/page guard - causes seh if read/write happens to it, inside readprocessmemory from an external process im unsure, worst case it fails...

readprocessmemory also has its own virtualprotect wrap and its own exception handler ... it sets the area to readable, attempts read, if successful you got the data, if not.. seh kicks in and returns out with a failure (it catches the exception), the memory block virtualprotect setting is then restored...

evlncrn8

Quote from: AkinforASM on June 03, 2007, 06:25:45 PM
If you start the application through a debugger it gives a warning that the application cannot be started from a debugger.
If you use a kernel mode debugger (like SoftIce ???), it even does not allow running of the process.

thats just anti debug / debugger detection... to avoid the wrath of hutch, all i will say is that any good cracker will have ways and means to stealth his/her debugger, making most debugger detections useless...