1212#include <stdio.h>
1313#include <stdlib.h>
1414#include <string.h>
15- #include <libgen.h>
1615#include <fcntl.h>
1716#include <errno.h>
1817#include <unistd.h>
18+ #include <limits.h>
1919#include <copyfile.h>
2020#include <stdbool.h>
2121#include <sys/stat.h>
2727
2828static const char __used
2929_whatMsg [] = "@(#) inject_decrypt: decrypt Mach-O executables using injection" ,
30- _whatUsg [] = "@(#) Usage: DYLD_INSERT_LIBRARIES=inject_decrypt.dylib <executable> [-avvv] <out_path> " ;
30+ _whatUsg [] = "@(#) Usage: DYLD_INSERT_LIBRARIES=inject_decrypt.dylib <executable>" ;
3131
3232__attribute__((constructor , noreturn ))
3333static void dump (int argc , char * argv []) {
34- const char * __restrict usageMessageFormat =
35- "Usage: DYLD_INSERT_LIBRARIES=inject_decrypt.dylib %s [-avvv] <out_path>\n"
34+ const char * usageMessage =
35+ "Usage: DYLD_INSERT_LIBRARIES=inject_decrypt.dylib <executable> [-avvv] <out_path>\n"
3636 " -a all images (out_path should be a non-existant directory)\n"
3737 " -v verbose mode, multiple increases verbosity" ;
38- char usageMessage [strlen (usageMessageFormat ) - 2 + strlen (argv [0 ]) + 1 ]; /* %s is -2, null term is +1 */
39- snprintf (usageMessage , sizeof (usageMessage ), usageMessageFormat , argv [0 ]);
4038
4139 if (argc < 2 ) {
4240 puts (usageMessage );
@@ -79,6 +77,18 @@ static void dump(int argc, char *argv[]) {
7977 }
8078 }
8179
80+ char realPathBuff [PATH_MAX ];
81+
82+ const char * mainExecPath = _dyld_get_image_name (0 );
83+ if (realpath (mainExecPath , realPathBuff ) == NULL ) {
84+ printf ("Could not resolve the real path of %s\n" , mainExecPath );
85+ exit (EXIT_FAILURE );
86+ }
87+ size_t const treePathLen = strrchr (realPathBuff , '/' ) + 1 - realPathBuff ;
88+ char treePath [treePathLen + 1 ];
89+ strlcpy (treePath , realPathBuff , sizeof (treePath ));
90+ VerboseLog (2 , "Using %s as tree root\n" , treePath );
91+
8292 for (uint32_t i = 0 ; i < _dyld_image_count (); i ++ ) {
8393 const struct mach_header * mh = _dyld_get_image_header (i );
8494
@@ -93,8 +103,7 @@ static void dump(int argc, char *argv[]) {
93103 }
94104
95105 const char * readPath = _dyld_get_image_name (i );
96- struct stat statInfo ;
97- if (stat (readPath , & statInfo ) != 0 ) {
106+ if (access (readPath , F_OK )) {
98107 if (errno == ENOENT ) {
99108 errno = 0 ;
100109 VerboseLog (3 , "%s doesn't exist on disk, skipping\n" , readPath );
@@ -104,6 +113,14 @@ static void dump(int argc, char *argv[]) {
104113 exit (EXIT_FAILURE );
105114 }
106115 }
116+ if (realpath (readPath , realPathBuff ) == NULL ) {
117+ printf ("Could not resolve the real path of %s\n" , readPath );
118+ exit (EXIT_FAILURE );
119+ }
120+ if (strncmp (realPathBuff , treePath , treePathLen )) {
121+ VerboseLog (3 , "Skipping %s, not in tree\n" , readPath );
122+ continue ;
123+ }
107124 VerboseLog (1 , "Decrypting %s\n" , readPath );
108125
109126 int read_fd = open (readPath , O_RDONLY );
@@ -112,15 +129,14 @@ static void dump(int argc, char *argv[]) {
112129 exit (EXIT_FAILURE );
113130 }
114131
115- const char * imageBase = basename (( char * ) readPath ) ;
132+ const char * imageBase = strrchr ( readPath , '/' ) + 1 ;
116133 char writePath [strlen (outPath ) + 1 + strlen (imageBase ) + 1 ];
117- strcpy (writePath , outPath );
134+ * writePath = 0 ;
135+ strlcat (writePath , outPath , sizeof (writePath ));
118136
119137 if (wantsFrameworks ) {
120- writePath [strlen (outPath )] = '/' ;
121- strcpy (writePath + strlen (outPath ) + 1 , imageBase );
122- } else {
123- writePath [strlen (outPath )] = 0 ;
138+ strlcat (writePath , "/" , sizeof (writePath ));
139+ strlcat (writePath , imageBase , sizeof (writePath ));
124140 }
125141 VerboseLog (2 , "Output file is %s\n" , writePath );
126142
0 commit comments