diff --git a/README.md b/README.md index bc77787..591b712 100755 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ ## Background +This is heavily modified shellcodeexec in order to support gcc, mingw and visual studio. Therefore, resulting binaries are much smaller. For example, win32 exe can be smaller than 4 KB when packed with UPX! + +## Background from inquisb + Most of the shellcode launchers out there, including proof of concepts part of many "security" books, detail how to allocate a memory page as readable/writable/executable on POSIX systems, copy over your shellcode and execute it. This works just fine. However, it is limited to POSIX, does not necessarily consider 64-bit architecture and Windows systems. ## Description diff --git a/bin/sce-linux-i586-static.bin b/bin/sce-linux-i586-static.bin new file mode 100755 index 0000000..ed6d3cd Binary files /dev/null and b/bin/sce-linux-i586-static.bin differ diff --git a/bin/sce-linux-x86_64-static.bin b/bin/sce-linux-x86_64-static.bin new file mode 100755 index 0000000..056a37d Binary files /dev/null and b/bin/sce-linux-x86_64-static.bin differ diff --git a/bin/sce-macosx-x64-dyn.bin b/bin/sce-macosx-x64-dyn.bin new file mode 100755 index 0000000..1bfad6b Binary files /dev/null and b/bin/sce-macosx-x64-dyn.bin differ diff --git a/bin/sce-win32.exe b/bin/sce-win32.exe new file mode 100755 index 0000000..2461859 Binary files /dev/null and b/bin/sce-win32.exe differ diff --git a/bin/sce-win64.exe b/bin/sce-win64.exe new file mode 100755 index 0000000..aa6d13b Binary files /dev/null and b/bin/sce-win64.exe differ diff --git a/linux/Makefile b/linux/Makefile deleted file mode 100644 index 8ce996a..0000000 --- a/linux/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -32: - gcc -Wall -Os shellcodeexec.c -o shellcodeexec - strip -sx shellcodeexec - -64: - gcc -Wall -Os shellcodeexec.c -fPIC -o shellcodeexec - strip -sx shellcodeexec diff --git a/linux/shellcodeexec.c b/linux/shellcodeexec.c deleted file mode 100644 index efec8d7..0000000 --- a/linux/shellcodeexec.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - shellcodeexec - Script to execute in memory a sequence of opcodes - Copyright (C) 2011 Bernardo Damele A. G. - web: http://bernardodamele.blogspot.com - email: bernardo.damele@gmail.com - - This source code is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include -#include -#include -#include -#include -#include - -#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) -#include -DWORD WINAPI exec_payload(LPVOID lpParameter); -#else -#include -#include -#include -#endif - -int sys_bineval(char *argv); - -int main(int argc, char *argv[]) -{ - if (argc < 2) { - printf("Run:\n\tshellcodeexec \n"); - exit(-1); - } - - sys_bineval(argv[1]); - - exit(0); -} - -int sys_bineval(char *argv) -{ - size_t len; - -#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) - int pID; - char *code; -#else - int *addr; - size_t page_size; - pid_t pID; -#endif - - len = (size_t)strlen(argv); - -#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) - // allocate a +rwx memory page - code = (char *) VirtualAlloc(NULL, len+1, MEM_COMMIT, PAGE_EXECUTE_READWRITE); - - // copy over the shellcode - strncpy(code, argv, len); - - // execute it by ASM code defined in exec_payload function - WaitForSingleObject(CreateThread(NULL, 0, exec_payload, code, 0, &pID), INFINITE); -#else - pID = fork(); - if(pID<0) - return 1; - - if(pID==0) - { - page_size = (size_t)sysconf(_SC_PAGESIZE)-1; // get page size - page_size = (len+page_size) & ~(page_size); // align to page boundary - - // mmap an +rwx memory page - addr = mmap(0, page_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED|MAP_ANON, 0, 0); - - if (addr == MAP_FAILED) - return 1; - - // copy over the shellcode - strncpy((char *)addr, argv, len); - - // execute it - ((void (*)(void))addr)(); - } - - if(pID>0) - waitpid(pID, 0, WNOHANG); -#endif - - return 0; -} - -#if defined(_WIN64) -void __exec_payload(LPVOID); - -DWORD WINAPI exec_payload(LPVOID lpParameter) -{ - __try - { - __exec_payload(lpParameter); - } - __except(EXCEPTION_EXECUTE_HANDLER) - { - } - - return 0; -} -#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) -DWORD WINAPI exec_payload(LPVOID lpParameter) -{ - __try - { - __asm - { - mov eax, [lpParameter] - call eax - } - } - __except(EXCEPTION_EXECUTE_HANDLER) - { - } - - return 0; -} -#endif diff --git a/linux/shellcodeexec.x32 b/linux/shellcodeexec.x32 deleted file mode 100755 index 2626cdb..0000000 Binary files a/linux/shellcodeexec.x32 and /dev/null differ diff --git a/linux/shellcodeexec.x64 b/linux/shellcodeexec.x64 deleted file mode 100755 index eaa1824..0000000 Binary files a/linux/shellcodeexec.x64 and /dev/null differ diff --git a/windows/README b/sce/README similarity index 100% rename from windows/README rename to sce/README diff --git a/windows/shellcodeexec.sln b/sce/shellcodeexec.sln similarity index 100% rename from windows/shellcodeexec.sln rename to sce/shellcodeexec.sln diff --git a/windows/shellcodeexec.x32.exe b/sce/shellcodeexec.x32.exe similarity index 100% rename from windows/shellcodeexec.x32.exe rename to sce/shellcodeexec.x32.exe diff --git a/sce/shellcodeexec/Makefile b/sce/shellcodeexec/Makefile new file mode 100644 index 0000000..d9058d8 --- /dev/null +++ b/sce/shellcodeexec/Makefile @@ -0,0 +1,16 @@ +CC ?= gcc +STRIP ?= strip +# STRIPFLAGS += -sx +CFLAGS += -Wall -Os +# CFLAGS += -DDEBUG=1 +# CFLAGS += -static +CFLAGS64 += -fPIC +OUT ?= shellcodeexec + +32: + $(CC) shellcodeexec.c -o $(OUT) $(CFLAGS) + $(STRIP) $(STRIPFLAGS) $(OUT) + +64: + $(CC) shellcodeexec.c $(CFLAGS64) -o $(OUT) $(CFLAGS) + $(STRIP) $(STRIPFLAGS) $(OUT) diff --git a/sce/shellcodeexec/Makefile.v64 b/sce/shellcodeexec/Makefile.v64 new file mode 100644 index 0000000..50edd90 --- /dev/null +++ b/sce/shellcodeexec/Makefile.v64 @@ -0,0 +1,8 @@ +shellcodeexecvc64.exe: shellcodeexec.obj __exec_payload.obj + link shellcodeexec.obj __exec_payload.obj + +shellcodeexec.obj: shellcodeexec.c + cl shellcodeexec.c /Os /TC /c + +__exec_payload.obj: __exec_payload.asm + ml64 __exec_payload.asm /c diff --git a/sce/shellcodeexec/__exec_payload.asm b/sce/shellcodeexec/__exec_payload.asm new file mode 100644 index 0000000..167e0ad --- /dev/null +++ b/sce/shellcodeexec/__exec_payload.asm @@ -0,0 +1,7 @@ +.CODE +__exec_payload PROC x:QWORD + mov rax, x + call QWORD PTR[rax] + ret +__exec_payload ENDP +END diff --git a/windows/shellcodeexec/shellcodeexec.c b/sce/shellcodeexec/shellcodeexec.c similarity index 55% rename from windows/shellcodeexec/shellcodeexec.c rename to sce/shellcodeexec/shellcodeexec.c index efec8d7..6ff4c56 100644 --- a/windows/shellcodeexec/shellcodeexec.c +++ b/sce/shellcodeexec/shellcodeexec.c @@ -1,5 +1,7 @@ /* shellcodeexec - Script to execute in memory a sequence of opcodes + Heavily rewritten by Vlatko Kosturjak, vlatko.kosturjak@gmail.com + Heavily based on: Copyright (C) 2011 Bernardo Damele A. G. web: http://bernardodamele.blogspot.com email: bernardo.damele@gmail.com @@ -21,26 +23,56 @@ #include #include +#include #include #include #include #include +/* Microsoft Visual Studio have different way of specifying variable number of args */ +#ifdef DEBUG + #ifdef _MSC_VER + #define DEBUG_PRINTF(fmt, ...) fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__) + #else + #define DEBUG_PRINTF(fmt, args...) fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, __LINE__, __FUNCTION__, ##args) + #endif +#else + #ifdef _MSC_VER + #define DEBUG_PRINTF(fmt, ...) + #else + #define DEBUG_PRINTF(fmt, args...) + #endif +#endif + +#ifdef __MINGW32__ +#define _WIN32_WINNT 0x502 +#endif + #if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) #include DWORD WINAPI exec_payload(LPVOID lpParameter); + #if defined(_WIN64) + void __exec_payload(LPVOID); + static DWORD64 handler_eip; + #else + static DWORD handler_eip; + #endif #else #include #include #include #endif +#ifndef CALL_FIRST +#define CALL_FIRST 1 +#endif + int sys_bineval(char *argv); int main(int argc, char *argv[]) { if (argc < 2) { - printf("Run:\n\tshellcodeexec \n"); + printf("Run:\n\t%s \n",argv[0]); exit(-1); } @@ -66,14 +98,18 @@ int sys_bineval(char *argv) #if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) // allocate a +rwx memory page + DEBUG_PRINTF("Allocating RWX memory...\n"); code = (char *) VirtualAlloc(NULL, len+1, MEM_COMMIT, PAGE_EXECUTE_READWRITE); // copy over the shellcode + DEBUG_PRINTF("Copying shellcode\n"); strncpy(code, argv, len); // execute it by ASM code defined in exec_payload function + DEBUG_PRINTF("Executing shellcode\n"); WaitForSingleObject(CreateThread(NULL, 0, exec_payload, code, 0, &pID), INFINITE); #else + DEBUG_PRINTF("Performing fork...\n"); pID = fork(); if(pID<0) return 1; @@ -84,15 +120,18 @@ int sys_bineval(char *argv) page_size = (len+page_size) & ~(page_size); // align to page boundary // mmap an +rwx memory page + DEBUG_PRINTF("Mmaping memory page (+rwx)\n"); addr = mmap(0, page_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED|MAP_ANON, 0, 0); if (addr == MAP_FAILED) return 1; // copy over the shellcode + DEBUG_PRINTF("Copying shellcode\n"); strncpy((char *)addr, argv, len); // execute it + DEBUG_PRINTF("Executing shellcode\n"); ((void (*)(void))addr)(); } @@ -103,8 +142,57 @@ int sys_bineval(char *argv) return 0; } +/* if windows */ +#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) +/* if mingw */ +#ifdef __MINGW32__ +LONG WINAPI VectoredHandler (struct _EXCEPTION_POINTERS *ExceptionInfo) { + PCONTEXT Context; + Context = ExceptionInfo->ContextRecord; + DEBUG_PRINTF("Exception occured. Entered into Exception Handler.\n"); +#ifdef _AMD64_ + Context->Rip = handler_eip; +#else + Context->Eip = handler_eip; +#endif + DEBUG_PRINTF("Returning from Exception handler\n"); + return EXCEPTION_CONTINUE_EXECUTION; +} + +DWORD WINAPI exec_payload(LPVOID lpParameter) +{ + PVOID h; + handler_eip = &&fail; + + DEBUG_PRINTF("Adding handler\n"); + h = AddVectoredExceptionHandler(CALL_FIRST,VectoredHandler); + DEBUG_PRINTF("Executing payload\n"); +#if defined(_WIN64) + DEBUG_PRINTF("Executing payload64\n"); + __asm__ ( + "mov %0, %%rax\n" + "call *%%rax\n" + : // no output + : "m"(lpParameter) // input + ); +#else + DEBUG_PRINTF("Executing payload32\n"); + __asm__ ( + "mov %0, %%eax\n" + "call *%%eax\n" + : // no output + : "m"(lpParameter) // input + ); +#endif +fail: + DEBUG_PRINTF("Removing handler\n"); + RemoveVectoredExceptionHandler(h); + + return 0; +} +#else /* MINGW */ + #if defined(_WIN64) -void __exec_payload(LPVOID); DWORD WINAPI exec_payload(LPVOID lpParameter) { @@ -135,4 +223,6 @@ DWORD WINAPI exec_payload(LPVOID lpParameter) return 0; } -#endif +#endif /* _WIN64 */ +#endif /* __MINGW__ */ +#endif /* if windows */ diff --git a/windows/shellcodeexec/shellcodeexec.vcproj b/sce/shellcodeexec/shellcodeexec.vcproj similarity index 100% rename from windows/shellcodeexec/shellcodeexec.vcproj rename to sce/shellcodeexec/shellcodeexec.vcproj