zoukankan      html  css  js  c++  java
  • dotNet MSIL中的一些不常见IL指令

    dotNet MSIL中的一些不常见IL指令

    在做HVM伪代码覆盖率检测时,在构造的一些dotNet程序样本中总是缺少一些MSIL指令

    ,没有覆盖所有的MSIL指令。
    如C#中的装箱和取消装箱的IL指令,可能很多人和我最初的想法一样,装箱是 box指令

    ,取消装箱是unbox指令,实际上这只对了一半。


    装箱使用的box指令没有错误,但是取消装箱不是用的unbox指令,而是 unbox.any 指

    令,在C#编译的程序中就从来没有发现过 unbox 指令。

    另外还有一批没有发现的指令有 calli , cpobj, ldobj, stobj, refanyval,

    mkrefany,arglist, refanytype, initblk, cpblk

    initobj指令也比较少见,不过在C#的泛型中遇到了:
    如 T obj = default(T); 编译后就会出现 initobj 指令。
    这个指令就是给变量赋初值。

    calli 在C#里面没有,在C++/CLI构造出来了,实际上它是调用函数指针的用法。

    refanyval, mkrefany,arglist, refanytype 看了一篇介绍 undocumented IL 的文章

    后构造出来了,具体可参考转的帖子。

    其它的指令构造不出来就只能蛮干了,把exe用ilasm整成的 il 文件,然后直接修改il

    ,再编译测试,经过反复实验,构造出了可以正常运行的程序。

    先看装箱和取消装箱,
    int i = 123;
    object obj = i;
    i = (int)obj;
    对应的il代码是:
    第一句:
    ldc.i4.s   123
    stloc.0
    第二句:
    ldloc.0
    box        [mscorlib]System.Int32
    stloc.1
    第三句:
    ldloc.1
    unbox.any  [mscorlib]System.Int32
    stloc.0

    首先我就是直接把
    unbox.any  [mscorlib]System.Int32
    改为
    unbox  [mscorlib]System.Int32

    然后测试,发现这是 i 的值不等于 123了,而是一个不确定的数字。看IL文档得知

    unbox生成的只是一个指针,也就是地址。
     
    这时想到了另外一个指令 ldobj ,这个指令直接从地址读取数据放到堆栈上。
    如是把
    unbox.any  [mscorlib]System.Int32
    改为
    unbox  [mscorlib]System.Int32
    ldobj  [mscorlib]System.Int32

    再测试,结果正确了。看起来 unbox + ldobj 的效果和 unbox.any一样。

    stobj 指令,从名称就能看出它和 ldobj只对应的。将立即数存入地址中。
    功能类似如c++中的 *p = value;

    i = 3;
    正常方式应该是
    ldc.i4.s 3
    stloc.s.0
    改为另一种模式
    ldloca.s 0 //载入 i 的地址
    ldc.i4.s 3 //载入立即数
    stobj [mscorlib]System.Int32 //将立即数存入地址


    cpobj 指令,直接从地址复制对象类似c++中的 *p1 = *p2;

    int i, j;
    i = 3;
    j = i;
    正常方式是
    ldc.i4.s 3
    stloc.s 0

    ldloc.s 0
    stloc.s 1
    改为使用cpobj的模式
    ldloca.s 1 //dest
    ldloca.s 0 //src
    cpobj [mscorlib]System.Int32 //copy

    initblk 类似如C中的 memset 函数
    cpblk 类似如C中的 memcpy函数

    DNGuard HVM核心是通过将IL代码替换为HVM伪指令然后提交给Jit去编译的,所以需要

    检测所有的HVM伪指令是否都能够被正确编译执行。测试遇到没有覆盖的指令只好用蛮

    干的方法构造样本了。
    目前以及完成了 .net framework 2.0, .net framework 3.0环境下的指令覆盖检测,

    所有HVM伪指令都编译通过了。
    接下来将对 .net framework 1.1 和 .net framework 3.5的环境进行指令覆盖检测。

     

  • 相关阅读:
    九大经典算法之插入排序、希尔排序
    1072 开学寄语 (20 分)
    1070 结绳 (25 分
    查找字符串中的所有数字
    通过类继承计算梯形面积
    将命令的输出生成一个Web页面
    从Internet下载一个文件
    使用Excel管理命令输出
    将一个命令的输出保存到CSV文件
    使用属性存储用户编号和姓名
  • 原文地址:https://www.cnblogs.com/rick/p/864295.html
Copyright © 2011-2022 走看看