首页
社区
课程
招聘
[求助]dump文件显示很诡异 MJ解释下为何重入APC
发表于: 2009-7-20 14:45 34413

[求助]dump文件显示很诡异 MJ解释下为何重入APC

2009-7-20 14:45
34413
收藏
免费 7
支持
分享
最新回复 (117)
雪    币: 170
活跃值: (90)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
76
NormalRoutine为0是一种特殊的情况,在这种情况下KernelRoutine所指的内核函数无条件地得到调用。但是,如果NormalRoutine非0,那么首先得到调用的是KernelRoutine,而指针NormalRoutine的地址是作为参数传下去的。KernelRoutine的执行有可能改变这个指针的值。这样,如果执行KernelRoutine以后NormalRoutine仍为非0,那就说明需要加以执行,所以通过这个函数指针予以调用。
2009-7-22 03:06
0
雪    币: 170
活跃值: (90)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
77
不是很理解啊
2009-7-22 03:08
0
雪    币: 170
活跃值: (90)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
78
要自己写个NormalRoutine吗?
2009-7-22 03:25
0
雪    币: 170
活跃值: (90)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
79
有去看了下WRK还是没理解
2009-7-22 03:33
0
雪    币: 170
活跃值: (90)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
80
不知道为何会重入呢?代码要如何修改下呢
2009-7-22 20:56
0
雪    币: 235
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
81
VOID
KeInitializeApc (
    __out PRKAPC Apc,
    __in PRKTHREAD Thread,
    __in KAPC_ENVIRONMENT Environment,
    __in PKKERNEL_ROUTINE KernelRoutine,
    __in_opt PKRUNDOWN_ROUTINE RundownRoutine,
    __in_opt PKNORMAL_ROUTINE NormalRoutine,    //应该是这个
    __in_opt KPROCESSOR_MODE ApcMode,
    __in_opt PVOID NormalContext
    )
KeInitializeApc 初始化NormalRoutine 看看..
再不行,就只能呼叫强大的MJ了..
2009-7-22 22:41
0
雪    币: 235
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
82
/*++

Routine Description:

    This function initializes a kernel APC object. The thread, kernel
    routine, and optionally a normal routine, processor mode, and normal
    context parameter are stored in the APC object.

Arguments:

    Apc - Supplies a pointer to a control object of type APC.

    Thread - Supplies a pointer to a dispatcher object of type thread.

    Environment - Supplies the environment in which the APC will execute.
        Valid values for this parameter are: OriginalApcEnvironment,
        AttachedApcEnvironment, CurrentApcEnvironment, or InsertApcEnvironment

    KernelRoutine - Supplies a pointer to a function that is to be
        executed at IRQL APC_LEVEL in kernel mode.

    RundownRoutine - Supplies an optional pointer to a function that is to be
        called if the APC is in a thread's APC queue when the thread terminates.

    NormalRoutine - Supplies an optional pointer to a function that is
        to be executed at IRQL 0 in the specified processor mode. If this
        parameter is not specified, then the ProcessorMode and NormalContext
        parameters are ignored.

    ApcMode - Supplies the processor mode in which the function specified
        by the NormalRoutine parameter is to be executed.

    NormalContext - Supplies a pointer to an arbitrary data structure which is
        to be passed to the function specified by the NormalRoutine parameter.

Return Value:

    None.
2009-7-22 22:43
0
雪    币: 170
活跃值: (90)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
83
NormalRoutine为0是一种特殊的情况,在这种情况下KernelRoutine所指的内核函数无条件地得到调用。
2009-7-23 10:32
0
雪    币: 170
活跃值: (90)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
84
KeInitializeApc(ExitApc,
                        ethread,                         //线程
                        OriginalApcEnvironment,
                        KernelKillThreadRoutine,
            NULL,
            NULL,
            KernelMode,
            NULL);//为线程初始化APC
                status=KeInsertQueueApc(ExitApc,NULL,NULL,0);   //插入Apc到线程队列
2009-7-23 10:34
0
雪    币: 170
活跃值: (90)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
85
VOID  KernelKillThreadRoutine(IN PKAPC Apc,
                              IN OUT PKNORMAL_ROUTINE *NormalRoutine,
                              IN OUT PVOID *NormalContext,
                              IN OUT PVOID *SystemArgument1,
                              IN OUT PVOID *SystemArgument2)
{
        //调用PsTerminateSystemThread结束线程
        //修改当前线程的ThreadFlags为系统线程
        PULONG ThreadFlags;
        ThreadFlags=(ULONG *)((ULONG)PsGetCurrentThread()+0x248);  //ETHREAD中CrossThreadFlags的偏移量为0x248
        if(MmIsAddressValid(ThreadFlags))   //地址进行下验证
        {
                *ThreadFlags=(*ThreadFlags) | PS_CROSS_THREAD_FLAGS_SYSTEM; //修改为系统权限
            PsTerminateSystemThread(STATUS_SUCCESS); //结束线程
        }
}
2009-7-23 10:34
0
雪    币: 170
活跃值: (90)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
86
内核特殊APC  NormalRoutine为空  调用KernelRoutine 怎么会出现重入呢?
在虚拟机杀冰刃才蓝屏
本机次次蓝屏
2009-7-23 10:36
0
雪    币: 170
活跃值: (90)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
87
等待MJ给出合理解释啊
2009-7-23 10:38
0
雪    币: 109
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
88
我也正在学习,来看看有啥可以值得看的
2009-7-23 12:41
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
89
KeInsertQueueApc(ExitApc,NULL,NULL,0);
改成
KeInsertQueueApc( ExitApc, ExitApc, NULL, 2 );
试试~~
我是来看MJ的~
2009-7-23 15:56
0
雪    币: 170
活跃值: (90)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
90
WRK是这么写的
KeInsertQueueApc( ExitApc, ExitApc, NULL, 2 );
2009-7-23 16:07
0
雪    币: 170
活跃值: (90)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
91
我们都是来看MJ的
2009-7-23 16:08
0
雪    币: 170
活跃值: (90)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
92
不知道道什么原因啊 我觉得跟NormalRoutine无关
2009-7-23 16:09
0
雪    币: 1705
活跃值: (1665)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
93
这个不蓝,太多了,我没仔细看你们的讨论。你自己对照找找问题。2000到vista都可以.
http://hi.baidu.com/alex_sec/blog/item/aaccba58c79ef6232934f0c1.html
2009-7-23 16:11
0
雪    币: 170
活跃值: (90)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
94
我代码跟他没什么差别 在我机器不行 蓝
2009-7-23 16:23
0
雪    币: 170
活跃值: (90)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
95
代码按照我的理解写的  存在一些问题 但是我不知道那里出问题了
2009-7-23 16:25
0
雪    币: 170
活跃值: (90)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
96
#define PS_CROSS_THREAD_FLAGS_SYSTEM 0x00000010UL

typedef enum _KAPC_ENVIRONMENT {
    OriginalApcEnvironment,
    AttachedApcEnvironment,
    CurrentApcEnvironment,
    InsertApcEnvironment
} KAPC_ENVIRONMENT;

VOID KeInitializeApc (
                 PKAPC Apc,
                 PETHREAD Thread,
                 KAPC_ENVIRONMENT Environment,
                 PKKERNEL_ROUTINE KernelRoutine,
                 PKRUNDOWN_ROUTINE RundownRoutine,
                 PKNORMAL_ROUTINE NormalRoutine,
                 KPROCESSOR_MODE ProcessorMode,
                 PVOID NormalContext
                 );

BOOLEAN KeInsertQueueApc(PKAPC Apc,PVOID SystemArg1,PVOID SystemArg2,KPRIORITY Increment);

VOID  KernelKillThreadRoutine(IN PKAPC Apc,
                              IN OUT PKNORMAL_ROUTINE *NormalRoutine,
                              IN OUT PVOID *NormalContext,
                              IN OUT PVOID *SystemArgument1,
                              IN OUT PVOID *SystemArgument2)
{
	//调用PsTerminateSystemThread结束线程
	//修改当前线程的ThreadFlags为系统线程
	PULONG ThreadFlags;
               ExFreePool(Apc);
	ThreadFlags=(ULONG *)((ULONG)PsGetCurrentThread()+0x248);  //ETHREAD中CrossThreadFlags的偏移量为0x248
	if(MmIsAddressValid(ThreadFlags))   //地址进行下验证
	{
		*ThreadFlags=(*ThreadFlags) | PS_CROSS_THREAD_FLAGS_SYSTEM; //修改为系统权限
	    PsTerminateSystemThread(STATUS_SUCCESS); //结束线程
	}
	else
	{
	}
	return;
}


VOID  KillProcessWithApc(ULONG epro)
{
	//遍历线程有2种做法:1、PsGetNextProcessThread(未导出函数,自己定位地址)  2、从EPROCESS的list链中ActiveThreads记录线程数量
	//3、遍历pspcidtable
	//为了防止KeInsertQueueApc被HOOK  我利用R3下函数GetProcessAddress获取地址,然后传入R0
	BOOLEAN status;
	PKAPC ExitApc=NULL;
	PEPROCESS eprocess;
	PETHREAD  ethread;
	ULONG i;
	ULONG num;   //线程数量
    ULONG Head;  //链表头
	ULONG address;//地址
	num=*(ULONG *)(epro+0x1a0);   //EPROCESS中ActiveThreads的数量  0x1a0是EPROCESS中ActiveThread的偏移量
    KdPrint(("[RecordThreadAddress] num: 0x%x\n",num));    //打印线程数量
	Head=epro+0x190;              //List_entry第一个节点地址
	for(i=0;i<num;i++)
	{   
		//记录线程地址
	    Head=(ULONG)((PLIST_ENTRY)Head)->Flink;
        address=Head-0x22c;
        KdPrint(("[RecordThreadAddress] address: 0x%x\n",address));      //打印线程地址
		ethread=(PETHREAD)address;                                       //转换成线程指针 
		ExitApc=(PKAPC)ExAllocatePoolWithTag(NonPagedPool,sizeof(KAPC),MEM_TAG);
		if(ExitApc==NULL)
		{
			KdPrint(("[KillProcessWithApc] malloc memory failed \n"));
			return;
		}
		KeInitializeApc(ExitApc,
			ethread,                         //线程
			OriginalApcEnvironment,
			KernelKillThreadRoutine,
            NULL,
            NULL,
            KernelMode,
            NULL);//为线程初始化APC
		status=KeInsertQueueApc(ExitApc,ExitApc,NULL,2);   //插入Apc到线程队列
		if(status)
		     KdPrint(("KeInsertQueueApc  success\n"));  
		else
            KdPrint(("KeInsertQueueApc  failed\n")); 
	}
}
2009-7-23 16:37
0
雪    币: 227
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
97
看看炉子写的那个,然后对照你的看看
2009-7-23 22:10
0
雪    币: 326
活跃值: (88)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
98
楼主可以试一下在
PsTerminateSystemThread(STATUS_SUCCESS); //结束线程
下一个断点,观察一下当前线程的APC队列。

看了一下PspExitThread。

kd> ub nt!PspExitThread+0x279
nt!PspExitThread+0x25e:
805c80b2 ff86d4000000    inc     dword ptr [esi+0D4h]
805c80b8 7513            jne     nt!PspExitThread+0x279 (805c80cd)
805c80ba 8d4634          lea     eax,[esi+34h]
805c80bd 3900            cmp     dword ptr [eax],eax   //是否还有APC
805c80bf 740c            je      nt!PspExitThread+0x279 (805c80cd)
805c80c1 c6464901        mov     byte ptr [esi+49h],1
805c80c5 b101            mov     cl,1
805c80c7 ff1500874d80    call    dword ptr [nt!_imp_HalRequestSoftwareInterrupt (804d8700)]

估计这里还有很多个相同的APC(全部都是调用KernelKillThreadRoutine),造成重入。

会不会是调用KillProcessWithApc出了问题啊~
2009-7-23 23:11
0
雪    币: 722
活跃值: (123)
能力值: ( LV12,RANK:300 )
在线值:
发帖
回帖
粉丝
99
我试了93楼给出的代码(改成汇编了)虚拟机里结束IceSword没蓝。
楼主的代码与93楼给出的代码的差别在于对各线程ETHREAD的获取方式,楼主采用EPROCESS中的ActiveThreads作为计数。不知道会不会是这里出的问题造成楼上所说的向同一个线程重复插入了APC。
倒,用ActiveThreads的作法我在虚拟机也试了,结束IceSword进程照样没蓝,IceSword是1.22中文版……
2009-7-24 00:38
0
雪    币: 170
活跃值: (90)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
100
诡异的问题啊  我换台电脑用95楼代码虚拟机测试结束冰刃竟然不蓝屏了
2009-7-24 01:07
0
游客
登录 | 注册 方可回帖
返回
//