Contents

攻防世界-mobile(新手篇2)

## 0x00 easyjava

jeb打开,分析关键代码,首先我们知道flag{}内的内容通过v4和v5加密得出的v3,最后为wigwrkaugala,所以逆推出解密的步骤就能得到flag。分析参考:https://www.cnblogs.com/cainiao-chuanqi/p/13565030.html

先分析v4,得到是c的数组左移2位,结果是17 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

再分析v5,得到c的数组左移3位,结果是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

b类的a函数,该函数首先获取传进来的字符在字符串b.b中的索引,然后得到在b类中定义的整形数组中与该索引相等的在数组中的索引,然后调用b类的a()函数,将b类中数组与字符串左移一位,然后返回该数组索引。

a类中的a(int)函数,该函数首先获取与传进来的参数相等的数组中的值的索引,然后获取在字符串中索引为该数组索引的字符,最后返回该字符,当然,其中也调用a()函数,但是该函数要求等于25,所以形同虚设。

所以整理解密的脚本如下:

cipherText = 'wigwrkaugala'

aArray = [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]
aString = 'abcdefghijklmnopqrstuvwxyz'

bArray = [17,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]
bString = 'abcdefghijklmnopqrstuvwxyz'

def changeBArrayandString():
	global bString
	global bArray
	chArray = bArray[0]
	chString = bString[0:1]
	for i in range(len(bArray) - 1):
		bArray[i] = bArray[i + 1]
	bArray[len(bArray) - 1] = chArray
	bString = bString[1:]
	bString += chString

def getBchar(ch):
	v2 = bArray[ch]
	arg = bString[v2]
	changeBArrayandString()
	return arg

def getAint(ch):
	global aString
	global aArray
	v1 = aString.index(ch)
	arg5 = aArray[v1]
	return arg5
    
flag =''
for k in cipherText:
	v0 = getAint(k)
	flag += getBchar(v0)
print('flag{' + flag + '}')

0x01 RememberOther

压缩包解压后,得到一个word文档和apk,文档内容是不懂安卓,所以就只是和安卓扯了扯边,,,Have fun~,点开可以看到需要输入用户名和一个16位的注册码。

jeb查看源代码,我们知道是经过checkSN函数的判断后,输出了一段字符,可能和flag有关,那么我们下一步就是要获取这个字符串,下面有三种方法。

方法1:我们能够在程序里看到输出的字符串是在程序中调用的,那它很可能存在程序的某段代码中,搜索发现,字符串在strings.xml中。

方法2:在分析checkSN函数时,惊奇地发现,在用户名和注册码都不填写的情况下会返回true。

方法3:分析checkSN函数可知,它是将用户名进行md5处理后,取所有的奇数位置的数字组合,组成16位sn再与注册码进行比较。

python脚本如下:

import hashlib
m = hashlib.md5()
m.update(b'123')
x = m.hexdigest()
sn = ''
for i in range(len(x)):
	if i%2 == 0:
		sn += x[i]
print (sn)

总之,最后得到b3241668ecbeb19921fdac5ac1aafa69,解密下md5,得到YOU_KNOW_,结合 word 中的提示,整理得到flag: YOU_KNOW_ANDROID

0x02 Ph0en1x-100

上模拟器,app功能是提交flag验证的。

上jeb分析代码,在主函数得到判断语句,接着往下分析。

encrypt和getFlag是从phcm库中调用的,导出库后,用ida分析。

encrypt函数,分析可知对字符串的每个字符的ascii值减一。

对于getFlag函数,由于该函数没有输入只有输出,所以可以通过APKIDE修改smali源码,在本来显示 Failed的地方,让其执行getFlag方法,将执行结果存入v1寄存器。

反编译后运行,可以得到一串字符串ek`fz@q2^x/t^fn0mF^6/^rb`qanqntfg^E`hq|

将字符串的ascii值移位得到flag

flag = ''
for i in c:
    flag += chr(ord(i) + 1)
print(flag)

0x03 黑客精神

JEB进行反编译,发现在MainActivity点击按钮后就弹出弹框,而后跳转到RegActivity界面去,在该界面点击注册后,调用了so层函数saveSN。

跳转到saveSN函数所在的类MyApp,进一步分析代码。

接着分析libmyjni.so文件,在JNI_OnLoad函数中注册了initSN、saveSN和work函数,代码如下

用IDA分析so文件发现在java层注册的native函数都是动态注册的,发现对应的函数n1n2n3

setValue函数的作用是设置com/gdufs/xman/MyApp类的静态字段m的值,输入的注册码通过一系列的计算后得到的值,initSN函数会判断/sdcard/reg.dat文件的内容是否为"EoPAoY62@ElRD",如果得到的值正确,则输入的注册码即为flag。

输入"EoPAoY62@ElRD",通过模拟器进行查看。

0x04 easy-dex

dex里面包含了所有app代码,利用反编译工具可以获取java源码。理解并修改dex文件,就能更好的apk破解和防破解。

https://box.kancloud.cn/8208f0e93ba1fc2e20ae480e31865dca_636x585.png

dex应该是藏在了so中,先寻找android_main函数,Native Activity的入口函数。qmemcpy函数将加密后的dex文件加载进来了,可以发现加密后的dex文件首地址为0x7004(IDA使用F5后,要使用那一块内存空间地址直接是以&unk地址命名的),长度为0x3ca10。

直接在静态下执行dump脚本

import idaapi

addr = 0x7004
size = 0x3ca10

with open('dump','wb') as f:
    f.write(get_bytes(addr,size))
    
print('[+] dump end')

这里直接用大佬的python解密dex脚本

import zlib

with open('dump','rb') as f:
    data1 = f.read()
    data = list(data1)
    count = 0
    
    while True:
        if count <= 0x59:
            count_tmp = (int)(count / 10)
            if count % 10 == 9:
                size = 0x3ca10
                size_tmp = (int)(size / 10)
                xor = (count_tmp + 1) * size_tmp
                if (size_tmp * count_tmp) < xor:
                    index = size_tmp * count_tmp
                    while size_tmp:
                        data[index] = data[index] ^ count
                        index = index + 1
                        size_tmp = size_tmp - 1
                if count == 89:
                    while xor < size:
                        data[xor] = data[xor] ^ 0x59
                        xor = xor + 1
        else:
            break
        count = count + 1

filebytes = bytes(data)
with open('easy-dex.dex','wb') as f1:
    f1.write(zlib.decompress(filebytes))
print('[+] decrypt end')

jeb分析解压后的dex文件,MainActivity.java有一个按钮监听事件,触发后调用了a.java里面的onClick函数,调用了MainActivity里面的a函数。

编写脚本,求出密文iE3y2hEF1izgbVUfGKWQrUCtgFQFop7iEkbmRwWdwsZ1HdQGcPxRVAkWzV/eDC9N

1
2
3
4
5
6
7
8
import base64

m = [-120, 77, -14, -38, 17, 5, -42, 44, -32, 109, 85, 0x1F, 24, -91, -112, -83, 0x40, -83, -128, 84, 5, -94, -98, -30, 18, 70, -26, 71, 5, -99, -62, -58, 0x75, 29, -44, 6, 0x70, -4, 81, 84, 9, 22, -51, 0x5F, -34, 12, 0x2F, 77]
res = []
for i in m:
    res.append(i & 0xff)
b = bytes(res)
print(base64.b64encode(b))

再根据a函数,得出明文+key = 密文。

在string.xml资源文件中发现字符串I have a male fish and a female fish.

怀疑是TwoFish加密,输入key值和加密文本,得到flag。

0x05 你是谁

点击皇上的图片,听到语音“你是个好人,但是我们不适合。”,白色的圆可以被点击。

在MainActivity中找到注释中存在@Override // com.iflytek.cloud.InitListener,搜索发现来源是科大讯飞的语音集成。在background类中发现编码,20667 25105 26159 36924的中文unicode编码为傻我是逼

推理得出编码前的flag顺序应该是25105 26159 20667 36924