One of the more modern methods of approaching an application for modifications and relocation of specific functions, data, pointers, etc. is through signature scanning. Rather then using raw offsets or addresses, signature scanning allows you to locate data through known instructions of a function that make use of that data. I wont get into the specifics of signature scanning in this topic though for those that do not understand it.
Read this full tutorial on my personal site here:
Code:
http://atom0s.com/forums/viewtopic.php?f=5&t=4
Here is the important code that is used with this:
PHP Code:
/**
* @brief Scans a given chunk of data for the given pattern and mask.
*
* @param data The data to scan within for the given pattern.
* @param baseAddress The base address of where the scan data is from.
* @param lpPattern The pattern to scan for.
* @param pszMask The mask to compare against for wildcards.
* @param offset The offset to add to the pointer.
* @param resultUsage The result offset to use when locating signatures that match multiple functions.
*
* @return Pointer of the pattern found, 0 otherwise.
*/
static DWORD __stdcall FindPattern(std::vector<unsigned char> data, unsigned int baseAddress, const unsigned char* lpPattern, const char* pszMask, int offset, int resultUsage)
{
// Build vectored pattern..
std::vector<std::pair<unsigned char, bool>> pattern;
for (size_t x = 0; x < strlen(pszMask); x++)
pattern.push_back(std::make_pair(lpPattern[x], pszMask[x] == 'x'));
// The result count for multiple results..
auto resultCount = 0;
auto scanStart = data.begin();
while (true)
{
// Search for the pattern..
auto ret = std::search(scanStart, data.end(), pattern.begin(), pattern.end(),
[&](unsigned char curr, std::pair<unsigned char, bool> currPattern)
{
return (!currPattern.second) || curr == currPattern.first;
});
// Did we find a match..
if (ret != data.end())
{
// If we hit the usage count, return the result..
if (resultCount == resultUsage || resultUsage == 0)
return (std::distance(data.begin(), ret) + baseAddress) + offset;
// Increment the found count and scan again..
++resultCount;
scanStart = ++ret;
}
else
break;
}
return 0;
}
Example Usage With Futures (Async)
PHP Code:
std::map<std::string, std::shared_future<unsigned long>> m_Signatures;
this->m_Signatures["sigName"] = std::async(std::launch::async, &FindPattern, std::ref(rawdata), sizeOfData, signature, mask, offset, resultUsage);
// Ensure all futures are completed..
std::for_each(this->m_Signatures.begin(), this->m_Signatures.end(), [](std::pair<std::string, std::shared_future<unsigned long>> s)
{
// Obtain the current future status..
auto status = std::future_status::timeout;
do
{
status = s.second.wait_for(std::chrono::milliseconds(5));
} while (status != std::future_status::ready);
// Obtain the status value..
auto pointer = s.second.get();
//
// At this point you can check if pointer is valid and handle
// any invalid pointers as needed. Perhaps you want the application
// to fail to load if any pointers are invalid etc.
//
});
/**
* @brief Returns a pointers current value.
*
* @param name The name of the pointer to obtain.
*
* @return The value of the pointer, 0 if not found.
*/
unsigned long Memory::GetPointer(const std::string& name) const
{
auto pointer = this->m_Signatures.find(name);
if (pointer == this->m_Signatures.end())
return 0;
return pointer->second.get();
}
Sorry for linking to my own site, the post limit is 10k chars which is too short to paste the whole post from my site. I included the important code above from the post though to have content here too.