mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2026-06-16 15:59:24 +00:00
Add files via upload
This commit is contained in:
@@ -0,0 +1,510 @@
|
||||
|
||||
;::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
; 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 e
|
||||
Reference in New Issue
Block a user