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

partoftheworlD

Помогаторы
  • Публикаций

    2637
  • Зарегистрирован

  • Посещение

  • Победитель дней

    162

partoftheworlD стал победителем дня 30 октября

partoftheworlD имел наиболее популярный контент!

Репутация

791 Advanced Gamehacker

Информация о partoftheworlD

  • Звание
    инженер проектирующий свалки

Посетители профиля

12104 просмотра профиля
  1. Нет, мне кажется даже глупо спрашивать о таком. Язык лишь инструмент автоматизации, а не супер-пупер инструмент позволяющий взламывать игры. В интернете их полно, тем более для CSS, каждый кому не лень пишет и выкладывает esp. Первый результат в поиске. Не самый разумный подход, если есть желания и дальше продолжать в этой области, надо знать возможности языка, чтобы использовать именно так как тебе нужно. А если это спонтанное желание у которого нет будущего, то проще посмотреть на исходники читов на гитхабе и не тратить впустую время. И с чего у всех какие-то странные временные отрезки по изучению языка в 5 лет, тот же C++ и за 10 лет выучить не удастся, и изучить все его возможности.
  2. 4C 8B 35 это конструкция mov r14, [rip] или mov r14, cs:[0], следующие 4 байта, указывают на смещение относительно этой инструкции.
  3. Не загоняйся по ерунде, на практике все равно будешь использовать 5-10 основных опкодов и инструкций, плюс есть утилиты и онлайн дизассемблеры, где можно посмотреть байты и какие инструкции они представляют для любой архитектуры, если уж так сильно захочется..
  4. Для того чтобы читать табличку, советую использовать интеловские доки (глава 3) там объясняется, что все это значит. Да и вообще интеловские доки, являются некой библией для каждого реверсера, так что, если думаешь серьезно заняться реверсом, советую прочитать их и использовать как справочник.
  5. Разный в зависимости от компиляции, вообще push размером в 1 байт это зарезервированные опкоды от 50 до 57 50 push rax 51 push rcx 52 push rdx 53 push rbx 54 push rsp 55 push rbp 56 push rsi 57 push rdi Ну и табличка:
  6. partoftheworlD

    как задать условие на трассеровку?

    Можешь сохранить трейслог и открыв его в текстовом редакторе искать что нужно
  7. Для этого нужно будет использовать OpenCV на чем-то компилируемом, иначе обработка в 15-20 кадров не подойдет. А для этого надо знать C# Единственный вариант остался, это найти все статические переменные в UnityPlayer в надежде, что какой-нибудь из них является индикатором загрузки уровней/передачи управления гг.
  8. Но, есть же f.lux.
  9. My Friend Pedro, состояние игры нужно, чтобы правильно работал внешний таймер, а именно удалял время между загрузками уровней. ll2cpp Внедрять ничего нельзя, это одна из проблем, игра должна оставаться чистой, только чтение значений из памяти допускается. Делал такую проверку, при переходе между уровнями появляется загрузочный экран, который делится на 3 части, затемнение экрана, загрузка уровня, затемнение экрана. Флаг загрузки уровня нашел, а вот с затемнением такое не работает из-за чего возникает разница во времени, а на 50+ уровнях это очень сильно заметно.(+2-3 минуты)
  10. Начнем с того, что теперь я ненавижу юнити, так, что моей ненавистью можно питать пару крупных городов еще и останется. Проблема возникла с тем, что у игры есть свои значения проверяющие загружена игра или нет, но получить к ним доступ через указатель оказалось невозможным. Перепробовав около 50 разных способов и потратив 1.5 недели, решил залезть в управление памятью юнити, возможно что-то интересно окажется там. Доков и исходников нет и поэтому - Реверсим, реврсим, вертим крутим и делаемся всякие непотребства с памятью и... Бам, оказалось( возможно это чистое совпадение), но UnityPlayer использует статические адреса для "работы" с CFG. CFG/CF это Control Flow Guard - механизм защиты Windows, нацеленный на усложнения процесса эксплуатации бинарных уязвимостей в пользовательских и ядреных приложения. Сам механизма проводит валидацию неявных вызовов, предотвращающая перехват потока исполнения, например переписывая таблицы виртуальных функций. Именно этим мы и воспользуемся, но для начала найдем максимум информации о CFG и его внутреннем устройстве. Итак, когда игра не загружена то, адреса должны указывать на статические данные внутри UnityPlayer.dll, но после загрузки игры выделяться, например в куче. Зная это, можем приступать к поиску. В итоге нашелся статический адрес указывающий на старшую часть указателя, который работает с CFG, когда игра находится в меню или загружается, то старшая часть равна 7FFX( X - значение от 0 до F), но когда игра загружена, то значение меняется на адрес кучи. Что-то типа: Static - 7FFFDEADBEEF Heap - 01EFDEADBEEF Значит берем старшую часть, уменьшаем её для более простого сравнения используя: value & 0xFFF В итоге, получаем значение которое можем засунуть для проверки в автосплитере, если игра не загружена, то значение равно от 4080 до 4095, но если игра загружена, то значение меньше 600, но на всякий случай, я указал: value < 4080 И на этом все, на все про все у меня ушло где-то 2.5-3 недели, просто чтобы узнать состояние игры. В общем, было интересно и стало более понятно как юнити работает с памятью. Желаю всем подобных заданий, это ведь интересней, чем патрончики накручивать.
  11. Это довольно не простая тема, поэтому в идеале необходимо знать ООП, так будет проще воспринимать устройство инвентаря. В фолаче 4-м вроде нет ячеек, это просто список указателей внутри массива. Если игра написана с использованием виртуальных методов, то для поиска предметов и инвентаря в целом можно использовать RTTI, если нет, придется делать все ручками. По RTTI есть статьи на форуме. А поиск руками, тут все достаточно нудно. Для начала инвентарь лучше забить предметами, которые скорее всего имеют общий родительский класс, ну например CWeapon, который содержит разные характеристики, которые CAK47 будет наследовать, но раз родитель общий, то и все остальные оружия, например CM16A3, тоже будут их наследовать. Получается, первый шаг это восстановить, хотя бы пару наследуемых значений например количество патрон и что-нибудь еще, чтобы в дальнейшем, можно было накладывать этот шаблон под разные указатели и проверять, является ли он каким-нибудь оружием. Из утилит подойдет ReClass, но в принципе хватит и CE. Второй шаг, найти указатель на структуру оружия, например базовый адрес 0xDEADBEEF, адрес патрон 0xE0. С этим справится обычный поиск, переводишь его в HEX вставляешь базовый адрес и ищешь. Получишь некое кол-во адресов. Каждый из которых нужно будет проверить, пока не найдешь, то что нужно. Третий шаг, проверяешь с помощью шаблона ближайшие адреса от найденных на втором шаге, чтобы восстановленное смещение в шаблоне на разных указателях указывало на патроны, а так же чтобы количество лежащих рядом указателей было таким же как и количество оружия/предметов в инвентаре. В упрощенном виде цепочка указателей выглядит примерно так: CWorld -> CLevel -> EntityArray[playerID] -> CActor -> CInventory -> CInventorySlot -> SlotArray[slotID] -> CWeapon -> ammo
  12. partoftheworlD

    как задать условие на трассеровку?

    Посчитай на бумажке как формируется eax, смотря по инструкциям, которые были выше.
  13. Небольшая заметка. В общем давняя проблема была со значениями при декомпиляции, а именно они просто не отображались и вывод декомпилятора выглядел вот так: fVar12 = (float)uVar3 * (float)0x2f800000 * FLOAT_142ab7340; а нам нужно: fVar12 = (float)uVar3 * (float)0x2f800000 * 6.28318548; Это возникает только при анализе дампов, когда гидра считает, что адрес по которому лежит значения является динамическим, поэтому брать на себя ответственность за неправильный вывод гидра не хочет и предоставляет нам адрес. Чтобы поправить вывод, необходимо указать, что этот адрес и значение в нем являются константой. Для этого надо перейти по адресу со значением, ПКМ по значению, Data -> Settings -> Mutability = constant. Теперь мне кажется, что гидра еще более сложный инструмент, чем ида.😄
  14. partoftheworlD

    [Writeup] TraineMe by Xipho

    (С сегодняшнего дня все статьи будут идти в 2-х экземплярах, постом в блоге и в pdf версии, чтобы скрины в случае чего не полетели) Прошла уже неделя с момента релиза TraineMe, думаю все кто хотел уже поковыряли программу и уже пора выпустить решебник. Итак начнем. Используемые программы: Ghidra, CE. x64dbg, CherryTree.(Гидра была выбрана по 2-м причинам, первая она мне больше нравится, а вторая декомпилятор с этим файлом у гидры генерировал более понятный код, чем hex-rays.) Задание 1 m_fnEncodeValue(this ,param_2,m_fHealth ,AllocatedMemory,0); m_fnEncodeValue(this ,param_2,m_fAttack ,AllocatedMemory,1); m_fnEncodeValue(this ,param_2,m_fHealth ,AllocatedMemory,2); Здоровье передается в функцию m_fnEncodeValue в hex 1000.f = 0x447A0000 линия 1 и 3 Реверсим...Ставим бряк по адресу TraineMe.0+12E6 в x64dbg: bp TraineMe.0+12e6 Чтобы узнать, что лежит в регистрах и сделать код в функции m_fnEncodeValue более читаемым. После восстановления видим, что существует 2 массива для работы со здоровьем с общей структурой т.е.: PlayersArray[idx * 4] = KeysArray[idx * 4] ^ m_fLoadedHealth Сам ключ вычисляется довольно просто: srand(time64(0)) //Задаем seed для последующей генерации "рандомных" чисел с помощью rand() m_wPseudorandom = rand() KeysArray[idx * 4] = (m_wPseudorandom + (m_wPseudorandom * 0x93275ab3) >> 0x3f) * 0xdeadbeef + 1 Обратите внимание на код, который был показан выше, а точнее на последний аргумент: m_fnEncodeValue(this ,param_2,m_fHealth ,AllocatedMemory,0); m_fnEncodeValue(this ,param_2,m_fAttack ,AllocatedMemory,1); m_fnEncodeValue(this ,param_2,m_fHealth ,AllocatedMemory,2); 0, 1, 2 указывает на используемый индекс в структуре, которая была выделена во время нажатия кнопки “Start Game” 0 - текущее значение 1 - урон (???) 2 - статичное значение, скорее всего максимальное значение здоровья Эти значения могут пригодится для одного из способов создания бессмертия. Немного о выделении памяти, в этом traineme существует 2 основных выделения памяти под структуры на 48 и 24 байт. Все основные вычисления проводятся в той что по-больше. Задание 2 Выполнив первое задание, мы без проблем можем обнаружить единственную нужную инструкцию. После быстрого анализа кода с помощью трассировок, найти участок кода, где здоровье вычитается(а на деле прибавляется.), не составит труда. А теперь вспомним о значение 50, которое мы находили в первом задании. Весь алгоритм вычисления урона: srand(time64(0)) damage_multiplier = rand() / 32767.00000000 //приводим множитель к 1 damage = 50.f * damage_multiplier ^ 0x80000000 // 50.0 * 0.67 = 33.5 ^ 0x80000000 = -33.5 // // Загружается и расшифровывается значение здоровья (health) // health += damage //1000.0 += -33.5 damage = 0 damage_multiplier = 0 Задание 3 Довольно сложное задание, для тех, кто никогда/мало работал с GDI, поэтому ответ есть в этом видео: 01. Основные графики Windows. Изучаем GDI. Pen, Brush, Rectangle. Ну и табличка прилагается. TraineMe.CT RE--TraineMe.pdf
×

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

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