NTFS XCB定位

标 题:  【原创】NTFS XCB定位。
作 者: zkgy
时 间: 2013-07-04,11:19:47

链 接: http://bbs.pediy.com/showthread.php?t=174789

NTFS XCB 定位小小的一个研究。。。顺便纠正一下sudami大牛在《NTFS底层挖掘中》关于通过SCB定位子LCB的一个错误。给研究NTFS的人做一点小小的贡献,欢迎大家踊跃批评。


NTFS XCB 小小研究

作者:李光耀
中国民航飞行学院
QQ:447649795E
mail:zkgy2000@126.com
2013-1-1

1、测试说明

WinDbg + Vmware双机调试 (Windows XP SP3)

----------------------------------------------------------------------------------------------------
在C盘建立以下文件结构
123(文件夹)----1.zip
       |-----2.exe
       |-----456(文件夹)-----1.exe
----------------------------------------------------------------------------------------------------
注意:上述所有文件和文件夹只有在第一次创建或者在被打开过至少一次后他们的SCB才会存在!
-----------------------------------------------------------------------------------------------------
先人工获得各自对应的FILEOBJECT 和SCB,如下图:
先获得对应文件的一个FILE_OBJECT然后,pFileObject->FsContext就是SCB

<<<============================================>>>>
GetObj-->\??\C:\123
FILEOBJECT:816E15F0 SCB:E1D64D20
GetObj-->\??\C:\123\1.zip
FILEOBJECT:81618B88 SCB:E1D038C0
GetObj-->\??\C:\123\2.exe
FILEOBJECT:81615D90 SCB:E1D17570
GetObj-->\??\C:\123\1.zip
FILEOBJECT:816D7098 SCB:E1D038C0
GetObj-->\??\C:\123\456
FILEOBJECT:81933D90 SCB:E1D1F898
GetObj-->\??\C:\123\456\1.exe
FILEOBJECT:81687C78 SCB:E1A97D90
<<<============================================>>>>

C:\123的SCB
 
地址    数据---------------------------------------------------------------------------------------------------------数据
附件 82897

地址e1d64e80为SCB+0x160,此处的两个指针e1d17710 e1d03a60就是指向子LCB的两个链表,一个指向第一个,一个指向最后一个。遍历其中任何一个链表都可找到123目录下所有被打开过的文件、文件夹的LCB,从LCB可以找到其对应的FCB和SCB以及CCB,就可以控制文件了!当该目录下没有存在任何文件或者没有任何文件被打开过时SCB+0x160与SCB+0x164均指向SCB+0x160,如上文的SCB,如果没有LCB时SCB+0x160 = SCB+0x164 = E1D64D20 + 0x160 = E1D64E80

2、手工定位XCB

2.1现在以SCB+0x160(e1d64e80),的指针指向的内容e1d17710遍历这个链表。


LCB的一些结构如下
名称:  2.png查看次数: 0文件大小:  22.4 KB

e1d17710指向的内容,图中画横线的内容便是e1d17710指向的内容,
地址     数据------------------------------------------------------------------------------------------------------数据
点击图片以查看大图图片名称:	3.png查看次数:	0文件大小:	21.5 KB文件 ID :	82899

因为LCB.ScbQueue.Flink的偏移为0x8故,这个LCB的地址为e1d17710-0x8 = e1d17708,图中内容实际为123下某个文件的LCB(地址),可以看到这个文件的FCB指针为LCB + 0x10 , *(e1d17708 + 0x14 = e1d174a8

FCB部分结构为:
名称:  4.png查看次数: 0文件大小:  22.9 KB

查看该FCB
地址   数据------------------------------------------------------------------------------------------------------数据
点击图片以查看大图图片名称:	5.png查看次数:	0文件大小:	20.6 KB文件 ID :	82901

可见FCB.ScbQueu.Flink = e1d175b0;
而SCB部分结构为
名称:  6.png查看次数: 0文件大小:  41.4 KB

故这个LCB->FCB->SCB地址为:  FCB.ScbQueu.Flink – (SCB.FcbLinks.Flink在SCB中的偏移0x40)
为e1d175b0– 0x40= e1d175b0对照开始得出的SCB地址,可见LCB FCB SCB 是C:\123\2.exe的。

2.2继续,下一个指向的是e1d1faa8

e1d1faa8指向的内容如下
地址   数据------------------------------------------------------------------------------------------------------数据
点击图片以查看大图图片名称:	7.png查看次数:	0文件大小:	9.5 KB文件 ID :	82903

根据上文此LCB的地址为: e1d1faa8 – 0x8 = e1d1faa0
LCB->FCB = *(e1d1faa0 + 0x14) = e1d1f7d0
查看FCB
地址     数据------------------------------------------------------------------------------------------------------数据
点击图片以查看大图图片名称:	8.png查看次数:	0文件大小:	25.1 KB文件 ID :	82904

可见FCB.ScbQueu.Flink = e1d1f8d8;
故这个文件的SCB地址为FCB.ScbQueu.Flink – (SCB.FcbLinks.Flink在SCB中的偏移0x40)
为e1d1f8d8 – 0x40 = E1D1F898根据开始手工获得的SCB地址对照为C:\123\456文件夹的SCB

2.3继续,下一个指向的是e1d03a60

图不再列出,LCB地址为 e1d03a60 -0x8 = e1d03a58    LCB->FCB = e1d037f8
根据FCB得出SCB地址为FCB.ScbQueu.Flink (e1d03900)– (SCB.FcbLinks.Flink在SCB中的偏移0x40)为e1d03900 – 0x40 = E1D038C0对照发现这个是C:\123\1.zip

2.4继续,下一个指向的是e1d64e80

e1d64e80就是开始时C:\123的SCB+0x160的数值。链表遍历完毕。
可见其目录结构为:

C:\123(文件夹SCB :E1D64D20 + 0x160处的LcbQueue.Flink链表)
                      ↓
               e1d17710  ----→LCB e1d17708 ->FCB e1d174a8 ->SCB e1d175b0 –>C:\123\2.exe
                      ↓
               e1d1faa8   ----→LCB e1d1faa0 ->FCB e1d1f7d0 ->SCB E1D1F898 –>C:\123\456文件夹
                      ↓
               e1d03a60   ----→LCB e1d03a58 ->FCB e1d037f8 ->SCB E1D038C0 –>C:\123\1.zip
                      ↓
               e1d64e80  ----→ C:\123 SCB + 0x160处的LcbQueue.Flink链表遍历完毕。

找到了C:\123目录下所有打开过的文件的SCB FCB LCB

3.本人归纳的XCB关系

1.用FCB->LcbLinks.Flink 可获得一个Lcb,此Lcb->Scb指向父目录SCB,同时,此Lcb->FcbLink指向自己的FCB.

2.用FCB->ScbLinks.Flink 可获得一个指向自己的Scb.

3.总之,Lcb.FcbLinks 指向自己FCB,

4.一个SCB只能有一个父母FCB,但是一个FCB可以有多个子SCB,也可以有多个父母SCB (这种情况下FCB通过lcb指向父母SCB).

点击图片以查看大图图片名称:	9.png查看次数:	0文件大小:	28.0 KB文件 ID :	82905

另外Windows 7中XCB中的大多数成员偏移都发生了变化,下面是本人跟踪调试的结果,亲测正确可用!

点击图片以查看大图图片名称:	10.png查看次数:	1文件大小:	50.5 KB文件 ID :	82906

4.Windows XP sp3下强制移动文件核心代码

(定位XCB并清空CleanupCount)
代码:
#define CLEANXCB(p/*PSCB*/) {p->CleanupCount = 0;p->Fcb->CleanupCount = 0;p->Fcb->LinkCount = 1;}


NTSTATUS NT5FuckChildren(PSCB pScb)//XP
{
  PULONG pExact = NULL ,pExact_Bak = NULL;
  PLCB pLcb = NULL;
  LIST_ENTRY *pList = NULL,*pNew = NULL; 
  PSCB pMyScb = NULL;
  char Sign = 0;
  if (!pScb || 0x703 != *(PUSHORT)pScb){
    DbgPrint("pScb为NULL或者非文件夹不用Fuck!\n");
    return 0;  
  }
  DbgPrint("----------------进入目录分析----------------\n");
    
    CLEANXCB(pScb)

   pExact_Bak = pExact = ((PCHAR)pScb + 0x160) ;
   
   //DbgPrint("pExact %X *pExact %X\n",pExact,*pExact);
   if (*pExact == (ULONG)pExact){
      
     DbgPrint("此SCB无子LCB!\n");
     DbgPrint("----------------目录分析完毕----------------\n");  
     return STATUS_UNSUCCESSFUL;
   }
    
   pLcb = (PLCB)(*pExact - 0x8);
   //DbgPrint("PLCB%XpLcb->ScbLinks.Flink%XpLcb->ScbLinks.Blink%X\n",pLcb,pLcb->ScbLinks.Flink,pLcb->ScbLinks.Blink);
   if (pLcb->NodeTypeCode != 0x70B){
     
     DbgPrint("此LCB错误!\n");
     DbgPrint("----------------目录分析完毕----------------\n");
     return STATUS_UNSUCCESSFUL;
   }

   while(pLcb->ScbLinks.Flink != pExact  ){

    DbgPrint("-->LCB: %X FCB: %X  SCB: %X\n",pLcb,pLcb->CleanupCount,pLcb->Scb);
    //===============================================================================
    pNew = pList = & ((PFCB)((PCHAR)pLcb+0x14))->ScbQueue;
    while(!((pList->Blink ==pNew || pList->Flink ==pNew) || pList->Flink==NULL)){
      pMyScb = CONTAINING_RECORD(pList->Flink,SCB, FcbLinks.Flink);
      DbgPrint("----------------MySCB %X NodeTypeCode:%X\n",pMyScb,pMyScb->Header.NodeTypeCode);
      //--------------------------
      CLEANXCB(pMyScb)
      //-------------------------
      if (0x703 == pMyScb->Header.NodeTypeCode)  {//此SCB代表一个目录
        DbgPrint("\t");
        NT5FuckChildren(pMyScb);
      }
      
        pList = pList->Flink;
    }
 //=================================================================================
    pLcb = ( ((PUCHAR)pLcb->ScbLinks.Flink)  -0x8); 

   }
    DbgPrint("-->LCB: %X FCB: %X  SCB: %X\n",pLcb,pLcb->CleanupCount,pLcb->Scb);
    pNew = pList = & ((PFCB)pLcb->CleanupCount)->ScbQueue;
    while(!((pList->Blink ==pNew || pList->Flink ==pNew) || pList->Flink==NULL)){
      pMyScb = CONTAINING_RECORD(pList->Flink,SCB, FcbLinks.Flink);
      DbgPrint("----------------MySCB: %X NodeTypeCode:%X\n",pMyScb,pMyScb->Header.NodeTypeCode);
       CLEANXCB(pMyScb)
      if (0x703 == pMyScb->Header.NodeTypeCode)  {//此SCB代表一个目录
        DbgPrint("\t");
        NT5FuckChildren(pMyScb);
      }
      
        pList = pList->Flink;
    }
    DbgPrint("----------------目录分析完毕----------------\n");  
  return STATUS_SUCCESS;
}
5.Windows 7下强制移动文件核心代码

(定位XCB并清空CleanupCount)
代码:
#defineNT7CLEANXCB(p/*PSCB*/){*(PULONG)((PUCHAR)p+0x60)=0;*(PULONG)(((PUCHAR)(*(PULONG)(( PUCHAR)p + 0x50))) + 0xC4) = 0;}
NTSTATUS NT7FuckChildren(PSCB pScb)
{
  PULONG pExact = NULL ,pExact_Bak = NULL;
  PLCB pLcb = NULL;
  LIST_ENTRY *pList = NULL,*pNew = NULL; 
  PSCB pMyScb = NULL;
  char Sign = 0;
    DbgPrint("----------------进入目录分析----------------\n");
    
    NT7CLEANXCB(pScb)

   pExact_Bak = pExact = (PULONG)((PCHAR)pScb + 0x168) ;
   
   //DbgPrint("pExact %X *pExact %X\n",pExact,*pExact);
   if (*pExact == (ULONG)pExact){
      
     DbgPrint("此SCB无子LCB!\n");
     DbgPrint("----------------目录分析完毕----------------\n");  
     return STATUS_UNSUCCESSFUL;
   }
    
   pLcb = (PLCB)(*pExact - 0x8);
   //DbgPrint("PLCB%XpLcb->ScbLinks.Flink%XpLcb->ScbLinks.Blink%X\n",pLcb,pLcb->ScbLinks.Flink,pLcb->ScbLinks.Blink);
   if (pLcb->NodeTypeCode != 0x70B){
     
     DbgPrint("此LCB错误!\n");
     DbgPrint("----------------目录分析完毕----------------\n");
     return STATUS_UNSUCCESSFUL;
   }

   while(  (PULONG)pLcb->ScbLinks.Flink != pExact /*&&  (PULONG) pLcb->ScbLinks.Blink != pExact */){

    DbgPrint("-->LCB: %X FCB: %X  SCB: %X\n",pLcb,*(PULONG)(( PUCHAR)pLcb + 0x18),pLcb->Scb);
    //===============================================================================
    pNew = pList = & ((PFCB)(*(PULONG)(( PUCHAR)pLcb + 0x18)))->LcbQueue;//实际为ScbQueue
    while(!((pList->Blink ==pNew || pList->Flink ==pNew) || pList->Flink==NULL)){
      pMyScb = (PSCB)((PUCHAR)pList->Flink - 0x48);
      DbgPrint("----------------My SCB%X NodeTypeCode:%X\n",pMyScb,pMyScb->Header.NodeTypeCode);
      //--------------------------
      NT7CLEANXCB(pMyScb)
      //-------------------------
      if (0x703 == *(PUSHORT)(pMyScb))  {//此SCB代表一个目录
        DbgPrint("\t");
        NT7FuckChildren(pMyScb);
      }
      
        pList = pList->Flink;
    }
     // =================================================================================
    pLcb =  (PLCB)( ((PUCHAR)pLcb->ScbLinks.Flink)  -0x8); 

   }
    DbgPrint("-->LCB: %X FCB: %X  SCB: %X\n",pLcb,*(PULONG)(( PUCHAR)pLcb + 0x18),pLcb->Scb);
    //===============================================================================
    pNew = pList = & ((PFCB)(*(PULONG)(( PUCHAR)pLcb + 0x18)))->LcbQueue;
    while(!((pList->Blink ==pNew || pList->Flink ==pNew) || pList->Flink==NULL)){
      pMyScb = (PSCB)((PUCHAR)pList->Flink - 0x48);
      DbgPrint("----------------My SCB%X NodeTypeCode:%X\n",pMyScb,pMyScb->Header.NodeTypeCode);
      //--------------------------
      NT7CLEANXCB(pMyScb)
      //-------------------------
      if (0x703 == *(PUSHORT)(pMyScb))  {//此SCB代表一个目录
        DbgPrint("\t");
        NT7FuckChildren(pMyScb);
      }
      
        pList = pList->Flink;
    }
    DbgPrint("----------------目录分析完毕----------------\n");  
  return STATUS_SUCCESS;
}
5.特殊说明

Windows7中为了保护系统文件,移动系统文件的话,必须清空FCB->FcbState中的系统文件标志0x100

代码:
NTSTATUS ModifyFcbSystemFileFlag(PVOID pScb,char bRm)
{
  PFCB pFcb = NULL;
  PULONG pLg = NULL;

  pFcb = (PFCB)(*(PULONG)((PCHAR)pScb + 0x50));
  if (!pFcb){
    DbgPrint("修改系统属性时,FCB获取失败\n");
    return;
  }
  pLg = (PULONG)((PUCHAR) pFcb + 4);

  if (bRm){
    DbgPrint("去除系统文件属性\n");
    *pLg = *pLg &(~0x100);}
  else{
    DbgPrint("增加系统文件属性\n");
    *pLg |=0x100;
  }
  DbgPrint("State:%X\n",*pLg);
  DbgPrint("修改系统属性成功!\n");
}
6.补充

Windows XP SP3中 sizeof(FCB) = 0xC8


注:本帖由看雪论坛志愿者PEstone 重新将DOC整理排版,若和原文有出入,以原作者附件为准*转载请注明来自看雪论坛@PEdiy.com 
上传的附件
文件类型: doc NTFS XCB定位技术.doc (301.0 KB, 316 次下载) [谁下载?]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值