CTF逆向-[De1CTF2019]Re_Sign-简单脱壳和base64换表编码的深度算法跟踪

CTF逆向-[De1CTF2019]Re_Sign-简单脱壳和base64换表编码的深度算法跟踪

来源:https://buuoj.cn/

内容

附件: 链接:https://pan.baidu.com/s/1BXcr8EQfqs8fLHh2V874kg?pwd=acal 提取码:acal

答案:de1ctf{E_L4nguag3_1s_K3KeK3_N4Ji4}

总体思路

发现upx老版本的壳,使用老版本upx去除

发现输入的值会被编码, 找到编码的地方并猜测其编码方式

发现是base64编码,发现编码的码表位置

发现验证函数是通过将编码后的值解码以后取其序号,并与一串内存比较

反向写出exp

详细步骤

  • 拿到题目以后发现是upx的压缩壳,且版本较低,无法通过3.x版本的upx工具脱壳,所以使用老旧的0.x版本的upx对其脱壳,得到源码。

    • CTF逆向-[De1CTF2019]Re_Sign-简单脱壳和base64换表编码的深度算法跟踪_第1张图片
  • i>63;break的位置通常是base64表初始化逻辑,看出在这里*lpa初始化了一个表

    • CTF逆向-[De1CTF2019]Re_Sign-简单脱壳和base64换表编码的深度算法跟踪_第2张图片
  • 让其继续运行一段直到base64的片段完成,通过返回结果查看,发现此处已经计算出了结果。

    • CTF逆向-[De1CTF2019]Re_Sign-简单脱壳和base64换表编码的深度算法跟踪_第3张图片
  • 根据v_b64_result倒查,发现是最开始的时候根据输入的值计算strlen以后得到的一个缓存,代入最开始初始化的表计算,发现果然是换表的base64,表为0123456789QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm+/

    • CTF逆向-[De1CTF2019]Re_Sign-简单脱壳和base64换表编码的深度算法跟踪_第4张图片
    • CTF逆向-[De1CTF2019]Re_Sign-简单脱壳和base64换表编码的深度算法跟踪_第5张图片
  • 观察到在f_check之后得到最后结果输出Success

    • CTF逆向-[De1CTF2019]Re_Sign-简单脱壳和base64换表编码的深度算法跟踪_第6张图片
  • 查看f_check的返回值位置,发现是判断值需要等于49

    • CTF逆向-[De1CTF2019]Re_Sign-简单脱壳和base64换表编码的深度算法跟踪_第7张图片
  • CTF逆向-[De1CTF2019]Re_Sign-简单脱壳和base64换表编码的深度算法跟踪_第8张图片

    • CTF逆向-[De1CTF2019]Re_Sign-简单脱壳和base64换表编码的深度算法跟踪_第9张图片
    • CTF逆向-[De1CTF2019]Re_Sign-简单脱壳和base64换表编码的深度算法跟踪_第10张图片
  • 继续向下找到跳出循环的地方,发现此处是逐位比较是否相同,内部是将base64过后的值逐位使用正常表的base64编码回原来的值


    • CTF逆向-[De1CTF2019]Re_Sign-简单脱壳和base64换表编码的深度算法跟踪_第11张图片
  • 故此处的f_decode其实是将base64decode以后取其在base64表中的序号 table[index]。

  • 整理流程为input->base64(input,new_table)->逐位base64decode(x).index 与 v_arr比较得到exp

    • 其中v_arr的值为080000003B00000001000000200000000700000034000000090000001F000000180000002400000013000000030000001000000038000000090000001B0000000800000034000000130000000200000008000000220000001200000003000000050000000600000012000000030000000F00000022000000120000001700000008000000010000002900000022000000060000002400000032000000240000000F0000001F0000002B0000002400000003000000150000004100000041000000ABABABABABABABAB0000000000000000B0F81AFE5FD30000C0005C00E84A5D00
  • CTF逆向-[De1CTF2019]Re_Sign-简单脱壳和base64换表编码的深度算法跟踪_第12张图片

    • exp

      • import base64
        import struct
        raw_table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
        new_table = '0123456789QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm+/='
        dictionary_decode = str.maketrans(new_table, raw_table)  # 创建字符映射关系 用于base64decode
        dictionary_encode = dict(zip(dictionary_decode.values(),dictionary_decode.keys())) # 创建一个与上面反向的映射关系用于base64encode
        
        result = '123123' # 123123 原始的数据
        
        result_b64 = base64.b64encode(result.encode()).decode() # MTIzMTIzMTIz base64encode(v) 正常的123123进行base64以后的值
        new_result_b64 = result_b64.translate(dictionary_encode) # EP8hEP8hEP8h base64encode(v,table) 换表以后base64以后的值
        new_data = new_result_b64.translate(dictionary_decode)  # MTIzMTIzMTIz base64encode(v) 变回正常的值
        
        
        v_arr = '080000003B00000001000000200000000700000034000000090000001F000000180000002400000013000000030000001000000038000000090000001B0000000800000034000000130000000200000008000000220000001200000003000000050000000600000012000000030000000F00000022000000120000001700000008000000010000002900000022000000060000002400000032000000240000000F0000001F0000002B0000002400000003000000150000004100000041000000ABABABABABABABAB0000000000000000B0F81AFE5FD30000C0005C00E84A5D00'
        v_arr = bytearray.fromhex(v_arr)
        sow = 4  # size_of_word
        v_arr = [v_arr[sow * x:sow * (x+1)] for x in range(int(len(v_arr)/sow))]
        v_arr = [struct.unpack(', x)[0] for x in v_arr]  # 按int类型小端转换
        v_arr = v_arr[0:48]
        
        v_base64_str = [raw_table[x-1] for x in v_arr]
        v_base64_str = ''.join(v_base64_str)
        v_base64_str = v_base64_str.translate(dictionary_decode)
        v_result = base64.b64decode(v_base64_str)
        print(v_result) # de1ctf{E_L4nguag3_1s_K3KeK3_N4Ji4}
        
  • 最终答案为 de1ctf{E_L4nguag3_1s_K3KeK3_N4Ji4}

其他文档

  • Python反汇编方法 Python的pyc字节码反编译反汇编相关知识

  • CTF逆向-常用的逆向工具 提取码:pnbt

  • B站教程中国某省队CTF集训(逆向工程部分)

    • 中国某省队CTF集训(逆向工程部分)(已授权)(一)
    • 基础加密方式例如 XXTEABase64换表
    • Python库 Z3 方程式、不定式等的 约束求解
    • 基础的假跳转花指令(脏字节)
    • 非自然程序流程
      • 扁平化程序控制流
      • OLLVM程序流程(虚拟机壳) 很难一般不考
      • ida里面按X键跟踪,寻找所有Tyw的引用(即类型是写入的),通常就是关键位置
    • 中国某省队CTF集训(逆向工程部分)(已授权)(二)
    • ollydb动调去壳,upx为例子
    • python的逆向和自定义虚拟指令
      • 使用pycdc 提取码:dorr 解密python编译的exe或者pyc
      • 逐条去解析用py字典手动实现的指令调用
      • C++编译的程序的逆向
    • 中国某省队CTF集训(逆向工程部分)(已授权)(三)
      • 简单模运算加密
      • base58 寻找一下特别大的数,这种数通常是算法的标识,或者ida7.7版本以上自带的find crypt插件ctrl+alt+f
      • 常见的关键位置是有新的内存分配的地方通常是关键地方,或者函数中间突然return的地方也是
      • 迷宫题 注意绘制出来就好
      • 动调题
        • 注意观察会执行的反调试分支,例如出现int 3,需要跳过去
  • 基本知识

    • 大小端序

更多CTF逆向题通用性做法和常用工具下载参考该博文内容:CTF逆向Reverse题的玩法

相关逆向CTF题

  • Python

    • [CTF逆向-羊城杯 2020]Bytecode-WP-Python字节码反编译
  • 远程调试汇编

    • CTF逆向-[watevrCTF 2019]Timeout-WP-远程调试和修改程序当前运行位置RIP
  • 流程控制

    • CTF逆向-Dig the way Interesting Pointer-通过栈溢出方式覆盖变量以达到修改执行流程的目的
  • 逆向思维

    • [CTF逆向-NPUCTF2020]Baby Obfuscation-逆向思维编写脚本以及函数含义的逻辑理解
    • [CTF逆向-MRCTF2020]EasyCpp - C++类型的逆向通用操作方法
    • [CTF逆向-SUCTF2018]babyre-WP-cpp简单迭代并按表输出值的爆破
  • 安卓

    • [CTF逆向-网鼎杯 2020 青龙组]bang-安卓脱壳逆向:frida-dexdump导出得到源码
  • 虚拟机

    • [CTF逆向-GWCTF 2019]babyvm-WP-虚机模拟流程反向编码和z3约束求解器解方程工具的使用
    • [CTF逆向-WMCTF2020]easy_re-WP_虚机-perl加载器截取
  • 反调试和SMC

    • [CTF逆向-SCTF2019]creakme-WP-基于AES加密算法下的保护:反调试及except_handler和SMC
  • 加密

    • [CTF逆向-FlareOn2]very_success-WP_rol循环位移加密
    • [CTF逆向-CISCN2018]2ex-WP_mips-32架构以及base64换表
  • 花指令

    • [CTF逆向-SCTF2019]babyre-WP_简单去花指令和流程识别
  • 流程混淆的扁平化处理

    • [CTF逆向-RoarCTF2019]polyre-WP_控制流扁平化去混淆idcpy去指令

    • CTF逆向-[SUCTF2019]hardcpp-使用优化过的deflat.py处理混淆的控制流并将cpp的lambda解析得到实际处理逻辑

你可能感兴趣的:(CTF-逆向,算法,web安全,安全)