The main release package of Ashita v3. Contains all the needed files for users to get up and running. Used by the launcher/injector to auto-update as well.
https://ashitaxi.com/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
225 lines
8.2 KiB
225 lines
8.2 KiB
/** |
|
* Ashita - Copyright (c) 2014 - 2016 atom0s [[email protected]] |
|
* |
|
* This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License. |
|
* To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/ or send a letter to |
|
* Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. |
|
* |
|
* By using Ashita, you agree to the above license and its terms. |
|
* |
|
* Attribution - You must give appropriate credit, provide a link to the license and indicate if changes were |
|
* made. You must do so in any reasonable manner, but not in any way that suggests the licensor |
|
* endorses you or your use. |
|
* |
|
* Non-Commercial - You may not use the material (Ashita) for commercial purposes. |
|
* |
|
* No-Derivatives - If you remix, transform, or build upon the material (Ashita), you may not distribute the |
|
* modified material. You are, however, allowed to submit the modified works back to the original |
|
* Ashita project in attempt to have it added to the original project. |
|
* |
|
* You may not apply legal terms or technological measures that legally restrict others |
|
* from doing anything the license permits. |
|
* |
|
* No warranties are given. |
|
*/ |
|
|
|
#ifndef __ASHITA_AS_MEMORY_H_INCLUDED__ |
|
#define __ASHITA_AS_MEMORY_H_INCLUDED__ |
|
|
|
#if defined (_MSC_VER) && (_MSC_VER >= 1020) |
|
#pragma once |
|
#endif |
|
|
|
#include <Windows.h> |
|
#include <sstream> |
|
#include <vector> |
|
|
|
namespace Ashita |
|
{ |
|
class Memory |
|
{ |
|
public: |
|
/** |
|
* Determines the length of data from the given offset valid to scan with. |
|
* |
|
* @param {std::vector} pattern - The pattern to find the length within. |
|
* @param {uintptr_t} offset - The offset to begin iterating at. |
|
* @returns {uintptr_t} The length of data from the given offset. |
|
*/ |
|
static uintptr_t FindLength(const std::vector<std::pair<uint8_t, bool>>& pattern, uintptr_t offset) |
|
{ |
|
// Ensure the offset is within the pattern range.. |
|
if (offset >= pattern.size()) |
|
return 0; |
|
|
|
auto len = 0; |
|
for (size_t x = 0; x < pattern.size(); x++) |
|
{ |
|
// Compare the data for wildcards or null characters.. |
|
if (pattern[x].second == false || |
|
pattern[x].first == 0x00) |
|
break; |
|
|
|
len++; |
|
} |
|
|
|
return len; |
|
} |
|
|
|
/** |
|
* Finds the largest chunk of valid data within the pattern to scan for. |
|
* |
|
* @param {std::vector} pattern - The pattern to find the chunk within. |
|
* @param {int32_t [2]} output - The output data to store the offset and length of data to use. |
|
*/ |
|
static void FindLargestChunk(const std::vector<std::pair<uint8_t, bool>>& pattern, uintptr_t output[2]) |
|
{ |
|
auto offset = (uintptr_t)0; |
|
auto length = (uintptr_t)FindLength(pattern, 0); |
|
auto maxlen = (uintptr_t)pattern.size(); |
|
|
|
// Loop the pattern and find its largest chunk.. |
|
for (auto x = length; x < maxlen; x++) |
|
{ |
|
// Ensure the data is required.. |
|
if (pattern[x].second != true) |
|
continue; |
|
|
|
// Find the length at the given offset.. |
|
auto count = FindLength(pattern, x); |
|
if (count > length) |
|
{ |
|
offset = x; |
|
length = count; |
|
} |
|
|
|
// Step past the current data.. |
|
if (count > 0) |
|
x += count - 1; |
|
} |
|
|
|
// Return the largest offset and length.. |
|
output[0] = offset; |
|
output[1] = length; |
|
} |
|
|
|
/** |
|
* Finds a pattern within the given range of data. |
|
* |
|
* @param {uintptr_t} baseAddress - The address of the data to begin searching within. |
|
* @param {uintptr_t} baseSize - The size of the data to search within. |
|
* @param {const char*} pattern - The pattern to search for. |
|
* @param {uintptr_t} offset - The offset from the found location to add to the pointer. |
|
* @param {uintptr_t} count - The result count to use if the pattern is found more than once. |
|
* @returns {uintptr_t} The address where the pattern was located, 0 otherwise. |
|
*/ |
|
static uintptr_t FindPattern(uintptr_t baseAddress, uintptr_t baseSize, const char* pattern, uintptr_t offset, uintptr_t count) |
|
{ |
|
// Ensure the incoming pattern is properly aligned.. |
|
if (strlen(pattern) % 2 > 0) |
|
return 0; |
|
|
|
// Convert the pattern to a vector of data.. |
|
std::vector<std::pair<uint8_t, bool>> vpattern; |
|
for (size_t x = 0, y = strlen(pattern) / 2; x < y; x++) |
|
{ |
|
// Obtain the current byte.. |
|
std::stringstream stream(std::string(pattern + (x * 2), 2)); |
|
|
|
// Check if this is a wildcard.. |
|
if (stream.str() == "??") |
|
vpattern.push_back(std::make_pair(00, false)); |
|
else |
|
{ |
|
auto byte = strtol(stream.str().c_str(), nullptr, 16); |
|
vpattern.push_back(std::make_pair((uint8_t)byte, true)); |
|
} |
|
} |
|
|
|
// Find the largest chunk of valid data to scan with.. |
|
uintptr_t p[2] = { 0 }; |
|
FindLargestChunk(vpattern, p); |
|
|
|
// Prepare the required variables.. |
|
const auto psize = vpattern.size(); |
|
const auto pstart = p[0]; |
|
const auto plen = (intptr_t)p[1]; |
|
const auto pfirst = vpattern[0].first; |
|
|
|
// Build the wildcard table.. |
|
uint8_t wildcard[UCHAR_MAX + 1] = { 0 }; |
|
for (auto x = pstart; x < pstart + plen; x++) |
|
wildcard[(uint8_t)vpattern[x].first] = 1; |
|
|
|
const auto data = (uint8_t*)baseAddress; |
|
const auto size = (uint32_t)baseSize; |
|
|
|
std::vector<uintptr_t> matches; |
|
|
|
// Loop the data and look for the pattern.. |
|
for (intptr_t x = size - psize; x >= 0; x--) |
|
{ |
|
auto c = data[x]; |
|
auto w = wildcard[c]; |
|
auto k = 0; |
|
|
|
// Step over wildcard characters.. |
|
while (w == 0 && x > (intptr_t)plen) |
|
{ |
|
x -= plen; |
|
w = wildcard[data[x]]; |
|
k = 1; |
|
} |
|
|
|
if (k == 1) |
|
{ |
|
x++; |
|
continue; |
|
} |
|
|
|
// Ensure the first byte matches.. |
|
if (c != pfirst) continue; |
|
|
|
// Validate the size.. |
|
if (x - pstart < 0 || x - pstart + psize > size) |
|
return 0; |
|
|
|
// Walk the pattern and match its data.. |
|
for (size_t y = 0; y < psize; y++) |
|
{ |
|
if (y == pstart || vpattern[y].second != true) |
|
continue; |
|
if (data[x - pstart + y] != vpattern[y].first) |
|
break; |
|
if (y + 1 == psize) |
|
matches.insert(matches.begin(), (uintptr_t)(data + (x - pstart)) + offset); |
|
} |
|
} |
|
|
|
// Handle the count match.. |
|
if (count < matches.size()) |
|
return matches[count]; |
|
return 0; |
|
} |
|
|
|
/** |
|
* Obtains the calling module handle for the given address. |
|
* |
|
* @param {uintptr_t} returnAddress - The address to locate the module owner of. |
|
* @returns {HMODULE} The module handle if found, nullptr otherwise. |
|
*/ |
|
static HMODULE __stdcall GetCallingModule(uintptr_t returnAddress) |
|
{ |
|
if (returnAddress == 0) |
|
return nullptr; |
|
|
|
MEMORY_BASIC_INFORMATION mbi = { 0 }; |
|
if (::VirtualQuery((LPCVOID)returnAddress, &mbi, sizeof(MEMORY_BASIC_INFORMATION)) == sizeof(MEMORY_BASIC_INFORMATION)) |
|
return (HMODULE)mbi.AllocationBase; |
|
|
|
return nullptr; |
|
} |
|
}; |
|
}; // namespace Ashita |
|
|
|
#endif // __ASHITA_AS_MEMORY_H_INCLUDED__
|