滴水逆向-静态链接库与动态链接库

发布时间:2022-07-05 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了滴水逆向-静态链接库与动态链接库脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

滴水逆向-静态链接库与动态链接库

滴水逆向-静态链接库与动态链接库

滴水逆向-静态链接库与动态链接库

滴水逆向-静态链接库与动态链接库

相关测试代码

代码复用的实现:

1.静态链接库


一,创建静态链接库:

(1)在VC6中创建项目:Win32 static Library
(2)在项目中创建两个文件:cntftools.h 和 cntftools.cpp; 这里创建两个文件就是上面操作完成之后,直接新建一个class即可生成这两文件;

cntftools.h文件:

#if !defined(AFX_test_H__DB32E837_3E66_4BE7_B873_C079BC621AF0__INCLUDED_)
#define AFX_TEST_H__DB32E837_3E66_4BE7_B873_C079BC621AF0__INCLUDED_

#if _MSC_VER > 1000
#PRagma once
#endif // _MSC_VER > 1000

int Plus(int x, int y);
int Sub(int x, int y);
int Mul(int x, int y);
int Div(int x, int y);

#endif

cntftools.cpp文件:

int Plus(int x, int y)
{
	return x+y;
}
int Sub(int x, int y)
{
	return x-y;
}
int Mul(int x, int y)
{
	return x*y;
}
int Div(int x, int y)
{
	return x/y;
}

3.编译  --- 点击编译即可,不需要执行,调试等其他操作;



二,使用静态链接库:

方式一:
(1)将上面编译完成之后,生成的cntftools.h 和 cntflibs.lib复制到要使用的项目中,这里放的位置是生成项目的文件夹,不是debug
文件夹里面;

(2)在需要使用的文件中包含:#include "cntftools.h"

(3)在需要使用的文件中包含:#pragma comment(lib, "cntflibs.lib")


(4)下面是重新生成的一个项目文件,然后放入上面的头文件和lib文件,编译成功可正常执行,下面是对应的代码

// sjlx.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdlib.h>
#include "cntftools.h"


#pragma comment(lib,"cntflibs.lib")

int main()
{
    int x = Plus(2,3);
    printf("%drn",x);
	System("pause");
	return 0;
}

方式二:

(1)将上面编译完成之后,生成的cntftools.h 和 cntflibs.lib复制到要使用的项目中,这里放的位置是生成项目的文件夹,不是debug
文件夹里面;

(2)在需要使用的文件中包含:#include "cntftools.h";

(3)在项目名称中右键-->设置-Link-->找到Object/library Module 在最后面空格一下,添加cntflibs.lib;下面是最终的结果;
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccP32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib、
 advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib  cntflibs.lib


(4)再次编译执行,可成功运行;


三,静态链接库的缺点:

(1)使用静态链接生成的可执行文件体积较大,造成浪费;
(2)我们常用的printf、memcpy、strcpy等就来自这种静态库	;
(3)最重要原因就是因为生成的函数对应代码是在变成成功之后的exe里面,所以如果要更改lib的话,很麻烦,需要;
需要再次重新编译生成exe文件;验证这一点,可以通过执行此函数的过程中查看反汇编代码;发现生成的反汇编代码;
其对应的内存地址是带入了ImageBase:0x00400000;


2.动态链接库

一,创建DLL

(1)在VC6中创建项目:Win32 Dynamic-Link Library ,名称写dtljkcntf
(2)再在项目中创建两个文件:mydll.h 和 mydll.cpp; 这里创建两个文件就是,直接新建一个class即可生成这两文件

1.文件中

int __stdcall Plus(int x,int y)
{
	return x+y;
}
int __stdcall Sub(int x,int y)
{
	return x-y;
}
int __stdcall Mul(int x,int y)
{
	return x*y;
}
int __stdcall Div(int x,int y)
{
	return x/y;
}

2.头文件中

extern "C" _declsPEc(dllexport) __stdcall int Plus (int x,int y);
extern "C" _declspec(dllexport) __stdcall int Sub (int x,int y);
extern "C" _declspec(dllexport) __stdcall int Mul (int x,int y);
extern "C" _declspec(dllexport) __stdcall int Div (int x,int y);

说明:

1.extern 表示这是个全局函数,可以供各个其他的函数调用;

2."C" 按照c语言的方式进行编译、链接

__declspec(dllexport)告诉编译器此函数为导出函数;


二,使用DLL

方式一:隐式连接

步骤1:将 *.dll  *.lib 放到工程目录下面

步骤2:将 #pragma comment(lib,"DLL名.lib") 添加到调用文件中

步骤3:加入函数的声明 --这里就是加在项目对应的主程序代码里面,我这里测试就在main函数入口的代码上面;

extern "C" __declspec(dllimport) __stdcall int Plus (int x,int y);
extern "C" __declspec(dllimport) __stdcall int Sub (int x,int y);
extern "C" __declspec(dllimport) __stdcall int Mul (int x,int y);
extern "C" __declspec(dllimport) __stdcall int Div (int x,int y);

说明:

__declspec(dllimport)告诉编译器此函数为导入函数;

下面是成功执行的主测试代码;

#include "stdafx.h"
#include <stdlib.h>

__declspec(dllimport) int Plus (int x,int y);
__declspec(dllimport) int Sub (int x,int y);
__declspec(dllimport) int Mul (int x,int y);
__declspec(dllimport) int Div (int x,int y);

#pragma comment(lib,"dtljkcntf.lib")

int main()
{
    int x = Plus(2,3);
    printf("%drn",x);
	system("pause");
	return 0;
}

上面需要注意的地方:
因为我测试编译生成dll和lib文件之前写的代码是没有带入extern "C" 和__stdcall这两个关键字;
当然上面是为了测试,实际情况需要带入是最好的;
测试结果是告诉我们,如果不带入上面两个关键字,那么编译生成的函数名称编译器会给我们重新命名;
简单理解操作就会给添加一些奇怪的字符,目的就是为了止函数重名,因为在C++里面有重载的说法;
如果函数重名会导致其他异常情况;
所以总结一下:在生成dll和lib之前我们写的什么关键字代码,那么这里就要写什么;

查看dll文件显示函数信息:
使用工具可以是微软VC6.0 ++ 自带的Dependency进行查看;
也可以用OD查看,点击按钮"E"; 使用OD查看的时候,记得要要把上面生成好的dtljkcntf.dll文件放在;
可执行程序exe的相同目录下测试查看验证;

下面是带入extern "C" 和__stdcall关键字的操作;

#include "stdafx.h"
#include <stdlib.h>

extern "C" __declspec(dllimport) __stdcall int Plus (int x,int y);
extern "C" __declspec(dllimport) __stdcall int Sub (int x,int y);
extern "C" __declspec(dllimport) __stdcall int Mul (int x,int y);
extern "C" __declspec(dllimport) __stdcall int Div (int x,int y);

#pragma comment(lib,"dtljkcntf.lib")

int main()
{
    int x = Plus(998,663);
    printf("%drn",x);
	system("pause");
	return 0;
}


方式二:显示链接

步骤1:	//定义函数指针
		typedef int (__stdcall *lpPlus)(int,int);
		typedef int (__stdcall *lpSub)(int,int);
		typedef int (__stdcall *lpMul)(int,int);
		typedef int (__stdcall *lpDiv)(int,int);

步骤2:  //声明函数指针变量
		lpPlus myPlus;
		lpSub mySub;
		lpMul myMul;
		lpDiv myDiv;

	步骤3:  //	//动态加载dll到内存中
		HINSTANCE   hModule = LoadLibrary("DllDemo.dll");

	步骤4:  //获取函数地址
		myPlus = (lpPlus)GetProCADdress(hModule,   "_Plus@8");
		mySub = (lpSub)GetProcAddress(hModule,   "_Sub@8");
		myMul = (lpMul)GetProcAddress(hModule,   "_Mul@8");
		myDiv = (lpDiv)GetProcAddress(hModule,   "_Div@8");


	步骤5:	//调用函数
		int a = myPlus(10,2);
		int b = mySub(10,2);
		int c = myMul(10,2);
		int d = myDiv(10,2);


上述操作完成之后,对应的可执行代码如下:

#include "stdafx.h"
#include <stdlib.h>
#include <windows.h>
//#include <string.h>

//定义函数指针;
typedef int (__stdcall *lpPlus)(int,int);
typedef int (__stdcall *lpSub)(int,int);
typedef int (__stdcall *lpMul)(int,int);
typedef int (__stdcall *lpDiv)(int,int);

//上面的*lpPlus *lpSub *lpMul *lpDiv都是指针类型;

int main()
{
    //在main函数里面声明函数指针变量;
    lpPlus myPlus;
    lpSub mySub;
    lpMul myMul;
    lpDiv myDiv;

    //动态加载dll到内存中;
    HINSTANCE   hModule = LoadLibrary("dtljkcntf.dll");

    //获取函数地址;
    myPlus = (lpPlus)GetProcAddress(hModule,   "_Plus@8");
    mySub = (lpSub)GetProcAddress(hModule,   "_Sub@8");
    myMul = (lpMul)GetProcAddress(hModule,   "_Mul@8");
    myDiv = (lpDiv)GetProcAddress(hModule,   "_Div@8");

    int x = myPlus(998,3);
    printf("%drn",x);
	system("pause");
	return 0;
}

特别说明:

Handle 是代表系统的内核对象,如文件句柄,线程句柄,进程句柄。

HMODULE 是代表应用程序载入的模块

HINSTANCE 在win32下与HMODULE是相同的东西 Win16 遗留

HWND 是窗口句柄

其实就是一个无符号整型,Windows之所以这样设计有2个目的:

(1)可读性更好
(2)避免在无意中进行运算


3.使用.def导出

(1)*.h文件

int Plus (int x,int y);
int Sub (int x,int y);
int Mul (int x,int y);
int Div (int x,int y);

(2)*.cpp文件

int Plus(int x,int y)
{
	return x+y;
}
int Sub(int x,int y)
{
	return x-y;
}
int Mul(int x,int y)
{
	return x*y;
}
int Div(int x,int y)
{
	return x/y;
}

(3)*.def文件

EXPORTS

Plus   	@12
Sub	    @15 NONamE
Mul    	@13
Div    	@16
(4)使用序号导出的好处:
名字是一段程序就精华的注释,通过名字可以直接猜测到函数的功能

通过使用序号,可以达到隐藏的目的.

动态链接库dll测试效果

滴水逆向-静态链接库与动态链接库

滴水逆向-静态链接库与动态链接库

滴水逆向-静态链接库与动态链接库

将生成的dll和lib文件拷贝到新建的一个项目里面

滴水逆向-静态链接库与动态链接库

使用显示链接的方式调用dll

滴水逆向-静态链接库与动态链接库

滴水逆向-静态链接库与动态链接库

dll内容

滴水逆向-静态链接库与动态链接库

脚本宝典总结

以上是脚本宝典为你收集整理的滴水逆向-静态链接库与动态链接库全部内容,希望文章能够帮你解决滴水逆向-静态链接库与动态链接库所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。