APC(二)

分析KeInsertQueueApc

BOOLEAN KeInsertQueueApc (
    __inout PRKAPC Apc, //APC的结构
    __in_opt PVOID SystemArgument1,
    __in_opt PVOID SystemArgument2,//参数
    __in KPRIORITY Increment//优先级
    )

然后把ntkrnlpa.exe放进IDA里面进行反编译,然后再找到这个函数。

char __stdcall KeInsertQueueApc(int apc, int SystemArgument1, int SystemArgument2, int Increment)
{
  int v4; // edi
  volatile signed __int32 *v5; // ebx
  char bRet; // [esp+13h] [ebp-Dh]
  int spinCount; // [esp+14h] [ebp-Ch]
  unsigned __int8 NewIrql; // [esp+18h] [ebp-8h]
  _KPRCB *kpcr; // [esp+1Ch] [ebp-4h]

  v4 = *(_DWORD *)(apc + 8);
  spinCount = 0;
  NewIrql = KeRaiseIrqlToDpcLevel();//提高当前IQL等级为DPC_LEVEL
  kpcr = KeGetPcr()->Prcb;
  v5 = (volatile signed __int32 *)(v4 + 96);
  while ( _InterlockedExchange(v5, 1) )//加锁 确保中途的过程不会被打断
  {
    do
    {
      if ( ++spinCount & HvlLongSpinCountMask || !(HvlEnlightenments & 0x40) )//验证加的锁
        _mm_pause();
      else
        HvlNotifyLongSpinWait(spinCount);
    }
    while ( *v5 );
  }
  if ( *(_DWORD *)(v4 + 184) & 0x20 && *(_BYTE *)(apc + 46) != 1 )
  {
    *(_DWORD *)(apc + 36) = SystemArgument1;
    *(_BYTE *)(apc + 46) = 1;
    *(_DWORD *)(apc + 40) = SystemArgument2;
    KiInsertQueueApc((signed __int32)kpcr, apc, NewIrql);//这个函数才起到了插入APC的作用
    bRet = 1;
  }
  else
  {
    bRet = 0;
  }
  _InterlockedAnd(v5, 0);//解锁
  KiExitDispatcher((int)kpcr, 0, 1, Increment, NewIrql);
  return bRet;
}

然后跟进KiInsertQueueApc函数中,继续去查看

char __fastcall KiInsertQueueApc(signed __int32 KPCR, int KAPC, unsigned __int8 IRQL)
{
  int v3; // edi
  int v4; // esi
  int v5; // ecx
  char v6; // bl
  int *v7; // ecx
  int v8; // edx
  int *v9; // eax
  int v10; // ecx
  _DWORD *v11; // edx
  int *v12; // eax
  int v13; // ecx
  int *v14; // eax
  int v15; // edx
  int *v16; // ecx
  int v17; // eax
  int v18; // ecx
  volatile signed __int32 *v19; // ebx
  volatile signed __int32 *v20; // edi
  int v21; // ebx
  char v22; // al
  unsigned int v23; // eax
  int v24; // esi
  unsigned int v25; // ecx
  int v26; // eax
  _KPRCB *v27; // eax
  char v29; // [esp+Fh] [ebp-19h]
  char v30; // [esp+Fh] [ebp-19h]
  int v31; // [esp+10h] [ebp-18h]
  signed __int32 v32; // [esp+14h] [ebp-14h]
  int v33; // [esp+18h] [ebp-10h]
  __int16 v34; // [esp+1Ch] [ebp-Ch]
  __int16 v35; // [esp+1Eh] [ebp-Ah]
  int v36; // [esp+24h] [ebp-4h]

  v3 = KAPC;
  v4 = *(_DWORD *)(KAPC + 8);                   // 获取线程
  v32 = KPCR;
  if ( *(_BYTE *)(KAPC + 0x2C) == 3 )           // 0x2c KAPC.ApcStateIndex 判断APC的索引
    *(_BYTE *)(KAPC + 0x2C) = *(_BYTE *)(v4 + 0x134);// 0x134 Kthread.ApcStateIndex 如果为3则选择当前的索引
  v5 = *(_DWORD *)(v4 + 4 * *(char *)(KAPC + 0x2C) + 0x168);// 获取0x168 Kthread.ApcStatePointer
  v6 = *(_BYTE *)(KAPC + 0x2D);                 // 0x2D KAPC.ApcMode 获取是内核还是用户
  if ( *(_DWORD *)(KAPC + 0x1C) )               // 0x1c KAPC.NormalRoutine 判断有无正常函数表
  {
    v29 = 1;
    if ( v6 && *(void (__stdcall **)(int, int, int, int, int))(KAPC + 0x14) == PsExitSpecialApc )// 0x14 KAPC.KernelRoutine 判断是否是退出线程的APC
    {
      *(_BYTE *)(v4 + 0x56) = 1;
      v7 = (int *)(v5 + 8 * v6);                // _KAPC_STATE
      v8 = *v7;
      v9 = (int *)(v3 + 0xC);
      *v9 = *v7;
      v9[1] = (int)v7;
      *(_DWORD *)(v8 + 4) = v3 + 0xC;           // 插入到头节点
      *v7 = v3 + 0xC;
    }
    else
    {
      v10 = v5 + 8 * v6;
      v11 = *(_DWORD **)(v10 + 4);
      v12 = (int *)(v3 + 12);
      *v12 = v10;
      v12[1] = (int)v11;
      *v11 = v3 + 12;
      *(_DWORD *)(v10 + 4) = v3 + 12;           // 如果不是就插入到尾节点
    }
  }
  else
  {
    v13 = v5 + 8 * v6;                          // 指向下一个节点
    v14 = *(int **)(v13 + 4);
    v29 = 0;
    while ( v14 != (int *)v13 && v14[4] )
      v14 = (int *)v14[1];
    v15 = *v14;                                 // KAPC.NormalRoutine
    v16 = (int *)(v3 + 12);
    *v16 = *v14;
    v16[1] = (int)v14;
    *(_DWORD *)(v15 + 4) = v3 + 12;
    *v14 = v3 + 12;
  }
  v17 = *(unsigned __int8 *)(v4 + 0x134);       // 0x134 Kthread.ApcStateIndex
  v18 = *(char *)(v3 + 0x2C);                   // 0x2c KAPC.ApcStateIndex 判断APC的索引
  if ( v18 == v17 )                             // 判断是否是一个 如果不一样直接跳走
  {
    LOBYTE(v17) = v32;
    if ( v4 == *(_DWORD *)(v32 + 4) )
    {
      if ( !v6 && (!*(_DWORD *)(v4 + 0x84) || !v29 && !*(_WORD *)(v4 + 0x86)) )// +0x084 KernelApcDisable +0x086 SpecialApcDisable 判断是否是特殊
                                                // 
      {
        *(_BYTE *)(v4 + 0x55) = 1;
        if ( IRQL < 1u )                        // 中断 检测APC是否需要执行
        {
          *(_DWORD *)(v4 + 60) |= 0x100u;       // 0x60 Kthread.ApcQueueLock
          return v17;
        }
LABEL_55:
        LOBYTE(v18) = 1;
        LOBYTE(v17) = HalRequestSoftwareInterrupt(v18);// 中断 然后执行APC
        return v17;
      }
    }
    else if ( v6 )                              // 如果是用户APC
    {
      LOBYTE(v17) = *(_BYTE *)(v4 + 0x68);      // Kthread.State
      if ( (_BYTE)v17 == 5 )                    // 一般直接返回
      {
        v30 = 0;
        v20 = (volatile signed __int32 *)(v4 + 52);
        v21 = 0;
        while ( _InterlockedExchange(v20, 1) )
        {
          do
          {
            if ( ++v21 & HvlLongSpinCountMask || !(HvlEnlightenments & 0x40) )
              _mm_pause();
            else
              HvlNotifyLongSpinWait(v21);
          }
          while ( *v20 );
        }
        if ( *(_BYTE *)(v4 + 104) == 5
          && *(_BYTE *)(v4 + 107) == 1
          && (*(_BYTE *)(v4 + 60) & 0x20 || *(_BYTE *)(v4 + 86)) )
        {
          v22 = KiSignalThread(v32, 192);
          *(_BYTE *)(v4 + 56) |= 0x20u;
          v30 = v22;
        }
        LOBYTE(v17) = 0;
        _InterlockedAnd(v20, 0);
        if ( v30 )
          *(_BYTE *)(v4 + 86) = 1;
      }                                         // 到这
    }
    else
    {
      *(_BYTE *)(v4 + 0x55) = 1;
      _InterlockedExchange(&v33, v32);          // 初始化
      v17 = *(unsigned __int8 *)(v4 + 0x68);    // Kthread.State
      if ( v17 == 2 )
      {
        v23 = KeGetCurrentProcessorNumberEx(0); // 获取处理器编号
        v18 = *(_DWORD *)(v4 + 0x58);
        if ( v23 == v18 )
          goto LABEL_55;
        v24 = *(_DWORD *)(v4 + 0x58);
        v34 = 1;
        v35 = 1;
        v36 = 0;
        v25 = (unsigned int)KiProcessorIndexToNumberMappingTable[v24] >> 6;
        v26 = KiProcessorIndexToNumberMappingTable[v24] & 0x3F;
        if ( v25 >= 1 )
          v34 = v25 + 1;
        *(&v36 + v25) |= KiMask32Array[v26];    // 获取位图
        v27 = KeGetPcr()->Prcb;
        ++v27->IpiSendSoftwareInterruptCount;
        LOBYTE(v17) = KiIpiSend(&v34);
      }
      else if ( v17 == 5 )
      {
        v31 = 0;
        v19 = (volatile signed __int32 *)(v4 + 52);
        while ( _InterlockedExchange(v19, 1) )
        {
          do
          {
            if ( ++v31 & HvlLongSpinCountMask || !(HvlEnlightenments & 0x40) )
              _mm_pause();
            else
              HvlNotifyLongSpinWait(v31);
          }
          while ( *v19 );
        }
        if ( *(_BYTE *)(v4 + 0x68) == 5
          && !*(_BYTE *)(v4 + 0x6A)
          && !*(_WORD *)(v4 + 0x86)
          && (!*(_DWORD *)(v3 + 0x1C) || !*(_WORD *)(v4 + 0x84) && !*(_BYTE *)(v4 + 0x54)) )
        {
          KiSignalThread(v32, 256);
          *(_BYTE *)(v4 + 56) |= 0x10u;
        }
        LOBYTE(v17) = 0;
        _InterlockedAnd(v19, 0);
      }
    }
  }
  return v17;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值