首页
社区
课程
招聘
[原创]第六题 Repwn writeup
2019-3-24 22:47 3906

[原创]第六题 Repwn writeup

2019-3-24 22:47
3906
这题还是比较简单的,不过好象还有后半部分,只是做题时间比较紧,所以提交成功就没看后半部分了
IDA中F5,分析见注释:
主函数:
int __thiscall sub_4014C0(void *this)
{
  unsigned int v1; // ebx
  char *Str; // [esp+0h] [ebp-68h]
  char v4[4]; // [esp+10h] [ebp-58h]
  char v5[32]; // [esp+20h] [ebp-48h]
  char sn[28]; // [esp+40h] [ebp-28h]

  sub_404930(0x10u, (int)this, (int)Str);
  sub_4044B0();
  v1 = 0;
  *(_DWORD *)v5 = 'yt^';
  *(_DWORD *)&v5[4] = '+pLc';
  *(_DWORD *)&v5[8] = 'a+SG';
  *(_DWORD *)&v5[12] = 'G-QG';
  *(_DWORD *)&v5[16] = 'Gl(V';
  *(_DWORD *)&v5[20] = ')y}J';
  *(_DWORD *)&v5[24] = 'SGA)';
  *(_DWORD *)&v5[28] = 'ea+';
  strcpy(v4, "Ansome_Is_Wrong");
  while ( v1 < strlen(v5) )
  {
    v5[v1] ^= 0x18u;
    ++v1;
  }
  puts("Please Input Your Key_ Now!");
  scanf("%s", sn);                              // 输入SN
  if ( check_8_20(sn) )                         // 检查SN[8-20] 为 "X1Y0uN3tG00d"
  {
    sub_401460(sn);                             // 这儿验证SN长度要为24,SN前8位要为"20101001",验证成功后会缓冲区溢出,用最后4位计算后覆盖返回地址,从而改变程序流程, 后四位为"HaCk"
                                                // 所以整个SN为 "20101001X1Y0uN3tG00dHaCk"
    system("pause");
  }
  else
  {
    puts(v4);
  }
  return 0;
}

signed int __cdecl check_8_20(char *sn)
{
  signed int v1; // ecx
  signed int v2; // edx
  signed int result; // eax
  char v4[12]; // [esp+0h] [ebp-38h]
  char v5[20]; // [esp+10h] [ebp-28h]

  v1 = 8;
  v2 = 0;
  strcpy(v5, "Your_Input_Is_Wrong");
  strcpy(v4, "X1Y0uN3tG00d");
  while ( v4[v2] == sn[v1] )                    // SN[8-19] 为 "X1Y0uN3tG00d"
  {
    ++v2;
    ++v1;
    if ( v2 > 11 )
    {
      result = 1;
      if ( sn[20] == 'H' )                      // SN[20] 要为"H"
        return result;
      return 0;
    }
  }
  return 0;
}

int __cdecl sub_401460(char *sn)
{
  char Dest[16]; // [esp+8h] [ebp-10h] //缓冲区只有16字节,要COPY24字节,在IDA STACK中能看到SN[20-23]覆盖返回地址

-00000018 ; D/A/*   : change type (data/ascii/array)
-00000018 ; N       : rename
-00000018 ; U       : undefine
-00000018 ; Use data definition commands to create local variables and function arguments.
-00000018 ; Two special fields " r" and " s" represent return address and saved registers.
-00000018 ; Frame size: 18; Saved regs: 4; Purge: 0
-00000018 ;
-00000018
-00000018 Str             dd ?                    ; offset
-00000014 Source          dd ?                    ; offset
-00000010 Dest            db 16 dup(?)
+00000000  s              db 4 dup(?)
+00000004  r              db 4 dup(?) //SN[20-23]覆盖返回地址
+00000008 sn              dd ?                    ; offset
+0000000C
+0000000C ; end of stack variables

  if ( strlen(sn) == 24 )                       // SN长度应该是24
  {
    if ( check_0_7((int)sn) )                   // 检查SN[0-7] 应该为 "20101001"
    {
      sn[20] -= 88;                             // SN[20-23]这儿的四位将覆盖返回地址从而改变流程,从之前的检测知道SN[20]是H,计算后为0xF0
                                                // 查看低字节为0XF0的函数应该是00401BF0
                                                // 因此这四个字节应该为"HaCk"
      sn[21] -= 70;
      sn[22] -= 3;
      sn[23] -= 107;
      strcpy(&Dest, sn);
    }
  }
  else
  {
    printf("String Length is Wrong");
  }
  return 0;
}

signed int __cdecl check_0_7(char *sn)
{
  int x; // ebx
  int y; // ecx
  int z; // esi
  signed int result; // eax

  sub_401380(sn);                               // 20101001
  x = dword_408020[3] + 1000 * dword_408020[0] + 100 * dword_408020[1] + 10 * dword_408020[2];// 2010
  y = dword_408020[5] + 10 * dword_408020[4];   // 10
  z = dword_408020[7] + 10 * dword_408020[6];   // 01
  if ( 2 * (x + y) != 4040 || 3 * y / 2 + 100 * z != 115 )// 
                                                // 三个数三个方程,解方程组:
                                                // 2 * (x + y) == 4040
                                                // 3 * y / 2 + 100 * z == 115
                                                // x - 110 * z == 1900
                                                // 得:
                                                // x = 2100
                                                // y = 10
                                                // z = 01
                                                // 所以前8个字符为 "20101001"
    goto LABEL_2;
  result = 1;
  if ( x - 110 * z != 1900 )
  {
    printf("Key_Is_Wrong,Please_Input_Again!");
LABEL_2:
    result = 0;
  }
  return result;
}

这个是验证成功进入的下一步函数,这儿没有过多的分析
void sub_401BF0()
{
  unsigned int v0; // ebx
  char *v1; // ebx
  char v2[9]; // [esp+10h] [ebp-48h]
  char v3[28]; // [esp+20h] [ebp-38h]
  __int16 v4; // [esp+3Ch] [ebp-1Ch]
  char v5; // [esp+3Eh] [ebp-1Ah]

  qmemcpy(v3, &unk_4060A4, sizeof(v3));
  v0 = 0;
  v4 = word_4060C0;
  v5 = byte_4060C2;
  while ( v0 < strlen(v3) )
  {
    v3[v0] += v0;
    ++v0;
  }
  system("cls");
  printf("%.*s\n", 29, v3);                     // "Success_Please_Input_The_Flag"
  strcpy(v2, "XiyouNet");
  fflush(iob);
  v1 = (char *)sub_401CF0(8u);
  gets(v1);
  sub_401730((int)v2);
  sub_4018B0(v1, v1);
}

从上面分析不难得到 SN 为 20101001X1Y0uN3tG00dHaCk


[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

最后于 2019-3-24 22:50 被AloneWolf编辑 ,原因:
收藏
点赞1
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回