@@ -513,39 +513,75 @@ impl PE64 {
513513 }
514514
515515 pub fn iat_binding ( & mut self , emu : & mut emu:: Emu ) {
516- // TODO: refactor this, instead of patching the raw and the loading it, do the iat_binding
517- // after the loading, in this way its possible to use virtual addreses instad of calculate
518- // the offset on the raw blob
519-
520516 // https://docs.microsoft.com/en-us/archive/msdn-magazine/2002/march/inside-windows-an-in-depth-look-into-the-win32-portable-executable-file-format-part-2#Binding
521517
522- log:: info!(
523- "IAT binding started image_import_descriptor.len() = {} ..." ,
524- self . image_import_descriptor. len( )
525- ) ;
526- let mut flipflop;
518+ if emu. cfg . verbose >= 1 {
519+ log:: info!(
520+ "IAT binding started image_import_descriptor.len() = {} ..." ,
521+ self . image_import_descriptor. len( )
522+ ) ;
523+ }
527524
528525 for i in 0 ..self . image_import_descriptor . len ( ) {
529526 let iim = & self . image_import_descriptor [ i] ;
530527
531528 if iim. name . is_empty ( ) {
532529 continue ;
533530 }
534-
535531 if emu:: winapi64:: kernel32:: load_library ( emu, & iim. name ) == 0 {
536532 log:: info!( "cannot found the library {} on maps64/" , & iim. name) ;
537533 return ;
538534 }
539535
540- // Walking function names.
541- let mut off_name =
542- PE32 :: vaddr_to_off ( & self . sect_hdr , iim. original_first_thunk ) as usize ;
536+ if iim. original_first_thunk == 0 {
537+ self . iat_binding_alternative ( emu, iim. first_thunk ) ;
538+ } else {
539+ self . iat_binding_original ( emu, iim. original_first_thunk , iim. first_thunk ) ;
540+ }
543541
544- //log::info!("----> 0x{:x}", iim.first_thunk);
545- let mut off_addr = PE32 :: vaddr_to_off ( & self . sect_hdr , iim. first_thunk ) as usize ;
546- //off_addr += 8;
542+ }
543+ log:: info!( "IAT Bound." ) ;
544+ }
545+
546+ pub fn iat_binding_alternative ( & mut self , emu : & mut emu:: Emu , first_thunk : u32 ) {
547+ // this function is called for every DLL that in iat.
548+
549+ let mut off = PE32 :: vaddr_to_off ( & self . sect_hdr , first_thunk) as usize ;
550+ let ordinal: u16 ;
551+
552+ loop {
553+ let entry = read_u64_le ! ( self . raw, off) ;
554+ if entry == 0 {
555+ break ;
556+ }
557+ if ( entry & 0x80000000_00000000 ) != 0 {
558+ ordinal = ( entry & 0xFFFF ) as u16 ;
559+ println ! ( "---- ordinal: {}" , ordinal) ;
560+ unimplemented ! ( "third variation of iat binding not implemented" ) ;
561+
562+ } else {
563+ let name_rva = entry as u32 ;
564+ let name_off = PE32 :: vaddr_to_off ( & self . sect_hdr , name_rva) as usize ;
565+ let api_name = PE32 :: read_string ( & self . raw , name_off+2 ) ;
566+
567+ let real_addr = emu:: winapi64:: kernel32:: resolve_api_name ( emu, & api_name) ;
568+ if real_addr > 0 {
569+ write_u64_le ! ( self . raw, off, real_addr) ; // patch the IAT to do the binding
570+ }
571+ }
572+
573+
574+ off += 8 ;
575+ }
576+ }
577+
578+ pub fn iat_binding_original ( & mut self , emu : & mut emu:: Emu , original_first_thunk : u32 , first_thunk : u32 ) {
579+ // this function is called for every DLL in iat.
547580
548- flipflop = false ;
581+ let mut off_name =
582+ PE32 :: vaddr_to_off ( & self . sect_hdr , original_first_thunk) as usize ;
583+ let mut off_addr = PE32 :: vaddr_to_off ( & self . sect_hdr , first_thunk) as usize ;
584+ let mut flipflop = false ;
549585
550586 loop {
551587 if self . raw . len ( ) <= off_name + 4 || self . raw . len ( ) <= off_addr + 8 {
@@ -555,10 +591,9 @@ impl PE64 {
555591 let hint = pe32:: HintNameItem :: load ( & self . raw , off_name) ;
556592 let addr = read_u32_le ! ( self . raw, off_addr) ; // & 0b01111111_11111111_11111111_11111111;
557593 let off2 = PE32 :: vaddr_to_off ( & self . sect_hdr , hint. func_name_addr ) as usize ;
594+
558595 if off2 == 0 {
559- //|| addr < 0x100 {
560596 off_name += pe32:: HintNameItem :: size ( ) ;
561- //off_addr += 8;
562597 if flipflop {
563598 break ;
564599 }
@@ -567,6 +602,7 @@ impl PE64 {
567602 }
568603 flipflop = false ;
569604 let func_name = PE32 :: read_string ( & self . raw , off2 + 2 ) ;
605+ //println!("resolving func_name: {}", func_name);
570606 let real_addr = emu:: winapi64:: kernel32:: resolve_api_name ( emu, & func_name) ;
571607 if real_addr == 0 {
572608 break ;
@@ -579,14 +615,12 @@ impl PE64 {
579615 let fake_addr = read_u64_le ! ( self . raw, off_addr) ;
580616
581617 //println!("writing real_addr: 0x{:x} {} 0x{:x} -> 0x{:x} ", off_addr, func_name, fake_addr, real_addr);
582-
583618 write_u64_le ! ( self . raw, off_addr, real_addr) ;
584619
585620 off_name += pe32:: HintNameItem :: size ( ) ;
586621 off_addr += 8 ;
587622 }
588- }
589- log:: info!( "IAT Bound." ) ;
623+
590624 }
591625
592626 pub fn import_addr_to_name ( & self , paddr : u64 ) -> String {
0 commit comments