kuaidui作業(yè)sign逆向及unidbg實現(xiàn)

kuaidui作業(yè)sign逆向及unidbg實現(xiàn)

Java層

apk用frida_dump脫殼后不见,重新打包,jadx搜索sign=

image-20220125144710183

nativeGetSign這個名字就值得點進(jìn)去看看

com.zuoyebang.baseutil.a.b

image-20220125144844816

com.zuoyebang.baseutil.NativeHelper.nativeGetSign

image-20220125144925303

找到函數(shù)了程癌,hook驗證一下

android hooking watch class_method com.zuoyebang.baseutil.NativeHelper.nativeGetSign --dump-args --dum-return
image-20220125151803309

輸入是一個base64字符串纷妆,解碼后是請求參數(shù)做個拼接亦镶。

接下來找找函數(shù)在哪個so里面摹芙,nativeInitBaseUtil看這函數(shù)名灼狰,應(yīng)該是初始化的,查看用例

image-20220125150251992

com.zuoyebang.baseutil.a.a

image-20220125150416858

看來應(yīng)該是在libbaseutil.so

so層

ida查看JNI_OnLoad

image-20220125150735443
image-20220125150811631

幾個函數(shù)都找到了

image-20220125150909577

看看CRYMd5

image-20220125151008457

hook一下CRYMd5

function hook_md5() {
    var bptr = Module.findBaseAddress("libbaseutil.so");
    Interceptor.attach(bptr.add(0x2ae8), {
        onEnter: function(args) {
            console.log("md5-arg0: ", args[0].readCString());
        },
        onLeave: function(retval) {
            console.log("md5-ret:", retval.readCString(32));
        }
    })
}
image-20220125151533967

cyberchef驗證是不是標(biāo)準(zhǔn)MD5

image-20220125165726612

多請求幾次浮禾,發(fā)現(xiàn)objSpamServer.random_number伏嗜,也就是cdAgblSOFM不變坛悉,說明它是個相對固定的值。

卸載app重裝后承绸,發(fā)現(xiàn)還是不變,說明和會話無關(guān)挣轨。

更換設(shè)備后军熏,發(fā)現(xiàn)值改變了,說明該值和設(shè)備相關(guān)卷扮。

一個比較取巧也比較無奈的辦法就是建立設(shè)備號和字符串的映射表荡澎,計算sign時選用對應(yīng)的字符串即可。

unidbg實現(xiàn)

由于app只提供了64位的so晤锹,所以此次運行的是64位so摩幔。依舊是先搭個框架

public class Kuaidui extends AbstractJni {
    private final AndroidEmulator emulator;
    private final VM vm;
    private final Module module;

    public static String pkgName = "com.kuaiduizuoye.scan";
    public static String apkPath = "unidbg-android/src/test/java/com/kuaidui/kuaidui540.apk";
    public static String soPath = "";

    public Kuaidui() {
        emulator = AndroidEmulatorBuilder.for64Bit().setProcessName(pkgName).build();
        Memory memory = emulator.getMemory();
        memory.setLibraryResolver(new AndroidResolver(23));
        vm = emulator.createDalvikVM(new File(apkPath));
        vm.setJni(this);
        vm.setVerbose(true);
        new AndroidModule(emulator, vm).register(memory);
        DalvikModule dm = vm.loadLibrary("baseutil", true);
        module = dm.getModule();
        dm.callJNI_OnLoad(emulator);
    }
    
    public static void main(String[] args) {
        Kuaidui test = new Kuaidui();
    }
}
image-20220125163430533

罕見的沒有報錯,那就開始調(diào)用鞭铆。

public void call_sign() {
    List<Object> list = new ArrayList<>(10);
    list.add(vm.getJNIEnv());
    list.add(0);
    list.add(vm.addLocalObject(new StringObject(vm, "everhu")));
    Number ret = module.callFunction(emulator, 0x1500, list.toArray());
    System.out.println(vm.getObject(ret.intValue()).getValue());
}
public static void main(String[] args) {
    Kuaidui test = new Kuaidui();
    test.call_sign();
}
image-20220125163950114

調(diào)用出結(jié)果了或衡,只是不是正確結(jié)果。說明環(huán)境不對车遂,可能有些參數(shù)沒有設(shè)置封断。

image-20220125164156818

native函數(shù)里面應(yīng)該有設(shè)置環(huán)境的函數(shù),hook看看哪個先被調(diào)用了舶担。

objection.exe -g com.kuaiduizuoye.scan explore --startup-command="android hooking watch class com.zuoyebang.baseutil.NativeHelper"
image-20220125170504364

可以看到nativeSetToken被調(diào)用了坡疼,再hook看看入?yún)?/p>

objection -g com.kuaiduizuoye.scan explore --startup-command="android hooking watch class_method com.zuoyebang.baseutil.NativeHelper.nativeSetToken --dump-args --dump-return"
image-20220125172845540

在unidbg補(bǔ)上。

public void call_token() {
    List<Object> list = new ArrayList<>(10);
    list.add(vm.getJNIEnv());
    list.add(0);
    list.add(vm.addLocalObject(vm.resolveClass("android/content/Context").newObject(null)));
    String devid = "F5D53AD5A66144B57783C7C67611F0F7|0";
    list.add(vm.addLocalObject(new StringObject(vm, devid)));
    String request = "03090b0106000807080e00080201090708060f00040700020d0503070c0606000c01000a080e07050808020d00060b0d070f0f080306060b00000f0d04070d0d02070b0f020a01010c0d030a09080e090b040f02080c0b040c0e0e060c0d0201020f0e02030d0107020d000e0e02090401070505030a0c0605080303040e0803020c020e0d020408010b030e0b090f060302000e0f0902010706040c00080d0e060d000f0805040b0e07000d020b0f07";
    list.add(vm.addLocalObject(new StringObject(vm, request)));
    String response = "0a040609080d020b0a03090e010306050d0d050c0c060207070105010b0b01090801000a020d0c0b03030209030e0d0a";
    list.add(vm.addLocalObject(new StringObject(vm, response)));
    Number ret = module.callFunction(emulator, 0x1264, list.toArray());
}
public static void main(String[] args) {
    Kuaidui test = new Kuaidui();
    test.call_token();
    test.call_sign();
}
image-20220125165148129

需要返回int剪况,用objection + Wallbreaker查看是64

@Override
public int getStaticIntField(BaseVM vm, DvmClass dvmClass, String signature) {
    switch (signature) {
        case "android/content/pm/PackageManager->GET_SIGNATURES:I": {
            return 64;
        }
    }
    return super.getStaticIntField(vm, dvmClass, signature);
}
image-20220125165335872

然后就出結(jié)果了拯欧。

完整實現(xiàn)

public class Kuaidui extends AbstractJni {
    private final AndroidEmulator emulator;
    private final VM vm;
    private final Module module;

    public static String pkgName = "com.kuaiduizuoye.scan";
    public static String apkPath = "unidbg-android/src/test/java/com/kuaidui/kuaidui540.apk";
    public static String soPath = "";

    public Kuaidui() {
        emulator = AndroidEmulatorBuilder.for64Bit().setProcessName(pkgName).build();
        Memory memory = emulator.getMemory();
        memory.setLibraryResolver(new AndroidResolver(23));
        vm = emulator.createDalvikVM(new File(apkPath));
        vm.setJni(this);
        vm.setVerbose(true);
        new AndroidModule(emulator, vm).register(memory);
        DalvikModule dm = vm.loadLibrary("baseutil", true);
        module = dm.getModule();
        dm.callJNI_OnLoad(emulator);
    }

    @Override
    public int getStaticIntField(BaseVM vm, DvmClass dvmClass, String signature) {
        switch (signature) {
            case "android/content/pm/PackageManager->GET_SIGNATURES:I": {
                return 64;
            }
        }
        return super.getStaticIntField(vm, dvmClass, signature);
    }

    public void call_sign() {
        List<Object> list = new ArrayList<>(10);
        list.add(vm.getJNIEnv());
        list.add(0);
        list.add(vm.addLocalObject(new StringObject(vm, "everhu")));
        Number ret = module.callFunction(emulator, 0x1500, list.toArray());
        System.out.println(vm.getObject(ret.intValue()).getValue());
    }

    public void call_token() {
        List<Object> list = new ArrayList<>(10);
        list.add(vm.getJNIEnv());
        list.add(0);
        list.add(vm.addLocalObject(vm.resolveClass("android/content/Context").newObject(null)));
        String devid = "F5D53AD5A66144B57783C7C67611F0F7|0";
        list.add(vm.addLocalObject(new StringObject(vm, devid)));
        String request = "03090b0106000807080e00080201090708060f00040700020d0503070c0606000c01000a080e07050808020d00060b0d070f0f080306060b00000f0d04070d0d02070b0f020a01010c0d030a09080e090b040f02080c0b040c0e0e060c0d0201020f0e02030d0107020d000e0e02090401070505030a0c0605080303040e0803020c020e0d020408010b030e0b090f060302000e0f0902010706040c00080d0e060d000f0805040b0e07000d020b0f07";
        list.add(vm.addLocalObject(new StringObject(vm, request)));
        String response = "0a040609080d020b0a03090e010306050d0d050c0c060207070105010b0b01090801000a020d0c0b03030209030e0d0a";
        list.add(vm.addLocalObject(new StringObject(vm, response)));
        Number ret = module.callFunction(emulator, 0x1264, list.toArray());
    }

    public static void main(String[] args) {
        Kuaidui test = new Kuaidui();
        test.call_token();
        test.call_sign();
    }
}

nativeSetToken

nativeSetToken入?yún)⒌?個字符串也是會隨著設(shè)備而改變该贾,分析一下它的來源杨蛋。

image-20220125171720998

可以看出是從Preference里取值。

image-20220125172235883
image-20220125173029331

不過,當(dāng)apk剛安裝的時候执隧,shared_prefs里面是沒有這兩個值的户侥。

image-20220125173219732

此時是從上圖處取值的蕊唐,可以看出調(diào)用了native的nativeInitBaseUtil函數(shù),之后發(fā)了個請求钓试,抓包可以看到

image-20220125173538268

可以看出耙替,post的請求數(shù)據(jù)就是第二個字符串俗扇,post的響應(yīng)數(shù)據(jù)就是第三個字符串铜幽。

其他

通過com.zuoyebang.baseutil.NativeHelper這個類看到了另一個app的名字zuoyebang除抛,很自然認(rèn)為二者用的是同一個簽名方案到忽。jadx打開zuoyebang的apk查看下喘漏,發(fā)現(xiàn)了同樣的接口。

再查看下so文件

image-20220126103238435

稍微不同的是zuoyebang只提供了32位so持灰,而kuaidui作業(yè)只提供64位so堤魁。

ida查看

image-20220126103919355
image-20220126104112002

可以看到kuaidui作業(yè)的函數(shù)名全是顯式的椭微,能夠通過函數(shù)名知道函數(shù)的作用盲链;而zuoyebang則全都是sub_*形式,很難直觀的了解函數(shù)的作用匈仗。二者都是用相同的方案,逆向的難度卻相差好幾倍逢慌,看來逆向的時候除了看看舊版本的apk,還可以看看其他使用相同方案的產(chǎn)品攻泼。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市忙菠,隨后出現(xiàn)的幾起案子何鸡,更是在濱河造成了極大的恐慌,老刑警劉巖牛欢,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異隔盛,居然都是意外死亡拾稳,警方通過查閱死者的電腦和手機(jī)龙亲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門鳄炉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來传趾,“玉大人迎膜,你說我怎么就攤上這事〗迹” “怎么了磕仅?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵珊豹,是天一觀的道長。 經(jīng)常有香客問我榕订,道長店茶,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任劫恒,我火速辦了婚禮贩幻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘两嘴。我一直安慰自己丛楚,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布憔辫。 她就那樣靜靜地躺著趣些,像睡著了一般。 火紅的嫁衣襯著肌膚如雪贰您。 梳的紋絲不亂的頭發(fā)上坏平,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機(jī)與錄音锦亦,去河邊找鬼舶替。 笑死,一個胖子當(dāng)著我的面吹牛杠园,可吹牛的內(nèi)容都是我干的顾瞪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼返劲,長吁一口氣:“原來是場噩夢啊……” “哼玲昧!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起篮绿,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤孵延,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后亲配,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體尘应,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年吼虎,在試婚紗的時候發(fā)現(xiàn)自己被綠了犬钢。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡思灰,死狀恐怖玷犹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情洒疚,我是刑警寧澤歹颓,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布坯屿,位于F島的核電站,受9級特大地震影響巍扛,放射性物質(zhì)發(fā)生泄漏领跛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一撤奸、第九天 我趴在偏房一處隱蔽的房頂上張望吠昭。 院中可真熱鬧,春花似錦胧瓜、人聲如沸矢棚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽幻妓。三九已至,卻和暖如春劫拢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背强胰。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工舱沧, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人偶洋。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓熟吏,卻偏偏與公主長得像,于是被迫代替她去往敵國和親玄窝。 傳聞我的和親對象是個殘疾皇子牵寺,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內(nèi)容