Skip to content

Commit de5fdb3

Browse files
committed
Add iOS Platforms. Add Mach-O Typelib support
1 parent 015bb4f commit de5fdb3

File tree

3 files changed

+218
-38
lines changed

3 files changed

+218
-38
lines changed

platform/mac/platform_mac.cpp

Lines changed: 147 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ using namespace BinaryNinja;
44
using namespace std;
55

66

7+
Ref<Platform> g_macX86, g_macX64, g_macArmv7, g_macThumb2, g_macArm64;
8+
Ref<Platform> g_iosArmv7, g_iosThumb2, g_iosArm64;
9+
10+
711
class MacX86Platform: public Platform
812
{
913
public:
@@ -31,6 +35,17 @@ class MacX86Platform: public Platform
3135
{
3236
return false;
3337
}
38+
39+
static Ref<Platform> Recognize(BinaryView* view, Metadata* metadata)
40+
{
41+
auto machoPlatform = metadata->Get("machoplatform");
42+
if (!machoPlatform || !machoPlatform->IsUnsignedInteger())
43+
return nullptr;
44+
if (machoPlatform->GetUnsignedInteger() != 2)
45+
return g_macX86;
46+
47+
return nullptr;
48+
}
3449
};
3550

3651

@@ -55,6 +70,17 @@ class MacX64Platform: public Platform
5570
{
5671
return false;
5772
}
73+
74+
static Ref<Platform> Recognize(BinaryView* view, Metadata* metadata)
75+
{
76+
auto machoPlatform = metadata->Get("machoplatform");
77+
if (!machoPlatform || !machoPlatform->IsUnsignedInteger())
78+
return nullptr;
79+
if (machoPlatform->GetUnsignedInteger() != 2)
80+
return g_macX64;
81+
82+
return nullptr;
83+
}
5884
};
5985

6086

@@ -79,6 +105,17 @@ class MacArmv7Platform: public Platform
79105
{
80106
return false;
81107
}
108+
109+
static Ref<Platform> Recognize(BinaryView* view, Metadata* metadata)
110+
{
111+
auto machoPlatform = metadata->Get("machoplatform");
112+
if (!machoPlatform || !machoPlatform->IsUnsignedInteger())
113+
return nullptr;
114+
if (machoPlatform->GetUnsignedInteger() != 2)
115+
return g_macArmv7;
116+
117+
return nullptr;
118+
}
82119
};
83120

84121

@@ -103,6 +140,86 @@ class MacArm64Platform: public Platform
103140
{
104141
return false;
105142
}
143+
144+
static Ref<Platform> Recognize(BinaryView* view, Metadata* metadata)
145+
{
146+
auto machoPlatform = metadata->Get("machoplatform");
147+
if (!machoPlatform || !machoPlatform->IsUnsignedInteger())
148+
return nullptr;
149+
if (machoPlatform->GetUnsignedInteger() != 2)
150+
return g_macArm64;
151+
152+
return nullptr;
153+
}
154+
};
155+
156+
157+
class IOSArmv7Platform: public Platform
158+
{
159+
public:
160+
IOSArmv7Platform(Architecture* arch, const std::string& name): Platform(arch, name)
161+
{
162+
Ref<CallingConvention> cc;
163+
164+
cc = arch->GetCallingConventionByName("cdecl");
165+
if (cc)
166+
{
167+
RegisterDefaultCallingConvention(cc);
168+
RegisterCdeclCallingConvention(cc);
169+
RegisterFastcallCallingConvention(cc);
170+
RegisterStdcallCallingConvention(cc);
171+
}
172+
}
173+
174+
virtual bool GetFallbackEnabled() override
175+
{
176+
return false;
177+
}
178+
179+
static Ref<Platform> Recognize(BinaryView* view, Metadata* metadata)
180+
{
181+
auto machoPlatform = metadata->Get("machoplatform");
182+
if (!machoPlatform || !machoPlatform->IsUnsignedInteger())
183+
return nullptr;
184+
if (machoPlatform->GetUnsignedInteger() == 2)
185+
return g_iosArmv7;
186+
187+
return nullptr;
188+
}
189+
};
190+
191+
class IOSArm64Platform: public Platform
192+
{
193+
public:
194+
IOSArm64Platform(Architecture* arch): Platform(arch, "ios-aarch64")
195+
{
196+
Ref<CallingConvention> cc;
197+
198+
cc = arch->GetCallingConventionByName("apple-arm64");
199+
if (cc)
200+
{
201+
RegisterDefaultCallingConvention(cc);
202+
RegisterCdeclCallingConvention(cc);
203+
RegisterFastcallCallingConvention(cc);
204+
RegisterStdcallCallingConvention(cc);
205+
}
206+
}
207+
208+
virtual bool GetFallbackEnabled() override
209+
{
210+
return false;
211+
}
212+
213+
static Ref<Platform> Recognize(BinaryView* view, Metadata* metadata)
214+
{
215+
auto machoPlatform = metadata->Get("machoplatform");
216+
if (!machoPlatform || !machoPlatform->IsUnsignedInteger())
217+
return nullptr;
218+
if (machoPlatform->GetUnsignedInteger() == 2)
219+
return g_iosArm64;
220+
221+
return nullptr;
222+
}
106223
};
107224

108225

@@ -126,50 +243,55 @@ extern "C"
126243
BINARYNINJAPLUGIN bool CorePluginInit()
127244
#endif
128245
{
246+
auto viewType = BinaryViewType::GetByName("Mach-O");
129247
Ref<Architecture> x86 = Architecture::GetByName("x86");
130248
if (x86)
131249
{
132-
Ref<Platform> platform;
133-
134-
platform = new MacX86Platform(x86);
135-
Platform::Register("mac", platform);
136-
BinaryViewType::RegisterPlatform("Mach-O", 0, x86, platform);
250+
g_macX86 = new MacX86Platform(x86);
251+
Platform::Register("mac", g_macX86);
252+
viewType->RegisterPlatformRecognizer(7, LittleEndian, MacX86Platform::Recognize);
137253
}
138254

139255
Ref<Architecture> x64 = Architecture::GetByName("x86_64");
140256
if (x64)
141257
{
142-
Ref<Platform> platform;
143-
144-
platform = new MacX64Platform(x64);
145-
Platform::Register("mac", platform);
146-
BinaryViewType::RegisterPlatform("Mach-O", 0, x64, platform);
258+
g_macX64 = new MacX64Platform(x64);
259+
Platform::Register("mac", g_macX64);
260+
viewType->RegisterPlatformRecognizer(0x01000007, LittleEndian, MacX64Platform::Recognize);
147261
}
148262

149263
Ref<Architecture> armv7 = Architecture::GetByName("armv7");
150264
Ref<Architecture> thumb2 = Architecture::GetByName("thumb2");
151265
if (armv7 && thumb2)
152266
{
153-
Ref<Platform> armPlatform, thumbPlatform;
154-
155-
armPlatform = new MacArmv7Platform(armv7, "mac-armv7");
156-
thumbPlatform = new MacArmv7Platform(thumb2, "mac-thumb2");
157-
armPlatform->AddRelatedPlatform(thumb2, thumbPlatform);
158-
thumbPlatform->AddRelatedPlatform(armv7, armPlatform);
159-
Platform::Register("mac", armPlatform);
160-
Platform::Register("mac", thumbPlatform);
161-
BinaryViewType::RegisterPlatform("Mach-O", 0, armv7, armPlatform);
267+
g_macArmv7 = new MacArmv7Platform(armv7, "mac-armv7");
268+
g_macThumb2 = new MacArmv7Platform(thumb2, "mac-thumb2");
269+
g_iosArmv7 = new IOSArmv7Platform(armv7, "ios-armv7");
270+
g_iosThumb2 = new IOSArmv7Platform(thumb2, "ios-thumb2");
271+
g_macArmv7->AddRelatedPlatform(thumb2, g_macThumb2);
272+
g_macThumb2->AddRelatedPlatform(armv7, g_macArmv7);
273+
g_iosArmv7->AddRelatedPlatform(thumb2, g_iosThumb2);
274+
g_iosThumb2->AddRelatedPlatform(armv7, g_iosArmv7);
275+
Platform::Register("mac", g_macArmv7);
276+
Platform::Register("ios", g_iosArmv7);
277+
Platform::Register("mac", g_macThumb2);
278+
Platform::Register("ios", g_iosThumb2);
279+
viewType->RegisterPlatformRecognizer(0xc, LittleEndian, MacArmv7Platform::Recognize);
280+
viewType->RegisterPlatformRecognizer(0xc, LittleEndian, IOSArmv7Platform::Recognize);
162281
}
163282

164283
Ref<Architecture> arm64 = Architecture::GetByName("aarch64");
165284
if (arm64)
166285
{
167-
Ref<Platform> platform;
168-
169-
platform = new MacArm64Platform(arm64);
170-
Platform::Register("mac", platform);
171-
BinaryViewType::RegisterPlatform("Mach-O", 9, arm64, platform);
172-
BinaryViewType::RegisterPlatform("Mach-O", 0, arm64, platform);
286+
g_macArm64 = new MacArm64Platform(arm64);
287+
g_iosArm64 = new IOSArm64Platform(arm64);
288+
Platform::Register("mac", g_macArm64);
289+
Platform::Register("ios", g_iosArm64);
290+
viewType->RegisterPlatformRecognizer(0, LittleEndian, MacArm64Platform::Recognize);
291+
viewType->RegisterPlatformRecognizer(0x0100000c, LittleEndian, MacArm64Platform::Recognize);
292+
viewType->RegisterPlatformRecognizer(0x0200000c, LittleEndian, MacArm64Platform::Recognize);
293+
viewType->RegisterPlatformRecognizer(0, LittleEndian, IOSArm64Platform::Recognize);
294+
viewType->RegisterPlatformRecognizer(0x0100000c, LittleEndian, IOSArm64Platform::Recognize);
173295
}
174296

175297
return true;

view/macho/machoview.cpp

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,7 @@ static string BuildToolVersionToString(uint32_t version)
138138
uint32_t update = version & 0xff;
139139

140140
stringstream ss;
141-
ss << major << "." << minor;
142-
if (update)
143-
ss << "." << update;
141+
ss << major << "." << minor << "." << update;
144142
return ss.str();
145143
}
146144

@@ -802,11 +800,14 @@ MachOHeader MachoView::HeaderForAddress(BinaryView* data, uint64_t address, bool
802800
case LC_LOAD_DYLIB:
803801
{
804802
uint32_t offset = reader.Read32();
803+
reader.Read32(); // timestamp
804+
uint32_t currentVersion = reader.Read32();
805805
if (offset < nextOffset)
806806
{
807807
reader.Seek(curOffset + offset);
808808
string libname = reader.ReadCString();
809-
header.dylibs.push_back(libname);
809+
auto version = BuildToolVersionToString(currentVersion);
810+
header.dylibs.push_back({libname, version});
810811
}
811812
}
812813
break;
@@ -1926,17 +1927,19 @@ bool MachoView::InitializeHeader(MachOHeader& header, bool isMainHeader, uint64_
19261927
{
19271928
vector<Ref<Metadata>> libraries;
19281929
vector<Ref<Metadata>> libraryFound;
1929-
for (auto& libName : header.dylibs)
1930+
for (auto& [libName, libVersion] : header.dylibs)
19301931
{
19311932
if (!GetExternalLibrary(libName))
19321933
{
19331934
AddExternalLibrary(libName, {}, true);
19341935
}
19351936
libraries.push_back(new Metadata(string(libName)));
1936-
Ref<TypeLibrary> typeLib = GetTypeLibrary(libName);
1937+
// Compose exact name with {install_name}.{platform}.{version}
1938+
std::string libNameExact = fmt::format("{}.{}.{}", libName, GetDefaultPlatform()->GetName(), libVersion);
1939+
Ref<TypeLibrary> typeLib = GetTypeLibrary(libNameExact);
19371940
if (!typeLib)
19381941
{
1939-
vector<Ref<TypeLibrary>> typeLibs = platform->GetTypeLibrariesByName(libName);
1942+
vector<Ref<TypeLibrary>> typeLibs = GetDefaultPlatform()->GetTypeLibrariesByName(libNameExact);
19401943
if (typeLibs.size())
19411944
{
19421945
typeLib = typeLibs[0];
@@ -1946,6 +1949,22 @@ bool MachoView::InitializeHeader(MachOHeader& header, bool isMainHeader, uint64_
19461949
libName.c_str(), typeLib->GetName().c_str(), typeLib->GetGuid().c_str());
19471950
}
19481951
}
1952+
if (!typeLib)
1953+
{
1954+
typeLib = GetTypeLibrary(libName);
1955+
if (!typeLib)
1956+
{
1957+
vector<Ref<TypeLibrary>> typeLibs = GetDefaultPlatform()->GetTypeLibrariesByName(libName);
1958+
if (typeLibs.size())
1959+
{
1960+
typeLib = typeLibs[0];
1961+
AddTypeLibrary(typeLib);
1962+
1963+
m_logger->LogDebug("mach-o: adding type library for '%s': %s (%s)",
1964+
libName.c_str(), typeLib->GetName().c_str(), typeLib->GetGuid().c_str());
1965+
}
1966+
}
1967+
}
19491968

19501969
if (typeLib)
19511970
libraryFound.push_back(new Metadata(typeLib->GetName()));
@@ -2344,8 +2363,6 @@ bool MachoView::InitializeHeader(MachOHeader& header, bool isMainHeader, uint64_
23442363
Ref<Symbol> MachoView::DefineMachoSymbol(
23452364
BNSymbolType type, const string& name, uint64_t addr, BNSymbolBinding binding, bool deferred)
23462365
{
2347-
Ref<Type> symbolTypeRef;
2348-
23492366
// If name is empty, symbol is not valid
23502367
if (name.size() == 0)
23512368
return nullptr;
@@ -2375,17 +2392,19 @@ Ref<Symbol> MachoView::DefineMachoSymbol(
23752392
return nullptr;
23762393
}
23772394

2395+
Ref<Type> symbolTypeRef;
2396+
23782397
if ((type == ExternalSymbol) || (type == ImportAddressSymbol) || (type == ImportedDataSymbol))
23792398
{
23802399
QualifiedName n(name);
2381-
// TODO
2382-
Ref<TypeLibrary> appliedLib = nullptr;
2400+
Ref<TypeLibrary> appliedLib;
23832401
symbolTypeRef = ImportTypeLibraryObject(appliedLib, n);
23842402
if (symbolTypeRef)
23852403
{
23862404
m_logger->LogDebug("mach-o: type Library '%s' found hit for '%s'", appliedLib->GetName().c_str(), name.c_str());
23872405
RecordImportedObjectLibrary(GetDefaultPlatform(), addr, appliedLib, n);
23882406
}
2407+
23892408
}
23902409

23912410
auto process = [=]() {
@@ -3785,11 +3804,50 @@ uint64_t MachoViewType::ParseHeaders(BinaryView* data, uint64_t imageOffset, mac
37853804
errorMsg = "invalid file class";
37863805
return 0;
37873806
}
3807+
uint64_t loadCommandStart = reader.GetOffset();
3808+
3809+
uint32_t cmd;
3810+
uint32_t cmdsize;
3811+
MachoPlatform machoPlat = MachoPlatform::MACHO_PLATFORM_MACOS; // Default to macOS.
3812+
// Quickly determine the OS from commands.
3813+
for (uint32_t i = 0; i < ident.ncmds; i++)
3814+
{
3815+
cmd = reader.Read32();
3816+
cmdsize = reader.Read32();
3817+
if (cmd == LC_BUILD_VERSION)
3818+
{
3819+
machoPlat = MachoPlatform(reader.Read32());
3820+
break;
3821+
}
3822+
else if (cmd == LC_VERSION_MIN_MACOSX)
3823+
{
3824+
machoPlat = MachoPlatform(1);
3825+
break;
3826+
}
3827+
else if (cmd == LC_VERSION_MIN_IPHONEOS)
3828+
{
3829+
machoPlat = MachoPlatform(2);
3830+
break;
3831+
}
3832+
else if (cmd == _LC_VERSION_MIN_TVOS)
3833+
{
3834+
machoPlat = MachoPlatform(3);
3835+
break;
3836+
}
3837+
else if (cmd == LC_VERSION_MIN_WATCHOS)
3838+
{
3839+
machoPlat = MachoPlatform(4);
3840+
break;
3841+
}
3842+
3843+
reader.SeekRelative(cmdsize - 8);
3844+
}
37883845

37893846
map<string, Ref<Metadata>> metadataMap = {
37903847
{"cputype", new Metadata((uint64_t) ident.cputype)},
37913848
{"cpusubtype", new Metadata((uint64_t) ident.cpusubtype)},
37923849
{"flags", new Metadata((uint64_t) ident.flags)},
3850+
{"machoplatform", new Metadata((uint64_t) machoPlat)},
37933851
};
37943852

37953853
Ref<Metadata> metadata = new Metadata(metadataMap);
@@ -3810,7 +3868,7 @@ uint64_t MachoViewType::ParseHeaders(BinaryView* data, uint64_t imageOffset, mac
38103868
*arch = g_machoViewType->GetArchitecture(ident.cputype, endianness);
38113869
}
38123870

3813-
return reader.GetOffset();
3871+
return loadCommandStart;
38143872
}
38153873

38163874

0 commit comments

Comments
 (0)