Перейти к содержанию

Лидеры

  1. srg91

    srg91

    Администраторы


    • Баллы

      15

    • Постов

      289


  2. Garik66

    Garik66

    Помогаторы


    • Баллы

      6

    • Постов

      5 750


  3. SER[G]ANT

    SER[G]ANT

    Разработчики (+)


    • Баллы

      4

    • Постов

      618


  4. Yuzia

    Yuzia

    Пользователи


    • Баллы

      1

    • Постов

      62


Популярный контент

Показан контент с высокой репутацией 30.04.2017 во всех областях

  1. @Garik66 спросил - как использовать createthread, чтобы он не крашился. Начал отвечать и это слегка вышло за рамки простого ответа в тему, поэтому решил выделить это в отдельный топик. Я не очень хорошо знаю assembler, но попробую описать возможные причины. createthread создает поток и просит его выполнить call с адресом переданной функции. Например в данном случае createthread(my_function) в отдельном потоке выполнит call my_function: И тут вступает в дело стек, да. Вот эта штука (в Memory View вызывается через ПКМ на правом нижнем окне и выборе пункта Full stack): После выполнения call my_function мы попадаем в нашу функцию, а в стек записывается адрес, куда нужно вернуться после выполнения этой функции (my_function). Собственно за возврат куда нужно и отвечает ret. Он берет первую запись из стека и делает jmp в правильное место. Собственно сам адрес возврата виден в стеке на скриншоте - это KERNEL32.BaseThreadInitThunk+24. Без ret ассемблер вывалится за пределы функции и попытается выполнить команду - add [eax],al , хотя для нас это просто участок пустой памяти - 00 00. Ну а так как в EAX ничего приличного нет, то программа выдает ошибку - сорян, не могу записать в данный участок памяти и падает. Поэтому ret обязателен. Из этого вытекает то, что при подходе к ret в последней записи в стеке (адрес в регистр ESP) должна быть с правильным адресом возврата, который был нам передан из call my_function. И основная причина крашей в том, что регистр ESP указывает не на тот адрес при выполнении команды ret. Программа выполняет jmp на неизвестный нам адрес и крешится из-за невозможности выполнить команды, на которые она попала (как с add [eax],al). А что собственно двигает стек и адрес регистра ESP? А двигают стек наши любимые команды push и pop. Собственно, когда мы пытаемся вызывать функцию и передаем параметры через push #100, на самом деле выполняются две команды - sub esp,4 и mov [esp],#100. Первая уменьшает адрес вершины стека на 4 байта, а вторая записывает на вершину стека значение 100. А pop eax сдвигает вершину в другую сторону - делает mov eax, [esp] и дальше сдвигает вершину стека назад add esp,4. Поэтому после того, как мы сдвинули стек с помощью push при передаче параметров в функцию - после её выполнения нужно сдвинуть стек обратно! Собственно следующий пример почти 100% скрешится: Мы ввели новую функцию second_function, которая берет переданный аргумент и записывает его в EAX. Вроде бы всё просто, передали в функцию 100, получили в EAX ответ, а всё равно креш. Почему? А это видно на следующем скриншоте - на вершине стека теперь хранится значение 0x64 (=100): Теперь когда выполнится ret он попытается прыгнуть на адрес 0x00000064, а не на 0x760E8744 как должен был. Как же этого избежать? Есть несколько путей: сохраняем значение регистра esp и возвращаем его перед ret внимательно следим за стеком по мере выполнения нашей функции и к концу программы он сам будет в правильном месте В целом первый способ очень неплох. Мы можем сохранить адрес регистра esp в памяти и вернуть его прямо перед вызовом ret. Например: Но это не совсем assembler-way, поэтому я предпочитаю следить за стеком самостоятельно. Для этого нужно обращать внимание на то, как со стеком работает вызываемая функция. Например, наша функция second_function не следит за стеком. Поэтому если мы делаем push для передачи параметров, то мы так же должны сдвинуть его назад. Это можно сделать через pop указав неиспользуемый регистр или просто добавить к адресу ESP 4 байта (размер адреса в 32 битной системе, в 64-битной - это 8 байт): Собственно таким образом мы двигаем стек за функцией. И в зависимости от количества переданных push - на такое же количество нужно сдвинуть и регистр ESP. Например для 3-х аргументов нужно выполнить 3 pop или добавить к esp 3 * 4 (3 - количество сдвигов, 4 - размер инструкции): В результате мы получим следующий код: Единственное, есть небольшое исключение - функции, которые сами заботятся о стеке, после их вызова не нужно сдвигать регистр esp, просто делаем push и call. Их довольно просто отличить, посмотрим на примере следующего кода: Основное отличие - после call функции которая сама двигает стек не идет ни каких add esp,8 или не выполняются pop: Так же можно обратить внимание на код самой функции, а точнее на ret 8. Параметр 8 указывает программе, что нужно не просто взять адрес из вершины стека и прыгнуть на него, а так же после этого сдвинуть стек на 8 байт, т.е. выполнить ret и add esp,8. Собственно и получается, что add делаем не мы, а сама функция. Вот и получается, что следя за стеком и тем, как вызываемые функции заботятся о стеке - мы не получим крашей в вызове createthread.
    9 баллов
  2. Отлично. И по поводу фильтра продолжу. Что ещё можно выцепить из ЛОГОВ (Хвала Дарк Байту): 1. Инструкция работает только с Гарри: cmp ecx,01 // Это и есть ID Гарри - он первый :) jne Core.dll+6D987 2. Соответственно, уверен на 90 % ID характеристик Гарри будут ещё в каком то регистре при срабатывания, т.е. ПКМ по инструкции, смотрим значения регистров адресов и находим ID здоровья, урона и т.д. и т.л. И пишем на этой инструкции не только GodMod/
    2 балла
  3. Эти инструкции работают со стеком FPU, стеком хранящим и оперирующим значениями с плавающей точкой. В CE его можно увидеть во время дебаггинга - справа в окне регистров будет кнопка со стрелкой ">": Собственно значения в этом окне и будут st(0), st(1) и т.д. Подебажив увидишь как они изменяются. Инструкция fstp dword ptr [eax] которую ты нашел - это запись здоровья из регистра st(0) в Health структуры игрока. Причем можно заметить, что попадает он в st(0) буквально на инструкцию выше - из fld dword ptr [esp+08] - эта инструкция берет значение из стека и пушит его в стек FPU. Из этого следует, что где-то раньше взяли твое текущее здоровье, отняли его и записали в [esp+08]. Можно попытаться найти это место, а можно просто после fstp (в целом я думаю можно даже не делать fstp) сделать push [MAX_HEALTH] и pop [eax]. Увы mov [eax],[MAX_HEALTH] сделать нельзя, поэтому приходится через push. Но ты можешь сделать и fld [MAX_HEALTH] и fstp [eax]. Возможно фильтры будут нужны, но у меня есть сохранение только уже на Волан де Морте, поэтому проверить быстро не могу Быстроскрипт без aobscan и фильтров:
    2 балла
  4. Готово. Да, так даже удобнее, я что-то машинально. Спасибо. Спасибо за отзывы. Если есть ошибки - пишите, я исправлю.
    2 балла
  5. @srg91 ответил Ещё раз ОГРОМНОЕ СПАСИБО!!! Жаль что не могу сразу на + 100 лайкнуть. @MasterGH может ты поставишь?
    2 балла
  6. Как я понял у тебя макс НР тоже во флоат, тогда у тебя первый скрипт не верный и моя поправка тоже. Нужно так: 1 скрипт: И второй:
    1 балл
  7. Написал бы мне личное сообщение, а то только случайно заметил твой текст. Да, действительно в 6.6 есть такая проблема. Только это проблема не в самом русификаторе (просто только он обновляется, а остальные переводы для CE не выше версии 6.3, поэтому в них такого косяка нет), а в доступности перевода тех строк, которых переводить нельзя. Это мой косяк. Перед выходом 6.6 я добавлял в код CE много новых строк для перевода. Лично нашёл 2-3 связанных с этим бага и исправил, а этот пропустил. В 6.7 этой проблемы нет. Насколько я могу судить, она была исправлена 26 января.2017 года.
    1 балл
  8. Смысл есть, только в случае, если всё это обратно, в основной репозиторий, вернётся. Иначе нету смысла иметь несколько репозитариев, один из которых будет устаревшим. А пустит ли DB с таким предложением в свой огород, в этом весь вопрос. ДА и может ему так тупо удобней/привык.
    1 балл
  9. Скорее всего мало место на диске, где хранятся временные файлы поиска.
    1 балл
×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.