不可能吧。
#include "stdafx.h"
#include <stdio.h>
#include <conio.h>
#include <windows.h>int main(int argc, char* argv[])
{
   HINSTANCE h=LoadLibrary("user32.dll");
   printf("msgbox: %04lx\n\n",(ULONG)GetProcAddress(h,"MessageBoxA"));
   printf("msgbox: %04lx\n\n",(ULONG)GetProcAddress(h,"MessageBoxA"));
   printf("msgbox: %04lx\n\n",(ULONG)GetProcAddress(h,"MessageBoxA"));
   
   getch();
   FreeLibrary(h);
   return 0;
}输出:
msgbox: bff541bamsgbox: bff541bamsgbox: bff541ba环境:Windows 98 4.10.2222,VC 6.0 Professional,Release。

解决方案 »

  1.   

    在我这里,是一模一样的,三次都一样,不知道你怎么搞的void CDllpDlg::OnWork() 
    {
    HINSTANCE h=LoadLibrary("user32.dll");
    CString str;

    str.Format("msgbox: %04lx\r\n",(ULONG)GetProcAddress(h,"MessageBoxA"));
    Output(str);
    str.Format("msgbox: %04lx\r\n",(ULONG)GetProcAddress(h,"MessageBoxA"));
    Output(str);
    str.Format("msgbox: %04lx\r\n",(ULONG)GetProcAddress(h,"MessageBoxA"));
    Output(str);
    }void CDllpDlg::Output(CString &str)
    {
    m_output.SetSel(-1);
    m_output.ReplaceSel((LPCTSTR)str);
    }
      

  2.   

    忘了贴我的输出了msgbox: 77e5d348
    msgbox: 77e5d348
    msgbox: 77e5d348
      

  3.   

    你用的一定是NT吧?98和NT有区别!!!!
      

  4.   

    zhoujiehg
       实在对不起,我搞错了,浪费你的时间和分数了,对不起!!呵呵
      

  5.   

    这样吧,你将HINSTANCE h=LoadLibrary("user32.dll"); 的H 也输出来也看一下,结果告知一下。 
      
      

  6.   

    我重新调整了程序,大家看看:#include "stdafx.h"
    #include <stdio.h>
    #include <conio.h>
    #include <windows.h>int main(int argc, char* argv[])
    {
    HINSTANCE h=LoadLibrary("user32.dll");

    printf("h: %04lx\n\n",(ULONG)h);

    printf("1.msgbox: %04lx\n\n",(ULONG)GetProcAddress(h,"MessageBoxA"));
    printf("1.msgbox: %04lx\n\n",(ULONG)GetProcAddress(h,"MessageBoxA"));
    printf("1.msgbox: %04lx\n\n",(ULONG)GetProcAddress(h,"MessageBoxA")); printf("2.msgbox: %04lx\n\n",*(ULONG *)GetProcAddress(h,"MessageBoxA"));
    printf("2.msgbox: %04lx\n\n",*(ULONG *)GetProcAddress(h,"MessageBoxA"));
    printf("2.msgbox: %04lx\n\n",*(ULONG *)GetProcAddress(h,"MessageBoxA")); getch();
    return 0;
    }输出:h: bff500001.msgbox: 894c04801.msgbox: 894c04901.msgbox: 894c04a02.msgbox: f541ba682.msgbox: f541ba682.msgbox: f541ba68系统:Win98 4.10.2222 VC++6.0
      

  7.   

    to azuo_lee():把你的那个编译成exe,寄给我试试[email protected]
      

  8.   

    我刚刚向matt发了信,希望有回音
    --------------------------------------------------------
    I have written a program like follow:#include "stdafx.h"
    #include <stdio.h>
    #include <conio.h>
    #include <windows.h>int main(int argc, char* argv[])
    {
        HINSTANCE h=LoadLibrary("user32.dll");
        
        printf("h: %04lx\n\n",(ULONG)h);
        
        printf("1.msgbox: %04lx\n\n",(ULONG)GetProcAddress(h,"MessageBoxA"));
        printf("1.msgbox: %04lx\n\n",(ULONG)GetProcAddress(h,"MessageBoxA"));
        printf("1.msgbox: %04lx\n\n",(ULONG)GetProcAddress(h,"MessageBoxA"));    printf("2.msgbox: %04lx\n\n",*(ULONG *)GetProcAddress(h,"MessageBoxA"));
        printf("2.msgbox: %04lx\n\n",*(ULONG *)GetProcAddress(h,"MessageBoxA"));
        printf("2.msgbox: %04lx\n\n",*(ULONG *)GetProcAddress(h,"MessageBoxA"));    getch();
        return 0;
    }output:h: bff500001.msgbox: 894c04801.msgbox: 894c04901.msgbox: 894c04a02.msgbox: f541ba682.msgbox: f541ba682.msgbox: f541ba68my system:win98 4.10.2222 + VC++ 6can you tell me why the GetProcAddress function get different value every time
    and it seems that the address which GetProcAddress point to contains the real pointer to dll function?
      

  9.   

    richen(苦行僧) 我用的是NT大家把自己用的系统注明一下,有可能是系统的问题
      

  10.   

    我用的是2000 Server,显示的值也是不变的。对于98中出现的那个现象,我认为有可能是因为两个系统内存管理上的区别造成的。比如这个地址虽然释放了,但没有立即放入可用内存中,或是别的什么原因。(以上纯属本人瞎吹,没有什么根据)
      

  11.   

    #include <stdafx.h>
    #include <stdio.h>
    #include <conio.h>
    #include <windows.h>int main(int argc, char* argv[])
    {
        HINSTANCE h=LoadLibrary("shell32.dll");
        
        printf("h: %04lx\n\n",(ULONG)h);
        
        printf("1.msgbox: %04lx\n\n",(ULONG)GetProcAddress(h,"ShellAboutA"));
        printf("1.msgbox: %04lx\n\n",(ULONG)GetProcAddress(h,"ShellAboutA"));
        printf("1.msgbox: %04lx\n\n",(ULONG)GetProcAddress(h,"ShellAboutA"));       getch();
        return 0;
    }换成这个,看一下结果
      

  12.   

    将  stdafx.h 头文件去掉
      

  13.   

    to richen:按你在楼上的楼上的方法
    输出:
    h: 7fcb00001.msgbox: 7fce16661.msgbox: 7fce16661.msgbox: 7fce1666why????????按你楼上的方法不通,VC报错f:\myprojects\ll\ll.cpp(32) : fatal error C1010: unexpected end of file while looking for precompiled header directive,并且光标停在程序末尾
      

  14.   


    #include <stdio.h>
    #include <conio.h>
    #include <windows.h>
    int main(int argc, char* argv[])
    {
        HINSTANCE h=LoadLibrary("user32.dll");
        
        printf("h: %04lx\n\n",(ULONG)h);
        
        PIMAGE_DOS_HEADER pDosHdr;
    PIMAGE_NT_HEADERS pNTHeader;
    DWORD ExportRva,FunctionRVA;
    WORD index;
    PIMAGE_EXPORT_DIRECTORY pExportStar;
    PDWORD  PAddressOfNames,PAddressOfFunctions;
        PWORD   PAddressOfNameOrdinals;
    LPBYTE base; pDosHdr = (PIMAGE_DOS_HEADER)h;
    base = (LPBYTE)pDosHdr;
    pNTHeader = (PIMAGE_NT_HEADERS)(base+ (pDosHdr->e_lfanew));
    ExportRva = pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
    pExportStar = (PIMAGE_EXPORT_DIRECTORY)(ExportRva + pNTHeader->OptionalHeader.ImageBase);
    PAddressOfNames=(PDWORD)(pExportStar->AddressOfNames + pNTHeader->OptionalHeader.ImageBase);
    PAddressOfNameOrdinals=(PWORD)(pExportStar->AddressOfNameOrdinals+ pNTHeader->OptionalHeader.ImageBase);
    PAddressOfFunctions=(PDWORD)(pExportStar->AddressOfFunctions+ pNTHeader->OptionalHeader.ImageBase);
    LPCSTR lpName;for(DWORD i=1;i<pExportStar->NumberOfNames;i++)
     
    {
       
    lpName = (LPCSTR)PAddressOfNames[i]+pNTHeader->OptionalHeader.ImageBase;
    if(strcmp(lpName,"MessageBoxA")==0 ){
           index=PAddressOfNameOrdinals[i];
           FunctionRVA=PAddressOfFunctions[index-pExportStar->Base];
       printf("1.msgbox: %s\n\n",lpName);
       printf("1.msgbox: %04lx\n\n",(ULONG)FunctionRVA+pNTHeader->OptionalHeader.ImageBase);
       break;
    }
    }
        
        getch();
        return 0;
    }看看这个式子!
      

  15.   

    看你那个式子的结果是对的,和我一样。你用上面我给的程序看看结果是什麽?如果编译不通过,你在加上stdafx.h 。不知为什麽,我的程序如果加上stdafx.h编译就不通过,而你相反?WHY???? 
      

  16.   

    #include <stdio.h>
    #include <conio.h>
    #include <windows.h>
    int main(int argc, char* argv[])
    {
        HINSTANCE h=LoadLibrary("user32.dll");
        
        printf("h: %04lx\n\n",(ULONG)h);
        
        PIMAGE_DOS_HEADER pDosHdr;
    PIMAGE_NT_HEADERS pNTHeader;
    DWORD ExportRva,FunctionRVA;
    WORD index;
    PIMAGE_EXPORT_DIRECTORY pExportStar;
    PDWORD  PAddressOfNames,PAddressOfFunctions;
        PWORD   PAddressOfNameOrdinals;
    LPBYTE base; pDosHdr = (PIMAGE_DOS_HEADER)h;
    base = (LPBYTE)pDosHdr;
    pNTHeader = (PIMAGE_NT_HEADERS)(base+ (pDosHdr->e_lfanew));
    ExportRva = pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
    pExportStar = (PIMAGE_EXPORT_DIRECTORY)(ExportRva + pNTHeader->OptionalHeader.ImageBase);
    PAddressOfNames=(PDWORD)(pExportStar->AddressOfNames + pNTHeader->OptionalHeader.ImageBase);
    PAddressOfNameOrdinals=(PWORD)(pExportStar->AddressOfNameOrdinals+ pNTHeader->OptionalHeader.ImageBase);
    PAddressOfFunctions=(PDWORD)(pExportStar->AddressOfFunctions+ pNTHeader->OptionalHeader.ImageBase);
    LPCSTR lpName;for(DWORD i=0;i<pExportStar->NumberOfNames;i++)
     
    {
       
    lpName = (LPCSTR)PAddressOfNames[i]+pNTHeader->OptionalHeader.ImageBase;
    if(strcmp(lpName,"MessageBoxA")==0 ){
           index=PAddressOfNameOrdinals[i];
           FunctionRVA=PAddressOfFunctions[index];
           printf("1.msgbox: %04d\n\n",(ULONG)index);
       printf("1.msgbox: %s\n\n",lpName);
       printf("1.msgbox: %04lx\n\n",(ULONG)FunctionRVA+pNTHeader->OptionalHeader.ImageBase);
       break;
    }
    }
     
        getch();
        return 0;
    }
    上面有误,不准确,执行这个!!!不好意思
      

  17.   

    为什么所有的人(除了我自己)都只LoadLibrary,而不FreeLibrary?这个习惯可不好啊……另外,在98环境下,USER32.DLL的优先加载地址(Image Base)的确是bff50000,这点zhoujiehg(周杰)的程序已经显示了(h的值),如果USER32.DLL的确被加载到这个位置的话,那么MessageBoxA的位置肯定是bff541ba。如果你用GetProcAddress返回的地址是8xxxxxx的话,说明VC的Debug库正在运行,它会用一个Stub函数(好像一般叫做__imp__GetProcAddressA之类的)代替GetProcAddress函数,用已完成堆栈校验等;同时,它返回的值也将不是指向真实的函数入口,而是也指向一个Stub函数(可能叫做__imp__MessageBoxA之类的),同理,这样做也是为了完成堆栈校验之类的工作。此时这个地址是一个函数入口,而决非一个函数指针。因此直接用(ULONG *)取到的值也不对。这个Stub函数入口处第一条指令是push XXXXXXX,就是保存真实函数的地址。因此,可以这样来得到实际的函数入口:DWORD addrMessageBoxA;
    LPBYTE p = (LPBYTE)GetProceAddress(h, "MessageBoxA");
    // 0x68是push立即数的指令,而真正的MessageBoxA的第一条指令是push ebp,应该是0x55
    addrMessageBoxA = (DWORD)(*p == 0x68 ? *((LPDOWRD)(p+1)) : (DWORD)p);
    printf("MessageBoxA: %08X\n", addrMessageBoxA);所以,你在Debug环境下取到上述的值就一点也不奇怪。换成Release就没有问题了。注:以上讨论只是针对98的情况。
      

  18.   

    TO:azuo_lee()
    我并不怀疑你说的,可为什麽我在DEBUG下运行照样正常呢?
      

  19.   

    TO richen(苦行僧):呵呵,不要用Run,用Go试试。
      

  20.   

    呵呵,zhoujiehg兄怎麽老用 “GO” 来运行程序吗?TO:azuo_lee() 那里有这方面的资料啊?老弟
      

  21.   

    to  richen:azuo_lee 让我见识了什么叫精彩,PFPFto  azuo_lee:你是中国的Matt。你的一番话使我感到了柳暗花明
    --------------------------------------------
    我是才学VC的,能够遇到这么多高手,真是荣幸荣幸!