病毒分析技巧之API地址获取

点击蓝字

病毒分析技巧之API地址获取

关注我们

病毒分析技巧之API地址获取

0x00目的

病毒分析技巧之API地址获取

通过该实验, 使学生掌握使用PEB结构确定kernel32.dll基地址的方法与原理,通过对PE导出表结构分析来理解获取API函数地址的方法,最终通过编码完成一个没有导入表的测试程序。

病毒分析技巧之API地址获取

0x01知识

病毒分析技巧之API地址获取

windbg命令:

此处我们列出文章中要用到的命令,更多详细的介绍,请参照官网

http://www.windbg.org/、

!teb:显示线程环境信息

dt nRet :看变量nRet的类型与值

dd memory_address :看memroy_address处的内存分布,以一个DWORD为一组。

du memory_address :查看使用unicode编码的字符串,该字符串的地址为memory_address.

masm的安装环境,可从

http://www.masm32.com/

官网下载

Masm是汇编文件的编译器,默认安装之后需要配置环境变量。

在环境变量中添加以下几项:(以默认安装为例,以下路径随安装路径变化)

Include =c:\masm32\include

Lib =c:\masm32\lib

Path = c:\masm32\bin

新手请掌握PE导出表结构

http://bbs.pediy.com/showthread.php?t=122632

病毒分析技巧之API地址获取

0x02步骤

病毒分析技巧之API地址获取

PE病毒和普通PE一样需要调用API,但是PE病毒只有一个代码段,不存在普通PE程序中的导入表结构。所以如果想要调用API函数,必须先找出这些API在DLL中的地址。为了获得API函数地址,首先必须获得kernel32的基地址,获取之后,就可以在此模块中搜索出GetProcAddress和LoadLibrary的地址。一旦有了这两个函数的地址,就可以直接道道任何需要的API地址。为了更好的理解上述核心原理,本实验的步骤如下:

通过使用PEB来获得kernel32.dll的基地址

从获得的DLL中通过导出表检索到需要的函数地址。

综合整理,构造一个没有导出表的PE程序。

1、步骤描述: 通过使用PEB来获得kernel32.dll的基地址

病毒分析技巧之API地址获取

上图表示了整个获得基地址的工作原理。在NT内核系统中,fs寄存器始终指向TEB结构,TEB+0x30处指向PEB结构,PEB+0xC处指向PEB_LDR_DATA结构,PEB_LDR_DATA+0x1c处存放了结构体LIST_ENTRY InnitalzationOrderLinks,该结构体指向LDR_DATA_TABLE_ENTRY结构,此结构中按顺序记录了进程初始化时加载的模块,LIST_ENTRY是个双向链表,因此可以通过链表找到所有加载模块的基本信息。

一个程序初始化加载时,会先加载ntdll.dll,紧接着加载kernel32.dll。通过查找链表第二项,便可找到kernel32.dll的基地址。

为了更好的理解此项,使用windbg来看一下。首先,选择符号文件路径。

病毒分析技巧之API地址获取

病毒分析技巧之API地址获取

在这里我们需要输入的是存放符号文件的文件夹。符号文件可以从微软服务器上连接获取所需,也可以从本地已下载的符号文件夹中获取。由于实验室提供的是断网学习,我们已经准备好了本地文件夹,添加成图中所示路径即可。

病毒分析技巧之API地址获取

由于调试原理相同,因此我们可以直接调试windbg,选择kernel Debug。

病毒分析技巧之API地址获取

在弹出的对话框中选择local选项卡,点击确定即可。

进入调试环境之后,我们首先来获取下TEB信息。输入!teb

病毒分析技巧之API地址获取

可以看到,TEB的地址为7ffde000,注意到PEB的地址为7ffda000.

为了解析一下teb的数据结构,我们使用命令dt nt!_teb ,并带入teb的地址,所以命令应该是 dt nt!_teb 7ffde000.

病毒分析技巧之API地址获取

可以看到,PEB在TEB地址偏移0x30处,也就是说我们可以通过TEB找到PEB。

同样的,来解析一下PEB结构,输入 dt nt!_peb 7ffda000

病毒分析技巧之API地址获取

可以看到 LDR在PEB地址偏移的0xc处。我们来解析一下ldr结构,输入dt _peb_ldr_data 191e90.

病毒分析技巧之API地址获取

可以看到,在0xc,0x14,0x1c处都存在一个_list_entry结构体,输入dt _list_entry 191f28后看到,改地址存放的依然是两个_list_entry结构体。事实上,在peb_ldr_data中出现的三个list是三张双向链表,你可以理解为这些List_entry是链表的表头。三张链表分别按照载入顺序,内存顺序和初始化顺序记录了所有的模块信息。一般采用第三个链表来检索kernel32.dll。这些链表的每个节点其实都是ldr_data_table_entry结构。关于这个结构,微软官方并没有公布,我们来看一下这个结构真实的情况。

输入

dt _ldr_data_table_entry 191f28.

病毒分析技巧之API地址获取

可以看到在偏移为0x18处存放的就是dll的基地址,在偏移0x24处存放的是dll的全路径,0x2c处存放的是dll的名字。

输入

dt _ldr_data_table_entry 191f28 –r1.

(r1表示深度解析,1表示解析1层)

病毒分析技巧之API地址获取

可以看到在0x28处存放了dll的全称。我们来测试一下。输入dd 191f28.

病毒分析技巧之API地址获取

可以看到通过初始化链表头(第三张链表)Flink地址191f28,找到了第一张

_ldr_data_table_entry table_entry,

这里存放的是ntdll.dll的信息。在0x0偏移处,存放的是下一个节点的地址,0x8处存放的是该Dll的基地址,0x18处存放dll的全路径,0x20处存放dll名。

我们来验证一下。输入 du 7c99d028和du 7c942158.

病毒分析技巧之API地址获取

接下来再看下一个节点,输入刚刚看到的地址 dd 191fd0.

病毒分析技巧之API地址获取

输入du 191f98 后,会看到这个dll正是kernel32.dll,在0x8处的偏移正好是kernel32.dll的地址7c80000.使用Process explorer检验一下。在左侧的进程树中随便找一个程序,在下方的dll中找到kernel32.dll。双击后选择image选项卡。

病毒分析技巧之API地址获取

2、步骤描述:从dll中获得函数地址

病毒分析技巧之API地址获取

从导出表的结构图中可以看出,如果想要按照函数名检索,需要从AddressOfNames去检索,确定函数名的索引号之后(偏移除4),以这个索引号在AddressOfNamesOrdinals中找到函数的地址索引(索引号*2获取),以此地址索引在AddressOfFunctions中找到函数的入口地址(地址索引号*4),加上DLL的基地址,得到的就是函数的地址了。

具体而言,常见的步骤如下:

定位到PE头

从PE文件头中找到数据目录表,表项的第一个双字值是导出表的起始RVA。

从导出表中获取NumberOfNames字段的值,确定检索次数。

从AddressOfNames字段指向的函数名称数组的第一项开始,与指定的函数名字进行匹配;如果找到,则记录从AddressOfNames开始的索引号。

通过索引号再去检索AddressOfNameOrdinals数组,从同样索引的位置找到函数的地址索引。

通过查询AddressOfFunction指定函数地址索引位置的值,找到相对虚拟地址。

将相对虚拟地址加上该动态链接库在被导入到地址空间的基地址,此地址为函数的真实入口地址。

结合代码来分析。

病毒分析技巧之API地址获取

该函数有两个参数,_hModule代表dll的基地址,_lpApi表示要在该dll中查找的函数名。

首先通过每个字节和0x0比较,计算出函数名长度,以@dwlen返回。

Mov esi,_hModule 和add esi,[esi+3ch]找到了pe的头文件地址。指向的是Image_nt_headers结构。

通过查找其扩展PE头中的数据目录的虚拟地址(RVA),最后再加上dll的基地址,就可以找到导出表的VA。

病毒分析技巧之API地址获取

用edx记录查找次数,当超过NumberOfNames时表示查找失败。通过比对函数字符串,如果成功则跳转到@@上。此时,ebx保存索取到的函数名VA,得到偏移之后,shr ebx,1将ebx值除2,ebx就是在AddressOfOrdinals中的地址偏移量(AddressOfOridnals为WORD大小)。检索出函数地址偏移索引之后存放到eax中,将eax*4(shl eax,2)获得地址偏移量,即函数名在函数地址数组中的地址偏移,在AddressOfFunctions中得到的地址依然是个RVA,需要加载模块的基地址,得到函数真实的VA。

3、步骤描述结合PEB找到kernel32.dll基地址,通过实验2得到LoadLibrary和GetProcAddress地址。 最终完成无导入表的弹窗测试程序。

首先要明确为什么需要这两个函数,这两个函数的地址找到之后,就可以任意调用其他dll文件中的函数API而不依赖于宿主文件导入表,非常方便。而这两个函数存在于kernel32.dll中,需要得到kernel32的基地址。

最终完成的汇编文件名叫noimport.asm。请打开查看。

病毒分析技巧之API地址获取

首先声明了自定义函数和函数指针。我们需要自己找到这两个函数的地址。通过

_getProcessAddress,_loadLibrary,_messageBox

记录函数对应的地址。

病毒分析技巧之API地址获取

_getKernel32Base是从实验1中的原理封装出来的,如果有问题,请回实验1中查看。初学者可能刚开始对mov eax,[eax+8]中的8感觉有些疑问,之所以不是0x18,是因为我们使用按初始化顺序链表List_entry得到的地址,是下一个节点中指向初始化顺序链表的List_entry,而不是按载入顺序得到的链表的List_entry,如果还有疑问,请查看实验1中的图。(0x18-0x10=0x8)

病毒分析技巧之API地址获取

上图所示是我们在实验二中封装的函数(代码不完整,具体请查看noimport.asm)

病毒分析技巧之API地址获取

在完成函数封装之后,我们首先通过自己的函数_getKernelBase获得了kernel32.dll的基地址并存放在hKernel32Base中。通过调用自己的函数_GetAPi获得getProcAddress地址和loadLibrary的地址。接下来,就和正常调用没有区别了,通过加载user32.dll,获得messagebox的地址,用_messagebox来存放,并最终实现调用。

病毒分析技巧之API地址获取

在masm编辑器中,菜单栏选择File->Open ,打开noImport.asm,选择Project->Assemble&link,生成同名noimport.exe文件。

病毒分析技巧之API地址获取

程序得以正常运行。接下来在stud_pe中打开此文件,切换到Functions选项卡。

病毒分析技巧之API地址获取

会看到,我们的程序并没有导入表的存在,却能够随意的调用系统API.

病毒分析技巧之API地址获取

0x03 总结

病毒分析技巧之API地址获取

在工作中,获得kernel32.dll的DllBase有多种方法,不局限于本文一种方法,大家可以自己在网上搜索。另外,文章需要对PE结构有一定的了解,才能操作和理解清楚,请读者在实操之前阅读相关的技术资料。分析病毒程序,可能会对本机造成危害,请读者提前了解,如果做出危害网络安全的行为后果自负,与合天智汇及本人无关,特此声明。

看不过瘾?合天2017年度干货精华请点击【精华】2017年度合天网安干货集锦

别忘了投稿哟!!!

合天公众号开启原创投稿啦!!!

大家有好的技术原创文章。

欢迎投稿至邮箱:[email protected]

合天会根据文章的时效、新颖、文笔、实用等多方面评判给予100元-500元不等的稿费哟。

有才能的你快来投稿吧!

重金悬赏 | 合天原创投稿等你来!

病毒分析技巧之API地址获取

    合天智汇

网址 : www.heetian.com

电话:4006-123-731

病毒分析技巧之API地址获取

长按图片,据说只有颜值高的人才能识别哦→