首页
社区
课程
招聘
2
[原创] dotNET 动态脱壳技术要点
发表于: 6天前 1038

[原创] dotNET 动态脱壳技术要点

htg 活跃值
4
6天前
1038

加壳脱壳要点

dotNET 程序文件内主要存储的是 IL 字节码,一般加壳之后,其 IL 字节码会隐藏或屏蔽,而脱壳的关键在于恢复 IL 字节码,进而近似获取程序源代码。

JIT主要作用

dotNET 程序一般在 JIT 的时候会将 IL 全部或部分解析出来,一般来说不对 token 加密的话,此时JIT的时候,会出现完整的IL。

JIT主要流程

dotNET JIT 流程大致是:

1
2
3
4
5
6
7
8
9
clr!ThePreStub
clr!PreStubWorker
clr!MethodDesc::DoPrestub
clr!MethodDesc::MakeJitWorker
clr!UnsafeJitFunction
clr!CallCompileMethodWithSEHWrapper
clr!invokeCompileMethod
clr!invokeCompileMethodHelper
clrjit!CILJit::compileMethod

dotNET 程序在运行的时候,具体到方法执行时,CLR 会为每个方法生成一个 stub,然后调用一堆JIT 函数,生成机器码。这里面关键 JIT 有两个,一个是 DoPrestub 函数,一个是 compileMethod 函数。相对来说,compileMethod 更偏底层。

通过JIT获取IL的关键要点:

IL 会在哪儿出现?

如果 dotNET 未加壳,那么在 DoPrestub 里就能够获取到 IL ,DoPrestub 的一个参数就是 MethodDesc,也就是方法描述符,通过它就可以获取IL。
但是 dotNET 加壳了,在 DoPreStub 里获取的 MethodDesc ,其找到 IL 是加密的或是错误的。一般壳体会劫持一些 JIT 函数,调用一些解密或恢复函数,进而获取真正的IL,然后再交由所劫持的 JIT 函数去生成机器码,进而执行该方法。
一般壳体不会完整实现更底层的功能,比如如何将每一个IL代码转换成一堆机器码,以及一些代码优化工作,这个工作量太大,而且不太会比原始 JIT 更好,还有可能出现运行错误。

获取 IL 的策略分析

一种策略是,遍历所有的方法,获取方法的 MethoDesc,然后手动触发 DoPrestub,进而触发壳体内部的 IL 解密或恢复函数,获取想要的IL。但是这里存在五个问题:

一是 某一个方法一旦触发 DoPreStub 之后,会被立即执行;

二是 某一个方法一旦触发 DoPreStub 之后,不会再次触发,如果壳体需要多次触发才能获取IL,怎么办?;

三是 UnboxingStub 不会被 JIT 直接编译;


[注意]看雪招聘,专注安全领域的专业人才平台!

最后于 6天前 被htg编辑 ,原因:
收藏
免费 2
支持
分享
赞赏记录
参与人
雪币
留言
时间
自由狼
+10
感谢你的积极参与,期待更多精彩内容!
5天前
科学上网
谢谢你的细致分析,受益匪浅!
6天前
最新回复 (0)
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册