一般在VC中,只要包含了Windows.h就可以使用其中的API函数了,那么这些函数的地址是怎么得到的?预先就有的还是,我们的程序中动态得到的。如果是预先固定的那么请问,windows那么多版本,它怎么保证每一个版本的DLL中每一个函数的地址都是一样的呢?
如果不是那么请看我反汇编的一个简单的C代码
win2k+VC6
#include "stdafx.h"
#include "Windows.h"int main(int argc, char* argv[])
{
MessageBox(NULL,"Somebody Help!",NULL,MB_OK);
printf("Hello World!\n");
return 0;
}7: int main(int argc, char* argv[])
8: {
00401010 push ebp
00401011 mov ebp,esp
00401013 sub esp,40h
00401016 push ebx
00401017 push esi
00401018 push edi
00401019 lea edi,[ebp-40h]
0040101C mov ecx,10h
00401021 mov eax,0CCCCCCCCh
00401026 rep stos dword ptr [edi]
9: MessageBox(NULL,"Somebody Help!",NULL,MB_OK);
00401028 mov esi,esp
0040102A push 0
0040102C push 0
0040102E push offset string "Somebody Help!" (0042002c)
00401033 push 0
00401035 call dword ptr [__imp__MessageBoxA@16 (0042528c)]
0040103B cmp esi,esp
0040103D call __chkesp (00401100)
10: printf("Hello World!\n");
00401042 push offset string "Hello World!\n" (0042001c)
00401047 call printf (00401080)
0040104C add esp,4
11: return 0;
/***********************************************************************/
winxp+vc7
--- f:\vc70\test_del\test_del\main.cpp -----------------------------------------
#include "stdio.h"
#include "windows.h"
int main()
{
00411A40 push ebp
00411A41 mov ebp,esp
00411A43 sub esp,0C0h
00411A49 push ebx
00411A4A push esi
00411A4B push edi
00411A4C lea edi,[ebp-0C0h]
00411A52 mov ecx,30h
00411A57 mov eax,0CCCCCCCCh
00411A5C rep stos dword ptr [edi]
MessageBox(NULL,"123",NULL,MB_OK);
00411A5E mov esi,esp
00411A60 push 0
00411A62 push 0
00411A64 push offset string "123" (424024h)
00411A69 push 0
00411A6B call dword ptr [__imp__MessageBoxA@16 (42A314h)]
00411A71 cmp esi,esp
00411A73 call @ILT+935(__RTC_CheckEsp) (4113ACh)
printf("OKKKKK");
00411A78 push offset string "OKKKKK" (42401Ch)
00411A7D call @ILT+1170(_printf) (411497h)
00411A82 add esp,4
return 0;
00411A85 xor eax,eax
}
/***********************************************************************/
XP+VC6--- G:\test_del\test_del.cpp ---------------------------------------------------------------------------------------------
1: // test_del.cpp : Defines the entry point for the console application.
2: //
3:
4: #include "stdafx.h"
5: #include "windows.h"
6: int main(int argc, char* argv[])
7: {
00401010 push ebp
00401011 mov ebp,esp
00401013 sub esp,40h
00401016 push ebx
00401017 push esi
00401018 push edi
00401019 lea edi,[ebp-40h]
0040101C mov ecx,10h
00401021 mov eax,0CCCCCCCCh
00401026 rep stos dword ptr [edi]
8: MessageBox(NULL,"123",NULL,MB_OK);
00401028 mov esi,esp
0040102A push 0
0040102C push 0
0040102E push offset string "123" (0042002c)
00401033 push 0
00401035 call dword ptr [__imp__MessageBoxA@16 (0042528c)]
0040103B cmp esi,esp
0040103D call __chkesp (00401100)
9: printf("Hello World!\n");
00401042 push offset string "Hello World!\n" (0042001c)
00401047 call printf (00401080)
0040104C add esp,4
10: return 0;
0040104F xor eax,eax
11: }
00401051 pop edi
00401052 pop esi
00401053 pop ebx
00401054 add esp,40h
00401057 cmp ebp,esp
00401059 call __chkesp (00401100)
0040105E mov esp,ebp
00401060 pop ebp
00401061 ret很奇怪吧,
vc7和vc6中MessageBox的地址是不一样的!!!!晕死了
如果不是那么请看我反汇编的一个简单的C代码
win2k+VC6
#include "stdafx.h"
#include "Windows.h"int main(int argc, char* argv[])
{
MessageBox(NULL,"Somebody Help!",NULL,MB_OK);
printf("Hello World!\n");
return 0;
}7: int main(int argc, char* argv[])
8: {
00401010 push ebp
00401011 mov ebp,esp
00401013 sub esp,40h
00401016 push ebx
00401017 push esi
00401018 push edi
00401019 lea edi,[ebp-40h]
0040101C mov ecx,10h
00401021 mov eax,0CCCCCCCCh
00401026 rep stos dword ptr [edi]
9: MessageBox(NULL,"Somebody Help!",NULL,MB_OK);
00401028 mov esi,esp
0040102A push 0
0040102C push 0
0040102E push offset string "Somebody Help!" (0042002c)
00401033 push 0
00401035 call dword ptr [__imp__MessageBoxA@16 (0042528c)]
0040103B cmp esi,esp
0040103D call __chkesp (00401100)
10: printf("Hello World!\n");
00401042 push offset string "Hello World!\n" (0042001c)
00401047 call printf (00401080)
0040104C add esp,4
11: return 0;
/***********************************************************************/
winxp+vc7
--- f:\vc70\test_del\test_del\main.cpp -----------------------------------------
#include "stdio.h"
#include "windows.h"
int main()
{
00411A40 push ebp
00411A41 mov ebp,esp
00411A43 sub esp,0C0h
00411A49 push ebx
00411A4A push esi
00411A4B push edi
00411A4C lea edi,[ebp-0C0h]
00411A52 mov ecx,30h
00411A57 mov eax,0CCCCCCCCh
00411A5C rep stos dword ptr [edi]
MessageBox(NULL,"123",NULL,MB_OK);
00411A5E mov esi,esp
00411A60 push 0
00411A62 push 0
00411A64 push offset string "123" (424024h)
00411A69 push 0
00411A6B call dword ptr [__imp__MessageBoxA@16 (42A314h)]
00411A71 cmp esi,esp
00411A73 call @ILT+935(__RTC_CheckEsp) (4113ACh)
printf("OKKKKK");
00411A78 push offset string "OKKKKK" (42401Ch)
00411A7D call @ILT+1170(_printf) (411497h)
00411A82 add esp,4
return 0;
00411A85 xor eax,eax
}
/***********************************************************************/
XP+VC6--- G:\test_del\test_del.cpp ---------------------------------------------------------------------------------------------
1: // test_del.cpp : Defines the entry point for the console application.
2: //
3:
4: #include "stdafx.h"
5: #include "windows.h"
6: int main(int argc, char* argv[])
7: {
00401010 push ebp
00401011 mov ebp,esp
00401013 sub esp,40h
00401016 push ebx
00401017 push esi
00401018 push edi
00401019 lea edi,[ebp-40h]
0040101C mov ecx,10h
00401021 mov eax,0CCCCCCCCh
00401026 rep stos dword ptr [edi]
8: MessageBox(NULL,"123",NULL,MB_OK);
00401028 mov esi,esp
0040102A push 0
0040102C push 0
0040102E push offset string "123" (0042002c)
00401033 push 0
00401035 call dword ptr [__imp__MessageBoxA@16 (0042528c)]
0040103B cmp esi,esp
0040103D call __chkesp (00401100)
9: printf("Hello World!\n");
00401042 push offset string "Hello World!\n" (0042001c)
00401047 call printf (00401080)
0040104C add esp,4
10: return 0;
0040104F xor eax,eax
11: }
00401051 pop edi
00401052 pop esi
00401053 pop ebx
00401054 add esp,40h
00401057 cmp ebp,esp
00401059 call __chkesp (00401100)
0040105E mov esp,ebp
00401060 pop ebp
00401061 ret很奇怪吧,
vc7和vc6中MessageBox的地址是不一样的!!!!晕死了
中不是有一堆的例如:kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib
入口的信息就在这些 .lib 的文件中
你看看菜单中的:project--->settings--->link标签中的 “object/library module”
中不是有一堆的例如:kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib
入口的信息就在这些 .lib 的文件中
问题就出在这里,那些*.lib文件中它怎么知道某个API的入口地址的呢?莫非从Win95到windows2003这些API的位置就一直没有变动过,不会吧
载入一个API所在的dll以后,使用GetProcAddress获得入口地址的,
然后保存在IAT(Import Address Table)表里,你可以自由用OllyDbg或者SoftIce跟踪一下
还有call dword ptr [__imp__MessageBoxA@16 (0042528c)]你如果看0042528c的内容就是一句 jmp 77xxxxxxx!转向真正的Messagebox的地址.
在这个表里记载了引用了哪个dll的哪个函数(或使用名字,或使用序号)
我上面已经修正了我的说法,这个Import Address Table里的入口地址
是根据这些函数名字取得入口地址的,所有在不同的系统不用担心入口地址是多少例如:
call dword ptr[0042528c] // call MessageBoxA[0042528c]处的内容才是真正跳转到API的地方,为什么要这么call了以后再跳,我想就是为了适应不同的dll版本。至于如何获得的入口地址,正如由 fbmsf(FBM) 说的是由 PE Loader 来做的(之前我说的是不对的,我更正了)