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

fre*_*ngs 2 c c++ memory winapi

我的代码.

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;
}
Run Code Online (Sandbox Code Playgroud)

结果如下.WriteProcessMemory函数失败,错误487,表示地址无效.

错误信息

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

Dav*_*nan 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(...);
Run Code Online (Sandbox Code Playgroud)

然后当你打电话时WriteProcessMemory,传递那个变量:

BOOL retval = WriteProcessMemory(..., lpBaseAddress, ...);
Run Code Online (Sandbox Code Playgroud)

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

不知道你的功能的长度可能是一个问题.如果你不能读取1024*1024超出的字节create怎么办?

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