|
|
| Посл.отвђт | Сообщенiе |
|
|
Дата: Июн 13, 2004 17:11:17 > Сначала открываешь жертву на чтение, закидываешь его целиком в память. если жертву вообще удастья открыть, у нас есть права на модификацию, она неожиданно не будет заблокирована кем-то еще и меньше 2 гб, иначе памяти не напассеся... да и тормозно это. лучше заюзать mmap, там размер не оганичен > Далее работаем с заголовком. Выдираем OEP, сохраняем куда-нить. Ищем Object Table - он в хвосте заголовка. после optional size > Баунд импорты для начала можно не проверять - зачем усложнять? дык они часто там есть ;) > В Object Table ищем секцию с наибольшим Physical Offset >- это даст гарантию, что секция последняя. хрен. это проекции секций упорядочены, а сами секции могут быть как угодно перемшены. а если файл содержит оверлей? > Я не встречал файлов, в которых физически секции располагаются иначе, чем виртуально, еще встретишь ;) > Кстати, также необходимо найти секцию с максимальным Virtual RVA, чтобы случайно чего не напортить. а че ее искать. это последняя секция, иначе файл не будет загружен > Далее, расширяем Object Table. и гробим боудны, если еще не первую секцию к известной матери > Phisical Offset = Phisical Offset последней секции + Physical Size оной. ага. только во-первых, физический размер должен быть округлен на величину FA, во-вторых, если физический размер больше виртуального, то он может быть вообще любым, так что твой алгоритм работает лишь в идеализированных условиях > Virtual Size можно оставить нуль - его никто не проверяет, проверяет. если v_sz == 0 берут физический > Он может быть нулем, реальным размером кода без выравнивания или же размеру кода с выравниванием. а по русски - выравнивания не требует. если он больше физического недостающая часть заполняется нулями > Далее. Virtual RVA = Virtual RVA последней секции + Physical Size оной. да ну? и какой же файл так можно заразить? если последней идет секция данных (а часто это так), то вирутальный размер больще физического и брать нужно именно виртуальный, округляя его на OA > Именно Phisical Size, т.к., как я уже говорил, Virtual Size может быть и 0 а вот если виртуальный равен нулю, берем физический и снова округляем на OA >Еще один подводный камень: новый объект может не влезть в заголовок, дык! > поэтому перед добавлением стоит проверить поле Header Size SizeOfHeaders > объект. При этом стоит учесть, что теперь у всех > объектов надо изменить Physical Offset и Virtual RVA. если изменить rva все грохнется. надо менять лищь физические смещения > Осталось только в хвост файла дописать эту секцию. Но > сначала надо проверить, выровнена ли последняя секция. а если там оверлей? > После этого берем указатель на начало файла в памяти и > прибавляем к нему Physical Offset новой секции. и получаем фуфло ;) > Кстати, в заголовке стоит еще изменить поле Image Size. весь вопрос в том как. хинт. оно равно rva + r_sz последней секции, выровненной на 64 кб > Ну вот. Теперь в хвосте файла есть новая секция, и файл должен работать, хрен он будет работать с таких описанием > Теперь наверху в стеке лежит дельта-смещение. Для > обращения виря к данным нужно прибавить смещение к короче, код вируса должен быть полностью перемещаем, чтобы не парится с гребанной дельтой, можно просто выделить память в стеке/куче, округлив ее скажем на 64 кб и адресоваться от начала этого виртуального "сегмента" ;) > Entry Point не исключение. Т.о. OEP хранит адрес для прыжка относительно себя, любимого. относительно начала базового адреса загрузки > не надо. В инициирующем коде можно ограничиться jmp 0, > а при записи тела в жертву надо изменить 0 на нужное > значение. кхм. что за изврты. мало того, что нам надо будет RVA адреса калькулировать, так еще и относительное смещение подсчитывтаь ;) > И последний немаловажный момент. У виря нет секции импорта. ну дык создать ;) > Т.е. для нормальной его работы нужно выполнить одно из взаимоисключающих условий: взаимодопонляющих ;) > 1) заменить все апи-функции своими. (в связи с этим тело виря увеличится до размеров мамонта, а сам вирь будет требовать высочайших привелегий или r0 :))) нихрена не понял, что имелось ввиду > 2) организовать поиск образа Kernel32 и поиск нужных апишек. (имхо, это намного проще п.1 :)))) это точно. искать можно втупую, через SEH и PEB > ЗЗЫ: это все очень образно и на полноту не претендует, > т.к. это все-таки не статья, а скромный пост. да... вот потому вирусы и глючат ;) все-таки я думаю, что моя статья будет полезной, я там перечисляю очень большое кол-во граблей, на которые остальные не обратили внимания ;) |
|
|
Дата: Июн 13, 2004 22:56:36 · Поправил: n0p kaspersky С удовольствием прочитал твой пост. Действительно, мое описание немного далеко от истины. :) Но общую идею оно должно объяснять. Баунды, оверлей и прочие навороты я не учитывал, т.к. дело и без того сложное, а так просто можно в конец запутаться. Мой пост действительно подходит только для идеальных жертв, лучше всего самодельных. :) Для реальных боевых условий этого, естественно, мало. Про замену апишек: я имел в виду написать аналоги свои. Ну там чтение файла, забрасывание в память (научная фантастика, короче) :)) > прибавляем к нему Physical Offset новой секции. и получаем фуфло ;) Да, это меня проглючило.. :)) В общем, жду с нетерпением твою статью, т.к. уровень моих знаний в вирусологии, прямо скажем, невысок. Точнее я рассказал почти все, что знал. :) Надо бы восполнить пробел, я так думаю.. ЗЫ: спасибо за конструктивную критику - буду знать на что обратить внимание, когда возобновлю изучение сией науки. |
|
|
Дата: Июн 14, 2004 01:50:49 > С удовольствием прочитал твой пост. да ладно тебе с удовольстем. нервный я чего-то стал в последнее время. на тебя вот наехал ни за что, а потом пожалел... вот такоя я хреновый мыщъх > Но общую идею оно должно объяснять. ну это да. однако, вирус должен быть предельно корректен, иначе это труба ;( > Баунды, оверлей и прочие навороты я не учитывал, т.к. дело и без того сложное, к сожалению они вездесущи... > Про замену апишек: я имел в виду написать аналоги свои. > Ну там чтение файла, забрасывание в память (научная фантастика, короче) :)) дык, чтобы читать файл нужно как минимум иметь интерфейс с драйвером файловой системы или портами ввода/вывода. ни того, ни другого вынь не дает. > В общем, жду с нетерпением твою статью, вот типа кусочек. тут еще не все выправлено (в частности не сказано, что если виртуальный размер меньше физического физический уже не учитывается), типа зацени. жду отзывов и критики. не обязательно констуктивной. можно просто."мыщтях!" или "фуфло!" таблица секций Четкого определения термина "секция" не существует. Упрощенно говоря, секция – это непрерывная область памяти внутри страничного имиджа со своими атрибутами, независящими от атрибутов остальных секций. Представление секции в памяти не обязательно должно совпадать с ее дисковым образом, который в принципе может вообще отсутствовать (секциям неинициализированных данных нечего делать на диске и потому они представлены исключительно в памяти). Каждая секция управляется "своей" записью в одноименной структуре данных, носящей имя "таблицы секций". Таблица секций начинается сразу же за концом опционального заголовка, размер которого содержится в поле SizeOfOptionalHeader, и представляет собой массив структур IMAGE_SECTION_HEADER, количество задается полем NumberOfSection. Порядок секций может быть любым, но системный загрузчик оптимизирован под следующую последовательность: сначала идет кодовая секция, за ней следует одна или несколько секции инициализированных данных и замыкает строк секция неинициализированных данных. Структура IMAGE_SECTION_HEADER состоит из следующих полей: typedef struct _IMAGE_SECTION_HEADER { BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; union { DWORD PhysicalAddress; DWORD VirtualSize; } Misc; DWORD VirtualAddress; DWORD SizeOfRawData; DWORD PointerToRawData; DWORD PointerToRelocations; DWORD PointerToLinenumbers; WORD NumberOfRelocations; WORD NumberOfLinenumbers; DWORD Characteristics; } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; Листинг 5 прототип структуры IMAGE_SECTION_HEADER Поле Name представляет собой восьми байтовый массив с ASCII-именем секции внутри (именно именем, а не указателем на имя!). Если длина имени меньше восьми байт, остающийся хвост дополняется нулями, если же имя занимает весь массив целиком, завершающий нуль в его конце не ставится (некоторые дизассемблеры не учитывают этого обстоятельства и захватывают примыкающий к массиву мусор). Само по себе имя секции не несет никакого метафизического смысла и было введено в эксплуатацию исключительно из эстетических соображений. Системный загрузчик его игнорирует, хотя некоторые вирусы/протекторы/упаковщики распознают "свои" секции только так и всякое искажение имени валит их наповал. Ходят слухи по поводу того, что библиотека oleaut32.dll, входящая в состав Windows, опознает секцию ресурсов по ее имени, а не по записи в DATA_DIRECTORY. В исходных текстах популярного упаковщика UPX присутствует следующий комментарий: "…after some windoze debugging I found that the name of the sections DOES matter :( .rsrc is used by oleaut32.dll (TYPELIBS) and because of this lame dll, the resource stuff must be the first in the 3rd section - the author of this dll seems to be too idiot to use the data directories... M$ suxx 4 ever! ...even worse: exploder.exe in NiceTry also depends on this to locate version info". Дизассемблирование подтверждает, что библиотека oleaut32.dll действительно содержит внутри себя текстовую строку ".rsrc" и активно ее использует. Да мало ли на свете идиотов, привязывающихся к именем секций? Поэтому без особой нужны имена секций чужого файла лучше не изменять. Поля VirtualAddress и PointerToRawData содержат RVA-адрес начала секции в памяти и ее смещение относительно начала файла соответственно. Виртуальный и физический адреса должены быть выровнены на величину Section Alignment/File Alignment, прописанную в опциональном заголовке, причем виртуальный адрес первой секции должен быть равен ALIGN_UP(SizeOfHeaders, SectionAlignment), в противном случае файл не загрузиться. Физический адрес секции может быть любым, достаточно только, чтобы он был выровнен на величину File Alignment. Поля VirtualSize и SizeOfRawData содержат виртуальную и физическую длину секции соответственно. Вот тут-то и начинается самое интересное! Если виртуальный размер больше физического, то при загрузке секции в память ее хвост заполняется нулями, при этом наличие атрибута инициализированных/неинициализированных данных совершенно необязательно. Если физический размер больше виртуального, то… единственное, что можно сказать с уверенностью, такой файл будет нормально загружен в память. Как? А вот это уже зависит от реализации! Начнем с того, что нулевой виртуальный размер предписывает загрузчику отталкиваться от физического размера секции, предварительно округлив его на величину Section Alignment и заполнив хвост нулями. Все промежуточные состояния неопределенны – загрузчик может считать: а) ровно Virtual Size байт; б) ALIGN_UP(Virtual Size, File Alignment) байт; в) ALIGN_UP(Virtual Size, Phys Sector Size) байт. Вообще-то, все пункты кроме первого – грубые ошибки реализации, но и… суровая реальность бытия вместе с тем, поэтому таких ситуаций лучше всего избегать. Физический размер должен быть выровнен на величину File Alignment, выравнивать виртуальный размер необязательно (загрузчик выравнивает его автоматически). Однако, и это правило не обходится без исключений: если физический размер меньше или равен виртуальному, то и его выравнивать необязательно, правда, смысла в этом немного, поскольку начало следующей секции в файле по любому должно быть выровнено на величину File Align. Виртуальный адрес следующей секции обязательно должен быть равен виртуальному адресу предыдущей секции плюс ее размер, выровненный на величину Section Alignment. Секции не могут ни перекрываться, ни образовывать виртуальные дыры. На физические адреса секций таких ограничений не наложено и они могут быть разбросаны по файлу в живописном беспорядке. Впрочем, увлекаться разбрасыванием право же не стоит – не ровен час системный загрузчик запутается и откажет файлу в загрузке, если еще не выпадет в синий экран. Кстати, на счет синих экранов. Напомним читателю, что если Section Alignment < 1000h, а физический размер секции вылетает за пределы файла, W2K SP3 (и вероятно все остальные представители линейки NT) выбрасывают синий экран и системе наступает кранты. Поле Characteristics определяет атрибуты доступа к секции и особенности ее загрузки. Имеются три атрибута как будто бы определяющих содержимое секции как код, инициализированные и неинициализированные данные (IMAGE_SCN_CNT_CODE/20h, IMAGE_SCN_CNT_INITIALIZED_DATA/40h, IMAGE_SCN_CNT_UNINITIALIZED_DATA/80h соответственно). Однако, системный загрузчик игнорирует их значение и потому опираться на них ни в коем случае нельзя. Теоретически секция неинициализированных данных при отсутствии прочих атрибутов не должна грузиться с диска, но… ведь грузиться! Некоторые вирусы/упаковщики/протекторы определяют кодовую секцию по наличную атрибута IMAGE_SCN_CNT_CODE. Что ж! Не такое уж и плохое решение, только будьте готовы к тому, что этого атрибута не окажется ни у одной из секции (что встречается достаточно часто), либо же он будет присвоен секции данных (что встречается пореже, но все-таки встречается). Другая триада атрибутов описывает права доступа ко всем страницам секции, назначаемым системным загрузчиков по умолчанию (будучи загруженным, файл может свободно манипулировать ими вызывая API-функцию VirtualProtectEx). В настоящее время определено три атрибута: исполнения, чтения и записи (IMAGE_SCN_MEM_EXECUTE/20000000h, IMAGE_SCN_MEM_READ/40000000h, IMAGE_SCN_MEM_WRITE/80000000h). На платформе Intel атрибуты чтения/исполнения полностью эквивалентны и соответствуют аппаратному атрибуту доступности (accessible) страницы. Атрибут записи обрабатывается вполне естественным образом. Следовательно, отличить секцию кода от секции данных в общем случае невозможно и приходится действовать исподтишка, объявляя секцией кода ту, в которую указывает точка входа. Два других интересных атрибута это – IMAGE_SCN_MEM_DISCARDABLE/2000000h (после загрузки файла секция может быть уничтожена в памяти) и IMAGE_SCN_MEM_SHARED/10000000h (секция является совместно используемой). Атрибут IMAGE_SCN_MEM_DISCARDABLE обычно присваивается секциям, содержащим вспомогательные структуры данных такие как, например, таблица перемещаемых элементов, необходимые лишь на этапе загрузки файла и впоследствии никем не используемые. А раз так – зачем они будут жрать память? Фатальная ошибка подавляющего большинства вирусов состоит в том, что внедрясь в последнею секцию файла (коей как раз DISCARDABLE-секция обычно и оказывается), они не проверяют ее атрибутов не "выкупают" права на память. Операционная система в любой момент может выгрузить оккупированные ими страницы и тогда инфицированный процесс рухнет, выдавая хорошо известное всем сообщение о критической ошибке приложения. Атрибут IMAGE_SCN_MEM_SHARED намного менее безобиден, но тоже с характером и помещать сюда исполняемый код категорически не рекомендуется. Во-первых, в любой момент он может быть затер посторонним процессом и тогда зараженное приложение опять-таки рухнет, а, во-вторых, Windows 9x насильно перегоняет SHARED-секции в верхнюю половину адресного пространства и действительный адрес загрузки уже не будет соответствовать виртуальному адресу секции (правда, полностью перемещаемый код в таких условиях вполне сможет работать). Остальные атрибуты либо неинтересны, либо имеют отношение только к объективным coff-файлам (не PE) и потому здесь не рассматриваются. Это в частности относится к атрибутам из семейства IMAGE_SCN_ALIGN_хBYTES, индивидуально настраивающим кратность выравнивая каждой секции. Для объективных файлов это, быть и может и так, но системный загрузчик эти атрибуты в упор игнорирует. Поля PointerToRelocations/NumberOfRelocations (указатель на таблицу перемещаемых элементов и количество элементов в этой таблице соответственно) имеют отношение только к объективным файлам, а исполняемые файлы и динамические библиотеки управляют своими перемещаемыми элементами через одноименную запись в DATA_DIRECTORY, поэтому эти поля могут содержать любые значения. Некоторые вирусы/упаковщики/проекторы помечают таким образом свои файлы, чтобы их не обрабатывать дважды. Способ глупый и ненадежный (задумайтесь, что произойдет с файлом после его упаковки любым посторонним упаковщиком?). Поля PointerToLinenumbers/NumberOfLinenumbers (указатели на таблицу номеров строк и количество элементов в этой таблице соответственно) ранее использовались для хранения отладочной информации, связывающей номера строк исходной программы с адресами откомпилированного файла. В настоящее время используется только в объективных файлах, а в исполняемых файлах отладочная информация хранится совсем в другом месте и в другом формате. Ниже приведен код, сканирующий таблицу секций и выводящий извлеченную информацию на терминал. #define xopt_sz(p) (*((WORD*)(p + 0x14 /* size of optional header */))) #define pSectionTable(p) ((BYTE*) (xopt_sz(p) + 0x18 /*sizeofimageheafer*/ + p)) #define pFirstSection(p) (pSectionTable(p)) #define pLastSection(p) (pSectionTable(p) + (xNumOfSec(p) - 1) * 40) Листинг 6 макросы, возвращающие указатели на IMAGE_SECTION_HEADER первой и последней секции файла a = xNumOfSec(p); pNextSection = pFirstSection(p); while(a--) { printf( "Name: %s\n"\ "\tVirtualSize : %04Xh RVA\n"\ "\tVirtualAddress : %04Xh RVA\n"\ "\tSizeOfRawData : %04Xh RVA\n"\ "\tPointerToRawData : %04Xh RVA\n"\ "\tPointerToRelocations : %04Xh RVA\n"\ "\tPointerToLinenumbers : %04Xh RVA\n"\ "\tNumberOfRelocations : %04Xh RVA\n"\ "\tNumberOfLinenumbers : %04Xh RVA\n\n", pNextSection, pNextSection[0x8], pNextSection[0xC], pNextSection[0x10], pNextSection[0x14], pNextSection[0x18], pNextSection[0x1C], pNextSection[0x20], pNextSection[0x14]); pNextSection+=40; // следующий элемент Section Table } Листинг 7 прогулка по таблице секций с выводом ее содержимого на терминал |
|
|
Дата: Июн 14, 2004 18:29:56 kaspersky Круто! В общем и целом очень доступно написано. Только вот целевая аудитория какова? Если расчет на людей, которые хоть что-то о PE знают, то все ок. А иначе новичкам будет сложновато понять кое-какие моменты, хотя если заставить их прочитать статью Виздома или другую литературу по PE, то должны понять. |
|
|
Дата: Июн 24, 2004 17:02:40 Крис: А когда примерно статью то ждать? Не не ..торопится не нада ..пусть лучше подольше но качественнее ..но всеж :) ? |
|
|
Дата: Июн 24, 2004 20:27:48 первая часть статьи уже вышла в сусадмине, вторая либо выйдет целиком в июльском номере, либо будет разбита на две, т.к. занимает 100 кб, ну и первая статья не меньше ;) |
|
|
Дата: Июн 25, 2004 11:08:20 Сусадмин это журнал такой,(сорри за серость)и где тогда его можно приобрести ? А может можно где нибудь электронную версию глянуть(одним глазком) ? |
|
|
Дата: Июн 25, 2004 16:17:50 subscribe |
|
|
Дата: Июн 25, 2004 18:26:30 Ну тогда и я что нибудь скажу Ж)) И мои слова как наезд воспринимать не нужно Ж)) Все способы инфекции которые ты описываешь уже были реализованы. Да же про НТФС потоки это по моему 29а номер 5. Так же некоторые ты не предусмотрел у зомби есть много прикольных реализаций. Так же возможна инфекция, чисто в хэдэр это делал уже Murkry но он забивал хардкорные адреса вынь апи функций. Разве что про оверлеи я не слышал, но это не значит что этог нет. А если мне не веришь посмотри на странице авп там помоему даже поиск есть. |
|
|
Дата: Июн 25, 2004 18:45:57#define xopt_sz(p) (*((WORD*)(p + 0x14 /* size of optional header */))) #define pSectionTable(p) ((BYTE*) (xopt_sz(p) + 0x18 /*sizeofimageheafer*/ + p)) #define pFirstSection(p) (pSectionTable(p)) #define pLastSection(p) (pSectionTable(p) + (xNumOfSec(p) - 1) * 40) Мелочно, ну да ничего с собой поделать не могу. Это у меня после исходников Перла появилось. Убил бы. МАКРОСЫ обозначаются ЗАГЛАВНЫМИ БУКВАМИ. Коль уж используются эти идиотские #define, значит, их надо обозначать ЗАГЛАВНЫМИ, чтобы было ясно с самого начала - что к чему. |
|
|
Дата: Июн 26, 2004 06:59:41 > Все способы инфекции которые ты описываешь уже были реализованы. просьба перечислить названия вирусов, где это реализовано. мне правда очень интересно. а то надоело однообразие. в основном все лезут в хвост. немногие в заголовок. единицы в регулярные последовательности внутри файла. а вот что развинуть секции и внедриться в конец/начало секции текст? > Да же про НТФС потоки это по моему 29а номер 5. угу. я ж не говорю, что я первый это придумал. к тому же у этого способа _столько_ проблем, что он абсолютно неработоспособен на практике и приведен в статье лишь из соображений полноты коллекции. кстати, у 29a NTFS потоки это все-таки _потоки_ (stream), а не атрибуты, так что нечего некоторым упрекать меня в незнании терминологии ;) > Так же некоторые ты не предусмотрел я рассматривал типовые способы, а их разновидностей существует бесчисленное количество >Так же возможна инфекция, чисто в хэдэр ну я описывал и хедер, и хэдер с развижкой как виртуальных, так и физических адресов, в том числе перемещение хедера в конец файла, тогда весь PE будет хэдером, причем это вполне легальный прием ;) > но он забивал хардкорные адреса вынь апи функций. про апи я рассматривал поиск: прямой поиск, поиск с раскрутой SEH и через PEB. > Разве что про оверлеи я не слышал, но это не значит что этог нет. ну оверлеи это просто ;) ставим в середине файла кусок, который никуда не проецируется, корректируем физические адреса секуций, виртуальные не трогаем, ибо оверлей страничный имидж не затрагивает. ну вот и все собственно ;) > А если мне не веришь посмотри на странице авп > там помоему даже поиск есть. так. еще раз. я не претендую на то, что я первый все это придумал, но утвержаю, что я первый описал это в том объеме и в том стиле в каком это написано, причем это не компиляция чужих источников, а собственные мыли, идеи, опыт полученный дизассемблированием вирей. граница между идеями и опытом настолько тонка, что я даже не пытаюсь проводить ее т.к. информация принадлежит миру, а не мне ;) |
|
|
Дата: Июн 26, 2004 07:01:54 > Сусадмин это журнал такой,(сорри за серость)и где тогда его можно приобрести ? да, жрунал. вот его сайт www.samag.ru > А может можно где нибудь электронную версию глянуть(одним глазком) ? пока она не будет опубликована в журнале - увы. имею желание, но не имею права (как морального, так и юридического). но если это все-таки интересно, могу сформировать lite-версию и выложить на сайт. |
|
|
Дата: Июн 26, 2004 07:04:27 > МАКРОСЫ обозначаются ЗАГЛАВНЫМИ БУКВАМИ. вопрос стиля ;) макросы - это в текущей версии. по нормальному их нужно делать функциями с проверками аргументов. > Коль уж используются эти идиотские #define, значит, их вопрос стиля. у define много проблем, но в програмах из полусотни строк ими можно пренебречь. а для более серьезных вещей приведенные примеры все равно не годятся. |
|
|
Дата: Июн 26, 2004 18:07:16 Ну и на счёт идей инфекции я делал эпо пятнами для передачи управления на тело, а тебе порекоменую всё тело сделать физической мутацией(порубить на куски и связать джампами как это делал векна) и раскидать его по кодовой секции и это будет супер инфекция пятнами. |
|
|
Дата: Июн 27, 2004 08:50:26 конечно интересно :), ты же культовый автор, пример для подражания, очень радует что такая личность обогатила своими постами восмфорум (каждый пост кладезь информации), у меня на компе доки отсортированы по темам, но есть отдельно папочка для культовых авторов (richter, stroustrup, russinovich, petzold etc) и в ней фолдер kaspersky, в него я складываю всё что удастся найти по сабжу |
|
Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.097 |