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: https://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