commit bd88bfde5270e1372c98c76bc2fbdd828e53c623 Author: hasherezade Date: Mon Aug 20 01:56:30 2018 +0200 [INIT] First working version (for 32bit PE) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fc2ff53 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.aps diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..4cc5a67 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "libpeconv"] + path = libpeconv + url = https://github.com/hasherezade/libpeconv.git diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..c64e34f --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required ( VERSION 2.8 ) + +# replace "peconv_project" by your own project name: +project ( pe_to_shellcode ) + +# libs +# modules: +set ( M_PARSER "libpeconv/libpeconv" ) + +# modules paths: +set (PECONV_DIR "${CMAKE_SOURCE_DIR}/${M_PARSER}" CACHE PATH "PEConv main path") +add_subdirectory ( ${PECONV_DIR} ) +set ( PECONV_LIB $ CACHE FILE "PEConvLib library path" ) + +# Add sub-directories +# +add_subdirectory ( pe_to_shellcode ) +add_subdirectory ( test_shc ) diff --git a/README.md b/README.md new file mode 100644 index 0000000..4cbba0d --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# pe_to_shellcode +Converts PE so that it can be then injected just like a normal shellcode. + +Clone: +- +Use recursive clone to get the repo together with all the submodules: +
+git clone --recursive https://github.com/hasherezade/pe_to_shellcode.git
+
diff --git a/libpeconv b/libpeconv new file mode 160000 index 0000000..10a841b --- /dev/null +++ b/libpeconv @@ -0,0 +1 @@ +Subproject commit 10a841b47e5d5922306f97e80a3610139fd79759 diff --git a/pe_to_shellcode/CMakeLists.txt b/pe_to_shellcode/CMakeLists.txt new file mode 100644 index 0000000..1abad99 --- /dev/null +++ b/pe_to_shellcode/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required (VERSION 2.8) + +project ( pe_to_shellcode ) + +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") + +# include libpeconv headers: +include_directories ( ${PECONV_DIR}/include ) + +set (srcs +#put your sources here +) + +# general headers - they will be used for both EXE and DLL: +set (hdrs + resource.h +) + +set (rsrc + resource.rc +) + +add_executable ( ${PROJECT_NAME} ${hdrs} ${srcs} ${rsrc} main.cpp ) + + +# link with libpeconv.lib +target_link_libraries ( ${PROJECT_NAME} ${PECONV_LIB} ) + +#dependencies: +add_dependencies( ${PROJECT_NAME} libpeconv ) diff --git a/pe_to_shellcode/LICENSE b/pe_to_shellcode/LICENSE new file mode 100644 index 0000000..c32a489 --- /dev/null +++ b/pe_to_shellcode/LICENSE @@ -0,0 +1,10 @@ +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 HOLDER 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. diff --git a/pe_to_shellcode/main.cpp b/pe_to_shellcode/main.cpp new file mode 100644 index 0000000..b36cf39 --- /dev/null +++ b/pe_to_shellcode/main.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include "peconv.h" +#include "resource.h" + +bool overwrite_hdr(BYTE *my_exe, size_t exe_size, DWORD raw) +{ + BYTE redir_code[] = "\x4D\x5A" + "\xE8\x00\x00\x00\x00" + "\x5B" // pop ebx + "\x81\xC3" // add ebx, + "\x59\x04\x00\x00" // value + "\x53\xC3"; + raw -= 7; //offset + //TODO: peconv virtual to raw + memcpy(redir_code + 10, &raw, sizeof(DWORD)); + memcpy(my_exe, redir_code, sizeof(redir_code)); + return true; +} + +BYTE* shellcodify32(BYTE *my_exe, size_t exe_size, size_t &out_size) +{ + out_size = 0; + size_t stub_size = 0; + BYTE *stub32 = peconv::load_resource_data(stub_size, STUB32); + if (!stub32) { + std::cout << "Stub not loaded" << std::endl; + return nullptr; + } + size_t ext_size = exe_size + stub_size; + BYTE *ext_buf = peconv::alloc_aligned(ext_size, PAGE_READWRITE); + if (!ext_buf) { + return nullptr; + } + memcpy(ext_buf, my_exe, exe_size); + memcpy(ext_buf + exe_size, stub32, stub_size); + + DWORD raw_addr = exe_size; + overwrite_hdr(ext_buf, ext_size, raw_addr); + + out_size = ext_size; + return ext_buf; +} + +bool is_supported_pe(BYTE *my_exe, size_t exe_size) +{ + if (!my_exe) return false; + WORD arch = peconv::get_nt_hdr_architecture(my_exe); + if (arch != IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + std::cout << "Only PE 32bit is supported!" << std::endl; + return false; + } + if (!peconv::has_relocations(my_exe)) { + std::cout << "The PE must have relocations!" << std::endl; + return false; + } + if (peconv::get_subsystem(my_exe) != IMAGE_SUBSYSTEM_WINDOWS_GUI) { + std::cout << "Subsystem must be GUI!" << std::endl; + return false; + } + return true; +} + +int main(int argc, char *argv[]) +{ + if (argc < 2) { + std::cout << "PE to shellcode" << std::endl; + std::cout << "Args: [output_file]" << std::endl; + system("pause"); + return 0; + } + + size_t exe_size = 0; + std::string in_path = argv[1]; + std::string out_str = in_path + ".shc"; + if (argc > 2) { + out_str = argv[2]; + } + + std::cout << "Reading module from: " << in_path << std::endl; + BYTE *my_exe = peconv::load_file(in_path.c_str(), exe_size); + if (!my_exe) { + system("pause"); + return -1; + } + if (!is_supported_pe(my_exe, exe_size)) { + std::cout << "[-] Not supported input file!" << std::endl; + peconv::free_file(my_exe); + return -2; + } + size_t ext_size = 0; + BYTE *ext_buf = shellcodify32(my_exe, exe_size, ext_size); + if (!ext_buf) { + std::cout << "[-] Adding the stub failed!" << std::endl; + peconv::free_file(my_exe); + return -3; + } + if (peconv::dump_to_file(out_str.c_str(), ext_buf, ext_size)) { + std::cout << "[+] Saved to file: " << out_str << std::endl; + } + else { + std::cout << "[-] Failed to save the output!" << std::endl; + } + peconv::free_file(my_exe); + peconv::free_aligned(ext_buf); + return 0; +} diff --git a/pe_to_shellcode/resource.h b/pe_to_shellcode/resource.h new file mode 100644 index 0000000..24afdfb --- /dev/null +++ b/pe_to_shellcode/resource.h @@ -0,0 +1,4 @@ +// resource.h + +#define STUB32 101 +#define STUB64 102 diff --git a/pe_to_shellcode/resource.rc b/pe_to_shellcode/resource.rc new file mode 100644 index 0000000..0250fce --- /dev/null +++ b/pe_to_shellcode/resource.rc @@ -0,0 +1,56 @@ +// resource.rc : + +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "windows.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_PLK) +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""windows.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// RCDATA +// + +STUB32 RCDATA "stub32.bin" + +#endif +///////////////////////////////////////////////////////////////////////////// diff --git a/pe_to_shellcode/stub32.bin b/pe_to_shellcode/stub32.bin new file mode 100644 index 0000000..2b8cc8a Binary files /dev/null and b/pe_to_shellcode/stub32.bin differ diff --git a/pe_to_shellcode/stub_license.md b/pe_to_shellcode/stub_license.md new file mode 100644 index 0000000..3dbd0fe --- /dev/null +++ b/pe_to_shellcode/stub_license.md @@ -0,0 +1,31 @@ +The stub32.bin is a rip-off: +https://github.com/stephenfewer/ReflectiveDLLInjection/blob/master/dll/src/ReflectiveLoader.c + +LICENSE: +//===============================================================================================// +// Copyright (c) 2012, 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. +//===============================================================================================// diff --git a/test_shc/CMakeLists.txt b/test_shc/CMakeLists.txt new file mode 100644 index 0000000..afb2073 --- /dev/null +++ b/test_shc/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required (VERSION 2.8) + +project ( test_shc ) + +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") + +# include libpeconv headers: +include_directories ( ${PECONV_DIR}/include ) + +set (srcs +#put your sources here +) + +add_executable ( ${PROJECT_NAME} ${hdrs} ${srcs} ${rsrc} main.cpp ) + + +# link with libpeconv.lib +target_link_libraries ( ${PROJECT_NAME} ${PECONV_LIB} ) + +#dependencies: +add_dependencies( ${PROJECT_NAME} libpeconv ) diff --git a/test_shc/LICENSE b/test_shc/LICENSE new file mode 100644 index 0000000..c32a489 --- /dev/null +++ b/test_shc/LICENSE @@ -0,0 +1,10 @@ +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 HOLDER 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. diff --git a/test_shc/main.cpp b/test_shc/main.cpp new file mode 100644 index 0000000..3bb0823 --- /dev/null +++ b/test_shc/main.cpp @@ -0,0 +1,32 @@ +#include +#include + +#include "peconv.h" + +int main(int argc, char *argv[]) +{ + if (argc < 2) { + std::cerr << "Args: " << std::endl; + system("pause"); + return 0; + } + + size_t exe_size = 0; + char* in_path = argv[1]; + + std::cout << "Reading module from: " << in_path << std::endl; + BYTE *my_exe = peconv::load_file(in_path, exe_size); + if (!my_exe) { + system("pause"); + return -1; + } + + std::cout << "Test it!" << std::endl; + BYTE *test_buf = peconv::alloc_aligned(exe_size, PAGE_EXECUTE_READWRITE); + if (test_buf) { + memcpy(test_buf, my_exe, exe_size); + void (*my_main)() = (void (*)()) ((ULONGLONG)test_buf); + my_main(); + } + return 0; +}