taiji78
驱动牛犊
驱动牛犊
  • 注册日期2009-12-08
  • 最后登录2012-08-16
  • 粉丝0
  • 关注0
  • 积分32分
  • 威望261点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:4113回复:12

一份编译通过的可以针对word透明加密的驱动源代码,里边还有一些问题,向高手求助

楼主#
更多 发布于:2009-12-08 12:37
一份编译通过的可以针对word透明加密的驱动源代码,是从楚狂人的代码例子中改的,里边还有一些问题,向高手求助

已经克服了重命名问题,现在这一份终于可以用word新建文件了,但是打开时出错,希望高手帮忙解决一下。

我还有以前的几份,其中一份已经实现把任意文件复制到d:\test目录下后就加密,然后用指定程序打开后就解密,但是word新建文件保存时就会word进程出错,等着整理一下也发上来。

这份代码,其中一个关键代码是在这里:
cfIrpCreatePre
{
…………
 // 得到了路径,打开这个文件。
        file_h = cfCreateFileAccordingIrp(
            next_dev,
            &path,
            irpsp,
            &status,
            &my_file,
            &information);
// 如果没有成功的打开,那么说明这个请求可以结束了
        if(!NT_SUCCESS(status))
        {
            /////////////ret = SF_IRP_COMPLETED;楚狂人原来是这样写的,结果rename前系统中会先出现一个Create新文件名的操作,应该是先查询一下啦,这里还是要放过的,否则会失败的。我跟踪调试了好一阵子才找出来的。
            ret = SF_IRP_PASS;////////////现在我这样写,嘿嘿,可以重命名啦!
            break;
        }
}

整个cfIrpCreatePre都列出来吧。


// 打开预处理。
ULONG cfIrpCreatePre(
    PIRP irp,
    PIO_STACK_LOCATION irpsp,
    PFILE_OBJECT file,
    PDEVICE_OBJECT next_dev)
{
    UNICODE_STRING path = { 0 };
    // 首先获得要打开文件的路径。
    ULONG length = cfFileFullPathPreCreate(file,&path);
    NTSTATUS status;
    ULONG ret = SF_IRP_PASS;
    PFILE_OBJECT my_file = NULL;
    HANDLE file_h;
    ULONG information = 0;
    LARGE_INTEGER file_size,offset = { 0 };
    BOOLEAN dir,sec_file;
    // 获得打开访问期望。
    ULONG desired_access = irpsp->Parameters.Create.SecurityContext->DesiredAccess;
    WCHAR header_flags[4] = {L'C',L'F',L'H',L'D'};
    WCHAR header_buf[4] = { 0 };
    ULONG disp;

    // 无法得到路径,直接放过即可。
    if(length == 0)
        return SF_IRP_PASS;

    // 如果只是想打开目录的话,直接放过
    if(irpsp->Parameters.Create.Options & FILE_DIRECTORY_FILE)
        return SF_IRP_PASS;

    do {

        // 给path分配缓冲区
        path.Buffer = ExAllocatePoolWithTag(NonPagedPool,length+4,CF_MEM_TAG);
        path.Length = 0;
        path.MaximumLength = (USHORT)length + 4;
        if(path.Buffer == NULL)
        {
            // 内存不够,这个请求直接挂掉
            status = STATUS_INSUFFICIENT_RESOURCES;
            ret = SF_IRP_COMPLETED;
            break;
        }
        length = cfFileFullPathPreCreate(file,&path);

        if(!ustr_startwith(&path,L"\\Device\\HarddiskVolume2\\test"))
            //break;
        {
            if(path.Buffer != NULL)
                {    ExFreePool(path.Buffer);  path.Buffer =NULL;}
            return ret;
        }
        if(ustr_havechar(&path,L':'))
        {
            return ret;
        }

        // 得到了路径,打开这个文件。
        file_h = cfCreateFileAccordingIrp(
            next_dev,
            &path,
            irpsp,
            &status,
            &my_file,
            &information);

        // 如果没有成功的打开,那么说明这个请求可以结束了
        if(!NT_SUCCESS(status))
        {
            //ret = SF_IRP_COMPLETED;
            ret = SF_IRP_PASS;
            break;
        }

        // 得到了my_file之后,首先判断这个文件是不是已经在
        // 加密的文件之中。如果在,直接返回passthru即可
        cfListLock();
        sec_file = cfIsFileCrypting(my_file);
        cfListUnlock();
        if(sec_file)
        {
            ret = SF_IRP_PASS;
            break;
        }

        // 现在虽然打开,但是这依然可能是一个目录。在这里
        // 判断一下。同时也可以得到文件的大小。
        status = cfFileGetStandInfo(
            next_dev,
            my_file,
            NULL,
            &file_size,
            &dir);

        // 查询失败。禁止打开。
        if(!NT_SUCCESS(status))
        {
            ret = SF_IRP_COMPLETED;
            break;
        }

        // 如果这是一个目录,那么不管它了。
        if(dir)
        {
            ret = SF_IRP_PASS;
            break;
        }

        // 如果文件大小为0,且有写入或者追加数据的意图,
        // 就应该加密文件。应该在这里写入文件头。这也是唯
        // 一需要写入文件头的地方。
        if(file_size.QuadPart == 0 &&
            (desired_access &
                (FILE_WRITE_DATA|
                FILE_APPEND_DATA)))
        {
            // 不管是否成功。一定要写入头。
            DbgPrint("cfWriteAHeader \n");
            cfWriteAHeader(my_file,next_dev);
            // 写入头之后,这个文件属于必须加密的文件
            ret = SF_IRP_GO_ON;
            break;
        }

        // 这个文件有大小,而且大小小于头长度。不需要加密。
        if(file_size.QuadPart < CF_FILE_HEADER_SIZE)
        {
            ret = SF_IRP_PASS;
            break;
        }

        // 现在读取文件。比较来看是否需要加密,直接读个8字
        // 节就足够了。这个文件有大小,而且比CF_FILE_HEADER_SIZE
        // 长。此时读出前8个字节,判断是否要加密。
        length = 8;
        status = cfFileReadWrite(next_dev,my_file,&offset,&length,header_buf,TRUE);
        if(status != STATUS_SUCCESS)
        {
            // 如果失败了就不加密了。
            ASSERT(FALSE);
            ret = SF_IRP_PASS;
            break;
        }
        // 读取到内容,比较和加密标志是一致的,加密。
        if(RtlCompareMemory(header_flags,header_buf,8) == 8)
        {
            // 到这里认为是必须加密的。这种情况下,必须返回GO_ON.
            ret = SF_IRP_GO_ON;
            break;
        }

        // 其他的情况都是不需要加密的。
        ret = SF_IRP_PASS;
    } while(0);

    if(path.Buffer != NULL)
        ExFreePool(path.Buffer);    
    if(file_h != NULL)
        ZwClose(file_h);
    if(ret == SF_IRP_GO_ON)
    {
        // 要加密的,这里清一下缓冲。避免文件头出现在缓冲里。
        cfFileCacheClear(my_file);
    }
    if(my_file != NULL)
        ObDereferenceObject(my_file);

    // 如果要返回完成,则必须把这个请求完成。这一般都是
    // 以错误作为结局的。
    if(ret == SF_IRP_COMPLETED)
    {
        irp->IoStatus.Status = status;
        irp->IoStatus.Information = information;
        IoCompleteRequest(irp, IO_NO_INCREMENT);
    }

    // 要注意:
    // 1.文件的CREATE改为OPEN.
    // 2.文件的OVERWRITE去掉。不管是不是要加密的文件,
    // 都必须这样做。否则的话,本来是试图生成文件的,
    // 结果发现文件已经存在了。本来试图覆盖文件的,再
    // 覆盖一次会去掉加密头。
    disp = FILE_OPEN;
    irpsp->Parameters.Create.Options &= 0x00ffffff;
    irpsp->Parameters.Create.Options |= (disp << 24);
    return ret;
}
附件名称/大小 下载次数 最后更新
mycrypt.rar (61KB)  194 2009-12-08 12:37
taiji78
驱动牛犊
驱动牛犊
  • 注册日期2009-12-08
  • 最后登录2012-08-16
  • 粉丝0
  • 关注0
  • 积分32分
  • 威望261点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2009-12-08 12:41
关于测试时的一些说明:

1。在这里可以很简单的添加加密进程。
BOOLEAN cfIsCurProcSec(void)
{
    WCHAR name_buf[32] = { 0 };
    UNICODE_STRING proc_name = { 0 };
    UNICODE_STRING note_pad = { 0 };
    ULONG length;
    RtlInitEmptyUnicodeString(&proc_name,name_buf,32*sizeof(WCHAR));
    length = cfCurProcName(&proc_name);
    //RtlInitUnicodeString(&note_pad,L"notepad.exe");
    /*RtlInitUnicodeString(&note_pad,L"wordpad.exe");
    if(RtlCompareUnicodeString(&note_pad,&proc_name,TRUE) == 0)
        return TRUE;*/
#define HHH(a) RtlInitUnicodeString(&note_pad,a);   if(RtlCompareUnicodeString(&note_pad,&proc_name,TRUE) == 0) return TRUE;
    HHH(L"mspaint.exe");
    HHH(L"wordpad.exe");
    HHH(L"notepad.exe");
    HHH(L"WINWORD.EXE");

    return FALSE;
}

2。cfIrpCreatePre中
if(!ustr_startwith(&path,L"\\Device\\HarddiskVolume2\\test"))
这里可以设置对某个盘某个目录加密。

否则word打开任意文件时都加密可不行了。
JeTus
驱动牛犊
驱动牛犊
  • 注册日期2007-09-22
  • 最后登录2010-01-17
  • 粉丝3
  • 关注0
  • 积分84分
  • 威望781点
  • 贡献值1点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2009-12-08 12:48
楚狂人的那个代码,对word文档进行透明,还要动大手术,拿来学习还可以……
taiji78
驱动牛犊
驱动牛犊
  • 注册日期2009-12-08
  • 最后登录2012-08-16
  • 粉丝0
  • 关注0
  • 积分32分
  • 威望261点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2009-12-08 13:24
是呀,太多的改动需要进行了,我是正在做.

JeTus 是不是已经做成功了?
taiji78
驱动牛犊
驱动牛犊
  • 注册日期2009-12-08
  • 最后登录2012-08-16
  • 粉丝0
  • 关注0
  • 积分32分
  • 威望261点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2009-12-09 10:51
不过,不是大手术,框架骨架都有了,就是一些细节问题啦.
shenhui
驱动小牛
驱动小牛
  • 注册日期2006-05-11
  • 最后登录2023-02-10
  • 粉丝14
  • 关注11
  • 积分142分
  • 威望1314点
  • 贡献值1点
  • 好评度146点
  • 原创分0分
  • 专家分1分
  • 社区居民
5楼#
发布于:2009-12-09 12:20
呵呵,估计问题才刚刚开始。 打不开可能是文件长度处理不对,或者解密不对。
作一名真实,诚实,优秀的科技工作者!
feng_zhibing
驱动牛犊
驱动牛犊
  • 注册日期2009-12-11
  • 最后登录2009-12-23
  • 粉丝0
  • 关注0
  • 积分20分
  • 威望191点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2009-12-11 13:43
再看了楚狂人的文件透明加密以后,我现在也在做关于word透明加密的研究。有时间一起探讨探讨.QQ;563289754
taiji78
驱动牛犊
驱动牛犊
  • 注册日期2009-12-08
  • 最后登录2012-08-16
  • 粉丝0
  • 关注0
  • 积分32分
  • 威望261点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2009-12-15 15:20
upup
bjzlb
驱动牛犊
驱动牛犊
  • 注册日期2010-01-25
  • 最后登录2010-02-23
  • 粉丝0
  • 关注0
  • 积分7分
  • 威望71点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2010-02-11 15:45
打开时出错问题怎么解决呀?
x1234521
驱动牛犊
驱动牛犊
  • 注册日期2008-10-26
  • 最后登录2010-03-18
  • 粉丝0
  • 关注0
  • 积分3分
  • 威望31点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2010-03-18 14:48
楼主,你的代码里缺少文件啊?

FileSecretHeader.c
FileSecretHeader.h

fat_headers整个目录都没有?

不知道能否给个完整的,我也刚开始学透明,woshixiaomao001@163.com

先谢谢了~
zhang572
驱动牛犊
驱动牛犊
  • 注册日期2009-03-02
  • 最后登录2010-08-07
  • 粉丝2
  • 关注2
  • 积分56分
  • 威望411点
  • 贡献值1点
  • 好评度0点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2010-04-20 20:38
楼主的问题解决了吗?  给个联系方式 探讨一下吧
zhang572
驱动牛犊
驱动牛犊
  • 注册日期2009-03-02
  • 最后登录2010-08-07
  • 粉丝2
  • 关注2
  • 积分56分
  • 威望411点
  • 贡献值1点
  • 好评度0点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2010-04-20 21:40
楼主你的测试代码也看不到加密呀。test目录中文件不能被普通进程打开,又不能考到别的地方,怎么看到文件是否加密呢?  
xiaoguangzaia
驱动牛犊
驱动牛犊
  • 注册日期2010-08-12
  • 最后登录2012-03-17
  • 粉丝2
  • 关注0
  • 积分33分
  • 威望291点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2010-09-21 09:06
楼主的问题不知道解决了没有,你那个重命名简单的那样改是不行的,后面对office文件编辑时那里确实需要设为complete
还有就是,新建word打不开应该是文件长度设定不对,在write里你可以看一下获得的文件长度是不是比实际的小
不知道楼主其他问题都解决没,我最近在做也遇到一些问题,希望可以探讨一下
游客

返回顶部