首页
社区
课程
招聘
[原创]看雪 2025·KCTF 签到题 废材少年觉醒 by 心学
发表于: 2025-8-17 21:26 142

[原创]看雪 2025·KCTF 签到题 废材少年觉醒 by 心学

htg 活跃值
6
2025-8-17 21:26
142

工具:IDA

一、观察程序运行结果

C:\Users\surface>C:\Users\surface\OneDrive\Crack\CTF\Kanxue\Kanxue2025KCTF\01\A_Case\kctf2025_checkin\checkin.exe
Welcome to KCTF 2025!
请输入签到口令: KCTF123456789
签到失败!

C:\Users\surface>

程序为 64bit exe。

二、IDA初步分析及尝试调试

主要运行顺序:

start()->sub_7FF61B9A1010()->sub_7FF61B9A1AF0()->sub_7FF61B9C4DA0()->sub_7FF61B9A1450()->sub_7FF61B9A1620()

最后一个才是序列号判断逻辑所在。

再进一步是:sub_7FF61B9A1560(),该函数是序列号的逐位判断,可直接看到正确的序列号(不在数据内存里,而是蕴含在代码的操作数里)。

主要代码(调用关键函数之前)摘选:

__int64 start()
{
  unk_7FF61BA7A220 = 0;
  return sub_7FF61B9A1010();
}
__int64 sub_7FF61B9A1010()
{
    ....
    result = sub_7FF61B9A1AF0();                  // 控制台程序输出信息
    ....
}
__int64 __fastcall sub_7FF61B9A1AF0()
{
  void *v1[3]; // [rsp+28h] [rbp-8h] BYREF

  sub_7FF61BA3E7E0();
  v1[0] = sub_7FF61B9A1620;                     // 关键函数
  return sub_7FF61B9C4DA0((__int64)v1, (__int64)&unk_7FF61BA41000);// 第一个v1是执行程序地址,第二个是调用某个程序的桩。
}

//下面是继续跟踪执行,兜兜转转,最终会执行 v1 函数,即 sub_7FF61B9A1620
__int64 __fastcall sub_7FF61B9C4DA0(__int64 a1, __int64 a2)
{
    ....
    result = (*(int (__fastcall **)(__int64))(a2 + 0x28))(a1);// 调用该函数:sub_7FF61B9A1450,最终就是调用 a1= sub_7FF61B9A1620
    ....
//该处伪码有问题,需要调试跟踪或查看汇编代码来获取 esi 的值的变化。
//调用的第二个参数存储在 rdx 中,rdx = 7FF61BA41000
//.text:00007FF61B9C4DAD                 mov     rsi, rdx
//.text:00007FF61B9C4E0F                 call    qword ptr [rsi+28h]
//而 7FF61BA41000+28=7FF61BA41028,该处存放的内容是:50 14 9A 1B F6 7F 00 00,即 7FF61B9A1450。
}
//此时的函数参数为 sub_7FF61B9A1620
__int64 __fastcall sub_7FF659C91450(_QWORD *a1)
{
  sub_7FF61B9A1470(*a1);
  return 0i64;
}
//此时的函数参数为 sub_7FF61B9A1620
__int64 __fastcall sub_7FF659C91470(__int64 (*a1)(void))
{
  return a1();//执行 sub_7FF61B9A1620
}

主要代码(关键函数)摘选

__int64 __fastcall sub_7FF61B9A1620()
{
    v22 = &off_7FF61BA410A0;//Welcome to KCTF 2025!
    ....
    sub_7FF61B9D1F30((__int64)&v22);              // 输出 Welcome to KCTF 2025!
    ....
    v22 = &off_7FF61BA410C8;//// 请输入签到口令:
    sub_7FF61B9D1F30((__int64)&v22);// 输出  请输入签到口令:
    ....
    if ( (sub_7FF61B9CE3A0(v29, (__int64)&v26) & 1) != 0 )// 获取用户输入
    ....
    v2 = (char *)lpMem + v28;                     // 获取的就是用户输入值,下面开始验证
    ....
    if ( sub_7FF61B9A1560((_BYTE *)lpMem + (_QWORD)v7, v3 - v7) )// 此处判断是否等于正确的序列号
    {
      v29[0] = (volatile signed __int8 *)v30;
      v29[1] = (volatile signed __int8 *)sub_7FF61B9A1480;
      v22 = (void **)&off_7FF61BA41140;           //  aFlag           db '签到成功!FLAG: ',0Ah,0
      v23 = 2i64;
      v24 = (__int64)v29;
      v25 = 1ui64;
    }
    else
    {
      v22 = (void **)&off_7FF61BA41118;           // asc_7FF659D31108 db '签到失败!',0Ah 
      v23 = 1i64;
      v24 = 8i64;
      v25 = 0i64;
    }
    result = sub_7FF61B9D1F30((__int64)&v22);
    if ( v26 )
      return sub_7FF61B9A1B50(lpMem);             // lpMem 为 用户输入字符串的指针
    return result;
}

主要代码(序列号所在处)

bool __fastcall sub_7FF659C91560(_BYTE *a1, __int64 a2)
{
  return a2 == 0x19
      && *a1 == 'f'
      && a1[1] == 'l'
      && a1[2] == 'a'
      && a1[3] == 'g'
      && a1[4] == '{'
      && a1[5] == 'k'
      && a1[6] == 'c'
      && a1[7] == 't'
      && a1[8] == 'f'
      && a1[9] == '_'
      && a1[10] == 't'
      && a1[11] == 'i'
      && a1[12] == 'm'
      && a1[13] == 'e'
      && a1[14] == '_'
      && a1[15] == 'l'
      && a1[16] == 'e'
      && a1[17] == 'a'
      && a1[18] == 'p'
      && a1[19] == '_'
      && a1[20] == '2'
      && a1[21] == '0'
      && a1[22] == '2'
      && a1[23] == '5'
      && a1[24] == '}';
}

三、序列号

手动拼接:

SN = flag{kctf_time_leap_2025}




传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回