⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 crudcom1.cpp

📁 当前支持 16-bit, 32-bit and 64-bit 的二进制文件
💻 CPP
📖 第 1 页 / 共 2 页
字号:

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 + -