Skip to content

Commit 8d26a62

Browse files
committed
refactor: Patch logic refactored using C++20
fix: Resolve issue with non-functional pause functionality fix: Throw error when .bak file already exists fix: Backup when file patched Signed-off-by: Mai Ooizumi <mai@imomoe.moe>
1 parent 9788592 commit 8d26a62

File tree

1 file changed

+91
-107
lines changed

1 file changed

+91
-107
lines changed

VScriptAutoPatcher/VScriptAutoPatcher.cpp

Lines changed: 91 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,83 @@
11
#include <iostream>
2-
#include <Windows.h>
32
#include <vector>
43
#include <cstdint>
54
#include <filesystem>
5+
#include <fstream>
6+
7+
#ifdef _WIN32
8+
#include <Windows.h>
9+
#include <conio.h>
610

7-
bool readFile(const std::string& filename, std::vector<uint8_t>& buffer)
11+
static std::string SelectPEFile()
812
{
9-
HANDLE fileHandle = CreateFileA(
10-
filename.c_str(),
11-
GENERIC_READ,
12-
FILE_SHARE_READ,
13-
NULL,
14-
OPEN_EXISTING,
15-
FILE_ATTRIBUTE_NORMAL,
16-
NULL
17-
);
18-
19-
if (fileHandle == INVALID_HANDLE_VALUE)
13+
TCHAR szBuffer[MAX_PATH] = { 0 };
14+
OPENFILENAME file = { 0 };
15+
16+
ZeroMemory(&file, sizeof(file));
17+
18+
file.hwndOwner = NULL;
19+
file.lStructSize = sizeof(file);
20+
file.lpstrFilter = L"vscript.dll(vscript.dll)\0vscript.dll\0所有文件(*.*)\0*.*\0\0";
21+
file.lpstrInitialDir = L"";
22+
file.lpstrFile = szBuffer;
23+
file.nMaxFile = sizeof(szBuffer) / sizeof(*szBuffer);
24+
file.nFilterIndex = 0;
25+
file.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
26+
27+
if (GetOpenFileName(&file))
2028
{
21-
std::cerr << "[ERROR] " << "Failed to create handle to: " << filename << std::endl;
22-
//std::cout << "[REMINDER] " << "Make sure the executable is in same folder with: " << filename << std::endl;
23-
return false;
29+
int size = WideCharToMultiByte(CP_ACP, 0, file.lpstrFile, -1, NULL, 0, NULL, NULL);
30+
if (size == 0)
31+
{
32+
return std::string();
33+
}
34+
std::string result(size - 1, 0);
35+
WideCharToMultiByte(CP_ACP, 0, file.lpstrFile, -1, &result[0], size, NULL, NULL);
36+
return result;
2437
}
38+
else
39+
{
40+
return std::string();
41+
}
42+
}
43+
44+
static void Pause()
45+
{
46+
std::cout << "Press any key to continue..." << std::flush;
47+
(void)_getch();
48+
}
2549

26-
DWORD fileSize = GetFileSize(fileHandle, NULL);
27-
buffer.resize(fileSize);
50+
#else
2851

29-
DWORD bytesRead = 0;
30-
ReadFile(fileHandle, buffer.data(), fileSize, &bytesRead, NULL);
52+
static void Pause()
53+
{
3154

32-
CloseHandle(fileHandle);
55+
}
3356

57+
#endif // _WIN32
58+
59+
static bool readFile(const std::string & fileName, std::vector<uint8_t> & buffer)
60+
{
61+
std::ifstream file(fileName, std::ios::binary);
62+
63+
if (!file.is_open())
64+
{
65+
std::cerr << "[ERROR] " << "Failed to open file: " << fileName << std::endl;
66+
return false;
67+
}
68+
69+
file.seekg(0, std::ios::end);
70+
std::streamsize fileSize = file.tellg();
71+
file.seekg(0, std::ios::beg);
72+
73+
buffer.resize(static_cast<size_t>(fileSize));
74+
file.read(reinterpret_cast<char *>(buffer.data()), fileSize);
75+
76+
file.close();
3477
return true;
3578
}
3679

37-
std::vector<size_t> findHexArray(std::vector<uint8_t>& buffer, const std::vector<uint8_t>& hexArray)
80+
static std::vector<size_t> findHexArray(const std::vector<uint8_t> & buffer, const std::vector<uint8_t> & hexArray)
3881
{
3982
std::vector<size_t> positions;
4083

@@ -43,16 +86,11 @@ std::vector<size_t> findHexArray(std::vector<uint8_t>& buffer, const std::vector
4386

4487
for (size_t i = 0; i <= bufferSize - arraySize; ++i)
4588
{
46-
bool found = true;
47-
48-
for (size_t j = 0; j < arraySize; ++j) {
49-
if (buffer[i + j] != hexArray[j] && hexArray[j] != 0x2A) {
50-
found = false;
51-
break;
52-
}
53-
}
54-
55-
if (found)
89+
if (std::ranges::equal(buffer.begin() + i, buffer.begin() + i + arraySize, hexArray.begin(), hexArray.end(),
90+
[](uint8_t a, uint8_t b)
91+
{
92+
return a == b || b == 0x2A;
93+
}))
5694
{
5795
std::cout << "[INFO] " << "Found position at buffer index: " << i << std::endl;
5896
positions.push_back(i);
@@ -62,37 +100,27 @@ std::vector<size_t> findHexArray(std::vector<uint8_t>& buffer, const std::vector
62100
return positions;
63101
}
64102

65-
bool writeFile(const std::string& filename, const std::vector<uint8_t>& buffer)
103+
static bool writeFile(const std::string & fileName, const std::vector<uint8_t> & buffer)
66104
{
67-
HANDLE fileHandle = CreateFileA(
68-
filename.c_str(),
69-
GENERIC_WRITE,
70-
0,
71-
NULL,
72-
CREATE_ALWAYS,
73-
FILE_ATTRIBUTE_NORMAL,
74-
NULL
75-
);
76-
77-
if (fileHandle == INVALID_HANDLE_VALUE)
78-
{
79-
std::cerr << "[ERROR] " << "Failed to create handle to: " << filename << std::endl;
80-
//std::cout << "[REMINDER] " << "Make sure the executable is in same folder with: " << filename << std::endl;
105+
std::ofstream file(fileName, std::ios::binary);
81106

107+
if (!file.is_open())
108+
{
109+
std::cerr << "[ERROR] " << "Failed to open file: " << fileName << std::endl;
82110
return false;
83111
}
84112

85-
DWORD bytesWritten = 0;
86-
WriteFile(fileHandle, buffer.data(), buffer.size(), &bytesWritten, NULL);
113+
file.write(reinterpret_cast<const char *>(buffer.data()), buffer.size());
87114

88-
CloseHandle(fileHandle);
115+
file.close();
89116

90-
return (bytesWritten == buffer.size());
117+
return true;
91118
}
92119

93-
void PatchFile(std::string fileName, std::vector<uint8_t> originalArray, std::vector<uint8_t> replacedArray)
120+
static void patchFile(const std::string & fileName, const std::vector<uint8_t> & originalArray, const std::vector<uint8_t> & replacedArray)
94121
{
95122
std::vector<uint8_t> buffer;
123+
96124
if (!readFile(fileName, buffer))
97125
{
98126
return;
@@ -102,19 +130,19 @@ void PatchFile(std::string fileName, std::vector<uint8_t> originalArray, std::ve
102130

103131
if (positions.empty())
104132
{
105-
std::cout << "[ERROR] " << fileName << " is already patched" << std::endl;
133+
std::cerr << "[ERROR] " << fileName << " is already patched" << std::endl;
106134
return;
107135
}
108136

137+
if (std::filesystem::exists(fileName + ".bak"))
138+
{
139+
std::filesystem::remove(fileName + ".bak");
140+
}
141+
std::filesystem::copy(fileName, fileName + ".bak");
142+
109143
for (size_t pos : positions)
110144
{
111-
for (size_t i = 0; i < replacedArray.size(); ++i)
112-
{
113-
if (replacedArray[i] != 0x2A)
114-
{
115-
buffer[pos + i] = replacedArray[i];
116-
}
117-
}
145+
std::ranges::copy(replacedArray.begin(), replacedArray.end(), buffer.begin() + pos);
118146
}
119147

120148
if (!writeFile(fileName, buffer))
@@ -125,48 +153,6 @@ void PatchFile(std::string fileName, std::vector<uint8_t> originalArray, std::ve
125153
std::cout << "[SUCCESS] " << fileName << " has been patched." << std::endl;
126154
}
127155

128-
static std::string SelectPEFile()
129-
{
130-
TCHAR szBuffer[MAX_PATH] = { 0 };
131-
OPENFILENAME file = { 0 };
132-
133-
ZeroMemory(&file, sizeof(file));
134-
135-
file.hwndOwner = NULL;
136-
file.lStructSize = sizeof(file);
137-
file.lpstrFilter = L"vscript.dll(vscript.dll)\0vscript.dll\0所有文件(*.*)\0*.*\0\0";
138-
file.lpstrInitialDir = L"";
139-
file.lpstrFile = szBuffer;
140-
file.nMaxFile = sizeof(szBuffer) / sizeof(*szBuffer);
141-
file.nFilterIndex = 0;
142-
file.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
143-
144-
if (GetOpenFileName(&file))
145-
{
146-
int size = WideCharToMultiByte(CP_ACP, 0, file.lpstrFile, -1, NULL, 0, NULL, NULL);
147-
if (size == 0)
148-
{
149-
return std::string();
150-
}
151-
std::string result(size - 1, 0);
152-
WideCharToMultiByte(CP_ACP, 0, file.lpstrFile, -1, &result[0], size, NULL, NULL);
153-
return result;
154-
}
155-
else
156-
{
157-
return std::string();
158-
}
159-
}
160-
161-
static void Pause()
162-
{
163-
std::cout << "Press any key to continue..." << std::flush;
164-
HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
165-
FlushConsoleInputBuffer(h);
166-
WaitForSingleObject(h, INFINITE);
167-
FlushConsoleInputBuffer(h);
168-
}
169-
170156
int main(int argc, const char * const * argv)
171157
{
172158
std::string filePath;
@@ -198,23 +184,21 @@ int main(int argc, const char * const * argv)
198184
{
199185
filePath = "./bin/win64/vscript.dll";
200186
}
201-
187+
#ifdef _WIN32
202188
if (!std::filesystem::exists(filePath))
203189
{
204190
filePath = SelectPEFile();
205191
}
192+
#endif // _WIN32
206193
if (std::filesystem::exists(filePath))
207194
{
208-
std::filesystem::copy(filePath, filePath + ".bak");
209-
210-
PatchFile(filePath, { 0xBE, 0x01, 0x2A, 0x2A, 0x2A, 0x2B, 0xD6, 0x74, 0x2A, 0x3B, 0xD6 }, { 0xBE, 0x02 });
195+
patchFile(filePath, { 0xBE, 0x01, 0x2A, 0x2A, 0x2A, 0x2B, 0xD6, 0x74, 0x2A, 0x3B, 0xD6 }, { 0xBE, 0x02 });
211196
}
212197
else
213198
{
214199
std::cerr << "File doesn't exist" << std::endl;
215200
return 2;
216201
}
217-
218202
}
219203
catch (const std::exception & e)
220204
{

0 commit comments

Comments
 (0)