CTF-Reverse---VM虚拟机逆向[HGAME 2023 week4]vm题目复现【详解】

文章目录

  • 前言
  • 0x1[HGAME 2023 week4]vm
    • 提取汇编指令
      • mov指令
      • push指令&pop指令
      • 运算操作
      • cmp指令
      • jmp指令
      • je 和 jne
    • exp

前言

没有前言。终于搞定第二题了。费劲是真的费。
题目在nssctf上有。
这一题写完才看到有提示,是关于构建结构体的,下次试试。


0x1[HGAME 2023 week4]vm

在这里插入图片描述
在这里插入图片描述

这里有几个技巧:

  • 将__int64 a1 改为 _DWORD *a1
  • a1 可以 改名为 reg
  • 函数返回值改为void

这样方便观看,还有其他一些函数的名称,不一一做解释。

sub_1400010B0 点进来,一个里面放着字节码改为opcode,一个是调度器。 当opcode当前的索引的值不为255的时候就一直读取下去。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这里是做过修过后的,可以看到特别的简洁明了。下面具体分析一下,汇编的实现过程。先给出完整的。

提取汇编指令

opcode = [0x00, 0x03, 0x02, 0x00, 0x03, 0x00, 0x02, 0x03, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, 0x02, 0x32,
          0x03, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
          0x01, 0x00, 0x00, 0x03, 0x02, 0x64, 0x03, 0x00, 0x02, 0x03,
          0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x01, 0x00, 0x00, 0x03,
          0x00, 0x08, 0x00, 0x02, 0x02, 0x01, 0x03, 0x04, 0x01, 0x00,
          0x03, 0x05, 0x02, 0x00, 0x03, 0x00, 0x01, 0x02, 0x00, 0x02,
          0x00, 0x01, 0x01, 0x00, 0x00, 0x03, 0x00, 0x01, 0x03, 0x00,
          0x03, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x01, 0x28,
          0x04, 0x06, 0x5F, 0x05, 0x00, 0x00, 0x03, 0x03, 0x00, 0x02,
          0x01, 0x00, 0x03, 0x02, 0x96, 0x03, 0x00, 0x02, 0x03, 0x00,
          0x00, 0x00, 0x00, 0x04, 0x07, 0x88, 0x00, 0x03, 0x00, 0x01,
          0x03, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03,
          0x01, 0x28, 0x04, 0x07, 0x63, 0xFF, 0xFF]
input1 = []
i = 0
while opcode[i] != 0xFF:
    match opcode[i]:
        case 0x00:
            print(f'{i}', end=' ')
            o = i + 1
            if opcode[o]:
                match opcode[o]:
                    case 0x01:
                        print("mov input[reg[2]], reg[0]")
                    case 0x02:
                        print("mov reg[%d], reg[%d]" % (opcode[i+2],opcode[i+3]))
                    case 0x03:
                        print("mov reg[%d], %d" % (opcode[i+2], opcode[i+3]))
            else:
                print("mov reg[0], input[reg[2]]")
            i += 4
        case 0x01:
            print(f'{i}', end=' ')
            o = i + 1
            if opcode[o]:
                match opcode[o]:
                    case 0x01:
                        print("push reg[0]")
                    case 0x02:
                        print("push reg[2]")
                    case 0x03:
                        print("push reg[3]")
            else:
                print("push reg[0]")
            i += 2
        case 0x02:
            print(f'{i}', end=' ')
            o = i + 1
            if opcode[o]:
                match opcode[o]:
                    case 0x01:
                        print("pop reg[1]")
                    case 0x02:
                        print("pop reg[2]")
                    case 0x03:
                        print("pop reg[3]")
            else:
                print("pop reg[0]")
            i += 2
        case 0x03:
            print(f'{i}', end=' ')
            o = i + 1
            match opcode[o]:
                case 0:
                    print("add reg[%d],reg[%d]" % (opcode[i + 2], opcode[i + 3]))
                case 1:
                    print("sup reg[%d],reg[%d]" % (opcode[i + 2], opcode[i + 3]))
                case 2:
                    print("mul reg[%d],reg[%d]" % (opcode[i + 2], opcode[i + 3]))
                case 3:
                    print("xor reg[%d],reg[%d]" % (opcode[i + 2], opcode[i + 3]))
                case 4:
                    print("shl reg[%d],reg[%d]" % (opcode[i + 2], opcode[i + 3]))
                case 5:
                    print("shr reg[%d],reg[%d]" % (opcode[i + 2], opcode[i + 3]))
            i += 4
        case 0x04:
            print(f'{i} cmp reg[0], reg[1]')
            i += 1
        case 0x05:
            print(f'{i} jmp %d ' % (opcode[i+1]))
            i += 2
        case 0x06:
            print(f'{i} je %d ' % (opcode[i+1]))
            i += 2
        case 0x07:
            print(f'{i} jne %d ' % (opcode[i+1]))
            i += 2

我第一次写,没有区分函数,最好可以写成 def mov(): 这样的形式。

mov指令

在这里插入图片描述

其实我也不太理解,为什么是reg[6](a1[6])这样子, 最后也只理解了它 等同于 i 索引值。

这里经过修改,还是蛮清楚的,reg是寄存器,reg[6] 当做是 i;这里例如case 1:可以理解为将reg[0] 的东西放入 input[reg[2]]里下面也是类似的。case2 是俩个寄存器,case 3就是将opcode[reg[3]]的数据放入寄存器。注意的是最后有个 i += 4 。

其实 i 可以理解为 rip。也就是读取指令的位置。

push指令&pop指令

在这里插入图片描述
栈 + 1,然后 将 reg[0] 的值放进去 ,就是push 指令 ,最后有 i += 2

pop指令同理,寄存器取了栈当前位置的值,然后栈再-1,

运算操作

在这里插入图片描述

这里其实蛮清楚的,就是寄存器之间的加减之类的运算。

cmp指令

在这里插入图片描述
比较函数,返回 0 或者 1;

jmp指令

在这里插入图片描述
改完后简单明了,就是 i = 下一个位置

je 和 jne

一个是不为 0 跳转 一个 是为零 跳转。
在这里插入图片描述
在这里插入图片描述

这里就分析完了。运行一开始的exp

得到近似的汇编

0 mov reg[2], 0
4 add reg[2],reg[3]
8 mov reg[0], input[reg[2]]
12 mov reg[1], reg[0]
16 mov reg[2], 50
20 add reg[2],reg[3]
24 mov reg[0], input[reg[2]]
28 add reg[1],reg[0]
32 mov reg[2], 100
36 add reg[2],reg[3]
40 mov reg[0], input[reg[2]]
44 xor reg[1],reg[0]
48 mov reg[0], 8
52 mov reg[2], reg[1]
56 shl reg[1],reg[0]
60 shr reg[2],reg[0]
64 add reg[1],reg[2]
68 mov reg[0], reg[1]
72 push reg[0]
74 mov reg[0], 1
78 add reg[3],reg[0]
82 mov reg[0], reg[3]
86 mov reg[1], 40
90 cmp reg[0], reg[1]
91 je 95 
93 jmp 0 
95 mov reg[3], 0
99 pop reg[1]
101 mov reg[2], 150
105 add reg[2],reg[3]
109 mov reg[0], input[reg[2]]
113 cmp reg[0], reg[1]
114 jne 136 
116 mov reg[0], 1
120 add reg[3],reg[0]
124 mov reg[0], reg[3]
128 mov reg[1], 40
132 cmp reg[0], reg[1]
133 jne 99 

分析后大概就是这样
在这里插入图片描述

  • a1 是 input[50 + i]
  • a2 是 input[100 + i]
  • a3 是 input[150 + i]

就是,取 input[50 + i]开始的值 和我们输入的flag 相加,然后和input[100+i]的值异或 。将异或后的值再做俩个移位处理相加起来,得到的值等于 input[150+i]的值。

将值都取出来,写个exp

exp

a1 = [155, 168, 2, 188, 172, 156, 206, 250, 2, 185, 255, 58, 116, 72, 25, 105, 232, 3, 203, 201,
      255, 252, 128, 214, 141, 215, 114, 0, 167, 29, 61, 153, 136, 153, 191, 232, 150, 46, 93, 87]
a2 = [201, 169, 189, 139, 23, 194, 110, 248, 245, 110, 99, 99, 213, 70, 93, 22, 152, 56, 48, 115, 56,
      193, 94, 237, 176, 41, 90, 24, 64, 167, 253, 10, 30, 120, 139, 98, 219, 15, 143, 156]
a3 = [18432, 61696, 16384, 8448, 13569, 25600, 30721, 63744, 6145, 20992, 9472, 23809, 18176, 64768, 26881, 23552,
      44801, 45568, 60417,
      20993, 20225, 6657, 20480, 34049, 52480, 8960, 63488, 3072, 52992, 15617, 17665, 33280, 53761, 10497, 54529, 1537,
      41473, 56832, 42497, 51713]
a4 = a3[::-1]
# a4 = [51713, 42497, 56832, 41473, 1537, 54529, 10497, 53761, 33280, 17665, 15617, 52992, 3072, 63488, 8960, 52480, 34049, 20480, 6657, 20225, 20993, 60417, 45568, 44801, 23552, 26881, 64768, 18176, 23809, 9472, 20992, 6145, 63744, 30721, 25600, 13569, 8448, 16384, 61696, 18432]
flag = [0] * 40
for i in range(40):
    flag[i] = ((a4[i] >> 8) & 0xff + (a4[i] << 8))
    flag[i] ^= a2[i]
    flag[i] -= a1[i]
print("".join([chr(a&0xff) for a in flag]))

# hgame{y0ur_rever5e_sk1ll_i5_very_g0od!!}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/113730.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

1360. 日期之间隔几天

1360. 日期之间隔几天 Java代码&#xff1a; 【DateFormat】DateFormat用于实现日期的格式化 import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; // 好像已过时class Solution {public int daysBet…

vue3+ts 提取公共方法

因为好多页面都会使用到这个效验规则&#xff0c;封装一个校检规则&#xff0c;方便维护 封装前 封装后

【机器学习】四、计算学习理论

1 基础知识 计算学习理论&#xff08;computational learning theory&#xff09;&#xff1a;关于通过“计算”来进行“学习”的理论&#xff0c;即关于机器学习的理论基础&#xff0c;其目的是分析学习任务的困难本质&#xff0c;为学习算法体统理论保证&#xff0c;并根据结…

frp-内网穿透部署-ubuntu22服务器-windows server-详细教程

文章目录 1.下载frp2.Ubuntu修改root用户3.配置服务器3.1.配置frps.ini文件3.2.设置服务文件3.3.设置开机自启和服务操作3.4.后台验证3.5.服务器重启 4.配置本地window4.1.frpc配置4.2.添加开机计划启动4.3.控制台启动隐藏窗口 5.centos防火墙和端口5.1.开放端口5.2.查看端口 6…

【电路笔记】-相量图和相量代数

相量图和相量代数 文章目录 相量图和相量代数1、概述2、相量图3、相量代数3.1 加减3.2 差异化与整合 4、总结 1、概述 交流电信号可以用三种不同的方法来表示&#xff0c;以便表征和实现代数运算。 前面的文章中已经介绍了两种方法&#xff0c;本文稍后将介绍一种新的图形方法…

Pytorch 注意力机制解析与代码实现

目录 什么是注意力机制1、SENet的实现2、CBAM的实现3、ECA的实现4、CA的实现 什么是注意力机制 注意力机制是深度学习常用的一个小技巧&#xff0c;它有多种多样的实现形式&#xff0c;尽管实现方式多样&#xff0c;但是每一种注意力机制的实现的核心都是类似的&#xff0c;就…

【计算机网络】(谢希仁第八版)第一章课后习题答案

1.计算机网络可以向用户提供哪些服务&#xff1f; 答&#xff1a;例如音频&#xff0c;视频&#xff0c;游戏等&#xff0c;但本质是提供连通性和共享这两个功能。 连通性&#xff1a;计算机网络使上网用户之间可以交换信息&#xff0c;好像这些用户的计算机都可以彼此直接连…

036-第三代软件开发-系统时间设置

第三代软件开发-系统时间设置 文章目录 第三代软件开发-系统时间设置项目介绍系统时间设置演示效果QML 实现小伙伴自创 TumblerQt 家 Tumbler C 端实现 总结一下 关键字&#xff1a; Qt、 Qml、 Time、 时间、 系统 项目介绍 欢迎来到我们的 QML & C 项目&#xff01;…

【VPX630】青翼 基于KU115 FPGA+C6678 DSP的6U VPX通用超宽带实时信号处理平台

板卡概述 VPX630是一款基于6U VPX总线架构的高速信号处理平台&#xff0c;该平台采用一片Xilinx的Kintex UltraScale系列FPGA&#xff08;XCKU115&#xff09;作为主处理器&#xff0c;完成复杂的数据采集、回放以及实时信号处理算法。采用一片带有ARM内核的高性能嵌入式处理器…

Nginx负载均衡 以及Linux前后端项目部署

一、Nginx简介 Nginx是一款高性能的开源Web服务器和反向代理服务器。它由俄罗斯的程序设计师Igor Sysoev创建&#xff0c;旨在解决传统Web服务器的性能限制问题。 Nginx采用事件驱动的架构和异步非阻塞的处理方式&#xff0c;使其能够处理大量并发连接&#xff0c;并具备良好…

【分享】winterm ssh登录报错Unkown error

非软文哈&#xff0c;实测Winterm非常好用&#xff0c;唯一的障碍是 某些特定服务器ssh登录报错Unkown error 后经github issue得知&#xff0c;关闭会话设置-ssh选项卡中的 尝试键盘交互认证的勾即可。 https://github.com/kingToolbox/WindTerm/issues/1922

二叉树题目:在二叉树中增加一行

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;在二叉树中增加一行 出处&#xff1a;623. 在二叉树中增加一行 难度 5 级 题目描述 要求 给定一个二叉树的根结…

Vue 数据绑定 和 数据渲染

目录 一、Vue快速入门 1.简介 : 2.MVVM : 3.准备工作 : 二、数据绑定 1.实例 : 2.验证 : 三、数据渲染 1.单向渲染 : 2.双向渲染 : 一、Vue快速入门 1.简介 : (1) Vue[/vju/]&#xff0c;是Vue.js的简称&#xff0c;是一个前端框架&#xff0c;常用于构建前端用户…

C++二分查找算法的应用:俄罗斯套娃信封问题

本文涉及的基础知识点 二分查找 题目 给你一个二维整数数组 envelopes &#xff0c;其中 envelopes[i] [wi, hi] &#xff0c;表示第 i 个信封的宽度和高度。 当另一个信封的宽度和高度都比这个信封大的时候&#xff0c;这个信封就可以放进另一个信封里&#xff0c;如同俄罗…

assert断言与const修饰指针的妙用(模拟实现strcpy函数)

assert断言 目录 assert断言的妙用&#xff1a; 头文件&#xff1a; 使用方法&#xff1a; const修饰指针的妙用 主要用法 const在*左边 const在*右边 断言和const修饰指针的应用 模拟实现C语言strcpy函数 1、若字符串str1,str2有空指针怎么办&#xff1f; 2.str2改变…

【Unity实战】最全面的库存系统(一)

文章目录 先来看看最终效果前言定义物品定义人物背包物品插槽数据拾取物品物品堆叠绘制UI移动拖拽物品选中物品跟随鼠标移动背包物品交换物品拆分物品物品堆叠完结先来看看最终效果 前言 它又来了,库存系统我前面其实一句做过很多次了,但是这次的与以往的不太一样,这个将是…

微信小程序:两层循环的练习,两层循环显示循环图片大图(大图显示、多层循环)

效果 代码分析 外层循环 外层循环的框架 <view wx:for"{{info}}" wx:key"index"></view> wx:for"{{info}}"&#xff1a;这里wx:for指令用于指定要遍历的数据源&#xff0c;即info数组。当遍历开始时&#xff0c;会依次将数组中的每…

前端架构体系调研整理汇总

1.公司研发人数与前端体系 小型创业公司 前端人数&#xff1a; < 3 人 产品类型&#xff1a; 产品不是非常成熟&#xff0c;比较新颖。 项目流程&#xff1a;不完善&#xff0c;快、紧促&#xff0c;没有固定的时间排期。 技术栈&#xff1a; 没有历史包袱&#xff0c;技…

oracle中关于connect by的语法及实现(前序遍历树)

语法 connect by是是结构化查询中用到的&#xff0c;其基本语法是&#xff1a; 1 select … from tablename 2 start with 条件1 3 connect by 条件2 4 where 条件3; 使用示例 例&#xff1a; create table tree(id int,parentid int); insert into tree values(120,184); …

web:[网鼎杯 2020 青龙组]AreUSerialz

题目 点进题目发现 需要进行代码审计 function __destruct() {if($this->op "2")$this->op "1";$this->content "";$this->process();}这里有__destruct()函数&#xff0c;在对象销毁时自动调用&#xff0c;根据$op属性的值进行…
最新文章