반응형

nic.pl --> 5. iphone/control_center_module-11up

※ iPhone6s+(iOS 13.5.1)에 THEOS를 설치하여 진행하였습니다.

 

Control Center Module 예제 소스코드는 https://github.com/M4cs/EzCC-Modules 에 많이 있습니다.

원하는 기능과 유사한 코드를 가져와서 쓰면 잘 작동합니다.

 

Control Center에 사용되는 아이콘은 배경이 제거된 흑백 아이콘 입니다.

컬러 변경은 파워포인트에서 손쉽게 할 수 있고, png 파일의 배경은 https://onlinepngtools.com/create-transparent-png 에서 쉽게 제거할 수 있습니다.

 

 

예제 소스코드를 보면 Resources/ 디렉터리 하위에 Icon@2x.png, Icon@3x.png 처럼 모양은 같으나 사이즈가 다른 아이콘들이 들어가 있더군요.

따라서, 배경이 제거된 흑백 아이콘을 이용해 다양한 사이즈의 아이콘을 만들어줄 필요가 있습니다.

해당 기능은  https://hotpot.ai/icon-resizer 에서 제공하고 있습니다.

배경이 제거된 흑백 아이콘을 업로드하고, "iOS Icon" 버튼을 켠다음 Convert 버튼을 누르면 여러사이즈의 아이콘이 포함된 zip 파일이 생성됩니다.

 

 

이제 아이콘을 제작하였으면 Resources/ 디렉터리 하위에 위치시켜줍니다. 메인소스코드에서도 해당 아이콘을 쓰겠다고 아이콘의 확장자를 제외한 이름을 명시해줘야 합니다.

// Icon of your module
- (UIImage *)iconGlyph {
    return [UIImage imageNamed:@"Icon" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
}

 

 

소스코드 상에 명시한 아이콘은 컨트롤 센터에서 보여지는 아이콘입니다.

Resources/ 하위에 위치해있는 SettingsIcon은 Control Center 설정창에서 보여지는 아이콘입니다. 해당 아이콘은 흑백 및 배경이 제거될 필요는 없으며, 소스코드상에 명시해줄 필요도 없습니다. 이름이 SettingsIcon이면 자동으로 인식하는 것으로 생각됩니다.

 

 

컨트롤 센터에서 선택했을때 respring 시켜주는 간단한 cc 모듈의 소스코드입니다.

// Makefile
TARGET := iphone:clang:latest:11.0
INSTALL_TARGET_PROCESSES = SpringBoard
ARCHS := arm64

include $(THEOS)/makefiles/common.mk

BUNDLE_NAME = respring
respring_BUNDLE_EXTENSION = bundle
respring_FILES = respring.m
respring_CFLAGS = -fobjc-arc
respring_PRIVATE_FRAMEWORKS = ControlCenterUIKit
respring_INSTALL_PATH = /Library/ControlCenter/Bundles/

include $(THEOS_MAKE_PATH)/bundle.mk
// respring.h
#import <ControlCenterUIKit/CCUIToggleModule.h>

@interface respring : CCUIToggleModule
@property (nonatomic, assign, readwrite) BOOL Hackcatml;
@end
// respring.m
#import "respring.h"
#import <spawn.h>
#import <sys/wait.h>

@implementation respring

// Icon of your module
- (UIImage *)iconGlyph {
    return [UIImage imageNamed:@"Icon" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
}

// Selected color of your module
- (UIColor *)selectedColor {
    return [UIColor blueColor];
}

// Current state of your module
- (BOOL)isSelected {
    return self.Hackcatml;
}

- (void)setSelected:(BOOL)selected {
    self.Hackcatml = selected;
	[super refreshState];
    [self respring];
}

- (void)respring {
    pid_t pid;
    int status;
    const char* args[] = {"sbreload", NULL};
    posix_spawn(&pid, "/usr/bin/sbreload", NULL, NULL, (char* const*)args, NULL);
    waitpid(pid, &status, WEXITED);
}
@end

 

 

여기서 조금 더 깊게 들어가서, 컨트롤 센터에서 터치하여 실행시켜주는 command는 root권한으로 실행되지 않습니다.

respring이나, uicache 같은 명령어는 굳이 root권한으로 실행안해줘도 잘 작동하므로 상관 없습니다.

그러나 제가 일전에 제작한 fricon(https://hackcatml.tistory.com/119) 툴의 경우에는 위의 방식대로 cc 모듈을 만들어도 실행되지 않습니다. fricon 명령어는 "mobile" userId의 권한으로 실행되지만, frida는 실행되지 않았습니다.

 

 

Control Center 모듈에서 root 권한으로 command 실행이 필요한 경우에는 어떻게 해야 할까요?

https://github.com/captinc/CommandModule 에서 아이디어를 얻을 수 있었습니다.

위 모듈은 CC에서 루트 권한으로 ShellScript를 실행시켜줍니다.

 

작동방식은 다음과 같습니다.

CC에서 아이콘 선택 --> 특정 command(ex. fricon)를 위한 command tool(ex. commandtoolforfricon) 호출 --> 호출된 command tool은 "setuid(0);" 가 설정된 상태에서 target command(ex. fricon) 호출 --> target command(ex. fricon)은 root권한으로 명령 수행

 

요약하면, CC로 수행하고자 하는 target command tool 사이에 권한상승을 위한 command tool을 하나 더 위치시킵니다.

"CC" ------------------------> "command tool for target command" ------------------------> "target command tool"

 

그런데, 중간에 위치한 "command tool for target command"은 "setuid(0);" 가 설정되었다고 해서 루트권한으로 실행되지 않더군요. chmod +s 명령어로 실행파일에 setuid 비트를 설정해줘야 합니다. 이 과정은 deb 패키지에 postinst 스크립트를 포함하여 해결할 수 있겠지요.

 

 

위 아이디어를 적용하여 특정 command를 root권한으로 실행시켜주는 CC 모듈을 작성해보았습니다.

// main.m(commandtoolforfricon)
#include <stdlib.h>
#include <unistd.h>
#include <spawn.h>

int main(int argc, char *argv[], char *envp[]) {
    setuid(0); //make us root. if not set this, command not work.
	pid_t pid;
    int status;

	// Process parameters
	NSArray *arguments =[[NSProcessInfo processInfo] arguments];
	NSString *command = [arguments objectAtIndex:1];

	// when cc selected, fricon start
	if([command isEqualToString:@"start"]){
    	const char* args[] = {"/usr/local/bin/fricon", "start", NULL};
    	posix_spawn(&pid, "/usr/local/bin/fricon", NULL, NULL, (char* const*)args, NULL);
	}
	// when cc is unselected, fricon stop
	else {
    	const char* args[] = {"/usr/local/bin/fricon", "stop", NULL};
    	posix_spawn(&pid, "/usr/local/bin/fricon", NULL, NULL, (char* const*)args, NULL);
	}
    
	waitpid(pid, &status, WEXITED);
		
    return 0;
}

 

 

CC에서 frida아이콘 선택시 정상적으로 fricon 명령어가 루트권한으로 실행되어 frida-server가 구동되는 것을 확인할 수 있습니다.

 

 

반응형

+ Recent posts