• 如何使用C#调用U8的COM组件之二 利器与初探


    前一章(点击可以看前一章内容),我们讲解了Interop的三大问题,本章将引入利器,对这三个问题进行初探,并加以解决

    善功必先利器

    工具一 SpyStudio

    这是我最近发现的一个特别牛逼的软件,主要用来HOOK程序,实时分析程序调用了那些api,读取了那些文件,用到了那些COM组件,读取了那些注册表。特别适合进行软件绿化,因为它能直接导出vmware thinapp,简直是神一样的存在,可惜不能在Win10下正常使用。但是绿化后的程序可以在各种系统下运行。

    工具二 ILMergeGUI_Portable和ILMerge

    用于将多个NET的DLL组件合并到一起,本来是一个命令行工具,后来我找到一个GUI的小程序,可以托拉拽了,特别强大和方便。

    工具三 DotNETHelper

    这也是一个杀手级别的利器,主要用来将NET反编译成IL文件,然后修改IL后,再次编译成DLL。我主要用它解决引用错误问题。因为Interop文件不能很完美反编译成C#语言,所以很多工作我都是在IL级别操作的。

    工具四 TotalCmd

    因为后期主要是对各种文件的操作,所以最好准备一个TC工具,可以非常方便的管理文件。对于这个软件可以说也是神级别的了,我就不多说了。自己百度吧。

    工具五 Mono.Cecil

    准确的说,这不是一个工具了,而是一个NET的类库,由Mono提供,可以修改Net程序的DLL文件,功能比DotHelper还要强大。因为需要对Interop文件进行批量的处理,而IL操作实在是太麻烦了,所以直接用这个类库,通过编程的方式,把我想修改的内容写成代码,然后执行,全部搞定!!

    工具使用

    以上的5个工具,除了SpyStudio暂时用不到,其他的工具,是下面将会用到的主要工具,所以希望大家提前去百度学习一下如何使用,这里不展开。毕竟也不是非常复杂,过程中我会尽量截图,让大家看的清除一些。

    Interop文件引用修复初探

    反编译观察

    有了工具,我们就可以分析Interop文件了,首先拿出DotNetHelper,把Interop.U8Login.dll反编译后,看一下IL文件的开始部分信息。
    DOTNETHELPER
    文件的内容很多,但是我们主要关注开头部分,因为开头部分是引用部分,相当于我们开发C#时,引用程序集那个部分的功能,具体的格式如下:

    // Metadata version: v2.0.50727
    .assembly extern mscorlib{
     .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .zV.4.. 
     .ver 2:0:0:0}
    .assembly extern ADODB{
     .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A )                         // .?_....: 
     .ver 7:0:3300:0
    }
    

    我们这里发现Interop.U8Login.dll 引用了两个组件,一个是2.0的mscorlib,也就是framewor 2.0的基本环境。一个是ADODB,版本7.0。并且我们发现ADDOB有两个特点。

    1、ADODB的这个引用带有强命名,.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A )
    2、ADODB这个引用前面没有Interop单词,.assembly extern ADODB,这个特征很重要,有时候我们在处理Interop.VBA.dll的时候你就会发现,有的引用居然是VBA.dll,有的是Interop.VBA.dll

    分析正确文件的特点

    我们再看一下,正确引用了Interop.U8Login.dll的其他Interop文件,比如下面就是我自己编译的Interop.USERPCO.dll,该类库引用了U8Login组件,这个类库也是非常重要的一个类,主要完成库存单据的保存功能。是API里面最核心的调用类。

    // Metadata version: v2.0.50727
    .assembly extern mscorlib
    {
      .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .zV.4..
      .ver 2:0:0:0
    }
    //这里的引用,publickey和U8login的ADODB引用是完全一样的
    .assembly extern ADODB
    {
      .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A )                         // .?_....:
      .ver 7:0:3300:0
    }
    .assembly extern Interop.VBA
    {
      .ver 6:0:0:0
    }
    //这里的引用,没有publickey
    .assembly extern Interop.USCOMMON
    {
      .ver 2:1:0:0
    }
    //注意这里的引用,有publickey
    .assembly extern Interop.U8Login
    {
      .publickeytoken = (79 A4 E7 AD 54 EE AB CA )                         // y...T...
      .ver 1:14:0:0
    }
    .assembly extern Interop.MSXML2
    {
      .ver 3:0:0:0
    }
    

    注意U8Login的强命名还有版本号 ,.publickeytoken = (79 A4 E7 AD 54 EE AB CA ) .ver 1:14:0:0
    注意ADODB的强命名和版本号,这两个值是(.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) .ver 7:0:3300:0 ),且和U8Login使用的ADODB完全一样,这样的文件,就是正确的,因为如果U8Login有返回值是ADODB中的类,那么这个Interop文件可以正常操作,不会出现类型转换失败的问题,因为他们引用的是同一个ADODB文件。

    错误文件的特征

    再看一个我们自己生成的Interop后最容易遇到的问题,往往我们自己生成Interop 文件以后,很有可能是这样的

    //前面的我就忽略不贴出来了,直接看关键的U8Login的引用
    .assembly extern Interop.U8Login
    {
      .ver 1:29:0:0
    }
    

    正确的应该如下

    .assembly extern Interop.U8Login
    {
      .publickeytoken = (79 A4 E7 AD 54 EE AB CA )                         // y...T...
      .ver 1:14:0:0
    }
    

    这里之所以不一致,就是前文说的拖家带口问题导致的,其实你仔细看,就会发现在你生成的Interop文件对应的目录里面,居然还有一个Interop.U8Login.dll,而这个文件就是版本1.29那个文件。而NET程序是绝对不能引用两个同名文件的。所以必须将公用引用文件保持一致。
    到此我们发现了正确文件的基本特征:

    1、公用文件,比如ADODB,他们引用的名称,版本号,强命名都是完全一样的
    2、彼此关联的文件,比如某DLL引用了Interop.U8Login.dll,必须保证某DLL中U8login的版本和强命名还有名称和原版的Interop.U8Login一致。

    Interop引用错误的问题修改

    毛爷爷教导我们,知错不改,不是好同志!既然我们知道了错误的根本原因,那么下面就开始做一名真正的好同志。

    修改方法1 反编译法

    之前说过,Interop.U8Login.dll不是能完美反编译成C#的,但是如果你愿意手工干预,通过后期的修改,这个项目可以完美的变成一个标准C#类库项目,然后通过修改引用,再次编译就好了。可惜,我不认为有人会这么干,因为Interop文件实在太多了,修改工作量巨大,错曾经尝试过几次,最后都放弃了。

    修改方法2 命令行参数法

    正统的解决方案微软其实是给出来的,就是通过在使用Tlbimp.exe这个命令行的时候,使用/reference 参数

    Tlbimp.exe C:U8SoftUfcomsqlU8Login.dll  /reference:"C:U8SoftInteropMSXML2.dll"
    Tlbimp.exe C:U8SoftUfcomsqlUSERPCO.dll  /reference:"C:U8SoftInteropInterop.U8Login.dll" /reference:"C:U8SoftInteropMSXML2.dll"
    
    

    上面的代码,展示了如何使用多个已有类库文件,解决引用错误。这个方法真的非常不错,我以前也使用,后来觉得还是改IL比较有成就感,所以就不怎么用这个方法。但是我还是强力推荐该方法。

    修改方法3 IL修改法

    之前的整个研究过程,都是基于IL进行,所以我最早使用的就是DotNetHelper工具进行IL修改去解决这个问题的。速度也比较快,反编译,打开IL文件,找到错误点,修改,重新编译,问题解决。(这里补充一下,因为ocx控件使用AxImp工具生成AxInterop文件,但是这个命令行工具没有引用参数reference,所以只能使用IL修复法。)修改的过程如下:

    //前面的我就忽略不贴出来了,直接看关键的U8Login的引用
    .assembly extern Interop.U8Login
    {
      .ver 1:29:0:0
    }
    
    

    正确的应该如下

    .assembly extern Interop.U8Login
    {
      .publickeytoken = (79 A4 E7 AD 54 EE AB CA )                         // y...T...
      .ver 1:14:0:0
    }
    

    本章完
    下一章,开始讲解在面对繁多的U8版本和繁多的Interop时,面临的新问题

  • 相关阅读:
    socket的一个错误的解释SocketException以及其他几个常见异常
    lambda表达式和ef的语句转化
    多线程的异步委托初识
    跨线程访问控件的方法
    P1337 [JSOI2004]平衡点 / 吊打XXX
    P4099 [HEOI2013]SAO
    UVA10529 Dumb Bones
    P1291 [SHOI2002]百事世界杯之旅
    P2675 《瞿葩的数字游戏》T3-三角圣地
    P4363 [九省联考2018]一双木棋chess
  • 原文地址:https://www.cnblogs.com/lothar/p/13335064.html
Copyright © 2020-2023  润新知