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

news2024/11/25 23:23:04

文章目录

  • 前言
  • 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.coloradmin.cn/o/1162626.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LiveNVR监控流媒体平台局域网Onvif/RTSP/SDK等方式接入监控视频后转GB28181/GB35114级联输出,上级平台无法播放如何抓包分析

1、第一步&#xff1a;抓包工具准备 1.1、Linux 使用 tcpdump 进行抓包&#xff0c;如果系统无此命令&#xff0c;自行安装 1.2、windows 下载安装 wireshark 进行抓包 2、第二步&#xff1a;找到上级平台ip 在基础配置里面GB28181级联配置中SIP服务IP 3、第三步&#…

重新理解B面供应链:在轻创业的潮流里

中国新式供应链正在成型。 在这个由于年轻的消费需求驱动的想法、AI大模型能力、严苛清晰的供应链、工厂图谱一共构成的链条上&#xff0c;越来越多的新创业和新产业模型都正在被加速成型&#xff0c;并真实转化为新的工业生产力。 作者|史圣园 编辑|皮爷 出品|产业家 …

Android 控件背景实现发光效果

主要实现的那种光晕效果&#xff1a;中间亮&#xff0c;四周逐渐变淡的。 这边有三种发光效果&#xff0c;先上效果图。 第一种、圆形发光体 实现代码&#xff1a;新建shape_light.xml&#xff0c;导入以下代码。使用时&#xff0c;直接给view设置为background。 <?xml …

IT开发怕失败?买个低代码搭建属于自己应用

目录 一、驱动低代码流行的主要几个特性 01、低代码缩短了开发时间 02、低代码允许平滑协作 03、低代码在云端和本地都可运行 二、低代码究竟好不好用 三、源码全交付的开发平台 01、高性能、高拓展 02、功能丰富&#xff0c;满足通用场景 03、私有化部署 04、部署方式 05、多数…

PFMEA详解结构分析——Sun FMEA软件

FMEA从1949年诞生到今天已经发生过多次更新&#xff0c;最新版本是2019年6月发布的《AIAG VDA FMEA手册》。新手册借鉴了AIAG的方框图、参数图、流程图等工具的运用&#xff0c;也借鉴了VDA的五步过程导向法&#xff0c;并在此基础上头尾各增加一步&#xff0c;形成了FMEA七步法…

【强化学习】14 —— A3C(Asynchronous Advantage Actor Critic)

A3C算法&#xff08; Asynchronous Methods for Deep Reinforcement Learning&#xff09;于2016年被谷歌DeepMind团队提出。A3C是一种非常有效的深度强化学习算法&#xff0c;在围棋、星际争霸等复杂任务上已经取得了很好的效果。接下来&#xff0c;我们先从A3C的名称入手&…

视频号的视频怎么保存到相册,第三方工具快速下载保存!

视频号是目前非常火爆的短视频平台之一&#xff0c;许多用户在上面发布了各种精彩的视频内容。然而&#xff0c;很多人都想把视频保存到自己的相册中&#xff0c;以便随时欣赏和分享。那么&#xff0c;如何将视频号的视频保存到相册呢&#xff1f; 我们需要了解一个专注于视频…

Nacos注册中心--适合小白体制

认识和安装NacosNacos快速入门Nacos服务分级存储模型Nacos环境隔离 代码获取&#xff1a;1693905917/springCloud: springCloud学习 (github.com) 认识和安装Nacos 认识Nacos Nacos是阿里巴巴的产品&#xff0c;现在是SpringCloud中的一个组件。相比Eureka功能更加丰富&…

voronoi diagram(泰森多边形) 应用 - Panda Preserve

欢迎关注更多精彩 关注我&#xff0c;学习常用算法与数据结构&#xff0c;一题多解&#xff0c;降维打击。 背景知识 voronoi 提出 voronoi 图一开始是由荷兰气候学家AHThiessen提出&#xff0c;是用来计算区域内的降雨量。 由于气象塔是离散放置的&#xff0c;该气候学家就…

大促来袭 线下门店查价同样重要

都说双十一是电商的狂欢&#xff0c;这话没错&#xff0c;但线下门店同样也会利用这波热度&#xff0c;做促销引流量&#xff0c;自然也会出现不同的低价&#xff0c;不管是线上还是线下低价&#xff0c;都会对各自的生意有所影响&#xff0c;当然也不是禁止低价&#xff0c;是…

C++17对if/switch的增强

C17之前不允许在if/switch语句中定义一个临时变量 但在C17之后可以了

Rocky9 上安装 redis-dump 和redis-load 命令

一、安装依赖环境 1、依赖包 dnf -y install perl gcc gcc-c zlib-devel2、编译openssl 1.X ### 下载编译 wget https://www.openssl.org/source/openssl-1.1.1t.tar.gz tar xf openssl-1.1.1t.tar.gz cd openssl-1.1.1t ./config --prefix/usr/local/openssl make make ins…

公会发展计划(GAP):经过实战考验的 Web3 任务模式

2020 年 12 月&#xff0c;Yield Guild Games 踏上了一段征程&#xff0c;以表彰兢兢业业的 Web3 游戏玩家所付出的时间和努力&#xff0c;同时为他们提供利用自己的技能促进个人成长的机会。这一旅程的第一步是于 2022 年 7 月推出的公会发展计划&#xff08;GAP&#xff09;。…

利用端口映射技术快速搭建微力私人网盘并实现远程访问【内网穿透】

文章目录 1.前言2. 微力同步网站搭建2.1 微力同步下载和安装2.2 微力同步网页测试2.3 cpolar的安装和注册 3.本地网页发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1.前言 私有云盘作为云存储概念的延伸&#xff0c;虽然谈不上多么新颖&#xff0c;但是其…

蓝桥杯每日一题2023.11.1

题目描述 乘积最大 - 蓝桥云课 (lanqiao.cn) 题目分析 先对a[1] ~ a[n]排序 分类讨论&#xff1a; 1.k n 全选 2.k < n ①k是偶数&#xff08;结果必然非负&#xff09; 负数有偶数个&#xff08;负负得正&#xff09; 负数有奇数个&#xff08;只用选取偶数个即可&…

PC页面-企业微信扫码登录

vue代码引入企业微信扫码登录 企业微信后台管理配置。前端vue 代码使用的配置信息 项目需求PC端登录需要对接企业微信扫码登录功能。 根据同事研究成果&#xff0c;记录该功能的流程。 前端代码用的是vue。 企业微信后台管理配置。 企业微信后台管理登录连接 1、扫码登录企业…

店铺消费短信通知模板,可以自定义编辑内容群发

店铺消费短信通知模板&#xff0c;可以自定义编辑内容群发 上图可以对短信的发送情况进行查询&#xff0c;可以通过该软件群发短信。 下图为 佳易王 会员管理系统软件&#xff0c;在会员充值或消费的时候&#xff0c;可以设置自动发送短信通知信息。 可以自由设置&#xff0c;…

系列六、Mybatis的一级缓存

一、概述 Mybatis一级缓存的作用域是同一个SqlSession&#xff0c;在同一个SqlSession中执行两次相同的查询&#xff0c;第一次执行完毕后&#xff0c;Mybatis会将查询到的数据缓存起来&#xff08;缓存到内存中&#xff09;&#xff0c; 第二次执行相同的查询时&#xff0c;会…

文件字符流的使用

文件字符输入流 概述 文件字符输入流&#xff1a;FileReader。 作用&#xff1a;以内存为基准&#xff0c;把磁盘文件中的数据以字符的形式读取到内存中去。 为什么要用&#xff1f; 字节流读取中文时为了避免乱码需要一次性读到字节数组里&#xff0c;如果文件很大的话&a…

linux profile文件环境变量配置

1、profile 文件 profile 文件位于/etc/目录下 /etc/profile &#xff0c; 当登入系统时候获得一个 shell 进程时&#xff0c;其读取环境profile 文件时候会读取&#xff0c;/etc/bash.bashrc&#xff0c;/etc/profile.d 文件下配置的sh文件&#xff0c;所以我们也可以在profi…