CTF黑客精神:算法还原

一、前言

这题的解法有很多,可以通过so文件的静态分析,直接将结果写入文件达到解题的目的,不过核心思想肯定是希望我们通过逆向他的算法来获取flag.接下来我将详细的分析算法逆向的过程。CTF黑客精神:算法还原_第1张图片

二、代码分析

java层的静态分析

打开APP先简单试玩下,发现点击不玩了或者注册码填写错误提交都会发生闪退,把代码拖入到jadx中。我们从代码找到注册页面。CTF黑客精神:算法还原_第2张图片

通过代码可以看出,他的flag核心代码在libmyjni.so里面,调用了这iniSN()、saveSM()、work()这三个函数。在分析so文件之前,我们先解决闪退的问题,关键代码 Process.killProcess(Process.myPid());通过frida hook修改其逻辑。

1

2

3

4

5

6

7

8

function hook_d(){

    Java.perform(function(){

        var process_class =  Java.use("android.os.Process");

        process_class['killProcess'].implementation = function(pid){

            this['killProcess'](444);//或者注释掉,不调用这个也行

        }

    })

}

so层分析

将APK解压,找到目标文件,拖入到IDA中,一眼看去并没有发现iniSN()、saveSM()、work()这个三个函数。

接着我们去JNI_OnLoad中去定位,找到他的伪C代码。CTF黑客精神:算法还原_第3张图片 

这段代码是一个 JNI(Java Native Interface)的实现,用于在Java虚拟机加载本地库时执行。然后主要看这段代码:

1

if ( !(*g_env)->RegisterNatives(g_env, (jclass)native_class, (const JNINativeMethod *)off_5004, 3) )

RegisterNatives 用于将本地方法与 Java 类关联起来。off_5004 是一个本地方法数组,包含要注册的本地方法的信息。这里注册了3个本地方法。在进入到off_5004后。如图所示,我们来理解下这段汇编代码。
aInitsn: 字符串,表示第一个本地方法的名字为 "initSN"
aV: 字符串,表示第一个本地方法的签名,这里是 "()V",表示无参数无返回值的方法。
n1+1: 指向 initSN 本地方法的实现函数的地址。
那么以此类推:
n1 = iniSN()
n2 = saveSM()
n3 = work()
这个时候思路就非常清晰了,先来看下这三个函数的代码:CTF黑客精神:算法还原_第4张图片n1这个函数的执行逻辑:
打开一个文件 /sdcard/reg.dat,读取文件内容,与指定的字符串进行比较,然后通过调用 setValue 函数将结果写入内存中。最后,关闭文件并返回 fclose 函数的结果。
n2这个函数的执行逻辑:
读取指定文件中的内容,对内容进行异或加密,然后将加密后的内容写回文件中。密钥是根据字符串 "W3_arE_whO_we_ARE" 计算得到的。
n3这个函数的执行逻辑:
他再次调用了n1函数,调用 getValue 函数的值,来判断该返回什么样的内存。返回值有&unk_2E6B、&unk_2E95、&unk_2E5B。我们点进去按A。CTF黑客精神:算法还原_第5张图片

很明显Value = getValue(a1) ==1 是我想要的结果。再回过头看n1函数。想要等于1就要满足

1

strcmp((const char *)v6, "EoPAoY62@ElRD") )

他又是从文件/sdcard/reg.dat文件取出来的,那问题来了,他又是怎么存的呢?n2函数里面的 :

1

fputs(v16, v5);// 将加密后的内容写入文件

代码逻辑是输入的值存进去的。再综合整理下代码的执行逻辑。
输入的值等于EoPAoY62@ElRD,再完成加密,保持EoPAoY62@ElRD到/sdcard/reg.dat文件中,再调用n3 (n1 里面满足了条件,设置1值)得到value=1.结束。

目标就是输入的值经过加密等于: EoPAoY62@ElRD 就得出flag

三、算法还原

通过上面的分析他的核心算法在n2中。CTF黑客精神:算法还原_第6张图片

通过分析发现他是将我们输入的值和给定的值进行异或操作。然后我们用python 进行算法还原:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

from urllib import parse

v7 = "EoPAoY62@ElRD"

v8 = bytearray(v7, 'utf-8')

v13 = "W3_arE_whO_we_ARE"

v12 = len(v7)

v9 = 2016

v10 = 0

while v10 < v12:

    if v10 % 3 == 1:

        v9 = (v9 + 5) % 16

        v11 = ord(v13[v9 + 1])

    elif v10 % 3 == 2:

        v9 = (v9 + 7) % 15

        v11 = ord(v13[v9 + 2])

    else:

        v9 = (v9 + 3) % 13

        v11 = ord(v13[v9 + 3])

    v8[v10] ^= v11

    v10 += 1

decrypted_bytes = bytes(v8)

print(decrypted_bytes.decode('utf-8')) //201608Am!2333

将结果201608Am!2333输入到APP中:
当再次打开的是时候出现:如下。
CTF黑客精神:算法还原_第7张图片

你可能感兴趣的:(逆向开发,编程技术,算法,python,开发语言)