1*a03ca8b9SKrzysztof Kosiński // Copyright 2017 The Chromium Authors. All rights reserved. 2*a03ca8b9SKrzysztof Kosiński // Use of this source code is governed by a BSD-style license that can be 3*a03ca8b9SKrzysztof Kosiński // found in the LICENSE file. 4*a03ca8b9SKrzysztof Kosiński 5*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/element_detection.h" 6*a03ca8b9SKrzysztof Kosiński 7*a03ca8b9SKrzysztof Kosiński #include <utility> 8*a03ca8b9SKrzysztof Kosiński 9*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/buildflags.h" 10*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/disassembler.h" 11*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/disassembler_no_op.h" 12*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/version_info.h" 13*a03ca8b9SKrzysztof Kosiński 14*a03ca8b9SKrzysztof Kosiński #if BUILDFLAG(ENABLE_DEX) 15*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/disassembler_dex.h" 16*a03ca8b9SKrzysztof Kosiński #endif // BUILDFLAG(ENABLE_DEX) 17*a03ca8b9SKrzysztof Kosiński 18*a03ca8b9SKrzysztof Kosiński #if BUILDFLAG(ENABLE_ELF) 19*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/disassembler_elf.h" 20*a03ca8b9SKrzysztof Kosiński #endif // BUILDFLAG(ENABLE_ELF) 21*a03ca8b9SKrzysztof Kosiński 22*a03ca8b9SKrzysztof Kosiński #if BUILDFLAG(ENABLE_WIN) 23*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/disassembler_win32.h" 24*a03ca8b9SKrzysztof Kosiński #endif // BUILDFLAG(ENABLE_WIN) 25*a03ca8b9SKrzysztof Kosiński 26*a03ca8b9SKrzysztof Kosiński #if BUILDFLAG(ENABLE_ZTF) 27*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/disassembler_ztf.h" 28*a03ca8b9SKrzysztof Kosiński #endif // BUILDFLAG(ENABLE_ZTF) 29*a03ca8b9SKrzysztof Kosiński 30*a03ca8b9SKrzysztof Kosiński namespace zucchini { 31*a03ca8b9SKrzysztof Kosiński 32*a03ca8b9SKrzysztof Kosiński namespace { 33*a03ca8b9SKrzysztof Kosiński 34*a03ca8b9SKrzysztof Kosiński // Impose a minimal program size to eliminate pathological cases. 35*a03ca8b9SKrzysztof Kosiński enum : size_t { kMinProgramSize = 16 }; 36*a03ca8b9SKrzysztof Kosiński 37*a03ca8b9SKrzysztof Kosiński } // namespace 38*a03ca8b9SKrzysztof Kosiński 39*a03ca8b9SKrzysztof Kosiński /******** Utility Functions ********/ 40*a03ca8b9SKrzysztof Kosiński MakeDisassemblerWithoutFallback(ConstBufferView image)41*a03ca8b9SKrzysztof Kosińskistd::unique_ptr<Disassembler> MakeDisassemblerWithoutFallback( 42*a03ca8b9SKrzysztof Kosiński ConstBufferView image) { 43*a03ca8b9SKrzysztof Kosiński #if BUILDFLAG(ENABLE_WIN) 44*a03ca8b9SKrzysztof Kosiński if (DisassemblerWin32X86::QuickDetect(image)) { 45*a03ca8b9SKrzysztof Kosiński auto disasm = Disassembler::Make<DisassemblerWin32X86>(image); 46*a03ca8b9SKrzysztof Kosiński if (disasm && disasm->size() >= kMinProgramSize) 47*a03ca8b9SKrzysztof Kosiński return disasm; 48*a03ca8b9SKrzysztof Kosiński } 49*a03ca8b9SKrzysztof Kosiński 50*a03ca8b9SKrzysztof Kosiński if (DisassemblerWin32X64::QuickDetect(image)) { 51*a03ca8b9SKrzysztof Kosiński auto disasm = Disassembler::Make<DisassemblerWin32X64>(image); 52*a03ca8b9SKrzysztof Kosiński if (disasm && disasm->size() >= kMinProgramSize) 53*a03ca8b9SKrzysztof Kosiński return disasm; 54*a03ca8b9SKrzysztof Kosiński } 55*a03ca8b9SKrzysztof Kosiński #endif // BUILDFLAG(ENABLE_WIN) 56*a03ca8b9SKrzysztof Kosiński 57*a03ca8b9SKrzysztof Kosiński #if BUILDFLAG(ENABLE_ELF) 58*a03ca8b9SKrzysztof Kosiński if (DisassemblerElfX86::QuickDetect(image)) { 59*a03ca8b9SKrzysztof Kosiński auto disasm = Disassembler::Make<DisassemblerElfX86>(image); 60*a03ca8b9SKrzysztof Kosiński if (disasm && disasm->size() >= kMinProgramSize) 61*a03ca8b9SKrzysztof Kosiński return disasm; 62*a03ca8b9SKrzysztof Kosiński } 63*a03ca8b9SKrzysztof Kosiński 64*a03ca8b9SKrzysztof Kosiński if (DisassemblerElfX64::QuickDetect(image)) { 65*a03ca8b9SKrzysztof Kosiński auto disasm = Disassembler::Make<DisassemblerElfX64>(image); 66*a03ca8b9SKrzysztof Kosiński if (disasm && disasm->size() >= kMinProgramSize) 67*a03ca8b9SKrzysztof Kosiński return disasm; 68*a03ca8b9SKrzysztof Kosiński } 69*a03ca8b9SKrzysztof Kosiński 70*a03ca8b9SKrzysztof Kosiński if (DisassemblerElfAArch32::QuickDetect(image)) { 71*a03ca8b9SKrzysztof Kosiński auto disasm = Disassembler::Make<DisassemblerElfAArch32>(image); 72*a03ca8b9SKrzysztof Kosiński if (disasm && disasm->size() >= kMinProgramSize) 73*a03ca8b9SKrzysztof Kosiński return disasm; 74*a03ca8b9SKrzysztof Kosiński } 75*a03ca8b9SKrzysztof Kosiński 76*a03ca8b9SKrzysztof Kosiński if (DisassemblerElfAArch64::QuickDetect(image)) { 77*a03ca8b9SKrzysztof Kosiński auto disasm = Disassembler::Make<DisassemblerElfAArch64>(image); 78*a03ca8b9SKrzysztof Kosiński if (disasm && disasm->size() >= kMinProgramSize) 79*a03ca8b9SKrzysztof Kosiński return disasm; 80*a03ca8b9SKrzysztof Kosiński } 81*a03ca8b9SKrzysztof Kosiński #endif // BUILDFLAG(ENABLE_ELF) 82*a03ca8b9SKrzysztof Kosiński 83*a03ca8b9SKrzysztof Kosiński #if BUILDFLAG(ENABLE_DEX) 84*a03ca8b9SKrzysztof Kosiński if (DisassemblerDex::QuickDetect(image)) { 85*a03ca8b9SKrzysztof Kosiński auto disasm = Disassembler::Make<DisassemblerDex>(image); 86*a03ca8b9SKrzysztof Kosiński if (disasm && disasm->size() >= kMinProgramSize) 87*a03ca8b9SKrzysztof Kosiński return disasm; 88*a03ca8b9SKrzysztof Kosiński } 89*a03ca8b9SKrzysztof Kosiński #endif // BUILDFLAG(ENABLE_DEX) 90*a03ca8b9SKrzysztof Kosiński 91*a03ca8b9SKrzysztof Kosiński #if BUILDFLAG(ENABLE_ZTF) 92*a03ca8b9SKrzysztof Kosiński if (DisassemblerZtf::QuickDetect(image)) { 93*a03ca8b9SKrzysztof Kosiński // This disallows very short examples like "ZTxtxtZ\n" in ensemble patching. 94*a03ca8b9SKrzysztof Kosiński auto disasm = Disassembler::Make<DisassemblerZtf>(image); 95*a03ca8b9SKrzysztof Kosiński if (disasm && disasm->size() >= kMinProgramSize) 96*a03ca8b9SKrzysztof Kosiński return disasm; 97*a03ca8b9SKrzysztof Kosiński } 98*a03ca8b9SKrzysztof Kosiński #endif // BUILDFLAG(ENABLE_ZTF) 99*a03ca8b9SKrzysztof Kosiński 100*a03ca8b9SKrzysztof Kosiński return nullptr; 101*a03ca8b9SKrzysztof Kosiński } 102*a03ca8b9SKrzysztof Kosiński MakeDisassemblerOfType(ConstBufferView image,ExecutableType exe_type)103*a03ca8b9SKrzysztof Kosińskistd::unique_ptr<Disassembler> MakeDisassemblerOfType(ConstBufferView image, 104*a03ca8b9SKrzysztof Kosiński ExecutableType exe_type) { 105*a03ca8b9SKrzysztof Kosiński switch (exe_type) { 106*a03ca8b9SKrzysztof Kosiński #if BUILDFLAG(ENABLE_WIN) 107*a03ca8b9SKrzysztof Kosiński case kExeTypeWin32X86: 108*a03ca8b9SKrzysztof Kosiński return Disassembler::Make<DisassemblerWin32X86>(image); 109*a03ca8b9SKrzysztof Kosiński case kExeTypeWin32X64: 110*a03ca8b9SKrzysztof Kosiński return Disassembler::Make<DisassemblerWin32X64>(image); 111*a03ca8b9SKrzysztof Kosiński #endif // BUILDFLAG(ENABLE_WIN) 112*a03ca8b9SKrzysztof Kosiński #if BUILDFLAG(ENABLE_ELF) 113*a03ca8b9SKrzysztof Kosiński case kExeTypeElfX86: 114*a03ca8b9SKrzysztof Kosiński return Disassembler::Make<DisassemblerElfX86>(image); 115*a03ca8b9SKrzysztof Kosiński case kExeTypeElfX64: 116*a03ca8b9SKrzysztof Kosiński return Disassembler::Make<DisassemblerElfX64>(image); 117*a03ca8b9SKrzysztof Kosiński case kExeTypeElfAArch32: 118*a03ca8b9SKrzysztof Kosiński return Disassembler::Make<DisassemblerElfAArch32>(image); 119*a03ca8b9SKrzysztof Kosiński case kExeTypeElfAArch64: 120*a03ca8b9SKrzysztof Kosiński return Disassembler::Make<DisassemblerElfAArch64>(image); 121*a03ca8b9SKrzysztof Kosiński #endif // BUILDFLAG(ENABLE_ELF) 122*a03ca8b9SKrzysztof Kosiński #if BUILDFLAG(ENABLE_DEX) 123*a03ca8b9SKrzysztof Kosiński case kExeTypeDex: 124*a03ca8b9SKrzysztof Kosiński return Disassembler::Make<DisassemblerDex>(image); 125*a03ca8b9SKrzysztof Kosiński #endif // BUILDFLAG(ENABLE_DEX) 126*a03ca8b9SKrzysztof Kosiński #if BUILDFLAG(ENABLE_ZTF) 127*a03ca8b9SKrzysztof Kosiński case kExeTypeZtf: 128*a03ca8b9SKrzysztof Kosiński return Disassembler::Make<DisassemblerZtf>(image); 129*a03ca8b9SKrzysztof Kosiński #endif // BUILDFLAG(ENABLE_ZTF) 130*a03ca8b9SKrzysztof Kosiński case kExeTypeNoOp: 131*a03ca8b9SKrzysztof Kosiński return Disassembler::Make<DisassemblerNoOp>(image); 132*a03ca8b9SKrzysztof Kosiński default: 133*a03ca8b9SKrzysztof Kosiński // If an architecture is disabled then null is handled gracefully. 134*a03ca8b9SKrzysztof Kosiński return nullptr; 135*a03ca8b9SKrzysztof Kosiński } 136*a03ca8b9SKrzysztof Kosiński } 137*a03ca8b9SKrzysztof Kosiński DisassemblerVersionOfType(ExecutableType exe_type)138*a03ca8b9SKrzysztof Kosińskiuint16_t DisassemblerVersionOfType(ExecutableType exe_type) { 139*a03ca8b9SKrzysztof Kosiński switch (exe_type) { 140*a03ca8b9SKrzysztof Kosiński #if BUILDFLAG(ENABLE_WIN) 141*a03ca8b9SKrzysztof Kosiński case kExeTypeWin32X86: 142*a03ca8b9SKrzysztof Kosiński return DisassemblerWin32X86::kVersion; 143*a03ca8b9SKrzysztof Kosiński case kExeTypeWin32X64: 144*a03ca8b9SKrzysztof Kosiński return DisassemblerWin32X64::kVersion; 145*a03ca8b9SKrzysztof Kosiński #endif // BUILDFLAG(ENABLE_WIN) 146*a03ca8b9SKrzysztof Kosiński #if BUILDFLAG(ENABLE_ELF) 147*a03ca8b9SKrzysztof Kosiński case kExeTypeElfX86: 148*a03ca8b9SKrzysztof Kosiński return DisassemblerElfX86::kVersion; 149*a03ca8b9SKrzysztof Kosiński case kExeTypeElfX64: 150*a03ca8b9SKrzysztof Kosiński return DisassemblerElfX64::kVersion; 151*a03ca8b9SKrzysztof Kosiński case kExeTypeElfAArch32: 152*a03ca8b9SKrzysztof Kosiński return DisassemblerElfAArch32::kVersion; 153*a03ca8b9SKrzysztof Kosiński case kExeTypeElfAArch64: 154*a03ca8b9SKrzysztof Kosiński return DisassemblerElfAArch64::kVersion; 155*a03ca8b9SKrzysztof Kosiński #endif // BUILDFLAG(ENABLE_ELF) 156*a03ca8b9SKrzysztof Kosiński #if BUILDFLAG(ENABLE_DEX) 157*a03ca8b9SKrzysztof Kosiński case kExeTypeDex: 158*a03ca8b9SKrzysztof Kosiński return DisassemblerDex::kVersion; 159*a03ca8b9SKrzysztof Kosiński #endif // BUILDFLAG(ENABLE_DEX) 160*a03ca8b9SKrzysztof Kosiński #if BUILDFLAG(ENABLE_ZTF) 161*a03ca8b9SKrzysztof Kosiński case kExeTypeZtf: 162*a03ca8b9SKrzysztof Kosiński return DisassemblerZtf::kVersion; 163*a03ca8b9SKrzysztof Kosiński #endif // BUILDFLAG(ENABLE_ZTF) 164*a03ca8b9SKrzysztof Kosiński case kExeTypeNoOp: 165*a03ca8b9SKrzysztof Kosiński return DisassemblerNoOp::kVersion; 166*a03ca8b9SKrzysztof Kosiński default: 167*a03ca8b9SKrzysztof Kosiński // If an architecture is disabled then null is handled gracefully. 168*a03ca8b9SKrzysztof Kosiński return kInvalidVersion; 169*a03ca8b9SKrzysztof Kosiński } 170*a03ca8b9SKrzysztof Kosiński } 171*a03ca8b9SKrzysztof Kosiński DetectElementFromDisassembler(ConstBufferView image)172*a03ca8b9SKrzysztof Kosińskistd::optional<Element> DetectElementFromDisassembler(ConstBufferView image) { 173*a03ca8b9SKrzysztof Kosiński std::unique_ptr<Disassembler> disasm = MakeDisassemblerWithoutFallback(image); 174*a03ca8b9SKrzysztof Kosiński if (disasm) 175*a03ca8b9SKrzysztof Kosiński return Element({0, disasm->size()}, disasm->GetExeType()); 176*a03ca8b9SKrzysztof Kosiński return std::nullopt; 177*a03ca8b9SKrzysztof Kosiński } 178*a03ca8b9SKrzysztof Kosiński 179*a03ca8b9SKrzysztof Kosiński /******** ProgramScanner ********/ 180*a03ca8b9SKrzysztof Kosiński ElementFinder(ConstBufferView image,ElementDetector && detector)181*a03ca8b9SKrzysztof KosińskiElementFinder::ElementFinder(ConstBufferView image, ElementDetector&& detector) 182*a03ca8b9SKrzysztof Kosiński : image_(image), detector_(std::move(detector)) {} 183*a03ca8b9SKrzysztof Kosiński 184*a03ca8b9SKrzysztof Kosiński ElementFinder::~ElementFinder() = default; 185*a03ca8b9SKrzysztof Kosiński GetNext()186*a03ca8b9SKrzysztof Kosińskistd::optional<Element> ElementFinder::GetNext() { 187*a03ca8b9SKrzysztof Kosiński for (; pos_ < image_.size(); ++pos_) { 188*a03ca8b9SKrzysztof Kosiński ConstBufferView test_image = 189*a03ca8b9SKrzysztof Kosiński ConstBufferView::FromRange(image_.begin() + pos_, image_.end()); 190*a03ca8b9SKrzysztof Kosiński std::optional<Element> element = detector_.Run(test_image); 191*a03ca8b9SKrzysztof Kosiński if (element) { 192*a03ca8b9SKrzysztof Kosiński element->offset += pos_; 193*a03ca8b9SKrzysztof Kosiński pos_ = element->EndOffset(); 194*a03ca8b9SKrzysztof Kosiński return element; 195*a03ca8b9SKrzysztof Kosiński } 196*a03ca8b9SKrzysztof Kosiński } 197*a03ca8b9SKrzysztof Kosiński return std::nullopt; 198*a03ca8b9SKrzysztof Kosiński } 199*a03ca8b9SKrzysztof Kosiński 200*a03ca8b9SKrzysztof Kosiński } // namespace zucchini 201