BUUCTF-[GWCTF 2019]babyvm

题目下载:下载

这种简单vm逆向搞了快半辈子了,看别人wp也看的迷迷糊糊的,今天突然就看明白了,可能是受一个python虚拟机题的影响,第一次见vm,简单记录一下~

参考:系统学习vm虚拟机逆向_43v3rY0unG的博客-CSDN博客

基本原理:

是指的意思是一种解释执行系统或者模拟器(Emulator)。逆向中的虚拟机保护是一种基于虚拟机的代码保护技术。它将基于x86汇编系统中的可执行代码转换为字节码指令系统的代码,来达到不被轻易逆向和篡改的目的。简单点说就是将程序的代码转换自定义的操作码(opcode),然后在程序执行时再通过解释这些操作码,选择对应的函数执行,从而实现程序原有的功能。

vm_start:

虚拟机的入口函数,对虚拟机环境进行初始化

vm_dispatcher:

调度器,解释opcode,并选择对应的handle函数执行,当handle执行完后会跳回这里,形成一个循环。

opcode :

程序可执行代码转换成的操作码

在这种情况下,如果要逆向程序,就需要对整个emulator结构进行逆向,理解程序功能,还需要结合opcode进行分析,整个程序逆向工程将会十分繁琐。这是一个一般虚拟机结构:

大概了解vm逆向后,解一下这个题目,载入IDA

有三个函数,进入第一个sub_CD1函数

发现有一个unk_202060,跟进查看发现是一堆数据,根据对vm的简单了解,这些应该是操作码,继续看函数其他的部分,应该是操作码及其对应的操作指令。

进入sub_B5F,看0xF1的指令

 是个赋值操作,所以对应mov操作。switch不同,赋值给的对象不同,所以可以看做是不同寄存器,所以0xE1->eax,0xE2->ebx,0xE3->ecx,0xE5->edx。其中还有个qword_2022A8,交叉引用一下,

所以这个应该就是flag。

进入sub_A64函数,看0xF2的指令
是个异或操作,看异或对象可知,xor eax,ebx

进入sub_AC5函数,看0xF5的指令

是获得flag长度,否则wrong

进入sub_956函数,看0xF4的指令
啥都没做,所以nop

进入sub_A08函数,看0xF7的指令
乘的操作,看操作对象是 mul eax,edx

进入sub_8F0函数,看0xF8的操作

是个交换操作,即swap eax,ebx

进入sub_99C函数,看0xF6操作

是一个线性运算,eax=ecx+2*ebx+3*eax

看主函数里的第二个函数sub_E0B函数

读取操作码,如果不是0xF4就进行操作,所以这个应该就是再进行操作码的翻译

看主函数里的第三个函数
这里就是再进行检查,看是否和aFzAmAmFmtSum[i]数组相同。

好了分析了个大概,现在主要操作就是翻译操作码,代码如下

opcode=[0xF5, 0xF1, 0xE1, 0x00, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4,
  0x20, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x01, 0x00, 0x00, 0x00,
  0xF2, 0xF1, 0xE4, 0x21, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x02,
  0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x22, 0x00, 0x00, 0x00,
  0xF1, 0xE1, 0x03, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x23,
  0x00, 0x00, 0x00, 0xF1, 0xE1, 0x04, 0x00, 0x00, 0x00, 0xF2,
  0xF1, 0xE4, 0x24, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x05, 0x00,
  0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x25, 0x00, 0x00, 0x00, 0xF1, 
  0xE1, 0x06, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x26, 0x00, 
  0x00, 0x00, 0xF1, 0xE1, 0x07, 0x00, 0x00, 0x00, 0xF2, 0xF1, 
  0xE4, 0x27, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x08, 0x00, 0x00, 
  0x00, 0xF2, 0xF1, 0xE4, 0x28, 0x00, 0x00, 0x00, 0xF1, 0xE1, 
  0x09, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x29, 0x00, 0x00, 
  0x00, 0xF1, 0xE1, 0x0A, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 
  0x2A, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0B, 0x00, 0x00, 0x00, 
  0xF2, 0xF1, 0xE4, 0x2B, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0C, 
  0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x2C, 0x00, 0x00, 0x00, 
  0xF1, 0xE1, 0x0D, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x2D, 
  0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0E, 0x00, 0x00, 0x00, 0xF2, 
  0xF1, 0xE4, 0x2E, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0F, 0x00, 
  0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x2F, 0x00, 0x00, 0x00, 0xF1, 
  0xE1, 0x10, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x30, 0x00, 
  0x00, 0x00, 0xF1, 0xE1, 0x11, 0x00, 0x00, 0x00, 0xF2, 0xF1, 
  0xE4, 0x31, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x12, 0x00, 0x00, 
  0x00, 0xF2, 0xF1, 0xE4, 0x32, 0x00, 0x00, 0x00, 0xF1, 0xE1, 
  0x13, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x33, 0x00, 0x00, 
  0x00, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5, 0xF1, 
  0xE1, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x01, 0x00, 0x00, 
  0x00, 0xF2, 0xF1, 0xE4, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE1, 
  0x01, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x02, 0x00, 0x00, 0x00, 
  0xF2, 0xF1, 0xE4, 0x01, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x02, 
  0x00, 0x00, 0x00, 0xF1, 0xE2, 0x03, 0x00, 0x00, 0x00, 0xF2, 
  0xF1, 0xE4, 0x02, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x03, 0x00, 
  0x00, 0x00, 0xF1, 0xE2, 0x04, 0x00, 0x00, 0x00, 0xF2, 0xF1, 
  0xE4, 0x03, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x04, 0x00, 0x00, 
  0x00, 0xF1, 0xE2, 0x05, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 
  0x04, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x05, 0x00, 0x00, 0x00, 
  0xF1, 0xE2, 0x06, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x05, 
  0x00, 0x00, 0x00, 0xF1, 0xE1, 0x06, 0x00, 0x00, 0x00, 0xF1, 
  0xE2, 0x07, 0x00, 0x00, 0x00, 0xF1, 0xE3, 0x08, 0x00, 0x00, 
  0x00, 0xF1, 0xE5, 0x0C, 0x00, 0x00, 0x00, 0xF6, 0xF7, 0xF1, 
  0xE4, 0x06, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x07, 0x00, 0x00, 
  0x00, 0xF1, 0xE2, 0x08, 0x00, 0x00, 0x00, 0xF1, 0xE3, 0x09, 
  0x00, 0x00, 0x00, 0xF1, 0xE5, 0x0C, 0x00, 0x00, 0x00, 0xF6, 
  0xF7, 0xF1, 0xE4, 0x07, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x08, 
  0x00, 0x00, 0x00, 0xF1, 0xE2, 0x09, 0x00, 0x00, 0x00, 0xF1, 
  0xE3, 0x0A, 0x00, 0x00, 0x00, 0xF1, 0xE5, 0x0C, 0x00, 0x00, 
  0x00, 0xF6, 0xF7, 0xF1, 0xE4, 0x08, 0x00, 0x00, 0x00, 0xF1, 
  0xE1, 0x0D, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x13, 0x00, 0x00, 
  0x00, 0xF8, 0xF1, 0xE4, 0x0D, 0x00, 0x00, 0x00, 0xF1, 0xE7, 
  0x13, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0E, 0x00, 0x00, 0x00, 
  0xF1, 0xE2, 0x12, 0x00, 0x00, 0x00, 0xF8, 0xF1, 0xE4, 0x0E, 
  0x00, 0x00, 0x00, 0xF1, 0xE7, 0x12, 0x00, 0x00, 0x00, 0xF1, 
  0xE1, 0x0F, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x11, 0x00, 0x00, 
  0x00, 0xF8, 0xF1, 0xE4, 0x0F, 0x00, 0x00, 0x00, 0xF1, 0xE7, 
  0x11, 0x00, 0x00, 0x00, 0xF4]
#print(opcode[0])
reg={0xE1:'eax',0xE2:'ebx',0xE3:'ecx',0XE5:'edx'}
opcode1={0xF1:'mov',0xF2:'xor',0xF5:'len(flag)',0xF4:'nop',0xF7:'mul',0xF8:'swap'}

i=0
for j in range(len(opcode)):
    if opcode[i]==0xF1:         #如果是0xf1,就是mov操作,一定会有下面的操作
        print('mov',end=' ')
        if opcode[i+1]==0xE1:
            print('eax '+'flag['+str(opcode[i+2])+']')
        elif opcode[i+1]==0xE2:
            print('ebx '+'flag['+str(opcode[i+2])+']')
        elif opcode[i+1]==0xE3:
            print('ecx '+'flag['+str(opcode[i+2])+']')
        elif opcode[i+1]==0xE4:
            print('flag['+str(opcode[i+2])+'] '+'eax')
        elif opcode[i+1]==0xE5:
            print('edx '+'flag['+str(opcode[i+2])+']')
        elif opcode[i + 1] == 0xE7:
            print('flag[' + str(opcode[i + 2]) + '] ' + 'ebx')
        i=i+6                  #加6是因为1+1+4,操作码+寄存器+dword类型数据(flag下标)
    elif opcode[i]==0xF2:
        print('xor eax, ebx')
        i=i+1
    elif opcode[i]==0xF2:
        print('xor eax, ebx')
        i=i+1
    elif opcode[i]==0xF5:
        print('len(flag)')
        i = i + 1
    elif opcode[i]==0xF4:
        print('nop')
        i = i + 1
    elif opcode[i]==0xF7:
        print('mul eax, edx')
        i = i + 1
    elif opcode[i]==0xF8:
        print('swap eax, ebx')
        i = i + 1
    elif opcode[i]==0xF6:
        print('eax = ecx + 2 * ebx + 3 * eax')
        i = i + 1
    else:
        i=i+1








得到

len(flag)                         
mov eax flag[0]
xor eax, ebx
mov flag[32] eax               
mov eax flag[1]
xor eax, ebx
mov flag[33] eax
mov eax flag[2]
xor eax, ebx
mov flag[34] eax
mov eax flag[3]
xor eax, ebx
mov flag[35] eax
mov eax flag[4]
xor eax, ebx
mov flag[36] eax
mov eax flag[5]
xor eax, ebx
mov flag[37] eax
mov eax flag[6]
xor eax, ebx
mov flag[38] eax
mov eax flag[7]
xor eax, ebx
mov flag[39] eax
mov eax flag[8]
xor eax, ebx
mov flag[40] eax
mov eax flag[9]
xor eax, ebx
mov flag[41] eax
mov eax flag[10]
xor eax, ebx
mov flag[42] eax
mov eax flag[11]
xor eax, ebx
mov flag[43] eax
mov eax flag[12]
xor eax, ebx
mov flag[44] eax
mov eax flag[13]
xor eax, ebx
mov flag[45] eax
mov eax flag[14]
xor eax, ebx
mov flag[46] eax
mov eax flag[15]
xor eax, ebx
mov flag[47] eax
mov eax flag[16]
xor eax, ebx
mov flag[48] eax
mov eax flag[17]
xor eax, ebx
mov flag[49] eax
mov eax flag[18]
xor eax, ebx
mov flag[50] eax
mov eax flag[19]
xor eax, ebx
mov flag[51] eax
nop

len(flag)
mov eax flag[0]
mov ebx flag[1]
xor eax, ebx
mov flag[0] eax
mov eax flag[1]
mov ebx flag[2]
xor eax, ebx
mov flag[1] eax
mov eax flag[2]
mov ebx flag[3]
xor eax, ebx
mov flag[2] eax
mov eax flag[3]
mov ebx flag[4]
xor eax, ebx
mov flag[3] eax
mov eax flag[4]
mov ebx flag[5]
xor eax, ebx
mov flag[4] eax
mov eax flag[5]
mov ebx flag[6]
xor eax, ebx
mov flag[5] eax
mov eax flag[6]
mov ebx flag[7]
mov ecx flag[8]
mov edx flag[12]
eax = ecx + 2 * ebx + 3 * eax
mul eax, edx
mov flag[6] eax
mov eax flag[7]
mov ebx flag[8]
mov ecx flag[9]
mov edx flag[12]
eax = ecx + 2 * ebx + 3 * eax
mul eax, edx
mov flag[7] eax
mov eax flag[8]
mov ebx flag[9]
mov ecx flag[10]
mov edx flag[12]
eax = ecx + 2 * ebx + 3 * eax
mul eax, edx
mov flag[8] eax
mov eax flag[13]
mov ebx flag[19]
swap eax, ebx
mov flag[13] eax
mov flag[19] ebx
mov eax flag[14]
mov ebx flag[18]
swap eax, ebx
mov flag[14] eax
mov flag[18] ebx
mov eax flag[15]
mov ebx flag[17]
swap eax, ebx
mov flag[15] eax
mov flag[17] ebx
nop

因为通过上面分析,我们知道如果是0xF4那就不进行操作,所以可以以nop为分界,把上面得到的分为两部分(后面就知道要使用第二部分)

我们先使用第一部分,第一部分就是异或操作,注意这里ebx==0x12,如下图可知

所以代码如下
发现是个假的flag...

通过观察发现还有一个检查函数

所以这次我们使用byte_202020的数据,在进行第二部分操作,第二部分就是对前六个进行异或变化,然后再变化str[6],str[7],str[8],在交换部分数据,所以解密代码如下:

#str1='Fz{aM{aM|}fMt~suM !!'
#str=list(map(ord,str1))
str=[0x69, 0x45, 0x2A, 0x37, 0x09, 0x17, 0xC5, 0x0B, 0x5C, 0x72,
  0x33, 0x76, 0x33, 0x21, 0x74, 0x31, 0x5F, 0x33, 0x73, 0x72]
flag=''
str[15],str[17]=str[17],str[15]
str[14],str[18]=str[18],str[14]
str[13],str[19]=str[19],str[13]

for i in range(32,128):
    if str[8]==((str[10]+2*str[9]+3*i)*str[12])&0xFF:
        str[8]=i
for i in range(32,128):
    if str[7]==((str[9]+2*str[8]+3*i)*str[12])&0xFF:
        str[7]=i
for i in range(32, 128):
    if str[6]==((str[8]+2*str[7]+3*i)*str[12])&0xFF:
        str[6]=i

for j in range(5,-1,-1):
    str[j]=str[j]^str[j+1]
for i in range(len(str)):
    flag+=chr(str[i])
print(flag)


 这次成功得到flag:Y0u_hav3_r3v3rs3_1t!

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

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

相关文章

标准分布的累计分布函数的差分去模拟离散的高斯分布

标准分布的累计分布函数的差分去模拟离散的高斯分布如何理解图像生成中“标准分布的累积分布函数的差分去模拟离散的高斯分布”?discretized_gaussian_log_likelihoodcodeapprox_standard_normal_cdftanh激活函数标准正态分布的累积密度函数如何理解图像生成中“标准…

提高代码质量!详解在Gradle项目中使用PMD的正确姿势

当今的软件开发需要使用许多不同的工具和技术来确保代码质量和稳定性。PMD是一个流行的静态代码分析工具,可以帮助开发者在编译代码之前发现潜在的问题。在本文中,我们将讨论如何在Gradle中使用PMD,并介绍一些最佳实践。 什么是PMD&#xff…

国内智慧城市标准是怎样的?

我国智慧城市标准化工作的历史可以回溯至2013 年,相关工作也得到了国家标准委、中央网信办、发展改革委、工业和信息化部等部门的高度关注和支持,在标准化协调机制、国家标准研制实施等方面取得了积极进展。 北京智汇云舟科技有限公司成立于2012年&#…

【vSphere | Python】vSphere Automation SDK for Python Ⅲ—— vCenter Datacenter APIs

目录5. vCenter Datacenter APIs操作5.1 Create Datacenter5.2 List Datacenter5.3 Get Datacenter5.4 Delete Datacenter参考资料5. vCenter Datacenter APIs 数据中心服务(Datacenter service)提供管理 vCenter Server 中数据中心的操作。 操作 Cre…

新加坡电商系统上线指南

如果您正在考虑在新加坡开展电子商务业务并准备上线您的电商网站,以下是一些指南和建议,可以帮助您成功地启动和运营您的电商业务: 确认您的业务模式和目标市场。在上线之前,您需要确定您的业务模式,例如是B2B&#xf…

Python 进阶指南(编程轻松进阶):六、编写 Python 风格的代码

原文:http://inventwithpython.com/beyond/chapter6.html 强大对于编程语言来说是一个没有意义的形容词。每种编程语言都称自己长处。官方 Python 教程开头就说 Python 是一种简单易学、功能强大的编程语言。但是没有一种语言可以做另一种语言不能做的算法&#xff…

Robosense激光雷达Linux配置

文章目录1.1 速腾rs16连接:1.2 网络配置1)官方说明2)设置网络3)检查是否连接成功2.1 激光雷达ROS包下载/编译1)下载ROS包2)安装libpcap依赖3)修改编译模式4)config文件配置5)编译并运…

AI-TestOps —— 软件测试工程师的一把利剑

写在前面软件测试的前世今生测试工具开始盛行AI-TestOps 云平台● AI-TestOps 功能模块● AI-TestOps 自动化测试流程写在前面 最近偶然间看到一句话:“软件测试是整个 IT 行业中最差的岗位”。这顿时激起了我对软件测试领域的兴趣,虽然之前未涉及过软件…

《Flutter进阶》flutter升级空安全遇到的一些问题及解决思路

空安全出来挺久了,由于业务需求较紧,一直没时间去升级空安全,最近花了几天去升级,发现其实升级也挺简单的,不要恐惧,没有想象中的多BUG。 flutter版本从1.22.4升到3.0.5; compileSdkVersion从1…

日撸 Java 三百行day11-13

文章目录说明day11-day12 顺序表1.面向过程面向对象区别2.代码2.1 面向过程2.2 面向对象day13 链表1.成员内部类2.链表的插入删除3.代码说明 闵老师的文章链接: 日撸 Java 三百行(总述)_minfanphd的博客-CSDN博客 自己也把手敲的代码放在了…

【51单片机】:LED任务及汇编解释任务

学习目标: 1、用汇编或者c语言实现D1 D3 D5 D7 为一组 ;D2 D4 D6 D8 为一组 ,两组实现 1)一组亮约一秒 另一组灭一秒,这样的互闪现象五次后 25分 2)所有灯灭约一秒后, …

关于ChatGPT的一些随笔

大家好,我是老三,最近几个月关于ChatGPT的信息可以说是铺天盖地。 “王炸,ChatGPT……” “xxx震撼发布……” “真的要失业了,xxx来袭……” “普通如何利用ChatGPT……” …… 不过老三前一阵比较忙,对ChatGPT…

ElasticSearch简介

第一章 ElasticSearch简介 1.1 什么是ElasticSearch Elaticsearch,简称为es, es是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理PB…

【数据结构与算法】树与二叉树

目录一.树1.树的定义2.结点的分类与关系3.树的相关概念4.树的表示方法二.二叉树1.二叉树的定义2.特殊二叉树3.二叉树的性质4.二叉树的顺序结构5.二叉树的链式结构(1)链式结构的创建(2)结点的创建(3)二叉树的手动构建(4)前中后序遍历(5)二叉树结点个数(6)二叉树的高度(7)第k层的…

Docker目录迁移

介绍 在docker的使用中随着下载镜像越来越多,构建镜像、运行容器越来越多, 数据目录必然会逐渐增大;当所有docker镜像、容器对磁盘的使用达到上限时,就需要对数据目录进行迁移。 如何避免: 1.在安装前对/var/lib/docker&#x…

如何3步精读《PMBOK指南》(含PMP备考资料)

初学者学习《PMBOK指南》的确有点吃亏,比不得那些项目管理专业以及相关专业的毕业生,哪怕只稍微接触过项目的都比初学者强。 所以,有计划性的阅读就显得尤为重要,要克服的不仅是阅读上的枯燥,还有专业知识的理解&…

Java——JDK动态代理

1.动态代理 1.1什么是动态代理? 动态代理(理解) 基于反射机制 举个例子,生活中一般在打官司的时候都会请代理律师,为什么要请律师呢?是因为开庭的时候大部人对于打官司没有经验,只会说出自己案件的陈述,并不…

软硬皆施,WMS仓库管理系统+PDA,实现效率狂飙

人工经验Excel表格,是传统第三方仓储企业常用的管理模式。在这种管理模式下,对仓库员工的Excel操作能力、业务经验和工作素养要求极高。一旦员工的经验能力不足,就会导致仓库业务运行不顺畅,效率低下,而员工也会因长时…

【MySQL】基于GTID的半同步主从复制(实践)

一、GTID简介 什么是GTID? 全局事务标识符GTID的全称为Global Transaction Identifier,是在整个复制环境中对一个事务的唯一标识。 它是MySQL 5.6加入的一个强大特性,目的在于能够实现主从自动定位和切换,而不像以前需要指定文件和位置。 …

ArduPilot飞控之DIY-F450计划

ArduPilot飞控之DIY-F450计划1. 历史2. 源由3. 计划3.1 硬件3.2 软件4. 动手4.1 接线4.1.1 ELRS nano接收机4.1.2 BN880 GPS模块4.1.3 Radio Telemetry4.2 配置4.2.1 选择四轴机型4.2.2 电源参数调整4.2.3 校准加速度计4.2.4 校准磁力计4.2.5 遥控器校准4.2.6 电机设置4.2.7 电…
最新文章