大概是从零开始做个外挂

大家七夕快乐!
作为一只单身狗,在这普天同庆的日子里总要找些事情做。我一般是会选择在这一天打打植物大战僵尸……
PVZ多少算是从小玩到大的游戏, 在我还是个小学生的时候,我只能靠别人写的修改器过日子,但是时代变了!作为一个二进制手,我可以自己写个外挂出来!
封面是我自己打的

Step 1: Find and Control

外挂说穿了其实就是那么点事,无非就是改改内存。不过第一步,我们需要找到进程。
Windows提供了tlhelp32.h作为API获取进程、模块、线程的快照信息。
CreateToolhelp32Snapshot提供进程快照,
OpenProcess则让我们接管进程,它们的原型如下

HANDLE
CreateToolhelp32Snapshot(
DWORD dwFlags,
DWORD th32ProcessID
);
HANDLE
OpenProcess(
_In_ DWORD dwDesiredAccess,
_In_ BOOL bInheritHandle,
_In_ DWORD dwProcessId
);

ok, 接下来要做的就是在茫茫一片进程中找到自己指定的受害者。
一般来讲外挂都是靠名字找pid

HANDLE OpenByName(char *pName)
{
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe32 = {sizeof(PROCESSENTRY32)};
for (BOOL ret = Process32First(hProcessSnap, &pe32); ret; ret = Process32Next(hProcessSnap, &pe32))
{
if (strcmp((char *)pe32.szExeFile, pName) == 0)
{
CloseHandle(hProcessSnap);
printf("%d\n", pe32.th32ProcessID);
return OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
}
}
}

我们可以发现这个代码写的非常不鲁棒

Step 2: Read And Write

既然已经接管了进程,那就可以改写内存了,为了实验我写了这样一个程序,

#include <stdio.h>
#include <windows.h>
int cnt = 0;
int main()
{
while (1)
{
cnt++;
Sleep(10000);
printf("%d\n", cnt);
}
}

它要干嘛非常明显,丢进IDA里发现cnt的地址在0x407030
Windows提供的读写内存的API分别是ReadProcessMemoryWriteProcessMemory
原型如下

BOOL
ReadProcessMemory(
_In_ HANDLE hProcess,
_In_ LPCVOID lpBaseAddress,
_Out_writes_bytes_to_(nSize,*lpNumberOfBytesRead) LPVOID lpBuffer,
_In_ SIZE_T nSize,
_Out_opt_ SIZE_T* lpNumberOfBytesRead
);

BOOL
WriteProcessMemory(
_In_ HANDLE hProcess,
_In_ LPVOID lpBaseAddress,
_In_reads_bytes_(nSize) LPCVOID lpBuffer,
_In_ SIZE_T nSize,
_Out_opt_ SIZE_T* lpNumberOfBytesWritten
);

读和写都有了……改就完事了嗷

HANDLE p = OpenByName(name);
while (1)
{
ReadProcessMemory(p, LPCVOID(0x407030), &ret, 4, 0);
printf("%d\n", ret);
ret = rand();
WriteProcessMemory(p, LPVOID(0x407030), &ret, 4, 0);
Sleep(10000);
}


我们可以看到,这个计数器变的乱七八糟已经是我的形状了

Step 3: Hack and Be arrested

到了这一步,接下来就是找几个游戏真枪实战干一回,然后就进去了
这个等我以后找到合适的对象再写。