инструкции чекаешь, смотришь как они кодируются, выписываешь байтики, заменяешь операнды(и регистры но это уже сложнее) на вопросики.
вот у тебя есть инструкция скажем "прибавить к регистру 123". у тебя тут сама инструкция это "прибавить к регистру какое-нибудь число", а операнд это и есть то самое число с которым инструкция работает, т.е. 123. вот это 123 может поменяться при апдейте, поэтому ты ищешь инструкцию типа "прибавить к регистру ?", т.е. игноришь 123 или что угодно там может быть. а потом уже когда ты нашел что надо ты эту 123(или другое что там может быть) спокойно можешь забирать если надо из памяти
операнды в некоторых инструментах и так уже выделены но зачастую они очевидны из инструкции. например вот у тебя место
Посмотреть вложение 267809
в х64дбг например операнды выделены пробелом(на скрине там красную полоску нарисовал где пробелы), но они и так очевидны
jne 0x00007FF9DA9D000C - прыжок куда? на сколько-то байт вперед(до 0x00007FF9DA9D000C). тут операнд очевиден это 0xB(прыжок на 11 байт вперед после данной инструкции. это и есть место 0x00007FF9DA9D000C)
mov rax, qword ptr ds:[0x00007FF9DAD314C0] - засунуть в регистр rax что? вот эту хуйню с адреса 0x00007FF9DAD314C0. тут тоже очевиден операнд это b8 14 36 00 это оффсет от места после данной инструкции(00007FF9DA9D0001 + 7 + 003614b8 = 00007FF9DAD314C0)
mov rax, qword ptr ds:[rax+0x8] - засунуть в регистр rax что? вот эту хуйню с + 8. тут операнд и есть эта 8
movss xmm1, dword ptr ds:[rax] - ну тут операнда нет(ну точнее он тут есть, это регистр rax(и еще xmm1), но он прямо в инструкцию закодирован похуй на него в большинстве случаев оно меняться не будет)
xorps xmm7, xmm7 - тут тоже похуй все в инструкцию закодировано напрямую
movss xmm0, dword ptr ds:[0x00007FF9DAC10A74] - засунуть в регистр xmm0 что? вот эту хуйню с адреса 0x00007FF9DAC10A74. тут операнд 59 0A 24 00(опять таки оффсет от места после данной инструкции(00007FF9DA9D0013 + 8 + 00240A59 = 00007FF9DAC10A74))
все эти операнды могут меняться при апдейте, поэтому ты их заменяешь на универсальные символы(т.е. игнорируешь при поиске), получается что тебе нужно найти последовательность инструкций
jne ?
mov rax, qword ptr ds:[?]
mov rax, qword ptr ds:[rax + ?]
movss xmm1, dword ptr ds:[rax]
xorps xmm7, xmm7
movss xmm0, dword ptr ds:[?]
тебе похуй что там в вопросиках главное чтобы внешний вид более менее совпадал
jne ? это в байтах 75 ??
mov rax, qword ptr ds:[?] это в байтах 48 8b 05 ?? ?? ?? ??
mov rax, qword ptr ds:[rax + ?] это в байтах 48 8b 40 ??
movss xmm1, dword ptr ds:[rax] это в байтах f3 0f 10 08
xorps xmm7, xmm7 это в байтах 0f 57 ff
movss xmm0, dword ptr ds:[?] это в байтах f3 0f 10 05 ?? ?? ?? ??
в итоге твоя сига это 75 ?? 48 8b 05 ?? ?? ?? ?? 48 8b 40 ?? f3 0f 10 08 0f 57 ff f3 0f 10 05 ?? ?? ?? ??
вопросики в конце можно убрать т.к. смысла от них нету(вопросик = игнор при поиске. зачем нам игнорить то что на конце если мы можем это лишнее говно просто не искать), т.е. 75 ?? 48 8b 05 ?? ?? ?? ?? 48 8b 40 ?? f3 0f 10 08 0f 57 ff f3 0f 10 05
сига должна быть уникальной, т.е. либо достаточно длинной, либо косвенной(сига на ссылку на место, а не на само место например. например вместо сиги на функцию можно сделать сигу на место где функция вызывается и оттуда уже этот адрес функции забрать)
теперь когда ты нашел в памяти такое место, ты идешь смотреть что же там на месте вопросиков(среди того что тебе интересно), т.е. считываешь память оттуда где надо. например от места где нашел + 5 до места где нашел + 9(т.е. 4 вопросика эти 75 ?? 48 8b 05
?? ?? ?? ??). это будет твой адрес квара(относительно следующей инструкции. т.е. ты берешь ее адрес(это место где нашел + 9) и прибавляешь туда эту хуйню которая в вопросиках)
например я по шаблону
75 ?? 48 8B 05 ?? ?? ?? ?? 48 8B 40 ?? F3 0F 10 08 0F 57 FF F3 0F 10 05 нашел
75 0B 48 8B 05 B8 14 36 00 48 8B 40 08 F3 0F 10 08 0F 57 FF F3 0F 10 05
вот у меня например интересующие меня данные это B8 14 36 00(литтл ендиан. перевернутое в оперативке хранится. если ты литтл ендиан процессором(а он у тебя литтл ендиан) из оперативки считывать будешь то оно само автоматически перевернется(при условии что ты считываешь инструкцией mov dword(ну т.е. работаешь с типом std::int32_t
, т.е. с числом а не с кучей байт) а не по каждому байту отдельно) не надо париться. это я тут вручуню считаю поэтому надо переворачивать). беру адрес где нашел, прибавляю 9(потому что именно там следующая инструкция начинается, на +9) и 003614b8, 00007FF9DA9CFFFF + 9 + 3614b8 = 00007FF9DAD314C0
ну погугли кароче signature scanning, pattern matching и тд на анноунчитс каком-нибудь или где-нибудь еще. считай ты просто ищешь в некой строке некую последовательность(например в строке "привет андрей" ищешь слово "андрей", т.е. то что после пробела, будет у тебя шаблон допустим \s(.*), т.е. самый последний пробел и после него захват всего что дальше) только тут более ограниченный набор, ты ищешь только конкретные байтики либо игноришь любые байтики поштучно. а игноришь ты операнды(т.е. то что при апдейте может поменяться). регистры и сами инструкции как правило не меняются при апдейте(т.к. компилятор которым доту собирают одной и той же версии и настройки никто не меняет и код по сто раз не переписывает)