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 dks∣M0˘000h+AYQg0˘000P∗!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"
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"
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)
str_m_fanzhuan
=
charArrayStr2[::
-
1
]
print
(str_m_fanzhuan)
return
str_m_fanzhuan
def
a_jie(str_m):
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)