Свежая книга по реверс-инжинирингу. К сожалению в открытом доступе найти пока не удалось, но все равно полезная инфа для интересующихся темой.
Предисловие 13
Что нового в обновленном издании книги? 14
Введение 15
Кто такие хакеры? 15
Чем мы будем заниматься? 20
Что нам понадобится? 20
Пара слов про Windows 23
Необходимые знания 23
Перед началом 25
Знакомство с базовыми приемами работы хакера 27
Шаг первый. Разминочный 28
Шаг второй. Знакомство с дизассемблером 33
Шаг третий. Хирургический 36
Знакомство с отладчиком 40
Способности отладчиков 40
Герои прошлого 41
Современный инструмент кодокопателя 42
Способ 0. Бряк на оригинальный пароль 43
Поиск адреса 46
Продолжаем осваивать отладчик 51
Перемещаемость EXE 51
Перемещаемость DLL 54
Дополнительные способы нахождения защитных механизмов в чужих программах 61
Способ 1. Прямой поиск введенного пароля в памяти 61
Промежуточные выводы 66
Способ 2. Бряк на функции ввода пароля 66
Взлом приложения с графическим интерфейсом 66
Способ 2.5. Изменяем тип данных 70
На сцене появляется IDA 73
Какую версию IDA Pro мы будем использовать? 74
Что не так с IDA? 80
IDA и зашифрованные программы 82
Данные 84
Расшифровка 87
Создание сегмента 92
Создание клона 96
Итоги 97
Дизассемблер и отладчик в связке 98
Способ №1 99
Способ №2 100
Заключение 103
Идентификация ключевых структур языков высокого уровня 104
Идентификация функций 104
Непосредственный вызов функции 106
Вызов функции по указателю 108
Вызов функции по указателю с комплексным вычислением целевого
адреса 109
«Ручной» вызов функции инструкцией JMP 112
Автоматическая идентификация функций посредством IDA Pro 114
Пролог 114
Эпилог 115
Специальное замечание 118
«Голые» (naked) функции 118
Идентификация встраиваемых (inline) функций 119
Итоги 123
Идентификация стартового кода и виртуальных функций приложений
под Win64 124
Идентификация стартовых функций в оконных приложениях 124
Компилили, компилим и будем компилить! 125
Динамические библиотеки 127
Консольные приложения 129
Идентификация виртуальных функций 130
Искаженные имена 136
Итоги 137
Другие виды виртуальных функций и способы их нахождения 138
Идентификация чисто виртуальных функций 138
Совместное использование виртуальной таблицы несколькими экземплярами класса 141
Копии виртуальных таблиц 143
Связанный список 144
Вызов через шлюз 144
Сложный пример наследования 145
Переименование инструкций 149
Статические объекты 152
Идентификация виртуальных таблиц 155
Второй вариант инициализации массива 157
Заключение 159
Идентификация конструктора и деструктора 160
Объекты в куче 160
Современные микропроцессоры архитектуры x86-64 166
Компьютеры Apple 168
Объекты в автоматической памяти 169
Идентификация конструктора/деструктора в глобальных объектах 170
Виртуальный деструктор 174
Виртуальный конструктор 174
Конструктор раз, конструктор два... 175
Зачем козе баян, или внимание: пустой конструктор 175
Как идентифицировать структуры и объекты в чужой программе 176
Идентификация структур 176
Идентификация объектов 187
Классы и объекты 194
Мой адрес — не дом и не улица! 195
Заключение 196
Распределение динамической памяти и указатели 198
Идентификация указателя this 198
Идентификация операторов new и delete 199
Умные указатели 201
Visual C++ 201
C++Builder 206
Подходы к реализации кучи 210
Microsoft C++ 212
Embarcadero C++ 213
Итоги 215
Идентификация библиотечных функций 216
На помощь вновь приходит IDA 216
Опознание функций 217
Определений библиотек и их версий 222
Заключение 223
Идентификация аргументов функций 225
Соглашения о передаче параметров 225
x64 227
Цели и задачи 228
Определение количества и типа передачи аргументов 228
Embarcadero C++Builder 235
Адресация аргументов в стеке 238
Заключение 242
Определяем «почерк» компилятора по вызовам функций 243
Соглашения о вызовах 243
stdcall 243
WINAPI 247
cdecl 249
PASCAL, WINAPI, CALLBACK 251
PASCAL VS WINAPI 252
Delphi 258
Соглашение о быстрых вызовах – fastcall 265
Идентификация передачи и приема регистров 266
Практическое исследование механизма передачи аргументов через регистры 267
Передача вещественных значений 280
Delphi 284
Соглашение о вызовах функций __thiscall 289
Параметры по умолчанию 293
Техника исследования механизма передачи параметров неизвестным компилятором 294
Идентификация значения, возвращаемого функцией 295
Возврат значения оператором return 296
Определение типа возвращаемого значения 301
Возвращение вещественных значений 315
Возвращение значений inline assembler функциями 317
Возврат значений через аргументы, переданные по ссылке 321
Возврат значений через динамическую память (кучу) 327
Возврат значений через глобальные переменные 330
Возврат значений через флаги процессора 336
Заключение 339
Способы обнаружения переменных разных типов в чужих программах 340
Идентификация локальных стековых переменных 340
Адресация локальных переменных 341
Детали технической реализации 342
Идентификация механизма выделения памяти 343
Инициализация локальных переменных 344
Размещение массивов и структур 345
Выравнивание в стеке 345
FPO — Frame Pointer Omission 353
Идентификация регистровых и временных переменных 355
Временные переменные 362
Создание временных переменных для сохранения значения, возвращенного функцией, и результатов вычисления выражений 367
Область видимости временных переменных 369
Идентификация глобальных переменных 370
Техника восстановления перекрестных ссылок 363
Отслеживание обращений к глобальным переменным контекстным
поиском их смещения в сегменте кода [данных] 370
Отличия констант от указателей или продолжаем разгребать мусор
дальше 372
Косвенная адресация глобальных переменных 373
Статические переменные 377
Заключение 370
Определение операндов 378
Идентификация констант и смещений 378
Определение типа непосредственного операнда 380
Сложные случаи адресации или математические операции с указателями 385
Порядок индексов и указателей 391
Использование LEA для сложения констант 392
Заключение 393
Определение литералов и строк 394
Типы строк 402
Определение типа строк 406
Turbo-инициализация строковых переменных 418
Заключение 423
Нахождение условных операторов в двоичном коде чужой программы для определения курса ее выполнения 424
Идентификация условных операторов if-then-else 424
Типы условий 428
Наглядное представление сложных условий в виде дерева 431
Исследование конкретных реализаций 435
Сравнение вещественных чисел 440
Условные команды булевой установки 446
Идентификация типов с помощью условий 447
Прочие условные команды 447
Команды условного перехода 447
Команды условной пересылки 448
Булевы сравнения 449
Итоги 450
Многообразие условных переходов в машинном коде.
Или вольности компилятора при генерации бинарного кода на основе
условных операторов 451
Идентификация тернарного оператора «(условие) ? do_it : continue» 451
Разбор дополнительных примеров 457
Целочисленные отношения 458
Вещественные отношения 461
Сложные примеры: использование деревьев для разбора вложенных
условий 465
Оптимизация ветвлений 472
Итоги 475
Разбираем самодеятельность компиляторов при трансляции оператора
выбора 476
Нахождение операторов switch-case-break в бинарном коде 476
Отличия switch от оператора case языка Pascal 486
Обрезка (балансировка) длинных деревьев 490
Сложные случаи балансировки или оптимизирующая балансировка 494
Ветвления в case-обработчиках 495
Итоги 496
Определяем циклы в двоичном коде ломаемой программы 498
Циклы с условиями в начале 500
Циклы с условием в конце 501
Циклы со счетчиком 502
Циклы с условием в середине 505
Циклы с множественными условиями выхода 505
Циклы с несколькими счетчиками 506
Идентификация continue 508
Сложные условия 508
Вложенные циклы 509
Заключение 510
Обнаружение циклов разных типов в дизассемблерных листингах программ. Практическое применение 511
Циклы while/do 511
Visual C++ 2022 с отключенной оптимизацией 511
Visual C++ 2022 с включенной оптимизацией 514
C++Builder 10 без оптимизации 516
C++Builder 10 с оптимизацией 519
Delphi 10 521
for 524
Visual C++ 2022 без оптимизации 524
Visual C++ 2022 с применением оптимизации 526
C++Builder 10 528
Циклы с условием в середине 529
Идентификация break 529
Идентификация continue 539
for с несколькими счетчиками 547
Заключение 551
Нахождение математических операторов в дизассемблерных листингах ломаемых программ 552
Идентификация оператора «+» 552
Идентификация оператора «—» 556
Идентификация оператора «/» 559
Оптимизированный вариант 566
C++Builder 568
Идентификация оператора «%» 572
Идентификация оператора «*» 575
C++Builder 581
Комплексные операторы 584
Итоги 587
Способы затруднения анализа программ 588
Приемы против отладчиков 590
Немного истории 590
Как работает отладчик 592
Обработка исключений в реальном и защищенном режимах 596
Как хакеры ломают программы 597
Как защитить свои программы 597
Как противостоять трассировке 598
Как противостоять контрольным точкам останова 607
Итоги 612
Боремся с дизассемблерами и затрудняем реверс программ 613
Приемы против дизассемблеров 613
Самомодифицирующийся код в современных операционных системах 613
Выполнение кода в стеке 618
Самомодифицирующийся код как средство защиты приложений 625
Заключение 630
Заключение 632
Что нового в обновленном издании книги? 14
Введение 15
Кто такие хакеры? 15
Чем мы будем заниматься? 20
Что нам понадобится? 20
Пара слов про Windows 23
Необходимые знания 23
Перед началом 25
Знакомство с базовыми приемами работы хакера 27
Шаг первый. Разминочный 28
Шаг второй. Знакомство с дизассемблером 33
Шаг третий. Хирургический 36
Знакомство с отладчиком 40
Способности отладчиков 40
Герои прошлого 41
Современный инструмент кодокопателя 42
Способ 0. Бряк на оригинальный пароль 43
Поиск адреса 46
Продолжаем осваивать отладчик 51
Перемещаемость EXE 51
Перемещаемость DLL 54
Дополнительные способы нахождения защитных механизмов в чужих программах 61
Способ 1. Прямой поиск введенного пароля в памяти 61
Промежуточные выводы 66
Способ 2. Бряк на функции ввода пароля 66
Взлом приложения с графическим интерфейсом 66
Способ 2.5. Изменяем тип данных 70
На сцене появляется IDA 73
Какую версию IDA Pro мы будем использовать? 74
Что не так с IDA? 80
IDA и зашифрованные программы 82
Данные 84
Расшифровка 87
Создание сегмента 92
Создание клона 96
Итоги 97
Дизассемблер и отладчик в связке 98
Способ №1 99
Способ №2 100
Заключение 103
Идентификация ключевых структур языков высокого уровня 104
Идентификация функций 104
Непосредственный вызов функции 106
Вызов функции по указателю 108
Вызов функции по указателю с комплексным вычислением целевого
адреса 109
«Ручной» вызов функции инструкцией JMP 112
Автоматическая идентификация функций посредством IDA Pro 114
Пролог 114
Эпилог 115
Специальное замечание 118
«Голые» (naked) функции 118
Идентификация встраиваемых (inline) функций 119
Итоги 123
Идентификация стартового кода и виртуальных функций приложений
под Win64 124
Идентификация стартовых функций в оконных приложениях 124
Компилили, компилим и будем компилить! 125
Динамические библиотеки 127
Консольные приложения 129
Идентификация виртуальных функций 130
Искаженные имена 136
Итоги 137
Другие виды виртуальных функций и способы их нахождения 138
Идентификация чисто виртуальных функций 138
Совместное использование виртуальной таблицы несколькими экземплярами класса 141
Копии виртуальных таблиц 143
Связанный список 144
Вызов через шлюз 144
Сложный пример наследования 145
Переименование инструкций 149
Статические объекты 152
Идентификация виртуальных таблиц 155
Второй вариант инициализации массива 157
Заключение 159
Идентификация конструктора и деструктора 160
Объекты в куче 160
Современные микропроцессоры архитектуры x86-64 166
Компьютеры Apple 168
Объекты в автоматической памяти 169
Идентификация конструктора/деструктора в глобальных объектах 170
Виртуальный деструктор 174
Виртуальный конструктор 174
Конструктор раз, конструктор два... 175
Зачем козе баян, или внимание: пустой конструктор 175
Как идентифицировать структуры и объекты в чужой программе 176
Идентификация структур 176
Идентификация объектов 187
Классы и объекты 194
Мой адрес — не дом и не улица! 195
Заключение 196
Распределение динамической памяти и указатели 198
Идентификация указателя this 198
Идентификация операторов new и delete 199
Умные указатели 201
Visual C++ 201
C++Builder 206
Подходы к реализации кучи 210
Microsoft C++ 212
Embarcadero C++ 213
Итоги 215
Идентификация библиотечных функций 216
На помощь вновь приходит IDA 216
Опознание функций 217
Определений библиотек и их версий 222
Заключение 223
Идентификация аргументов функций 225
Соглашения о передаче параметров 225
x64 227
Цели и задачи 228
Определение количества и типа передачи аргументов 228
Embarcadero C++Builder 235
Адресация аргументов в стеке 238
Заключение 242
Определяем «почерк» компилятора по вызовам функций 243
Соглашения о вызовах 243
stdcall 243
WINAPI 247
cdecl 249
PASCAL, WINAPI, CALLBACK 251
PASCAL VS WINAPI 252
Delphi 258
Соглашение о быстрых вызовах – fastcall 265
Идентификация передачи и приема регистров 266
Практическое исследование механизма передачи аргументов через регистры 267
Передача вещественных значений 280
Delphi 284
Соглашение о вызовах функций __thiscall 289
Параметры по умолчанию 293
Техника исследования механизма передачи параметров неизвестным компилятором 294
Идентификация значения, возвращаемого функцией 295
Возврат значения оператором return 296
Определение типа возвращаемого значения 301
Возвращение вещественных значений 315
Возвращение значений inline assembler функциями 317
Возврат значений через аргументы, переданные по ссылке 321
Возврат значений через динамическую память (кучу) 327
Возврат значений через глобальные переменные 330
Возврат значений через флаги процессора 336
Заключение 339
Способы обнаружения переменных разных типов в чужих программах 340
Идентификация локальных стековых переменных 340
Адресация локальных переменных 341
Детали технической реализации 342
Идентификация механизма выделения памяти 343
Инициализация локальных переменных 344
Размещение массивов и структур 345
Выравнивание в стеке 345
FPO — Frame Pointer Omission 353
Идентификация регистровых и временных переменных 355
Временные переменные 362
Создание временных переменных для сохранения значения, возвращенного функцией, и результатов вычисления выражений 367
Область видимости временных переменных 369
Идентификация глобальных переменных 370
Техника восстановления перекрестных ссылок 363
Отслеживание обращений к глобальным переменным контекстным
поиском их смещения в сегменте кода [данных] 370
Отличия констант от указателей или продолжаем разгребать мусор
дальше 372
Косвенная адресация глобальных переменных 373
Статические переменные 377
Заключение 370
Определение операндов 378
Идентификация констант и смещений 378
Определение типа непосредственного операнда 380
Сложные случаи адресации или математические операции с указателями 385
Порядок индексов и указателей 391
Использование LEA для сложения констант 392
Заключение 393
Определение литералов и строк 394
Типы строк 402
Определение типа строк 406
Turbo-инициализация строковых переменных 418
Заключение 423
Нахождение условных операторов в двоичном коде чужой программы для определения курса ее выполнения 424
Идентификация условных операторов if-then-else 424
Типы условий 428
Наглядное представление сложных условий в виде дерева 431
Исследование конкретных реализаций 435
Сравнение вещественных чисел 440
Условные команды булевой установки 446
Идентификация типов с помощью условий 447
Прочие условные команды 447
Команды условного перехода 447
Команды условной пересылки 448
Булевы сравнения 449
Итоги 450
Многообразие условных переходов в машинном коде.
Или вольности компилятора при генерации бинарного кода на основе
условных операторов 451
Идентификация тернарного оператора «(условие) ? do_it : continue» 451
Разбор дополнительных примеров 457
Целочисленные отношения 458
Вещественные отношения 461
Сложные примеры: использование деревьев для разбора вложенных
условий 465
Оптимизация ветвлений 472
Итоги 475
Разбираем самодеятельность компиляторов при трансляции оператора
выбора 476
Нахождение операторов switch-case-break в бинарном коде 476
Отличия switch от оператора case языка Pascal 486
Обрезка (балансировка) длинных деревьев 490
Сложные случаи балансировки или оптимизирующая балансировка 494
Ветвления в case-обработчиках 495
Итоги 496
Определяем циклы в двоичном коде ломаемой программы 498
Циклы с условиями в начале 500
Циклы с условием в конце 501
Циклы со счетчиком 502
Циклы с условием в середине 505
Циклы с множественными условиями выхода 505
Циклы с несколькими счетчиками 506
Идентификация continue 508
Сложные условия 508
Вложенные циклы 509
Заключение 510
Обнаружение циклов разных типов в дизассемблерных листингах программ. Практическое применение 511
Циклы while/do 511
Visual C++ 2022 с отключенной оптимизацией 511
Visual C++ 2022 с включенной оптимизацией 514
C++Builder 10 без оптимизации 516
C++Builder 10 с оптимизацией 519
Delphi 10 521
for 524
Visual C++ 2022 без оптимизации 524
Visual C++ 2022 с применением оптимизации 526
C++Builder 10 528
Циклы с условием в середине 529
Идентификация break 529
Идентификация continue 539
for с несколькими счетчиками 547
Заключение 551
Нахождение математических операторов в дизассемблерных листингах ломаемых программ 552
Идентификация оператора «+» 552
Идентификация оператора «—» 556
Идентификация оператора «/» 559
Оптимизированный вариант 566
C++Builder 568
Идентификация оператора «%» 572
Идентификация оператора «*» 575
C++Builder 581
Комплексные операторы 584
Итоги 587
Способы затруднения анализа программ 588
Приемы против отладчиков 590
Немного истории 590
Как работает отладчик 592
Обработка исключений в реальном и защищенном режимах 596
Как хакеры ломают программы 597
Как защитить свои программы 597
Как противостоять трассировке 598
Как противостоять контрольным точкам останова 607
Итоги 612
Боремся с дизассемблерами и затрудняем реверс программ 613
Приемы против дизассемблеров 613
Самомодифицирующийся код в современных операционных системах 613
Выполнение кода в стеке 618
Самомодифицирующийся код как средство защиты приложений 625
Заключение 630
Заключение 632
Последнее редактирование: