diff --git a/No-Consolation.cna b/No-Consolation.cna index b10c0f5..de60361 100644 --- a/No-Consolation.cna +++ b/No-Consolation.cna @@ -107,6 +107,15 @@ alias noconsolation else if (@_[$i] eq "--free-libraries" || @_[$i] eq "-fl") { $free_libs = 1; + $i++; + + if($i >= size(@_)) + { + berror($1, "missing --free-libraries value"); + return; + } + + $free_libs = @_[$i]; } else if (@_[$i] eq "--dont-save" || @_[$i] eq "-ds") { @@ -209,8 +218,8 @@ alias noconsolation } } - # allow users to close all handles without having to run a PE - if (strlen($unload_pe) == 0 && $list_pes == 0 && $name_set == 0 && $path_set == 0 && $close_handles == 0) + # allow users to perform some tasks without having to run a PE + if (strlen($free_libs) == 0 && strlen($unload_pe) == 0 && $list_pes == 0 && $name_set == 0 && $path_set == 0 && $close_handles == 0) { berror($1, "PE path not provided"); return; @@ -234,12 +243,30 @@ alias noconsolation return; } + if (strlen($free_libs) != 0 && $list_pes) + { + berror($bid, "The option --list-pes must be ran alone"); + return; + } + + if (strlen($free_libs) != 0 && strlen($unload_pe) != 0) + { + berror($bid, "The option --unload-pe must be ran alone"); + return; + } + if ($path_set && strlen($unload_pe) != 0) { berror($bid, "The option --unload-pe must be ran alone"); return; } + if ($path_set && strlen($free_libs) != 0) + { + berror($bid, "The option --free-libraries must be ran alone"); + return; + } + if ($timeout_set && $inthread) { berror($bid, "The options --inthread and --timeout are not compatible"); @@ -299,7 +326,7 @@ sub runpe{ } # Pack the arguments - $args = bof_pack($1, "ZzZbziiiZzziiiiiiizzziiizzzi", $2 $2, $3, $4, $5, $6, $7, $8, $9, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27); + $args = bof_pack($1, "ZzZbziiiZzziiiziiizzziiizzzi", $2 $2, $3, $4, $5, $6, $7, $8, $9, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27); # Execute BOF beacon_inline_execute($1, $data, "go", $args); @@ -311,7 +338,7 @@ beacon_command_register( " Summary: Run an unmanaged EXE/DLL inside Beacon's memory. -Usage: noconsolation [--local] [--inthread] [--link-to-peb] [--dont-unload] [--timeout 60] [-k] [--method funcname] [-w] [--no-output] [--alloc-console] [--close-handles] [--free-libraries] [--dont-save] [--list-pes] [--unload-pe pename] [--load-all-dependencies] [--load-all-dependencies-but advapi32.dll] [--load-dependencies wininet.dll] [--search-paths C:\\Windows\\Temp\\] /path/to/binary.exe arg1 arg2 +Usage: noconsolation [--local] [--inthread] [--link-to-peb] [--dont-unload] [--timeout 60] [-k] [--method funcname] [-w] [--no-output] [--alloc-console] [--close-handles] [--free-libraries wininet.dll,winhttp.dll] [--dont-save] [--list-pes] [--unload-pe pename] [--load-all-dependencies] [--load-all-dependencies-but advapi32.dll] [--load-dependencies wininet.dll] [--search-paths C:\\Windows\\Temp\\] /path/to/binary.exe arg1 arg2 --local, -l Optional. The binary should be loaded from the target Windows machine --inthread, -it Optional. Run the PE with the main thread. This might hang your beacon depending on the PE and its arguments. --link-to-peb, -ltp Optional. Load the PE into the PEB @@ -323,7 +350,7 @@ Usage: noconsolation [--local] [--inthread] [--link-to-peb] [--dont-unload] [--t --no-output, -no Optional. Do not try to obtain the output --alloc-console, -ac Optional. Allocate a console. This will spawn a new process --close-handles, -ch Optional. Close Pipe handles once finished. If PowerShell was already ran, this will break the output for PowerShell in the future - --free-libraries, -fl Optional. Free all loaded DLLs + --free-libraries, -fl DLL_A,DLL_B Optional. List of DLLs (previously loaded with --dont-unload) to be offloaded --dont-save, -ds Optional. Do not save this binary in memory --list-pes, -lpe Optional. List all PEs that have been loaded in memory --unload-pe PE_NAME, -upe PE_NAME Optional. Unload from memory a PE diff --git a/README.md b/README.md index c7c1dee..ee0d5d5 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ This is a Beacon Object File (BOF) that executes unmanaged PEs inline and retrie ``` Summary: Run an unmanaged EXE/DLL inside Beacon's memory. -Usage: noconsolation [--local] [--inthread] [--link-to-peb] [--dont-unload] [--timeout 60] [-k] [--method funcname] [-w] [--no-output] [--alloc-console] [--close-handles] [--free-libraries] [--dont-save] [--list-pes] [--unload-pe pename] [--load-all-dependencies] [--load-all-dependencies-but advapi32.dll] [--load-dependencies wininet.dll] [--search-paths C:\\Windows\\Temp\\] /path/to/binary.exe arg1 arg2 +Usage: noconsolation [--local] [--inthread] [--link-to-peb] [--dont-unload] [--timeout 60] [-k] [--method funcname] [-w] [--no-output] [--alloc-console] [--close-handles] [--free-libraries wininet.dll,winhttp.dll] [--dont-save] [--list-pes] [--unload-pe pename] [--load-all-dependencies] [--load-all-dependencies-but advapi32.dll] [--load-dependencies wininet.dll] [--search-paths C:\Windows\Temp\] /path/to/binary.exe arg1 arg2 --local, -l Optional. The binary should be loaded from the target Windows machine --inthread, -it Optional. Run the PE with the main thread. This might hang your beacon depending on the PE and its arguments. --link-to-peb, -ltp Optional. Load the PE into the PEB @@ -30,7 +30,7 @@ Usage: noconsolation [--local] [--inthread] [--link-to-peb] [--dont-unload] [--t --no-output, -no Optional. Do not try to obtain the output --alloc-console, -ac Optional. Allocate a console. This will spawn a new process --close-handles, -ch Optional. Close Pipe handles once finished. If PowerShell was already ran, this will break the output for PowerShell in the future - --free-libraries, -fl Optional. Free all loaded DLLs + --free-libraries, -fl DLL_A,DLL_B Optional. List of DLLs (previously loaded with --dont-unload) to be offloaded --dont-save, -ds Optional. Do not save this binary in memory --list-pes, -lpe Optional. List all PEs that have been loaded in memory --unload-pe PE_NAME, -upe PE_NAME Optional. Unload from memory a PE @@ -42,9 +42,9 @@ Usage: noconsolation [--local] [--inthread] [--link-to-peb] [--dont-unload] [--t /path/to/binary.exe Required. Full path to the windows EXE/DLL you wish you run inside Beacon. If already loaded, you can simply specify the binary name. ARG1 ARG2 Optional. Parameters for the PE. Must be provided after the path - Example: noconsolation --local C:\\windows\\system32\\windowspowershell\\v1.0\\powershell.exe \$ExecutionContext.SessionState.LanguageMode + Example: noconsolation --local C:\windows\system32\windowspowershell\v1.0\powershell.exe $ExecutionContext.SessionState.LanguageMode Example: noconsolation /tmp/mimikatz.exe privilege::debug token::elevate exit - Example: noconsolation --local C:\\windows\\system32\\cmd.exe /c ipconfig + Example: noconsolation --local C:\windows\system32\cmd.exe /c ipconfig Example: noconsolation --list-pes Example: noconsolation LoadedBinary.exe args ``` diff --git a/dist/NoConsolation.x64.o b/dist/NoConsolation.x64.o index ccefa34..0295419 100644 Binary files a/dist/NoConsolation.x64.o and b/dist/NoConsolation.x64.o differ diff --git a/dist/NoConsolation.x86.o b/dist/NoConsolation.x86.o index 389de4d..61fa8db 100644 Binary files a/dist/NoConsolation.x86.o and b/dist/NoConsolation.x86.o differ diff --git a/include/entry.h b/include/entry.h index 3679d8c..867bab1 100644 --- a/include/entry.h +++ b/include/entry.h @@ -53,7 +53,6 @@ typedef struct _LOADED_PE_INFO { BOOL use_unicode; BOOL nooutput; BOOL alloc_console; - BOOL unload_libs; BOOL load_all_deps; LPSTR load_all_deps_but; LPSTR load_deps; diff --git a/source/entry.c b/source/entry.c index 7bfaabd..0ef352c 100644 --- a/source/entry.c +++ b/source/entry.c @@ -28,7 +28,7 @@ int go(IN PCHAR Buffer, IN ULONG Length) BOOL nooutput = FALSE; BOOL alloc_console = FALSE; BOOL close_handles = FALSE; - BOOL unload_libs = FALSE; + LPSTR unload_libs = NULL; BOOL dont_save = FALSE; BOOL list_pes = FALSE; LPSTR unload_pe = NULL; @@ -68,7 +68,8 @@ int go(IN PCHAR Buffer, IN ULONG Length) nooutput = BeaconDataInt(&parser); alloc_console = BeaconDataInt(&parser); close_handles = BeaconDataInt(&parser); - unload_libs = BeaconDataInt(&parser); + unload_libs = BeaconDataExtract(&parser, NULL); + unload_libs = unload_libs[0] ? unload_libs : NULL; dont_save = BeaconDataInt(&parser); list_pes = BeaconDataInt(&parser); unload_pe = BeaconDataExtract(&parser, NULL); @@ -101,7 +102,6 @@ int go(IN PCHAR Buffer, IN ULONG Length) peinfo->cmdline = cmdline[0] ? cmdline : NULL; peinfo->nooutput = nooutput; peinfo->alloc_console = alloc_console; - peinfo->unload_libs = unload_libs; peinfo->link_to_peb = link_to_peb; peinfo->dont_unload = dont_unload; peinfo->is_dependency = FALSE; @@ -336,29 +336,36 @@ Cleanup: lib_loaded = lib_tmp; } - if (peinfo && !peinfo->dont_unload) - unload_dependency(peinfo); - - /* - if (peinfo && unload_libs) + if (unload_libs) { - //libs_entry = peinfo->libs_loaded; - libs_entry = BeaconGetValue(NC_LOADED_DLL_KEY); - while (libs_entry) + lib_loaded = (PLIB_LOADED)libs_loaded->list.Flink; + while (&lib_loaded->list != &libs_loaded->list) { - DPRINT("Freeing %s", libs_entry->name); - FreeLibrary(libs_entry->address); + lib_tmp = (PLIB_LOADED)lib_loaded->list.Flink; - libs_tmp = libs_entry->next; - memset(libs_entry, 0, sizeof(LIB_LOADED)); - intFree(libs_entry); - libs_entry = libs_tmp; + DPRINT("unload_libs: %s, lib_loaded->name: %s", unload_libs, lib_loaded->name); + if (string_is_included(unload_libs, lib_loaded->name)) + { + PRINT("unloaded %s", lib_loaded->name); + if (lib_loaded->peinfo->custom_loaded) + unload_dependency(lib_loaded->peinfo); + else + FreeLibrary(lib_loaded->address); + + unlink_from_list(&lib_loaded->list); + memset(lib_loaded->peinfo, 0, sizeof(LOADED_PE_INFO)); + intFree(lib_loaded->peinfo); + memset(lib_loaded, 0, sizeof(LIB_LOADED)); + intFree(lib_loaded); + } + + lib_loaded = lib_tmp; } } - */ - if (peinfo) + if (peinfo && !peinfo->dont_unload) { + unload_dependency(peinfo); memset(peinfo, 0, sizeof(LOADED_PE_INFO)); intFree(peinfo); } diff --git a/source/loader.c b/source/loader.c index ec7a0c1..d4231ef 100644 --- a/source/loader.c +++ b/source/loader.c @@ -762,6 +762,11 @@ BOOL load_pe( goto Cleanup; } + if (peinfo->dont_unload) + { + store_loaded_dll(peinfo, peinfo->pe_base, peinfo->pe_name); + } + peinfo->loaded = TRUE; return TRUE;