#include "loadimage.hh"
#include "sleigh.hh"
#include "emulate.hh"
#include <iostream>
static uint1 myprog[] = {
0x8d, 0x4c, 0x24, 0x04, 0x83, 0xe4, 0xf0, 0xff, 0x71, 0xfc, 0x55,
0x89, 0xe5, 0x51, 0x81, 0xec, 0xb4, 0x01, 0x00, 0x00, 0xc7, 0x45, 0xf4,
0x00, 0x00, 0x00, 0x00, 0xeb, 0x12, 0x8b, 0x45, 0xf4, 0xc7, 0x84,
0x85, 0x64, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x83, 0x45, 0xf4,
0x01, 0x83, 0x7d, 0xf4, 0x63, 0x7e, 0xe8, 0xc7, 0x45, 0xf4, 0x02,
0x00, 0x00, 0x00, 0xeb, 0x28, 0x8b, 0x45, 0xf4, 0x01, 0xc0, 0x89, 0x45,
0xf8, 0xeb, 0x14, 0x8b, 0x45, 0xf8, 0xc7, 0x84, 0x85, 0x64, 0xfe,
0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x8b, 0x45, 0xf4, 0x01, 0x45, 0xf8,
0x83, 0x7d, 0xf8, 0x63, 0x7e, 0xe6, 0x83, 0x45, 0xf4, 0x01, 0x83,
0x7d, 0xf4, 0x31, 0x7e, 0xd2, 0xc7, 0x04, 0x24, 0x40, 0x85, 0x04, 0x08,
0xe8, 0x9c, 0xfe, 0xff, 0xff, 0xc7, 0x45, 0xf4, 0x02, 0x00, 0x00,
0x00, 0xeb, 0x25, 0x8b, 0x45, 0xf4, 0x8b, 0x84, 0x85, 0x64, 0xfe, 0xff,
0xff, 0x85, 0xc0, 0x75, 0x13, 0x8b, 0x45, 0xf4, 0x89, 0x44, 0x24,
0x04, 0xc7, 0x04, 0x24, 0x47, 0x85, 0x04, 0x08, 0xe8, 0x62, 0xfe, 0xff,
0xff, 0x83, 0x45, 0xf4, 0x01, 0x83, 0x7d, 0xf4, 0x63, 0x7e, 0xd5,
0x81, 0xc4, 0xb4, 0x01, 0x00, 0x00, 0x59, 0x5d, 0x8d, 0x61, 0xfc, 0xc3,
0x90, 0x90, 0x90, 0x90, 0x55, 0x89, 0xe5, 0x5d, 0xc3, 0x8d, 0x74,
0x26, 0x00, 0x8d, 0xbc, 0x27, 0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xe5,
0x57, 0x56, 0x53, 0xe8, 0x5e, 0x00, 0x00, 0x00, 0x81, 0xc3, 0xa5,
0x11, 0x00, 0x00, 0x83, 0xec, 0x1c, 0xe8, 0xd7, 0xfd, 0xff, 0xff, 0x8d,
0x83, 0x20, 0xff, 0xff, 0xff, 0x89, 0x45, 0xf0, 0x8d, 0x83, 0x20,
0xff, 0xff, 0xff, 0x29, 0x45, 0xf0, 0xc1, 0x7d, 0xf0, 0x02, 0x8b, 0x55,
0xf0, 0x85, 0xd2, 0x74, 0x2b, 0x31, 0xff, 0x89, 0xc6, 0x8d, 0xb6,
0x00, 0x00, 0x00, 0x00, 0x8b, 0x45, 0x10, 0x83, 0xc7, 0x01, 0x89, 0x44,
0x24, 0x08, 0x8b, 0x45, 0x0c, 0x89, 0x44, 0x24, 0x04, 0x8b, 0x45,
0x08, 0x89, 0x04, 0x24, 0xff, 0x16, 0x83, 0xc6, 0x04, 0x39, 0x7d, 0xf0,
0x75, 0xdf, 0x83, 0xc4, 0x1c, 0x5b, 0x5e, 0x5f, 0x5d, 0xc3, 0x8b,
0x1c, 0x24, 0xc3, 0x90, 0x90, 0x90, 0x55, 0x89, 0xe5, 0x53, 0xbb, 0x50,
0x95, 0x04, 0x08, 0x83, 0xec, 0x04, 0xa1, 0x50, 0x95, 0x04, 0x08,
0x83, 0xf8, 0xff, 0x74, 0x0c, 0x83, 0xeb, 0x04, 0xff, 0xd0, 0x8b, 0x03,
0x83, 0xf8, 0xff, 0x75, 0xf4, 0x83, 0xc4, 0x04, 0x5b, 0x5d, 0xc3,
0x55, 0x89, 0xe5, 0x53, 0x83, 0xec, 0x04, 0xe8, 0x00, 0x00, 0x00, 0x00,
0x5b, 0x81, 0xc3, 0x0c, 0x11, 0x00, 0x00, 0xe8, 0x00, 0xfe, 0xff,
0xff, 0x59, 0x5b, 0xc9, 0xc3, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x72, 0x69, 0x6d, 0x65, 0x73,
0x00, 0x25, 0x64, 0x0a, 0x00, 0x00
};
class MyLoadImage : public LoadImage {
uintb baseaddr;
int4 length;
uint1 *data;
public:
MyLoadImage(uintb ad,uint1 *ptr,int4 sz) : LoadImage("nofile") { baseaddr = ad; data = ptr; length = sz; }
virtual void loadFill(uint1 *ptr,int4 size,const Address &addr);
virtual string getArchType(void) const { return "myload"; }
virtual void adjustVma(long adjust) { }
};
void MyLoadImage::loadFill(uint1 *ptr,int4 size,const Address &addr)
{
uintb start = addr.getOffset();
uintb max = baseaddr + (length-1);
for(int4 i=0;i<size;++i) { uintb curoff = start + i; if ((curoff < baseaddr)||(curoff>max)) { ptr[i] = 0; continue;
}
uintb diff = curoff - baseaddr;
ptr[i] = data[(int4)diff]; }
}
class AssemblyRaw : public AssemblyEmit {
public:
virtual void dump(const Address &addr,const string &mnem,const string &body) {
addr.printRaw(cout);
cout << ": " << mnem << ' ' << body << endl;
}
};
static void dumpAssembly(Translate &trans)
{ AssemblyRaw assememit; int4 length;
Address addr(trans.getDefaultCodeSpace(),0x80483b4); Address lastaddr(trans.getDefaultCodeSpace(),0x804846c);
while(addr < lastaddr) {
length = trans.printAssembly(assememit,addr);
addr = addr + length;
}
}
class PcodeRawOut : public PcodeEmit {
public:
virtual void dump(const Address &addr,OpCode opc,VarnodeData *outvar,VarnodeData *vars,int4 isize);
};
static void print_vardata(ostream &s,VarnodeData &data)
{
s << '(' << data.space->getName() << ',';
data.space->printOffset(s,data.offset);
s << ',' << dec << data.size << ')';
}
void PcodeRawOut::dump(const Address &addr,OpCode opc,VarnodeData *outvar,VarnodeData *vars,int4 isize)
{
if (outvar != (VarnodeData *)0) {
print_vardata(cout,*outvar);
cout << " = ";
}
cout << get_opname(opc);
for(int4 i=0;i<isize;++i) {
cout << ' ';
print_vardata(cout,vars[i]);
}
cout << endl;
}
static void dumpPcode(Translate &trans)
{ PcodeRawOut emit; AssemblyRaw assememit; int4 length;
Address addr(trans.getDefaultCodeSpace(),0x80483b4); Address lastaddr(trans.getDefaultCodeSpace(),0x80483bf);
while(addr < lastaddr) {
cout << "--- ";
trans.printAssembly(assememit,addr);
length = trans.oneInstruction(emit,addr); addr = addr + length; }
}
class PutsCallBack : public BreakCallBack {
public:
virtual bool addressCallback(const Address &addr);
};
bool PutsCallBack::addressCallback(const Address &addr)
{
MemoryState *mem = static_cast<EmulateMemory *>(emulate)->getMemoryState();
uint1 buffer[256];
uint4 esp = mem->getValue("ESP");
AddrSpace *ram = mem->getTranslate()->getSpaceByName("ram");
uint4 param1 = mem->getValue(ram,esp+4,4);
mem->getChunk(buffer,ram,param1,255);
cout << (char *)&buffer << endl;
uint4 returnaddr = mem->getValue(ram,esp,4);
mem->setValue("ESP",esp+8);
emulate->setExecuteAddress(Address(ram,returnaddr));
return true; }
class PrintfCallBack : public BreakCallBack {
public:
virtual bool addressCallback(const Address &addr);
};
bool PrintfCallBack::addressCallback(const Address &addr)
{
MemoryState *mem = static_cast<EmulateMemory *>(emulate)->getMemoryState();
AddrSpace *ram = mem->getTranslate()->getSpaceByName("ram");
uint4 esp = mem->getValue("ESP");
uint4 param2 = mem->getValue(ram,esp+8,4);
cout << (int4)param2 << endl;
uint4 returnaddr = mem->getValue(ram,esp,4);
mem->setValue("ESP",esp+12);
emulate->setExecuteAddress(Address(ram,returnaddr));
return true;
}
class TerminateCallBack : public BreakCallBack {
public:
virtual bool addressCallback(const Address &addr);
};
bool TerminateCallBack::addressCallback(const Address &addr)
{
emulate->setHalt(true);
return true;
}
static void doEmulation(Translate &trans,LoadImage &loader)
{
MemoryImage loadmemory(trans.getDefaultCodeSpace(),8,4096,&loader);
MemoryPageOverlay ramstate(trans.getDefaultCodeSpace(),8,4096,&loadmemory);
MemoryHashOverlay registerstate(trans.getSpaceByName("register"),8,4096,4096,(MemoryBank *)0);
MemoryHashOverlay tmpstate(trans.getUniqueSpace(),8,4096,4096,(MemoryBank *)0);
MemoryState memstate(&trans); memstate.setMemoryBank(&ramstate);
memstate.setMemoryBank(®isterstate);
memstate.setMemoryBank(&tmpstate);
BreakTableCallBack breaktable(&trans); EmulatePcodeCache emulater(&trans,&memstate,&breaktable);
memstate.setValue("ESP",0xbffffffc);
emulater.setExecuteAddress(Address(trans.getDefaultCodeSpace(),0x80483b4));
PutsCallBack putscallback;
PrintfCallBack printfcallback;
TerminateCallBack terminatecallback;
breaktable.registerAddressCallback(Address(trans.getDefaultCodeSpace(),0x80482c8),&putscallback);
breaktable.registerAddressCallback(Address(trans.getDefaultCodeSpace(),0x80482b8),&printfcallback);
breaktable.registerAddressCallback(Address(trans.getDefaultCodeSpace(),0x804846b),&terminatecallback);
emulater.setHalt(false);
do {
emulater.executeInstruction();
} while(!emulater.getHalt());
}
int main(int argc,char **argv)
{
if (argc != 2) {
cerr << "USAGE: " << argv[0] << " disassemble" << endl;
cerr << " " << argv[0] << " pcode" << endl;
cerr << " " << argv[0] << " emulate" << endl;
return 2;
}
string action(argv[1]);
MyLoadImage loader(0x80483b4,myprog,408);
ContextInternal context;
string sleighfilename = "specfiles/x86.sla";
Sleigh trans(&loader,&context);
DocumentStorage docstorage;
Element *sleighroot = docstorage.openDocument(sleighfilename)->getRoot();
docstorage.registerTag(sleighroot);
trans.initialize(docstorage);
context.setVariableDefault("addrsize",1); context.setVariableDefault("opsize",1);
if (action == "disassemble")
dumpAssembly(trans);
else if (action == "pcode")
dumpPcode(trans);
else if (action == "emulate")
doEmulation(trans,loader);
else
cerr << "Unknown action: "+action << endl;
}