Pavel3333 1,147 Posted May 13, 2018 (edited) Клиент с XFW Native грузится в 3 раза дольше, чем без него. По предложению @GPCracker, это связано с регулярным поиском сигнатур функций питона в памяти. Есть предложение от @GPCracker- Цитата а нельзя ли эти точки закешировать в пределах неизменности контрольной суммы exe клиента и значимых dll? То есть при каждом патче пройтись по exe'шнику танков и записать смещения функций питона. Мне кажется, это очень разумно и будет намного быстрее по времени загрузки, чем каждый раз сканировать память клиента на предмет нахождения сигнатур функций. Edited October 1, 2019 by Mixaill 2 Share this post Link to post Short link Share on other sites
GPCracker 2,088 #430465 Posted May 13, 2018 18 minutes ago, Pavel3333 said: То есть при каждом патче пройтись по exe'шнику танков и записать смещения функций питона. Мне кажется, это очень разумно и будет намного быстрее по времени загрузки, чем каждый раз сканировать память клиента на предмет нахождения сигнатур функций. Ну по факту, сканировать все же придется (использовать старые координаты вслепую не самая лучшая идея), однако запоминая смещения функций, которые были при предыдущем запуске клиента игры, и используя их в качестве места для предварительного поиска, можно весьма серьезно ускорить запуск клиента. 1 Share this post Link to post Short link Share on other sites
Pavel3333 1,147 #430466 Posted May 13, 2018 (edited) 6 минут назад, GPCracker сказал: вслепую Не совсем вслепую, при совпадении хэшей exe'шника танков не совпадает - пофиг, пляшем от регулярного поиска сигнатур по шаблону @sirmax, @Mixaill? -------------- Надо найти точку входа главной питоновской функции и уже от нее считать смещения. Или, если они все располагаются непоследовательно, как предложил @GPCracker, запоминать смещения в памяти танков и искать сигну по шаблону уже в области этих смещений Edited May 13, 2018 by Pavel3333 Share this post Link to post Short link Share on other sites
GPCracker 2,088 #430468 Posted May 13, 2018 (edited) 21 minutes ago, Pavel3333 said: Не совсем вслепую, при совпадении хэшей exe'шника танков Существование таких вещей как таблицы для CheatEngine и ArtMoney явно подтверждает тот факт, что адреса большинства переменных в памяти не изменяются между запусками приложения, однако в случае с динамическим распределением памяти это может не прокатить. Вариант с предварительным поиском по старому адресу просто элементарно надежнее (исключает ошибочное определение адреса) и скорее всего даже быстрее (не нужно тратить время на вычисление контрольных сумм и определять что от чего зависит, а поиск-проверка в известных координатах выполняется достаточно быстро). В любом случае, кастуем сюда @Mixaill, ибо именно он стоит за коммитами в тот самый репозиторий. 21 minutes ago, Pavel3333 said: Надо найти точку входа главной питоновской функции и уже от нее считать смещения. Если большая часть смещений между запусками не изменяются, нет смысла заморачиваться с ограничением зоны поиска, временем первого запуска можно пренебречь, при условии что он будет занимать не более чем занимает сейчас. Edited May 13, 2018 by GPCracker 1 Share this post Link to post Short link Share on other sites
StranikS_Scan 4,123 #430474 Posted May 13, 2018 Прежде чем чего-то советовать хотелось бы мельком увидеть как реализован поиск сигнатур сейчас. Share this post Link to post Short link Share on other sites
GPCracker 2,088 #430475 Posted May 13, 2018 1 minute ago, StranikS_Scan said: Прежде чем чего-то советовать хотелось бы мельком увидеть как реализован поиск сигнатур сейчас. А в чем собственно проблема? Репозиторий лежит здесь. Share this post Link to post Short link Share on other sites
StranikS_Scan 4,123 #430476 Posted May 13, 2018 6 минут назад, GPCracker сказал: Существование таких вещей как таблицы для CheatEngine и ArtMoney явно подтверждает тот факт, что адреса большинства переменных в памяти не изменяются между запусками приложения, однако в случае с динамическим распределением памяти это может не прокатить. Мы же ведем речь об импортах функций, экспорт которых просто убрали из exe. Там должны быть статичные адреса в пределах одной сборки exe. Только что, GPCracker сказал: А в чем собственно проблема? Репозиторий лежит здесь. Ну конечно проблем нет. Это как сослаться на библиотеку. Она же стоит и книг там много и вход свободный. Я не разбираюсь что там к чему. Мне нужен конкретный модуль. Share this post Link to post Short link Share on other sites
Pavel3333 1,147 #430478 Posted May 13, 2018 @GPCracker @StranikS_Scan вот на примере helper.c: DWORD WOTPYTHON_FindFunction(DWORD startpos, DWORD endpos, DWORD* curpos, const char* pattern, const char* mask) { DWORD pos; for (pos=(*curpos); pos < endpos; pos++) { if (WOTPYTHON_DataCompare((char*)pos, pattern, mask)) { (*curpos) = pos; return pos; } } for (pos = startpos; pos < (*curpos); pos++) { if (WOTPYTHON_DataCompare((char*)pos, pattern, mask)) { (*curpos) = pos; return pos; } } (*curpos) = startpos; return 0; } То есть задается область памяти (от void* startpos до void* endpos), в ней байт за байтом считываются блоки данных и сверяются по маске. fix_winapi.c FARPROC WINAPI GetProcAddress_libpython(HMODULE hModule, LPCSTR lpProcName) { FARPROC ret = NULL; if(hModule==PyWin_DLLhModule) { ret = (FARPROC)WOTPYTHON_GetRealAddress(lpProcName); if (ret != NULL) { return ret; } } return GetProcAddress_real(hModule, lpProcName); } Ищется адрес python27.lib. Не нашли - ищем во ВСЕЙ памяти процесса. Share this post Link to post Short link Share on other sites
GPCracker 2,088 #430480 Posted May 13, 2018 5 minutes ago, StranikS_Scan said: Мы же ведем речь об импортах функций, экспорт которых просто убрали из exe. Там должны быть статичные адреса в пределах одной сборки exe. Я конечно разбираюсь во всем этом как белый медведь в апельсинах, но факт остается фактом - если адреса функций в памяти не изменяются в таких вполне себе ощутимых пределах как сборка exe (или микропатч), вычислять их при каждом запуске методом полного расчета без проверки актуальности вычисленных ранее (без предварительной проверки в "старом" месте) как минимум неправильно. А поскольку я не привык считать маловероятные события невозможными, и на этом основании их исключать из рассмотрения, я все же не торопился бы принимать за аксиому неизменность адресов, тем более что проверка по конкретному адресу (вместо утверждения этого адреса вслепую) не будет оказывать сколь бы то ни было заметного влияния на скорость загрузки, и притом такой подход исключает как необходимость анализа контрольных сумм (или других критериев наличия изменений в файлах игры), так и возможность получения неверных данных, да и в случае изменяющегося адреса будет вполне корректно работать (пусть и медленно, но в такой ситуации другого варианта все равно нет). Share this post Link to post Short link Share on other sites
Mixaill 1,700 #430481 Posted May 13, 2018 (edited) При сборке порядок поиска выставляется так, чтобы был только один проход по памяти Worldoftanks.exe. Но так как порядок линковки объектных файлов в MSVC недетерминирован, то довольно часто случается так, что этот порядок сбивается, и при поиске каждой сигнатуры приходится пролопачивать значительно большую часть памяти процесса. Как костыль можно просто перебилдить библиотеку, но более верное решение, как тут уже отметили, сейвить результаты в какой-то файловый кэш. Edited May 13, 2018 by Mixaill Share this post Link to post Short link Share on other sites
GPCracker 2,088 #430482 Posted May 13, 2018 51 minutes ago, StranikS_Scan said: Мне нужен конкретный модуль. Ну так бы сразу и сказал. А то я уж было подумал, что ты не знаешь про репозиторий :) Share this post Link to post Short link Share on other sites
Pavel3333 1,147 #430483 Posted May 13, 2018 (edited) @Mixaill кэш можно реализовать, как понимаю, в виде "сигнатура - позиция, по которой она последний раз была найдена". При дальнейших запусках клиента смотреть в кэш. Если не совпало - надо делать по старинке. Edited May 13, 2018 by Pavel3333 Share this post Link to post Short link Share on other sites
GPCracker 2,088 #430484 Posted May 13, 2018 1 minute ago, Pavel3333 said: При дальнейших запусках клиента смотреть в кэш. Если не совпало - надо делать по старинке. Собственно, так я и предложил делать в самом начале темы. Использовать предыдущие координаты в качестве места для предварительной проверки. 3 minutes ago, Pavel3333 said: кэш можно реализовать, как понимаю, в виде "сигнатура - позиция, по которой она последний раз была найдена". Навряд ли тут можно предположить что-то другое... Но в любом случае файл с кэшем должен лежать в известном месте, чтобы при необходимости его можно было удалить и тем самым инициировать поиск по стандартному алгоритму. 1 Share this post Link to post Short link Share on other sites
StranikS_Scan 4,123 #430485 Posted May 13, 2018 (edited) Только что, Pavel3333 сказал: @Mixaill кэш можно реализовать, как понимаю, в виде "сигнатура - позиция, по которой она найдена". Поддержу. Нужен однократный алгоритм поиска всех адресов исключительно с однократным прогоном по памяти. С кэшированием адресов в файл. В результате с одной стороны все последующие загрузки клиента будут без задержек, а с другой стороны - время поиска будет меньше сейчас, так как действительно многократный повторный поиск с нуля - жрёт кучу времени. Я код посмотрел, я не специалист, но мне кажется если если сравниваться будут не Char, а Byte, то будет быстрее. Но я в си не рублю совсем потому могу ошибаться. И еще меня удивило что там чуть ли не на каждый байт памяти игры вызывается функция сравнения с сигнатурой WOTPYTHON_DataCompare . Это если 50 Мб скажем игры, то 50 млн вызовов. Edited May 13, 2018 by StranikS_Scan Share this post Link to post Short link Share on other sites
Pavel3333 1,147 #430486 Posted May 13, 2018 2 минуты назад, StranikS_Scan сказал: но мне кажется если если сравниваться будут не Char, а Byte, то будет быстрее а что char, что byte - это одно и то же. Самый быстрый тип байта в Си - это ЕМНИП unsigned char, он же uint8_t Share this post Link to post Short link Share on other sites
StranikS_Scan 4,123 #430488 Posted May 13, 2018 Только что, Pavel3333 сказал: а что char, что byte - это одно и то же. Самый быстрый тип байта в Си - это ЕМНИП unsigned char, он же uint8_t Там нет разницы, там типа char = uint8_t прописано? Share this post Link to post Short link Share on other sites
Mixaill 1,700 #430490 Posted May 13, 2018 5 минут назад, StranikS_Scan сказал: Это если 50 Мб скажем игры, то 50 млн вызовов. Должно быть заинлайнено при текущих флагах, но ок, пропишу тут явно. Share this post Link to post Short link Share on other sites
GPCracker 2,088 #430491 Posted May 13, 2018 1 minute ago, Pavel3333 said: а что char, что byte - это одно и то же. Самый быстрый тип байта в Си - это ЕМНИП unsigned char, он же uint8_t Это все проверяется компиляцией и просмотром кода на ассемблере. И что-то мне подсказывает, что "скорость типа" определяется исключительно его размером (ну сложностью самой операции над этим типом). Share this post Link to post Short link Share on other sites
Pavel3333 1,147 #430492 Posted May 13, 2018 @StranikS_Scan нет, наоборот, прописано следующее: typedef unsigned char uint8_t; самый быстрый тип байта - uint_fast8_t, тоже определен как unsigned char: typedef unsigned char uint_fast8_t; Подробнее - в stdint.h (хедер, использующий его - iostream) Share this post Link to post Short link Share on other sites
StranikS_Scan 4,123 #430493 Posted May 13, 2018 Только что, GPCracker сказал: Это все проверяется компиляцией и просмотром кода на ассемблере. И что-то мне подсказывает, что "скорость типа" определяется исключительно его размером (ну сложностью самой операции над этим типом). Вот. Я когда изучал и потом сам писал и юзал поисковики адресов в ОЗУ, правда на ОbPas, придерживался двух принципов - ни каких промежуточных вызовов и обращений куда-то там в теле цикла - только простейщие операции и типы, а это Byte = 0...255, считанный блок из ОЗУ как массив числе, и сигнатура предварительно переведена в массив чисел Share this post Link to post Short link Share on other sites