[网鼎杯 2020 青龙组]singal

这个题目方法有很多,目的是练习算法的分析和vm练习,尝试了静态直接逆算法和动态静态结合的方法方法1拖入ida找到main函数int __cdecl main(int argc, const char **argv, const char **envp){ int v4; // [sp+18h] [bp-1D4h]@1 __main(); qmemcpy(&v4, &unk_403040, 0x1C8u);//拷贝opcode表 vm_operad(&v4,
摘要由CSDN通过智能技术生成

这个题目方法有很多,目的是练习算法的分析和vm练习,尝试了静态直接逆算法和动态静态结合的方法

方法1

拖入ida找到main函数

int __cdecl main(int argc, const char **argv, const char **envp)
{
   
  int v4; // [sp+18h] [bp-1D4h]@1

  __main();
  qmemcpy(&v4, &unk_403040, 0x1C8u);//拷贝opcode表
  vm_operad(&v4, 114);//关键函数
  puts("good,The answer format is:flag {}");
  return 0;
}

找到关键函数

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

  v10 = 0;
  v9 = 0;
  v8 = 0;
  v7 = 0;
  v6 = 0;
  while ( 1 )
  {
   
    result = v10;
    if ( v10 >= a2 )
      return result;
    switch ( a1[v10] )                          // a1是opcode  v10是索引
    {
   
      case 10:                                  // 输入点
        read(v3);
        ++v10;
        break;
      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] )            // 最终判断 a1->v5->v4
        {
   
          printf("what a shame...");
          exit(0);
        }
        ++v8;
        v10 += 2;
        break;
      case 11:
        v5 = v3[v9] - 1;
        ++v10;
        break;
      case 12:
        v5 = v3[v9] + 1;
        ++v10;
        break;
      case 8:
        v3[v6] = v5;
        ++v10;
        ++v6;
        break;
      default:
        continue;
    }
  }
}

可以判断这是一个vm逆向,分析逻辑,输入点是case 10最后的判断位置是case 7。v4由v5得到,且必经过case 1,v5由opcode经过运算得到,所以我们可以模拟算法,先找出每次switch使用哪个索引值v10和整个过程中进行比较的opcode v4。
逆向算法如下

#include <stdio.h>
#include <string.h>
unsigned char opcode[] =
{
   
  0x0A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00,
  0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
  0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00,
  0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
  0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00,
  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
  0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00,
  0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
  0x04
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值