[toc]

使用CE寻找种植Call并编写自动汇编脚本

1. 通过CE找到汇编Call(掠过)

2. 编写自动汇编脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat

alloc(newmem,1024)
createthread(newmem)
newmem:

//根据基地址和偏移量计算第一个参数的变量地址
mov ebx,00729670
mov ebx,[ebx]
mov ebx,[ebx+868]

//call function
push FFFFFFFF //常量-1
push 2 //种植ID 此刻为樱桃炸弹
mov eax,4 //Y轴座标
push 0 //x轴坐标

push ebx//地址[PlantsVsZombies.exe+329670]+868
call 0040FA10//函数地址
ret

[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)

通过Dll将代码注入

1. 编写动态链接库

dllmain.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// dllmain.c : Defines the entry point for the DLL application.
#include <windows.h>
int AsmPlant_();


BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
AsmPlant_();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
MessageBoxA(GetDesktopWindow, "Unload dll", "title", 1);
break;
}
return TRUE;
}

plant.asm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
; Plant.asm
.586
.model flat,stdcall,c
option casemap:none

.data
.code
AsmPlant_ proc
;根据基地址和偏移量计算第一个参数的变量地址
mov ebx,00729670h
mov ebx,[ebx]
mov ebx,[ebx+868h]

;call function
push 0FFFFFFFFh ;//常量-1
push 2 ;//种植ID 此刻为樱桃炸弹
mov eax,4 ;//Y轴座标
push 0 ;//x轴坐标

push ebx ;//地址[PlantsVsZombies.exe+329670]+868
mov ecx,0040FA10h
call ecx;//函数地址
ret
AsmPlant_ endp
end

2. 编写C语言程序将dll加载到程序中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//Message.c
#include <stdio.h>
#include <Windows.h>

BOOL Inject(DWORD dwProcessID, const WCHAR* szPath)
{
//LoadLibrary
//CreateRemoteThread
//1.打开目标进程获取句柄
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID);
//2.在目标进程体内申请空间
LPVOID lpAddress = VirtualAllocEx(hProcess, NULL, 0x100, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
//3.写入DLL路径
SIZE_T sWriteLength = 0;
BOOL bRet = WriteProcessMemory(hProcess, lpAddress, szPath, ((wcslen(szPath) + 1) * 2), &sWriteLength);
if (bRet == FALSE)
{
MessageBoxW(NULL, L"WriteProcessMemory Failed!", L"Error", MB_OK);
}
//4.创建远程线程,执行回调
HANDLE hThread = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibraryW, lpAddress, NULL, NULL);
//5.等待远程线程执行结束(LoadLibrary返回了)
WaitForSingleObject(hThread, INFINITE);
//6.释放空间
VirtualFreeEx(hProcess, lpAddress, 0, MEM_RELEASE);
//7.释放句柄
CloseHandle(hProcess);
CloseHandle(hThread);
//8.返回结果
return TRUE;
}
int main()
{
//传入的两个参数分别为进程id与dll的绝对路径
Inject(19756, L"D:\\test\\CC++\\C+Windows+Pragrma\\C+windows\\Debug\\Dll1.dll");
return 0;
}

使用C语言根据种植Call编写自动种植脚本

1. 在x64dbg中编写汇编代码后转为机器码(略过)

汇编代码:

1

二进制代码

1

2. 使用C语言编写自动种植功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <Windows.h>
#include <Tlhelp32.h>
#include <stdio.h>
int PlantCall()
{
DWORD pid = NULL;
HWND hWnd = FindWindowW(NULL, L"Plants vs. Zombies");
if (hWnd == 0)
{
wprintf(L"Module wrong %p\n", hWnd);
return 0;
}
else
{
wprintf(L"Module %p\n", hWnd);
}
GetWindowThreadProcessId(hWnd, &pid);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
if (hProcess == 0)
{
wprintf(L"hProcess wrong %p\n", hProcess);
return 0;
}
else
{
wprintf(L"hProcess %p\n", hProcess);
}
//获取模块地址
DWORD modaddr = NULL;
MODULEENTRY32 modentry;
memset(&modentry, 0, sizeof(modentry));
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
modentry.dwSize = sizeof(MODULEENTRY32);
Module32FirstW(hSnapshot, &modentry);
do {
if (wcscmp(modentry.szModule, L"PlantsVsZombies.exe") == 0)
{
wprintf(L"Module %s\n", modentry.szModule);
modaddr = (DWORD)modentry.hModule;
CloseHandle(hSnapshot);
break;
}

} while (Module32Next(hSnapshot, &modentry));
//shellcode
BYTE shellcode[1024] = {
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x8D, 0x6D, 0x1D, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0x6A,
0x02, 0x8B, 0x45, 0x00, 0x8B, 0x4D, 0x04, 0x51, 0x8B, 0x55, 0x08, 0x52, 0x8B, 0x4D, 0x0C, 0xFF,
0xD1, 0x61, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00
};
//对象指针 pObj [[PlantsVsZombies.exe+329670]+0x868]
//函数指针 pFunc PlantsVsZombies.exe+FA10
DWORD x = 8;
DWORD y = 0;
DWORD pObj = modaddr;
printf("module addr pOBJ is %p\n", pObj);
ReadProcessMemory(hProcess, (LPVOID)(pObj + 0x329670), &pObj, 4, 0);
printf("pOBJ is %p\n", pObj);
ReadProcessMemory(hProcess, (LPVOID)(pObj + 0x868), &pObj, 4, 0);
printf("pOBJ is %p\n", pObj);
DWORD pFunc = modaddr + 0xFA10;
//*(DWORD*)(shellcode + 0x10)==种植ID
*(char*)(shellcode + 0x10) = 0x02;
*(DWORD*)(shellcode + 0x23) = y;
*(DWORD*)(shellcode + 0x27) = x;
*(DWORD*)(shellcode + 0x2B) = pObj;
*(DWORD*)(shellcode + 0x2F) = pFunc;
while (true)
{
*(DWORD*)(shellcode + 0x23) = y;
LPVOID calladdr = VirtualAllocEx(hProcess, NULL, 1024, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (calladdr == 0)return 0;
printf("%p is %p\n", &calladdr, calladdr);
WriteProcessMemory(hProcess, calladdr, shellcode, 1024, NULL);
HANDLE hRemote = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)calladdr, NULL, NULL, NULL);
WaitForSingleObject(hRemote, INFINITE);
y++;
if (y == 5) y = 0;
Sleep(1000);
CloseHandle(hRemote);

}
CloseHandle(hProcess);
return 0;

}
int main()
{
PlantCall();
return 0;
}