攻防世界 Reverse Hello,CTF

ida反编译

下载下来是一个exe,直接拖到ida然后f5查看源码

int __cdecl main(int argc, const char **argv, const char **envp)
{
  signed int v3; // ebx
  char v4; // al
  int result; // eax
  int v6; // [esp+0h] [ebp-70h]
  int v7; // [esp+0h] [ebp-70h]
  char v8; // [esp+12h] [ebp-5Eh]
  char v9[20]; // [esp+14h] [ebp-5Ch]
  char v10; // [esp+28h] [ebp-48h]
  __int16 v11; // [esp+48h] [ebp-28h]
  char v12; // [esp+4Ah] [ebp-26h]
  char v13; // [esp+4Ch] [ebp-24h]

  strcpy(&v13, "437261636b4d654a757374466f7246756e"); //将字符串拷贝进v13中
  while ( 1 )
  {
    memset(&v10, 0, 0x20u); //最后的u是unsigned的意思,将v10的前32个字符置为0
    v11 = 0;
    v12 = 0;
    sub_40134B(aPleaseInputYou, v6); //sub_40134B()这个函数就是会输出'aPleaseInputYou'这个里面的存的东西,我也没搞懂是干啥的
    scanf(aS, v9); //读取aS存入v9
    if ( strlen(v9) > 0x11 ) //如果v9的长度大于17就报错
      break;
    v3 = 0;
    do
    {
      v4 = v9[v3];
      if ( !v4 ) //v4为0x00时跳出
        break;
      sprintf(&v8, asc_408044, v4); //asc_408044在ida中查看,值是'%x'
      strcat(&v10, &v8); //把v8复制给v10
      ++v3;
    }
    while ( v3 < 17 );
    if ( !strcmp(&v10, &v13) ) //读到的字符串在sprintf()中被处理,与v13进行比较,具体操作后面分析
      sub_40134B(aSuccess, v7); //一致则输出成功
    else
      sub_40134B(aWrong, v7);
  }
  sub_40134B(aWrong, v7); //这里开始就没太看懂,盲猜是用来重启程序的,希望高人指点二三
  result = stru_408090._cnt-- - 1;
  if ( stru_408090._cnt < 0 )
    return _filbuf(&stru_408090);
  ++stru_408090._ptr;
  return result;
}

里面涉及到了几个c库的基本函数,之前不是很懂,尤其是本题中最重要的sprintf(),在这个博客做了一下笔记,memset()函数见这里

解题

先从上到下看一遍,大致流程如下:

  1. "437261636b4d654a757374466f7246756e"存入v13
  2. 读入用户输入的字符串到v9
  3. sprintf()处理输入的字符串,并将处理后的字符串存入v8中,而后v8中的值又被复制给v10
  4. 比较v13v10中的值是否相同

在整道题中,关键的一个函数就是sprintf(),这个函数处理了用户输入的字符串,在这里sprintf()的三个参数分别为一个用来存放字符串的指针x%用户输入字符串中挨个取出的字母,其中的x%是一个格式化参数,它可以将后面的字符转成16进制的对应的数字,因此这道题的flag,也就是输入的值,就是把上面那一堆数转成字符串,即CrackMeJustForFun

学习到了啥

  1. sprintf()函数的用法
  2. memset()函数的作用,可以将指针存储的字符串的前n位全部替换成想要的字符,位数不变
  3. sub_40134B()用来输出字符串

你可能感兴趣的:(#,攻防世界)