Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 14.07.2016, 16:58   #11
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

А что я так понял вы тут просто процитировали найденный в интернете материал.

Цитата:
Меня интересовало: не вызовет-ли подмена инструкций в конвейере, крах всей программы?
Я ссылки выше для кого давал? Краха не будет. Вот весь алгоритм, что будет.
https://docviewer.yandex.ru/?url=ya-...88a13&page=313

Цитата:
Подскажите, в ту-ли степь меня несёт?
Вы сделали то что хотели, а именно - разобраться с устройством конвейера.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .
Pavia вне форума Ответить с цитированием
Старый 14.07.2016, 22:28   #12
R71MT
Участник клуба
 
Аватар для R71MT
 
Регистрация: 16.06.2011
Сообщений: 1,428
По умолчанию

Pavia, там-же указано, что это из выловленой из сети инфы.
А за ссылки спасибо, но маны от Intel все на буржуйском, а у меня с ним сплошные NOPы. Переводчик "Сократ" выдаёт вообще непонятно что, и понять суть его перевода достаточно проблематично. Но макушек всё-же нахватался.

Теперь, собственно, по сабжу...
Понимаю, что это бесполезное занятие, и в реальных программах может не пригодится, но ассемблер для меня чисто хобби, а потому интересны сами/нестандартные алгоритмы, и способы их реализаций.

Планирую написать полиморфный движок, который генерил-бы различные варианты вызова одних и тех-же функций, переходов, добавление хэшей (ака мусор), всяких пустышек и никому-не-нужных процедур, и т.п. При этом должа в полной мере сохранятся работоспособность программы. Пока - метод вызовов выбрал табличный. Буду благодарен, если подскажете другие варианты.

Т.к. все/это должно происходить в случайном порядке, нужен рандом. Я тупо читаю тики с порта(40h) или-же беру их напрямую из памяти биос. Можно потом разделить эти тики на опкод текущего байта, проксорить значением из AH и т.п. - это уже дело вкуса. Теперь, в зависимости от длины таблицы, нужно оставить от рандома нужный диапазон чисел. К примеру, если в таблице 16 элементов, то достаточно применить операцию 'and-random-0fh', как мы получим число в диапазоне 0..15 от рандома:
Код:
   in    ax,40h           ; читаю системные тики
   and   al,0Fh           ; получаю число в диапазоне 0..15
Здесь нужно учитывать, что операция 'AND' сбрасывает все биты числа, которые в маске имеют значени(0). Это означает, что мы не сможем получить таким способом любой диапазон чисел, а только тот, в котором все биты маски взведены. Например, если в таблице 20 элементов, то маска(20d) будет равна: 10100b и операция 'AND AX,20' будет возвращать только 4 значения: 0,4,16,20.

Вот несколько масок, которые можно применять с инстуркцией 'AND':
Код:
  Маска DEC.      Диапазон.  Размер таблицы.
---------------------------------------------
 00001b = 01      0..1       2
 00011b = 03      0..3       4
 00111b = 07      0..7       8
 01111b = 15      0..15      16
 11111b = 31      0..31      32
Для получения остальных диапазонов чисел можно разделить рандом на требуемый диапазон. Остаток от деления не может быть больше делителя, поэтому мы получим число в требуемом диапазоне:
Код:
   in    al,40h            ; получаю рандом
   xor   ah,ah             ; в BL требуемый диапазон 
   div   bl                ; AH = число в диапазоне
Приведу пример с простым генератором условных переходов..
Если посмотреть в справочнике на таблицу опкодов, то можно обнаружить, что все/условные переходы заняли там 16 последовательных позиций начиная с опкода 70h (JO) и заканчивая 7Fh (JG). 16 опкодов как-раз позволяют заюзать инструкцию 'AND':
Код:
   push  bx               ; в ВХ лежит адрес перехода
   call  Random           ; 
   and   al,0Fh           ; выделяю диапазон из рандома
   add   al,70h           ; получаю условный переход
   stosb                  ; вставляю его опкод по адресу ES:DI
   pop   ax               ;
   stosw                  ;    ..и следом сам адрес перехода
С безусловными переходами нужно быть аккуратней, т.к. они могут испортить все планы, прыгнув на абсолютно незапланированный участок кода. Их всего 3, с опкодами E9,EA,EBh: JMP near/far/short соответственно. Генерить их можно или по заранее известному указателю, или-же просто на следующую инструкцию кода, типа '$+1'

..ну и конечно-же мусор. Генерировать его проще-простого, но зато как он отравляет жизнь пионерам крэкинга. Если заглянуть в справочник, то глаза разбегаются, сколько там однобайтных команд, которые без особых последствий можно вставлять между полезными инструкциями кода. Вот их короткий список:
Код:
hashTable:
   db   026h          ; ES:
   db   02Eh          ; CS:
   db   03Eh          ; DS:
   db   036h          ; SS:
   db   027h          ; daa
   db   037h          ; aaa
   db   02Fh          ; das
   db   03Fh          ; aas
   db   040h          ; inc ax
   db   041h          ; inc cx
   db   042h          ; inc dx
   db   043h          ; inc bx
   db   048h          ; dec ax
   db   049h          ; dec cx
   db   04Ah          ; dec dx
   db   04Bh          ; dec bx
   db   090h          ; nop
   db   098h          ; cbw
   db   099h          ; cwd
   db   09Eh          ; sahf
   db   09Fh          ; lahf
   db   0CCh          ; int 3h
   db   0F5h          ; cmc
   db   0F8h          ; clc
   db   0F9h          ; stc
   db   0FDh          ; std
                      ;   ..и многие другие
В этой таблице всего 26 элементов и столько-же смещений в байтах.
Чтобы выбрать из неё случайную инструкцию, достаточно сохранить адрес начала таблицы и добавить к этому адресу рандом из диапазона(0..25). В качестве регистров адресации могут использоваться SI/DI/BX:
Код:
GetHashByte:
   mov   bl,26             ; кол-во элементов в таблице
   mov   si,hashTable      ; адрес таблицы
   in    ax,40h            ; получаем случайное число
   xor   al,ah             ; ксорим его старшей частью
   div   bl                ; 
   shr   ax,8              ; AL = число в диапазоне 0..25
   add   si,ax             ; получаем случайное смещение внутри таблицы
   mov   al,byte[si]       ; выбираем опкод из таблицы
   stosb                   ; запись в ES:DI
   ret
Нужно сказать, что это моя первая попытка освоить подобную технику, и пока только в теории, ..на бумажке. Я в принципе имею общую картину происходящего, но как получится на практике - без понятия. В планах есть много подобных направлений, типа переходы 'Jump->Call', способы вызовов прерываний под DOS, пустые параметры для API и прерываний и т.д, и т.п.
Нашедшего выход - затаптывают первым..
R71MT вне форума Ответить с цитированием
Старый 14.07.2016, 22:32   #13
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,493
По умолчанию

The first polymorphic engine was called MtE (short for Mutation Engine). It was written in 1992 by a virus author who called himself 'Dark Avenger'.

Ref:
https://en.wikipedia.org/wiki/Polymorphic_engine
https://en.wikipedia.org/wiki/1260_(computer_virus))
waleri вне форума Ответить с цитированием
Старый 14.07.2016, 22:50   #14
R71MT
Участник клуба
 
Аватар для R71MT
 
Регистрация: 16.06.2011
Сообщений: 1,428
По умолчанию

waleri, 'Dark Avenger' gave us direction and we must his use! :D
Нашедшего выход - затаптывают первым..
R71MT вне форума Ответить с цитированием
Старый 17.07.2016, 11:44   #15
R71MT
Участник клуба
 
Аватар для R71MT
 
Регистрация: 16.06.2011
Сообщений: 1,428
По умолчанию

Помимо пустых инструкций, можно вызывать и пустые прерывания, передавая им номера ничего не делающих функций. Вернее эти функции не совсем пустые, а просто возвращают определённые значения, которые можно тупо проигнорировать. Ниже идёт перечень таких функций для INT-21h, и возможный способ вызова сервиса(DOS) по случайному алгоритму:
Код:
HashFunction:
   mov   bx,13           ; кол-во функций в таблице
   call  Random          ; рандом, в диапазоне 0..12
   mov   si,FuncTable    ;
   add   si,ax           ; выбираем номер функции из таблицы
   mov   ah,byte[si]     ; отправляем его в AH
   int   21h             ; зовём DOS!
   ret                   ;
;-------------------------------------------------------
FuncTable:
    db    0Bh          ; Проверить статус ввода
    db    0Dh          ; Сброс дисковых буферов
    db    19h          ; Дать номер текущего диска
    db    2Ah          ; Читать дату
    db    2Ch          ; Читать время
    db    30h          ; Версия DOS
    db    33h          ; Статус [Ctrl+Break]
    db    36h          ; Свободная память диска
    db    45h          ; Копия дескриптора
    db    4Dh          ; Получить код ошибки
    db    51h          ; Получить текущий сегмент (DOS)
    db    59h          ; Полный код ошибки
    db    62h          ; Получить текущий сегмент PSP
    ; ..и многие другие.
Нашедшего выход - затаптывают первым..
R71MT вне форума Ответить с цитированием
Старый 18.07.2016, 15:11   #16
R71MT
Участник клуба
 
Аватар для R71MT
 
Регистрация: 16.06.2011
Сообщений: 1,428
По умолчанию

..несколько вариантов вывода текстовых строк на консоль.
Здесь, как и прежде генерится рандом в диапазоне кол-ва функций в таблице. Но нужно учитывать, что адреса в таблице имеют размер 2 байта, поэтому полученный рандом нужно умножить на два. Дальше, идёт считывание этого адреса в АХ и переход по нему.

Если у кого-то есть ещё варианты, то прошу подкинуть их мне. Осталось ещё несколько направлений (вывод напрямую в видео/буфер, некоторые функции видео/сервиса), но они не удобны тем, что нужно постоянно сдвигать курсор (т.е. они не телетайпные). Часто не знаешь, в какую именно область экрана будет выводится строка, поэтому я их отфильтровал. Вот что получилось..
Код:
;-----------------------------------------------------------
; Случайное число ------------------------------------------
; Вход:  BL = требуемый диапазон
; Выход: AX = рандом
;-----------------------------------------------------------
Random:
   in   ax,40h
   xor  ah,ah
   div  bl
   shr  ax,8                 ; оставляем только остаток
   ret
;-----------------------------------------------------------
; Случайный способ вывода строки на экран ------------------
; Вход: DX = адрес строки (маркер конца = '$')
;-----------------------------------------------------------
GetRandomString:
   mov   bx,6                ; Всего вариантов в таблице
   call  Random              ; Выбираем случайный..
   shl   ax,1                ; Умножить смещение на 2
   mov   si,StringTable      ; 
   add   si,ax               ; 
   lodsw                     ;
   call  ax                  ; Вызов функции!
   ret

;Таблица указателей на функции
StringTable:
   dw    String@0
   dw    String@1
   dw    String@2
   dw    String@3
   dw    String@4
   dw    String@5

;------- Вариант #0 (классический DOS) ------------------
String@0:
   mov   ah,9
   int   21h
   ret

;------- Вариант #1 (lodsb/INT-29h) ---------------------
String@1:
   mov   si,dx
@1prn:
   lodsb
   cmp   al,'$'               ; конец строки?
   je    @stop1
   int   29h
   jmp   @1prn
@stop1:  ret   

;------- Вариант #2 (fn(6).INT-21h) ---------------------
String@2:
   mov   ah,6
   mov   bx,dx
@2prn:
   mov   dl,byte[bx]
   cmp   dl,'$'
   je    @stop2
   int   21h
   inc   bx
   jmp   @2prn
@stop2:  ret

;------- Вариант #3 (fn(2).INT-21h) ---------------------
String@3:
   mov   ah,2
   mov   si,dx
@3prn:
   lodsb
   xchg  al,dl
   cmp   dl,'$'
   je    @stop3
   int   21h
   jmp   @3prn
@stop3:  ret

;------- Вариант #4 (fn(0Eh) видео/сервиса) ------------
String@4:
   mov   bp,dx
   mov   ah,0Eh
@4prn:
   mov   al,byte[bp]
   cmp   al,'$'
   je    @stop4
   int   10h
   inc   bp
   jmp   @4prn
@stop4:  ret

;------- Вариант #5 (полный изврат) --------------------
String@5:
   mov   bp,sp
   mov   sp,dx           ; стек указывает на строку
   mov   di,sp
   mov   al,'$'          ; вычисляем длину строки
   mov   cx,0ffffh
   repne scasb           
   not   cx              ; СХ = длина строки
   shr   cx,1            ;    ..в словах
@5prn:
   pop   ax              ; снимаем со-стека по 2 символа
   int   29h
   shr   ax,8
   int   29h             ; выводим их на экран
   loop  @5prn
   mov   sp,bp           ; восстановим адрес возврата
   ret
Нашедшего выход - затаптывают первым..
R71MT вне форума Ответить с цитированием
Старый 18.07.2016, 15:48   #17
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,493
По умолчанию

Насколько я понимаю, идея не в том, чтоб использовать разные варианты одной функции а чтоб полиморфить код самой функции... например сделать так, чтоб указатель на строку передавался в разных регистрах.
Ясное дело, что для вызова системных функций это смысла не имеет.
С другой стороны, это наложит ограничение на инструкции, которыми можно пользоваться. Например lodsb или mul не особо подойдут, поскольку работают с определенными регистрами.
waleri вне форума Ответить с цитированием
Старый 18.07.2016, 18:21   #18
R71MT
Участник клуба
 
Аватар для R71MT
 
Регистрация: 16.06.2011
Сообщений: 1,428
По умолчанию

waleri да, именно так: т.е. мне нужны любые нестандартные решения, которые могут хоть как-то помешать взлому. Пусть это будет передача параметров в других регистрах, какие-нить глючные функции, и т.д. Приведу вкратце свой алгоритм..

Весь код разбиваю на блоки, которых на данный момент 3:
- Блок мусорных инструкций;
- Блок вывода сообщений случайным образом;
- Блок вызова прерываний случайным образом (в разработке).

В свою очередь 'мусорный блок' делится ещё на 3 уровня. Уровни выбираются в случайном порядке, и позволяют выводить или пустой переход(Jump), или 1-байтную инструкцию(Byte), или-же безобидную функцию сервиса DOS (Function). Все они описаны выше и вызыватся так:
Код:
RandomJunk:
    mov   bx,3
    call  Random 
    shl   ax,1
    mov   si,CallTable
    add   si,ax 
    lodsw
    call  ax               ; Вызов случайной функции!
    ret

CallTable:
    dw    GetHashJump
    dw    GetHashByte
    dw    GetHashFunction
    ;[...]
В любое время внутри своего кода я беру рандом и проверяю в нём какой-нить бит от-фонаря. Если сперматазоид попал в цель, то зовётся функция выше 'RandomJunk'. Одним словом задаётся вопрос, типа: 'Мусор нужен?':
Код:
   in    ax,40h
   xor   al,ah
   test  al,0100b
   jz    fuck
   call  RandomJunk
fuck: ....
Остальные/два блока работают так-же, только внутри них уже по одному уровню, которые просто выполняют одну-и-ту-же задачу разными способами.

В результате, при каждом запуске приложения, код будет отличатся от предыдущего, т.к. откуда-то будут появлятся новые инструкции. В идеале, можно будет вообще зашифровать всё тело случайным ключом, который хранить где-нить внутри этих процедур. Пока что, мне нужны просто какие-нибудь интересные фрагменты кода, которые я смогу поместить в эту тушку. Любые.., лишь-бы это не было из области: "для тех, кто в танке".

На данный момент планирую проверять и сразу подменять содержимое регистров нужным набором по типу, как это делают стандартные обработчики прерываний DOS. Если оттрасировать код в отладчике '..со-входом в INT', то там видно, что обработчик начинает проверять AH на номер функции начиная снизу-вверх. Если не находит, то увеличивает AH и продолжает поиск. Хочу замутить так-же, и при совпадении заносить уже в остальные регистры стандартные значения. Именно поэтому я и затрагивал вначале, тему конвейера. Посмотрю, что получится..
Нашедшего выход - затаптывают первым..

Последний раз редактировалось R71MT; 18.07.2016 в 18:39.
R71MT вне форума Ответить с цитированием
Старый 19.07.2016, 09:45   #19
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,493
По умолчанию

Взлому это не помешает.
Все это делалось для избегания антивирусов, которые искали по шаблонам.
То, что код каждый раз отличается помешает только отладчику но тулзам типа IDA это не помеха. Вот если зашифорвать код, это уже будет труднее а шифровать код умеет любой ЕХЕ компрессор.
waleri вне форума Ответить с цитированием
Старый 19.07.2016, 17:59   #20
R71MT
Участник клуба
 
Аватар для R71MT
 
Регистрация: 16.06.2011
Сообщений: 1,428
По умолчанию

waleri, да конечно! Взлому вообще ничто не может помешать. Если творение достойно взлома, то и шифрование не спасёт: снимут дамп памяти и кранты шифрованию. Здесь вопрос в другом - чтоб шарики чуть расшевелить, развить мышление, ..но в пределах разумного!

Например легче повеситься, чем проверять регистры по алгоритму DOS (о чём я говорил выше). Вот идею спёр у 'Ржавого робота', который последовательно проверяет значения в таблице, и растасовывает эти значения по РОН в порядке 'АBCD'. Если в таблице встречается флаг 'full' (со значением FFFFh), то это поле пропускается и означает, что до вызова процедуры кто-то/что-то уже положил в этот регистр. Вариант реализации привожу ниже..

В примере вызывается функция DOS(0Ah), которая требует адрес приёмного буфера в DX. Поэтому заношу в последнее поле флаг 'full' (мол не трогать!), а остальные регистры забиваю константами из таблицы. Не шедевр конечно, но на первых порах сойдёт и такой вариант:
Код:
full   equ  -1h             ; флаг пропуска 
;----------------------------------------------------------
     mov   si,inpBuff       ; выбираем функцию в таблице
     call  Crazy21h
     ;...
;----------------------------------------------------------
; Процедура заполнения регистров из таблицы       
;----------------------------------------------------------
Crazy21h:
     lodsw
     push  ax
     lodsw
     cmp   ax,full
     jz    @1
     mov   bx,ax
@1:  lodsw
     cmp   ax,full
     jz    @2
     mov   cx,ax
@2:  lodsw
     cmp   ax,full
     jz    @3
     mov   dx,ax
@3:  pop   ax
     int   21h                ; DOS call
     ret

;------------------------------------------------------
;            Таблица значений регистров
;------------[ ax     bx    cx     dx ]----------------
;------------------------------------------------------
keybInp1   dw  0100h, 0   , 0    , 0        ; Ввод с клавы с эхом  
keybInp8   dw  0800h, 0   , 0    , 0        ; Ввод с клавы без эхо
strOutp    dw  0900h, 0   , 0    , full     ; Вывод строки
inpBuff    dw  0a00h, 0   , 0    , full     ; Ввод в буфер
getDate    dw  2a00h, 0   , 0    , 0        ; Получить дату
getTime    dw  2c00h, 0   , 0    , 0        ; Получить время
creatFile  dw  3c00h, 0   , 20h  , full     ; Создать файл
openFile   dw  3d02h, full, 0    , full     ; Открыть.. 
closeFile  dw  3e00h, full, 0    , 0        ; Закрыть..
readFile   dw  3f00h, full, full , full     ; Читать..
writeFile  dw  4000h, full, full , full     ; ПисАть..
giveMem    dw  4800h, full, 0    , 0        ; Выделить память
findFile   dw  4e00h, 0   , full , full     ; Искать файл..
nextFile   dw  4f00h, 0   , full , full     ; Продолжить поиск..
Нашедшего выход - затаптывают первым..
R71MT вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Полиморфизм Anubys Помощь студентам 1 26.12.2011 20:42
Полиморфизм Zorgan Visual C++ 22 29.08.2011 12:23
Полиморфизм MasterSporta Общие вопросы C/C++ 3 10.04.2011 23:46
полиморфизм slayerblya Общие вопросы C/C++ 1 27.02.2011 01:43
Полиморфизм mister2010 Общие вопросы C/C++ 30 24.05.2010 01:07