领航杯-GetFlag

admin 2022年4月7日23:12:22评论173 views字数 3176阅读10分35秒阅读模式

领航杯-GetFlag


本文由Scynull编译,校对,转载请注明。
 免责申明


        归零安全的技术文章仅供参考,此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等(包括但不限于)进行检测或维护参考,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失,均由使用者本人负责。
        本文所提供的工具仅用于学习,禁止用于其他,请在24小时内删除工具文件!!!


01


初探程序



01

安装并打开


         在安卓模拟器上安装程序并打开,输入任意字符进行测试,点击check后提示Wrong flag

领航杯-GetFlag



使用super-jadx-gui加载getFlag.apk文件,搜索Wrong flag,定位到关键点

领航杯-GetFlag


02

具体分析



  1. 根据上下文信息,使用super-jadx-gui功能将变量进行重命名操作

  2. 调用check.check_format检查flag格式

  3. 初始化enc字节数组

  4. 在资源文件layout中读取key

  5. 截取flag主体部分

  6. 传入flagkey调用check.enc_-Fz0kQmc方法

  7. 调用check.check_final_-GBYM_sE验证enc是否正确

领航杯-GetFlag



02


检验flag格式



分析check_format方法,得知flag的长度为42位,且是flag{}格式

领航杯-GetFlag




03


加密flag内容



01

分析enc_-Fz0kQmc方法


 分析enc_-Fz0kQmc方法,功能就是将flag的每一位都异或一下i

领航杯-GetFlag


领航杯-GetFlag


领航杯-GetFlag



02

模拟代码




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内容



01

分析函数


分析check_final_-GBYM_sE函数,将enc_-Fz0kQmc方法生成enc作为被验证序列与正确的序列进行比较

领航杯-GetFlag


02

得到索引



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中找到


领航杯-GetFlag



03

还原容,得到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 + "}");

}



文件获取,后台回复CTF-220406

领航杯-GetFlag

领航杯-GetFlag


原文始发于微信公众号(归零安全):领航杯-GetFlag

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年4月7日23:12:22
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   领航杯-GetFlaghttps://cn-sec.com/archives/881760.html

发表评论

匿名网友 填写信息