CryptAES randomly crashing my script

Ask for help, how to use AHK_H, etc.
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: CryptAES randomly crashing my script

12 Jan 2020, 12:29

HotKeyIt wrote:
12 Jan 2020, 11:48
Can you disable AV and try again and make sure no other program is running.
Try also running it with windbg to see what happens.
I have no AV. I closed Discord, Steam, Nvidia Panel, all Sound devices software. Also tried it in my laptop with a fresh w10 install, same behaviour.
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: CryptAES randomly crashing my script

12 Jan 2020, 14:20

@HotKeyIt

I used code from this post https://www.autohotkey.com/boards/viewtopic.php?f=6&t=23413 by jNizM to remake the CryptAES function using CNG instead of advapi32.dll.

It's working without any problems. It can be improved a lot but I didn't want to mess a lot with it. I changed the code to be as close as possible as the one you made.

parameters:
string = string to encrypt / decrypt.
iv = Initialization Vector (you can read this answer on StackOverflow to learn about it: https://stackoverflow.com/questions/9049789/aes-encryption-key-versus-iv
key = Secret Key
e = Encrypt. If True it will Encrypt, if False it will Decrypt.


Code: Select all

CryptAES(string, iv, key, e := 1)
{
	static BCRYPT_AES_ALGORITHM   := "AES"
    static BCRYPT_OBJECT_LENGTH   := "ObjectLength"
    static BCRYPT_BLOCK_LENGTH    := "BlockLength"
    static BCRYPT_CHAINING_MODE   := "ChainingMode"
    static BCRYPT_CHAIN_MODE_CBC  := "ChainingModeCBC"
    static BCRYPT_OPAQUE_KEY_BLOB := "OpaqueKeyBlob"
    static BCRYPT_BLOCK_PADDING   := 0x00000001
	
	DllCall("bcrypt\BCryptOpenAlgorithmProvider", "ptr*", ALG_HANDLE, "ptr", &BCRYPT_AES_ALGORITHM, "ptr", 0, "uint", 0)
	DllCall("bcrypt\BCryptGetProperty", "ptr", ALG_HANDLE, "ptr", &BCRYPT_OBJECT_LENGTH, "uint*", OBJECT_LENGTH, "uint", 4, "uint*", cbResult, "uint",  0)
	DllCall("bcrypt\BCryptGetProperty", "ptr", ALG_HANDLE, "ptr", &BCRYPT_BLOCK_LENGTH, "uint*", BLOCK_LENGTH, "uint", 4, "uint*", cbResult, "uint",  0)
	DllCall("bcrypt\BCryptSetProperty", "ptr", ALG_HANDLE, "ptr", &BCRYPT_CHAINING_MODE, "ptr", &BCRYPT_CHAIN_MODE_CBC, "uint", StrLen(BCRYPT_CHAIN_MODE_CBC), "uint", 0)
	VarSetCapacity(KEY_OBJECT, OBJECT_LENGTH, 0)
	VarSetCapacity(pbSecret, cbSecret := StrPut(KEY, "UTF-8"), 0) && StrPut(KEY, &pbSecret, "UTF-8"), cbSecret--
	DllCall("bcrypt\BCryptGenerateSymmetricKey", "ptr", ALG_HANDLE, "ptr*", KEY_HANDLE, "ptr", &KEY_OBJECT, "uint", OBJECT_LENGTH, "ptr", &pbSecret, "uint", cbSecret, "uint", 0)
	
	if e
	{
		VarSetCapacity(pbInput, cbInput := StrLen(string) << 1, 0)
		DllCall("msvcrt\memcpy", "ptr", &pbInput, "ptr", &string, "ptr", cbInput)
		VarSetCapacity(pbIV, BLOCK_LENGTH, 0)
		DllCall("msvcrt\memcpy", "ptr", &pbIV, "ptr", &IV, "ptr", BLOCK_LENGTH)
		DllCall("bcrypt\BCryptEncrypt", "ptr", KEY_HANDLE, "ptr", &pbInput, "uint",  cbInput, "ptr", 0, "ptr", &pbIV, "uint", BLOCK_LENGTH, "ptr", 0, "uint", 0, "uint*", CIPHER_LENGTH, "uint", "BCRYPT_BLOCK_PADDING")
		VarSetCapacity(CIPHER_DATA, CIPHER_LENGTH, 0)
		DllCall("bcrypt\BCryptEncrypt", "ptr", KEY_HANDLE, "ptr", &pbInput, "uint", cbInput, "ptr", 0, "ptr", &pbIV, "uint", BLOCK_LENGTH, "ptr", &CIPHER_DATA, "uint", CIPHER_LENGTH, "uint*", CIPHER_LENGTH, "uint", "BCRYPT_BLOCK_PADDING")
	}
	else
	{
		len := strLen(string)*(A_IsUnicode+1)
		VarSetCapacity(pbInput, len, 0)
		DllCall("msvcrt\memcpy", "ptr", &pbInput, "ptr", &string, "ptr", len)
		VarSetCapacity(pbIV, BLOCK_LENGTH, 0)
		DllCall("msvcrt\memcpy", "ptr", &pbIV, "ptr", &iv, "ptr", BLOCK_LENGTH)
		DllCall("bcrypt\BCryptDecrypt", "ptr", KEY_HANDLE, "ptr", &pbInput, "uint", len, "ptr", 0, "ptr", &pbIV, "uint", BLOCK_LENGTH, "ptr", 0, "uint", 0, "uint*", CIPHER_LENGTH, "uint", "BCRYPT_BLOCK_PADDING")
		VarSetCapacity(CIPHER_DATA, CIPHER_LENGTH, 0)
		DllCall("bcrypt\BCryptDecrypt", "ptr", KEY_HANDLE, "ptr", &pbInput, "uint", len, "ptr", 0, "ptr", &pbIV, "uint", BLOCK_LENGTH, "ptr", &CIPHER_DATA, "uint", CIPHER_LENGTH, "uint*", CIPHER_LENGTH, "uint", "BCRYPT_BLOCK_PADDING")		
	}
	
	DllCall("bcrypt.dll\BCryptDestroyKey", "ptr", KEY_HANDLE)

	DllCall("bcrypt\BCryptCloseAlgorithmProvider", "ptr",  ALG_HANDLE, "uint", 0)
	if e
		return CIPHER_DATA
	else
		return StrGet(&CIPHER_DATA, CIPHER_LENGTH /= 2, "utf-16")
}
HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: CryptAES randomly crashing my script

12 Jan 2020, 14:22

I will take a look.
Can you try to run it in Debugger, e.g.: windbg
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: CryptAES randomly crashing my script

12 Jan 2020, 14:40

HotKeyIt wrote:
12 Jan 2020, 14:22
I will take a look.
Can you try to run it in Debugger, e.g.: windbg
Sure, do you have a Discord account so I can easily send you screenshots?
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: CryptAES randomly crashing my script

12 Jan 2020, 15:10

I forgot to add this line on the function:

Code: Select all

static hBCRYPT := DllCall("LoadLibrary", "str", "bcrypt.dll", "ptr")
guest3456
Posts: 3463
Joined: 09 Oct 2013, 10:31

Re: CryptAES randomly crashing my script

12 Jan 2020, 15:26

kyuuuri wrote:
12 Jan 2020, 11:03
Did the same steps with:
w10, ahk_h v1 (I changed /MT to /MD):
x64
x86 Unicode

w10, ahk_h v1 (I didn't change /MT):
x64
x86 Unicode

The script had the same behaviour on all those tests, the number of times I opened it and it crashed varies but again it's like random.
are you running this on your own custom compiled version of AHK_H? or the public release?

kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: CryptAES randomly crashing my script

12 Jan 2020, 16:15

guest3456 wrote:
12 Jan 2020, 15:26
kyuuuri wrote:
12 Jan 2020, 11:03
Did the same steps with:
w10, ahk_h v1 (I changed /MT to /MD):
x64
x86 Unicode

w10, ahk_h v1 (I didn't change /MT):
x64
x86 Unicode

The script had the same behaviour on all those tests, the number of times I opened it and it crashed varies but again it's like random.
are you running this on your own custom compiled version of AHK_H? or the public release?
Hello, tried both!
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: CryptAES randomly crashing my script

15 Jan 2020, 18:34

We fixed it! I mean, HotKeyIt did but I helped(?) hahaha.
The first VarSetCapacity() needed an extra 16 bytes, that's why it crashed sometimes.
He spent like 2-3 hours to find the problem (most of it because my computer had missing dlls and was a fresh w10 installation) and also I had a problem with my computer and he helped with that as well.
I'm glad to see that he cares so much about ahk.
Thank you again and sorry for wasting your time. (I thought it was a bug in ahk_h's source). I will post the corrected code once I arrive home.
Also thank you everyone who participated in this topic.

P.S = had 0 errors on MemTest. It doesn't matter anymore but anyway :D
@edit:

Code: Select all

f1::
Path := "D:\test.txt"
hash := "f1461877468516263ea376f8588c8bc0c1413ca7712f9d4d5e624b95efda69c5"
sz:=130 ; 130 because: hashLength = 64 * 2 = 128 (unicode) + 2 for terminating char = 130
VarSetCapacity(str, sz+16) ; fix for crash problem.
StrPut(hash, &str)
sz := CryptAES(str, sz, "431GddAtuifssBogjCkgdoswMasegvsA5fkd8/*4-fa@#d", true)
tooltip a
; Write
file := FileOpen(Path, "a")
test := StrGet(&str, sz/(A_IsUnicode+1)) ; sz / 1+1 = 144 / 2 = 72
File.RawWrite(test, 144)
File.close()
return

CryptAES(ByRef lp,sz,pw,e:=1,SID:=256){
	static AES_128:=0x660E,AES_192:=1+AES_128,AES_256:=1+AES_192,SHA1:=1+0x8003 ; MD5
	If !DllCall("Advapi32\CryptAcquireContext","Ptr*",hP,"Uint",0,"Uint",0,"Uint",24,"UInt",0xF0000000) ;PROV_RSA_AES, CRYPT_VERIFYCONTEXT
	|| !DllCall("Advapi32\CryptCreateHash","Ptr",hP,"Uint",SHA1,"Uint",0,"Uint",0,"Ptr*",H )
	;|| !CryptHashData(H,&pw,StrLen(pw)*2,0)
	|| !DllCall("Advapi32\CryptHashData", "Ptr", H, "Uchar", &pw, "Uint", StrLen(pw)*2, "UInt", 0)
	;|| !CryptDeriveKey(hP,AES_%SID%,H,SID<<16,getvar(hK:=0))
	|| !DllCall("Advapi32\CryptDeriveKey", "Ptr", hP, "Ptr", AES_%SID%, "Ptr", H, "Uint", SID<<16, "Ptr", getvar(hK:=0))
	;|| !CryptDestroyHash(H)
	|| !DllCall("Advapi32\CryptDestroyHash", "Ptr", H)
		return 0
	if e
		DllCall("Advapi32\CryptEncrypt", "Ptr", hK, "Ptr", 0, "int", 1, "Uint", 0, "Uchar", &lp, "Uint", getvar(sz), "Uint", sz+16)
	else
		DllCall("Advapi32\CryptDecrypt", "Ptr", hK, "Ptr", 0, "int", 1, "Uint", 0, "Uchar", &lp, "Uint", getvar(sz))
		;DllCall("Advapi32\CryptDecrypt",hK,0,1,0,&lp,getvar(sz))
	DllCall("Advapi32\CryptDestroyKey", "Ptr", hK) 
	DllCall("Advapi32\CryptReleaseContext", "Ptr", hP, "Uint", 0)
	return sz
}
;~ CryptAES(ByRef lp,sz,pw,e:=1,SID:=256){
	;~ static f:="advapi32\Crypt",t:="UPtr",t_:="UPtr*",AES_128:=0x660E,AES_192:=1+AES_128,AES_256:=1+AES_192,SHA1:=1+0x8003 ; MD5
	;~ return e?VarSetCapacity(lp,sz+16):0,DllCall(f "AcquireContext",t_,hP,t,0,t,0,t,24,t,0xF0000000) ;PROV_RSA_AES, CRYPT_VERIFYCONTEXT
  ;~ ,DllCall(f "CreateHash",t,hP,t,SHA1,t,0,t,0,t_,H),DllCall(f "HashData",t,H,str,pw,t,StrLen(pw)*2,t,0)
  ;~ ,DllCall(f "DeriveKey",t,hP,t,AES_%SID%,t,H,t,SID<<16,t_,hK),DllCall(f "DestroyHash",t,H)
  ;~ ,e?DllCall(f "Encrypt",t,hK,t,0,t,1,t,0,t,&lp,t_,sz,t,sz+16):DllCall(f "Decrypt",t,hK,t,0,t,1,t,0,t,&lp,t_,sz)
  ;~ ,DllCall(f "DestroyKey",t,hK),DllCall(f "ReleaseContext",t,hP,t,0)
  ;~ ,sz
;~ }
guest3456
Posts: 3463
Joined: 09 Oct 2013, 10:31

Re: CryptAES randomly crashing my script

15 Jan 2020, 20:20

kyuuuri wrote:
15 Jan 2020, 18:34
We fixed it! I mean, HotKeyIt did but I helped(?) hahaha.
The first VarSetCapacity() needed an extra 16 bytes, that's why it crashed sometimes.
He spent like 2-3 hours to find the problem (most of it because my computer had missing dlls and was a fresh w10 installation) and also I had a problem with my computer and he helped with that as well.
do you remember what dlls were missing?

and how would we know to add an extra 16 bytes in the future?

kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: CryptAES randomly crashing my script

15 Jan 2020, 20:27

guest3456 wrote:
15 Jan 2020, 20:20
kyuuuri wrote:
15 Jan 2020, 18:34
We fixed it! I mean, HotKeyIt did but I helped(?) hahaha.
The first VarSetCapacity() needed an extra 16 bytes, that's why it crashed sometimes.
He spent like 2-3 hours to find the problem (most of it because my computer had missing dlls and was a fresh w10 installation) and also I had a problem with my computer and he helped with that as well.
do you remember what dlls were missing?

and how would we know to add an extra 16 bytes in the future?
Hello, about the dlls: Not related to this problem, it didn't have any vc redist nor any .net redist, but my pc had some other problems non-related to ahk.
About the 16 bytes: we found it on the docs https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptencrypt it's not explicit, if I'm not wrong it was this section:
dwBufLen

Specifies the total size, in bytes, of the input pbData buffer.

Note that, depending on the algorithm used, the encrypted text can be larger than the original plaintext. In this case, the pbData buffer needs to be large enough to contain the encrypted text and any padding.

As a rule, if a stream cipher is used, the ciphertext is the same size as the plaintext. If a block cipher is used, the ciphertext is up to a block length larger than the plaintext.
SOTE
Posts: 1426
Joined: 15 Jun 2015, 06:21

Re: CryptAES randomly crashing my script

17 Jan 2020, 04:01

HotKeyIt wrote:
12 Jan 2020, 14:22
I will take a look.
Can you try to run it in Debugger, e.g.: windbg
If this is going to be updated, would suggest (wish list) that hash functions be added as well, like MD5 and SHA, in addition to AES encryption.
wpb
Posts: 150
Joined: 14 Dec 2015, 01:53

Re: CryptAES randomly crashing my script

25 Oct 2023, 10:32

kyuuuri wrote:
12 Jan 2020, 14:20
@HotKeyIt

I used code from this post viewtopic.php?f=6&t=23413 by jNizM to remake the CryptAES function using CNG instead of advapi32.dll.

It's working without any problems. It can be improved a lot but I didn't want to mess a lot with it. I changed the code to be as close as possible as the one you made.

parameters:
string = string to encrypt / decrypt.
iv = Initialization Vector (you can read this answer on StackOverflow to learn about it: https://stackoverflow.com/questions/9049789/aes-encryption-key-versus-iv
key = Secret Key
e = Encrypt. If True it will Encrypt, if False it will Decrypt.


Code: Select all

CryptAES(string, iv, key, e := 1)
{
	static BCRYPT_AES_ALGORITHM   := "AES"
    static BCRYPT_OBJECT_LENGTH   := "ObjectLength"
    static BCRYPT_BLOCK_LENGTH    := "BlockLength"
    static BCRYPT_CHAINING_MODE   := "ChainingMode"
    static BCRYPT_CHAIN_MODE_CBC  := "ChainingModeCBC"
    static BCRYPT_OPAQUE_KEY_BLOB := "OpaqueKeyBlob"
    static BCRYPT_BLOCK_PADDING   := 0x00000001
	
	DllCall("bcrypt\BCryptOpenAlgorithmProvider", "ptr*", ALG_HANDLE, "ptr", &BCRYPT_AES_ALGORITHM, "ptr", 0, "uint", 0)
	DllCall("bcrypt\BCryptGetProperty", "ptr", ALG_HANDLE, "ptr", &BCRYPT_OBJECT_LENGTH, "uint*", OBJECT_LENGTH, "uint", 4, "uint*", cbResult, "uint",  0)
	DllCall("bcrypt\BCryptGetProperty", "ptr", ALG_HANDLE, "ptr", &BCRYPT_BLOCK_LENGTH, "uint*", BLOCK_LENGTH, "uint", 4, "uint*", cbResult, "uint",  0)
	DllCall("bcrypt\BCryptSetProperty", "ptr", ALG_HANDLE, "ptr", &BCRYPT_CHAINING_MODE, "ptr", &BCRYPT_CHAIN_MODE_CBC, "uint", StrLen(BCRYPT_CHAIN_MODE_CBC), "uint", 0)
	VarSetCapacity(KEY_OBJECT, OBJECT_LENGTH, 0)
	VarSetCapacity(pbSecret, cbSecret := StrPut(KEY, "UTF-8"), 0) && StrPut(KEY, &pbSecret, "UTF-8"), cbSecret--
	DllCall("bcrypt\BCryptGenerateSymmetricKey", "ptr", ALG_HANDLE, "ptr*", KEY_HANDLE, "ptr", &KEY_OBJECT, "uint", OBJECT_LENGTH, "ptr", &pbSecret, "uint", cbSecret, "uint", 0)
	
	if e
	{
		VarSetCapacity(pbInput, cbInput := StrLen(string) << 1, 0)
		DllCall("msvcrt\memcpy", "ptr", &pbInput, "ptr", &string, "ptr", cbInput)
		VarSetCapacity(pbIV, BLOCK_LENGTH, 0)
		DllCall("msvcrt\memcpy", "ptr", &pbIV, "ptr", &IV, "ptr", BLOCK_LENGTH)
		DllCall("bcrypt\BCryptEncrypt", "ptr", KEY_HANDLE, "ptr", &pbInput, "uint",  cbInput, "ptr", 0, "ptr", &pbIV, "uint", BLOCK_LENGTH, "ptr", 0, "uint", 0, "uint*", CIPHER_LENGTH, "uint", "BCRYPT_BLOCK_PADDING")
		VarSetCapacity(CIPHER_DATA, CIPHER_LENGTH, 0)
		DllCall("bcrypt\BCryptEncrypt", "ptr", KEY_HANDLE, "ptr", &pbInput, "uint", cbInput, "ptr", 0, "ptr", &pbIV, "uint", BLOCK_LENGTH, "ptr", &CIPHER_DATA, "uint", CIPHER_LENGTH, "uint*", CIPHER_LENGTH, "uint", "BCRYPT_BLOCK_PADDING")
	}
	else
	{
		len := strLen(string)*(A_IsUnicode+1)
		VarSetCapacity(pbInput, len, 0)
		DllCall("msvcrt\memcpy", "ptr", &pbInput, "ptr", &string, "ptr", len)
		VarSetCapacity(pbIV, BLOCK_LENGTH, 0)
		DllCall("msvcrt\memcpy", "ptr", &pbIV, "ptr", &iv, "ptr", BLOCK_LENGTH)
		DllCall("bcrypt\BCryptDecrypt", "ptr", KEY_HANDLE, "ptr", &pbInput, "uint", len, "ptr", 0, "ptr", &pbIV, "uint", BLOCK_LENGTH, "ptr", 0, "uint", 0, "uint*", CIPHER_LENGTH, "uint", "BCRYPT_BLOCK_PADDING")
		VarSetCapacity(CIPHER_DATA, CIPHER_LENGTH, 0)
		DllCall("bcrypt\BCryptDecrypt", "ptr", KEY_HANDLE, "ptr", &pbInput, "uint", len, "ptr", 0, "ptr", &pbIV, "uint", BLOCK_LENGTH, "ptr", &CIPHER_DATA, "uint", CIPHER_LENGTH, "uint*", CIPHER_LENGTH, "uint", "BCRYPT_BLOCK_PADDING")		
	}
	
	DllCall("bcrypt.dll\BCryptDestroyKey", "ptr", KEY_HANDLE)

	DllCall("bcrypt\BCryptCloseAlgorithmProvider", "ptr",  ALG_HANDLE, "uint", 0)
	if e
		return CIPHER_DATA
	else
		return StrGet(&CIPHER_DATA, CIPHER_LENGTH /= 2, "utf-16")
}
Wouldn't it be a problem passing the data to decrypt as a string, because as I understand it, AES-encrypted data could contain a NULL right in the middle of the data?

Return to “Ask for Help”

Who is online

Users browsing this forum: No registered users and 55 guests