Sunday, July 26, 2020

Powershell - Evaluate Timestamps of Files in a Directory

I was looking for a script to output files in a directory that may have been changed or created in a given time frame.  The time stamps that are evaluated are the MFT File Record for the file, the creation time, last access time and last write time.  As I was building this, I found a powershell project called PowerForensics which is very nice for more in-depth project related to forensics.

Here is the script use at your own risk:

   

# Modify the directory that you are looking at and the timestamps

$currentDirectory = "c:\windows"
$files = Get-ChildItem $currentDirectory
# Change the below line to look like the below if you want to recursively look at the files in a directory
#$files = Get-ChildItem $currentDirectory -Recurse
$startDate = Get-Date 2020-03-01
$endDate = Get-Date 2020-06-30

# Only outputs results where a creation time, last access time, and last write time are within the timeframe listed above
# Added the function to look at the MFT File Record for the file being examined.  If that time is within the timeframe it 
# is also captured...
#
# Looking at the MFT File Record will indicate time stomping...

Function Color-Text {
    param ( $inDate)
    If (($inDate -ge $startDate) -and ($inDate -le $endDate)) {
        Write-Host "$($inDate) " -ForegroundColor Yellow -NoNewline
    }
    Else {
        Write-Host "$($inDate) " -NoNewline
    }
}

Function Get-ChangeTime {
    # This function is from https://gallery.technet.microsoft.com/scriptcenter/Get-MFT-Timestamp-of-a-file-9227f399
    # Modified to work in this context.

    param ( $inFile )
    $FileStream = [System.IO.File]::Open($inFile, 'Open', 'Read', 'ReadWrite')
    #$FileStream

    #[void][ntdll]
    #region Module Builder
    $Domain = [AppDomain]::CurrentDomain
    $DynAssembly = New-Object System.Reflection.AssemblyName('TestAssembly')
    $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run) # Only run in memory
    $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('TimeStampModule', $False)
    #endregion Module Builder

    #region ENUMs
    $EnumBuilder = $ModuleBuilder.DefineEnum('FileInformationClass', 'Public', [UInt32])
    # Define values of the enum
    [void]$EnumBuilder.DefineLiteral('FileDirectoryInformation', [UInt32] 1)
    [void]$EnumBuilder.DefineLiteral('FileBasicInformation', [UInt32] 4)
    [void]$EnumBuilder.DefineLiteral('FileModeInformation', [UInt32] 16)
    [void]$EnumBuilder.DefineLiteral('FileHardLinkInformation', [UInt32] 46)

    #Create ENUM Type
    [void]$EnumBuilder.CreateType()
    #endregion ENUMs

   
    #region FileBasicInformation
    #Define STRUCT
    $Attributes = 'AutoLayout, AnsiClass, Class, ExplicitLayout, Sealed, BeforeFieldInit,public'
    $TypeBuilder = $ModuleBuilder.DefineType('FileBasicInformation', $Attributes, [System.ValueType], 8, 0x28)
    $CreateTimeField = $TypeBuilder.DefineField('CreationTime', [UInt64], 'Public')
    $CreateTimeField.SetOffset(0)
    $LastAccessTimeField = $TypeBuilder.DefineField('LastAccessTime', [UInt64], 'Public')
    $LastAccessTimeField.SetOffset(8)
    $LastWriteTimeField = $TypeBuilder.DefineField('LastWriteTime', [UInt64], 'Public')
    $LastWriteTimeField.SetOffset(16)
    $ChangeTimeField = $TypeBuilder.DefineField('ChangeTime', [UInt64], 'Public')
    $ChangeTimeField.SetOffset(24)
    $FileAttributesField = $TypeBuilder.DefineField('FileAttributes', [UInt64], 'Public')
    $FileAttributesField.SetOffset(32)
    #Create STRUCT Type
    [void]$TypeBuilder.CreateType()
    #endregion FileBasicInformation

    #region IOStatusBlock
    #Define STRUCT
    $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
    $TypeBuilder = $ModuleBuilder.DefineType('IOStatusBlock', $Attributes, [System.ValueType], 1, 0x10)
    [void]$TypeBuilder.DefineField('status', [UInt64], 'Public')
    [void]$TypeBuilder.DefineField('information', [UInt64], 'Public')
    #Create STRUCT Type
    [void]$TypeBuilder.CreateType()
    #endregion IOStatusBlock

    #region DllImport    $TypeBuilder = $ModuleBuilder.DefineType('ntdll', 'Public, Class')    #region NtQueryInformationFile Method    $PInvokeMethod = $TypeBuilder.DefineMethod(        'NtQueryInformationFile', #Method Name        [Reflection.MethodAttributes] 'PrivateScope, Public, Static, HideBySig, PinvokeImpl', #Method Attributes        [IntPtr], #Method Return Type        [Type[]] @([Microsoft.Win32.SafeHandles.SafeFileHandle], [IOStatusBlock], [IntPtr] ,[UInt16], [FileInformationClass]) #Method Parameters    )
    $DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String]))    $FieldArray = [Reflection.FieldInfo[]] @(        [Runtime.InteropServices.DllImportAttribute].GetField('EntryPoint'),        [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError')    )
    $FieldValueArray = [Object[]] @(        'NtQueryInformationFile', #CASE SENSITIVE!!        $True    )
    $SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder(        $DllImportConstructor,        @('ntdll.dll'),        $FieldArray,        $FieldValueArray    )
    $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)    #endregion NtQueryInformationFile Method
    [void]$TypeBuilder.CreateType()    #endregion DllImport


    $fbi = New-Object "FileBasicInformation"
    $iosb = New-Object "IOStatusBlock"
    $p_fbi = [System.Runtime.InteropServices.Marshal]::AllocHGlobal([System.Runtime.InteropServices.Marshal]::SizeOf($fbi))
    
    # Pull file timestamps from file
    #[DllImport("ntdll.dll", SetLastError=$true)] 
    $iprc = [ntdll]::NtQueryInformationFile($FileStream.SafeFileHandle, $iosb, $p_fbi, 
        [System.Runtime.InteropServices.Marshal]::SizeOf($fbi), [FileInformationClass]::FileBasicInformation
    )

    

    # Check to make sure no issues occurred
    $IsOK = (($iprc -eq [intptr]::Zero) -AND ($iosb.status -eq 0))

    If ($IsOK) {
        # Pull data from unmanaged memory block into a usable object
        # The below line in the original document does notwork.  Add [System.Type] in the front and it works...
        # https://poshsecurity.com/blog/2014/2/3/powershell-error-the-specified-structure-must-be-blittable-o.html
        $fbi = [System.Runtime.InteropServices.Marshal]::PtrToStructure($p_fbi, [System.Type][FileBasicInformation])
        #$Object = [pscustomobject]@{
        #    FullName = $FileStream.Name
        #    CreationTime = [datetime]::FromFileTime($fbi.CreationTime)
        #    LastAccessTime = [datetime]::FromFileTime($fbi.LastAccessTime)
        #    LastWriteTime = [datetime]::FromFileTime($fbi.LastWriteTime)
        #    ChangeTime = [datetime]::FromFileTime($fbi.ChangeTime)
        #}
        #$Object.PSTypeNames.Insert(0,'System.Io.FileTimeStamp')
        return [datetime]::FromFileTime($fbi.ChangeTime)
    } Else {
        return "$($Item): $(New-Object ComponentModel.Win32Exception)"
    }
    #region Perform Cleanup
    $FileStream.Close()
    # Deallocate memory
    If ($p_fbi -ne [intptr]::Zero) {
        [System.Runtime.InteropServices.Marshal]::FreeHGlobal($p_fbi)
    }

}


ForEach ($file in $files) {
    $creationTime = $file.CreationTime
    $lastAccessTime = $file.LastAccessTime
    $lastWriteTime = $file.LastWriteTime
    Try {
        If ($file.Attributes -notmatch 'Directory') {
            $changeTime = Get-ChangeTime -inFile $file.FullName
        }
        Else {
            # Arbitrary change time if one is not found by the function...
            $changeTime = (Get-Date).AddYears(-20)
        }
    }
    Catch {
        # Arbitrary change time if one is not found by the function...
        $changeTime = (Get-Date).AddYears(-20)
    }


    # Only output what matches the criteria above
    # If the MFT time of creation matches the timeframe it is output
    If ((($creationTime -ge $startDate) -and ($creationTime -le $endDate)) -or (($lastAccessTime -ge $startDate) -and ($lastAccessTime -le $endDate)) -or (($lastWriteTime -ge $startDate) -and ($lastWriteTime -le $endDate)) -or (($changeTime -ge $startDate) -and ($changeTime -le $endDate))) {
        Write-Host "-- File Information --"
        Write-Host "Name: " -NoNewLine  -ForegroundColor Green
        Write-Host "$($file.FullName)"
        Write-Host "Attributes: " -NoNewline -ForegroundColor Green
        Write-Host "$($file.Attributes)" 
        Write-Host "Length: " -NoNewline -ForegroundColor Green
        Write-Host "$($file.Length)"
        If ($file.Attributes -notmatch 'Directory') {
            $changeTime = Get-ChangeTime -inFile $file.FullName
            Write-Host "MFT Change Time: " -NoNewline -ForegroundColor Green
            Write-Host (Color-Text -inDate $changeTime)
        }
        Write-Host "Create: " -NoNewline -ForegroundColor Green
        Write-Host (Color-Text -inDate $creationTime) -NoNewline
        Write-Host "Last Access Time: " -NoNewline -ForegroundColor Green
        Write-Host (Color-Text -inDate $lastAccessTime) -NoNewline
        Write-Host "Last Write Time: " -NoNewline -ForegroundColor Green
        Write-Host (Color-Text -inDate $lastWriteTime)
        If ($file.Attributes -notmatch 'Directory') {
            $md5 = (Get-FileHash -LiteralPath $file.FullName -Algorithm MD5 -ErrorAction SilentlyContinue).Hash
            $sha1 = (Get-FileHash -LiteralPath $file.FullName -Algorithm SHA1 -ErrorAction SilentlyContinue).Hash
            $sha256 = (Get-FileHash -LiteralPath $file.FullName -Algorithm SHA256 -ErrorAction SilentlyContinue).Hash
            Write-Host "-- Hashes --"
            Write-Host "MD5: " -NoNewline -ForegroundColor Green
            Write-Host $md5 
            Write-Host "SHA1: " -NoNewline -ForegroundColor Green
            Write-Host $sha1
            Write-Host "SHA256: " -NoNewline -ForegroundColor Green
            Write-Host $sha256
        }
        Write-Host "`r`n`r`n"
    }
    
}


Saturday, July 18, 2020

Python3 Script Obfuscator

A while ago I wrote a python script obfuscator for python2.  Today I needed this and rewrote it for python3.


#!/usr/bin/python3

import base64
import zlib
import bz2

def applyb64(i):
 print("base64 Encoding the Information")
 headerInfo = '#!/usr/bin/python3\n'
 headerInfo += 'import base64;exec(base64.b64decode("'
 encodedInfo = base64.b64encode(i.encode("utf-8"))
 footerInfo = '"))'
 outputInfo = headerInfo + str(encodedInfo, "utf-8") + footerInfo
 return outputInfo

def applyZLIB(i):
 print("zlib Compress the Information")
 compressionLevel = input("Select compression level (1-9): ")
 headerInfo = '#!/usr/bin/python3\n'
 headerInfo += 'import zlib, base64;z=base64.b64decode("'
 encodedInfo = base64.b64encode(zlib.compress(i.encode("utf-8"), int(compressionLevel)))
 footerInfo = '");y=zlib.decompress(z);exec(y)'
 outputInfo = headerInfo + str(encodedInfo, "utf-8") + footerInfo
 return outputInfo

def applyBZ2(i):
 print("bz2 Compress the Information")
 compressionLevel = input("Select compression level (1-9): ")
 headerInfo = '#!/usr/bin/python3\n'
 headerInfo += 'import bz2, base64;w=base64.b64decode("'
 encodedInfo = base64.b64encode(bz2.compress(i.encode("utf-8"), int(compressionLevel)))
 footerInfo = '");r=bz2.decompress(w);exec(r)'
 outputInfo = headerInfo + str(encodedInfo, "utf-8") + footerInfo
 return outputInfo

def applyXOR(i):
 print("XOR Information")
 hexValue = input("XOR INT Value: ")
 headerInfo = '#!/usr/bin/python3\n'
 headerInfo += 'import base64;j=bytearray(base64.b64decode("'
 bArray = bytearray(i.encode("utf-8"))
 for b in range(len(bArray)):
  bArray[b] ^= int(hexValue)
 encodedInfo = base64.b64encode(bArray)
 footerInfo = '"));\n'
 footerInfo += 'for c in range(len(j)): j[c] ^= ' + hexValue + '\n'
 footerInfo += 'exec(str(j, "utf-8"))'
 outputInfo = headerInfo + str(encodedInfo, "utf-8") + footerInfo
 return outputInfo


def executeRecipe(r):
 outputPython = "outFile.py"
 print 
 filename = input("Filename to apply recipe: ")
 print
 info = ''
 f = open(filename, "r")
 for line in f:
  if '#!/usr/bin/python3' not in line:
   info += line
 f.close()
 for recipe in r:
  if recipe == "b64":
   outputRecipe = applyb64(info)
   info = outputRecipe
  elif recipe == "XOR":
   outputRecipe = applyXOR(info)
   info = outputRecipe
  elif recipe == "zlib":
   outputRecipe = applyZLIB(info)
   info = outputRecipe
  elif recipe == "bz2":
   outputRecipe = applyBZ2(info)
   info = outputRecipe
 f = open(outputPython, "w")
 f.write(outputRecipe)
 f.close()
 



def main():
 recipes = []
 selection = 'a'
 print
 print("Build a Encoded/Compressed File from a Recipe you Build")
 while selection != 'q' and selection != 'Q':
  print("Select which task to fulfill:")
  print("1. Base64 Encode")
  print("2. XOR")
  print("3. zlib Compress")
  print("4. bz2 Compress")
  print
  print("D. Display Recipe")
  print("E. Execute Recipe")
  print("Q. Quit")
  selection = input("> ")
  if selection == '1':
   print
   print("base64")
   recipes.append("b64")
   print
  elif selection == '2':
   print
   print("XOR")
   recipes.append("XOR")
   print
  elif selection == '3':
   print
   print("zlib")
   recipes.append("zlib")
   print
  elif selection == '4':
   print
   print("bz2")
   recipes.append("bz2")
   print
  elif selection == "D" or selection == "d":
   print
   print("Recipe:")
   for recipe in recipes:
    print(recipe)
   print
  elif selection == "E" or selection == "e":
   print
   print("Execute the Recipe")
   executeRecipe(recipes)
   print
   recipes = []


if __name__ == "__main__":
    main()
  


Test Authentication from Linux Console using python3 pexpect

Working with the IT420 lab, you will discover that we need to discover a vulnerable user account.  The following python3 script uses the pex...