02--网鼎杯第一场

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Eira_H/article/details/82318671

0x01 Beijing

解题过程

拖进IDA查看main函数的伪C代码如下:

int __cdecl main()
{
  char v0; // al
  char v1; // al
  char v2; // al
  char v3; // al
  char v4; // al
  char v5; // al
  char v6; // al
  char v7; // al
  char v8; // al
  char v9; // al
  char v10; // al
  char v11; // al
  char v12; // al
  char v13; // al
  char v14; // al
  char v15; // al
  char v16; // al
  char v17; // al
  char v18; // al
  char v19; // al
  char v20; // al

  v0 = sub_8048460(dword_804A03C);
  printf("%c", v0);
  fflush(stdout);
  v1 = sub_8048460(dword_804A044);
  printf("%c", v1);
  fflush(stdout);
  v2 = sub_8048460(dword_804A0E0);
  printf("%c", v2);
  fflush(stdout);
  v3 = sub_8048460(dword_804A050);
  printf("%c", v3);
  fflush(stdout);
  v4 = sub_8048460(dword_804A058);
  printf("%c", v4);
  fflush(stdout);
  v5 = sub_8048460(dword_804A0E4);
  printf("%c", v5);
  fflush(stdout);
  v6 = sub_8048460(dword_804A064);
  printf("%c", v6);
  fflush(stdout);
  v7 = sub_8048460(dword_804A0E8);
  printf("%c", v7);
  fflush(stdout);
  v8 = sub_8048460(dword_804A070);
  printf("%c", v8);
  fflush(stdout);
  v9 = sub_8048460(dword_804A078);
  printf("%c", v9);
  fflush(stdout);
  v10 = sub_8048460(dword_804A080);
  printf("%c", v10);
  fflush(stdout);
  v11 = sub_8048460(dword_804A088);
  printf("%c", v11);
  fflush(stdout);
  v12 = sub_8048460(dword_804A090);
  printf("%c", v12);
  fflush(stdout);
  v13 = sub_8048460(dword_804A098);
  printf("%c", v13);
  fflush(stdout);
  v14 = sub_8048460(dword_804A0A0);
  printf("%c", v14);
  fflush(stdout);
  v15 = sub_8048460(dword_804A0A8);
  printf("%c", v15);
  fflush(stdout);
  v16 = sub_8048460(dword_804A0B0);
  printf("%c", v16);
  fflush(stdout);
  v17 = sub_8048460(dword_804A0B8);
  printf("%c", v17);
  fflush(stdout);
  v18 = sub_8048460(dword_804A0C0);
  printf("%c", v18);
  fflush(stdout);
  v19 = sub_8048460(dword_804A0C8);
  printf("%c", v19);
  fflush(stdout);
  v20 = sub_8048460(dword_804A0D0);
  printf("%c", v20);
  fflush(stdout);
  printf("\n");
  return 0;
}

发现从v0到v20这21个字符都是经过sub_8048460函数后输出,那么我们跟进这个函数:

int __cdecl sub_8048460(int a1)
{
  char v2; // [esp+Fh] [ebp-1h]

  switch ( a1 )
  {
    case 0:
      v2 = byte_804A021 ^ byte_804A020;
      break;
    case 1:
      v2 = byte_804A023 ^ byte_804A022;
      break;
    case 2:
      v2 = byte_804A025 ^ byte_804A024;
      break;
    case 3:
      v2 = byte_804A027 ^ byte_804A026;
      break;
    case 4:
      v2 = byte_804A029 ^ byte_804A028;
      break;
    case 5:
      v2 = byte_804A02B ^ byte_804A02A;
      break;
    case 6:
      v2 = byte_804A02D ^ byte_804A02C;
      break;
    case 7:
      v2 = byte_804A02F ^ byte_804A02E;
      break;
    case 8:
      v2 = byte_804A031 ^ byte_804A030;
      break;
    case 9:
      v2 = byte_804A033 ^ byte_804A032;
      break;
    case 10:
      v2 = byte_804A035 ^ byte_804A034;
      break;
    case 11:
      v2 = byte_804A037 ^ byte_804A036;
      break;
    case 12:
      v2 = byte_804A039 ^ byte_804A038;
      break;
    case 13:
      v2 = byte_804A03B ^ byte_804A03A;
      break;
    default:
      v2 = 0;
      break;
  }
  return v2;
}

从dword_804A03C起注意第一个数字都是双字,那么从v0到v20sub_8048460函数的参数分别为:0x6,0x9,?,0x1,0xa,?,0x8,?,0xb,0x2,0x3,0x1,0xd,0x4,0x5,0x2,0x7,0x2,0x3,0x1,0xc
从byte_804A020开始的数组的值如下:
这里写图片描述
按照顺序每两个字符异或后只有switch参数是0,1,2,3,4,6的时候才是正常字符,而这显然不是我们要的结果。而我们注意到每次异或的后面一项都是正常字符时,我们大胆猜测每次异或的前面那一项是干扰项,于是可以得出v0到v20输出结果为:fl?g{?m?zing_beijing}我们知道flag的格式为flag{……},那么?代表的字符就是a,带入得到最终flag为flag{amazing_beijing}

fflush(stdout)的作用

fflush(stdout):清空标准输出缓冲区。
fflush(stdin):清空标准输入缓冲区。
在使用多个输出(输入)函数进行连续多次输出(输入)的时候,因为上一个数据还没有输出(输入)完毕,还在缓冲区的时候,下一个输出(输入)函数就将另一个数据放入缓冲区,那么就覆盖掉了上一个数据,这样就会出现错误。但是如果加入fflush()函数及时进行刷新的话就不会出现这种错误。

eg1.

#include<stdio.h>
int main()
{
    char c;
    scanf("%c",&c);
    printf("0x%x\n",c);

    scanf("%c",&c);
    printf("0x%x\n",c);
    return 0;
}

我们在运行这个程序的过程中,如果只输入一个字符c,那么在我们的期待中输出的应该是0x63,但是在实际运行过程中输出的却是:
这里写图片描述
我们查看ascii码表发现0xa对应的是换行,也就是enter键,这说明scanf读取了两个字符,但是像换行这种字符明显不是我们所需要的,我们修改代码:

#include<stdio.h>
int main()
{
    char c;
    scanf("%c",&c);
    printf("0x%x\n",c);

    fflush(stdin);
    scanf("%c",&c);
    printf("0x%x\n",c);
    return 0;
}

此时输入c输出结果为0x63,控制台等待我们再一次输入然后再输出。
这里写图片描述
这才是我们想要的答案。通过这个例子我们更清楚的了解fflush(stdin)的作用。

eg2.在笔者测试的几个使用的fflush(stdout)的代码运行时看不出什么差别,若读者有好的实例欢迎分享。

0x02 Blend

解题过程

0x03 Advanced

解题过程

首先我们观察到src文件的类型不明确,我们将这个文件放在kali中运行一下,如果直接运行会提示权限不够,于是我们给其增加执行权限。

chmod +x src
./src

运行后得到:

welcome, here is your identification, please keep it in your pocket: 4b404c4b5648725b445845734c735949405c414d5949725c45495a51

我们联想到题目的提示:please keep identification in your pocket :)。我们有理由相信这串数据很重要。先将其转换成ASCII码看一下:K@LKVHr[DXEsLsYI@\AMYIr\EIZQ,并得不到什么有用的信息。flag的格式应该是flag{……},我们将已知的这六个字符与字符串进行异或,发现0x2D和0x2C交替出现,我们将字符串依次异或0x2D和0x2C,得到flag为:flag{d_with_a_template_phew}

猜你喜欢

转载自blog.csdn.net/Eira_H/article/details/82318671