获取DLL的基地址

(1)首先通过段选择器FS在内存中找到当前的线程环境块TEB。
(2)线程环境块中找到进程环境块PEB的指针。
(3)进程环境块中找到指向PEB_LDR_DATA结构体的指针,其中存放着已经被进程装载的动态链接库的信息。
(4)PEB_LDR_DATA结构体中找到指向模块信息LIST_ENTRY链表的头指针。
(5)遍历_LIST_ENTRY链表,找到想要获取DLL的基地址。

1.TEB

    内存中FS:0是当前的线程环境块TEB的基地址。用WinDbg验证了一下:
在这里插入图片描述
    通过WinDbg查看TEB数据结构:
在这里插入图片描述
    TEB偏移0x30处存放的是进程环境块PEB的指针。

2.PEB

    通过WinDbg查看PEB数据结构:
在这里插入图片描述
    PEB偏移0x0c处存放的是PEB_LDR_DATA结构体的指针。

3.PEB_LDR_DATA

    通过WinDbg查看PEB_LDR_DATA数据结构:
在这里插入图片描述

    发现有三个模块链表,按变量名字来看应该是按初始化顺序的模块链表、按装载顺序的模块链表和按在内存中顺序的模块链表。
    _LIST_ENTRY结构如下,是一个双向链表:
在这里插入图片描述
    链表实际指向的内容是LDR_DATA_TABLE_ENTRY结构体:
在这里插入图片描述
    LDR_DATA_TABLE_ENTRY偏移0x18就是DLL基地址。同时还看到FullDllName和BaseDllName可以帮助我们区分是哪个DLL。

代码遍历模块链表

    模块链表是一个双向循环链表,以下以遍历InLoadOrderModuleList举例:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

typedef struct _LIST_ENTRY
{
	_LIST_ENTRY* Flink;
	_LIST_ENTRY* Blink;
}_LIST_ENTRY;

typedef struct _UNICODE_STRING
{
	unsigned short Length;
	unsigned short MaximumLength;
	wchar_t* Buffer;
};

int main()
{
	int* pPEB = NULL;

	__asm
	{
		push eax
		mov eax,fs:[0x30]
		mov pPEB,eax
		pop eax
	}

	int* pIDR = (int*)(*(pPEB + 0x03)); //0x03 * 4 = 0x0c

	_LIST_ENTRY* pInLoadOrderModuleList = (_LIST_ENTRY*)(pIDR + 0x03); //0x03 * 4 = 0x0c

	_LIST_ENTRY* pHead, *p;
	p = pHead = pInLoadOrderModuleList->Flink;

	int count = 0;
	do
	{
		printf("%d: ", count++);
		_UNICODE_STRING* pBaseName = (_UNICODE_STRING*)(((int)p) + 0x2c);
		if (pBaseName->Buffer)
			wprintf(L"%s ", pBaseName->Buffer);
		printf("0x%x\n", *((int*)(((int)p) + 0x18)));
		//
		p = p->Flink;
	} while (p != pHead);

	return 0;
}

代码的输出如下:
0: ASM.exe 0x1230000
1: ntdll.dll 0x77c10000
2: KERNEL32.DLL 0x749a0000
3: KERNELBASE.dll 0x746d0000
4: VCRUNTIME140D.dll 0x5f580000
5: ucrtbased.dll 0xf840000
6: 0x0

对照VS里的 调试-窗口-模块 里的内容,读取正确:
在这里插入图片描述

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 在LabVIEW中,可以使用DLL调用节点来获取DLL中的字符串数组。 首先,需要使用函数原型定义工具将DLL的函数原型导入到LabVIEW中。在函数原型定义工具中,选择创建从DLL导入函数原型。然后,选择DLL文件并指定函数名称和返回值类型。 接下来,使用DLL调用节点来调用DLL中的函数。在调用节点的函数原型中选择之前导入的函数原型。如果函数需要输入参数,则在节点上设置相应的输入参数。 对于字符串数组的返回值,可以创建一个与DLL函数返回类型匹配的LabVIEW数组。使用数组指针传递数据,将其传递到DLL调用节点上。然后,使用LabVIEW的字符串函数来解析数组中的每个字符串。 最后,在LabVIEW中创建一个循环来处理数组中的每个字符串。可以使用For循环或While循环来遍历数组。在循环内部,使用字符串函数来处理每个字符串。 使用上述步骤,就可以在LabVIEW中获取DLL中的字符串数组。需要确保DLL中的函数原型和LabVIEW的函数原型一致,并正确处理返回的字符串数组。 ### 回答2: 在LabVIEW中,要获取DLL中的字符串数组,可以按照以下步骤进行操作。 首先,使用LabVIEW中的Call Library Function Node (CLFN)来调用DLL文件。通过双击CLFN,打开Function Prototype面板。 在Function Prototype面板中,我们需要添加DLL函数的名称和参数。对于返回字符串数组的DLL函数,我们需要添加一个input参数来指定字符串数组的长度,和一个output参数来接收返回的字符串数组。 然后,点击Add Library和选择DLL文件。接着,点击Add Function将DLL函数添加到Function Name窗口中。 在Function Prototype面板中,我们需要设置输入输出参数的数据类型。对于输入参数,我们可以选择输入数据的类型,如整数、字符串等。对于输出参数,我们可以选择输出数据的类型为指针。 接下来,使用LabVIEW中的Array functions来处理返回的字符串数组。使用Array functions中的Create Array和Array To String函数,将返回的字符串数组转换为LabVIEW中的字符串。 最后,在LabVIEW的Block Diagram中,将CLFN和Array functions进行连接,使其按照顺序执行。通过运行程序,我们可以获取并处理从DLL函数返回的字符串数组。 这样,我们就可以使用LabVIEW来获取DLL中的字符串数组了。 ### 回答3: 在LabVIEW中获取DLL字符串数组需要遵循以下步骤: 1. 首先,确保你已经拥有了需要使用的DLL文件,并且你已经将它加载到了LabVIEW环境中。可以通过工具菜单中的"加载外部代码库"选项来加载DLL文件。 2. 创建一个新的VI,并将其命名为"获取DLL字符串数组"。 3. 在VI中,使用"函数面板"上的"调用库函数"节点来调用DLL函数。双击该节点以打开"配置调用库函数"对话框。 4. 在"配置调用库函数"对话框中,选择要调用的DLL文件,并在"库函数"列表中选择相应的函数。通常DLL函数将返回一个字符串数组的指针。 5. 设置输入和输出参数。如果DLL函数需要输入参数,则可以通过"配置调用库函数"对话框中的"输入参数"选项卡添加相应的参数。对于输出参数,你可以创建相应的LabVIEW变量来存储它们的值。 6. 连接节点。使用"调用库函数"节点连接其他节点,以便在调用DLL函数之前或之后执行其他操作。 7. 运行VI,以便调用DLL函数并获取字符串数组。你可以将输出参数显示在"前面板"中,以便查看结果。 需要注意的是,获取DLL字符串数组的具体方法可能会因为DLL文件的不同而有所差异,上述步骤仅为一般示例。你需要参考相应的DLL文件的文档或者相关的LabVIEW教程来获取更具体的信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值