程式設計思路:
一個測試程式 + 搜尋記憶體 & 修改記憶體
定義兩個變數,分別對這個兩個變數裡的內容進行改變(相當不斷的修改同一記憶體的值),這樣最是為了後面搜尋記憶體的時候確定唯一的那一塊。正如經過一點可以有很多直線,再加一個點就可以完全確定這個直線了。這裡正是利用這個思想,當然這裡不一定兩次就可以唯一確定。首先根據第一個值,在該進程的記憶體內尋找符合該值的所有記憶體,並將滿足條件的記憶體儲存起來。
測試程式:
#include <stdio.h></p><p>int g_nNum;</p><p>int main(int argc,char *argv[])<br />{<br />int i=198;<br />g_nNum=1003;</p><p> while(1)<br />{<br />printf("i=%d , addr = %081x ; g_nNum = %d , addr = %081x/n",++i , &i , --g_nNum , &g_nNum);<br />getchar();<br />}<br />return 0;<br />}
首先根據OS的版本不同找到不同的起始點,從該起始點搜尋到2G的記憶體。
//find the kind of the operate system , to decide the start address<br />DWORD dwBase ;<br />OSVERSIONINFO vi = { sizeof(vi) } ;<br />::GetVersionEx(&vi);<br />if (vi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)<br />{<br />dwBase = 4 * 1024 * 1024 ; //windows 98 4 MB<br />}<br />else<br />{<br />dwBase = 64 * 1024; //windows NT 64KB<br />}
根據windows採用分頁機制管理記憶體,每頁的大小是4KB。我們也是以頁為單位,提高搜尋的效率。
for ( dwBase已由上面程式確定 ; dwBase <= 2 * dwOneGB ; dwBase += dwOnePage))
利用ReadProcessMemory() 讀取一頁的記憶體,然後再在該一頁一次進行匹配是否相等
如果FindFirst() 得到的記憶體不止一個,我們繼續在已經得到的記憶體裡通過改變要尋找的記憶體的值,繼續FindNext () 尋找篩選。每次尋找一次,所得到要儲存的記憶體逐漸減少,知道最後只剩下一個為止,既得到所要尋找的記憶體,然後利用WriteProcessMemory()對該記憶體的值修改為自己想得到的值。
FindFirst() , FindNext() , WriteProcessMemory() 如下:
BOOL CompareAPage(DWORD dwBaseAddr , DWORD dwValue)<br />{<br />//讀一頁的記憶體<br />BYTE arBytes[4096];<br />if (!::ReadProcessMemory(g_hProcess , (LPVOID)dwBaseAddr , arBytes , 4096 , NULL))<br />{<br />return FALSE;<br />}<br />//在這一頁記憶體中尋找<br />DWORD *pdw;<br />for (int i=0 ; i < (int)4*1024-3 ; i++)<br />{<br />pdw=(DWORD *)&arBytes[i];<br />if(pdw[0] == dwValue)<br />{<br />if (g_nListCnt >= 1024)<br />return FALSE;</p><p>g_arList[g_nListCnt++]=dwBaseAddr + i;<br />}<br />}<br />return TRUE;<br />}</p><p>BOOL FindFirst(DWORD dwValue)<br />{<br />const DWORD dwOneGB = 1024 * 1024 * 1024 ;<br />const DWORD dwOnePage = 4 * 1024 ;</p><p>if (g_hProcess == NULL)//be careful "=="<br />{<br />return FALSE;<br />}</p><p>//find the kind of the operate system , to decide the start address<br />DWORD dwBase ;<br />OSVERSIONINFO vi = { sizeof(vi) } ;<br />::GetVersionEx(&vi);<br />if (vi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)<br />{<br />dwBase = 4 * 1024 * 1024 ; //windows 98 4 MB<br />}<br />else<br />{<br />dwBase = 64 * 1024; //windows NT 64KB<br />}</p><p>//start to find from the dwBase addr to 2GB<br />for ( ; dwBase <= 2 * dwOneGB ; dwBase += dwOnePage)<br />{<br />CompareAPage(dwBase , dwValue);<br />}<br />return TRUE ;<br />}</p><p>void ShowList()<br />{<br />for (int i=0 ; i < g_nListCnt ; i++)<br />{<br />printf("%081x/n",g_arList[i]);<br />}<br />}</p><p>BOOL FindNext(DWORD dwValue)<br />{<br />int nOrgCnt = g_nListCnt;<br />g_nListCnt = 0;</p><p>BOOL bRet = FALSE ;<br />DWORD dwReadValue ;<br />for (int i = 0 ; i < nOrgCnt ; i++)<br />{<br />if (::ReadProcessMemory(g_hProcess , (LPVOID)g_arList[i] , &dwReadValue , sizeof(DWORD) , NULL))<br />{<br />if (dwReadValue == dwValue)<br />{<br />g_arList[g_nListCnt++] = g_arList[i] ;<br />bRet = TRUE ;<br />}<br />}<br />}<br />return bRet ;<br />}</p><p>BOOL WriteMemory(DWORD dwAddr , DWORD dwValue)<br />{<br />return ::WriteProcessMemory(g_hProcess , (LPVOID)dwAddr , &dwValue , sizeof(DWORD) , NULL);<br />}<br />
Main函數附下:
int main(int argc , char * argv[])<br />{<br />//start the process "02Testor"<br />char szFileName[] = "F://steel//windows programme//02Testor//Debug//02Testor.exe";<br />STARTUPINFO si = { sizeof(si) } ;<br />PROCESS_INFORMATION pi;<br />::CreateProcess( NULL , szFileName , NULL , NULL , FALSE , CREATE_NEW_CONSOLE , NULL , NULL , &si , &pi );<br />::CloseHandle( pi.hThread );</p><p>g_hProcess = pi.hProcess ;</p><p>int ival;<br />printf("Input ival = ");<br />scanf(" %d " , &ival);</p><p>//find for the first time<br />FindFirst(ival);</p><p> printf("g_nListCnt = %d /n",g_nListCnt);</p><p>//show the result<br />ShowList();</p><p>while (g_nListCnt > 1)<br />{<br />printf("Input ival = ");<br />scanf(" %d " , &ival);</p><p>//find for the first time<br />FindNext(ival);</p><p>//show the result<br />ShowList();</p><p>}</p><p>//get the new value<br />printf("Input the new value = ");<br />scanf("%d",&ival);</p><p>if (WriteMemory(g_arList[0],ival))<br />{<br />printf("Write new value success !/n");<br />}</p><p>::CloseHandle(g_hProcess);</p><p>return 0;</p><p>}