第二次遇到鸿蒙逆向的题,感觉挺新奇,琢磨了一中午,虽然中间有些出题人疏忽的小插曲,不过修复的速度也挺快,也是顺利拿了个一血哈哈
题目给了一个shctf.app
文件,对于文件结构可以查看官方文档的描述 应用程序包基础知识 实际上同安卓类似,使用解压缩软件即可解压,得到一个.hap
文件和一个pack.info
HAP(Harmony Ability Package)是应用安装和运行的基本单元。HAP包是由代码、资源、第三方库、配置文件等打包生成的模块包,其主要分为两种类型:entry和feature。 entry:应用的主模块,作为应用的入口,提供了应用的基础功能。 feature:应用的动态特性模块,作为应用能力的扩展,可以根据用户的需求和设备类型进行选择性安装。 应用程序包可以只包含一个基础的entry包,也可以包含一个基础的entry包和多个功能性的feature包。
然后继续解压hap文件 在etc目录下,可以看到一个module.abc
文件
abc文件 方舟字节码(ArkCompiler Bytecode)文件,是ArkCompiler的编译工具链以源代码作为输入编译生成的产物,其文件后缀名为.abc。在发布时,abc文件会被打包到HAP中。
接下来就是想办法如何去反编译这个abc文件,最后在github上发现一个基于jadx的开源abc反编译工具 abc-decompiler ,虽然反编译效果还不是很完美,期待大佬们的完善
分析page/Index
,在构造函数中初始化了secretKey
获取用户输入,并加密,和secretKey对比,如果校验通过则创建一个迷宫,然后写入What文件中
先对model/encode
方法进行分析,一些常规的运算,单字节加密
可以直接写个爆破脚本来解决
由于手上没有鸿蒙的机子,也没有调试hap的方法,因此只能继续静态分析他是如何创建迷宫的 分析model/maze
,在构造函数中初始化了迷宫数据
CreateMaze
方法中设置了迷宫的起点(S)和终点(E),并将我们输入的内容填充在迷宫中
FillF1ag
方法遍历迷宫所有格子,判断是否为空格,然后调用CheckGround
再判断,由于反编译工具还不完善,反编译结果看着还比较难懂,手动优化一下可以发现他进行了边界检查,以及返回四个方向空格的个数,当个数超过2时,FillFlag
就会将输入内容填充进去
接着只需要模拟一下对地图填充字符,然后写个bfs算法走迷宫即可,最后还顺便调用matplotlib库绘制了一下迷宫路径
public Object Index(Object functionObject, Object newTarget, Index
this
, Object arg0, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) {
if
((0 == arg3 ? 1 : 0) != 0) {
arg3 = -1;
}
if
((0 == arg4 ? 1 : 0) != 0) {
arg4 =
null
;
}
Object obj =
super
(arg0, arg2, arg3, arg5);
if
((
"function"
==
typeof
(arg4) ? 1 : 0) != 0) {
obj.paramsGenerator_ = arg4;
}
obj.__userInput = ObservedPropertySimplePU(
""
, obj,
"userInput"
);
obj.secretKey =
"[f#fLw)??Pz?#9w)Du[ks[q[#w4D?4P4UJf,kU[f.rDkfwrDtq...)?J.#rP4[qrPDJkkJ|.9J|qffU?k|D4P4P[wkk.)k?JUJ[k#9kww[r??wUfw|PkrPUf.P#f.P#.PwJ4f4q.PU4UPDr9.[9fJ#PqP)cDDffJPDrJ.J4qPP[r[.JfJ4f|?U9#"
;
obj.setInitiallyProvidedValue(arg1);
obj.finalizeConstruction();
return
obj;
}
public Object Index(Object functionObject, Object newTarget, Index
this
, Object arg0, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) {
if
((0 == arg3 ? 1 : 0) != 0) {
arg3 = -1;
}
if
((0 == arg4 ? 1 : 0) != 0) {
arg4 =
null
;
}
Object obj =
super
(arg0, arg2, arg3, arg5);
if
((
"function"
==
typeof
(arg4) ? 1 : 0) != 0) {
obj.paramsGenerator_ = arg4;
}
obj.__userInput = ObservedPropertySimplePU(
""
, obj,
"userInput"
);
obj.secretKey =
"[f#fLw)??Pz?#9w)Du[ks[q[#w4D?4P4UJf,kU[f.rDkfwrDtq...)?J.#rP4[qrPDJkkJ|.9J|qffU?k|D4P4P[wkk.)k?JUJ[k#9kww[r??wUfw|PkrPUf.P#f.P#.PwJ4f4q.PU4UPDr9.[9fJ#PqP)cDDffJPDrJ.J4qPP[r[.JfJ4f|?U9#"
;
obj.setInitiallyProvidedValue(arg1);
obj.finalizeConstruction();
return
obj;
}
public Object validateAndCreateMaze(Object functionObject, Object newTarget, Index
this
, Object arg0) {
newlexenv(2);
_lexenv_0_0_ = newTarget;
_lexenv_0_1_ =
this
;
Object newobjrange = import { encode } from
"@bundle:com.welcome.shctf/entry/ets/model/encode"
();
if
((_lexenv_0_1_.secretKey == newobjrange.encode(arg0) ? 1 : 0) == 0) {
Object promptAction = import {
default
as promptAction } from
"@ohos:promptAction"
;
promptAction.showToast(createobjectwithbuffer([
"message"
,
"口令错误!"
]));
return
null
;
}
Object newobjrange2 = import { maze } from
"@bundle:com.welcome.shctf/entry/ets/model/maze"
();
r12 = getContext(_lexenv_0_1_).filesDir +
"/What"
;
try
{
Object fileIo = import {
default
as fileIo } from
"@ohos:file.fs"
;
Object openSync = fileIo.openSync(r12, import {
default
as fileIo } from
"@ohos:file.fs"
.OpenMode.READ_WRITE | import {
default
as fileIo } from
"@ohos:file.fs"
.OpenMode.CREATE);
Object CreateMaze = newobjrange2.CreateMaze(arg0);
Object map = CreateMaze.map(
#11009740135539449431#);
Object join = map.join(
"\n"
);
Object fileIo2 = import {
default
as fileIo } from
"@ohos:file.fs"
;
fileIo2.writeSync(openSync.fd, join);
Object promptAction2 = import {
default
as promptAction } from
"@ohos:promptAction"
;
Object obj = promptAction2.showToast;
Object obj2 = createobjectwithbuffer([
"message"
, 0,
"duration"
, 5000]);
obj2.message =
"口令正确!\n等下!好像创建了什么东西?\n"
+ r12 +
""
;
obj(obj2);
return
null
;
}
catch
(ExceptionI0 unused) {
Object promptAction3 = import {
default
as promptAction } from
"@ohos:promptAction"
;
Object obj3 = promptAction3.showToast;
Object obj4 = createobjectwithbuffer([
"message"
, 0]);
obj4.message =
"文件操作失败: "
+ r12.message +
""
;
obj3(obj4);
return
null
;
}
}
public Object validateAndCreateMaze(Object functionObject, Object newTarget, Index
this
, Object arg0) {
newlexenv(2);
_lexenv_0_0_ = newTarget;
_lexenv_0_1_ =
this
;
Object newobjrange = import { encode } from
"@bundle:com.welcome.shctf/entry/ets/model/encode"
();
if
((_lexenv_0_1_.secretKey == newobjrange.encode(arg0) ? 1 : 0) == 0) {
Object promptAction = import {
default
as promptAction } from
"@ohos:promptAction"
;
promptAction.showToast(createobjectwithbuffer([
"message"
,
"口令错误!"
]));
return
null
;
}
Object newobjrange2 = import { maze } from
"@bundle:com.welcome.shctf/entry/ets/model/maze"
();
r12 = getContext(_lexenv_0_1_).filesDir +
"/What"
;
try
{
Object fileIo = import {
default
as fileIo } from
"@ohos:file.fs"
;
Object openSync = fileIo.openSync(r12, import {
default
as fileIo } from
"@ohos:file.fs"
.OpenMode.READ_WRITE | import {
default
as fileIo } from
"@ohos:file.fs"
.OpenMode.CREATE);
Object CreateMaze = newobjrange2.CreateMaze(arg0);
Object map = CreateMaze.map(
#11009740135539449431#);
Object join = map.join(
"\n"
);
Object fileIo2 = import {
default
as fileIo } from
"@ohos:file.fs"
;
fileIo2.writeSync(openSync.fd, join);
Object promptAction2 = import {
default
as promptAction } from
"@ohos:promptAction"
;
Object obj = promptAction2.showToast;
Object obj2 = createobjectwithbuffer([
"message"
, 0,
"duration"
, 5000]);
obj2.message =
"口令正确!\n等下!好像创建了什么东西?\n"
+ r12 +
""
;
obj(obj2);
return
null
;
}
catch
(ExceptionI0 unused) {
Object promptAction3 = import {
default
as promptAction } from
"@ohos:promptAction"
;
Object obj3 = promptAction3.showToast;
Object obj4 = createobjectwithbuffer([
"message"
, 0]);
obj4.message =
"文件操作失败: "
+ r12.message +
""
;
obj3(obj4);
return
null
;
}
}
public Object
#9151489524504893103#encode(Object functionObject, Object newTarget, encode this, Object arg0) {
Object obj = [Object];
Object obj2 = obj;
throw
(obj);
Object obj3 = getiterator(arg0);
Object obj4 = obj3.next;
while
(
true
) {
Object callthisN = obj4();
throw
.ifnotobject(callthisN);
if
(istrue(callthisN.done) !=
null
) {
break
;
}
Object obj5 = callthisN.value;
try
{
obj2.push(String.fromCharCode((((114514 * (obj5.charCodeAt(0) - 32)) + 1919810) % 95) + 32));
}
catch
(ExceptionI0 unused) {
if
(istrue(0) ==
null
) {
try
{
obj2 = obj3.
return
;
}
catch
(ExceptionI0 unused2) {
}
if
((0 == obj2 ? 1 : 0) == 0) {
obj2();
throw
(obj5);
}
}
throw
(obj5);
}
}
return
obj2.join(
""
);
}
public Object
#9151489524504893103#encode(Object functionObject, Object newTarget, encode this, Object arg0) {
Object obj = [Object];
Object obj2 = obj;
throw
(obj);
Object obj3 = getiterator(arg0);
Object obj4 = obj3.next;
while
(
true
) {
Object callthisN = obj4();
throw
.ifnotobject(callthisN);
if
(istrue(callthisN.done) !=
null
) {
break
;
}
Object obj5 = callthisN.value;
try
{
obj2.push(String.fromCharCode((((114514 * (obj5.charCodeAt(0) - 32)) + 1919810) % 95) + 32));
}
catch
(ExceptionI0 unused) {
if
(istrue(0) ==
null
) {
try
{
obj2 = obj3.
return
;
}
catch
(ExceptionI0 unused2) {
}
if
((0 == obj2 ? 1 : 0) == 0) {
obj2();
throw
(obj5);
}
}
throw
(obj5);
}
}
return
obj2.join(
""
);
}
s
=
"[f#fLw)??Pz?#9w)Du[ks[q[#w4D?4P4UJf,kU[f.rDkfwrDtq...)?J.#rP4[qrPDJkkJ|.9J|qffU?k|D4P4P[wkk.)k?JUJ[k#9kww[r??wUfw|PkrPUf.P#f.P#.PwJ4f4q.PU4UPDr9.[9fJ#PqP)cDDffJPDrJ.J4qPP[r[.JfJ4f|?U9#"
f
=
""
for
i
in
range
(
len
(s)):
for
j
in
range
(
32
,
128
):
tmp
=
((
114514
*
(j
-
32
)
+
1919810
)
%
95
)
+
32
if
s[i]
=
=
chr
(tmp):
f
+
=
chr
(j)
break
print
(f)
s
=
"[f#fLw)??Pz?#9w)Du[ks[q[#w4D?4P4UJf,kU[f.rDkfwrDtq...)?J.#rP4[qrPDJkkJ|.9J|qffU?k|D4P4P[wkk.)k?JUJ[k#9kww[r??wUfw|PkrPUf.P#f.P#.PwJ4f4q.PU4UPDr9.[9fJ#PqP)cDDffJPDrJ.J4qPP[r[.JfJ4f|?U9#"
f
=
""
for
i
in
range
(
len
(s)):
for
j
in
range
(
32
,
128
):
tmp
=
((
114514
*
(j
-
32
)
+
1919810
)
%
95
)
+
32
if
s[i]
=
=
chr
(tmp):
f
+
=
chr
(j)
break
print
(f)
public Object maze(Object functionObject, Object newTarget, maze
this
) {
Object[] objArr = [Object];
objArr[0] = createarraywithbuffer([
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
]);
objArr[1] = createarraywithbuffer([
"#"
,
" "
,
"#"
,
" "
,
" "
,
" "
,
" "
,
" "
,
"#"
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
"#"
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
"#"
,
" "
,
" "
,
" "
,
" "
,
" "
,
"#"
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
"#"
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
"#"
,
" "
,
" "
,
" "
,
"#"
,
" "
,
" "
,
" "
,
"#"
,
" "
,
" "
,
" "
,
"#"
,
" "
,
" "
,
" "
,
"#"
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
"#"
]);
......
this
.maze = objArr;
return
this
;
}
public Object maze(Object functionObject, Object newTarget, maze
this
) {
Object[] objArr = [Object];
objArr[0] = createarraywithbuffer([
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
,
"#"
]);
objArr[1] = createarraywithbuffer([
"#"
,
" "
,
"#"
,
" "
,
" "
,
" "
,
" "
,
" "
,
"#"
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
"#"
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
"#"
,
" "
,
" "
,
" "
,
" "
,
" "
,
"#"
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
"#"
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
"#"
,
" "
,
" "
,
" "
,
"#"
,
" "
,
" "
,
" "
,
"#"
,
" "
,
" "
,
" "
,
"#"
,
" "
,
" "
,
" "
,
"#"
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
" "
,
"#"
]);
......
this
.maze = objArr;
return
this
;
}
public Object CreateMaze(Object functionObject, Object newTarget, maze
this
, Object arg0) {
this
.maze[77][1] =
"E"
;
this
.maze[1][83] =
"S"
;
return
this
.FillF1ag(
this
.maze, arg0);
}
public Object CreateMaze(Object functionObject, Object newTarget, maze
this
, Object arg0) {
this
.maze[77][1] =
"E"
;
this
.maze[1][83] =
"S"
;
return
this
.FillF1ag(
this
.maze, arg0);
}
public Object FillF1ag(Object functionObject, Object newTarget, maze
this
, Object arg0, Object arg1) {
int i = 0;
for
(int i2 = 0; (i2 < arg0.length ? 1 : 0) != 0; i2 = tonumer(i2) + 1) {
for
(int i3 = 0; (i3 < arg0[0].length ? 1 : 0) != 0; i3 = tonumer(i3) + 1) {
if
(isfalse((
" "
== arg0[i2][i3] ? 1 : 0)) ==
null
&& isfalse((
this
.CheckGround(arg0, i3, i2) > 2 ? 1 : 0)) ==
null
) {
arg0[i2][i3] = arg1[i];
i++;
}
}
}
return
arg0;
}
public Object CheckGround(Object functionObject, Object newTarget, maze
this
, Object arg0, Object arg1, Object arg2) {
Object obj;
r16 = [Object];
r162 = [Object];
r162[0] = -1;
r162[1] = 0;
r16[0] = r162;
r16[1] = createarraywithbuffer([1, 0]);
Object createarraywithbuffer = createarraywithbuffer([0]);
createarraywithbuffer[1] = -1;
r16[2] = createarraywithbuffer;
Object createarraywithbuffer2 = createarraywithbuffer([0, 1]);
r16[3] = createarraywithbuffer2;
throw
(createarraywithbuffer2);
Object obj2 = getiterator(r16);
Object obj3 = obj2.next;
int i = 0;
while
(
true
) {
Object callthisN = obj3();
throw
.ifnotobject(callthisN);
if
(istrue(callthisN.done) !=
null
) {
break
;
}
Object obj4 = callthisN.value;
try
{
ldobjbyvalue = obj4[0];
ldobjbyvalue2 = obj4[1];
int i2 = arg1 + ldobjbyvalue;
int i3 = arg2 + ldobjbyvalue2;
int i4 = (i2 >= 0 ? 1 : 0);
int i5 = i4;
obj4 = isfalse(i4);
if
(obj4 ==
null
) {
i5 = (i2 < arg0[0].length ? 1 : 0);
}
if
(isfalse(i5) ==
null
) {
i5 = (i3 >= 0 ? 1 : 0);
}
if
(isfalse(i5) ==
null
) {
i5 = (i3 < arg0.length ? 1 : 0);
}
if
(isfalse(i5) ==
null
&& isfalse((
" "
== arg0[i3][i2] ? 1 : 0)) ==
null
) {
i++;
}
}
catch
(ExceptionI0 unused) {
Object obj5 = obj4;
if
(istrue(0) ==
null
) {
try
{
obj = obj2.
return
;
}
catch
(ExceptionI0 unused2) {
}
if
((0 == obj ? 1 : 0) == 0) {
obj();
throw
(obj5);
}
}
throw
(obj5);
}
}
return
i;
}
public Object FillF1ag(Object functionObject, Object newTarget, maze
this
, Object arg0, Object arg1) {
int i = 0;
for
(int i2 = 0; (i2 < arg0.length ? 1 : 0) != 0; i2 = tonumer(i2) + 1) {
for
(int i3 = 0; (i3 < arg0[0].length ? 1 : 0) != 0; i3 = tonumer(i3) + 1) {
if
(isfalse((
" "
== arg0[i2][i3] ? 1 : 0)) ==
null
&& isfalse((
this
.CheckGround(arg0, i3, i2) > 2 ? 1 : 0)) ==
null
) {
arg0[i2][i3] = arg1[i];
i++;
}
}
}
return
arg0;
}
public Object CheckGround(Object functionObject, Object newTarget, maze
this
, Object arg0, Object arg1, Object arg2) {
Object obj;
r16 = [Object];
r162 = [Object];
r162[0] = -1;
r162[1] = 0;
r16[0] = r162;
r16[1] = createarraywithbuffer([1, 0]);
Object createarraywithbuffer = createarraywithbuffer([0]);
createarraywithbuffer[1] = -1;
r16[2] = createarraywithbuffer;
Object createarraywithbuffer2 = createarraywithbuffer([0, 1]);
r16[3] = createarraywithbuffer2;
throw
(createarraywithbuffer2);
Object obj2 = getiterator(r16);
Object obj3 = obj2.next;
int i = 0;
while
(
true
) {
Object callthisN = obj3();
throw
.ifnotobject(callthisN);
if
(istrue(callthisN.done) !=
null
) {
break
;
}
Object obj4 = callthisN.value;
try
{
ldobjbyvalue = obj4[0];
ldobjbyvalue2 = obj4[1];
int i2 = arg1 + ldobjbyvalue;
int i3 = arg2 + ldobjbyvalue2;
int i4 = (i2 >= 0 ? 1 : 0);
int i5 = i4;
obj4 = isfalse(i4);
if
(obj4 ==
null
) {
i5 = (i2 < arg0[0].length ? 1 : 0);
}
if
(isfalse(i5) ==
null
) {
i5 = (i3 >= 0 ? 1 : 0);
}
if
(isfalse(i5) ==
null
) {
i5 = (i3 < arg0.length ? 1 : 0);
}
if
(isfalse(i5) ==
null
&& isfalse((
" "
== arg0[i3][i2] ? 1 : 0)) ==
null
) {
i++;
}
}
catch
(ExceptionI0 unused) {
Object obj5 = obj4;
if
(istrue(0) ==
null
) {
try
{
obj = obj2.
return
;
}
catch
(ExceptionI0 unused2) {
}
if
((0 == obj ? 1 : 0) == 0) {
obj();
throw
(obj5);
}
}
throw
(obj5);
}
}
return
i;
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2024-10-20 20:22
被TubituX编辑
,原因: 上传附件
上传的附件: