Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change powershell platform to windows and add powershell support to some methods #15403

Merged

Conversation

pingport80
Copy link
Contributor

@pingport80 pingport80 commented Jul 8, 2021

Summary

This PR adds powershell support to some methods which required powershell cmdlets to work properly and weren't compatible with windows command shell commands.

This also changes the session.platform value for powershell sessions to windows.

The methods which are enhanced:

  • pwd
  • file?
  • get_processes
  • exist?
  • rm_f
  • rm_rf

Note:

  • rm_rf method had some issues when I tested it, so working on it still.

Verification Steps

>> pwd
=> "C:\\Users\\User\\Links"

>> file?('test-directory')
=> false
>> file?('windows_powershell.exe')
=> true

>> get_processes
=> 
[{"id"=>3992, "name"=>"cmd"},
 {"id"=>5024, "name"=>"conhost"},
...
...
...
 {"id"=>6104, "name"=>"YourPhone"}]
>> has_pid? 496
=> true
>> pidof 'wininit'
=> [496]


>> exist?('test-directory')
=> true
>> exist?('windows_powershell.exe')
=> true

>> rm_f('windows_powershell.exe') # verified that it deleted the file
=> ["windows_powershell.exe"]

@pingport80 pingport80 changed the title Powershell session type improvements Change powershell platform to windows and add powershell support to some methods Jul 8, 2021
@smcintyre-r7 smcintyre-r7 self-assigned this Jul 9, 2021
@smcintyre-r7 smcintyre-r7 added GSoC Google Summer of Code project PRs library labels Jul 9, 2021
@smcintyre-r7
Copy link
Contributor

Did you by chance search through the code base for existing references to the incorrect platform that was previously used win? I want to make sure that when we change this to the correct value of windows we don't break cases where previous developers may have relied on it being defined as win.

@pingport80
Copy link
Contributor Author

pingport80 commented Jul 9, 2021

yeah I have changed session.platform to windows for powershell sessions, but I am not sure if that's the right place!

@smcintyre-r7 smcintyre-r7 added the powershell Issues and PRs related to powershell sessions and payloads label Jul 9, 2021
@bcoles
Copy link
Contributor

bcoles commented Jul 12, 2021

Perhaps a dumb question: what happens when PowerShell is running on Linux ?

@pingport80
Copy link
Contributor Author

Interesting, I also use powershell on linux. But do we have a powershell payload which runs on linux?

@bcoles
Copy link
Contributor

bcoles commented Jul 12, 2021

Interesting, I also use powershell on linux. But do we have a powershell payload which runs on linux?

Maybe, maybe not. But we could one day. Powershell is OS-agnostic.

@pingport80
Copy link
Contributor Author

Makes sense! I think we can take the same approach that's used for differentiating platforms for shell payloads but can't say for sure as I haven't seen the code.

@pingport80
Copy link
Contributor Author

pingport80 commented Jul 12, 2021

This might be a horrible idea 😅 but I meant creating separate interaction classes for powershell_linux and powershell_windows which wil be there just to define the platform. Like how currently command_shell_unix.rb and command_shell_windows.rb are being used.

/lib/msf/base/sessions/powershell_windows.rb

module Msf::Sessions

class PowershellWindows < PowerShell

  def initialize(*args)
      self.platform = "windows"
      super
    end

    def shell_command(cmd)
      super
    end
  end

end

note: I'm totally unaware of what will be changes in handler or payload required for this.

@smcintyre-r7
Copy link
Contributor

smcintyre-r7 commented Jul 12, 2021

Let's not worry about that too much in this PR. Making sure we're in a good position to move forward in the future with supporting Powershell on non-Windows systems seems sufficient for now. I think the approach you described about testing both the platform and session type is a good strategy. We should just keep in mind that a session type of Powershell may not always mean a platform of Windows.

@pingport80
Copy link
Contributor Author

okay cool, that sounds reasonable :)

@smcintyre-r7
Copy link
Contributor

Have you tested these methods with paths that contain spaces? It doesn't look like any are quoted.

Also when I was asking about the old win platform, what I meant was did you search through the framework to see if there were any comparisons of #platform to 'win' implying the author was looking for Powershell sessions (which would be the only type using that platform name). If platform was being compared to 'win' anywhere, those locations should be reviewed to ensure the new and correct platform name isn't going to break anything.

@pingport80
Copy link
Contributor Author

Got it! will quote the paths and check and change if win is being used for checking platform.

@bcoles
Copy link
Contributor

bcoles commented Jul 13, 2021

Got it! will quote the paths and check and change if win is being used for checking platform.

May also be worth checking for 'windows'. There is some inconsistency in Framework between using the two as they're interchangeable.

Copy link
Contributor

@smcintyre-r7 smcintyre-r7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just the two changes requested, everything else looks good. Nice work!

lib/msf/core/post/file.rb Show resolved Hide resolved
lib/msf/core/post/process.rb Outdated Show resolved Hide resolved
@smcintyre-r7
Copy link
Contributor

May also be worth checking for 'windows'. There is some inconsistency in Framework between using the two as they're interchangeable.

I checked around for references comparing session.platform to windows and didn't find anything that looked obviously broken. They just about always explicitly check for meterpreter and fail over the execute OS commands if not which should work in Powershell if there's not a name collision with an applet (sc is the only one I'm currently aware of).

I think we should be set to land these changes shortly and then finish up the rest of the methods in this mixin next.

@pingport80
Copy link
Contributor Author

@smcintyre-r7, I've updated get_processes method to check for powershell 👍 . Kindly review.

Copy link
Contributor

@smcintyre-r7 smcintyre-r7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested out these methods using Windows 7 x64 Powershell v2.0 and all of the methods that have been added look good and the platform name change looks good too. There's some other methods within this mixin that need testing / updating but those will be in another PR.

Testing Output
msf6 payload(cmd/windows/powershell_reverse_tcp) > [*] Powershell session session 1 opened (192.168.159.128:4444 -> 192.168.159.11:49176) at 2021-07-16 14:53:43 -0400

msf6 payload(cmd/windows/powershell_reverse_tcp) > 
msf6 payload(cmd/windows/powershell_reverse_tcp) > use post/windows/gather/checkvm 
msf6 post(windows/gather/checkvm) > pry
[*] Starting Pry shell...
[*] You are in the "post/windows/gather/checkvm" module object

[1] pry(#<Msf::Modules::Post__Windows__Gather__Checkvm::MetasploitModule>)> get_processes
=> [{"name"=>"[System Process]", "pid"=>0},
 {"name"=>"System", "pid"=>4},
 {"name"=>"smss.exe", "pid"=>252},
 {"name"=>"csrss.exe", "pid"=>344},
 {"name"=>"wininit.exe", "pid"=>388},
 {"name"=>"csrss.exe", "pid"=>404},
 {"name"=>"services.exe", "pid"=>452},
 {"name"=>"lsass.exe", "pid"=>484},
 {"name"=>"winlogon.exe", "pid"=>492},
 {"name"=>"lsm.exe", "pid"=>500},
 {"name"=>"svchost.exe", "pid"=>616},
 {"name"=>"svchost.exe", "pid"=>692},
 {"name"=>"svchost.exe", "pid"=>776},
 {"name"=>"svchost.exe", "pid"=>836},
 {"name"=>"svchost.exe", "pid"=>892},
 {"name"=>"audiodg.exe", "pid"=>956},
 {"name"=>"svchost.exe", "pid"=>108},
 {"name"=>"svchost.exe", "pid"=>992},
 {"name"=>"spoolsv.exe", "pid"=>1136},
 {"name"=>"svchost.exe", "pid"=>1164},
 {"name"=>"VGAuthService.exe", "pid"=>1324},
 {"name"=>"vmtoolsd.exe", "pid"=>1392},
 {"name"=>"svchost.exe", "pid"=>1660},
 {"name"=>"svchost.exe", "pid"=>1704},
 {"name"=>"WmiPrvSE.exe", "pid"=>1908},
 {"name"=>"dllhost.exe", "pid"=>1964},
 {"name"=>"msdtc.exe", "pid"=>1184},
 {"name"=>"taskhost.exe", "pid"=>2184},
 {"name"=>"sppsvc.exe", "pid"=>2348},
 {"name"=>"WmiPrvSE.exe", "pid"=>2528},
 {"name"=>"dwm.exe", "pid"=>2664},
 {"name"=>"explorer.exe", "pid"=>2688},
 {"name"=>"vm3dservice.exe", "pid"=>2772},
 {"name"=>"vmtoolsd.exe", "pid"=>2784},
 {"name"=>"SearchIndexer.exe", "pid"=>2940},
 {"name"=>"wmpnetwk.exe", "pid"=>3064},
 {"name"=>"cmd.exe", "pid"=>2004},
 {"name"=>"conhost.exe", "pid"=>1212},
 {"name"=>"SearchProtocolHost.exe", "pid"=>2252},
 {"name"=>"svchost.exe", "pid"=>2420},
 {"name"=>"svchost.exe", "pid"=>2700},
 {"name"=>"WmiApSrv.exe", "pid"=>2712},
 {"name"=>"powershell.exe", "pid"=>2072},
 {"name"=>"tasklist.exe", "pid"=>400}]
[2] pry(#<Msf::Modules::Post__Windows__Gather__Checkvm::MetasploitModule>)> pidof('lsass.exe')
=> [484]
[3] pry(#<Msf::Modules::Post__Windows__Gather__Checkvm::MetasploitModule>)> pwd
=> "C:\\Users\\smcintyre"
[4] pry(#<Msf::Modules::Post__Windows__Gather__Checkvm::MetasploitModule>)> exists?(pwd)
=> true
[5] pry(#<Msf::Modules::Post__Windows__Gather__Checkvm::MetasploitModule>)> file?(pwd)
=> false
[6] pry(#<Msf::Modules::Post__Windows__Gather__Checkvm::MetasploitModule>)> file?("C:\\Windows\\system32\\cmd.exe")
=> true
[7] pry(#<Msf::Modules::Post__Windows__Gather__Checkvm::MetasploitModule>)> cmd_exec("mkdir empty")
=> "\r\n\r\n    Directory: C:\\Users\\smcintyre\r\n\r\n\r\nMode                LastWriteTime     Length Name                              \r\n----                -------------     ------ ----                              \r\nd----         7/16/2021   2:55 PM            empty                             "
[8] pry(#<Msf::Modules::Post__Windows__Gather__Checkvm::MetasploitModule>)> rm_f('empty')
=> ["empty"]
[9] pry(#<Msf::Modules::Post__Windows__Gather__Checkvm::MetasploitModule>)> cmd_exec('dir')
=> "\r\n\r\n    Directory: C:\\Users\\smcintyre\r\n\r\n\r\nMode                LastWriteTime     Length Name                              \r\n----                -------------     ------ ----                              \r\nd-r--          2/5/2020   2:16 PM            Contacts                          \r\nd-r--         7/15/2021  12:06 PM            Desktop                           \r\nd-r--          2/5/2020   2:16 PM            Documents                         \r\nd-r--          2/5/2020   2:16 PM            Downloads                         \r\nd----         7/16/2021   2:55 PM            empty                             \r\nd-r--          2/5/2020   2:16 PM            Favorites                         \r\nd-r--          2/5/2020   2:16 PM            Links                             \r\nd-r--          2/5/2020   2:16 PM            Music                             \r\nd-r--          2/5/2020   2:16 PM            Pictures                          \r\nd-r--          2/5/2020   2:16 PM            Saved Games                       \r\nd-r--          2/5/2020   2:16 PM            Searches                          \r\nd-r--          2/5/2020   2:16 PM            Videos                            "
[10] pry(#<Msf::Modules::Post__Windows__Gather__Checkvm::MetasploitModule>)> puts cmd_exec('dir')


    Directory: C:\Users\smcintyre


Mode                LastWriteTime     Length Name                              
----                -------------     ------ ----                              
d-r--          2/5/2020   2:16 PM            Contacts                          
d-r--         7/15/2021  12:06 PM            Desktop                           
d-r--          2/5/2020   2:16 PM            Documents                         
d-r--          2/5/2020   2:16 PM            Downloads                         
d----         7/16/2021   2:55 PM            empty                             
d-r--          2/5/2020   2:16 PM            Favorites                         
d-r--          2/5/2020   2:16 PM            Links                             
d-r--          2/5/2020   2:16 PM            Music                             
d-r--          2/5/2020   2:16 PM            Pictures                          
d-r--          2/5/2020   2:16 PM            Saved Games                       
d-r--          2/5/2020   2:16 PM            Searches                          
d-r--          2/5/2020   2:16 PM            Videos                            
=> nil
[11] pry(#<Msf::Modules::Post__Windows__Gather__Checkvm::MetasploitModule>)> rm_rf('empty')
=> ["empty"]
[12] pry(#<Msf::Modules::Post__Windows__Gather__Checkvm::MetasploitModule>)> puts cmd_exec('dir')


    Directory: C:\Users\smcintyre


Mode                LastWriteTime     Length Name                              
----                -------------     ------ ----                              
d-r--          2/5/2020   2:16 PM            Contacts                          
d-r--         7/15/2021  12:06 PM            Desktop                           
d-r--          2/5/2020   2:16 PM            Documents                         
d-r--          2/5/2020   2:16 PM            Downloads                         
d-r--          2/5/2020   2:16 PM            Favorites                         
d-r--          2/5/2020   2:16 PM            Links                             
d-r--          2/5/2020   2:16 PM            Music                             
d-r--          2/5/2020   2:16 PM            Pictures                          
d-r--          2/5/2020   2:16 PM            Saved Games                       
d-r--          2/5/2020   2:16 PM            Searches                          
d-r--          2/5/2020   2:16 PM            Videos                            
=> nil
[13] pry(#<Msf::Modules::Post__Windows__Gather__Checkvm::MetasploitModule>)> 

You'll see that rm_f does not delete the empty directory while rm_rf does which is the intended functionality and is consistent with the other session types.

@smcintyre-r7 smcintyre-r7 merged commit d0b2ea6 into rapid7:master Jul 16, 2021
@smcintyre-r7
Copy link
Contributor

Release Notes

This makes changes to the Powershell session type to report its platform using a value consistent with the other session types. It also adds Powershell session support to some methods within the file mixin.

@gwillcox-r7 gwillcox-r7 added enhancement rn-enhancement release notes enhancement labels Jul 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement GSoC Google Summer of Code project PRs library powershell Issues and PRs related to powershell sessions and payloads rn-enhancement release notes enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants