原理
虚拟内存
用户程序区的范围:0x00010000-0x7ffeffff
读取信息:
//进程查看器/结束进程
//write by yuanchunxu
#include <stdio.h>
#include <Windows.h>
int main()
{
SYSTEM_INFO systemInfo;
GetNativeSystemInfo(&systemInfo);
printf("处理器个数:%d\n", systemInfo.dwNumberOfProcessors);
printf("分配粒度:%d\n", systemInfo.dwAllocationGranularity);
printf("分页大小:%d\n", systemInfo.dwPageSize);
printf("最小寻址范围:%x", systemInfo.lpMinimumApplicationAddress);
printf("最大寻址单元:%x\n", systemInfo.lpMaximumApplicationAddress);
if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64
|| systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64) {
printf("64位系统\n");
}
else {
printf("32位系统\n");
}
system("pause");
return 0;
}
API
程序:
/*
教学示例:游戏修改器
功能说明:
1. 列出现有进程。
2. 指定进程并修改该进程目标内存。
1)打开进程,获取内核对象句柄。
2)查找首轮目标。
3)列出查找结果。
4)结果大于1时,查找二轮目标。
5)修改二轮目标中所有内存的值。
3. 杀死指定进程。
4. 退出。
编写者:袁春旭
*/
#include <stdio.h>
#include <Windows.h>
#include <stdlib.h>
#include <TlHelp32.h>
const DWORD KONEK = 1024;//1k
const DWORD KPAGE = 4 * KONEK;//4k 一页
const DWORD KONEG = KONEK * KONEK * KONEK;//1G
void ShowMenu();
void ShowProcessList();
void EditProcessData();
void KillProcess();
void FirstRound(HANDLE hProcess, DWORD dwValue, DWORD *pAddrList, DWORD *pAddrListCounter, const DWORD addrListMax);
BOOL CompareOnePage(HANDLE hProcess, DWORD dwBaseAddr, DWORD dwValue, DWORD *pAddrList, DWORD *pAddrListCounter, const DWORD addrListMax);
void ShowAddrList(DWORD *pDwAddrList, DWORD dwAddrCount);
void SecondRound(HANDLE hProcess, DWORD dwValue, DWORD *pAddrList, DWORD dwAddrListCounter, DWORD *pTargetList, DWORD *pTargetCounter);
int main(void)
{
int select = 0;
while (true)
{
//显示菜单
ShowMenu();
while (!scanf_s("%d", &select))
{
rewind(stdin);
printf("please input your choice...");
}
switch (select)
{
case 1:
ShowProcessList();
break;
case 2:
EditProcessData();
break;
case 3:
KillProcess();
break;
case 4:
printf("Thank your using ...\n");
system("pause");
return 0;
default:
printf("Please select again 1-4...\n");
}
}
return 0;
}
void ShowMenu()
{
printf("\n--------------------------\n");
printf("Menu:\n");
printf("\t1.Show system process list.\n");
printf("\t2.Input process id which you want to edit.\n");
printf("\t3.Input process id which you want to kill.\n");
printf("\t4.Exit\n");
printf("--------------------------\n");
}
void ShowProcessList()
{
PROCESSENTRY32 pc;
pc.dwSize = sizeof(pc);
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
BOOL bMore = Process32First(hProcessSnap, &pc);
while(bMore)
{
printf("\n-------------------\n");
printf("%d\n", pc.th32ProcessID);
wprintf(L"%s\n", pc.szExeFile);
bMore = Process32Next(hProcessSnap, &pc);
}
CloseHandle(hProcessSnap);
}
void EditProcessData()
{
DWORD dwId = 0;
DWORD dwSearchValue = 0;
DWORD dwAddrList[4 * KONEK] = { 0 };
DWORD dwAddrCount = 0;
BOOL bRet = FALSE;
printf("please input process id which you want to edit:");
while (!scanf_s("%u", &dwId))
{
rewind(stdin);
printf("please input again:");
}
//printf("\nprocess id = %u\n", dwId);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwId);
if (NULL == hProcess)
{
printf("Open process failed...\n");
return;
}
else
{
printf("Open process success...\n");
system("pause");
printf("Please input the value which you want search first round:");
scanf_s("%u", &dwSearchValue);
// 进程句柄 查找的值 存放符合条件的地址的数组首地址 符合的个数 数组大小
FirstRound(hProcess, dwSearchValue, dwAddrList, &dwAddrCount, 4 * KONEK);
//显示找到的数据
ShowAddrList(dwAddrList, dwAddrCount);
if (dwAddrCount == 0)
{
return;
}
else if (dwAddrCount == 1)
{
DWORD value;
printf("input the value which you want to set");
scanf_s("%u", &value);
bRet = WriteProcessMemory(hProcess, (LPVOID)dwAddrList[0], (LPCVOID)&value, sizeof(DWORD), NULL);
if (bRet)
{
printf("Edit Success!!!\n");
}
else
{
printf("Edit failed!!!\n");
}
}
else
{
DWORD dwSecondRoundSearchValue = 0;
DWORD dwTargetList[KONEK] = { 0 };
DWORD dwTargetCounter = 0;
printf("input the value which you need second round find:");
scanf_s("%u", &dwSecondRoundSearchValue);
//找到的值的个数超过1个 从大于1的内存列表中找修改后为dwSecondRoundSearchValue的内存地址
SecondRound(hProcess, dwSecondRoundSearchValue, dwAddrList, dwAddrCount, dwTargetList, &dwTargetCounter);
ShowAddrList(dwTargetList, dwTargetCounter);
DWORD value;
printf("input the value which you want to set");
scanf_s("%u", &value);
for (DWORD i = 0; i < dwTargetCounter; i++)
{
bRet = WriteProcessMemory(hProcess, (LPVOID)dwTargetList[i], &value, sizeof(value), NULL);
if (bRet)
{
printf("Edit Success!!!\n");
}
else
{
printf("Edit failed!!!\n");
}
}
}
}
CloseHandle(hProcess);
}
void KillProcess()
{
BOOL bRet = FALSE;
DWORD dwId = 0;
printf("Please input process id while you want to kill...\n");
while (!scanf_s("%u", &dwId))
{
rewind(stdin);
printf("please input process id while you want to kill");
}
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwId);
if (hProcess != NULL)
{
bRet = TerminateProcess(hProcess, 0);
}
CloseHandle(hProcess);
if (bRet)
{
printf("kill process success\n");
}
else
{
printf("kill process failed\n");
}
}
void FirstRound(HANDLE hProcess, DWORD dwValue, DWORD *pAddrList, DWORD *pAddrListCounter, const DWORD addrListMax)
{
DWORD dwBaseAddr = 64 * KONEK;//内存中的前64k
DWORD dwPageCount = (2 * KONEG - 64 * KONEK * 2) / KPAGE;//用户程序区页的总数
printf("%u pages\n", dwPageCount);
printf("Start searching ...\n");
DWORD dwBeginAddr = dwBaseAddr;
for (; dwBaseAddr < 2 * KONEG - 64 * KONEK; dwBaseAddr += KPAGE)
{
//比较一页
if (!CompareOnePage(hProcess, dwBaseAddr, dwValue, pAddrList, pAddrListCounter, addrListMax))
{
return;
}
//计算进度百分比
DWORD page = (dwBaseAddr - dwBeginAddr) / KPAGE + 1;
printf("current is %u page\n", page);
double temp = ((double)page / dwPageCount) * 100;
printf("-----%%%f------\n", temp);
}
printf("\nSearch finished...\n");
system("pause");
}
//比较一页 返回值bool ture 代表pAddrList数组未满
BOOL CompareOnePage(HANDLE hProcess, DWORD dwBaseAddr, DWORD dwValue, DWORD *pAddrList, DWORD *pAddrListCounter, const DWORD addrListMax)
{
BYTE byPage[KPAGE] = {0};//读取一页的数据
if (!ReadProcessMemory(hProcess, (LPCVOID)dwBaseAddr, (LPVOID)byPage, KPAGE, NULL))
{
printf("Read Memory error!!!\n");
return TRUE;
}
DWORD *pdwPointer = NULL;
pdwPointer = (DWORD *)byPage;//因为DWORD dwValue,所以要把数组指针转成 DWORD
//要查找的是DWORD 占4字节 因此需要搜索KONEK次
for (DWORD i = 0; i < KONEK; i++)
{
if (*pAddrListCounter >= addrListMax)
{
printf("Too many data, can not save...\n");
return FALSE;
}
if (pdwPointer[i] == dwValue)
{
pAddrList[*pAddrListCounter] = dwBaseAddr + i * sizeof(DWORD);//记录内存地址 dwBaseAddr是该页基地址
(*pAddrListCounter)++;
}
}
return TRUE;
}
void ShowAddrList(DWORD *pDwAddrList, DWORD dwAddrCount)
{
printf("\n----------Address list begin----------\n");
for (DWORD i = 0; i < dwAddrCount; i++)
{
printf("%X\n", pDwAddrList[i]);
}
printf("\n----------Address list end------------\n");
}
void SecondRound(HANDLE hProcess, DWORD dwValue, DWORD *pAddrList, DWORD dwAddrListCounter, DWORD *pTargetList, DWORD *pTargetCounter)
{
DWORD dwTemp = 0;
for (DWORD i = 0; i < dwAddrListCounter; i++)
{
if (ReadProcessMemory(hProcess, (LPCVOID)pAddrList[i], &dwTemp, sizeof(dwTemp), NULL))
{
if (dwTemp == dwValue)
{
pTargetList[*pTargetCounter] = pAddrList[i];
(*pTargetCounter)++;
}
}
}
}