c指针与地址空间的理解

进程各种地址打印

进程各种地址打印

进程内存布局

进程内存布局

各种变量地址打印示例

int global1;
int global2;
int globalbig[1000000];
int global3;
int global4;

void func1()
{   
}

void func2()
{   
}

int _tmain(int argc, _TCHAR* argv[])
{
    void *p;
    HMODULE hmod;
    int stack1 = 1;
    int stack2 = 2; 
    int stackbig[100000];
    int stack3 = 3;
    int stack4 = 4;     

    //比照    
    printf("ffffffff-c0000000:内核代码\n");
    printf("c0000000-80000000:系统dll\n");
    printf("80000000-10000000:用户dll\n");
    printf("10000000-00400000:数据,代码,堆栈\n");
    printf("00400000-00001000:dos\\win16兼容\n");
    printf("00001000-00000000:空指针\n");
    printf("其中00400000为exe建议装入地址,10000000为dll建议装入地址\n");
    printf("\n");

    //观察系统dll及api地址
    hmod = ::GetModuleHandle(L"user32.dll");
    printf("系统dll:user32:%x\n",hmod);   
    p = ::MessageBox;
    printf("系统api:MessageBox:%x\n",p);
    printf("\n");

    //观察用户dll及导出函数地址
    hmod = ::LoadLibrary(L"HookTool.dll");  
    printf("用户dll:HookTool:%x\n",hmod);
    p = ::GetProcAddress(hmod,"AddWnd");
    printf("DLL函数:AddWnd:%x\n",p);
    printf("\n");

    //观察exe基址
    hmod = ::GetModuleHandle(NULL);
    printf("exe基址:%x\n",hmod);
    printf("总结:由于重定位,实际装入地址总与标准建议装入地址不同\n");
    printf("\n");

    //观察全局变量地址
    printf("全局-变量1:%x\n",&global1);
    printf("全局-变量2:%x\n",&global2);
    printf("全局-大型:%x\n",&globalbig);    
    printf("全局-变量3:%x\n",&global3);
    printf("全局-变量4:%x\n",&global4);
    printf("总结:全局变量严格按照声明顺序从高向低排列在一起\n");
    printf("\n");

    //观察本地函数地址
    printf("本地函数1:%x\n",&func1);
    printf("本地函数2:%x\n",&func2);
    printf("\n");

    //观察栈变量地址
    printf("栈-变量1:%x\n",&stack1);
    printf("栈-变量2:%x\n",&stack2);
    printf("栈-大型:%x\n",&stackbig);
    printf("栈-变量3:%x\n",&stack3);
    printf("栈-变量4:%x\n",&stack4);
    printf("总结:堆栈变量严格按照声明顺序从高向低排列在一起(对齐的)\n");
    printf("\n");   

    //观察栈参数地址       
    printf("栈-参数1:%x\n",&argc);
    printf("栈-参数2:%x\n",&argv);
    printf("\n");

    //观察堆变量地址   
    p = new int[100];
    printf("堆-变量1:%x\n",p);
    p = new int[100];
    printf("堆-变量2:%x\n",p);
    p = new int[1000000];
    printf("堆-大型:%x\n",p);
    p = new int[100];
    printf("堆-变量3:%x\n",p);
    p = new int[100];
    printf("堆-变量4:%x\n",p);
    printf("\n");

    system("pause");
    return 0;
}

获取PE相关地址

    DWORD p;
    DWORD base;
    IMAGE_DOS_HEADER* dosheader;
    IMAGE_NT_HEADERS* ntheader;
    IMAGE_IMPORT_DESCRIPTOR* imp;
    IMAGE_THUNK_DATA* td;
    IMAGE_IMPORT_BY_NAME* iname;

    base = (DWORD)GetModuleHandle(NULL);    

    dosheader = (IMAGE_DOS_HEADER*)base;

    p = base + dosheader->e_lfanew;
    ntheader = (IMAGE_NT_HEADERS *)p;

    p = base+ntheader->OptionalHeader.DataDirectory[1].VirtualAddress;  
    imp = (IMAGE_IMPORT_DESCRIPTOR*)p;  
    int len = sizeof(IMAGE_IMPORT_DESCRIPTOR);
    while(imp->FirstThunk)
    {       
        p = base+imp->Name;
        char* dllname = (char*)p;       
        p = base + imp->FirstThunk;
        td = (IMAGE_THUNK_DATA*)p;
        DWORD num = 0;      
        while(td->u1.AddressOfData) 
        {
            num ++;
            td += sizeof(IMAGE_THUNK_DATA);         
        }       
        DWORD tmp = (DWORD)imp;
        tmp += sizeof(IMAGE_IMPORT_DESCRIPTOR);
        imp = (IMAGE_IMPORT_DESCRIPTOR*)tmp;
    }