WriteProcessMemory写入内存的问题?

jinggangshi 2011-02-28 10:14:32
下段代码是我测试写入内存的一段。
问题:WriteProcessMemory能完成写入并没有报错,但我再次读取数据时发现内存中的数据没有更改,请问我错在哪里?
备注:编程的目的是将一个进程的模块从内存链表中移除


int main(int argc, char* argv[])  
{

BOOL EnableDebugPrivilege() ;

HMODULE hm = ::LoadLibrary( L"dll3.dll");

PPEB pPEB;
char str[200];
TCHAR strr1[200];
PPEB_LDR_DATA pLdr;
PLIST_ENTRY pListEntry;
PLDR_MODULE pModule;
char DllName[300];
RMTDATA stRmtData = {0};
_asm{
push eax
mov eax,fs:[30h]
mov pPEB, eax
pop eax
}


pLdr = pPEB->LoaderData;

pListEntry = pLdr->InLoadOrderModuleList.Flink;

HANDLE hcid;

if (pLdr->InMemoryOrderModuleList.Flink)
{
pListEntry = pLdr->InMemoryOrderModuleList.Flink;

while(pListEntry != &pLdr->InMemoryOrderModuleList)
{
pModule = (PLDR_MODULE)(pListEntry - 1);

WideCharToMultiByte(CP_ACP, 0, pModule->FullDllName.Buffer, pModule->FullDllName.Length, DllName, 300, NULL, FALSE);

printf("模块名 :%s\n", DllName);

sprintf(str, "BaseAddress: 0x%08X sizeofImage: 0x%08X", pModule->BaseAddress, pModule->SizeOfImage);

printf("地址 :%s\n", str);

if(strcmp(DllName, "C:\\WINDOWS\\system32\\msvcrt.dll") == 0)
{
hcid = OpenProcess(PROCESS_ALL_ACCESS|PROCESS_VM_WRITE | PROCESS_VM_OPERATION , TRUE, GetCurrentProcessId());
if(hcid != NULL){


int tme = 97;
DWORD dwNumberOfBytesRead;

VirtualProtect(pModule->BaseAddress,pModule->FullDllName.Length,PAGE_READWRITE,&dwNumberOfBytesRead);

if(!WriteProcessMemory(hcid, pModule->BaseAddress , "C:\\eWINDOWS\\sysem32\\ffwww.dll", 1, &dwNumberOfBytesRead))
{
printf("%d\n", GetLastError());
}else
{
WideCharToMultiByte(CP_ACP, 0, pModule->FullDllName.Buffer, pModule->FullDllName.Length, DllName, 300, NULL, FALSE);

printf("更改后的路径 :%s\n", DllName);
WideCharToMultiByte(CP_ACP, 0, pModule->BaseDllName.Buffer, pModule->BaseDllName.Length, DllName, 300, NULL, FALSE);

printf("更改后的名称:%s\n", DllName);
}
if(!WriteProcessMemory(hcid, pModule->BaseAddress , &stRmtData, pModule->FullDllName.Length, 0))
{
printf("%d\n", GetLastError());
}
}

::CloseHandle(hcid);
}

pListEntry = pListEntry->Flink;
}

}



printf("%s\n\n", "--");
printf("************************** :%s\n", "***");
printf("%s\n\n", "--");

_asm{
push eax
mov eax,fs:[30h]
mov pPEB, eax
pop eax
}

pLdr = pPEB->LoaderData;


pListEntry = pLdr->InLoadOrderModuleList.Flink;
if (pLdr->InMemoryOrderModuleList.Flink)
{
pListEntry = pLdr->InMemoryOrderModuleList.Flink;

while(pListEntry != &pLdr->InMemoryOrderModuleList)
{
pModule = (PLDR_MODULE)(pListEntry - 1);

WideCharToMultiByte(CP_ACP, 0, pModule->FullDllName.Buffer, pModule->FullDllName.Length, DllName, 300, NULL, FALSE);

printf("模块名 :%s\n", DllName);

WideCharToMultiByte(CP_ACP, 0, pModule->BaseDllName.Buffer, pModule->BaseDllName.Length, DllName, 300, NULL, FALSE);

printf("模块名 :%s\n", DllName);

sprintf(str, "BaseAddress: 0x%08X sizeofImage: 0x%08X", pModule->BaseAddress, pModule->SizeOfImage);

printf("地址 :%s\n", str);


pListEntry = pListEntry->Flink;
}

}

::FreeLibrary(hm);

system("pause");
return 0;
}


原贴位置:
http://topic.csdn.net/u/20110225/10/f5be219c-7841-46d8-ab5e-85429ade70db.html
...全文
631 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
jinggangshi 2011-03-01
  • 打赏
  • 举报
回复
NtQueryInformationProcess( hProcess,
ProcessBasicInformation,
(PVOID)&pbi,
sizeof(PROCESS_BASIC_INFORMATION),
NULL);
返回值是0;但pbi 没有数据。

NtReadVirtualMemory(hProcess,pbi.PebBaseAddress,&Peb,sizeof(PEB),0);
返回值 0
NtReadVirtualMemory(hProcess,Peb.LoaderData,&Ldr,sizeof(PEB_LDR_DATA ), 0);
返回值 0
jinggangshi 2011-03-01
  • 打赏
  • 举报
回复
+ pbi.PebBaseAddress 0x7ffda000 {InheritedAddressSpace=??? ReadImageFileExecOptions=??? BeingDebugged=??? ...} _PEB *
Lactoferrin 2011-03-01
  • 打赏
  • 举报
回复
打印pbi.pebbaseaddress,结果是多少
jinggangshi 2011-03-01
  • 打赏
  • 举报
回复
谢谢列宁同志,测试成功了,我得好好看看你的代码。
先结帖了!
jinggangshi 2011-03-01
  • 打赏
  • 举报
回复
明白了,一会我试试,刚才看代码也不象是输出,不好意思。
我再看看,太麻烦你了。
Lactoferrin 2011-03-01
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 jinggangshi 的回复:]

C/C++ code
if(NtQueryInformationProcess(ProcessHandle, /*(PROCESSINFOCLASS)*/0,&PBI,sizeof(PROCESS_BASIC_INFORMATION),0))return;

编译时提示cannot convert parameter 2 from 'int' to 'PROCESSINFOCLASS……
[/Quote]
第二个参数是枚举型,ProcessBasicInformation=0

你可能没有理解我的程序的意思,BaseAddress不是输出,是输入,作用是寻找基地址为BaseAddress的模块并把它从双向链表中移除

你要这样用

HANDLE h=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE,0,1936);
CloakModule(h,(void*)0x76b10000);
这里的0x76b10000是目标进程某个模块的基地址,你上次代码中me32.hModule的值就可以作为BaseAddress的实际参数
你可以先用CreateToolhelp32Snapshot枚举一次模块,然后选择其中的一个CloakModule,然后再CreateToolhelp32Snapshot一次,看那个模块还能不能被列举出来
jinggangshi 2011-03-01
  • 打赏
  • 举报
回复
if(NtQueryInformationProcess(ProcessHandle, /*(PROCESSINFOCLASS)*/0,&PBI,sizeof(PROCESS_BASIC_INFORMATION),0))return;

编译时提示cannot convert parameter 2 from 'int' to 'PROCESSINFOCLASS'。
强制转换后通过(不知道能不能强制转换),运行后数据是0;
这是我的调用
	LPVOID pm = (LPVOID)LocalAlloc(LPTR, 4096);
CloakModule( hProcess,pm);
PLDR_MODULE pModule = (PLDR_MODULE)pm;
/*省略*/
LocalFree(pm);

调试中看变量及输出:能看到地址值(循环中)的变化,能看到有些模块名,但最后没有输出值到pm。

你先看看到的调用对不对,我再去看看你的代码。
真不好意思。
Lactoferrin 2011-03-01
  • 打赏
  • 举报
回复
试这个
BaseAddress是你枚举得到的模块基地址,一般叫hModule
ProcessHandle需要PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE

void CloakModule(HANDLE ProcessHandle,void*BaseAddress)
{void*TargetAddr;PEB Peb;PEB_LDR_DATA Ldr;LDR_MODULE Dll;PROCESS_BASIC_INFORMATION PBI;
if(NtQueryInformationProcess(ProcessHandle,0,&PBI,sizeof(PROCESS_BASIC_INFORMATION),0))return;
if(NtReadVirtualMemory(ProcessHandle,PBI.PebBaseAddress,&Peb,sizeof(PEB),0))return;
if(NtReadVirtualMemory(ProcessHandle,Peb.Ldr,&Ldr,sizeof(PEB_LDR_DATA),0))return;
TargetAddr=(void*)Ldr.InLoadOrderModuleList.Flink;
do
{
if(NtReadVirtualMemory(ProcessHandle,TargetAddr,&Dll,sizeof(LDR_MODULE),0))return;
TargetAddr=(void*)Dll.InLoadOrderModuleList.Flink;
if(TargetAddr==&Peb.Ldr->InLoadOrderModuleList)return;
}
while(Dll.BaseAddress!=BaseAddress);
NtWriteVirtualMemory(ProcessHandle,(void*)((ULONG_PTR)Dll.InLoadOrderModuleList.Flink+sizeof(void*)),&Dll.InLoadOrderModuleList.Blink,sizeof(void*),0);
NtWriteVirtualMemory(ProcessHandle,(void*)(Dll.InLoadOrderModuleList.Blink),&Dll.InLoadOrderModuleList.Flink,sizeof(void*),0);
NtWriteVirtualMemory(ProcessHandle,(void*)((ULONG_PTR)Dll.InInitializationOrderModuleList.Flink+sizeof(void*)),&Dll.InInitializationOrderModuleList.Blink,sizeof(void*),0);
NtWriteVirtualMemory(ProcessHandle,(void*)(Dll.InInitializationOrderModuleList.Blink),&Dll.InInitializationOrderModuleList.Flink,sizeof(void*),0);
NtWriteVirtualMemory(ProcessHandle,(void*)((ULONG_PTR)Dll.InMemoryOrderModuleList.Flink+sizeof(void*)),&Dll.InMemoryOrderModuleList.Blink,sizeof(void*),0);
NtWriteVirtualMemory(ProcessHandle,(void*)(Dll.InMemoryOrderModuleList.Blink),&Dll.InMemoryOrderModuleList.Flink,sizeof(void*),0);
NtWriteVirtualMemory(ProcessHandle,(void*)((ULONG_PTR)Dll.HashTableEntry.Flink+sizeof(void*)),&Dll.HashTableEntry.Blink,sizeof(void*),0);
NtWriteVirtualMemory(ProcessHandle,(void*)(Dll.HashTableEntry.Blink),&Dll.HashTableEntry.Flink,sizeof(void*),0);
}

Lactoferrin 2011-02-28
  • 打赏
  • 举报
回复
去掉保护后
void RemoveListEntry(PLIST_ENTRY ListEntry)
{
ListEntry->BLink->FLink=ListEntry->FLink;
ListEntry->FLink->BLink=ListEntry->BLink;
}
jinggangshi 2011-02-28
  • 打赏
  • 举报
回复
pModule.InLoadOrderModuleList,是啊,想过,但不知道怎么。
这不是对象,没有办法REmove
Lactoferrin 2011-02-28
  • 打赏
  • 举报
回复
你这样是不会把模块从链中移除,你修改的是模块映像,不是双向链表。
如果要看是否写入成功,请读取模块映像数据比较。
如果要从链表移除模块,修改pModule.InLoadOrderModuleList中前一个节点和后一个节点,使前后节点连起来
Lactoferrin 2011-02-28
  • 打赏
  • 举报
回复
哪个步骤不成功,把返回值给我
jinggangshi 2011-02-28
  • 打赏
  • 举报
回复
不成功,我要崩溃了。
Lactoferrin 2011-02-28
  • 打赏
  • 举报
回复
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |PROCESS_VM_READ, FALSE, 6004/*其他进程的Pid*/);
NtQueryInformationProcess(hProcess, 0, (PVOID)&pbi, sizeof(PROCESS_BASIC_INFORMATION), NULL );
这里看NtQueryInformationProcess返回值是不是0,如果是0就成功
PEB Peb;LDR_LOADER_DATA Ldr;
NtReadVirtualMemory(hProcess,pbi.PebBaseAddress,&Peb,sizeof(PEB),0);
返回值是0就成功
NtReadVirtualMemory(hProcess,Peb.Ldr,&Ldr,sizeof(LDR_LOADER_DATA ),0);
......................
jinggangshi 2011-02-28
  • 打赏
  • 举报
回复
PebBaseAddress等于多少

错误的值。不知取到了谁的
你说下怎么取吧!
累死我了
Lactoferrin 2011-02-28
  • 打赏
  • 举报
回复
NtQueryInformationProcess最后一个参数可选
Lactoferrin 2011-02-28
  • 打赏
  • 举报
回复
PebBaseAddress等于多少
这个是别的进程的地址,需要用NtReadVirtualMemory读取,不能直接用你上面的代码
jinggangshi 2011-02-28
  • 打赏
  • 举报
回复
NtQueryInformationProcess(hProcess, 0, (PVOID)&pbi, sizeof(PROCESS_BASIC_INFORMATION), NULL );

最后一个参数的问题。
回头总结下发上来。
jinggangshi 2011-02-28
  • 打赏
  • 举报
回复
NtQueryInformationProcess

这个我用了,只能获取本进程的,其他进程的获取不到PPEB

HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION , FALSE, 6004/*其他进程的Pid*/);

以上是获取进程句柄,PROCESS_QUERY_INFORMATION 参数换了读写也不行!

NtQueryInformationProcess(hProcess, 0, (PVOID)&pbi, sizeof(PROCESS_BASIC_INFORMATION), NULL );
pPEB = pbi.PebBaseAddress;

以上是读取进程信息,PebBaseAddress是无效的。
Lactoferrin 2011-02-28
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 jinggangshi 的回复:]

C/C++ code
_asm{
push eax
mov eax,fs:[30h]
mov pPEB, eax
pop eax
}


剩下这个问题。
这个获取的PPEB是当前进程的吧?
指定进程的PPEB怎样获取?
[/Quote]
不能这样,需要调用NtQueryInformationProcess
加载更多回复(2)

15,471

社区成员

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

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