01
初探程序
安装并打开
在安卓模拟器上安装程序并打开,输入任意字符进行测试,点击check后提示Wrong flag
super-jadx-gui
加载getFlag.apk
文件,搜索Wrong flag
,定位到关键点具体分析
-
根据上下文信息,使用
super-jadx-gui
功能将变量进行重命名操作 -
调用
check.check_format
检查flag格式 -
初始化
enc
字节数组 -
在资源文件
layout
中读取key
-
截取
flag
主体部分 -
传入
flag
和key
调用check.enc_-Fz0kQmc
方法 -
调用
check.check_final_-GBYM_sE
验证enc
是否正确
02
检验flag格式
check_format
方法,得知flag
的长度为42位
,且是flag{}
格式03
加密flag内容
分析enc_-Fz0kQmc
方法
分析enc_-Fz0kQmc
方法,功能就是将flag
的每一位都异或一下i
模拟代码
r0 = []
for i in range(36):
r0.append(flag[i] ^ i)
enc = []
for k in range(j):
enc.append(r0[35 - k] ^ key[k%16])
for n in range(0,36):
b = enc[n]
# 前36存放的是高字节
enc[n] = (enc[n] & 0xF0) // 16
# 后36位存放的是低字节
enc[n+36] = b &0x0F
04
验证flag内容
分析函数
check_final_-GBYM_sE
函数,将enc_-Fz0kQmc
方法生成enc
作为被验证序列与正确的序列进行比较得到索引
seq = 'ccccebeebbeafbeeeabefabfaffffafaafaaea4b292he31922g6d54a62hchf2bb9ehagdc'
chars = "abcdefgh13462579"
indexs = []
for i in seq:
indexs.append(chars.index(i))
print(indexs)
结果:
[2, 2, 2, 2, 4, 1, 4, 4, 1, 1, 4, 0, 5, 1, 4, 4, 4, 0, 1, 4, 5, 0, 1, 5, 0, 5, 5, 5, 5, 0, 5, 0, 0, 5, 0, 0, 4, 0, 10, 1, 12, 15, 12, 7, 4, 9, 8, 15, 12, 12, 6, 11, 3, 13, 10, 0, 11, 12, 7, 2, 7, 5, 12, 1, 1, 15, 4, 7, 0, 6, 3, 2]
key
可以在资源文件的layout
中找到
还原内容,得到flag
将2个4 bit
进行合并成1字节,还原正确enc
内容
enc_indexs = [2, 2, 2, 2, 4, 1, 4, 4, 1, 1, 4, 0, 5, 1, 4, 4, 4, 0, 1, 4, 5, 0, 1, 5, 0, 5, 5, 5, 5, 0, 5, 0, 0, 5, 0, 0, 4, 0, 10, 1, 12, 15, 12, 7, 4, 9, 8, 15, 12, 12, 6, 11, 3, 13, 10, 0, 11, 12, 7, 2, 7, 5, 12, 1, 1, 15, 4, 7, 0, 6, 3, 2]
# 2.还原enc的内容
for n in range(0,36):
enc_indexs[n] = enc_indexs[n] * 16 | enc_indexs[36+n]
print(enc_indexs[:36])
# 结果 [36, 32, 42, 33, 76, 31, 76, 71, 20, 25, 72, 15, 92, 28, 70, 75, 67, 13, 26, 64, 91, 12, 23, 82, 7, 85, 92, 81, 81, 15, 84, 7, 0, 86, 3, 2]
enc
与密文进行异或获得加密一次的flag
,再遍历0~35将结果依次异或运算得到明文flag
enc_indexs = enc_indexs[:36]
# 3.获得异或一次的flag
key = b"123456789getflag"
user_in = [0]*36
for k in range(0,36):
user_in[ 35 - k] = enc_indexs[k] ^ key[ k % 16 ]
# 4.得到明文flag
flag = "".join([ chr(user_in[j] ^ j) for j in range(0,36) ])
print("flag{"+flag+"}")
# 结果
flag{61f2d0e0-085f-4ad8-a82f-c4d6cf7f5806}
05
完整脚本
python3
编写解密脚本# 1.获得正确的enc索引
seq = 'ccccebeebbeafbeeeabefabfaffffafaafaaea4b292he31922g6d54a62hchf2bb9ehagdc'
chars = "abcdefgh13462579"
enc_indexs = []
for i in seq:
enc_indexs.append(chars.index(i))
# 2.还原enc的内容
for n in range(0,36):
enc_indexs[n] = enc_indexs[n] * 16 | enc_indexs[36+n]
# 3.获得异或一次的flag
key = b"123456789getflag"
user_in = [0]*36
for k in range(0,36):
user_in[ 35 - k] = enc_indexs[k] ^ key[ k % 16 ]
# 4.得到明文flag
flag = "".join([ chr(user_in[j] ^ j) for j in range(0,36) ])
# 5.输出flag
print("flag{"+flag+"}")
kotlin
编写解密脚本import java.util.ArrayList
import kotlin.experimental.xor
fun main(args: Array<String>) {
// 1.获取正确的enc索引
var enc = ArrayList<Int>();
var seq = "ccccebeebbeafbeeeabefabfaffffafaafaaea4b292he31922g6d54a62hchf2bb9ehagdc";
for (i in seq) {
enc.add("abcdefgh13462579".indexOf(i));
}
// 2.还原enc原来的内容
for (j in 0..35) {
enc[j] = enc.get(j) shl 4 or enc.get(j + 36);
}
// 3.获取明文flag
// 1)将key转成byte数组
var keys = "123456789getflag".toByteArray();
var user_in = ByteArray(36);
for (n in 0..35) {
// 2)将enc与keys异或后的结果与35-n进行异或得到原用户输入的值
user_in[35 - n] = enc[n].toByte() xor keys[n % 16] xor (35 - n).toByte();
}
//3)flag字节数组转成字符串
var flag = user_in.map { it.toChar() }.joinToString("");
println("flag{" + flag + "}");
}
原文始发于微信公众号(归零安全):领航杯-GetFlag
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论