VirtualAllocEx成功返回基址,但WriteProcess失败,错误为487

时间:2016-08-29 03:22:22

标签: c++ c winapi memory

我的代码。

int main()
{
HANDLE hTargetHandle;
int TargetProcessId=GetTargetProcessId();


hTargetHandle=OpenProcess(PROCESS_ALL_ACCESS,FALSE,TargetProcessId);

if(hTargetHandle==INVALID_HANDLE_VALUE)
{
    DWORD d=GetLastError();
    printf("openprocess fail\n");
    printf("the TargetProcessId is: %d\n",TargetProcessId);

    printf("the result of getlast is: %d\n",d);
    system("PAUSE");
    exit(-1);
}

DWORD dwBufferSize=(DWORD)GetTargetProcessId-(DWORD)create;

DWORD dwProcBaseAddress=(DWORD)VirtualAllocEx(hTargetHandle,NULL,1024*1024,MEM_COMMIT,PAGE_EXECUTE_READWRITE);     //the size here is 1024*1024,I don't know the size of the function I am going to inject to another process,so I use 1024*1024 here.I have ever tried to use 1024*1024*10,but it is the same error.

if(dwProcBaseAddress==NULL)
{
    DWORD d=GetLastError();
    printf("virtualallocex has fail\n");
    printf("the last error is:%d\n",d);
    system("PAUSE");
    exit(-1);
}

int a=WriteProcessMemory(hTargetHandle,&dwProcBaseAddress,create,1024*1024,NULL);             //create is a function I defined,used to inject to another process.
if(a==0)
{
    DWORD d=GetLastError();
    printf("writeprocessmemory has fail\n");
    printf("the last error is %d\n",d);
    system("PAUSE");
    exit(-1);
}

DWORD dwThreadId;

HANDLE hRemoteThreadHandle=CreateRemoteThread(hTargetHandle,NULL,NULL,(LPTHREAD_START_ROUTINE)dwProcBaseAddress,NULL,0,&dwThreadId);

if(hRemoteThreadHandle!=INVALID_HANDLE_VALUE)
{

    printf("succeed\n");
    system("PAUSE");
    exit(-1);
}


system("PAUSE");
return 1;
}

以下是结果。 WriteProcessMemory函数失败,错误487,表示地址无效。

Error message

但是地址是VirtualAllocEx函数的返回值,返回值不为null,因此地址应该可用。我不知道问题出在哪里。

1 个答案:

答案 0 :(得分:6)

遇到错误代码时,请查找。这里记录了:https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382.aspx。你有487,ERROR_INVALID_ADDRESS。相关描述是:

  

尝试访问无效地址。

所以,让我们深入挖掘。如果地址无效,可能是什么?传递给函数的两个地址位于第二个和第三个参数中。当然第一个,lpBaseAddress是错误的。您打算传递您分配的内存的地址。而是传递包含该地址的变量的地址。

我怀疑你的部分问题是你错误的类型转换。 VirtualAllocEx返回LPVOID。将其转换为DWORD对于32位进程可能没问题,但对于64位进程肯定不行。但是你为什么要施展呢? LPVOID正是您需要传递给WriteProcessMemory的内容。您的代码中充斥着错误的强制转换。作为一个广泛的规则,对你的方式进行类型转换是一种代码气味,表明存在错误。按照您的方式进行转换会阻止编译器键入检查代码。

这是基本地址变量的声明方式:

LPVOID lpBaseAddress = VirtualAllocEx(...);

然后当你致电WriteProcessMemory时,传递该变量:

BOOL retval = WriteProcessMemory(..., lpBaseAddress, ...);

我不知道你为什么使用int来获取变量来捕获WriteProcessMemory的返回值。文档将其作为BOOL。这传达了语义。您还可以使用int作为PID。 PID的类型为DWORD

不知道你的功能长度可能是个问题。如果您无法阅读1024*1024以外的create个字节,该怎么办?

程序中的缺陷很简单。你传了错误的地址。但是,我认为你需要退一步。不要只是修复那个缺陷并继续前进。您真的需要花一些时间来了解Win32 API使用的类型。除非你戒掉这个习惯,否则你的肆意强制转变会一次又一次地伤害你。