![]() |
Модификация исполняемых Pe-файлов
Модификация исполняемых PE-файлов
I. Intro Наверняка многим когда-то хотелось сделать что-то с чужим кодом. Действительно, есть огромное множество великолепных ICQ-клиентов, но почему-то очень малое их количество умеет отправлять пароли пользователей на почту. И очень хочется это исправить… Разумеется, стараясь не нарушать законы «об авторском праве» - всё исключительно для эстетических целей =) . Но можно приделывать не только деструктивные (для кого-то) функции, но и наоборот, к примеру… А, в общем, не буду разглагольствовать на пустом месте – вы сами придумаете, как это можно применять, а я покажу, как это можно реализовать. PS Заранее предупреждаю – если вам кажется, что мы делаем что-то неправильно или не до конца, то не надо кричать и топать ногами – в этой статье расскажу не только про то, как нужно править PE-файлы, но и рассмотрю способы устранения некоторых нарочно сделанных реальных ошибок. II. Выбираем цель Прежде, чем что-то делать, надо понять, что именно мы хотим сделать. В данном случае, у нас есть неимоверное количество потенциальных вариантов, но сейчас я покажу только, на мой взгляд, самый простой случай. Итак, план действий: 1) Берём exe’шник (я буду использовать дельфийский проект с пустой формой, см. Приложения). 2) Вставляем свой код так, чтобы он выполнялся при запуске. В этой статье, я попробую вставить код, который запрашивает http://ya.ru и сохраняет результат в “a.txt”. |
III. Берём скальпель.
Открываем наш файл (target.exe) в Olly Debugger: http://i001.radikal.ru/0803/24/a6906d027ae9.png У нас есть 2 варианта – так как места в секции кода почти всегда мало (в смысле RawSize – размер в исполняемом файле), а размер в памяти VirtualSize >> RawSize, то в конце кода у нас есть достаточно большой нулевой блок. Мы можем поступить одним из двух способов – записать свой код поверх этих нулей, потом сделать дамп из памяти и получить то, что хотим, а можем заранее создать свою секцию и писать в неё. Что касается имеющейся секции данных, то там, как правило, место всегда есть, но если создавать свою секцию кода, то свою секцию данных создать – уже не проблема. А можно сделать её одновременно и секцией данных, разрешив писать в неё… Ну, в общем, всё по порядку. IV. Подготовка к операции Сейчас я пойду по второму пути (в первый раз, когда я делал такое, я шёл по первому, и… в общем, это было очень муторно. А если вы захотите всё-таки когда-то делать так (например, кажется, что код влезет в RawSize, а он не влезает…), то вот вам мой совет: единственная сработавшая у меня связка – это OllyDump без восстановления импорта + ImpRec). Поэтому закрываем Олю и открываем наш файл в LordPE или PETools: http://i015.radikal.ru/0803/16/d03f0f630919.png И идём в раздел “Sections”: http://i034.radikal.ru/0803/a9/1bb5f2596a11.png Нажимаем правую кнопку на какой-нибудь секции, выбираем “add section header”: http://i009.radikal.ru/0803/29/6b1935fb9c46.png В конце списка появляется новая секция. Щёлкакем на ней правой кнопкой, выбираем “edit section header”: http://i010.radikal.ru/0803/d6/72460b09e54d.png 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: http://i021.radikal.ru/0803/39/87c99465ca63.png То, что нам нужно, уже отмечено – проверяем: 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, станет ясно потом. Теперь заголовок выглядит как-то вот так: http://i027.radikal.ru/0803/78/2a671e2e97b9.png Всё, жмём 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. http://i050.radikal.ru/0803/cd/798a9257deb0.png “ОК”, “Ctrl-S”, “Exit” =) Всё, секция готова, пытаемся запустить файл… Ошибка… http://i009.radikal.ru/0803/d6/e06964af1593.png Но уже «хорошая»! То есть наша программа запускается! Ура-ура! Это валидный PE-файл! |
V. Операция
Снова открываем наш файл в Оле. http://i009.radikal.ru/0803/56/01e717fc8e8b.png Поднимаемся наверх (до конца – на две строчки ;) ) Жмём пробел, находясь на самой первой строчке, и пишем Код:
jmp 44CA98Код:
jmp 460000http://i012.radikal.ru/0803/2b/d94a321120e3.png Запускаем программу (F9). Она работает!!! Закрываем форму, а в Оле – “Ctrl+F2”: перезагружаем (нет, не компьютер =) ) программу. А! Наш прыжок на OEP пропал! Ну ладно, восстановим его (либо вводим заново, либо, так как Оля сохраняет изменения в файле, то открываем Patches: http://i039.radikal.ru/0803/70/ec72be983add.png Выделяем первый и единственный пункт и нажимаем пробел – всё вернулось =) ). А теперь начинаем кодить! Пустой прыжок сразу на OEP, сделанный для проверки, нам уже не нужен, поэтому начинаем писать поверх него. Пытаемся создать файл с помощью CreateFileA: параметры мы, разумеется, не помним, поэтому пишем несколько раз Код:
push 0Код:
call CreateFileAhttp://i017.radikal.ru/0803/72/f3e23c74ee8d.png Вот справа указаны все параметры. Нам нужны только mode, access и filename, остальное для примера не важно. Идём куда-нибудь вниз, например на 461000, и, нажав (Ctrl+E), записываем туда “a.txt” и 0-символ, означающий конец строки: http://i047.radikal.ru/0803/9b/aae2ee233509.png «ОК»… Если у вас вместо “a.txt” появились какие-то жуткие команды, то выделяем их, нажимаем правую кнопку->Analysis->During next analysis…->ASCII text; Ctrl+A. Вот, так лучше: http://i050.radikal.ru/0803/2a/7241b512fdbb.png Запоминаем адрес 461000, и идём наверх, и записываем поверх того что там есть (и, когда не жалко, нажимаем ctrl+A): http://i018.radikal.ru/0803/b7/41b71741f4b2.png Кстати, можно писать выражения типа “push CREATE_ALWAYS” и “push GENERIC_WRITE” – Оля их понимает. Далее по F8 доходим до 46001E. В EAX – число, не равное FFFFFFFF, то есть функция успешно выполнена. В EAX – handle открытого файла. Всё, закрываем его (CloseHandle) -пока на этом остановимся – и прыгаем на OEP: http://i013.radikal.ru/0803/e2/27c7e5712394.png Трассируем по F8 до прыжка: eax = 1. Всё работает. А сейчас, давайте сохраним изменения в exe’шнике. Выделяем всё изменённое (это делается так же, как и в любом текстовом редакторе – с помощью Shift и стрелок или мышки), не забывая про 461000 с “a.txt”. А точно! Мы же не влезем в размер секции в файле! Слишком далеко мы поставили “a.txt”! Ладно, перенесём его на чуть пораньше: на 460600, а там удалим (или аналогично через “Patches”, или выделяем, правая кнопка -> Binary -> Fill with 00’s) и поправим код (выделяем команду push 461000 -> пробел -> push 460600). http://i015.radikal.ru/0803/f0/f20ac238f48f.png Снова выделяем всё изменённое. Далее: либо [правая кнопка -> Copy to executable -> Selection], либо [правая кнопка -> binary -> copy; правая кнопка -> view -> executable file; откроется окошко с выделенным текстом; в нём: правая кнопка -> binary -> paste]. Тем самым мы заменили оригинальные байты в файле на то, что мы написали. Закрываем окошко, Оля нам предлагает сохраниться – сохраняемся, например в target_.exe. Так, у нас в папке уже есть какой-то a.txt. Удаляем его и запускаем программу. Вау! Она запускается, работает, и… даже файл создаётся! |
Казалось бы всё, основная идея ясна, дальше всё просто… Но, увы, нет. Попробуйте запустить файл на другом компьютере – и у вас, скорее всего, ничего не получится. Всё дело в том, что, если вы теперь нажмёте пробел на «call функция из библиотеки», то вы увидите что-то типа “CALL 7C801A24”, то есть абсолютный адрес в библиотеке. А если у нас другая версия kernel32.dll, к примеру? Тогда произойдёт ошибка, и программа работать не будет. Поэтому нам надо грамотно импортировать все используемые нами функции. Для этого существует мехонизм под названием Import Address Table (IAT). Как она работает, я подробно рассказывать не буду, а ограничусь лишь тем, что скажу, что, используя данный механизм, программа (вернее, не совсем программа, ну да ладно) при загрузке в память вычисляет адреса импортируемых функций по их символьным именам. Итак, нам надо описать должным образом нужные нам функции. Конечно, некоторые из них уже описаны, но легче описать их заново, чем искать в других секциях… А если программа ещё и запакована, что, кстати, в случае отсутствия проверки CRC никоим образом не отражается на нашей работе, то там эта оригинальная IAT ещё и спрятана.
Для нашей цели необходимы следующие функции: CreateFileA, WriteFile, CloseHandle из библиотеки kernel32.dll и WSAStartup, connect, send, recv и WSACleanup из WS2_32.dll. Поэтому закрываем Олю и открываем нашу программу в LordPE (PETools тоже умеет редактировать IAT, но у неё с этим иногда, почему-то, возникают недоразумения в виде обрезания имён функций – так WSAStartup может стать WSAStartu и т.п.): http://i022.radikal.ru/0803/84/f2c9ff569362.png Directories -> ImportTable -> … -> правая кнопка -> add import… В появившемся окне добавляем вначале функции из kernel32.dll (вводим название библиотеки, а потом по очереди добавляем нужные функции кнопкой «+»): http://i045.radikal.ru/0803/a4/3557a553aad8.png Закрываем диалог, а теперь вызываем его ещё раз, чтобы добавить функции WinSock’а: http://i011.radikal.ru/0803/b5/df686b6b55ba.png Закрываем диалог, закрываем LordPE, стараясь нажимать Save везде, где можно. Попробуем запустить программу… Она работает. А если бы мы что-нибудь напутали, то появилась бы ошибка вида: «Точка входа в функцию xxx не найдена в библиотеке yyy». Запускаем программу в Olly, после этого снова загружаем её в LordPE и идём в ту же самую таблицу импорта. «Зачем мы его закрывали?»,- спросите вы. А затем, чтобы лорд дал нам возможность работать с файлом. Теперь в его заголовке видим слова “Read only”, то есть теперь мы можем только смотреть на заголовок, но не можем его модифицировать. Смотрим на добавленные нами импорты: http://i036.radikal.ru/0803/e8/1d97e59d405c.png Нам нужен ThunkRVA – по этому адресу будет находиться адрес функции в памяти после загрузки программы (разумеется, +ImageBase). И в данном свете вместо “call CreateFileA" надо писать “call xxxxxxxx”, где по адресу xxxxxxxx находится команда “jmp dword ptr [464035]”, или просто “jmp [464035]”, так как 464035 = ImageBase + ThunkRVA фунуции CreateFileA. Да, действительно, это правда – надо делать call на jmp – это не ошибка и не бред, а на самом деле очень логичная операция, так как, во-первых, к одной функции программа может стучаться несколько раз, а, во-вторых, хочется, чтобы к функциям обращение шло через обычный call. Итак, нам надо записать эти самые прыжки. Запишем их начиная с адреса 460500 (они должны попадать внутрь файла, то есть до 461000). Переключаемся в Олю, переходим на этот адрес (быстрый переход – Ctrl+G), нажимаем пробел и пишем по очереди jmp [464035], jmp [464039], jmp [46403D] – импорт из kernel32.dll, и также с WS2_32.dll – jmp [64082], jmp [64086] и т.д. Кстати, компиляторы часто зачем-то разделяют эти прыжки командой “mov eax, eax" http://i033.radikal.ru/0803/54/317ceeb1cc38.png Теперь идём в начало секции, и изменяем “call CreateFileA” на “call 460500”, аналогично – CloseHandle. (Для этого выделяем команду, жмём пробел и пишем новый код): http://i027.radikal.ru/0803/3e/5729b0428e04.png Заметим, что Olly заменил наши call’ы на логичные названия. Если нажать Ctrl+A, то он точно так же выводит список параметров функции. Можно убедиться, что всё действительно работает, можно сохранить уже имеющиеся изменения уже описанным способом, но я не буду этим заниматься, а постараюсь быстренько доделать всё до победного конца. |
VI. Заканчиваем план
Удалять открытие файла мне лень, поэтому пусть структура кода будет такой: 1) Открываем файл 2) Инициализируем WinSock 3) Подключаемся к Ya.ru (213.180.204.8) 4) Отправляем GET-запрос “GET / HTTP/1.1”, CR, LF, “Host: ya.ru”, CR, LF, CR, LF. 5) Получаем данные 6) Сохраняем в файл 7) Закрываем WinSock 8) Закрываем файл Итак, поехали! 1) Файл уже открыт. Надо либо удалить код с CloseHandle (выделяем -> пр. кнопка -> Binary -> Fill with 00’s), либо писать поверх – закрытый файл нам не нужен. 2) WSAStartup – это у нас «CALL 00460512» Параметры можно посмотреть вышеописанным способом, а можно вспомнить =) http://i013.radikal.ru/0803/18/e21f66d61e11.png Нам нужно найти место, где мы будем хранить WSAData – то, что вернёт WSAStartup (а версию сокетов я поставил 2, т.е. 2.0). WSAData’у можно хранить в виртуальной памяти, не трогая место в файле. Поэтому смело указываем что-нибудь типа 461000 – это адрес внутри нашей секции, в которую мы можем писать данные, но он уже вне секции в файле, иначе говоря, этот адрес находится от начала секции на расстоянии, большем, чем её RawSize. Хотя нам сама структура WSAData как результат WSAStartup и не понадобится, но, если что, то она – там. http://i031.radikal.ru/0803/78/bc08fda4de88.png Можем проверить – трассируем программу (по F8) – и видим, что по адресу 461000 действительно что-то появилось. Кстати, если где-то в вашем коде – ошибка, а вы уже прошли то место, где она возникла, то всегда можно изменить текущую выполняемую инструкцию – выбираем интересующее нас место и нажимаем Ctrl+”*” c NumPad'а (или прав. кнопка -> New Origin Here). 3) Подключаемся к ya.ru. Для этого нам нужно где-то хранить его IP-адрес, и хранить его мы должны, так сказать, в физическом месте файла, то есть он должен «влезть» в RawSize. Запишем его рядом с “a.txt” (в 460606): http://i020.radikal.ru/0803/97/9db9f3d5ac08.png А заодно нажмём Ctrl+A... И в этот прекрасный момент мы понимаем, что забыли подгрузить функции inet_addr, socket и closesocket... Ну, ничего, это поправимо! Сохраняем все уже сделанные в Оле изменения (конечно, только то, что нам нужно сохранить – нам не нужна полученная WSAData, да и места под неё в файле нет!) в файле target_2.exe вышеописанным способом, закрываем Олю, закрываем LordPE и открываем его снова с target_2.exe, на этот раз – с правом на запись. Заходим в таблицу импорта, добавляем ещё одну группу импортов из WS2_32.dll (да, ничего плохого в этом нет) с нужными функциями. http://i001.radikal.ru/0803/c8/ed8bc330de15.png http://i019.radikal.ru/0803/e8/18058c49a1c4.png Наши ThunkRVA – это 640C8, 640CC, 640D0. Закрываем лорда, он нам больше не понадобится, и открываем target_2.exe в Оле. Идём в то место, где мы писали прыжки на внешние функции, и дописываем туда jmp [4640C8] и т.п. http://i022.radikal.ru/0803/37/f9ec3d72fdba.png Для подключения нам нужно заполнить структуру SockAddr (её описание можно без труда найти, я заполню её без лишних комментариев). Хранить её мы будем, к примеру, по адресу 461020. Она занимает 16 байт. Запишем туда адрес сервера (он будет в 461020+4). Идём в начало кода, и вызываем оттуда inet_addr с параметром – адресом строки с IP. http://i015.radikal.ru/0803/1d/0d585c796c48.png Полученное в eax значение сохраняем в 461024: Код:
MOV DWORD PTR DS:[461024], EAXКод:
MOV WORD PTR DS:[ 461020], 2Код:
MOV WORD PTR DS:[ 461022], 5000Код:
PUSH 0 // это - IPPROTO_IPhttp://i015.radikal.ru/0803/12/407db7f9f379.png |
4) Дальше для функции send нам нужно куда-то записать сам GET-запрос. И его рядом с «a.txt» поставим =)
http://i004.radikal.ru/0803/78/94d2d9f24b59.png ОК, Ctrl+A. Считаем размер передаваемых данных (нужен для send): 31d=1Fh. Запоминаем адрес: 460614, и возвращаемся к коду. Пишем: Код:
PUSH 0 //какие-то флаги…Код:
PUSH 0 // опять какие-то флаги…http://i017.radikal.ru/0803/ab/4cafc83309dc.png Трассируем программу до нулей. Если всё прошло без ошибок (а оно должно пройти без ошибок), то тогда, начиная с адреса 462000 должно быть содержание сайта ya.ru. Проверим – да, действительно, там появилось что-то похожее. В eax после выполнения recv лежит размер полученных данных – хорошо бы его где-то запомнить, чтобы потом WriteFile знал, сколько байт писать. А сейчас мы как раз должны его вызвать. Но… нам нужен дескриптор файла, открытого в CreateFileA, а мы его не сохранили… Что же делать? Опять есть 2 варианта (ой, как всё ветвится-то!). Первый – «занопить» тот вызов CreateFileA’а, то есть забить командами nop (выделяем -> пр. кнопка -> Binary -> Fill with NOP’s) и вызвать её уже после всяких операций с сокетами. А я воспользуюсь другим: в коде на месте CALL <JMP.&kernel32.CreateFileA> поставим прыжок куда-нибудь подальше (заменяя его, лучше поставить галочку “Fill with NOP’s”), а там, в этом самом «по-дальше», выполним этот самый call, сохраним результат куда-нибудь и вернёмся обратно. Иначе говоря, схема вот такая: http://i029.radikal.ru/0803/83/e062b7a64b94.png Невольно напрашивается аналогия с вызовом функции. Возьмём в качестве xxxxxx, к примеру, 460200 – с запасом: http://i002.radikal.ru/0803/a0/db2921794f52.png Теперь в 460300 будет лежать дескриптор файла. А наверху: http://i037.radikal.ru/0803/be/1751db446f3e.png Дописываем нашу программу – нам осталось только закрыть сокет, закрыть WinSock, сохранить в файл и закрыть его. Но, для начала, так как мы поменяли что-то в уже пройденных командах, лучше перезапустить программу (Ctrl + F2), чтобы пройти их заново. Но перед этим надо убедиться, что в Олиных настройках разрешено сохранение информации об исследуемых файлах, то есть она сохраняет сделанные патчи (Alt-O -> Security -> Save user data outside any module to main .udd file, вроде, должен быть включён, а, может, Olly всегда сохраняет эти данные – честно говорю, не помню :cool: ). Тогда и после перезапуска программы, и даже после перезапуска самого отладчика, при открытии диалога (или как там это окошко назвать?) Patches (как это делается, я уже показал), отобразится куча всяких изменений. Пробелом восстанавливаем те из них, которые находятся, вернее, должны будут находиться, внутри исполняемого файла, то есть: http://i014.radikal.ru/0803/42/314114d2ead9.png После этого с чистой совестью доходим до конца написанного нами кода по F8 или поставив бряк на последней команде (F2) и пустив программу работать саму (F9). Что там дальше? Дописываем наш код: cохраняем результат recv’а, то есть размер полученных данных, к примеру, в [463000]: MOV [463000], EAX Закрываем сокет: Push [461040] CALL 0046053C А дальше всё понятно, подробно объяснять не буду: Вызываем WSACleanup, вызываем WriteFile, вызываем CloseHandle: http://i028.radikal.ru/0803/5a/f3d4c636fd58.png Ну, как бы, вроде, и всё… Но что-то мы забыли… Что же? Правильно, прыжок на OEP: http://i037.radikal.ru/0803/4e/5c1eaa75f8b0.png Ну вот, a теперь точно всё. Выделяем весь код от начала секции до 460999 включительно (ну, или до последнего использованного адреса), и сохраняем их в файл, например, “fin.exe” (это я тоже уже описал). Можем пустить дальше программу в Оле по F9 или F8, чтобы убедиться в отсутствии ошибок, а можем закрыть уже успевший надоеть нам отладчик и запустить fin.exe. Так и сделаем – закрываем Олю, удаляем старый файл “a.txt”,чтобы не мешал, и запускаем fin.exe. Ждём – всё-таки загрузка страницы не мгновенна… Ура! Всё работает! :cool: |
VII. Заключение
Вот и закончилась эта, м-м-м, «небольшая» статья, на которую у меня ушла неделя. В ней я постарался рассмотреть основы модификации исполняемых файлов, основные ошибки, встречающиеся в этом нелёгком деле и методы их устранения. Надеюсь, эта статья вам в чём-то поможет. Что планируется в будущем? В будущем я постараюсь описать процесс внедрения не только в начало программы, то есть, по сути, некоторую «склейку», но и в некоторые её функции, а также, если будет не лень, то и внедрение в GUI. Greetz to antichat.ru, cracklab.ru и redxak.net, который обязательно когда-нибудь появится, а также спасибо inf’у, за хороший ICQ-клиент и вдохновение ;) Персональные приветы следующим людям, имеющим прямое отношение к реверсингу: XSerg, ProTeuS и 0x0c0de, а также Sealed, Apocalipse, Terrific, Jan3A1r (повторяю - нелепый ник!), и т.д. VIII. Полезные ссылки 1. http://www.insidepro.com/kk/019/019r.shtml - Хорошая статья про PE 2. http://tuts4you.com - тут можно скачать все использованные мной программы. 3. http://redxak.net 4. http://antichat.ru 5. http://cracklab.ru 6. http://wasm.ru 7. http://ollydbg.de IX. Приложения 1. Исходный target.exe - http://webfile.ru/1819431 2. Получившийся fin.exe - http://webfile.ru/1819434 3. Получившийся a.txt - http://webfile.ru/1819436 (с) 73ru5 aka desTiny, 2008. Да, кстати, публикуется исключительно для ознакомительных целей, я не несу никакой ответственности за использование приведённых материалов. |
хорошо статейку оформил, многим будет полезно. только вот парева небыло бы совершенно, если добавить в секцию заранее написаный базонезависимый код. и никакого импорта, никакого-инлайн асма и гемороя...
|
Цитата:
Конечно, можно было бы заметить, что функции можно искать и без внесения импорта, как подробно описано тут(Greetz to TermoSINteZ). Вот небольшой экстракт кода оттуда: Цитата:
|
при4ем здесь склейка, ты забиваешь руками свой скомпиленый код в заранее подготовленную секцию, априоре он никогда не спалится аверем, это просто код, разница только 4то не зависящий от базы, 4то ты и как туда будешь пихать - это второй вопрос. никто не говорит о малварях, а только об удобстве ру4ной модификации бинаря, авери будут алармать и на базонезависымый код в рантайме и на стати4ески скомпиленый с импортом и им пофигу на базу, т.к. код исполнятся будет ОДИН И ТОТ ЖЕ и в том, и в другом слу4ае. вопрос только в том, 4то при зна4ительных объемах кода писать в ольке на инлайн-асме вру4ную неудобно, для этого и придуман кодинг в шеллкод-стиле
|
| Время: 02:00 |