Jump to content
RTFC

CodeCrypter - Encrypt your Script

Recommended Posts

arcker

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 !

  • Like 1

-- 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
RTFC

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...

RT

Share this post


Link to post
Share on other sites
Siggasen

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
RTFC

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:

RT

Share this post


Link to post
Share on other sites
arcker

Hi RTFC,

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
RTFC

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
nullschritt

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
RTFC

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
TonyBriscoe

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.3.3.8.1 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 ;)

Thanks!

Share this post


Link to post
Share on other sites
RTFC

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,

RT

Share this post


Link to post
Share on other sites
TonyBriscoe

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

#include <MCFinclude.au3>

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

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 ):

; CODE SCANNER Output
;
; Source Language: AutoIt
; Extracted from : D:\test\myscript.au3
; on             : 2013-10-29, at 21:15:08
; CodeScanner was itself running AutoIt version: 3.3.8.1
;
; 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:

issues_zpsc6421d21.jpg

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

https://mega.co.nz/#!E80RRI7Z!BzH6YTGXd40gumABGuiDTCvqweZckTpjFDQX4XGwFBU

Thanks for your reply and trying to help!

Share this post


Link to post
Share on other sites
RTFC

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
  • Like 1

Share this post


Link to post
Share on other sites
RTFC

@TonyBriscoe

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.

  • Like 1

Share this post


Link to post
Share on other sites
TonyBriscoe

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!

Tony

myscript.rar

Share this post


Link to post
Share on other sites
RTFC

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.

  • Like 1

Share this post


Link to post
Share on other sites
TonyBriscoe

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!

Respectfully,

Tony

Share this post


Link to post
Share on other sites
RTFC

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
MagicSpark

Hi RTFC,

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, "")
    EndIf
    Return $test
EndFunc

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

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

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

    • SolemnStrike
      By SolemnStrike
      Hey, 
      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)
    • colombeen
      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
       
      TODO:
      ???  
      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
    • colombeen
      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?
       
      Greetz
      colombeen
    • careca
      By careca
      Let's say you have some files you dont want anyone to know what they are,
      and you dont want anyone to be able to open them, you could encrypt them,
      but if the files are big it'll take a long time to do the operations for you to be able to open those files.
      I made this to make this process faster, and still not easy for someone to open the files, or even know what type they are.
      What it does is change the filename to a random number with 8 digits and .inc extension.
      The original filename is encrypted in the file itself, with a PIN provided by the user up to 4 digits, this PIN is also a number that's going to be used to split the file and change it internally, so the end result is a file with a header that's got the original filename encrypted, and the rest of the file scrambled a bit.
      The way it works is simple, place the application in a folder where you want to hide the files, it will ask for a pin, after you press ok, the application asks :
      Encrypt or decrypt?
      If encrypt, the files will become the 8 digit .inc files.
      The originals will stay, the user can delete the originals or do whatever.
      Then to open the files back, same process, but this time choose decrypt, and a listview will show the random filenames and the corresponding decrypted/original filenames and extension, uppon double click they open with whatever application is the default for them. There's a search feature, and an "extract all" button, to get all files back to original/unencrypted versions.
      Feedback is wellcome.
    • Overkill
      By Overkill
      Hi all,
      I am working on a GUI program to update Google's Dynamic DNS (API at https://support.google.com/domains/answer/6147083?authuser=1&hl=en if you scroll to bottom). I am not a programmer by any means - just a sysadmin who has picked up on some things along the way. I am sure that there's better ways to do a lot of things in this script; I'm just going with what I know.
      My challenge right now is that I'd like a better way to store the credentials both in memory as well as in system registry or INI file (not sure which way I want to go for local storage). How should I convert the passwords to a secure string in a manner that can't be easily reversed, yet is still accessible to the script? Is that even an option in AutoIt?
      Can anybody provide me with links to good reference posts, or coding suggestions for how best to achieve this in the script below? I am using the WinHTTP UDF (https://github.com/dragana-r/autoit-winhttp/releases) to make my API calls.
      #include<WinHTTP.au3> #include<GUIConstantsEx.au3> #include<EditConstants.au3> #include<iNet.au3> #include<Array.au3> DIM $aDomainList[1][4] $aDomainList[0][0] = 0 $gMainGUI = GUICreate("Overkill's Google DNS Updater",800,800) $gDomainLabel = GUICtrlCreateLabel("FQDN",21,8) $gDomainInput = GUICtrlCreateInput("",60,5,300) $gUserLabel = GUICtrlCreateLabel("Username",5,36) $gUserInput = GUICtrlCreateInput("",60,32,130,Default,BitOR($GUI_SS_DEFAULT_INPUT,$ES_PASSWORD)) $gPasswordLabel = GUICtrlCreateLabel("Password",6,64) $gPassInput = GUICtrlCreateInput("",60,60,130,Default,BitOR($GUI_SS_DEFAULT_INPUT,$ES_PASSWORD)) $gAddButton = GUICtrlCreateButton("ADD DOMAIN",200,31,160,52) $gCurrentIP = GUICtrlCreateLabel("Current IP: " & _CheckIP(),5,780) $gDomainList = GUICtrlCreateListView("Domain | Resolved IP | Update Status",5,120,600,600) GUISetState(@SW_SHOW,$gMainGUI) while 1 $m = GUIGetMsg() IF $M = $GUI_EVENT_CLOSE then Exit IF $M = $gAddButton Then $sAddDomain = GUICtrlRead($gDomainInput) $sAddUser = GUICtrlRead($gUserInput) $sAddPass = GUICtrlRead($gPassInput) $sResolveIP = _DNSCheck($sAddDomain) ;Google wants you to avoid sending updates when there are no changes If StringCompare($sResolveIP,_CheckIP()) = 0 Then $sStatus = "No change, not sending update" Else $sStatus = _DNSUpdate($sAddDomain,$sAddUser,$sAddPass) EndIf ;Check to make sure all fields are completed before continuing IF StringLen($sAddDomain) = 0 OR StringLen($sAddUser) = 0 OR StringLen($sAddPass) = 0 Then MsgBox(0,"","Please complete all fields") Else ; If the fields all have data, then continue ;Check to see if the entry exists in the array already $iSanity = _ArraySearch($aDomainList,$sAddDomain) IF $iSanity = 0 Then _ArrayAdd($aDomainList,$sAddDomain & "|" & $sAddUser & "|" & $sAddPass ) If @error = 0 Then $aDomainList[0][0] += 1 $aDomainList[$aDomainList[0][0]][3] = GUICtrlCreateListViewItem($sAddDomain & "|" & $sResolveIP & "|" & $sStatus,$gDomainList) Else MsgBox(0,"","Error adding input to list") EndIf Else ; If $iSanity <> 0 ; Update existing info in array and listviewitem $aDomainList[$iSanity][0] = $sAddDomain $aDomainList[$iSanity][1] = $sAddUser $aDomainList[$iSanity][2] = $sAddPass GUICtrlSetData($aDomainList[$iSanity][3],$sAddDomain & "|" & $sResolveIP & "|" & $sStatus) EndIf ; If $iSanity = 0 EndIf ; If StringLen... EndIf ; If $m = $gaddbutton WEnd ;---------------------------------------------------------------------------------------- Func _DNSCheck($sFQDN) $sJSON = _INetGetSource("https://dns.google.com/resolve?name=" & $sFQDN & "&cd=1") ConsoleWrite($sJSON & @CRLF) $sIPAddress = StringRegExpReplace($sJSON,'^.*data": "(.*?)".*?$',"\1") Return $sIPAddress EndFunc ;---------------------------------------------------------------------------------------- Func _DNSUpdate($sFQDN,$sUser,$sPass) Local $sGoogleAPIURI = "https://domains.google.com" Local $hOpen = _WinHttpOpen() Local $hConnect = _WinHttpConnect($hOpen, $sGoogleAPIURI) Local $sHeader = _ 'Authorization: Basic ' & _Base64Encode($sUser & ":" & $sPass) & @CRLF & _ 'Accept: */*' & @CRLF & _ 'User-Agent: AutoITScript/' & @AutoItVersion & @CRLF & _ 'Content-Type: application/x-www-form-urlencoded' Local $aHTTPResponse = _WinHttpSimpleSSLRequest($hConnect, "POST", "/nic/update", Default, "hostname=" & $sFQDN, $sHeader, True, Default, Default, Default, True) _WinHttpCloseHandle($hConnect) _WinHttpCloseHandle($hOpen) If IsArray($aHTTPResponse) Then $sHTTPResponse = "Header:" & @CRLF & $aHTTPResponse[0] & @CRLF & "Data:" & @CRLF & $aHTTPResponse[1] & @CRLF & @CRLF & @CRLF Return $aHTTPResponse[1] Else $sHTTPResponse = "NO REPLY" Return "No reply from " & $sGoogleAPIURI EndIf EndFunc ;---------------------------------------------------------------------------------------- Func _Base64Encode($sData) Local $oXml = ObjCreate("Msxml2.DOMDocument") If Not IsObj($oXml) Then SetError(1, 1, 0) EndIf Local $oElement = $oXml.createElement("b64") If Not IsObj($oElement) Then SetError(2, 2, 0) EndIf $oElement.dataType = "bin.base64" $oElement.nodeTypedValue = Binary($sData) Local $sReturn = $oElement.Text If StringLen($sReturn) = 0 Then SetError(3, 3, 0) EndIf Return $sReturn EndFunc ;---------------------------------------------------------------------------------------- Func _CheckIP() Return _INetGetSource("https://domains.google.com/checkip") EndFunc ;----------------------------------------------------------------------------------------  
×