Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

heuristic.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 "heuristic.h"
00031 
00032 using namespace std;
00033 
00034 THeuristicMotor::THeuristicMotor(const CodeParser& codeInfo)
00035 {
00036   // numero consecutivo di indirizzi a codice
00037 //  unsigned numAddress = 0;
00038 //  vector<vma_t> lastAddress;
00039 
00040   FOR_EACH_SECTION_CODE_BEGIN(codeInfo.module,p)
00041     vma_t address = (*p).begin;
00042     vma_t end     = (*p).end;
00043     for(; address<end; )
00044     {
00045       bool processed = false;
00046       // salta istruzioni gia' processate
00047       int len = 1,l;
00048       if ( (l=codeInfo.byteInfo.GetIstrLen(address)) != 0)
00049       {
00050         len = l;
00051         processed = true;
00052         // se non e' istruzione non processare
00053         // se sono data sono gia' stati processati
00054         if (codeInfo.byteInfo[address].GetType() != ByteInfo::typeInstruction)
00055         {
00056           address += len;
00057           continue;
00058         }
00059         //address += (len-1);
00060         //continue;
00061       }
00062 
00063         Instruction instruction;
00064         int res = GetInstruction(*codeInfo.module,address,instruction);
00065 
00066         // !!! size constant
00067         if (res > addr_bytes)
00068         {
00069           enum FlowTypes flow = instruction.GetFlowType();
00070           switch (flow)
00071           {
00072           case FLOW_CALL:
00073             _PRG_ASSERT(instruction.numArg == 1);
00074             // !!! constant
00075             // !!! questo primo test serve perche' non si prendano anche certi
00076             // prefissi che potrebbero appertenere ad altre istruzioni
00077             if (res==5 && instruction.Args[0].type == Param::t_literal)
00078             {
00079               if (codeInfo.module->GetSection(instruction.Args[0].literal)->IsCode())
00080                 constCallCount[instruction.Args[0].literal].push_back(address+res);
00081             }
00082             if (codeInfo.IsApiReference(instruction.Args[0]))
00083             {
00084               callApi.insert(address+res);
00085             }
00086           case FLOW_JUMP:
00087 //          if (IsApiReference(instruction.Args[0]))
00088 //          {
00089 //            callApi.insert();
00090 //          }
00091             break;
00092           }
00093         }
00094 
00095         // processa argomenti memoria per vedere riferimenti costanti
00096         for (int n=0; n < instruction.numArg; ++n)
00097           if (instruction.Args[n].GetType() == Param::t_memory)
00098           {
00099             // se argomento [xxx] aggiungi alla lista
00100             Param &param = instruction.Args[n];
00101             if (param.mem_reg1 == null_reg && param.mem_reg2 == null_reg)
00102             {
00103               if (codeInfo.ContainValidAddress(param))
00104                 globalVarCount[param.literal].push_back(address+res);
00105             }
00106           }
00107 /*
00108       // !!! la scansione di tutti gli indirizzi non mi sembra molto "euristica"
00109       // processa puntatori nel codice e nei dati
00110       for(;;)
00111       {
00112         if (processed)
00113           break;
00114 
00115         // test non occupato
00116         vma_t addr;
00117         if (::byteInfo.IsOccupied(address,addr_bytes))
00118           break;
00119 
00120         // test relocation
00121         if (hasRelocation && relocationInfos.GetRelocationType(address) == Relocation::relNone)
00122           break;
00123 
00124         // test indirizzo valido
00125         addr = module->ReadDword(address);
00126         if (!hasRelocation && !module->IsValid(addr))
00127           break;
00128 
00129         // inserisci indirizzo in costanti
00130         addrConstants.insert(addr);
00131         break;
00132       }
00133 */
00134       address += len;
00135     }
00136   FOR_EACH_SECTION_CODE_END(module,p)
00137 }
00138 
00139 bool THeuristicMotor::Process(unsigned minimun,enum ByteInfo::TPriority priority,CodeParser& codeInfo)
00140 {
00141   // !!! 1 e 3 problemi con AddTempFlow
00142   //1- chiamate call costante con costante che e' gia' stata chiamata.
00143   //   (rientra nel caso 2 se chiamata fissa)
00144   //*2- chiamate call costante con costante che si trova piu volte (>1).
00145   //*3- jmp/chiamata ad export api o api export (gia' in 1??)
00146   //   (se call istruzioni seguenti)
00147   //4- chiamate call costante con costante che si trova una volta (non sicuro).
00148   //5- Costanti generiche. Verificare che non siano stringhe (non sicuro).
00149   //6-? Costanti che puntano al codice (non sicuro).
00150 
00151   // processa chiamate a chiamate a api
00152   while(callApi.begin() != callApi.end())
00153   {
00154     // toglie primo elemento
00155     vma_t address = *callApi.begin();
00156     callApi.erase(callApi.begin());
00157 
00158     // scandisce a partire da dopo la chiamata
00159 
00160     codeInfo.CheckCodeRecursively(address,priority,false);
00161   }
00162 
00163   unsigned maxConstCount = 0;
00164   FOR_EACH_BEGIN(TConstCallCount,constCallCount,p)
00165     if ( (*p).second.size() > maxConstCount )
00166       maxConstCount = (*p).second.size();
00167   FOR_EACH_END(TConstCallCount,constCallCount,p)
00168 
00169   // dividere in due procedure (stesse variabili)
00170   FOR_EACH_BEGIN(TConstCallCount,globalVarCount,p)
00171     if ( (*p).second.size() > maxConstCount )
00172       maxConstCount = (*p).second.size();
00173   FOR_EACH_END(TConstCallCount,globalVarCount,p)
00174 
00175   // !!! more checks for 1 ??
00176   // for unsecure heuristic check for validity of code following all calls
00177   bool bResult = false;;
00178   if (maxConstCount >= minimun)
00179   {
00180     maxConstCount = f77_min(maxConstCount,4u); // 4 or more is secure
00181     // !!! usare remove_if ??
00182     bool bFinded;
00183     do
00184     {
00185       bFinded = false;
00186       FOR_EACH_BEGIN(TConstCallCount,constCallCount,p)
00187         if ( (*p).second.size() >= maxConstCount )
00188         {
00189           codeInfo.CheckCodeRecursively((*p).first,priority);
00190           FOR_EACH_BEGIN(TAddress,(*p).second,i)
00191             // scandisce a iniziare dopo la chiamata senza settare Label
00192             codeInfo.CheckCodeRecursively(*i,priority,false);
00193           FOR_EACH_END(TAddress,(*p).second,i)
00194           constCallCount.erase(p);
00195           bFinded = true;
00196           bResult = true;
00197           break;
00198         }
00199       FOR_EACH_END(TConstCallCount,(*constCallCount),p)
00200     } while (bFinded);
00201 
00202     // scan data references
00203     do
00204     {
00205       bFinded = false;
00206       FOR_EACH_BEGIN(TConstCallCount,globalVarCount,p)
00207         if ( (*p).second.size() >= maxConstCount )
00208         {
00209           // !!! non testare dall'indirizzo (dati presenti)
00210           FOR_EACH_BEGIN(TAddress,(*p).second,i)
00211             // scandisce a iniziare dopo la chiamata senza settare Label
00212             codeInfo.CheckCodeRecursively(*i,priority,false);
00213           FOR_EACH_END(TAddress,(*p).second,i)
00214           globalVarCount.erase(p);
00215           bFinded = true;
00216           bResult = true;
00217           break;
00218         }
00219       FOR_EACH_END(TConstCallCount,globalVarCount,p)
00220     } while (bFinded);
00221   }
00222   return bResult;
00223 }
00224 

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