首页
社区
课程
招聘
[原创]看雪 2024 KCTF 年度赛 第二题 星际生物
发表于: 2024-8-16 13:27 5338

[原创]看雪 2024 KCTF 年度赛 第二题 星际生物

2024-8-16 13:27
5338

常规题目,C#程序,无壳无混淆

dnspy打开,定位到main函数

逻辑很清楚,分几个阶段:

提取原始数独:<Module>.sudoku,0xf换成0

求解:

抽出填进去的数:34689155813271746868579324125982187492581517263447389126

迷宫:$ArrayType$$$BY133E 局部变量:

!是起始位置,?是目标位置,+是空地,-是墙,WSAD控制行走
8步正好走到终点:SDSDDWWA

组合上述,最终flag为:

 

今年的第一个题后碎碎念:
 
看雪CTF今年的规则是一点都没变啊,还真是坚持自己的特色。犹记得从去年到现在群里很多人都提出过当前计分模式不合理(防守方难度分极大的由一血时间决定而不怎么受做出人数的影响;攻击分积分受时间影响过大,衰减过于严重,以至于去年曾短暂出现过仅靠一道一血排名就高出了做出四道题的人的心寒时刻,而从题目难度看,那四道题付出的精力可并不低)
 
给希望拿奖的防守方提供一点点出题思路

签到题还没做,不是屯flag,是真的卡壳没思路……

// <Module>
// Token: 0x06000003 RID: 3 RVA: 0x00001090 File Offset: 0x00000490
internal unsafe static int main()
{
    $ArrayType$$$BY0BAA@D $ArrayType$$$BY0BAA@D;
    initblk(ref $ArrayType$$$BY0BAA@D, 0, 256);
    <Module>.printf(ref <Module>.??_C@_0BJ@MNCFGMHN@Please?5input?5your?5flag?3?5?$AA@);
    <Module>.scanf(ref <Module>.??_C@_05HPMPOKFN@?$CF?$FL?$FO?6?$FN?$AA@, ref $ArrayType$$$BY0BAA@D);
    sbyte* ptr = ref $ArrayType$$$BY0BAA@D;
    if ($ArrayType$$$BY0BAA@D != null)
    {
        do
        {
            ptr += 1L;
        }
        while (*ptr != 0);
    }
    if (ptr - (ref $ArrayType$$$BY0BAA@D) != 70U)
    {
        <Module>.printf(ref <Module>.??_C@_0M@IIPHMAMA@Try?5again?$CB?6?$AA@);
        return -1;
    }
    if ($ArrayType$$$BY0BAA@D == 102 && *((ref $ArrayType$$$BY0BAA@D) + 1) == 108 && *((ref $ArrayType$$$BY0BAA@D) + 2) == 97 && *((ref $ArrayType$$$BY0BAA@D) + 3) == 103 && *((ref $ArrayType$$$BY0BAA@D) + 4) == 123 && *((ref $ArrayType$$$BY0BAA@D) + 69) == 125)
    {
        $ArrayType$$$BY0EA@E $ArrayType$$$BY0EA@E;
        cpblk(ref $ArrayType$$$BY0EA@E, (ref $ArrayType$$$BY0BAA@D) + 5, 64);
        uint num = 0U;
        uint num2 = 0U;
        $ArrayType$$$BY188E* ptr2 = &<Module>.sudoku;
        do
        {
            uint num3 = 0U;
            $ArrayType$$$BY188E* ptr3 = ptr2;
            do
            {
                if (*(byte*)ptr3 == 15)
                {
                    byte b = *((ulong)num + (ref $ArrayType$$$BY0EA@E));
                    if (b < 48 || b > 57)
                    {
                        goto IL_109;
                    }
                    *(byte*)ptr3 = b - 48;
                    num += 1U;
                }
                num3 += 1U;
                ptr3 += 1L / (long)sizeof($ArrayType$$$BY188E);
            }
            while (num3 < 9U);
            num2 += 1U;
            ptr2 += 9L / (long)sizeof($ArrayType$$$BY188E);
        }
        while (num2 < 9U);
        uint num4 = 1U;
        uint num5 = 1U;
        uint num6 = 0U;
        long num7 = 0L;
        while (num4 == 1U)
        {
            long num8 = 0L;
            uint num9 = 1U;
            while (num4 == 1U)
            {
                uint num10 = num9;
                if (num9 < 9U)
                {
                    long num11 = (long)((ulong)num9);
                    byte b2 = *(num7 + num8 + (ref <Module>.sudoku));
                    num4 = 1U;
                    $ArrayType$$$BY188E* ptr4 = num7 + num11 + (ref <Module>.sudoku);
                    while (b2 != *(byte*)ptr4)
                    {
                        num10 += 1U;
                        ptr4 += 1L / (long)sizeof($ArrayType$$$BY188E);
                        if (num10 >= 9U)
                        {
                            goto IL_17F;
                        }
                    }
                    num4 = 0U;
                }
                IL_17F:
                num9 += 1U;
                num8 += 1L;
                if (num9 - 1U >= 9U)
                {
                    break;
                }
            }
            num6 += 1U;
            num7 += 9L;
            if (num6 >= 9U)
            {
                break;
            }
        }
        uint num12 = 0U;
        long num13 = 0L;
        while (num5 == 1U)
        {
            uint num14 = 1U;
            $ArrayType$$$BY188E* ptr5 = num13 + (ref <Module>.sudoku);
            while (num5 == 1U)
            {
                uint num15 = num14;
                if (num14 < 9U)
                {
                    $ArrayType$$$BY188E* ptr6 = num14;
                    byte b3 = *(byte*)ptr5;
                    num5 = 1U;
                    $ArrayType$$$BY188E* ptr7 = ptr6 * 9L + num13 / (long)sizeof($ArrayType$$$BY188E) + (ref <Module>.sudoku) / sizeof($ArrayType$$$BY188E);
                    while (b3 != *(byte*)ptr7)
                    {
                        num15 += 1U;
                        ptr7 += 9L / (long)sizeof($ArrayType$$$BY188E);
                        if (num15 >= 9U)
                        {
                            goto IL_209;
                        }
                    }
                    num5 = 0U;
                }
                IL_209:
                num14 += 1U;
                ptr5 += 9L / (long)sizeof($ArrayType$$$BY188E);
                if (num14 - 1U >= 9U)
                {
                    break;
                }
            }
            num12 += 1U;
            num13 += 1L;
            if (num12 >= 9U)
            {
                break;
            }
        }
        if (num4 == 1U && num5 == 1U)
        {
            $ArrayType$$$BY133E $ArrayType$$$BY133E = 33;
            *((ref $ArrayType$$$BY133E) + 1) = 45;
            *((ref $ArrayType$$$BY133E) + 2) = 63;
            *((ref $ArrayType$$$BY133E) + 3) = 43;
            *((ref $ArrayType$$$BY133E) + 4) = 43;
            *((ref $ArrayType$$$BY133E) + 5) = 43;
            *((ref $ArrayType$$$BY133E) + 6) = 45;
            *((ref $ArrayType$$$BY133E) + 7) = 43;
            *((ref $ArrayType$$$BY133E) + 8) = 45;
            *((ref $ArrayType$$$BY133E) + 9) = 43;
            *((ref $ArrayType$$$BY133E) + 10) = 43;
            *((ref $ArrayType$$$BY133E) + 11) = 43;
            *((ref $ArrayType$$$BY133E) + 12) = 43;
            *((ref $ArrayType$$$BY133E) + 13) = 45;
            *((ref $ArrayType$$$BY133E) + 14) = 45;
            *((ref $ArrayType$$$BY133E) + 15) = 43;
            byte b4 = 0;
            byte b5 = 0;
            uint num16 = 0U;
            do
            {
                int num17 = (int)(*((ulong)num + (ref $ArrayType$$$BY0EA@E)));
                num += 1U;
                if (num17 != 65)
                {
                    if (num17 != 68)
                    {
                        if (num17 != 83)
                        {
                            if (num17 == 87)
                            {
                                if (b4 == 0)
                                {
                                    goto IL_323;
                                }
                                b4 -= 1;
                            }
                        }
                        else
                        {
                            if (b4 == 3)
                            {
                                goto IL_330;
                            }
                            b4 += 1;
                        }
                    }
                    else
                    {
                        if (b5 == 3)
                        {
                            goto IL_33D;
                        }
                        b5 += 1;
                    }
                }
                else
                {
                    if (b5 == 0)
                    {
                        goto IL_34A;
                    }
                    b5 -= 1;
                }
                if (*((ulong)b5 + (ref $ArrayType$$$BY133E) + (ulong)b4 * 4UL) == 45)
                {
                    goto IL_357;
                }
                num16 += 1U;
            }
            while (num16 < 8U);
            if (*((ulong)b5 + (ref $ArrayType$$$BY133E) + (ulong)b4 * 4UL) == 63)
            {
                <Module>.printf(ref <Module>.??_C@_0BB@MGPKLNCH@You?5are?5winner?$CB?6?$AA@);
                return 0;
            }
            goto IL_381;
            IL_323:
            <Module>.printf(ref <Module>.??_C@_0M@IIPHMAMA@Try?5again?$CB?6?$AA@);
            return -1;
            IL_330:
            <Module>.printf(ref <Module>.??_C@_0M@IIPHMAMA@Try?5again?$CB?6?$AA@);
            return -1;
            IL_33D:
            <Module>.printf(ref <Module>.??_C@_0M@IIPHMAMA@Try?5again?$CB?6?$AA@);
            return -1;
            IL_34A:
            <Module>.printf(ref <Module>.??_C@_0M@IIPHMAMA@Try?5again?$CB?6?$AA@);
            return -1;
            IL_357:
            <Module>.printf(ref <Module>.??_C@_0M@IIPHMAMA@Try?5again?$CB?6?$AA@);
            return -1;
        }
        goto IL_381;
        IL_109:
        <Module>.printf(ref <Module>.??_C@_0M@IIPHMAMA@Try?5again?$CB?6?$AA@);
        return -1;
    }
    IL_381:
    <Module>.printf(ref <Module>.??_C@_0M@IIPHMAMA@Try?5again?$CB?6?$AA@);
    return -1;
}
// <Module>
// Token: 0x06000003 RID: 3 RVA: 0x00001090 File Offset: 0x00000490
internal unsafe static int main()
{
    $ArrayType$$$BY0BAA@D $ArrayType$$$BY0BAA@D;
    initblk(ref $ArrayType$$$BY0BAA@D, 0, 256);
    <Module>.printf(ref <Module>.??_C@_0BJ@MNCFGMHN@Please?5input?5your?5flag?3?5?$AA@);
    <Module>.scanf(ref <Module>.??_C@_05HPMPOKFN@?$CF?$FL?$FO?6?$FN?$AA@, ref $ArrayType$$$BY0BAA@D);
    sbyte* ptr = ref $ArrayType$$$BY0BAA@D;
    if ($ArrayType$$$BY0BAA@D != null)
    {
        do
        {
            ptr += 1L;
        }
        while (*ptr != 0);
    }
    if (ptr - (ref $ArrayType$$$BY0BAA@D) != 70U)
    {
        <Module>.printf(ref <Module>.??_C@_0M@IIPHMAMA@Try?5again?$CB?6?$AA@);
        return -1;
    }
    if ($ArrayType$$$BY0BAA@D == 102 && *((ref $ArrayType$$$BY0BAA@D) + 1) == 108 && *((ref $ArrayType$$$BY0BAA@D) + 2) == 97 && *((ref $ArrayType$$$BY0BAA@D) + 3) == 103 && *((ref $ArrayType$$$BY0BAA@D) + 4) == 123 && *((ref $ArrayType$$$BY0BAA@D) + 69) == 125)
    {
        $ArrayType$$$BY0EA@E $ArrayType$$$BY0EA@E;
        cpblk(ref $ArrayType$$$BY0EA@E, (ref $ArrayType$$$BY0BAA@D) + 5, 64);
        uint num = 0U;
        uint num2 = 0U;
        $ArrayType$$$BY188E* ptr2 = &<Module>.sudoku;
        do
        {
            uint num3 = 0U;
            $ArrayType$$$BY188E* ptr3 = ptr2;
            do
            {
                if (*(byte*)ptr3 == 15)
                {
                    byte b = *((ulong)num + (ref $ArrayType$$$BY0EA@E));
                    if (b < 48 || b > 57)
                    {
                        goto IL_109;
                    }
                    *(byte*)ptr3 = b - 48;
                    num += 1U;
                }
                num3 += 1U;
                ptr3 += 1L / (long)sizeof($ArrayType$$$BY188E);
            }
            while (num3 < 9U);
            num2 += 1U;
            ptr2 += 9L / (long)sizeof($ArrayType$$$BY188E);
        }
        while (num2 < 9U);
        uint num4 = 1U;
        uint num5 = 1U;
        uint num6 = 0U;
        long num7 = 0L;
        while (num4 == 1U)
        {
            long num8 = 0L;
            uint num9 = 1U;
            while (num4 == 1U)
            {
                uint num10 = num9;
                if (num9 < 9U)
                {
                    long num11 = (long)((ulong)num9);
                    byte b2 = *(num7 + num8 + (ref <Module>.sudoku));
                    num4 = 1U;
                    $ArrayType$$$BY188E* ptr4 = num7 + num11 + (ref <Module>.sudoku);
                    while (b2 != *(byte*)ptr4)
                    {
                        num10 += 1U;
                        ptr4 += 1L / (long)sizeof($ArrayType$$$BY188E);
                        if (num10 >= 9U)
                        {
                            goto IL_17F;
                        }
                    }
                    num4 = 0U;
                }
                IL_17F:
                num9 += 1U;
                num8 += 1L;
                if (num9 - 1U >= 9U)
                {
                    break;
                }
            }
            num6 += 1U;
            num7 += 9L;
            if (num6 >= 9U)
            {
                break;
            }
        }
        uint num12 = 0U;
        long num13 = 0L;
        while (num5 == 1U)
        {
            uint num14 = 1U;
            $ArrayType$$$BY188E* ptr5 = num13 + (ref <Module>.sudoku);
            while (num5 == 1U)
            {
                uint num15 = num14;
                if (num14 < 9U)
                {
                    $ArrayType$$$BY188E* ptr6 = num14;
                    byte b3 = *(byte*)ptr5;
                    num5 = 1U;
                    $ArrayType$$$BY188E* ptr7 = ptr6 * 9L + num13 / (long)sizeof($ArrayType$$$BY188E) + (ref <Module>.sudoku) / sizeof($ArrayType$$$BY188E);
                    while (b3 != *(byte*)ptr7)
                    {
                        num15 += 1U;
                        ptr7 += 9L / (long)sizeof($ArrayType$$$BY188E);
                        if (num15 >= 9U)
                        {
                            goto IL_209;
                        }
                    }
                    num5 = 0U;
                }
                IL_209:
                num14 += 1U;
                ptr5 += 9L / (long)sizeof($ArrayType$$$BY188E);
                if (num14 - 1U >= 9U)
                {
                    break;
                }
            }
            num12 += 1U;
            num13 += 1L;
            if (num12 >= 9U)
            {
                break;

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2024-8-17 00:19 被mb_mgodlfyn编辑 ,原因:
收藏
免费 4
支持
分享
最新回复 (5)
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
求大佬帮忙
2024-8-19 13:06
0
雪    币: 23697
活跃值: (12240)
能力值: ( LV15,RANK:1744 )
在线值:
发帖
回帖
粉丝
3
补充回复:文末的“出题思路”不知道会被怎样理解,千万别真按这个来出题啊,实际想表达的意思是当前比赛规则不太合理以及给防守方带来的负面引导

难度奖:0解题必然比有解题分数高,想拿防守方第一自然是题目怎么复杂怎么出。但是,这会让攻击方的体验大打折扣。不过,诸如基于1day或新论文的pwn、crypto等,即使做不出来,单看writeup也能学到新知识,攻击方自然有动力积极破解;而加壳加混淆的逆向题则是完全相反的体验了,一来这肯定是重体力劳动,二来即使破解了混淆大概率也只是适应这一道题(相同的时间精力还不如用来破解市面上现有的混淆,至少搞出来能立刻应对一大批现实样本),三来,前述的超难pwn、crypto等,至少出题人一定是会解的,而且需要的知识量和付出的工作量并不会比攻击方少;但是换到以加混淆为考点的reverse,如果出题人给不出合理的去混淆方法,完全可以认定为出题人自己并不会解这道题(至于writeup只给一份序列号生成代码?出题人的题解至少要从攻击方的角度考虑,而不能依靠于仅自己出题时的额外信息(未混淆的代码));当然,本届第三题至少开源了加混淆的代码,已经比过往的一些题目好很多了,点赞作者,不过在此还是希望出题人尽快公开自己的去混淆方法(总不能,出题人自己都没尝试过吧,要真是这样可太过分了))
(当然,现实中的样本,往往面对的各种加壳混淆反调试更加恶心,但这样的任务通常有与之匹配的高额回报。CTF毕竟侧重于技术交流,奖励适中,攻守平衡,出题人会(以不多于攻击方的信息)解自己的题(包括去混淆)应该是验题的一个基本要求;或者,退一步,至少在题目放出时在描述中写清楚,出题人自己有没有尝试过解混淆之类的,给攻击方一个明确的预期)  
火力奖:主要问题是,以一血时间衡量难度远远不如以做出人数衡量难度准确。时间因素占比过重,往往容易催生题目的猜谜程度(猜谜总要花时间,而人数基数大猜中的人数也会多)。另外,中午12:00放题,很多人并不能第一时间参与进来(线下赛不存在这个问题),等到晚上再做,可能与一血已经差了一倍的分,已经是严重的不公平了。另外,一血时间有时不能反应真实难度,例如有个别做题人通灵感应确实强大,这不能反应出题目的真实设计。  
精致奖:除了前几次有一道BROP的pwn题以外,想要短小精悍难度大,似乎往crypto方向机会更多一些
2024-8-22 03:42
0
雪    币: 2402
活跃值: (6808)
能力值: ( LV7,RANK:102 )
在线值:
发帖
回帖
粉丝
4
上班天天分析这些东东也就算了,下班回家来把黑神话悟空不香吗
2024-8-22 12:52
0
雪    币: 264
活跃值: (699)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
5
mb_mgodlfyn 补充回复:文末的“出题思路”不知道会被怎样理解,千万别真按这个来出题啊,实际想表达的意思是当前比赛规则不太合理以及给防守方带来的负面引导 难度奖:0解题必然比有解题分数高,想拿防守方第一自然是题 ...

不好意思,四天过后才看到师傅你的想法,小菜我最近在反思新的感悟,没什么机会碰电脑。这届赛期结束前,一定交出来自己的  WriteUp。关于混淆规则的建议,我个人觉得很有道理,下次的 KCTF,我会注意。夜晚拿掉一血,等其他小组成员醒来,攻击方的得分真的衰减太多了。("真的"和“真地”的用法似乎有些许争论,用 “真的”习惯较多,很少看到有文章用 “真地”一词修饰句子)

最后于 2024-8-26 14:14 被zZhouQing编辑 ,原因:
2024-8-26 14:00
0
雪    币: 264
活跃值: (699)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
6
2024年KCTF水泊梁山-WriteUp-反混淆
https://bbs.kanxue.com/thread-283190.htm 
2024-8-30 23:51
0
游客
登录 | 注册 方可回帖
返回
//