通用ShellCode深入剖析(4)

发布时间:2021-06-05

其中的值是函数相对于可执行文件在内存映象中基地址的一个相对偏移值,真正的函数地址等于这个相对偏移值+可执行文件在内存映象中的基地址,我们可以Call这个计算后的真实地址来调用数.AddressOfNames是一个二级字符指针,该数组成员所指就是函数名称字符串相对于可执行文件在内存映象中的基地址的一个偏移值,同样可以通过相对偏移值+可执行文件在内存映象中的基地址来引用函数名称字串.Name也是一个字符指针,它也只存储了相对偏移值,如果是kernel32的IMAGE_EXPORT_DIRECTORY那么它指向的字串就为"KERNEL32.dll".

3,本节应用实例

关于PE和引出表我们已经分析了与编写ShellCode密切相关的部分,这一部分的确有点难,但一定要把它搞清楚,只有把它搞懂我们才能进行下一节的学习,在本节的最后附上一个小程序,在内联汇编代码中大量使用了"间接引用",如果你对指针很熟悉基本上它很好理解,在程序里我们实现了Windows APIGetProcAddress的功能,这种技术对于想使用一些未公开的系统函数也是非常之有用的.


GetFunctionByName函数可以从一个PE执行文件中以函数名查找引出表并返回引出函数地址,只需要知道KERNEL32.DLL的基地址值,使用它在本程序中我们不包括头文件也可以使用任何一个Windows API.在我的机器上它是0x77e60000程序如下:

//GetFunctionByName.c
//原型:DWORD GetFunctionByName(DWORD ImageBase,const char*FuncName,int flen);
//参数:
// ImageBase: 可执行文件的内存映象基址
// FuncName: 函数名称指针
// flen: 函数名称长度
//返回值:
// 函数成功时返回有效的函数地址,失败时返回0.
//最终在写ShellCode时,应该给该函数加上__inline声明,因为它要与ShellCode融为一体.

//注意,在本例中我们没有包括任何一个.h文件

unsigned int GetFunctionByName(unsigned int ImageBase,const char*FuncName,int flen)
{
unsigned int FunNameArray,PE,Count=0,*IED;

__asm
{
mov eax,ImageBase
add eax,0x3c//指向PE头部偏移值e_lfanew
mov eax,[eax]//取得e_lfanew值
add eax,ImageBase//指向PE header
cmp [eax],0x00004550
jne NotFound//如果ImageBase句柄有错
mov PE,eax
mov eax,[eax+0x78]
add eax,ImageBase
mov [IED],eax//指向IMAGE_EXPORT_DIRECTORY
//mov eax,[eax+0x0c]
//add eax,ImageBase//指向引出模块名,如果在查找KERNEL32.DLL的引出函数那么它将指向"KERNEL32.dll"
//mov eax,[IED]
mov eax,[eax+0x20]
add eax,ImageBase
mov FunNameArray,eax//保存函数名称指针数组的指针值
mov ecx,[IED]
mov ecx,[ecx+0x14]//根据引出函数个数NumberOfFunctions设置最大查找
次数
FindLoop:
push ecx//使用一个小技巧,使用程序循环更简单
mov eax,[eax]
add eax,ImageBase
mov esi,FuncName
mov edi,eax
mov ecx,flen//逐个字符比较,如果相同则为找到函数,注意这

精彩图片

热门精选

大家正在看