summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--platform/mac/platform_mac.cpp172
-rw-r--r--view/macho/machoview.cpp82
-rw-r--r--view/macho/machoview.h2
3 files changed, 218 insertions, 38 deletions
diff --git a/platform/mac/platform_mac.cpp b/platform/mac/platform_mac.cpp
index f1a33333..6a539f66 100644
--- a/platform/mac/platform_mac.cpp
+++ b/platform/mac/platform_mac.cpp
@@ -4,6 +4,10 @@ using namespace BinaryNinja;
using namespace std;
+Ref<Platform> g_macX86, g_macX64, g_macArmv7, g_macThumb2, g_macArm64;
+Ref<Platform> g_iosArmv7, g_iosThumb2, g_iosArm64;
+
+
class MacX86Platform: public Platform
{
public:
@@ -31,6 +35,17 @@ public:
{
return false;
}
+
+ static Ref<Platform> Recognize(BinaryView* view, Metadata* metadata)
+ {
+ auto machoPlatform = metadata->Get("machoplatform");
+ if (!machoPlatform || !machoPlatform->IsUnsignedInteger())
+ return nullptr;
+ if (machoPlatform->GetUnsignedInteger() != 2)
+ return g_macX86;
+
+ return nullptr;
+ }
};
@@ -55,6 +70,17 @@ public:
{
return false;
}
+
+ static Ref<Platform> Recognize(BinaryView* view, Metadata* metadata)
+ {
+ auto machoPlatform = metadata->Get("machoplatform");
+ if (!machoPlatform || !machoPlatform->IsUnsignedInteger())
+ return nullptr;
+ if (machoPlatform->GetUnsignedInteger() != 2)
+ return g_macX64;
+
+ return nullptr;
+ }
};
@@ -79,6 +105,17 @@ public:
{
return false;
}
+
+ static Ref<Platform> Recognize(BinaryView* view, Metadata* metadata)
+ {
+ auto machoPlatform = metadata->Get("machoplatform");
+ if (!machoPlatform || !machoPlatform->IsUnsignedInteger())
+ return nullptr;
+ if (machoPlatform->GetUnsignedInteger() != 2)
+ return g_macArmv7;
+
+ return nullptr;
+ }
};
@@ -103,6 +140,86 @@ public:
{
return false;
}
+
+ static Ref<Platform> Recognize(BinaryView* view, Metadata* metadata)
+ {
+ auto machoPlatform = metadata->Get("machoplatform");
+ if (!machoPlatform || !machoPlatform->IsUnsignedInteger())
+ return nullptr;
+ if (machoPlatform->GetUnsignedInteger() != 2)
+ return g_macArm64;
+
+ return nullptr;
+ }
+};
+
+
+class IOSArmv7Platform: public Platform
+{
+public:
+ IOSArmv7Platform(Architecture* arch, const std::string& name): Platform(arch, name)
+ {
+ Ref<CallingConvention> cc;
+
+ cc = arch->GetCallingConventionByName("cdecl");
+ if (cc)
+ {
+ RegisterDefaultCallingConvention(cc);
+ RegisterCdeclCallingConvention(cc);
+ RegisterFastcallCallingConvention(cc);
+ RegisterStdcallCallingConvention(cc);
+ }
+ }
+
+ virtual bool GetFallbackEnabled() override
+ {
+ return false;
+ }
+
+ static Ref<Platform> Recognize(BinaryView* view, Metadata* metadata)
+ {
+ auto machoPlatform = metadata->Get("machoplatform");
+ if (!machoPlatform || !machoPlatform->IsUnsignedInteger())
+ return nullptr;
+ if (machoPlatform->GetUnsignedInteger() == 2)
+ return g_iosArmv7;
+
+ return nullptr;
+ }
+};
+
+class IOSArm64Platform: public Platform
+{
+public:
+ IOSArm64Platform(Architecture* arch): Platform(arch, "ios-aarch64")
+ {
+ Ref<CallingConvention> cc;
+
+ cc = arch->GetCallingConventionByName("apple-arm64");
+ if (cc)
+ {
+ RegisterDefaultCallingConvention(cc);
+ RegisterCdeclCallingConvention(cc);
+ RegisterFastcallCallingConvention(cc);
+ RegisterStdcallCallingConvention(cc);
+ }
+ }
+
+ virtual bool GetFallbackEnabled() override
+ {
+ return false;
+ }
+
+ static Ref<Platform> Recognize(BinaryView* view, Metadata* metadata)
+ {
+ auto machoPlatform = metadata->Get("machoplatform");
+ if (!machoPlatform || !machoPlatform->IsUnsignedInteger())
+ return nullptr;
+ if (machoPlatform->GetUnsignedInteger() == 2)
+ return g_iosArm64;
+
+ return nullptr;
+ }
};
@@ -126,50 +243,55 @@ extern "C"
BINARYNINJAPLUGIN bool CorePluginInit()
#endif
{
+ auto viewType = BinaryViewType::GetByName("Mach-O");
Ref<Architecture> x86 = Architecture::GetByName("x86");
if (x86)
{
- Ref<Platform> platform;
-
- platform = new MacX86Platform(x86);
- Platform::Register("mac", platform);
- BinaryViewType::RegisterPlatform("Mach-O", 0, x86, platform);
+ g_macX86 = new MacX86Platform(x86);
+ Platform::Register("mac", g_macX86);
+ viewType->RegisterPlatformRecognizer(7, LittleEndian, MacX86Platform::Recognize);
}
Ref<Architecture> x64 = Architecture::GetByName("x86_64");
if (x64)
{
- Ref<Platform> platform;
-
- platform = new MacX64Platform(x64);
- Platform::Register("mac", platform);
- BinaryViewType::RegisterPlatform("Mach-O", 0, x64, platform);
+ g_macX64 = new MacX64Platform(x64);
+ Platform::Register("mac", g_macX64);
+ viewType->RegisterPlatformRecognizer(0x01000007, LittleEndian, MacX64Platform::Recognize);
}
Ref<Architecture> armv7 = Architecture::GetByName("armv7");
Ref<Architecture> thumb2 = Architecture::GetByName("thumb2");
if (armv7 && thumb2)
{
- Ref<Platform> armPlatform, thumbPlatform;
-
- armPlatform = new MacArmv7Platform(armv7, "mac-armv7");
- thumbPlatform = new MacArmv7Platform(thumb2, "mac-thumb2");
- armPlatform->AddRelatedPlatform(thumb2, thumbPlatform);
- thumbPlatform->AddRelatedPlatform(armv7, armPlatform);
- Platform::Register("mac", armPlatform);
- Platform::Register("mac", thumbPlatform);
- BinaryViewType::RegisterPlatform("Mach-O", 0, armv7, armPlatform);
+ g_macArmv7 = new MacArmv7Platform(armv7, "mac-armv7");
+ g_macThumb2 = new MacArmv7Platform(thumb2, "mac-thumb2");
+ g_iosArmv7 = new IOSArmv7Platform(armv7, "ios-armv7");
+ g_iosThumb2 = new IOSArmv7Platform(thumb2, "ios-thumb2");
+ g_macArmv7->AddRelatedPlatform(thumb2, g_macThumb2);
+ g_macThumb2->AddRelatedPlatform(armv7, g_macArmv7);
+ g_iosArmv7->AddRelatedPlatform(thumb2, g_iosThumb2);
+ g_iosThumb2->AddRelatedPlatform(armv7, g_iosArmv7);
+ Platform::Register("mac", g_macArmv7);
+ Platform::Register("ios", g_iosArmv7);
+ Platform::Register("mac", g_macThumb2);
+ Platform::Register("ios", g_iosThumb2);
+ viewType->RegisterPlatformRecognizer(0xc, LittleEndian, MacArmv7Platform::Recognize);
+ viewType->RegisterPlatformRecognizer(0xc, LittleEndian, IOSArmv7Platform::Recognize);
}
Ref<Architecture> arm64 = Architecture::GetByName("aarch64");
if (arm64)
{
- Ref<Platform> platform;
-
- platform = new MacArm64Platform(arm64);
- Platform::Register("mac", platform);
- BinaryViewType::RegisterPlatform("Mach-O", 9, arm64, platform);
- BinaryViewType::RegisterPlatform("Mach-O", 0, arm64, platform);
+ g_macArm64 = new MacArm64Platform(arm64);
+ g_iosArm64 = new IOSArm64Platform(arm64);
+ Platform::Register("mac", g_macArm64);
+ Platform::Register("ios", g_iosArm64);
+ viewType->RegisterPlatformRecognizer(0, LittleEndian, MacArm64Platform::Recognize);
+ viewType->RegisterPlatformRecognizer(0x0100000c, LittleEndian, MacArm64Platform::Recognize);
+ viewType->RegisterPlatformRecognizer(0x0200000c, LittleEndian, MacArm64Platform::Recognize);
+ viewType->RegisterPlatformRecognizer(0, LittleEndian, IOSArm64Platform::Recognize);
+ viewType->RegisterPlatformRecognizer(0x0100000c, LittleEndian, IOSArm64Platform::Recognize);
}
return true;
diff --git a/view/macho/machoview.cpp b/view/macho/machoview.cpp
index 257f57a6..ef5b1c3b 100644
--- a/view/macho/machoview.cpp
+++ b/view/macho/machoview.cpp
@@ -138,9 +138,7 @@ static string BuildToolVersionToString(uint32_t version)
uint32_t update = version & 0xff;
stringstream ss;
- ss << major << "." << minor;
- if (update)
- ss << "." << update;
+ ss << major << "." << minor << "." << update;
return ss.str();
}
@@ -802,11 +800,14 @@ MachOHeader MachoView::HeaderForAddress(BinaryView* data, uint64_t address, bool
case LC_LOAD_DYLIB:
{
uint32_t offset = reader.Read32();
+ reader.Read32(); // timestamp
+ uint32_t currentVersion = reader.Read32();
if (offset < nextOffset)
{
reader.Seek(curOffset + offset);
string libname = reader.ReadCString();
- header.dylibs.push_back(libname);
+ auto version = BuildToolVersionToString(currentVersion);
+ header.dylibs.push_back({libname, version});
}
}
break;
@@ -1926,17 +1927,19 @@ bool MachoView::InitializeHeader(MachOHeader& header, bool isMainHeader, uint64_
{
vector<Ref<Metadata>> libraries;
vector<Ref<Metadata>> libraryFound;
- for (auto& libName : header.dylibs)
+ for (auto& [libName, libVersion] : header.dylibs)
{
if (!GetExternalLibrary(libName))
{
AddExternalLibrary(libName, {}, true);
}
libraries.push_back(new Metadata(string(libName)));
- Ref<TypeLibrary> typeLib = GetTypeLibrary(libName);
+ // Compose exact name with {install_name}.{platform}.{version}
+ std::string libNameExact = fmt::format("{}.{}.{}", libName, GetDefaultPlatform()->GetName(), libVersion);
+ Ref<TypeLibrary> typeLib = GetTypeLibrary(libNameExact);
if (!typeLib)
{
- vector<Ref<TypeLibrary>> typeLibs = platform->GetTypeLibrariesByName(libName);
+ vector<Ref<TypeLibrary>> typeLibs = GetDefaultPlatform()->GetTypeLibrariesByName(libNameExact);
if (typeLibs.size())
{
typeLib = typeLibs[0];
@@ -1946,6 +1949,22 @@ bool MachoView::InitializeHeader(MachOHeader& header, bool isMainHeader, uint64_
libName.c_str(), typeLib->GetName().c_str(), typeLib->GetGuid().c_str());
}
}
+ if (!typeLib)
+ {
+ typeLib = GetTypeLibrary(libName);
+ if (!typeLib)
+ {
+ vector<Ref<TypeLibrary>> typeLibs = GetDefaultPlatform()->GetTypeLibrariesByName(libName);
+ if (typeLibs.size())
+ {
+ typeLib = typeLibs[0];
+ AddTypeLibrary(typeLib);
+
+ m_logger->LogDebug("mach-o: adding type library for '%s': %s (%s)",
+ libName.c_str(), typeLib->GetName().c_str(), typeLib->GetGuid().c_str());
+ }
+ }
+ }
if (typeLib)
libraryFound.push_back(new Metadata(typeLib->GetName()));
@@ -2344,8 +2363,6 @@ bool MachoView::InitializeHeader(MachOHeader& header, bool isMainHeader, uint64_
Ref<Symbol> MachoView::DefineMachoSymbol(
BNSymbolType type, const string& name, uint64_t addr, BNSymbolBinding binding, bool deferred)
{
- Ref<Type> symbolTypeRef;
-
// If name is empty, symbol is not valid
if (name.size() == 0)
return nullptr;
@@ -2375,17 +2392,19 @@ Ref<Symbol> MachoView::DefineMachoSymbol(
return nullptr;
}
+ Ref<Type> symbolTypeRef;
+
if ((type == ExternalSymbol) || (type == ImportAddressSymbol) || (type == ImportedDataSymbol))
{
QualifiedName n(name);
- // TODO
- Ref<TypeLibrary> appliedLib = nullptr;
+ Ref<TypeLibrary> appliedLib;
symbolTypeRef = ImportTypeLibraryObject(appliedLib, n);
if (symbolTypeRef)
{
m_logger->LogDebug("mach-o: type Library '%s' found hit for '%s'", appliedLib->GetName().c_str(), name.c_str());
RecordImportedObjectLibrary(GetDefaultPlatform(), addr, appliedLib, n);
}
+
}
auto process = [=]() {
@@ -3785,11 +3804,50 @@ uint64_t MachoViewType::ParseHeaders(BinaryView* data, uint64_t imageOffset, mac
errorMsg = "invalid file class";
return 0;
}
+ uint64_t loadCommandStart = reader.GetOffset();
+
+ uint32_t cmd;
+ uint32_t cmdsize;
+ MachoPlatform machoPlat = MachoPlatform::MACHO_PLATFORM_MACOS; // Default to macOS.
+ // Quickly determine the OS from commands.
+ for (uint32_t i = 0; i < ident.ncmds; i++)
+ {
+ cmd = reader.Read32();
+ cmdsize = reader.Read32();
+ if (cmd == LC_BUILD_VERSION)
+ {
+ machoPlat = MachoPlatform(reader.Read32());
+ break;
+ }
+ else if (cmd == LC_VERSION_MIN_MACOSX)
+ {
+ machoPlat = MachoPlatform(1);
+ break;
+ }
+ else if (cmd == LC_VERSION_MIN_IPHONEOS)
+ {
+ machoPlat = MachoPlatform(2);
+ break;
+ }
+ else if (cmd == _LC_VERSION_MIN_TVOS)
+ {
+ machoPlat = MachoPlatform(3);
+ break;
+ }
+ else if (cmd == LC_VERSION_MIN_WATCHOS)
+ {
+ machoPlat = MachoPlatform(4);
+ break;
+ }
+
+ reader.SeekRelative(cmdsize - 8);
+ }
map<string, Ref<Metadata>> metadataMap = {
{"cputype", new Metadata((uint64_t) ident.cputype)},
{"cpusubtype", new Metadata((uint64_t) ident.cpusubtype)},
{"flags", new Metadata((uint64_t) ident.flags)},
+ {"machoplatform", new Metadata((uint64_t) machoPlat)},
};
Ref<Metadata> metadata = new Metadata(metadataMap);
@@ -3810,7 +3868,7 @@ uint64_t MachoViewType::ParseHeaders(BinaryView* data, uint64_t imageOffset, mac
*arch = g_machoViewType->GetArchitecture(ident.cputype, endianness);
}
- return reader.GetOffset();
+ return loadCommandStart;
}
diff --git a/view/macho/machoview.h b/view/macho/machoview.h
index 4bf37ef0..6a5e80ae 100644
--- a/view/macho/machoview.h
+++ b/view/macho/machoview.h
@@ -1285,7 +1285,7 @@ namespace BinaryNinja
std::vector<section_64> symbolStubSections;
std::vector<section_64> symbolPointerSections;
- std::vector<std::string> dylibs;
+ std::vector<std::pair<std::string, std::string>> dylibs;
build_version_command buildVersion;
std::vector<build_tool_version> buildToolVersions;