1 #include "pe_analyzer.h"
2 #include "pe_utils.h"
3 #include "pe_constants.h"
4 #include "../../support/rtti/msvc/rtti_msvc.h"
5
6 #define IMPORT_NAME(library, name) PEUtils::importName(library, name)
7 #define IMPORT_TRAMPOLINE(library, name) ("_" + IMPORT_NAME(library, name))
8 #define ADD_WNDPROC_API(argidx, name) m_wndprocapi.emplace_front(argidx, name)
9
10 namespace REDasm {
11
PEAnalyzer(const PEClassifier * classifier,DisassemblerAPI * disassembler)12 PEAnalyzer::PEAnalyzer(const PEClassifier *classifier, DisassemblerAPI *disassembler): Analyzer(disassembler), m_classifier(classifier)
13 {
14 ADD_WNDPROC_API(4, "DialogBoxA");
15 ADD_WNDPROC_API(4, "DialogBoxW");
16 ADD_WNDPROC_API(4, "DialogBoxParamA");
17 ADD_WNDPROC_API(4, "DialogBoxParamW");
18 ADD_WNDPROC_API(4, "CreateDialogParamA");
19 ADD_WNDPROC_API(4, "CreateDialogParamW");
20 ADD_WNDPROC_API(4, "CreateDialogIndirectParamA");
21 ADD_WNDPROC_API(4, "CreateDialogIndirectParamW");
22 }
23
analyze()24 void PEAnalyzer::analyze()
25 {
26 Analyzer::analyze();
27
28 if(!m_classifier->isClassified() || m_classifier->checkVisualStudio())
29 this->findCRTWinMain();
30
31 if(m_classifier->checkVisualStudio())
32 {
33 this->findAllWndProc();
34 REDasm::log("Searching MSVC RTTI...");
35
36 if(m_classifier->bits() == 64)
37 RTTI::RTTIMsvc<u64>(m_disassembler).search();
38 else
39 RTTI::RTTIMsvc<u32>(m_disassembler).search();
40
41 return;
42 }
43
44 this->findAllWndProc();
45 }
46
getImport(const std::string & library,const std::string & api)47 Symbol* PEAnalyzer::getImport(const std::string &library, const std::string &api)
48 {
49 Symbol* symbol = m_disassembler->document()->symbol(IMPORT_TRAMPOLINE(library, api));
50
51 if(!symbol)
52 symbol = m_disassembler->document()->symbol(IMPORT_NAME(library, api));
53
54 return symbol;
55 }
56
getAPIReferences(const std::string & library,const std::string & api)57 ReferenceVector PEAnalyzer::getAPIReferences(const std::string &library, const std::string &api)
58 {
59 Symbol* symbol = this->getImport(library, api);
60
61 if(!symbol)
62 return ReferenceVector();
63
64 return m_disassembler->getReferences(symbol->address);
65 }
66
findAllWndProc()67 void PEAnalyzer::findAllWndProc()
68 {
69 for(auto it = m_wndprocapi.begin(); it != m_wndprocapi.end(); it++)
70 {
71 ReferenceVector refs = this->getAPIReferences("user32.dll", it->second);
72
73 for(address_t ref : refs)
74 this->findWndProc(ref, it->first);
75 }
76 }
77
findWndProc(address_t address,size_t argidx)78 void PEAnalyzer::findWndProc(address_t address, size_t argidx)
79 {
80 auto it = m_document->instructionItem(address);
81
82 if(it == m_document->end())
83 return;
84
85 size_t arg = 0;
86 it--; // Skip call
87
88 while(arg < argidx)
89 {
90 const InstructionPtr& instruction = m_document->instruction((*it)->address);
91
92 if(!instruction)
93 break;
94
95 if(instruction->is(InstructionType::Push))
96 {
97 arg++;
98
99 if(arg == argidx)
100 {
101 const Operand* op = instruction->op(0);
102 Segment* segment = m_document->segment(op->u_value);
103
104 if(segment && segment->is(SegmentType::Code))
105 {
106 m_document->lockFunction(op->u_value, "DlgProc_" + REDasm::hex(op->u_value));
107 m_disassembler->disassemble(op->u_value);
108 }
109 }
110 }
111
112 if((arg == argidx) || (it == m_document->begin()) || instruction->is(InstructionType::Stop))
113 break;
114
115 it--;
116 }
117 }
118
findCRTWinMain()119 void PEAnalyzer::findCRTWinMain()
120 {
121 InstructionPtr instruction = m_document->entryInstruction(); // Look for call
122
123 if(!instruction || !instruction->is(InstructionType::Call))
124 return;
125
126 Symbol* symbol = m_document->symbol(PE_SECURITY_COOKIE_SYMBOL);
127
128 if(!symbol)
129 return;
130
131 auto target = m_disassembler->getTarget(instruction->address);
132
133 if(!target.valid)
134 return;
135
136 bool found = false;
137 ReferenceVector refs = m_disassembler->getReferences(symbol->address);
138
139 for(address_t ref : refs)
140 {
141 const ListingItem* scfuncitem = m_document->functionStart(ref);
142
143 if(!scfuncitem || ((target != scfuncitem->address)))
144 continue;
145
146 m_document->lock(scfuncitem->address, "__security_init_cookie");
147 found = true;
148 break;
149 }
150
151 if(!found || !m_document->advance(instruction) || !instruction->is(InstructionType::Jump))
152 return;
153
154 m_document->lock(target, "__mainCRTStartup", SymbolType::Function);
155 m_document->setDocumentEntry(target);
156 }
157
158 }
159