We help IT Professionals succeed at work.

Anti Debugger

k4hvd77
k4hvd77 asked
on
2,595 Views
Last Modified: 2008-05-12
Hi,
I'm looking for a solution to protect my application from Anti debugger, SoftIce, dumper, disassembler and.....

I know there is no 100 % protection, but knows any body some solutions??

k4hvd77
Comment
Watch Question

i know this one: Debugers handle in speccific way some interrupts (hell i dont remember witch one, but i'm sure there is three of them), so if any application uses those interrupts you block or exit your application. sometimes it's good to do also time check (in protecded procedure if time between two lines of code is greater than one secon then exit or make list of running process and determine if there's any know debuger that is dangerous for your application
you can call IsDebuggerPresent to check if a debugger is attached to your process

function IsDebuggerPresent: BOOL; stdcall; external 'kernel32.dll';

if it is then terminate the process
because of late attachments you'd need to call this in every function to be sure :)

btw .. it's NT specific
Russell LibbySoftware Engineer, Advisory
CERTIFIED EXPERT
Top Expert 2005

Commented:

This page also offers some good tips in the detection of softice and others:

http://www.soft-analysts.com/debugging.php

As the debug trap in windows is triggered by INT 3, the techniques offered in the above link offer some routines that are hard for debuggers to overcome.

HTH,
Russell

cool tips :)

Commented:
Russell's Links are so informative, I was looking for such a thing, thanks

The easy way to do is keep checking "IsDebuggerPresent"  in a timer

thanks

Author

Commented:
rllibby,
"As the debug trap in windows is triggered by INT 3, the techniques offered in the above link offer some routines that are hard for debuggers to overcome", can you tell me more??

k4hvd77

Author

Commented:
ok, I write a simple example

function IsDebuggerPresent: BOOL; stdcall; external 'kernel32.dll';

begin
   if IsDebuggerPresent then
      begin
        Application.Terminate
      end
      else
      begin
        Showmessage('HELLO');
     end;
end;


Is there still any way to crack this function so that it don't check for the debugger but show the message?
Does it work by softIce, disassembler and....??


k4hvd77
I wrote that it was NT only .. I as wrong
quote from MSDN:
Client: Requires Windows XP, Windows 2000 Professional, Windows NT Workstation 4.0, Windows Me, or Windows 98.
Server: Requires Windows Server 2003, Windows 2000 Server, or Windows NT Server 4.0.
I only checked win32 help .. forgot to check MSDN ... sorry about that :-)


and yes it IS posible to crack it .. a cracker needs to find where you call that function and remove the asm jnz call (I could be wrong bout the asm call) :)
as bijith suggeested it's easiest using it in a timer
giving the methods strange names also makes it harder to crack
Russell LibbySoftware Engineer, Advisory
CERTIFIED EXPERT
Top Expert 2005

Commented:

Regard the INT 3 trap, I should probably explain what is required to handle this first.

The first thing you should have is a piece of code that is able to examine functions/procedures at run time: in other words, a disassembler. Madshi has produced just such a thing in his code libraries (you will of course have to abide by his usage policy/licensing scheme). Source for such a thing can also be found at:

Source for the libdisasm project:
http://bastard.sourceforge.net/libdisasm.html

But mind you, the code is in C. As a side note to this: I am in the process of converting the source code for the libdisasm project over to Delphi, but I have not decided if I will make this available or not, as I would hate to see it used maliciously....

Anyways,
Once you have the ability to take a function (which is nothing more than a pointer to jump to in memory), and break it into asm instructions, you could then perform the following:

1.) Before you make a function call that you do not wish to be hooked (by a debugger), you would scan the function for any INT3 instructions. If no INT3 calls are found, then execute as normal. Follow step 2 if INT3 is located...
2.) Unprotect the memory using VirtualProtect(...)
3.) Change the INT3 instruction to a NOP (byte 90), as both are single byte asm instructions. NOP is a "no-operation" instruction.
4.) Keep scanning until a RET type ($C3, $C2, $CB, $CA) instruction is located.
5.) Finally, execute the function/procedure.

Using this technique, along with the other detection techniques mentioned in the link, will make it very hard for someone to debug/hack the application.

But.... as everyone has probably told you before, there is no 100% guarantee. The most you can do is to make things more difficult.

Regards,
Russell






an example of handling this would be
Russell LibbySoftware Engineer, Advisory
CERTIFIED EXPERT
Top Expert 2005

Commented:
Please disregard the trailer on my last, got left by accident...

<... an example of handling this would be  ...>

;-)
Russell

Author

Commented:
Russell,
it seems not easy! could you post any example to do it with delphi? (500 extra points for a solution).

what if I write a dll for my function and let the function, and let the dll checks the IsDebuggerPresent? Is that possible to debugg the dll and change the function inside the dll??


k4hvd77
Russell LibbySoftware Engineer, Advisory
CERTIFIED EXPERT
Top Expert 2005

Commented:

No, it is not an easy thing. And as I said, I am still in the process of converting a disassembler over to Delphi (for things I am working on), and am still contemplating "releasing" it to others, so to speak.

You also asked if it is possible to change a function inside the dll. The "short" answer to this is yes, it is possible. But it does requires a fair amount of assembly knowledge. There are some anti-debugger packages out there that will take the exe, and encrypt the actual function calls, then at runtime they will decrypt and execute the correct code JIT (just in time). If this level/type of protection is something you require, then you should look at the packages out there (they aren't free though).

Back to the use of IsDebuggerPresent though:
Using IsDebuggerPresent provides a decent level of protection, and I have used it as well in a couple of situations. If the result is true, then you can decide what to do. Many applications just call ExitProcess(...), and bail at that point; refusing to run if being debugged. This works for debuggers, but does not handle an outside application "hooking" into your application and making use of another INT call, as we can see with the use of SoftIce and others.

If you wish to handle the anti-debugging yourself, then the best choice would be to use a mix of routines/algorithms:
1.) Include checking for known disassemblers like SoftIce, ICECream, etc
2.) Include checking for IsDebuggerPresent
3.) Make use of no-op loops, and calls to functions that do nothing.
4.) Encode/Encrypt data, which makes it harder to determine data values in memory.
5.) Include time checking for routines that should run at a constant time (nothing with UI, or IO related). For example, if you allow 3 seconds on a routine that should run in sub second time, and that time is exceeded, then chances are someone is "single stepping" your code.

It all comes down to these few things though:
- Are you, and to what extent, willing to sacrifice code readability for safety
- How much safety do you require, knowing that you can never make an exe that is 100% secure.
- How comfortable are you with assembly, and the concepts of self-modifying code and the performance impact that may result.

IMHO, it is best to shoot for the middle ground; use things that are effective, yet easy to implement, and realize that nothing is perfect.

Another link, in case your interested:
http://www.woodmann.com/crackz/Tutorials/Protect.htm


Russell



Author

Commented:
do you have some codes for delphi to do them?


k4hvd77
Russell LibbySoftware Engineer, Advisory
CERTIFIED EXPERT
Top Expert 2005

Commented:

As you have noticed, nearly all the detection routines are in straight asm, but this is not much of an issue as Delphi lets you code inline assembly. If someone does not beat me to it, I will take some time later to convert those functions over for you

Russell
Software Engineer, Advisory
CERTIFIED EXPERT
Top Expert 2005
Commented:
Unlock this solution and get a sample of our free trial.
(No credit card required)
UNLOCK SOLUTION

Author

Commented:
ok,
if you found something other post them here please, will give you 500 points extra!


thank you!
Russell LibbySoftware Engineer, Advisory
CERTIFIED EXPERT
Top Expert 2005

Commented:
Will do...

Note: I am leaning towards posting this disassembler on the net when done. The code is out there in C already, and it appears to be used widely by perl prorammers, it also falls under an "artistic license", so ....

Which leaves me with a question. Are there any tech sites out there that anybody would recommend me placing this on?

Regards,
Russell

Author

Commented:
another  question, is that  meaningfully to use these codes in DLLs too?
Russell LibbySoftware Engineer, Advisory
CERTIFIED EXPERT
Top Expert 2005

Commented:

Yes, it is meaningful, as a dll gets mapped into the working process space of an exe in order to run. Your dll could then call ExitProcess(...) if you found it was being debugged, which will cause the exe to terminate.

This api call cannot be stopped by the exe (unless someone actually hooks the ExitProcess api call).

Russell

Author

Commented:
Could you send me the Code in C too?

Author

Commented:
there is an error ( EExternalException ) in function BoundsCheckerDetected: Boolean on  " cmp   ax, 4"
Russell LibbySoftware Engineer, Advisory
CERTIFIED EXPERT
Top Expert 2005

Commented:

Actually, the error is in the INT 3 call. Forgot to test this outside of Delphi (which debugs your programs by setting the INT 3 handler). It suffers from the same "problem" as the other sources out there, and that is, if the INT is untrapped, an exception is raised.

Best thing to do is to put a try ... except  and the call. If an exception is raised, then the int is NOT trapped, and whatever your checking for

INT 3 - debugger
INT $68 - softice
etc...

Is not currently attached to your process. If your ok with this, then I can also suppy the code for other detections (like INT $68, etc).

--
Regarding the C stuff:

What is that you want in C code? The dissasembler or the above functions? If you want the libdisasm code in C, then the link is:

http://bastard.sourceforge.net/libdisasm.html

Now as far as the Delphi conversion goes, Im done (the base api stuff is anyways, as I am looking at also putting a wrapper object around this to simplify its use). Using this sort of code, you can scan a function/procedure ahead of time (before calling) to determine if whatever traps you are looking for have been inserted. You can even get really clever with it, and "NOP" the code out.

My preference would be to find a site where I can post this code, that way it is available to all. Still looking in that regards...

Russell


Author

Commented:
Ok about the Code you could post it to Torry.net Samples section!
I wrote something like that:

//----------------------------------------------------------------
program Project1;

uses
  Forms,
  SysUtils,
  Dialogs,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}
function BoundsCheckerDetected: Boolean;
begin
  try
    asm
      push  ebp
      mov   ebp, 'BCHK'
      mov   ax, 4
      int   3
      cmp   ax, 4
      jne   @@softice_detected
      mov   ax, 0
      jmp   @@exit
      @@softice_detected:
      mov   ax, 1
      @@exit:
      pop   ebp
    end;
   except
   on E: EExternalException do
    begin
      showmessage('NOT trappedr');
    end;
   end;
end;
begin
 if  BoundsCheckerDetected then
  begin
    application.Terminate;
  end
  else
  begin
    Application.Initialize;
    Application.CreateForm(TForm1, Form1);
    Application.Run;
  end;
end.

//----------------------------------------------------------------

is that right??
I trid to debug the programm using a debugger but I was able to do that!!!


k4hvd77
Russell LibbySoftware Engineer, Advisory
CERTIFIED EXPERT
Top Expert 2005

Commented:
Yes to the code being right.
And yes, that code checks for "bounds checker", not just any old generic debugger. (it is expecting to see the eax register get modified).

Regarding the disassembler:
Torry sounds like as good a place as any; I need another day get everything together and make sure it is all working properly. Also need to get some demo code put together, etc.. Once posted there, I can show you some examples based directly on that unit.

Russell



Author

Commented:
thank you for the code Russell!
Could you send me the code for other detections (like INT $68, etc).
and do all debuggers use INT 3?


k4hvd77
Russell LibbySoftware Engineer, Advisory
CERTIFIED EXPERT
Top Expert 2005

Commented:

All "standard" windows debuggers, like that in C++, Delphi, etc, use INT3. Compiled code that makes use of the DebugBreak api also ends up executing an INT3 call. As a side note, you may have heard of people asking why, when they debug their app that makes use of custom dll's etc, why the CPU pane comes up when they call the custom dll. Well, its usually because someone left DebugBreak calls left in the dll code.

Custom debuggers like SoftIce and others will usually use a different interrupt trap. Int $41 and $68 appear to be the most commonly used ones.

Regarding more detection code:
I will give you a few more when I get a chance, most likely in the next day or so. You will need to exception wrap the calls, just as you did before, due to the same reason as the others. (if the trap is not hooked, then an exception is thrown).

Russell
Russell LibbySoftware Engineer, Advisory
CERTIFIED EXPERT
Top Expert 2005

Commented:
k4hvd77,

Adding 2 more codes to this.
For all that are interested, I have been in contact with the author of libdisasm and hopefully by the end of the week, I will have the delphi source code for this library posted on SourceForge.


Regards,
Russell

function SoftIceVXDDetected: Boolean;
begin
  try
     asm
        push  esi
        push  edi
        mov   ax, $1684
        mov   bx, $0202 // VXD ID for SoftIce
        xor   di, di
        mov   es, di
        int   $2F
        mov   ax, es
        add   di,ax
        cmp   di, 0
        jne   @@softice_detected
        mov   ax, 0
        jmp   @@exit
     @@softice_detected:
        mov   ax, 1
     @@exit:
        pop   edi
        pop   esi
     end;
  except
     // Not hooked
     result:=False;
  end;
end;

function WinIceDetected: Boolean;
begin
  try
     asm
        mov   ah, $43
        int   $68
        cmp   ax, $F386
        jz    @@winice_detected
        mov   ax, 0
        jmp   @@exit
     @@winice_detected:
        mov   ax, 1
     @@exit:
     end;
  except
     // Not hooked
     result:=False;
  end;
end;

As a sidenote... Russell, you *really* like C->Delphi conversion stuff, don't you? ;-)
Russell LibbySoftware Engineer, Advisory
CERTIFIED EXPERT
Top Expert 2005

Commented:

It keeps the wits sharp, DragonSlayer ;-). Plus, why let the C/C++ guys have all the fun??

Kind Regards,
Russell
hehe... yeah, I've become a dumb-wit since abandoning asm ;-)
Russell LibbySoftware Engineer, Advisory
CERTIFIED EXPERT
Top Expert 2005

Commented:

For those that are insterested, the source has been posted and is now available on the Programmers Heaven web site. (still waiting to coordinate this on SourceForge).

The link to the source, which also includes a small demo, is at:

http://www.programmersheaven.com/search/download.asp?FileID=32918

Kind Regards to all,
Russell
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.