Показать сообщение отдельно

  #2  
Старый 22.03.2008, 12:44
desTiny
Reservists Of Antichat - Level 6
Регистрация: 04.02.2007
Сообщений: 1,152
Провел на форуме:
3008839

Репутация: 1502


По умолчанию

III. Берём скальпель.
Открываем наш файл (target.exe) в Olly Debugger:

У нас есть 2 варианта – так как места в секции кода почти всегда мало (в смысле RawSize – размер в исполняемом файле), а размер в памяти VirtualSize >> RawSize, то в конце кода у нас есть достаточно большой нулевой блок. Мы можем поступить одним из двух способов – записать свой код поверх этих нулей, потом сделать дамп из памяти и получить то, что хотим, а можем заранее создать свою секцию и писать в неё. Что касается имеющейся секции данных, то там, как правило, место всегда есть, но если создавать свою секцию кода, то свою секцию данных создать – уже не проблема. А можно сделать её одновременно и секцией данных, разрешив писать в неё… Ну, в общем, всё по порядку.


IV. Подготовка к операции
Сейчас я пойду по второму пути (в первый раз, когда я делал такое, я шёл по первому, и… в общем, это было очень муторно. А если вы захотите всё-таки когда-то делать так (например, кажется, что код влезет в RawSize, а он не влезает…), то вот вам мой совет: единственная сработавшая у меня связка – это OllyDump без восстановления импорта + ImpRec). Поэтому закрываем Олю и открываем наш файл в LordPE или PETools:


И идём в раздел “Sections”:


Нажимаем правую кнопку на какой-нибудь секции, выбираем “add section header”:


В конце списка появляется новая секция. Щёлкакем на ней правой кнопкой, выбираем “edit section header”:


1) В поле Name вводим какое-нибудь название секции, например “.code”;
2) Поля VirtualAddress и RawOffset не трогаем – это адреса секции в памяти и в файле соответственно, вычисляются как
VirtualAddress = ((VirtualAddress(предыдущая секция) + VirtualSize(предыдущая секция) – 1) div VirtualAlign) + 1) * VirtualAlign;
(Перевожу на русский – наименьшее число, делящееся на VirtualAlign и большее последнего адреса предыдущей секции =) )

Аналогично считается и RawOffset, только вместо VirtualAlign стоит FileAlign.
Их LordPE считает автоматом, и менять их не надо! Кстати, VirtualAlign и FileAlign – тоже поля заголовка PE, должны быть степенями двойки, притом VirtualAlign >= 1000h; FileAlign >= 200h. Подробнее это рассмотрено в [1].
3) VirtualSize и RawSize.
А вот это нам и надо! RawSize – размер секции в файле, а VirtualSize – в памяти. Поставим RawSize = 1000 (ну уж 4кб нам под код хватит), а VirtualSize = 4000 (то есть 16кб). «Зачем нам такой большой VirtualSize?»,- спросите вы,- «Ведь если код в файле занимает 4кб, то зачем под него выделять целых 16?» Просто я хочу писать сюда не только код, но и данные, чтобы не создавать новую секцию, хоть это и не трудно. А помните, что мы хотели сделать? Да-да, загрузить http://ya.ru. А сколько он там весит? Не помню, но в 16кб, думаю, влезет…
4) А теперь редактируем флаги секции. Нажимаем на кнопочку рядом с полем Flags:


То, что нам нужно, уже отмечено – проверяем:

a) Что-то в секции можно выполнять
b) Из неё можно читать
c) В неё можно писать
d) В ней есть код
e) В ней есть инициализированные данные
f) В ней есть неинициализированные данные

А если что-то здесь лишнее, то это не смертельно.
Всё, жмём «ОК», потом, запомнив VirtualOffset и RawOffset нашей секции (60000h и 59E00h), закрываем окошко с секциями. Зачем запоминать VirtualOffset? Всё дело в том, что есть в PE-заголовке такое поле, как BaseOfCode. В нём сейчас записан VirtualOffset (всё, надоело, дальше вместо VirtualOffset буду говорить просто RVA) секции «CODE», и Olly, которым мы будем пользоваться дальше, не будет анализировать (потом об этом) нашу секцию, считая её чем-то странным и не понимая, как туда попала программа. А ориентируется он как раз на BaseOfCode. Значит, пишем в BaseOfCode запомненный RVA. А RawOffset… В общем, скоро поймёте. Теперь смотрим на важный параметр EntryPoint (Если не ясно, что это, то вам в [1]), запоминаем его значение (4CA98), и пишем туда (RVA нашей секции + 5). Почему +5, станет ясно потом. Теперь заголовок выглядит как-то вот так:


Всё, жмём Save, жмём “OK”, и пытаемся запустить файл. А он не запускается… И правильно! Секцию-то мы объявили, а записать – не записали! Открываем target.exe во FlexHex и идём в самый конец файла. Теперь ищем то место, где будет новая секция. А она начинается с запомненного нами RawOffset (назовём его Raw = 59E00). Если последний существующий байт файла имеет адрес, отличный от (Raw-1), то забиваем нулями всё место от конца файла до этого числа (Щёлкаем после последнего байта в файле, далее Edit->Insert Zero Block; Block Size = Raw - адрес последнего байта - 1. Калькулятор вам в помощь =)). Но нам этого делать не надо – у нас и так всё хорошо.
Теперь щёлкаем на пустой квадратик по адресу Raw, далее Edit->Insert Zero Block; Block Size = размер нашей секции, RawSize, то есть 1000h.


“ОК”, “Ctrl-S”, “Exit” =)
Всё, секция готова, пытаемся запустить файл… Ошибка…

Но уже «хорошая»! То есть наша программа запускается! Ура-ура! Это валидный PE-файл!
__________________
Bedankt euch dafür bei euch selbst.

H_2(S^3/((z1, z2)~(exp(2pi*i/p)z1, exp(2pi*q*i/p)z2)))=Z/pZ