Make your own free website on Tripod.com
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

codescan.cpp

Go to the documentation of this file.
00001 /*
00002 PeRdr - PE file disassembler
00003 Copyright (C) 1999-2003 Frediano Ziglio
00004 -----
00005 
00006 This program is free software; you can redistribute it and/or modify
00007 it under the terms of the GNU General Public License as published by
00008 the Free Software Foundation; either version 2 of the License, or
00009 (at your option) any later version.
00010 
00011 This program is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 GNU General Public License for more details.
00015 
00016 You should have received a copy of the GNU General Public License
00017 along with this program; if not, write to the Free Software
00018 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 -----
00020 
00021 INFORMATION
00022   www: http://freddy77.tripod.com/perdr/
00023   e-mail: freddy77@angelfire.com
00024 */
00025 #include "global.h"
00026 #ifdef HAVE_HDRSTOP
00027 #pragma hdrstop
00028 #endif
00029 
00030 #include "signfile.hpp"
00031 #include "module.h"
00032 #include "code.h"
00033 #include "codeglob.h"
00034 #include "x86istr.h"
00035 #include "heuristic.h"
00036 #include "codescan.h"
00037 #ifdef DEBUG
00038 #include <cctype>
00039 #endif
00040 #include "utils/f77auto_ptr"
00041 
00042 using namespace std;
00043 
00044 //extern IstrReferences varReferences;
00045 //void AddTempFlow(enum FlowTypes flow,vma_t from,vma_t to,
00046 //  enum ByteInfo::TPriority priority);
00047 //bool AddTempFlow(enum FlowTypes flow,vma_t from,const Instruction& instruction,
00048 //  enum ByteInfo::TPriority priority,bool bAddComplex=true);
00049 
00050 // declarations
00051 //bool ExecuteComplexReferenceMemory(vma_t address,const Instruction& instruction);
00052 
00053 void CodeParser::_ReverseScan(IScanning* scanning,vma_t address,IMachineStatus* status)
00054 {
00055   _PRG_ASSERT(scanning != NULL);
00056   _PRG_ASSERT(status != NULL);
00057   _PRG_ASSERT(&*module != NULL);
00058   vma_t addr = address;
00059   // !!! check for loop
00060   for(;;)
00061   {
00062           // processa riferimenti
00063     IstrReferences::iterator i   =
00064       istrReferences.beginReferenceTo(addr);
00065     IstrReferences::iterator end =
00066       istrReferences.endReferenceTo(addr);
00067     for(;i != end; ++i)
00068     {
00069       if ( !(*i).direct )
00070       {
00071         IMachineStatus* newStatus = status->Clone();
00072         _ReverseScan(scanning,(*i).to,newStatus);
00073         delete newStatus;
00074       }
00075     }
00076 
00077     // testa se esiste un'istruzione precedente
00078     if (!byteInfo[addr].IsPrevInstruction())
00079       break;
00080 
00081     // cerca istruzione precedente
00082     _DEBUG_(vma_t debug_temp_addr = addr);
00083     while (byteInfo.GetIstrLen(--addr) == 0);
00084     // !!! bug this can be a bastard overlapped code or non exit call
00085     // !!! only in max priority
00086     _PRG_ASSERT(byteInfo.GetIstrLen(addr) == (debug_temp_addr-addr));
00087 
00088     // leggi istruzione precedente
00089     Instruction currInstruction;
00090     int result = GetInstruction(*module,addr,currInstruction);
00091     if (!result)
00092     {
00093       _PRG_ASSERT(0);
00094       return;
00095     }
00096 
00097     // processa istruzione
00098     if (!scanning->ProcessInstruction(addr,currInstruction,status,*this))
00099       break;
00100   }
00101 }
00102 
00103 void CodeParser::ReverseScan(IScanning* scanning,vma_t address)
00104 {
00105   _PRG_ASSERT(scanning != NULL);
00106   IMachineStatus* status = scanning->CreateMachineStatus();
00107   _PRG_ASSERT(status != NULL);
00108   _PRG_ASSERT(&*module != NULL);
00109   _ReverseScan(scanning,address,status);
00110   delete status;
00111 }
00112 
00113 class ScanningComplexReg;
00114 class MachineStatusReg: public IMachineStatus
00115 {
00116 public:
00117   IMachineStatus* Clone() const { return new MachineStatusReg(*this); };
00118 };
00119 
00120 class ScanningComplexReg: public IScanning
00121 {
00122 public:
00123   ScanningComplexReg(vma_t _address,reg_t _reg):
00124     reg(_reg),address(_address),bResult(true)
00125   {};
00126   bool GetResult() const;
00127   IMachineStatus* CreateMachineStatus() const
00128   { return new MachineStatusReg(); };
00129   bool ProcessInstruction(vma_t address,const Instruction& instr,
00130                           IMachineStatus* status,CodeParser& codeInfo);
00131 private:
00132   reg_t reg;
00133   vma_t address;
00134   bool bResult;
00135 
00136   bool CheckLoop(vma_t address) { return IsPresent(story,address); };
00137   void AddLabel(vma_t address) { story.insert(address); };
00138   std::set<vma_t, std::less<vma_t> > story;
00139 };
00140 
00141 bool ScanningComplexReg::GetResult() const
00142 {
00143   return bResult;
00144 }
00145 
00146 #ifdef __BORLANDC__
00147 #pragma argsused
00148 #endif
00149 bool ScanningComplexReg::ProcessInstruction(vma_t address,
00150   const Instruction& instr,IMachineStatus* status,CodeParser& codeInfo)
00151 {
00152   // segna che abbiamo attraversato questa etichetta
00153   if ( codeInfo.byteInfo[address].IsLabel() )
00154   {
00155     // !!! non ci sono problemi dato che nel loop
00156     // non ci possono essere modifiche
00157     if (CheckLoop(address))
00158       return false; // !!!
00159     AddLabel(address);
00160   }
00161 
00162   // !!! cosa succede se ci sono chiamate ???
00163   enum FlowTypes flow = instr.GetFlowType();
00164   _PRG_ASSERT( flow != FLOW_JUMP);
00165   if ( flow == FLOW_CALL )
00166   {
00167     // !!! assumi che tutte le chiamate lascino inalterate ESI, EDI, EBX e EBP
00168     // !!! codice non portatile
00169     if ( REG(esi)!=reg && REG(edi)!=reg && REG(ebx)!=reg && REG(ebp)!=reg)
00170       if ( REG(si)!=reg && REG(di)!=reg && REG(bx)!=reg && REG(bp)!=reg )
00171       {
00172         bResult = false;
00173         return false;
00174       }
00175   }
00176 
00177   // semplificazione quasi completa
00178   // ci devono essere solo istruzioni per sovrascrivere registro
00179   // se un'istruzione non e' supportata ritorna errore
00180   enum Instruction::UseType useType;
00181   try
00182   {
00183     useType = instr.GetUseType(reg);
00184   }
00185   catch (const Instruction::UseTypeUnimplemented&)
00186   {
00187     return (bResult = false);
00188   }
00189 #ifdef DEBUG
00190   // !!! corregge un errore del debugger di Borland C++ 5.01
00191   if (useType == 32) return (bResult = false);
00192 #endif
00193   _PRG_ASSERT(useType != 32);
00194 
00195   if ( (useType&Instruction::useMaskChange) == Instruction::useModify )
00196   {
00197     bResult = false;
00198     return false;
00199   }
00200 
00201   if ( (useType&Instruction::useMaskChange) == Instruction::useOverwrite )
00202   {
00203     Instruction currInstruction;
00204     _DEBUG_(int res =) GetInstruction(*codeInfo.module,this->address,currInstruction);
00205     _PRG_ASSERT(res != 0);
00206 
00207     // !!! modify instruction
00208     _PRG_ASSERT(currInstruction.numArg == 1);
00209     instr.GetUseType(reg,&currInstruction.Args[0]);
00210 
00211     // caso special: puntatore nullo
00212     if (currInstruction.Args[0].type == Param::t_literal)
00213     {
00214       if (IsNullAddress(currInstruction.Args[0].literal))
00215         return false;
00216       if (!codeInfo.module->GetSection(currInstruction.Args[0].literal)->IsCode())
00217       {
00218         // !!! segna da qualche parte
00219         return false;
00220       }
00221     }
00222 
00223     // se memoria esegui complesso memoria
00224     if (currInstruction.Args[0].type == Param::t_memory)
00225     {
00226       bResult = codeInfo.ExecuteComplexReferenceMemory(this->address,currInstruction);
00227       return false;
00228     }
00229 
00230     // se il reference e' ancora complesso non bisogna aggiungerlo
00231     if (!codeInfo.AddTempFlow(currInstruction.GetFlowType(),this->address,
00232            currInstruction,address,
00233            codeInfo.byteInfo[this->address].GetPriority(),false))
00234     {
00235       // sovrascrittura complessa
00236       // !!! finish (chiama ricorsivamente sccaner per funzioni complesse)
00237 #ifdef DEBUG
00238 //      fprintf(stderr,"Debug: unknow flow\n");
00239 #endif
00240       bResult = false;
00241     }
00242     return false;
00243   }
00244 
00245   return true;
00246 }
00247 
00248 bool CodeParser::ExecuteComplexReferenceReg(vma_t address,const Instruction& instruction)
00249 {
00250   _PRG_ASSERT(instruction.numArg == 1);
00251   _PRG_ASSERT(instruction.Args[0].type == Param::t_registry);
00252   reg_t reg = instruction.Args[0].mem_reg1;
00253   ScanningComplexReg scan(address,reg);
00254   ReverseScan(&scan,address);
00255   return scan.GetResult();
00256 }
00257 
00258 bool IsCodePointer(const ByteInfos& byteInfo,vma_t address)
00259 {
00260   const ByteInfo& info = byteInfo[address];
00261   if (info.len != addr_bytes)
00262     return false;
00263   if (info.GetType() != ByteInfo::typePointer)
00264     return false;
00265   return true;
00266 }
00267 
00268 bool CodeParser::ExecuteComplexReferenceMemory(vma_t address,const Instruction& instruction)
00269 {
00270   _PRG_ASSERT(instruction.numArg == 1);
00271   _PRG_ASSERT(instruction.Args[0].type == Param::t_memory);
00272   _PRG_ASSERT(&*module != NULL);
00273   const Param& arg = instruction.Args[0];
00274   // check for simple jmp dword ptr[reg*4+const]
00275   // !!! not portable
00276   // !!! un pochino semplificato
00277   if (arg.mem_reg1 == null_reg && arg.mem_reg2 != null_reg && arg.factor == addr_bytes)
00278   {
00279     // !!! gestire sovrapposizioni con codice
00280     if (ContainValidAddress(arg))
00281     {
00282       unsigned count = 0;
00283       bool isFirstValid = true;
00284       // !!! size constant
00285       try
00286       {
00287                                 ObjectModule::DataReader reader = module->GetDataReader(arg.literal);
00288         for(;;)
00289         {
00290           for(;;)
00291           {
00292             vma_t addr;
00293             // !!! la seconda volta sono gia' marcati
00294             if (byteInfo.IsOccupied(reader.Tell(),addr_bytes))
00295             {
00296               if (!IsCodePointer(byteInfo,reader.Tell()))
00297                 break;
00298             }
00299             if (module->HasRelocation() && !module->GetRelocationInfos().GetRelocation(reader.Tell()))
00300               break;
00301             addr = reader.ReadDword();
00302             if (!module->GetSection(addr)->IsCode())
00303               break;
00304             ++count;
00305           }
00306           if (count !=0)
00307             break;
00308           // ignora errore se e' il primo
00309           ++count;
00310           isFirstValid = false;
00311                                         // starting skipping first entry
00312                                         reader = reader = module->GetDataReader(arg.literal+addr_bytes);
00313         }
00314       }
00315       catch(const ObjectModule::OutOfAddress&) {}
00316       if (!isFirstValid)
00317         --count;
00318       if (count<=2) // !!! costante
00319         return false;
00320 
00321       // aggiunge tutti i puntatori per scandire codice
00322       enum ByteInfo::TPriority priority = byteInfo[address].GetPriority();
00323       vma_t tableAddress = arg.literal + (isFirstValid ? 0 : addr_bytes);
00324                         ObjectModule::DataReader reader = module->GetDataReader(tableAddress);
00325       for(; count != 0 ; --count)
00326       {
00327         ByteInfo& info = byteInfo[reader.Tell()];
00328         info.len = addr_bytes;
00329         info.SetType(ByteInfo::typePointer);
00330         info.SetPriority(priority);
00331         vma_t pointer = reader.ReadDword();
00332         AddTempFlow(instruction.GetFlowType(),address,pointer,priority);
00333       }
00334       byteInfo[tableAddress].SetIsLabel();
00335       return true;
00336     }
00337   }
00338 
00339   if (arg.mem_reg1 == null_reg && arg.mem_reg2 == null_reg && arg.GetMemSize() == (unsigned int)addr_bytes)
00340   {
00341     // se non e' un indirizzo invalido esci
00342     if (!ContainValidAddress(arg))
00343       return false;
00344 
00345     // processa contenuto corrente
00346     if (!module->HasRelocation() || module->GetRelocationInfos().GetRelocation(arg.literal))
00347     {
00348       vma_t addr;
00349                         ObjectModule::DataReader reader = module->GetDataReader(arg.literal);
00350       addr = reader.ReadDword();
00351       if (!IsNullAddress(addr) && module->GetSection(addr)->IsCode())
00352       {
00353         AddTempFlow(instruction.GetFlowType(),address,addr,
00354                     byteInfo[address].GetPriority());
00355       }
00356     }
00357 
00358           // processa riferimenti
00359     IstrReferences::iterator i   =
00360       varReferences.beginReferenceTo(arg.literal);
00361     IstrReferences::iterator end =
00362       varReferences.endReferenceTo(arg.literal);
00363 
00364     const ByteInfo& info = byteInfo[arg.literal];
00365 
00366     for(;i != end; ++i)
00367     {
00368       if ( !(*i).direct )
00369       {
00370         // la priorita' della chiamata e' la minima tra chiamata e memoria
00371         enum ByteInfo::TPriority priority = 
00372           f77_min(byteInfo[address].GetPriority(),info.GetPriority());
00373 
00374         // leggi istruzione
00375         Instruction instruction;
00376         int result = GetInstruction(*module,(*i).to,instruction);
00377         if (!result)
00378           return false;
00379 
00380         // !!! test brutale mov [xxx],xxx
00381         if (instruction.instruction == istr_mov && instruction.Args[0].type == Param::t_memory && instruction.Args[1].type == Param::t_literal)
00382         {
00383           _PRG_ASSERT(instruction.Args[0].mem_reg1 == null_reg);
00384           _PRG_ASSERT(instruction.Args[0].mem_reg2 == null_reg);
00385           _PRG_ASSERT(instruction.Args[0].literal  == arg.literal);
00386           if (ContainValidAddress(instruction.Args[1]))
00387             AddTempFlow(instruction.GetFlowType(),address,
00388                     instruction.Args[1].literal,
00389                     priority);
00390         }
00391       }
00392     }
00393     return true;
00394   }
00395 
00396   return false;
00397 }
00398 
00399 // cerca di "eseguire" un salto complesso
00400 bool CodeParser::ExecuteComplexReference(vma_t address)
00401 {
00402   _PRG_ASSERT(&*module != NULL);
00403 
00404   // leggi prossima istruzione
00405   Instruction currInstruction;
00406   int result = GetInstruction(*module,address,currInstruction);
00407   if (!result || currInstruction.numArg != 1)
00408   {
00409     // !!!
00410     _PRG_ASSERT(0);
00411     return false;
00412   }
00413 
00414   if ( currInstruction.Args[0].type == Param::t_registry )
00415     return ExecuteComplexReferenceReg(address,currInstruction);
00416 
00417   if ( currInstruction.Args[0].type == Param::t_memory )
00418     return ExecuteComplexReferenceMemory(address,currInstruction);
00419 
00420   return false;
00421 }
00422 
00423 

Generated on Mon Jan 13 22:20:34 2003 for perdr by doxygen1.2.15