江苏省领航杯2023年初赛

maze #

静态链接,先恢复符号

readelf -p .comment Maze

GCC: (Debian 10.2.1-6) 10.2.1 20210110

首先程序用 freopen 将文件重定向到 STDIN

然后所有的 scanf 就是从文件读取内容而不是终端了

走迷宫的代码,迷宫大小是 201x201

要求是必须经过 (96, 163) 并最终到达 (193, 131)

将迷宫分成两个部分去解,尝试了一下递归会爆栈需要采用迭代

dirs = [
    [lambda x, y: (x, y + 1), 'R'],
    [lambda x, y: (x - 1, y), 'U'],
    [lambda x, y: (x + 1, y), 'D'],
    [lambda x, y: (x, y - 1), 'L']
]

def solve_maze(x1, y1, x2, y2):
    path = []
    stack = []
    stack.append((x1, y1))
    while (len(stack) > 0):
        curr = stack[-1]
        if (curr[0] == x2 and curr[1] == y2):
            return ''.join(path)

        for d in dirs:
            nxt = d[0](curr[0], curr[1])
            if maze[nxt[0]][nxt[1]] == 0:
                stack.append(nxt)
                path.append(d[1])
                maze[curr[0]][curr[1]] = 2
                break
        else:
            maze[curr[0]][curr[1]] = 2
            path.pop()
            stack.pop()
    else:
        return False

easyobf #

混淆过的 .NET 程序,32 位

搜索 Cmile_96 可以找到这样一个混淆项目 ConfuserEx-Plus

网上的 ConfuserEx 解包软件对这个魔改版本都不太有效,只能硬着头皮先分析

该混淆难在控制流平坦化和针对 dnSpy 的局部变量保护

调试时无法取得被混淆函数局部变量的值

但是找到检验函数还是不难的


因为笔者的实验环境为 VMware,需要先绕过混淆器的 VM 保护

        static void Initialize()
        {
            if (AntiVM.CspParameters())
            {
                AntiVM.CrossAppDomainSerializer("START CMD /C \"ECHO VirtualMachine Detected ! && PAUSE\" ");
                Process.GetCurrentProcess().Kill();
            }
        }

根据混淆器源码在 System.Diagnostics.Process.Kill 下断点

弹出的 cmd 为生成的子进程可以直接关闭

设置第 2565 行成为下一条语句就可以轻松跳过 VM 保护


简单测试一下发现结果由 MessageBox 回弹,于是在 System.Windows.Forms.MessageBox 启用类断点

断点触发后查看调用堆栈,就可以找到程序逻辑 Cmile_96_BAB8C43947

状态 0 和 2 的基本块形式类似都是弹出 MessageBox

经过检查 Cmile_96_4885DF3A94 比较可疑应该是检验函数

在每个基本块上下断点即可得到执行顺序

这时注意到状态 1 中有一个 CodeDomProvider,这是用来即时编译源码的类

检查第 141 行的调用链,最终停在了 CompileAssemblyFromSource

在这里下断点,由于它不属于主模块 dnSpy 可以解析局部变量的值

右键保存 sources[0] 就得到了本题混淆前的源码

using System;
using System.Text;
public class Script
{
    public static string Execute(string input)
    {
        string msg = string.Empty;
        if (input.StartsWith("CnHongKe{") && input.EndsWith("}"))
        {
            string content = input.Replace("CnHongKe{", "").Replace("}","");
            if (content.Length == 36)
            {
                msg = "You are great~!";

                byte[] bC = Encoding.ASCII.GetBytes(content);
                byte[] bT = Convert.FromBase64String("ISN5JnUkeHdtJCUidm10IXEmbXl2JSNtdSJwJXZyI3UiJCZ2");
                for (int i = 0; i < bC.Length; i++)
                {
                    if (bT[i] != (bC[i]^0x40))
                    {
                        msg = "Invalid Flag.";
                        break;
                    }
                }
            }
            else
            {
                msg = "Invalid Length.";
            }
        }
        else
        {
            msg = "Invalid Format.";
        }
        return msg;
    }
}

可以看到就是异或 0x40

prng #

在 $Z_5$ 上解矩阵方程 $R \cdot x=s$,其中 $R$ 和 $s$ 都已知

db #

这题的 $\log{d} \approx 299/1024=0.2919921875$,已经比较逼近上限 $0.292$,需要做一些微调

回顾一下 BD 攻击的切入点

$$ \begin{aligned} ed&=x’\phi(N)+1 \newline &=x’(N+1-p-q)+1 \newline &=2x’(\frac{N+1}{2}-\frac{p+q}{2})+1 \newline &=x(A+y)+1 \newline \end{aligned} $$

一般取 $y=\frac{p+q}{2}$ 的上限为 $N^{0.5}$,但这题中 $p$ 和 $q$ 的高 70 位泄漏

如果把泄漏的部分 $\bar{p}$ 和 $\bar{q}$ 算进 $A$ 中,就可以把 $\log{y}$ 的上限缩小到 $(512-70)/1024=0.431640625$

所以在攻击模板中取 $Y=N^{0.44},A=\frac{N+1-\bar{p}-\bar{q}}{2}$ 即可