- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
测试下VMP加密.NET的强度,选了最新的.Net8+AOT编译,用VMP给它加壳。最后逆向下,简单的分析,本篇看下.
一.前奏 首先一段简单的C#代码:
namespace Test_{
internal class Program{
static void Main(string[] args) {
Console.WriteLine("hello, World!");
Console.ReadLine();
}
}
}
把这段代码编译成AOT:
1.csproj里面添加 <PublishAot>true</PublishAot>
2.dotnet publish -r win-x64 -c Release
编译完成之后在路径 。
bin\release\net8.0\win-x64\publish
找到Test_.exe,然后对它进行VMP加密。这里用的是VMP3.7.1。为了最大强度加密,把它所有加密全选上,如下图: 最后得到一个独立的Exe文件Test_.vmp.exe。把这个Exe运行之后,拍摄一个内存快照,它的堆栈如下 。
00 00000000`0014fad8 00007fff`00cc65cb ntdll!NtReadFile+0x14
01 00000000`0014fae0 00000001`40140e2b KERNELBASE!ReadFile+0x7b
02 00000000`0014fb50 00000001`401419d9 Test__vmp+0x140e2b
03 00000000`0014fc10 00000001`401418d1 Test__vmp+0x1419d9
04 00000000`0014fc60 00000001`40143bed Test__vmp+0x1418d1
05 00000000`0014fca0 00000001`400e0796 Test__vmp+0x143bed
06 00000000`0014fd00 00000001`400e0857 Test__vmp+0xe0796
07 00000000`0014fd50 00000001`401440ce Test__vmp+0xe0857
08 00000000`0014fda0 00000001`401413d2 Test__vmp+0x1440ce
09 00000000`0014fde0 00000001`4007b455 Test__vmp+0x1413d2
0a 00000000`0014fe10 00000001`4016bc0b Test__vmp+0x7b455
0b 00000000`0014fe40 00000001`4006e15e Test__vmp+0x16bc0b
0c 00000000`0014fea0 00000001`400694b4 Test__vmp+0x6e15e
0d 00000000`0014fef0 00007fff`029426ad Test__vmp+0x694b4
0e 00000000`0014ff30 00007fff`0370aa68 kernel32!BaseThreadInitThunk+0x1d
0f 00000000`0014ff60 00000000`00000000 ntdll!RtlUserThreadStart+0x28
因为它停在了ReadLine()这个托管函数上面,又因为托管代码进行了AOT,所以它这里的堆栈其实就是非托管栈.
注意这个堆栈里面的第10行,也即编号09哪一行 。
09 00000000`0014fde0 00000001`4007b455 Test__vmp+0x1413d2
这里就是.Net8预编代码AOT的托管Main入口的非托管表现.
Test__Test__Program__Main
看下它的内容:
00000001`4007b440 4883ec28 sub rsp,28h
00000001`4007b444 488d0d6dc52200 lea rcx,[Test__vmp+0x2a79b8 (00000001`402a79b8)]
00000001`4007b44b e8905f0c00 call Test__vmp+0x1413e0 (00000001`401413e0)
00000001`4007b450 e86b5f0c00 call Test__vmp+0x1413c0 (00000001`401413c0)
00000001`4007b455 90 nop
00000001`4007b456 4883c428 add rsp,28h
00000001`4007b45a c3 ret
这里刚好的是托管示例的机器码调用,注意它只是内存里面的表现
二:虚拟机原理 这里需要简单了解下虚拟机的原理,虚拟机会根据传递进来的代码,对这些代码进行,解析,组合,变形等等之后,组合成新的机器码在机器上运行。这里的VMP本身就是个虚拟机,它把AOT的汇编代码,进行解析,组合,变形之后形成汇编代码运行。了解了这一点,我们就知道上面的内存快照只不过是它运行时候的表现,而实际上Exe里面的代码未必会是这种表现.
这里看下,hello World字符串 。
00000001`4007b444 488d0d6dc52200 lea rcx,[Test__vmp+0x2a79b8 (00000001`402a79b8)]
它指向的就是字符串实例的MethodTable,hello world字符串清晰可见:
00000001`402a79b8 88 41 20 40 01 00 00 00-0d 00 00 00 48 00 68 00 .A @........h.e.
00000001`402a79c8 6c 00 6c 00 6f 00 2c 00-20 00 57 00 6f 00 72 00 l.l.o.,. .W.o.r.
00000001`402a79d8 6c 00 64 00 21 00 00 00-00 00 00 00 00 00 00 00 l.d.!...........
但是这些代码只是内存的表现,而实际上存储在Exe里面可能是加密过的字符串,这里是解析之后,最后运行的结果。如果想要修改掉这串字符,那么得找到这串字符ASCII单个byte加密的地方.
三:特征码 我们可以看到字符串的操作取地址lea指令后面是立即数:
00000001`4007b444 488d0d6dc52200 lea rcx,[Test__vmp+0x2a79b8 (00000001`402a79b8)]
一般来说,这种取地址不会混淆,所以这里在Test_.vmp.exe的整个汇编里面搜索一下特征 。
lea rcx 后面跟立即数的
结果如下:
000000014067AA6D: 48 8D 0C 06 lea rcx,[000000014067B101]
地址:000000014067AAE4如下:
000000014067B101: 93 xchg eax,ebx
000000014067B102: 32 C0 xor al,al
000000014067B104: CB retf
000000014067B105: 02 68 B0 add ch,byte ptr [rax-50h]
可以看到地址:000000014067B106有个0x68,还记得上面的hello World字符串嘛,首字母h的ASCII就是0x68.
OK,要找的就是这个地方了,在十六进制编辑器里面把它改成0x67,然后保存运行下Test_.vmp.exe。字符串hello World变成了gello World,如下图.
非常简单的一个例子,如果你对以上感兴趣,可以扫描下面卡片关注我。带你玩好玩的技术.
最后此篇关于.Net8AOT+VMP简单的逆向分析的文章就讲到这里了,如果你想了解更多关于.Net8AOT+VMP简单的逆向分析的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在尝试从 Unity 发布到我的 iPhone 4s。构建成功,但我继续收到此消息: “在 aot-only 模式下运行时无法加载 AOT 模块‘Assembly-CSharp’,因为依赖项无法找
在听说了这么多有关 Angular AOT 模式的信息后,我想尝试一下。因此,我们将应用程序迁移到 Angular v4.1.2,并进行了所有必要的更改。当我尝试使用我的 webpack 配置文件中的
我有一个 C# 项目,我需要将其编译为 native 二进制文件。我在这里读过: http://www.mono-project.com/AOT Mono 可以将程序集预编译为两个选项之一: --ao
我搜索了很多关于这种伟大语言的信息,并在此页面上找到了自己 https://github.com/dart-lang/sdk/wiki/Snapshots但它没有回答一些问题: 快照和 AOT 有什么
我知道什么是字节码检测。它只是在运行时更改 .class 文件字节码,这似乎从 JDK 1.5 开始可用。但是,据说是在类加载期间而不是运行时。 现在我的问题是,什么是 AOT 或提前检测?相反的程序
我正在为我的应用程序构建一个插件系统。我读到任何人都可以反编译 .class 文件,因此我不得不使用 Ahead-Of-Time 编译器(对吗?)。问题是我需要动态加载一些插件类。现在,我正在将所有
我的问题是 Angular 模块之一无法在 Safari 浏览器中正常工作。 我有以下代码: @NgModule({ bootstrap: [ AppComponent ], impo
我在这里问是因为我无法在网上找到完整的文档。示例 here太简单了。我有一个包含多个组件和一些模块的应用程序。用ngc编译后,我有很多错误。我发现修复它们的方法是使用相对路径。因此,我在所有组件中都使
在使用 webpack 进行 AOT 构建后,bundle 将每个组件模板包含两次,使得 bundle 比需要的大得多,因为模板作为字符串包含在内,UglifyJS 无法缩小。 我希望组件模板被排除为
我正在尝试使用 ngc 编译 angular 2.4.4: Error: Error encountered resolving symbol values statically. Expressio
当我这样做时,有什么原因(我可以解决): ngc -p tsconfig.aot.json 作为回应,它要求: 姓名: ngc 似乎忽略了我的 tsconfig.aot.json。 这可能是什么原因?
我正在开发一个 Angular 7 应用程序,除了加载问题外它工作正常,在研究中我发现我应该使用 AOT 构建而不是 JIT 或正常构建,由于应用程序规模巨大,我无法进行 aot 构建,它正在返回堆我
我在 Dynamics AX 2012 中有一个 AOT 查询,它由 HcmWorker 和 HcmEmployment 表(等等)组成。我的问题是,当我创建报告(不是 SSRS)或以其他方式使用此查
有谁知道在使用带有 AOT 编译的 Angular CLI 时如何获得更详细的错误堆栈跟踪?使用 JIT 编译运行时,我的应用程序没有问题,但是当我运行 ng build --aot 时,我得到的只是
我想查询 AOT 以查看是否存在使用 X++ 的表名。谁能指出我正确的方向或提供一些示例代码来做到这一点? 如果表存在并提供名称 (str tableName),则返回 true;否则,返回false
我有一个 Angular 5 应用程序,当我在测试模式下运行时没有问题,也就是说,当我使用 ng serve 命令在本地运行应用程序时。但是,当我在生产模式下部署应用程序时,即通过命令ng build
语境 我正在创建一个 Angular 应用程序的桌面版本,为此我正在使用 Electron 。 打开主窗口非常简单: win = new BrowserWindow({ width: 1280
我有一个看起来像这样的错误处理程序: @Injectable() export class GlobalErrorHandler implements ErrorHandler { construct
当我尝试构建启用了 AOT 选项的 Android 应用程序时,收到以下错误消息。 Invalid command line switch for "aapt.exe". VersionCode is
我在我的 Angular 2 应用程序中使用 Highcharts 和 Kendo Charts,当我尝试运行 AOT 编译时,它会抛出类似的错误 Cannot Import Module 或 Hom
我是一名优秀的程序员,十分优秀!