helldrg Опубликовано 8 октября, 2016 Поделиться Опубликовано 8 октября, 2016 Здравствуйте! Потихоньку пишу и оптимизирую трейнер и возник вопрос: 1) Корректно ли писать так: DWORD jmpAddress = 0; byte *bytes = new byte[20]; jmpAddress = allocAddress - (baseAddress + offsetAddress[0]) - 5; ... memcpy((void*)&(*(bytes+1)), &jmpAddress, 4); 2) Я сократил количество кода заменив memcpy на такое выражение Цитата (DWORD&)((*(bytes + 1))) = allocAddress - (baseAddress + offsetAddress[0]) - 5; Как с точки зрения "Чистого кода" можно так делать? Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 8 октября, 2016 Поделиться Опубликовано 8 октября, 2016 Не очень понимаю, зачем массив байт делать указателем - он типа и так указатель уже. Я обычно просто 0-й байт присваивал опкоду jmp\call, а остальные 4 (8) - нужному адресу. И все. Скрытый текст void *DetourFunc(BYTE *src, const BYTE *dst, const int len) { BYTE *jmp = (BYTE*)malloc(len + 5); // Выделяем памяти в длину кода len + 5 байт на прыжок DWORD dwback; // Переменная для сохранения флагов защиты VirtualProtect(src, len, PAGE_READWRITE, &dwback); // Ставим защиту нужного участка кода в RW memcpy(jmp, src, len); jmp += len; // Копируем код в выделенную память + занимаем место под прыжок jmp[0] = 0xE9; // 0-й байт - опкод JMP *(DWORD*)(jmp + 1) = (DWORD)(src + len - jmp) - 5; // Записываем в выделенную память код (с 1-го байта, учитывая занятые под прыжок и адрес 5 байт) src[0] = 0xE9; *(DWORD*)(src + 1) = (DWORD)(dst - src) - 5; VirtualProtect(src, len, dwback, &dwback); return (jmp - len); } Ссылка на комментарий Поделиться на другие сайты Поделиться
helldrg Опубликовано 8 октября, 2016 Автор Поделиться Опубликовано 8 октября, 2016 Цитата Не очень понимаю, зачем массив байт делать указателем Я делаю сразу несколько опций чита и все сдвиги и размеры находятся в массивах, и у меня выглядит не так byte *bytes = new byte[20]; а вот так byte *bytes = new byte[jmpBackAddressSize[0]]; если делать не указателем, то так нельзя сделать: byte bytes[jmpBackAddressSize[0]]; Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 8 октября, 2016 Поделиться Опубликовано 8 октября, 2016 В общем, как видишь, в моем примере принцип копирования примерно тот же, так что он явно имеет право на жизнь. Каноничнее, конечно, воспользоваться memcpy, но у нее есть два недостатка - она медленная и она медленная. С другой стороны, обычно подобные операции проводятся один раз в рамках игровой сессии, так что можно и подзабить. В-третьих, маньяков вроде меня, считающих байты кода и такты процессора - крайне мало, так что я бы советовал лишний раз не заморачиваться. Плюс в таком подходе один (помимо скорости) - резко возрастает понимание того, что делаешь. Ссылка на комментарий Поделиться на другие сайты Поделиться
helldrg Опубликовано 8 октября, 2016 Автор Поделиться Опубликовано 8 октября, 2016 keng Сложнооо) Я пользуюсь функциями записи, чтения, выделения и освобождения памяти, из ваших уроков по созданию трейнеров. Вы не успели записать новые по тому как рассчитываются адреса для прыжков, и как эти адреса соединять с кодом, вот и додумываю =) Я даже с комментариями понять не могу эту функцию =((((( Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 8 октября, 2016 Поделиться Опубликовано 8 октября, 2016 @helldrg это ручное создание хуков, аля Microsoft Detours. Имеем на входе два адреса - адрес исходной функции и адрес конечной (хука). Выделяем 5 байт. Копируем начало функции из исходной в выделенные 5 байт. Дальше в 0-й байт выделенной памяти записываем опкод JMP. После этого рассчитываем, на сколько байт нам нужно прыгнуть, а в начало исходной функции записываем такой же массив вида "JMP *выделенные_5_байт*". Итого: Было: Скрытый текст void Blah() { ololo; // Какой-то код return; } Стало: Скрытый текст void Hook() { // Наш хук ololo; // Сохраненный код, который мы затерли прыжком сюда jmp *ret_from_hook* // Выход на место сразу после перехода на хук в Blah() } void Blah() { jmp Hook // Переход на хук *ret_from_hook* // Blah + 5 байт, сюда вернемся return; } Типа того. Нужно просто несколько раз в отладчике посмотреть, чтобы понять, как это работает. Отладчик - твой друг! Я сам дня 2-3 ломал голову, когда писал это все. Ссылка на комментарий Поделиться на другие сайты Поделиться
helldrg Опубликовано 8 октября, 2016 Автор Поделиться Опубликовано 8 октября, 2016 keng Я попытался осмыслить, но, надо в отладчик лезть) Сегодня уж попытаюсь доделать трейнер на с++ и winapi, выложу, и почитаю про с++ и xaml, что бы сделать трейнер в стиле metro и баи) А завтра уже попробую в DetourFunc вникнуть А пока у меня такое представление: для всего этого нужно: 1) адрес, где будет производится переход на нужный нам код (baseAddress + offsetAddress) адрес модуля и смещения в нем 2) размер кода перехода jmpSrcAddressSize - в него входит 5 байт для перехода и нопы, в случае необходимости 3) размер кода для которого мы выделили память jmpDestAddressSize туда входит код и 5 байт для перехода 4) массив байт с кодом который мы записываем new byte[jmpDestAddressSize] там находится код вместе с переходом 5) массив байт для восстановления, в случае если решили отключить опцию, также этот параметр нужен для определения куда нужно возвращаться после выполнения нашего кода Зная это нужно рассчитать адреса для перехода в выделенную память Скрытый текст bytes[0] = '\xe9'; (DWORD&)((*(bytes + 1))) = allocAddress - (baseAddress + offsetAddress[0]) - 5; bytes[5] = '\x90'; bytes[6] = '\x90'; bytes[7] = '\x90'; bytes[8] = '\x90'; bytes[9] = '\x90'; bytes[10] = '\x90'; if (Process.WriteMemory(baseAddress + offsetAddress[0], (LPVOID)bytes, jmpSrcAddressSize[0]) == FALSE) wsprintf(buffer, "Ошибка!"); и надо рассчитать адрес возвращения Скрытый текст jmpAddress = (baseAddress + offsetAddress[0]) - allocAddress - 10 + jmpSrcAddressSize[0]; memcpy((void*)bAddres, &jmpAddress, 4); bytes[0] = '\x83'; bytes[1] = '\x7f'; bytes[2] = '\x08'; bytes[3] = '\x02'; bytes[4] = '\x0f'; bytes[5] = '\x84'; bytes[6] = bAddres[0]; bytes[7] = bAddres[1]; bytes[8] = bAddres[2]; bytes[9] = bAddres[3]; jmpAddress = (baseAddress + offsetAddress[0]) - allocAddress - jmpDestkAddressSize[0] + jmpSrcAddressSize[0]; memcpy((void*)bAddres, &jmpAddress, 4); bytes[10] = '\x89'; bytes[11] = '\x47'; bytes[12] = '\x04'; bytes[13] = '\xc7'; bytes[14] = '\x44'; bytes[15] = '\x24'; bytes[16] = '\x74'; bytes[17] = '\xff'; bytes[18] = '\xff'; bytes[19] = '\xff'; bytes[20] = '\xff'; bytes[21] = '\xe9'; bytes[22] = bAddres[0]; bytes[23] = bAddres[1]; bytes[24] = bAddres[2]; bytes[25] = bAddres[3]; if (Process.WriteMemory(allocAddress, (LPVOID)bytes, jmpDestkAddressSize[0]) == FALSE) wsprintf(buffer, "Ошибка!"); в первой строчке минус 10, потому что в коде находится 2 джампа,1 проверочный, если требования не выполняются то раньше возвращаемся в программу И вот это все применить к DetourFunc, меня просто в ужас бросает, надеюсь отладчик поможет =) Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 8 октября, 2016 Поделиться Опубликовано 8 октября, 2016 Учти, что мой код - в dll, так что я нахожусь в одном адресном пространстве с игрой. Следовательно, мне нужно просто рассчитать два смещения - туда и обратно. И все. Извне делать такие штуки тоже можно, но на пару действий больше понадобится. Ссылка на комментарий Поделиться на другие сайты Поделиться
Dino Опубликовано 8 октября, 2016 Поделиться Опубликовано 8 октября, 2016 *(DWORD*)&bytes[1] = (DWORD)(allocAddress - (baseAddress + offsetAddress[0]) - 5); так лучше 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
gmz Опубликовано 9 октября, 2016 Поделиться Опубликовано 9 октября, 2016 я бы сделал примерно так static BYTE bytes[] = {0xE8,0x00,0x00,0x00,0x00,0x90}; DWORD temp = baseAddress-offsetAddress-5; memcpy(&bytes[1],&temp ,sizeof temp ); компиль всеравно memcpy заменит на 1-2 инстр. 2 Ссылка на комментарий Поделиться на другие сайты Поделиться
helldrg Опубликовано 9 октября, 2016 Автор Поделиться Опубликовано 9 октября, 2016 gmz Ух ты, так намного лучше смотрится спасибо, так и сделаю Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения