首页
论坛
课程
招聘
[原创]第六题 Repwn(缓冲区溢出)
2019-3-13 09:16 1265

[原创]第六题 Repwn(缓冲区溢出)

2019-3-13 09:16
1265

通过查找字符串Please Input Your Key_ Now!,定位输入flag的位置:

int __thiscall sub_4014C0(void *this)
{
/*
*******省略n行
*/
  sub_404930(0x10u, (int)this, (int)Str);
  sub_4044B0();
  v1 = 0;
  v5 = 0x7F79745E;
  v6 = 0x2B704C63;
  v7 = 0x612B5347;
  v8 = 0x472D5147;
  v9 = 0x476C2856;
  v10 = 0x29797D4A;
  v11 = 1397178665;
  v12 = 6644011;
  strcpy(v4, "Ansome_Is_Wrong");
  while ( v1 < strlen((const char *)&v5) )
    *((_BYTE *)&v5 + v1++) ^= 0x18u;
  puts("Please Input Your Key_ Now!");
  scanf("%s", &v13);
  if ( sub_4012F0((int)&v13) )                  
  {
    sub_401460(&v13);       
    system("pause");
  }
  else
  {
    puts(v4);
  }
  return 0;
}

查看检测flag的两个函数sub_4012F0((int)&v13)sub_401460(&v13)

signed int __cdecl sub_4012F0(int a1)
{

/*
*******省略n行
*/
  v1 = 8;
  v2 = 0;
  v8 = 1920298841;
  v9 = 1886275935;
  v10 = 1230992501;
  v11 = 1918328691;
  v12 = 6778479;
  v4 = 0x30593158;
  v5 = 0x74334E75;
  v6 = 0x64303047;
  v7 = 0;
  while ( *((_BYTE *)&v4 + v2) == *(_BYTE *)(v1 + a1) )
  {
    ++v2;
    ++v1;
    if ( v2 > 11 )
    {
      result = 1;
      if ( *(_BYTE *)(a1 + 20) == 0x48 )
        return result;
      return 0;
    }
  }
  return 0;
}

这个函数已经确定第9到20位为X1Y0uN3tG00d,老版本的程序没有判断第21位,导致有多个解,3月12日下午更新过的程序加上了对21位的判断,这一位是H

nt __cdecl sub_401460(char *Str)
{
  char Dest; // [esp+8h] [ebp-10h]

  if ( strlen(Str) == 24 )
  {
    if ( sub_4013B0((int)Str) )
    {
      Str[20] -= 0x58;
      Str[21] -= 0x46;
      Str[22] -= 3;
      Str[23] -= 0x6B;
      strcpy(&Dest, Str);
    }
  }
  else
  {
    printf("String Length is Wrong");
  }
  return 0;
}

这个函数判断flag的长度是否为24,如果是的话,调用sub_4013B0(int a1),把第1到8位转换成8个数字,判断其是否满足下面的条件:

v1=flags[0]*1000+flags[1]*100+flags[2]*10+flags[3]
v2=flags[4]*10+flags[5]
v3=flags[6]*10+flags[7]
  • 2*(v1+v2)==4040
  • 3*v2/2+100*v3==115
  • v1-110*v3==1900

解出这个三元一次方程,可得flags前8位是20101001,之后程序会修改flags第21到24位,使用strcpy把flags复制到Dest中造成栈溢出,影响返回值地址。到现在为止,已经推算出了flags的前21位是20101001X1Y0uN3tG00dH,flags的后4位会修改函数的返回地址(传说中的栈溢出/Stackoverflow)

 

代码段位置基本都是0x0040****,又已知flags[20]==0x48

 

flags[20]-0x58==(-0x10)==0xF0
flags[21]-0x46==__
flags[22]-0x03==0x40
flags[23]-0x6B==0x00

 

所以除了第22位暂不确定外,程序的flags是:20101001X1Y0uN3tG00dH_Ck,程序的返回地址是0x0040**F0,由于代码量比较少,查找调用putsprintf的代码段,找到一个可疑的地方0x00401BF0,这个地方并没有定义函数,也没有函数直接调用这里,所以这应该就是目标返回地址了。

 

带入计算可得flags[21]=0x46+0x1B='a',所以flags可能是20101001X1Y0uN3tG00dHaCk,输入程序中,返回Success_Please_Input_The_Flag

 

但是之前搜索字符串时,并没有找到类似Success的字符串,这是因为这个字符串也被混淆了,执行下面的脚本,可以解密出字符串来。

s="Sta`anmXHc[VgXQ:^_caK?RNG-RFK÷\"K÷\"\""
for i in range(29):
    print(chr(ord(s[i])+i), end='')

[看雪官方培训] Unicorn Trace还原Ollvm算法!《安卓高级研修班》2021年秋季班火热招生!!

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