“This is the 20th day of my participation in the First Challenge 2022. For details: First Challenge 2022.”

preface

Dynamic library injection principle:

  • One is based on modificationMach-O Load Commands is implemented by modifying the Load Commands of the executable. Add LC_LOAD_DYLIB to Load Commands and write to the dylib path.Usage: insert_dylib dylib_path binary_path [new_binary_path]
  • One is to use the environment variable DYLD_INSERT_LIBRARIES, for example for dumpdecrypted (added:Clutchthroughposix_spawnpGenerate a new process, then suspend the process and dump memory)
  • The other is to create a suspended thread on the mounted process, apply for a piece of memory in this thread to load the dynamic library, and then restore the thread, and the dynamic library is injected (using the taskFor_PID function to get the target process handle, and then create a new thread within the process and execute its own code). Cycript executes script code in this way.

I. The difference between static and dynamic libraries

1.1 Characteristics of dynamic library

  • It exists in the form of.dylib,.framework and.tdb;
  • Its advantage is that it can keep only one file and memory space, so it can be used by multiple processes, such as system dynamic library;
  • Reduces the size of the executable file without linking to the object file.

1.2 Characteristics of static libraries

  • A way of sharing program code in the form of a. A or. Framework, which is essentially a binary executable; Often part of a program’s functionality is compiled into a library, exposing the form of a header file for developers to call
  • Static libraries consist of one or more object files. Can disassemble a static library into multiple Object files (AR-X)
  • Static libraries link directly to the object file and exist as part of it.

II. Compilation and injection of dynamic libraries

2.1 build

xcrun --sdk iphoneos clang++ dynamiclib -arch arm64 -framework Foundation Person.mm -o target.dylib -fvisibility=hidden

Copy the code
  • Makefile
CC = xcrun --sdk iphoneos clang++
ARCH = arm64
FRAMEWORK = -framework Foundation
VERSION = -compatibility_version 1 -current_version 1
VISIBLE = -fvisibility=hidden
TARGET = target.dylib

SOURCE = Person.m 

$(TARGET):$(SOURCE)
	$(CC) -dynamiclib -arch $(ARCH) $(FRAMEWORK) $(SOURCE) -o $(TARGET) $(VERSION)

.PHONY:clean
clean:
	rm $(TARGET)

Copy the code

2.2 Injection mode of dynamic library

2.2.1 How cycript is injected into dynamic libraries

Create a suspended thread on the mounted process, apply for a block of memory in this thread to load the dynamic library, and then restore the thread, the dynamic library is injected (using the taskFor_PID function to get the target process handle, and then create a new thread within the process and execute its own code).

2.2.2 Inject through the environment variable DYLD_INSERT_LIBRARIES

DYLD_INSERT_LIBRARIES = / PathFrom/dumpdecrypted dylib/PathTo # New Run Script Phase: CD ${TARGET_BUILD_DIR}export DYLD_INSERT_LIBRARIES=./libKNoke.dylib && /Applications/QKNQ.app/Contents/MacOS/QKNQ

Copy the code

2.2.3 Add LC_LOAD_DYLIB or LC_LOAD_WEAK_DYLIB of load command to specify the path of dynamic library to implement injection

  • optool
  • insert_dylib: Command line utility for inserting a dylib load command into a Mach-O binary

Modify the header of the App executable, add a load command to it, load the dylib that we built

  • Injection of repackaged dynamic libraries:Avoid injecting from environment variables every time - static: load dylib via LC_LOAD_DYLIB

This is done by modifying the Load Commands in the executable. Add LC_LOAD_DYLIB to Load Commands and write to the dylib path

Usage: insert_dylib dylib_path binary_path [new_binary_path]

Setuid + bash is used to run most iOS apps with root privileges

2. The information required by App to run is generally stored in its MachO header 43, where dylib information is specified by load Commands.

This information is stored statically in a binary file (not dynamically specified by DYLD_INSERT_LIBRARIES) and dynamically loaded by dyLD, so we give it the name “static” — when the App is executed, Dyld looks at load commands in its MachO header and loads the dylib associated with LC_LOAD_DYLIB into the process’s memory space

  • To modify LC_ID_DYLIDB, LC_LOAD_DYLIB, and LC_LOAD_DYLIB, use install_name_tool
install_name_toll -id xxx imputfile
install_name_toll -change old new imputfile

Copy the code
  • Enhanced injection by Cydia Substrate:

Configure the PList file, And put the corresponding plist and dylib files into the specified directory / Layout/Library/MobileSubstrate/DynamicLibraries /, / usr/lib/TweakInject is yourself through the DYLD_INSERT_LIBRARIES injection, Then run through the plist file in the DynamicLibraries directory and open the DynamicLibraries that meet the rules using dlopen

III. Export and hide symbols

3.1 Exporting Symbols

  • View exported symbol information
 nm  -gm tmp_64.dylib 

Copy the code
(__DATA,__data) external
(undefined) external _CFDataCreate (from CoreFoundation)
                 (undefined) external _CFNotificationCenterGetDarwinNotifyCenter (from CoreFoundation)
 (__TEXT,__text) external 
                  (undefined) external _IOObjectRelease (from IOKit)
                 (undefined) external _IORegistryEntryCreateCFProperty (from IOKit)
000000010ffa3f97 (__DATA,__objc_data) external _OBJC_CLASS_$_BslyjNwZmPCJkVst
000000010ffa3f97 (__DATA,__objc_data) external _OBJC_CLASS_$_ChiDDQmRSQpwQJgm

Copy the code

3.2 Hidden Symbols

  • Static parameter modification, does not export symbolic information
static char _person_name[30] = {'\ 0'};

Copy the code
  • Add -exported_symbols_list export_list to the compile parameter
CC = xcrun --sdk iphoneos clang
ARCH = arm64
FRAMEWORK = -framework Foundation
VERSION = -compatibility_version 1 -current_version 1 
EXPORT = -exported_symbols_list export_list
VISIBLE = -fvisibility=hidden
TARGET = target.dylib

SOURCE = Person.mm

target1:$(SOURCE1)
	$(CC) -dynamiclib -arch $(ARCH) $(FRAMEWORK) $(SOURCE) -o $(TARGET) $(VERSION)

target2:$(SOURCE1)
	$(CC) -dynamiclib -arch $(ARCH) $(FRAMEWORK) $(SOURCE) -o $(TARGET) $(VERSION) $(EXPORT)


target3:$(SOURCE1)
	$(CC) -dynamiclib -arch $(ARCH) $(FRAMEWORK) $(SOURCE) -o $(TARGET) $(VERSION) $(VISIBLE)

clean:
	rm $(TARGET)

Copy the code
  • Export symbols by specifying -fvisibility=hidden in the build parameter and increasing visibility(” default “) over the specified symbol
//#define EXPORT __attribute__((visibility("default")))

Copy the code
CC = xcrun --sdk iphoneos clang++
ARCH = arm64
FRAMEWORK = -framework Foundation
VERSION = -compatibility_version 1 -current_version 1
VISIBLE = -fvisibility=hidden
TARGET = target.dylib

SOURCE = Person.m 

$(TARGET):$(SOURCE)
	$(CC) -dynamiclib -arch $(ARCH) $(FRAMEWORK) $(SOURCE) -o $(TARGET) $(VERSION)

.PHONY:clean
clean:
	rm $(TARGET)

Copy the code

see also

Due to space reasons, more content please pay attention to # small program: iOS reverse, only for you to present valuable information, focus on mobile technology research field; For more services and advice, please follow # publicid: iOS Reverse.

🍅 Contact author: iOS Reverse (public number: iosrev)


🍅 Author profile: CSDN blog expert certification 🏆 international Top 50, Huawei Cloud enjoy expert certification 🏆, iOS reverse public number master


🍅 Resume template, technical assistance. Pay attention to me, all for you.