이번에 트윅 개발을 위해 세팅을 진행할려고 한다.

본 환경은 맥북 m1 pro  환경에서 진행 되고 필자가 오늘 설치한 방법이니 참고하면 좋겠다.

기본적으로 트윅은 theos라는 툴을 이용하여 제작한다. 여러 라이브러리 및 기본 세팅을 도와주는 좋은 툴이다.

 

기본 세팅에 대한 정보는 hackcattml 님에게 얻었습니다.

https://hackcatml.tistory.com/107

 

THEOS 설치

frida로 후킹 시 알수 없는 이유로 크래시나는 경우가 있습니다. 그럴 경우, Theos 후킹 트윅 개발을 고려해볼수 있습니다. 저 같은 경우 탈옥탐지우회를 위해 fopen함수를 frida로 후킹하였는데, 알

hackcatml.tistory.com

맥에는 Homebrew가 세팅되어야 나중에 설정이 안꼬입니다.

 

# git과 ldid 설치
brew install git
brew install ldid

# user명 아래 파일에 theos 폴더와 안에 staging명으로 폴더 생성
mkdir ~/theos
mkdir ~/theos/staging

# theos와 staging을 환경 변수로 설정
echo "export THEOS=~/theos" >> ~/.zshrc
echo "export THEOS_STAGING_DIR=~/theos/staging" >> ~/.zshrc

# theos device 라이브러리를 다운로드
git clone --recursive https://github.com/theos/theos.git $THEOS

# ios sdk 중 원하는 버전을 다운로드 필자는 우선 다 다운로드함
# tmp이라는 거는 임시 폴더를 생성해야 불필요한 파일 생성을 줄이기 위해 임시 폴더 이용
curl -LO https://github.com/theos/sdks/archive/master.zip
TMP=$(mktemp -d)
unzip master.zip -d $TMP
mv $TMP/sdks-master/*.sdk $THEOS/sdks
rm -r master.zip $TMP

# 환경 변수에 추가
export workzone="$HOME/theos/bin"

# 환경 변수 적용을 위해서는 아래 명령어를 실행해야함
source ~/.zshrc

# 환경 변수 문제가 없다면 빨간 표시 없이 아무것도 뜨지 않을것이다.

위 세팅이 끝나면

theos/bin 내부에 있는 nic.pl을 실행시키면 된다

다만 ~경로가 아닌 theos 내부에서 프로젝트 생성이 아래 에러가 날것이다. 그렇기 때문에 ~경로에서 nic.pl을 실행하여

~디렉토리 바로 아래에 프로젝트를 생성한다.

[error] Cowardly refusing to make a project inside $THEOS

 

Project Name 은 소문자로 작성

특정 패키지 명으로 설정하고 싶으면 아래와 같이 설정 ex) com.hack.test

Package Name [com.yourcompany.tio]: com.hack.test
  • "이름 <메일>" 형식으로 작성
Author/Maintainer Name [Tyrell]:  <root@tyrell.kr>

SpringBoard에서 작동 시키고 싶다면 그냥 스킵을 위해 엔터

만약 특정 bundle id에 만 트윅이 작동하기 위해서는 세팅에 아래와 같이 설정

[iphone/tweak] MobileSubstrate Bundle filter [com.apple.springboard]: com.aaa.bbb
  • 설치 후 적용을 위해 지정한 앱 강제 종료
  • 강제 종료 원하지 않으면 "-"
  • 무시 "enter"로 스킵
[iphone/tweak] List of applications to terminate upon installation (space-separated, '-' for none) [SpringBoard]: (enter)

이제 code ./Tweak.x 명령어로 트윅 코딩을 시작하면 된다.

# vscode로 tweak.x를 여는 명령어
code ./Tweak.x

# 아래 둘다 가능하고 작성 코드를 기반으로 deb 아이폰 설치 파일을 만들어 주는 명령어
make package
# 빌드 번호 없이 파일명으로 생성
make package FINALPACKAGE=1

만약 빌드가 다 완료되었을 경우 

scp를 이용하여 deb 파일을 기기 내로 이동시킨다.

# 파일 보내기
# 폴더 전송시 -r 옵션을 주면 됨
scp [옵션] [파일명] [원격지_id]@[원격지_ip]:[받는 위치]
scp testfile root@[IP]:/tmp/data/local/  
# 파일 가져오기
cp [옵션] [원격지_id]@[원격지_ip]:[원본 위치] [받는 위치]
scp root@[IP]:/tmp/data/local/testfile /tmp

만든 트윅 파일 설치

dpkg -i [deb패키지파일]

설치 시

/Library/MobileSubstrate/DynamicLibraries 에 해당 트윅이 설치된 것을 확인가능

해당 트윅이 정상 작동 안할 시 SpringBoard 리스프링 할 것

killall SpringBoard

iOS의 경우 탈옥 탐지 우회 트윅이 존재한다. 하지만 안드로이드의 경우 잘 알려지지 않았는데

riru의 모듈과 Hide-My-Applist 모듈을 알려주려고 한다. 설치 방법은 매우 간단하니 루팅 후 Magisk만 사용하면 된다.

추후에 사용법에 대해 올리도록 하겠다.

https://github.com/LSPosed/LSPosed/releases/tag/v1.8.6

 

Release 1.8.6 · LSPosed/LSPosed

New Xposed API proposal As Android version iterates, the original Xposed API by rovo89 reaches its limits. Now we are working on the new modern Xposed API with features of application scope managem...

github.com

https://github.com/Dr-TSNG/Hide-My-Applist/releases/tag/V3.1.1

 

Release V3.1.1 · Dr-TSNG/Hide-My-Applist

Fix bugs Reduce logs when detail logs off Support system data isolation manage Don't need to reload config every time when upgrading system service version Fix system service not running on some A1...

github.com

https://github.com/vvb2060/riru-unshare/releases/tag/v2.0

 

Release v2.0 · vvb2060/riru-unshare

v2.0

github.com

https://github.com/canyie/Riru-MomoHider/releases/tag/0.0.8

 

Release 0.0.8 · canyie/Riru-MomoHider

Fix init.rc hiding on rootfs devices Optimize binaries size to speedup booting Note: This is the last version of this module. We are developing a new module "Shamiko" which based on Zygisk and pro...

github.com

https://mt2.cn/download/

 

下载 | MT管理器

 

mt2.cn

사용법은 Magisk에 들어가면 모듈 탭에 들어가고 저장소에서 설치를 들어간다. 

zip 파일선택시 아래와 같이 자동으로 깔리게 되고 재부팅 하면 사용이 가능하다.

'APP 모의해킹 > Android' 카테고리의 다른 글

Android TCP 통신 패킷 잡기  (0) 2023.07.13
Hooking 함수명 모를때  (0) 2023.05.11
Scrcpy 안드로이드 앱 화면 공유  (0) 2023.04.11
Frida Hooking  (0) 2023.03.29
Burp 인증서 설치  (0) 2023.03.28

https://github.com/Genymobile/scrcpy/releases/tag/v2.0

 

Release scrcpy v2.0 · Genymobile/scrcpy

To receive a notification on new releases, click on Watch > Custom > Releases on the top. scrcpy v2.0 Changes since v1.25: Add Audio forwarding (#14, #3757) Add H265 and AV1 video codec support (...

github.com

위 URL에 접속 후 자신의 환경에 맞게 파일 Download 필자는 Win64

다운로드 받은 파일을 adb가 저장된 폴더에 집어넣기 덮어쓰기 항목이 3개 있을텐데 덮어쓰기 진행

그 후 scrcpy 입력시 연결됨 만약 원격으로 붙고 싶을 시

#그냥 실행시
scrcpy
#단말기 IP 확인
scrcpy --tcpip
#원격으로 접속시
scrcpy --tcpip = [단말기 IP주소]
#화면 녹화
scrcpy --record file.mp4
#중단 후 저장
scrcpy --no-display --record file.mp4 scrcpy -Nr file.mkv

출력된 화면

한글 입력 안될시 Gboard 설치 후 아래와 같이 세팅

'APP 모의해킹 > Android' 카테고리의 다른 글

Hooking 함수명 모를때  (0) 2023.05.11
루팅 탐지 우회 모듈  (0) 2023.04.11
Frida Hooking  (0) 2023.03.29
Burp 인증서 설치  (0) 2023.03.28
안드로이드 무결성 검증  (0) 2023.03.28

구버전 앱 빌드 시 재설정 필요한 것들

에러 문구

Org.gradle.api.GradleScriptException: A problem occurred evaluating project ':app'.
Could not initialize class com.android.repository.api.RepoManager

https://stackoverflow.com/questions/69072328/could-not-initialize-class-com-android-repository-api-repomanager

 

> Could not initialize class com.android.repository.api.RepoManager

I am new in Android Studio. After setup, When I am trying to import an application I am getting that error So that gradle not able to build. Error:> Could not initialize class com.android.repos...

stackoverflow.com

compile, runtime, testCompile, testRuntime 은 Gradle 4.10 (2018.8.27) 이후 더이상 사용 안함
Gradle 7.0 (2021.4.9)에서 삭제되었다.

Gradle 7.3.3을 이용시에 그 전 버전 명령어 이용시 오류 반환 아래 표름 참고하여 변경함

Caused by: org.gradle.internal.metaobject.AbstractDynamicObject$CustomMessageMissingMethodException: Could not find method compile() for arguments
구 명령어 새로운 명령어
compile implementation
runtime runtimeOnly
testCompile testImplementation,
testRuntime testRuntimeOnly

에러문구

[Android] Manifest merger failed with multiple errors

안드로이드 12 부터는 exported 를 명시적으로 선언해야 한다.

AndroidManifest.xml의 activity와 receiver 항목에  android:exported="true" 속성을 추가해 주었다.

'Android App 개발 > APP 개발 일지' 카테고리의 다른 글

[Android Studio]View Binding  (0) 2022.08.24

Objection

설치

pip install objection

사용방법

objection -g [app name] explore
ios jailbreak disable
ios hooking watch method "[후킹 메소드]" --dump-return
ios hooking set return_value "[메소드]" 0x0
file download <FILENAME> : iOS > PC 파일 다운받기
file upload <local_file_path> : PC > iOS 파일 업로드

frida-trace

사용방법

open을 사용하는 클래스 추출

frida-trace -U -f [PACKAGE_NAME] -i “open*”

 init으로 시작하는 클래스 추출

frida-trace -U -i “init*” [PID]

 

Class 내 모든 Method 추출

function hook_class_method(class_name, method_name)
{
	var hook = ObjC.classes[class_name][method_name];
		Interceptor.attach(hook.implementation, {
			onEnter: function(args) {
			console.log("[*] Detected call to: " + class_name + " -> " + method_name);
		}
	});
}

function run_hook_all_methods_of_specific_class(className_arg)
{
	console.log("[*] Started: Hook all methods of a specific class");
	console.log("[+] Class Name: " + className_arg);
	//Your class name here
	var className = className_arg;
	//var methods = ObjC.classes[className].$methods;
	var methods = ObjC.classes[className].$ownMethods;
	for (var i = 0; i < methods.length; i++)
	{
		console.log("[-] "+methods[i]);
		console.log("\t[*] Hooking into implementation");
		//eval('var className2 = "'+className+'"; var funcName2 = "'+methods[i]+'"; var hook = eval(\'ObjC.classes.\'+className2+\'["\'+funcName2+\'"]\'); Interceptor.attach(hook.implementation, {   onEnter: function(args) {    console.log("[*] Detected call to: " + className2 + " -> " + funcName2);  } });');
		var className2 = className;
		var funcName2 = methods[i];
		hook_class_method(className2, funcName2);
		console.log("\t[*] Hooking successful");
	}
	console.log("[*] Completed: Hook all methods of a specific class");
}

function hook_all_methods_of_specific_class(className_arg)
{
	setImmediate(run_hook_all_methods_of_specific_class,[className_arg])
}

//Your class name goes here
hook_all_methods_of_specific_class("추출한 Class Name")

Method trace 스크립트 by hackcatml

// generic trace
function trace(pattern)
{
    var type = (pattern.indexOf(" ") === -1) ? "module" : "objc";    // [A B]와 같이 공백이 있으면 objc, 없으면 모듈  
    var res = new ApiResolver(type);
    var matches = res.enumerateMatchesSync(pattern);
    var targets = uniqBy(matches, JSON.stringify);

    targets.forEach(function(target) {
      if (type === "objc")
          traceObjC(target.address, target.name);
      else if (type === "module")
          traceModule(target.address, target.name);
  });
}

// remove duplicates from array
function uniqBy(array, key) 
{
    var seen = {};
    return array.filter(function(item) {
        var k = key(item);
        return seen.hasOwnProperty(k) ? false : (seen[k] = true);
    });
}

// trace ObjC methods
function traceObjC(impl, name)
{
    console.log("Tracing " + name);

    Interceptor.attach(impl, {

        onEnter: function(args) {

            // debug only the intended calls
            this.flag = 0;
            // if (ObjC.Object(args[2]).toString() === "1234567890abcdef1234567890abcdef12345678")
                this.flag = 1;

            if (this.flag) {
                console.warn("\n[+] entered " + name);
                // print caller
                console.log("\x1b[31mCaller:\x1b[0m \x1b[34m" + DebugSymbol.fromAddress(this.returnAddress) + "\x1b[0m\n");

                // print args
                console.log("\x1b[31margs[2]:\x1b[0m \x1b[34m" + args[2] + ", \x1b[32m" + ObjC.Object(args[2]) + "\x1b[0m")
                console.log("\x1b[31margs[3]:\x1b[0m \x1b[34m" + args[3] + ", \x1b[32m" + ObjC.Object(args[3]) + "\x1b[0m")
                // console.log("\x1b[31margs[4]:\x1b[0m \x1b[34m" + args[4] + ", \x1b[32m" + ObjC.Object(args[4]) + "\x1b[0m")
                
                // print full backtrace
                // console.log("\nBacktrace:\n" + Thread.backtrace(this.context, Backtracer.ACCURATE)
                //      .map(DebugSymbol.fromAddress).join("\n"));
            }
        },

        onLeave: function(retval) {

            if (this.flag) {
                // print retval
                console.log("\n\x1b[31mretval:\x1b[0m \x1b[34m" + retval + "\x1b[0m");
                console.warn("[-] exiting " + name);
            }
        }

    });
}

// trace Module functions
function traceModule(impl, name)
{
    console.log("Tracing " + name);

    Interceptor.attach(impl, {

        onEnter: function(args) {

            // debug only the intended calls
            this.flag = 0;
            // var filename = Memory.readCString(ptr(args[0]));
            // if (filename.indexOf("Bundle") === -1 && filename.indexOf("Cache") === -1) // exclusion list
            // if (filename.indexOf("my.interesting.file") !== -1) // inclusion list
                this.flag = 1;

            if (this.flag) {
                console.warn("\n*** entered " + name);

                // print backtrace
                console.log("\nBacktrace:\n" + Thread.backtrace(this.context, Backtracer.ACCURATE)
                        .map(DebugSymbol.fromAddress).join("\n"));
            }
        },

        onLeave: function(retval) {

            if (this.flag) {
                // print retval
                console.log("\nretval: " + retval);
                console.warn("\n*** exiting " + name);
            }
        }

    });
}

// usage examples. 관심있는 클래스를 명시. 대소문자 구분
if (ObjC.available) {
    trace("*[JailbreakDetection *]")
    // trace("*[FireflySecurityUtil *]")
    // trace("*[ *ncrypt*]");
    // trace("*[* *]"); 모든 클래스 추적. 앱이 다운됨
    // trace("exports:libSystem.B.dylib!CCCrypt");
    // trace("exports:libSystem.B.dylib!open");
    // trace("exports:*!open*");
    
} else {
    send("error: Objective-C Runtime is not available!");
}

 

UI Dump by hackcatml

var window = ObjC.classes.UIWindow.keyWindow();
var rootControl = window.rootViewController();

var ui = window.recursiveDescription().toString();
var ui_autolayout = window['- _autolayoutTrace']().toString();
var control = rootControl['- _printHierarchy']().toString();

// 전체 UI 계층 출력하고 싶은 경우    
// console.log("\n\x1b[31m" + ui + "\x1b[0m"); 

// Simplified recursiveDescription
// console.log("\n\x1b[34m" + ui_autolayout + "\x1b[0m");

// 현재 화면에 보여지는 UIController를 알고 싶은 경우
console.log("\n\x1b[32m" + control + "\x1b[0m");

 

'APP 모의해킹 > Setting' 카테고리의 다른 글

Burp Fiddler 연동  (0) 2023.07.10
TCP Proxy  (0) 2023.04.04
IDA Setting  (0) 2023.04.03
Anaconda Setting for virtual environment + frida  (0) 2023.03.23
pip 인증서 문제  (0) 2023.03.22

+ Recent posts