📄 newcoff.cpp
字号:
++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 = ⌖
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 + -