summaryrefslogtreecommitdiff
path: root/view/macho/machoview.cpp
diff options
context:
space:
mode:
authorObriv Mostov <mostobriv@gmail.com>2025-04-03 23:35:59 +0700
committerkat <kat@vector35.com>2025-06-03 08:28:25 -0400
commit4bc31537add776f79cff0847feb4ccb8f0c43d22 (patch)
tree15c3aa90fc0b8bcf4ef7237df99237ae63559b94 /view/macho/machoview.cpp
parent742b25d62c01f7177687a1473cd8233d371fcf36 (diff)
[MachoView] Add support of __init_offsets
Diffstat (limited to 'view/macho/machoview.cpp')
-rw-r--r--view/macho/machoview.cpp71
1 files changed, 50 insertions, 21 deletions
diff --git a/view/macho/machoview.cpp b/view/macho/machoview.cpp
index b832e1e5..cb38826c 100644
--- a/view/macho/machoview.cpp
+++ b/view/macho/machoview.cpp
@@ -448,7 +448,7 @@ MachOHeader MachoView::HeaderForAddress(BinaryView* data, uint64_t address, bool
sect.flags,
sect.reserved1,
sect.reserved2);
- if (!strncmp(sect.sectname, "__mod_init_func", 15))
+ if (!strncmp(sect.sectname, "__mod_init_func", 15) || !strncmp(sect.sectname, "__init_offsets", 14))
header.moduleInitSections.push_back(sect);
if ((sect.flags & (S_ATTR_SELF_MODIFYING_CODE | S_SYMBOL_STUBS)) == (S_ATTR_SELF_MODIFYING_CODE | S_SYMBOL_STUBS))
header.symbolStubSections.push_back(sect);
@@ -551,7 +551,7 @@ MachOHeader MachoView::HeaderForAddress(BinaryView* data, uint64_t address, bool
sect.reserved1,
sect.reserved2,
sect.reserved3);
- if (!strncmp(sect.sectname, "__mod_init_func", 15))
+ if (!strncmp(sect.sectname, "__mod_init_func", 15) || !strncmp(sect.sectname, "__init_offsets", 14))
header.moduleInitSections.push_back(sect);
if ((sect.flags & (S_ATTR_SELF_MODIFYING_CODE | S_SYMBOL_STUBS)) == (S_ATTR_SELF_MODIFYING_CODE | S_SYMBOL_STUBS))
header.symbolStubSections.push_back(sect);
@@ -1640,7 +1640,7 @@ bool MachoView::InitializeHeader(MachOHeader& header, bool isMainHeader, uint64_
string type;
BNSectionSemantics semantics = DefaultSectionSemantics;
- switch (header.sections[i].flags & 0xff)
+ switch (header.sections[i].flags & SECTION_TYPE)
{
case S_REGULAR:
if (header.sections[i].flags & S_ATTR_PURE_INSTRUCTIONS)
@@ -1731,6 +1731,10 @@ bool MachoView::InitializeHeader(MachOHeader& header, bool isMainHeader, uint64_
case S_THREAD_LOCAL_INIT_FUNCTION_POINTERS:
type = "THREAD_LOCAL_INIT_FUNCTION_POINTERS";
break;
+ case S_INIT_FUNC_OFFSETS:
+ type = "INIT_FUNC_OFFSETS";
+ semantics = ReadOnlyDataSectionSemantics;
+ break;
default:
type = "UNKNOWN";
break;
@@ -1897,30 +1901,55 @@ bool MachoView::InitializeHeader(MachOHeader& header, bool isMainHeader, uint64_
if (find(threadStarts.begin(), threadStarts.end(), moduleInitSection.offset) != threadStarts.end())
continue;
- // The mod_init section contains a list of function pointers called at initialization
- // if we don't have a defined entrypoint then use the first one in the list as the entrypoint
size_t i = 0;
reader.Seek(moduleInitSection.offset);
- for (; i < (moduleInitSection.size / m_addressSize); i++)
+
+ if (!strncmp(moduleInitSection.sectname, "__mod_init_func", 15))
+ {
+ // The mod_init section contains a list of function pointers called at initialization
+ // if we don't have a defined entrypoint then use the first one in the list as the entrypoint
+ for (; i < (moduleInitSection.size / m_addressSize); i++)
+ {
+ uint64_t target = (m_addressSize == 4) ? reader.Read32() : reader.Read64();
+ target += m_imageBaseAdjustment;
+ if (m_header.ident.filetype == MH_FILESET)
+ {
+ // FIXME: This isn't a super robust way of detagging,
+ // should look into xnu source and the tools used to build this cache (if they're public)
+ // and see if anything better can be done
+
+ // mask out top 8 bits
+ uint64_t tag = 0xFFFFFFFF00000000 & header.textBase;
+ // and combine them with bottom 8 of the original entry
+ target = tag | (target & 0xFFFFFFFF);
+ }
+ Ref<Platform> targetPlatform = GetDefaultPlatform()->GetAssociatedPlatformByAddress(target);
+ auto name = "mod_init_func_" + to_string(modInitFuncCnt++);
+ AddEntryPointForAnalysis(targetPlatform, target);
+ auto symbol = new Symbol(FunctionSymbol, name, target, GlobalBinding);
+ DefineAutoSymbol(symbol);
+ }
+ }
+ else if (!strncmp(moduleInitSection.sectname, "__init_offsets", 14))
{
- uint64_t target = (m_addressSize == 4) ? reader.Read32() : reader.Read64();
- target += m_imageBaseAdjustment;
- if (m_header.ident.filetype == MH_FILESET)
+ // The init_offsets section contains a list of 32-bit RVA offsets to functions called at initialization
+ // if we don't have a defined entrypoint then use the first one in the list as the entrypoint
+ for (; i < (moduleInitSection.size / 4); i++)
{
- // FIXME: This isn't a super robust way of detagging,
- // should look into xnu source and the tools used to build this cache (if they're public)
- // and see if anything better can be done
+ uint64_t target = reader.Read32();
+ target += header.textBase;
+ Ref<Platform> targetPlatform = GetDefaultPlatform()->GetAssociatedPlatformByAddress(target);
+ auto name = "mod_init_func_" + to_string(modInitFuncCnt++);
+ AddEntryPointForAnalysis(targetPlatform, target);
+ auto symbol = new Symbol(FunctionSymbol, name, target, GlobalBinding);
+ DefineAutoSymbol(symbol);
- // mask out top 8 bits
- uint64_t tag = 0xFFFFFFFF00000000 & header.textBase;
- // and combine them with bottom 8 of the original entry
- target = tag | (target & 0xFFFFFFFF);
+ // FIXME: i don't know how to define proper pointer type at this stage of analysis
+ Ref<Type> pointerVar = TypeBuilder::PointerType(4, Type::VoidType())
+ .SetPointerBase(RelativeToConstantPointerBaseType, header.textBase)
+ .Finalize();
+ DefineDataVariable(GetStart() + reader.GetOffset() - 4, pointerVar);
}
- Ref<Platform> targetPlatform = GetDefaultPlatform()->GetAssociatedPlatformByAddress(target);
- auto name = "mod_init_func_" + to_string(modInitFuncCnt++);
- AddEntryPointForAnalysis(targetPlatform, target);
- auto symbol = new Symbol(FunctionSymbol, name, target, GlobalBinding);
- DefineAutoSymbol(symbol);
}
}