Created
December 20, 2012 09:51
-
-
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).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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