首页
论坛
专栏
课程

[原创] 看雪CTF.TSRC 2018 团队赛 第六题

2018-12-11 21:36 652

[原创] 看雪CTF.TSRC 2018 团队赛 第六题

2018-12-11 21:36
652
该程序是一个带窗口的程序,首先根据GetDlgItemTextA函数的交叉引用,来到sub_401040函数处,调用 GetDlgItemTextA函数 最多获取20个字符。


查看sub_401020函数没有任何关于输入的处理,查看区块发现有一个tls段,并且有一个tls回调函数,tls回调函数先于程序的入口点执行。


ida可以识别出tls回调函数,跟进该函数分析发现执行sub_401D50和sub_401C10两个函数后,启动了一个线程


跟进函数sub_401D50分析发现,这个函数获取了 sub_401020到 sub_401080的跳转距离。再看v5=0xE9,该值是一个jmp指令,最后保存到addr_414018,可以猜测这个程序可能使用了hook技术改变了执行流程。不过查看该全局变量的引用,addr_414018并没有被使用。


继续分析sub_401C10函数,结合动态分析发现该函数hook了 GetDlgItemTextA 函数。hook点在 GetDlgItemTextA函数地址加上32,跳转到目标函数sub_401A10


然后分析那个线程函数StartAddress,发现是一个死循环。根据dword_4147FC的值来决定是否执行sub_401C10这个hook函数。


接下来重点分析 sub_401A10这个目标函数。这个函数进行了sn的验证,在通过sub_401290和sub_4017B0这个两个函数的判断后,通过异或运算解密出输入正确的提示信息,OK和success两个字符串,并替换掉错误提示信息的字符串。


在sub_401290函数中对num_byte_4147D0这个byte类型的数组进行了赋值,然后执行sub_4015B0函数。


sub_4015B0 的返回值不能为0才能通过验证,跟进sub_4015B0这个函数分析。把sn按两个字符进行分组,并根据第一个字符是否等于w,d,s,a来决定v6的值,对第二个字符减掉48作为 sub_401380函数 的第二个参数。然后调用sub_401380函数, 最后判断num_byte_4147D0数组 的值是否等于[1,2,3,4,5,6,7,8,0]。


跟进sub_401380函数继续分析。
char __cdecl sub_401380(int a1, int a2_sn_1byte)
{
  char result; // al@2
  signed int i; // [sp+8h] [bp-8h]@5
  signed int v4; // [sp+Ch] [bp-4h]@3

  if ( a2_sn_1byte )
  {
    v4 = 0;
LABEL_4:
    if ( v4 >= 3 )
    {
      result = 0;
    }
    else
    {
      for ( i = 0; ; ++i )
      {
        if ( i >= 3 )
        {
          ++v4;
          goto LABEL_4;
        }
        if ( *(&num_byte_4147D0[3 * v4] + i) == a2_sn_1byte )
          break;
LABEL_6:
        ;
      }
      switch ( a1 )
      {
        case 0:                                 // w
          if ( v4 )
          {
            if ( *(&num_byte_4147D0[3 * (v4 - 1)] + i) )
            {
              result = 0;
            }
            else
            {
              *(&num_byte_4147D0[3 * (v4 - 1)] + i) = *(&num_byte_4147D0[3 * v4] + i);
              *(&num_byte_4147D0[3 * v4] + i) = 0;
              result = 1;
            }
          }
          else                                  
          {
            result = 0;
          }
          break;
        case 1:                                 // d
          if ( i == 2 )
          {
            result = 0;
          }
          else if ( *(&num_byte_4147D0[3 * v4 + 1] + i) )
          {
            result = 0;
          }
          else
          {
            *(&num_byte_4147D0[3 * v4 + 1] + i) = *(&num_byte_4147D0[3 * v4] + i);
            *(&num_byte_4147D0[3 * v4] + i) = 0;
            result = 1;
          }
          break;
        case 2:                                 // s
          if ( v4 == 2 )
          {
            result = 0;
          }
          else if ( *(&num_byte_4147D0[3 * (v4 + 1)] + i) )
          {
            result = 0;
          }
          else
          {
            *(&num_byte_4147D0[3 * (v4 + 1)] + i) = *(&num_byte_4147D0[3 * v4] + i);
            *(&num_byte_4147D0[3 * v4] + i) = 0;
            result = 1;
          }
          break;
        case 3:                                 // a
          if ( i )
          {
            if ( *(&byte_4147CF[3 * v4] + i) )
            {
              result = 0;
            }
            else
            {
              *(&byte_4147CF[3 * v4] + i) = *(&num_byte_4147D0[3 * v4] + i);
              *(&num_byte_4147D0[3 * v4] + i) = 0;
              result = 1;
            }
          }
          else
          {
            result = 0;
          }
          break;
        default:
          goto LABEL_6;
      }
    }
  }
  else
  {
    result = 0;
  }
  return result;
}
从这个函数可以看出 num_byte_4147D0是一个3X3的二维数组,该函数的功能是根据第二个参数通过for循环找到num_byte_4147D0 中需要移动的元素,并对其进行移动,移动的长度为1。w,s,a,d代表上下左右四个方向,第二个参数表示需要移动的元素,且只能移动到元素为0的位置。根据前面对sub_4015B0函数的分析,移动后的最终位置为[1,2,3,4,5,6,7,8,0]。感觉这样的移动并不复杂,所以手动推导出一个移动方案,方案如下:
4	1	3
7	2	5	d6
8	6	0
	↓
4	1	3
7	2	5	d8
8	0	6	
	↓
4	1	3
7	2	5	s7
0	8	6
	↓
4	1	3
0	2	5	s4
7	8	6
	↓
0	1	3
4	2	5	a1
7	8	6
	↓
1	0	3
4	2	5	w2
7	8	6
	↓
1	2	3
4	0	5	a5
7	8	6
	↓
1	2	3
4	5	0	w6
7	8	6
	↓
1	2	3
4	5	6	
7	8	0

长度没有超过20个字符,试了下d6d8s7s4a1w2a5w6这个sn,验证通过 


因为是通过移动数组中的元素来达到sn的验证,所以会有多种移动方案,sub_401A10函数中的第二个if判断是为了防止多解。分析了下sub_4017B0函数,通过sn的长度参与到对元素的异或运算中最后结果为0x5634D252



[招聘]欢迎市场人员加入看雪学院团队!

最新回复 (0)
游客
登录 | 注册 方可回帖
返回