/* * LinuxStubLibrary.java - This file is part of the Jakstab project. * Copyright 2007-2015 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.HashMap; import java.util.Map; import org.jakstab.Program; import org.jakstab.asm.AbsoluteAddress; import org.jakstab.asm.SymbolFinder; import org.jakstab.rtl.expressions.ExpressionFactory; import org.jakstab.rtl.expressions.RTLExpression; import org.jakstab.rtl.expressions.RTLSpecialExpression; import org.jakstab.rtl.statements.*; import org.jakstab.rtl.statements.RTLGoto.Type; import org.jakstab.ssl.Architecture; import org.jakstab.util.Logger; /** * @author Johannes Kinder */ public class LinuxStubLibrary implements StubProvider { private static final Logger logger = Logger.getLogger(LinuxStubLibrary.class); private Map<String,AbsoluteAddress> activeStubs; private int impId; private Architecture arch; private SymbolFinder symFinder; private Map<AbsoluteAddress,String> addressMap; public LinuxStubLibrary(Architecture arch) { this.arch = arch; activeStubs = new HashMap<String, AbsoluteAddress>(); addressMap = new HashMap<AbsoluteAddress, String>(); impId = 0; } private AbsoluteAddress createStubInstance(String library, String function) { boolean returns = true; if (function.equals("exit") || function.equals("__stack_chk_fail")) { returns = false; } impId += 0x10; AbsoluteAddress address = new AbsoluteAddress(STUB_BASE + impId); StatementSequence seq = new StatementSequence(); ILBuilder builder = ILBuilder.getInstance(); // start_main is special if (function.equals("__libc_start_main")) { // env builder.createPush(ExpressionFactory.nondet(arch.getAddressBitWidth()), seq); // argv builder.createPush(ExpressionFactory.nondet(arch.getAddressBitWidth()), seq); // argc builder.createPush(ExpressionFactory.nondet(arch.getAddressBitWidth()), seq); // return address (use epilogue to directly jump to halt) builder.createPush(ExpressionFactory.createNumber(Harness.epilogueAddress), seq); // address of program main is passed as arg0 to __libc_start_main // args0 is 5 dwords from esp: 3 for main's args, 1 for the return address, and 1 // for the return address from the entry point code RTLExpression arg0 = ExpressionFactory.createMemoryLocation(ExpressionFactory.createPlus( arch.stackPointer(), 5 * arch.getAddressBitWidth() / 8), 32); seq.addLast(new RTLGoto(arg0, Type.CALL)); // Complete pseudo call to main builder.linkAndStoreSequence(address, seq); return address; } // manual printf stub, helps debugging else if (function.equals("printf")) { seq.addLast(new RTLDebugPrint("Call to printf, format @ %esp =", ExpressionFactory.createSpecialExpression(RTLSpecialExpression.DBG_PRINTF, ExpressionFactory.createPlus(arch.stackPointer(), 4)))); } else if (function.equals("malloc")) { // Simple stub that nondeterministically allocates memory or returns NULL seq.addLast(new RTLAlloc(ExpressionFactory.createVariable("%eax"))); seq.addLast(new RTLVariableAssignment( ExpressionFactory.createVariable("%eax"), ExpressionFactory.createConditionalExpression( ExpressionFactory.nondet(1), ExpressionFactory.createVariable("%eax"), ExpressionFactory.createNumber(0, 32)))); seq.addLast(new RTLVariableAssignment(ExpressionFactory.createVariable("%ecx"), ExpressionFactory.nondet(32))); seq.addLast(new RTLVariableAssignment(ExpressionFactory.createVariable("%edx"), ExpressionFactory.nondet(32))); } // Any other function clobbers eax, ecx, edx by default else { seq.addLast(new RTLVariableAssignment(ExpressionFactory.createVariable("%eax"), ExpressionFactory.nondet(32))); seq.addLast(new RTLVariableAssignment(ExpressionFactory.createVariable("%ecx"), ExpressionFactory.nondet(32))); seq.addLast(new RTLVariableAssignment(ExpressionFactory.createVariable("%edx"), ExpressionFactory.nondet(32))); } // store return address in retaddr if (returns) { seq.addLast(new RTLVariableAssignment(arch.returnAddressVariable(), ExpressionFactory.createMemoryLocation(arch.stackPointer(), arch.stackPointer().getBitWidth()) )); } // pop PC int stackIncrement = arch.programCounter().getBitWidth() / 8; // adjust stack pointer builder.createSPIncrement(stackIncrement, seq); if (returns) { // Read return address from temporary variable seq.addLast(new RTLGoto(Program.getProgram().getArchitecture().returnAddressVariable(), RTLGoto.Type.RETURN)); } else { // artificial termination statement seq.addLast(new RTLHalt()); } builder.linkAndStoreSequence(address, seq); return address; } @Override public AbsoluteAddress resolveSymbol(String library, String symbol) { if (library == null) return null; AbsoluteAddress functionAddress; if (activeStubs.containsKey(symbol)) functionAddress = activeStubs.get(symbol); else { // create a new stub instance functionAddress = createStubInstance(library, symbol); activeStubs.put(symbol, functionAddress); addressMap.put(functionAddress, symbol); logger.debug("Created new stub for " + symbol + "@" + library); } return functionAddress; } @Override public SymbolFinder getSymbolFinder() { if (symFinder == null) { symFinder = new SymbolFinder() { @Override public boolean hasSymbolFor(AbsoluteAddress va) { return addressMap.containsKey(va); } @Override public String getSymbolFor(AbsoluteAddress va) { String sym = addressMap.get(va); if (sym == null) return va.toString(); else return sym; } @Override public String getSymbolFor(long address) { return getSymbolFor(new AbsoluteAddress(address)); } @Override public AbsoluteAddress getAddressFor(String symbol) { return activeStubs.get(symbol); } }; } return symFinder; } }