On-line patching в секретах и советах Крис касперски Хакер, номер #093, стр. 093-080-1 Побеждаем упакованный код Off-line patch (он же bit-hack) - это способ взлома кода, когда мы грузим программу в hiew и правим там пару байт. А если программа упакована? тогда у нас два пути — распаковать ее и хакнуть в off-line, или же, дождавшись завершения распаковки, модифицировать память процесса на лету, проворно обходя ловушки типа проверки CRC. Вот об этом способе мы и будем говорить! Снять навороченный упаковщик/протектор чрезвычайно сложно. Качественных распаковщиков нет и приходится маньячить руками, что сильно напрягает. К тому же последние версии протекторов устраивают разные подлянки (крадут часть инструкций, внедряют p-код, эмулируют выполнение условных переходов и т. д.), в результате чего, распакованная программа работает неустойчиво и периодически падает, споткнувшись об очередную не удаленную подлянку. Поиск и удаление защиты отнимает кучу времени и не дает никаких гарантий. Ладно, если это взлом "для себя" — взломанная программа "доводится до ума" в ходе эксплуатации. А если надо что-то срочно взломать для заказчика? Получить дамп, пригодный для дизассемблирования (не для запуска!), относительно несложно и с этой задачей с лихвой справляется PE-TOOLS. Программы с динамической шифровкой (т. е. когда расшифровка идет небольшими порциями и отработавший свое фрагмент тут же зашифровывается вновь) обычно исследуются в отладчике. Возлагая все надежды на навесной протектор, программисты довольно небрежно относятся к "термоядерному реактору" защитного механизма, отвечающего за контроль серийного номера, проверку кол-ва запусков, истечение испытательного строка и т. д. Большинство программ по-прежнему ломаются правкой нескольких байт, только вот расположены эти байты глубоко под слоем упакованного кода. Hiew тут уже непригоден и действовать приходится так: запускаем ломаемый процесс на выполнение, ждем несколько секунд, чтобы все, что нужно, успело распаковаться, а затем модифицируем образ процесса прямо в памяти! Вот это и называется on-line patching'ом. Разумеется, приведенная схема далека от идеала и не учитывает ряда практических реалий, но надо же с чего-то начинать! Простейший on-line patcher Чтение памяти "чужого" процесса осуществляется функций ReadProcessMemory, а запись — WriteProcessMemory. Некоторые лесные сурки пишут, что нужно остановить все потоки процесса перед тем как его патчить через SuspendThread, а после патча возобновить их выполнение функцией ResumeThread. Но это не так! Патчить можно и активный процесс, но только по одной команде за раз, в противном случае возможна такая ситуация, что процесс был прерван планировщиков между хакаемыми командами, а мы их заменили. Причем не факт, что границы новых команд совпадают со старыми (то есть EIP указывает на начало команды, а не в середину), в противном случае поведение ломаемой программы становится непредсказуемым и мы получаем крах, хотя вероятность этого события ничтожна мала. Правильно делать так: остановить все потоки, а затем прочитать контекст каждого из функцией GetThreadContext, убедившись, что ни один из потоков в данный момент времени не выполняет хакаемый код, в противном случае необходимо либо скорректировать EIP, переустановив его на начало хакнутой команды, либо разморозить потоки и подождать еще чуть-чуть. Но, во-первых, это слишком навороченно выходит, а во-вторых, остановка/пробуждение потоков может сильно аукнуться, поскольку далеко не все программисты следят за синхронизацией. |