1.0

有这么个东西
image.png

1.1

还是一样,有个对比
image.png

2.0

首先,在原位置还有一个对比
image.png

其次,在上面对输入的字符串做了变换
image.png

要注意的是字符串是从0开始数的

2.1

还是老位置的对比
注意对比之前的操作
image.png

将v3和v5交换,这两个是什么呢,v3是字符串的第三位,v5是buf之后的一个数据
image.png

同时需要注意一个问题,buf字符串是int类型,意味着只有4位,在输入的时候却获取了5位,结合上面的分析,将字符串的第三位和第五位交换

3.0

image.png
buf一共5位,不难理解吧?

3.1

这好像没啥区别
image.png

4.0

当时好好学c语言确实是个不错的选择
image.png

4.1

一样的内容,感觉这两题他的对比值不应该这么写=.=

5.0

异或嘛,整个小脚本就出来了
image.png

5.1

一样的东西咯
image.png

6.0

首先看程序都做了什么

  • 对输入的字符串,奇数位异或0xE3,偶数为异或0xA1
  • 以对称中心交换位置
  • 从小到大排序

并且现在我们知道排序之后的内容,那么就可以直接不用管其他,以现在的位置,奇数位异或0xE3,偶数位异或0xA1,下面两个无效果直接绕过
image.png

6.1

三次交换
image.png

7.0

整理程序流程:

  • 交换第1位和第17位
  • 两次异或
  • 排序
  • 反序

根据上述流程可以将密文初步解密(两次异或+交换1和17的位置),但是解出来的东西无法显示,用python脚本进行输入
image.png

7.1

switch需要修复,修复教程:
image.png

image.png

image.png

image.png

image.png

总结程序流程:

  • 第4位和第14位交换位置(buf和v13都是8字节,并且v13在buf下面紧邻)

    v3 = BYTE3(buf);
    BYTE3(buf) = BYTE5(v13);
    BYTE5(v13) = v3;

  • 倒序
  • 从小到大排序
  • 再次倒序
  • 5个一组进行异或处理

说白了就是一堆排序外加一个异或处理,那么就可以直接异或回去找输入

#include<iostream>
using namespace std;

int main(int argc, char const *argv[])
{
    int buf[] = {0x0F, 0x04, 0x7B, 0x47, 0xBF, 0x0C, 0x06, 0x79, 0x4A, 0xB0, 
  0x01, 0x0D, 0x70, 0x52, 0xAA, 0x18, 0x12, 0x6A, 0x56, 0xAE, 
  0x1F, 0x16, 0x67, 0x59, 0xA6, 0x16, 0x1C, 0x63, 0x5C, 0x00};


    for (int n = 0; n <= 28; ++n )
  {
      switch ( (n % 5) )
      {
        case 0:
          *(buf + n) ^= 0x75;
          break;
        case 1:
          *(buf + n) ^= 0x7E;
          break;
        case 2:
          *(buf + n) ^= 1; 
          break;
        case 3:
          *(buf + n) ^= 0x3D;
          break;
        case 4:
          *(buf + n) ^= 0xC5;
          break;
        default:
          continue;
      }
  }


    for(int i =0; i<=28; i++)
    {
        printf("%c", buf[i]);
    }
    return 0;
}

8.0

首先修复switch
image.png

分析:

  • 从小到大排序
  • 奇偶位进行不同的异或处理
  • 同上
  • 倒序
  • 六个一组进行异或处理
  • 交换第14和第17位数据
  • 交换第6和第33位

这次的交换就需要先处理了,应为交换是放在最后的,所以一定会影响最终结果

#include<iostream>
using namespace std;

int main(int argc, char const *argv[])
{
    int buf[] = {0xA6, 0x4E, 0x73, 0xB2, 0x56, 0x67, 0xA9, 0x40, 0x71, 0xB0, 
  0x55, 0x68, 0xAD, 0x4B, 0x75, 0xAE, 0x44, 0x71, 0xB6, 0x5F, 
  0x6C, 0xA2, 0x47, 0x7D, 0xBA, 0x53, 0x61, 0xA1, 0x45, 0x7F, 
  0xBB, 0x52, 0x6D, 0xA6, 0x43, 0x79, 0xBD, 0x00};

    int a=buf[5];
    buf[5] = buf[32];
    buf[32] = a;

    a= buf[13];
    buf[13] = buf[16];
    buf[16] = a;

    for (int i1 = 0; i1 <= 36; ++i1 )
  {
    if ( (i1 % 6) <= 5 )
    {
      switch ( i1 % 6 )
      {
        case 0:
          *(buf + i1) ^= 0xB5;
          break;
        case 1:
          *(buf + i1) ^= 0x73;
          break;
        case 2:
          *(buf + i1) ^= 0x6E;
          break;
        case 3:
          *(buf + i1) ^= 0x80;
          break;
        case 4:
          *(buf + i1) ^= 0x4B;
          break;
        case 5:
          *(buf + i1) ^= 0x5E;
          break;
        default:
          continue;
      }
    }
  }

    for (int n = 0; n <= 36; ++n )
  {
    if ( n % 2 )
    {
        *(buf + n) ^= 0x67;
        *(buf + n) ^= 0x22;
    }
    else
    {
      *(buf + n) ^= 0x1A;
      *(buf + n) ^= 0x70;
    }
  }




    for(int i =0; i<=36; i++)
    {
        printf("%c", buf[i]);
    }
    return 0;
}

8.1

流程分析

  • 小到大排序
  • 交换第5和21位
  • 交换第2和25位
  • 交换第6和26位
  • 四个一组进行异或处理
  • 交换第4和30位
  • 倒序

按照顺序写脚本吧

#include<iostream>
using namespace std;

int main(int argc, char const *argv[])
{
    int buf[] = {0x11, 0xFA, 0x4E, 0x66, 0x1E, 0x65, 0x4C, 0x74, 0x1A, 0xE6, 
  0x49, 0x68, 0x06, 0xEC, 0x5D, 0x69, 0x04, 0xEE, 0x52, 0x6E, 
  0x01, 0xEA, 0x51, 0x6F, 0x0E, 0xE5, 0x5C, 0x62, 0x0C, 0xF0, 
  0x57, 0xF7, 0x0B, 0xF5, 0x58, 0x00};

    for (int m = 0; m <= 16; ++m )
  {
    int v8 = *(buf + m);
    *(buf + m) = *(buf + 34 - m);
    *(buf + 34 - m) = v8;
  }

    int a = buf[3];
    buf[3] = buf[29];
    buf[29] = a;

    for (int k = 0; k <= 34; ++k )
  {
    int v3 = k % 4;
    if ( k % 4 == 3 )
    {
      *(buf + k) ^= 7u;
    }
    else if ( v3 <= 3 )
    {
      if ( v3 == 2 )
      {
        *(buf + k) ^= 0x69u;
      }
      else if ( v3 <= 2 )
      {
        if ( v3 )
        {
          if ( v3 == 1 )
            *(buf + k) ^= 0x82u;
        }
        else
        {
          *(buf + k) ^= 0x39u;
        }
      }
    }
  }

    a = buf[6];
    buf[6] = buf[26];
    buf[26] = a;

    a = buf[2];
    buf[2] = buf[25];
    buf[25] = a;

    a = buf[5];
    buf[5] = buf[21];
    buf[21] = a;


    for(int i =0; i<0x23; i++)
    {
        printf("%c", buf[i]);
    }
    return 0;
}

9.0

考的是patch,程序给了任意patch的能力,注意这个v12是程序加载基址
image.png

这样的话将下面的jnz改成jz就行,或者直接nop掉

9.1

同上

10.0

同上,注意只能改一个字节

10.1

同上

11.0

同上,只不过需要改两处

11.1

大致一样,注意第一个跳转
image.png

12.0

vm题,挺好玩,也就费了我一中午时间(T_T),输入我用的py进行输入的

[s] IMM b = 0x62
[s] IMM c = 0x8
[s] IMM a = 0
[s] SYS 0x4 a
[s] ... read_memory ----> read a1[0x62]
aaa
[s] ... return value (in register a): 0x4
[s] IMM b = 0x82
[s] IMM c = 0x1
[s] IMM a = 0xc8
[s] STM *b = a ----> a1[b]=a ====> a1[0x82]=0xc8
[s] ADD b c ----> b=b+c ====> b=0x83
[s] IMM a = 0xfc
[s] STM *b = a ----> a1[b]=a ====> a1[0x83]=0xfc
[s] ADD b c ----> b=b+c ====> b=0x84
[s] IMM a = 0x5b
[s] STM *b = a ----> a1[b]=a ====> a1[0x84]=0x5b
[s] ADD b c
[s] IMM a = 0xa8
[s] STM *b = a ----> a1[b]=a ====> a1[0x85]=0xa8
[s] ADD b c
[s] IMM a = 0x58
[s] STM *b = a ----> a1[b]=a ====> a1[0x86]=0x58
[s] ADD b c
[s] IMM a = 0xf4
[s] STM *b = a ----> a1[b]=a ====> a1[0x87]=0xf4
[s] ADD b c
[s] IMM a = 0x6b
[s] STM *b = a ----> a1[b]=a ====> a1[0x88]=0x6b
[s] ADD b c
[s] IMM a = 0xce
[s] STM *b = a ----> a1[b]=a ====> a1[0x89]=0xce
[s] ADD b c

v2 = memcmp((const void *)(a1 + 0x82), (const void *)(a1 + 0x62), 8uLL) == 0;

Q.E.D.


来都来了,点个广告再走吧(=・ω・=)