#include <windows.h>
#include <tlhelp32.h>
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>
#include <chrono>
#include <thread>
using
namespace
std;
const
wstring TARGET_EXE = L
"AML.exe"
;
const
string SEARCH_PATTERN =
"32 44 32 44 32 44 32 44 32 44 34 32 34 35 34 37 34 39 34 45 32 30 35 30 35 35 34 32 34 43 34 39 34 33 32 30 34 42 34 35 35 39 32 44 32 44 32 44 32 44 32 44 30 41 34 44 34 39 34 37 36 36 34 44 34 31 33 30 34 37 34 33 35 33 37 31 34 37 35 33 34 39 36 32 33 33 34 34 35 31 34 35 34 32 34 31 35 31 35 35 34 31 34 31 33 34 34 37 34 45 34 31 34 34 34 33 34 32 36 39 35 31 34 42 34 32 36 37 35 31 34 33 35 36 34 44 36 43 33 39 36 45 36 33 35 36 35 39 33 39 35 41 36 31 36 32 35 39 34 39 36 44 33 38 36 32 35 38 33 32 36 38 37 35 36 46 35 30 34 46 36 32 30 41 34 42 36 31 37 39 35 30 33 33 34 31 36 35 37 30 34 41 34 37 33 35 35 37 37 34 37 36 35 41 35 34 34 46 36 43 34 31 36 46 33 38 35 39 33 30 34 37 33 37 36 36 35 41 36 35 34 31 36 39 33 39 34 31 36 33 36 41 34 37 34 35 36 39 36 41 34 41 36 33 35 34 37 41 34 36 35 39 33 32 37 37 33 39 37 37 33 34 37 30 33 33 34 35 34 41 35 36 37 36 37 36 37 39 33 39 34 36 34 39 37 37 37 34 34 44 34 41 30 41 33 34 35 35 33 35 33 31 35 37 36 31 33 33 33 34 36 34 37 36 35 33 35 32 34 46 36 38 33 36 37 33 33 35 36 43 35 39 35 37 34 42 34 46 35 39 37 31 36 41 32 46 37 34 34 31 34 38 36 38 36 32 34 41 35 30 37 36 35 30 37 30 35 38 37 33 36 31 32 46 35 38 34 31 36 31 33 39 34 36 37 41 33 37 36 41 37 35 36 39 37 33 35 37 36 39 37 37 32 42 35 32 37 32 35 34 35 38 35 36 34 41 34 41 37 34 34 43 30 41 36 43 37 36 35 32 35 31 34 46 35 30 34 34 34 34 33 34 36 31 36 42 34 34 35 39 32 42 33 34 37 39 36 46 35 31 34 39 34 34 34 31 35 31 34 31 34 32 30 41 32 44 32 44 32 44 32 44 32 44 34 35 34 45 34 34 32 30 35 30 35 35 34 32 34 43 34 39 34 33 32 30 34 42 34 35 35 39 32 44 32 44 32 44 32 44 32 44"
;
const
string REPLACE_PATTERN =
"32 44 32 44 32 44 32 44 32 44 34 32 34 35 34 37 34 39 34 45 32 30 35 30 35 35 34 32 34 43 34 39 34 33 32 30 34 42 34 35 35 39 32 44 32 44 32 44 32 44 32 44 30 41 34 44 34 39 34 37 36 36 34 44 34 31 33 30 34 37 34 33 35 33 37 31 34 37 35 33 34 39 36 32 33 33 34 34 35 31 34 35 34 32 34 31 35 31 35 35 34 31 34 31 33 34 34 37 34 45 34 31 34 34 34 33 34 32 36 39 35 31 34 42 34 32 36 37 35 31 34 34 35 32 32 46 36 41 35 34 34 43 35 34 35 35 36 33 33 34 37 37 33 39 34 38 37 37 36 34 34 33 34 33 34 45 37 38 34 31 33 38 37 34 34 41 33 35 33 37 33 39 30 41 36 35 37 35 35 34 32 46 36 46 34 34 35 31 37 38 36 32 37 39 35 41 36 31 33 32 37 34 35 31 32 46 36 41 34 34 36 46 37 39 36 45 34 38 33 32 35 30 37 32 34 46 35 35 33 35 34 45 33 38 33 36 34 42 34 38 35 37 33 35 37 31 34 46 37 37 32 42 34 42 35 30 37 39 34 41 37 35 35 33 32 42 36 46 36 44 34 39 36 34 37 32 37 38 34 43 34 34 35 31 36 42 37 41 35 35 34 38 37 32 35 32 37 41 33 33 33 35 30 41 34 46 35 33 34 34 35 38 37 34 35 38 35 34 37 39 36 35 34 35 32 42 34 44 37 36 35 41 35 31 37 30 36 44 33 33 35 33 34 36 35 36 37 41 35 34 36 44 37 38 36 37 36 46 36 42 37 30 35 37 37 38 36 42 34 36 35 38 33 39 36 36 36 43 33 35 37 37 36 36 35 35 36 42 34 43 34 46 34 37 36 42 37 41 35 39 34 31 36 37 34 39 33 39 36 34 37 37 34 43 37 30 35 36 36 42 36 34 37 34 33 36 37 34 35 34 36 42 30 41 34 34 36 37 36 33 35 39 35 31 37 33 35 35 35 32 34 34 33 34 37 38 35 35 36 33 36 37 33 30 35 39 33 33 35 31 34 39 34 34 34 31 35 31 34 31 34 32 30 41 32 44 32 44 32 44 32 44 32 44 34 35 34 45 34 34 32 30 35 30 35 35 34 32 34 43 34 39 34 33 32 30 34 42 34 35 35 39 32 44 32 44 32 44 32 44 32 44"
;
struct
ProcessInfo {
DWORD
pid;
FILETIME creationTime;
bool
isFirstInstance =
false
;
};
ProcessInfo g_firstProcess = { 0 };
vector<
BYTE
> ParseHexPattern(
const
string& patternStr) {
vector<
BYTE
> result;
stringstream ss(patternStr);
string hexByte;
while
(ss >> hexByte) {
try
{
int
value = stoi(hexByte,
nullptr
, 16);
result.push_back(
static_cast
<
BYTE
>(value));
}
catch
(...) {
cerr <<
"[ERROR] 无效的十六进制字节: "
<< hexByte << endl;
exit
(EXIT_FAILURE);
}
}
return
result;
}
bool
StartAMLProcess() {
STARTUPINFO si = {
sizeof
(STARTUPINFO) };
PROCESS_INFORMATION pi;
wchar_t
currentDir[MAX_PATH];
GetCurrentDirectoryW(MAX_PATH, currentDir);
wstring exePath = wstring(currentDir) + L
"\\"
+ TARGET_EXE;
if
(!CreateProcessW(
exePath.c_str(),
NULL,
NULL,
NULL,
FALSE,
0,
NULL,
currentDir,
&si,
&pi
)) {
cerr <<
"[ERROR] 无法启动进程 (错误码: 0x"
<< hex << GetLastError() <<
")"
<< endl;
return
false
;
}
FILETIME creationTime, exitTime, kernelTime, userTime;
GetProcessTimes(pi.hProcess, &creationTime, &exitTime, &kernelTime, &userTime);
g_firstProcess.pid = pi.dwProcessId;
g_firstProcess.creationTime = creationTime;
g_firstProcess.isFirstInstance =
true
;
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
cout <<
"已成功启动初始进程 (PID: "
<< pi.dwProcessId <<
")"
<< endl;
return
true
;
}
vector<ProcessInfo> FindAMLProcesses() {
vector<ProcessInfo> processes;
HANDLE
snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if
(snapshot == INVALID_HANDLE_VALUE) {
cerr <<
"[ERROR] 创建进程快照失败 (0x"
<< hex << GetLastError() <<
")"
<< endl;
return
processes;
}
PROCESSENTRY32W pe = {
sizeof
(PROCESSENTRY32W) };
if
(!Process32FirstW(snapshot, &pe)) {
CloseHandle(snapshot);
return
processes;
}
do
{
if
(_wcsicmp(pe.szExeFile, TARGET_EXE.c_str()) == 0) {
HANDLE
hProcess = OpenProcess(
PROCESS_QUERY_LIMITED_INFORMATION,
FALSE,
pe.th32ProcessID
);
if
(hProcess) {
FILETIME creationTime, exitTime, kernelTime, userTime;
if
(GetProcessTimes(hProcess, &creationTime, &exitTime, &kernelTime, &userTime)) {
ProcessInfo info;
info.pid = pe.th32ProcessID;
info.creationTime = creationTime;
info.isFirstInstance = (pe.th32ProcessID == g_firstProcess.pid);
processes.push_back(info);
}
CloseHandle(hProcess);
}
}
}
while
(Process32NextW(snapshot, &pe));
CloseHandle(snapshot);
return
processes;
}
DWORD
WaitForSecondProcess() {
cout <<
"等待第二个AML.exe进程启动..."
<< endl;
const
int
maxWaitSeconds = 30;
auto
startTime = chrono::steady_clock::now();
while
(
true
) {
auto
elapsed = chrono::duration_cast<chrono::seconds>(
chrono::steady_clock::now() - startTime).count();
if
(elapsed > maxWaitSeconds) {
cerr <<
"[ERROR] 等待超时,未检测到第二个进程"
<< endl;
exit
(EXIT_FAILURE);
}
auto
processes = FindAMLProcesses();
vector<ProcessInfo> newProcesses;
copy_if(processes.begin(), processes.end(), back_inserter(newProcesses),
[](
const
ProcessInfo& pi) {
return
!pi.isFirstInstance; });
if
(!newProcesses.empty()) {
sort(newProcesses.begin(), newProcesses.end(),
[](
const
ProcessInfo& a,
const
ProcessInfo& b) {
return
CompareFileTime(&a.creationTime, &b.creationTime) < 0;
});
cout <<
"发现目标进程 (PID: "
<< newProcesses[0].pid <<
")"
<< endl;
return
newProcesses[0].pid;
}
this_thread::sleep_for(chrono::seconds(1));
}
}
bool
MemoryOperation(
HANDLE
hProcess,
const
vector<
BYTE
>& searchPattern,
const
vector<
BYTE
>& replacePattern) {
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
uintptr_t
minAddr = (
uintptr_t
)sysInfo.lpMinimumApplicationAddress;
uintptr_t
maxAddr = (
uintptr_t
)sysInfo.lpMaximumApplicationAddress;
MEMORY_BASIC_INFORMATION memInfo;
vector<
BYTE
> buffer;
size_t
replaceCount = 0;
for
(
uintptr_t
addr = minAddr; addr < maxAddr; ) {
if
(!VirtualQueryEx(hProcess, (
LPCVOID
)addr, &memInfo,
sizeof
(memInfo))) {
addr += sysInfo.dwPageSize;
continue
;
}
addr = (
uintptr_t
)memInfo.BaseAddress + memInfo.RegionSize;
if
(memInfo.State != MEM_COMMIT ||
memInfo.Protect == PAGE_NOACCESS ||
(memInfo.Protect & PAGE_GUARD)) {
continue
;
}
vector<
BYTE
> chunk(memInfo.RegionSize);
SIZE_T
bytesRead;
if
(ReadProcessMemory(hProcess, memInfo.BaseAddress,
chunk.data(), memInfo.RegionSize, &bytesRead)) {
for
(
size_t
i = 0; i + searchPattern.size() <= bytesRead; ++i) {
if
(
memcmp
(chunk.data() + i,
searchPattern.data(),
searchPattern.size()) == 0) {
uintptr_t
targetAddr = (
uintptr_t
)memInfo.BaseAddress + i;
DWORD
oldProtect;
if
(VirtualProtectEx(hProcess, (
LPVOID
)targetAddr,
searchPattern.size(),
PAGE_EXECUTE_READWRITE, &oldProtect)) {
SIZE_T
written;
if
(WriteProcessMemory(hProcess, (
LPVOID
)targetAddr,
replacePattern.data(),
replacePattern.size(), &written)) {
replaceCount++;
cout <<
"成功修改地址: 0x"
<< hex << targetAddr << endl;
}
VirtualProtectEx(hProcess, (
LPVOID
)targetAddr,
searchPattern.size(), oldProtect, &oldProtect);
}
}
}
}
}
cout <<
"\n共完成 "
<< dec << replaceCount <<
" 处修改"
<< endl;
return
replaceCount > 0;
}
int
main() {
if
(!StartAMLProcess()) {
return
EXIT_FAILURE;
}
DWORD
targetPid = WaitForSecondProcess();
HANDLE
hTarget = OpenProcess(
PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION,
FALSE, targetPid);
if
(!hTarget) {
DWORD
err = GetLastError();
cerr <<
"[ERROR] 无法打开目标进程 (0x"
<< hex << err <<
")"
<< endl;
return
EXIT_FAILURE;
}
auto
searchBytes = ParseHexPattern(SEARCH_PATTERN);
auto
replaceBytes = ParseHexPattern(REPLACE_PATTERN);
if
(searchBytes.size() != replaceBytes.size()) {
cerr <<
"[ERROR] 搜索模式和替换模式长度不一致"
<< endl;
CloseHandle(hTarget);
return
EXIT_FAILURE;
}
cout <<
"\n开始内存修改操作..."
<< endl;
Sleep(1100);
MemoryOperation(hTarget, searchBytes, replaceBytes);
CloseHandle(hTarget);
cout <<
"操作已完成"
<< endl;
return
EXIT_SUCCESS;
}