!C99Shell v. 2.0 [PHP 7 Update] [25.02.2019]!

Software: Apache/2.4.18 (Ubuntu). PHP/7.0.33-0ubuntu0.16.04.16 

uname -a: Linux digifus 3.13.0-57-generic #95-Ubuntu SMP Fri Jun 19 09:28:15 UTC 2015 x86_64 

uid=33(www-data) gid=33(www-data) groups=33(www-data) 

Safe-mode: OFF (not secure)

/usr/share/nmap/nselib/data/psexec/   drwxr-xr-x
Free 9.85 GB of 29.4 GB (33.5%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     nmap_service.c (10.55 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/**This is the program that's uploaded to a Windows machine when psexec is run. It acts as a Windows
 * service, since that's what Windows expects. When it is started, it's passed a list of programs to
 * run. These programs are all expected to be at the indicated path (whether they were uploaded or 
 * they were always present makes no difference). 
 * 
 * After running the programs, the output from each of them is ciphered with a simple xor encryption
 * (the encryption key is passed as a parameter; because it crosses the wire, it isn't really a 
 * security feature, more of validation/obfuscation to prevent sniffers from grabbing the output. This
 * output is placed in a temp file. When the cipher is complete, the output is moved into a new file. 
 * When Nmap detects the presence of this new file, it is downloaded, then all files, temp files, and
 * the service (this program) is deleted. 
 *
 * One interesting note is that executable files don't require a specific extension to be used by this
 * program. By default, at the time of this writing, Nmap appends a .txt extension to the file. 
 *
 * @args argv[1]   The final filename where the ciphered output will go. 
 * @args argv[2]   The temporary file where output is sent before being renamed; this is sent as a parameter
 *                 so we can delete it later (if, say, the script fails). 
 * @args argv[3]   The number of programs that are going to be run.
 * @args argv[4]   Logging: a boolean value (1 to enable logging, 0 to disable). 
 * @args argv[5]   An 'encryption' key for simple 'xor' encryption. This string can be as long or as short
 *                 as you want, but a longer string will be more secure (although this algorithm should 
 *                 *never* really be considered secure).
 * @args Remaining There are two arguments for each program to run: a path (including arguments) and 
 *                 environmental variables. 
 *
 * @auther    Ron Bowes
 * @copyright Ron Bowes
 * @license   "Same as Nmap--See https://nmap.org/book/man-legal.html"
 */

#include <stdio.h>
#include <windows.h>

FILE *outfile;

SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE hStatus;

static char *enc_key;
static int   enc_key_loc;

static void log_message(char *format, ...)
{
    static int enabled = 1;

    if(!format)
    {
        enabled = 0;
        DeleteFile("c:\\nmap-log.txt");
    }
        

    if(enabled)
    {
        va_list argp;
        FILE *file;

        fopen_s(&file, "c:\\nmap-log.txt", "a");

        if(file != NULL) 
        {
            va_start(argp, format);
            vfprintf(file, format, argp);
            va_end(argp);
            fprintf(file, "\n");
            fclose(file);
        }
    }
}

static char cipher(char c)
{
    if(strlen(enc_key) == 0)
        return c;

    c = c ^ enc_key[enc_key_loc];
    enc_key_loc = (enc_key_loc + 1) % strlen(enc_key);

    return c;
}

static void output(int num, char *str, int length)
{
    int i;

    if(length == -1)
        length = strlen(str);

    for(i = 0; i < length; i++)
    {
        if(str[i] == '\n')
        {
            fprintf(outfile, "%c", cipher('\n'));
            fprintf(outfile, "%c", cipher('0' + (num % 10)));
        }
        else
        {
            fprintf(outfile, "%c", cipher(str[i]));
        }
    }
}

static void go(int num, char *lpAppPath, char *env, int headless, int include_stderr, char *readfile)
{
    STARTUPINFO         startupInfo;
    PROCESS_INFORMATION processInformation;
    SECURITY_ATTRIBUTES sa;
    HANDLE              stdout_read, stdout_write;
    DWORD               creation_flags;

    int bytes_read;
    char buffer[1024];

    /* Create a security attributes structure. This is required to inherit handles. */
    ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
    sa.nLength              = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;

    if(!headless)
        sa.bInheritHandle       = TRUE;

    /* Create a pipe that'll be used for stdout and stderr. */
    if(!headless)
        CreatePipe(&stdout_read, &stdout_write, &sa, 1);

    /* Initialize the startup info struct. The most important part is setting the stdout/stderr handle to our pipe. */
    ZeroMemory(&startupInfo, sizeof(STARTUPINFO));
    startupInfo.cb         = sizeof(STARTUPINFO);

    if(!headless)
    {
        startupInfo.dwFlags    = STARTF_USESTDHANDLES;
        startupInfo.hStdOutput = stdout_write;
        if(include_stderr)
            startupInfo.hStdError  = stdout_write;
    }

    /* Log a couple messages. */
    log_message("Attempting to load the program: %s", lpAppPath);

    /* Initialize the PROCESS_INFORMATION structure. */
    ZeroMemory(&processInformation, sizeof(PROCESS_INFORMATION));

    /* To divide the output from one program to the next */
    output(num, "\n", -1);

    /* Decide on the creation flags */
    creation_flags = CREATE_NO_WINDOW;
    if(headless)
        creation_flags = DETACHED_PROCESS;

    /* Create the actual process with an overly-complicated CreateProcess function. */
    if(!CreateProcess(NULL, lpAppPath, 0, &sa, sa.bInheritHandle, CREATE_NO_WINDOW, env, 0, &startupInfo, &processInformation))
    {
        output(num, "Failed to create the process", -1);

        if(!headless)
        {
            CloseHandle(stdout_write);
            CloseHandle(stdout_read);
        }
    }
    else
    {
        log_message("Successfully created the process!");

        /* Read the pipe, if it isn't headless */
        if(!headless)
        {
            /* Close the write handle -- if we don't do this, the ReadFile() coming up gets stuck. */
            CloseHandle(stdout_write);

            /* Read from the pipe. */
            log_message("Attempting to read from the pipe");
            while(ReadFile(stdout_read, buffer, 1023, &bytes_read, NULL))
            {
                if(strlen(readfile) == 0)
                    output(num, buffer, bytes_read);
            }
            CloseHandle(stdout_read);

            /* If we're reading an output file instead of stdout, do it here. */
            if(strlen(readfile) > 0)
            {
                FILE *read;
                errno_t err;

                log_message("Trying to open output file: %s", readfile);
                err = fopen_s(&read, readfile, "rb");

                if(err)
                {
                    log_message("Couldn't open the readfile: %d", err);
                    output(num, "Couldn't open the output file", -1);
                }
                else
                {
                    char buf[1024];
                    int count;
                    
                    count = fread(buf, 1, 1024, read);
                    while(count)
                    {
                        output(num, buf, count);
                        count = fread(buf, 1, 1024, read);
                    }

                    fclose(read);
                }
            }
        }
        else
        {
            output(num, "Process has been created", -1);
        }

        log_message("Done!");
    }
}

// Control handler function
static void ControlHandler(DWORD request) 

    switch(request) 
    { 
        case SERVICE_CONTROL_STOP: 

            ServiceStatus.dwWin32ExitCode = 0; 
            ServiceStatus.dwCurrentState  = SERVICE_STOPPED; 
            SetServiceStatus (hStatus, &ServiceStatus);
            return; 
 
        case SERVICE_CONTROL_SHUTDOWN: 

            ServiceStatus.dwWin32ExitCode = 0; 
            ServiceStatus.dwCurrentState  = SERVICE_STOPPED; 
            SetServiceStatus (hStatus, &ServiceStatus);
            return; 
        
        default:
            break;
    } 
 
    SetServiceStatus(hStatus,  &ServiceStatus);
}



static void die(int err)
{
    // Not enough arguments
    ServiceStatus.dwCurrentState  = SERVICE_STOPPED;
    ServiceStatus.dwWin32ExitCode = err;
    SetServiceStatus(hStatus, &ServiceStatus);
}

static void ServiceMain(int argc, char** argv) 
{
    char   *outfile_name;
    char   *tempfile_name;
    int     count;
    int     logging;
    int     result;
    int     i;
    char   *current_directory;

    /* Make sure we got the minimum number of arguments. */
    if(argc < 6)
        return; 

    /* Read the arguments. */
    outfile_name      = argv[1];
    tempfile_name     = argv[2];
    count             = atoi(argv[3]);
    logging           = atoi(argv[4]);
    enc_key           = argv[5];
    enc_key_loc       = 0;
    current_directory = argv[6];

    /* If they didn't turn on logging, disable it. */
    if(logging != 1)
        log_message(NULL);

    /* Log the state. */
    log_message("");
    log_message("-----------------------");
    log_message("STARTING");

    /* Log all the arguments. */
    log_message("Arguments: %d\n", argc);
    for(i = 0; i < argc; i++)
        log_message("Argument %d: %s", i, argv[i]);

    /* Set up the service. Likely unnecessary for what we're doing, but it doesn't hurt. */
    ServiceStatus.dwServiceType             = SERVICE_WIN32; 
    ServiceStatus.dwCurrentState            = SERVICE_RUNNING; 
    ServiceStatus.dwControlsAccepted        = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
    ServiceStatus.dwWin32ExitCode           = 0; 
    ServiceStatus.dwServiceSpecificExitCode = 0; 
    ServiceStatus.dwCheckPoint              = 0; 
    ServiceStatus.dwWaitHint                = 0;  
    hStatus = RegisterServiceCtrlHandler("", (LPHANDLER_FUNCTION)ControlHandler); 
    SetServiceStatus(hStatus, &ServiceStatus);

    /* Registering Control Handler failed (this is a bit late, but eh?) */
    if(hStatus == (SERVICE_STATUS_HANDLE)0) 
    {
        log_message("Service failed to start");
        die(-1);
        return; 
    }

    /* Set the current directory. */
    SetCurrentDirectory(current_directory);

    /* Open the output file. */
    log_message("Opening temporary output file: %s", tempfile_name);

    /* Open the outfile. */
    if(result = fopen_s(&outfile, tempfile_name, "wb"))
    {
        log_message("Couldn't open output file: %d", result);
        die(-1);
    }
    else
    {
        /* Run the programs we were given. */
        for(i = 0; i < count; i++)
        {
            char *program        = argv[(i*5) + 7];
            char *env            = argv[(i*5) + 8];
            char *headless       = argv[(i*5) + 9];
            char *include_stderr = argv[(i*5) + 10];
            char *read_file      = argv[(i*5) + 11];

            go(i, program, env, !strcmp(headless, "true"), !strcmp(include_stderr, "true"), read_file);
        }

        /* Close the output file. */
        if(fclose(outfile))
            log_message("Couldn't close the file: %d", errno);

        /* Rename the output file (this is what tells Nmap we're done. */
        log_message("Renaming file %s => %s", tempfile_name, outfile_name);

        /* I noticed that sometimes, programs inherit the handle to the file (or something), so I can't change it right
         * away. For this reason, allow about 10 seconds to move it. */
        for(i = 0; i < 10; i++)
        {
            if(rename(tempfile_name, outfile_name))
            {
                log_message("Couldn't rename file: %d (will try %d more times)", errno, 10 - i - 1);
            }
            else
            {
                log_message("File successfully renamed!");
                break;
            }

            Sleep(1000);
        }

        /* Clean up and stop the service. */
        die(0);
    }
}

int main(int argc, char *argv[])
{
    SERVICE_TABLE_ENTRY ServiceTable[2];
    ServiceTable[0].lpServiceName = "";
    ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;

    ServiceTable[1].lpServiceName = NULL;
    ServiceTable[1].lpServiceProc = NULL;
    // Start the control dispatcher thread for our service
    StartServiceCtrlDispatcher(ServiceTable);
}


:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 2.0 [PHP 7 Update] [25.02.2019] maintained by KaizenLouie | C99Shell Github | Generation time: 0.0066 ]--