| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1150 人关注过本帖, 1 人收藏
标题:【原创】学习笔记--函数在内存中的定位
只看楼主 加入收藏
五当家
Rank: 12Rank: 12Rank: 12
等 级:火箭侠
威 望:2
帖 子:1112
专家分:3674
注 册:2010-10-20
结帖率:96.3%
收藏(1)
已结贴  问题点数:20 回复次数:4 
【原创】学习笔记--函数在内存中的定位
// querySystemInfomation.cpp : 定义控制台应用程序的入口点。
//



#include "stdafx.h"
#include "windows.h"
#include "malloc.h"

/*发一篇学习心得,本人很菜,自学编程 ,学习点东西都很费力,希望大牛不要笑我
/最近学到内核编程遇到了很多直接强类型缓存区,譬如从SSDT中定位api,ZwQuerySystemInformation 等....
以前学没考虑过这些,当遇到这些问题时候,思路还是很模糊的,这些天,不断的遇到这样的操作,于是我就
写了下面这个练习,证明,在内存中数据的存取是靠基址 + 偏移,有了基地之 就可以通过偏移改PE文件,idt,ssdt等等操作
*/


typedef enum _class
{
    P_INFORMATION=1, //SYSTEM_PROCESS_INFORMATION
    M_INFORMATION, //SYSTEM_MODULE_INFORMATION
    T_INFORMATION //根据这个标志等下我们随意的一个偏移处写个函数放进去
}INFO_CLASS;

//进程结构
typedef struct _SYSTEM_PRCESS_INFORMATION
{
    UINT pid;
    char name[8];
}SYSTEM_PROCESS_INFORMATION,*PSYSTEM_PROCESS_INFORMATION;

//模块结构
typedef struct _SYSTEM_MODULE_INFORMATION
{
    DWORD addr;
    char name[8];
    int flag;
}SYSTEM_MODULE_INFORMATION,*PSYSTEM_MODULE_INFORMATION;

//假设这个函数在ssdt中 偏移为16 也就是 index = 4  ===>baseAddress + index * 4 得到这个 函数地址  
int add(int a,int b)
{
    return a+b;
}

#pragma pack(4)
PVOID QueryInfo(INFO_CLASS cls,PVOID buffer)
{
    //初始化,取一些信息,放在内存中,供查询使用
    UINT pid=1234; //取进程id
    DWORD pName = 0x4241 ;//取进程名字:ab --这里注意下字节序
    DWORD mName = 0x4443 ; //取模块名字:cd
    int flag = 888; //取模块标志
    DWORD addr = 0xff; //取模块地址
    PVOID functionAddr = (PVOID)add; //取函数地址
   

    //下面我不用变量写入,直接用汇编写内存,避免变量概念的干扰
    switch(cls)
    {
    case P_INFORMATION:
        _asm
        {
            //这里写进程id 和进程名 pName
            mov eax,buffer
            mov ebx,pid
            mov [eax],ebx
            mov ebx,pName
            mov [eax+4],ebx
        }
        
        break;
    case M_INFORMATION:
    _asm
        {
            //这里写模块地址addr,模块名字mName,模块标志flag
            mov eax,buffer
            mov ebx,addr
            mov [eax],ebx
            mov ebx,mName
            mov [eax+4],ebx
            mov ebx,flag
            mov [eax+12],ebx

        }
        break;
    case T_INFORMATION:
        _asm
        {
            //我们把Add函数存在ssdt中,偏移16
            mov eax,buffer
            mov ebx,functionAddr
            mov [eax+16],ebx
        }
        break;
    }
    return buffer;
}
#pragma pack()

int _tmain(int argc, _TCHAR* argv[])
{

    PVOID buffer = malloc(36);

////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //读取一下进程信息
    PVOID baseAddress = QueryInfo(P_INFORMATION,buffer);
    if(baseAddress == NULL)
    {
        goto error;
    }
    PSYSTEM_PROCESS_INFORMATION pMessage = (PSYSTEM_PROCESS_INFORMATION)baseAddress;
    printf("|查询进程信息pid:%d -- pName:%s\n|",pMessage->pid,pMessage->name);

////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //读取一下模块信息
    baseAddress = QueryInfo(M_INFORMATION,buffer);
    if(baseAddress == NULL)
    {
        goto error;
    }
    PSYSTEM_MODULE_INFORMATION mMessage = (PSYSTEM_MODULE_INFORMATION)baseAddress;
    printf("|查询模块信息addr:0x%x -- mName:%s\--flag:%d\n|",mMessage->addr,mMessage->name,mMessage->flag);
   
////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //读取下偏移为16那里的函数
    typedef  int (*funs)(int a,int b);
    funs add;
    baseAddress = QueryInfo(T_INFORMATION,buffer);
    if(baseAddress == NULL)
    {
        goto error;
    }
    PVOID fMessage = baseAddress;   
    _asm
    {
        mov eax,fMessage
        mov eax,[eax+16]
        mov add,eax
    }
    int c =  add(50,20);
    printf("add函数结果:%d\n",c);
    //譬如说SSDT中偏移为16的地方存了一个函数入口地址 add(0x45645678)
    //现在我们就可以typedef void (*funs)()
    //funs f = (fun)[baseAddress+16]
    //f();
    //或者修改函数地址,这里要注意内存写保护的问题,和大小问题
    //(*(ULONG *)(baseAddress+16)) = myfunc;

    delete buffer;
    return 0;
error:
    printf("读取内存失败\n");
    delete buffer;
    return -1;
}
//系统的那个ZwQuerySystemInformation肯定比这个复杂很多,但是我感觉原理该差不多了,
//写完之后,感觉自己更加清晰了,可以很轻松的用KeServiecDescriptorTable + index *4 等去定位一些东西了.
//希望对那些和我一样菜的,还不是很明白的人能有所帮助,以后遇到譬如KeServiecDescriptorTable + index*4 ,ZwQuerySystemInformation 这样的东西不感到恐惧.
//2点了,睡觉。
收到的鲜花
  • zaixuexi2011-11-22 21:04 送鲜花  50朵   附言:原创内容,鼓励
搜索更多相关主题的帖子: 定位 内存 应用程序 include 
2011-11-21 15:41
慕容绾绾
Rank: 2
等 级:论坛游民
帖 子:15
专家分:66
注 册:2010-12-23
收藏
得分:10 
2011-11-21 15:56
zaixuexi
Rank: 12Rank: 12Rank: 12
来 自:上海
等 级:火箭侠
威 望:8
帖 子:858
专家分:3233
注 册:2010-12-1
收藏
得分:10 
比较大型的结构数据,基本都靠指针来访问,否则会消耗大量的code rom。通过基址+变址的方式进行读写,数组就是最简单的例子,作为函数参数退化为指针。任意一片地址空间上的数据,你想怎么解析都可以。但是说在内存中数据的存取是靠基址 + 偏移,这个好像太绝对了吧。数据强转很常用的,多用用就熟了。

技术问题,请不要以短消息方式提问
2011-11-21 18:35
五当家
Rank: 12Rank: 12Rank: 12
等 级:火箭侠
威 望:2
帖 子:1112
专家分:3674
注 册:2010-10-20
收藏
得分:0 
多谢指点

经验积累中............
2011-11-24 21:01
你们都要疼我哦
Rank: 11Rank: 11Rank: 11Rank: 11
来 自:火星
等 级:贵宾
威 望:49
帖 子:1296
专家分:2746
注 册:2008-7-13
收藏
得分:0 
吃吃饭饭  睡睡觉觉  顶顶贴贴

小妹,哥哥看你骨骼清奇,绝非凡人,将来必成大业,不如这样,你先把裤裤脱了,待哥哥为你开启灵窍,然后我们一起努力钻研如何
2011-11-28 04:24
快速回复:【原创】学习笔记--函数在内存中的定位
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.021900 second(s), 10 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved