今天注释的是CITMaker类,其中应该有不少的错误,请大家附加自己的思考吧
这个类的主要作用是根据下面的字符串计算所需的导入表大小以及构建导入表
PEMaker6下载地址:http://www.mydatabus.com/public/panzhibin/pemaker6.zipstatic const char *sz_IT_EXE_strings[]=
{
"Kernel32.dll" ,
"LoadLibraryA" ,
"GetProcAddress" ,
0,
0,
};
const char *sz_IT_OCX_strings[]=
{
"Kernel32.dll" ,
"LoadLibraryA" ,
"GetProcAddress" ,
"GetModuleHandleA" ,
0,
"User32.dll" ,
"GetKeyboardType" ,
"WindowFromPoint" ,
0,
"AdvApi32.dll" ,
"RegQueryValueExA" ,
"RegSetValueExA" ,
"StartServiceA" ,
0,
"Oleaut32.dll" ,
"SysFreeString" ,
"CreateErrorInfo" ,
"SafeArrayPtrOfIndex" ,
0,
"Gdi32.dll" ,
"UnrealizeObject" ,
0,
"Ole32.dll" ,
"CreateStreamOnHGlobal" ,
"IsEqualGUID" ,
0,
"ComCtl32.dll" ,
"ImageList_SetIconSize" ,
0,
0,
};//---------------------------------------------------------------- using namespace std ;//---------------------------------------------------------------- typedef struct
{
CHAR szFunction[32];
}t_IMAGE_THUNK, *pt_IMAGE_THUNK;//---------------------------------------------------------------- typedef struct
{
CHAR szLibrary[32];
//链表
list <t_IMAGE_THUNK> ThunksList;
//链表指针
list <t_IMAGE_THUNK>::iterator ThunkIter;
CHAR szFunction[32];
}t_IMAGE_IMPORT_TABLE, *pt_IMAGE_IMPORT_TABLE;//---------------------------------------------------------------- static list <t_IMAGE_IMPORT_TABLE> ImportTable;static list <t_IMAGE_IMPORT_TABLE>::iterator ImportIter;//================================================================
CITMaker::CITMaker(int iType)
{
//初始化
Initialization(iType);
//计算出所需的导入表大小
dwSize=Get_IT_Size();
//申请空间
pMem=new CHAR [dwSize];
}
CITMaker::~CITMaker()
{
ImportTable.clear();
delete [] pMem;
}//---------------------------------------------------------------- // This function makes the dll name strings, saves them to the linked list void CITMaker::Initialization(int iType)
{
int i;
PCHAR *sz_IT_strings;
t_IMAGE_IMPORT_TABLE imageimport;
t_IMAGE_THUNK imagethunk;
switch (iType)
{
case IMPORT_TABLE_EXE:
sz_IT_strings=(PCHAR *)sz_IT_EXE_strings;
break ;
case IMPORT_TABLE_OCX:
sz_IT_strings=(PCHAR *)sz_IT_OCX_strings;
break ;
}
//静态全局变量--------------------------------------------
ImportTable.clear();
i=0;
do
{
//复制库名
strcpy(imageimport.szLibrary,sz_IT_strings[i]);
//清空imageimport--Thunk列表
imageimport.ThunksList.clear();
do
{
i++;
//取API函数名
if (sz_IT_strings[i]!=0)
{
//向imagethunk---复制函数名
strcpy(imagethunk.szFunction,sz_IT_strings[i]);
//放入链表
imageimport.ThunksList.push_back(imagethunk);
}
}while (sz_IT_strings[i]!=0); //循环取得函数名
ImportTable.push_back(imageimport); //入ImportTable链表
i++;
}
while (sz_IT_strings[i]!=0);
//其实EXE文件只有一个表被建立--------------------------------------------
}//---------------------------------------------------------------- // This function calculated zise of Import Table. //计算导入表大小 //引入表实际上是一个 IMAGE_IMPORT_DESCRIPTOR 结构数组。 //每个结构包含PE文件引入函数的一个相关DLL的信息 //比如,如果该PE文件从10个不同的DLL中引入函数,那么这个数组就有10个成员。 //该数组以一个全0的成员结尾。 //这里引入另一篇文章的自建导入表的结构,借鉴一下更直观,不一定准确: /*align 4
v_ImportA dd Ker_API-v_ImportA ;IMAGE_THUNK_DATA 数组指针
v_TimeDateA dd 0 ;文件建立时间
v_ForChainA dd 0 ;0
v_DllNameA dd KerName-v_ImportA ;DLL名称
v_FThunkA dd vGetprocAddress-v_ImportA ;IMAGE_THUNK_DATA 数组指针
v_ImportB dd Use_API-v_ImportA ;IMAGE_THUNK_DATA 数组指针
v_TimeDateB dd 0 ;文件建立时间
v_ForChainB dd 0 ;0
v_DllNameB dd UserName-v_ImportA ;DLL名称
v_FThunkB dd vMessageBoxA-v_ImportA ;IMAGE_THUNK_DATA 数组指针
dd 20 dup (0) ;引入表结束符
KerName db 'KERNEL32.DLL',0
Ker_API dd KAPI_A-v_ImportA
dd KAPI_B-v_ImportA
dd KAPI_C-v_ImportA
dd KAPI_D-v_ImportA
dd KAPI_E-v_ImportA
dd KAPI_F-v_ImportA
dd KAPI_G-v_ImportA
dd KAPI_H-v_ImportA
dd KAPI_I-v_ImportA
dd KAPI_J-v_ImportA
dd KAPI_K-v_ImportA
dd KAPI_L-v_ImportA
dd KAPI_M-v_ImportA
dd KAPI_N-v_ImportA
dd KAPI_O-v_ImportA
dd KAPI_P-v_ImportA
dd KAPI_Q-v_ImportA
dd 0 UserName db 'USER32.DLL',0
Use_API dd UAPI_A-v_ImportA
dd 0
vGetprocAddress dd 0
vGetModuleHandleA dd 0
vLoadLibraryA dd 0
vExitprocess dd 0
vCreateFileA dd 0
vCreateFileMappingA dd 0
vGetTempPathA dd 0
vGetTempFileNameA dd 0
vlstrlen dd 0
vMapViewOfFile dd 0
vWriteFile dd 0
vUnmapViewOfFile dd 0
vCloseHandle dd 0
vCopyFileA dd 0
vGetModuleFileNameA dd 0
vDeleteFileA dd 0
vWinExec dd 0
vMessageBoxA dd 0
dd 0
KAPI_A db 0,0,'GetprocAddress',0
KAPI_B db 0,0,'GetModuleHandleA',0
KAPI_C db 0,0,'LoadLibraryA',0
KAPI_D db 0,0,'Exitprocess',0
KAPI_E db 0,0,'CreateFileA',0
KAPI_F db 0,0,'CreateFileMappingA',0
KAPI_G db 0,0,'GetTempPathA',0
KAPI_H db 0,0,'GetTempFileNameA',0
KAPI_I db 0,0,'lstrlen',0
KAPI_J db 0,0,'MapViewOfFile',0
KAPI_K db 0,0,'WriteFile',0
KAPI_L db 0,0,'UnmapViewOfFile',0
KAPI_M db 0,0,'CloseHandle',0
KAPI_N db 0,0,'CopyFileA',0
KAPI_O db 0,0,'GetModuleFileNameA',0
KAPI_P db 0,0,'DeleteFileA',0
KAPI_Q db 0,0,'WinExec',0
UAPI_A db 0,0,'MessageBoxA',0 ; 根据引入表的格式,自建的引入表。
;------------------------------------(上面的)--
align 4
*/
DWORD CITMaker::Get_IT_Size()
{
DWORD dwDLLNum=0;
DWORD dwFunNum=0;
DWORD dwszDLLSize=0;
DWORD dwszFuncSize=0;
DWORD dwImportSize=0;
t_IMAGE_IMPORT_TABLE imageimport;
t_IMAGE_THUNK imagethunk;
//ImportIter是全局变量
for (ImportIter=ImportTable.begin();ImportIter!=ImportTable.end();ImportIter++)
{
imageimport=*ImportIter;
//注意库名长度计算,+1就是结尾的0
dwszDLLSize=dwszDLLSize+strlen(imageimport.szLibrary)+1;
//遍历THUnk链表
for (imageimport.ThunkIter=imageimport.ThunksList.begin();
imageimport.ThunkIter!=imageimport.ThunksList.end();
imageimport.ThunkIter++)
{
imagethunk=*imageimport.ThunkIter;
//注意长度计算,括号中为原始THUNK的结构
//格式:0,0,函数名字符串,0
dwszFuncSize=dwszFuncSize+(2+strlen(imagethunk.szFunction)+1);
//函数计数
dwFunNum++;
}
//以0结尾
dwFunNum++;
//库计数
dwDLLNum++;
}
//以空IMAGE_IMPORT_DESCRIPTOR结构结尾
dwDLLNum++;
//每个DLL需要一个导入表(20字节)+(API函数数量)*(DWORD)+(所有DLL字符串长度)+(所有函数名字符串长度)
//这个地方我计算的不是很明白,应该有两个RVA数组,一个是函数名RVA数组,一个是函数地址RVA数组
//有知道的朋友请指出一下。
dwImportSize=dwDLLNum*20+dwFunNum*4+dwszDLLSize+dwszFuncSize;
return (dwImportSize);
}//---------------------------------------------------------------- //---------------------------------------------------------------- // This function build the dll name strings, saves the ImageImportDescriptors to the loader data. //建立导入表 void CITMaker::Build(DWORD dwRVA)
{
//是个RVA
DWORD pITBaseRVA=dwRVA;
DWORD temp;
DWORD dwDLLNum, dwDLLName, dwDLLFirst, dwszDLLSize;
DWORD dwIIDNum, dwFunNum, dwFunFirst, dwszFuncSize;
DWORD dwFirstThunk, dwImportSize;
//局部变量
t_IMAGE_IMPORT_TABLE imageimport;
t_IMAGE_THUNK imagethunk;
//真正导入表结构
IMAGE_IMPORT_DESCRIPTOR import_descriptor;// -> IID
//初始化--------------------------------------------
import_descriptor.OriginalFirstThunk=0;
import_descriptor.TimeDateStamp=0;
import_descriptor.ForwarderChain=0;
import_descriptor.Name=0;
import_descriptor.FirstThunk=0;
dwDLLNum=dwDLLName=dwDLLFirst=dwszDLLSize=0;
dwIIDNum=dwFunNum=dwFunFirst=dwszFuncSize=0;
dwFirstThunk=dwImportSize=0;
//遍历总链表--------------------------------------------
for (ImportIter=ImportTable.begin();ImportIter!=ImportTable.end();ImportIter++)
{
imageimport=*ImportIter;
dwszDLLSize=dwszDLLSize+strlen(imageimport.szLibrary)+1;
for (imageimport.ThunkIter=imageimport.ThunksList.begin();
imageimport.ThunkIter!=imageimport.ThunksList.end();
imageimport.ThunkIter++)
{
imagethunk=*imageimport.ThunkIter;
dwszFuncSize=dwszFuncSize+2+strlen(imagethunk.szFunction)+1;
dwFunNum++;
}
dwFunNum++;
dwDLLNum++;
}
dwDLLNum++;
//重复得出大小,跟上面一样,为什么不调用函数计算呢,晕
dwImportSize=dwDLLNum*20+dwFunNum*4+dwszDLLSize+dwszFuncSize;
//pMem已经初始化:在构造函数中,大小为所有引入表大小--------------------------------------------
FillMemory(pMem,dwImportSize,0x00);
//一些偏移量
dwFirstThunk=dwDLLNum*20;
dwDLLFirst=dwDLLNum*20+dwFunNum*4;
dwFunFirst=dwDLLNum*20+dwFunNum*4+dwszDLLSize;
//pITBaseRVA
//--------------------------------------------
for (ImportIter=ImportTable.begin();ImportIter!=ImportTable.end();ImportIter++)
{
imageimport=*ImportIter;
//pITBaseRVA为传递的参数
//Name:含有指向DLL名字的RVA
//越过之前的所有IMAGE_IMPORT_DESCRIPTOR结构+所有API地址数组而到达指向DLL名字的RVA
import_descriptor.Name=pITBaseRVA+dwDLLFirst;
//越过之前的所有IMAGE_IMPORT_DESCRIPTOR结构得到FirstThunk的RVA
import_descriptor.FirstThunk=pITBaseRVA+dwFirstThunk;
//复制一系列IMAGE_IMPORT_DESCRIPTOR
memcpy(pMem+dwIIDNum*sizeof (IMAGE_IMPORT_DESCRIPTOR),
&import_descriptor,
sizeof (IMAGE_IMPORT_DESCRIPTOR));
//复制动态库名称,注意位置dwDLLFirst=dwDLLNum*20+dwFunNum*4!
memcpy(pMem+dwDLLFirst,
imageimport.szLibrary,
strlen(imageimport.szLibrary)+1);
//--------------------------------------------
for (imageimport.ThunkIter=imageimport.ThunksList.begin();
imageimport.ThunkIter!=imageimport.ThunksList.end();
imageimport.ThunkIter++)
{
//函数名称链
imagethunk=*imageimport.ThunkIter;
//计算函数名称字符串RVA
temp=pITBaseRVA+dwFunFirst;
//复制的是一个RVA,包含函数名数组RVA的RVA数组
//dwFirstThunk=dwDLLNum*20
memcpy(pMem+dwFirstThunk,
&temp,
4);
//THUNK指向的RVA数组所指向的函数名数组
//dwFunFirst=dwDLLNum*20+dwFunNum*4+dwszDLLSize
memcpy(pMem+dwFunFirst+2,
imagethunk.szFunction,
strlen(imagethunk.szFunction)+1);
//指向下一个位置
dwFunFirst=dwFunFirst+2+strlen(imagethunk.szFunction)+1;
dwFirstThunk=dwFirstThunk+4;
}
//--------------------------------------------
temp=0;
//以零结尾
memcpy(pMem+dwFirstThunk,
&temp,
4);
//指向下一个位置
dwFirstThunk=dwFirstThunk+4;
dwDLLFirst=dwDLLFirst+strlen(imageimport.szLibrary)+1;
//表的数量加一
dwIIDNum++;
}
//莫非是最后一个表,以空表结束--------------------------------------------
import_descriptor.Name=0;
import_descriptor.FirstThunk=0;
//--------------------------------------------
memcpy(pMem+dwIIDNum*sizeof (IMAGE_IMPORT_DESCRIPTOR),
&import_descriptor,
sizeof (IMAGE_IMPORT_DESCRIPTOR));
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课