📄 module.cpp
字号:
if(!is_kernel() && !fixup_like_kernel())
assert(!"Error: Unknown fixup type encountered");
break;
}
if(debug_show) printf("\n");
return true;
}
/*****************************************************************************/
// MIPS relocation Types:
//
// Relocation types are different in DEBUG fixups
//
// Example COFF Fixup DEBUG Fixup
//
// lui ax,0x8c05 4 4
// jal 0x85049231 5 3
// addiu a0,a0,0xC610 2 5
// 0x8c049201 3 2
//
//#define IMAGE_REL_MIPS_ABSOLUTE 0
//#define IMAGE_REL_MIPS_REFHALF 01
//#define IMAGE_REL_MIPS_REFWORD 02
//#define IMAGE_REL_MIPS_JMPADDR 03
//#define IMAGE_REL_MIPS_REFHI 04
//#define IMAGE_REL_MIPS_REFLO 05
//
//
//#define IMAGE_REL_BASED_ABSOLUTE 0
//#define IMAGE_REL_BASED_HIGH 1
//#define IMAGE_REL_BASED_LOW 2
//#define IMAGE_REL_BASED_HIGHLOW 3
//#define IMAGE_REL_BASED_HIGHADJ 4
//#define IMAGE_REL_BASED_MIPS_JMPADDR 5
//
// PPC relocation Types:
// type 8 00568 81620000 lwz r11,dpCurSettings(r2) ; dpCurSettings
// type 6 00590 4bfffa71 bl ..NKDbgPrintfW ; NKDbgPrintfW (subroutine call)
//
// type 16 13EFC 3C608002 lis r3,[hia]HandleException
// type 17 13F00 386387E0 addi r3,r3,[lo]HandleException
//
// type 18 (PAIR) always immediately follows type 16
//
// #define IMAGE_REL_PPC_REFHI 0x0010
// #define IMAGE_REL_PPC_REFLO 0x0011
// #define IMAGE_REL_PPC_PAIR 0x0012
//
/*****************************************************************************/
/*****************************************************************************
fixup_nk()
in:
none
out:
boolean value indicating success
desc:
do special kernal fixups
*****************************************************************************/
bool Module::fixup_nk(){
assert(is_kernel());
#define DEBUG_IMAGE_REL_BASED_ABSOLUTE 0
#define DEBUG_IMAGE_REL_BASED_HIGH 1
#define DEBUG_IMAGE_REL_BASED_LOW 5
#define DEBUG_IMAGE_REL_BASED_HIGHLOW 2
#define DEBUG_IMAGE_REL_BASED_HIGHADJ 4
#define DEBUG_IMAGE_REL_BASED_MIPS_JMPADDR 3
#define DEBUG_IMAGE_REL_BASED_I386_HIGHLOW 20
#define DEBUG_IMAGE_REL_BASED_I386_HIGHLOW2 6
#define DEBUG_IMAGE_REL_BASED_PPC_REL24 6
#define DEBUG_IMAGE_REL_BASED_PPC_REFHI 16
#define DEBUG_IMAGE_REL_BASED_PPC_REFLO 17
#define DEBUG_IMAGE_REL_BASED_PPC_PAIR 18
DWORD rva_delta = m_vreloc - m_e32.e32_vbase;
DWORD *fixup_addr;
WORD *fixup_addr_hi;
DWORD fixup_value;
bool matched_ref_lo = false;
for(unsigned i = 0; i < m_kernel_fixup_list.size(); i++){
fixup_addr = (DWORD*)1;
if(m_e32.e32_cpu == IMAGE_FILE_MACHINE_ARM || m_e32.e32_cpu == IMAGE_FILE_MACHINE_THUMB){
switch(m_kernel_fixup_list[i].Type){
case DEBUG_IMAGE_REL_BASED_MIPS_JMPADDR:
break;
case DEBUG_IMAGE_REL_BASED_HIGH:
*(long UNALIGNED *)fixup_addr += get_rva_delta(m_kernel_fixup_list[i], rva_delta);
break;
default:
fprintf(stderr, "Error: Not doing fixup type %d\n", m_kernel_fixup_list[i].Type);
fprintf(stderr, "type %u, location %08x target %08x fixupop %08x\n",
m_kernel_fixup_list[i].Type,
m_kernel_fixup_list[i].RvaLocation,
m_kernel_fixup_list[i].RvaTarget,
*fixup_addr);
return false;
break;
}
continue;
}
switch(m_kernel_fixup_list[i].Type){
case DEBUG_IMAGE_REL_BASED_ABSOLUTE:
break;
case DEBUG_IMAGE_REL_BASED_HIGH:
fixup_addr_hi = (WORD *)fixup_addr;
matched_ref_lo = true;
break;
case DEBUG_IMAGE_REL_BASED_LOW:
case DEBUG_IMAGE_REL_BASED_PPC_REFLO:
if(matched_ref_lo){
fixup_value = (*fixup_addr_hi << 16) + *(WORD *)fixup_addr + get_rva_delta(m_kernel_fixup_list[i], rva_delta);
*fixup_addr_hi = HIWORD(fixup_value + 0x8000);
matched_ref_lo = false;
}
else
fixup_value = *(WORD *)fixup_addr + get_rva_delta(m_kernel_fixup_list[i], rva_delta);
*(WORD *)fixup_addr = LOWORD(fixup_value);
break;
case DEBUG_IMAGE_REL_BASED_I386_HIGHLOW:
break;
case DEBUG_IMAGE_REL_BASED_I386_HIGHLOW2:
if(m_e32.e32_cpu & IMAGE_FILE_MACHINE_POWERPC){
if(*fixup_addr & 0x2){
fixup_value = *fixup_addr & 0x03fffffc;
fixup_value += rva_delta;
if(fixup_value & 0xfc000000){
fprintf(stderr, "Error: fixup overflow at location %08x\n", m_kernel_fixup_list[i].RvaLocation);
assert(!"Fatal error");
}
*fixup_addr = (*fixup_addr & 0xfc000003) | (fixup_value & 0x03fffffc);
}
}
else{
fixup_value = *fixup_addr & 0xff000000;
*fixup_addr += get_rva_delta(m_kernel_fixup_list[i], rva_delta);
}
break;
case DEBUG_IMAGE_REL_BASED_HIGHLOW:
*(long UNALIGNED *)fixup_addr += get_rva_delta(m_kernel_fixup_list[i], rva_delta);
break;
case DEBUG_IMAGE_REL_BASED_PPC_REFHI:
if(m_e32.e32_cpu != IMAGE_FILE_MACHINE_POWERPC){
fixup_value = *(WORD *)fixup_addr & 0x03ff;
fixup_value = (fixup_value >> 5) | ((fixup_value & 0x1f) << 5);
fixup_value = (fixup_value << 16) | *((WORD *)fixup_addr + 1);
fixup_value += get_rva_delta(m_kernel_fixup_list[i], rva_delta) >> 2;
*((WORD *)fixup_addr + 1) = LOWORD(fixup_value);
fixup_value = HIWORD(fixup_value) & 0x3ff;
fixup_value = (fixup_value >> 5) | ((fixup_value & 0x1f) << 5);
*(WORD *)fixup_addr = LOWORD((*(WORD *)fixup_addr & 0x1c00) | fixup_value);
break;
}
/* fall through for PowerPC's */
case DEBUG_IMAGE_REL_BASED_HIGHADJ:
assert(i + 1 < m_kernel_fixup_list.size());
fixup_value = *(short UNALIGNED *)fixup_addr << 16;
fixup_value += (long)(short)LOWORD(m_kernel_fixup_list[i].RvaTarget + m_kernel_fixup_list[i + 1].RvaTarget);
fixup_value += get_rva_delta(m_kernel_fixup_list[i], rva_delta); // a REFHI has to be followed by a PAIR
i++; // increment fixup list counter
*(short UNALIGNED *)fixup_addr = HIWORD(fixup_value + 0x8000);
break;
case DEBUG_IMAGE_REL_BASED_MIPS_JMPADDR:
fixup_value = (*fixup_addr & 0x03ffffff) + (rva_delta >> 2);
*fixup_addr = (*fixup_addr & 0xfc000000) | (fixup_value & 0x3ffffff);
break;
default:
fprintf(stderr, "Error: Not doing fixup type %d\n", m_kernel_fixup_list[i].Type);
fprintf(stderr, "type %u, location %08x target %08x fixupop %08x\n",
m_kernel_fixup_list[i].Type,
m_kernel_fixup_list[i].RvaLocation,
m_kernel_fixup_list[i].RvaTarget,
*fixup_addr);
return false;
break;
}
}
return true;
}
bool Module::fixupvar(DWORD section, DWORD addr, DWORD value){
if(!is_kernel()){
fprintf(stderr, "Warning: All fixupvar elements must point to kernel addresses...ignored\n");
return false;
}
O32List::iterator o32_itr = &m_o32_list[section];
*(DWORD *)(o32_itr->data.ptr() + addr) = value;
return true;
}
/*****************************************************************************
remove_discardable_sections()
in:
none
out:
boolean value indicating success
desc:
Delete the discardable sections from the object list
*****************************************************************************/
bool Module::remove_discardable_sections(){
// remove discardable flag from resource section, we need to keep it
for(O32List::iterator o32_itr = m_o32_list.begin(); o32_itr != m_o32_list.end(); o32_itr++){
if(o32_itr->o32_rva == m_e32.e32_unit[RES].rva){
o32_itr->o32_flags &= ~IMAGE_SCN_MEM_DISCARDABLE;
break;
}
}
// remove all sections still marked as discardable
o32_itr = m_o32_list.begin();
while(o32_itr != m_o32_list.end())
if(o32_itr->is_discardable())
o32_itr = m_o32_list.erase(o32_itr);
else
o32_itr++;
// adjust the object count to reflect the current count after removal
m_e32.e32_objcnt = m_o32_list.size();
return true;
}
/*****************************************************************************
do_imports()
in:
module_list - may be needed for recursive searching
out:
boolean value indicating success
desc:
resolve import tables
*****************************************************************************/
void Module::resolve_imports(ModuleList &module_list, bool error_late_bind){
if(!m_e32.e32_unit[IMP].size){
LAST_PASS_PRINT cout << "No imports for " << m_name << endl;
return;
}
// Make imports section readonly since we're fixing it up
for(O32List::iterator o32_itr = m_o32_list.begin(); o32_itr != m_o32_list.end(); o32_itr++){
if(o32_itr->o32_rva == m_e32.e32_unit[IMP].rva || o32_itr->o32_rva == m_e32.e32_unit[EXP].rva){
o32_itr->o32_flags &= ~IMAGE_SCN_MEM_WRITE;
break;
}
}
ImpHdr *block_ptr, *block_start;
block_ptr = block_start = (ImpHdr *)rva2ptr(m_e32.e32_unit[IMP].rva);
while(block_ptr->imp_lookup){
ModuleList::iterator mod_itr;
// find dll name in module list
mod_itr = find(module_list.begin(), module_list.end(), Module((char *)rva2ptr(block_ptr->imp_dllname)));
if(mod_itr != module_list.end())
mod_itr->set_static_ref_flag();
else
if (error_late_bind){
cerr << "Error: Unable to do imports from "
<< m_name << " to " << (char *)rva2ptr(block_ptr->imp_dllname)
<< endl;
}
else{
cerr << "Warning: Unable to do imports from "
<< m_name << " to " << (char *)rva2ptr(block_ptr->imp_dllname)
<< " - will late bind" << endl;
}
DWORD *ltptr = (DWORD *)rva2ptr(block_ptr->imp_lookup);
DWORD *atptr = (DWORD *)rva2ptr(block_ptr->imp_address);
while(*ltptr){
if(mod_itr != module_list.end()){ // found it above
if(*ltptr & 0x80000000)
*atptr = mod_itr->resolve_imp_ord(module_list, *ltptr & ~0x80000000);
else{ // see if the hint string is of any help
ImpProc *impptr = (ImpProc *)rva2ptr(*ltptr);
*atptr = mod_itr->resolve_imp_hint_str(module_list, impptr->ip_hint, string((char *)impptr->ip_name));
}
if(!*atptr){
cerr << "Error: Fatal import error in " << m_name << endl;
s_import_success_status = false;
}
} else // it's now statically loaded, forget about it
*atptr = 0;
ltptr++;
atptr++;
}
block_ptr++;
}
}
/*****************************************************************************
compress()
in:
bool comp - global compression flag
out:
boolean value indicating success
desc:
(pretty self explanatory)
******************************************************************************/
bool Module::compress(bool comp){
/* WARNING TO READERS
* you don't want to mess with any of the logic
* in here if you don't absolutely have to :)
*/
// no compression wanted or zero length
if(!comp || !m_file_size){
m_file_attributes &= ~FILE_ATTRIBUTE_COMPRESSED;
// truncate the kernel writable sections even if compression is off
if(is_kernel() || fixup_like_kernel())
for(O32List::iterator o32_itr = m_o32_list.begin(); o32_itr != m_o32_list.end(); o32_itr++)
if(o32_itr->is_writable())
truncate_o32(*o32_itr);
return true;
}
for(O32List::iterator o32_itr = m_o32_list.begin(); o32_itr != m_o32_list.end(); o32_itr++){
// I am REALLY sorry for this conditional!
if(m_e32.e32_unit[IMP].rva == o32_itr->o32_rva || m_e32.e32_unit[EXP].rva == o32_itr->o32_rva){
if(m_file_attributes & FILE_ATTRIBUTE_COMPRESSED)
compress_o32(*o32_itr);
}
else if(is_kernel() || fixup_like_kernel()){
if(o32_itr->is_writable())
truncate_o32(*o32_itr); // don't compress, only truncate the kernel writable sections
}
else if(m_file_attributes & FILE_ATTRIBUTE_COMPRESSED ||
o32_itr->is_writable() ||
o32_itr->name() == ".pdata" ||
(o32_itr->name() == ".rsrc" && compress_resources())
)
compress_o32(*o32_itr);
}
return true;
}
/*****************************************************************************
*****************************************************************************/
void Module::print_header(){
static char *suppress = (suppress = getenv("ri_suppress_info")) ? strstr(suppress, "move") : NULL;
if(suppress) return;
LAST_PASS_PRINT printf("\nMODULES Section\n");
LAST_PASS_PRINT printf("Module Section Start Length psize vsize Filler\n");
LAST_PASS_PRINT printf("---------------------- -------- --------- ------- ------- ------- ------\n");
}
/*****************************************************************************
move_readonly_sections()
in:
reserve_list - reserved memory list
DWORD next_avail - next available stor
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -