病毒基础系列_第1页
病毒基础系列_第2页
病毒基础系列_第3页
病毒基础系列_第4页
病毒基础系列_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、病毒基础系列 -API 函数地址的获取关键字API, 病毒, 函数,地址、八前言 :病毒没有什么可怕的 , 也并不象想像中的复杂 , 玩汇编的人如果没有看过病毒?简直是白活一遭 . 病毒就象是双刃剑 , 恶意使用就会带来恶果 , 我本人对于此类行为深恶痛绝 ! 我们 研究不是为了破坏而是为了知己知彼 , 另外病毒中确实也有很多高超的技巧值得我们学习 , 这才是我们的目的所在 , 我绝没有教唆人犯罪的意图而且就我的水平来讲也远达不到 .在研究病毒之前有几项基础知识要了解 :1) ring0的获取 , 可参见我翻译的一篇 ring0 的文章 , 另外这些资料 internet 上也很多 .2) S

2、eh 的知识 , 可参见我写的 <<seh in asm 研究 >>3) PE结构的知识 ZouDan大侠的论文,lczeLion 的PE教学和载 LUEVELSMEYE的 PE文件格式,最为重要!4) 文件读写的基本知识 , 主要是 Create. 等文件读写知识 , 如果你还不了解 , 最好先 学学win32ASM的基础知识.5) PolyEngine.MetaMorphism等基本概念6) anti-debug的一些概念7) 有关MBR,FAT等知识,对了解一些老 Virus有用.下面我有的一些 tips, 可能会对理解病毒有所帮助 . 另外这些技术在加壳类软件

3、中也很常见 .Tip1: API 函数地址的获取这是一个老题目了 , 如果我们不用任何引入库 , 能否在程序中调用 api 函数 ?当然可以 !方法 有很多 , 你可能早就知道了 , 如果你已经了解了 , 就此打住 , 这是为还不了解这一技术而写 . 另 外这也是病毒必用的技巧之一 , 如果你对病毒技术感兴趣 , 接着看下去 .这里假设你了解 PE的基本结构,如果还不懂,找点资料来看看,到处都是呦.在几乎每个病毒的开头都用下面的语句deltacalldelta:popsubmovebpebp,offset delta dword ptr ebp+offset appBase,ebp让我们考虑一

4、下程序的执行情况 , 如果下面的代码由编译器自动编译连接 , 那么程序执行的 基址一般是 400000h, 如果是在 Nt 下执行 , 那么基址可能不同 , 比如从 100000h 开始 , 不用担), 也是 delta 在程序执行时的心, 操作系统的 Loader 会自动为你重定位 . 但是这里停下来让我们看一下 , 如果你想要把这 段代码 附加到其他程序的后面 并想让其正确执行的话 , 就不是那么简单了 , 因为你的代码可 能要从555588h处开始执行,而在没有得到宿主程序许可 的情况下期望操作系统自动为你修 正偏移错误是不可能的 , 既然有非常的目的 , 就得费点力气 , 自己搞定重定

5、位 . 而上面的代码 就是首先得到eip指针(保存CPU要执行的下一个指令的地址. 这就是你上面看到的 . 如果 面的例子演示了这一点 , 并没有全部重定位 ,实际偏移 (用 pop ebp , 把它存入 ebp 中), 然后减掉代码头到 delta 的偏移从而得到你的代 码的真正基址 , 后面对于偏移的操作都应以这个真正的偏移为准 不明白 , 就仔细想一下 ,nothing difficult! 因为这只是技术演示 .现在回到本文的正式内容 , 要想获得 api 的地址 , 得首先获得诸如 kernel32.dll,user32.dll 的基址 , 然后再找到真正的函数地址 . 如何获得基址

6、和函数地址呢呢?有几种方法1)搜寻宿主的引入表获得 GetModuleHandleA 函数和 GetProcAddress 的地址 , 然后 通过他返回系统 dll 的基址 .因为很多程序都要使用这两个函数 ,因此在某些情况下是可行 的 , 如果宿主没有使用 GetProcAddress, 那你就不得不搜寻 Export 表了 .2)直接获得 kernel32.dll 的基址 , 然后再搜寻 Export 表获得 GetProcAddress 和 LoadLibraryA 的地址 , 然后我们就能得到任何想调用的函数地址 .3)硬编码调用函数,比如在9X下GetModuleHandleA的地址

7、一般是 BFF7*第一种和第三种方法存在兼容性的问题 , 假如宿主没有调用 GetModuleHandleA, 那么你就不 能获得基址,别的就更别想了 硬编码问题更大,操作系统不同则不能运行了 ,比如9X下可 能在有些计算机上正常 , 但肯定不能在 Nt/2K 下运行 .第二种方法兼容性比较好 , 因此作以介绍 .一点背景 :在 PE Loader 装入我们的程序启动后 堆栈顶的地址 是程序的返回地址 , 肯定在 Kernel 中(当然是在没有动堆栈的情况下) !因此我们可以得到这个地址 , 然后向低地址缩减验证一直到找到模块的起始地址 , 验证条件为PE头不能大于4096bytes ,PE

8、header的lmageBase(文件的优先装载地址)值应 该和当前指针 相等(不是我们的程序 ,而是那个 kernel32.dll), 嘿嘿,简单吧,而且兼容性还 不错.要获得 Api 的地址首先要获得 GetModuleHandle,LoadLibraryA,GetProcAddress 的地址,这是通过搜索 Export 表来实现的 ,具体原理就是 PE Export 表的结构 ,如果了解了 PE结构就很简单了 .下面我加了点注释,没有优化代码,是为了便于理解.好, 这一部分结束了 !这是一个例子 , 没有用任何预引入函数 , 加了一条 invoke lnitCommonControls

9、 是为了在 2K 下也能正常运行 , 否则不能在 2K 下不加载 !程序得到MessageBoxA的地址然后显示一个消息框,目的在于演示,重要部分加了注释,很好 明白 .注意连接时加入 /section:.text,RWE 选项。 .586; case sensitive.model flat, stdcall option casemap :none include c:hdhd.h include c:hdmac.hGetApiAproto:DWORD,:DWORDJ J.CODEappBasedd ?k32Basedd ?lpApiAddrslabelnearddoffset sGetM

10、oduleHandleddoffset sGetProcAddressddoffset sExitProcessddoffset sLoadLibrarydd0sGetModuleHandledb "GetModuleHandleA",0sGetProcAddressdb "GetProcAddress",0sExitProcessdb "ExitProcess",0sLoadLibrarydb "LoadLibraryA",0sMessageBoxAdb "MessageBoxA",0aGet

11、ModuleHandledd 0aGetProcAddressdd 0aExitProcessdd 0aLoadLibrarydd 0aMessageBoxAdd 0u32db "User32.dll",0k32db "Kernel32.dll",0sztitdb "By Hume,2002",0szMsg0db "Hey,Hope U enjoy it!",0Start:invokeInitCommonControlscalldeltadelta:popebp; 得到 delta 地subebp,offset d

12、elta址可能不是默认的所以需要重定位dword ptr ebp+offset appBase,ebp; 因为在其他程序中基mov; 呵呵仔细想想movecx,espxor; 返回地址edx,edxgetK32Base:dececx; 逐字节比较验mov ecx+3ch test 不可能太大 , 超过 jnzdx,word ptr ecx+IMAGE_DOS_HEADER.e_lfanew ; 就 是dx,0f000h 4096byte getK32Base cmp ecx+edx+IMAGE_NT_HEADERS.OptionalHeader.ImageBase jnz getK32Base

13、 ecx 即模块起始值 ,ebp+offset k32Base,ecx;Dos Header+stub; 加速检验 ecx,dwordptr; 看 Image_Base 值是否等于kernel32mov的 Base 值; 如果是, 就认为找到lop_get:End_Get:User32.dlllealealodsdedi,ebp+offset aGetModuleHandle esi,ebp+offset lpApiAddrscmp jz push pushcallGetApiAeax,0End_Geteaxdword ptr ebp+offset k32Base; 获 取 API 地stos

14、d jmppush calllop_getoffset u32dword ptr ebp+offset aLoadLibrary; 在程序空间加载leaEDX,EBP+OFFSET sMessageBoxAedxeaxeax,dword ptr ebp+aGetProcAddresspush push mov获得MessageBoxA 的地址calleax调用GetProcAddresspush40h+1000hepushoffset sztitpushoffsetszMsg0内容push0calleax一个消息框产生了 .嘿嘿八、八、J有理由为此高兴吧, 因为我们没有预先引入:J这些函数pu

15、sh0callebp+aExitProcessK32_api_retrieveproc;用 GetProcAddress;styl;title; 消息Base:DWORD ,sApi:DWORDpush xor Next_Api:movedxeax,eax; 保存 edx; 此时 esi=sApi;edi=AddressOfNamesxordec Match_Api_name:esi,sApi edx,edx edxmov inccmp jz inc push movbl,byte esi bl,0founditedxptr esiaddcmp pop jzeax eax,edi+eax*4

16、eax,Base bl,byte eaxptr eax+edxMatch_Api_name;AddressOfNames 的指针 , 递增;注意是RVA,定要加Base值; 逐字符比较; 继续搜寻inceax; 不匹配 , 下一个 apiloopNext_Apijmpno_exist; 若全部搜完 , 即未存在foundit:popedx;edx=AddressOfNameOrdinalsshleax,1;*2 得 到AddressOfNameOrdinals 的指针movzxeax,wordptr edx+eax ;eax返回指向 AddressOfFunctions 的指针retno_ex

17、ist:popedxxoreax,eaxretK32_api_retrieveendpJGetApiAprocBase:DWORD,sApi:DWORDlocalADDRofFun:DWORDpushadmovedi,Baseaddedi,IMAGE_DOS_HEADER.e_lfanewmovedi,edi; 现在 edi=offPE_HEADERaddedi,Base;得到IMAGE_NT_HEADERS偏移movebx,edimovedi,edi+IMAGE_NT_HEADERS.OptionalHeader.DataDirectory.VirtualAddressaddedi,Base;得到edi=IMAGE_EXPORT_DIRECTORY口moveax,edi+1ch;AddressOfFunctions的地址addeax,BasemovADDRofFun,eax;ecx=NumberOfNamesmovecx,e

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论