by Iczelion (翻译:花心萝卜yqzq@163.net) 9.5.2000

这篇短文是讲述关于建立MASM导入库(import libraries)技巧,我假设你已经知道什么是导入库。在下面,我将集中讲述建立MASM导入库的方法。

MASM导入库的格式:


MASM和VC++可以使用相同的导入库,MS导入库使用不同于TASM的OMF格式的变更的COFF文件格式,这就是为什么TASM和MASM的导入库不能互用的原因,我将不详细介绍有关MS导入库的格式。可以这样说,每一个MS导入库都包含某个DLL中函数的信息(你将要用这些信息来调用DLL中的函数),这些信息包括函数名和它所有参数的尺寸。如果你用一个文本编辑器打开kernel32.lib,你回发现一些如下格式的信息:

_ExitProcess@4
_CreateProcessA@40

函数名被装饰上了一个“_”,在“@”之后的数字表示了该函数所有参数的尺寸(字节为单位),ExitProcess 函数只有一个DWORD的参数,所以后面的数字是4。 LIB中为什么要包含这些参数尺寸的信息呢?当你用INVOKE调用函数时,这些信息被用来检测传递给函数的参数是否正确。如果你使用“手工”将参数压入堆栈,并通过“CALL”来调用函数的话,MASM将无法检测参数是否正确。这将导致我们几乎没有办法建立一个DLL的导入库,因为DLL并不包含清楚的关于参数尺寸的信息。

从DLL建立MASM导入库


如果你很乐意用“手动”(CALL)的方法去调用函数的话,你可以象下面这样为任何一个DLL建立MASM的导入库:

使用dumpbin.exe,它可以导出DLL 输出(EXPORT)函数的名字。

Dumpbin /EXPORTS  blah.dll  >  output.txt

在你获得了函数名列表之后,通过他们建立一个模块定义文件(.DEF)。 举个例子:如果DLL只包含一个函数:GetSomeLine 在一个文本文件中输入如下内容:

LIBRARY blah
EXPORTS
GetSomeLine

并将其保存为“blah.def

象这样,运行lib.exe,通过模块定义文件建立一个导入库:

lib /DEF:blah.def

就是它了!你将获得blah.lib,只要你不使用INVOKE调用函数的话,你就可以在MASM中使用它。

建立通过INVOKE调用函数的MASM导入库:


我并不反对你使用上面的方法,但INVOKE确实是一个调用函数的好途径。这也是我较TASM更喜欢MASM的原因之一。但就象我早先强调的,我们几乎不可能从一个DLL建立一个能100%工作的MASM导入库。如果你使用INVOKE,你将不能用上面的方法建立一个MASM导入库。举个例子,你可以想象如果你在.DEF文件中修改了函数的“@XX”部分,导入库将仍然正常建立,但请相信我,他不会工作的。 建立一个可以使用INVOKE的导入库的一个简单的方法是使用MASM。如果你写过DLL的代码,你会发现你不仅的到了一个DLL,而且还得到了一个导入库,没错,它就是我们要得! 我们的策略是:

  1. 获得函数名和所有参数的尺寸
  2. 建立一个包含正确个数和尺寸的DLL源代码
  3. 建立一个描述ASM源代码中相应函数的模块定义文件(.DEF)
  4. 将源代码按DLL汇编

你将获得一个功能完全的MASM导入库,上面的步骤应做更多的说明

获得函数名和所有参数尺寸


这是我们处理过程中最困难的部分了。如果你仅仅只有DLL,你将经历无意义的冒险。下面是我所能想出的方法,不过没有一个能100%工作。

使用交互式反编译工具(Interactive Disassembler (IDA))反编译DLL,通过这个奇妙的工具,你可以获得函数参数的大概尺寸,但这些信息是不完全的,IDA是一个功能强大的工具,不过有时必须靠我们自己判断什么是什么。你将不得不仔细分析反编译后的结果。

观察堆栈指针在调用函数之前和之后的值。方法如下:

  1. 通过GetProcAddress获得函数的地址。
  2. 调用想要测试的每一个函数,但请注意,调用这些函数时,不要给他们传递任何的参数。调用前请注意ESP的值。
  3. 当函数返回后,比较调用函数前、后ESP的值。基本原理是:stdcall参数调用协定规定,函数自己负责恢复堆栈,现在知道为什么我们要不传递任何参数了吧,我们没传递参数,而函数却自作聪明“恢复”了ESP指针,所以ESP的变化值就是我们要得参数尺寸了。

不过,上面的方法并不是万无一失的,下面的这些情况将会导致失败:

  • 如果DLL中的函数使用了不同于stdcall的别的参数传递协定。
  • 如果函数在恢复堆栈时失败,我们将无法得到ESP的正确值。
  • 如果这个函数的作用是去做一些危险的事情,比如硬盘格式化,那我们即使得到了ESP,恐怕代价大了点

研究现有的使用DLL的程序,你可以通过调试/反编译这些程序去获得函数参数的个数和尺寸。不论如何,只要有函数在DLL中,而又没有任何程序调用过它,你可以用上面的两个方法。

建立我们自己的DLL


在你获得了函数的名字和参数尺寸后,你可以建立一个DLL框架并在框架中添加和其他DLL、文件中的相同名称的函数。举个例子,如果DLL只含有一个函数:GetSomeLine.它有16BYTES的参数。在ASM文件中,你可以这样写:

.386
.model flat,stdcall
.code
GetSomeLine proc param1:DWORD, param2:DWORD, param3:DWORD, param4:DWORD
GetSomeline endp
end

你可能要问,“这是什么?”。一个没有处理部分的程序?请记住:一个导入库并没有记录一个函数是如何实现的,它只是记录函数名和参数尺寸而已,它的任务就是提供函数的名称和尺寸。所以我们不需要添加函数的处理部分。当我们建立DLL时,MASM会帮我们完成它的导入库的建立。 MASM在建立导入库时并不关心每个具体参数的尺寸,它总是象下面这样:

 

.386
.model flat,stdcall
.code
GetSomeLine proc param1:BYTE, param2:BYTE, param3:BYTE, param4:BYTE
GetSomeline endp
end

然后MASM将在导入库中建立_GetSomeLine@16(它会把每一个参数看作DWORD),而并不管它的参数是4个BYTE还是DWORD或是其他什么

建立匹配的模块定义文件(.DEF)


这是一个简单的工作,你需要这个文件来指导MASM去建立正确的DLL和与之匹配的导入库。一个模块定义文件模板如下:

LIBRARY  <The name of the DLL>
EXPORTS
<The names of the functions>

你仅仅需要填入DLL的名字,然后在EXPORTS下添入函数的名字。每个函数名一行。保存文件,你将获得一个模块定义文件。

汇编DLL源代码


最后一步也是最简单的一步,仅仅需要ML.EXE和LINK.EXE

ml /c /coff /Cp blah.asm
link /DLL /NOENTRY /def:blah.def /subsystem:windows blah.obj

好了,查看一下你的项目目录,你会发现你想要的导入库和DLL。

转自http://blog.csdn.net/taowen2002/article/details/15837

怎样建立你自己的MASM导入库的更多相关文章

  1. 动态链接库dll,导入库lib,静态链接库lib

    目前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Libary,以下简称“导入库” ...

  2. 静态链接库(lib)、动态链接库(dll)与动态链接库的导入库(lib)

    静态链接库与动态链接库相对应.动态链接库的导入库不同于以上两种库. 1.静态链接库(lib)     程序编译一般需经编辑.编译.连接.加载和运行几个步骤.在我们的应用中,有一些公共代码是需要反复使用 ...

  3. 静态库&动态库&导入库

    我遇到的问题 先贴一个StackOverflow上的问题 上面的问题让我知道了更多动态库的知识. 我需要使用一个声音库(irrKlang)为2d游戏提供声音,我使用的编译器是mingw-w64,但是i ...

  4. 动态链接库dll,静态链接库lib, 导入库lib

    转载地址:http://www.cnblogs.com/chio/archive/2008/08/05/1261296.html 目前以lib后缀的库有两种,一种为静态链接库(Static Libar ...

  5. 目前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Libary,以下简称“导入库”)。静态库是一个或者多个obj文件的打包

    前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Libary,以下简称“导入库”) ...

  6. dll的导入库(lib)输出路径

    创建动态链接库项目A, 它会生成:dll, lib, exp 等,其中 lib & exp 生成的路径设置在:[Linker]->[All Options]->[Import Li ...

  7. 环信 之 iOS 客户端集成一:导入库

    1. 导入 我采用cocoapod的方式,在project同级目录下创建Podfile,Podfile内容如下: platform :ios, '7.0' pod 'EaseMobSDKFull', ...

  8. OfficeOpenXml:World、Excel导出导入库

    基础库:EPPlus 根据模版:OfficeOpenXml.Entends

  9. oracle 导库建立测试库

    由于客户要定制的关系,需要对产品的数据进行相关的修改,所以需要复制原来的库出来,然后在此基础上再进行修改.步骤如下: 在PL/SQL下操作: /*分为四步 *//*第1步:创建临时表空间  */cre ...

随机推荐

  1. windows下golang环境搭建

    (1)golang安装配置. 下载地址:https://www.golangtc.com/download 解压后直接配置系统环境变量path,加上go.exe所在文件的路径即可. 配置系统环境变量G ...

  2. git时光机操作

    A状态:代码版本A B状态:代码版本B(比A状态时增加了图片.代码) 这时,git add. git commit -m"" .push之前,意识到忘了让git忽略图片的添加,就: ...

  3. 【2017-03-21】HTML表单及标记

    一.表单 表单在网页中主要负责数据采集功能 表单格式 <form action="服务器路径" method=get(用的比较少)/post(最常用)></for ...

  4. MVC 中的Model对象

    最近实在是太忙,客户丢了一个框架,没有任何说明文档,更没有所谓的技术支持,一直忙于学习,最后好歹还有点头绪,话不多说,MVC的学习是不能拉下的,就当前小白的我,认为MVC中的M并不是想象中的那样简单, ...

  5. MySql 应用语句

    [1]MySQL基础语句 -- 查询mysql版本号 SELECT VERSION(); -- 创建数据库 DROP DATABASE IF EXISTS study; -- 如果存在先删除 CREA ...

  6. 从windows本地IDE启动远程Linux文件进行调试

    1)  因为WingIDE调用putty和plink进行ssh连接,需要先设置putty. 点击下载putty,并解压,把解压路径附到操作系统PATH环境变量中,之后重新启动WingIDE,让它重新读 ...

  7. 什么是Unicode

    写这篇博客的原因, 从做软件开始,什么ASCII码, Unicode,UTF-8,UTF-16,UTF-32......这些鬼东西总是经常碰到,只知道这些鬼是编码格式,其他的就啥都不清楚了,既然总是遇 ...

  8. 【前端安全】JavaScript防流量劫持

    劫持产生的原因和方式 在网页开发的访问过程中,http是我们主要的访问协议.我们知道http是一种无状态的连接.即没有验证通讯双方的身份,也没有验证信息的完整性,所以很容易受到篡改.运营商就是利用了这 ...

  9. mysql命令(三)

    创建一个名字为Student库: create database Student; 用以下地命令来查看创建的数据库是否成功: show databases; 进入数据库: use Student; 用 ...

  10. APIClound 弹出层 Frame

    JS api.openFrame({ name: 'showPic', url: './showPic.html', rect: { // x: api.pageParam.marginBottom, ...