• 网鼎杯2020 joker逆向


    gcc编译,无壳:

    看一下程序结构:

    程序有函数分析错误,堆栈的原因,我就没改它了,因为汇编也简单,上手就撸:

    第一个关键块:

    4017DD就是一个字符串拷贝函数,动态可见,然后4017EB是第一个无用函数,看一下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    char *__cdecl wrong(char *a1)
    {
      char *result; // eax
      signed int i; // [esp+Ch] [ebp-4h]
     
      for ( i = 0; i <= 23; ++i )
      {
        if ( i & 1 )
        {
          result = &a1[i];
          a1[i] -= i;
        }
        else
        {
          result = &a1[i];
          a1[i] ^= i;
        }
      }
      return result;
    }

    a1就是输入的flag,简单操作之后到4017F9函数判断:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    int __cdecl omg(char *a1)
    {
      int result; // eax
      int v2[24]; // [esp+18h] [ebp-80h]
      int i; // [esp+78h] [ebp-20h]
      int v4; // [esp+7Ch] [ebp-1Ch]
     
      v4 = 1;
      qmemcpy(v2, byte_4030C0, sizeof(v2));
      for ( i = 0; i <= 23; ++i )
      {
        if ( a1[i] != v2[i] )
          v4 = 0;
      }
      if ( v4 == 1 )
        result = puts("hahahaha_do_you_find_me?");
      else
        result = puts("wrong ~~ But seems a little program");
      return result;
    }

    byte_4030C0是硬编码字符,大概逆一下得到虚假flag:

    byte_4030c0=[0x66, 0x6B, 0x63, 0x64, 0x7F, 0x61,  0x67, 0x64, 0x3B, 0x56, 0x6B, 0x61, 0x7B, 0x26, 0x3B, 0x50, 0x63, 0x5F, 0x4D, 0x5A, 0x71, 0x0C, 0x37, 0x66]

    flag=""

    for i in range(23):

        if i &1:

            byte_4030c0[i]+=i

        else:

            byte_4030c0[i]^=i

    for i in range(23):

        flag+=chr(byte_4030c0[i])

    print(flag)

    flag{fak3_alw35_sp_me!!

    肯定是不对的,然后下面这块吸引我的注意:

    有smc操作,而且代码中确实有很多没有解释的byte,解密函数很简单,写idc也行,我直接动态调试:

    虚假函数nop掉:

    这就是刚刚的fake函数,nop掉就行:

    下面就是自解密函数:

    解密位置是401500,断在182D,然后过掉看结果:

    之后就是调用这块代码了:

    跟进去,单步可以看得到懂逻辑的:

    大概意思就是输入的位数,和hahahaha_do_you_find_me?这个字符串异或之后,等于3040位置的硬编码值

    意思很简单,单步就ok

    然后解密得到前部分flag:

    str=[0x0E,0x0D,0x09,0x06,0x13,0x05,0x58,0x56,0x3E,0x06,0x0C,0x3C,0x1F,0x57,0x14,0x6B,0x57,0x59,0x0D]

    str2="hahahaha_do_you_find_me?"

    flag=""

    for i in range(19):

        flag+=chr(str[i]^ ord(str2[i]))

    print(flag)

    flag{d07abccf8a410c

    但是位数明显不够,少5位,还有一个finall函数:

    动态的时候这一步改jmp,或者z=0过掉:

    进入final函数:

    如果是字节强制分析就成:

    时间函数过滤,没用:

    会得到%tp&:  五个字符,后面竟然和前面的flag{做比较

    所以忙猜这是flag最后的五个字节,:就是 }的异或答案,那么:答案就是b37a}

    所以

    flag{d07abccf8a410cb37a}

    总结:感染函数,自解密很到位,但最后的函数确实有点无脑,这样盲猜不适合大型比赛,不行就好好整算法题目像kctf一样(手动狗头.jpg)

  • 相关阅读:
    Wwise音频解决方案概述
    图形学中的几何光学理论与视觉现象
    Visual Studio 2015 Tools for Unity使用基础
    C++编译器优化技术:RVO、NRVO和复制省略
    【ElasticSearch】 ElasticSearch基本概念和RESTful API(四)
    【ElasticStack】入门介绍(三)
    【Java】开发一个Java-SDK
    【Java】Maven 打包可运行jar包
    【SpringBoot】Spring Boot Admin 微服务应用监控
    【Java面试题】方法的参数传递机制
  • 原文地址:https://www.cnblogs.com/jentleTao/p/12865189.html
Copyright © 2020-2023  润新知