尝试使用memcpy复制数据,收到错误“访问冲突写入位置”

时间:2010-02-25 07:51:37

标签: c++

我在第二次记忆时遇到错误 memcpy(& check_user,& ZZZ,(int)& main - (int)& check_user);

11.exe中的0x72cc1f57(msvcr100.dll)处的未处理异常:0xC0000005:访问冲突写入位置0x00f31000。“

有什么问题?

#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();

}

6 个答案:

答案 0 :(得分:1)

行。这很奇怪,但我想我明白了。您希望通过XOR对某些代码进行“加密”。

您将不得不在自己分配的内存缓冲区中执行此操作,该缓冲区是可读写的,也是可执行的。在Windows上,您可以使用VirtualAlloc()实现此目的。在Unix上,您可以将mmap()MAP_ANON一起使用。请参阅其中任何一个调用的保护标志:再次需要可写的可执行内存。

此外,通过函数指针直接与此进行交互是一种粗略的方式。我认为你应该编写一些代码,编译/汇编它们,应用某种类型的密码,并将你的混淆代码作为一个字节序列放入。或类似的东西。

我提到这是一个坏主意吗?

答案 1 :(得分:0)

您正在尝试写入函数check_user的内存位置。 此函数的代码必须位于只读存储器位置,不允许您写入。

答案 2 :(得分:0)

您正在尝试写入&amp; check_user,这是一个函数。

程序的代码段很可能是受保护/只读的。

在旧机器上,写入代码段是可能的,但很危险。 现代机器/操作系统根本不允许这样做。

答案 3 :(得分:0)

使用此“技术”

无法获得功能的“大小”

答案 4 :(得分:0)

正如ssg所写,你不能指望复制代码内存完全可以工作。此外,(int)&main - (int)&check_user可能是负值,因为main不能保证位于内存中check_user之上。

答案 5 :(得分:0)

如果您尝试创建自修改代码,则需要将此代码放在数据部分中,并通知Windows该区域不应受DEP保护(它将位于支持NX位的处理器上)

可在此处找到更多信息:Windows ISV Security.请注意,在所有情况下都需要通过指针调用函数。如果您的代码最初没有修改,则可以在启动时初始化指向代码部分的指针。