Тимур,
отличная статья! Радуй нас своими находками чаще!
отличная статья! Радуй нас своими находками чаще!
Следуйте инструкциям в видео ниже, чтобы узнать, как установить наш сайт как веб-приложение на главный экран вашего устройства.
Примечание: Эта функция может быть недоступна в некоторых браузерах.
BOOL CryptProtectData( ;//<------- 0 = ошибка!
pDataIn dd 0 ;// линк на структуру DATA_BLOB, которая описывает данные для шифрования
ppszDataDescr dd 0 ;// 0, или линк на строковое описание шифруемых данных
pOptionalEntropy dd 0 ;// 0, или линк на DATA_BLOB, с паролем или доп.энтропией (соль)
pvReserved dd 0 ;// 0
pPromptStruct dd 0 ;// 0, или линк на структуру CRYPTPROTECT_PROMPTSTRUCT (подсказки)
dwFlags dd 0 ;// 0, или флаги управления процессом шифрования
pDataOut dd 0 ;// линк на структуру DATA_BLOB, в которую функция вернёт зашифрованные данные
);
;//************************************************
struct DATA_BLOB
dwDataSize dd 0 ;// размер данных
pData dd 0 ;// указатель (pointer) на данные
ends
struct DPAPI_DATABLOB
dwVersion dd 0 ;// версия структуры
ProvGuid db 16 dup(0) ;// Guid крипто-провайдера
MasterKeyVersion dd 0 ;// версия ключа
MasterKeyGuid db 16 dup(0) ;// Guid ключа
dwFlags dd 0 ;// флаги
dwDataDescLen dd 0 ;// размер аргумента(2) "DataDescr" функции CryptProtectData()
szDataDesc db ? ;// ^^значение аргумента.
algCrypt dd 0 ;// алгоритм шифрования (например AES)
cryptAlgLen dd 0 ;// ^^размер ключа (например 256, итого AES-256)
dwSaltLen dd 0 ;// размер соли хеширования
pSalt db ? ;// ^^значение соли
dwHmacKeyLen dd 0 ;// размер "кода-аутентификации" HMAC
pHmac db ? ;// ^^значение HMAC
algHash dd 0 ;// алгоритм хеширования (например SHA)
hashAlgLen dd 0 ;// ^^размер блока (например 512, итого SHA-512)
dwHmac2KeyLen dd 0 ;// см.выше
pHmac2 db ? ;// ^^^
dwDataLen dd 0 ;// размер зашифрованных данных
pData db ? ;// ^^данные
dwSignLen dd 0 ;// размер сигнатуры
pSign db ? ;// ^^сигнатура
ends
;// Константы алгоритмов
;//----------------------------------
CALG_DES = 0x00006601 ;//<--- шифрование
CALG_3DES = 0x00006603
CALG_AES = 0x00006611
CALG_AES_128 = 0x0000660e
CALG_AES_192 = 0x0000660f
CALG_AES_256 = 0x00006610
CALG_RC2 = 0x00006602
CALG_RC4 = 0x00006801
CALG_RC5 = 0x0000660d
CALG_HASH_REPLACE_OWF = 0x0000800b ;//<--- хеширование
CALG_HMAC = 0x00008009
CALG_MAC = 0x00008005
CALG_MD2 = 0x00008001
CALG_MD4 = 0x00008002
CALG_MD5 = 0x00008003
CALG_SHA = 0x00008004
CALG_SHA1 = 0x00008004
CALG_SHA256 = 0x0000800c
CALG_SHA384 = 0x0000800d
CALG_SHA512 = 0x0000800e
CALG_SSL3_SHAMD5 = 0x00008008
CALG_TLS1_PRF = 0x0000800a
;//----------------------------------
;// Таблица алгоритмов шифрования
;//----------------------------------
CryptTable dd 0x6603,calgDes,0x6610,calgAes
dd 0x6801,calgRc4,0x660d,calgRc5
calgDes db '3DES',0
calgAes db 'AES.256',0
calgRc4 db 'RC4',0
calgRc5 db 'RC5',0
format pe console
entry start
;//------------
section '.inc' data readable
include 'win32ax.inc'
include 'equates\dpapi.inc'
;//------------
.data
inBlob CRYPT_BLOB ;// структура с исходными данными
outBlob CRYPT_BLOB ;// сюда получим результат
hndl dd 0
dwRet dd 0
buff db 0
;//------------
.code
start: invoke SetConsoleTitle,<'*** DPAPI Crypt/Decrypt ***',0>
;//-- Запрос на ввод пароля и узнаём его длину
cinvoke printf,<10,' Type password....: ',0>
cinvoke scanf,<'%s',0>,buff
invoke lstrlen,buff
;//-- Оформляем входную структуру DATA_BLOB и шифруем пароль!
mov [inBlob.dataSize],eax
mov [inBlob.pData],buff
invoke CryptProtectData,inBlob,0,0,0,0,0,outBlob
;//-- Получили выходную структуру DATA_BLOB – покажем инфу из неё
mov ecx,[outBlob.dataSize]
mov esi,[outBlob.pData]
push esi ecx
cinvoke printf,<10,' BLOB data size...: %d byte',\
10,' BLOB data offset.: 0x%08x',10,\
10,' DPAPI BLOB dump...............',10,10,0>,ecx,esi
pop ecx esi
call PrintHexDump
;//************************************************************
;//-- Проецируем структуру DPAPI_DATABLOB на полученные данные,
;//-- и выводим их на консоль.
cinvoke printf,<10,10,' Decode BLOB dump..............',0>
mov esi,[outBlob.pData]
mov eax,[esi + DPAPI_DATABLOB.dwVersion]
cinvoke printf,<10,10,' DPAPI version...: %d',0>,eax
mov esi,[outBlob.pData]
push esi esi
add esi,DPAPI_DATABLOB.ProvGuid
invoke StringFromGUID2,esi,buff,dwRet
cinvoke printf,<10,' CryptProv Guid..: %ls',0>,buff
pop esi
add esi,DPAPI_DATABLOB.MasterKeyGuid
invoke StringFromGUID2,esi,buff,dwRet
cinvoke printf,<10,' MasterKey Guid..: %ls',0>,buff
pop esi
mov eax,[esi + DPAPI_DATABLOB.dwFlags]
cinvoke printf,<10,' dwProtect Flag..: 0x%08x',10,0>,eax
mov esi,[outBlob.pData]
mov eax,[esi + DPAPI_DATABLOB.dwDataDescLen]
push esi eax
cinvoke printf,<10,' dwDataDesc len..: %d',\
10,' DataDesc......: ',0>,eax
pop ecx esi
add esi,DPAPI_DATABLOB.szDataDesc
push esi ecx
call PrintHexString
pop ecx esi
add esi,ecx ;//<--- вычисляем динамически адрес сл.поля
lodsd
push esi
mov ebx,eax
mov esi,CryptTable
mov ecx,4
call GetAlgorithm
cinvoke printf,<10,' algCrypt........: 0x%08x = %s',0>,ebx,edx
pop esi
add esi,4
lodsd
push eax esi eax esi
cinvoke printf,<10,' dwSalt len......: %d',\
10,' Salt..........: ',0>,eax
pop esi ecx
or ecx,ecx
je @f ;//<---- пропустить, если поле пустое
call PrintHexString
@@: pop esi eax
add esi,eax
lodsd
push eax esi eax esi
cinvoke printf,<10,' dwHmacKey len...: %d',\
10,' HmacKey.......: ',0>,eax
pop esi ecx
or ecx,ecx
je @f
call PrintHexString
@@: pop esi eax
add esi,eax
lodsd
push esi
mov ebx,eax
mov esi,HashTable
mov ecx,13
call GetAlgorithm
cinvoke printf,<10,' algHash.........: 0x%08x = %s',0>,ebx,edx
pop esi
add esi,4
lodsd
push eax esi eax esi
cinvoke printf,<10,\
10,' dwHmac2Key len..: %d',\
10,' Hmac2Key......: ',0>,eax
pop esi ecx
or ecx,ecx
je @f
call PrintHexString
@@: pop esi eax
add esi,eax
lodsd
push eax esi eax esi
cinvoke printf,<10,\
10,' dwCryptData len.: %d',\
10,' CryptData.....: ',0>,eax
pop esi ecx
or ecx,ecx
je @f
call PrintHexString
@@: pop esi eax
add esi,eax
lodsd
push eax esi
cinvoke printf,<10,\
10,' dwSign len......: %d',\
10,' Signature.....: ',0>,eax
pop esi ecx
or ecx,ecx
je @exit
call PrintHexString
@exit: cinvoke _getch ;//<---- GAME OVER!!! ------------//
cinvoke exit,0
;//------------
;//----- Процедуры вывода дампа на консоль --------------
;//----- на входе: ESI = указатель на данные, ECX = длина
proc PrintHexString
mov ebp,32 ;// кол-во байт в строке
@@: or ebp,ebp
jnz @miss0
push ecx
cinvoke printf,<10,20 dup(' '),0>
pop ecx
mov ebp,32
@miss0: xor eax,eax
lodsb
push ecx esi
cinvoke printf,<'%02x',0>,eax ;//<--- без разделителя байт
pop esi ecx
dec ebp
loop @b
ret
endp
proc PrintHexDump
mov ebp,16
@@: or ebp,ebp
jnz @miss1
push ecx
cinvoke printf,<10,0>
pop ecx
mov ebp,16
@miss1: xor eax,eax
lodsb
push ecx esi ebp
cinvoke printf,<' %02x',0>,eax ;//<--- с разделителем байт
pop ebp esi ecx
dec ebp
loop @b
ret
endp
;//----- Процедура поиска алгоритмов --------------
;//----- на входе: EBX = код алгоритма, ESI = указатель на таблицу, ECX = длина таблицы
;//----- на выходе: EDX = указатель на строку с именем (см.инклуд DPAPI.INC)
proc GetAlgorithm
mov edx,unk
@findAlgo:
lodsd
cmp ebx,eax
jne @f
mov edx,[esi]
jmp @foundAlgo
@@: add esi,4
loop @findAlgo
@foundAlgo: ret
endp
;//------------
section '.idata' import data readable
library kernel32,'kernel32.dll',msvcrt,'msvcrt.dll',\
crypt32,'crypt32.dll',ole32,'ole32.dll'
import ole32,StringFromGUID2,'StringFromGUID2'
include 'api\kernel32.inc'
include 'api\crypt32.inc'
include 'api\msvcrt.inc'
{df9d8cd0-1501-11d1-8c7a-00c04fc297eb} – это системный провайдер Win по-умолчанию, реализованный в библиотеке Psbase.dll. Если этот провайдер нас чем-то не устраивает, другого можно выбрать в ветке реестра HKLM\Software\Microsoft\Cryptography\Protect\Providers. Далее следует идентификатор мастер-ключа, сброшенный флаг в предпоследнем аргументе функции CryptProtectData(), и дефолтное значение Unicode-нуль второго аргумента "pszDataDesc".C:\Users\%USER%\AppData\Roaming\Microsoft\Protect\%SID%\, где SID – это директория, имя которой совпадает с описателем безопасности SID пользователя. В доках эту папку называют ещё "MasterKey-Storage-Folder" и в ней складируются буквально все, когда-либо сгенерированные системой ключи. Имя активного на данный момент ключа и срок его действия хранится в файле Preferred, который лежит рядом с ключами – первые 16-байт в нём Guid ключа, а оставшиеся 8-байт – дата в формате FILETIME. Файлы ключей именуются без расширения согласно присвоенным им Guid, и на моей машине выглядят так:struct MASTERKEY_HEADER
dwVersion dd 0 ;// версия файла с ключом
dwReserved1 dq 0 ;//
szGuid db 72 dup(0) ;// Юникоде-строка с GUID'ом ключа
dwUnused dq 0 ;//
dwPolicy dd 0 ;// поле с флагами
dwUserKeySize dd 0 ;// размер мастер-ключа юзера
dwLocalEncKeySize dd 0 ;// размер резервного ключа Backup
dwLocalKeySize dd 0 ;// размер локального ключа, или поля CREDHIST
dwDomainKeySize dd 0 ;// резервная копия ключа домена
dwReserved2 db 16 dup(0) ;//
;//-- MasterKey info
Version dd 0 ;// версия слота
pSalt db 16 dup(0) ;// значение соли, добавленной к ключу
dwRounds dd 0 ;// счётчик итераций в алго генерации ключа PBKDF2
HmacAlgId dd 0 ;// алго проверки целостности данных
CryptAlgId dd 0 ;// алго шифрования ключа
pKey db ? ;// зашифрованный мастер-ключ!
ends
struct WIN32_FIND_DATA
dwFileAttributes dd 0 ;// атрибуты файла/папки
ftCreationTime FILETIME ;// время создания
ftLastAccessTime FILETIME ;// время последнего доступа
ftLastWriteTime FILETIME ;// время последнего изменения
nFileSizeHigh dd 0 ;// размер файла
nFileSizeLow dd 0 ;// ^^^
dwReserved dq 0 ;//
cFileName rb 256 ;// Win-имя файла/папки <----- наш клиент!
cAlternateFileName rb 14 ;// DOS-имя в формате 8.3
dwFileType dd 0 ;// 0
dwCreatorType dd 0 ;// 0
wFinderFlags dw 0 ;// 0
ends
S-1-5-21-xxxxx, то первые четыре символа "S-1-" можно использовать в качестве маски для поиска. Дружелюбную дату и время из 8-байтной структуры FILETIME можно получить функцией FileTimeToSystemTime(), а папку юзера Roaming – функцией SHGetFolderPathA() с флагом CSIDL_APPDATA. Вот пример такого алго:format pe console
entry start
;//------------
section '.inc' data readable
include 'win32ax.inc'
include 'equates\dpapi.inc'
;//------------
.data
userPath db 512 dup(0)
keyPath db '\Microsoft\Protect\*.*',0
preferred db '\preferred',0
fd WIN32_FIND_DATA
sysTime SYSTEMTIME
hndl dd 0
dwRet dd 0
fName db 64 dup(0)
buff db 0
;//------------
.code
start: invoke SetConsoleTitle,<'*** DPAPI MasterKey info ***',0>
;//-- Формируем путь до файла "Master-Key"
invoke SHGetFolderPathA,0,CSIDL_APPDATA,0,0,userPath
invoke lstrcat,userPath,keyPath
;//-- Вычисляем имя папки SID, с ключами пользователя
invoke FindFirstFile,userPath,fd
mov [hndl],eax
@find0: cmp dword[fd.cFileName],'S-1-'
je @found0
invoke FindNextFile,[hndl],fd
or eax,eax
jnz @find0
cinvoke printf,<10,' ERROR! KeyDir not found.',0>
jmp @exit
;//-- Каталог нашли – покажем SID юзера (имя папки)
@found0: invoke FindClose,[hndl]
cinvoke printf,<10,' User SID......: %s',0>,fd.cFileName
;//-- Добавляем к пути имя папки, чтобы открыть её
mov edi,userPath
xor ecx,ecx
dec ecx
mov al,'*'
repne scasb
dec edi
mov byte[edi],0
invoke lstrcat,userPath,fd.cFileName
invoke lstrcat,userPath,preferred
;//-- Прочитать из папки SID файл "Preferred"
invoke _lopen,userPath,0
or eax,eax ;// ошибка?
jns @next
cinvoke printf,<10,' ERROR! Preferred file not found.',0>
jmp @exit
@next: push eax
invoke _lread,eax,buff,24 ;// читаем файл в буфер
pop eax
invoke _lclose,eax
;//-- Покажем время действия мастер-ключа, из последних 8-байт файла "Preferred"
mov eax,buff
add eax,24-8
invoke FileTimeToSystemTime,eax,sysTime
movzx ecx,word[sysTime.wYear]
movzx ebx,word[sysTime.wMonth]
movzx eax,word[sysTime.wDay]
movzx edx,word[sysTime.wHour]
movzx esi,word[sysTime.wMinute]
cinvoke printf,<10,' Key valid time: %02d.%02d.%d %02d:%02d',0>,\
eax,ebx,ecx,edx,esi
;//-- Вытащим из файла "Preferred" GUID активного ключа,
;//-- и переведём его из Unicode в ANSI
invoke StringFromGUID2,buff,fName,dwRet
mov esi,fName
mov edi,esi
mov byte[esi],'\'
@@: lodsw
cmp al,'}'
je @f
stosb
jmp @b
@@: mov byte[edi],0
;//-- Наконец добавим к пути Guid в виде имени файла-ключа
invoke lstrlen,userPath
mov esi,userPath
add esi,eax
sub esi,10
mov byte[esi],0
invoke lstrcat,userPath,fName
;//-- Читаем файл мастер-ключа в свой буфер
invoke _lopen,userPath,0
or eax,eax ;// ошибка?
jns @open
cinvoke printf,<10,' ERROR! MasterKey file not openned.',0>
jmp @exit
@open: push eax
invoke _lread,eax,buff,468
pop eax
invoke _lclose,eax
;//*******************************************************
;//-- Проецируем структуру MASTERKEY_HEADER на данные файла-ключа,
;//-- и выводим всю инфу на консоль.
cinvoke printf,<10,10,' MasterKey HEADER ****',0>
mov esi,buff
push esi
mov eax,[esi + MASTERKEY_HEADER.dwVersion]
cinvoke printf,<10,' dwVersion........: 0x%08x = %d',0>,eax,eax
pop esi
add esi,MASTERKEY_HEADER.szGuid
cinvoke printf,<10,' szMasterKeyGuid..: {%ls}',0>,esi
mov esi,buff
mov eax,[esi + MASTERKEY_HEADER.dwPolicy]
mov ebx,[esi + MASTERKEY_HEADER.dwUserKeySize]
mov ecx,[esi + MASTERKEY_HEADER.dwLocalEncKeySize]
mov edx,[esi + MASTERKEY_HEADER.dwLocalKeySize]
mov edi,[esi + MASTERKEY_HEADER.dwDomainKeySize]
cinvoke printf,<10,' dwFlags..........: 0x%08x = %d',\
10,' dwMasterKey len..: 0x%08x = %d',\
10,' dwBackupKey len..: 0x%08x = %d',\
10,' dwCredHist len..: 0x%08x = %d',\
10,' dwDomainKey len..: 0x%08x = %d',0>,\
eax,eax,ebx,ebx,ecx,ecx,edx,edx,edi,edi
cinvoke printf,<10,10,' MasterKey INFO ******',0>
mov esi,buff
push esi
mov eax,[esi + MASTERKEY_HEADER.Version]
cinvoke printf,<10,' dwVersion........: 0x%08x = %d',\
10,' Salt (16-bytes)..: ',0>,eax,eax
pop esi
add esi,MASTERKEY_HEADER.pSalt
mov ecx,16
call PrintHexString
mov esi,buff
mov eax,[esi + MASTERKEY_HEADER.dwRounds]
cinvoke printf,<10,' PBKDF2 rounds....: 0x%08x = %d',0>,eax,eax
mov esi,buff
mov ebx,[esi + MASTERKEY_HEADER.HMACAlgId]
mov ecx,13
mov esi,HashTable
call GetAlgorithm
cinvoke printf,<10,' Hash algorithm..: 0x%08x = %s',0>,ebx,edx
mov esi,buff
mov ebx,[esi + MASTERKEY_HEADER.CryptAlgId]
mov ecx,4
mov esi,CryptTable
call GetAlgorithm
cinvoke printf,<10,' Crypt algorithm..: 0x%08x = %s',\
10,10,' Master-Key hash value............. ',10,10,0>,,ebx,edx
mov esi,buff
mov ecx,[esi + MASTERKEY_HEADER.dwUserKeySize]
add esi,MASTERKEY_HEADER.pKey
call PrintHexString
@exit: cinvoke _getch
cinvoke exit,0
;//------------
;//----- Процедура вывода дампа на консоль --------------
;//----- на входе: ESI = указатель на данные, ECX = длина
proc PrintHexString
mov ebp,16
@@: or ebp,ebp
jnz @miss
push ecx
cinvoke printf,<10,0>
pop ecx
mov ebp,16
@miss: xor eax,eax
lodsb
push ecx esi ebp
cinvoke printf,<' %02x',0>,eax
pop ebp esi ecx
dec ebp
loop @b
ret
endp
;//----- Процедура поиска алгоритмов --------------
;//----- на входе: EBX = код алгоритма, ESI = указатель на таблицу, ECX = длина таблицы
;//----- на выходе: EDX = указатель на строку с именем (см.инклуд DPAPI.INC)
proc GetAlgorithm
mov edx,unk
@findAlgo:
lodsd
cmp ebx,eax
jne @f
mov edx,[esi]
jmp @foundAlgo
@@: add esi,4
loop @findAlgo
@foundAlgo: ret
endp
;//------------
section '.idata' import data readable
library kernel32,'kernel32.dll',shell32,'shell32.dll',\
ole32,'ole32.dll',msvcrt,'msvcrt.dll'
import ole32,StringFromGUID2,'StringFromGUID2'
include 'api\kernel32.inc'
include 'api\shell32.inc'
include 'api\msvcrt.inc'
Статья читается полностью. Тезисы со ссылками на разделы появятся позже.
Комментарии
4