zoukankan      html  css  js  c++  java
  • 2019 湖湘杯 Reverse WP

    0x01 arguement

    下载链接:https://www.lanzous.com/i7atyhc

    1.准备

    获取到信息:

    1. 32位的文件
    2. upx加密文件

    在控制台打开文件

    使用"upx -d reverse.exe"解密

    2.IDA打开

    直接在String中,找到引用"Input Your Flag:"的位置

    int __usercall sub_415280@<eax>(int xmm0_4_0@<xmm0>, int a1, int a2)
    {
      int v3; // edx
      FILE *v4; // eax
      int v5; // edx
      int v6; // ecx
      char *v7; // eax
      int v8; // edx
      int v9; // ecx
      int v10; // ST04_4
      int v11; // ST08_4
      char v13; // [esp+0h] [ebp-134h]
      char Buf; // [esp+D0h] [ebp-64h]
      size_t i; // [esp+100h] [ebp-34h]
      FILE *File; // [esp+10Ch] [ebp-28h]
      char v17; // [esp+118h] [ebp-1Ch]
      int v18; // [esp+130h] [ebp-4h]
      int savedregs; // [esp+134h] [ebp+0h]
    
    
      sub_411208((int)&unk_41C008);
      printf("Input Your Flag:
    ", v13);
      sub_41137F("%19s", (unsigned int)&v17);       // v12大小为24
      if ( a1 != 2 )
      {
        printf("Input error!
    ", v13);
        exit(1);
      }
      printf("%s
    ", *(_DWORD *)(a2 + 4));          // 在执行文件时,执行的第一个参数
      for ( i = 0; i < j_strlen(*(const char **)(a2 + 4)); ++i )// 遍历执行文件时输入的字符串
        *(_BYTE *)(*(_DWORD *)(a2 + 4) + i) += i;   // 每一位 str[i] += i
      if ( !j_strcmp(Str1, *(const char **)(a2 + 4)) )// 和“fmcj2y~{”比较
      {
        v4 = fopen(*(const char **)(a2 + 4), "r");  // 下面两句文件操作,应该是获取输入的
        File = (FILE *)sub_411212(v6, v5, &v13 == &v13, (int)v4, xmm0_4_0);
        if ( File )
        {
          v7 = fgets(&Buf, 40, File);
          sub_411212(v9, v8, &v13 == &v13, (int)v7, xmm0_4_0);
          if ( j_strlen(&Buf) != 32 || j_strlen(&Buf) % 2 == 1 )// 输入长度应该是32
            exit(1);
          sub_4113B1(xmm0_4_0, &Buf, (int)&unk_41A4E0);
          if ( sub_4113B6(xmm0_4_0, (int)&unk_41A4E0) )
            printf("flag{%s}", (unsigned int)&Buf);
          else
            printf("Input Error!
    ", v13);
        }
        else
        {
          printf("Input Error!
    ", v13);
        }
      }
      else
      {
        printf("Input Error!
    ", v13);
      }
      sub_411235(&savedregs, dword_4154C4, 0, v3);
      return sub_411212((unsigned int)&savedregs ^ v18, v11, 1, v10, xmm0_4_0);
    }

    因此在运行时文件我们要在后面带一个参数,这个参数通过分析代码,我们可以写个脚本解出

    str1 = 'fmcj2y~{'
    
    str2 = ''
    
    for i in range(len(str1)):
        str2 += chr(ord(str1[i]) - i)
    
    print (str2

    3.代码分析

    通过分析,可以知道关键的函数是sub_4113B1sub_4113B6

    3.1 sub_4113B1函数

    int __usercall sub_414E50@<eax>(int a1@<xmm0>, char *Str, int a3)
    {
      unsigned int v3; // eax
      int v4; // edx
      int v5; // ecx
      char v7; // [esp+0h] [ebp-E4h]
      int v8; // [esp+D0h] [ebp-14h]
      signed int i; // [esp+DCh] [ebp-8h]
    
    
      sub_411208((int)&unk_41C008);
      dword_41A078[8] = 0xA7;
      dword_41A078[9] = 0xDE;
      dword_41A078[10] = 0xDA;
      dword_41A078[11] = 0x46;
      dword_41A078[12] = 0xAB;
      dword_41A078[13] = 0x2E;
      dword_41A078[14] = 0xFF;
      dword_41A078[15] = 0xDB;
      for ( i = 0; ; i += 2 )                       // 0开始,2跳
      {
        v3 = j_strlen(Str);                         // v3为Buf长度32
        if ( i >= v3 )
          break;
        if ( Str[i] >= 48 && Str[i] <= 57 )         // '0'~'9'
        {
          *(_DWORD *)(a3 + 4 * (i / 2)) = Str[i] - 48;// 字符转换为整型
        }
        else
        {
          if ( Str[i] < 97 || Str[i] > 102 )        // 非'a'~'f',说明组成的字符是'0'~'9'||'a'~'f',十六进制啊
          {
            printf("Input Error!
    ", v7);
            exit(0);
          }
          *(_DWORD *)(a3 + 4 * (i / 2)) = Str[i] - 87;// 十六进制啊!'a'~'f'就是10~15
        }
        *(_DWORD *)(a3 + 4 * (i / 2)) *= 16;        // 最后还要乘16
        if ( Str[i + 1] >= 48 && Str[i + 1] <= 57 ) // i=1,3,5...如果为数字
        {
          v8 = Str[i + 1] - 48;                     // v8=字符转数字
        }
        else
        {
          if ( Str[i + 1] < 97 || Str[i + 1] > 102 )
          {
            printf("Input Error!
    ", v7);
            exit(0);
          }
          v8 = Str[i + 1] - 87;                     // i=1,3,5...如果是'a'~'f'字符转数字,10~15
        }
        *(_DWORD *)(a3 + 4 * (i / 2)) += v8;        // a3[i]+=v8
      }
      return sub_411212(v5, v4, 1, v3, a1);
    }

    这个函数有两个作用:

    1. 对dword_41A078后8双字节赋值
    2. 将输入的字符串,两两字符转换为数字,存入v4,例如:输入"a1b2c3"将会转换为0xa1b2c3

    3.2 sub_4113B6函数

    int __usercall sub_411D90@<eax>(int a1@<xmm0>, int a2)
    {
      int v2; // edx
      int v3; // ecx
      int v4; // eax
      signed int i; // [esp+D0h] [ebp-8h]
    
    
      sub_411208((int)&unk_41C008);
      for ( i = 0; i < 16; ++i )
      {
        v3 = a2;                                    // v3赋值为之前得到的整数
        v2 = *(_DWORD *)(a2 + 4 * i) + 1;           // v2=v2[i]+1
        if ( v2 != dword_41A078[i] )
        {
          v4 = 0;
          return sub_411212(v3, v2, 1, v4, a1);
        }
      }
      v4 = 1;
      return sub_411212(v3, v2, 1, v4, a1);
    }

    这个函数将我们转换输入字符串得到的v4。每一位加1之后与已知的dword_41A078数组比较。

    dword_41A078

    50h 0C6h 0F1h 0E4h 0E3h 0E2h 9Ah 0A1h 0A7h 0DEh 0DAh 46h 0ABh 2Eh 0FFh 0DBh

    因此我们只要将dword_41A078每一位减1,就能得到v4,从而输入的Buf也得到了了

    v4

    4fc5f0e3e2e199a0a6ddd945aa2dfeda

    Buf

    "4fc5f0e3e2e199a0a6ddd945aa2dfeda"

    而回到主函数

    if ( sub_4113B6(xmm0_4_0, (int)&unk_41A4E0) )
        printf("flag{%s}", (unsigned int)&Buf);

    flag就是flag{Buf}

    4.get flag!

    flag{4fc5f0e3e2e199a0a6ddd945aa2dfeda}

    0x02 EzRE

    下载链接:https://www.lanzous.com/i7atzwd

     原题:

    https://www.jianshu.com/p/7fdfe2333123

    http://www.pianshen.com/article/8985544588/

    flag{#FFRFFF####ZZRZZZ##FF#FFFF}

     

    0x03 icekey

    下载链接:https://www.lanzous.com/i7atzwd

    使用dnSpy打开之后,找到main函数打开

    这通过观察反编译的C#代码,能够知道这段代码就是将我们输入的字符串经过加密后,与b="3ACF8D62AAA0B630C4AF43AF327CE129D46F0FEB98D9040F713BE65502A5107A"比较,相同则返回true否则返回false。

    并且这段代码还很贴心的在下面写出了解密函数,因此只需要在我们调试中,输入字符串并加密后,将调试窗口处的array数组和bytes数组改为与b数组相等即可(因为在加密和比较中用到了这两个数组)

    最终,调试至程序结束,我们能够在内存窗口追踪到bytes解密后的字符数组,即为我们正确的输入:

    5acb06231724c8c369bae711166dbe85

    0x04 android

    下载链接:https://www.lanzous.com/i7au7pe

     2019中国杭州网络安全技能大赛 预选赛原题,不过没解完。

    https://xhyeax.github.io/2019/04/07/2019-hzwas-wp/

    0x05 总结

    湖湘杯又被吐槽了...Reverse基本都是签到题,菜鸡做着还是舒服。

  • 相关阅读:
    HDU4341 Gold miner 分组背包
    卡特兰数
    欧拉函数
    求一个阶乘数尾零的个数
    线性时间 筛素数,求前n个数的欧拉函数值,求前n个数的约数个数
    HDU4335 What is N? 欧拉函数,欧拉定理
    HDU4336 Card Collector 容斥定理 Or 概率DP
    ie8恶心的bug4个小时的教训
    39个超实用jQuery实例应用特效
    ECSHOP 模板结构说明
  • 原文地址:https://www.cnblogs.com/Mayfly-nymph/p/11837962.html
Copyright © 2011-2022 走看看