动态获取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