mirror of
https://github.com/stasenso/SHA256.git
synced 2026-06-26 21:32:43 +03:00
224 lines
12 KiB
NASM
224 lines
12 KiB
NASM
OPTION DOTNAME
|
|
include includes\temphls.inc
|
|
include includes\win64.inc
|
|
include includes\user32.inc
|
|
includelib includes\user32.lib
|
|
OPTION PROLOGUE:none
|
|
OPTION EPILOGUE:none
|
|
.data
|
|
AppName: ;DLL Skeleton
|
|
dw 0044h,004ch,004ch,0020h,0053h,006bh,0065h,006ch,0065h,0074h,006fh,006eh,0000h
|
|
HelloMsg: ;Вызвана функция TestHello
|
|
dw 0412h,044bh,0437h,0432h,0430h,043dh,0430h,0020h,0444h,0443h,043dh,043ah,0446h,0438h,044fh,0020h,0054h,0065h,0073h,0074h,0048h,0065h,006ch,006ch,006fh,0000h
|
|
LoadMsg: ;DLL Загружена
|
|
dw 0044h,004ch,004ch,0020h,0417h,0430h,0433h,0440h,0443h,0436h,0435h,043dh,0430h,0000h
|
|
UnloadMsg: ;DLL выгружена
|
|
dw 0044h,004ch,004ch,0020h,0432h,044bh,0433h,0440h,0443h,0436h,0435h,043dh,0430h,0000h
|
|
SHAMsg: ;"SHA256 Запущена!"
|
|
dw 0053h,0048h,0041h,0032h,0035h,0036h,0020h,0417h,0430h,043fh,0443h,0449h,0435h,043dh,0430h,0021h,0000h
|
|
|
|
DllAtata: ;Неожиданно прилетел DLL_THREAD_ATTACH
|
|
dw 041dh,0435h,043eh,0436h,0438h,0434h,0430h,043dh,043dh,043eh,0020h,043fh,0440h,0438h,043bh,0435h,0442h,0435h,043bh,0020h,0044h,004ch,004ch,005fh,0054h,0048h,0052h,0045h,0041h,0044h,005fh,0041h,0054h,0054h,0041h,0043h,0048h,0000h
|
|
prime2nums: ;Простые числа от 2 до 311
|
|
dw 02h,03h,05h,07h,0Bh,0Dh,11h,13h,17h,1Dh,1Fh,25h,29h,2Bh,2Fh,35h,3Bh,3Dh,43h,47h,49h,4Fh,53h,59h
|
|
dw 61h,65h,67h,6Bh,6Dh,71h,7Fh,83h,89h,8Bh,95h,97h,9Dh,0A3h,0A7h,0ADh,0B3h,0B5h,0BFh,0C1h,0C5h,0C7h,0D3h,0DFh
|
|
dw 0E3h,0E5h,0E9h,0EFh,0F1h,0FBh,101h,107h,10Dh,10Fh,115h,119h,11Bh,125h,133h,137h
|
|
|
|
DllDetata: ;Неожиданно прилетел DLL_PROCESS_DETACH
|
|
dw 041dh,0435h,043eh,0436h,0438h,0434h,0430h,043dh,043dh,043eh,0020h,043fh,0440h,0438h,043bh,0435h,0442h,0435h,\
|
|
043bh,0020h,0044h,004ch,004ch,005fh,0050h,0052h,004fh,0043h,0045h,0053h,0053h,005fh,0044h,0045h,0054h,0041h,0043h,0048h,0000h
|
|
|
|
prime_nums: ; 8 байт с простыми числами от 2 до 19
|
|
db 0 dup (8)
|
|
align 16
|
|
my3sqrt REAL8 0.3333333333333333333333333333
|
|
;xmminst dq 12232434,13342342342
|
|
xmmhash xmmword 0 dup (4); 4 Байта в которых хранится хэш
|
|
k_konst dd 0 dup (64) ;64 32-битных значения инициированных первыми 32 битами дробной части кубических корней от 2 о 311
|
|
myXMMSAVE xmmword 0 dup (10) ;глобальная переменная для сохранения/восстановления регистров XMM6-XMM15 (неизменяемые)
|
|
myRnSAVE dq 0 dup (4) ;глобальная переменная для сохранения/восстановления регистров R12-R15 (неизменяемые)
|
|
|
|
.code
|
|
DllMain proc hInstDLL:QWORD, reason:QWORD, unused:QWORD
|
|
;push rbp
|
|
;mov rbp,rsp
|
|
sub rsp,28h
|
|
.if edx==DLL_PROCESS_ATTACH ;Обрабатываю событие вызова DLL
|
|
call _isAvxSupported
|
|
pshufd xmm0,xmm0,10010011b ;Перераспределяет 32-битные qword'ы в xmm согласно битовой маске: 2 бита, числа от 0-3 сообщают
|
|
pshufd xmm0,xmm0,10010011b ;слева направо новое расположение qword'ов в регистре XMM. Например: 3-2-1-0 -> 2-1-0-3(10010011b)
|
|
pshufd xmm0,xmm0,10010011b
|
|
pshufd xmm0,xmm0,10010011b
|
|
mov eax,001020304h ;вычисляю Σ0
|
|
xor rcx,rcx
|
|
ror eax,2
|
|
xor ecx,eax
|
|
ror eax,11
|
|
xor ecx,eax
|
|
ror eax,9
|
|
xor ecx,eax
|
|
;вычисляю ключ
|
|
mov eax,001020304h
|
|
xor eax,ecx
|
|
mov edx,eax ; в EDX - ключ
|
|
mov eax,001020304h
|
|
xor eax,edx
|
|
;смотрю, подходит ли он для других чисел
|
|
mov eax,005040304h ;вычисляю Σ0
|
|
xor rcx,rcx
|
|
ror eax,2
|
|
xor ecx,eax
|
|
ror eax,11
|
|
xor ecx,eax
|
|
ror eax,9
|
|
xor ecx,eax
|
|
;Подставляю ключ из первого примера
|
|
mov eax,005040304h
|
|
xor eax,edx
|
|
lea rdx,LoadMsg ;Указатель на сообщение "DLL загружена"
|
|
.elseif edx==DLL_PROCESS_DETACH ;Обрабатываю событие закрытия DLL
|
|
lea rdx,UnloadMsg ;Указатель на сообщение "DLL выгружена"
|
|
.elseif edx==DLL_THREAD_ATTACH ;Обрабатываю событие создания треда в вызывающем процессе
|
|
;(ох и попило крови это событие: не обрабатывал, а по-умолчанию падало на другой обработчик)
|
|
;lea rdx,DllAtata ;Указатель на сообщение "неожиданно прилетел DLL_THREAD_ATTACH"
|
|
add rsp,28h ;восстанавливаю вершину стека
|
|
xor rax,rax ;возвращаю ноль
|
|
ret ;Выхожу
|
|
.elseif edx==DLL_THREAD_DETACH ;Обрабатываю событие закрытия треда в вызывающем процессе
|
|
;lea rdx,DllDetata ;Указатель на сообщение "Неожиданно прилетел DLL_PROCESS_DETACH"
|
|
add rsp,28h ;восстанавливаю вершину стека
|
|
xor rax,rax ;возвращаю ноль
|
|
ret ;Выхожу
|
|
.endif
|
|
mov r9d,MB_OK ;
|
|
jmp exit
|
|
DllMain Endp
|
|
TestHello proc
|
|
sub rsp,28h
|
|
lea rdx,HelloMsg
|
|
mov r9d,MB_OK + MB_ICONERROR
|
|
exit:: lea r8,AppName
|
|
xor rcx,rcx
|
|
call MessageBoxW
|
|
;mov rsp,rbp
|
|
;pop rbp
|
|
add rsp,28h
|
|
mov rax,TRUE
|
|
ret
|
|
TestHello endp
|
|
;Sha256 - Функция, принимающая в качестве параметра 1-Адрес хешируемого объекта;2-его полный размер; 3-Размер отрезка; 4-последний ли он?. Возвращаемое значение: NULL в случае успеха
|
|
Sha256 proc __fastcall
|
|
enter 128,0
|
|
|
|
leave
|
|
xor rax,rax
|
|
ret
|
|
Sha256 Endp
|
|
;Инициализация хэш функции, ввод исходных значений
|
|
Sha256Init proc __fastcall
|
|
LOCAL myInt64:QWORD ;Число для преобразования
|
|
LOCAL squareRoot:QWORD ;Корень
|
|
LOCAL delitel:QWORD ;делитель (равен 1 для извлечения дробной части числа)
|
|
LOCAL mnoz:QWORD;множитель для выведение целого числа
|
|
LOCAL myxmmword:XMMWORD
|
|
enter 8*8,0
|
|
lea rdx,prime_nums ;в RDX массив простых чисел
|
|
lea r8,xmmhash ;в R8 - адрес инициализированного хэша (его начальных значений)
|
|
mov rcx,8 ;в RCX количество повторений цикла. Для процессора нет разницы, обращаться к DL или к RDX, поэтому снижаю расходы приводя всё к единому размеру
|
|
mov rax,1373893702338282242
|
|
mov QWORD PTR [rdx],rax ; инициализирую простые числа от 2 до 19
|
|
loop1:
|
|
finit
|
|
mov al, BYTE PTR [rdx] ;беру текущее простое число
|
|
and rax,255
|
|
mov myInt64,rax
|
|
mov delitel,1 ;делитель 1 нужен для отсечения целой части, при делениии на 1 по модулю
|
|
mov rax,4294967296 ;множитель 2^32, нужен...\
|
|
mov QWORD PTR mnoz,rax ;...для сдвига дробной части на 32 бита
|
|
fild QWORD PTR mnoz ; сохраняю всё в стек FPU
|
|
fild QWORD PTR delitel
|
|
fild QWORD PTR myInt64
|
|
fsqrt ;извлекаю корень
|
|
fprem ;делю на 1 по модулю
|
|
fmul ST,ST(2) ;сдвигаю на 32
|
|
fisttp qword ptr squareRoot ;сохраняю для проверки
|
|
mov eax,dword ptr squareRoot ;сохраняю результат в хеше
|
|
mov dword ptr [r8],eax
|
|
add r8,4;сдвигаю указатель на хэш
|
|
inc rdx ;сдвигаю указатель на простое число
|
|
dec rcx
|
|
jnz loop1 ;цикл
|
|
; Далее, инициализирую константы (k) кубическим корнем ряда первых 64 простых числел от 2 до 311
|
|
lea rdx,prime2nums ;в RDX адресс массива простых числел
|
|
forxmm0: ;Заполняю регистр XMM0 значениями 4-х корней
|
|
mov r8,64 ;счётчик цикла
|
|
lea r9,k_konst ;указатель на буфер k_konst
|
|
loopxmm0:
|
|
mov cx, word ptr [rdx]; беру текущее простое число
|
|
and rcx,65535 ;обнуляю остальные биты
|
|
call z3sqrt ;вызываю процедуру рассчёта дробной части от кубического корня от числа в rcx
|
|
mov dword ptr [r9],eax ;сохраняю результат в буфер
|
|
add rdx,2 ;сдвигаю указатель на простое число
|
|
add r9,4 ;сдвигаю указатель на буфер k_konst
|
|
dec r8 ;уменьшаю счётчик
|
|
jnz loopxmm0 ;цикл
|
|
leave
|
|
ret
|
|
Sha256Init Endp
|
|
_isAvxSupported: ; extern "C" int isAvxSupported()
|
|
xor eax, eax
|
|
cpuid
|
|
cmp eax, 1 ; Поддерживает ли CPUID параметр eax = 1?
|
|
jb not_supported
|
|
mov eax, 1
|
|
cpuid
|
|
and ecx, 018000000h ; Проверяем, что установлены биты 27 (ОС использует XSAVE/XRSTOR)
|
|
cmp ecx, 018000000h ; и 28 (поддержка AVX процессором)
|
|
jne not_supported
|
|
xor ecx, ecx ; Номер регистра XFEATURE_ENABLED_MASK/XCR0 есть 0
|
|
xgetbv ; Регистр XFEATURE_ENABLED_MASK теперь в edx:eax
|
|
and eax, 110b
|
|
cmp eax, 110b ; Убеждаемся, что ОС сохраняет AVX регистры при переключении контекста
|
|
jne not_supported
|
|
mov eax, 1
|
|
ret
|
|
not_supported:
|
|
xor eax, eax
|
|
ret
|
|
z3sqrt proc __fastcall ;вынес вычисление кубического корня в процедуру. На входе, в rcx - простое число, на выходе, в rax 32 бита остатка.
|
|
LOCAL myInt64:QWORD ;локальная переменная для хранения простого числа
|
|
LOCAL delitel:QWORD ;делитель (равен 1 для извлечения дробной части числа)
|
|
LOCAL mnoz:QWORD;множитель для выведение целого числа
|
|
LOCAL result:QWORD ;результат
|
|
LOCAL regCR:word ;ячейка для сохренения регистра CR (FPU)
|
|
enter 5*8,0
|
|
mov myInt64,rcx ;сохраняю в переменную
|
|
mov delitel,1 ;единица для деления по модулю
|
|
mov rax,4294967296 ;множитель 2^32, нужен...\
|
|
mov QWORD PTR mnoz,rax ;...для сдвига дробной части на 32 бита
|
|
finit
|
|
fstcw regCR ;сохраняю регистр CR (FPU), для изменения значения бита округления
|
|
or word ptr regCR,3072 ;включаю 10 и 11 биты, сообщающие, что нужно округлять до нуля (в сторону нуля)
|
|
fldcw regCR ;записываю изменённые значения в регистра CR
|
|
fild QWORD PTR mnoz ; сохраняю всё в стек FPU
|
|
fild QWORD PTR delitel
|
|
fld QWORD PTR my3sqrt ;загружаю 1/3
|
|
fild QWORD PTR myInt64 ;текущее простое число
|
|
FYL2X ;получаю LN(x)
|
|
fld ST(0) ;Создаем еще одну копию LN(x)
|
|
frndint ;Округляем
|
|
fsubr st(0),st(1) ;ST(1)=z, ST(0)=z-trunc(z)
|
|
f2xm1 ;ST(1)=z, ST(0)=2**(z-trunc(z))-1
|
|
fld1
|
|
faddp ;ST(1)=z, ST(0)=2**(z-trunc(z))
|
|
fscale ;ST(1)=z, ST(0)=(2**trunc(z))*(2**(z-trunc(z)))=2**t
|
|
fxch st(1)
|
|
fstp st ;Результат остается на вершине стека ST(0)
|
|
fprem ;делю на 1 по модулю
|
|
fmul ST,ST(2) ;сдвигаю на 32
|
|
fisttp qword ptr result ;сохраняю результат
|
|
mov rax,result
|
|
leave
|
|
ret
|
|
z3sqrt endp
|
|
end |