一次脱单的机会-西南赛区线下赛

题目是一个大佬发的,说是西南赛区的一道逆向题目

解压出来是一个exe文件

在这里插入图片描述

运行起来是这样的

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

先看文件信息,没有加壳,64位程序

在这里插入图片描述

用IDA64位打开,分析代码

int __cdecl main(int argc, const char **argv, const char **envp)
{
  unsigned int v3; // eax
  double v4; // xmm1_8
  int v5; // xmm0_4
  int i; // eax
  float v7; // xmm2_4
  const char *v8; // rbx
  __m128i si128; // xmm2
  __int64 v10; // rbx
  unsigned int v11; // eax
  const char *v12; // rbx
  int v14; // [rsp+20h] [rbp-98h] BYREF
  int v15[3]; // [rsp+24h] [rbp-94h] BYREF
  __int128 v16[5]; // [rsp+30h] [rbp-88h]

  v3 = time64(0i64);
  srand(v3);
  v4 = (double)rand() / 100000.0;
  *(float *)&v5 = v4 + 491.0;
  dword_14000563C = v5;
  *(float *)&dword_140005638 = v4 + 10.0;
  if ( IsDebuggerPresent() )
LABEL_22:
    exit(1);
  printf("\n");
  printf("\n");
  printf(asc_140003288);
  printf("\n");
  printf(asc_1400032C8);
  printf("\n");
  printf(asc_1400032F0);
  printf("\n");
  printf(asc_140003318);
  printf("\n");
  printf(asc_140003348);
  printf("\n");
  printf(asc_140003378);
  printf("\n");
  printf(asc_1400033A0);
  printf("\n");
  printf(asc_1400033D0);
  printf("\n");
  printf(asc_140003408);
  printf("\n");
  printf("---------------------------------------------------------------------------\n");
  printf("\n");
  printf(asc_140003490);
  printf("\n");
  printf(asc_1400034A8, dword_14000563C);
  printf("\n");
  printf(asc_1400034C0, dword_140005638);
  printf("\n");
  printf(a1);
  printf("\n");
  printf(a2);
  printf("\n");
  printf(asc_140003510);
  scanf("%d", &v14, 1i64);
  for ( i = v14; v14 == 1; i = v14 )
  {
    printf("\n");
    printf(asc_140003528);
    scanf("%d", v15, 3i64);
    if ( v15[0] > 9 || (v7 = (float)v15[0], (float)v15[0] > (float)(501.0 - *(float *)&dword_14000563C)) )
    {
      v8 = (const char *)&unk_140003540;
    }
    else if ( v15[0] > 0 )
    {
      v8 = (const char *)&unk_140003568;
      *(float *)&dword_14000563C = *(float *)&dword_14000563C + v7;
      *(float *)&dword_140005638 = *(float *)&dword_140005638 - v7;
    }
    else
    {
      v8 = asc_140003558;
    }
    printf("\n");
    printf(v8);
    printf("\n");
    if ( *(float *)&dword_140005638 <= 0.0 )
    {
      if ( IsDebuggerPresent() )
        goto LABEL_22;
      printf("f");
      if ( IsDebuggerPresent() )
        goto LABEL_22;
      printf("l");
      if ( IsDebuggerPresent() )
        goto LABEL_22;
      printf("ag");
      printf("{md5(");
      si128 = _mm_load_si128((const __m128i *)&xmmword_1400035F0);
      v10 = 0i64;
      v11 = _mm_cvtsi128_si32(si128);
      v16[2] = (__int128)_mm_load_si128((const __m128i *)&xmmword_1400035D0);
      v16[1] = (__int128)_mm_load_si128((const __m128i *)&xmmword_1400035E0);
      v16[0] = (__int128)si128;
      v16[3] = (__int128)si128;
      for ( v16[4] = 0i64; v11; v11 = *((_DWORD *)v16 + v10) )
      {
        printf("%c", v11);
        ++v10;
      }
      if ( IsDebuggerPresent() )
        goto LABEL_22;
      printf(")");
      if ( IsDebuggerPresent() )
        goto LABEL_22;
      printf("}");
    }
    printf("---------------------------------------------------------------------------\n");
    printf("\n");
    printf(asc_140003490);
    printf("\n");
    printf(asc_1400034A8, dword_14000563C);
    printf("\n");
    printf(asc_1400034C0, dword_140005638);
    printf("\n");
    printf(a1);
    printf("\n");
    printf(a2);
    printf("\n");
    printf(asc_140003510);
    scanf("%d", &v14, 1i64);
  }
  v12 = (const char *)&unk_140003578;
  if ( i != 2 )
    v12 = asc_140003590;
  printf("\n");
  printf(v12);
  getchar();
  getchar();
  return 0;
}

一点点分析,这里面有好几个检测动态调试的函数

 if ( IsDebuggerPresent() )
LABEL_22:
    exit(1);

这里这段就是输出flag了,跟进查看,也看不出什么,只能用动态调试了

 printf("f");
      if ( IsDebuggerPresent() )
        goto LABEL_22;
      printf("l");
      if ( IsDebuggerPresent() )
        goto LABEL_22;
      printf("ag");
      printf("{md5(");
      si128 = _mm_load_si128((const __m128i *)&xmmword_1400035F0);
      v10 = 0i64;
      v11 = _mm_cvtsi128_si32(si128);
      v16[2] = (__int128)_mm_load_si128((const __m128i *)&xmmword_1400035D0);
      v16[1] = (__int128)_mm_load_si128((const __m128i *)&xmmword_1400035E0);
      v16[0] = (__int128)si128;
      v16[3] = (__int128)si128;
      for ( v16[4] = 0i64; v11; v11 = *((_DWORD *)v16 + v10) )
      {
        printf("%c", v11);
        ++v10;
      }
      if ( IsDebuggerPresent() )
        goto LABEL_22;
      printf(")");
      if ( IsDebuggerPresent() )
        goto LABEL_22;
      printf("}");

x64debug 打开,f8单步运行,运行到这里调用的是main函数

在这里插入图片描述

在这里插入图片描述

f7跟进查看

在这里插入图片描述

这里对应的就是开始的那个检测动态调试的地方

在这里插入图片描述
在这里插入图片描述

然后就是一步步运行分析了,我是分析过的,我就直接说简单方法了:搜索字符串

这里有个输出md5( 的,那么在注释里面应该有这段字符串,直接搜索

在这里插入图片描述

在这里插入图片描述

过滤一下,双击跳转

在这里插入图片描述

在这之前下个断点,记下地址 00007FF73737143F

在这里插入图片描述

执行到这个检测这个debug的地方

在这里插入图片描述

把下面那一句 test eax,eax 改成 jmp 00007FF73737143F,选择剩下字节以nop
填充

在这里插入图片描述

然后直接执行跳到那里就行

在这里插入图片描述

执行结果: ag{md5(女神早已不是女神,这里flag已经出来了,可以不用继续了

在这里插入图片描述

后面这两个检测是否有动态调试的函数,后面的输出也只是把括号补全而已

在这里插入图片描述
在这里插入图片描述

补全后的结果:ag{md5(女神早已不是女神)}

在这里插入图片描述

然后再md5加密一下

md5(女神早已不是女神,32) = 056a5ae5aa88a2151e96ba83948b83aa
md5(女神早已不是女神,16) = aa88a2151e96ba83

最终flag:

flag{056a5ae5aa88a2151e96ba83948b83aa} 或者 flag{aa88a2151e96ba83} (咱也没进到线下赛,也不知道哪个对的)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ofo300

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值