├── shellcode_launcher.exe ├── README.md ├── sc_launcher.dsw ├── sc_launcher.dsp └── sc_launcher.cpp /shellcode_launcher.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clinicallyinane/shellcode_launcher/HEAD/shellcode_launcher.exe -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | shellcode_launcher 2 | ================== 3 | 4 | Shellcode launcher utility written to support the labs for the incredibly awesome book Practical Malware Analysis (http://practicalmalwareanalysis.com/) 5 | 6 | 7 | -------------------------------------------------------------------------------- /sc_launcher.dsw: -------------------------------------------------------------------------------- 1 | Microsoft Developer Studio Workspace File, Format Version 6.00 2 | # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! 3 | 4 | ############################################################################### 5 | 6 | Project: "sc_launcher"=".\sc_launcher.dsp" - Package Owner=<4> 7 | 8 | Package=<5> 9 | {{{ 10 | }}} 11 | 12 | Package=<4> 13 | {{{ 14 | }}} 15 | 16 | ############################################################################### 17 | 18 | Global: 19 | 20 | Package=<5> 21 | {{{ 22 | }}} 23 | 24 | Package=<3> 25 | {{{ 26 | }}} 27 | 28 | ############################################################################### 29 | 30 | -------------------------------------------------------------------------------- /sc_launcher.dsp: -------------------------------------------------------------------------------- 1 | # Microsoft Developer Studio Project File - Name="sc_launcher" - Package Owner=<4> 2 | # Microsoft Developer Studio Generated Build File, Format Version 6.00 3 | # ** DO NOT EDIT ** 4 | 5 | # TARGTYPE "Win32 (x86) Console Application" 0x0103 6 | 7 | CFG=sc_launcher - Win32 Debug 8 | !MESSAGE This is not a valid makefile. To build this project using NMAKE, 9 | !MESSAGE use the Export Makefile command and run 10 | !MESSAGE 11 | !MESSAGE NMAKE /f "sc_launcher.mak". 12 | !MESSAGE 13 | !MESSAGE You can specify a configuration when running NMAKE 14 | !MESSAGE by defining the macro CFG on the command line. For example: 15 | !MESSAGE 16 | !MESSAGE NMAKE /f "sc_launcher.mak" CFG="sc_launcher - Win32 Debug" 17 | !MESSAGE 18 | !MESSAGE Possible choices for configuration are: 19 | !MESSAGE 20 | !MESSAGE "sc_launcher - Win32 Release" (based on "Win32 (x86) Console Application") 21 | !MESSAGE "sc_launcher - Win32 Debug" (based on "Win32 (x86) Console Application") 22 | !MESSAGE 23 | 24 | # Begin Project 25 | # PROP AllowPerConfigDependencies 0 26 | # PROP Scc_ProjName "" 27 | # PROP Scc_LocalPath "" 28 | CPP=cl.exe 29 | RSC=rc.exe 30 | 31 | !IF "$(CFG)" == "sc_launcher - Win32 Release" 32 | 33 | # PROP BASE Use_MFC 0 34 | # PROP BASE Use_Debug_Libraries 0 35 | # PROP BASE Output_Dir "Release" 36 | # PROP BASE Intermediate_Dir "Release" 37 | # PROP BASE Target_Dir "" 38 | # PROP Use_MFC 0 39 | # PROP Use_Debug_Libraries 0 40 | # PROP Output_Dir "Release" 41 | # PROP Intermediate_Dir "Release" 42 | # PROP Ignore_Export_Lib 0 43 | # PROP Target_Dir "" 44 | # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c 45 | # ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c 46 | # ADD BASE RSC /l 0x409 /d "NDEBUG" 47 | # ADD RSC /l 0x409 /d "NDEBUG" 48 | BSC32=bscmake.exe 49 | # ADD BASE BSC32 /nologo 50 | # ADD BSC32 /nologo 51 | LINK32=link.exe 52 | # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 53 | # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/shellcode_launcher.exe" 54 | 55 | !ELSEIF "$(CFG)" == "sc_launcher - Win32 Debug" 56 | 57 | # PROP BASE Use_MFC 0 58 | # PROP BASE Use_Debug_Libraries 1 59 | # PROP BASE Output_Dir "Debug" 60 | # PROP BASE Intermediate_Dir "Debug" 61 | # PROP BASE Target_Dir "" 62 | # PROP Use_MFC 0 63 | # PROP Use_Debug_Libraries 1 64 | # PROP Output_Dir "Debug" 65 | # PROP Intermediate_Dir "Debug" 66 | # PROP Ignore_Export_Lib 0 67 | # PROP Target_Dir "" 68 | # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c 69 | # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c 70 | # ADD BASE RSC /l 0x409 /d "_DEBUG" 71 | # ADD RSC /l 0x409 /d "_DEBUG" 72 | BSC32=bscmake.exe 73 | # ADD BASE BSC32 /nologo 74 | # ADD BSC32 /nologo 75 | LINK32=link.exe 76 | # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept 77 | # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/shellcode_launcher.exe" /pdbtype:sept 78 | 79 | !ENDIF 80 | 81 | # Begin Target 82 | 83 | # Name "sc_launcher - Win32 Release" 84 | # Name "sc_launcher - Win32 Debug" 85 | # Begin Group "Source Files" 86 | 87 | # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" 88 | # Begin Source File 89 | 90 | SOURCE=.\sc_launcher.cpp 91 | # End Source File 92 | # End Group 93 | # Begin Group "Header Files" 94 | 95 | # PROP Default_Filter "h;hpp;hxx;hm;inl" 96 | # End Group 97 | # Begin Group "Resource Files" 98 | 99 | # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" 100 | # End Group 101 | # End Target 102 | # End Project 103 | -------------------------------------------------------------------------------- /sc_launcher.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * shellcode_launcher.exe: allows loading & executing arbitrary binary files. 3 | * Copyright (C) 2010 Jerrold "Jay" Smith (public@clinicallyinane.com) 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | * 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #define EXTRA_SPACE 0x10000 27 | #define MAX_REG_NAME_SIZE 4 28 | 29 | #define REG_EAX 0 30 | #define REG_EBX 1 31 | #define REG_ECX 2 32 | #define REG_EDX 3 33 | #define REG_EDI 4 34 | #define REG_ESI 5 35 | 36 | #define REG_MAX 6 37 | 38 | #define MAX_OPEN_FILES 10 39 | 40 | char* regNames[] = { 41 | "eax", 42 | "ebx", 43 | "ecx", 44 | "edx", 45 | "edi", 46 | "esi" 47 | }; 48 | 49 | #define NUM_REGISTERS 6 50 | 51 | typedef void(*void_func_ptr)(void); 52 | 53 | unsigned char callNext[] = { 54 | 0xe8, 0x00, 0x00, 0x00, 0x00, //call $+5 55 | }; 56 | 57 | #if 0 58 | unsigned char callPopEdi[] = { 59 | 0xe8, 0x00, 0x00, 0x00, 0x00, //call $+5 60 | 0x5f //pop edi 61 | }; 62 | #endif 63 | 64 | unsigned char popRegInstr[] = { 65 | 0x58, //eax 66 | 0x5b, //ebx 67 | 0x59, //ecx 68 | 0x5a, //edx 69 | 0x5f, //edi 70 | 0x5e //esi 71 | }; 72 | 73 | #if 0 74 | unsigned char addEdiImmediate[] = { 75 | 0x81, 0xc7 // add edi, <32-bit immediate> 76 | }; 77 | #endif 78 | 79 | unsigned char addRegImmediate[][2] = { 80 | { 0x81, 0xc0 }, //add eax, 0x11223344: 81c0 44332211 81 | { 0x81, 0xc3 }, //add ebx, 0x11223344: 81c3 44332211 82 | { 0x81, 0xc1 }, //add ecx, 0x11223344: 81c1 44332211 83 | { 0x81, 0xc2 }, //add edx, 0x11223344: 81c2 44332211 84 | { 0x81, 0xc6 }, //add esi, 0x11223344: 81c6 44332211 85 | { 0x81, 0xc7 }, //add edi, 0x11223344: 81c7 44332211 86 | }; 87 | 88 | unsigned char jmp32bitOffset[] = { 89 | 0xe9 // jmp <32-bit immediate_offset> 90 | }; 91 | 92 | unsigned char breakpoint[] = { 93 | 0xcc // int3 94 | }; 95 | 96 | struct FileInfo { 97 | int index; 98 | char* names[MAX_OPEN_FILES]; 99 | HANDLE handles[MAX_OPEN_FILES]; 100 | }; 101 | 102 | struct ConfigurationData { 103 | int doBp; 104 | DWORD startOff; 105 | DWORD baseAddress; 106 | char* shellcodeFilename; 107 | DWORD shellcodeSize; 108 | int setRegStart[NUM_REGISTERS]; 109 | int setRegEnd[NUM_REGISTERS]; 110 | struct FileInfo readFiles; 111 | struct FileInfo writeFiles; 112 | struct FileInfo readWriteFiles; 113 | struct FileInfo loadedLibraries; 114 | }; 115 | 116 | void usage(void) { 117 | printf("Usage: shellcode_launcher.exe\n"); 118 | printf("shellcode_launcher.exe -i -o -ba [-bp] [-r ]\n [-w ] [-L ][+]\n"); 119 | printf(" is the binary containing the shellcode to execute\n"); 120 | printf(" is the (decimal) offset into the shellcode to start executing\n"); 121 | printf(" is your preferred base address to insert the shellcode (i.e. 0xFD0000\n"); 122 | printf(" is an additional file to open, either readonly (-r) \n"); 123 | printf(" or writeable (-w), such as for a malicious PDF the shellcode\n"); 124 | printf(" requires an open handle for\n"); 125 | printf(" -: load register with a pointer to the start of the shellcode\n"); 126 | printf(" +: load register with a pointer to the end of the shellcode\n"); 127 | printf(" -bp: add a breakpoint prior to jumping into the shellcode\n"); 128 | printf(" -L : Load library during initialization\n"); 129 | } 130 | 131 | // Returns TRUE (1) if string s1 is equal to string s2 132 | int isStrEqual(const char *s1, const char*s2) { 133 | return (0 == strncmp(s1, s2, strlen(s2))); 134 | } 135 | 136 | // Validates that there is an additional argument by examining argc & the 137 | // current argv index. If it is missing, prints a message using the given 138 | // argFlag to format the message, prints usage, and exits. 139 | void checkExtraArgument(int argc, int currI, char* argFlag) { 140 | if((currI+1) >= argc) { 141 | printf("Missing argument to %s", argFlag); 142 | usage(); 143 | exit(1); 144 | } 145 | } 146 | 147 | // For the given source string, checks if it starts with the desired 148 | // '+' or '-' character given in plusMinus. If so, normalizes the case 149 | // and then compares the remainder of the string against all of hte 150 | // Returns -1 if this fails, else returns the REG_X index value for the 151 | // found register. 152 | int isRegisterCommand(const char *source, char plusMinus) { 153 | char localSource[MAX_REG_NAME_SIZE]; 154 | unsigned int i; 155 | if(!source) { 156 | return -1; 157 | } 158 | if(source[0] != plusMinus) { 159 | return -1; 160 | } 161 | size_t len = strlen(source); 162 | if(len > MAX_REG_NAME_SIZE) { 163 | return -1; 164 | } 165 | memset(localSource, 0, sizeof(localSource)); 166 | for(i=0; iloadedLibraries.index; i++) { 184 | 185 | printf("Trying to LoadLibrary: %s\n", config->loadedLibraries.names[i]); 186 | HMODULE libHandle = LoadLibrary(config->loadedLibraries.names[i]); 187 | if(libHandle == NULL) { 188 | printf("Error loading library %s: 0x%08\n", config->loadedLibraries.names[i], GetLastError()); 189 | return -1; 190 | } 191 | config->loadedLibraries.handles[i] = libHandle; 192 | } 193 | return 0; 194 | } 195 | 196 | int doCreateFiles(struct ConfigurationData* config) { 197 | int i; 198 | //open read-only files 199 | for(i=0; ireadFiles.index; i++) { 200 | HANDLE inFile = INVALID_HANDLE_VALUE; 201 | printf("Opening readable file: %s\n", config->readFiles.names[i]); 202 | inFile = CreateFile(config->readFiles.names[i], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 203 | if (inFile == INVALID_HANDLE_VALUE) { 204 | printf("Couldn't open file %s: %08x\n", config->readFiles.names[i], GetLastError()); 205 | return 1; 206 | } 207 | config->readFiles.handles[i] = inFile; 208 | } 209 | 210 | for(i=0; iwriteFiles.index; i++) { 211 | printf("Opening writeable file: %s\n", config->writeFiles.names[i]); 212 | HANDLE inFile = CreateFile(config->writeFiles.names[i], GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 213 | if (inFile == INVALID_HANDLE_VALUE) { 214 | printf("Couldn't open file %s: %08x\n", config->readFiles.names[i], GetLastError()); 215 | return 1; 216 | } 217 | config->writeFiles.handles[i] = inFile; 218 | } 219 | 220 | for(i=0; i < config->readFiles.index; i++) { 221 | printf("Opening read-writeable file: %s\n", config->readWriteFiles.names[i]); 222 | HANDLE inFile = CreateFile(config->readWriteFiles.names[i], GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 223 | if (inFile == INVALID_HANDLE_VALUE) { 224 | printf("Couldn't open file %s: %08x\n", config->readFiles.names[i], GetLastError()); 225 | return 1; 226 | } 227 | config->readWriteFiles.handles[i] = inFile; 228 | } 229 | 230 | return 1; 231 | } 232 | 233 | //return -1 on error, else #of bytes written 234 | int doSetupShellcodeJump(unsigned char* buffer, DWORD dataOffset, DWORD shellcodeOffset, DWORD startOff) { 235 | int amtWritten = (sizeof(jmp32bitOffset) + sizeof(DWORD)); 236 | DWORD jumpOffset = (EXTRA_SPACE+startOff)-dataOffset; 237 | //subtract the size of the jump instruction 238 | jumpOffset -= amtWritten; 239 | 240 | memcpy(buffer + dataOffset, jmp32bitOffset, sizeof(jmp32bitOffset)); 241 | DWORD* jumpTarget = (DWORD*)(buffer+dataOffset+sizeof(jmp32bitOffset)); 242 | 243 | //store the jump offset 244 | //printf("Writing 0x%08x:0x%08x\n", jumpTarget, jumpOffset); 245 | *jumpTarget = jumpOffset; 246 | 247 | return amtWritten; 248 | } 249 | 250 | //allocates the fills the buffer with dat 251 | //returns -1 on failure, else 0 on success 252 | //allocated outBuffer 253 | int createShellcodeBuffer(struct ConfigurationData* config, unsigned char** outBuffer) { 254 | if(!outBuffer) { 255 | printf("ERROR: no output buffer specified\n"); 256 | return -1; 257 | } 258 | HANDLE inFile = CreateFile(config->shellcodeFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 259 | if (inFile == INVALID_HANDLE_VALUE) { 260 | printf("Couldn't open shellcode-containing file %s: %08x\n", config->shellcodeFilename, GetLastError()); 261 | return -1; 262 | } 263 | config->shellcodeSize = GetFileSize(inFile, NULL); 264 | if(config->shellcodeSize == INVALID_FILE_SIZE) { 265 | printf("Couldn't get file size\n"); 266 | return -1; 267 | } 268 | if(config->startOff > config->shellcodeSize) { 269 | printf("Execution offset larger than file size!\n"); 270 | return -1; 271 | } 272 | if(config->baseAddress) { 273 | config->baseAddress -= EXTRA_SPACE; 274 | } 275 | 276 | //extra space for extra pieces 277 | unsigned char* buffer = (unsigned char*)VirtualAlloc((PVOID) config->baseAddress, config->shellcodeSize + EXTRA_SPACE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 278 | 279 | if(buffer == NULL) { 280 | printf("Couldn't allocate %d bytes\n", config->shellcodeSize); 281 | return -1; 282 | } 283 | DWORD bytesRead = 0; 284 | if(!ReadFile(inFile, (buffer+EXTRA_SPACE), config->shellcodeSize, &bytesRead, NULL)) { 285 | printf("Couldn't read file bytes\n"); 286 | return -1; 287 | } 288 | //keep an open handle to shellcode file in case the shellcode looks for the open handle 289 | //CloseHandle(inFile); 290 | 291 | if(bytesRead != config->shellcodeSize) { 292 | printf("Only read %d of %d bytes!\n", bytesRead, config->shellcodeSize); 293 | return -1; 294 | } 295 | *outBuffer = buffer; 296 | 297 | return 0; 298 | } 299 | 300 | //set the specified register to a value just prior to the shellcode 301 | int doSetRegStart(unsigned char*buffer, DWORD currOffset, DWORD shellcodeOffset, int regIndex) { 302 | printf("Setting reg start: %08x %08x %d\n", currOffset, shellcodeOffset, regIndex); 303 | int totalCopied = 0; 304 | //copy call $ 305 | memcpy(buffer+currOffset, callNext, sizeof(callNext)); 306 | totalCopied += sizeof(callNext); 307 | //copy pop register 308 | printf("Setting pop %d at 0x%08x\n", regIndex, currOffset+totalCopied); 309 | buffer[currOffset+totalCopied] = popRegInstr[regIndex]; 310 | totalCopied += sizeof(popRegInstr[0]); 311 | 312 | //calculate immed value to add to reg to point to start of shellcode 313 | DWORD immed = shellcodeOffset - (currOffset + sizeof(callNext)); 314 | //copy the add reg 32-bit immed instr 315 | memcpy(buffer+currOffset+totalCopied, addRegImmediate[regIndex], sizeof(addRegImmediate[0])); 316 | totalCopied += sizeof(addRegImmediate[0]); 317 | DWORD* immedTarget = (DWORD*)(buffer + currOffset + totalCopied); 318 | *immedTarget = immed; 319 | totalCopied += sizeof(DWORD); 320 | 321 | return totalCopied; 322 | } 323 | 324 | 325 | //set the specified register to a value at the end of the shellcode 326 | int doSetRegEnd(unsigned char*buffer, DWORD currOffset, DWORD shellcodeOffset, int regIndex, int shellcodeSize) { 327 | printf("Setting reg end: %08x %08x %d\n", currOffset, shellcodeOffset, regIndex); 328 | int totalCopied = 0; 329 | //copy call $ 330 | memcpy(buffer+currOffset, callNext, sizeof(callNext)); 331 | totalCopied += sizeof(callNext); 332 | //copy pop register 333 | buffer[currOffset+totalCopied] = popRegInstr[regIndex]; 334 | totalCopied += sizeof(popRegInstr[0]); 335 | 336 | //calculate immed value to add to reg to point to start of shellcode 337 | DWORD immed = shellcodeSize + shellcodeOffset - (currOffset + sizeof(callNext)); 338 | //copy the add reg 32-bit immed instr 339 | memcpy(buffer+currOffset+totalCopied, addRegImmediate[regIndex], sizeof(addRegImmediate[0])); 340 | totalCopied += sizeof(addRegImmediate[0]); 341 | DWORD* immedTarget = (DWORD*)(buffer + currOffset+totalCopied); 342 | *immedTarget = immed; 343 | totalCopied += sizeof(DWORD); 344 | 345 | return totalCopied; 346 | } 347 | 348 | //set the specified register to a value at the end of the shellcode 349 | int doSetBp(unsigned char*buffer, DWORD currOffset) { 350 | printf("Creating breakpoint at: 0x%08x\n", (unsigned int)(buffer + currOffset)); 351 | memcpy(buffer + currOffset, breakpoint, sizeof(breakpoint)); 352 | 353 | return sizeof(breakpoint); 354 | } 355 | 356 | //returns -1 on failure, else 0 on success 357 | int fillPreambleBuffer(struct ConfigurationData* config, unsigned char* buffer, DWORD shellcodeOffset) { 358 | //okay, start filling in the preamble bytes 359 | DWORD dataOffset = 0; 360 | DWORD amtWritten = 0; 361 | int i = 0; 362 | 363 | if(!config || !buffer) { 364 | printf("ERROR: bad args to fillPreambleBuffer\n"); 365 | } 366 | 367 | //for each entry n the setRegStart & setRegEnd arrays, add 368 | for(i=0; isetRegStart[i]) { 370 | amtWritten = doSetRegStart(buffer, dataOffset, shellcodeOffset, i); 371 | if(amtWritten<0) { 372 | printf("Error during doSetRegStart\n"); 373 | return -1; 374 | } 375 | dataOffset += amtWritten; 376 | } 377 | 378 | if(config->setRegEnd[i]) { 379 | amtWritten = doSetRegEnd(buffer, dataOffset, shellcodeOffset, i, config->shellcodeSize); 380 | if(amtWritten<0) { 381 | printf("Error during doSetRegEnd\n"); 382 | return -1; 383 | } 384 | dataOffset += amtWritten; 385 | } 386 | } 387 | 388 | //add breakpoint if requested 389 | if(config->doBp) { 390 | amtWritten = doSetBp(buffer, dataOffset); 391 | if(amtWritten < 0) { 392 | printf("Error during doSetBp\n"); 393 | return -1; 394 | } 395 | dataOffset += amtWritten; 396 | } 397 | 398 | 399 | //setup jump to shellcode location 400 | return doSetupShellcodeJump(buffer, dataOffset, shellcodeOffset, config->startOff); 401 | } 402 | 403 | // Fills in the provided ConfigurationData config struct from the provided command line parameters. 404 | // Returns -1 on error, else success 405 | int parseCommandLineArgs(int argc, char** argv, struct ConfigurationData* config) { 406 | 407 | int i = 1; 408 | int regIndex; 409 | 410 | while(i < argc) { 411 | if (isStrEqual(argv[i], "-i")) { 412 | checkExtraArgument(argc, i, "-i"); 413 | config->shellcodeFilename = argv[i+1]; 414 | i += 2; 415 | } else if (isStrEqual(argv[i], "-o")) { 416 | char *endOfString = NULL; 417 | config->startOff = strtoul(argv[i+1], &endOfString, 0); 418 | printf("Using starting offset: 0x%08x (%d)\n", config->startOff, config->startOff); 419 | i += 2; 420 | } else if (isStrEqual(argv[i], "-ba")) { 421 | char *endOfString = NULL; 422 | config->baseAddress = strtoul(argv[i+1], &endOfString, 0); 423 | printf("Using base address: 0x%08x (%d)\n", config->baseAddress, config->baseAddress); 424 | i += 2; 425 | } else if (isStrEqual(argv[i], "-bp")) { 426 | config->doBp = 1; 427 | i += 1; 428 | } else if (isStrEqual(argv[i], "-x")) { 429 | //orange: i forget why i wanted -x 430 | i += 1; 431 | } else if (isStrEqual(argv[i], "-L")) { 432 | checkExtraArgument(argc, i, "-L"); 433 | int index = config->loadedLibraries.index; 434 | if(index < MAX_OPEN_FILES) { 435 | config->loadedLibraries.names[index] = argv[i+1]; 436 | } 437 | config->loadedLibraries.index += 1; 438 | 439 | i += 2; 440 | } else if(isStrEqual(argv[i], "-r")) { 441 | checkExtraArgument(argc, i, "-r"); 442 | if(config->readFiles.index < MAX_OPEN_FILES) { 443 | config->readFiles.names[config->readFiles.index] = argv[i+1]; 444 | config->readFiles.index += 1; 445 | } else { 446 | printf("ERROR: Too many -r files specified. Limit is %d\n", MAX_OPEN_FILES); 447 | return -1; 448 | } 449 | i += 2; 450 | } else if(isStrEqual(argv[i], "-w")) { 451 | checkExtraArgument(argc, i, "-w"); 452 | if(config->writeFiles.index < MAX_OPEN_FILES) { 453 | config->writeFiles.names[config->writeFiles.index] = argv[i+1]; 454 | config->writeFiles.index += 1; 455 | } else { 456 | printf("ERROR: Too many -w files specified. Limit is %d\n", MAX_OPEN_FILES); 457 | return -1; 458 | } 459 | 460 | i += 2; 461 | } else if(isStrEqual(argv[i], "-rw")) { 462 | checkExtraArgument(argc, i, "-rw"); 463 | 464 | if(config->readWriteFiles.index < MAX_OPEN_FILES) { 465 | config->readWriteFiles.names[config->readWriteFiles.index] = argv[i+1]; 466 | config->readWriteFiles.index += 1; 467 | } else { 468 | printf("ERROR: Too many -rw files specified. Limit is %d\n", MAX_OPEN_FILES); 469 | return -1; 470 | } 471 | i += 2; 472 | 473 | 474 | } else if( (regIndex = isRegisterCommand(argv[i], '-')) >= 0) { 475 | //make sure there isn't confliching +/- for same register 476 | if(config->setRegEnd[regIndex]) { 477 | printf("ERROR: conflicting +/- requests for register %s\n", regNames[regIndex]); 478 | usage(); 479 | return -1; 480 | } 481 | //set the flag for the given regiser 482 | printf("Setting %d -%s\n", regIndex, regNames[regIndex]); 483 | config->setRegStart[regIndex] = 1; 484 | i += 1; 485 | } else if( (regIndex = isRegisterCommand(argv[i], '+')) >= 0) { 486 | //make sure there isn't confliching +/- for same register 487 | if(config->setRegStart[regIndex]) { 488 | printf("ERROR: conflicting +/- requests for register %s\n", regNames[regIndex]); 489 | usage(); 490 | return -1; 491 | } 492 | //set the flag for the given regiser 493 | printf("Setting %d +%s\n", regIndex, regNames[regIndex]); 494 | config->setRegEnd[regIndex] = 1; 495 | i += 1; 496 | } else { 497 | printf("WARNING: unknown flag: %s. Skipping\n", argv[i]); 498 | i += 1; 499 | } 500 | } 501 | return 0; 502 | } 503 | 504 | int main(int argc, char* argv[]) { 505 | printf("Starting up\n"); 506 | struct ConfigurationData config; 507 | if(argc < 3) { 508 | usage(); 509 | return 1; 510 | } 511 | memset(&config, 0, sizeof(struct ConfigurationData)); 512 | if(parseCommandLineArgs(argc, argv, &config) < 0) { 513 | return 1; 514 | } 515 | 516 | //load required libraries 517 | if(doLoadLibraries(&config) < 0) { 518 | printf("Load Libraries failed. Exiting\n"); 519 | return 1; 520 | } 521 | if(doCreateFiles(&config) < 0) { 522 | printf("Creat auxiliary files failed. Exiting\n"); 523 | return 1; 524 | } 525 | 526 | unsigned char* buffer = NULL; 527 | if(createShellcodeBuffer(&config, &buffer) < 0) { 528 | printf("Creating shellcode buffer failed. Exiting\n"); 529 | return 1; 530 | } 531 | 532 | if(fillPreambleBuffer(&config, buffer, EXTRA_SPACE) < 0) { 533 | printf("Filling preamble buffer failed. Exiting\n"); 534 | return 1; 535 | } 536 | 537 | 538 | //now call the buffer - does not return 539 | void_func_ptr callLoc = (void_func_ptr)(buffer); 540 | printf("Calling file now. Loaded binary at: 0x%08x\n", (unsigned int)(buffer+EXTRA_SPACE)); 541 | callLoc(); 542 | 543 | 544 | return 0; 545 | } 546 | 547 | --------------------------------------------------------------------------------