# vm逆向

vm逆向

虚拟机逆向与实现-CSDN博客

对上面博客的总结。

vm逆向题,一般是小型虚拟机程序,可以理解为一种模拟器,有start,dispatcher,opcode等结构。常见使用while-switch/if这类循环+选择结构来实现简单的虚拟机模拟,如下:

逆向重点:

  • 分析入口,搞清输入和opcode的位置

  • 理清结构,包括dispatcher和各handler

  • 逆向各handler,分析opcode意义

小型虚拟机实现

目标:

  • 定义一套opcode

  • 实现opcode解释器

要点:

  • 定义系列虚拟寄存器ri,指针eip指向正在解释的地址,opcode及其对应处理函数的列表

  • 初始化。将寄存器置0,eip指向opcode首地址,并初始化opcode列表每一项的opcode值以及对应的handle函数。

  • start。用while循环结构,如果eip目前指向的opcode不为ret(或其他标识程序结束的指令),那么调用dispatcher来执行当前eip所指向的指令。

  • dispatcher。在opcode列表中查找当前需要的opcode,如果找到,那么执行对应的handler函数,退出遍历。

  • 注意要关注handler函数所占字节数,函数执行完毕后要将eip偏移相应位移。

例题:moectf2024 moejvav

用jadx打开,看Main:

package defpackage;import exceptions.BuDaoLePaoException;
import exceptions.DxIsNanTongException;
import exceptions.GenshinImpactException;
import exceptions.LuoIsNotDogException;
import exceptions.NotSigninException;
import exceptions.NullCafeException;
import exceptions.StarrySkyMeowNotFoundException;
import exceptions.TokioEatWhatException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;/* renamed from: Main  reason: default package */
/* loaded from: moejvav.jar:Main.class */
public class Main {public static void main(String[] args) {System.out.println("这里是moejvav! 请输入你的flag:");String flag = new Scanner(System.in).next();if (flag.length() != 44) {System.out.println("flag长度不对");return;}List<Byte> array = new ArrayList<>();for (byte b : flag.getBytes(StandardCharsets.UTF_8)) {array.add(Byte.valueOf((byte) ((Byte.valueOf(b).byteValue() ^ 202) + 32)));}int[] vmInsn = new int[310];vmInsn[0] = 0;vmInsn[1] = 1;vmInsn[2] = 60;vmInsn[3] = 2;vmInsn[4] = -20;vmInsn[5] = 6;vmInsn[6] = -25;vmInsn[7] = 0;vmInsn[8] = 1;vmInsn[9] = 60;vmInsn[10] = 2;vmInsn[11] = -20;vmInsn[12] = 6;vmInsn[13] = -27;vmInsn[14] = 0;vmInsn[15] = 1;vmInsn[16] = 60;vmInsn[17] = 2;vmInsn[18] = -20;vmInsn[19] = 6;vmInsn[20] = -33;vmInsn[21] = 0;vmInsn[22] = 1;vmInsn[23] = 60;vmInsn[24] = 2;vmInsn[25] = -20;vmInsn[26] = 6;vmInsn[27] = -31;vmInsn[28] = 0;vmInsn[29] = 1;vmInsn[30] = 60;vmInsn[31] = 2;vmInsn[32] = -20;vmInsn[33] = 6;vmInsn[34] = -50;vmInsn[35] = 0;vmInsn[36] = 1;vmInsn[37] = 60;vmInsn[38] = 2;vmInsn[39] = -20;vmInsn[40] = 6;vmInsn[41] = -36;vmInsn[42] = 0;vmInsn[43] = 1;vmInsn[44] = 60;vmInsn[45] = 2;vmInsn[46] = -20;vmInsn[47] = 6;vmInsn[48] = -39;vmInsn[49] = 0;vmInsn[50] = 1;vmInsn[51] = 60;vmInsn[52] = 2;vmInsn[53] = -20;vmInsn[54] = 6;vmInsn[55] = -24;vmInsn[56] = 0;vmInsn[57] = 1;vmInsn[58] = 60;vmInsn[59] = 2;vmInsn[60] = -20;vmInsn[61] = 6;vmInsn[62] = -52;vmInsn[63] = 0;vmInsn[64] = 1;vmInsn[65] = 60;vmInsn[66] = 2;vmInsn[67] = -20;vmInsn[68] = 6;vmInsn[69] = -29;vmInsn[70] = 0;vmInsn[71] = 1;vmInsn[72] = 60;vmInsn[73] = 2;vmInsn[74] = -20;vmInsn[75] = 6;vmInsn[76] = -52;vmInsn[77] = 0;vmInsn[78] = 1;vmInsn[79] = 14;vmInsn[80] = 2;vmInsn[81] = 5;vmInsn[82] = 6;vmInsn[83] = -64;vmInsn[84] = 0;vmInsn[85] = 1;vmInsn[86] = 14;vmInsn[87] = 2;vmInsn[88] = 5;vmInsn[89] = 6;vmInsn[90] = -58;vmInsn[91] = 0;vmInsn[92] = 1;vmInsn[93] = 14;vmInsn[94] = 2;vmInsn[95] = 5;vmInsn[96] = 6;vmInsn[97] = -63;vmInsn[98] = 0;vmInsn[99] = 1;vmInsn[100] = 14;vmInsn[101] = 2;vmInsn[102] = 5;vmInsn[103] = 6;vmInsn[104] = -52;vmInsn[105] = 0;vmInsn[106] = 1;vmInsn[107] = 14;vmInsn[108] = 2;vmInsn[109] = 5;vmInsn[110] = 6;vmInsn[111] = -90;vmInsn[112] = 0;vmInsn[113] = 1;vmInsn[114] = 14;vmInsn[115] = 2;vmInsn[116] = 5;vmInsn[117] = 6;vmInsn[118] = -39;vmInsn[119] = 0;vmInsn[120] = 1;vmInsn[121] = 14;vmInsn[122] = 2;vmInsn[123] = 5;vmInsn[124] = 6;vmInsn[125] = -43;vmInsn[126] = 0;vmInsn[127] = 1;vmInsn[128] = 14;vmInsn[129] = 2;vmInsn[130] = 5;vmInsn[131] = 6;vmInsn[132] = 26;vmInsn[133] = 0;vmInsn[134] = 1;vmInsn[135] = 14;vmInsn[136] = 2;vmInsn[137] = 5;vmInsn[138] = 6;vmInsn[139] = 25;vmInsn[140] = 0;vmInsn[141] = 1;vmInsn[142] = 14;vmInsn[143] = 2;vmInsn[144] = 5;vmInsn[145] = 6;vmInsn[146] = -49;vmInsn[147] = 0;vmInsn[148] = 1;vmInsn[149] = 14;vmInsn[150] = 2;vmInsn[151] = 5;vmInsn[152] = 6;vmInsn[153] = -64;vmInsn[154] = 0;vmInsn[155] = 1;vmInsn[156] = 10;vmInsn[157] = 2;vmInsn[158] = 5;vmInsn[159] = 6;vmInsn[160] = -51;vmInsn[161] = 0;vmInsn[162] = 1;vmInsn[163] = 10;vmInsn[164] = 2;vmInsn[165] = 5;vmInsn[166] = 6;vmInsn[167] = 25;vmInsn[168] = 0;vmInsn[169] = 1;vmInsn[170] = 10;vmInsn[171] = 2;vmInsn[172] = 5;vmInsn[173] = 6;vmInsn[174] = -45;vmInsn[175] = 0;vmInsn[176] = 1;vmInsn[177] = 10;vmInsn[178] = 2;vmInsn[179] = 5;vmInsn[180] = 6;vmInsn[181] = -55;vmInsn[182] = 0;vmInsn[183] = 1;vmInsn[184] = 10;vmInsn[185] = 2;vmInsn[186] = 5;vmInsn[187] = 6;vmInsn[188] = -47;vmInsn[189] = 0;vmInsn[190] = 1;vmInsn[191] = 10;vmInsn[192] = 2;vmInsn[193] = 5;vmInsn[194] = 6;vmInsn[195] = 24;vmInsn[196] = 0;vmInsn[197] = 1;vmInsn[198] = 10;vmInsn[199] = 2;vmInsn[200] = 5;vmInsn[201] = 6;vmInsn[202] = -41;vmInsn[203] = 0;vmInsn[204] = 1;vmInsn[205] = 10;vmInsn[206] = 2;vmInsn[207] = 5;vmInsn[208] = 6;vmInsn[209] = -60;vmInsn[210] = 0;vmInsn[211] = 1;vmInsn[212] = 10;vmInsn[213] = 2;vmInsn[214] = 5;vmInsn[215] = 6;vmInsn[216] = 22;vmInsn[217] = 0;vmInsn[218] = 1;vmInsn[219] = 10;vmInsn[220] = 2;vmInsn[221] = 5;vmInsn[222] = 6;vmInsn[223] = -40;vmInsn[224] = 0;vmInsn[225] = 1;vmInsn[226] = 10;vmInsn[227] = 2;vmInsn[228] = 5;vmInsn[229] = 6;vmInsn[230] = -60;vmInsn[231] = 0;vmInsn[232] = 2;vmInsn[233] = 14;vmInsn[234] = 2;vmInsn[235] = 10;vmInsn[236] = 6;vmInsn[237] = -15;vmInsn[238] = 0;vmInsn[239] = 2;vmInsn[240] = 14;vmInsn[241] = 2;vmInsn[242] = 10;vmInsn[243] = 6;vmInsn[244] = 50;vmInsn[245] = 0;vmInsn[246] = 2;vmInsn[247] = 14;vmInsn[248] = 2;vmInsn[249] = 10;vmInsn[250] = 6;vmInsn[251] = -51;vmInsn[252] = 0;vmInsn[253] = 2;vmInsn[254] = 14;vmInsn[255] = 2;vmInsn[256] = 10;vmInsn[257] = 6;vmInsn[258] = -31;vmInsn[259] = 0;vmInsn[260] = 2;vmInsn[261] = 14;vmInsn[262] = 2;vmInsn[263] = 10;vmInsn[264] = 6;vmInsn[265] = 50;vmInsn[266] = 0;vmInsn[267] = 2;vmInsn[268] = 14;vmInsn[269] = 2;vmInsn[270] = 10;vmInsn[271] = 6;vmInsn[272] = 50;vmInsn[273] = 0;vmInsn[274] = 2;vmInsn[275] = 14;vmInsn[276] = 2;vmInsn[277] = 10;vmInsn[278] = 6;vmInsn[279] = -35;vmInsn[280] = 0;vmInsn[281] = 2;vmInsn[282] = 14;vmInsn[283] = 2;vmInsn[284] = 10;vmInsn[285] = 6;vmInsn[286] = 50;vmInsn[287] = 0;vmInsn[288] = 2;vmInsn[289] = 14;vmInsn[290] = 2;vmInsn[291] = 10;vmInsn[292] = 6;vmInsn[293] = -35;vmInsn[294] = 0;vmInsn[295] = 2;vmInsn[296] = 14;vmInsn[297] = 2;vmInsn[298] = 10;vmInsn[299] = 6;vmInsn[300] = 51;vmInsn[301] = 0;vmInsn[302] = 2;vmInsn[303] = 14;vmInsn[304] = 2;vmInsn[305] = 10;vmInsn[306] = 6;vmInsn[307] = -17;vmInsn[308] = 114514;vmInsn[309] = 1919810;Exception[] exceptions2 = {new BuDaoLePaoException(), new DxIsNanTongException(), new GenshinImpactException(), new LuoIsNotDogException(), new NotSigninException(), new NullCafeException(), new StarrySkyMeowNotFoundException(), new TokioEatWhatException(), new RuntimeException()};int i = 0;int store = 0;while (i < vmInsn.length) {int insn = vmInsn[i];i++;if (insn == 114514) {break;}try {throw exceptions2[insn];break;} catch (BuDaoLePaoException e) {store = array.get(0).byteValue();array.remove(0);} catch (DxIsNanTongException e2) {store ^= vmInsn[i];i++;} catch (GenshinImpactException e3) {store += vmInsn[i];i++;} catch (LuoIsNotDogException e4) {store &= vmInsn[i];i++;} catch (NotSigninException e5) {store <<= vmInsn[i];i++;} catch (NullCafeException e6) {store |= vmInsn[i];i++;} catch (StarrySkyMeowNotFoundException e7) {i++;if (store != vmInsn[i]) {vmInsn[i] = 7;}} catch (TokioEatWhatException e8) {vmInsn[i] = 8;} catch (Exception e9) {System.out.println("wrong flag, oh no...");throw new RuntimeException(e9);}}System.out.println("输入的flag正确!");}
}

这里使用了try-catch抛出异常来实现switch分支选择结构,原理是throw出expections2数组中的函数,catch捕捉到对应编号的函数异常,编号即为该分支的case条件。这个虚拟机的opcode与其对应的handler可以明显地看出。每当opcode为0,取出flag的一个字符,opcode为1~5,对字符进行加密运算,opcode为6,进行一次check,若check不通过则说wrong flag。因此对每一次opcode6的结果一步步向上解密,直到遇到opcode0,则输出该字符,就能得到flag。

exp:

#include<bits/stdc++.h>
using namespace std;
int vmInsn[310];
int decode1(int x)
{return (x-32)^202;
}
int cracker_and(int chip,int x)
{for(int i=-255;i<=255;i++)if(i&x==chip)return i;
}
int cracker_or(int chip,int x)
{for(int i=-255;i<=255;i++)if(i|x==chip)return i;
}int main()
{//vmInsn[...]=...int cnt=0;for(int i=0;;i++){if(vmInsn[i]==114514)break;if(vmInsn[i]!=6)continue;int p=i,chip=vmInsn[p+1];while(1){if(vmInsn[p-1]==0)break;p-=2;int opnum=vmInsn[p+1];switch(vmInsn[p]){case 1:chip^=opnum;break;case 2:chip-=opnum;break;case 3:chip=cracker_and(chip,opnum);break;case 4:chip>>=opnum;break;case 5:chip=cracker_or(chip,opnum);break;}}printf("%c",decode1(chip));}return 0;//cout<<cnt;}
//moectf{jvav_eXcEpt10n_h4ndl3r_1s_s0_c00o0o1}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Gossip 协议】Redis 集群中节点之间的通信方式?

# 分布式系统 # Gossip 协议 在分布式系统中,不同的节点进行数据/信息共享是一个基本的需求。 一种比较简单粗暴的方法就是 集中式发散消息,简单来说就是一个主节点同时共享最新信息给其他所有节点,比较适合中心化系统。这种方法的缺陷也很明显,节点多的时候不光同步消息的…

推荐一款超棒的 Minecraft 启动器:Voxelum/x-minecraft-launcher

X Minecraft Launcher (XMCL) 是一个便于你管理多种整合包、模组、资源包、光影包的现代化启动器。它还支持 Minecraft Forge、 Fabric、Quilt、CurseForge 和 Modrinth它具有以下令人心动的特点:多版本兼容性:支持多个 Minecraft 版本,正式版和愚人节版本。自动化资源下载与…

互联网大中小厂实习面经:滴滴、美团、货拉拉、蔚来、信通院等

本文介绍Momenta、蔚来、中国信息通信研究院、昆仑万维、滴滴、易智瑞等企业各类技术岗位的暑期实习、日常实习面试流程与具体问题~本文介绍Momenta、蔚来、中国信息通信研究院、昆仑万维、滴滴、易智瑞等企业各类技术岗位的暑期实习、日常实习面试流程与具体问题。在前一段时间…

2025年1月买的几个好用的「新物件」

前言 去年底比较忙,换工作+搬家什么的,一堆事情凑在一起,很多24年买的东西还没发开箱 只能后面慢慢补上了,现在先把1月份买的一些东西发一下 红米k80手机 本来我是不想买手机的 不过办了新的套餐,营业厅送了购机补贴,不是很多,所以在补贴范围内选择了「看起来」性价比最…

安卓平板使用can-utils检查can通信功能

安装 termux 打开安卓平板 USB 调试模式,并确保电脑安装了 adb。 下载 termux,通过adb install ./termux.exe安装 termux 到安卓平板。 设置 termux 换源 安装好 termux 后打开,进行换源操作。 termux 中输入termux-change-repo。空格切换选中状态,移动方向键切换选中项目,…

最小系统板五要素

最小系统板五要素 电源在进入芯片的时候需要旁路电容将高频杂散干扰旁路掉VBAT:备用电池 VDD:普通电源 VDDA:ADC信号的电源地VSS:普通地 VSSA:ADC的地晶振给单片机提供时钟脉冲,具体的电容值参考晶振手册??OSC: 外部高速晶振 OSC32: 外部低速晶振复位上电复位和按键复位…

nodecanvas插件的黑魔法:一行代码避免拖拽节点的意外脱离

简介 在nodecanvas造轮子的过程,遇到了鼠标拖拽太快,节点经常会脱离控制的情况。但是nodecanvas却不会有这个问题。 一番折腾发现是nodecanvas调用了GUI.DragWindow(),而我觉得这个函数没啥用给删除了的原因。。 GUI.DragWindow()在MouseDown事件触发时,会调用GrabMouseCon…

windows server2016搭建AD域服务器

windows server2016搭建AD域服务器@目录一、背景二、搭建AD域服务器步骤三、生成可供java程序使用的keystore文件四、导出某用户的keytab文件五、主机配置hosts文件六、主机确认是否能ping通本人其他相关文章链接 一、背景 亲测可用,之前搜索了很多博客,啥样的都有,就是不介绍…

07 异常

什么是异常 异常就像是生活中遇到的意外情况。在程序运行过程中,可能会出现一些意想不到的问题,比如要打开的文件不存在、网络连接突然中断、除数为零等,这些就是异常。当异常发生时,如果不处理,程序可能会崩溃或出现错误结果,所以需要我们去处理这些异常,让程序能更稳健…

MySQL基础 数据库表的增删改

Mysql 数加科技整理 一、原理定义概念 定义数据库(Database)是按照数据结构来组织、存储和管理数据的建立在计算机存储设备上的仓库。 数据库是长期储存在计算机内、有组织的、可共享的数据集合。分类: ​ 非结构化数据: ​ 数据相对来讲没有固定的特点,这种数据非常不便于…

加入我们|申请成为亚马逊云科技 Community Builder,共建云端社区!

亚马逊云科技 Community Builder 项目为开发者社区中的技术爱好者和新兴思想领袖提供技术资源、学习和交流机会,帮助开发者探索、分享技术相关知识,并与亚马逊云科技产品团队、技术专家和更多开发者社区成员建立紧密联系。亚马逊云科技开发者社区为开发者们提供全球的开发技术…

[ARC070E] NarrowRectangles

前言 模拟赛 \(\rm{T4}\) , 不会比较正常, 仅仅只是记录做法 然后就是还有每日一练 思路 首先是朴素的 \(\rm{dp}\) 令 \(f_{i, j}\) 表示考虑到第 \(i\) 行, 其中这一行的左端点位置为 \(j\) 的最优花费 容易写出转移 \[f_{i, j} \gets \min_{k \in [j - len_{i - 1}, j + len…