问题
I am trying to extract libraries from the Dyld_shared_cache, and need to fix in external references.
For example, the pointers in the __DATA.__objc_selrefs
section usually point to data outside the mach-o file, to fix that I would have to copy the corresponding c-string from the dyld and append it to the __TEXT.__objc_methname
section.
Though from my understanding of the Mach-O file format, this extension of the __TEXT.__objc_methname
would shift all the sections after it and would force me to fix all the offsets and pointers that reference them. Is there a way to add data to a section without breaking a lot of things?
Thanks!
回答1:
UPDATE
After clarifing with OP that extension of __TEXT.__objc_methname
would happen during Mach-O post processing of an existing executable I had a fresh look on the problem.
Another take would be to create a new load command LC_SEGMENT_64
with a new __TEXT_EXEC.__objc_methname
segment / section entry (normally __TEXT_EXEC
is used for some kernel stuff but essentially it's the same thing as __TEXT
). Here's a quick POC to ilustrate the concept:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
printf("%lx",[NSObject new]);
}
return 0;
}
Compile like this:
gcc main.m -c -o main.o
ld main.o -rename_section __TEXT __objc_methname __TEXT_EXEC __objc_methname -lobjc -lc
Interestingly only ld
up to High Sierra 10.14.6 generates __TEXT.__objc_methname
, no trace of it on Catalina, it's done differently.
UPDATE2.
Playing around with it, I noticed execution rights for __TEXT
segment (and __TEXT_EXEC
for that matter) are not required for __objc_methname
to work.
Even better specific segment & section names are not required:
I could pull off:
__DATA.__objc_methname
__DATA_CONST.__objc_methname
__ARBITRARY.__arbitrary
or in my case last __DATA
section__DATA.__objc_classrefs
where the original the data got concatenated by the selector name.
It's all fine as long as a proper null terminated C-string with the selector name is there. If I intentionally break the "new\0" in hex editor or MachOView I'll get
"+[NSObject ne]: unrecognized selector sent to instance ..."
upon launching my POC executable so the value is used for sure.
So to sum __TEXT.__objc_methname
section itself is likely some debugger hint made by the linker. The app runtime seems to only need selector names as char*
anywhere in memory.
回答2:
Thanks to @Kamil.S for the idea about adding a new load command and section.
One way to achieve adding more data to a section is to create a duplicate segment and section and insert it before the __LINKEDIT segment.
- Slide the __LINKEDIT segment so we have space to add the new section.
- define the slide amount, this must be page-aligned, so I choose 0x4000.
- add the slide amount to the relevant load commands, this includes but is not limited to:
- __LINKEDIT segment (duh)
- dyld_info_command
- symtab_command
- dysymtab_command
- linkedit_data_commands
- physically move the __LINKEDIT in the file.
- duplicate the section and change the following1
- size, should be the length of your new data.
- addr, should be in the free space.
- offset, should be in the free space.
- duplicate the segment and change the following1
- fileoff, should be the start of the free space.
- vmaddr, should be the start of the free space.
- filesize, anything as long as it is bigger than your data.
- vmsize, must be identical to filesize.
- nsects, change to reflect how many sections your adding.
- cmdsize, change to reflect the size of the segment command and its section commands.
- insert the duplicated segment and sections before the __LINKEDIT segment
- update the mach_header
- ncmds
- sizeofcmds
- physically write the extra data in the file.
- you can optionally change the segname and sectname fields, though it isn't necessary. thanks Kamil.S!
来源:https://stackoverflow.com/questions/61293156/extend-section-in-mach-o-file