Make your own free website on Tripod.com
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: 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 "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