IOS Cheat Sheet

IOS Cheat Sheet

in

진단 전

IPA 추출 (AppStore)

FlexDump (AppStore)

flexdecrypt, flexdump 설치

chmod 777 flexdecrypt
chmod 777 flexdump
dpkg -i flexdecrypt
dpkg - i flexdump

스크린샷 2022-10-29 오후 4 45 56 스크린샷 2022-10-29 오후 4 46 07

IpaInstaller

Cydia 에서 ipa installer 설치 가능

ipainstaller -b [번들식별자]
- 저장경로
/private/var/mobile/Documents

스크린샷 2022-10-29 오후 4 50 01


Frida Code

Frida-trace
frida-trace -U -f kr.wink.alda -m "*[*Jail* *]"

-m : 키워드 포함 클래스 출력
-M : 키워드 제외 클래스 출력


raptor_frida_ios_trace.js

// 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!");
}
ObjC Class & Method 확인
  • Class 확인
if(ObjC.available) { 
    for(var classname in ObjC.classes) 
        console.log(classname);
}
  • Method 확인
if(ObjC.available) { 
    var classname = "JailbreakDetection"
    var methods = ObjC.classes[classname].$ownMethods
    console.log(methods)
}
  • 반환값 확인
if(ObjC.available) { 
    var classname = "JailbreakDetection"
    var methodsname = "isJailbroken"
    var hook = ObjC.classes[classname][methodsname] 

    Interceptor.attach(hook.implementation, { 
        onLeave: function(retval) { //반환값을 확인하기 위해서는 onLeave 사용
            console.log("Class name = " + classname)
            console.log("Method name = " + methodsname)
            console.log("Type of return value = " + hook.returnType)
            console.log("return vaule = " + retval)
        }
    })
}
Swift 리턴값 변경
  • Return Value 변경
var realBase = Module.findBaseAddress('번들아이디');
console.log("리얼베이스 주소값 : " + realBase);

var Jailbreak_address = realBase.add('0x1cbdd0'); //변경하려는 메모리 주소
console.log("if/else 비교 주소 : " + Jailbreak_address);

Interceptor.attach(Jailbreak_address, {
    onEnter: function(args) {
        console.log(JSON.stringify(this.context));
        this.context.x0 = 0x0 
        console.log(JSON.stringify(this.context)); 
    }
})


진단

코드패치

코드패치

Online ARM to HEX Converter

코드 패치 후 앱 서명

ldid -e [원본바이너리파일]
ldid -e [원본바이너리파일] > useegod.xml
chmod +x [패치바이너리파일]
ldid -Suseegod.xml [패치바이너리파일]



👀 ETC


📃 References