Здравствуйте, на просторах интернета я нашёл программу, которая зашифровывает и расшифровывает строку с помощью CryptProtectData и CryptUnprotectData. Я попробовал переписать её под 64 бита. Но в моей версии после выполнения CryptUnprotectData я получал ошибку 87(invalid_argument). В чём я ошибся? Оригинальная 32 битная программа: Code (ASM): include 'win32ax.inc' entry main szData db 'paSSword',0 DataSize = $ - szData main: mov [datain.pbData], szData mov [datain.cbData], DataSize invoke CryptProtectData, datain, 0, 0, 0, 0, 0, dataout cinvoke wsprintf,buf,PASS,[dataout.pbData] invoke MessageBox,0,buf,cap,MB_OK invoke CryptUnprotectData, dataout, 0, 0, 0, 0, 0, datain cinvoke wsprintf,buf,PASS,[datain.pbData] invoke MessageBox,0,buf,cap,MB_OK invoke ExitProcess,0 section '.data' data readable writeable struct DATA_BLOB cbData dd ? pbData dd ? ends datain DATA_BLOB dataout DATA_BLOB cap db 'Result',0 PASS db 'Pass: %s',10,13,0 buf db 64 dup (?) section '.idata' import data readable writeable library kernel32,'KERNEL32.DLL',\ user32,'USER32.DLL',\ Crypt32, 'Crypt32.dll' import Crypt32,\ CryptUnprotectData, 'CryptUnprotectData',\ CryptProtectData,'CryptProtectData' include 'api\kernel32.inc' include 'api\user32.inc' Моя 64 битная программа: Code (ASM): format PE64 GUI include 'C:\FASM\INCLUDE\win64ax.inc' entry main szData db 'paSSword',0 DataSize = $ - szData main: mov [datain.pbData], szData mov [datain.cbData], DataSize sub rsp, 8 invoke CryptProtectData, datain, 0, 0, 0, 0, 0, dataout cinvoke wsprintf,buf,PASS,[dataout.pbData] invoke MessageBox,0,buf,cap,MB_OK invoke SetLastError, 0 mov eax, [dataout.pbData] invoke CryptUnprotectData, dataout, 0, 0, 0, 0, 0, datain invoke GetLastError mov eax, [datain.pbData] mov eax, [datain.cbData] cinvoke wsprintf,buf,PASS,[datain.pbData] invoke MessageBox,0,buf,cap,MB_OK invoke ExitProcess,0 section '.data' data readable writeable struct DATA_BLOB cbData dd ? pbData dd ? ends datain DATA_BLOB dataout DATA_BLOB cap db 'Result',0 PASS db 'Pass: %s',10,13,0 buf db 64 dup (?) section '.idata' import data readable writeable library kernel32,'KERNEL32.DLL',\ user32,'USER32.DLL',\ Crypt32, 'Crypt32.dll' import kernel32,\ GetLastError, 'GetLastError',\ SetLastError, 'SetLastError' import Crypt32,\ CryptUnprotectData, 'CryptUnprotectData',\ CryptProtectData,'CryptProtectData' include 'C:\FASM\INCLUDE\api\kernel32.inc' include 'C:\FASM\INCLUDE\api\user32.inc'
Читаем описание функции CryptUnprotectData: DATA_BLOB *pDataIn - A pointer to a DATA_BLOB structure that holds the encrypted data. The DATA_BLOB structure's cbData member holds the length of the pbData member's byte string that contains the text to be encrypted. То есть в качестве аргумента должен передаваться УКАЗАТЕЛЬ на входную структуру DATA_BLOB (на выходную в том числе). Теперь, внимание, вопрос: как вы дали понять компилятору, что необходимо использовать именно указатель на структуру, а не структуру целиком? (Подсказка: для этих целей в языке ASMЪ предусмотрены ADDR и OFFSET) А вот куда их вставить - домашнее задание. P.S. Данную практику необходимо распространить на все вызываемые функции во избежание косяков (ЕБ**ЕЙ НЕВЕДОМОЙ Х**НИ) в будущем.
HESH, возможно, я чего-то не понял и ошибаюсь, но в CryptProtect(Unprotect)Data передаётся именно указатель на начало этой структуры
Ты все правильно понял, в функцию передается ИМЕННО УКАЗАТЕЛЬ на структуру, предварительно инициализированную. По скрину дебаггера видно, что первые 2 строки кода - инициализация этой структуры, но указатель на струкуру (судя по листингу она находится по адресу 401000) фигурирует только в инструкции mov rcx, 401000. В стек это значение перед вызовом функции CryptProtectData НЕ ПОПАДАЕТ ни через PUSH ни через mov qword [RSP+...], rcx и это не есть TRUE.
HESH, По скрину чуть ниже видно, что в функцию передаётся указатель на выходную структуру(401008) командой mov qword ptr ss:[rsp+30], 401008 --- Сообщение объединено, Jul 26, 2019 --- HESH, а первое значение в функцию передаётся через rcx(fastcall). Или я чего-то не понимаю?
Не уверен, отладчика под рукой нету - только вечером точнее сказать смогу. Но если хочешь, попробуй зайти в тело функции и посмотреть, допустима ли передача аргумента через rcx или после пролога CryptProtectData читает входной аргумент из стека. [MS]: The __fastcall calling convention specifies that arguments to functions are to be passed in registers, when possible. This calling convention only applies to the x86 architecture.
Ок, тогда смотри, что ты имеешь в выходной структуре по результатам выполнения функции. Заполняется ли она, данные защищаются ? Если да - тогда иди к UnprotectData.
Довольно необычно, функция добавляет к указателю на структуру 8 байт(т.е переступает её) и сравнивает значение с нулём, после этого идёт устанавливать ошибку 87(invalid_argument)
У тебя структура DATA_BLOB имеет в своем составе 2 поля: размер данных и указатель на их начало. Ну если поле размера теоретически может иметь размер dword, то второе поле (указатель) в x64 обязан иметь размер QWORD, так что есть подозрение, что объявление самой структуры неверно. Если руководствоваться логикой, то размер этой структуры в x64 должен быть никак не меньше sizeof(dword)+ sizeof(qword). Скорее всего, структура имеет 2 поля по QWORD. Проверь объявление этой структуры в заголовочных файлах и попробуй назначить ее членам другие размеры, как я сказал ранее.