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

📄 newcoff.cpp

📁 当前支持 16-bit, 32-bit and 64-bit 的二进制文件
💻 CPP
📖 第 1 页 / 共 2 页
字号:
						++ix;
					}
					assert(ix != t.end());	// no '.' in symbol!
					std::string fwd_module = make_uppercase(std::string(t.begin(), ix)) + ".DLL";
					++ix;
					std::string fwd_procedure = std::string(ix, t.end());	// may be e.g. #xx
					assert(!fwd_procedure.empty());

					std::string u = do_resolve_symbol(finder, fwd_module, fwd_procedure, s);
					if(u.empty())
					{
						std::cerr << " (can't resolve " << make_uppercase(remove_extension(dll_name)) + "." + i->second << ")" << std::endl;
					}
					target.forwarders[i->second] = u;

//std::cerr << make_uppercase(remove_extension(dll_name)) + "." + i->second << " -> " << u << std::endl;

					continue;
				}
	
				// (i->second, offset) is an export.
				target.exports[i->second] = offset;
				target.names[offset].export_name = i->second;
				target.ordinals[i->first] = make_uppercase(remove_extension(dll_name)) + "." + i->second;
			}
		}
		//--- end process exports ---
		
		delete [] bin;
	}

	return ptarget;
}

void load_coff(std::string path, std::string file, loaded_target_t &target, U1 **loaded, dll_finder_t &finder);

std::string resolve_symbol(dll_finder_t &finder, std::string dll_name, std::string procedure, coff_state_t &s)
{
	loaded_target_t *target = load_dll(s, finder, dll_name);
	if(target == NULL)
	{
		return "";
	}
	if(target->forwarders.find(procedure) != target->forwarders.end())
		return target->forwarders[procedure];
	// procedure is not a forwarder -- just return it!
	return make_uppercase(remove_extension(dll_name)) + "." + procedure;
}

std::string resolve_symbol(dll_finder_t &finder, std::string dll_name, int ordinal, coff_state_t &s)
{
	loaded_target_t *target = load_dll(s, finder, dll_name);
	if(target == NULL)
		return "";
	//std::string prefix = remove_extension(make_uppercase(dll_name)) + ".";
	std::string suffix = target->ordinals[ordinal];
	return /*prefix + */ suffix;
}

// This loads 'file'. Upon return, taret.size will be nonzero, unless an error
// occurred.
void load_coff(std::string path, std::string file, loaded_target_t &target, U1 **loaded, dll_finder_t &finder)
{
	coff_state_t s;
	s.root = make_uppercase(file);	// always add .DLL when searching for a module.
	s.primary = &target;

	if(loaded != NULL)
		*loaded = NULL;
	target.clear();
	U1 *bin = load_target(path, file, target);
	if(bin == NULL)
		return;
	
	coff_t *coff = (coff_t *)(bin + get_coff32(bin, target.size));
	if(coff == NULL)
	{
		delete [] bin;
		target.clear();
		return;
	}

	// Go thru all EXPORTS. If it is NOT a forwarder, add it to our list.
	// Then go thru all IMPORTS. Print ten dots for the lot of them. For
	// each import, add it to our list -- but look up the name if it's an
	// ordinal, and follow forwarders.
	
	target.exports[".Start"] = target.start;
	target.names[target.start].export_name = ".Start";

	// --- process sections ---
	coff_section_header_t *sections = (coff_section_header_t *)((U1 *)(coff) +
		sizeof(coff_t) - sizeof(coff_data_dir_t) +
		sizeof(coff_data_dir_t) * coff->number_data_dirs
	);
	for(U4 i = 0; i < coff->number_of_sections; ++i)
	{
		target.section_offset.push_back(sections[i].virtual_address);
	}
	// --- end sections ---
	
	// --- process exports ---
	if(coff->number_data_dirs == 0 || coff->data_dirs[0].rva == 0 || coff->data_dirs[0].size == 0)
		;	// no exports
	else
	{
		std::map<U4, std::string> xexports;
		edt_t *exports = (edt_t *)(bin + coff->data_dirs[0].rva);
		U4 *functions = (U4 *)(bin + exports->rva_functions);
		U4 *names = (U4 *)(bin + exports->rva_names);
		U2 *ordinals = (U2 *)(bin + exports->rva_ordinals);

		for(U4 x = 0; x < exports->number_of_functions; ++x)
		{
			U4 y = x + exports->ordinals_base;
			xexports[y] = std::string("#") + int_to_string(y);
		}
		for(U4 x = 0; x < exports->number_of_names; ++x)
		{
			xexports[ordinals[x] + exports->ordinals_base] = std::string((char *)(bin + names[x]));
		}
		
		using namespace std;
		//cout << "Exports:" << endl;
		std::string newname;
		for(std::map<U4, std::string>::iterator i = xexports.begin(); i != xexports.end(); ++i)
		{
			U8 offset = functions[i->first - exports->ordinals_base];
			
			if(offset == 0)
			{
				// We are not concerned with this!
				continue;
			}

			//std::cout << i->second << " " << std::hex << offset << std::dec << std::endl;

			// check for forwarders.
			if(offset >= coff->data_dirs[0].rva && offset < coff->data_dirs[0].rva + coff->data_dirs[0].size)
			{
				// Is a forwarder. The root DLL might forward you to X.DLL which might forward back to the
				// root. What if the root then forwards back out again?
				target.forwarders[i->second] = "BAD.CycleDetected";
				continue;
			}

			// (i->second, offset) is an export.
			target.exports[i->second] = offset;
			target.names[offset].export_name = i->second;
			
			target.ordinals[i->first] = make_uppercase(remove_extension(file)) + "." + i->second;
		}
	}
	// --- end process exports ---
	
	// --- process imports ---
	if(coff->number_data_dirs < 2 || coff->data_dirs[1].rva == 0 || coff->data_dirs[1].size == 0)
		;	// no imports
	else
	{
		iat_t *imports = (iat_t *)(bin + coff->data_dirs[1].rva);
		while(imports->name_rva != 0)
		{
			std::string dll_name = make_uppercase(std::string((const char *)(bin + imports->name_rva)));
			
			U4 *x = (U4 *)(bin + imports->import_lookup_table_rva);
			U4 y = 0;
			while(*x != 0)
			{
				std::string procname;
			
				if(*x < 0x80000000)
				{
					std::string t = std::string((char *)(bin) + *x + 2);
					procname = resolve_symbol(finder, dll_name, t, s);
				}
				else
				{
					U4 z = *x & 0x7fffffff;
					procname = resolve_symbol(finder, dll_name, z, s);
//std::cerr << procname << std::endl;
				}
				
				if(procname.empty())
				{
					std::cerr << " error" << std::endl;
					std::cerr << "Unable to resolve a symbol in '" << dll_name << "'." << std::endl;
					std::cerr << "Symbol we want is: " << remove_extension(make_uppercase(dll_name)) << ".";
					if(*x < 0x80000000)
					{
						std::cerr << std::string((char *)(bin) + *x + 2);
					}
					else
					{
						U4 z = *x & 0x7fffffff;
						std::cerr << z;
					}
					std::cerr << std::endl;
					std::cerr << "If necessary, copy that file to the current directory and try again." << std::endl;
					delete [] bin;
					target.clear();
					return;
				}
				
				//std::cout << " " << procname << " " << std::hex << (imports->iat_rva + y + module.image.base) << std::dec << std::endl;
				U4 procaddr = imports->iat_rva + y;
				
				// do something here with (procname, procaddr)
				target.imports.insert(procname);
				target.names[procaddr].import_name = procname;
				
				++x;
				y += 4;
			}
			
			++imports;
		}
	}
	// --- end imports ---
	
	// --- process delayed imports ---
	if(coff->number_data_dirs < 14 || coff->data_dirs[13].rva == 0 || coff->data_dirs[13].size == 0)
		;//cout << "No import dlls" << endl;
	else
	{
		struct PACKED(delay_imp_t)
		{
			U4 x1;
			U4 dll_name;
			U4 hmod;
			U4 iat;
			U4 xint;
			U4 biat;
			U4 uint;
			U4 date;
		};
		
		delay_imp_t *delay_imp = (delay_imp_t *)(bin + coff->data_dirs[13].rva);
		
		//iat_t *imports = (iat_t *)(bin + delay_imp->x);
		while(delay_imp->dll_name != 0)
		{
			std::string dll_name = make_lowercase(std::string((const char *)(bin + delay_imp->dll_name)));
			U4 *x = (U4 *)(bin + delay_imp->xint);
			U4 y = 0;
			while(*x != 0)
			{
				std::string procname;
				/*
				for(std::string::iterator i = dll_name.begin(); i != dll_name.end(); ++i)
				{
					if(*i == '.')
						break;
					procname += *i;
				}
				*/
				//procname = dll_name;
				//procname += ".";
				if(*x < 0x80000000)
				{
					std::string t = std::string((char *)(bin) + *x + 2);
					//std::cout << " " << s << std::endl;
					//procname += s;
					procname = resolve_symbol(finder, dll_name, t, s);
				}
				else
				{
					U4 z = *x & 0x7fffffff;
					procname = resolve_symbol(finder, dll_name, z, s);
				}
				
				U4 procaddr = delay_imp->iat + y;
				//std::cout << " " << procname << " " << std::hex << (delay_imp->iat + y + module.image.base) << std::dec << std::endl;
				//std::cout << std::hex << procaddr << std::dec << " - " << procname << std::endl;
				// do something here with (procname, procaddr)
				target.imports.insert(procname);
				target.names[procaddr].import_name = procname;
//std::cerr << procname << " is at " << procaddr << std::endl;

				++x;
				y += 4;
			}
			
			++delay_imp;
		}
	}
	// --- end process delayed imports ---
		
	// --- process relocations ---
	if(coff->number_data_dirs < 6 || coff->data_dirs[5].rva == 0 || coff->data_dirs[5].size == 0)
		;
	else
	{
		U4 z = coff->data_dirs[5].size;
		U4 y = 0;
		while(y < z)
		{
			U4 page_rva = ((U4 *)(bin + coff->data_dirs[5].rva + y))[0];
			U4 num_relocs = ((U4 *)(bin + coff->data_dirs[5].rva + y))[1] / 2 - 4;
//std::cerr << "Image contains " << num_relocs << " relocations." << std::endl;
			for(U4 u = 0; u < num_relocs; ++u)
			{
				U4 x = ((U2 *)(bin + coff->data_dirs[5].rva + y + 8))[u];
				U4 type = (x >> 12) & 0xf;
				U4 offset = (x & 0xfff) + page_rva;
				
				if(type == 3 && offset + 4 - 1 < target.size)
				{
					//U4 w = *(U4 *)(bin + offset);
					U4 w = offset;
					//if(w >= target.base)
					{
						//w -= module.image.base;
						if(w < target.size)
						{
//std::cerr << "- Relocation here: " << std::hex << w << std::dec << std::endl;
							// Make 'w' a relocation.
							target.relocations.insert(w);
						}
					}
				}
			}
			y += num_relocs * 2 + 8;
		}
	}
	// --- end process relocations ---
	
	if(loaded == NULL)
		delete [] bin;
	else
		*loaded = bin;
}

void load_coff(dll_finder_t &finder, std::string name, loaded_target_t &target, U1 **loaded)
{
	if(loaded != NULL)
		*loaded = NULL;
	target.clear();
	if(name.empty())
		return;		// nothing to do!
	std::string s = finder.find(name);
	if(s.empty())
		return;		// can't find
	// 's' is full path to the requested file.
	std::string path, file;
	split_filename(s, path, file);
	if(file.empty())
		return;
	// path may be empty if the file is in the current directory.
	load_coff(path, file, target, loaded, finder);
}


void do_get_pdb_filename(std::string modulename, std::string &mod, std::string &ext)
{
	mod.clear();
	ext.clear();
	if(modulename.empty())
		return;
	std::string::iterator i = modulename.end();
	while(i != modulename.begin())
	{
		--i;
		if(*i == '.')
			break;
	}
	if(*i != '.' || i == modulename.end())
		return;
	mod = std::string(modulename.begin(), i);
	++i;
	ext = make_lowercase(std::string(i, modulename.end()));
}

std::string get_pdb_filename(std::string modulename, std::string dbgdir)
{
	std::string mod, ext;
	do_get_pdb_filename(modulename, mod, ext);
	if(mod.empty())
		return "";
	std::string s;
	dbgdir = fixslash(dbgdir);
	
	// first look in the user-supplied path (and the current directory).
	dll_finder_t myfinder1(dbgdir);
	s = myfinder1.find(mod + ".pdb");
	if(!s.empty())
		return s;
	
	// now try [dbgdir]/ext/xx.pdb
	dll_finder_t myfinder2(dbgdir + "ext/");
	s = myfinder2.find(mod + ".pdb");
	return s;
}

void load_target(dll_finder_t &finder, std::string name, loaded_target_t &target, U1 **loaded, std::string dbgdir)
{
	load_coff(finder, name, target, loaded);
	std::string pdbfile = get_pdb_filename(name, dbgdir);
	if(!pdbfile.empty())
	{
		pdb_t pdb;
		read_pdb(pdbfile, pdb);
		if(!pdb.empty())
		{
			// process 'sym' stream.
			int stream = get_stream_sym(pdb);
			if(stream != -1)
			{
				std::vector<U1> &v = pdb[stream];
				U1 *data = &v[0];
				U2 type, len;
				symbol_110e_t *symbol;
				std::string name;
				UINT y;
				U8 addr;
				for(UINT x = 0; x < v.size();)
				{
					len = *(U2 *)(data + x);
					type = *(U2 *)(data + x + 2);
					
					if(type == 0x110e)
					{
						symbol = (symbol_110e_t *)(data + x + 4);
						name.clear();
						for(y = 14; y < (2 + len); ++y)
						{
							if(symbol->name[y - 14] == '\0')
								break;
							name += symbol->name[y - 14];
						}
						addr = target.section_offset[symbol->section - 1] + symbol->offset;
						target.names[addr].user_name = name;
//std::cout << "[" << name << "]" << " " << std::hex << symbol->unknown << " " << target.section_offset[symbol->section - 1] << " + " << symbol->offset << " = " << addr << std::dec << " - " << target.names[addr].user_name << std::endl;
					}
					
					x += (U4)(len) + 2;
				}
			}
		}
	}
}

}	// namespace ceres

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -