Пожалуйста, обратите внимание, что пользователь заблокирован
Когда-то давно я игрался с кодогенерацией и сделал этот мутатор loadPE шеллкодов. Я понимаю, что создаваемый код убог, но сама идея интересна. LLVM IR для бедных
Каждый раз мутатор выдаёт другой код. Не воспринимайте серьёзно, потому что код смишнявый 
Изначально написано для украинского форума программистов
platform.js файл
tablecall.js файл
Изначально написано для украинского форума программистов
platform.js файл
Код:
var pad = require('./modules/node-pad/lib/pad.js');
var fs = require('fs');
var _ = require('./modules/underscore/underscore.js');
const DONT_ADD_TO_LIST = 1; USE_ONLY_GENERAL_REGS = 2; LOCK_REG = 4; LOCK_VAR = 4;
exports.DONT_ADD_TO_LIST = DONT_ADD_TO_LIST; exports.USE_ONLY_GENERAL_REGS = USE_ONLY_GENERAL_REGS; exports.LOCK_REG = LOCK_REG;
exports.LOCK_VAR = LOCK_VAR;
const REG_EAX = 0, REG_EBX = 1, REG_ECX = 2, REG_EDX = 3, REG_ESI = 4, REG_EDI = 5, REG_EBP = 6;
exports.REG_EAX = REG_EAX; exports.REG_EBX = REG_EBX; exports.REG_ECX = REG_ECX; exports.REG_EDX = REG_EDX; exports.REG_ESI = REG_ESI;
exports.REG_EDI = REG_EDI; exports.REG_EBP = REG_EBP;
const REG_DWORD = 0, REG_LOWORD = 1, REG_HIBYTE = 2, REG_LOBYTE = 3;
exports.REG_DWORD = REG_DWORD; exports.REG_LOWORD = REG_LOWORD; exports.REG_HIBYTE = REG_HIBYTE; exports.REG_LOBYTE = REG_LOBYTE;
const REG_R32 = 0, REG_R16 = REG_LOWORD<<3, REG_R8H = REG_HIBYTE<<3, REG_R8L = REG_LOBYTE<<3;
exports.REG_R32 = REG_R32; exports.REG_R16 = REG_R16; exports.REG_R8H = REG_R8H; exports.REG_R8L = REG_R8L;
const REG_AX=REG_EAX+(REG_LOWORD<<3), REG_BX=REG_EBX+(REG_LOWORD<<3), REG_CX=REG_ECX+(REG_LOWORD<<3), REG_DX=REG_EDX+(REG_LOWORD<<3),
REG_AL=REG_EAX+(REG_LOBYTE<<3), REG_BL=REG_EBX+(REG_LOBYTE<<3), REG_CL=REG_ECX+(REG_LOBYTE<<3), REG_DL=REG_EDX+(REG_LOBYTE<<3),
REG_AH=REG_EAX+(REG_HIBYTE<<3), REG_BH=REG_EBX+(REG_HIBYTE<<3), REG_CH=REG_ECX+(REG_HIBYTE<<3), REG_DH=REG_EDX+(REG_HIBYTE<<3),
REG_SI=REG_ESI+(REG_LOWORD<<3), REG_DI=REG_EDI+(REG_LOWORD<<3);
exports.REG_AX = REG_AX; exports.REG_BX = REG_BX; exports.REG_CX = REG_CX; exports.REG_DX = REG_DX;
exports.REG_AL = REG_AL; exports.REG_BL = REG_BL; exports.REG_CL = REG_CL; exports.REG_DL = REG_DL;
exports.REG_AH = REG_AH; exports.REG_BH = REG_BH; exports.REG_CH = REG_CH; exports.REG_DH = REG_DH;
exports.REG_SI = REG_SI; exports.REG_AX = REG_DI;
const MEM32 = 0, MEM16 = 1, MEM8 = 2;
exports.MEM32 = MEM32; exports.MEM16 = MEM16; exports.MEM8 = MEM8;
function unchainMem(s) {
var r="";
if (_.isString(s) && (r = s.match(/\[([a-zA-Z\.]\w*)\]/)) !== null) return(r[1]);
return(r);
}
function unchainConst(s){
var r = "";
if (_.isString(s) && (r = s.match(/0x[0-9a-fA-F]*/)) !== null) return(r[0]);
return(r);
}
function BytesToDword (B1, B2, B3, B4) {
var iResult = B1 + (B2<<8)+(B3<<16) + (B4<<24);
return(iResult>>>0);
};
exports.BytesToDword = BytesToDword;
Number.prototype.toHex = function() {
return('0x'+this.toString(16)); };
function arrRndValue (arr) {
return(arr[Math.floor(Math.random()*arr.length)]);};
function arrRndOrderConact(array){
return(_.shuffle(array).join(''));};
var Register = function (sNameDW, sNameLW, sNameLB, sNameHB) {
this.name = [sNameDW, sNameLW, sNameLB, sNameHB]; this.using = false; };
RegisterProto = {
lock: function() { this.using = true;},
unlock: function() { this.using = false; },
toString: function(i) {if ( _.isUndefined(i) || i < 0 || i > 3) i = 0; return(this.name[i]);},
isGeneral: function(){return(this.name[3] !== null);}};
SetRegister = function(i) {if(_.isUndefined(i)||i<0||i>0x7f) i = 0; this.num = i;};
module.exports.Register = Register;
module.exports.Register.prototype = RegisterProto;
SetRegisterProto = {
arrNames: ['eax', 'ebx', 'ecx', 'edx', 'esi', 'edi', 'ebp'],
has: function (i) {
if (_.isUndefined(i) || i < REG_EAX || i > REG_EBP) return(false); return ((this.num & 1 << i)!=0);},
add: function(i) {
if (_.isUndefined(i) || i < REG_EAX || i > REG_EBP) return(false); this.num |= ((1 << i)>>>0); return(true);},
remove: function(i) {
if (_.isUndefined(i) || i < REG_EAX || i > REG_EBP) return(false); this.num &= ~ ((1 << i)>>>0); return(true);},
toArrayIndex: function() {
var x = []; _.each(_.range(REG_EBP+1), function(a){ if (this.has(a)) x.push(a)}, this); return(x); },
toArrayIndexInverse: function() {
var x = []; _.each(_.range(REG_EBP+1), function(a){ if (!this.has(a)) x.push(a)}, this); return(x); },
toArrayNamesInverse: function() {return(_.map(this.toArrayIndexInverse(), function(x){ return (this.arrNames[x])}, this));},
toArrayNames: function() {return(_.map(this.toArrayIndex(), function(x){ return (this.arrNames[x])}, this));},
getInt: function () {return(this.num);},
setInt: function (i) {this.num = i; return (true);},
not: function() {this.num = ((~ this.num >>> 0) & 0x7f); return(true);}};
module.exports.SetRegister = SetRegister;
module.exports.SetRegister.prototype = SetRegisterProto;
SetRegister.prototype = SetRegisterProto;
function Registers() {
var rn = [['eax', 'ax', 'ah', 'al'], ['ebx', 'bx', 'bh', 'bl'], ['ecx', 'cx', 'ch', 'cl'], ['edx', 'dx', 'dh', 'dl'],
['esi', 'si', null, null ], ['edi', 'di', null, null], ['ebp', 'bp', null, null]];
this.container = []; this.used = new SetRegister();
_.each(rn, function(x, y) { this.container[y] = new Register(x[0], x[1], x[2], x[3]); }, this);};
RegistersProto = {
objToIndex : function (a) {
var b = null; _.find(this.container, function (x, y) { if (x === a) b=y; return (x === a);}, this); return(b);},
arrIndexToArrObj : function (a) {
if (_.isUndefined(a) || (!_.isArray(a)) || _.find(a, function(x) {if (x>REG_EBP || x<REG_EAX) return(true);})) return(null);
return(_.map(a, function(x) { return(this.container[x]); }, this))},
getIndexByName : function (sName){
var num = NaN; _.find(this.container, function(x, y) { if (x.name[0]===sName) {num = y; return(true);} }, this); return (num);},
getByIndex : function (i) { if (_.isUndefined(i) || i < REG_EAX || i > REG_EBP) return(null); return(this.container[i]);},
getArrFreeIndex : function () { return(this.used.toArrayIndexInverse()); },
getArrFreeName : function () {return(this.used.toArrayNamesInverse());},
getArrFreeObj : function (){return(_.filter(this.container, function(x) {return(!x.using);}, this));},
getUsedIndex : function () {return(this.used.toArrayIndex());},
getUsedNames : function() {return(this.used.toArrayNames());},
getUsedObj : function () {return(this.arrIndexToArrObj(this.used.toArrayIndex()));},
getFreeIndex : function(flags) {
var rs = this.getArrFreeObj(), r, res;
if (flags & USE_ONLY_GENERAL_REGS) rs = _.filter(rs, function(x) {return(x.isGeneral());}, this);
if (!_.size(rs)) return(NaN);
r = arrRndValue(rs);
if (flags & LOCK_REG) r.lock();
res = this.objToIndex(r);
if (!(flags & DONT_ADD_TO_LIST)) this.used.add(res);
return(res);
},
getFreeObj : function(flags) {
var rs = this.getArrFreeObj(), r;
if (flags & USE_ONLY_GENERAL_REGS) rs = _.filter(rs, function(x) { return(x.isGeneral()); }, this);
if (!_.size(rs)) return(null);
r = arrRndValue(rs);
if (flags & LOCK_REG) r.lock();
if (!(flags & DONT_ADD_TO_LIST)) this.used.add(this.objToIndex(r));
return(r);
}
}
module.exports.Registers = Registers;
module.exports.Registers.prototype = RegistersProto;
Registers.prototype = RegistersProto;
function Variable (sName, iSize) {
this.name = sName; this.use = false; this.size = iSize;};
module.exports.Variable = Variable;
function Variables () {
this.container = new Array();};
VariablesProto = {
add : function (sName, iSize) {if (!sName) return(null); if (!iSize) iSize = 4; if (!this.isExists(sName)) return(this.container.push(new Variable(sName, iSize))); return(null);},
isExists : function (sName) {
return((!_.isUndefined(sName)) && (_.find(this.container, function(x){ return (x.name === sName) }, this)));},
toString : function (sName) {
return(_.reduce(_.shuffle(this.container), function (m, x) {return(m+' local '+x.name+this.getAsmType(x.size)+'\n')}, '', this));},
getAsmType : function(i) {
var obj = {'1':':Byte', '2':':WORD', '4':':DWORD', '8':':QWORD'}; if (_.isUndefined(i) || i < 1 || (!_.isNumber(i))) return(null);
if (_.has(obj, i)) return(obj[i]); return ('['+i.toHex()+']:BYTE');}};
module.exports.Variables = Variables;
Variables.prototype = VariablesProto;
module.exports.Variables.ptototype = VariablesProto;
//module.exports.Variables.ptototype = VariablesProto;
function ExecutionEnvironment(sName, sCallConv, arrParam) {
var f;
this.regs = new Registers(); this.vars = new Variables(); this.name = sName;
this.callconv = sCallConv;
if (sCallConv == 'stdcall') { this.regs.container[REG_EBP].lock(); };
this.tableCmd = [];
f = function (p, f) {
f.emit([['add', p[0].s, '1'], ['sub', p[0].s, '-1'], ['inc', p[0].s]][_.random(2)]); return(true);}
this.tableCmd.push(['inc', ['r8'], 1, f]);
this.tableCmd.push(['inc', ['r16'], 1, f]);
this.tableCmd.push(['inc', ['r32'], 1, f]);
this.tableCmd.push(['inc', ['m32'], 1, f]);
f = function (p, f) {
f.emit(['add', p[1].s, p[0].s]); return(true);};
this.tableCmd.push(['add', ['c8', 'r8'], 2, f]);
this.tableCmd.push(['add', ['c16', 'r16'], 2, f]);
f = function (p, f) {
f.emit([['add', p[1].s, p[0].s], ['lea', p[1].s, '['+ p[1].s+'+'+unchainConst(p[0].s)+']']][_.random(1)]); return(true);};
this.tableCmd.push(['add', ['c32', 'r32'], 2, f]);
f = function (p, f) {f.emit([['add', p[1].s, p[0].s], ['lea', p[1].s, '['+p[0].s+'+'+p[1].s+']']][_.random(1)]); return(true);}
this.tableCmd.push(['add', ['r32', 'r32'], 2, f]);
f = function (p, f) {
f.emit([['push', p[0].s, ';', 'pop', p[1].s], ['mov', p[1].s, p[0].s]][_.random(1)]); return(true);};
this.tableCmd.push(['load', ['m32', 'r32'], 2, f]);
this.tableCmd.push(['load', ['r32', 'm32'], 2, f]);
this.tableCmd.push(['load', ['r32', 'r32'], 2, f]);
this.tableCmd.push(['load', ['c32', 'r32'], 2, f]);
this.tableCmd.push(['load', ['c32', 'm32'], 2, f]);
f = function (p, f) {
f.emit(['push', p[0].s, ';', 'pop', p[1].s]);
return(true);
};
this.tableCmd.push(['load', ['m32', 'm32'], 2, f]);
f = function (p, f) {
f.emit([['add', p[0].s, '-0x1'], ['sub', p[0].s, '0x1'], ['dec', p[0].s], ['lea', p[0].s, '['+p[0].s+'-0x1]']][_.random(3)]);
return(true);
};
this.tableCmd.push(['dec', ['r8'], 1, f]); this.tableCmd.push(['dec', ['r16'], 1, f]); this.tableCmd.push(['dec', ['r32'], 1, f]);
f = function(p, f) {
f.emit([['test', p[0].s, p[0].s], ['cmp', p[0].s, (0).toHex()], ['or', p[0].s, p[0].s]][_.random(2)]);
return(true);
};
this.tableCmd.push(['checkz', ['r8'], 1, f]);
this.tableCmd.push(['checkz', ['r16'], 1, f]);
this.tableCmd.push(['checkz', ['r32'], 1, f]);
f = function(p, f) {
f.emit([['mov', p[0].s, '0x0'], ['push', '0x0', ';', 'pop', p[0].s], ['and', p[0].s, '0x0'], ['xor', p[0].s, p[0].s], ['sub', p[0].s, p[0].s]][_.random(4)]);
return(true)
};
this.tableCmd.push(['loadz', ['r32'], 1, f]);
f = function(p, f) {
f.emit(['movzx', p[1].s, p[0].s]);
return(true)
};
this.tableCmd.push(['loadzx', ['m8', 'r32'], 2, f]);
this.tableCmd.push(['loadzx', ['m16', 'r32'], 2, f]);
f = function(p, f) {
var r;
if (_.random(1)) {
f.emit(['cmp', p[1].s, p[0].s]);
} else {
r = f.getFreeReg(LOCK_REG);
f.cmd('loadzx_m16$r32', [unchainMem(p[1].s), r.i]);
f.emit(['cmp', r.s, (p[0].i).toHex()]);
r.o.unlock();
};
return(true);
};
this.tableCmd.push(['check', ['c16', 'm16'], 2, f]);
f = function(p, f) {
f.emit(['cmp', p[1].s, p[0].s]); return(true);
};
this.tableCmd.push(['check', ['c32', 'm32'], 2, f]);
this.tableCmd.push(['check', ['m32', 'r32'], 2, f]);
this.useForResult = null; this.params = arrParam; this.code = ''; this.settings = {fTrashGen: false};
};
ExecutionEnvironmentProto = {
emit : function (line) {
ax = []; ay= []; if (_.isString(line)) {this.code+=line;return(line);} if (!_.isArray(line)) return(null);
_.each(line, function(x, i, arr) { if (x == ';') { ay.push(ax); ax = []; return(0); } ax.push(x); } , this); if (_.size(ax)) ay.push(ax);
this.code+=_.reduce(ay, function(m, x) { var s =''; if(_.size(x)){s=' '+pad(x[0], 8);
if (_.size(x) > 1) { s += x.slice(1).join(', ');}} return(m+s+'\n');}, '', this);return(true);},
finalize : function(r) {
if (this.callconv == 'stdcall') {
var sResultType, bSaveUsedRegs = _.random(1), optimize = _.random(1);
regz = this.regs.getUsedIndex();
if (bSaveUsedRegs && _.isNumber(this.useForResult)) {
if (this.useForResult == REG_EAX && optimize ) {this.regs.used.remove(REG_EAX);}
else { this.vars.add('iResult'); this.cmd('load_r32$m32', [this.useForResult, 'iResult']); };
} else {
this.vars.add('iResult');
if (_.isNumber(this.useForResult)) {this.cmd('load_r32$m32', [this.useForResult, 'iResult']);} else {
if (!this.vars.isExists(this.useForResult)) {this.cmd('load_m32$m32', [this.useForResult, 'iResult']);};};
};
if (bSaveUsedRegs) {
this.code = _.reduce(this.regs.getUsedNames(), function(memo, i) {return(' push '+i+'\n'+memo+' pop '+i+'\n');}, this.code, this);}
else {this.code = ' pusha\n'+this.code+' popa\n';};
if (!(optimize && bSaveUsedRegs && this.useForResult == REG_EAX)) {this.cmd('load_m32$r32', ['iResult', REG_EAX]); };
this.code = 'proc '+this.name+' '+this.params.join(', ')+'\n'+this.vars+this.code+' ret\nendp\n';
return (true);};
return(false);},
setUseForResult : function(r) {if (_.isString(r) || _.isNumber(r)) { this.useForResult = r; return(true); }; return(false); },
toString : function () {return(this.code);},
toType : function(t, v) {
var getRSZ, isMem, toMem, toReg, oTableType; getRSZ = function(a) { return((a>>3)&3); };
isMem = function (a){ return(_.isString(a) ? '['+a+']': null); };
toMem = function (m, i) { var obj = {'0':'DWord', '1':'Word', '2':'Byte'}, p; if (_.isUndefined(i)||(!(p = isMem(m)))||(!_.isNumber(i)))
return(null); if (_.has(obj, i)) return({s:obj[i]+' '+p, o: null, i:null}); return(null); }
toReg = function (p, ee) { return({i: p, o: ee.regs.getByIndex(p&7), s: ee.regs.getByIndex(p&7).toString(getRSZ(p))});};
//
oTableType = {
'm32': function (p, ee) {return(toMem(p, MEM32));},
'm16': function (p, ee) {return(toMem(p, MEM16));},
'm8': function (p, ee) {return(toMem(p, MEM8));},
'r32': function (p, ee) {return((_.isUndefined(p) || (p<REG_EAX) ||p>REG_EBP) ? null:toReg(p, ee));},
'r16': function (p, ee) {return((_.isUndefined(p) || (getRSZ(p)!==REG_LOWORD)) ? null:toReg(p, ee));},
'r8': function (p, ee) {return((_.isUndefined(p) || (getRSZ(p)!==REG_HIBYTE&&getRSZ(p)!==REG_LOBYTE)) ? null:toReg(p, ee))},
'c32': function (p, ee) { return(((!_.isUndefined(p))&&_.isNumber(p)) ? {o:null,s:'DWORD ' + p.toHex(),i:p} : (_.isString(p) ? {o:null, s:p, i:null}: null) )},
'c16': function (p, ee) { return(((!_.isUndefined(p))&&_.isNumber(p)) ? {o:null,s:'WORD ' + p.toHex(),i:p} : (_.isString(p) ? {o:null, s:p, i:null}: null) )},
'c8': function (p, ee) { return(((!_.isUndefined(p))&&_.isNumber(p)) ? {o:null,s:'BYTE ' + p.toHex(),i:p} : (_.isString(p) ? {o:null, s:p, i:null}: null) )}
};
return(_.has(oTableType,t)?oTableType[t](v,this):null);
},
cmd : function(name, params) {
var p = [], c = _.find(this.tableCmd, function(x) { return ( (!_.size(x[1])) || (x[0]+'_'+x[1].join('$')===name));}, this);
if ((!c)||(!_.isFunction(c[3]))) return(false); _.each(c[1], function (x, i) { var v = this.toType(x, params[i]);
if (v) p.push(v);}, this); if (_.size(p)!==c[2]) return(false); c[3](p, this); return(true);},
getFreeReg: function(f) {
return(this.toType('r32', this.regs.getFreeIndex(f)));}};
module.exports.ExecutionEnvironment = ExecutionEnvironment;
module.exports.ExecutionEnvironment.prototype = ExecutionEnvironmentProto;
ExecutionEnvironment.prototype = ExecutionEnvironmentProto;
tablecall.js файл
Код:
var pad = require('./modules/node-pad/lib/pad.js');
var _ = require('./modules/underscore/underscore.js');
var p = require('./platform.js');
function nameptrfnc(v) {
if (_.isObject(v) && _.has(v, 'lib') && _.has(v, 'fnc'), _.isString(v.lib), _.isString(v.lib)) {
return('p'+v.fnc+'_'+v.lib.replace(/\.dll/gi, ''))}};
module.exports = nameptrfnc;
function namehandlelib(slib) {
if (_.isString(slib)) return('h'+slib.replace(/\.dll/gi, ''));};
module.exports = namehandlelib;
function namestrzlib(slib) {
if (_.isString(slib)) return('sz'+slib.replace(/\.dll/gi, ''));};
module.exports = namestrzlib;
function genAPIStruct(ta) {
return (_.reduce(_.shuffle(ta), function(memo, val) { return (memo + pad(' '+nameptrfnc(val), 40)+' dd ?\n'); }, 'struct stAPITable\n') + 'ends\n');};
module.exports.genAPIStruct = genAPIStruct;
toHex = function(x) {
return('0x'+x.toString(16));};
CodeSnippet = function(name, callconv, params, fSnippet, prmz) {
var ee = new p.ExecutionEnvironment(name, callconv, params);
fSnippet(ee, ee.regs, ee.vars, prmz);
ee.finalize();
return({e : ee, code: ee.code, buffer: null});};
module.exports.CodeSnippet = CodeSnippet;
var fHashRor7Xor = function (e, r, v) {
var r1 = e.getFreeReg(p.USE_ONLY_GENERAL_REGS|p.LOCK_REG), r2 = e.getFreeReg(p.LOCK_REG);
e.cmd('load_m32$r32', ['strz', r2.i]);
e.cmd('load_c32$r32', [0, r1.i]);
e.emit(['push',''+r1.s]);
e.emit('.CalcHash:\n');
e.emit(['ror', r1.s, 7]);
e.emit(['xor','[esp]', r1.s]);
e.emit(['mov', e.toType('r8', r1.i+p.REG_R8L).s, 'Byte ['+r2.s+']']);
e.cmd('inc_r32', [r2.i]);
e.cmd('checkz_r8', [r1.i+p.REG_R8L]);
e.emit(['jnz','.CalcHash']);
e.emit(['pop','eax']);
e.setUseForResult(p.REG_EAX);};
var fGetNtdll = function (e, r, v) {
var r1, r2, r3, r4;
r1 = e.getFreeReg(p.LOCK_REG);
e.cmd('load_m32$r32', ['fs:0x30', r1.i]);
r1.o.unlock();
r2 = e.getFreeReg(p.LOCK_REG);
e.cmd('load_m32$r32', [r1.s+'+0xC', r2.i]);
r2.o.unlock();
r3 = e.getFreeReg(p.LOCK_REG);
e.cmd('load_m32$r32', [r2.s+'+0x1C', r3.i]);
r3.o.unlock();
e.setUseForResult(r3.s+'+0x8');};
var fGetK32 = function (e, r, v){
var reg1, reg2, reg3, reg4, reg5; c = _.shuffle([0x6b, 0x4b]);
e.vars.add('iResult');
reg1 = e.getFreeReg(p.LOCK_REG);
e.cmd('load_m32$r32', ['fs:0x30', reg1.i]);
reg1.o.unlock();
reg2 = e.getFreeReg(p.LOCK_REG);
e.cmd('load_m32$r32', [reg1.s+'+0xC', reg2.i]);
reg2.o.unlock();
reg3 = e.getFreeReg(p.LOCK_REG);
e.cmd('load_m32$r32', [reg2.s+'+0x1C', reg3.i]);
e.emit('.NextModule:\n');
e.cmd('load_m32$m32', [reg3.s+'+0x8', 'iResult']);
reg4 = e.getFreeReg(p.LOCK_REG);
e.cmd('load_m32$r32', [reg3.s+'+0x20', reg4.i]);
e.cmd('load_m32$r32', [reg3.s, reg3.i]);
reg5 = e.getFreeReg(p.LOCK_REG|p.USE_ONLY_GENERAL_REGS);
e.cmd('loadzx_m8$r32', [reg4.s+'+0x18', reg5.i]);
e.cmd('checkz_r32', [reg5.i]);
e.emit(['jne', '.NextModule']);
e.cmd('loadzx_m8$r32', [reg4.s, reg5.i]);
e.emit(['cmp', reg5.s, toHex(c[0]), ';', 'je', '.Found_K32', ';', 'cmp', reg5.s, toHex(c[1]), ';', 'jne', '.NextModule']);
e.emit('.Found_K32:\n');
e.setUseForResult('iResult');};
function genData(e, buff, memdest) {
var i = 0, r = e.getFreeReg(LOCK_REG);
e.emit(['lea', r.s, '['+memdest+']']);
while( i < buff.length){
if ((buff.length - i - 1) > 4) {
e.cmd('load_c32$m32', [p.BytesToDword(buff[i], buff[i+1], buff[i+2], buff[i+3]), r.s]); i+=4; e.cmd('add_c32$r32', [4, r.i]);
} else { e.emit(['mov', 'BYTE ['+r.s+']', toHex(buff[i])]); i++; if (i !== buff.length) { e.cmd('inc_r32', [r.i]);}; }; }; r.o.unlock();};
module.exports.genData = genData;
function fAltGetProcAddress (e, r, v){
var r1;
e.vars.add('iResult');
r1 = e.getFreeReg(p.LOCK_REG);
eval(_.shuffle(["e.cmd('load_c32$m32', [0, 'iResult'])", "e.cmd('load_m32$r32', ['hLib', r1.i])"]).join(';'));
e.cmd('check_c16$m16', [0x5a4d, r1.s]);
e.emit(['jne', '.End']);
r2 = e.getFreeReg(p.LOCK_REG);
e.cmd('loadzx_m16$r32', [r1.s+'+0x3c', r2.i]);
e.cmd('add_r32$r32', [r1.i, r2.i]);
e.cmd('check_c32$m32', [0x4550, r2.s]);
e.emit(['jne', '.End']);
r3 = e.getFreeReg(p.LOCK_REG);
e.cmd('load_m32$r32', [r2.s+'+0x78', r3.i]);
r2.o.unlock();
e.cmd('add_r32$r32', [r1.i, r3.i]);
r4 = e.getFreeReg(p.LOCK_REG);
e.cmd('load_m32$r32', [r3.s+'+0x18', r4.i]);
r5 = e.getFreeReg(p.LOCK_REG);
e.emit(['push', r3.s]);
e.cmd('loadz_r32', [r5.i]);
r6 = e.getFreeReg(p.LOCK_REG);
e.cmd('load_m32$r32', [r3.s+'+0x20', r6.i]);
r3.o.unlock();
e.cmd('add_r32$r32', [r1.i, r6.i]);
e.emit('.MainLoop:\n');
r7 = e.getFreeReg(p.LOCK_REG);
e.cmd('load_m32$r32', [r6.s, r7.i]);
e.cmd('add_r32$r32', [r1.i, r7.i]);
e.emit(['push', 'eax']);
e.emit(['stdcall', '[fHashProc]', r7.s]);
e.cmd('check_m32$r32', ['iHashVal', p.REG_EAX]);
e.emit(['pop', 'eax']);
e.emit(['jz', '.FoundProcname']);
eval(_.shuffle(["e.cmd('add_c32$r32', [0x4, r6.i])", "e.cmd('inc_r32', [r5.i])", "e.cmd('dec_r32', [r4.i])"]).join(';'));
e.cmd('checkz_r32', [r4.i]);
e.emit(['jnz', '.MainLoop']);
e.emit(['pop', e.getFreeReg().s]);
e.emit(['jmp', '.End']);
e.emit('.FoundProcname:\n');
r7.o.unlock(); r6.o.unlock(); r4.o.unlock();
r8 = e.getFreeReg(p.LOCK_REG);
e.emit(['pop', r8.s]);
eval("e.emit(['shl', r5.s, 0x1])");
e.emit(['add', r5.s, (e.toType('m32', r8.s+'+0x24')).s]);
r9 = e.getFreeReg(p.LOCK_REG);
e.cmd('loadzx_m16$r32', [r5.s+'+'+r1.s, r9.i]);
eval(["e.emit(['shl', r9.s, 0x2]); e.cmd('add_r32$r32', [r1.i, r9.i]);",
"e.emit(['lea', r9.s, '['+ r9.s+'*4+'+r1.s+']']);"][_.random(1)]);
e.emit(['add', r9.s, (e.toType('m32', r8.s+'+0x1C')).s]);
r8.o.unlock(); r10 = e.getFreeReg(p.LOCK_REG);
e.cmd('load_m32$r32', [r9.s, r10.i]);
e.cmd('add_r32$r32', [r1.i, r10.i]);
e.cmd('load_r32$m32', [r10.i, 'iResult']);
e.emit('.End:\n');
};
function tableApiUnique (ta) {
return(eval('[ '+(_.uniq(_.map(ta, function(x) { return(JSON.stringify(x));}))).join(', ')+' ]'));};
function tableApiHasLib(ta, sDll) {
return (_.size(_.where(ta, {lib:sDll})) > 0);};
function tableApiHasUserLibs(ta){
return(_.find ( ta, function(value) { return ( value.lib !== 'kernel32.dll' && value.lib !== 'ntdll.dll') }) === null);};
function tableApiGetUserLibs(ta) {
return(_.filter(_.unique(_.pluck(ta, 'lib')), function(value) { return (value !== 'kernel32.dll' && value !== 'ntdll.dll') }));};
var oGetNtdllProc = CodeSnippet('GetNtdll', 'stdcall', [], fGetNtdll);
var oGetK32Proc = CodeSnippet('GetK32', 'stdcall', [], fGetK32);
var oGetHashProc = CodeSnippet('GetHashSz', 'stdcall', ['strz'], fHashRor7Xor);
var oAltGetProcAddress = CodeSnippet('AltGetProcAddressByHash', 'stdcall', ['hLib', 'fHashProc', 'iHashVal'], fAltGetProcAddress);
function _rotr (value, shift) {
if ((shift &= 31) == 0) return value;
return ((value >>> shift) | (value << (32 - shift)));};
function hash_ror7xor(b){
var r = 0, x = 0;
for (i = 0; i<_.size(b); i++) { x = _rotr(x, 7); r ^= x; x = x & 0xffffff00; x |= b[i]>>>0; };
return( (r^=_rotr(x, 7))>>>0);};
function followApiTable(e, ta){
var bufflib, r = e.regs, v = e.vars;
reg_addr = e.toType('r32', [p.REG_EBX, p.REG_ESI, p.REG_EDI][_.random(2)]);
reg_addr.o.lock();
if (tableApiHasUserLibs(ta)) {
ta.push({fnc: 'LoadLibraryA', lib: 'kernel32.dll'});};
ta = tableApiUnique(ta);
v.add('pGetHashSz');
e.cmd('load_m32$r32', ['pMyAddr', reg_addr.i]);
e.emit(['lea', reg_addr.s, '['+reg_addr.s+'+GetHashSz]']);
e.cmd('load_r32$m32', [reg_addr.i, 'pGetHashSz']);
if (tableApiHasLib(ta, 'kernel32.dll')) {
e.vars.add(namehandlelib('kernel32.dll'));
e.emit(['call', 'GetK32']);
e.cmd('load_r32$m32', [p.REG_EAX, namehandlelib('kernel32.dll')]);};
if (tableApiHasLib(ta, 'ntdll.dll')) {
e.vars.add(namehandlelib('ntdll.dll'));
e.emit(['call', 'GetNtdll']);
e.cmd('load_r32$m32', [p.REG_EAX, namehandlelib('ntdll.dll')]);};
e.vars.add('APITable',_.size(ta)*4);
_.each(tableApiGetUserLibs(ta), function(lib) {
e.emit(['stdcall', 'AltGetProcAddressByHash', '['+namehandlelib('kernel32')+']', reg_addr.s, toHex(hash_ror7xor(new Buffer('LoadLibraryA', 'utf-8')))]);
e.cmd('load_r32$m32', [p.REG_EAX, 'APITable+stAPITable.pLoadLibraryA_kernel32']);
var s, bufflib, ro;
s = namestrzlib(lib);
bufflib = new Buffer(lib+'\0', 'utf-8');
v.add(s, _.size(bufflib));
genData(e, bufflib, s);
v.add(namehandlelib(lib));
ro = e.getFreeReg(p.LOCK_REG);
e.emit(['lea', ro.s, '['+s+']'])
e.emit(['stdcall', 'DWord [APITable+stAPITable.pLoadLibraryA_kernel32]', ro.s]); ro.o.unlock();
e.cmd('load_r32$m32', [p.REG_EAX, namehandlelib(lib)]);
}, this);
_.each(ta, function(value) {
if (!(tableApiHasUserLibs(ta) && value.fnc === "LoadLibraryA")) {
e.emit(['stdcall', 'AltGetProcAddressByHash', '['+namehandlelib(value.lib)+']', reg_addr.s, toHex(hash_ror7xor(new Buffer(value.fnc, 'utf-8')))]);
e.cmd('load_r32$m32', [p.REG_EAX, 'APITable+stAPITable.'+nameptrfnc(value)]);}
}, this);
reg_addr.o.unlock();
return(genAPIStruct(ta));};
module.exports.followApiTable = followApiTable;
module.exports.procz = [oGetNtdllProc, oGetK32Proc, oGetHashProc, oAltGetProcAddress];