herm1t LIVE!ng room [entries|archive|friends|userinfo]
herm1t

[ website | twilight corner in the herm1t's cave ]
[ userinfo | ljr userinfo ]
[ archive | journal archive ]

Будни извращенцев-3 [Oct. 12th, 2009|04:37 pm]
[Tags|, ]

Объявил обработчик сигнала, как (int, struct sigcontext*), два часа из-за звёздочки промучался, потом ещё gcc решил поморочить голову, он же, сука умный, он же решил, что раз структура передается по значению, то всё что модифицирует её содержимое можно просто дропнуть. Добавил volatile...
Link2 comments|Leave a comment

Угадайка [Jul. 10th, 2009|02:22 pm]
[Tags|, , ]

Написал небольшое продолжение этого проекта. "Linker" таскает за собой таблицу релоков, "Linker G" (guess what is G for?) их "угадывает". Идея в следующем: процесс живет в четырёх-гигабайтном адресном пространстве, из которого только крохотная часть - это код и данные вируса. В данном случае 4 килобайта. Неплохое соотношение. А поэтому, выдаём вирусу дизассемблер (1 шт.) и вперёд - парсить свой код на наличие констант похожих на адреса. Дальше просто - копируем тушку в жертву и из каждой найденной константы вычитаем базовый адрес вируса в текущем процессе и добавляем базовый адрес вируса же в файле-жертве. Константами со значением близким к 0x08049000 по понятным причинам лучше не пользоваться. libc вызывается довольно извращённым способом, но это можно и переделать, нельзя использовать .bss, но это от лени. :-) всё. вот так выглядит relocate() в версии G ) В принципе, можно применить этот вариант и к жертве, но стрёмно, двух простых правил маловато, чтобы отличить константу от адреса, хотя вероятность напороться не очень высока. Я считал.

Скачать исходники, бинари. Тестировано на RHEL 5.3. (оно немного глючит. но это же альфа, просто, чтобы показать идею.

Осталось добавить ещё третий вариант, когда вирус добавляет свои релоки в .rel.dyn, тогда всю работу выполнит RTLD. И никакого, блядь, ассемблера, дельт злоебучих, массивов заполняемых push и mov и прочей ахинеи. :-)

LinkLeave a comment

sed ужасен :-) [Jul. 9th, 2009|06:22 pm]
[Tags|, ]

1h;1!H;${g;s/^.*\(\/\* Sc\)/\1/;s/===*.*$//;s/\.\(data\|text\) *:[^}]*}[ =x0-9]*/s\1 =.;_\1 :{1.o(.\1)}e\1 =.;/gp}
кто-нибудь угадает для чего эта хуйня мне понадобилась?
LinkLeave a comment

Будни извращенцев-2 [Jun. 9th, 2009|01:24 pm]
[Tags|, ]

Иногда просто зарубает на абсолютно дурацких пустяках. А компилятор между тем противиться насилию над собой, с 4.1, эта фича вылилась в вот такой код:
 80483c0:       81 ff ef be ad de       cmp    $0xdeadbeef,%edi
 80483c6:       74 18                   je     80483e0
 80483c8:       b8 e0 83 04 08          mov    $0x80483e0,%eax
 80483cd:       83 ec 0c                sub   $0xc,%esp
 80483d0:       2d 74 80 04 08          sub    $0x8048074,%eax
 80483d5:       01 f8                   add    %edi,%eax
 80483d7:       50                      push   %eax
 80483d8:       e8 8a 00 00 00          call   8048467 <jmp.2859>
 80483dd:       83 c4 0c                add   $0xc,%esp
 80483e0:
Решение для 4.1 (ключевого слова asm не избежать Ж-):
void __attribute__((noinline,stdcall)) jmp(uint32_t addr) {
  *(volatile uint32_t*)(&addr - 1) = addr;
}
extern void L;
jmp(nloc + (uint32_t)&L - (uint32_t)&virus_start); asm ("L:");
LinkLeave a comment

Один байт, блядь, всего один, пожалуйста... [May. 20th, 2009|02:06 pm]
[Tags|, ]
[Current Mood | angry]

Есть загрузчик ) И в нём один лишний байт... ;-(
UPD теперь нет )
Link2 comments|Leave a comment

Linked [Apr. 8th, 2009|01:12 pm]
[Tags|, , ]
[Current Mood | blank]

Пофиксил баг в "линкере", не везде учел addends, конструкции вроде:
uint32_t s = ((uint32_t)&__code_start + 4095) & 0xfffff000;
С включенной оптимизацией порождают, что-то вроде:
 190:   c7 45 cc ff 0f 00 00    movl   $0xfff,0xffffffcc(%ebp)
                        193: R_386_32   __code_start
 19a:   81 65 cc 00 f0 ff ff    andl   $0xfffff000,0xffffffcc(%ebp)
Вирус не добавлял 4095 и всё шло к чертям собачьим. Ж-) А так вроде ничего, вчера выложил на форум второй черновичок.
LinkLeave a comment

.dynamic [Oct. 9th, 2008|07:27 pm]
[Tags|, , ]

К 32-м нулям в .dynamic зарезервированым для prelink можно ещё добавить DT_INIT/DT_FINI (в экзешках линкер игнорирует эти таги, а в библиотеках их можно использовать, как точку входа). А можно не убивать, а заменить на DT_FLAGS со значением DF_BIND_NOW, после чего можно грохнуть команды (push .../jmp _plt) в .plt и получить 16 + <number of .plt entries>*10 байт. Можно связать освобождённое таким образом место при помощи «EB 06». И следить за тем, чтобы в собственном коде не было инструкций длинее 8 байт. Где-то так... )
LinkLeave a comment

Расширение сегмента кода [Oct. 9th, 2008|02:36 pm]
[Tags|, , , ]

Принцип «Работает — не трогай!» называют иногда «золотым правилом». Только вот беда, это «золотое» правило возвращает нас в бронзовый век. Если метод прост, надёжен и используется десяток лет, то никто и не пытается его улучшить. Пока не придёт кто-нибудь с непрокомпостированными мозгами, например Якуб Желинек. В начале сам допёр, разглядывая бинари, а потом сообразил, что именно так и работает prelink.

Как? )
LinkLeave a comment

EPO Revisited, Bruteforce relocation [Oct. 2nd, 2008|01:13 pm]
[Tags|, , ]

Есть пара идей, которыми лень сейчас заниматься. Первая касается EPO (маскировка точки входа). Классический подход заключается в том, чтобы заменить команду, на которую указывает точка входа бинаря, на переход к телу вируса. Развитие этой идеи - заменять перую команду call/jmp/jcc. Тогда переход к телу вируса расположен чуть дальше от начала программы. Можно заменить случайную команду в коде, но так как большая часть кода программы не исполняется, то и шансы получить управление у вируса не велики. Что ещё можно сделать? Получить CFG программы и найти в нём точку сочленения расположенную как можно дальше и от начала (точка входа) и от конца (вызов _exit, возврат в __libc_start_main). Так как кандидатов будет много, то можно приписать каждому ребру метрику (количество инструкций) и выбрать такую точку, для которой сумма метрик кратчайшего пути, проходящего через неё максимальна). Вероятность получить управление увеличивается (код в программе расположен не абы как, чем больше инструкций в одной из ветвей, тем больше вероятность, что именно эта ветвь делает ту работу, ради которой была написана программа).
Вторая мысль касается интеграции в бинари без релоков. Необязательно потрошить программу полностью. Можно востановить релоки для текста. Правило, которое позволит отличить адрес кода от константы предельно простое: адрес указывает на секцию с кодом И адрес указывает на начало инструкции. Если встречаем любую подозрительную фигню, например, данные в кодовой секции, можно или сразу выйти или увеличить "счетчик подозрительной фигни", и выйти, если он достигнет некоторого заранее выбранного значения. Для востановления релоков в .data этот метод не подходит, поэтому просто оставим данные, как есть, сдвинем только код. Для надежности, можно использовать следующий финт ушами (раньше использовался для ASLR): не просто сдвинем код, сдвинем его подальше, так чтобы старый и новый диапазоны адресов сегмента кода не перекрывались, установим обработчик SIGSEGV, и он поймает и исправит все обращения к "старому" сегменту кода.
LinkLeave a comment

navigation
[ viewing | most recent entries ]