Author Topic: Crash when executing a piece of code in C::B (not in another IDE or at runtime)  (Read 6352 times)

Offline skirby

  • Almost regular
  • **
  • Posts: 137
Hello,

Is somebody could tell me what is wrong in my piece of code?

Quote
#include <windows.h>
#include <stdio.h>

void f1(void) {
  MessageBox(0, "f1", "", 0);
}

void f2(void) {
  MessageBox(0, "f2", "", 0);
}

int main(void)
{
  char *mem;
  int len;
  int i;

  len = (int)(&f2 - &f1);
  printf("len : %d\n", len);
  mem = (char*)malloc(len * sizeof(char));

  ////// BLOCK 1
  // Put these lines in comment and uncomment the last call to func() just after the system("PAUSE"); => All is ok
  CopyMemory(mem, (void*)&f1, len);
//  for (i = 0; i < len; i++) {
//    printf("%X ", (unsigned char)mem);
//  }
  //********************************************
  printf("\n");
  free(mem);

  //////////////////////////////////
  char *seh;
  seh = (char*)VirtualAlloc(0, 0x10000, MEM_COMMIT, PAGE_READWRITE);
  *seh = 0xC3;  // RET instruction (opcode)

  PDWORD OLDProtect;
  VirtualProtect(seh, 0x00000010, PAGE_EXECUTE_READ | PAGE_GUARD, OLDProtect);

  FARPROC func;
  func = (FARPROC)f1;
  func();

  func = (FARPROC)seh;
  system("PAUSE");
  ////// BLOCK 2
  func();   // put this line in comment and uncomment the block above => all is ok
  //////////////////////////////////

  system("PAUSE");
  return 0;
}

If you uncomment the BLOCK 1 and 2 You have an error message when you execute this piece of code directly from C::B
There is no error message at runtime (directly from the .exe)

To make it works, "simply" comment the BLOCK 1 or 2 and it works.

I test it under PellesC IDE and there is no problem.
So, I don't know if the bug is due to C::B.

For information I always use the last nightly build (currently the 07/03/2006).
I am on Windows 2000 sp4 with 2 Go RAM.

I hope you could help me.

Thakns and have a nice day.

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Code
CopyMemory(mem, (void*)&f1, len);
This code is inherently evil. Please don't blame us if it bites your butt :)
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

Offline skirby

  • Almost regular
  • **
  • Posts: 137
I don't understand why this code is inherently evil.

In fact, I would like to know why I got an error message when I run my code into C::B and not under PellesC.
More, I do not have any message if I run my executable directly.

Otherwise, what will be the best to do what I want to do.

Do you have an idea which could explain my problem.

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Code
CopyMemory(mem, (void*)&f1, len);
&f1 is an address that points to executable code. Doing any such thing as using CopyMemory on such an address alone gives me the creeps.

Code
printf("%X ", (unsigned char)mem)
Looking a bit closer at it, you cast char* to unsigned char (note the pointer) which you print out len times. Not only do you print out the address instead of the memory (which I suspect was what you intended), but printf with %X expects int, too...

All in all, the code is just scary, sorry. :)
Copying around executable memory and fiddling with pointers and differently-sized variables in such a manner is the devil's code. If you don't shoot your foot that way today, you sure will tomorrow.
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

Offline skirby

  • Almost regular
  • **
  • Posts: 137
Code
CopyMemory(mem, (void*)&f1, len);
&f1 is an address that points to executable code. Doing any such thing as using CopyMemory on such an address alone gives me the creeps.

In fact, I would like to access my function at runtime in order to detect if a breakpoint (INT 3) has been placed.
I need to detect any 0xCC opcode in the function that's why I have written this piece of code.
What is the best way ?
CopyMemory or ReadProcessMemory ?

Code
printf("%X ", (unsigned char)mem)
Looking a bit closer at it, you cast char* to unsigned char (note the pointer) which you print out len times. Not only do you print out the address instead of the memory (which I suspect was what you intended), but printf with %X expects int, too...

It is a mistake. In my original source code I don't have this problem.
I have printf("%X ", (unsigned char)mem[ i ]); and it works very well.
In fact, the forum interpretes [ i ] characters like italic.

All in all, the code is just scary, sorry. :)
Copying around executable memory and fiddling with pointers and differently-sized variables in such a manner is the devil's code. If you don't shoot your foot that way today, you sure will tomorrow.

I have remove PAGE_GUARD in the VirtualProtect function and now it works perfectly.

To finish, do you think my code is so ugly?
What is the best way to access executable code at runtime ?

But, I really would like to understand why I have had an error message with C::B and no error message when executing direclty the exe file.
I don't like not to understand something.

Thanks and have a nice day.

Offline mandrav

  • Project Leader
  • Administrator
  • Lives here!
  • *****
  • Posts: 4315
    • Code::Blocks IDE
Quote from: skirby
In fact, the forum interpretes [ i ] characters like italic.

That's your fault because you used [ quote ] instead of [ code ] tags for your code :)
Be patient!
This bug will be fixed soon...

Offline skirby

  • Almost regular
  • **
  • Posts: 137
Hello mandrav,

Yes, you are absolutly right.
Shame on me  :)

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
In fact, I would like to access my function at runtime in order to detect if a breakpoint (INT 3) has been placed.
I need to detect any 0xCC opcode in the function that's why I have written this piece of code.
What is the best way ?
In my opinion, there is absolutely no excuse for reading from or writing to executable data, except if someone is writing a debugger or an executable packer (both of these obviously don't work otherwise).
Looking for 0xcc is probably meant to be an anti-cracking measure, but you can rest assured that you are wasting your time with this. Don't expect this will delay any halfway serious cracker for more than 2 minutes.

Also, x86 instructions are variable length, so unless you write a fully-fledged realtime disassembler, you will have a hard time, as you don't necessarily know whether a byte at some random position is an opcode, or maybe an offset or an immediate. The byte 0xcc can, in principle, appear in many completely harmless places throughout your code (something like mov eax, [ebx + 204]?). Thus, be prepared to see false positives.

If you think that you absolutely must make sure your code is unmodified, you should calculate one or several checksums (CRC32 or MD5, whatever) and make code in a different place depend on this checksum (do not check the value, but use it). Such things are are hard to track and hard to tamper, if you are only a little bit creative.
However, even then you should have no illusions about your ingenuity. Code that cannot be cracked does not exist. It is only a matter of how much time someone is willing to invest.
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
By the way... what makes you think that len = (int)(&f2 - &f1); produces any significant, usable, and meaningful value?

The compiler can arrange functions any way it happens to feel like at the time of compilation. f1 may appear before f2 or after it, and 250 other functions might be in between.
You don't even know whether they are placed in the same segment and on the same memory page. This may be the case, but it may as well not be.
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

Offline skirby

  • Almost regular
  • **
  • Posts: 137
Thank you very much thomas.
I will try to follow your advices.

Otherwise, I absolutely know that checking for 0xCC opcode isn't enough to stop a cracker.
In fact, I try to do that above all for the knowledge.

So, if you know some good and pretty simple anti debugging technics to code I would be happy to try to implement them.

Thanks ans have a nice day.

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
There is no simple good and easy thing you can do. It greatly depends on what you do, who (and what medium) you target, and how much time and money you have (or are willing to spend).
Generally, it is a lot more economical to accept that some people will crack your program after 3-4 months, if you can sell enough copies during that time. Let them have it, you will soon release an update anyway.

Generally, when fighting reverse engineering, you are fighting a battle that you cannot win. Although many "crackers" are just 13 year old lamers who want to impress their girlfriend as would-be hackers, there are others who read machine code like you read English, and they have tools at hand that are outright scary. Also, they are many and you are one. They can spend many man-years in a only a few weeks, if your program is only interesting enough. You cannot win.

What you can do to stop the most stupid noobs is to use an executable packer/encryptor. That will prevent at least the unexperienced lamers from disassembling and editing the executable in a hex editor, but it won't cost anyone else more than a minute.

Similarly, detecting breakpoints may help to stop your 8 year old sister, but it is not a serious obstacle to anybody else. The simplest thing (which does not even require any special tools) to get around the protection in your above code snippet would for example be to put a breakpoint into MessageBoxA.

Also, there are various techniques which you can find on the internet to detect one or the other debugger, or to crash one or the other debugger, but quite a few are rather outdated and you can safely assume that these exploits are well-known by people who have a little bit of experience, anyway.

Other common techniques to prevent debugging and cracking are to perform senseless calculations. First off, this does not prevent debugging at all, and as far as cracking is concerned, against any serious cracker, it is useless. Nevertheless, throwing in some chaff can fend off a few bloody noobs.
But: You have to be aware that this makes debugging harder for you, too! Probably the best solution for chaff is to define a set of macros that evaluate to nothing in debug build and to chaff in release.

Speaking of debug and release builds... it should be clear that you must *never* distribute a debug build (or a non-stripped executable) or a "preview" that has no protection if you are serious about all this reverse-engineering stuff.

Checksums still don't prevent people from debugging your code, but it makes it a lot harder to patch it, if you do it correctly. The most important thing about it is to not give out any hints of what is happening. If you display a MessageBox saying "code incorrect" or "hey, don't debug this program" then you give out a very valuable clue that can be and will be exploited.

On the other hand, if you build a couple of checksums (starting at different offsets, running from different parts of the application) and use the results of these checksums to look up data or to look up a jump table, then your program may behave odd at some random point later or may crash unexpectedly, which is hard to track and reproduce. The important thing is that you don't compare the value (this can be found and patched easily), but you make other things (which are not immediately obvious) depend on it.
Yes, this is nowhere near easy, but it is nowhere near easy to track and tamper with, either.

If you are particularly sadistic, you can build in a hysteresis such as everything works OK for three or four days, even if your program is modified. Unless someone is willing to test for at least a week, he risks that after boasting with his great crack and spreading it everywhere, all his friends will call him a loser because the crack keeps crashing all the time.
If you're writing a game, you might have it crash only in the 3rd or 4th level. If the game is good, that might actually get some people addicted enough so they buy a copy, who knows. In that case, cracking may even be a form of free advertising :)

If you do something like a shareware program that has save disabled in the non-registered version, then the non-registered version should not disable the menu item or check for a registration number to enable it. It should not have the code to save. If a cracker needs to patch 2 bytes to enable a menu item, then all your valuable protection is good for nothing.

Requiring validation via internet is annoying to the end user (a bad thing, look at MS), but may be a viable and very effective measure.

The list is endless, and there is no one and only good thing, sorry.
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."