본문 바로가기
Hack/Mobile

Frida Cheat Sheet

by Becoming a Hacker 2020. 9. 21.
반응형

공통


Frida attach Code

import frida, sys

def on_message(message, data):
    if message['type'] == 'send':
        payload = message['payload']
        print(payload)
        print("")
    else:
        print(message)

jscode = """
"""

try:
    target = ""
    process = frida.get_usb_device(timeout=5).attach(target)
    script = process.create_script(jscode)
    script.on("message", on_message)
    script.load()
    sys.stdin.read()
    
except Exception as e:
    print(e)

 

Frida spawn Code

import frida, sys

def on_message(message, data):
    if message['type'] == 'send':
        payload = message['payload']
        print(payload)
        print("")
    else:
        print(message)

jscode = '''
'''

try:
	target = ""
	device = frida.get_usb_device(timeout=5)
	pid = device.spawn([target])
	process = device.attach(pid)
	script = process.create_script(jscode)
	script.on('message',on_message)
	script.load()
	device.resume(pid)
	sys.stdin.read()

except Exception as e :
	print(e)

 

특정 Module 내 함수 및 변수와 Offset 확인

var jailCheck = Process.findModuleByName("Jailbreak");
if(jailCheck != null){
    var exports = jailCheck.enumerateExports();
    for(var j=0;j<exports.length; j++){
        console.log(JSON.stringify(exports[j]));
    }
}

 

메모리 write 권한 부여

Interceptor.attach(Module.findExportByName(null,"fopen"),{
        onEnter:function(args){
			Memory.protect(ptr(args[0]),16,'rw-')
			args[0].writeUtf8String("/deadbeef")
		}
})

 

메모리 덤프

Process.enumerateModules({
    onMatch: function(module) {
        var count = 0
        var maxSize = 200000
        var str = "";          
        if(module.name.indexOf("123")!=-1){
            while(count<module.size){
                var a= Memory.readByteArray(ptr(module.base.toInt32()+count+0x100000000), maxSize)
                var b = new Uint8Array(a);
                for(var i = 0; i < b.length; i++) {
                    if(b[i]<0x10){
                        str += ("0"+b[i].toString(16));
                    }else{
                        str += (b[i].toString(16));                
                    }
                }
                count+=maxSize
                send(str)
                console.log(count)
                console.log(module.size-count)
                break
            }
        }
    },
    onComplete: function() {
    }
});

 

Interceptor 한 번에

var name_list = ["stat","lstat"];
name_list.forEach((f_name, index, array) => {
      Interceptor.attach(Module.findExportByName(null,f_name), {
          onEnter(args) {
              console.log(f_name);
          }
      });
});

 

Instruction 기준으로 offset 구하기

var pattern_list = ["ff ff ff ff ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??" + "80 dd dd dd dd dd dd dd dd ff ff ff"]
var pattern_size = pattern_list.length
var address_list = []
var memory_ranges = Process.enumerateRangesSync({
    protection: "r--",
    coalesce: true
})

var flag = false
while(pattern_size--){
    var pattern = pattern_list[pattern_size]
    console.log(pattern)
    for (var i = 0; i < memory_ranges.length; i++) {
        var range = memory_ranges[i]
        var matches = Memory.scanSync(range.base, range.size, pattern)
        if (matches.length > 0) {
            console.log("Found " + matches.length + " matches in " + range.base + "-" + (range.base.add(range.size)))
            for (var j = 0; j < matches.length; j++) {
                console.log("Found match at " + matches[j].address)
                console.log("Static offset is " + matches[j].address.sub(base))
                address_list.push(matches[j].address-base)
                console.log("address_list",address_list)
                flag = true
            }
        }
        if(flag){
            break
        }
    }
}

Android

 


특정 라이브러리 함수 이름 출력

Java.perform(function(){
    var func = Module.enumerateImportsSync("libfoo.so");
    for(var i=0; i<func.length;i++){
        console.log(func[i].name);
    }
})

 

특정 메소드 실행 시 후킹

1. implementation

Java.perform(function(){
    var tls = Java.use("com.contextlogic.wish.http.Tls12Helper");
        
    tls.enableTls12.implementation = function(arg4){
        this.enableTls12(arg4);
    };
})

 

2. attach

Java.perform(function(){
    Interceptor.attach(Module.findExportByName(null,"sendto"),{
        onEnter: function(args){
            console.log("sockfd="+args[0]+", buf="+args[1]+", len="+args[2]);
            console.log(Memory.readUtf16String(args[1],parseInt(args[2])));
        },
        onLeave : function(retval){
            console.log("RET : "+retval);
            return retval;
        }
    })
})

 

3. replace

Java.perform(function(){
    var p_pthread_create = Module.findExportByName("libc.so", "pthread_create");
    var pthread_create = new NativeFunction( p_pthread_create, "int", ["pointer", "pointer", "pointer", "pointer"]);
 
    Interceptor.replace( p_pthread_create, new NativeCallback(function (ptr0, ptr1, ptr2, ptr3) {
        var ret = pthread_create(ptr0,ptr1,ptr2,ptr3);
    }, "int", ["pointer", "pointer", "pointer", "pointer"]));
});
Java.perform(function(){
    var il2 = Module.getBaseAddress("libil2cpp.so");
    var saveMoney = il2.add(0x6E53B0);
    var fun = new NativeFunction(saveMoney,"void",["float","int","int","float"]);
    
    Interceptor.replace(saveMoney,new NativeCallback(function(totalGold, cash, cash_super, goldperClick){
        totalGold = 100000000000000000;
        fun(totalGold, cash, cash_super, goldperClick);
    },"void",["float","int","int","float"]));
})

 

현재 실행 중인 클래스 객체 및 변수 접근

Java.perform(function () {
    var SpannableStringBuilder = Java.use("android.text.SpannableStringBuilder");
    var String = Java.use("java.lang.String");
    Java.choose("android.widget.EditText", {
        onMatch: function (instance) {
            console.log("Found instance: " + instance);
            console.log("[*] EditText RootView: " + instance.getRootView());
            console.log("[*] EditText InputType: " + instance.getInputType());
            console.log("[*] EditText Text: " + Java.cast(instance.getText(), SpannableStringBuilder));
            console.log("[*] EditText Hint: " + Java.cast(instance.getHint(), String));
        },
        onComplete: function () {
            console.log("[*] Finished heap search");
        }
    });

});

 

Class 내 Method와 Variable 확인

function describeJavaClass(className) {
  var jClass = Java.use(className);
  console.log(JSON.stringify({
    _name: className,
    _methods: Object.getOwnPropertyNames(jClass.__proto__).filter(m => {
      return !m.startsWith('$') // filter out Frida related special properties
         || m == 'class' || m == 'constructor' // optional
    }), 
    _fields: jClass.class.getFields().map(f => {
      return f.toString()
    })  
  }, null, 2));
}

 

[Object Object] 값 확인

var sms;
Java.choose("Class.Path",
{
    onMatch: function(instance1){
        sms = instance1;
    },
    onComplete: function(){
        console.log(sms.value); // output -> [Object Object]
        console.log(JSON.stringify(sms.value)); // output -> {"value:"1234", "filedType":2, ...
    }
});
Java.perform(function(){
    console.log("Running Hook");
    var ch1 = Java.use("com.sms.mobilesecurity.Challenge1");
    var SpannableStringBuilder = Java.use("android.text.SpannableStringBuilder");

    ch1.get_account.implementation = function(arg1, arg2){
        var text = Java.cast(arg1,SpannableStringBuilder);
        console.log(text);
        return "";
    }
})
Java.perform(function(){
    var String = Java.use("java.lang.String")
    var lock = Java.use("com.a.a.ui.phone.LockActivity")
    lock.checkPassword.implementation = function(){
        console.log(this.mPassWords.value)
    }
})

 

로드되는 모듈 확인

Process.enumerateModules({
    onMatch: function(module) {
        console.log("");
        console.log("- Module.name : " + module.name);
        console.log("- Module.base : " + module.base);
        console.log("- Module.size : " + module.size);
        console.log("- Module.path : " + module.path);        
    },
    onComplete: function() {
        console.log("[+] Process.enumerateModules Done.");
    }
});

 

실행되는 Activity 출력

Java.perform(function(){
    var Activity = Java.use("android.app.Activity");
    Activity.onResume.implementation = function () {
        console.log("onResume() " + this);
        this.onResume();
    }
})

 

Stack Trace

Java.perform(function(){
    var tls = Java.use("com.contextlogic.wish.http.Tls12Helper");
    tls.enableTls12.implementation = function(arg4){
    	console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new()));
        this.enableTls12(arg4);
    }
})

 

Interceptor.attach(Module.findExportByName(null,"read"),{
    onEnter:function(args){
        this.args1 = args[1]
    },onLeave:function(retval){
        console.log(Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n');
    }
})

 

function printBacktrace(_this, debugTag) {
   var backtrace = Thread.backtrace(_this.context, Backtracer.ACCURATE);
   var module = Process.findModuleByAddress(backtrace[0]);
   var log = '|-> ' + backtrace[0] + ': ' + module.path + '!' + '0x' + (backtrace[0] - module.base).toString(16) + ' (' + module.name + ':' + module.base + ')|';
   if(module.path.includes(debugTag) != true) {
       console.log('[+] ' + debugTag);
       console.log('[-] ', JSON.stringify(_this));
       console.log('-'.repeat(log.length));
       console.log(log);
       console.log('-'.repeat(log.length));
   }
}

Interceptor.attach(Module.findExportByName(null, "dlsym"), {
    onEnter: function (args) {
    	printBacktrace(this, "libc");
    }
})

 

Android SSL Pinning ByPass (인증서 관련 메소드)

Java.perform(function(){
    var array_list = Java.use("java.util.ArrayList");
    var ApiClient = Java.use('com.android.org.conscrypt.TrustManagerImpl');

    ApiClient.checkTrustedRecursive.implementation = function(a1, a2, a3, a4, a5, a6) {
        console.log('Bypassing SSL Pinning');
        var k = array_list.$new();
        return k;
    }
})

 

Java Log 메소드 후킹

var Log = Java.use("android.util.Log");

Log.d.overload('java.lang.String', 'java.lang.String').implementation = function (a, b) {
   console.log("Log.d() : "+a.toString()+" / "+b.toString());
   return this.d.overload('java.lang.String', 'java.lang.String').call(this, a, b);
};
Log.v.overload('java.lang.String', 'java.lang.String').implementation = function (a, b) {
   console.log("Log.v() : "+a.toString()+" / "+b.toString());
   return this.v.overload('java.lang.String', 'java.lang.String').call(this, a, b);
};

Log.i.overload('java.lang.String', 'java.lang.String').implementation = function (a, b) {
   console.log("Log.i() : "+a.toString()+" / "+b.toString());
   return this.i.overload('java.lang.String', 'java.lang.String').call(this, a, b);
};
Log.e.overload('java.lang.String', 'java.lang.String').implementation = function (a, b) {
   console.log("Log.e() : "+a.toString()+" / "+b.toString());
   return this.e.overload('java.lang.String', 'java.lang.String').call(this, a, b);
};
Log.w.overload('java.lang.String', 'java.lang.String').implementation = function (a, b) {
   console.log("Log.w() : "+a.toString()+" / "+b.toString());
   return this.w.overload('java.lang.String', 'java.lang.String').call(this, a, b);
};

 

String Build Method 후킹

const StringBuilder = Java.use('java.lang.StringBuilder');
StringBuilder.toString.implementation = function () {
	var retVal = this.toString();
	console.log(retVal);
	return retVal;
}

 

Byte to String, String to Byte

function string2Bin(str) {
  var result = [];
  for (var i = 0; i < str.length; i++) {
    result.push(str.charCodeAt(i));
  }
  return result;
}

function bin2String(array) {
  return String.fromCharCode.apply(String, array);
}

 

Hooking Code

Interceptor.attach(Module.findExportByName(null, "opendir"), {
    onEnter: function (args) {
        console.log("* dir : "+args[0].readCString());
    },
   onLeave: function (retval) {
   }
})

Interceptor.attach(Module.findExportByName(null, "readdir"), {
    onEnter: function (args) {
    
    },
   onLeave: function (retval) {
        var str =retval.add(19);
        try{
            console.log(str.readCString());
        }
        catch(err){
            console.log(" END");
        }
   }
})

 

알림창 띄우기

Java.perform(function() {
    Java.use("android.app.Activity").onCreate.overload("android.os.Bundle").implementation = function(savedInstanceState) {
        var Toast = Java.use("android.widget.Toast");
        var currentApplication = Java.use('android.app.ActivityThread').currentApplication();
        var context = currentApplication.getApplicationContext();
        Toast.makeText.overload('android.content.Context', 'java.lang.CharSequence', 'int').call(Toast,context,"hello world", Toast.LENGTH_SHORT.value).show();
        
        return this.onCreate.overload("android.os.Bundle").call(this, savedInstanceState);
    };
});
Java.perform(function() {
    var System = Java.use('java.lang.System');
    var ActivityThread = Java.use("android.app.ActivityThread");
    var AlertDialogBuilder = Java.use("android.app.AlertDialog$Builder");
    var DialogInterfaceOnClickListener = Java.use('android.content.DialogInterface$OnClickListener');

    Java.use("android.app.Activity").onCreate.overload("android.os.Bundle").implementation = function(savedInstanceState) {
        var currentActivity = this;

        // Get Main Activity
        var application = ActivityThread.currentApplication();
        var launcherIntent = application.getPackageManager().getLaunchIntentForPackage(application.getPackageName());
        var launchActivityInfo = launcherIntent.resolveActivityInfo(application.getPackageManager(), 0);

        // Alert Will Only Execute On Main Package Activity Creation
        if (launchActivityInfo.name.value === this.getComponentName().getClassName()) {
            var alert = AlertDialogBuilder.$new(this);
            alert.setMessage.overload('java.lang.CharSequence').call(alert,"Hello World")

            alert.setPositiveButton.overload('java.lang.CharSequence', 'android.content.DialogInterface$OnClickListener').call(alert,"Check", Java.registerClass({
                name: 'il.co.realgame.OnClickListenerPositive',
                implements: [DialogInterfaceOnClickListener],
                methods: {
                    getName: function() {
                        return 'OnClickListenerPositive';
                    },
                    onClick: function(dialog, which) {
                        // Dismiss
                        dialog.dismiss();
                    }
                }
            }).$new());

            alert.create().show();
        }
        return this.onCreate.overload("android.os.Bundle").call(this, savedInstanceState);
    };
});

 

화면 캡처 방지 비활성화

var surface_view = Java.use('android.view.SurfaceView');

var set_secure = surface_view.setSecure.overload('boolean');

set_secure.implementation = function(flag){ 
    set_secure.call(false);
};

var window = Java.use('android.view.Window');
var set_flags = window.setFlags.overload('int', 'int');

var window_manager = Java.use('android.view.WindowManager');
var layout_params = Java.use('android.view.WindowManager$LayoutParams');

set_flags.implementation = function(flags, mask){
    flags =(flags.value & ~layout_params.FLAG_SECURE.value);
    set_flags.call(this, flags, mask);
};

 

다른 Class Loader로 Load된 Class 찾기

// console.log(Java.enumerateClassLoadersSync()) // array check 
var classLoader = Java.enumerateClassLoadersSync()[2] 
Java.classFactory.loader = classLoader;
var class_name = Java.classFactory.use("class Name")

IOS


현재 앱에서 로드된 Class Name 및 Method Name 출력

if(ObjC.available){
    Object.keys(ObjC.classes).forEach(function(className){
        console.log(className);
        var methods = eval("ObjC.classes['"+className+"'].$methods");
        for(var i = 0; i<methods.length; i++){
            console.log(methods[i]);
        }
    });
}

 

특정 메소드 인자 타입 및 개수 확인

var arguType = ObjC.classes['Class Name']['Method Name'].argumentTypes;

 

특정 메소드 리턴 값 타입 확인

var retType = ObjC.classes['Class Name']['Method Name'].returnType;

 

특정 메소드 실행 시 후킹

1. implementation

if(ObjC.available){
    console.log("Running Hooking");
    var rooting = ObjC.classes['ANSMetadata'];
    var meta = rooting['- setValueInDictionary:withKey:toObject:'];
    var metafunc = meta.implementation;
    meta.implementation = ObjC.implement(meta,function(handler, selector, arg1, arg2, arg3){
        if(ObjC.Object(arg2).toString()=="jailbroken"){
            var arg3 = ObjC.classes.NSString.stringWithString_("0");
        }
        metafunc(handler,selector,arg1, arg2, arg3);
    })
}

 

2. attach

if(ObjC.available){
    console.log("Running Hooking");
    var meta = ObjC.classes['ANSMetadata']['- setValueInDictionary:withKey:toObject:'];
    Interceptor.attach(meta.implementation,{
        onEnter: function(args){
            console.log("onEnter");
        },
        onLeave: function(retval){
        	retval.replace(0x1)
        }
    })    
}
var baseAddr = Module.findBaseAddress('file_name');
var sub1 = baseAddr.add(0x145214);
Interceptor.attach(sub1, {
    onEnter: function (args) {
    	console.log("sub_145214 IN");
    },
    onLeave: function (retval) {
        console.log("sub_145214 OUT");
    }
})

 

3. replace

var base = Module.findBaseAddress("Jailbreak");
var check = base.add(0x70EC)

Interceptor.replace(check, new NativeCallback(function(){
    console.log("Check IN");
    return 1;
},'int',[]));

 

Swift 함수 인자 및 리턴 값 변조

var base = Module.findBaseAddress("file Name")

// Show Correct Password
var sub3 = base.add(0xEFF3C)
Interceptor.attach(sub3,{
    onEnter:function(args){
        // x0 == Correct Password
        // x2 == Input Password
        console.log("Correct Password : "+this.context.x0)
        // console.log(this.context.x2)
    }
})

// Bypass Password Authentication
var sub4 = base.add(0xEFF40)
Interceptor.attach(sub4,{
    onEnter:function(args){
        this.context.x0 = 0x01
        console.log("Bypass Lock")
  }
})

 

알림창 띄우기

var handler = new ObjC.Block({
  retType: 'void',
  argTypes: ['object'],
  implementation: function () {
  }
});

// Import ObjC classes
var UIAlertController = ObjC.classes.UIAlertController;
var UIAlertAction = ObjC.classes.UIAlertAction;
var UIApplication = ObjC.classes.UIApplication;

// Using Grand Central Dispatch to pass messages (invoke methods) in application's main thread
ObjC.schedule(ObjC.mainQueue, function () {
  // Using integer numerals for preferredStyle which is of type enum UIAlertControllerStyle
  var alert = UIAlertController.alertControllerWithTitle_message_preferredStyle_('Frida', 'Hello from Frida', 1);
  // Again using integer numeral for style parameter that is enum
  var defaultAction = UIAlertAction.actionWithTitle_style_handler_('OK', 0, handler);
  alert.addAction_(defaultAction);
  // Instead of using `ObjC.choose()` and looking for UIViewController instances
  // on the heap, we have direct access through UIApplication:
  UIApplication.sharedApplication().keyWindow().rootViewController().presentViewController_animated_completion_(alert, true, NULL);
})

 

특정 클래스들의 고유 메소드가 실행될 때 로그 출력

1. if(className.indexOf("ClassName")!=-1){ 을 변경함으로써 후킹할 클래스들을 정할 수 있다.

2. $ownMethods, $methods로 부모 클래스에 상속받은 고유 메소드까지 포함시킬 지 정할 수 있다.

- $methods : array containing native method names exposed by this object’s class and parent classes

- $ownMethods : array containing native method names exposed by this object’s class, not including parent classes

 

※ 아이폰 메모리 문제인지 너무 많은 클래스에 후킹을 걸면 강제 리부팅이 되는 경우가 있다. 강제 재탈옥

if(ObjC.available){
    var keyArr = new Object();
    Object.keys(ObjC.classes).forEach(function(className){
        if(className.indexOf("ClassName")!=-1){
            var methods = eval("ObjC.classes['"+className+"'].$ownMethods");
            for(var i = 0; i<methods.length; i++){
                var method = methods[i];
                var hook = eval("ObjC.classes['"+className+"']['"+method+"']");
                keyArr[hook.selector]= className+" -> "+method;
                Interceptor.attach(hook.implementation,{
                    onEnter : function(args){
                        console.log(keyArr[args[1]]);
                    }
                })      
            }       
        }
    })
    console.log("Hooking End");
}

 

Call Stack 확인

Interceptor.attach(Module.findExportByName(null,"fopen"),{
    onEnter: function(args){
        console.log(Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n');
    }
});

 

NSString isEqualToString 후킹

Interceptor.attach(ObjC.classes.NSString['- isEqualToString:'].implementation, {
    onEnter: function (args) {
        var str = new ObjC.Object(ptr(args[2])).toString()
        console.log('[+] Hooked -[NSString isEqualToString:] ->'+str);
    },onLeave: function (retval){
        console.log(retval)
    }
});

Interceptor.attach(ObjC.classes.__NSCFString['- isEqualToString:'].implementation, {
    onEnter: function (args) {
      var str = new ObjC.Object(ptr(args[2])).toString()
      console.log('[+] Hooked __NSCFString[- isEqualToString:] ->' , str);
    }
});

Interceptor.attach(ObjC.classes.NSTaggedPointerString['- isEqualToString:'].implementation, {
    onEnter: function (args) {
      var str = new ObjC.Object(ptr(args[2])).toString()
      console.log('[+] Hooked NSTaggedPointerString[- isEqualToString:] ->' , str);
    }
});

 

NSDATA String 조작

var DataProc = ObjC.classes['DataProc']['- getInputData']
Interceptor.attach(DataProc.implementation,{
        onEnter:function(args){
        },onLeave:function(retval){
            var tmp = ObjC.Object(retval).bytes()
            tmp.writeUtf8String("NSDATA String")
            return retval
        }
})

 

지문인증 우회

var lacontext = ObjC.classes['LAContext']
var localized = lacontext['- evaluatePolicy:localizedReason:reply:']

Interceptor.attach(localized.implementation, {
    onEnter: function(args) {
        var block = new ObjC.Block(args[4]);
        var callback = block.implementation;
        block.implementation = function (error, value)  {
            console.log("Touch ID Bypass")
            const result = callback(1, null);
            return result;
        }
    }
});

 

JailBreak Bypass

if(ObjC.available){
    console.log("Running Hooking");
    var rooting = ObjC.classes['ANSMetadata'];
    var meta = rooting['- setValueInDictionary:withKey:toObject:'];
    var metafunc = meta.implementation;
    var jailbreakList = [
    "/etc/apt",
    "/Library/MobileSubstrate/MobileSubstrate.dylib",
    "/Applications/Cydia.app",
    "/Applications/blackra1n.app",
    "/Applications/FakeCarrier.app",
    "/Applications/Icy.app",
    "/Applications/IntelliScreen.app",
    "/Applications/MxTube.app",
    "/Applications/RockApp.app",
    "/Applications/SBSettings.app",
    "/Applications/WinterBoard.app",
    "/usr/sbin/sshd",
    "/usr/bin/sshd",
    "/usr/libexec/sftp-server",
    "/private/var/tmp/cydia.log",
    "/private/var/tmp/cydia",
    "/private/var/lib/cydia",
    "/System/Library/LaunchDaemons/com.ikey.bbot.plist",
    "/System/Library/LaunchDaemons/com.saurik.Cydia.Startup.plist",
    "/var/log/syslog",
    "/bin/bash",
    "/bin/sh",
    "/etc/ssh/sshd_config",
    "/usr/libexec/ssh-keysign",
    "/private/var/lib/apt",
    "/private/var/stash",
    "/private/var/mobile/Library/SBSettings/Themes",
    "/Library/MobileSubstrate/DynamicLibraries/Veency.plist",
    "/Library/MobileSubstrate/DynamicLibraries/LiveClock.plist",
    "/usr/lib/system/libsystem_kernel.dylib"
    ];

    meta.implementation = ObjC.implement(meta,function(handler, selector, arg1, arg2, arg3){
        if(ObjC.Object(arg2).toString()=="jailbroken"){
            var arg3 = ObjC.classes.NSString.stringWithString_("0");
        }
        metafunc(handler,selector,arg1, arg2, arg3); // isJailbroken = 1 -> isJailbroken = 0
    })

    var fileExist = ObjC.classes.NSFileManager["- fileExistsAtPath:"];
    Interceptor.attach(fileExist.implementation,{
        onEnter: function(args){
            this.jailbreak = true;
            var tmp = ObjC.Object(args[2]);
            var i = jailbreakList.length;
            while(i--){
                if(tmp.toString()==jailbreakList[i]){
                    this.jailbreak = false;
                }
            }
        },
        onLeave: function(retval){
            if(this.jailbreak==false){
                retval.replace(0x00);
            }
            return retval;
        }
    })
}

 

iOS 14 SSL Pinning ByPass (인증서 관련 메소드)

try {
    Module.ensureInitialized("libboringssl.dylib");
} catch(err) {
    console.log("libboringssl.dylib module not loaded. Trying to manually load it.")
    Module.load("libboringssl.dylib");  
}

var SSL_VERIFY_NONE = 0;
var ssl_set_custom_verify;
var ssl_get_psk_identity;   

ssl_set_custom_verify = new NativeFunction(
    Module.findExportByName("libboringssl.dylib", "SSL_set_custom_verify"),
    'void', ['pointer', 'int', 'pointer']
);

ssl_get_psk_identity = new NativeFunction(
    Module.findExportByName("libboringssl.dylib", "SSL_get_psk_identity"),
    'pointer', ['pointer']
);

/** Custom callback passed to SSL_CTX_set_custom_verify */
function custom_verify_callback_that_does_not_validate(ssl, out_alert){
    return SSL_VERIFY_NONE;
}

/** Wrap callback in NativeCallback for frida */
var ssl_verify_result_t = new NativeCallback(function (ssl, out_alert){
    custom_verify_callback_that_does_not_validate(ssl, out_alert);
    return -1;
},'int',['pointer','pointer']);

Interceptor.replace(ssl_set_custom_verify, new NativeCallback(function(ssl, mode, callback) {
    //  |callback| performs the certificate verification. Replace this with our custom callback
    ssl_set_custom_verify(ssl, mode, ssl_verify_result_t);
}, 'void', ['pointer', 'int', 'pointer']));

Interceptor.replace(ssl_get_psk_identity, new NativeCallback(function(ssl) {
    return "notarealPSKidentity";
}, 'pointer', ['pointer']));
    
console.log("[+] Bypass successfully loaded ");

댓글