Jump to content

CodeCrypter - Encrypt your Script

Recommended Posts

Hi !

I just test it and i don't know how you did it, but that's simply amazing !!

I didn't change the key since I have to understand better how it works and how to create

a script that would run ok on another environnements :)

For an advice, maybe you could put every needed files in one zip,

and some Tools to automate the crypt process.

last advice, it's not easy to use codescanner ( treeview click interface ), a little more explanation would be interesting :)

but at last, that's amazing. How much security can we guess with this ? Does it prevent decompilation ?

i'll test with bigger script I have and try to report you.

Hope some users will test it too, maybe afraid of all needed scripts, but as you said, once understood, it's easy :)

Great job !

-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]

Share this post

Link to post
Share on other sites

Hi arcker,

Read many of your posts in the past; your Service UDF is outstanding, I use it almost daily! :thumbsup:

Thanks very much for responding so positively and your helpful suggestions! :)

A single zip package is easily set up, but a bit of a pain to maintain afterwards (whenever any of the pieces change, I'd have to update every bundle too). But it's probably an additional threshold for people who might be mildly interested, but don't want to have to jump through lots of hoops to get it working. So I can definitely set that up now.

Tools to automate the crypt process?  CodeCrypter was supposed to take care of that (see Presets). Or do you mean selecting/setting up a new key definition? Interesting suggestion, I'll have to think about that.

Codescanner is as you say kind of sparsely explained, it's true. :think: But I don't see how a tutorial pdf or FAQ is going to help much. I suppose I could make a short flash video tutorial (and maybe another one for CodeCrypter?), to show that it really can all be done in a few clicks. People don't have to program a single line to obfuscate and heavily encrypt  their script, I guess I need to clarify this. If any Moderator is reading this, how would posting a video work? Would I post a YouTube link or should I upload an .flv directly, or do it some other way? Any suggestions welcome (I'm still a complete noob on all this posting stuff).

How much security?

A determined, skilful attacker would be able through decompilation to figure out how you obtain your decryption key, but not what it is, unless they have access to the full environment (host machine, User ID, and whatever else you use as key(s)) where the script is intended to run. So your script is safe to the extent to which the key is protected. No amount of decompilation can reveal what is not present to begin with, and the key itself is never stored anywhere. But if an attacker can install hidden spying software on a legitimate user's machine and/or fake-personify the user, there's not much I can do against that. Nothing is 100% secure, and people are usually the weakest link in any crypto.

To give an example: an attacker can figure out by analysing the code that you're using (for example) keytype 1, which queries the user for a password at startup. They could of course also figure this out if they can watch a legitimate user start the script. So then it's simply a question of whether the real user can keep their password safe without taping a note of it to their keyboard or screen. I suggested in CodeCrypter's Q&A pdf to create a more secure key by maybe combining something user-specific, something machine-specific and your own web server's response to the script's unique serial number (you'd have to put that serial number in yourself, I'm afraid, and define an InetGet() keytype in MCFinclude).

The encryption itself is currently using Ward's AES, which AFAIK even the NSA has trouble with (no obvious backdoor in the algorithm, like DES for example), but you can use whatever algorithm you want (just replace the few encryption calls in MCF and one decrpytion call in MCfinclude).

I've tried to give people as much control as possible.

Thanks again for your encouragements! I'll see if I can make things easier...


Share this post

Link to post
Share on other sites

Hi there!

I just started looking into scripting, and chose AutoIt since my boss thought it was simply amazingly easy to understand once you get the hang of it.

Although I am indeed at the bottom of the knowledge tree, i understand what you have done here and I must say it is rather impressive.

Personally, I have only made small installers, using different multi install sources like Ninite.com (for Client and Internal machines) and it is working perfectly fine.

I am looking to expand my knowledge, which is why I am commenting on this post - I hope brilliant people like yourself and your commenters keep this up :)

Lastly, i wish to thank the community for posting examples like this, I have read alot of examples and posts in the "GUI help" sections to get ideas and expand my understanding.

Thank you!

Share this post

Link to post
Share on other sites

Hi Siggassen, and welcome to the AutoIT forums!

Thanks for your comments, very much appreciated!

I only started using AutoIt less than a year ago myself (did have previous programming experience though). The great thing about this language (to me at least) is that it is not only incredibly simple and intuitive to get started with, but it also keeps growing with you; as your own knowledge expands, you discover new, powerful ways to use it (Dll calls, for example). And I've benefited greatly from other people's amazing UDFs (code annotations also clarify a lot) and their helpful replies to queries. Not at all like some other forums I know...

Best of luck with your projects! :bye:


Share this post

Link to post
Share on other sites


Thx for your word about Services UDF, even if I really fixed it early ( you learn so much in 5 years Oo )

I try to pass more time here on community to help since autoit has served me well in the past years in my carrier :)

For your project, no problem for the automatization of the crypt process.

I would just post a screenshot about codescanner and how to program it, even if I love this interface, it's original and

all information we need is here.

I've another question : I've seen a lot of execute, so I wonder about performance, even if I know that's not the point here.

if you have just some bench on it :)

-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]

Share this post

Link to post
Share on other sites

Hi again arcker,

Thanks re. the interface, it was the first time I used TreeViews, so I thought, might as well see how else it could be useful aside from showing includes and calls.

Screenshots would be quick and easy to do, I'll see if I can rustle something up when I have a spare moment.

Benchmarks I haven't done yet. I suspect it's very reliant on your baseline, i.e., the kinds of commands your script is using. As a rough rule of thumb (mentioned in my Q & A / FAQ pdf in the CodeCrypter thread), I guesstimated a factor 2 for single encryption (keytype visible in MCFCC calls) and a factor 3 for nested encryption (keytype hidden), but that may be wide off the mark. You can reduce the processing load by enabling subset encryption, so under the Tab Encrypt you would enable the subset checkbox and set the proportion (or percentage) to less than 1 (c.q. <100%); the encryption then only affects a proportion (selected at random). If you enter an integer number N larger than one, CodeCrypter will sequentially encrypt only every N-th line (of the total number of encryptable lines). So you can reduce the extra processing load that way if you're not too worried about your code design and ideas being partly legible.

You can also encypt specific lines (well, phrases) you select yourself, for example a particular bunch of UDFs you need to protect, leaving the GUI part in clear code. See the Q & A pdf for instructions how to do this. (Basically you run a full encrypt pass first, then rebuild the phrasesNew array the way you want from phrasesUsed and phraseEncryp, then call CreateNew.)

Finally, the simplest way to reduce the processing load is to move the location where you include MCFinclude.au3 in your script. If this is your first line, then all other includes that follow it will be encrypted too, and since these #includes are publicly available anyway, it may be a waste of time to shield that. So I tend to make MCFinclude the last include before my main code starts, so only my own stuff is protected. (I would however obfuscate everything, since it costs nothing extra in processing power).

Slowdown is definitely an issue, you're right. I tested CodeCrypter on a few AutoIt games, and unless you reduce the encryption to a subset of about 10%, games like Mario and Autoiteroids become so slow that they're unplayable; same story with trancexx's XMplayer, which just fails altogether if more than a tiny fraction is encrypted. If slowdown is an issue, you'll have to do some fine-tuning to decide which parts of your code need protection most. It can be a difficult trade-off.

BTW I updated CodeScanner this morning, still version 2.0, but fixed a small bug.

Share this post

Link to post
Share on other sites

This looks very interesting, I haven't had time to look clear through the code yet, but could you please explain the method you use to allow the code to be decrypted without including the key in the source code? Are you using key pairs (like pgp)? Please explain further.

Share this post

Link to post
Share on other sites

Hello nullschritt,

Nope, not using key pairs. It works like this:

  • you include the supplied file MCFinclude.au3 in your script
  • this file contains an initialisation function called MCFCC_Init()
  • this function contains various optional calls and macros that when invoked, return some string from the environment. You can use one (or more) of the pre-supplied ones, or add new calls (to existing functions or your own UDF) yourself. One of the supplied defaults (option 1) is for example the old chestnut of the user password query dialog box at startup. The important part is, these calls all extract some information from the run-time environment (the user, the host machine, the network, the internet, whatever).

The returned string is your decryption key for the encrypted code lines.

Now the trick is that you can tell Codecrypter when you encrypt to use either:

  • a direct call to your chosen initialisation function (in this case the target will work only in your own environment), OR
  • an "expected response" you enter yourself, that matches some other environment (so the target will only work there).

CodeCrypter uses the response as key to encrypt your code, and edits the dummy call to MCFCC_Init to initialise with your defined function call, and the moment you exit CodeCrypter, the key is gone. When the encrypted script is started, MCFCC_Init calls your selected function, this returns some string, which is used as decryption key. If the returned string does not match your original key, only garbage is returned, and the programme won't run.

Hope that clarifies matters! ;)

For more information, see the Remarks section inside the CodeCrypter script.

Edited by RTFC

Share this post

Link to post
Share on other sites

First I give you my special thanks for sharing this useful tool! Nice to see in this forum that kind of tools which are trying to protect our work!

I have a little issue or I can't understand very well but .... I use autoit-v. and:

1. I have a simple script in which I placed the MCFinclude.au3

2. I place the requared include AES.au3, MCF.au3, MCFinclude.au3, readCSdatadump.au3

3. Furst I run CodeScanner ( with WriteMetaCode=True ). It create folder myscript.au3.CS_DATA

4. Then codecrypter.exe which create MCF0test.au3

All this is ok but my new script give this error:

#include _MCFCC("0x04E69DA809736DCB6752B39D3C6CF669184CBAD8C44FABBB9456EF6E3673E1AC487",3)

MCF0test.au3(2,10) : ERROR: illegal character in include directive.
#include _

I make something wrong.. the help file is not helping me ;)


Share this post

Link to post
Share on other sites

Hello TonyBriscoe,

Firstly ,thanks for your comments.

Re. your issue, something definitely went very wrong because your new script should no longer contain any includes.

My first suggestion would be to create a BackTranslated testMCF0.au3 (either from CodeScanner or from CodeCrypter) from your original script. If this script still contains lines that start with #include ... then that would be very odd. In that case, I would love to analyse your script to see how that could possibly have happened.

Secondly,  maybe I've misunderstood, but your point 2 seems to suggest that you've included MCF.au3 etc in your script?? If that's the case, that would be a mistake, because you should only include MCFinclude.au3 (which automatically includes AES.au3). Under no circumstance should any of the other includes you mention in point 2 be explicitly incorporated in your script.

Thanks for pointing this out, I will amend the instructions to clarify this.

So 1) remove all MCF-related #includes from your script except MCFinclude.au3, and 2) do a BackTranslate, and check that all #include lines are removed from your testMCF0.au3 output. If not, then please let me know.

Best of luck,


Share this post

Link to post
Share on other sites

No, my simple script contain only MCFinclude.au3 include.

#include <MCFinclude.au3>

Local $Is = 1
While $Is<11
    MsgBox(-1,"Count Up to 10",".. and the count is: " &$Is,1)

All other necessery file (AES.au3, MCF.au3, MCFinclude.au3, readCSdatadump.au3) I placed in the include folder of the autoit program.

The BackTranslated give me this ( again it have includes inside ):

; Source Language: AutoIt
; Extracted from : D:\test\myscript.au3
; on             : 2013-10-29, at 21:15:08
; CodeScanner was itself running AutoIt version:
; This Single-Build was generated on 2013-10-29, at 21:15:45

#include "MemoryConstants.au3"       ; {file:4}{line:3}
#include "StructureConstants.au3"       ; {file:4}{line:4}
#include "ProcessConstants.au3"       ; {file:4}{line:5}

#include "SecurityConstants.au3"       ; {file:5}{line:3}
#include "StructureConstants.au3"       ; {file:5}{line:4}

#include "StructureConstants.au3"       ; {file:7}{line:3}
#include "FileConstants.au3"       ; {file:7}{line:4}

Global $__gaWinList_WinAPI[64][2] = [[0, 0]]       ; {file:7}{line:19}{ref637}
Global Const $__WINAPICONSTANT_GW_HWNDNEXT = 2       ; {file:7}{line:47}{ref658}
Global Const $__WINAPICONSTANT_GW_CHILD = 5       ; {file:7}{line:48}{ref659}

Func __WinAPI_EnumWindowsAdd($hWnd,$sClass="")       ; {file:7}{line:1898}
    If $sClass="" Then $sClass=_WinAPI_GetClassName($hWnd)       ; {file:7}{line:1899}
    $__gaWinList_WinAPI[0][0]+= 1       ; {file:7}{line:1900}
    Local $iCount=$__gaWinList_WinAPI[0][0]       ; {file:7}{line:1901}

And this is given potential issues:


I think that there is something wrong with my included files. I uploaded them here if you want to take a look:


Thanks for your reply and trying to help!

Share this post

Link to post
Share on other sites

Hi again,

Sorry to hear you're still having trouble with this. I've tried unsuccessfully to reproduce your problem, first with my own test scripts, then (when you posted your code) with yours.

That CodeScanner output is nothing to worry about; those includes are flagged quite often as redundant (depends on which WinAPI functions are actually called), and regardless of whether CodeScanner considers files redundant, the MCF writer processes them anyway, so in CodeCrypter you can still decide to keep everything in.

I have trouble downloading from your posted link; FF requests my permission to download large files, but offers no way of giving it (apparently lots of people are struggling with the same problem on the web). I've been playing with the permissions, but nothing I tried lifts the block.

I did however copy your test script, ran it, CodeScanned it, BackTranslated it, encrypted it.

I can't find anything wrong with it, and everything works as normal at this end.

I've attached my copy of your script (weird.au3), the single build (MCF0.txt), the backtranslation (MCF0.au3), and the encrypted version (MCf0test.au3) using default settings.

weird.zip (apologies for the renaming, I have too many "test" scripts/dirs already)

The encrypted version uses password "test" all lower-case

Some questions:

  • Does this happen only with this script or with every script you try?
  • Are your original scripts ASCII or UniCode? (bit of a long shot)
  • What happens when you process my copy of your original script (weird.au3)?
  • Can you do a file compare between your version and my copy?


Codescan + CreateMCF0 + Backtranslation is enough (don't forget to call Create Single Build before each Backtranslation; a newer version of MCF (not yet uploaded) will do this automatically, but this one still requires manual labour (well, an extra click). If the Backtranslate still has #includes in it then it failed.

I must say I'm baffled :unsure: , and not being able to reproduce the error makes it difficult for me to help you, I'm sorry to say. If my copied version is essentially the same as yours, then I suspect there's something peculiar in your AutoIt environment (as we are running the same version, it can't be that). and could you perhaps just attach your own version of your script to your next post here (the web code paste in the post may hide some low-level differences)? Thanks.


Edited by RTFC

Share this post

Link to post
Share on other sites


I finally managed to download your includes, hooked them up, reran your test script, and it all works flawlessly here.

If the tests in my previous post don't clarify matters, you could edit your MCF.au3 (maybe save a copy of the original first) around line 795, in recursive UDF _WriteMCF0()  where the very first metacode checked for is "{incl". I suspect that somehow, in your environment, for whatever reason, that stringtest fails. If you have a hex editor, you may also wish to check "#include ..." lines in metacode files MCF1-MCF* for 00h, FFh, or other "empty" characters that are not 09h or 20h. If the StringinStr fails to find the  {incl#} metacode tag because of some file corruption, then the converter would treat it as a normal compiler directive, and copy it verbatim.

You could perhaps add a Msgbox(0,"",$curline), if $pos1<1 And stringleft($curline,8)="#include" to determine which lines are skipped, that will help you focus on whatever is tripping up the StringinStr test.

Share this post

Link to post
Share on other sites

So sorry for the trouble that I've created for you by downloading the files.. This was my mistake to not upload them here..

Thank you very much for taking your time and given me enough examples and explanations to help me with solving the problem, but it still persist :( .

Some answers:

  • Does this happen only with this script or with every script you try? - This happen with every script.
  • What happens when you process my copy of your original script (weird.au3)? - it works fine.
  • Can you do a file compare between your version and my copy? - Yes, the only difference is in the beggining where my script begin with some includes and some missing Globals..

I think that the codescanner miss some includes, so after that the codecrypter can't do his wokr correct.

I attach the files that you need to compare and I'll try again to see what is wrong with me according your suggestions.

Wishing you all the best!



Share this post

Link to post
Share on other sites

I am a 24-carat, industrial strength moron. :doh:

What do all your retained includes have in common? They are all Constants files.

Your latest upload allowed me to check your CodeScanner settings. What do you have switched off? Include constants files.

Now I haven't figured out how CodeScanner was able to process MetaCode with this switch off; it's automatically switched on whenever you set WriteMetaCode on. You didn't edit your CodeScanner.ini file by hand inbetween, did you?

Anyway, I'll add some additional checks in CodeScanner to ensure that this will be impossible in future; expect an update in the near future.

For now, just make sure you've got "Include Constants files" switched on in the Settings before you process your target source. That should fix it.

Share this post

Link to post
Share on other sites

Thank you so mutch!

    In the beginning I changed only the WriteMetaCode to be True in the CodeScanner settings and I did not pay attention that IncludeConstants was False ! Now all works PERFECT and I can continue using it in my main projects! I will continue to give my feedback here.

  Once again Thank You for your excellent work!



Share this post

Link to post
Share on other sites

Glad I could help! :)

Thanks for persisting, the output shows that I need to build in some extra settings checking in CodeScanner (working on it...) I guess because writemetacode and includeconstants are normally synced, I failed to consider the notion of them becoming unsynced later. It's not supposed to happen, but Murphy's Law always applies. My bad. :idiot:

Share this post

Link to post
Share on other sites

CodeScanner updated to version 2.1 (MCF-related bug fixes), updated in bundle, and FAQ updated.

Share this post

Link to post
Share on other sites


first I want to say thank you for your nice tool-package.

I have some problems to get SetError() to work with an encrypted script.

Take the following example-script and then encrypt it with codecrypter:

#include "..\CodeScannerCrypterBundle\MCFinclude.au3"

Func _Test($test)
    If $test == "" Then
        Return SetError(1, 0, "")
    Return $test

Local $test = _Test("test")
If @error Then
    ConsoleWrite("1st call Error: " & @error & @CRLF)
    ConsoleWrite("1st call Value: " & $test & @CRLF)

$test = _Test("")
If @error Then
    ConsoleWrite("2nd call Error: " & @error & @CRLF)
    ConsoleWrite("2nd call Value: " & $test & @CRLF)

The (unencoded) original output after run the script is:

1st call Value: test
2nd call Error: 1

But after encryption the console output is:

1st call Value: test
2nd call Error: 0

Do you have an idea, how to overcome this?

Thanks in advance.

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

  • Similar Content

    • By Colduction
      I had created login form and this form first goes to de-crypting file that encrypted then read the saved credentials by de-cryptied file, but doesn't work properly!
      I want just read encrypted data without saving de-crypted file, just read! 
      #NoTrayIcon #include <Crypt.au3> #include <FileConstants.au3> #include <MsgBoxConstants.au3> #include <ButtonConstants.au3> #include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> ;==================================Variables=================================== ;Encryption settings _Crypt_Startup() $PEK = _Crypt_DeriveKey("BS#Password", $CALG_AES_256, $CALG_SHA_512) $DefaultCredFile = "[Credentials]" & @CRLF & "BUsername=NoAdmin" & @CRLF & "BPassword=NoAdmin" & @CRLF & "[Process]" & @CRLF & "ProcessKillingTimeout=3600" $EncryptDefaultCred = _Crypt_EncryptData($DefaultCredFile, $PEK, $CALG_AES_256) $IniReadCredPassword = IniRead(@WindowsDir & "\Config\GUIDecCred.dat", "Credentials", "BPassword", "") $IniReadCredUsername = IniRead(@WindowsDir & "\Config\GUIDecCred.dat", "Credentials", "BUsername", "") ;==================================Variables=================================== AuthForm() Func AuthForm() Global $LoginForm = GUICreate("Login", 201, 161, -1, -1) Global $CloseBTN = GUICtrlCreateButton("Close", 23, 126, 75, 25) Global $SignInBTN = GUICtrlCreateButton("Sign-in", 103, 126, 75, 25) GUICtrlSetFont(-1, 8, 800, 0, "MS Sans Serif") Global $PasswordInput = GUICtrlCreateInput("admin", 8, 88, 185, 21, BitOR($GUI_SS_DEFAULT_INPUT,$ES_CENTER,$ES_PASSWORD)) Global $UsernameInput = GUICtrlCreateInput("admin", 8, 40, 185, 21, BitOR($GUI_SS_DEFAULT_INPUT,$ES_CENTER)) Global $UsernameLBL = GUICtrlCreateLabel("Username:", 8, 21, 55, 17) Global $PasswordLBL = GUICtrlCreateLabel("Password:", 8, 68, 53, 17) GUISetState(@SW_SHOW) While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit Case $SignInBTN AuthProcess() EndSwitch WEnd EndFunc AuthProcess() Func AuthProcess() $ReadEnteredUsername = GUICtrlRead($UsernameInput) $ReadEnteredPassword = GUICtrlRead($PasswordInput) If Not FileExists(@WindowsDir & "\Config\GUIEncCred.dat") Then FileDelete(@WindowsDir & "\Config\GUIDecCred.dat") ;Delete previous de-crypted credentials FileWrite(@WindowsDir & "\Config\GUIEncCred.dat", $EncryptDefaultCred) ;Write en-crypted credentials as "*.dat" file FileClose(@WindowsDir & "\Config\GUIEncCred.dat") ;Close en-crypted credentials file _Crypt_DecryptFile(@WindowsDir & "\Config\GUIEncCred.dat", @WindowsDir & "\Config\GUIDecCred.dat", $PEK, $CALG_AES_256) ;Write de-crypted file from an en-crypted file as "*.dat" file Else _Crypt_DecryptFile(@WindowsDir & "\Config\GUIEncCred.dat", @WindowsDir & "\Config\GUIDecCred.dat", $PEK, $CALG_AES_256) ;Write de-crypted file from an en-crypted file as "*.dat" file EndIf Sleep(25) If $ReadEnteredUsername == $IniReadCredUsername And $ReadEnteredPassword == $IniReadCredPassword Then ;Username and Password verify stage MsgBox(64, "", "Welcome!") FileDelete(@WindowsDir & "\Config\GUIDecCred.dat") Exit Else MsgBox(14, "", "Incorrect!") FileDelete(@WindowsDir & "\Config\GUIDecCred.dat") Sleep(25) EndIf EndFunc How Can i? 
    • By Beege
      I found this article and enjoyed it so much I had play with some code since the numbers are small enough. 
      Standard Encryption's vs RSA Encryption (Public Key Encryption) Fundamental Differences
      If you read that and couldn't immediately clarify the difference then let me blow your mind because its simple:
      ORIGINAL_DATA + Password(or KEY) = Encrypted DATA
          Then to decrypt -> 
              Encrypted DATA + (SAME Password(or SAME KEY)) = ORIGINAL_DATA
              ORIGINAL_DATA + Password(or PUBLIC_KEY) = Encrypted DATA
          Then to decrypt -> 
              Encrypted DATA + (DIFFERENT Password(or PRIVATE_KEY)) = ORIGINAL_DATA
      Are we all caught up? Did the colors help? I think they did
      That's crazy right? Don't answer. It is. And crazier its used EVERY TIME we make a secure connection to a server over the internet. But here's the craziest part to me that I recently got clarity on from the toy example and that is the simplicity of this very very very very important algorithm that has yet to be cracked (fingers crossed):
                 Mod($vData ^ $key, $n)
      So ya. That's it. That's the magic algorithm. 3 values. Oh and $n is also a shared known value that will be in the certificate with the public key that your browser reads when it makes a connection:

      That's just mind blowing to me so couldn't resist getting something going in AUT. After playing with this code, I got a much better understanding of how its not just that algorithm that makes this whole thing possible. The numbers that we pick to form the public key and n are just as important and also how important it is to be random! 
      Let me know if you have any problems. Enjoy!
      #include <array.au3> _Toy_RSA_Example() ;https://thatsmaths.com/2016/08/11/a-toy-example-of-rsa-encryption/ Func _Toy_RSA_Example() Local $p, $q, $n, $nT, $e, $d Local $aPublicKeys, $aCrypt, $sDecrypt, $sMsg ;Pick two random primes (they will be between 1000-10000) $p = _GetRandomPrime() $q = _GetRandomPrime() $sMsg = 'p= %i \t\t| Prime 1 - [NOT SHARED!]\nq= %i \t\t| Prime 2 - [NOT SHARED!]\n' ;Calculate lowest common multiple $nT = _LCM($p - 1, $q - 1) $sMsg &= 'nT= %i \t| _LCM(p - 1,q - 1) - [NOT SHARED!]\n' ;Calculate n. This is a shared number $n = $p * $q $sMsg &= 'n= %i \t| p * q - [Shared]\n' ;Get a small random list of possible public keys to pick from. Only searching for 100ms $aPublicKeys = _GetPublicKeys($nT) _ArrayDisplay($aPublicKeys, "Possible Public Keys Found") ;Pick a random public (encryption) key from array $e = $aPublicKeys[Random(1, $aPublicKeys[0], 1)] $sMsg &= 'e= %i \t| Public (Encryption) Key - [Shared]\n' ;Generate our private (decryption) key $d = _GetPrivateKey($e, $nT) $sMsg &= 'd= %i \t| Private (Decryption) Key - [NOT SHARED!]\n' ;format our msg (rsa details) to encrypt $sMsg = StringFormat($sMsg, $p, $q, $nT, $n, $e, $d) ;encrypt message $aCrypt = _RSA($sMsg, $e, $n) _ArrayDisplay($aCrypt, 'Encrypted RSA messsage') ;Decrypt array back $sDecrypt = _RSA($aCrypt, $d, $n) MsgBox(0, 'Decrypted RSA messsage', $sDecrypt) EndFunc ;==>_Toy_RSA_Example ;Function will perfrom Mod($v ^ $key, $n) on each char/element. ;Excepts Arrays or Strings. If input is array a string is returned and vice versa. Func _RSA($vDat, $key, $n) Local $bIsStr = IsString($vDat) If $bIsStr Then $vDat = StringToASCIIArray($vDat) For $i = 0 To UBound($vDat) - 1 $vDat[$i] = _Modular($vDat[$i], $key, $n) Next Return $bIsStr ? $vDat : StringFromASCIIArray($vDat) EndFunc ;==>_RSA ;algorithm is from the book "Discrete Mathematics and Its Applications 5th Edition" by Kenneth H. Rosen. Func _Modular($iBase, $iExp, $iMod) ; Mod($v ^ $key, $n) Local $iPower = Mod($iBase, $iMod) Local $x = 1 For $i = 0 To (4 * 8) - 1 If BitAND(0x00000001, BitShift($iExp, $i)) Then $x = Mod(($x * $iPower), $iMod) EndIf $iPower = Mod(($iPower * $iPower), $iMod) Next Return $x EndFunc ;==>_Modular ;Generate a "random" list of possible valid public keys to choose from based on $nT Func _GetPublicKeys($nT, $iMs = 100) Do Local $aKeys[10000] = [0], $iTime = TimerInit() Local $i = (Mod(@SEC, 2) ? Int($nT / 2) : Int($nT / 4)) ; randomize where we start Do If _IsPrime($i) And _IsCoPrime($i, $nT) Then $aKeys[0] += 1 $aKeys[$aKeys[0]] = $i EndIf $i += (Mod(@MSEC, 2) ? 1 : 100) ; randomize step size Until ($i >= ($nT - 1)) Or (TimerDiff($iTime) > $iMs) ReDim $aKeys[$aKeys[0] + 1] Until $aKeys[0] > 5 ; Ive seen 200+ returned sometimes and 0 on others. Make sure we have at least a few choices Return $aKeys EndFunc ;==>_GetPublicKeys ;https://www.geeksforgeeks.org/multiplicative-inverse-under-modulo-m/ - _ModInverse(a,m) Func _GetPrivateKey($a, $m) If ($m = 1) Then Return 0 ; Local $t, $q, $y = 0, $x = 1, $m0 = $m While ($a > 1) $q = Int($a / $m) ;q is quotient $t = $m ; $m = Mod($a, $m) ;m is remainder now, process same as Euclid's algo $a = $t ; $t = $y ; $y = $x - $q * $y ;Update y and x $x = $t ; WEnd Return $x < 0 ? $x + $m0 : $x EndFunc ;==>_GetPrivateKey ;Pick the next nearest prime from a random number (or number you cho0se) Func _GetRandomPrime($iStart = Default) Local $iPrime = ($iStart = Default ? Random(1000, 10000, 1) : $iStart) Do $iPrime += 1 Until _IsPrime($iPrime) Return $iPrime EndFunc ;==>_GetRandomPrime #Region Math Functions Func _IsPrime($n) For $i = 2 To (Int($n ^ 0.5) + 1) If Mod($n, $i) = 0 Then Return False Next Return True EndFunc ;==>_IsPrime Func _IsCoPrime($a, $b) Return _GCD($a, $b) = 1 EndFunc ;==>_IsCoPrime Func _GCD($iX, $iY) Local $iM While 1 $iM = Mod($iX, $iY) If $iM = 0 Then Return $iY $iX = $iY $iY = $iM WEnd EndFunc ;==>_GCD Func _LCM($iX, $iY) Return ($iX * $iY) / _GCD($iX, $iY) EndFunc ;==>_LCM #EndRegion Math Functions  
      You should get a message box displaying the decrypted message with details of the values used:

    • By SolemnStrike
      I know the title sounds weird, but i couldn't find better words for it...
      I finally managed to have a working image search (yes yes i know image search is evil :p).
      I noticed that even if the script is compiled, the images have to be in my script folder.
      But i don't want that the images i'm searching for on the screen can be viewed, edited etc by every user.
      Is there a way to... uhm... put them in a file like .rar, but one that can't be easily opened? 🤔
      Edit: Now that i think of .rar, maybe using a .rar which is protected by a password... Can autoit search, open, extract, use and delete that? (I guess so, I didn't search for this yet, going to google that asap)
    • By colombeen
      Hi everyone, I created a function to gather bitlocker information. It can tell you whether or not a drive is protected, which encryption method is being used, ...
      I tried to cover all the details in the function description
      The function (and 3 "internal" functions) :
      ; #FUNCTION# ==================================================================================================================== ; Name...........: _BitlockerDriveInfo ; Description ...: Get Bitlocker information for one or multiple drives ; Syntax.........: _BitlockerDriveInfo([$sDrive[, $sComputer = @ComputerName[, $bDebug = False]]]) ; Parameters ....: $sDrive - Optional: The drive. Allowed values are: ; |"" - Get the info for all available drives ; |Letter: - Get the info for the specific drive ; $sComputer - Optional: The computer from which the info should be requested ; $bDebug - Optional: Shows the hex ReturnValue from the WMI methods if set to True ; Return values .: Success - Returns a 2D array with the following information ; |[string] Drive Letter ; |[string] Drive Label ; |[string] Volume Type ; |[bool] Initialized For Protection ; |[string] Protection Status ; |[string] Lock Status ; |[bool] Auto Unlock Enabled ; |[bool] Auto Unlock Key Stored ; |[string] Conversion Status ; |[string] Encryption Method ; |[int] Encryption Percentage ; |[string] Wiping Status ; |[int] Wiping Percentage ; |[array] Key Protectors (Or [string] "None" if the drive isn't protected) ; Failure - 0, sets @error to: ; |1 - There was an issue retrieving the COM object. @extended returns error code from ObjGet ; |2 - The specified drive in $Drive doesn't exist ; |3 - There was an issue running the WMI query ; Author ........: colombeen ; Modified.......: ; Remarks .......: Requires to be run with admin elevation. Windows Vista or newer! ; A BIG THANKS to everyone from the community who contributed! ; Related .......: ; Link ..........: ; Example .......: #include <Array.au3> ; $Header = "Drive Letter|Drive Label|Volume Type|Initialized For Protection|Protection Status|" & _ ; "Lock Status|Auto Unlock Enabled|Auto Unlock Key Stored|Conversion Status|Encryption " & _ ; "Method|Encryption Percentage|Wiping Status|Wiping Percentage|Key Protectors" ; _ArrayDisplay(_BitlockerDriveInfo(), "Bitlocker Drive Info", "", 64, Default, $Header) ; =============================================================================================================================== Func _BitlockerDriveInfo($sDrive = "", $sComputer = @ComputerName, $bDebug = False) Local $aConversionStatusMsg[7] = ["Unknown", "Fully Decrypted", "Fully Encrypted", "Encryption In Progress", "Decryption In Progress", "Encryption Paused", "Decryption Paused"] Local $aEncryptionMethodMsg[9] = ["Unknown", "None", "AES_128_WITH_DIFFUSER", "AES_256_WITH_DIFFUSER", "AES_128", "AES_256", "HARDWARE_ENCRYPTION", "XTS_AES_128", "XTS_AES_256"] Local $aKeyProtectorTypeMsg[11] = ["Unknown or other protector type", "Trusted Platform Module (TPM)", "External key", "Numerical password", "TPM And PIN", "TPM And Startup Key", "TPM And PIN And Startup Key", "Public Key", "Passphrase", "TPM Certificate", "CryptoAPI Next Generation (CNG) Protector"] Local $aLockStatusMsg[3] = ["Unknown", "Unlocked", "Locked"] Local $aProtectionStatusMsg[3] = ["Unprotected", "Protected", "Unknown"] Local $aVolumeTypeMsg[3] = ["Operating System Volume", "Fixed Data Volume", "Portable Data Volume"] Local $aWipingStatusMsg[5] = ["Unknown", "Free Space Not Wiped", "Free Space Wiped", "Free Space Wiping In Progress", "Free Space Wiping Paused"] Local $iRow = 0 Local $sRunMethod, $objWMIService, $objWMIQuery, $sDriveFilter, $iProtectionStatus, $iLockStatus, $bIsAutoUnlockEnabled, $bIsAutoUnlockKeyStored, $iConversionStatus, $iEncryptionPercentage, $iEncryptionFlags, $iWipingStatus, $iWipingPercentage, $iEncryptionMethod, $aVolumeKeyProtectorID, $aVolumeKeyProtectors, $iKeyProtectorType $objWMIService = ObjGet("winmgmts:{impersonationLevel=impersonate,authenticationLevel=pktPrivacy}!\\" & $sComputer & "\root\CIMV2\Security\MicrosoftVolumeEncryption") If @error Then Return SetError(1, @error, 0) If $sDrive <> "" Then Local $iDriveType = _WMIPropertyValue("DriveType", "Win32_LogicalDisk", "WHERE DeviceID='" & $sDrive & "'", Default, $sComputer) If @error Or ($iDriveType <> 2 And $iDriveType <> 3) Then Return SetError(2, 0, 0) $sDriveFilter = " WHERE DriveLetter='" & $sDrive & "'" EndIf $objWMIQuery = $objWMIService.ExecQuery("SELECT * FROM Win32_EncryptableVolume" & $sDriveFilter, "WQL", 0) If Not IsObj($objWMIQuery) Then Return SetError(3, 0, 0) Local $aResult[$objWMIQuery.count][14] For $objDrive In $objWMIQuery If $bDebug Then ConsoleWrite(@CRLF & "+> " & $objDrive.DriveLetter & @CRLF) If _WMIMethodExists($objDrive, "GetConversionStatus") Then $sRunMethod = $objDrive.GetConversionStatus($iConversionStatus, $iEncryptionPercentage, $iEncryptionFlags, $iWipingStatus, $iWipingPercentage) If $bDebug Then ConsoleWrite("!> GetConversionStatus 0x" & Hex($sRunMethod) & @CRLF) Else $iConversionStatus = -1 $iWipingStatus = -1 $iEncryptionPercentage = 0 $iWipingPercentage = 0 EndIf If _WMIMethodExists($objDrive, "GetEncryptionMethod") Then $sRunMethod = $objDrive.GetEncryptionMethod($iEncryptionMethod) If $bDebug Then ConsoleWrite("!> GetEncryptionMethod 0x" & Hex($sRunMethod) & @CRLF) Else $iEncryptionMethod = 0 EndIf If _WMIMethodExists($objDrive, "GetKeyProtectors") Then $sRunMethod = $objDrive.GetKeyProtectors("0", $aVolumeKeyProtectorID) If $bDebug Then ConsoleWrite("!> GetKeyProtectors 0x" & Hex($sRunMethod) & @CRLF) Else $aVolumeKeyProtectorID = 0 EndIf If _WMIMethodExists($objDrive, "GetLockStatus") Then $sRunMethod = $objDrive.GetLockStatus($iLockStatus) If $bDebug Then ConsoleWrite("!> GetLockStatus 0x" & Hex($sRunMethod) & @CRLF) Else $iLockStatus = -1 EndIf If _WMIMethodExists($objDrive, "GetProtectionStatus") Then $sRunMethod = $objDrive.GetProtectionStatus($iProtectionStatus) If $bDebug Then ConsoleWrite("!> GetProtectionStatus 0x" & Hex($sRunMethod) & @CRLF) Else $iProtectionStatus = 2 EndIf If _WMIMethodExists($objDrive, "IsAutoUnlockEnabled") Then $sRunMethod = $objDrive.IsAutoUnlockEnabled($bIsAutoUnlockEnabled) If $bDebug Then ConsoleWrite("!> IsAutoUnlockEnabled 0x" & Hex($sRunMethod) & @CRLF) Else $bIsAutoUnlockEnabled = "Unknown" EndIf If _WMIMethodExists($objDrive, "IsAutoUnlockKeyStored") Then $sRunMethod = $objDrive.IsAutoUnlockKeyStored($bIsAutoUnlockKeyStored) If $bDebug Then ConsoleWrite("!> IsAutoUnlockKeyStored 0x" & Hex($sRunMethod) & @CRLF) Else $bIsAutoUnlockKeyStored = "Unknown" EndIf If IsArray($aVolumeKeyProtectorID) And UBound($aVolumeKeyProtectorID) > 0 Then Dim $aVolumeKeyProtectors[UBound($aVolumeKeyProtectorID)][2] For $i = 0 To UBound($aVolumeKeyProtectorID) - 1 $aVolumeKeyProtectors[$i][0] = $aVolumeKeyProtectorID[$i] If _WMIMethodExists($objDrive, "GetKeyProtectorType") Then If $objDrive.GetKeyProtectorType($aVolumeKeyProtectorID[$i], $iKeyProtectorType) = 0 Then $aVolumeKeyProtectors[$i][1]= $aKeyProtectorTypeMsg[$iKeyProtectorType] Else $aVolumeKeyProtectors[$i][1]= "Unknown" EndIf Else $aVolumeKeyProtectors[$i][1] = "Unknown" EndIf Next Else $aVolumeKeyProtectors = "None" EndIf ; DriveLetter $aResult[$iRow][0] = $objDrive.DriveLetter ; DriveLabel $aResult[$iRow][1] = _WMIPropertyValue("VolumeName", "Win32_LogicalDisk", "WHERE DeviceID='" & $objDrive.DriveLetter & "'", Default, $sComputer) ; VolumeType If _WMIPropertyExists($objDrive, "VolumeType") Then $aResult[$iRow][2] = $aVolumeTypeMsg[$objDrive.VolumeType] Else If $objDrive.DriveLetter = _WMIPropertyValue("SystemDrive", "Win32_OperatingSystem", "", Default, $sComputer) Then $aResult[$iRow][2]= $aVolumeTypeMsg[0] ElseIf _WMIPropertyValue("DriveType", "Win32_LogicalDisk", "WHERE DeviceID='" & $objDrive.DriveLetter & "'", Default, $sComputer) = 3 Then $aResult[$iRow][2]= $aVolumeTypeMsg[1] ElseIf _WMIPropertyValue("DriveType", "Win32_LogicalDisk", "WHERE DeviceID='" & $objDrive.DriveLetter & "'", Default, $sComputer) = 2 Then $aResult[$iRow][2]= $aVolumeTypeMsg[2] Else $aResult[$iRow][2]= "Unknown" EndIf EndIf ; IsVolumeInitializedForProtection If _WMIPropertyExists($objDrive, "IsVolumeInitializedForProtection") Then $aResult[$iRow][3] = $objDrive.IsVolumeInitializedForProtection Else $aResult[$iRow][3] = "Unkown" EndIf ; ProtectionStatus $aResult[$iRow][4] = $aProtectionStatusMsg[$iProtectionStatus] ; LockStatus $aResult[$iRow][5] = $aLockStatusMsg[$iLockStatus + 1] ; IsAutoUnlockEnabled $aResult[$iRow][6] = $bIsAutoUnlockEnabled ; IsAutoUnlockEnabled $aResult[$iRow][7] = $bIsAutoUnlockKeyStored ; ConversionStatus $aResult[$iRow][8] = $aConversionStatusMsg[$iConversionStatus + 1] ; EncryptionMethod $aResult[$iRow][9] = $aEncryptionMethodMsg[$iEncryptionMethod + 1] ; EncryptionPercentage $aResult[$iRow][10] = $iEncryptionPercentage ; WipingStatus $aResult[$iRow][11] = $aWipingStatusMsg[$iWipingStatus + 1] ; WipingPercentage $aResult[$iRow][12] = $iWipingPercentage ; KeyProtectors $aResult[$iRow][13] = $aVolumeKeyProtectors $iRow += 1 Next _ArraySort($aResult) Return $aResult EndFunc ;==>_BitlockerDriveInfo Func _WMIPropertyExists($Object, $Property) If Not IsObj($Object) Then Return False For $sProperty In $Object.Properties_ If $sProperty.Name = $Property Then Return True Next Return False EndFunc ;==>_WMIPropertyExists Func _WMIMethodExists($Object, $Method) If Not IsObj($Object) Then Return False For $sMethod In $Object.Methods_ If $sMethod.Name = $Method Then Return True Next Return False EndFunc ;==>_WMIMethodExists Func _WMIPropertyValue($sProperty = "", $sClass = "", $sFilter = "", $sNamespace = Default, $sComputer = @ComputerName) Local $objWMIService, $objWMIQuery If $sClass = "" Or $sProperty = "" Then Return SetError(1, 0, 0) If $sFilter <> "" Then $sFilter = " " & $sFilter If $sNamespace = Default Then $sNamespace = "\root\CIMV2" $objWMIService = ObjGet("winmgmts:{impersonationLevel=impersonate,authenticationLevel=pktPrivacy}!\\" & $sComputer & $sNamespace) If @error Then Return SetError(2, @error, 0) $objWMIQuery = $objWMIService.ExecQuery("SELECT * FROM " & $sClass & $sFilter, "WQL", 0x30) If Not IsObj($objWMIQuery) Then Return SetError(3, 0, 0) For $objItem In $objWMIQuery For $Property In $objItem.Properties_ If $Property.Name = $sProperty Then Return $Property.Value EndIf Next Next Return SetError(4, 0, 0) EndFunc ;==>_WMIPropertyValue  
      Example 1:
      #RequireAdmin #include <array.au3> ; Get information on all available drives Global $test = _BitlockerDriveInfo() If @error Then ConsoleWrite("!> _BitlockerDriveInfo() error: " & @error & ". extended: " & @extended & @CRLF) ElseIf IsArray($test) Then _ArrayDisplay($test, "Bitlocker Drive Info", "", 64, Default, "Drive Letter|Drive Label|Volume Type|Initialized For Protection|Protection Status|Lock Status|Auto Unlock Enabled|Auto Unlock Key Stored|Conversion Status|Encryption Method|Encryption Percentage|Wiping Status|Wiping Percentage|Key Protectors") ; Display the Key Protectors for the first record If IsArray($test[0][13]) Then _ArrayDisplay($test[0][13]) EndIf Example 2:
      #RequireAdmin #include <array.au3> ; Get information on the C-drive of the current computer + show extra information in the console Global $test = _BitlockerDriveInfo("C:", @ComputerName, True) If @error Then ConsoleWrite("!> _BitlockerDriveInfo() error: " & @error & ". extended: " & @extended & @CRLF) ElseIf IsArray($test) Then ConsoleWrite("Bitlocker information on the " & $test[0][0] & " drive" & @CRLF) ConsoleWrite("Protection Status: " & $test[0][4] & @CRLF) EndIf  
      Screenshot for the first example:

      Suggestions? Bugs?
      Just let me know
      Version 1.0:
      Initial release Version 1.1:
      Fixed: Drive Label will not work when you request the information from a remote system (currently using DriveGetLabel) Fixed: The current fix for the missing VolumeType property in some Windows versions will only work locally Added: New internal function (_WMIPropertyValue()) Version 1.2:
      Fixed: The drive exists & drive type check only worked locally when a drive was specified in $sDrive
    • By colombeen
      Hi guys,
      I'm trying to get some information using WMI, from the Win32_EncryptableVolume class.
      I exec my query, filter out the C-drive, but when I need more info using the objects methods, I only get 1 value back and I can't seem to retrieve the other out params that should be there.
      A very minimal version of what I'm trying to do (no error checking etc, very basic). You need to start SciTE as admin or you won't see any results in the console!
      #RequireAdmin $strComputer = @ComputerName $objWMIService = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $strComputer & "\root\CIMV2\Security\MicrosoftVolumeEncryption") $objWMIQuery = $objWMIService.ExecQuery("SELECT * FROM Win32_EncryptableVolume WHERE DriveLetter='C:'", "WQL", 0) For $objDrive In $objWMIQuery ConsoleWrite("> " & $objDrive.GetConversionStatus() & @CRLF) ConsoleWrite("> " & $objDrive.GetConversionStatus().ConversionStatus & @CRLF) ConsoleWrite("> " & $objDrive.GetConversionStatus().EncryptionPercentage & @CRLF) Next The result from the console is : 
      > 0 > > What I'm expecting to get back is : 
      > 0 > 0 > 0 When using powershell I get this (run as admin is required!!!) : 
      PS C:\WINDOWS\system32> (Get-WmiObject -namespace "Root\cimv2\security\MicrosoftVolumeEncryption" -ClassName "Win32_Encryptablevolume" -Filter "DriveLetter='C:'").GetConversionStatus() ... ConversionStatus : 0 EncryptionFlags : 0 EncryptionPercentage : 0 ReturnValue : 0 ... All I seem to be getting is the ReturnValue when I use the method.
      I've tried this on multiple methods, always ending up with the same result
      Anyone here who has experience with this type of thing?
  • Create New...