[BUUCTF]REVERSE——[网鼎杯 2020 青龙组]singal

[网鼎杯 2020 青龙组]singal

附件

步骤

  1. 例行检查,32位程序,无壳
    在这里插入图片描述
  2. 本地试运行一下程序
    在这里插入图片描述
  3. 32位ida载入,首先是找到main函数确定了flag字符串的样式flag{……}
    在这里插入图片描述
    根据输入点的提示字符串,找到对应函数,确定了字符串的长度是15
    在这里插入图片描述
    右击该函数,找到调用该函数的地方,来到了vm_operad()函数处,看main函数可以知道,vm_operad里的参数v4在上面一行调用了qmemcpy函数,百度上说逆向里的qmemcpy=memcpy,memcpy在c语言里的拷贝函数,在unk_403040中拷贝了0x1C8字节的数据给v4
    unk_403040这个地址上有好多数据拷贝0x1C8个就是到0x403208
    在这里插入图片描述
    选中,shift+e转换成数组
    在这里插入图片描述
    4字节等于一个int,interl处理器是小端存储,刚好a1数组的值就是三个00之前那十六进制,整理一下得到
    v4=[10, 4, 16, 8, 3, 5, 1, 4, 32, 8, 5, 3, 1, 3, 2, 8, 11, 1, 12, 8, 4, 4, 1, 5, 3, 8, 3, 33, 1, 11, 8, 11, 1, 4, 9, 8, 3, 32, 1, 2, 81, 8, 4, 36, 1, 12, 8, 11, 1, 5, 2, 8, 2, 37, 1, 2, 54, 8, 4, 65, 1, 2, 32, 8, 5, 1, 1, 5, 3, 8, 2, 37, 1, 4, 9, 8, 3, 32, 1, 2, 65, 8, 12, 1]
    这里要注意32位程序存储的时候的小端序的问题,我这边先不逆序,下面还要找一下内存中处理的时候的一些数据

接着调用了该数组和114进入了vm_operad函数

int __cdecl vm_operad(int *a1, int _114)
{
  int result; // eax
  char Str[200]; // [esp+13h] [ebp-E5h] BYREF
  char v4; // [esp+DBh] [ebp-1Dh]
  int v5; // [esp+DCh] [ebp-1Ch]
  int v6; // [esp+E0h] [ebp-18h]
  int v7; // [esp+E4h] [ebp-14h]
  int v8; // [esp+E8h] [ebp-10h]
  int v9; // [esp+ECh] [ebp-Ch]

  v9 = 0;
  v8 = 0;
  v7 = 0;
  v6 = 0;
  v5 = 0;
  while ( 1 )
  {
    result = v9;
    if ( v9 >= _114 )
      return result;
    switch ( a1[v9] )
    {
      case 1:
        Str[v6 + 100] = v4;
        ++v9;
        ++v6;
        ++v8;
        break;
      case 2:
        v4 = a1[v9 + 1] + Str[v8];
        v9 += 2;
        break;
      case 3:
        v4 = Str[v8] - LOBYTE(a1[v9 + 1]);
        v9 += 2;
        break;
      case 4:
        v4 = a1[v9 + 1] ^ Str[v8];
        v9 += 2;
        break;
      case 5:
        v4 = a1[v9 + 1] * Str[v8];
        v9 += 2;
        break;
      case 6:
        ++v9;
        break;
      case 7:
        if ( Str[v7 + 100] != a1[v9 + 1] )
        {
          printf("what a shame...");
          exit(0);
        }
        ++v7;
        v9 += 2;
        break;
      case 8:
        Str[v5] = v4;
        ++v9;
        ++v5;
        break;
      case 10:
        read(Str);
        ++v9;
        break;
      case 11:
        v4 = Str[v8] - 1;
        ++v9;
        break;
      case 12:
        v4 = Str[v8] + 1;
        ++v9;
        break;
      default:
        continue;
    }
  }
}

当值等于7时str数组的值会与a1数组的下一位进行比较,相等继续,不等报错。7后面的数字就是正确输入进行加密后需要与之比较的值,刚好7这个值在a1数组的最后,将这串值提取出来

str=[]
a1=[10, 4, 16, 8, 3, 5, 1, 4, 32, 8, 5, 3, 1, 3, 2, 8, 11, 1, 12, 8, 4, 4, 1, 5, 3, 8, 3, 33, 1, 11, 8, 11, 1, 4, 9, 8, 3, 32, 1, 2, 81, 8, 4, 36, 1, 12, 8, 11, 1, 5, 2, 8, 2, 37, 1, 2, 54, 8, 4, 65, 1, 2, 32, 8, 5, 1, 1, 5, 3, 8, 2, 37, 1, 4, 9, 8, 3, 32, 1, 2, 65, 8, 12, 1, 7, 34, 7, 63, 7, 52, 7, 50, 7, 114, 7, 51, 7, 24, 7, 167, 255, 255, 255, 7, 49, 7, 241, 255, 255, 255, 7, 40, 7, 132, 255, 255, 255, 7, 193, 255, 255, 255, 7, 30, 7, 122]
for i in range(0,len(a1)):
          if a1[i]==7:
                    str.append(a1[i+1])

print(a1)

在这里插入图片描述
str=[34, 63, 52, 50, 114, 51, 24, 167, 49, 241, 40, 132, 193, 30, 122]
然后switch里的其他case选项就是对str数组进行了操作,最后得到了str里面的值,逆向算法解一下

这里面有个LOBYTE这个函数,做的时候我去百度了有说是取最右边那位,有说右边四位,没有统一的说法,找了其他师傅的wp,说这是ida的函数,可以忽略这个函数。rax是64位寄存器,eax是32位寄存器,ax是16位寄存器,al是ax寄存器低8位,ah是ax寄存器高8位。
在这里插入图片描述

a1=[]
v4=[10, 4, 16, 8, 3, 5, 1, 4, 32, 8, 5, 3, 1, 3, 2, 8, 11, 1, 12, 8, 4, 4, 1, 5, 3, 8, 3, 33, 1, 11, 8, 11, 1, 4, 9, 8, 3, 32, 1, 2, 81, 8, 4, 36, 1, 12, 8, 11, 1, 5, 2, 8, 2, 37, 1, 2, 54, 8, 4, 65, 1, 2, 32, 8, 5, 1, 1, 5, 3, 8, 2, 37, 1, 4, 9, 8, 3, 32, 1, 2, 65, 8, 12, 1, 7, 34, 7, 63, 7, 52, 7, 50, 7, 114, 7, 51, 7, 24, 7, 167, 255, 255, 255, 7, 49, 7, 241, 255, 255, 255, 7, 40, 7, 132, 255, 255, 255, 7, 193, 255, 255, 255, 7, 30, 7, 122]
for i in range(0,len(v4)):
          if v4[i]==7:
                    a1.append(v4[i+1])
#print(a1)

a1 = [34, 63, 52, 50, 114, 51, 24, 167, 49, 241, 40, 132, 193, 30, 122]
a1.reverse()
v4.reverse()

v9 = 0
us = 0
v5 = 0
flag = []
for i in range(0, len(v4)):
    if i == len(v4) - 1:
        flag.append(us)

    if v4[i] == 1 and v4[i - 1] != 1:
        v5 = a1[v9]
        v9 += 1
        flag.append(us)

    if v4[i] == 2:
        if (v4[i + 1] != 3 and v4[i + 1] != 4 and v4[i + 1] != 5):
            us = v5 - v4[i - 1]
            # print(us,v5,a[i-1])

    if v4[i] == 3:
        if (v4[i + 1] != 2 and v4[i + 1] != 4 and v4[i + 1] != 5):
            us = v5 + v4[i - 1]  # LOBYTE是al有8位,参与运算的5、33、32是全值,所以LOBYTE可省略

    if v4[i] == 4:
        if (v4[i + 1] != 3 and v4[i + 1] != 2 and v4[i + 1] != 5):
            us = v5 ^ v4[i - 1]

    if v4[i] == 5:
        if (v4[i + 1] != 3 and v4[i + 1] != 4 and v4[i + 1] != 2):
            us = int(v5 / v4[i - 1])
    if v4[i] == 8:
        v5 = us

    if v4[i] == 11:
        us = v5 + 1

    if v4[i] == 12:
        us = v5 - 1
        # print("12:",us)

flag.reverse()
out = ''
for j in flag:
    out += chr(j)
print("flag{" + out + "}")

flag{757515121f3d478 }

猜你喜欢

转载自blog.csdn.net/mcmuyanga/article/details/114309960