/// <summary> /// Add first RET in the data block to the return address list. /// </summary> /// <param name="data"></param> /// <param name="baseAddress"></param> /// <param name="returnAddresses"></param> /// <returns></returns> public static void AddFirstRet(byte[] data, int baseAddress, int startOffset, ref oAsmRetList returnAddresses) { // Disassemble all the instructions in the data block int offset = startOffset; while (offset + 10 < data.Length) { // Process this instruction // Decode SIMPLE_INSTRUCTION instruction = decodeInstruction(data, offset, baseAddress); // Process switch (instruction.opcode) { case SIMPLE_INSTRUCTION.OP_RET_NULL: if (instruction.size == 1) returnAddresses.addRet(instruction.address, 0); return; case SIMPLE_INSTRUCTION.OP_RET_IMM16: if (instruction.size == 3) returnAddresses.addRet(instruction.address, instruction.immediate); return; } // Next instruction offset += instruction.size; } }
/// <summary> /// Return instructions are outputted to returnAddresses. /// </summary> /// <param name="data"></param> /// <param name="baseAddress"></param> /// <param name="returnAddresses"></param> /// <returns></returns> public static void DisassembleBlockRetOnly(byte[] data, int baseAddress, ref oAsmRetList returnAddresses) { // Disassemble all the instructions in the data block int offset = 0; while (offset + 10 < data.Length) { // Process this instruction // Decode SIMPLE_INSTRUCTION instruction = decodeInstruction(data, offset, baseAddress); // Process switch (instruction.opcode) { case SIMPLE_INSTRUCTION.OP_RET_NULL: if (instruction.size == 1) { returnAddresses.addRet(instruction.address, 0); } break; case SIMPLE_INSTRUCTION.OP_RET_IMM16: if (instruction.size == 3) { returnAddresses.addRet(instruction.address, instruction.immediate); } break; } // Next instruction offset += instruction.size; } }
/// <summary> /// Estimates the number of input parameters of each funciton. /// </summary> /// <param name="retList">Return instruction list.</param> public static void estimateFunctionParameters(oAsmRetList retList, oEbpArgumentList ebpAddresses, Form parent) { if( functions == null ) functions = new List<oFunction>(); // Estimate the number of parameters for each function return int count = 0; formProgress progress = new formProgress(parent); progress.Show(parent); progress.setMin(0); progress.setMax(oFunctionMaster.numFunctions/273); progress.setTitle("Estimating Number Parameter Counts..."); progress.setLabel1("Estimating Function Input Parameter Counts: " + count.ToString() + "0 of " + oFunctionMaster.numFunctions.ToString() ); progress.setLabel2(""); // Loop through each function, estimating the number of parameters List<oFunction> invalidFunctions = new List<oFunction>(0); foreach( oFunction function in functions ) { // Estimate parameters function.estimateNumParameters(retList, ebpAddresses); // Check the number of parameters is valid if (function.getNumParams() > 50) { // Invalid function invalidFunctions.Add( function ); } count++; if(count%273 == 0) { progress.setLabel1("Estimating Function Input Parameter Counts: " + count.ToString() + "0 of " + oFunctionMaster.numFunctions.ToString()); progress.increment(); } } // Remove the invalid functions foreach( oFunction function in invalidFunctions ) { functions.Remove(function); } progress.Dispose(); }
/// <summary> /// Decodes all the call instructions from the block. Return instructions are outputted to returnAddresses. /// </summary> /// <param name="data"></param> /// <param name="baseAddress"></param> /// <param name="returnAddresses"></param> /// <returns></returns> public static List <SIMPLE_INSTRUCTION> DisassembleBlockCallsOnly(byte[] data, int baseAddress, ref oAsmRetList returnAddresses, ref oEbpArgumentList ebpArguments, ref List <jmpInstruction> jumps) { // Disassemble all the instructions in the data block int offset = 0; List <SIMPLE_INSTRUCTION> result = new List <SIMPLE_INSTRUCTION>(data.Length / 100); while (offset + 10 < data.Length) { // Process this instruction // Decode SIMPLE_INSTRUCTION instruction = decodeInstruction(data, offset, baseAddress); // Process switch (instruction.opcode) { case SIMPLE_INSTRUCTION.OP_CALL_IMM32: if (instruction.size == 5 && instruction.numPrefix == 0) { result.Add(instruction); } break; case SIMPLE_INSTRUCTION.OP_RET_NULL: if (instruction.size == 1 && instruction.numPrefix == 0) { returnAddresses.addRet(instruction.address, 0); } break; case SIMPLE_INSTRUCTION.OP_RET_IMM16: if (instruction.size == 3 && instruction.numPrefix == 0) { returnAddresses.addRet(instruction.address, instruction.immediate); } break; case SIMPLE_INSTRUCTION.OP_MOV_REG32: if (instruction.size == 3 && (data[offset + 1] == 0x45 || data[offset + 1] == 0x5d || data[offset + 1] == 0x4D || data[offset + 1] == 0x55 || data[offset + 1] == 0x75 || data[offset + 1] == 0x7D) && data[offset + 2] <= 0x7F && data[offset + 2] > 0x04) { // mov reg32, [ebp+imm8] // Save this immediate value, it tells us how many arguments this function has ebpArguments.addEbpReference(instruction.address, (int)(data[offset + 2] - 4) / 4); } break; case SIMPLE_INSTRUCTION.OP_PUSH_DEREF_REG32: if (instruction.size == 3 && data[offset + 1] == 0x75 && data[offset + 2] <= 0x7F && data[offset + 2] > 0x04) { // push [ebp+imm8] // Save this immediate value, it tells us how many arguments this function has ebpArguments.addEbpReference(instruction.address, (int)(data[offset + 2] - 4) / 4); } break; case SIMPLE_INSTRUCTION.OP_JMP_IMM32: if (instruction.size == 5) { // jmp imm32 // Save this jump jumps.Add(new jmpInstruction(instruction.address, instruction.jmp_target)); } break; } // Check to see if it is a mov reg32, [ebp+imm8] instruction. // Next instruction offset += instruction.size; } // Return the resulting call instructions return(result); }
/// <summary> /// Decodes all the call instructions from the block. Return instructions are outputted to returnAddresses. /// </summary> /// <param name="data"></param> /// <param name="baseAddress"></param> /// <param name="returnAddresses"></param> /// <returns></returns> public static List<SIMPLE_INSTRUCTION> DisassembleBlockCallsOnly(byte[] data, int baseAddress, ref oAsmRetList returnAddresses, ref oEbpArgumentList ebpArguments, ref List<jmpInstruction> jumps) { // Disassemble all the instructions in the data block int offset = 0; List<SIMPLE_INSTRUCTION> result = new List<SIMPLE_INSTRUCTION>(data.Length/100); while( offset + 10 < data.Length) { // Process this instruction // Decode SIMPLE_INSTRUCTION instruction = decodeInstruction(data, offset, baseAddress); // Process switch(instruction.opcode) { case SIMPLE_INSTRUCTION.OP_CALL_IMM32: if( instruction.size == 5 && instruction.numPrefix == 0 ) result.Add(instruction); break; case SIMPLE_INSTRUCTION.OP_RET_NULL: if (instruction.size == 1 && instruction.numPrefix == 0) returnAddresses.addRet(instruction.address, 0); break; case SIMPLE_INSTRUCTION.OP_RET_IMM16: if (instruction.size == 3 && instruction.numPrefix == 0) returnAddresses.addRet(instruction.address, instruction.immediate); break; case SIMPLE_INSTRUCTION.OP_MOV_REG32: if (instruction.size == 3 && (data[offset+1] == 0x45 || data[offset+1] == 0x5d || data[offset+1] == 0x4D || data[offset+1] == 0x55 || data[offset+1] == 0x75 || data[offset+1] == 0x7D) && data[offset + 2] <= 0x7F && data[offset + 2] > 0x04) { // mov reg32, [ebp+imm8] // Save this immediate value, it tells us how many arguments this function has ebpArguments.addEbpReference(instruction.address, (int) (data[offset + 2]-4)/4); } break; case SIMPLE_INSTRUCTION.OP_PUSH_DEREF_REG32: if (instruction.size == 3 && data[offset + 1] == 0x75 && data[offset + 2] <= 0x7F && data[offset + 2] > 0x04) { // push [ebp+imm8] // Save this immediate value, it tells us how many arguments this function has ebpArguments.addEbpReference(instruction.address, (int)(data[offset + 2] - 4) / 4); } break; case SIMPLE_INSTRUCTION.OP_JMP_IMM32: if (instruction.size == 5) { // jmp imm32 // Save this jump jumps.Add( new jmpInstruction(instruction.address, instruction.jmp_target) ); } break; } // Check to see if it is a mov reg32, [ebp+imm8] instruction. // Next instruction offset += instruction.size; } // Return the resulting call instructions return result; }