Add files via upload

This commit is contained in:
vxunderground
2020-10-09 21:50:53 -05:00
committed by GitHub
parent 3b1112577c
commit 930c435323
36 changed files with 16849 additions and 0 deletions
+758
View File
@@ -0,0 +1,758 @@
;::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Simple Morpher v.0.1 :
; :
; x0man © 2008 :
; :
; http://www.virustech.org/ :
;::::::::::::::::::::::::::::::::::::::::::::::::::::::
;-----------------------------------------------------------------------------------------:
; :
;В Кратце расскажу алгоритм, который у меня реализован. :
; :
;Есть массив в который заносятся данные о инструкциях :
;Одним эллементом массива является: :
; :
;_OPCODE struct; :
; dwOldAddress dd ? ; Старый адрес инструкции (до морфинга) :
; dwNewAddress dd ? ; Новый адрес инструкции (после морфинга) :
; dwJumpAddress dd ? ; Адрес куда должен указывать прыжок(или вызов) :
; ; (если инструкция им является) :
; dwLength dd ? ; в данном примере эта переменная не используется :
; ; Надеюсь вам она пригодиться больше чем мне :) :
;_OPCODE ends :
; :
;В "мой" Первый этап входит :
; 1. Парсинг кода, и выделение на каждую инструкцию одного :
; эллемента массива, заполняя данные в структуре _OPCODE. :
; 2. Расширение кода для будущих изменений (замена коротких прыжков на длинные) :
; 3. Если инструкция является прыжком или вызовом, нам нужно :
; подсчитать скажем так EIP при выполнении оной. :
; 4. И есстественно разбавление кода (инструкцией NOP) :
; :
;Второй этап :
; 1. Проходимся по массиву с описаниями инструкций :
; 2. Если инструкция является вызовом, то вычисляем параметр у прыжка :
; или вызова, и меняем его на корректный(уже в изменённом коде). :
; :
; :
;Вроде бы всё... для более точных описаний смотрим код! :
; :
;Дизассемблер длинн инструкций я взял Catchy_32, который можно скачать с :
; http://www.wasm.ru, он также прилагается к исходникам в приложении. :
; :
;GreeTz: :
; Osen :
; izee [ EOF-Project ] http://eof-project.net/ :
; :
; tPORt (http://www.tport.org/) :
; REVENGE(http://www.revenge-crew.com/) :
; TLG (http://tlg.astalavista.ms/) :
; TSRh (http://tsrh.org.ua/) :
; TPOC (http://vx.netlux.org/tpoc/) :
; :
; :
; Спасибо за внимание! :
; :
; 10.05.2008 :
; x0man [VirusTech] :
; http://www.virustech.org :
;-----------------------------------------------------------------------------------------:
.386
.model flat, stdcall
option casemap :none
include \MASM32\INCLUDE\windows.inc
include \MASM32\INCLUDE\kernel32.inc
include \MASM32\INCLUDE\user32.inc
includelib \MASM32\LIB\kernel32.lib
includelib \MASM32\LIB\user32.lib
; #########################################################################
_OPCODE struct
dwOldAddress dd ? ; Старый адрес инструкции (до морфинга)
dwNewAddress dd ? ; Новый адрес инструкции (после морфинга)
dwJumpAddress dd ? ; Адрес куда должен указывать прыжок(или вызов)
; (если инструкция им является)
dwLength dd ? ; в данном примере эта переменная не используется
; Надеюсь вам она пригодиться больше чем мне :)
_OPCODE ends
; #########################################################################
.code
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Код для теста :)
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
test_code:
@@:
jmp @F
mov eax, edx
pop eax
push eax
call @F
cmp eax, 0
jne @B
jmp @B
add ecx, edx
add eax, edx
xchg edx, ecx
call @B
jne @F
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
jne @B
ret
@@:
ret
int 3
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::
; Подключим дизасм длинн инструкций
include Catchy32\Catchy32.inc
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::|
; Функция для подсчёта числа, куда должен указывать прыжок|
; Пример: dwCurrentAddress - указывает на код |
; |
; 00000000: 74 30 JE imm8 |
; эта функция высчитывает "imm8" |
; в нашем примере imm8 = 00000000 + 30 + 2 = 00000032 |
; т.е. |
; 00000000 - Текущий адрес |
; 30 - Параметр |
; 2 - Длинна инструкции JE imm8 |
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::|
; 00000000: 74 30 JE 00000032 --. |
; 00000002: | |
; | |
; 00000032: <-----° |
; Это описание для "положительных" прыжков |
; Для отрицательных, попробуйте разобрать сами |
; там не сложно ;-) |
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::|:::|
; IN dwCurrentAddress : текущий адрес предпологаемого прыжка |
; OUT EAX : Адрес куда прыжок указывает |
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::|
get_jump_address proc dwCurrentAddress : DWORD
push ecx
push edi
mov edi, dwCurrentAddress
mov al, byte ptr [edi]
;:::::::::::::::::::::::::::::::::::::
; XX imm8
cmp al, 070h
jl @F
cmp al, 07Fh
jna @_jump_imm8_
@@:
;:::::::::::::::::::::::::::::::::::::
cmp al, 0EBh
je @_jump_uncond_imm8_
;:::::::::::::::::::::::::::::::::::::
; 0F XX imm32
cmp al, 00Fh
jne @F
mov ah, byte ptr [edi + 1]
cmp ah, 080h
jl @F
cmp ah, 08Fh
jna @_jump_imm32_
;:::::::::::::::::::::::::::::::::::::
@@:
;:::::::::::::::::::::::::::::::::::::
; JMP imm32
cmp al, 0E9h
je @_jump_uncond_imm32_
;:::::::::::::::::::::::::::::::::::::
; CALL
cmp al, 0E8h
je @_call_imm32_
;:::::::::::::::::::::::::::::::::::::
jmp @_exit_
;:::::::::::::::::::::::::::::::::::::
@_jump_imm8_:
@_jump_uncond_imm8_:
;:::::::::::::::::::::::::::::::::::::
; Короткие прыжки
movzx eax, byte ptr [edi + 1]
mov cl, al
test cl, 10000000b ; isNegative?
jnz @_neg_1
add edi, eax
add edi, 2
xchg eax, edi
jmp @_exit_
@_neg_1:
neg al
sub al, 2
sub edi, eax
xchg eax, edi
jmp @_exit_
@_jump_imm32_:
;:::::::::::::::::::::::::::::::::::::
; Длинные прыжки
mov eax, dword ptr [edi + 2]
mov ecx, eax
shr ecx, 24d
test ecx, 10000000b ; isNegative?
jnz @_neg_2
add eax, edi
add eax, 6
jmp @_exit_
@_neg_2:
neg eax
sub eax, 6
sub edi, eax
xchg eax, edi
jmp @_exit_
;:::::::::::::::::::::::::::::::::::::
@_jump_uncond_imm32_:
@_call_imm32_:
;:::::::::::::::::::::::::::::::::::::
; JMP imm32 & CALL imm32
mov eax, dword ptr [edi + 1]
mov ecx, eax
shr ecx, 24d
test ecx, 10000000b ; isNegative?
jnz @_neg_3
add edi, eax
add edi, 5
xchg eax, edi
jmp @_exit_
@_neg_3:
neg eax
sub eax, 5
sub edi, eax
xchg eax, edi
;///////////////////////////////////////
@_exit_:
pop edi
pop ecx
ret
get_jump_address endp
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::|
; Функция для поиска в массиве описаний инструкций |
; Нового адреса для прыжка.... |
; |
; IN dwAddress - Адрес прыжка |
; IN pOpcodes - Указатель на массив с описаниями опкодов |
; OUT EAX - Новый адрес прыжка... |
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::|
get_new_jump_address proc dwAddress:DWORD, pOpcodes : DWORD
push ecx
assume ecx : ptr _OPCODE
mov ecx, pOpcodes
mov eax, dwAddress
@@:
cmp [ecx].dwOldAddress, eax
je @F
add ecx, sizeof _OPCODE
cmp [ecx].dwOldAddress, 0
jne @B
xor eax, eax
@@:
mov eax, [ecx].dwNewAddress
pop ecx
ret
get_new_jump_address endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::|
; Функция разбавляет определённый код, инструкцией NOP |
; ВАЖНО! Код должен заканчиваться опкодом 0CCh |
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::|
; IN dwCodeAddress - Адрес кода для морфинга |
; IN dwOutputBuffer - Адрес куда будет занесён проморфленный код |
; OUT EAX - Размер проморфленного кода |
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::|
MorphCode proc dwCodeAddress : DWORD, dwOutputBuffer : DWORD
local pOpcodes : DWORD
local dwTotalCodeSize : DWORD
;::::::::::::::::::::::::::::::::::::::::::::::::::
; pOpcodes - Указатель на описания опкодов ::
; dwOutputBuffer - Проморфленный код ::
;::::::::::::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Зарезервируем памяти для массива с описаниям инструкций
invoke VirtualAlloc, NULL, 1024*1024, MEM_COMMIT + MEM_RESERVE, PAGE_READWRITE
mov pOpcodes, eax
;::::::::::::::::::::::::::::::::::::::::::::
; Обнулим переменную в которую будем заносить
; Общий размер кода
push 0
pop dwTotalCodeSize
;:::::::::::::::::::::::::::::::::::::::::
; Без комментариев
assume ecx : ptr _OPCODE
mov esi, dwCodeAddress ; Code Address
mov edi, dwOutputBuffer ; New Code Address
mov ecx, pOpcodes ; array of _OPCODES
;::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::
; Первый этап :::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Укажем для первой инструкции её новый адрес что в EDI
mov [ecx].dwNewAddress, edi
;::::::::::::::::::::::::::::::::::::
; Начинаем цикл
; Loop 1
@_loop_1:
;::::::::::::::::::::::::::::::::::::
; Узнаем длинну у инструкции
; IN ESI == Current Code Offset
; OUT EAX == Instruction Length
call c_Catchy
;:::::::::::::::::::::::::::::::::::::
; Занесём данные в массив с описаниями
mov [ecx].dwOldAddress, esi
mov [ecx].dwLength, eax
;::::::::::::::::::::::::::::::::::::
; Короткие условные прыжки меняем на длинные
; Они отличаются от длинных префиксом 00Fh
; в начале и +10h к текущему опкоду прыжка
; Пример:
; Было :00000000: 74 30
; 0F +10 30 00 00 00
; Стало:00000000: 0F 84 30 00 00 00
cmp byte ptr [esi], 070h
jl @F
cmp byte ptr [esi], 07Fh
ja @F
push eax
mov al, 00Fh
stosb
movzx eax, byte ptr [esi]
add eax, 10h
stosd
;:::::::::::::::::::::::::::::::::::::::
; Подсчитаем адрес куда указывает прыжок
push esi
call get_jump_address
;::::::::::::::::::::::::
; Занесём данные в массив
mov [ecx].dwJumpAddress, eax
pop eax
;::::::::::::::::::::::::::::::::::::
; Прибавим к общему размеру кода
; Длинну 00Fh XXh imm32, т.е. число 6
; где XX » [80h..8Fh]
add dwTotalCodeSize, 6
;::::::::::::::::::::::::::::::::::::
; Пропустим перенос маленького прыжка
; Переходим к следующей инструкции
jmp @_next_inst_
@@:
;::::::::::::::::::::::::::::::::::::
; Меняем...
; JMP imm8 -> JMP imm32
; Пример
; Было : 00000000: EB 33
; Стало: 00000000: E9 33 00 00 00
cmp byte ptr [esi], 0EBh
jne @F
push eax
mov al, 0E9h
stosb
xor eax, eax
stosd
;:::::::::::::::::::::::::::::::::::::::
; Подсчитаем адрес куда указывает прыжок
push esi
call get_jump_address
;::::::::::::::::::::::::
; Занесём данные в массив
mov [ecx].dwJumpAddress, eax
pop eax
;:::::::::::::::::::::::::::::::
; Прибавим к общему размеру кода
; Длинну E9 imm32, т.е. число 5
add dwTotalCodeSize, 5
jmp @_next_inst_
;::::::::::::::::::::::::::::::::::::
@@:
;::::::::::::::::::::::::::::::::::::
; Проверим на JMP imm32
cmp byte ptr [esi], 0E9h
jne @F
push eax
push esi
call get_jump_address
mov [ecx].dwJumpAddress, eax
pop eax
jmp @_replace_instr_
;::::::::::::::::::::::::::::::::::::
@@:
;::::::::::::::::::::::::::::::::::::
; Проверим на CALL
cmp byte ptr [esi], 0E8h
jne @F
push eax
push esi
call get_jump_address
mov [ecx].dwJumpAddress, eax
pop eax
jmp @_replace_instr_
;::::::::::::::::::::::::::::::::::::
@@:
;::::::::::::::::::::::::::::::::::::
; 00Fh XX imm32
cmp byte ptr [esi], 00Fh
jne @F
cmp byte ptr [esi + 1], 080h
jl @F
cmp byte ptr [esi + 1], 08Fh
ja @F
push eax
push esi
call get_jump_address
mov [ecx].dwJumpAddress, eax
pop eax
;::::::::::::::::::::::::::::::::::::
@@:
@_replace_instr_:
;::::::::::::::::::::::::::::::::::::::::::
; Переносим инструкцию в новый буффер.
; Этот код выполниться в том случае
; Если мы не меняли оригинальные инструкции
push esi
push ecx
mov ecx, eax
rep movsb
pop ecx
pop esi
; Добавим к общему размеру кода
; длинну текущей инструкции
add dwTotalCodeSize, eax
;::::::::::::::::::::::::::::::::::::
; сюда прыгаем если мы заменили текущую инструкцию на свою
@_next_inst_:
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Разбавляем код инструкцией NOP
; Тут можно разбавлять код
; любыми "пустыми" инструкциями
; вида:
;--------------
; push eax
; pop eax
;--------------
; mov eax, eax
;--------------
; и т.д.
push eax
mov al, 90h
stosb
pop eax
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Увеличим общий размер кода на 1 (Длинна инструкции NOP)
; Так же если будете добавлять свой "пустой" код
; Нужно будет прибавить к dwTotalCodeSize его общую длинну(!)
add dwTotalCodeSize, 1
;::::::::::::::::::::::::::::::::::::
; Перейдём к следующей инструкции
add esi, eax
;::::::::::::::::::::::::::::::::::::
; перейдём к следующему элементу
; в нашей таблице с описаниями опкодов
add ecx, sizeof _OPCODE
;::::::::::::::::::::::::::::::::::::
; Заносим новый адрес у следующей инструкции
mov [ecx].dwNewAddress, edi
;::::::::::::::::::::::::::::::::::::
; Доходим до int 3
; Это значит что код закончился....
; и следовательно нам тут делать уже нечего.
cmp byte ptr [esi], 0CCh
jne @_loop_1
; End Loop 1
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::
; Укажем что массив с описаниями закончился
mov [ecx].dwOldAddress, 0
;::::::::::::::::::::::::::::::::::::::::
; Второй этап :::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::
mov ecx, pOpcodes
@_loop_2:
;::::::::::::::::::::::::::::::::::::::::
; Если инструкция является прыжком или вызовом
; то dwJumpAddress != 0 (!)
cmp [ecx].dwJumpAddress, 0
je @F
;::::::::::::::::::::::::::::::::::::::::
; Получим новый адрес адрес куда должен
; указывать прыжок или вызов
push pOpcodes
push [ecx].dwJumpAddress
call get_new_jump_address
;::::::::::::::::::::::::::::::::::::::::
; Проверим результат на нуль.
; По идее тут проверки быть не должно
; ибо EAX (если весь код по адресу dwCodeAddress был корректным)
; никогда не будет равняться нулю
; и эти 2 строчки лишние, но мне захотелось
; всётаки их написать :)))
cmp eax, 0
je @F
;::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::
; Проверим адрес какой инструкции
; нужно поменять на новый
mov edx, [ecx].dwNewAddress
;:::::::::::::::::::::::::
; Длинные условные прыжки
; 00Fh XXh imm32
cmp byte ptr [edx], 00Fh
je @_0F_XX_imm32
;:::::::::::::::::::::::::::
; Длинный безусловный прыжок
; JMP imm32
cmp byte ptr [edx], 0E9h
je @_XXX_imm32_
;::::::::::::::::::::::
; Вызов (CALL imm32)
cmp byte ptr [edx], 0E8h
je @_XXX_imm32_
;::::::::::::::::::::::
jmp @F
;::::::::::::::::::::::::::::::::::::::
; 00Fh XXh imm32
; Нам нужно заменить есстественно imm32
; что находится по смещению [АДРЕС ПРЫЖКА + 2]
; Пример:
; 00Fh 84 imm32 ; JE imm32
; 00Fh 85 imm32 ; JNE imm32
@_0F_XX_imm32:
cmp eax, [ecx].dwNewAddress
jle @_less_or_equal_1
push eax
sub eax, [ecx].dwNewAddress
sub eax, 6
mov edx, [ecx].dwNewAddress
mov dword ptr [edx + 2], eax
pop eax
jmp @F
@_less_or_equal_1:
push eax
mov edx, [ecx].dwNewAddress
sub edx, eax
neg edx
sub edx, 6
mov eax, [ecx].dwNewAddress
mov dword ptr [eax + 2], edx
pop eax
jmp @F
;:::::::::::::::::::::::::::::::::::::::::::::
; Смещение imm32 в инструкциях JMP и CALL
; одно и тоже, следовательно код обработки
; нового адреса у них можно сделать одним
; imm32 находится по смещению [АДРЕС ПРЫЖКА + 1]
; Пример:
; E9 imm32
; E8 imm32
; :)
@_XXX_imm32_:
cmp eax, [ecx].dwNewAddress
jle @_less_or_equal_2
push eax
sub eax, [ecx].dwNewAddress
sub eax, 5
mov edx, [ecx].dwNewAddress
mov dword ptr [edx + 1], eax
pop eax
jmp @F
@_less_or_equal_2:
push eax
mov edx, [ecx].dwNewAddress
sub edx, eax
neg edx
sub edx, 5
mov eax, [ecx].dwNewAddress
mov dword ptr [eax + 1], edx
pop eax
jmp @F
;::::::::::::::::::::::::::::::::::::::::
@@:
;::::::::::::::::::::::::::::::
; Перейдём к следующем описанию
; Следующего опкода :)
add ecx, sizeof _OPCODE
;:::::::::::::::::::::::::::::::::::::
; Повторяем до тех пор пока
; не наткнёмся на конец массива
; На это указывает Нуль в dwOldAddress
cmp [ecx].dwOldAddress, 0
jne @_loop_2
;::::::::::::::::::::::::::::::::::::::::
; Освободим память что занимали
invoke VirtualFree, pOpcodes, NULL, MEM_RELEASE
@_exit_:
mov eax, dwTotalCodeSize
ret
MorphCode endp
.data
; Буфер куда занесём проморфленный код
dwOutputBuffer dd 0
; Размер буфера
dwOutputBufferSize dd 0
; Кол-во байт записанных в фаил
dwBytesWritten dd 0
; Имя файлика в который запишем проморфленный код
szFileName db 'morphed_code_dump_raw.bin',0
; Текст для MessageBoxA
szComplete db 'Complete! :)', 0
.code
start:
;:::::::::::::::::::::::::::::::::::::::::::::::::::::
; Зарезервируем память для проморфленного кода
; Размер можете выставить конечноже свой
; Всё зависит от кол-ва кода что собираетесь Морфить
invoke VirtualAlloc, NULL, 1024*1024, MEM_COMMIT + MEM_RESERVE, PAGE_READWRITE
mov dwOutputBuffer, eax
;::::::::::::::::
; Морфим код.....
invoke MorphCode, offset test_code, dwOutputBuffer
mov dwOutputBufferSize, eax
;::::::::::::::::::::::::::::::::
; Дампим проморфленный код в фаил
invoke CreateFile, offset szFileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, 0
push eax
invoke WriteFile, eax, dwOutputBuffer, dwOutputBufferSize, addr dwBytesWritten, NULL
call CloseHandle
;:::::::::::::::::
; Освободим память
invoke VirtualFree, dwOutputBuffer, NULL, MEM_RELEASE
;:::::::::::::::::
; Мессадж :)
invoke MessageBoxA, 0, offset szComplete, 0, MB_ICONINFORMATION
;:::::::::::::::::
; Выход)
xor eax, eax
ret
end start
; #########################################################################