1 #include <boost/foreach.hpp>
2 #include <ail/memory.hpp>
3 #include <ail/string.hpp>
6 #include "arguments.hpp"
9 hot_patch_entry::hot_patch_entry(std::string
const & module
, std::string
const & procedure
, void * function
, void * & real_function
, bool enabled
):
13 real_function(real_function
),
18 bool hot_patch_function(std::string
const & module
, std::string
const & function
, void * function_pointer
, void * & old_address
)
20 HMODULE module_handle
= GetModuleHandle(module
.c_str());
21 if(module_handle
== 0)
23 error("Unable to retrieve " + module
+ " module handle");
27 char * address
= reinterpret_cast<char *>(GetProcAddress(module_handle
, function
.c_str()));
30 error("Unable to get procedure address of " + function
+ " in module " + module
);
34 old_address
= address
+ 2;
36 std::string expected_bytes
= "\x8b\xff";
37 std::string procedure_bytes
;
38 procedure_bytes
.assign(address
, expected_bytes
.length());
40 if(procedure_bytes
!= expected_bytes
)
42 error("Unable to patch " + function
+ " in module " + module
+ " - are you running a pre Windows XP SP1 operating system by Microsoft?");
46 unsigned function_address
= reinterpret_cast<unsigned>(function_pointer
) - reinterpret_cast<unsigned>(address
);
47 std::string replacement_string
= ail::little_endian_string(function_address
, 4);
48 std::string replacement
= "\xe9" + replacement_string
+ "\xeb\xf9";
50 char * offset
= address
- 5;
53 if(VirtualProtect(offset
, replacement
.length(), PAGE_EXECUTE_READWRITE
, &old_protection
) == 0)
55 error("Unable to patch " + function
+ " in module " + module
+ " because I was unable to make it writable");
59 std::memcpy(offset
, replacement
.c_str(), replacement
.length());
62 if(VirtualProtect(offset
, replacement
.length(), old_protection
, &unused
) == 0)
64 error("Unable to protect our patch of " + function
+ " in module " + module
);
71 bool patch_function(std::string
const & module
, std::string
const & procedure
, void * & address
, void * custom_function
)
73 std::string name
= module
+ "!" + procedure
;
74 if(!procedure_lookup(module
, procedure
, address
))
77 unsigned const patch_size
= 5 + 5;
78 //unsigned const patch_size = 5;
81 if(!VirtualProtect(address
, patch_size
, PAGE_EXECUTE_READWRITE
, &old_protection
))
83 error("Failed to make the page of " + name
+ " writable");
87 unsigned eip
= reinterpret_cast<unsigned>(address
) + patch_size
;
88 unsigned offset
= reinterpret_cast<unsigned>(custom_function
) - eip
;
90 char * data
= reinterpret_cast<char *>(address
);
103 unsigned * offset_pointer
= reinterpret_cast<unsigned *>(data
+ 6);
107 unsigned * offset_pointer = reinterpret_cast<unsigned *>(data + 1);
110 *offset_pointer
= offset
;
113 if(!VirtualProtect(address
, patch_size
, old_protection
, &unused
))
115 error("Failed to restore the old page permissions for " + name
);
122 //dangerous, this is detected by Warden due to 0xe9 and possibly the 4 address bytes! Use for singleplayer testing only!
124 bool patch_address(unsigned address
, void * target
)
126 std::size_t patch_size
= 5;
128 LPVOID address_pointer
= reinterpret_cast<LPVOID
>(address
);
130 DWORD old_protection
;
131 if(!VirtualProtect(address_pointer
, patch_size
, PAGE_EXECUTE_READWRITE
, &old_protection
))
133 error("Failed to patch address " + ail::hex_string_32(address
));
137 unsigned eip
= address
+ static_cast<unsigned>(patch_size
);
138 *reinterpret_cast<uchar
*>(address
) = 0xe9;
139 *reinterpret_cast<unsigned *>(address
+ 1) = reinterpret_cast<unsigned>(target
) - eip
;
142 if(!VirtualProtect(address_pointer
, patch_size
, old_protection
, &unused
))
144 error("Failed to restore the old page permissions for address " + ail::hex_string_32(address
));