Jump to content

Dllcall for CryptUnprotectData


Recommended Posts

Hey all,

I was wondering if anyone could help me convert an existing autoit function for using CryptProtectData (from the Windows crypt32.dll file) into one that does the reverse: CryptUnprotectData

The autoit function for encrypting the data using CryptProtectData was posted by another user here, but you can also see it at the end of my post.

Both functions from the Crypt32.dll library appear to be very similar in the way they require data to be given to it. You can find info about them both here: CryptUnprotectData, CryptProtectData. But dealing with data blobs and everything just makes me confused, and I don't know what needs to be changed, so I was hoping someone here might be able to tweak the existing function to make a different one that handles CryptUnprotectData.

So in the end, I would have 2 functions. The CryptProtectData one already works fine, and the CryptUnprotectData would obviously decrypt any data that was encrypted by the first.

Thanks in advance for your help :D !

Func CryptRDPPassword($str)
    Const $CRYPTPROTECT_UI_FORBIDDEN = 0x1
    Const $DATA_BLOB = "int;ptr"

    Dim $passStr = DllStructCreate("byte[1024]")
    Dim $DataIn = DllStructCreate($DATA_BLOB)
    Dim $DataOut = DllStructCreate($DATA_BLOB)
    $pwDescription = 'psw'
    $PwdHash = ""
        
    DllStructSetData($DataOut, 1, 0)
    DllStructSetData($DataOut, 2, 0)
    
    DllStructSetData($passStr, 1, StringToBinary($str,2)); UTF16 Little Endian
    DllStructSetData($DataIn, 2, DllStructGetPtr($passStr, 1)) 
    DllStructSetData($DataIn, 1, StringLen($str)*2) 
    
    $return = DllCall("crypt32.dll","int", "CryptProtectData", _ 
                                    "ptr", DllStructGetPtr($DataIn), _ 
                                    "wstr", $pwDescription, _ 
                                    "ptr", 0, _ 
                                    "ptr", 0, _ 
                                    "ptr", 0, _ 
                                    "dword", $CRYPTPROTECT_UI_FORBIDDEN, _ 
                                    "ptr", DllStructGetPtr($DataOut))
    If @error Then Return ""
        
    $len = DllStructGetData($DataOut, 1)
    $PwdHash = Ptr(DllStructGetData($DataOut, 2))
    $PwdHash = DllStructCreate("byte[" & $len & "]", $PwdHash)
    $encodeStr = ""
    For $x = 1 To $len
            $encodeStr &= Hex(DllStructGetData($PwdHash, 1, $x),2)
    Next
    Return $encodeStr
EndFunc
Link to comment
Share on other sites

Hey all,

I was wondering if anyone could help me convert an existing autoit function for using CryptProtectData (from the Windows crypt32.dll file) into one that does the reverse: CryptUnprotectData

The autoit function for encrypting the data using CryptProtectData was posted by another user here, but you can also see it at the end of my post.

Both functions from the Crypt32.dll library appear to be very similar in the way they require data to be given to it. You can find info about them both here: CryptUnprotectData, CryptProtectData. But dealing with data blobs and everything just makes me confused, and I don't know what needs to be changed, so I was hoping someone here might be able to tweak the existing function to make a different one that handles CryptUnprotectData.

So in the end, I would have 2 functions. The CryptProtectData one already works fine, and the CryptUnprotectData would obviously decrypt any data that was encrypted by the first.

Thanks in advance for your help :D !

Func CryptRDPPassword($str)
    Const $CRYPTPROTECT_UI_FORBIDDEN = 0x1
    Const $DATA_BLOB = "int;ptr"

    Dim $passStr = DllStructCreate("byte[1024]")
    Dim $DataIn = DllStructCreate($DATA_BLOB)
    Dim $DataOut = DllStructCreate($DATA_BLOB)
    $pwDescription = 'psw'
    $PwdHash = ""
        
    DllStructSetData($DataOut, 1, 0)
    DllStructSetData($DataOut, 2, 0)
    
    DllStructSetData($passStr, 1, StringToBinary($str,2)); UTF16 Little Endian
    DllStructSetData($DataIn, 2, DllStructGetPtr($passStr, 1)) 
    DllStructSetData($DataIn, 1, StringLen($str)*2) 
    
    $return = DllCall("crypt32.dll","int", "CryptProtectData", _ 
                                    "ptr", DllStructGetPtr($DataIn), _ 
                                    "wstr", $pwDescription, _ 
                                    "ptr", 0, _ 
                                    "ptr", 0, _ 
                                    "ptr", 0, _ 
                                    "dword", $CRYPTPROTECT_UI_FORBIDDEN, _ 
                                    "ptr", DllStructGetPtr($DataOut))
    If @error Then Return ""
        
    $len = DllStructGetData($DataOut, 1)
    $PwdHash = Ptr(DllStructGetData($DataOut, 2))
    $PwdHash = DllStructCreate("byte[" & $len & "]", $PwdHash)
    $encodeStr = ""
    For $x = 1 To $len
            $encodeStr &= Hex(DllStructGetData($PwdHash, 1, $x),2)
    Next
    Return $encodeStr
EndFunc
This seems to work:
Global $sRed1 = "This is a test."
ConsoleWrite("$sRed1 = " & $sRed1 & @LF)

Global $sBlack = CryptRDPPassword($sRed)
ConsoleWrite("$sBlack = " & $sBlack & @LF)

Global $sRed2 = UncryptRDPPassword($sBlack)
ConsoleWrite("$sRed2 = " & $sRed2 & @LF)

Func CryptRDPPassword($str)
    Local Const $CRYPTPROTECT_UI_FORBIDDEN = 0x1
    Local Const $DATA_BLOB = "int;ptr"

    Local $passStr = DllStructCreate("byte[1024]")
    Local $DataIn = DllStructCreate($DATA_BLOB)
    Local $DataOut = DllStructCreate($DATA_BLOB)
    $pwDescription = 'psw'
    $PwdHash = ""

    DllStructSetData($DataOut, 1, 0)
    DllStructSetData($DataOut, 2, 0)

    DllStructSetData($passStr, 1, StringToBinary($str,2)); UTF16 Little Endian
    DllStructSetData($DataIn, 2, DllStructGetPtr($passStr, 1))
    DllStructSetData($DataIn, 1, StringLen($str)*2)

    $return = DllCall("crypt32.dll","int", "CryptProtectData", _
                                    "ptr", DllStructGetPtr($DataIn), _
                                    "wstr", $pwDescription, _
                                    "ptr", 0, _
                                    "ptr", 0, _
                                    "ptr", 0, _
                                    "dword", $CRYPTPROTECT_UI_FORBIDDEN, _
                                    "ptr", DllStructGetPtr($DataOut))
    If @error Then Return ""

    $len = DllStructGetData($DataOut, 1)
    $PwdHash = Ptr(DllStructGetData($DataOut, 2))
    $PwdHash = DllStructCreate("byte[" & $len & "]", $PwdHash)
    Return DllStructGetData($PwdHash, 1)
EndFunc

Func UncryptRDPPassword($bin)
    Local Const $CRYPTPROTECT_UI_FORBIDDEN = 0x1
    Local Const $DATA_BLOB = "int;ptr"

    Local $passStr = DllStructCreate("byte[1024]")
    Local $DataIn = DllStructCreate($DATA_BLOB)
    Local $DataOut = DllStructCreate($DATA_BLOB)
    $pwDescription = 'psw'
    $PwdHash = ""

    DllStructSetData($DataOut, 1, 0)
    DllStructSetData($DataOut, 2, 0)

    DllStructSetData($passStr, 1, $bin)
    DllStructSetData($DataIn, 2, DllStructGetPtr($passStr, 1))
    DllStructSetData($DataIn, 1, BinaryLen($bin))

    $return = DllCall("crypt32.dll","int", "CryptUnprotectData", _
                                    "ptr", DllStructGetPtr($DataIn), _
                                    "ptr", 0, _
                                    "ptr", 0, _
                                    "ptr", 0, _
                                    "ptr", 0, _
                                    "dword", $CRYPTPROTECT_UI_FORBIDDEN, _
                                    "ptr", DllStructGetPtr($DataOut))
    If @error Then Return ""

    $len = DllStructGetData($DataOut, 1)
    $PwdHash = Ptr(DllStructGetData($DataOut, 2))
    $PwdHash = DllStructCreate("byte[" & $len & "]", $PwdHash)
    Return BinaryToString(DllStructGetData($PwdHash, 1), 2)
EndFunc

Note that I changed the return value of your CryptRDPPassword() to a binary type because screwing around with the string-to-binary-to-string stuff makes my hair hurt.

So in this version you pass a string to CryptRDPPassword() and get an encrypted binary back. Then you pass the encrypted binary to the new UncryptRDPPassword() and get the decrypted string back.

:D

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

Very nice! On line 4 of your test portion of the code I believe it should be $sRed1, but no biggie as I changed it and it works fine.

However, the encrypted strings I am working with look very similar to the output your CryptRDPPassword function gives, except mine do not have the beginning 0x. It's just 0100000...blahblahblah

I tried adding "0x" at the beginning of my encrypted string and running it through UncryptRDPPassword() but the script returns nothing. I think I might have to get my encrypted string into your binary format first, but I'm not sure how to do that. I would think it's already in that form but I dunno :D

Here is an example of what my encrypted strings look like (remove those line breaks of course so its one string):

01000000d08c9ddf0115d1118c7a00c04fc297eb01000000c3393cc2a4e98248ea3f41349b5df10300000000400000005400

680069007300200069007300200074006800650020006400650073006300720069007000740069006f006e00200073007400

720069006e0067002e00000003660000a8000000100000009b5f86dce0a19ca6201e6f452f5a131c0000000004800000a000

0000100000001f780e2d2ceaddaab51752a28f3816ad1800000020dc644fe83cedb87812d3d28fcbc5722545abde66a99107

14000000f911a8fb6a648c90c3b061a0668ad749dfdf8574

Thanks for your help so far!

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...