frida的简单应用

来自看雪3w班的一道题

拿到app,先装上手机
image.png

看样子是要拿到正确的flag才能通过。
将apk拖入jadx中,发现加固了,那就先脱壳

image.png

上frida脱壳,这里用到的是github上大佬写的脱壳工具,https://github.com/lasting-yang/frida_dump
脱壳后发现有三个dex,很显然是最后一个

image.png

将dex拖入jadx中分析下,发现问题并没那么简单,居然onCreate方法都是jni函数化


image.png

将libnative-lib.so拖入ida分析,查看导出函数,并未发现onCreate及check,十分火大,看来还是动态注册


image.png

拷贝大佬写的对RegisterNatives方法的hook,再spawn方式启动启动app

function hook_RegisterNatives() {
    var symbols = Module.enumerateSymbolsSync("libart.so");
    var addrRegisterNatives = null;
    for (var i = 0; i < symbols.length; i++) {
        var symbol = symbols[i];
        
        //_ZN3art3JNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi
        if (symbol.name.indexOf("art") >= 0 &&
                symbol.name.indexOf("JNI") >= 0 && 
                symbol.name.indexOf("RegisterNatives") >= 0 && 
                symbol.name.indexOf("CheckJNI") < 0) {
            addrRegisterNatives = symbol.address;
            console.log("RegisterNatives is at ", symbol.address, symbol.name);
        }
    }

    if (addrRegisterNatives != null) {
        Interceptor.attach(addrRegisterNatives, {
            onEnter: function (args) {
                console.log("[RegisterNatives] method_count:", args[3]);
                var env = args[0];
                var java_class = args[1];
                var class_name = Java.vm.tryGetEnv().getClassName(java_class);
                //console.log(class_name);

                var methods_ptr = ptr(args[2]);

                var method_count = parseInt(args[3]);
                for (var i = 0; i < method_count; i++) {
                    var name_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3));
                    var sig_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize));
                    var fnPtr_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize * 2));

                    var name = Memory.readCString(name_ptr);
                    var sig = Memory.readCString(sig_ptr);
                    var find_module = Process.findModuleByAddress(fnPtr_ptr);
                    console.log("[RegisterNatives] java_class:", class_name, "name:",name ,"sig:", sig, "fnPtr:", fnPtr_ptr, "module_name:", find_module!=null?find_module.name:"unknown", "module_base:", find_module!=null?find_module.base:"unknown", "offset:", find_module!=null?ptr(fnPtr_ptr).sub(find_module.base):"unknown");

                }
            }
        });
    }
}

function replaceLoader(){
    Java.perform(function() {
        console.log("Entering")
        var application = Java.use("android.app.Application");
        application.attach.overload('android.content.Context').implementation = function(context) {
            this.attach(context); // 先执行原来的attach方法
             // 获取classloader
            Java.classFactory.loader = context.getClassLoader();
            hook_RegisterNatives();
        }
    });
}

直接打印出动态注册函数的地址偏移


image.png

直接找到check的动态注册地址,跳转过去,并修改传入参数的定义。分析发现flag为20位


image.png

往后再看,发现似乎用了strcmp比对,那问题不就简单了吗。直接hook位于libc.so的strcmp函数


image.png

再写个函数,直接调用check方法,并随便传入20位数字或字母


image.png

image.png

起脚本,观察日志发现,似乎是拿了我输入的前6位与kanxue对比


image.png

问题是我们需要的flag应该为20位才对。尝试输入以kanxue开头的20个字母

image.png

image.png

那基本上就水落石出了,先是kanxue,再是training,然后是course,正正好好20个字母。
在app端输入kanxuetrainingcourse,果然就通过了


image.png

再回看输入kanxue后,又动态注册了两次check函数,分别跳转查看

int __fastcall sub_1234(JNIEnv *a1, int a2, int a3)
{
  int v3; // r1
  jstring v4; // r0
  int v6; // [sp+20h] [bp-48h]
  int v7; // [sp+24h] [bp-44h]
  char *s; // [sp+28h] [bp-40h]
  _DWORD v11[2]; // [sp+3Ch] [bp-2Ch] BYREF
  char s1[4]; // [sp+44h] [bp-24h] BYREF
  int v13; // [sp+48h] [bp-20h]
  char v14; // [sp+4Ch] [bp-1Ch]
  int v15[3]; // [sp+50h] [bp-18h] BYREF

  s = (char *)GetStringUTFChars(a1, a3, 0);
  if ( strlen(s) != 14 )
    return 0;
  v15[2] = (int)sub_1148;
  v15[1] = (int)&unk_50B0;
  v15[0] = (int)aGlago;
  v7 = sub_135C(a1, &unk_50D0);
  sub_1386(a1, v7, v15, 1);
  v6 = sub_13CE(a1, v7, aGlago, &unk_50B0);
  v14 = 0;
  v13 = 0;
  *(_DWORD *)s1 = 0;
  v3 = *(_DWORD *)s;
  v13 = *((_DWORD *)s + 1);
  *(_DWORD *)s1 = v3;
  if ( strcmp(s1, aFSU2) )
    return 0;
  *(_DWORD *)((char *)v11 + 3) = 0;
  v11[0] = 0;
  LOWORD(v11[1]) = *((_WORD *)s + 6);
  v11[0] = *((_DWORD *)s + 2);
  v4 = sub_1416(a1, (int)v11);
  return (unsigned __int8)sub_1444(a1, v7, v6, v4);
}
bool __fastcall sub_1148(JNIEnv *a1, int a2, int a3)
{
  char *s; // [sp+18h] [bp-28h]
  bool v5; // [sp+2Bh] [bp-15h]
  _DWORD s1[2]; // [sp+2Ch] [bp-14h] BYREF

  s = (char *)GetStringUTFChars(a1, a3, 0);
  v5 = 0;
  if ( strlen(s) == 6 )
  {
    *(_DWORD *)((char *)s1 + 3) = 0;
    s1[0] = 0;
    LOWORD(s1[1]) = *((_WORD *)s + 2);
    s1[0] = *(_DWORD *)s;
    if ( !strcmp((const char *)s1, byte_5096) )
      v5 = 1;
  }
  return v5;
}

发现其中比对了两次字符串,地址编译分别为0x50F7,0x5096,再次编写代码,直接读这个地址打印cstring

function print_string(addr){
    var nativelib_baseAddr = Process.getModuleByName("libnative-lib.so");
    var str_addr = nativelib_baseAddr.base.add(addr);
    console.log(addr,"==>",ptr(str_addr).readCString());
}
image.png

到此结束,非常值得新手尝试的crackme

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容