home *** CD-ROM | disk | FTP | other *** search
/ Programming Win32 Under the API / ProgrammingWin32UnderTheApiPatVillani.iso / pedasm.zip / ExeRep.cpp < prev    next >
C/C++ Source or Header  |  1998-10-23  |  28KB  |  814 lines

  1. /*        fichier exeRep.cpp : fichier implementation
  2.  *
  3.  *    descr : classe qui represente un binaire
  4.  *
  5.  *    projet : PEDasm
  6.  *    
  7.  *    rq:
  8.  *    Ce programme est libre de droits. Il peut etre distribue et/ou modifie
  9.  *  selon les termes de la licence 'GNU General Public License version 2'.
  10.  *    
  11.  *    Ce programme est distribue sans aucunes garanties, y compris d'utilite 
  12.  *    ni de risques encouru, quelle que soit son utilisation.
  13.  *
  14.  *    lire le fichier licence.txt fourni ou bien ecrire a :
  15.  *    the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16.  *    pour recevoir une copie de la licence.
  17.  *
  18.  *    Copyright (C) 1997 - 1998 Nicolas Witczak <witczak@geocities.com>
  19.  */
  20.  
  21. #include "Config.h"
  22.  
  23. #include <algorithm>
  24. #include <cassert>
  25.  
  26. #include "ExeRep.h"
  27. #include "DasmBase.h"
  28.  
  29.  
  30.  
  31. //////////////////////////////////////////////////////////////////
  32. // implementation class CSection 
  33.  
  34. CSection::CSection( int idSection )
  35.     : m_idSection( idSection ) 
  36. {
  37.     m_pHeader = GetExe()->m_arSectHeader[ idSection ] ; 
  38.     m_pRawData = GetExe()->rva2ptr( m_pHeader->VirtualAddress );
  39.     m_pImageDir = 0 ;
  40. }
  41.  
  42. // information
  43. unsigned int CSection::size()                
  44. { return RoundUp( max ( m_pHeader->SizeOfRawData , m_pHeader->Misc.VirtualSize ), 4096 ) ;}
  45.     
  46. unsigned int CSection::init_size()        
  47. {    return m_pHeader->Misc.VirtualSize ; } ;
  48.  
  49. BYTE* CSection::begin()        
  50. {    return m_pRawData ; }; 
  51.  
  52. BYTE* CSection::end()            
  53. {    return m_pRawData + size() ; };
  54.  
  55. BYTE* CSection::init_end()    
  56. {    return m_pRawData + init_size() ; };
  57.  
  58. unsigned int CSection::va_begin()    
  59. {    return GetExe()->rva2va( m_pHeader->VirtualAddress ) ; };
  60.  
  61. unsigned int CSection::va_end()    
  62. {    return GetExe()->rva2va( m_pHeader->VirtualAddress ) + size() ; };
  63.  
  64. unsigned int CSection::va_init_end()
  65. {    return GetExe()->rva2va( m_pHeader->VirtualAddress ) + init_size() ; };
  66.  
  67. DWORD CSection::GetFlags()
  68. {
  69.     return m_pHeader->Characteristics ;
  70. }
  71.  
  72. bool CSection::IsCode()
  73. {
  74.     return (( GetFlags() & IMAGE_SCN_CNT_CODE ) != 0 ) 
  75.         || (( GetFlags() & IMAGE_SCN_MEM_EXECUTE ) != 0 ) ;
  76. }
  77.  
  78. bool CSection::IsData()
  79. {
  80.     bool bRet = ( GetFlags() & (IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_CNT_INITIALIZED_DATA ) ) != 0 ;    
  81.     bRet &= ( ( GetFlags() & IMAGE_SCN_LNK_NRELOC_OVFL ) == 0 ) ;
  82.     bRet &= ( ( GetFlags() & IMAGE_SCN_MEM_DISCARDABLE ) == 0 ) ;
  83.     bRet &=    ( strcmp( (const char*)&(m_pHeader->Name[0]) ,".rsrc") != 0 );
  84.     bRet &=    ( strcmp( (const char*)&(m_pHeader->Name[0]) ,".reloc") != 0 );
  85.     return bRet ;
  86. }
  87.  
  88. //////////////////////////////////////////////////////////////////
  89. // implementation class CExeRep 
  90. /** singleton exe */
  91. CExeRep    m_theExe ;
  92.  
  93.     //////////////////////////////////////////////////////////////
  94.     // initialisation
  95.  
  96. CExeRep::CExeRep()
  97. {}
  98.  
  99. CExeRep::~CExeRep()
  100. {
  101.     for( int idSection = 0 ; idSection < m_arRawSections.size() ; idSection ++)
  102.     {
  103.         delete m_arRawSections[ idSection ] ;    
  104.     }
  105.     CSymbolColl::iterator iter ;
  106.     for( iter = m_arSymbols.begin() ;iter != m_arSymbols.end(); iter ++)
  107.         delete *iter ;    
  108. }
  109.  
  110. void CExeRep::SetFileName( const char* pszFileIn , const char* pszFileOut )
  111. {
  112.     int iTmpIdx ;
  113.  
  114.     if( strchr( pszFileIn , PATH_SEP ) != 0 )
  115.     {
  116.         const char* pTmpStr = strrchr( pszFileIn , PATH_SEP ) ;
  117.         iTmpIdx = pTmpStr - pszFileIn ;
  118.         m_strPath = string( pszFileIn , iTmpIdx ) ;
  119.         ++ pTmpStr ;
  120.         iTmpIdx = strrchr( pszFileIn , '.' ) -  pTmpStr ;
  121.         m_strBaseName = string( pTmpStr , strrchr( pszFileIn , '.' ) ) ;
  122.     }
  123.     else
  124.     {
  125.         char pszTmp[128] ;
  126.         GetCurrentDirectory( 127 , pszTmp );
  127.         m_strPath = pszTmp ;
  128.         if( strchr( pszFileIn , '.' ) != 0 )
  129.         {
  130.             iTmpIdx = strrchr( pszFileIn , '.' ) - pszFileIn ;
  131.             m_strBaseName = string( pszFileIn , iTmpIdx ) ;
  132.         }
  133.         else
  134.             m_strBaseName = pszFileIn ;
  135.     }
  136.     if( pszFileOut != 0 )
  137.         m_strOutput = pszFileOut ;
  138.     else 
  139.         m_strOutput = string( m_strBaseName + string(".asm") ).c_str() ;
  140.  
  141. }
  142.  
  143. void CExeRep::ProcessExe( const char* pszFileIn , const char* pszFileOut )
  144. {
  145.     SetFileName( pszFileIn , pszFileOut );
  146.     if( LoadBin( pszFileIn ) )
  147.     {
  148.         CDasm* pDasm = CreateCDasm() ;        
  149.         if( !HasReloc() ) // test si manque relocations
  150.             printf( "warning : missing relocation info , disassembly source may be inaccurate\n") ;
  151.         printf( "Collecting directory entry symbols\n" ) ;
  152.         AddDirEntrySymb() ;
  153.         AddDllSymb() ;        
  154.         AddRelocSymb() ;
  155.         AddExportSymb() ;
  156.         AddEntryPoint() ;
  157.  
  158. // boucle sections    desassemblage passe d'analyse
  159.         vector< CSection* >::iterator iterSect  ;        
  160.         for( int iDasmStep = 1 ; iDasmStep < m_iPassNum ; ++ iDasmStep )
  161.         {
  162.             printf( "Desassembling pass %i\n" , iDasmStep ) ;        
  163.  
  164.             for( iterSect = m_arRawSections.begin() + 1 ; iterSect != m_arRawSections.end() ; ++ iterSect )
  165.             {
  166.                 if( (*iterSect)->IsCode() || (*iterSect)->IsData() )
  167.                 {
  168.                     pDasm->SetWindow( *iterSect ) ;
  169.                     pDasm->Run( ctePassScan ) ;
  170.                 }
  171.             }
  172.         }
  173.  
  174.         FILE* pOutFile = fopen( m_strOutput.c_str() ,"wb") ;
  175.         pDasm->SetFile( pOutFile ) ;
  176.         OutputMainHeader( pOutFile ) ;
  177.  
  178. // boucle sections    desassemblage pass de sortie asm
  179.         printf( "Desassembling pass %i \n" ,m_iPassNum ) ;
  180.         for( iterSect = m_arRawSections.begin() + 1  ; iterSect != m_arRawSections.end() ; ++ iterSect )
  181.         {
  182.             if( (*iterSect)->IsCode() || (*iterSect)->IsData() )
  183.             {    
  184.                 pDasm->SetWindow( *iterSect ) ;
  185.                 OutputSectionHeader( *iterSect , pOutFile );
  186.                 pDasm->Run( ctePassEcho ) ;
  187.             }
  188.         }
  189.         fprintf( pOutFile , "\nend\n" );
  190.         delete pDasm ;
  191.         fclose( pOutFile ) ;
  192.     }
  193. }
  194.  
  195. bool CExeRep::LoadBin( const char* pszName ) 
  196. {
  197.     BYTE* pFilePtr ;
  198.     DWORD iFileSize = GetImageSize( pszName ) ;
  199.     if( iFileSize == 0 )
  200.         return false ;
  201. // ouverture fichier et allocation
  202.     FILE*     pFile = fopen( pszName , "rb" ) ;
  203.     if( pFile == 0 )
  204.     {
  205.         printf( "error: unable to open file : %s \n" , pszName ) ;
  206.         return false ;
  207.     }
  208.     m_pRawData = (BYTE*)VirtualAlloc( 0 , iFileSize , MEM_COMMIT , PAGE_READWRITE ) ;
  209.     pFilePtr = m_pRawData ;
  210.     if( m_pRawData == 0 )
  211.     {
  212.         printf( "error: unable to allocate memory\n") ;        
  213.         return false ;
  214.     }
  215.  
  216. // lecture headers
  217.     m_pDosHeader = (_IMAGE_DOS_HEADER*) pFilePtr ;
  218.     fread( m_pDosHeader , sizeof( _IMAGE_DOS_HEADER ) , 1 , pFile );
  219.     fseek( pFile , m_pDosHeader->e_lfanew , SEEK_SET ) ;    
  220.     pFilePtr += m_pDosHeader->e_lfanew ;
  221.     fread( pFilePtr , 4 , 1 , pFile ) ;
  222.     m_dwNTSign =  *((DWORD*)pFilePtr) ;
  223.     pFilePtr += 4 ;
  224.     m_pNTHeader = (_IMAGE_FILE_HEADER*)( pFilePtr ) ;
  225.     fread( m_pNTHeader , sizeof(_IMAGE_FILE_HEADER) , 1 , pFile ) ;    
  226.     pFilePtr += sizeof( _IMAGE_FILE_HEADER ) ;
  227.     m_pNTOptHeader = (IMAGE_OPTIONAL_HEADER*)( pFilePtr ) ;
  228.     fread( m_pNTOptHeader , sizeof( IMAGE_OPTIONAL_HEADER ) , 1 , pFile ) ;
  229.     pFilePtr += sizeof( IMAGE_OPTIONAL_HEADER ) ;
  230.     if( m_pNTHeader->SizeOfOptionalHeader > sizeof( IMAGE_OPTIONAL_HEADER ) )// avance vers la table des sections
  231.     {
  232.         fseek( pFile , m_pNTHeader->SizeOfOptionalHeader - sizeof( IMAGE_OPTIONAL_HEADER ) , SEEK_CUR ) ;    
  233.         pFilePtr += m_pNTHeader->SizeOfOptionalHeader - sizeof( IMAGE_OPTIONAL_HEADER ) ;    
  234.     }
  235.  
  236.     m_vaOffset = reinterpret_cast<unsigned int>( m_pRawData ) - m_pNTOptHeader->ImageBase ;
  237.  
  238. // verifications
  239.     if( m_dwNTSign != IMAGE_NT_SIGNATURE )
  240.         printf( "warning : bad NT image signature\n" ) ;
  241.     if( m_pNTHeader->Machine != IMAGE_FILE_MACHINE_I386 )
  242.     {
  243.         printf( "error: unsupported processor\n");
  244.         return false ;
  245.     }
  246.     if( ( ( m_pNTHeader->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE ) == 0 ) 
  247.         || ( m_pNTHeader->SizeOfOptionalHeader == 0 ) )
  248.     {
  249.         printf( "error: obj or lib files unsupported\n" );
  250.         return false ;    
  251.     }
  252.     
  253.     m_arSectHeader.resize( m_pNTHeader->NumberOfSections + 1 ) ;
  254.     
  255.     // on considere le header comme une section ( des RVA utiles pointent dessus )    
  256.     IMAGE_SECTION_HEADER* pHeaderSect = new IMAGE_SECTION_HEADER ;
  257.     memset( pHeaderSect , 0 , sizeof(IMAGE_SECTION_HEADER) ) ;
  258.     strcpy( (char*)pHeaderSect->Name , "header" ) ;
  259.     pHeaderSect->SizeOfRawData = m_pNTOptHeader->SizeOfHeaders ;
  260.     pHeaderSect->Misc.VirtualSize = m_pNTOptHeader->SizeOfHeaders ;
  261.     pHeaderSect->VirtualAddress = m_pNTOptHeader->ImageBase ;
  262.     m_arSectHeader[0] = pHeaderSect ;
  263.     for( int idSect = 1 ; idSect < m_arSectHeader.size() ; idSect ++ )
  264.     {
  265.         m_arSectHeader[ idSect ] = (IMAGE_SECTION_HEADER*)pFilePtr ;        
  266.         fread( m_arSectHeader[ idSect ] , sizeof( IMAGE_SECTION_HEADER ) , 1 , pFile ) ;
  267.         pFilePtr += sizeof( IMAGE_SECTION_HEADER ) ;
  268.     }
  269. // lecture sections
  270.     m_arRawSections.resize( m_arSectHeader.size() );
  271.     for( idSect = 0 ; idSect < m_arSectHeader.size() ; idSect ++ )
  272.     {
  273.         m_arRawSections[idSect] = new CSection( idSect ) ;
  274.         fseek( pFile , m_arSectHeader[ idSect ]->PointerToRawData , SEEK_SET ) ;
  275.         fread( m_arRawSections[idSect]->begin() , m_arSectHeader[ idSect ]->SizeOfRawData , 1 , pFile ) ;        
  276.     }
  277.     DWORD dwTmp ; VirtualProtect( m_pRawData ,m_pNTOptHeader->SizeOfImage , PAGE_READONLY , &dwTmp ) ;
  278.     fclose( pFile );
  279.     return true;
  280. }
  281.  
  282. bool CExeRep::ScanConfFile( FILE* pFile )
  283. {
  284.     char_buff pszTmpBuff ;
  285.     char* pszCur ;
  286.     unsigned int iAdr = 0 ;
  287.     unsigned int  iType ;
  288.     for( int iLine = 0 ; fgets( pszTmpBuff , sizeof(pszTmpBuff) - 1 , pFile ) != 0 ; ++ iLine )
  289.     {
  290.         if( pszTmpBuff[0] == '#' || pszTmpBuff[0] == '\n' )
  291.             continue ;
  292.         
  293.         pszCur = strtok( pszTmpBuff , " \t,") ;
  294.         if( ( pszCur == 0 ) 
  295.             || ( sscanf( pszCur , "%x" , &iAdr ) == EOF )
  296.             || ( iAdr  == 0 )
  297.             || ( ( pszCur = strtok( 0 , " \t\r\n,") ) == 0 ) )
  298.         {
  299.             printf("config file error line %i \n" , iLine  ) ;
  300.             return false ;
  301.         }
  302.         if( stricmp( pszCur , "data") == 0 )
  303.             iType = cSymData | fSymUser ;
  304.         else if( stricmp( pszCur , "funct") == 0 )
  305.             iType = cSymFunc | fSymUser  ;
  306.         else if( stricmp( pszCur , "ptr") == 0 )
  307.             iType = cSymDataPtr | fSymUser ;
  308.         else
  309.         {
  310.             printf("config file error line %i : %s bad symbol type \n" , iLine , pszCur ) ;
  311.             return false ;
  312.         }
  313.         pszCur = strtok( 0 , " \r\n\t,") ;
  314.         CSymbol* pSymbol = new CSymbol( iAdr , iType , pszCur ) ;
  315.         m_arSymbols.insert( pSymbol ) ;
  316.     }
  317.     return true ;
  318. }
  319.  
  320.  
  321. void CExeRep::AddDirEntrySymb() 
  322. {
  323.     for( int idDirTable = 0 ; idDirTable < IMAGE_NUMBEROF_DIRECTORY_ENTRIES ; idDirTable ++ )
  324.     {
  325.         if( m_pNTOptHeader->DataDirectory[ idDirTable ].Size > 0 )
  326.         {
  327.             CSection* pOwner = GetSectFromVA( rva2va( m_pNTOptHeader->DataDirectory[ idDirTable ].VirtualAddress)  ) ;
  328.             if( pOwner != 0 )
  329.                 pOwner->m_pImageDir = &(m_pNTOptHeader->DataDirectory[ idDirTable ]) ;
  330.         }
  331.     }
  332. }
  333.  
  334. void CExeRep::AddDllSymb()
  335. {
  336.     static char_buff pszTmp ; 
  337. // creation fichier include pour les import de dll
  338.     FILE* pOutFile = fopen( "dllImport.inc" ,"wb") ;    
  339.     fprintf(pOutFile,"%s%s\n" , cteHeaderSep , cteHeaderStLine ) ;
  340.     fprintf(pOutFile,
  341.         "%s     PEDasm generated dll import file for file: %s.asm \n" 
  342.         ,cteHeaderStLine, m_strBaseName.c_str() );    
  343.     fprintf( pOutFile, "%s\n%s\n%s\n\n" , cteHeaderStLine,cteHeaderStLine,cteHeaderStLine);
  344.  
  345.     IMAGE_IMPORT_DESCRIPTOR* pImpDllTable = (IMAGE_IMPORT_DESCRIPTOR*)rva2ptr(
  346.         m_pNTOptHeader->DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT ].VirtualAddress ) ;
  347.     for( ; ( pImpDllTable != 0 ) && ( pImpDllTable->Name != 0 ) ; pImpDllTable ++ )
  348.     {    // iteration sur les dll
  349.         DWORD    curFunVA = (DWORD)pImpDllTable->FirstThunk + m_pNTOptHeader->ImageBase ;
  350.         DWORD*    pRVANameArray ;
  351.         const char* pszDllName = (const char*)rva2ptr( pImpDllTable->Name ) ;
  352.         const char* pFunName ;
  353.     // chargement de la dll
  354.         if( !LoadImpDll( pszDllName ) )
  355.         {
  356.             printf( "Unable to Load dll : %s , use listing option \n" , pszDllName ) ;
  357.             exit(1) ;
  358.         }
  359.     // creation de fichier .def pour creer des import lib    
  360.         sprintf( pszTmp ,"%s.def" , GetBaseName(pszDllName) ) ;
  361.         FILE* pDefFile = fopen( pszTmp , "wb" ) ;
  362.         fprintf(pDefFile,
  363.     "LIBRARY %s\n\nDESCRIPTION 'import lib def file for use with LIB.EXE'\n\nEXPORTS\n", GetBaseName(pszDllName) ) ;
  364.  
  365.     // ajout d'une section ds le fichier include
  366.         fprintf(pOutFile,"\n\n%s%s\n",ctePartSep , ctePartStLine ) ;
  367.         fprintf(pOutFile,
  368.             "%s    from dll : %s \n%s\n\n" , ctePartStLine , pszDllName , ctePartStLine );    
  369.         
  370.         if( pImpDllTable->Characteristics != 0 )
  371.             pRVANameArray = (DWORD*)rva2ptr( pImpDllTable->Characteristics ) ;
  372.         else
  373.             pRVANameArray = (DWORD*)rva2ptr( (DWORD)pImpDllTable->FirstThunk ) ;
  374.         do
  375.         {    
  376.             bool bHasName ;
  377.             CSymbol* pDllImpSym ;
  378.             // iteration sur les fonctions de la dll
  379.             if( ( (*pRVANameArray ) & IMAGE_ORDINAL_FLAG ) != 0 )            
  380.             {
  381.                 pFunName = GetNameFromOrd( pszDllName , (*pRVANameArray) & 0x0000ffff , &bHasName ) ;
  382.                 if( bHasName )
  383.                     fprintf( pDefFile , "\t%s\t@%i\n", pFunName , (*pRVANameArray) & 0x0000ffff);                            
  384.                 else
  385.                     fprintf( pDefFile , "\t%s\t@%i\tNONAME\n",pFunName,(*pRVANameArray) & 0x0000ffff);            
  386.             }
  387.             else
  388.             {
  389.                 pFunName = (const char*)&(((IMAGE_IMPORT_BY_NAME*)rva2ptr( *pRVANameArray ))->Name)[0] ;            
  390.                 fprintf( pDefFile , "\t%s\t@%i\n", pFunName , GetOrdFromName( pszDllName , pFunName ) );            
  391.             }
  392.             pDllImpSym = new CSymbol( curFunVA , cSymDllImp , pFunName ) ;
  393.             m_arSymbols.insert( pDllImpSym );
  394.             curFunVA += 4 ;
  395.             pRVANameArray ++ ;
  396.             fprintf(pOutFile , "%s" , pDllImpSym->GetDeclaration() ) ;        
  397.         }
  398.         while( *pRVANameArray != 0 ) ;
  399.         fclose( pDefFile ) ;
  400.     }
  401.     fclose( pOutFile ) ;
  402. }
  403.  
  404. void CExeRep::AddRelocSymb()
  405. {
  406.     BYTE* pRelocTable , *pRelocCur , *pRelocEnd ;
  407.     pRelocTable = (BYTE*)rva2ptr( 
  408.         m_pNTOptHeader->DataDirectory[ IMAGE_DIRECTORY_ENTRY_BASERELOC ].VirtualAddress );
  409.     pRelocCur = pRelocTable ;
  410.     pRelocEnd = pRelocTable + m_pNTOptHeader->DataDirectory[ IMAGE_DIRECTORY_ENTRY_BASERELOC ].Size ;
  411.     while( ( pRelocCur < pRelocEnd ) 
  412.         && ( *((DWORD*)pRelocCur) != 0 ) && (((DWORD*)pRelocCur)[1] != 0 ) )
  413.     {    // iteration sur les pages de 4 Ko 
  414.         unsigned int iVirtAdr = *((DWORD*)pRelocCur) + m_pNTOptHeader->ImageBase ;    
  415.         int iNumReloc = ( ((DWORD*)pRelocCur)[1] - sizeof( IMAGE_BASE_RELOCATION ) ) / sizeof(WORD) ;
  416.         pRelocCur += sizeof( IMAGE_BASE_RELOCATION );
  417.         for( int idReloc = 0 ; idReloc < iNumReloc ; idReloc++ , pRelocCur += sizeof(WORD) )
  418.         {    // iteration sur les reloc de la page
  419.             if( ( (*(WORD*)pRelocCur ) >> 12 ) & IMAGE_REL_BASED_HIGHLOW != 0 )
  420.             {
  421.                 unsigned int iRelocVA = ( (*(WORD*)pRelocCur) & 0x0fff ) + iVirtAdr ;
  422.                 CSymbol*    pReloc = new CSymbol( iRelocVA ) ; 
  423.                 m_arRelocSymbols.insert( pReloc );
  424.             }
  425.         }
  426.     }
  427. }
  428.  
  429. void CExeRep::AddExportSymb( )
  430. {
  431.     static char_buff pszTmp ; 
  432.     int iMaxNamedFunOrd = 0 ;
  433.     
  434.     if( m_pNTOptHeader->DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ].VirtualAddress == 0 )
  435.         return ; // rien a exporter
  436.  
  437. // creation de fichier .def pour creer des import lib    
  438.     sprintf( pszTmp ,"%s.def" , m_strBaseName.c_str() ) ;
  439.     FILE* pDefFile = fopen( pszTmp , "wb" ) ;
  440.     fprintf(pDefFile,"LIBRARY %s\n\nDESCRIPTION 'exported symbols def file '\n\nEXPORTS\n"
  441.         ,  m_strBaseName.c_str() ) ;
  442.  
  443.     IMAGE_EXPORT_DIRECTORY* pExtDir = (IMAGE_EXPORT_DIRECTORY*)rva2ptr( 
  444.         m_pNTOptHeader->DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ].VirtualAddress );
  445.  
  446.     void** parFunNames = (void**)rva2ptr(  (long)pExtDir->AddressOfNames );
  447.     WORD*  pOrdinals = (WORD*)rva2ptr( (long)pExtDir->AddressOfNameOrdinals );
  448.     DWORD* pAdresses = (DWORD*)rva2ptr( (long)pExtDir->AddressOfFunctions ); 
  449.     const char* pFunName ;
  450.     int iOrdinal ;
  451.     DWORD dwFunAddress ;
  452.     CSymbol* pCurSymbol ;
  453.     for( int idFun = 0 ; idFun < pExtDir->NumberOfNames ; idFun ++ )
  454.     {
  455.         pFunName = (const char*)rva2ptr( (long)( parFunNames[ idFun ] ) ) ;
  456.         iOrdinal = pExtDir->Base + pOrdinals[ idFun ] ;
  457.         dwFunAddress = rva2va( pAdresses[ idFun ] ) ;
  458.         pCurSymbol = new CSymbol( dwFunAddress, cSymFunc | fSymPublic , pFunName );
  459.         m_arSymbols.insert( pCurSymbol ) ;
  460.         iMaxNamedFunOrd = max( iMaxNamedFunOrd , iOrdinal ) ;
  461.         fprintf( pDefFile , "\t%s\t@%i\n", pFunName , iOrdinal );
  462.     }
  463.     for( ; idFun < pExtDir->NumberOfFunctions ; idFun ++ )
  464.     {    // recuperation des fct exorte par ordinal -> ds l'ordre des ordinaux
  465.         ++iMaxNamedFunOrd ;
  466.         iOrdinal = pExtDir->Base + pOrdinals[ idFun ] ;
  467.         dwFunAddress = rva2va( pAdresses[ idFun ] ) ;
  468.         pCurSymbol = new CSymbol( dwFunAddress, cSymFunc | fSymPublic , 0 );
  469.         m_arSymbols.insert( pCurSymbol ) ;
  470.         iMaxNamedFunOrd = max( iMaxNamedFunOrd , iOrdinal ) ;
  471.         fprintf( pDefFile , "\t%s\t@%i\tNONAME\n", pCurSymbol->GetName() , iOrdinal ) ;
  472.     }        
  473.     fclose( pDefFile ) ;
  474. }
  475.  
  476. void CExeRep::AddEntryPoint()
  477. {
  478.     if( m_arSymbols.find( &CSymbol( m_pNTOptHeader->AddressOfEntryPoint + m_pNTOptHeader->ImageBase ) )
  479.         != m_arSymbols.end() ) 
  480.         return ;
  481.     const char* pszEntryPoint ;
  482.     if( IsExeBin() )
  483.         pszEntryPoint = "main" ;
  484.     else
  485.         pszEntryPoint = "dllmain" ;
  486.     m_arSymbols.insert( new CSymbol( m_pNTOptHeader->AddressOfEntryPoint 
  487.         + m_pNTOptHeader->ImageBase, cSymFunc | fSymPublic , pszEntryPoint ) ) ;
  488. }
  489.  
  490.  
  491. CSection* CExeRep::GetSectFromVA( unsigned int uAdresse )
  492. {
  493.     CSection* pRet = 0 ;
  494.     CSection* pSection ;
  495.     for( int idSect = 0 ; idSect < m_arSectHeader.size() ; idSect ++ )
  496.     {
  497.         pSection = m_arRawSections[idSect] ;
  498.         if( ( pSection->va_begin() <= uAdresse ) && ( pSection->va_end() > uAdresse ) ) 
  499.         {
  500.             pRet = pSection ;
  501.             break ;
  502.         }
  503.     }
  504.     return pRet ;
  505. }
  506.  
  507.  
  508.     //////////////////////////////////////////////////////////////
  509.     // fonctions d'aides
  510.  
  511. bool CExeRep::IsExeBin()
  512. {
  513.     return ( m_pNTHeader->Characteristics & IMAGE_FILE_DLL ) == 0 ;
  514. }
  515.  
  516. bool CExeRep::HasReloc()
  517. {
  518.     return ( m_pNTHeader->Characteristics & IMAGE_FILE_RELOCS_STRIPPED ) == 0  ;
  519. }
  520.  
  521. bool CExeRep::LoadImpDll( const char* pszDllName )
  522. {
  523.     int iMaxNamedFunOrd = 0 ;
  524.     LOADED_IMAGE sImage ;
  525.     unsigned long szDir ;
  526.     if( ! MapAndLoad( (char*)pszDllName , 0 , &sImage , TRUE , TRUE ) ) 
  527.         return false ;
  528.     dll_iterator iterDll = (m_arDll.insert( pair<const char* const,dllname_coll>( pszDllName , dllname_coll() ) ) ).first ;
  529.     IMAGE_EXPORT_DIRECTORY* pExtDir = (IMAGE_EXPORT_DIRECTORY* )ImageDirectoryEntryToData( sImage.MappedAddress , FALSE 
  530.          , IMAGE_DIRECTORY_ENTRY_EXPORT , &szDir ) ;
  531.     void** parFunNames = (void**)ImageRvaToVa( sImage.FileHeader, sImage.MappedAddress , (long)pExtDir->AddressOfNames , 0 );
  532.     WORD*  pOrdinals = (WORD*)ImageRvaToVa( sImage.FileHeader, sImage.MappedAddress , (long)pExtDir->AddressOfNameOrdinals , 0 );
  533.     dll_fun        funName ;
  534.     for( int idFun = 0 ; idFun < pExtDir->NumberOfNames ; idFun ++ )
  535.     {
  536.         const char* pTmp ;
  537.         pTmp = (const char*)ImageRvaToVa( sImage.FileHeader, sImage.MappedAddress , (long)(parFunNames[idFun]) , 0 );
  538.         funName.m_bHasName = true ;
  539.         funName.m_pszDllName = pszDllName ;
  540.         funName.m_iOrdinal = pExtDir->Base + pOrdinals[idFun] ;
  541.         funName.m_pszName = new char[ strlen(pTmp) + 1 ] ;
  542.         strcpy( (char*)funName.m_pszName , pTmp ) ;        
  543.         ((*iterDll).second).push_back( funName ) ;
  544.         iMaxNamedFunOrd = max( iMaxNamedFunOrd , funName.m_iOrdinal ) ;
  545.     }
  546.     for( ; idFun < pExtDir->NumberOfFunctions ; idFun ++ )
  547.     {    // recuperation des fct exorte par ordinal -> ds l'ordre des ordinaux
  548.         ++iMaxNamedFunOrd ;
  549.         funName.m_bHasName = false ;
  550.         funName.m_iOrdinal = iMaxNamedFunOrd ;
  551.         funName.m_pszDllName = pszDllName ;
  552.         funName.m_pszName = 0 ;
  553.         ((*iterDll).second).push_back( funName ) ;
  554.     }        
  555.     UnMapAndLoad( &sImage ) ;
  556.     return true ;
  557. }
  558.  
  559. const char* CExeRep::GetNameFromOrd( const char* pszDllName ,int iOrdinal,bool* pbHasName )
  560. {
  561.     dll_iterator iterDll = m_arDll.find( pszDllName ) ;
  562.     if( iterDll == m_arDll.end() )
  563.         return 0 ;
  564.     for( dllfun_iterator iterFctName = (*iterDll).second.begin() 
  565.         ; iterFctName != (*iterDll).second.end() ; ++ iterFctName  )
  566.     {
  567.         if( iOrdinal == iterFctName->m_iOrdinal )
  568.         {
  569.             if( iterFctName->m_bHasName )
  570.             {
  571.                 if( pbHasName != 0 ) *pbHasName = true ;
  572.             }
  573.             else
  574.             {
  575.                 if( pbHasName != 0 ) *pbHasName = false ;
  576.             }
  577.             return iterFctName->GetName() ;
  578.         }
  579.     }
  580.     return 0 ;
  581. }
  582.  
  583. int CExeRep::GetOrdFromName( const char* pszDllName , const char* pszFunName )
  584. {
  585.     dll_iterator iterDll = m_arDll.find( pszDllName ) ;
  586.     if( iterDll == m_arDll.end() )
  587.         return 0 ;
  588.     for( dllfun_iterator iterFctName = (*iterDll).second.begin() 
  589.         ; iterFctName != (*iterDll).second.end() ; ++ iterFctName  )
  590.     {
  591.         if( iterFctName->m_bHasName && ( stricmp( pszFunName , iterFctName->m_pszName ) == 0 ) )
  592.             return iterFctName->m_iOrdinal ;
  593.     }
  594.     return -1 ;
  595. }
  596.  
  597.  
  598. void CExeRep::AddSymbol( unsigned int uVA,unsigned int uRefVA, bool bTrust , unsigned int SymbolCat   )
  599. {
  600.     CSymbolColl::const_iterator prevSym = m_arSymbols.find( & CSymbol( uVA ) ) ;
  601.     bool bReallySymbol = bTrust || ( m_arRelocSymbols.find( & CSymbol( uRefVA ) ) != m_arRelocSymbols.end() ) ;
  602.     if( ( prevSym == m_arSymbols.end() ) && bReallySymbol )
  603.     {    // nouveau symbol a referencer
  604.         if( SymbolCat == cSymData ) // test si eventuellement callback 
  605.         {
  606.             CSection* pSect = GetSectFromVA( uVA ) ;
  607.             if( ( pSect != 0 ) && pSect->IsCode() )
  608.                 SymbolCat = cSymCallBack ;
  609.         }
  610.         m_arSymbols.insert( new CSymbol( uVA , SymbolCat ) ) ;
  611.     }
  612.     if( prevSym != m_arSymbols.end() && ( ( (*prevSym)->m_Attrib & fSymUser ) == 0 ) )
  613.     {    // on complete eventuellement
  614.         if( (*prevSym)->m_Attrib == cSymUnknown )
  615.             (*prevSym)->m_Attrib = SymbolCat ;
  616.         else if( ( (*prevSym)->m_Attrib == cSymData ) && ( SymbolCat == cSymDataPtr ) )
  617.             (*prevSym)->m_Attrib = cSymDataPtr ;
  618.         else if( ( (*prevSym)->m_Attrib == cSymCallBack )
  619.             && ( ( SymbolCat == cSymJmp ) || ( SymbolCat == cSymFunc ) /*|| ( SymbolCat == cSymData )*/) )
  620.             (*prevSym)->m_Attrib = SymbolCat ;
  621.     }
  622. }
  623.  
  624. const char* CExeRep::GetSymbName( unsigned int uVA, unsigned int refVA , bool bTrust , unsigned int uflags  )
  625. {
  626.     static char_buff pszRet ;
  627.     const char*        pszTmp ;
  628.     CSymbolColl::const_iterator ppSymb = m_arSymbols.end() ;
  629.  
  630. // recherche si c'est un symbol et recupere un iterateur dessus ci c'est le cas
  631.     if( bTrust || ( m_arRelocSymbols.find( & CSymbol( refVA ) ) != m_arRelocSymbols.end() ) )
  632.     {
  633.         ppSymb = m_arSymbols.find( & CSymbol( uVA ) ) ;
  634.         if( ppSymb == m_arSymbols.end() ) 
  635.         {
  636.             //assert(0);
  637.             CSection* pSection = GetSectFromVA( uVA );
  638.         }
  639.     }
  640.  
  641. // recuperation symbol    
  642.     if( ppSymb != m_arSymbols.end() )
  643.         pszTmp = (*ppSymb)->GetName() ;
  644.     else
  645.         pszTmp = GetValue( uVA , uflags ) ;
  646.  
  647. // decoration
  648.     if( ( uflags & cteDecorate ) != 0 )
  649.     {
  650.         if( ( ppSymb == m_arSymbols.end() ) && ( ( uflags & cteDecOffset ) != 0 ) )
  651.             return pszTmp ; // val num et offset
  652.  
  653.         if( ( uflags & cteDecOffset ) == 0 )
  654.             sprintf( pszRet , "[ %s ]" , pszTmp ) ;
  655.         else
  656.             sprintf( pszRet , "offset %s" , pszTmp ) ;
  657.         return pszRet ;
  658.     }
  659.     else 
  660.         return pszTmp ;
  661. }
  662.  
  663. const char* CExeRep::GetValue( unsigned int uVal , int uflags ) 
  664. {
  665.     static char pszTmpBuff[32] ;
  666.     if( ( uflags & cteFmtInteger ) != 0 )
  667.     {
  668.         if( ( uflags & cteFmtSign ) != 0 )    
  669.         {
  670.             if( ((signed int)uVal) < 0 )
  671.                 sprintf( pszTmpBuff , "- %i" , -((signed int)uVal)  ) ;    
  672.             else
  673.                 sprintf( pszTmpBuff , "+ %i" , uVal  ) ;
  674.         }
  675.         else
  676.             sprintf( pszTmpBuff , "%i" , uVal  ) ;    
  677.     }
  678.     else
  679.     {
  680.         sprintf( pszTmpBuff , "0%Xh" , uVal  ) ;    
  681.     }
  682.  
  683.     return pszTmpBuff ;
  684. }
  685.  
  686. CSymbol* CExeRep::GetSymbol( unsigned int uVA )
  687. {
  688.     CSymbolColl::iterator iterCurSymb = m_arSymbols.find( &CSymbol( uVA ) ) ;
  689.     if( iterCurSymb == m_arSymbols.end() ) 
  690.         return 0 ;
  691.     else
  692.         return *iterCurSymb ;
  693. }
  694.  
  695. CSymbol* CExeRep::FindSymbol( unsigned int uVA , unsigned int uMask )
  696. {
  697.     symb_iterator iter = m_arSymbols.lower_bound( &CSymbol(uVA) ) ;
  698.     while( ( iter != m_arSymbols.end() ) && ( ( (*iter)->m_Attrib ) & uMask ) == 0 )    
  699.         ++ iter ;
  700.     if( iter == m_arSymbols.end()  )
  701.         return 0 ;
  702.     else 
  703.         return *iter ;
  704. }
  705.  
  706. CSymbol* CExeRep::FindSymbol( unsigned int uVA )
  707. {
  708.     symb_iterator iter = m_arSymbols.lower_bound( &CSymbol(uVA) ) ;
  709.     if( iter == m_arSymbols.end()  )
  710.         return 0 ;
  711.     else 
  712.         return *iter ;
  713. }
  714.  
  715. void CExeRep::OutputMainHeader( FILE* pFile )
  716. {
  717.     fprintf(pFile,"%s%s\n" , cteHeaderSep , cteHeaderStLine ) ;
  718.     fprintf(pFile, "%s     PEDasm generated source file : %s.asm \n" 
  719.         ,cteHeaderStLine, m_strBaseName.c_str() );    
  720.     fprintf(pFile, "%s\n%s\n" 
  721.         ,cteHeaderStLine, cteHeaderStLine );    
  722.     fprintf(  pFile, "\n\n.586P\n.model flat , stdcall\n\n" );
  723.     fprintf(  pFile, "\n\n.radix 10 \n\n" );
  724.     fprintf(  pFile, "include dllImport.inc\n\n" );
  725. }
  726.  
  727. void CExeRep::OutputSectionHeader( CSection* pSection ,FILE* pFile )
  728. {
  729.     fprintf(pFile,"\n\n\n%s%s section %8s\n" , cteHeaderSep 
  730.         , cteHeaderStLine ,pSection->m_pHeader->Name) ;
  731.     fprintf(pFile,"%s\tV.A = 0x%08x , init part size = %u , total size = %u\n" 
  732.         , cteHeaderStLine , pSection->va_begin() , pSection->init_size() , pSection->size() ) ;    
  733.     fprintf(pFile,"%s\tflags : ", cteHeaderStLine );
  734.     
  735.     if( ( pSection->GetFlags() & IMAGE_SCN_CNT_CODE ) != 0 )
  736.         fprintf(pFile," code section , ");
  737.     if( ( pSection->GetFlags() & IMAGE_SCN_CNT_INITIALIZED_DATA ) != 0 )
  738.         fprintf(pFile," initialized data section , ");
  739.     if( ( pSection->GetFlags() & IMAGE_SCN_CNT_UNINITIALIZED_DATA ) != 0 )
  740.         fprintf(pFile," uninitialized data section , ");
  741.     if( ( pSection->GetFlags() & IMAGE_SCN_LNK_INFO ) != 0 )
  742.         fprintf(pFile," section contains comments ,");
  743.  
  744.     if( ( pSection->GetFlags() & IMAGE_SCN_LNK_NRELOC_OVFL ) != 0 )
  745.         fprintf(pFile," section contains extended relocations ,");
  746.     if( ( pSection->GetFlags() & IMAGE_SCN_MEM_DISCARDABLE ) != 0 )
  747.         fprintf(pFile," section can be discarded , ");
  748.     if( ( pSection->GetFlags() & IMAGE_SCN_MEM_NOT_CACHED ) != 0 )
  749.         fprintf(pFile," section not cachable ,");
  750.     if( ( pSection->GetFlags() & IMAGE_SCN_MEM_NOT_PAGED ) != 0 )
  751.         fprintf(pFile," section not pageable ,");
  752.     if( ( pSection->GetFlags() & IMAGE_SCN_MEM_SHARED ) != 0 )
  753.         fprintf(pFile," section in shared memory ,");
  754.     if( ( pSection->GetFlags() & IMAGE_SCN_MEM_EXECUTE ) != 0 )
  755.         fprintf(pFile," section executable , ");
  756.     if( ( pSection->GetFlags() & IMAGE_SCN_MEM_READ ) != 0 )
  757.         fprintf(pFile," section readable ");
  758.     if( ( pSection->GetFlags() & IMAGE_SCN_MEM_WRITE ) != 0 )
  759.         fprintf(pFile," section writeable ");
  760.  
  761.     if( pSection->IsData() )
  762.         fprintf(pFile,"\n\n.data\n\n\n" ) ;
  763.     else if( pSection->IsCode() )
  764.         fprintf(pFile,"\n\n.code\n\nassume fs:nothing ; this requiered for SEH\n\n" ) ;
  765. }
  766.  
  767.  
  768. //////////////////////////////////////////////////////////////////
  769. // fonctions globales
  770.  
  771.  
  772. unsigned int GetImageSize( const char* pszStr )
  773. {
  774.     _IMAGE_DOS_HEADER            dosHeader ;
  775.     _IMAGE_FILE_HEADER            NTHeader ;
  776.     IMAGE_OPTIONAL_HEADER        NTOptHeader ;
  777.     DWORD                        dwNTSign ;
  778.     unsigned int                uiRetSize ;
  779.     FILE*     pFile = fopen( pszStr , "rb" ) ;
  780.     if( pFile == 0 )
  781.     {
  782.         printf( "error: unable to open file : %s\n" , pszStr ) ;    
  783.         return 0;
  784.     }
  785.     fread( &dosHeader , sizeof( _IMAGE_DOS_HEADER ) , 1 , pFile );
  786.     fseek( pFile , dosHeader.e_lfanew , SEEK_SET ) ;
  787.     fread( &dwNTSign , 4 , 1 , pFile ) ;
  788.     
  789.     if( dwNTSign != IMAGE_NT_SIGNATURE )
  790.     {
  791.         fclose(pFile) ;
  792.         printf( "error: unrecognized binary format , file : %s\n" , pszStr ) ;
  793.         return 0;
  794.     }
  795.     fread( &NTHeader , sizeof(_IMAGE_FILE_HEADER) , 1 , pFile ) ;
  796.     if( NTHeader.Machine != IMAGE_FILE_MACHINE_I386 )
  797.     {
  798.         fclose(pFile) ;
  799.         printf( "error: unknown processor , file : %s\n" , pszStr ) ;
  800.         return 0;
  801.     }
  802.     if( ( ( NTHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE ) == 0 ) 
  803.         || ( NTHeader.SizeOfOptionalHeader == 0 ) )
  804.     {
  805.         fclose(pFile) ;
  806.         printf( "error: file : %s not executable\n" , pszStr ) ;    
  807.         return 0 ;    
  808.     }    
  809.     fread( &NTOptHeader , sizeof( IMAGE_OPTIONAL_HEADER ) , 1 , pFile ) ;
  810.     uiRetSize = NTOptHeader.SizeOfImage ;
  811.     fclose(pFile) ;
  812.     return uiRetSize  ;
  813. }
  814.