动态获取API地址

cncpp 

动态获取API地址是病毒界和密界中常用的程序设计技术
Author: 属于中国破解组织 - xIkUg[BCG][DFCG][OCN][DCM][CZG]
Date: 2004-07-28
Email: [email protected]
xIkUg's程序园: http://www.xp-program.com
XP-极限编程: http://bbs.xp-program.com


一点理论,Win32系统通过CreateProcess创建进程并运行一个程序。。。
在进入程序时跟一般的应用程序调用Call类似,会在堆栈中压入一个返回地址。。。这时压入的是kernel32.dll中一某一个返回地址,我们可以得到这个地址,然后找到kernel32.dll在内存中的基地址,然后找到Export Table,找到我们
需要GetModuleHandleA/LoadLibrary/GetProcAddress这几个Api函数的地址,就可以得到想要的Api地址,并在程序中使用了,这需要你对PE文件格式非常清楚

因为没有导入Api函数,在我们的程序中没有导入表,因此在OD中要调试这个程序就不能再用Api下断了,但是也有其他办法

下面我们来看看如何做,程序中已经添加了注释

001  .386
002  
003  .model flat, stdcall
004  
005  include d:/masm32/include/windows.inc
006  
007  
008  .code
009  
010  GetApiAddress PROC k32Base: DWORD, ApiName: DWORD
011      LOCAL    NumberOfNames: DWORD
012      
013      push    ebx
014      push    ecx
015      push    edx
016      push    ebp
017      push    esi
018      push    edi
019      
020      mov        edi, k32Base
021      mov        eax, edi
022      add        eax, [eax + 3Ch]                ;Kernel32.dll 的 PeHeader
023      
024      assume    eax: ptr IMAGE_NT_HEADERS
025      mov        ebx, edi
026      add        ebx, [eax].OptionalHeader.DataDirectory.VirtualAddress    ;IMAGE_EXPORT_DIRECTORY引出表入口
027      assume    eax: nothing
028  
029      mov        eax, ApiName
030      
031      mov        ecx, ebx
032      mov        ebx, [ecx + 1Ch]                ;AddressOfFunctions的地址
033      
034      mov        edx, ecx
035      mov        edx, [edx + 18h]                ;NumberOfNames地址
036      mov        NumberOfNames, edx
037      mov        edx, ApiName
038              
039      mov        ebp, ecx            ;IMAGE_EXPORT_DIRECTORY引出表入口
040      mov        ebp, [ebp + 20h]                ;AddressOfNames 地址
041      
042      mov        esi, ecx
043      mov        esi, [esi + 24h]                ;AddressOfNameOrdinals
044      
045  
046      push    ebx
047      push    ecx
048      push    esi
049      xor        ebx, ebx
050      xor        ecx, ecx
051      xor        eax, eax
052      add        ebp, edi
053      
054  getApiGetModuleHandleA:
055      mov        esi, edi
056      add        esi, [ebp + ecx * 4]
057  
058  cmpAPI:
059      mov        al, [edx + ebx]
060      cmp        al, [esi + ebx]
061      jne        getNext
062      inc        ebx
063      mov        al, 0
064      cmp        al, [esi + ebx]
065      jne        cmpAPI
066      je        getOK
067  getNext:
068      xor        ebx, ebx
069      inc        ecx
070      cmp        ecx, NumberOfNames
071      jne        getApiGetModuleHandleA
072         
073  getOK:
074      pop        esi
075      
076      add        esi, edi
077      ;ecx 为AddressOfNameOrdinals的index   
078      xor        eax, eax
079      mov        ax, word ptr [esi + ecx * 4]
080      
081      pop        ebx
082      pop        ebx
083      add        ebx, edi
084      mov        esi, [ebx + ecx * 4]
085      add        esi, edi                        ;esi为GetModuleHandleA的API地址
086      push    esi
087      pop        eax
088  
089      pop        edi
090      pop        esi
091      pop        ebp
092      pop        edx   
093      pop        ecx   
094      pop        ebx
095         
096      ret
097  
098  GetApiAddress endp
099  
100  start:
101      ;搜索kernel32.dll的基地址
102      mov        eax, [esp]
103      and        eax, 0ffff0000h
104      
105      xor        edx, edx
106      
107  getK32Base:
108      dec     eax                             ;逐字节比较验证
109      mov     dx,word  ptr [eax+IMAGE_DOS_HEADER.e_lfanew]   ;就是ecx+3ch
110      test    dx,0f000h                       ;Dos Header+stub不可能太大,超过4096byte
111      jnz     getK32Base                      ;加速检验
112      cmp     eax,dword ptr [eax+edx+IMAGE_NT_HEADERS.OptionalHeader.ImageBase]
113      jnz     getK32Base                      ;看Image_Base值是否等于ecx即模块起始值,
114      mov        edi, eax
115      
116      mov        eax, offset sGetModuleHandleA
117      push    eax
118      push    edi
119      call    GetApiAddress
120      mov        esi, eax                        ;esi为GetModuleHandleA的API地址
121      
122      
123      mov        eax, offset sLoadLibraryA
124      push    eax
125      push    edi
126      call    GetApiAddress                    ;ebp为LoadLibraryA的API地址
127      mov        ebp, eax
128      
129      mov        eax, offset sGetProcAddress
130      push    eax
131      push    edi
132      call    GetApiAddress
133      mov        edi, eax                        ;edi为GetProcAddress的API地址
134      
135      mov        eax, offset sUser32
136      push    eax
137      call    ebp
138      
139      mov        ebx, offset sApiMessageBoxA
140      push    ebx
141      push    eax
142      call    edi
143      
144      mov        esi, eax                        ;eax为MessageBoxA
145      
146         
147      push    0
148      mov        eax, offset sTitle
149      push    eax
150      mov        eax, offset sCaption
151      push    eax
152      push    0
153      call    esi
154      
155      ret        
156  
157      sGetModuleHandleA        db        'GetModuleHandleA', 0
158      sGetProcAddress            db        'GetProcAddress', 0
159      sLoadLibraryA            db        'LoadLibraryA',0
160      sFreeLibrary            db        'FreeLibrary',0
161      sUser32                    db        'user32',0
162      
163      sApiMessageBoxA            db        'MessageBoxA',0
164      
165      sCaption                db        'Hello xIkUg!',0
166      sTitle                    db        'test',0
167      
168  end start
169  

源代码可到我的论坛下载:http://bbs.xp-program.com

你可能感兴趣的:(动态获取API地址)