WriteProcessMemory 请问怎样写入字符串

大漠飞狐 2016-10-12 11:22:58
我不知道问题在哪里,写入整型类型没有问题,但我要写入字符串却不成功。


DWORD pid;

HWND hWnd = ::FindWindow(NULL, TEXT("TestServer"));
if (!hWnd)
{
AfxMessageBox(L"没有找到");
}

::GetWindowThreadProcessId(hWnd, &pid);
HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);

LPVOID lpBaseAddress = (LPVOID)14177052;
UpdateData();
//DWORD dwValue = _wtoi(m_strWrite);
LPCTSTR kk = m_strWrite;
if (!::WriteProcessMemory(hProcess, lpBaseAddress, (void*)kk, 10, 0))
return;
...全文
581 11 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
BeanJoy 2016-10-14
  • 打赏
  • 举报
回复
所以说你的问题是没有把申请内存,再把字符串拷贝进去是吧? 还有,要注意strPrompt.Format(L"查询0x%x的页面信息失败" );这句里面把0x%x去掉,后面没有参数。
大漠飞狐 2016-10-12
  • 打赏
  • 举报
回复
引用 2 楼 BeanJoy 的回复:
(LPVOID)14177052是个什么地址,这个地址代表什么东西,有多大? 修改前一般需要修改内存的保护属性,使用VirtualProtectEx。 这个文章可以参考下:内存搜索、修改器(附VC6源码)
14177052 是变量的地址,我改整型变量的内容正常,想改字符趾却弄不了。
VirtualProtectEx(hProcess, lpBaseAddress, 8, PAGE_EXECUTE_READWRITE,0 );
这句也加了,没反应。
encoderlee 2016-10-12
  • 打赏
  • 举报
回复
WriteProcessMemory(hProcess, lpBaseAddress, (void*)kk, 10, 0) 这里的10是10个字节,要注意字符集是多字节字符集还是Unicode
BeanJoy 2016-10-12
  • 打赏
  • 举报
回复
(LPVOID)14177052是个什么地址,这个地址代表什么东西,有多大? 修改前一般需要修改内存的保护属性,使用VirtualProtectEx。 这个文章可以参考下:内存搜索、修改器(附VC6源码)
向立天 2016-10-12
  • 打赏
  • 举报
回复
是不是你的长度指定有问题 应该是字节长度而不是字符串长度 如果你写入的是unicode字符串应该是字符串长度的2倍
大漠飞狐 2016-10-12
  • 打赏
  • 举报
回复
引用 2 楼 BeanJoy 的回复:
(LPVOID)14177052是个什么地址,这个地址代表什么东西,有多大? 修改前一般需要修改内存的保护属性,使用VirtualProtectEx。 这个文章可以参考下:内存搜索、修改器(附VC6源码)
下载了这个例子,我再通过提炼,成功运行。写的时候字节数大一些小一些问题不大。

	DWORD pid;
	HWND hWnd = ::FindWindow(NULL, TEXT("TestServer"));
	if (!hWnd)
	{
		AfxMessageBox(L"没有找到");
	}
	::GetWindowThreadProcessId(hWnd, &pid);
	HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);

	LPVOID lpBaseAddress = (LPVOID)14177052;

	CString strPrompt;
	BOOL bRet = FALSE;
	CString aa;
	m_editStr.GetWindowTextW(aa);
	LPCTSTR paa = aa;
	aa.Trim();
	int width = aa.GetLength()*2+2;
	BYTE* strModi = new BYTE[width];
	memcpy(strModi, paa, width);
	MEMORY_BASIC_INFORMATION mbi;
	DWORD dwOldProtect;
	if (sizeof(mbi) != VirtualQueryEx(hProcess, lpBaseAddress, &mbi, sizeof(mbi)))
	{
		strPrompt.Format(L"查询0x%x的页面信息失败" );		AfxMessageBox(strPrompt);
	}
	if (FALSE == VirtualProtectEx(hProcess, mbi.BaseAddress, mbi.RegionSize,
		PAGE_EXECUTE_READWRITE, &dwOldProtect))
	{
		strPrompt.Format(L"设置0x%x的页面属性失败");		AfxMessageBox(strPrompt);
	}
	bRet = WriteProcessMemory(hProcess, lpBaseAddress, strModi, width, NULL);
	if (FALSE == bRet)
	{
		strPrompt.Format(L"修改0x%x的值失败");		AfxMessageBox(strPrompt);
	}
	delete strModi;
非常感谢各位的帮助,现在问题解决了。
大漠飞狐 2016-10-12
  • 打赏
  • 举报
回复
引用 8 楼 jacksonfan 的回复:
要先把字符串写到目标进程才行 LPTSTR pText = NULL; pText = (LPTSTR)VirtualAllocEx(hProcess, NULL, 256, MEM_COMMIT, PAGE_READWRITE); WriteProcessMemory(hProcess,pText ,你的字符串,长度,NULL); 然后再把这个地址写入目标地址中
目标地址 在哪个语句中用起来?
jacksonfan 2016-10-12
  • 打赏
  • 举报
回复
要先把字符串写到目标进程才行
LPTSTR pText = NULL;
pText = (LPTSTR)VirtualAllocEx(hProcess, NULL, 256, MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(hProcess,pText ,你的字符串,长度,NULL);

然后再把这个地址写入目标地址中
Eleven 2016-10-12
  • 打赏
  • 举报
回复
WriteProcessMemory调用失败的GetLastError值是什么?
BeanJoy 2016-10-12
  • 打赏
  • 举报
回复
引用 4 楼 cyjcn1 的回复:
[quote=引用 2 楼 BeanJoy 的回复:] (LPVOID)14177052是个什么地址,这个地址代表什么东西,有多大? 修改前一般需要修改内存的保护属性,使用VirtualProtectEx。 这个文章可以参考下:内存搜索、修改器(附VC6源码)
14177052 是变量的地址,我改整型变量的内容正常,想改字符趾却弄不了。
VirtualProtectEx(hProcess, lpBaseAddress, 8, PAGE_EXECUTE_READWRITE,0 );
这句也加了,没反应。[/quote] 在内存中,整形和字符串是没有区别的,既然整形没问题,那么字符串也应该行的,注意字符串的大小,以后最后以0结束。 先一点点的调整字符串的大小,然后观察情况进行分析。 比如int a=10;可以将a写入进去,然后这样: *(char *)&a ='A'; *(((char *)&a) + 1) = 0; 这样a的地址就是存的字符”A"了,然后调试分析,一点点加长字符串的长度。
大漠飞狐 2016-10-12
  • 打赏
  • 举报
回复
关于字节数,我不管改大点还是改成一样,或改小点都不行。读可以正常读,就是不能写
VB一些常用控件集,以及一些方法模块,编辑框.ctl、进度条、全局热键钩子、网站服务器、托盘控件、WinSock.ctl、曲线图.ctl、压缩算法-升级版.cls、数组加解密.cls、打开文件属性面板.bas等,其中一个模块的部分代码摘录如下:   ------------------------------------------------------------------------------------------    ‘遍历进程,查找notepad.exe    MyRemoteProcessId = OpenProcess(PROCESS_CREATE_THREAD PROCESS_VM_OPERATION PROCESS_VM_WRITE PROCESS_VM_READ, False, ProcessInfo.th32ProcessID)    ‘打开进程获得notepad的句柄供后面的操作使用    DllFileName = "C:Vblegend.dll"    MyDllFileLength = Len(DllFileName) 1    ‘学过C语言的朋友应该知道字符串最后要一个ASCII 0标志结尾,所以要加1    MyDllFileBuffer = VirtualAllocEx(MyRemoteProcessId, 0, MyDllFileLength, MEM_COMMIT, PAGE_READWRITE)    ‘在指定进程里申请一块内存区域出来供我们存放字符串“c: est.dll“    ‘传string给api时,byval byref有区别,应该使用byval,这样会传给api一个标准的C字符指针,不能byref,否则函数调用没问题    ‘但是起不到预期效果,VirtualAllocEx返回的是申请到的内存地址值.    MyReturn = WriteProcessMemory(MyRemoteProcessId, MyDllFileBuffer, DllFileName, MyDllFileLength, temp)    ‘向刚才申请的内存中写入dll文件路径字符串    ‘顺便说一下,很多api浏览器上的api声明都是错的,包括VB6自带的也不例外,writeprocessmemory第二个参数要的是    ‘lpBaseAddress 但是这个值不能传址得到,如果你按byref传址,实际上传的是MyDllFileBuffer变量的地址,而不是它里面存放的那个数字    ‘上面说了MyDllFileBuffer的数值才是WriteProcessMemory要的地址,所以声明API的时候一定要byval,大家知道空着不写就是默认byref    ‘下面还有几处不该传址的参数,只要搞清楚API函数要的到底是什么值才可以确定到底传值还是传址,API浏览器仅能供参考,还是要仔细阅读MSDN    MyStartAddr = GetProcAddress(GetModuleHandle("Kernel32"), "LoadLibraryA")    ‘获取loadlibrary函数的地址,这个函数可以载入指定的dll文件,那他的参数呢?就是我们刚才在notepad.exe进程里写入的“c: est.dll“    ‘不过还得让CreateRemoteThread告诉他.另外简单的说一下windows下应用程序的内存管理,我也不很懂,呵呵,win32下的应用程序    ‘的内存区域是隔开的,每个程序有自己的一块内存不能直接访问别的程序的内存区,当然,这里调用的几个系统函数有访问别的程序内存区域的特权    ‘而且每个应用程序的内存区域都映射到系统内存区域里,也就是说在这里GetProcAddress得到的VB程序里LoadLibraryA函数的入口地址和    ‘notepad程序里的LoadLibraryA函数地址是一致的(映射的作用),所以不必担心.另外在VB写的程序里    ‘要使用LoadLibraryA,notepad不是用vc写的吗?要注意根notepad没关系,我们现在是在自己的VB程序里面找LoadLibraryA函数的入口.    ‘还有要注意函数大小写,api函数和vb不一样的。    MyResult = CreateRemoteThread(MyRemoteProcessId, 0, 0, MyStartAddr, MyDllFileBuffer, 0, temp)    ‘好了,现在该让LoadLibrary载入“c: est.dll“吧,现在CreateRemoteThread做的就是在notepad进程中把控制权转到LoadLibrar

15,467

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧