/// <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> /// Counts the number of warnings for the data block. If escapeOnRet is set, any /// instrutions after a return will be ignored. /// </summary> /// <param name="data"></param> /// <param name="baseAddress"></param> /// <param name="escapeOnRet"></param> /// <param name="instructionAddress"></param> /// <returns></returns> public static int CountWarnings(byte[] data) { // Disassemble all the instructions in the data block int offset = 0; int warnings = 0; while (offset + 6 < data.Length) { // Process this instruction // Decode SIMPLE_INSTRUCTION instruction = decodeInstruction(data, offset, 0); // Check the warning cost of this opcode if (warningOpCodeTable.ContainsKey((int)instruction.opcode)) { // There exists a warning for this opcode warnings += (int)warningOpCodeTable[(int)instruction.opcode]; } // Next instruction offset += instruction.size; } return(warnings); }
/// <summary> /// This processes instructions starting at the beginning of the memory block, and searches for the /// the smallest number of instructions that form at least 5 bytes. /// </summary> /// <param name="readMemory"></param> /// <returns></returns> public static byte[] getMinFiveBytesCode(byte[] data) { int offset = 0; while (offset + 5 < data.Length && offset < 5) { // Decode this instruction SIMPLE_INSTRUCTION instruction = decodeInstruction(data, offset, 0); // Next instruction offset += instruction.size; } // Generate the result byte[] result = new byte[offset]; Array.ConstrainedCopy(data, 0, result, 0, offset); 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); }