tags:

views:

224

answers:

7

I'm getting error on second memcpy
memcpy(&check_user, &ZZZ, (int)&main - (int)&check_user);

"Unhandled exception at 0x72cc1f57 (msvcr100.dll) in 11.exe: 0xC0000005: Access violation writing location 0x00f31000."

What is wrong?

#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <stdio.h>
#include <iostream>

#define PASSWD "+++"
#define MAX_LEN 1023
#define MAX_CODE_SIZE (0x10 * 1024)
#define OFFSET_1 0x42
#define OFFSET_2 0x67

#define x_original_1 0xc01b0574
#define x_original_2 0x44681574
#define x_original_all 0x13D4C04B

#define x_crypt 0x66
using namespace std;

int check_user()
{
        char passwd[MAX_LEN];

        cout<< "enter password:";
        fgets(passwd, MAX_LEN, stdin);
        return ~strcmp(passwd, PASSWD);
}

int my_func()
{
        if (check_user())
        {
                cout<<"passwd ok\n";
        }
        else
        {
                cout<<"wrong passwd\n";
                exit(-1);
        }
        return 0;
}

int main()
{
        int a, b = 0;
        #pragma pack(1)
        union f
        {
                char buf[MAX_CODE_SIZE];
                struct
                {
                        int local_var_1;
                        int local_var_2;
                        char gag_1[OFFSET_1 - sizeof(int) * 2];
                        int x_val_1;
                        char gag_2[OFFSET_2 - OFFSET_1 - sizeof(int)];
                        int x_val_2;
                };
        };
  union f ZZZ;

     memcpy(&ZZZ, &check_user, (int)&main - (int)&check_user);

        for (a = 0; a < (int)&main - (int)&check_user; a++)
        {
                (*(char *) ((int)&ZZZ + a)) ^= x_crypt;
        }

     memcpy(&check_user, &ZZZ, (int)&main - (int)&check_user);

        for (a = 0; a < (int)&main - (int)&check_user; a++)
        {
                b += *(int *)((int)&check_user + a);
        }
        if (b != x_original_all)
        {
                fprintf(stderr, "-ERR: invalid CRC (%x)\n", b);
                return 0;
        }


        my_func();

}
+1  A: 

You are trying to overwrite a code memory block (check_user function) which is read-only on modern operating systems.

From what I understand you want to make sure "check_user" function is encrypted and not tampered with after password check. This kind of tampering is only possible with administrative privileges, and with administrative privileges, there is nothing you can prevent tampering :) (That guy can change your "tampering check" code as well)

About the encryption part, one can easily skip to your "decryption" code by debugging and see the "unencrypted" code easily. But if you really must do it, you should create a copy of code in the heap and execute the code there. You have to make sure code contains no absolute offsets either.

Edit: As Samuel pointed out, executing the code on the heap may not be possible on every OS. In that case you'll have to specifically create a memory block with "execute" flags. This might again require administrative privileges.

ssg
Depending on OS, executing code in the heap may not be possible (and over time, most OS's will stop supporting that). The reason why is code injection is how many attacks are performed so OS's are starting to disallow that. Read up on the NX bit (http://en.wikipedia.org/wiki/NX_bit) for more details
R Samuel Klatchko
As far as I know this is how UPX and other executable compressors work, I don't think it's disabled completely. I know the stack is marked NX though. Added a note to my answer regarding this.
ssg
@R Samuel Klatchko -- But OSs provide all sorts of ways around this. Like `mprotect()` on POSIX. Or you could allocate the pages write+execute yourself, via `mmap` (Unix) or `VirtualAlloc` (Windows).
asveikau
A: 

You are trying to write to the memory location of the function check_user. The code of this function must reside in a read only memory location, where you are not allowed to write.

Didier Trosset
A: 

You are trying to write to &check_user, which is a function.

It is highly likely that the code-segment of your program is protected/read-only.

On old machines, writing to code-segments was possible, but dangerous. Modern machines/OS's won't allow it at all.

abelenky
A: 

You can't get "size" of a function using this "technique"

qehgt
+1  A: 

OK. It's weird, but I think I get it. You want some code to be "encrypted" via a XOR.

You're going to have to do this in a memory buffer you allocate yourself that is read-write and also executable. On Windows you can achieve this with VirtualAlloc() . On Unix you can use mmap() with MAP_ANON. See the protection flags for either of these calls: again you want writable, executable memory.

Also, interacting directly with this via function pointers is kind of sketchy. I think you should write some code, compile/assemble it, apply some kind of cypher, and put in your obfuscated code as a sequence of bytes. Or something like that.

Did I mention this is a bad idea?

asveikau
You're right.mmm... why is this bad idea?
Aelynn
Its hellacious to debug, may not operate properly across many systems unless it is well tested, and makes people laugh at your security attempts :-)
Yann Ramin
@Aelynn - Well. First, this will make your code less maintainable. Second, you'll put a lot of work into the "cyphered" code and getting that working correctly, for very little benefit, using up time that you could be using doing something more constructive. Lastly... It doesn't really gain you anything. If a hacker (or whoever) knows what they are doing, they will still figure out what's going on and be able to look at your code all the same.
asveikau
A: 

As ssg wrote you can't expect copying code memory to work at all. Also, (int)&main - (int)&check_user is possibly a negative value as main is not guaranteed to be located above check_user in memory.

ur
I always get positive number. But it doesn't mean that everything fine, yeah?
Aelynn
A: 

If you are attempting to create self-modifying code, you will need to place this code in a data section, and inform Windows that this region should not be protected with DEP (which it will be on processors which support NX bits).

More information can be found here: Windows ISV Security. Note that you will need to call your function through a pointer in all cases. If your code is not modifying at first, you can initialize the pointer to a code section at startup.

Yann Ramin