Jump to content
funkey

CryptProtectData & CryptUnprotectData

Recommended Posts

funkey

Hello,

I wrapped the two functions CryptProtectData and CryptUnprotectData to protect passwords.

MSDN says: Typically, only a user with the same logon credential as the user who encrypted the data can decrypt the data. In addition, the encryption and decryption usually must be done on the same computer.

For detailed information visit MSDN:

* CryptProtectData:     http://msdn.microsoft.com/en-us/library/aa380261(v=vs.85).aspx

* CryptUnprotectData: http://msdn.microsoft.com/en-us/library/aa380882(v=vs.85).aspx

I hope that there are no memory leaks, if you find one, please tell me!

Have fun!!!

#include <WinAPI.au3>

;When this flag is set, it associates the data encrypted with the current computer instead of with an individual user.
;Any user on the computer on which CryptProtectData is called can use CryptUnprotectData to decrypt the data.
Global Const $CRYPTPROTECT_LOCAL_MACHINE = 0x4

;This flag is used for remote situations where presenting a user interface (UI) is not an option. When this flag is set
;and a UI is specified for either the protect or unprotect operation, the operation fails and GetLastError returns the ERROR_PASSWORD_RESTRICTION code.
Global Const $CRYPTPROTECT_UI_FORBIDDEN = 0x1

;This flag generates an audit on protect and unprotect operations.
Global Const $CRYPTPROTECT_LOCAL_AUDIT = 0x10

Global Const $CRYPTPROTECT_VERIFY_PROTECTION = 0x40

;This flag is used to provide the prompt for the protect phase.
Global Const $CRYPTPROTECT_PROMPT_ON_PROTECT = 0x2

;This flag can be combined with CRYPTPROTECT_PROMPT_ON_PROTECT to enforce the UI (user interface) policy of the caller.
;When CryptUnprotectData is called, the dwPromptFlags specified in the CryptProtectData call are enforced.
Global Const $CRYPTPROTECT_PROMPT_ON_UNPROTECT = 0x1


Global Const $ERROR_INVALID_DATA = 13

Global Const $tagDATA_BLOB = "DWORD cbData;ptr pbData;"
Global Const $tagCRYPTPROTECT_PROMPTSTRUCT = "DWORD cbSize;DWORD dwPromptFlags;HWND hwndApp;ptr szPrompt;"

Global $hDLL_CryptProtect = DllOpen("crypt32.dll")

Global $sString2Hide = "This is a test string to protect!"

Global $bData, $sData, $sDesc = ""

$bData = _CryptProtectData($sString2Hide, "Some information")
ConsoleWrite("Error protecting: " & @error & " - " & @extended & @LF)
ConsoleWrite("Protected data: " & $bData & @LF)

$sData = _CryptUnprotectData($bData, $sDesc)
ConsoleWrite("Error unprotecting: " & @error & " - " & @extended & @LF)
ConsoleWrite("Unprotected string: " & $sData & @LF)
ConsoleWrite("Unprotected description: " & $sDesc & @LF)

ConsoleWrite(@LF & @LF)

$bData = _CryptProtectData($sString2Hide, "Some other information", "pass")
ConsoleWrite("Error protecting: " & @error & " - " & @extended & @LF)
ConsoleWrite("Protected data: " & $bData & @LF)

$sData = _CryptUnprotectData($bData, $sDesc, "")
ConsoleWrite("Error unprotecting: " & @error & " - " & @extended & @LF)
ConsoleWrite("Unprotected string: " & $sData & @LF)
ConsoleWrite("Unprotected description: " & $sDesc & @LF)

ConsoleWrite(@LF & @LF)

$bData = _CryptProtectData($sString2Hide, "Some other information", "pwd")
ConsoleWrite("Error protecting: " & @error & " - " & @extended & @LF)
ConsoleWrite("Protected data: " & $bData & @LF)

$sData = _CryptUnprotectData($bData, $sDesc, "pwd")
ConsoleWrite("Error unprotecting: " & @error & " - " & @extended & @LF)
ConsoleWrite("Unprotected string: " & $sData & @LF)
ConsoleWrite("Unprotected description: " & $sDesc & @LF)

ConsoleWrite(@LF & @LF)


Global $sPromptString = "Data protection will be done"
Global $tPromptString = DllStructCreate("wchar szPrompt[256]")
DllStructSetData($tPromptString, "szPrompt", $sPromptString)

Global $tPrompt = DllStructCreate($tagCRYPTPROTECT_PROMPTSTRUCT)
DllStructSetData($tPrompt, "cbSize", DllStructGetSize($tPrompt))
DllStructSetData($tPrompt, "dwPromptFlags", BitOR($CRYPTPROTECT_PROMPT_ON_PROTECT, $CRYPTPROTECT_PROMPT_ON_UNPROTECT))
DllStructSetData($tPrompt, "szPrompt", DllStructGetPtr($tPromptString))

$bData = _CryptProtectData($sString2Hide, "Protection example with Gui", "pwd", 0, DllStructGetPtr($tPrompt))
ConsoleWrite("Error protecting: " & @error & " - " & @extended & @LF)
ConsoleWrite("Protected data: " & $bData & @LF)

$sPromptString = "Data unprotection will be done"
DllStructSetData($tPromptString, "szPrompt", $sPromptString)

$sData = _CryptUnprotectData($bData, $sDesc, "pwd", 0, DllStructGetPtr($tPrompt))
ConsoleWrite("Error unprotecting: " & @error & " - " & @extended & @LF)
ConsoleWrite("Unprotected string: " & $sData & @LF)
ConsoleWrite("Unprotected description: " & $sDesc & @LF)

DllClose($hDLL_CryptProtect)



;http://msdn.microsoft.com/en-us/library/aa380261(v=vs.85).aspx
Func _CryptProtectData($sString, $sDesc = "", $sPwd = "", $iFlag = 0, $pPrompt = 0)
    ;funkey 2014.08.11th
    Local $aRet, $iError, $tEntropy, $tDesc, $pEntropy = 0, $pDesc = 0
    Local $tDataIn = _DataToBlob($sString)
    If $sPwd <> "" Then
        $tEntropy = _DataToBlob($sPwd)
        $pEntropy = DllStructGetPtr($tEntropy)
    EndIf

    If $sDesc <> "" Then
        $tDesc = DllStructCreate("wchar desc[" & StringLen($sDesc) + 1 & "]")
        DllStructSetData($tDesc, "desc", $sDesc)
        $pDesc = DllStructGetPtr($tDesc)
    EndIf

    Local $tDataBuf = DllStructCreate($tagDATA_BLOB)

    $aRet = DllCall($hDLL_CryptProtect, "BOOL", "CryptProtectData", "struct*", $tDataIn, "ptr", $pDesc, "ptr", $pEntropy, "ptr", 0, "ptr", $pPrompt, "DWORD", $iFlag, "struct*", $tDataBuf)
    $iError = @error

    _WinAPI_LocalFree(DllStructGetData($tDataIn, "pbData"))

    If $sPwd <> "" Then _WinAPI_LocalFree(DllStructGetData($tEntropy, "pbData"))
    If $iError Then Return SetError(1, 0, "")
    If $aRet[0] = 0 Then Return SetError(2, _WinAPI_GetLastError(), "")

    Local $tDataOut = DllStructCreate("byte data[" & DllStructGetData($tDataBuf, "cbData") & "]", DllStructGetData($tDataBuf, "pbData"))
    Local $bData = DllStructGetData($tDataOut, "data")

    _WinAPI_LocalFree(DllStructGetData($tDataBuf, "pbData"))

    Return $bData
EndFunc   ;==>_CryptProtectData

;http://msdn.microsoft.com/en-us/library/aa380882(v=vs.85).aspx
Func _CryptUnprotectData($bData, ByRef $sDesc, $sPwd = "", $iFlag = 0, $pPrompt = 0)
    ;funkey 2014.08.11th
    Local $aRet, $iError, $tEntropy, $pEntropy = 0
    Local $tDataIn = _DataToBlob($bData)
    $sDesc = ""

    If $sPwd <> "" Then
        $tEntropy = _DataToBlob($sPwd)
        $pEntropy = DllStructGetPtr($tEntropy)
    EndIf

    Local $tDataBuf = DllStructCreate($tagDATA_BLOB)
    Local $tDesc = DllStructCreate("ptr desc")
    Local $pDesc = DllStructGetPtr($tDesc)

    $aRet = DllCall($hDLL_CryptProtect, "BOOL", "CryptUnprotectData", "struct*", $tDataIn, "ptr*", $pDesc, "ptr", $pEntropy, "ptr", 0, "ptr", $pPrompt, "DWORD", $iFlag, "struct*", $tDataBuf)
    $iError = @error

    _WinAPI_LocalFree(DllStructGetData($tDataIn, "pbData"))

    If $sPwd <> "" Then _WinAPI_LocalFree(DllStructGetData($tEntropy, "pbData"))
    If $iError Then Return SetError(1, 0, "")
    If $aRet[0] = 0 Then Return SetError(2, _WinAPI_GetLastError(), "")

    Local $tDataOut = DllStructCreate("char data[" & DllStructGetData($tDataBuf, "cbData") & "]", DllStructGetData($tDataBuf, "pbData"))
    Local $sData = DllStructGetData($tDataOut, "data")

    Local $aLen = DllCall("msvcrt.dll", "UINT:cdecl", "wcslen", "ptr", $aRet[2])
    Local $tDesc = DllStructCreate("wchar desc[" & $aLen[0] + 1 & "]", $aRet[2])
    $sDesc = DllStructGetData($tDesc, "desc")

    _WinAPI_LocalFree($aRet[2])
    _WinAPI_LocalFree(DllStructGetData($tDataBuf, "pbData"))

    Return $sData
EndFunc   ;==>_CryptUnprotectData


;Creates a DATA_BLOB structure where the function stores the decrypted data.
;When you have finished using the DATA_BLOB structure, free its pbData member by calling the _WinAPI_LocalFree function.
Func _DataToBlob($data)
    ;funkey 2014.08.11th
    Local $iLen, $tDataIn, $tData, $aMem
    Local Const $LMEM_ZEROINIT = 0x40
    Select
        Case IsString($data)
            $iLen = StringLen($data)
        Case IsBinary($data)
            $iLen = BinaryLen($data)
        Case Else
            Return SetError(1, 0, 0)
    EndSelect

    $tDataIn = DllStructCreate($tagDATA_BLOB)
    $aMem = DllCall("Kernel32.dll", "handle", "LocalAlloc", "UINT", $LMEM_ZEROINIT, "UINT", $iLen)
    $tData = DllStructCreate("byte[" & $iLen & "]", $aMem[0])

    DllStructSetData($tData, 1, $data)
    DllStructSetData($tDataIn, "cbData", $iLen)
    DllStructSetData($tDataIn, "pbData", DllStructGetPtr($tData))

    Return $tDataIn
EndFunc   ;==>_DataToBlob

Edit: Added example for using CRYPTPROTECT_PROMPTSTRUCT.

CryptProtect.zip

Edited by funkey
  • Like 1

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Share this post


Link to post
Share on other sites
Chance

neat, I've been using that API for some time to manage passwords on my chromium installation..

I've been meaning to make a password manager in autoit for some time now that imports passwords.. I already have one that does that for chrome/chromium

I'm surprised noone's made a legit one yet.. or thrown some source for one here..

Share this post


Link to post
Share on other sites
funkey

Thanks,

I was surprised, that this functions are not already wrapped for AutoIt, because they are very useful.

Added example for using CRYPTPROTECT_PROMPTSTRUCT.


Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Share this post


Link to post
Share on other sites
guinness

A trac request can be created, but the functions need to be amended to adhere to this standard we expect before inclusion >> https://www.autoitscript.com/wiki/UDF-spec


UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Share this post


Link to post
Share on other sites
funkey

I made a UDF out of it and attached to the first thread. I'm sure function names have to change but I did not rename them for now.


Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Share this post


Link to post
Share on other sites
HardXOR

Hi, I test your script but don't work for me, still get error 1 from encrypt function, can u help me how to solve?

Thanks, Hard

Share this post


Link to post
Share on other sites
funkey

Hi, I test your script but don't work for me, still get error 1 from encrypt function, can u help me how to solve?

Thanks, Hard

Seems like DllCall for CryptProtectData() fails, but I cannot help you any further without more information. Show me your script and tell me what Windows and AutoIt versions you are using.


Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Share this post


Link to post
Share on other sites
HardXOR

it seems now it runs ok, i update autoit to latest version 3.3.12.0 and my win version is win 8.1 x64, version of crypt32.dll is 6.3.9600.16431, ty for help and escecially for your UDF  :thumbsup:

Share this post


Link to post
Share on other sites
funkey

it seems now it runs ok, i update autoit to latest version 3.3.12.0 and my win version is win 8.1 x64, version of crypt32.dll is 6.3.9600.16431, ty for help and escecially for your UDF  :thumbsup:

You are welcome. Since the functions work quite well with AutoIt version 3.3.8.1 I'm curious what old version you did run before updating to 3.3.12.0 :huh2:


Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Share this post


Link to post
Share on other sites
Spider001

string length problem

on a 64bit windows 8.1

works perfect on xp 32bit

autoit version 3.3.12.0

password to encrypt 'OLse2YGrw0XUj6Jct9Kv4Ida7MPom5Ru1 '

password after decrypt OLse2YGrw0XUj6Jct9Kv

Func _unprotect($data)
   If $data <> '' Then
      Local $sDesc='',$iError2,$iExtended2
      $data = _CryptUnprotectData($data, $sDesc)
      $iError2 = @error
      $iExtended2 = @extended
      If $iError2 > 0 Or $iExtended2 > 0 Then
         MsgBox(0,'error',"Error protecting: " & $iError2 & @LF & "Windows error protecting: " & $iExtended2)
         Exit
      EndIf
      Return $data
   Else
      Return ''
   EndIf
EndFunc

Func _protect($data)
   Local $iError1,$iExtended1
   Local $tCur = _Date_Time_GetLocalTime()
   $tCur = _Date_Time_SystemTimeToDateTimeStr($tCur)
   $data = _CryptProtectData($data, $tCur)
   $iError1 = @error
   $iExtended1 = @extended
   If $iError1 > 0 Or $iExtended1 > 0 Then
      MsgBox(0,'error',"Error protecting: " & $iError1 & @LF & "Windows error protecting: " & $iExtended1)
      Exit
   EndIf
   Return $data
EndFunc
Edited by Spider001

Share this post


Link to post
Share on other sites
funkey

string length problem

on a 64bit windows 8.1

works perfect on xp 32bit

autoit version 3.3.12.0

 

password to encrypt 'OLse2YGrw0XUj6Jct9Kv4Ida7MPom5Ru1 '

password after decrypt OLse2YGrw0XUj6Jct9Kv

Thanks for your feedback, but I can only test it on Win7 x64 and there is no problem with string length.

Maybe someone else can test this with Win8(.1)??

#include <Date.au3>
#include "CryptProtect.au3"

Global $sString2Hide = "OLse2YGrw0XUj6Jct9Kv4Ida7MPom5Ru1 "
Global $bCrypted = _protect($sString2Hide)
Global $sResult = _unprotect($bCrypted)

MsgBox(0, "There and back again", $sResult)


Func _unprotect($data)
    If $data <> '' Then
        Local $sDesc = '', $iError2, $iExtended2
        $data = _CryptUnprotectData($data, $sDesc)
        $iError2 = @error
        $iExtended2 = @extended
        If $iError2 > 0 Or $iExtended2 > 0 Then
            MsgBox(0, 'error', "Error protecting: " & $iError2 & @LF & "Windows error protecting: " & $iExtended2)
            Exit
        EndIf
        Return $data
    Else
        Return ''
    EndIf
EndFunc   ;==>_unprotect

Func _protect($data)
    Local $iError1, $iExtended1
    Local $tCur = _Date_Time_GetLocalTime()
    $tCur = _Date_Time_SystemTimeToDateTimeStr($tCur)
    ConsoleWrite($tCur & @CRLF)
    $data = _CryptProtectData($data, $tCur)
    $iError1 = @error
    $iExtended1 = @extended
    If $iError1 > 0 Or $iExtended1 > 0 Then
        MsgBox(0, 'error', "Error protecting: " & $iError1 & @LF & "Windows error protecting: " & $iExtended1)
        Exit
    EndIf
    Return $data
EndFunc   ;==>_protect

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Share this post


Link to post
Share on other sites
Spider001

Can it be that the problem the exe compiler from autoit?

Share this post


Link to post
Share on other sites
funkey

Can it be that the problem the exe compiler from autoit?

No definitely not. Why do you ask? Does it work for you when not compiled?


Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Share this post


Link to post
Share on other sites
Spider001

that whas the only thing i forgot to test

Why do you ask?

i whas not sure about the version then editor <> exe compiler but it's the same version

Does it work for you when not compiled?

no same result

Share this post


Link to post
Share on other sites
funkey

So lets wait until another one hopefully will test on Win8.1.

  • Like 1

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Share this post


Link to post
Share on other sites
UEZ

No problems on my Win 8.1 x64.

Neither when running it from SciTE nor when compiled.

Br,

UEZ


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites
Spider001

thanks for testing

but strange verry strange result

Share this post


Link to post
Share on other sites
IanN1990

Would this work on different "physical" machines that all share the same build / image ?

 

(and i dont mean the same version of windows or stuff, a complete clone of the image)

Edited by IanN1990

Share this post


Link to post
Share on other sites
funkey

I don't know. Just try it and tell us. ;)


Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×