5

I'm looking at some simple anti-debug measures as listed in this article http://www.codeproject.com/Articles/30815/An-Anti-Reverse-Engineering-Guide#BpMem

I've implemented a simple check for int 3 breakpoints in a given function so that the function testForInt3Breakpoints returns true if a breakpoint is set anywhere within thisIsADummyFunction.

int thisIsADummyFunction()
{
    int i = rand();
    ++i;  
    return i;
}

bool testForInt3Breakpoints()
{  
    bool breakPointPresent = false;
    unsigned char* memPtr = reinterpret_cast<unsigned char*>( thisIsADummyFunction );

    auto size = 0x16; //this value determined by manual inspection of compiled code

    for ( size_t i = 0; i < size; i++ ) {
        if ( memPtr[ i ] == 0xCC ) {           //see if byte equals int 3 instruction
            breakPointPresent = true;
            break;            
        }
    }
    return breakPointPresent;
}

The function above works fine for me for that one specific function but I would like to be able to monitor multiple functions without having to check the compiled code each time.

My question is are there any methods for getting a function's memory footprint in order to know what memory to monitor ?

I understand there is no general cross platform way to do it at runtime: How to get the length of a function in bytes?

but I am running on windows x64 and visual studio 2015 and quite happy for platform specific answers or anything that could automate the process in some way.

Community
  • 1
  • 1
David Woo
  • 749
  • 4
  • 13
  • 1
    Your code produces false positives. If you really wanted to check for `int 3` opcodes, you'd have to parse the instructions. 0xCC could be part of an opcode other than `int 3` (e.g. an immediate value). Besides, a debugger has all the power to change your world. It can suspend threads, skip over code, or set up breakpoints other then by injecting a 0xCC sequences. This is really a very naive attempt to thwart off attacks. – IInspectable Apr 12 '16 at 15:36
  • Instead of scanning for 0xCC, it is better to generate a hash of the code and then compare for differences. This has the benefit of detecting other code modification attacks as well. – josh poley Apr 12 '16 at 15:44
  • In short there isn't a good way to do this. See also: http://stackoverflow.com/questions/4156585/how-to-get-the-length-of-a-function-in-bytes – josh poley Apr 12 '16 at 15:45

1 Answers1

0

As stated in the comments above already, there is no good solution for this specific problem description, especially not in combination with scanning for 0xCC as it is a valid byte which will occur in your code sooner or later even if no breakpoints are set.

As also stated, a better approach would be hashing the whole code section. However, this has the following disadvantages:

  • Hen-and-egg problem: You would need to get the hashed value after compilation, but actually use it inside your code to compare the actual hash with the expected one.
  • Depending how often you do the checks and how large your code section is (including library code), this may have a larger performance impact. Plus, if you do the check while your application is idle, Windows will have to page in all parts of the code even if they are not executing at the moment, effectively locking your whole program in memory even though it's not required.
  • You may run into issues with security software and other tools which do low-level modifications of other processes. Some tools like this overwrite/hook part of your code directly in memory to perform additional security functions.

If you still wanted to go this route, you could get the boundaries of your code section using VirtualQuery with a pointer anywhere in the code (such as &main), then read it all and use a hash algorithm such as Murmurhash (which is pretty fast) to create a hash and compare it against the stored value.

To solve the hen-and-egg issue there, you could, for example, get a hash from a running copy of your program (either using some kind of "secret" command-line switch, or by reading the memory using another program from which you use OpenProcess, VirtualQueryEx and ReadProcessMemory to do the job) and store it in a location which is not part of the hash, such as your data section or resources. If you use the latter, you can even set the correct hash in the file without recompiling it.

CherryDT
  • 25,571
  • 5
  • 49
  • 74