00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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 #ifdef DEBUG
00045 static unsigned long int bytes;
00046 static unsigned long int jumps;
00047 static unsigned long int calls;
00048 static unsigned long int loopCount;
00049
00050 #endif
00051
00052 void WriteInstruction(const Instruction& instruction,FILE* file)
00053 {
00054 char buffer[80];
00055 instruction.Write(buffer);
00056 fprintf(file,"%s\n",buffer);
00057 }
00058
00059
00060 void CodeParser::CheckForAddress(vma_t instAddress,const Instruction& instruction,enum ByteInfo::TPriority priority)
00061 {
00062 for (int n=0; n < instruction.numArg; ++n)
00063 {
00064 const Param *param = &instruction.Args[n];
00065 switch (param->type)
00066 {
00067 case Param::t_literal:
00068 if (param->GetLiteralSize() != addr_bytes)
00069 break;
00070
00071 if (!ContainValidAddress(*param))
00072 break;
00073
00074 addrGeneral.insert(param->literal);
00075 break;
00076 case Param::t_memory:
00077
00078 if (!ContainValidAddress(*param))
00079 break;
00080
00081 if (param->mem_reg1 == null_reg && param->mem_reg2 == null_reg)
00082 {
00083
00084
00085 if ( param->GetMemSize() != 0 )
00086 {
00087 varReferences.Add(instAddress,param->literal,FLOW_NONE);
00088
00089
00090 if (!byteInfo.IsOccupied(param->literal,param->GetMemSize()))
00091 {
00092 ByteInfo& info = byteInfo[param->literal];
00093 if (info.GetPriority() < priority)
00094 {
00095 info.len = param->GetMemSize();
00096
00097 info.SetType(ByteInfo::typeInteger);
00098 info.SetPriority(priority);
00099 info.SetIsLabel();
00100 }
00101 }
00102 break;
00103 }
00104 }
00105
00106 addrGeneral.insert(param->literal);
00107 break;
00108 }
00109 }
00110 }
00111
00112
00113 void CodeParser::CheckImmediateCodeAddress(const Instruction& instruction)
00114 {
00115 vma_t address;
00116 const Param *param;
00117 switch(instruction.instruction)
00118 {
00119
00120
00121
00122 case istr_mov:
00123 _PRG_ASSERT(instruction.numArg >= 2);
00124 _PRG_ASSERT(instruction.Args[1].type != Param::t_literal || instruction.Args[1].GetLiteralSize() != 0);
00125 param = &instruction.Args[1];
00126 goto addr_ok;
00127 case istr_push:
00128 param = &instruction.Args[0];
00129 addr_ok:
00130
00131 if ( param->type != Param::t_literal || param->GetLiteralSize() != addr_bytes )
00132 break;
00133 address = param->literal;
00134
00135
00136 if (!ContainValidAddress(*param))
00137 break;
00138
00139 addrConstants.insert(address);
00140 break;
00141 }
00142 }
00143
00144 void CodeParser::AddTempFlow(enum FlowTypes flow,vma_t from,vma_t to,
00145 enum ByteInfo::TPriority priority)
00146 {
00147 if (flow == FLOW_NONE || flow == FLOW_RET)
00148 return;
00149
00150
00151 #ifdef DEBUG
00152 int inc = (priority == ByteInfo::priCheckOnly)?0:1;
00153 #endif
00154
00155 TempReference tempRef;
00156 tempRef.from = from;
00157 tempRef.type = flow;
00158 tempRef.to = to;
00159 tempRef.priority = static_cast<uchar>(priority);
00160
00161 if (istrReferences.IsPresent(tempRef.from,tempRef.to))
00162 return;
00163
00164 switch(flow)
00165 {
00166 case FLOW_CALL:
00167 pTempRefs->push(tempRef);
00168 #ifdef DEBUG
00169 calls += inc;
00170 #endif
00171 break;
00172 case FLOW_CJUMP:
00173 case FLOW_JUMP:
00174 pTempRefs->push(tempRef);
00175 #ifdef DEBUG
00176 jumps += inc;
00177 #endif
00178 break;
00179 }
00180 }
00181
00182
00183 bool CodeParser::AddTempFlow(enum FlowTypes flow,vma_t from,
00184 const Instruction& instruction,vma_t instAddress,
00185 enum ByteInfo::TPriority priority,bool bAddComplex)
00186 {
00187 if (flow == FLOW_NONE || flow == FLOW_RET)
00188 return true;
00189
00190 const Param ¶m = instruction.Args[0];
00191 if (param.type != Param::t_literal)
00192 {
00193
00194 if (param.type == Param::t_memory)
00195 if (param.mem_reg1 == null_reg && param.mem_reg2 == null_reg)
00196 {
00197 if ( ContainValidAddress(param) )
00198 {
00199 pair<Symbols::iterator,Symbols::iterator> sym = module->GetSymbols()[param.literal];
00200 if ( sym.first != sym.second )
00201 {
00202 if (flow == FLOW_JUMP)
00203 {
00204 apiAlias[from] = param.literal;
00205 }
00206 return true;
00207 }
00208 }
00209 }
00210
00211
00212
00213
00214
00215 if (bAddComplex && priority != ByteInfo::priCheckOnly)
00216 complexReference.insert(instAddress);
00217 #if 0
00218 #ifdef DEBUG
00219 fprintf(stderr,"Debug: (Flow) ");
00220 WriteInstruction(instruction,stderr);
00221 #endif
00222 #endif
00223 return false;
00224 }
00225
00226
00227
00228
00229 AddTempFlow(flow,from,instruction.Args[0].literal,priority);
00230 return true;
00231 }
00232
00233 void CodeParser::AddExportTempFlow(vma_t to,enum ByteInfo::TPriority priority)
00234 {
00235 _PRG_ASSERT(pTempRefs != NULL);
00236
00237
00238 if ( istrReferences.beginReferenceTo(to) !=
00239 istrReferences.endReferenceTo(to) )
00240 return;
00241
00242 TempReference tempRef;
00243 tempRef.from = 0;
00244 tempRef.type = FLOW_NONE;
00245 tempRef.to = to;
00246 tempRef.priority = static_cast<uchar>(priority);
00247
00248 pTempRefs->push(tempRef);
00249 }
00250
00251
00252 bool CodeParser::ExtractTempRef(TempReference& tempRef)
00253 {
00254
00255 _PRG_ASSERT((pTempRefs!=NULL));
00256
00257 if (pTempRefs->empty())
00258 return false;
00259
00260
00261 tempRef = pTempRefs->top();
00262 pTempRefs->pop();
00263
00264
00265 if (tempRef.priority == ByteInfo::priCheckOnly)
00266 return true;
00267
00268
00269 switch(tempRef.type)
00270 {
00271 case FLOW_CALL:
00272 istrReferences.Add(tempRef.from,tempRef.to,tempRef.type);
00273 #ifdef DEBUG
00274 --calls;
00275 #endif
00276 break;
00277 case FLOW_CJUMP:
00278 case FLOW_JUMP:
00279 istrReferences.Add(tempRef.from,tempRef.to,tempRef.type);
00280 #ifdef DEBUG
00281 --jumps;
00282 #endif
00283 break;
00284 }
00285
00286 return true;
00287 }
00288
00289
00290 bool CodeParser::IsApiReference(const Param& arg) const
00291 {
00292
00293 if (arg.type == Param::t_memory)
00294 {
00295
00296 if (ContainValidAddress(arg))
00297 if (arg.mem_reg1 == null_reg && arg.mem_reg2 == null_reg)
00298 {
00299 _PRG_ASSERT(module!=NULL);
00300 if (module->GetSymbols().IsValid(arg.literal))
00301 return true;
00302 }
00303 return false;
00304 }
00305 if (arg.type == Param::t_literal)
00306 {
00307
00308 TApiAlias::const_iterator i = apiAlias.find(arg.literal);
00309 if (i != apiAlias.end())
00310 {
00311 _PRG_ASSERT(module!=NULL);
00312 if (module->GetSymbols().IsValid((*i).second))
00313 return true;
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323 }
00324 return false;
00325 }
00326
00327 #ifdef DEBUG
00328 static bool printIstr = false;
00329 #endif
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 enum CodeParser::TScanCodeResult CodeParser::ScanCode(vma_t& address,ByteInfo::TPriority priority,bool bSetLabel)
00340 {
00341 InstructionDecoder decoder(module->GetRelocationInfos());
00342
00343
00344 if ( priority != ByteInfo::priMax && byteInfo.GetIstrLen(address)==0
00345 && byteInfo.IsOccupied(address) )
00346 {
00347 return scanCodeOverlapped;
00348 }
00349
00350 bool bFirst = true;
00351 ObjectModule::DataReader reader = module->GetDataReader(address);
00352 for(;;)
00353 {
00354 #ifdef DEBUG
00355
00356
00357 #endif
00358
00359 ByteInfo &info = byteInfo[address];
00360
00361
00362
00363 if (bFirst && bSetLabel)
00364 info.SetIsLabel();
00365
00366
00367 if ( info.len != 0 && priority <= info.GetPriority() )
00368 {
00369
00370
00371 if (!bFirst && priority != ByteInfo::priCheckOnly)
00372 info.SetIsPrevInstruction();
00373 if (bFirst)
00374 return scanCodeAlreadyProcessed;
00375 if (info.GetType() != ByteInfo::typeInstruction)
00376 return scanCodeInvalid;
00377 break;
00378 }
00379
00380
00381 Instruction currInstruction;
00382 int result = decoder.Decode(currInstruction,reader);
00383
00384
00385
00386
00387
00388 if (!result)
00389 return scanCodeInvalid;
00390
00391 #ifdef DEBUG
00392 if (printIstr)
00393 WriteInstruction(currInstruction);
00394 #endif
00395
00396
00397 if ( priority != ByteInfo::priMax && byteInfo.GetIstrLen(address)==0
00398 && byteInfo.IsOccupied(address+result-1) )
00399 {
00400
00401 return scanCodeOverlapped;
00402 }
00403
00404
00405 enum FlowTypes flow = currInstruction.GetFlowType();
00406
00407
00408
00409 if ( priority <= ByteInfo::priConstant )
00410 if ( flow == FLOW_JUMP || flow == FLOW_CJUMP || flow == FLOW_CALL )
00411 if ( currInstruction.Args[0].type == Param::t_literal )
00412 {
00413 if (!module->GetSection(currInstruction.Args[0].literal)->IsCode())
00414 return scanCodeInvalidJump;
00415 }
00416
00417
00418 #ifdef DEBUG
00419 if ( ((++loopCount) & 0x3f) == 0 )
00420 fprintf(stderr,"Process: (Code) bytes: %lu calls: %lu jumps: %lu\n",
00421 bytes,calls,jumps);
00422 #endif
00423
00424
00425 info.len = (uchar)result;
00426
00427
00428 if (info.GetPriority() < priority)
00429 {
00430 info.SetPriority(priority);
00431 #ifdef DEBUG
00432 bytes += result;
00433 #endif
00434 }
00435
00436
00437 if (!bFirst)
00438 info.SetIsPrevInstruction();
00439
00440
00441
00442
00443
00444 AddTempFlow(flow,address,currInstruction,address,priority);
00445
00446
00447
00448 if (priority != ByteInfo::priCheckOnly)
00449 {
00450 CheckImmediateCodeAddress(currInstruction);
00451 CheckForAddress(address,currInstruction,priority);
00452 }
00453
00454
00455 if (flow == FLOW_JUMP || flow == FLOW_RET)
00456 {
00457 break;
00458 }
00459
00460
00461 address += result;
00462 bFirst = false;
00463 }
00464 return scanCodeNoError;
00465 }
00466
00467 void CodeParser::ResetCodeRange(const range<vma_t>& r)
00468 {
00469 for(vma_t address = r.begin;;)
00470 {
00471 _PRG_ASSERT(address <= r.end);
00472 ByteInfo& info = byteInfo[address];
00473 _PRG_ASSERT(info.len != 0 || address == r.end);
00474 _PRG_ASSERT(info.GetPriority() == ByteInfo::priCheckOnly || address == r.end);
00475 int len = info.len;
00476 if (info.GetPriority() == ByteInfo::priCheckOnly)
00477 {
00478
00479 info.Reset();
00480 }
00481 if (address == r.end)
00482 break;
00483 address += len;
00484 }
00485 }
00486
00487 void CodeParser::SetCodeRange(const range<vma_t>& r,ByteInfo::TPriority priority,bool bSetLabel)
00488 {
00489 vma_t begin = r.begin;
00490 #ifdef DEBUG
00491
00492 #endif
00493 ScanCode(begin,priority,bSetLabel);
00494
00495
00496
00497
00498
00499
00500 }
00501
00502
00503
00504
00505
00506 bool CodeParser::CheckCode(vma_t& address,ByteInfo::TPriority priority,bool bSetLabel)
00507 {
00508 _PRG_ASSERT(pTempRefs->size() == 0);
00509 TScanCodeResult lastResult = scanCodeNoError;
00510
00511
00512 vma_t start = address;
00513 vma_t scanAddress;
00514 try
00515 {
00516 scanAddress = start;
00517 lastResult = ScanCode(scanAddress,ByteInfo::priCheckOnly,bSetLabel);
00518 }
00519 catch(const ObjectModule::OutOfAddress&)
00520 {
00521 lastResult = scanCodeInvalid;
00522 }
00523 for (TempReference tempRef;ExtractTempRef(tempRef););
00524
00525
00526 if (lastResult <= scanCodeNoError)
00527 SetCodeRange(range<vma_t>(start,scanAddress),priority,bSetLabel);
00528 else
00529 ResetCodeRange(range<vma_t>(start,scanAddress));
00530 {for (TempReference tempRef;ExtractTempRef(tempRef););}
00531
00532 address = scanAddress;
00533
00534 return (lastResult <= scanCodeNoError);
00535 }
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549 bool CodeParser::CheckCodeRecursively(vma_t address,ByteInfo::TPriority priority,bool _bSetLabel)
00550 {
00551 _PRG_ASSERT(pTempRefs->size() == 0);
00552
00553
00554 range_set<vma_t> ranges;
00555
00556 TAddresses addresses;
00557 TScanCodeResult lastResult = scanCodeNoError;
00558 bool bSetLabel = _bSetLabel;
00559
00560
00561 AddExportTempFlow(address,ByteInfo::priCheckOnly);
00562 for (;;)
00563 {
00564 TempReference tempRef;
00565 if (!ExtractTempRef(tempRef))
00566 break;
00567
00568
00569 vma_t address = tempRef.to;
00570 try
00571 {
00572 lastResult = ScanCode(address,ByteInfo::priCheckOnly,bSetLabel);
00573 }
00574 catch(const ObjectModule::OutOfAddress&)
00575 {
00576 lastResult = scanCodeInvalid;
00577 }
00578
00579
00580 bSetLabel = true;
00581
00582
00583 _PRG_ASSERT(tempRef.to <= address);
00584 if ( tempRef.to == address)
00585 addresses.insert(tempRef.to);
00586 else
00587 ranges.insert(range<vma_t>(tempRef.to,address));
00588
00589
00590 if (lastResult > scanCodeNoError)
00591 break;
00592 }
00593
00594
00595 {
00596 typedef range_set<vma_t>::iterator iterator;
00597 iterator i = ranges.begin();
00598 iterator end = ranges.end();
00599 for(;i!=end;++i)
00600 {
00601 if (lastResult <= scanCodeNoError)
00602 SetCodeRange(*i,priority,_bSetLabel || (*i).begin != address);
00603 else
00604
00605
00606
00607 ResetCodeRange(*i);
00608 }
00609 }
00610
00611
00612 {
00613 typedef TAddresses::iterator iterator;
00614 iterator i = addresses.begin();
00615 iterator end = addresses.end();
00616 for(;i!=end;++i)
00617 {
00618 if (lastResult <= scanCodeNoError)
00619 SetCodeRange(range<vma_t>(*i,*i),priority,_bSetLabel || (*i) != address);
00620 else
00621
00622
00623
00624 ResetCodeRange(range<vma_t>(*i,*i));
00625 }
00626 }
00627
00628
00629 for (TempReference tempRef;ExtractTempRef(tempRef););
00630
00631 return (lastResult <= scanCodeNoError);
00632 }
00633
00634 int GetInstruction(ObjectModule& module,vma_t address,Instruction& instruction)
00635 {
00636
00637 InstructionDecoder decoder(module.GetRelocationInfos());
00638 ObjectModule::DataReader reader = module.GetDataReader(address);
00639 return decoder.Decode(instruction,reader);
00640 }
00641
00642 void CodeParser::ExcludeFileRange(CSignFile& _file,const RVAFileTranslator& rva,uint32_t imageBase)
00643 {
00644 range_set<long> excludeRange = _file.GetRanges();
00645 range_set<long>::iterator i = excludeRange.begin();
00646 range_set<long>::iterator end = excludeRange.end();
00647 for( ;i!= end; ++i)
00648 {
00649
00650 vma_t start;
00651 vma_t finish;
00652 try
00653 {
00654 start = rva.File2RVASafe((*i).begin) + imageBase;
00655 finish = rva.File2RVASafe((*i).end-1) + imageBase;
00656 }
00657 catch(std::runtime_error&)
00658 { continue; }
00659
00660
00661
00662 range<long> r = *i;
00663
00664
00665
00666 while( (finish-start+1) != static_cast<unsigned long>(r.end - r.begin) )
00667 {
00668
00669 const PeSection *p;
00670 for(unsigned n=0;; ++n)
00671 {
00672 p = rva.GetSection(n);
00673 if (p == NULL)
00674 {
00675 throw runtime_error("I think there is a bug inside");
00676 }
00677 if ((unsigned long)r.begin >= p->RawAddress && ((unsigned long)r.begin-p->RawAddress) < p->RawSize)
00678 {
00679
00680 ByteInfo& info = byteInfo[start];
00681 info.SetPriority(ByteInfo::priMax);
00682 info.SetType(ByteInfo::typeLoader);
00683
00684
00685 byteInfo.SetLen(start,p->RawSize - (r.begin-p->RawAddress) );
00686
00687
00688 r.begin = p->RawAddress+p->RawSize;
00689 start = rva.File2RVASafe(r.begin) + imageBase;
00690 break;
00691 }
00692 }
00693 }
00694
00695
00696 ByteInfo& info = byteInfo[start];
00697 info.SetPriority(ByteInfo::priMax);
00698 info.SetType(ByteInfo::typeLoader);
00699
00700
00701 byteInfo.SetLen(start,finish-start+1);
00702 }
00703 }
00704
00705
00706 void CodeParser::Parse(CSignFile& _file,uint32_t imageBase,vma_t _entryPoint,
00707 const RVAFileTranslator& rva,const Symbols& _symbols,const Symbols& _exportedSymbols,
00708 bool hasRelocation,const RelocationInfos& relocationInfos)
00709 {
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733 #ifdef DEBUG
00734 unsigned maxStringInCode = 0;
00735 unsigned currStringLen = 0;
00736 unsigned istrCount[num_instructions];
00737 memset(&istrCount,0,sizeof(istrCount));
00738 #endif
00739
00740
00741 ExcludeFileRange(_file,rva,imageBase);
00742
00743 ObjectModule _module(_file,rva,imageBase,hasRelocation,relocationInfos,
00744 _symbols,_exportedSymbols,_entryPoint);
00745
00746 this->module = &_module;
00747
00748 vma_t end;
00749
00750
00751 int numCodeSections = 0;
00752 FOR_EACH_SECTION_CODE_BEGIN(module,p)
00753 if ( (*p).IsCode() )
00754 ++numCodeSections;
00755 FOR_EACH_SECTION_CODE_END(module,p)
00756 if (numCodeSections == 0)
00757 return;
00758
00759 #ifdef DEBUG
00760 bytes = 0;
00761 bytes = jumps = calls = 0;
00762 loopCount = 0;
00763 #endif
00764 pTempRefs = new TTempRefs;
00765
00766
00767
00768 for(vma_t address = module->GetExportSymbols().GetNextValid(0); !IsNullAddress(address); address = module->GetExportSymbols().GetNextValid(address))
00769 if (module->GetSection(address)->IsCode())
00770 {
00771
00772 CheckCodeRecursively(address,ByteInfo::priExport);
00773 }
00774 if (!IsNullAddress(module->GetEntryPoint()))
00775 AddExportTempFlow(module->GetEntryPoint(),ByteInfo::priEntryPoint);
00776
00777 bool bProcessed = false;
00778
00779 bool bFlowChangedSinceReference = false;
00780
00781 bool bFlowChangedSinceApi = false;
00782
00783 bool bSomeUnknown = false;
00784 bool bUseConstantPrinted = false;
00785
00786 freddy77::auto_delete_ptr<THeuristicMotor> heuristics;
00787
00788
00789
00790 for(;;)
00791 {
00792
00793
00794
00795
00796 for(;;)
00797 {
00798
00799 TempReference tempRef;
00800 if (!ExtractTempRef(tempRef))
00801 break;
00802
00803
00804 vma_t address = tempRef.to;
00805
00806 if (ScanCode(address,static_cast<ByteInfo::TPriority>(tempRef.priority)) !=
00807 scanCodeAlreadyProcessed && address != tempRef.to)
00808
00809 bProcessed = true;
00810 }
00811
00812
00813 if (bProcessed)
00814 {
00815 bFlowChangedSinceApi = true;
00816 bFlowChangedSinceReference = true;
00817 bSomeUnknown = false;
00818 }
00819
00820
00821 if (bFlowChangedSinceReference && !bSomeUnknown) for(bProcessed = false;;)
00822 {
00823 bFlowChangedSinceReference = false;
00824
00825
00826
00827 if ( complexReference.empty() )
00828 break;
00829
00830 #if 0
00831 #ifdef DEBUG
00832 {
00833 TTempComplexReference::iterator i = complexReference.begin();
00834 for(int n=1;i != complexReference.end();++i,++n)
00835 {
00836 if ( (n%6) == 1 )
00837 fprintf(stderr,"Debug: (Complex) ");
00838 fprintf(stderr,(n%6==0)?"%08lX\n":"%08lX ",unsigned(*i));
00839 }
00840 fprintf(stderr,"\n");
00841 }
00842 #endif
00843 #endif
00844
00845
00846 TTempComplexReference::iterator i = complexReference.begin();
00847 #ifdef DEBUG
00848 unsigned numUnknown = 0;
00849 unsigned numKnown = 0;
00850 #endif
00851 for(;i != complexReference.end();++i)
00852 {
00853 if (!ExecuteComplexReference(*i))
00854 {
00855
00856
00857 bSomeUnknown = true;
00858 _DEBUG_(++numUnknown);
00859 }
00860 else
00861 {
00862
00863 bProcessed = true;
00864 _DEBUG_(++numKnown);
00865 }
00866 }
00867 #ifdef DEBUG
00868 if ( (numKnown+numUnknown) != 0 )
00869 fprintf(stderr,"Debug: (Complex) Perc %f\n",
00870 float(((double)numKnown*100)/(numKnown+numUnknown)));
00871 #endif
00872
00873
00874
00875 break;
00876 }
00877 if (bProcessed)
00878 {
00879
00880 bProcessed = false;
00881 continue;
00882 }
00883
00884
00885
00886
00887 if (bFlowChangedSinceApi && !bSomeUnknown) for(bProcessed = false;;)
00888 {
00889 bFlowChangedSinceApi = false;
00890 bSomeUnknown = true;
00891
00892
00893 break;
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904 }
00905 if (bProcessed)
00906 {
00907
00908 bProcessed = false;
00909 continue;
00910 }
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951 if (!&*heuristics)
00952 heuristics = new THeuristicMotor(*this);
00953
00954 if ( (bProcessed=heuristics->ProcessSecure(*this)) != false )
00955 continue;
00956
00957 if (!bUseConstantPrinted)
00958 {
00959 #ifdef DEBUG
00960 {
00961 unsigned bytes = 0;
00962 FOR_EACH_SECTION_CODE_BEGIN(module,p)
00963 vma_t address = (*p).begin;
00964 end = (*p).end;
00965 for(; address<end; )
00966 {
00967 int len = byteInfo.GetIstrLen(address);
00968 if (len != 0)
00969 {
00970 bytes += len;
00971 address += len;
00972 }
00973 else
00974 ++address;
00975 }
00976 FOR_EACH_SECTION_CODE_END(module,p)
00977 unsigned codeSize = 0;
00978 FOR_EACH_SECTION_CODE_BEGIN(module,p)
00979 codeSize += (*p).end - (*p).begin;
00980 FOR_EACH_SECTION_CODE_END(module,p)
00981 if (codeSize)
00982 fprintf(stderr,"\"Secure code\" %.1f%%\n",
00983 float(((double)bytes*100)/codeSize) );
00984 }
00985 #endif
00986
00987 fprintf(stderr,"Warning: Constant processed\n");
00988 if (complexReference.empty())
00989 fprintf(stderr,"Wow: complex reference is empty\n");
00990 if (addrConstants.empty())
00991 fprintf(stderr,"Wow: Constants address empty\n");
00992 bUseConstantPrinted = true;
00993 }
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003 for(;;)
01004 {
01005 if ( addrConstants.begin() == addrConstants.end() )
01006 break;
01007
01008 vma_t address = *addrConstants.begin();
01009 addrConstants.erase(addrConstants.begin());
01010
01011
01012
01013
01014 unsigned len,printable;
01015 GetStringStats(address,len,printable);
01016
01017
01018 if ( len >0 && printable>2 && printable*100 > (len-1)*75 )
01019 {
01020 ByteInfo& info = byteInfo[address];
01021
01022 info.SetPriority(ByteInfo::priConstant);
01023 info.SetType(ByteInfo::typeASCIIZ);
01024
01025 byteInfo.SetLen(address,len);
01026 continue;
01027 }
01028
01029
01030 PointerArrayStat pStat;
01031 GetPointerArrayStats(address,pStat);
01032
01033 if ( pStat.nFirstNull >= 2 )
01034 {
01035
01036
01037 if (pStat.nCodePointer >= pStat.nFirstNull)
01038 {
01039 for(unsigned n=0; n<pStat.nPointer;++n,address+=addr_bytes)
01040 {
01041
01042 ByteInfo& info = byteInfo[address];
01043 info.len = addr_bytes;
01044 info.SetType(ByteInfo::typePointer);
01045 info.SetPriority(ByteInfo::priConstant);
01046
01047
01048 ObjectModule::DataReader reader = module->GetDataReader(address);
01049 vma_t addr = reader.ReadDword();
01050 if (IsNullAddress(addr))
01051 {
01052
01053 if (!module->GetSection(addr)->IsCode())
01054 break;
01055
01056 if (CheckCodeRecursively(addr,ByteInfo::priConstant))
01057 bProcessed = true;
01058 }
01059 }
01060 }
01061 continue;
01062 }
01063
01064
01065
01066
01067
01068
01069 if (module->GetSection(address)->IsCode())
01070 if (CheckCodeRecursively(address,ByteInfo::priConstant))
01071 {
01072 bProcessed = true;
01073 }
01074 }
01075
01076 if (bProcessed)
01077 continue;
01078
01079 _PRG_ASSERT(pTempRefs->empty());
01080 _PRG_ASSERT(addrConstants.empty());
01081
01082
01083
01084
01085 break;
01086 }
01087
01088
01089
01090
01091
01092 FOR_EACH_SECTION_CODE_BEGIN(module,p)
01093 vma_t address = (*p).begin;
01094 end = (*p).end;
01095 for(; address<end; )
01096 {
01097 ObjectModule::DataReader reader = module->GetDataReader(address);
01098
01099 int len = byteInfo.GetIstrLen(address);
01100
01101
01102 if (len != 0)
01103 {
01104 #ifdef DEBUG
01105
01106
01107 Instruction currInstruction;
01108 int result = GetInstruction(*module,address,currInstruction);
01109 if (result)
01110 {
01111 _PRG_ASSERT(currInstruction.instruction>=0);
01112 _PRG_ASSERT(currInstruction.instruction<=num_instructions);
01113 ++istrCount[currInstruction.instruction];
01114 ObjectModule::DataReader reader = module->GetDataReader(address);
01115 for (int i=0;i<len;++i)
01116 {
01117 int c = reader.ReadByte();
01118 if (isprint(c))
01119 {
01120 ++currStringLen;
01121 if ( currStringLen > maxStringInCode )
01122 {
01123 maxStringInCode = currStringLen;
01124 }
01125 }
01126 else
01127 currStringLen = 0;
01128 }
01129
01130 }
01131 #endif
01132 address += len;
01133 continue;
01134 }
01135 _DEBUG_(currStringLen = 0);
01136
01137
01138 const Relocation *rel =
01139 module->GetRelocationInfos().GetRelocation(address,addr_bytes);
01140 if (rel && rel != &RelocationInfos::relError)
01141 {
01142 ByteInfo& info = byteInfo[address];
01143 info.len = addr_bytes;
01144 info.SetType(ByteInfo::typeInteger);
01145 info.SetPriority(ByteInfo::priFiller);
01146
01147 address += addr_bytes;
01148 continue;
01149 }
01150
01151
01152 int c;
01153 try {
01154 c = reader.ReadByte();
01155 }
01156 catch (ObjectModule::OutOfAddress&)
01157 {
01158 return;
01159 }
01160
01161
01162 _PRG_ASSERT(len ==0);
01163 if ( c==0 )
01164 {
01165 _DEBUG_(currStringLen = 0);
01166 do
01167 {
01168 try {
01169 c = reader.ReadByte();
01170 }
01171 catch (ObjectModule::OutOfAddress&)
01172 {
01173 c = -1;
01174 }
01175 len = byteInfo.GetIstrLen(++address);
01176 } while ( c==0 && len==0
01177 && !module->GetRelocationInfos().GetRelocation(address)
01178 && address<end );
01179 continue;
01180 }
01181
01182
01183 vma_t checkAddr = address;
01184 if ( !CheckCode(checkAddr,ByteInfo::priFiller) )
01185 {
01186
01187
01188
01189 ++address;
01190 }
01191
01192
01193
01194 }
01195 FOR_EACH_SECTION_CODE_END(module,p)
01196
01197
01198 for (TempReference tempRef;ExtractTempRef(tempRef););
01199
01200 #ifdef DEBUG
01201 fprintf(stderr,"Stat: (Code) MaxStringLenInCode: %u\n",maxStringInCode);
01202 for (unsigned ni=0; ni<num_instructions; ++ni)
01203 if (istrCount[ni])
01204 fprintf(stderr,"Stat: (Instr) %s: %u\n",
01205 x86instructions_names[ni],istrCount[ni]);
01206 #endif
01207
01208 WriteCode();
01209
01210
01211 delete pTempRefs;
01212 pTempRefs = NULL;
01213
01214 this->module = NULL;
01215 }
01216
01217 void ParseCode(CSignFile& file,uint32_t imageBase,vma_t entryPoint,const RVAFileTranslator& rva,const Symbols& symbols,const Symbols& exportedSymbols,bool hasRelocation,const RelocationInfos& relocationInfos)
01218 {
01219 CodeParser* p = new CodeParser;
01220 p->Parse(file,imageBase,entryPoint,rva,symbols,exportedSymbols,hasRelocation,relocationInfos);
01221 delete p;
01222 }
01223
01224
01225