2020网鼎杯 signal wp(buu复现)

很久之前就想着要复现,结果忘记了...一直拖到现在...

找到关键函数:vm_operad()

点进去看看:

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

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

a1:


然后就主要分析一下这几个case都是做什么的:

  • 第一类:判断验证

(这里的a1是固定的值,与v4进行比较的数据可以理解为由上图内存中每个0x07后的数据构成的数组,v4是我们输入的字符串经过一系列操作存放的位置,v3为我们输入的字符串)

case 7:
    if ( v4[v8] != a1[v10 + 1] )
    {
      printf("what a shame...");
      exit(0);
    }
    ++v8;
    v10 += 2;
    break;
  • 第二类:基本处理字符操作
case 2:
  v5 = a1[v10 + 1] + v3[v9];
  v10 += 2;
  break;
case 3:
  v5 = v3[v9] - LOBYTE(a1[v10 + 1]);
  v10 += 2;
  break;
case 4:
  v5 = a1[v10 + 1] ^ v3[v9];
  v10 += 2;
  break;
case 5:
  v5 = a1[v10 + 1] * v3[v9];
  v10 += 2;
  break;
case 11:
  v5 = v3[v9] - 1;
  ++v10;
  break;
case 12:
  v5 = v3[v9] + 1;
  ++v10;
  break;
  • 第三类:中转赋值

这里v5其实就是一个中间值,把我们输入的字符串在第二类case经过一系列操作存在v5中,然后遇到case1就把v5赋值给v4,最后用v4去和a1比较,都相同就get flag!

case 1:
  v4[v7] = v5;
  ++v10;
  ++v7;
  ++v9;  
  break;
case 6:
  ++v10;
  break;
case 8:
  v3[v6] = v5;
  ++v10;
  ++v6;
  break;

逻辑就挺清楚的了,具体这些case是做什么的就不多说了(一些加减异或基本操作,自行理解),直接上脚本吧:

exp

这里用的是爆破的方法,也可以直接写出其逆过程+逆运算,从结果直接推出flag

encrypts = [0x22, 0x3F, 0x34, 0x32, 0x72, 0x33, 0x18, 0xA7, 0x31, 0xF1, 0x28, 0x84, 0xC1, 0x1E, 0x7A]

data = [[4, 0x10, 8, 3, 5, 1]
    , [4, 0x20, 8, 5, 3, 1]
    , [3, 2, 8, 0x0B, 1]
    , [0x0C, 8, 4, 4, 1]
    , [5, 3, 8, 3, 0x21, 1]
    , [0x0B, 8, 0x0B, 1]
    , [4, 9, 8, 3, 0x20, 1]
    , [2, 0x51, 8, 4, 0x24, 1]
    , [0x0C, 8, 0x0B, 1]
    , [5, 2, 8, 2, 0x25, 1]
    , [2, 0x36, 8, 4, 0x41, 1]
    , [2, 0x20, 8, 5, 1, 1]
    , [5, 3, 8, 2, 0x25, 1]
    , [4, 9, 8, 3, 0x20, 1]
    , [2, 0x41, 8, 0x0C, 1]]

for_each = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
            'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
            'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0']


def encrypted(c, li):
    # print(li)
    x = 0
    while x < len(li):
        if li[x] == 2:
            c = c + li[x + 1]
            x += 2
        elif li[x] == 3:
            c = c - li[x + 1]
            x += 2
        elif li[x] == 4:
            c = c ^ li[x + 1]
            x += 2
        elif li[x] == 5:
            c = c * li[x + 1]
            x += 2
        elif li[x] == 11:
            c = c - 1
            x += 1
        elif li[x] == 12:
            c = c + 1
            x += 1
        elif li[x] == 8:
            x += 1
        elif li[x] == 1:
            break
    res = c
    return res


if __name__ == '__main__':
    flag = ''
    for x in range(len(encrypts)):
        for i in for_each:
            tmp = encrypted(ord(i), data[x])
            if tmp == encrypts[x]:
                flag += i
                break
            else:
                continue
    print('flag{%s}' % flag)

# flag{757515121f3d478}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值