首页
社区
课程
招聘
[原创]2021 KCTF 春季赛 第四题 英雄救美 wp
发表于: 2021-5-14 18:50 5715

[原创]2021 KCTF 春季赛 第四题 英雄救美 wp

2021-5-14 18:50
5715

windows32位控制台程序.
输入错误时没有回显.
输入成功的提示是段shellcode, 使用VirtualAlloc分配地址解密shellcode再执行.
观察验证逻辑, 不难发现是个9*9的经典数独游戏.

ida F5, main函数逻辑如下:

输入完serial后, 要执行成功的回显, 必须要满足三个条件:
1.输入length不大于64
2.fun_convert_input(sub_401240)验证通过
3.fun_check_game(sub_401000)验证通过

分析fun_convert_input和fun_check_game两个函数的逻辑.

将输入的serial每个字符进行转换.
遇到非数字字符, 查表的第n行(n从1开始)转换对应下标.

遇到数字字符, 验证这行转换了的下标个数加上数字字符是不是等于'9'(满足数独一行有9个数字), 并且切换查表的下一行(n++).

把转换好的下标(1~9数字)填入游戏格子内.

验证数独是否成立(每行每列每个九宫格都是数字1~9).

先到网页上在线解数独:链接

每行需要填的数字为:

根据fun_convert_input里的字符表进行转换:

每行最后加上数字(9-要填写的数字个数), 最后得到:

:u$YBPf2pa]Dt4#QM^H4ic'j0`w2y{d-Zzo2%/n_s@+2<UW)e4AR;F.4=-qEkvC2

验证通过!

拿到flag后处于好奇瞅了一眼成功提示的MessageBox代码, 和之前猜测的一样, 是段shellcode.

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int nLen; // kr00_4
  int v4; // ecx
  __m128i *v5; // esi
  int v6; // edi
  void (*v8)(void); // [esp+10h] [ebp-2C8h]
  int v9[22]; // [esp+14h] [ebp-2C4h] BYREF
  char v10[508]; // [esp+6Ch] [ebp-26Ch] BYREF
  __int128 v11; // [esp+26Ch] [ebp-6Ch] BYREF
  char v12[88]; // [esp+27Ch] [ebp-5Ch] BYREF
 
  printf("\t\t\t看雪CTF大赛\r\n");
  printf("\t\t祝愿看雪CTF大赛越办越好\r\n");
  printf("Serial: ");
  scanf_s("%s", (char *)&v11 + 12);
  nLen = strlen((const char *)&v11 + 12);
  if ( nLen <= 64 && fun_convert_input((int)&v11 + 12, nLen, &v9[21]) == 1 && fun_check_game((int)v10, nLen - 9) == 1 )
  {
    v11 = 0i64;
    memset(v9, 0, sizeof(v9));
    v9[5] = 0;
    v9[4] = 0;
    v9[0] = 0x67452301;
    v9[1] = 0xEFCDAB89;
    v9[2] = 0x98BADCFE;
    v9[3] = 0x10325476;
    sub_4014E0((int)v12, (int)v9, nLen);
    sub_4015B0((int)&v11, (int)v9);
    sub_401ED0(v4, (unsigned __int8 *)&v11);
    v8 = (void (*)(void))VirtualAlloc(0, 0x620u, 0x1000u, 0x40u);
    v5 = (__m128i *)v8;
    v6 = 0x62;
    do
    {
      *v5 = _mm_loadu_si128((__m128i *)((char *)v5 + &sub_4181A0 - (_UNKNOWN *)v8));
      ((void (__fastcall *)(char *, __m128i *))loc_4028B0)(v10, v5++);
      --v6;
    }
    while ( v6 );
    v8();
  }
  return 0;
}
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int nLen; // kr00_4
  int v4; // ecx
  __m128i *v5; // esi
  int v6; // edi
  void (*v8)(void); // [esp+10h] [ebp-2C8h]
  int v9[22]; // [esp+14h] [ebp-2C4h] BYREF
  char v10[508]; // [esp+6Ch] [ebp-26Ch] BYREF
  __int128 v11; // [esp+26Ch] [ebp-6Ch] BYREF
  char v12[88]; // [esp+27Ch] [ebp-5Ch] BYREF
 
  printf("\t\t\t看雪CTF大赛\r\n");
  printf("\t\t祝愿看雪CTF大赛越办越好\r\n");
  printf("Serial: ");
  scanf_s("%s", (char *)&v11 + 12);
  nLen = strlen((const char *)&v11 + 12);
  if ( nLen <= 64 && fun_convert_input((int)&v11 + 12, nLen, &v9[21]) == 1 && fun_check_game((int)v10, nLen - 9) == 1 )
  {
    v11 = 0i64;
    memset(v9, 0, sizeof(v9));
    v9[5] = 0;
    v9[4] = 0;
    v9[0] = 0x67452301;
    v9[1] = 0xEFCDAB89;
    v9[2] = 0x98BADCFE;
    v9[3] = 0x10325476;
    sub_4014E0((int)v12, (int)v9, nLen);
    sub_4015B0((int)&v11, (int)v9);
    sub_401ED0(v4, (unsigned __int8 *)&v11);
    v8 = (void (*)(void))VirtualAlloc(0, 0x620u, 0x1000u, 0x40u);
    v5 = (__m128i *)v8;
    v6 = 0x62;
    do
    {
      *v5 = _mm_loadu_si128((__m128i *)((char *)v5 + &sub_4181A0 - (_UNKNOWN *)v8));
      ((void (__fastcall *)(char *, __m128i *))loc_4028B0)(v10, v5++);
      --v6;
    }
    while ( v6 );
    v8();
  }
  return 0;
}
 
$BPV:ubfY
p}]DtN>aT
^MGmJQ#*H
r`O'wjic0
!hdy{oZz-
@n+?&%s_/
g<e[W)XUx
RFSLRA;.l
=CEkvK-(q
$BPV:ubfY
p}]DtN>aT

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

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