REVERSE-COMPETITION-CISCN-2024

asm_re

手撕汇编
re
抠出来数据直接逆

import struct
arr = [215, 31, 0, 0, 183, 33, 0, 0, 71, 30, 0, 0, 39, 32, 0, 0, 231, 38, 0, 0, 215, 16, 0, 0, 39, 17, 0, 0, 7, 32, 0, 0, 199, 17, 0, 0, 71, 30, 0, 0, 23, 16, 0, 0, 23, 16, 0, 0, 247, 17, 0, 0,
       7, 32, 0, 0, 55, 16, 0, 0, 7, 17, 0, 0, 23, 31, 0, 0, 215, 16, 0, 0, 23, 16, 0, 0, 23, 16, 0, 0, 103, 31, 0, 0, 23, 16, 0, 0, 199, 17, 0, 0, 199, 17, 0, 0, 23, 16, 0, 0, 215, 31, 0, 0, 23, 31, 0, 0, 7, 17, 0, 0, 71, 15, 0, 0, 39, 17, 0, 0, 55, 16, 0, 0, 71, 30, 0, 0, 55, 16, 0, 0, 215, 31, 0, 0, 7, 17, 0, 0, 215, 31, 0, 0, 7, 17, 0, 0, 135, 39, 0, 0]
arr = bytes(arr)
enc = []
for i in range(0, len(arr), 4):
    enc.append(struct.unpack("<I", arr[i:i+4])[0])
for i in range(len(enc)):
    enc[i] -= 0x1E
    enc[i] ^= 0x4D
    enc[i] -= 0x14
    enc[i] //= 0x50
print(bytes(enc))
# flag{67e9a228e45b622c2992fb5174a4f5f5}

androidso_re

调试拿到key和iv,分别是A8UdWaeq和Wf3DLups,解密DES
re

rust_baby

调试
循环,8字节一组进入enc1,结果依次异或0x33
re
enc1就是输入的一组8字节与已知的另外两个8字节做变换,可z3求解
re
下面还有一次异或
re
最后就是标准base64,与已知密文比较,解密得到flag

import base64
import claripy
enc = "igdydo19TVE13ogW1AT5DgjPzHwPDQle1X7kS8TzHK8S5KCu9mnJ0uCnAQ4aV3CSYUl6QycpibWSLmqm2y/GqW6PNJBZ/C2RZuu+DfQFCxvLGHT5goG8BNl1ji2XB3x9GMg9T8Clatc="
enc = list(base64.b64decode(enc))
xor_box = [220, 95, 32, 34, 194, 121, 25, 86, 53, 218, 139, 71, 211, 25, 252, 85, 20, 205, 210, 123, 88, 89, 9, 66, 222, 44, 180, 72, 217, 242, 27, 169, 64, 225, 166, 251, 255, 56, 193, 213, 226, 232, 119, 120, 111, 34, 4, 230, 22, 62, 12,
           53, 82, 92, 253, 193, 229, 89, 28, 208, 174, 90, 178, 221, 25, 248, 66, 230, 44, 137, 89, 229, 17, 156, 200, 123, 129, 112, 127, 111, 188, 111, 2, 143, 247, 244, 200, 112, 174, 2, 248, 91, 226, 114, 8, 9, 111, 191, 75, 57, 181, 208, 30, 163]
for i in range(len(enc)):
    enc[i] ^= xor_box[i]
enc1_a2_arr = [0xe71675b493928150, 0x37c65d4c7ba24118, 0x2f6e0584c3b26920, 0xc74625ecf3321978, 0x9ffe15f4fb724940, 0x27c69d1453f2e1b0,
               0xe71675b493928150, 0x37c65d4c7ba24118, 0x2f6e0584c3b26920, 0xc74625ecf3321978, 0x9ffe15f4fb724940, 0x27c69d1453f2e1b0, 0xe71675b493928150]
enc1_a3_arr = [0x1, 0x1, 0x4, 0x5, 0x1, 0x4, 0x1, 0x9, 0x1, 0x9, 0x8, 0x1, 0x0]
def rev(res, a2, a3):
    a1_arr = [claripy.BVS(f"inp_{i}", 8) for i in range(8)]
    a2_arr = [int(i) for i in list(bytes.fromhex(hex(a2)[2:].zfill(16)))[::-1]]
    a3_arr = [int(i) for i in list(bytes.fromhex(hex(a3)[2:].zfill(16)))[::-1]]
    ret_arr = []
    for i in range(4):
        v9 = ((a2_arr[i*2] ^ a3_arr[i*2]) |
              (a2_arr[i*2+1] ^ a3_arr[i*2+1])) & 1
        ret_arr.append(i-v9+a1_arr[a2_arr[i*2] & 7])
        ret_arr.append(i-v9+a1_arr[a2_arr[i*2+1] & 7])
    for i in range(len(ret_arr)):
        ret_arr[i] ^= 0x33
    s = claripy.Solver()
    for i in range(len(ret_arr)):
        s.add(ret_arr[i] == res[i])
    for i in s.batch_eval(a1_arr, 1):
        print("".join(chr(c) for c in i), end="")
for i in range(8):
    rev(enc[i*8:(i+1)*8], enc1_a2_arr[i], enc1_a3_arr[i])
# flag{6e2480b3-4f02-4cf1-9bc0-123b75f9a922}

whereThel1b

whereThel1b.whereistheflag(flag)是标准base64和随机数加法,但没用
ret = whereThel1b.trytry(flag)
PyObject *__fastcall _pyx_pw_11whereThel1b_1trytry设置随机数种子
然后调用了PyObject *__fastcall _pyx_pw_11whereThel1b_5whereistheflag1
re
re
whereistheflag1
先是标准base64
re
然后和随机数异或
re
抠出随机数解密即可

import base64
enc = [108, 117, 72, 80, 64, 49, 99, 19, 69, 115, 94, 93, 94, 115, 71, 95, 84, 89, 56, 101, 70, 2, 84, 75, 127, 68, 103, 85,
       105, 113, 80, 103, 95, 67, 81, 7, 113, 70, 47, 73, 92, 124, 93, 120, 104, 108, 106, 17, 80, 102, 101, 75, 93, 68, 121, 26]
box = list(bytes.fromhex(
    "361830381a0210201f193235131e16250d200812083006273310222d33260913062e04362b151e2306161b1427280d231e1c372110033323"))
for i in range(len(enc)):
    enc[i] ^= box[i]
print(base64.b64decode(bytes(enc)))
# flag{7f9a2d3c-07de-11ef-be5e-cf1e88674c0b}

GoReverse

读取./flag文件
异或
re
xxtea和sm4
re
xxtea魔改了delta和MX
re
re
对应源码即为
re
sm4并不是对上一步的xxtea密文加密
而是先随机生成16字节(叫做randbytes1)
然后把randbytes1最后1字节加1得到randbytes2,再加1得到randbytes3
sm4加密的密文即为randbytes1+ randbytes2+ randbytes3
得到的密文与上一步的xxtea密文异或
(实际上就是SM4 CTR模式,CTR就是randbytes1,之前没见过,虽然有个NewCTR,但是当时没反应过来
re
拼接randbytes1和上一步异或的结果,进行标准的aes cbc和base32
re
解密过程如下
先解base32和标准aes cbc
re
前16字节即为randbytes1

enc = list(bytes.fromhex(
    "60e9247906011b712636b8e6042d88ad178394df594155adac50312a18b56490bae5dea3b7a397ae8bde39bf08cfcc1f56b4eda573aadf08e03fc9ff04040404"))
sm4_plain = enc[:len(enc)//4]
print(bytes(sm4_plain).hex())
# 60e9247906011b712636b8e6042d88ad

手动sm4加密randbytes1+ randbytes2+ randbytes3
re
将sm4密文(去掉padding部分)与上面enc除前16字节的部分异或即可得到xxtea密文

import struct
enc = list(bytes.fromhex(
    "60e9247906011b712636b8e6042d88ad178394df594155adac50312a18b56490bae5dea3b7a397ae8bde39bf08cfcc1f56b4eda573aadf08e03fc9ff04040404"))
sm4_plain = enc[:len(enc)//4]
print(bytes(sm4_plain).hex())
# 60e9247906011b712636b8e6042d88ad
sm4_plain_enc = list(bytes.fromhex(
    "fe5034b71989721b85ff575d7918b68814d8b9ff323905b57d6662e23095b54156e733c2534ecb3cebae0cabb24f51f7"))
inp_enc = enc[len(enc)//4:]
for i in range(len(inp_enc)):
    inp_enc[i] ^= sm4_plain_enc[i]
inp_enc = bytes(inp_enc)
for i in range(0, len(inp_enc), 4):
    print(hex(struct.unpack("<I", inp_enc[i:i+4])[0]), end=",")
# 0x68a0d3e9,0xb627c840,0x7766af29,0x18d2ad61,0x5c673dae,0x1b929a85,0x5d5bb8f6,0x5e795a38,0x67de5300,0x3414e420,0x54c5910b,0xf3554bb6

解密xxtea,需要注意的是要把上一步结果中最后的0xf3554bb6去掉,对应的是04040404(padding

#include <stdio.h>
#include <stdint.h>

#define DELTA 0x7FAB4CAD
#define MX (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y)) + ((key[(p & 3) ^ e] ^ z)))

void btea(uint32_t *v, int n, uint32_t const key[4])
{
    uint32_t y, z, sum;
    unsigned p, rounds, e;
    //加密
    if (n > 1)
    {
        rounds = 6 + 52 / n;
        sum = 0;
        z = v[n - 1];
        do
        {
            sum += DELTA;
            e = (sum >> 2) & 3;
            for (p = 0; p < n - 1; p++)
            {
                y = v[p + 1];
                z = v[p] += MX;
            }
            y = v[0];
            z = v[n - 1] += MX;
        } while (--rounds);
    }
    //解密
    else if (n < -1)
    {
        n = -n;
        rounds = 6 + 52 / n;
        sum = rounds * DELTA;
        y = v[0];
        do
        {
            e = (sum >> 2) & 3;
            for (p = n - 1; p > 0; p--)
            {
                z = v[p - 1];
                y = v[p] -= MX;
            }
            z = v[n - 1];
            y = v[0] -= MX;
            sum -= DELTA;
        } while (--rounds);
    }
    printf("sum==0x%x\n", sum);
}

//打印数据 hex_or_chr: 1-hex 0-chr
void dump_data(uint32_t *v, int n, bool hex_or_chr)
{
    if (hex_or_chr)
    {
        for (int i = 0; i < n; i++)
        {
            printf("0x%x,", v[i]);
        }
    }
    else
    {
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < sizeof(uint32_t) / sizeof(uint8_t); j++)
            {
                printf("0x%x,", (v[i] >> (j * 8)) & 0xFF);
            }
        }
    }
    printf("\n");
    return;
}

int main()
{
    // v为要加解密的数据
    uint32_t v[] = {0x68a0d3e9, 0xb627c840, 0x7766af29, 0x18d2ad61, 0x5c673dae, 0x1b929a85, 0x5d5bb8f6, 0x5e795a38, 0x67de5300, 0x3414e420, 0x54c5910b};
    // k为加解密密钥,4个32位无符号整数,密钥长度为128位
    uint32_t k[4] = {0x385e7342, 0x345a772a, 0x6f38756c, 0x6b402652};

    int n = sizeof(v) / sizeof(uint32_t);
    /*
    printf("加密前明文数据:");
    dump_data(v, n, 1);

    btea(v, n, k);
    */
    printf("加密后密文数据:");
    dump_data(v, n, 1);

    btea(v, -n, k);

    printf("解密后明文数据:");
    dump_data(v, n, 1);

    printf("解密后明文字符:");
    dump_data(v, n, 0);

    return 0;
}
// 0x22,0x5b,0x23,0x2d,0x37,0x40,0x2e,0x5f,0xc,0x77,0x53,0x45,0x57,0x49,0x34,0x71,0x5b,0x56,0x1e,0x7d,0x77,0x59,0x7a,0x5c,0x6c,0x63,0x55,0x45,0x73,0x35,0x9,0xe,0x27,0x53,0x0,0x5e,0x59,0x1e,0x0,0x72,0x4,0xc,0x0,0x0

最后就是与一个已知的box异或即可得到flag

enc = [0x22, 0x5b, 0x23, 0x2d, 0x37, 0x40, 0x2e, 0x5f, 0xc, 0x77, 0x53, 0x45, 0x57, 0x49, 0x34, 0x71, 0x5b, 0x56, 0x1e, 0x7d, 0x77,
       0x59, 0x7a, 0x5c, 0x6c, 0x63, 0x55, 0x45, 0x73, 0x35, 0x9, 0xe, 0x27, 0x53, 0x0, 0x5e, 0x59, 0x1e, 0x0, 0x72, 0x4, 0xc, 0x0, 0x0]
box = [0x44, 0x37, 0x42, 0x4A, 0x4C, 0x73, 0x4F, 0x6B, 0x39, 0x40,
       0x66, 0x26, 0x31, 0x64, 0x57, 0x49, 0x6E, 0x35, 0x33, 0x49,
       0x44, 0x6C, 0x4A, 0x71, 0x55, 0x53, 0x36, 0x24, 0x5E, 0x57,
       0x68, 0x6B, 0x41, 0x6B, 0x32, 0x6B, 0x6B, 0x2A, 0x32, 0x47,
       0x61, 0x71, 0x6D, 0x4C, 0x77, 0x69, 0x4C, 0x58, 0x5E, 0x62,
       0x47, 0x47, 0x45, 0x24, 0x26, 0x64, 0x6D, 0x71, 0x52, 0x5E,
       0x67, 0x35, 0x62, 0x4C, 0x33, 0x6C, 0x43, 0x41, 0x35, 0x5E,
       0x48, 0x47, 0x4B, 0x24, 0x39, 0x71, 0x6F, 0x35, 0x54, 0x40,
       0x42, 0x77, 0x6F, 0x6D, 0x39, 0x76, 0x45, 0x58, 0x79, 0x61,
       0x30, 0x48, 0x41, 0x56, 0x33, 0x4C, 0x72, 0x57, 0x57]
for i in range(len(enc)):
    enc[i] ^= box[i]
print(bytes(enc))
# flag{3a4575cf-c85c-4350-90ca-baef8252425e}

gdb_debug

逻辑很清楚
异或
re
换位
re
然后又是两个异或
re
直接解密即可

enc = [0x63, 0x6F, 0x6E, 0x67, 0x72, 0x61, 0x74, 0x75, 0x6C, 0x61,
       0x74, 0x69, 0x6F, 0x6E, 0x73, 0x74, 0x6F, 0x79, 0x6F, 0x75,
       0x63, 0x6F, 0x6E, 0x67, 0x72, 0x61, 0x74, 0x75, 0x6C, 0x61,
       0x74, 0x69, 0x6F, 0x6E, 0x73, 0x74, 0x6F, 0x79]
xor_box3 = [0xBF, 0xD7, 0x2E, 0xDA, 0xEE, 0xA8, 0x1A, 0x10, 0x83, 0x73,
            0xAC, 0xF1, 0x06, 0xBE, 0xAD, 0x88, 0x04, 0xD7, 0x12, 0xFE,
            0xB5, 0xE2, 0x61, 0xB7, 0x3D, 0x07, 0x4A, 0xE8, 0x96, 0xA2,
            0x9D, 0x4D, 0xBC, 0x81, 0x8C, 0xE9, 0x88, 0x78]
for i in range(len(enc)):
    enc[i] ^= xor_box3[i]
xor_box2 = [0xde, 0xaa, 0x42, 0xfc, 0x9, 0xe8, 0xb2, 0x6, 0xd, 0x93, 0x61, 0xf4, 0x24, 0x49, 0x15, 0x1, 0xd7, 0xab,
            0x4, 0x18, 0xcf, 0xe9, 0xd5, 0x96, 0x33, 0xca, 0xf9, 0x2a, 0x5e, 0xea, 0x2d, 0x3c, 0x94, 0x6f, 0x38, 0x9d, 0x58, 0xea]
for i in range(len(enc)):
    enc[i] ^= xor_box2[i]
idx = [0x12, 0x0E, 0x1B, 0x1E, 0x11, 0x05, 0x07, 0x01, 0x10, 0x22,
       0x06, 0x17, 0x16, 0x08, 0x19, 0x13, 0x04, 0x0F, 0x02, 0x0D,
       0x25, 0x0C, 0x03, 0x15, 0x1C, 0x14, 0x0B, 0x1A, 0x18, 0x09,
       0x1D, 0x23, 0x1F, 0x20, 0x24, 0x0A, 0x00, 0x21]
flag = [-1]*len(enc)
for i in range(len(enc)):
    flag[idx[i]] = enc[i]
xor_box1 = [0xd9, 0xf, 0x18, 0xbd, 0xc7, 0x16, 0x81, 0xbe, 0xf8, 0x4a, 0x65, 0xf2, 0x5d, 0xab, 0x2b, 0x33, 0xd4, 0xa5,
            0x67, 0x98, 0x9f, 0x7e, 0x2b, 0x5d, 0xc2, 0xaf, 0x8e, 0x3a, 0x4c, 0xa5, 0x75, 0x25, 0xb4, 0x8d, 0xe3, 0x7b, 0xa3, 0x64]
for i in range(len(flag)):
    flag[i] ^= xor_box1[i]
print(bytes(flag))
# flag{78bace5989660ee38f1fd980a4b4fbcd}
  • 26
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

P1umH0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值