首页
社区
课程
招聘
[原创]Frida 实战 KGB Messenger
发表于: 2023-7-22 14:01 7670

[原创]Frida 实战 KGB Messenger

2023-7-22 14:01
7670

KGB Messenger是一个类似闯关的APP,有很多关卡,通过的方法有很多种,这里我们主要用frida进行闯关。中间有很多关于算法的实现和反推演的过程,其实对于新手还是很有挑战的,当然了对于我来说也是很有挑战的,接下分享下通关的思路和方法。

打开APP,映入眼前的就是 This app can only run on Russian devices.的提示报错,如果不解决这个,后面将无法进行,我们将APP拖入jadx进行分析。
图片描述
搜索到目标代码,我们分析发现 System.getProperty("user.home") = Russia 即可满足条件进入下一关。
图片描述
System.getProperty(String name)方法用于得到系统的属性.System是在lang包中的一个类,这个类中存在大
量和系统打交道的实用方法,而且一般都是类方法,.getProperty(String key)就是其中一个比较常用的方
法,用于返回系统参数文件中这个方法指定键所代表的值。

根据上面的图片,这一关的关键是System.getenv("USER") = getResources().getString(R.string.User)即可通过下一关。通过上一关的分析我知道getenv的类是java.lang.String用样的方法hook修改返回值即可。那返回值是什么呢?从getResources大概可以猜测是资源文件,再跳转到R.string.User。
图片描述
得到 User = 0x7f0d0000 应该是标记内存地址指向了某个元素,相互映射的关系,我们再搜索 0x7f0d0000
图片描述
果然再资源文件里面,我再进行搜索。发现 对应的user字符串: RkxBR3s1N0VSTDFOR180UkNIM1J9Cg==
图片描述

来到这一关是一个登录界面,随便输入账号密码,提示:User not recognized.,看来登录是有文章的,我们查看代码分析.
图片描述
通过第二关的分析,我们很容容易找到了R.string.username = codenameduchess

随便输入密码 会提示 Incorrect password.,查看上面的图片我们可以知道,j()这函数是关键,满足true这个条件,即可跳入到下一关。
图片描述
让结果强行改true.

来到这一关,我们进入到一个消息聊天界面,发送消息是没有反馈的,看代码:
图片描述
this.o.add(new com.tlamb96.kgbmessenger.b.a(R.string.user, obj, j(), false));这个是发送消息的模板,true是对方发送的,flase代表我发发送的消息。当然了这段代码和解密无关,但是地了解它的发送逻辑,排除掉无关的代码。a(obj.toString()).equals(this.p)是闯关的关键。 p="V@]EAASB\u0012WZF\u0012e,a$7(&am2(3.\u0003";输入的值经过a方法,返回值等于p值即可进入下一关。
a()

这个a方法是一个算法,只要我们反推出这个算法,就知道应该输入什么值,遇到这样的问题,我觉得我们应该先还原算法,不要硬反推,应该这样很烧脑,很浪费时间,正向还原比反向推导要简单的多,我们安装他的逻辑进行编写即可。
再写算法之前,我们先了解下python的异或^运算。

python a()还原:

"abcdef" 经过加密得到 #TWV"# ,当然了得必须验证下你得算法是否正确,万一写错误,不是陷入到了死胡同?所有hook a方法,输入 abcdef 看看打印的结果是不是TWV"#

得到了正向的加密,反推就简单多了,因为写了一遍,再反推和没写直接推演是不一样的。在这里我们要注意下 ^ 这个值的还原。记住这一点:当然也不一定对,欢迎批评指正,互相学习。

反推算法:

我们输入 TWV"# 得到值 :abcedf 完全正确。这个时候我们再输入p值:

输入 : Boris, give me the password 即可进入到下一关。

这一关的思路和第五关一样,他们的风控手段也是雷同的。主要是 b(String str) = r = "\u0000dslp}oQ\u0000 dksM0˘000h+AYQg0˘000P!M|M\u0000h +AYQg\u0000P*!MgQ\u0000";
b() 源码:

b方法python正向还原:

我们发现以下代码是主要的加密位置,后面只是实现了一个倒序,只是他实现的过程比较复杂,如果用python 实现这个逻辑只要一行代码就行。废话不多说,只要实现以下代码的反推逻辑即可破解。

反推后的代码:

得到 : 补全单词:May I PLEASE have the password
总体来说hook的逻辑还是简单的,代码相信大家都能看得懂,唯一的难度就是a和b方法的加密算法的还原。

var system = Java.use("java.lang.System");
system.getProperty.overload('java.lang.String').implementation = function (str) {
    var re = this.getProperty(str);
    return "Russia";
}
var system = Java.use("java.lang.System");
system.getProperty.overload('java.lang.String').implementation = function (str) {
    var re = this.getProperty(str);
    return "Russia";
}
var system = Java.use("java.lang.System");
system.getenv.overload('java.lang.String').implementation = function (str) {
    console.log("system.getenv : ", str)
    var re = this.getenv(str);
    console.log("system.getenv.re : ", re)
    return "RkxBR3s1N0VSTDFOR180UkNIM1J9Cg==";
}
var system = Java.use("java.lang.System");
system.getenv.overload('java.lang.String').implementation = function (str) {
    console.log("system.getenv : ", str)
    var re = this.getenv(str);
    console.log("system.getenv.re : ", re)
    return "RkxBR3s1N0VSTDFOR180UkNIM1J9Cg==";
}
adb shell input text 'codenameduchess'
adb shell input text 'codenameduchess'
var LoginActivity = Java.use("com.tlamb96.kgbmessenger.LoginActivity");
LoginActivity["j"].implementation = function () {
    var ret = this.j();
    return true;
};
var LoginActivity = Java.use("com.tlamb96.kgbmessenger.LoginActivity");
LoginActivity["j"].implementation = function () {
    var ret = this.j();
    return true;
};
private String a(String str) {
    char[] charArray = str.toCharArray();
    for (int i = 0; i < charArray.length / 2; i++) {
        char c = charArray[i];
        charArray[i] = (char) (charArray[(charArray.length - i) - 1] ^ '2');
        charArray[(charArray.length - i) - 1] = (char) (c ^ 'A');
    }
    return new String(charArray);
}
private String a(String str) {
    char[] charArray = str.toCharArray();
    for (int i = 0; i < charArray.length / 2; i++) {
        char c = charArray[i];
        charArray[i] = (char) (charArray[(charArray.length - i) - 1] ^ '2');
        charArray[(charArray.length - i) - 1] = (char) (c ^ 'A');
    }
    return new String(charArray);
}
chr()将数字(10进制)转化为中文
 
ord() 将中文转化为数字(10进制)
chr()将数字(10进制)转化为中文
 
ord() 将中文转化为数字(10进制)
def a(str_m):
    charArray2 = list(str_m)
    for ii in range(0, int(len(charArray2) / 2)):
        cc = charArray2[ii]
        print("ii ", ii, cc, " charArray2[ii] :", len(charArray2) - ii - 1, charArray2[len(charArray2) - ii - 1],
              chr(ord(charArray2[len(charArray2) - ii - 1]) ^ ord('2')), "charArray2[len(charArray2) - ii - 1] :",
              len(charArray2) - ii - 1, chr(ord(cc) ^ ord('A')))
        charArray2[ii] = chr(ord(charArray2[len(charArray2) - ii - 1]) ^ ord('2'))
        charArray2[len(charArray2) - ii - 1] = chr(ord(cc) ^ ord('A'))
    charArrayStr2 = "".join(charArray2)
    print("charArrayStr2:", charArrayStr2)
    return charArrayStr2
 
if __name__ == '__main__':
    str_m = "abcdef"  # UTWd" 
    # re = a(str_m)
def a(str_m):
    charArray2 = list(str_m)
    for ii in range(0, int(len(charArray2) / 2)):
        cc = charArray2[ii]
        print("ii ", ii, cc, " charArray2[ii] :", len(charArray2) - ii - 1, charArray2[len(charArray2) - ii - 1],
              chr(ord(charArray2[len(charArray2) - ii - 1]) ^ ord('2')), "charArray2[len(charArray2) - ii - 1] :",
              len(charArray2) - ii - 1, chr(ord(cc) ^ ord('A')))
        charArray2[ii] = chr(ord(charArray2[len(charArray2) - ii - 1]) ^ ord('2'))
        charArray2[len(charArray2) - ii - 1] = chr(ord(cc) ^ ord('A'))
    charArrayStr2 = "".join(charArray2)
    print("charArrayStr2:", charArrayStr2)
    return charArrayStr2
 
if __name__ == '__main__':
    str_m = "abcdef"  # UTWd" 
    # re = a(str_m)
        var MessengerActivity = Java.use("com.tlamb96.kgbmessenger.MessengerActivity");
        MessengerActivity["a"].implementation = function (str) {
            console.log('a is called' + ', ' + 'str: ' + str);
            var ret = this.a(str);
            console.log('a ret value is ' + ret);
            return ret;
        };
 
结果:
a is called, str: abcdef
a ret value is TWV"#
        var MessengerActivity = Java.use("com.tlamb96.kgbmessenger.MessengerActivity");
        MessengerActivity["a"].implementation = function (str) {
            console.log('a is called' + ', ' + 'str: ' + str);
            var ret = this.a(str);
            console.log('a ret value is ' + ret);
            return ret;
        };
 
结果:
a is called, str: abcdef
a ret value is TWV"#
求y : x ^ '值' = y
求x : y ^ '值' = x
求y : x ^ '值' = y
求x : y ^ '值' = x
def a_jie(str_m):
    str_m_fanzhuan = str_m[::-1]
    charArray2 = list(str_m_fanzhuan)
    for ii in range(0, int(len(charArray2) / 2)):
        cc = charArray2[ii]
        charArray2[ii] = chr(ord(charArray2[len(charArray2) - ii - 1]) ^ ord('2'))
        charArray2[len(charArray2) - ii - 1] = chr(ord(cc) ^ ord('A'))
    charArrayStr2 = "".join(charArray2)
    print("charArrayStr2:", charArrayStr2)  # fedcba
    # 再反转:
    str_m_fanzhuan = charArrayStr2[::-1]
    print(str_m_fanzhuan)
    return str_m_fanzhuan
def a_jie(str_m):

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 1
支持
分享
最新回复 (2)
雪    币: 3004
活跃值: (30866)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
又有bug了,不能收藏
2023-7-22 16:23
1
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
最后是只要补相同的就可以了
2023-8-23 16:02
0
游客
登录 | 注册 方可回帖
返回
//