WriteProcessMemory寫入內存的問題?


下段代碼是我測試寫入內存的一段。
問題: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

22 个解决方案

#1


你這樣是不會把模塊從鏈中移除,你修改的是模塊映像,不是雙向鏈表。
如果要看是否寫入成功,請讀取模塊映像數據比較。
如果要從鏈表移除模塊,修改pModule.InLoadOrderModuleList中前一個節點和后一個節點,使前后節點連起來

#2


pModule.InLoadOrderModuleList,是啊,想過,但不知道怎么。
這不是對象,沒有辦法REmove

#3


去掉保護后
void RemoveListEntry(PLIST_ENTRY ListEntry)
{
ListEntry->BLink->FLink=ListEntry->FLink;
ListEntry->FLink->BLink=ListEntry->BLink;
}

#4


你繞了這么大的圈子,好象又把我繞回來了,列寧同志。
哈哈,好象解決了。

#5


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


剩下這個問題。
這個獲取的PPEB是當前進程的吧?
指定進程的PPEB怎樣獲取?

#6


引用 5 樓 jinggangshi 的回復:
C/C++ code
_asm{
        push eax
            mov eax,fs:[30h]
        mov pPEB, eax
            pop eax
    }


剩下這個問題。
這個獲取的PPEB是當前進程的吧?
指定進程的PPEB怎樣獲取?

不能這樣,需要調用NtQueryInformationProcess

#7


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是無效的。

#8


NtQueryInformationProcess(hProcess, 0, (PVOID)&pbi, sizeof(PROCESS_BASIC_INFORMATION), NULL );

最后一個參數的問題。
回頭總結下發上來。

#9


PebBaseAddress等於多少
這個是別的進程的地址,需要用NtReadVirtualMemory讀取,不能直接用你上面的代碼

#10


NtQueryInformationProcess最后一個參數可選

#11


PebBaseAddress等於多少

錯誤的值。不知取到了誰的
你說下怎么取吧!
累死我了

#12


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);
......................

#13


不成功,我要崩潰了。

#14


哪個步驟不成功,把返回值給我

#15


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

#16


打印pbi.pebbaseaddress,結果是多少

#17


+ pbi.PebBaseAddress 0x7ffda000 {InheritedAddressSpace=??? ReadImageFileExecOptions=??? BeingDebugged=??? ...} _PEB *

#18


試這個
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);
}

#19


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。

你先看看到的調用對不對,我再去看看你的代碼。
真不好意思。

#20


引用 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……

第二個參數是枚舉型,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一次,看那個模塊還能不能被列舉出來

#21


明白了,一會我試試,剛才看代碼也不象是輸出,不好意思。
我再看看,太麻煩你了。

#22


謝謝列寧同志,測試成功了,我得好好看看你的代碼。
先結帖了!

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com