Package org.jakstab.loader

Source Code of org.jakstab.loader.HeuristicHarness

/*
* HeuristicHarness.java - This file is part of the Jakstab project.
* Copyright 2007-2012 Johannes Kinder <jk@jakstab.org>
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, see <http://www.gnu.org/licenses/>.
*/
package org.jakstab.loader;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.jakstab.Program;
import org.jakstab.asm.AbsoluteAddress;
import org.jakstab.loader.pe.AbstractCOFFModule;
import org.jakstab.cfa.Location;
import org.jakstab.rtl.expressions.ExpressionFactory;
import org.jakstab.rtl.expressions.RTLExpression;
import org.jakstab.rtl.expressions.RTLVariable;
import org.jakstab.rtl.statements.*;
import org.jakstab.util.Logger;

public class HeuristicHarness implements Harness {

  @SuppressWarnings("unused")
  private static final Logger logger = Logger.getLogger(HeuristicHarness.class);
 
  private static int CALL_INSTR_DISTANCE = 1;
 
  private static byte[][] procedureHeads = new byte[][] {
    // mov edi, edi; push ebp; mov ebp, esp;
    { -0x75, -0x01, 0x55, -0x75, -0x14},
    // push ebp; mov ebp, esp;
    { 0x55, -0x75, -0x14 }
  };
 
  private long PROLOGUE_BASE = 0xface0000L;
  private long EPILOGUE_BASE = 0xfee70000L;
  private AbsoluteAddress prologueAddress = new AbsoluteAddress(PROLOGUE_BASE);
  private AbsoluteAddress epilogueAddress = new AbsoluteAddress(EPILOGUE_BASE);
  private AbsoluteAddress lastAddress;


  private RTLVariable esp = Program.getProgram().getArchitecture().stackPointer();
 
  private List<AbsoluteAddress> entryPoints;
 
  public HeuristicHarness() {
    entryPoints = new LinkedList<AbsoluteAddress>();
   
    Program program = Program.getProgram();
   
    if (program.getMainModule() instanceof AbstractCOFFModule) {
    byte[] data = ((AbstractCOFFModule)program.getMainModule()).getByteArray();
    for (int filePtr=0; filePtr<data.length; filePtr++) {
      patternLoop: for (int patternIdx = 0; patternIdx < procedureHeads.length; patternIdx++) {
        for (int i = 0; i < procedureHeads[patternIdx].length; i++) {
          if (data[filePtr + i] != procedureHeads[patternIdx][i])
            continue patternLoop;
        }
        // Pattern matched!
        AbsoluteAddress newEntryPoint = program.getMainModule().getVirtualAddress(filePtr);
        entryPoints.add(newEntryPoint);
        logger.verbose("Found possible procedure entry at " + newEntryPoint);
        filePtr += procedureHeads[patternIdx].length;
        break;
      }
    }
    }
  }
 
  @Override
  public void install(Program program) {

    StatementSequence seq = new StatementSequence();
    seq.addLast(new RTLVariableAssignment(1, ExpressionFactory.createVariable("%DF", 1), ExpressionFactory.FALSE));

    AbsoluteAddress currentAddress = prologueAddress;
    AbsoluteAddress fallthroughAddress = new AbsoluteAddress(currentAddress.getValue() + CALL_INSTR_DISTANCE);
   
    // Call the entry point of the executable
    push32(seq, ExpressionFactory.createNumber(fallthroughAddress.getValue(), 32));
    seq.addLast(new RTLGoto(ExpressionFactory.createNumber(program.getStart().getAddress().getValue(), 32), RTLGoto.Type.CALL));
    putSequence(program, seq, currentAddress);
    program.setEntryAddress(currentAddress);
   
    // Now call all procedures that were heuristically detected

    for (Iterator<AbsoluteAddress> iter = entryPoints.iterator(); iter.hasNext();) {
      AbsoluteAddress entryPoint = iter.next();
      currentAddress = fallthroughAddress;
      fallthroughAddress = iter.hasNext() ? new AbsoluteAddress(currentAddress.getValue() + 1) : prologueAddress;
      seq = new StatementSequence();

      for (RTLVariable v : program.getArchitecture().getRegisters()) {
        if (!v.equals(esp))
          clearReg(seq, v);
      }
      push32(seq, ExpressionFactory.createNumber(fallthroughAddress.getValue(), 32));
      seq.addLast(new RTLGoto(ExpressionFactory.createNumber(entryPoint.getValue(), 32), RTLGoto.Type.CALL));
      putSequence(program, seq, currentAddress);
    }
   
    lastAddress = currentAddress;

    // epilogue with halt statement
    seq = new StatementSequence();
    //seq.addLast(new RTLSkip());
    seq.addLast(new RTLHalt());
    putSequence(program, seq, epilogueAddress);
  }
 
  private void push32(StatementSequence seq, RTLExpression value) {
    seq.addLast(new RTLVariableAssignment(esp.getBitWidth(), esp,
        ExpressionFactory.createPlus(esp, ExpressionFactory.createNumber(-4, esp.getBitWidth()))
    ));
    if (value != null) {
      seq.addLast(new RTLMemoryAssignment(ExpressionFactory.createMemoryLocation(esp, 32), value));
    }
  }
 
  private void clearReg(StatementSequence seq, RTLVariable v) {
    seq.addLast(new RTLVariableAssignment(v.getBitWidth(), v, ExpressionFactory.nondet(v.getBitWidth())));
  }
 
  private void putSequence(Program program, StatementSequence seq, AbsoluteAddress address) {
    int rtlId = 0;
    for (RTLStatement stmt : seq) {
      stmt.setLabel(address, rtlId++);
      stmt.setNextLabel(new Location(address, rtlId));
    }
    seq.getLast().setNextLabel(null);

    // add stub statements to program
    for (RTLStatement s : seq)
      program.putStatement(s);
  }

  @Override
  public boolean contains(AbsoluteAddress a) {
    return a.getValue() >= PROLOGUE_BASE && a.getValue() <= lastAddress.getValue();
  }

  @Override
  public AbsoluteAddress getFallthroughAddress(AbsoluteAddress a) {
    if (a.getValue() >= PROLOGUE_BASE && a.getValue() < lastAddress.getValue())
      return new AbsoluteAddress(a.getValue() + CALL_INSTR_DISTANCE);
    else if (a.equals(lastAddress))
      return epilogueAddress;
    else
      return null;
  }

}
TOP

Related Classes of org.jakstab.loader.HeuristicHarness

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.