一道VM的逆向所引发的符号执行思路
逆向虚拟机保护
虚拟机保护类的题目需要找到虚拟机的vm_code(字节码),各个handler,然后进一步分析虚拟机保护代码的流程。
用IDA打开程序,经分析后0x403040全局变量地址处存储的就是所有的字节码,共114个。

所有的字节码:
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, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00
0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x09, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x51, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x36, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x09, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x41, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0xA7, 0xFF, 0xFF, 0xFF,
0x07, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0xF1, 0xFF, 0xFF, 0xFF,
0x07, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x84, 0xFF, 0xFF, 0xFF,
0x07, 0x00, 0x00, 0x00, 0xC1, 0xFF, 0xFF, 0xFF,
0x07, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x7A, 0x00, 0x00, 0x00
我们进入vm函数后发现,虚拟机的流程大致是将我们的输入flag与a1字节码数组运算后存到V4数组中,然后比较V4数组与a1字节码中的某些数据是否相等,相等则输入正确。所以我们可以先得出数组V4。

我们将v4[v8] != a1[v10 + 1] 改为 v4[v8] = a1[v10 + 1]的出正确的数组,同时记录虚拟机的执行顺序即执行字节码的顺序。最后的出V4数组与执行字节码的顺序分别为:
unsigned char v4[] = { 0X22, 0X3F, 0X34, 0X32, 0X72, 0X33, 0X18, 0XFFFFFFA7, 0X31, 0XFFFFFFF1, 0X28, 0XFFFFFF84, 0XFFFFFFC1, 0X1E, 0X7A };
unsigned char Index[100] = { 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 17, 18, 19, 20, 22, 23, 25, 26, 28, 29, 30, 31, 32, 33, 35, 36, 38, 39, 41, 42, 44, 45, 46, 47, 48, 49, 51, 52, 54, 55, 57, 58, 60, 61, 63, 64, 66, 67, 69, 70, 72, 73, 75, 76, 78, 79, 81, 82, 83, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114 };
将虚拟机的算法的逆过程结合V4和Index得出代码求出flag。
int __cdecl vm_operad(int *a1, int a2)
{
int result; // eax
unsigned char Str[100] = {0}; // [esp+13h] [ebp-E5h]
unsigned char v4[100] = {0x22, 0x3f, 0x34, 0x32, 0x72, 0x33, 0x18, 0xa7, 0x31, 0xf1, 0x28, 0x84, 0xc1, 0x1e, 0x7a }; // [esp+77h] [ebp-81h]
char v5; // [esp+DBh] [ebp-1Dh]
int v6; // [esp+DCh] [ebp-1Ch]
int v7; // [esp+E0h] [ebp-18h]
int v8; // [esp+E4h] [ebp-14h]
int v9; // [esp+E8h] [ebp-10h]
int v10; // [esp+ECh] [ebp-Ch]
char Index[] = {1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 17, 18, 19, 20, 22, 23, 25, 26, 28, 29, 30, 31, 32, 33, 35, 36, 38, 39, 41, 42, 44, 45, 46, 47, 48, 49, 51, 52, 54, 55, 57, 58, 60, 61, 63, 64, 66, 67, 69, 70, 72, 73, 75, 76, 78, 79, 81, 82, 83, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114};
v10 = 0x72;
v9 = 0xf;
v7 = 0xf;
v6 = 0xf;
int i = 0;
while ( 1 )
{
result = v10;
if ( sizeof(Index) - i + 1 == 0 )
return result;
i++;
switch ( a1[Index[sizeof(Index) - i]] )
{
case 1:
--v9;
--v7;
--v10;
v5 = v4[v7];
break;
case 2:
v10 -= 2;
Str[v9] = v5 - a1[v10 + 1];
break;
case 3:
v10 -= 2;
Str[v9] = v5 + LOBYTE(a1[v10 + 1]);
break;
case 4:
v10 -= 2;
Str[v9] = v5 ^ a1[v10 + 1] ;
break;
case 5:
v10 -= 2;
Str[v9] = v5 / a1[v10 + 1];
break;
case 6:
--v10;
break;
case 7:
v10 -= 2;
break;
case 8:
--v6;
--v10;
v5 = Str[v6];
break;
case 10:
--v10;
break;
case 11:
--v10;
Str[v9] = v5 + 1;
break;
case 12:
--v10;
Str[v9] = v5 - 1;
break;
default:
continue;
}
}
}
利用符号执行
符号执行
符号执行指的是用符号值来代替某些变量的真实值,用符号值来遍历程序所有的执行分支,而用真实值只能遍历一条分支。然后通过约束求解引擎来在筛选所有的分支选出符合条件的那一个,最后得出正确的输入值。
angr
angr是二进制程序分析框架,可以用来进行完成符号执行。
在此题目中我们希望程序执行到vm函数自然返回处,而不会执行到what a shame...处,这样就说明其输入正确。
vm函数自然返回处的地址为0x40175E

what a shame...处的地址为0x4016e6

所以我们可以利用angr写python符号执行脚本:
import angr #导入angr库
p = angr.Project('signal.exe',auto_load_libs=False) #创建一个Project,程序不引用任何其他导入库
st = p.factory.entry_state() #将程序加载并执行到入口处,返回其状态
sm = p.factory.simulation_manager(st) #创建一个模拟执行器
sm.explore(find=0x40175E, avoid=0x4016E6) #设置约束条件,find是程序需要执行到的地址,avoid是程序不能执行到的地址
print(sm.found[0].posix.dumps(0)) #输出结果
参考:https://www.52pojie.cn/thread-1176826-1-1.html
一道VM的逆向所引发的符号执行思路的更多相关文章
- 一道国外前端面试题引发的Coding...
刚刚看到CSDN微信公众号一篇文章,关于国外程序员面试前端遇到的一道测试题,有点意思,遂写了下代码,并记录一下~ 题目是这样的: ['Tokyo', 'London', 'Rome', 'Donlon ...
- 一道有意思的笔试题引发的对于new操作符的思考
楼主比较喜欢看一些很短但很有意思的题目,无意间又瞥到了一题,大家不妨可以一试.(原题链接猛戳这里) function Fn1() { this.name = 'peter'; return { nam ...
- 一道JS面试题所引发的"血案",透过现象寻本质,再从本质看现象
觉得本人写的不算很烂的话,可以登录关注一下我的GitHub博客,新手写东西写的不好之处,还望见谅,毕竟水平有限,写东西只为交流提高,一起学习,还望大神多加指点,指出纰漏,和提出宝贵的意见,博客会坚持写 ...
- 通过JS逆向ProtoBuf 反反爬思路分享
前言 本文意在记录,在爬虫过程中,我首次遇到Protobuf时的一系列问题和解决问题的思路. 文章编写遵循当时工作的思路,优点:非常详细,缺点:文字冗长,描述不准确 protobuf用在前后端传输,在 ...
- 【一天一道LeetCode】#57. Insert Interval
一天一道LeetCode系列 (一)题目 Given a set of non-overlapping intervals, insert a new interval into the interv ...
- 网络爬虫之记一次js逆向解密经历
1 引言 数月前写过某网站(请原谅我的掩耳盗铃)的爬虫,这两天需要重新采集一次,用的是scrapy-redis框架,本以为二次爬取可以轻松完成的,可没想到爬虫启动没几秒,出现了大堆的重试提示,心里顿时 ...
- x32下PsSetLoadImageNotifyRoutine的逆向
一丶简介 纯属兴趣爱好.特来逆向玩玩. PsSetLoadImageNotifyRoutine 是内核中用来监控模块加载.操作系统给我们提供的回调. 我们只需要填写对应的回调函数原型即可进行加监控. ...
- 「每日一题」有人上次在dy面试,面试官问我:vue数据绑定的实现原理。你说我该如何回答?
关注「松宝写代码」,精选好文,每日一题 时间永远是自己的 每分每秒也都是为自己的将来铺垫和增值 作者:saucxs | songEagle 来源:原创 一.前言 文章首发在「松宝写代码」 2020. ...
- JavaScript OOP 之「创建对象」
工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程.工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题. function createPers ...
随机推荐
- Linux入门视频笔记一(基本命令)
一.简单命令 1.date:当前时间 2.cal:当前日期(日历格式) ①cal 2019:2019年全年日历 ②cal 1 2019:2019年1月份 二.Linux文件结构 1.根目录:root( ...
- 《C++反汇编与逆向分析技术揭秘》--算术运算和赋值
一.加法 1.Debug下: 14: int nVarOne0 = 1 + 5 - 3 * 6;//编译时计算得到结果 00C0550E C7 45 F8 F4 FF FF FF mov dword ...
- Caused by: java.lang.RuntimeException: JxBrowser license check failed: No valid license found
使用jxbrower报错,原因时证书检验失败, 解决方案: 1.首先创建证书,下面是我在IDEA maven项目中创建的位置,Java项目中在src/目录下创建, META-INF/teamdev.l ...
- teprunner测试平台用例前置模块开发
本文开发内容 现在正式进入测试相关功能开发.teprunner测试平台底层是pytest,中间层是tep,还没了解的朋友可以先看看tep的文章,整个平台的设计思路和后面用例的执行都会基于这个工具.te ...
- Amundsen在REA Group公司的应用实践
REA Group是一家专门面向房地产与实业资产的跨国数字广告公司. 他们主要为消费者提供房地产购买.出售与租赁服务,同时发布各类房产新闻.装修技巧以及生活方式层面的内容.每一天,都有数百万消费者访问 ...
- 原来Java的发家史是这么回事
java的诞生: 1991 年Sun公司成立了一个计算机开发小组,由James Gosling等人开发一款希望用于控制嵌入在有线电视交换盒.PDA等的微处理器的计算机语言,本来他们想直接扩展C++,后 ...
- Android Activity间跳转与传递数据
1 概述 Activity之间的跳转主要使用 startActivity(Intent intent); startActivityForResult(Intent intent,int reques ...
- SpringBoot开发秘籍 - 集成Graphql Query
概述 REST作为一种现代网络应用非常流行的软件架构风格受到广大WEB开发者的喜爱,在目前软件架构设计模式中随处可见REST的身影,但是随着REST的流行与发展,它的一个最大的缺点开始暴露出来: 在很 ...
- Day11_51_Collections工具类之sort方法和list集合的遍历方式
Collections工具类之sort方法 * 使用Collections工具类对List集合进行排序 Collections.sort(List集合) * Collections.sort()方法只 ...
- 某大佬的TODOLIST
回文串 manacher(完成时间:2018.12.10)回文串计数最长双回文串(完成时间:2018.12.10) 扫描线 棋盘制作巨大的牛棚玉蟾宫某个blog 汉诺塔相关 新汉诺塔SHOI 博弈论 ...