1+ #include < Windows.h>
2+ #include < iomanip>
3+ #include < iostream>
4+ #include < vector>
5+
6+
7+ namespace {
8+ struct AddressAndReg {
9+ DWORD func_rva_start;
10+ DWORD func_rva_end;
11+ const std::vector<BYTE> native_code;
12+ };
13+
14+ // 0~26 VanillaDimensions::toSerializedInt
15+ // 27~39 VanillaDimensions::fromSerializedInt(int)
16+ std::vector<AddressAndReg> data = {
17+ {0x082BA6F , 0x082BA9A , {0x89 , 0xC8 } },
18+ {0x26D1CFB , 0x26D1D1F , {0x89 , 0xC3 } },
19+ {0x10F0CD7 , 0x10F0D00 , {0x89 , 0xC2 } },
20+ {0x10FFF2E , 0x10FFF57 , {0x89 , 0xC2 } },
21+ {0x1107480 , 0x11074A9 , {0x89 , 0xC2 } },
22+ {0x1108365 , 0x110838E , {0x89 , 0xC2 } },
23+ {0x121CE22 , 0x121CE4B , {0x89 , 0xC3 } },
24+ {0x123B4A3 , 0x123B4C6 , {0x89 , 0xC3 } },
25+ {0x124926F , 0x1249298 , {0x89 , 0xC2 } },
26+ {0x1262064 , 0x126208D , {0x89 , 0xC2 } },
27+ {0x1B0D610 , 0x1B0D638 , {0x41 , 0x88 , 0xC9 } },
28+ {0x1B0D8DB , 0x1B0D8FE , {0x88 , 0xC8 } },
29+ {0x1D8677C , 0x1D867A4 , {0x41 , 0x88 , 0xC9 } },
30+ {0x27A6E57 , 0x27A6E82 , {0x89 , 0xC3 } },
31+ {0x2803614 , 0x280363F , {0x89 , 0xC3 } },
32+ {0x2803ABD , 0x2803AE9 , {0x89 , 0xDF } },
33+ {0x280089F , 0x28008C5 , {0x41 , 0x89 , 0xC6 } },
34+ {0x281BE40 , 0x281BE69 , {0x89 , 0xC3 } },
35+ {0x281B5B0 , 0x281B5DB , {0x89 , 0xD3 } },
36+ {0x2B45EA2 , 0x2B45ED0 , {0x41 , 0x89 , 0xC6 } },
37+ {0x2B48EA0 , 0x2B48EC4 , {0x89 , 0xC7 } },
38+ {0x2B502EE , 0x2B50311 , {0x88 , 0xD8 } },
39+ {0x2AA89D3 , 0x2AA89F6 , {0x89 , 0xC3 } },
40+ {0x31078C2 , 0x31078F0 , {0x41 , 0x89 , 0xC3 } },
41+ {0x31D6A15 , 0x31D6A39 , {0x89 , 0xCB } },
42+ {0x31D7A6E , 0x31D7A93 , {0x89 , 0xDF } },
43+ {0x337435D , 0x3374385 , {0x40 , 0x88 , 0xC7 } },
44+ {0x27A9901 , 0x27A9931 , {0x41 , 0x89 , 0xC8 } },
45+ {0x27C09AC , 0x27C09D8 , {0x89 , 0xC8 } },
46+ {0x0C262E0 , 0x0C26330 , {0x89 , 0x8E , 0x3C , 0x00 , 0x00 , 0x00 }},
47+ {0x11F1079 , 0x11F10A5 , {0x89 , 0xCB } },
48+ {0x121C5A7 , 0x121C5D3 , {0x89 , 0xCF } },
49+ {0x16D27E5 , 0x16D281D , {0x89 , 0xC8 } },
50+ {0x281B520 , 0x281B582 , {0x89 , 0xC8 } },
51+ {0x280189D , 0x2801A4C , {0x89 , 0x8E , 0x30 , 0x0B , 0x00 , 0x00 }},
52+ {0x281BE40 , 0x281BE69 , {0x89 , 0xC3 } },
53+ {0x2B45771 , 0x2B4579D , {0x89 , 0xC8 } },
54+ {0x2B490CE , 0x2B490FA , {0x89 , 0xC8 } },
55+ {0x31DDBA4 , 0x31DDBD0 , {0x89 , 0xC8 } },
56+ {0x3376088 , 0x33760B7 , {} }
57+ };
58+
59+ bool PatchFunction (HMODULE hModule, DWORD faddress_start, DWORD faddress_end, const std::vector<BYTE>& native_code) {
60+ LPVOID patchAddress = (LPVOID)((DWORD_PTR)hModule + faddress_start);
61+
62+
63+ // Construct the patch
64+ std::vector<BYTE> patch;
65+
66+ patch.insert (patch.end (), native_code.begin (), native_code.end ());
67+
68+
69+ // jmp faddress_end
70+ // Calculate the relative offset for the jump
71+ DWORD_PTR offset = (DWORD_PTR)hModule + faddress_end
72+ - ((DWORD_PTR)patchAddress + patch.size () + 5 ); // +5 for the size of the jmp instruction
73+
74+ patch.push_back (0xE9 ); // jmp opcode
75+ patch.push_back ((BYTE)(offset & 0xFF ));
76+ patch.push_back ((BYTE)((offset >> 8 ) & 0xFF ));
77+ patch.push_back ((BYTE)((offset >> 16 ) & 0xFF ));
78+ patch.push_back ((BYTE)((offset >> 24 ) & 0xFF ));
79+
80+ HANDLE hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE , GetCurrentProcessId ());
81+
82+ // Write the patch to memory
83+ DWORD oldProtect;
84+ if (!VirtualProtect (patchAddress, patch.size (), PAGE_EXECUTE_READWRITE, &oldProtect)) {
85+ std::cerr << " Failed to change memory protection" << std::endl;
86+ return false ;
87+ }
88+
89+ SIZE_T bytesWritten;
90+ if (!WriteProcessMemory (hProcess, patchAddress, patch.data (), patch.size (), &bytesWritten)
91+ || bytesWritten != patch.size ()) {
92+ std::cerr << " Failed to write to process memory" << std::endl;
93+ CloseHandle (hProcess);
94+ return false ;
95+ }
96+
97+ if (!VirtualProtect (patchAddress, patch.size (), oldProtect, &oldProtect)) {
98+ std::cerr << " Failed to restore memory protection" << std::endl;
99+ return false ; // Though the patch is applied, restoring protection failed.
100+ }
101+
102+ return true ;
103+ }
104+
105+ void printHexBytes (const void * address, size_t numBytes) {
106+ const unsigned char * start = static_cast <const unsigned char *>(address);
107+
108+ for (size_t i = 0 ; i < numBytes; ++i) {
109+ std::cout << std::hex << std::setw (2 ) << std::setfill (' 0' ) << static_cast <int >(start[i]) << " " ;
110+ // Optionally add a newline after every 16 bytes for better readability
111+ if ((i + 1 ) % 16 == 0 ) {
112+ std::cout << std::endl;
113+ }
114+ }
115+ std::cout << std::dec << std::endl; // Reset to decimal output
116+ }
117+
118+ } // namespace
119+
120+
121+ void injectNaticeCode () {
122+ // Calculate the address in the target process
123+ HMODULE hModule = GetModuleHandle (L" bedrock_server_mod.exe" );
124+ if (!hModule) {
125+ std::cerr << " Failed to get module handle for bedrock_server_mod.exe" << std::endl;
126+ return ;
127+ }
128+ for (auto & item : data) {
129+ PatchFunction (hModule, item.func_rva_start , item.func_rva_end , item.native_code );
130+ };
131+ };
0 commit comments