📄 crudcom1.cpp
字号:
static U1 *read_file(const char *filename, U4 *size)
{
U1 *data;
FILE *f = fopen(filename, "rb");
if(f == NULL)
return NULL;
if(feof(f))
{
fclose(f);
return NULL; // no data
}
fseek(f, -1, SEEK_END);
*size = 1 + ftell(f);
data = new U1 [*size];
rewind(f);
if(fread(data, *size, 1, f) != 1)
{
delete [] data;
fclose(f);
return NULL; // unable to read
}
fclose(f);
return data;
}
// Once done parsing, this disassembles everything, from start to finish.
class disassembler_t
{
private:
std::ostream &of;
parser_t &parser;
memory_t &memory;
//std::set<U8> targets;
public:
disassembler_t(parser_t &parser_tag, memory_t &memory_tag, std::ostream &of_t) :
of(of_t),
parser(parser_tag),
memory(memory_tag)
{
}
~disassembler_t()
{
of << std::endl;
}
void go()
{
icode_t icode;
decode_state_t s;
s.icode = &icode;
s.dsz = parser.dsz;
int x;
char line[1024];
NasmWriter nasmdis;
U8 offset, target;
of << std::hex << "org 0x" << memory.image_base << std::dec;
for(U8 i = 0; i < memory.image_size; )
{
again:
if(memory.meta[i].entry == 1)
{
of << std::endl;
of << "; Calls:";
for(std::set<U8>::iterator j = parser.xgraph[i].calls.begin(); j != parser.xgraph[i].calls.end(); ++j)
of << " " << std::hex << "fn_" << (U4)((*j + memory.image_base) & memory.rip_mask) << std::dec;
of << std::endl;
if(memory.meta[i].branch == 1)
of << "; There are other branches here too." << std::endl;
if(!parser.xgraph[i].decompile)
of << "; This function can not be decompiled." << std::endl;
of << "fn_" << std::hex << (U4)((i + memory.image_base) & memory.rip_mask) << std::dec << ":" << std::endl;
}
else
if(memory.meta[i].branch == 1)
{
of << "loc_" << std::hex << (U4)((i + memory.image_base) & memory.rip_mask) << std::dec << ":" << std::endl;
}
if(memory.meta[i].size != 0)
{
bool overlaps = false;
for(U8 j = 1; j < memory.meta[i].size; ++j)
if(memory.meta[i + j].entry || memory.meta[i + j].branch)
{
overlaps = true;
break;
}
if(overlaps)
{
of << "loc_" << std::hex << (U4)((i + memory.image_base) & memory.rip_mask) << ": db 0x" << (U2)memory.image[i] << std::dec;
of << " ; overlapping instruction detected.";
of << std::endl;
++i;
goto again;
}
s.insn = memory.image + i;
s.end = s.insn + 15;
x = decode(s);
if(x != 0) // this will happen for invalid opcodes...
{
of << std::endl;
for(;;)
{
of << "loc_" << std::hex << (U4)((i + memory.image_base) & memory.rip_mask) << ": db 0x" << (U2)memory.image[i] << std::dec << std::endl;
++i;
if(i == memory.image_size)
return;
if(memory.meta[i].size != 0)
goto again;
}
}
line[0] = '\0';
const char *imm = NULL;
const char *disp = NULL;
char buf[1024];
bool star = false;
//---
// look at instruciton here.
target = i;
switch(encodings[s.encoding].insn)
{
case insn__ret:
case insn__retf:
case insn__retfnum:
case insn__retnum:
case insn__iret:
break;
case insn_jmp:
case insn__jcc:
case insn__jrcxz:
case insn__loopnz:
case insn__loopz:
case insn__loop:
case insn_call:
// fixme: add 64-bit support here. Also do something about memory.cs_base.
offset = (U8)s.icode->imm + (U8)target + (U8)s.size + (U8)memory.image_base;
offset &= memory.rip_mask;
if(offset < (U8)memory.image_base)
throw std::runtime_error("jmp above image base");
target = offset - (U8)memory.image_base;
if(memory.meta[target].entry)
{
std::sprintf(buf, "fn_%x", offset);
imm = buf;
}
else
if(memory.meta[target].branch)
{
std::sprintf(buf, "loc_%x", offset);
imm = buf;
}
break;
break;
case insn__calli:
case insn__callfd:
case insn__callfi:
case insn__jmpfd:
case insn__jmpfi:
case insn__jmpi:
star = true;
break;
}
//---
nasmdis.disasm(line, &s, imm, disp, i + (U8)s.size + memory.image_base);
of << " " << line;
if(star)
of << " ; (*) not followed";
of << std::endl;
i += memory.meta[i].size;
}
else
{
int linecount = -1;
bool yet = false;
do
{
if(linecount == -1 || linecount == 15)
{
linecount = 0;
of << std::endl;
of << "loc_" << std::hex << (U4)((i + memory.image_base) & memory.rip_mask) << ": db";
yet = false;
}
else
++linecount;
if(yet)
of << ",";
of << " 0x" << std::hex << (U2)memory.image[i] << std::dec;
yet = true;
++i;
} while(i != memory.image_size && memory.meta[i].size == 0);
of << std::endl;
if(i != memory.image_size)
{
if(memory.meta[i].entry == 0)
{
of << std::endl;
}
}
}
}
}
};
#if 0
std::set<U8> test_loc;
void test_dfs(parser_t &parser, U8 target, memory_t &memory)
{
if(test_loc.find(target) != test_loc.end())
return; // been here already
test_loc.insert(target);
// call all children.
for(std::set<U8>::iterator i = parser.xgraph[target].calls.begin(); i != parser.xgraph[target].calls.end(); ++i)
test_dfs(parser, *i, memory);
std::printf("%08x", (U4)((target + memory.image_base) & memory.rip_mask));
if(!parser.xgraph[target].decompile)
std::printf("*");
std::printf(":");
for(std::set<U8>::iterator i = parser.xgraph[target].calls.begin(); i != parser.xgraph[target].calls.end(); ++i)
std::printf(" %08x", (U4)((*i + memory.image_base) & memory.rip_mask));
std::printf("\n");
}
#endif
void help()
{
std::cout << "Copyright (C) 2008 Willow Schlanger" << std::endl;
std::cout << "Intelligent disassembler for x86 and x86-64 binary image files" << std::endl;
std::cout << std::endl;
std::cout << "usage: crudcom1 filename bits origin [entrypoint]" << std::endl;
std::cout << "bits must be one of: 16, 32, 64 (64 bit mode needs some work!)" << std::endl;
std::cout << "the entrypoint is an offset in the image, and defaults to 0." << std::endl;
}
int main(int argc, char **argv)
{
std::string filename;
int dsz = argsize_16;
if(argc < 4)
{
help();
return 1;
}
filename = argv[1];
std::string bits = argv[2];
if(bits == "16")
dsz = argsize_16;
else
if(bits == "32")
dsz = argsize_32;
else
if(bits == "64")
dsz = argsize_64;
else
{
help();
std::cout << std::endl << "error: bad number of bits -- must be exactly one of these: 16, 32, 64" << std::endl;
return 1;
}
char *endp;
U4 origin = strtol(argv[3], &endp, 0);
if(*endp != '\0')
{
help();
std::cout << std::endl << "error: bad origin given - use 0x for hex numbers" << std::endl;
return 1;
}
U4 myentry = 0;
if(argc >= 5)
{
myentry = strtol(argv[4], &endp, 0);
if(*endp != '\0')
{
help();
std::cout << std::endl << "error: bad entrypoint given - use 0x for hex numbers" << std::endl;
return 1;
}
}
U4 size_tag;
U1 *image = read_file(filename.c_str(), &size_tag);
if(image == NULL)
{
std::cout << filename << ": can\'t open and read, or file has a size of 0 bytes\n" << std::endl;
return 1;
}
U8 size = size_tag;
U8 entry = myentry;
memory_t memory;
if(dsz == argsize_16)
memory.rip_mask = 0xffff;
else
if(dsz == argsize_32)
memory.rip_mask = 0xffffffff;
else
memory.rip_mask = (U8)(-1ll);
memory.image = image;
memory.image_size = size;
memory.image_base = origin;
memory.cs_base = 0;
memory.meta = new metadata_t [size];
try
{
parser_t parser(memory, dsz);
for(;;)
{
parser.reset();
parser.add_entrypoint(entry); // call for each entrypoint
bool again = parser.parse();
if(!again)
break;
}
// decompile here. clear 'decompile' flag for a function if we were unable
// to decompile it.
//printf("Call graph:\n");
//test_loc.clear();
//test_dfs(parser, entry, memory); // call for each entrypoint
disassembler_t disasm(parser, memory, std::cout);
disasm.go(); // call for each entrypoint
}
catch(std::runtime_error err)
{
std::cout << "Error: " << err.what() << std::endl;
}
delete [] memory.meta;
delete [] image;
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -