本文的目的就是想探究dll文件中的变量是如何导出。借此了解ntoskrnl.exe
的导出到底是怎么实现的。
在前面的《SSDT HOOK》代码段中有这么一句话:
extern "C" PSERVICE_DESCRIPTOR_TALBE KeServiceDescriptorTable;
当时是说:这个符号是从ntoskrnl.exe
中导出的。从当时测试的时候改变符号名发现执行错误就可以看出来,这个符号绝对是从ntoskrnl.exe
文件中查找出来的。今天使用Depend walker
查看了一下,有这样的结果。
按键F10(c/c++ 符号形式)
转换,发现都是同一个函数名,因此可以判定这个符号是用C导出的。
这是因为如果使用的是c++符号形式导出,那么由于多态性的原因,其导出格式会发生改变。
为此我又做了一次测试。新建dll文件生成cpp
格式。源码如下:
FINAL.H
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the FINAL_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// FINAL_API functions as being imported from a DLL, wheras this DLL sees symbols
// defined with this macro as being exported.
#ifdef FINAL_EXPORTS
#define FINAL_API __declspec(dllexport)
#else
#define FINAL_API __declspec(dllimport)
#endif
// This class is exported from the FINAL.dll
class FINAL_API CFINAL {
public:
CFINAL(void);
// TODO: add your methods here.
};
extern FINAL_API int nFINAL;
extern FINAL_API int nTemp ; //add here,others are default input.
FINAL_API int fnFINAL(void);
--------------
// FINAL.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#include "FINAL.h"
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
// This is an example of an exported variable
FINAL_API int nFINAL=0;
FINAL_API int nTemp = 0x10; //add here.
// This is an example of an exported function.
FINAL_API int fnFINAL(void)
{
return 42;
}
// This is the constructor of a class that has been exported.
// see FINAL.h for the class definition
CFINAL::CFINAL()
{
return;
}
程序很简单,
这时候打开depends
查看一下导出情况。
下图是c++默认的导出符号表(最左侧的C++ 表示是通过C++方式导出)
F10切换后,去掉装饰,不知道这个算不算变为C的方式呢?后期注意这个问题。
虽然用depends
可以切换,但是我更想知道编译器做了什么,用PEView
可以查看(导出表name段在.rdata段)。
由于PEView
不能复制结果出来,在这里我用十六进制查看器(Winhex)查看了一下,结果如下。
Offset 0 1 2 3 4 5 6 7 8