Mas0n
to be reverse engineer🐧
翻车鱼

MarDASCTF RE writeUP

MarDASCTF RE writeUP

一如既往的前言

DAS的比赛我只能说,力不从心了。令我惊讶的是一道定位为简单题的”喝茶“题我也没做出来,这就是所谓的”春回大地“难度…

显而易见,真正意义上我只做出了一题…本来不打算写这个博客的,因为C#的题直接粘贴运行就好了= =后来用Python尝试复现一下,写下来算是学习一下Python下的无符号参数的处理吧

Enjoyit-1

C#程序,直接放ILSpy就能出源码

敏感的发现那段Base64字符串,去看c方法,CTF经典的换码表

https://cdn.shi1011.cn/2021/03/d3fafd23973ed8229ab437894b261bd8.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5
敏感的发现Base64字符串
https://cdn.shi1011.cn/2021/03/69afb7e26e6211a52a4f6280bb0c5a74.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5
换了码表的Base64

替换码表后解密就能得到text

方法一(最快)

从主处理逻辑里扣代码出来,运行完事

static void bbbb(ref uint[] A_0, byte[] A_1)
        {
            uint num = 2654435464u;
            uint num2 = A_0[0];
            uint num3 = A_0[1];
            uint num4 = 0u;
            for (int i = 0; i < 32; i++)
            {
                num2 += (((num3 << 4) ^ (num3 >> 5)) + num3) ^ (num4 + A_1[num4 & 3]);
                num4 += num;
                num3 += (((num2 << 4) ^ (num2 >> 5)) + num2) ^ (num4 + A_1[(num4 >> 11) & 3]);
                Console.Write(num2);
                Console.Write(" ");
                Console.Write(num4);
                Console.Write(" ");
                Console.WriteLine(num3);
            }
            A_0[0] = num2;
            A_0[1] = num3;
        }
        static void Main(string[] args) 
        {
            string str = "";
            string text = "";
            byte[] array = new byte[26];
            _ = new byte[26];
            byte[] array2 = new byte[8];
            byte[] array3 = new byte[32] {2, 5, 4, 13, 3, 84, 11, 4, 87, 3, 86, 3, 80, 7, 83, 3, 0, 4, 83, 94, 7, 84, 4, 0, 1, 83, 3, 84, 6, 83, 5, 80 };
            uint[] A_ = new uint[2] { 288u, 369u };
            text = "combustible_oolong_tea_plz";
            array = Encoding.Default.GetBytes(text);
            bbbb(ref A_, array);
            Console.WriteLine("Here is your tea, and flag!");
            str += A_[0].ToString("x2");
            str += A_[1].ToString("x2");
            array2 = Encoding.Default.GetBytes(str);
            Console.Write("flag{");
            for (int j = 0; j < 32; j++){
                array3[j] ^= array2[j % array2.Length];
            }
            Console.Write(Encoding.Default.GetString(array3));
            Console.Write("}");
            Console.ReadKey();
        }

方法二(Python)

个人认为打比赛的时候用Python去复现这种C#能直接跑出来的题,有点浪费时间

因为Python特性,无符号类型的参数在Python中无法通过定义的方式声明

但好在Python拥有ctypes模块强制指定为无符号参数

import ctypes


def b(A_0, A_1):
    num = ctypes.c_uint32(2654435464)
    num2 = A_0[0]
    num3 = A_0[1]
    num4 = ctypes.c_uint32(0)
    for i in range(32):
        num2.value += (((num3.value << 4) ^ (num3.value >> 5)) + num3.value) ^ (num4.value + A_1[num4.value & 3].value)
        num4.value += num.value
        num3.value += (((num2.value << 4) ^ (num2.value >> 5)) + num2.value) ^ (
                num4.value + A_1[(num4.value >> 11) & 3].value)
    A_0[0] = num2
    A_0[1] = num3


strs = ""
array = []
for i in "combustible_oolong_tea_plz":
    array.append(ctypes.c_ubyte(ord(i)))

A_ = [ctypes.c_uint32(288), ctypes.c_uint32(369)]
b(A_, array)
strs += hex(A_[0].value)[2:].zfill(2)
strs += hex(A_[1].value)[2:].zfill(2)

array2 = strs
array3 = [2, 5, 4, 13, 3, 84, 11, 4, 87, 3, 86, 3, 80, 7, 83, 3, 0, 4, 83, 94, 7, 84, 4, 0, 1, 83, 3, 84, 6, 83, 5, 80]

for j in range(32):
    array3[j] = chr(array3[j] ^ ord(array2[j % len(array2)]))
print("".join(array3))

drinkSomeTea

喝茶吗?(苦涩)

昨天赛后,Buu群的一位师傅发了一份此题的WP,拜读了一下,师傅是直接汇编patch掉了,奈何我刚学的汇编没这么强的功底。周日正好有空,就打算用Python还原下这个特殊的TEA算法

然而想法是简单的,过程是曲折的,Python缺少了算术位移(也可能是我Python了解并不透彻),只好自己写了一个函数模拟算术移位

先上一下那位师傅的WP叭

Python的复现之路

正如师傅们所说的,对于此题,直接使用C去还原算法是较快的解决方法,但是,我还是选择使用Python复现一下这个算法,也算是我对于汇编知识以及Python特性的一个练习叭

如有不足之处,欢迎师傅们指正~

核心的处理过程当然是TEA算法,不过此题的TEA算法使用了算术移位,并且是带符号

这对于Python来说并不是一件顺其自然的事情……..不说了,上exp了(废话太多)

import struct


def sar(DWORD=0, num=0):
    """
    python没有算数右移,笨办法模拟了一下算数右移

    :param DWORD: 四字节 整数
    :param num:右移量
    :return:移位后整数
    """
    binWORD = bin(DWORD)  # 四字节转二进制
    signbit = binWORD[2:3]  # 取符号位
    DWORD = DWORD >> num  # 逻辑右移
    if signbit == 0 or len(binWORD[2:]) != 32:  # 高位为 0 或 不足32位
        return DWORD  # 直接返回右移结果
    else:
        bit = ["1"] * num  # 高位 补num位 1
        DWORD = "0b" + "".join(bit) + bin(DWORD).replace('0b', '').zfill(8)  # 组合成二进制形式
        return int(DWORD, 2)  # 转整数


def teaEnc(DwordArray, keys):
    delta = 0
    v1 = DwordArray[1]
    v0 = DwordArray[0]
    for i in range(32):
        delta += 0x9E3779B9
        v0 += (keys[1] + sar(v1, 5) & 0xffffffff) ^ ((delta + v1) & 0xffffffff) ^ (keys[0] + (16 * v1) & 0xffffffff)
        v0 = v0 & 0xffffffff
        v1 += (keys[3] + sar(v0, 5) & 0xffffffff) ^ ((delta + v0) & 0xffffffff) ^ (keys[2] + (16 * v0) & 0xffffffff)
        v1 = v1 & 0xffffffff
    DwordArray[1] = v1
    DwordArray[0] = v0
    result = DwordArray
    return result


def teaDec(DwordArray, keys):
    delta = 0x9E3779B9 << 5
    v1 = DwordArray[1]
    v0 = DwordArray[0]
    for i in range(32):
        v1 -= (keys[3] + sar(v0, 5) & 0xffffffff) ^ ((delta + v0) & 0xffffffff) ^ (
                keys[2] + (16 * v0) & 0xffffffff)
        v1 = v1 & 0xffffffff
        v0 -= (keys[1] + sar(v1, 5) & 0xffffffff) ^ ((delta + v1) & 0xffffffff) ^ (
                keys[0] + (16 * v1) & 0xffffffff)
        v0 = v0 & 0xffffffff
        delta -= 0x9E3779B9
    DwordArray[1] = v1
    DwordArray[0] = v0
    result = DwordArray
    return result


key = [0x67616C66, 0x6B61667B, 0x6C665F65, 0x7D216761]

with open("tea.png.out", "rb") as f:
    file = f.read()
png = b""
for i in range(len(file) // 8):
    arr = list(struct.unpack("<LL", file[i*8:i*8 + 8]))  # 小端,转为 DWORD
    dec = teaDec(DwordArray=arr, keys=key)
    png += struct.pack("<LL", dec[0], dec[1])  # 小端,转为字节
with open("tea.png", "wb") as f:
    f.write(png)

拿到的是一张图片,真就爽歪歪

https://cdn.shi1011.cn/2021/03/d210e52d5f81f2fa4c378b5edd519f02.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

感想

我还是老老实实用C还原吧(逃)

本文链接:https://blog.shi1011.cn/ctf/1183
本文采用 CC BY-NC-SA 4.0 Unported 协议进行许可

Mas0n

文章作者

推荐文章

回复 arcovegle 取消回复

textsms
account_circle
email

翻车鱼

MarDASCTF RE writeUP
一如既往的前言 DAS的比赛我只能说,力不从心了。令我惊讶的是一道定位为简单题的”喝茶“题我也没做出来,这就是所谓的”春回大地“难度... 显而易见,真正意义上我只做出了一题...本…
扫描二维码继续阅读
2021-03-27