Skip to content

Instantly share code, notes, and snippets.

@tec27
Created December 20, 2012 09:51
Show Gist options
  • Save tec27/4344251 to your computer and use it in GitHub Desktop.
Save tec27/4344251 to your computer and use it in GitHub Desktop.
Function for efficiently replacing a single occurrence of a set of magic bytes within a larger sequence of bytes (in my case, replacing these within function code to be injected into another process).
// Replaces a single instance of magic_bytes in the function_bytes
// Works most efficiently if magic_bytes contains no repeated values, but works fine either way
// replacement_bytes is assumed to be the same length as magic_bytes here
bool ReplaceMagicBytes(byte* function_bytes, const size_t function_length, const byte* magic_bytes,
const size_t magic_bytes_length, const byte* replacement_bytes) {
// first we construct a table that says how much to jump ahead/back by for any given byte value
int jump_by[256];
// for most values (assuming magic_bytes contains few characters), we can skip
// MB_length bytes
for(int i = 0; i < 256; i++) {
jump_by[i] = magic_bytes_length;
}
// then for each byte value in MB we can calculate the actual skip value (may be negative)
// except for the first byte value, which will make more sense later
for(size_t i = 1; i < magic_bytes_length; i++) {
jump_by[magic_bytes[i]] = -i;
}
byte magic_start = magic_bytes[0];
bool matching = false;
size_t matching_index = 0;
// Loop through the bytes, skipping as many as possible on each iteration.
// Whenever we find the starting byte of magic_bytes, we go into a matching mode
// and move forward 1-by-1 until we either match all the magic_bytes, or find a
// non-matching byte. If the latter, we go back into skip-mode, otherwise we
// replace and return.
for(size_t i = 0; i < function_length;) {
if(!matching) {
if(function_bytes[i] != magic_start) {
// not the start of our magic bytes, jump by as much as possible
int jump = jump_by[function_bytes[i]];
if(i+jump < 0) jump = magic_bytes_length;
i += jump;
}
else {
// may have found the first magic byte
matching = true;
matching_index = 1;
i += 1;
}
}
else {
if(matching_index == magic_bytes_length) {
// we found a match! do the replacement and return
for(size_t j = i - magic_bytes_length, x = 0; j < i; j++, x++) {
function_bytes[j] = replacement_bytes[x];
}
return true;
}
else if(function_bytes[i] != magic_bytes[matching_index]) {
// this is not our magic bytes location
matching = false;
i += magic_bytes_length;
}
else {
// still a match, continue on
matching_index += 1;
i += 1;
}
}
}
return false;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment