samedi 6 février 2016

RSA with PowerShell - PowerRSA


Based on this very good article (, I have implemented a RSA algorithm.

The code :

Caution : I did it for fun. Don't use it in production ;-) For the demo, I encrypt directly the data, in the real world, you encrypt the symetric key (which you exchange between Sender and Recipient) that will encrypt the data.

Generate the keys 

To generate the Modulus, the private key and the public key, enter this command

.\PowerRSA.ps1 -Method GenKeys 

PowerRSA will generate the necessary keys
PS F:\Crypto> .\PowerRSA.ps1 -Method GenKeys
Keys generating...

Keys saved in F:\Crypto\20160206104626 

and save them in a folder

Example of the Modulus generated

To generate a 2048-bit key :

.\PowerRSA.ps1 -Method GenKeys -KeyType 2048-bit

How I do it

"This is the original algorithm.
  1. Generate two large random primes, p and q, of approximately equal size such that their product n = pq is of the required bit length, e.g. 1024 bits.
  2. Compute n = pq and (phi) φ = (p-1)(q-1).
  3. Choose an integer e, 1 < e < phi, such that gcd(e, phi) = 1.
  4. Compute the secret exponent d, 1 < d < phi, such that ed ≡ 1 (mod phi).
  5. The public key is (n, e) and the private key (d, p, q). Keep all the values d, p, q and phi secret. [We prefer sometimes to write the private key as (n, d) because you need the value of n when using d. Other times we might write the key pair as ((N, e), d).]
    • n is known as the modulus.
    • e is known as the public exponent or encryption exponent or just the exponent.
    • d is known as the secret exponent or decryption exponent."

For length k required of 2048 bits

  1. I generate big (128 bytes) random number p and check if it is a Prime number with Rabbin-Miller algorithm
  2. I generate big (128 bytes) random number q and check if it is a Prime number with Rabbin-Miller algorithm
  3. I compute n (modulus) which is p * q
  4. I compute φ (PHI) which is (p-1)*(q-1)
  5. We choose 65537 or 10001 in Hex for Exponent Public Key(why ? In practice, common choices for e are 3, 5, 17, 257 and 65537 (216+1). These particular values are chosen because they are primes and make the modular exponentiation operation faster, having only two bits of value 1.
    Aside: These five numbers are the first five Fermat numbers, referred to as F0 to F4, where Fx=2^(2^x)+1. Just be careful, these first five Fermat numbers are prime ("Fermat primes"), but the numbers F5 and above are not prime. 
    For example, F5 = 4294967297 = 641 × 6700417.
    The usual choice for e is F4 = 65537 = 0x10001. Also, having chosen e, it is simpler to test whether gcd(e, p-1)=1 and gcd(e, q-1)=1 while generating and testing the primes in step 1. Values of p or q that fail this test can be rejected there and then. )
  6.  I compute d which is the Exponent Private Key using the Extended Euclidean algorithm 

Encrypt data

To encrypt data using PowerRSA enter this command

.\PowerRSA.ps1 -Method Enc -Exponent F:\Crypto\20160206104626\PublicKey -Modulus F:\Crypto\20160206104626\Modulus 

Enter the data string to encrypt :

Enter message to encrypt: Hi! I'm an encrypted data string 

PowerRSA will encrypt data :
PS F:\Crypto> .\PowerRSA.ps1 -Method Enc -Exponent F:\Crypto\20160206104626\PublicKey -Modulus F:\Crypto\20160206104626\Modulus
Enter message to encrypt: Hi! I'm an encrypted data string :-)
Data saved in F:\Crypto\20160206110641 

and save it in a folder

Encrypted data looks like that 

How I do it

"Sender A does the following:-

Obtains the recipient B's public key (n, e).
Represents the plaintext message as a positive integer m, 1 < m < n [see note 4].
Computes the ciphertext c = me mod n.
Sends the ciphertext c to B."

With the public key (which is composed of the Modulus and the Public Exponent), I encrypt the data string provided.

To crypt it and for each character: 
  1. I transform character into an integer representation
  2. I generate a Random Padding 
  3. I concatenate the integer character representation with the random padding = m
  4. I encrypt the concatenation result by compute c = me % n where c is the encrypted character, m = the concatenate integer character with random padding, e = the public Exponent key and n = the Modulus

Decrypt data

To decrypt data using PowerRSA enter this command

.\PowerRSA.ps1 -Method Dec -Data F:\Crypto\20160206110641\Data -Exponent F:\Crypto\20160206104626\PrivateKey -Modulus F:\Crypto\20160206104626\Modulus 

PowerRSA will decrypt the data :
PS F:\Crypto> .\PowerRSA.ps1 -Method Dec -Data F:\Crypto\20160206110641\Data -Exponent F:\Crypto\20160206104626\PrivateKey -Modulus F:\Crypto\20160206104626\Modulus
Hi! I'm an encrypted data string :-) 

How I do it

"Recipient B does the following:-

Uses his private key (n, d) to compute m = cd mod n.
Extracts the plaintext from the message representative m."

With the private key (which is composed of the Modulus and the Private Exponent), I decrypt the data string provided.
  1. I decrypt the encoded string by compute m = cd % n
  2. I remove the random padding
  3. I transform the integer into its character representation

samedi 12 septembre 2015

PowerShell - dbghelp reflexion to write a MiniDump

function Write-MiniDumpDBGHelp ($process, $dumpFilePath){
    $MethodDefinition = @'
[DllImport("DbgHelp.dll", CharSet = CharSet.Unicode)]
public static extern bool MiniDumpWriteDump(
    IntPtr hProcess,
    uint processId,
    IntPtr hFile,
    uint dumpType,
    IntPtr expParam,
    IntPtr userStreamParam,
    IntPtr callbackParam

    $dbghelp = Add-Type -MemberDefinition $MethodDefinition -Name 'dbghelp' -Namespace 'Win32' -PassThru

    $miniDumpWithFullMemory = [UInt32] 2

    $processId = $process.Id
    $processName = $process.Name
    $processHandle = $process.Handle
    $processFileName = "$($processName).dmp"

    $processDumpPath = "$dumpFilePath\$processFileName"

    $fileStream = New-Object IO.FileStream($processDumpPath, [IO.FileMode]::Create)
        $result = $dbghelp::MiniDumpWriteDump($processHandle,$processId,$fileStream.SafeFileHandle.DangerousGetHandle(),$miniDumpWithFullMemory,[IntPtr]::Zero,[IntPtr]::Zero,[IntPtr]::Zero)
        if(!$result) {
            Write-Host "Error : cannot dump the process" -ForegroundColor Red
        Write-Host "Error : cannot dump the process" -ForegroundColor Red

lundi 3 août 2015

PowerShell - Get username, Logon Date, Password Last Set and Creation date of local users

Hi !

Here's a little PowerShell script to retrieve from the registry the username, Logon Date, Password Last Set and Creation date of the local users on a windows computer.

You can find here :

# Thanks to Boe Prox for his Get-RegistryKeyTimestamp function (
function Get-RegistryKeyTimestamp {
        DefaultParameterSetName = 'ByValue'
    Param (
        [parameter(ValueFromPipeline=$True, ParameterSetName='ByValue')]
    Begin {
        #region Create Win32 API Object
        Try {
        } Catch {
            #region Module Builder
            $Domain = [AppDomain]::CurrentDomain
            $DynAssembly = New-Object System.Reflection.AssemblyName('RegAssembly')
            $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run) # Only run in memory
            $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('RegistryTimeStampModule', $False)
            #endregion Module Builder

            #region DllImport
            $TypeBuilder = $ModuleBuilder.DefineType('advapi32', 'Public, Class')

            #region RegQueryInfoKey Method
            $PInvokeMethod = $TypeBuilder.DefineMethod(
                'RegQueryInfoKey', #Method Name
                [Reflection.MethodAttributes] 'PrivateScope, Public, Static, HideBySig, PinvokeImpl', #Method Attributes
                [IntPtr], #Method Return Type
                [Type[]] @(
                    [Microsoft.Win32.SafeHandles.SafeRegistryHandle], #Registry Handle
                    [System.Text.StringBuilder], #Class Name
                    [UInt32 ].MakeByRefType(),  #Class Length
                    [UInt32], #Reserved
                    [UInt32 ].MakeByRefType(), #Subkey Count
                    [UInt32 ].MakeByRefType(), #Max Subkey Name Length
                    [UInt32 ].MakeByRefType(), #Max Class Length
                    [UInt32 ].MakeByRefType(), #Value Count
                    [UInt32 ].MakeByRefType(), #Max Value Name Length
                    [UInt32 ].MakeByRefType(), #Max Value Name Length
                    [UInt32 ].MakeByRefType(), #Security Descriptor Size          
                    [long].MakeByRefType() #LastWriteTime
                ) #Method Parameters

            $DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String]))
            $FieldArray = [Reflection.FieldInfo[]] @(      

            $FieldValueArray = [Object[]] @(
                'RegQueryInfoKey', #CASE SENSITIVE!!

            $SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder(

            #endregion RegQueryInfoKey Method

            #endregion DllImport
        #endregion Create Win32 API object
    Process {
        #region Constant Variables
        $ClassLength = 255
        [long]$TimeStamp = $null
        #endregion Constant Variables

        #region Registry Key Data
        If ($PSCmdlet.ParameterSetName -eq 'ByPath') {
            #Get registry key data
            $RegistryKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($RegistryHive, $Computername).OpenSubKey($SubKey)
            If ($RegistryKey -isnot [Microsoft.Win32.RegistryKey]) {
                Throw "Cannot open or locate $SubKey on $Computername"

        $ClassName = New-Object System.Text.StringBuilder $RegistryKey.Name
        $RegistryHandle = $RegistryKey.Handle
        #endregion Registry Key Data

        #region Retrieve timestamp
        $Return = [advapi32]::RegQueryInfoKey(
        Switch ($Return) {
            0 {
               #Convert High/Low date to DateTime Object
                $LastWriteTime = [datetime]::FromFileTime($TimeStamp)

                #Return object
                $Object = [pscustomobject]@{
                    FullName = $RegistryKey.Name
                    Name = $RegistryKey.Name -replace '.*\\(.*)','$1'
                    LastWriteTime = $LastWriteTime
            122 {
                Throw "ERROR_INSUFFICIENT_BUFFER (0x7a)"
            Default {
                Throw "Error ($return) occurred"
        #endregion Retrieve timestamp

function Get-UserName([byte[]]$V) {
    if (-not $V) {return $null};
    $offset = [BitConverter]::ToInt32($V[0x0c..0x0f],0) + 0xCC;
    $len = [BitConverter]::ToInt32($V[0x10..0x13],0);
    return [Text.Encoding]::Unicode.GetString($V, $offset, $len);

function Get-LastLogonDate([byte[]]$F) {
    $lastLogon = ""   
    $hexLastLogon = @()   
    while($i -lt $F.Length) {
        if($i -eq 8 -or ($i -gt 7 -and $i -lt 16)) {
            $lastLogon = $lastLogon + $F[$i]
            $hexLastLogon += '{0:X2}' -f $F[$i]       

    $i=$hexLastLogon.Length - 1
    $lastLogon = ""
    while($i -ge 0) {
        $lastLogon = $lastLogon + $hexLastLogon[$i]
    $lastLogon = "0x$lastLogon"
    return $lastLogon

function Get-PasswordLastSet([byte[]]$F) {
    $passwordLastSet = ""
    $hexPasswordLastSet = @()
    while($i -lt $F.Length) {
        if($i -eq 24 -or ($i -gt 23 -and $i -lt 32)) {
            $passwordLastSet = $passwordLastSet + $F[$i]
            $hexPasswordLastSet += '{0:X2}' -f $F[$i] 

  $i=$hexPasswordLastSet.Length - 1
    $passwordLastSet = ""
    while($i -ge 0) {
        $passwordLastSet = $passwordLastSet + $hexPasswordLastSet[$i]
    $passwordLastSet = "0x$passwordLastSet"
    return $passwordLastSet

function Get-LastWriteTime($key) {
    $RegistryKey = Get-Item $key
    $extendExport = $RegistryKey | Get-RegistryKeyTimestamp   
    return $extendExport
function Get-UserKeys {
    ls HKLM:\SAM\SAM\Domains\Account\Users |
        where {$_.PSChildName -match "^[0-9A-Fa-f]{8}$"} |
            Add-Member AliasProperty KeyName PSChildName -PassThru |           
            Add-Member ScriptProperty UserName {Get-UserName($this.GetValue("V"))} -PassThru |
            Add-Member ScriptProperty LastLogonDate {Get-LastLogonDate($this.GetValue("F"))} -PassThru |
            Add-Member ScriptProperty PasswordLastSet {Get-PasswordLastSet($this.GetValue("F"))} -PassThru

$localUsers = Get-UserKeys| %{
    $logonDate = $([datetime]::FromFileTime($_.LastLogonDate).ToLocalTime())
    $passwordLastSet = $([datetime]::FromFileTime($_.PasswordLastSet).ToLocalTime())
    $subkey = $_.UserName
    $RegistryKey = Get-Item "HKLM:\SAM\SAM\Domains\Account\Users\Names\$subkey"
    $extendExport = $RegistryKey | Get-RegistryKeyTimestamp
    $lastWriteTime = $($extendExport.LastWriteTime.ToLocalTime())
    "{0}::{1}::{2}::{3}" -f ($_.UserName,$logonDate,$passwordLastSet,$lastWriteTime)}
"{0}::{1}::{2}::{3}" -f ("UserName","LogonDate","PasswordLastSet","LastWriteTime")

Result : 

Administrator::7/26/2012 3:22:17 AM::7/26/2012 3:27:03 AM::8/1/2015 10:10:34 AM
Guest::12/31/1600 7:00:00 PM::12/31/1600 7:00:00 PM::8/1/2015 10:10:34 AM
Test1::12/31/1600 7:00:00 PM::10/20/2013 3:53:30 AM::8/2/2015 4:36:30 PM
Test2::8/19/2013 1:30:05 AM::7/24/2013 3:47:52 PM::8/1/2015 10:10:34 AM
Test3::6/11/2015 7:16:26 PM::3/18/2015 5:12:51 PM::8/1/2015 10:10:34 AM
TestRegistry::8/1/2015 3:42:15 PM::8/1/2015 4:53:47 PM::8/1/2015 12:39:58 PM 

Enjoy !