首页
社区
课程
招聘
[原创]修改“Starting a Process from KernelMode”
发表于: 2008-4-15 21:46 23518

[原创]修改“Starting a Process from KernelMode”

2008-4-15 21:46
23518

这个例子就是从内核模式中启动一个用户进程,网上讲解的有很多了,不过源代码编译后不能正常启动用户进程,例子自带的ntifs.h中EPROCESS,_KPROCESS,ETHREAD,_KTHREAD结构中成员偏移位置有偏差。
查看上述结构方法很简单,用WinDbg的dt命令,如 dt EPROCESS
我的系统是windows sp2,其他系统需做相应调整
修改部分源代码见下:
void RunProcess(LPSTR lpProcess)
{
    //全部定义为ULONG类型
    ULONG pTargetProcess;     //self explanatory
    ULONG pTargetThread;     //thread that can be either alerable or non-alertable
    ULONG pNotAlertableThread; //non-alertable thread
    ULONG pSystemProcess;     //May not necessarily be the 'System' process
    ULONG pTempThread;
    ULONG pNextEntry, pListHead, pThNextEntry,pThListHead;

    if(strlen(lpProcess)>300) return; //name not longer than 300 characters
    //获得系统进程
    pSystemProcess =(ULONG)PsGetCurrentProcess(); //make sure you are running at IRQL PASSIVE_LEVEL

    if(!pSystemProcess)
    {
        DbgPrint("KernelExec -> Cannot find 'System' process!");
        return;
    }
    //获取进程列表头(+0x088 ActiveProcessLinks : _LIST_ENTRY)
    pListHead=pSystemProcess+0x88;
    //得到下一个EPROCESS结构的ActiveProcessLinks偏移地址
    pNextEntry=*(ULONG*)pListHead;
    if(!pNextEntry)
        DbgPrint("KernelExec -> No processes found!");
    else
    {

        while(pNextEntry != pListHead) //start looping through the available processes
        {    //得到EPROCESS的首地址
            pSystemProcess =pNextEntry-0x88;
            //进程名偏移
            //+0x174 ImageFileName:[16] UChar
            DbgPrint("ProcessName %s \n",(char*)pSystemProcess+0x174);
                    //Is this explorer.exe?
                    if(_strnicmp((char*)pSystemProcess+0x174,"explorer.exe",12)==0)
                    {    //得到进程的EPROCESS结构的地址
                        pTargetProcess = pSystemProcess; //Yes,we have found it!
                        DbgPrint("yes,we have found explorer.exe!");
                        
                        pTargetThread = pNotAlertableThread = 0;
                        //获取线程列表头
                        //+0x050 ThreadListHead   : _LIST_ENTRY
                        //也就是_KPROCESS(PCB)中ThreadListHead的偏移地址
                        pThListHead = pSystemProcess+0x50;
                        //得到ETHREAD结构中_KTHREAD(Tcb)的+0x1b0 ThreadListEntry  : _LIST_ENTRY地址
                        pThNextEntry=*(ULONG *)pThListHead;
                        //Now we loop through it's threads, seeking an alertable thread
                        while(pThNextEntry != pThListHead)
                        {    //所属ETHREAD的首地址
                            pTempThread =pThNextEntry-0x1b0;
                            DbgPrint("ethread address is:0x%x\n",(ULONG *)pTempThread);
                            //线程ID
                            //ETHREAD+0x1ec Cid : _CLIENT_ID为进程ID
                            //再向下+4为线程ID
                            DbgPrint("thread Id is %d\n",*(ULONG *)(pTempThread+0x1f0));
                            //是否警告状态
                            //+0x164 Alertable : UChar
                            DbgPrint("Alertable is:%x",*(char *)(pTempThread+0x164));
                            //tcb=*(PKTHREAD)pTempThread;
                            if(*(char *)(pTempThread+0x164)) //Tcb is the KTHREAD of this ETHREAD and stands for 'Thread Control Block'
                            {
                                //Good, an alertable thread was found.
                                //得到explorer.exe中符合条件的线程PKTHREAD(ETHREAD)结构的地址
                                pTargetThread =pTempThread;

                                DbgPrint("KernelExec -> Found alertable thread");
                                //We will be using this one, so break now
                                break;
                            }
                            else
                            {
                                //Didn't find an alertable thread yet, so we'll keep this one
                                //just in case we won't find ANY alertable threads
                                //至少需要一个非警告状态的线程
                                pNotAlertableThread =pTempThread;
                            }
                            //下一个线程块
                            pThNextEntry = *(ULONG *)pThNextEntry; //check next thread
                        }
                        break;   
                    }
            //下一个进程块
            pNextEntry = *(ULONG *)pNextEntry; //get next process
        }
    }
   
    if(!pTargetProcess)
    {
        DbgPrint("KernelExec -> Couldn't find Explorer.exe!");
        return;
    }
    if(!pTargetThread)
    {
        //No alertable thread was found, so let's hope we've at least got a non-alertable one (we'll set its alertable flag ON)
        //There's no problem with non-alertable threads, except for the fact that it takes
        //a little longer for them to return from KernelMode. (that means our process execution will be delayed)
        pTargetThread = pNotAlertableThread;
    }

    if(pTargetThread)
    {
        DbgPrint("KernelExec -> Targeted thread: 0x%p",pTargetThread);
        //We have one thread (alertable or n/a), now install the APC
        InstallUserModeApc(lpProcess,pTargetThread,pTargetProcess);
    }
    else
        DbgPrint("KernelExec -> No thread found!"); //Explorer exe with NO threads (???)*/
}
另外还需要修改WinExec函数的地址
顺便说一下遍历所有线程的方法,这里用的是第一种(详见JIURL玩玩Win2k进程线程篇)
1.一个链表是以 EPROCESS 结构的 KPROCESS Pcb 中的 ThreadListHead 为链表的链表头。链上的每一项是一个线程的 KTHREAD ETHREAD 结构的 Tcb 中的 ThreadListEntry 。
2.另一个链表是以 EPROCESS 结构中的 ThreadListHead 为链表的链表头。链上的每一项是一个线程的 ETHREAD 结构中的 ThreadListEntry 。
通过这两个链表中的任何一个,都可以找到一个进程的所有线程的 ETHREAD 结构,当然找到 ETHREAD 结构,就可以找到 ETHREAD 结构中的 KTHREAD。


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (17)
雪    币: 321
活跃值: (271)
能力值: ( LV13,RANK:1050 )
在线值:
发帖
回帖
粉丝
2
沙发学习,收入rootkit专题了。
7。ring0中执行ring3程序
1) apc方式
2008-4-15 21:58
0
雪    币: 154
活跃值: (80)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
谢谢分享,最近搞内核方面研究的特别多,趁机大补一下
2008-4-15 22:59
0
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
4
好  文  !
2008-4-16 10:50
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
我是新手,想问楼主一个问题。
我将RunProcess函数从驱动的初始化函数,迁移到分发例程中。当给驱动发送命令后,驱动无法启动预设的应用程序。
请问,这个是不是和驱动程序运行时的优先级有关?
2008-7-3 16:16
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
好``东西``
2008-7-19 21:31
0
雪    币: 93
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
确实好文,用楼主的办法稍加改动,试验即获通过,多谢共享!
2008-10-4 21:12
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
8
回5楼:应该是PsGetCurrentProcess的问题,在DriverEntry中才是SYSTEM
2008-10-4 21:22
0
雪    币: 522
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
进程链表结构 都是一样的
随便是其中哪一个 应该都可以把整个链表拉出来
2008-10-5 16:58
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
我放在定时器中,也是一样不能启动,跟踪发现在定时器PsGetCurrentProcess返回的是0。如果不能在其它地方启动,意义可是不太啊。
2008-10-25 07:25
0
雪    币: 112
活跃值: (51)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
顶。。。。。
2008-12-15 23:43
0
雪    币: 145
活跃值: (85)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
12
lkd> dt EPROCESS
Symbol EPROCESS not found.
2009-3-27 21:30
0
雪    币: 225
活跃值: (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
13
dt _EPROCESS
2009-3-27 21:47
0
雪    币: 145
活跃值: (85)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
14
刚好从网上查到。。
2009-3-27 21:47
0
雪    币: 2512
活跃值: (672)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
15
多谢楼主分享!!!
2009-3-27 21:54
0
雪    币: 419
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
启动失败中

不知怎么修改中
2009-4-4 00:03
0
雪    币: 125
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
thanks

mark
2009-4-28 18:43
0
雪    币: 200
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
好东西,很好用
2009-8-27 22:35
0
游客
登录 | 注册 方可回帖
返回
//