// ./insert_dylib @executable_path(表示加载bin所在目录)/inject.dylib test   
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/stat.h>
#include <copyfile.h>
#include <mach-o/loader.h>
#include <mach-o/fat.h>

#define IS_64_BIT(x) ((x) == MH_MAGIC_64 || (x) == MH_CIGAM_64)
#define IS_LITTLE_ENDIAN(x) ((x) == FAT_CIGAM || (x) == MH_CIGAM_64 || (x) == MH_CIGAM)
#define SWAP32(x, magic) (IS_LITTLE_ENDIAN(magic)? OSSwapInt32(x): (x))

__attribute__((noreturn)) void usage(void) {
	printf("Usage: insert_dylib [--inplace] [--weak] dylib_path binary_path [new_path]\n");
	
	exit(1);
}

__attribute__((format(printf, 1, 2))) bool ask(const char *format, ...) {
	char *question;
	asprintf(&question, "%s [y/n] ", format);
	
	va_list args;
	va_start(args, format);
	vprintf(question, args);
	va_end(args);
	
	free(question);
	
	while(true) {
		char *line = NULL;
		size_t size;
		getline(&line, &size, stdin);
		
		switch(line[0]) {
			case 'y':
			case 'Y':
				return true;
				break;
			case 'n':
			case 'N':
				return false;
				break;
			default:
				printf("Please enter y or n: ");
		}
	}
}

void remove_code_signature(FILE *f, struct mach_header *mh, size_t header_offset, size_t commands_offset) {
	fseek(f, commands_offset, SEEK_SET);
	
	uint32_t ncmds = SWAP32(mh->ncmds, mh->magic);
	
	for(int i = 0; i < ncmds; i++) {
		struct load_command lc;
		fread(&lc, sizeof(lc), 1, f);
		
		if(SWAP32(lc.cmd, mh->magic) == LC_CODE_SIGNATURE) {
			if(i == ncmds - 1 && ask("LC_CODE_SIGNATURE load command found. Remove it?")) {
				fseek(f, -((long)sizeof(lc)), SEEK_CUR);
				
				struct linkedit_data_command ldc;
				fread(&ldc, sizeof(ldc), 1, f);
				
				uint32_t cmdsize = SWAP32(ldc.cmdsize, mh->magic);
				uint32_t dataoff = SWAP32(ldc.dataoff, mh->magic);
				uint32_t datasize = SWAP32(ldc.datasize, mh->magic);
				
				fseek(f, -((long)sizeof(ldc)), SEEK_CUR);
				
				char *zero = calloc(cmdsize, 1);
				fwrite(zero, cmdsize, 1, f);
				free(zero);
				
				fseek(f, header_offset + dataoff, SEEK_SET);
				
				zero = calloc(datasize, 1);
				fwrite(zero, datasize, 1, f);
				free(zero);
				
				mh->ncmds = SWAP32(ncmds - 1, mh->magic);
				mh->sizeofcmds = SWAP32(SWAP32(mh->sizeofcmds, mh->magic) - ldc.cmdsize, mh->magic);
				
				return;
			} else {
				printf("LC_CODE_SIGNATURE is not the last load command, so couldn't remove.");
			}
		}
		
		fseek(f, SWAP32(lc.cmdsize, mh->magic) - sizeof(lc), SEEK_CUR);
	}
}

bool insert_dylib(FILE *f, size_t header_offset, const char *dylib_path, bool weak) {
	fseek(f, header_offset, SEEK_SET);
	
	struct mach_header mh;
	fread(&mh, sizeof(struct mach_header), 1, f);
	
	if(mh.magic != MH_MAGIC_64 && mh.magic != MH_CIGAM_64 && mh.magic != MH_MAGIC && mh.magic != MH_CIGAM) {
		printf("Unknown magic: 0x%x\n", mh.magic);
		return false;
	}
	
	size_t commands_offset = header_offset + (IS_64_BIT(mh.magic)? sizeof(struct mach_header_64): sizeof(struct mach_header));
	
	remove_code_signature(f, &mh, header_offset, commands_offset);
	
	size_t dylib_path_len = strlen(dylib_path);
	size_t dylib_path_size = (dylib_path_len & ~3) + 4;
	uint32_t cmdsize = (uint32_t)(sizeof(struct dylib_command) + dylib_path_size);
	
	struct dylib_command dylib_command = {
		.cmd = SWAP32(weak? LC_LOAD_WEAK_DYLIB: LC_LOAD_DYLIB, mh.magic),
		.cmdsize = SWAP32(cmdsize, mh.magic),
		.dylib = {
			.name = SWAP32(sizeof(struct dylib_command), mh.magic),
			.timestamp = 0,
			.current_version = 0,
			.compatibility_version = 0
		}
	};
	
	uint32_t sizeofcmds = SWAP32(mh.sizeofcmds, mh.magic);
	
	fseek(f, commands_offset + sizeofcmds, SEEK_SET);
	char space[cmdsize];
	
	fread(&space, cmdsize, 1, f);
	
	bool empty = true;
	for(int i = 0; i < cmdsize; i++) {
		if(space[i] != 0) {
			empty = false;
			break;
		}
	}
	
	if(!empty) {
		if(!ask("It doesn't seem like there is enough empty space. Continue anyway?")) {
			return false;
		}
	}
	
	fseek(f, -((long)cmdsize), SEEK_CUR);
	
	char *dylib_path_padded = calloc(dylib_path_size, 1);
	memcpy(dylib_path_padded, dylib_path, dylib_path_len);
	
	fwrite(&dylib_command, sizeof(dylib_command), 1, f);
	fwrite(dylib_path_padded, dylib_path_size, 1, f);
	
	free(dylib_path_padded);
	
	mh.ncmds = SWAP32(SWAP32(mh.ncmds, mh.magic) + 1, mh.magic);
	sizeofcmds += cmdsize;
	mh.sizeofcmds = SWAP32(sizeofcmds, mh.magic);
	
	fseek(f, header_offset, SEEK_SET);
	fwrite(&mh, sizeof(mh), 1, f);
	
	return true;
}

int main(int argc, const char *argv[]) {
	int inplace = false;
	int weak = false;
	
	struct option long_options[] = {
		{"inplace", no_argument, &inplace, true},
		{"weak",    no_argument, &weak,    true}
	};
	
	while(true) {
		int option_index = 0;
		
		int c = getopt_long(argc, (char *const *)argv, "", long_options, &option_index);
		
		if(c == -1) {
			break;
		}
		
		switch(c) {
			case 0:
				break;
			case '?':
				usage();
				break;
			default:
				abort();
				break;
		}
	}
	
	argv = &argv[optind - 1];
	argc -= optind - 1;
	
	if(argc < 3 || argc > 4) {
		usage();
	}
	
	const char *lc_name = weak? "LC_LOAD_WEAK_DYLIB": "LC_LOAD_DYLIB";
	
	const char *dylib_path = argv[1];
	const char *binary_path = argv[2];
	
	struct stat s;
	
	if(stat(binary_path, &s) != 0) {
		perror(binary_path);
		exit(1);
	}
	
	if(stat(dylib_path, &s) != 0) {
		if(!ask("The provided dylib path doesn't exist. Continue anyway?")) {
			exit(1);
		}
	}
	
	bool binary_path_was_malloced = false;
	if(!inplace) {
		char *new_binary_path;
		if(argc == 4) {
			new_binary_path = (char *)argv[3];
		} else {
			asprintf(&new_binary_path, "%s_patched", binary_path);
			binary_path_was_malloced = true;
		}
		
		if(stat(new_binary_path, &s) == 0) {
			if(!ask("%s already exists. Overwrite it?", new_binary_path)) {
				exit(1);
			}
		}
		
		if(copyfile(binary_path, new_binary_path, NULL, COPYFILE_DATA | COPYFILE_UNLINK)) {
			printf("Failed to create %s\n", new_binary_path);
			exit(1);
		}
		
		binary_path = new_binary_path;
	}
	
	FILE *f = fopen(binary_path, "r+");
	
	if(!f) {
		printf("Couldn't open file %s\n", argv[1]);
		exit(1);
	}
	
	bool success = true;
		
	uint32_t magic;
	fread(&magic, sizeof(uint32_t), 1, f);
	
	switch(magic) {
		case FAT_MAGIC:
		case FAT_CIGAM: {
			fseek(f, 0, SEEK_SET);
			
			struct fat_header fh;
			fread(&fh, sizeof(struct fat_header), 1, f);
			
			uint32_t nfat_arch = SWAP32(fh.nfat_arch, magic);
			
			printf("Binary is a fat binary with %d archs.\n", nfat_arch);
			
			struct fat_arch archs[nfat_arch];
			fread(&archs, sizeof(archs), 1, f);
			
			int fails = 0;
			
			for(int i = 0; i < nfat_arch; i++) {
				bool r = insert_dylib(f, SWAP32(archs[i].offset, magic), dylib_path, weak);
				if(!r) {
					printf("Failed to add %s to arch #%d!\n", lc_name, i + 1);
					fails++;
				}
			}
			
			if(fails == 0) {
				printf("Added %s to all archs in %s\n", lc_name, binary_path);
			} else if(fails == nfat_arch) {
				printf("Failed to add %s to any archs.\n", lc_name);
				success = false;
			} else {
				printf("Added %s to %d/%d archs in %s\n", lc_name, nfat_arch - fails, nfat_arch, binary_path);
			}
			
			break;
		}
		case MH_MAGIC_64:
		case MH_CIGAM_64:
		case MH_MAGIC:
		case MH_CIGAM:
			if(insert_dylib(f, 0, dylib_path, weak)) {
				printf("Added %s to %s\n", lc_name, binary_path);
			} else {
				printf("Failed to add %s!\n", lc_name);
				success = false;
			}
			break;
		default:
			printf("Unknown magic: 0x%x\n", magic);
			exit(1);
	}
	
	fclose(f);
	
	if(!success) {
		if(!inplace) {
			unlink(binary_path);
		}
		exit(1);
	}
	
	if(binary_path_was_malloced) {
		free((void *)binary_path);
	}
	
    return 0;
}

你可能感兴趣的文章

评论区

已有248位网友发表了看法:

1L 游客  2024-07-15 11:11:38 回复
楼主是男的还是女的?http://ymmbzo.0478g.com
2L 游客  2024-07-15 11:48:43 回复
关注一下!http://gengsha.cn/
3L 游客  2024-07-15 13:20:33 回复
楼主很有艺术范!http://www.zgcpx.cn/c/2243245.html
4L 游客  2024-07-15 13:35:55 回复
听楼主一席话,省我十本书!http://vrer.ffnbx.net/test/422504405.html
5L 游客  2024-07-15 13:57:41 回复
这里的资源非常丰富,帮助我解决了很多问题。https://www.iyxwzx.com/zhishi/
6L 游客  2024-07-15 14:00:59 回复
论坛的人气不行了!https://www.iyxwzx.com/zhishi/
7L 游客  2024-07-15 14:15:27 回复
坚持回帖!https://www.taofangke.cn/cd/house/185.html
8L 游客  2024-07-15 16:59:56 回复
知识就是力量啊!http://2f1.www.cdrtri.com
9L 游客  2024-07-15 17:43:06 回复
小弟默默的路过贵宝地~~~http://tdvt.ffnbx.net/test/608260444.html
10L 游客  2024-07-15 18:15:57 回复
支持一个https://xzl.ddzxzl.com/post/18816.html
11L 游客  2024-07-15 18:19:30 回复
最近回了很多帖子,都没人理我!https://jianhaozhan.com/13401
12L 游客  2024-07-15 20:18:13 回复
雷锋做好事不留名,都写在帖子里!https://www.qupojie.cn/category-azgame.html
13L 游客  2024-07-15 21:39:06 回复
太高深了,理解力不够用了!https://sdceda.com/fei/260525282/
14L 游客  2024-07-15 23:50:40 回复
听楼主一席话,省我十本书!https://www.qupojie.cn/category-azgame.html
15L 游客  2024-07-16 01:04:47 回复
楼主是我最崇拜的人!http://lzwm.ffnbx.net/test/259570115.html
16L 游客  2024-07-16 04:48:11 回复
很经典,收藏了!https://sdceda.com/fei/405968268/
17L 游客  2024-07-16 07:58:55 回复
语言表达流畅,没有冗余,读起来很舒服。http://rc1d.0478g.com
18L 游客  2024-07-16 08:23:43 回复
雷锋做好事不留名,都写在帖子里!http://www.yiwu-company.com/bx/info_37130.html
19L 游客  2024-07-16 10:17:02 回复
这么经典的话只有楼主能想到!https://www.gwxz8.com/articleColumn/fdgw/tztb/init/1.html
20L 游客  2024-07-16 11:05:30 回复
经典!http://kgse.ffnbx.net/test/175078944.html
21L 游客  2024-07-16 11:26:58 回复
楼主加油,看好你哦!https://weibo.com/tv/show/1034:5056362657284148
22L 游客  2024-07-16 12:41:19 回复
这么经典的话只有楼主能想到!http://5fa06k.https://www.hkdiyi.com/a/17698.html
23L 游客  2024-07-16 14:27:47 回复
小弟默默的路过贵宝地~~~https://sdceda.com/fei/032953252/
24L 游客  2024-07-16 14:35:01 回复
无图无真相!https://sdceda.com/fei/847821993/
25L 游客  2024-07-16 14:37:06 回复
大神就是大神,这么经典!http://cssd.ffnbx.net/test/079181163.html
26L 游客  2024-07-16 14:37:38 回复
语言表达流畅,没有冗余,读起来很舒服。http://wcch.ffnbx.net/test/757331942.html
27L 游客  2024-07-16 16:10:48 回复
态度决定一切,不错!https://www.gwxz8.com/articleColumn/fdgw/tztb/init/1.html
28L 游客  2024-07-16 16:26:47 回复
怎么我回帖都没人理我呢?http://www.yuhua77.com
29L 游客  2024-07-16 16:43:44 回复
楼上的这是啥态度呢?https://sdceda.com/fei/911886506/
30L 游客  2024-07-16 17:27:30 回复
今天怎么了,什么人都出来了!https://sdceda.com/fei/942210778/
31L 游客  2024-07-16 17:51:53 回复
管它三七二十一!http://www.zhijian.me/t-56-1-1.html
32L 游客  2024-07-16 20:58:22 回复
这篇文章真是让人受益匪浅!http://gengsha.cn/dna/147.html
33L 游客  2024-07-16 22:04:08 回复
大神就是大神,这么经典!https://www.henghost.com/
34L 游客  2024-07-17 00:20:21 回复
楼上的别说的那么悲观好吧!http://175kf.com
35L 游客  2024-07-17 02:51:16 回复
以后要跟楼主好好学习学习!http://gengsha.cn/dna/83.html
36L 游客  2024-07-17 04:15:58 回复
回帖也有有水平的!https://www.weimaitu.com/13.html
37L 游客  2024-07-17 07:56:30 回复
哥回复的不是帖子,是寂寞!http://ncjm.google520.net
38L 游客  2024-07-17 09:25:38 回复
很多天不上线,一上线就看到这么给力的帖子!http://175kf.com
39L 游客  2024-07-17 10:39:52 回复
听楼主一席话,省我十本书!http://gqqhd.www.zsbfz.com
40L 游客  2024-07-17 11:55:57 回复
不灌水就活不下去了啊!https://www.guanzhangtu.com/redianzixun/
41L 游客  2024-07-17 12:44:15 回复
支持楼上的!http://www.sm598.com/n/293246013.html
42L 游客  2024-07-17 13:16:32 回复
对牛弹琴的人越来越多了!http://a69.zhijian.me
43L 游客  2024-07-17 13:18:36 回复
突然觉得楼主说的很有道理,赞一个!http://sf5.zhijian.me
44L 游客  2024-07-17 13:23:50 回复
文章写太挺好了,真的值得推荐http://www.zhijian.me/t-56-1-1.html
45L 游客  2024-07-17 15:56:05 回复
我回帖楼主给加积分吗?http://66iko.http://datongkeyun.com
46L 游客  2024-07-17 16:47:14 回复
祖国尚未统一,我却天天灌水,好内疚!http://bi2p.www.weimaitu.com
47L 游客  2024-07-17 18:16:36 回复
楼上的说的很多!https://www.gjtt.net
48L 游客  2024-07-17 19:32:46 回复
以后就跟楼主混了!http://175kf.com
49L 游客  2024-07-17 22:08:06 回复
灌水不是我的目的!http://m.pc235.com/soft/386.html
50L 游客  2024-07-17 22:11:06 回复
回帖也有有水平的!http://www.zgcpx.cn/c/5746190.html
51L 游客  2024-07-17 22:15:03 回复
最近回了很多帖子,都没人理我!http://www.yiwu-company.com/bx/info_29864.html
52L 游客  2024-07-18 03:05:28 回复
我只看看不说话。。。http://www.sm598.com/n/435543740.html
53L 游客  2024-07-18 03:42:20 回复
这么经典的话只有楼主能想到!http://gengsha.cn/dna/433.html
54L 游客  2024-07-18 04:32:37 回复
楼主的等级很高啊!http://175kf.com
55L 游客  2024-07-18 05:44:24 回复
在哪里跌倒,就在那里多爬一会儿!http://m.pc235.com/game/925.html
56L 游客  2024-07-18 05:45:23 回复
大神就是大神,这么经典!http://m.pc235.com/game/263.html
57L 游客  2024-07-18 06:40:12 回复
顶一个!http://gengsha.cn/dna/19.html
58L 游客  2024-07-18 10:44:12 回复
看了这么多帖子,第一次看到这么经典的!https://www.uuu9923.cn/1872.html
59L 游客  2024-07-18 11:25:53 回复
怎么我回帖都没人理我呢?https://www.gjtt.net
60L 游客  2024-07-18 11:35:56 回复
信楼主,得永生!http://175kf.com
61L 游客  2024-07-18 13:22:31 回复
吹牛的人越来越多了!http://aafi.zhijian.me
62L 游客  2024-07-18 13:57:32 回复
有品位!http://175kf.com
63L 游客  2024-07-18 16:21:37 回复
听楼主一席话,省我十本书!https://www.uuu9923.cn/1858.html
64L 游客  2024-07-18 17:43:58 回复
支持一下!http://60i.www.lcget.com
65L 游客  2024-07-18 18:28:28 回复
论坛的人气越来越旺了!http://kwl75.www.szhqty.com/
66L 游客  2024-07-18 19:55:10 回复
楼主的头像是本人吗?https://weibo.com/tv/show/1034:5057436592046153
67L 游客  2024-07-18 20:33:59 回复
有机会找楼主好好聊聊!http://4jhlh.google520.net
68L 游客  2024-07-18 21:06:37 回复
楼主是在找骂么?https://www.uuu9923.cn/1872.html
69L 游客  2024-07-19 00:07:13 回复
收藏了,以后可能会用到!http://www.pc235.com/news/274.html
70L 游客  2024-07-19 02:17:20 回复
楼主加油,看好你哦!https://www.uuu9923.cn/1872.html
71L 游客  2024-07-19 02:25:44 回复
怪事年年有,今年特别多!http://175kf.com
72L 游客  2024-07-19 02:25:52 回复
楼主主机很热情啊!https://www.uuu9923.cn/1872.html
73L 游客  2024-07-19 02:45:12 回复
对牛弹琴的人越来越多了!http://hrkut.www.szhqty.com/
74L 游客  2024-07-19 06:16:41 回复
最近回了很多帖子,都没人理我!http://m.pc235.com/game/1300.html
75L 游客  2024-07-19 07:31:40 回复
楼主你想太多了!https://www.uuu9923.cn/1858.html
76L 游客  2024-07-19 08:17:16 回复
强,我和我的小伙伴们都惊呆了!http://6vj.https://www.weimaitu.com/
77L 游客  2024-07-19 08:21:35 回复
学习雷锋,好好回帖!http://xoh.www.lcget.com
78L 游客  2024-07-19 08:57:43 回复
不是惊喜,是惊吓!http://toolg.cn/
79L 游客  2024-07-19 09:27:21 回复
楼主的等级很高啊!https://www.uuu9923.cn/1858.html
80L 游客  2024-07-19 09:28:59 回复
刚分手,心情不好!https://www.uuu9923.cn/1872.html
81L 游客  2024-07-19 09:29:13 回复
楼主最近很消极啊!https://www.uuu9923.cn/1872.html
82L 游客  2024-07-19 11:52:01 回复
经典,收藏了!http://175kf.com
83L 游客  2024-07-19 12:10:40 回复
支持一个https://www.uuu9923.cn/1872.html
84L 游客  2024-07-19 14:46:45 回复
楼主今年多大了?http://4xpx.www.ywz1.com
85L 游客  2024-07-19 15:01:11 回复
顶顶更健康!http://175kf.com
86L 游客  2024-07-19 15:15:08 回复
很给力!https://www.uuu9923.cn/1858.html
87L 游客  2024-07-19 15:27:39 回复
收藏了,以后可能会用到!http://175kf.com
88L 游客  2024-07-19 15:32:49 回复
楼主是我最崇拜的人!https://www.uuu9923.cn/1858.html
89L 游客  2024-07-19 15:59:35 回复
看帖不回帖的人就是耍流氓,我回复了!https://weibo.com/tv/show/1034:5057779245973557
90L 游客  2024-07-19 16:37:13 回复
很多天不上线,一上线就看到这么给力的帖子!http://175kf.com
91L 游客  2024-07-19 17:16:42 回复
帖子好乱!https://www.uuu9923.cn/1872.html
92L 游客  2024-07-19 17:18:58 回复
管它三七二十一!http://o1zs3.www.lcget.com
93L 游客  2024-07-19 18:23:55 回复
网页的加载速度非常快,不会影响用户体验。http://175kf.com
94L 游客  2024-07-19 19:20:29 回复
态度决定一切,不错!https://weibo.com/tv/show/1034:5057776578134066
95L 游客  2024-07-19 21:37:10 回复
楼主的帖子提神醒脑啊!https://www.ggplus.cn/18816.html
96L 游客  2024-07-19 22:01:09 回复
好帖子!http://175kf.com
97L 游客  2024-07-19 22:32:30 回复
这里的资源非常丰富,帮助我解决了很多问题。https://www.youxixiong.com/18.html
98L 游客  2024-07-19 22:54:23 回复
哥回复的不是帖子,是寂寞!https://www.msl.wang/links/c04d9eea9917470f707e.html
99L 游客  2024-07-19 23:28:15 回复
我对楼主的敬仰犹如滔滔江水绵延不绝!http://www.pc235.com/game/109.html
100L 游客  2024-07-20 02:05:47 回复
我和我的小伙伴都惊呆了!http://zhan.icu/thread-19-1-1.html

发表评论

必填

选填

选填

必填

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。