Сохранение значения регистра на С++
-
Привет, подскажите, каким способом вы сохраняете значение регистра используя С++?
Речь идет о 64 битной архитектуре.
К регистрам (RCX, RDX, R8, R9), которые связаны со входными параметрами функции, получить доступ просто. Но как быть с другими регистрам, R10, R11?Не использовать же приостановку потока со взятием его контекста.
К примеру есть игровая функция из пяти строк. В этой функции нужно получить значение R13 и сделать свои дела.
Искать ли место выше где R13 принимает нужное значение? Но там могут быть такие глубокие дебри. -
@Antonshka Используй ассемблерные вставки, а после получения нужных данных вызывай оригинальную функцию.
-
@__fastcall Насколько мне известно, Visual Studio не поддерживает вставки для x64.
Вообще, у меня есть одна идея, но я хотел узнать и другие варианты.
-
@Antonshka В интернете где-то видел про обход ограничений.
-
@__fastcall Я видел как люди пишут AsmJit библиотеки. Но такой вариант не вариант. Мне не хочется подключать стороннюю библиотеку. Я даже не стал использовать ни MinHook ни PolyHook ни им подобные.
Хотя нет, я все же посмотрел как работает MinHook и написал нечто похожее. Чисто для себя. Без авто-дизасемблера. С ручным заданием офсетов и длин.
std::unordered_map<std::string, std::unique_ptr<Hook::Signature>> Camera::createSignatures() { std::unordered_map<std::string, std::unique_ptr<Signature>>signatures; Hook::Instruction instruction{}; instruction.instructionsCount = 1; instruction.totalByteLength = 5; instruction.byteLengthPerInstruction.push_back(5); signatures.emplace("FreezeFOV", std::make_unique<Signature>("FreezeFOV", "F3 0F 11 4B 14 41 B6 01", instruction, 0)); instruction.instructionsCount = 2; instruction.totalByteLength = 6; instruction.byteLengthPerInstruction.clear(); instruction.byteLengthPerInstruction.push_back(2); instruction.byteLengthPerInstruction.push_back(4); signatures.emplace("CheckPlayerInCar", std::make_unique<Signature>("CheckPlayerInCar", "40 53 48 83 EC 30 80 79 60 00", instruction, 0)); return signatures; }
Моя идея состоит в том, чтобы написать класс генерирующий байты регистровых инструкций. Например в signatures записывается нужный регистр и имя поля класса (переменной) с ним связанным. Далее этот класс в месте трамплина, сразу за ним, запишет эти байты регистровых инструкций. Занес в signatures три регистра и три поля, значит будет три инструкции, сразу за трамплином. А после третьей инструкции, будет jmp на трамплин, из которого будет jmp на hook функцию, из которой будет потом jmp на трамплин до jmp на hook, выполниться пролог, и наконец jmp обратно в оригинальный код плюс оффсет на пролог.
-
@Antonshka Не, там проще это обходят. Если погуглить, то найдёшь.
-
@__fastcall Нашел
Проверил, работает нормально. Спасибо за совет.