首页
社区
课程
招聘
[原创]MobileCTF easy系列合集:Flag算法还原
发表于: 2023-12-27 23:30 9245

[原创]MobileCTF easy系列合集:Flag算法还原

2023-12-27 23:30
9245

这是由一系列CTF easy项目组成的,难度系数也是逐渐增加的。不管是简单还是复杂,获取flag不是目的,目的是分析和解决问题的方法和思路,不管多少道题,还是逆向其他网站,解决问题的方式是差不多,接下来我们将详细的分析每个项目的算法。

这题考察的是base64算法的知识点,通过Base64Encode()对输入的字符串进行加密,然后与字符串5rFf7E2K6rqN7Hpiyush7E6S5fJg6rsi5NBf6NGT5rs=进行比较,如果相等就完成破解。这题我们用2种解法来获取flag,先来看代码:
图片描述
既然如此,我们前期不考虑验证通过的问题,先正向还原他的加密,输入一个简单的数据:例如 abcd 编码结果: JHqKyv==
有了输入值,和返回值,我们用python 还原他的算法:

再将 5rFf7E2K6rqN7Hpiyush7E6S5fJg6rsi5NBf6NGT5rs= 值代入其中,解密后得到:05397c42f9b6da593a3644162d36eb01
输入到APP 显示验证成功。

还有一种处理的办法,从他的代码其实可以看出他是一个base64加密的换表算法,因为加密的逻辑是符合base64的原理的,然后我们写代码来验证下:

结果是一样的,所以算法的底层逻辑是很重要的,必要时候能节省很多时间。

这题是基于java层的,算法是层层嵌套,代码逻辑是非常清晰的,将输入的字符串经过层层处理,得到一个新的字符串,满足sb.toString().equals("wigwrkaugala")即可破解,我们来分析下:
图片描述
我们先来分析他正常逻辑的算法:
这段代码看起来是在处理一个形如 "flag{...}" 的字符串,通过某种特定的处理和比较,最终确定是否符合特定的条件。

图片描述
拿到值之后,我们先分析下:
输入abced
b方法: a 9、b 8、c 7、e 1、d 21
a方法:9 h、8 w、7 x、1 v、21 a
用python 还b方法验证:

图片描述
和hook的值一样 没有问题。
再还原a方法进行验证:

图片描述
和hook的值一样,说明算法还原没问题。
现在知道结果 wigwrkaugala 进行反推a方法 再反推 b方法。
反推的算法如下:先输入我们之前输入的abced 将得到结果 hwxva 输入其中,看看能不能得到 abced :

图片描述
反推算法没问题,我们再输入输入:wigwrkaugala 得到:['v', 'e', 'n', 'i', 'v', 'i', 'd', 'i', 'v', 'k', 'c', 'r']
flag : flag{venividivkcr} APP验证成功

这题是java层和so层相结合的算法逆向,但从代码上看,逻辑还是很清晰的。如果认真分析过easy_apk这个项目,很容易看出,他就是一个base64的换表算法。我们同样采用2种解题的方法。不过以后如果遇到类似的,直接采用第二种方法就行。先来看代码:
图片描述
hook a()方法,方便后面进行验证:

输入:abcdefgabcdefgabcdefgab 结果:2eXTQS8AQC7I2CntQAkO2A1/QeQx2eG=
输入的字符串经过 a(byte[] bArr) 加密后,带入so里面经过处理,剩下逻辑在so里面,我们来看so里面的代码:
图片描述

对于这段代码我们分析下:
这个函数的主要逻辑是对字符串进行一系列处理,包括颠倒、移位等操作,然后将结果与预定义字符串进行比较。如果最终处理后的字符串与预定义字符串相等,函数返回 true;否则,返回 false。

根据so的代码逻辑,我们还原她的正向和逆向算法:

解密函数reverse_ncheck(ciphertext) 带入MbT3sQgX039i3g==AQOoMQFPskB1Bsc7 得到:
QAoOQMPFks1BsB7cbM3TQsXg30i9g3==
so函数的分析到此为止。
现在来还原下,java层的a()方法:

那么逆向还原这个算法:

图片描述
算法加解密验证没问题。
将QAoOQMPFks1BsB7cbM3TQsXg30i9g3== 带入解密函数中,得到结果:flag{just_ANot#er_@p3}

这题的整体逻辑并不复制,加密算法主要在so里面,读懂代码,并能推导出来,这个很重要。接下来我们详细的分析,先来看代码:
图片描述
java层的代码逻辑非常清晰,就是验证输入值在so里面的检测,来看so代码:
图片描述
1.首先获取字符串的长度 v4,然后根据长度动态分配内存。这里使用了 malloc 函数,它会分配 v6 个字节的内存空间,并将其起始地址存储在 v7 中
2.将字符串 v3 的内容复制到动态分配的内存中。首先判断内存是否足够,如果不够则进行相应的内存清零操作。然后使用 memcpy 将字符串复制到动态分配的内存中
3.对字符串的每两个字符进行交换,即将字符串的第一个字符与第二个字符、第三个字符与第四个字符交换位置
4.对字符串进行了更多的字符交换操作,将第一个字符与第二个字符交换,然后每两个字符交换一次,直到字符串末尾
5.return strcmp(v8, "f72c5a36569418a20907b55be5bf95ad") == 0最后,通过 strcmp 函数比较经过处理的字符串 v8 是否与固定字符串 "f72c5a36569418a20907b55be5bf95ad" 相等,如果相等则返回 0,表示字符串相等。
算法还原:

图片描述

90705bb55efb59da7fc2a5636549812a 验证成功

class Base64New:
    RANGE = 255
    Base64ByteToStr = ['v', 'w', 'x', 'r', 's', 't', 'u', 'o', 'p', 'q', '3', '4', '5', '6', '7', 'A', 'B', 'C', 'D',
                       'E', 'F', 'G', 'H', 'I', 'J', 'y', 'z', '0', '1', '2', 'P', 'Q', 'R', 'S', 'T', 'K', 'L', 'M',
                       'N', 'O', 'Z', 'a', 'b', 'c', 'd', 'U', 'V', 'W', 'X', 'Y', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
                       'l', 'm', 'n', '8', '9', '+', '/']
    StrToBase64Byte = {char: idx for idx, char in enumerate(Base64ByteToStr)}
 
    def Base64Encode(self, bytes):
        res = []
        for i in range(0, len(bytes), 3):
            enBytes = [0] * 4
            tmp = 0
            for k in range(3):
                if i + k < len(bytes):
                    enBytes[k] = ((bytes[i + k] & 255) >> ((k * 2) + 2)) | tmp
                    tmp = (((bytes[i + k] & 255) << ((2 - k) * 2 + 2)) & 255) >> 2
                else:
                    enBytes[k] = tmp
                    tmp = 64
            enBytes[3] = tmp
            for k2 in range(4):
                if enBytes[k2] <= 63:
                    res.append(self.Base64ByteToStr[enBytes[k2]])
                else:
                    res.append('=')
 
        return ''.join(res)
 
    def Base64Decode(self, encoded_str):
        decoded_bytes = bytearray()
 
        for i in range(0, len(encoded_str), 4):
            enChars = encoded_str[i:i + 4]
            deBytes = [0] * 4
 
            for k in range(4):
                if enChars[k] != '=':
                    deBytes[k] = self.StrToBase64Byte[enChars[k]]
 
            decoded_bytes.extend((((deBytes[0] << 2) & 255) | (deBytes[1] >> 4)).to_bytes(1, 'big'))
 
            if enChars[2] != '=' and len(enChars) > 2:
                decoded_bytes.extend((((deBytes[1] << 4) & 255) | (deBytes[2] >> 2)).to_bytes(1, 'big'))
 
            if enChars[3] != '=' and len(enChars) > 3:
                decoded_bytes.extend((((deBytes[2] << 6) & 255) | deBytes[3]).to_bytes(1, 'big'))
 
        return decoded_bytes
class Base64New:
    RANGE = 255
    Base64ByteToStr = ['v', 'w', 'x', 'r', 's', 't', 'u', 'o', 'p', 'q', '3', '4', '5', '6', '7', 'A', 'B', 'C', 'D',
                       'E', 'F', 'G', 'H', 'I', 'J', 'y', 'z', '0', '1', '2', 'P', 'Q', 'R', 'S', 'T', 'K', 'L', 'M',
                       'N', 'O', 'Z', 'a', 'b', 'c', 'd', 'U', 'V', 'W', 'X', 'Y', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
                       'l', 'm', 'n', '8', '9', '+', '/']
    StrToBase64Byte = {char: idx for idx, char in enumerate(Base64ByteToStr)}
 
    def Base64Encode(self, bytes):
        res = []
        for i in range(0, len(bytes), 3):
            enBytes = [0] * 4
            tmp = 0
            for k in range(3):
                if i + k < len(bytes):
                    enBytes[k] = ((bytes[i + k] & 255) >> ((k * 2) + 2)) | tmp
                    tmp = (((bytes[i + k] & 255) << ((2 - k) * 2 + 2)) & 255) >> 2
                else:
                    enBytes[k] = tmp
                    tmp = 64
            enBytes[3] = tmp
            for k2 in range(4):
                if enBytes[k2] <= 63:
                    res.append(self.Base64ByteToStr[enBytes[k2]])
                else:
                    res.append('=')
 
        return ''.join(res)
 
    def Base64Decode(self, encoded_str):
        decoded_bytes = bytearray()
 
        for i in range(0, len(encoded_str), 4):
            enChars = encoded_str[i:i + 4]
            deBytes = [0] * 4
 
            for k in range(4):
                if enChars[k] != '=':
                    deBytes[k] = self.StrToBase64Byte[enChars[k]]
 
            decoded_bytes.extend((((deBytes[0] << 2) & 255) | (deBytes[1] >> 4)).to_bytes(1, 'big'))
 
            if enChars[2] != '=' and len(enChars) > 2:
                decoded_bytes.extend((((deBytes[1] << 4) & 255) | (deBytes[2] >> 2)).to_bytes(1, 'big'))
 
            if enChars[3] != '=' and len(enChars) > 3:
                decoded_bytes.extend((((deBytes[2] << 6) & 255) | deBytes[3]).to_bytes(1, 'big'))
 
        return decoded_bytes
import base64
s1 = "vwxrstuopq34567ABCDEFGHIJyz012PQRSTKLMNOZabcdUVWXYefghijklmn89+/"
s2 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
 
# abcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZ
 
data = "5rFf7E2K6rqN7Hpiyush7E6S5fJg6rsi5NBf6NGT5rs="
 
print(str.maketrans(s1, s2))
print(data.translate(str.maketrans(s1, s2)).encode('utf-8'))
key = str(base64.b64decode(data.translate(str.maketrans(s1, s2)).encode('utf-8')), encoding="utf-8")
print(" key = ", key)
#  key =  05397c42f9b6da593a3644162d36eb01
import base64
s1 = "vwxrstuopq34567ABCDEFGHIJyz012PQRSTKLMNOZabcdUVWXYefghijklmn89+/"
s2 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
 
# abcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZ
 
data = "5rFf7E2K6rqN7Hpiyush7E6S5fJg6rsi5NBf6NGT5rs="
 
print(str.maketrans(s1, s2))
print(data.translate(str.maketrans(s1, s2)).encode('utf-8'))
key = str(base64.b64decode(data.translate(str.maketrans(s1, s2)).encode('utf-8')), encoding="utf-8")
print(" key = ", key)
#  key =  05397c42f9b6da593a3644162d36eb01
function hook_java() {
    Java.perform(function () {
        var MainActivity = Java.use("com.a.easyjava.MainActivity");
        MainActivity["a"].overload('java.lang.String', 'com.a.easyjava.b', 'com.a.easyjava.a').implementation = function (str, bVar, aVar) {
            console.log("MainActivity.a is called: str=${str}, bVar=${bVar}, aVar=${aVar}",str,bVar,aVar);
            var result = this["a"](str, bVar, aVar);
            console.log("MainActivity.a result=${result}", result);
            return result;
        };
        var a = Java.use("com.a.easyjava.a");
        a["a"].overload('java.lang.Integer').implementation = function (num) {
            console.log("a.a is called: num=${num}", num);
            var result = this["a"](num);
            console.log("a.a result=${result}", result);
            return result;
        };
 
        var b = Java.use("com.a.easyjava.b");
        b["a"].overload('java.lang.String').implementation = function (str) {
            console.log("b.a is called: str=${str}", str);
            var result = this["a"](str);
            console.log("b.a result=${result}", result);
            return result;
        };
    })
}
 
function main() {
    hook_java()
}
 
setImmediate(main)
function hook_java() {
    Java.perform(function () {
        var MainActivity = Java.use("com.a.easyjava.MainActivity");
        MainActivity["a"].overload('java.lang.String', 'com.a.easyjava.b', 'com.a.easyjava.a').implementation = function (str, bVar, aVar) {
            console.log("MainActivity.a is called: str=${str}, bVar=${bVar}, aVar=${aVar}",str,bVar,aVar);
            var result = this["a"](str, bVar, aVar);
            console.log("MainActivity.a result=${result}", result);
            return result;
        };
        var a = Java.use("com.a.easyjava.a");
        a["a"].overload('java.lang.Integer').implementation = function (num) {
            console.log("a.a is called: num=${num}", num);
            var result = this["a"](num);
            console.log("a.a result=${result}", result);
            return result;
        };
 
        var b = Java.use("com.a.easyjava.b");
        b["a"].overload('java.lang.String').implementation = function (str) {
            console.log("b.a is called: str=${str}", str);
            var result = this["a"](str);
            console.log("b.a result=${result}", result);
            return result;
        };
    })
}
 
function main() {
    hook_java()
}
 
setImmediate(main)
class B:
    a = []
    b = "abcdefghijklmnopqrstuvwxyz"
    d = 0
 
    c = [8, 25, 17, 23, 7, 22, 1, 16, 6, 9, 21, 0, 15, 5, 10, 18, 2, 24, 4, 11, 3, 14, 19, 12, 20, 13]
 
    def __init__(self, num):
        for value in self.c[num:]:
            self.a.append(value)
        for value in self.c[:num]:
            self.a.append(value)
        self.a = self.a[:len(self.c)-1]
        print(self.a)
    @staticmethod
    def process_input():
        global b, d
        value = B.a[0]
        B.a.pop(0)
        B.a.append(value)
        b += b[0]
        b = b[1:27]
        d += 1
 
    def process_string(self, string):
        i = 0
        if string.lower() in b:
            value = b.index(string.lower())
            for i2 in range(len(self.a) - 1):
                if self.a[i2] == value:
                    i = i2
        else:
            i = -10 if " " in string else -1
        B.process_input()
        return i
 
    def get_d(self):
        return d
 
# 示例用法:
b = "abcdefghijklmnopqrstuvwxyz"
d = 0
= 2
jiami_str = "abced"
for jstr in jiami_str:
    print("jstr ",jstr)
    obj = B(q)
    result = obj.process_string(jstr)
    print(result)  # 示例返回:2
    q = q +1
class B:
    a = []
    b = "abcdefghijklmnopqrstuvwxyz"
    d = 0
 
    c = [8, 25, 17, 23, 7, 22, 1, 16, 6, 9, 21, 0, 15, 5, 10, 18, 2, 24, 4, 11, 3, 14, 19, 12, 20, 13]
 
    def __init__(self, num):
        for value in self.c[num:]:
            self.a.append(value)
        for value in self.c[:num]:
            self.a.append(value)
        self.a = self.a[:len(self.c)-1]
        print(self.a)
    @staticmethod
    def process_input():
        global b, d
        value = B.a[0]
        B.a.pop(0)
        B.a.append(value)
        b += b[0]
        b = b[1:27]
        d += 1
 
    def process_string(self, string):
        i = 0
        if string.lower() in b:
            value = b.index(string.lower())
            for i2 in range(len(self.a) - 1):
                if self.a[i2] == value:
                    i = i2
        else:
            i = -10 if " " in string else -1
        B.process_input()
        return i
 
    def get_d(self):
        return d
 
# 示例用法:
b = "abcdefghijklmnopqrstuvwxyz"
d = 0
= 2
jiami_str = "abced"
for jstr in jiami_str:
    print("jstr ",jstr)
    obj = B(q)
    result = obj.process_string(jstr)
    print(result)  # 示例返回:2
    q = q +1
class A:
    a = []
    b = "abcdefghijklmnopqrstuvwxyz"
    d = 0
 
    c = [7, 14, 16, 21, 4, 24, 25, 20, 5, 15, 9, 17, 6, 13, 3, 18, 12, 10, 19, 0, 22, 2, 11, 23, 1, 8]
 
    def __init__(self, num):
        for value in self.c[num:]:
            self.a.append(value)
        for value in self.c[:num]:
            self.a.append(value)
 
    @staticmethod
    def process_input():
        global d
        d += 1
        if d == 25:
            value = A.a[0]
            A.a.pop(0)
            A.a.append(value)
            d = 0
 
    def process_string(self, num):
        num2 = 0
        if num == -10:
            A.process_input()
            return " "
        for i in range(len(self.a) - 1):
            if self.a[i] == num:
                num2 = i
        A.process_input()
        return self.b[num2]
 
 
# 示例用法:
a = "abcdefghijklmnopqrstuvwxyz"
d = 0
 
obj = A(3)
num_str = [9,8,7,1,21]
for n in num_str:
    print("输入值:",n)
    result = obj.process_string(n)
    print(result)  # 示例返回:c
    print("----------------------------")
obj.process_string(-10# 示例返回:' '
class A:
    a = []
    b = "abcdefghijklmnopqrstuvwxyz"
    d = 0
 
    c = [7, 14, 16, 21, 4, 24, 25, 20, 5, 15, 9, 17, 6, 13, 3, 18, 12, 10, 19, 0, 22, 2, 11, 23, 1, 8]
 
    def __init__(self, num):
        for value in self.c[num:]:
            self.a.append(value)
        for value in self.c[:num]:
            self.a.append(value)
 
    @staticmethod
    def process_input():
        global d
        d += 1
        if d == 25:
            value = A.a[0]
            A.a.pop(0)
            A.a.append(value)
            d = 0
 
    def process_string(self, num):
        num2 = 0
        if num == -10:
            A.process_input()
            return " "
        for i in range(len(self.a) - 1):
            if self.a[i] == num:
                num2 = i
        A.process_input()
        return self.b[num2]
 
 
# 示例用法:
a = "abcdefghijklmnopqrstuvwxyz"
d = 0
 
obj = A(3)
num_str = [9,8,7,1,21]
for n in num_str:
    print("输入值:",n)
    result = obj.process_string(n)
    print(result)  # 示例返回:c
    print("----------------------------")
obj.process_string(-10# 示例返回:' '
def a(a_str):
    index_str = "abcdefghijklmnopqrstuvwxyz"
    index_list = [21, 4, 24, 25, 20, 5, 15, 9, 17, 6, 13, 3, 18, 12, 10, 19, 0, 22, 2, 11, 23, 1, 8, 7, 14, 16]
    index = 0
    i = 0
    for a in index_str:
        if a == a_str:
            index = i
            break
        i = i + 1
    return_num = index_list[index]
    return return_num
 
 
def b(b_num, index_list, index_str):
    print(index_list,index_str)
    print(index_list[b_num-1])
    print(index_str[index_list[b_num]])
    index_b_str = index_str[index_list[b_num-1]]
    return index_b_str
 
 
a_strs = "hwxva"
a_num_list = []
for a_s in a_strs:
    a_num = a(a_s)
    a_num_list.append(a_num)
print(a_num_list)  # [9, 8, 7, 1, 21]
 
index_str = "abcdefghijklmnopqrstuvwxyz"
index_list = [23, 7, 22, 1, 16, 6, 9, 21, 0, 15, 5, 10, 18, 2, 24, 4, 11, 3, 14, 19, 12, 20, 13, 8, 25, 17]
i = 0
input_str = []
for b_n in a_num_list:
    index_list_new = []
    for value in index_list[i:]:
        index_list_new.append(value)
    for value in index_list[:i]:
        index_list_new.append(value)
 
    input_str.append(b(b_n, index_list_new, index_str))
    index_str += index_str[0]
    index_str = index_str[1:27]
    i = i + 1
print(input_str)
def a(a_str):
    index_str = "abcdefghijklmnopqrstuvwxyz"
    index_list = [21, 4, 24, 25, 20, 5, 15, 9, 17, 6, 13, 3, 18, 12, 10, 19, 0, 22, 2, 11, 23, 1, 8, 7, 14, 16]
    index = 0
    i = 0
    for a in index_str:
        if a == a_str:
            index = i
            break
        i = i + 1
    return_num = index_list[index]
    return return_num
 
 
def b(b_num, index_list, index_str):
    print(index_list,index_str)
    print(index_list[b_num-1])
    print(index_str[index_list[b_num]])
    index_b_str = index_str[index_list[b_num-1]]
    return index_b_str
 
 
a_strs = "hwxva"
a_num_list = []
for a_s in a_strs:
    a_num = a(a_s)
    a_num_list.append(a_num)
print(a_num_list)  # [9, 8, 7, 1, 21]
 

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 4
支持
分享
最新回复 (4)
雪    币: 3004
活跃值: (30866)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2023-12-28 09:13
1
雪    币: 10
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
感谢分享
2023-12-28 10:17
0
雪    币: 2328
活跃值: (10364)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
感谢分享
2023-12-28 17:52
0
雪    币: 498
活跃值: (47971)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
顶一下
2023-12-29 08:25
0
游客
登录 | 注册 方可回帖
返回
//