首页
社区
课程
招聘
[讨论]对office加密文档的快速破译问题的研究
发表于: 2008-11-1 17:27 134048

[讨论]对office加密文档的快速破译问题的研究

2008-11-1 17:27
134048
收藏
免费 7
支持
分享
最新回复 (257)
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
26
我不知道下面的填充是什么意思:
//put block number in byte 6...9
  pwarray[5] := byte(block and $FF);
  pwarray[6] := byte((block shr 8) and $FF);
  pwarray[7] := byte((block shr 16) and $FF);
  pwarray[8] := byte((block shr 24) and $FF);
  pwarray[9] := $80;
  pwarray[56] := $48;
2008-11-10 19:30
0
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
27
为什么有:
pwarray[9] := $80;
pwarray[56] := $48;
这样两个赋值?
2008-11-10 19:31
0
雪    币: 215
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
28
我问的问题:
“因为我还没有生成这个全查表,所以不清楚B5字节key(输入)A  映射到  5字节ks(输出)B的关系,按照您说的意思,5字节ks(输出)B存在大量的碰撞,也就是说,同一个5字节ks(输出)B,会有2^24个key(输入)A 值的对应?在2^16个文件中,每个文件中的只需要存放A值就够了,因为这些A值所对应的B值都是一样的?如果这样的话,不会存在根据客户端传回的B值而查询不到A值的情况吧。”

您的回答:
"你的理解是对的,每个文件中的2^24个A(输入)按照映射关系都对应同一个输出B。根据5字节的B值来查表,对应文件中的2^24个A值都是“嫌疑”对象(可能的密钥),到底哪一个是“真凶”(加密该office文件的正确密钥),验证依据就是48字节随机数中后32字节的md5依赖关系。"

哦。我原来理解为2^24个A(输入)都会输出同一个B值。所以就以为是总共只有2^16个不同的B值,然后每个B值相同的A都放到同一个文件中,所以就有2^16个文件。看来是我理解错了。

如果存放在同一个文件中的A值所对应的B值不一样,那么文件内容应该是同时存放A和B值,而不能只存放A值啊,如果这样的话那么所占用的空间就是10T,而不是5T了啊。
2008-11-10 19:36
0
雪    币: 215
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
29
[QUOTE=jeffcjh;533317]为什么有:
pwarray[9] := $80;
pwarray[56] := $48;
这样两个赋值?[/QUOTE]

这些代码是我从wv-0.7.2里面转过来的。wv-0.7.2的开源代码里面就是这样写的。
2008-11-10 19:44
0
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
30
如果我的理解没错,那pwarray[9] := $80;pwarray[56] := $48;这些填充是肯定没有的。生产ks的16字节密钥纯粹是对byteA[]的9字节(前5字节是输入A,后4字节是块号)的标准MD5。

所以看来主要问题就在这里吧。
2008-11-10 19:50
0
雪    币: 215
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
31
那么我用什么方法来检查我生成的全查表是正确的呢?这个是比较关键的问题了。因为生成全查表要花费大量的时间,我只有确定按照这个公式生成的全查表是正确的,才能继续生成下去,否则如果花费几个月的时间来生成完之后,才发现生成的表是错误的,那就麻烦了。
2008-11-10 19:51
0
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
32
可能还有一些细节以前没有讨论到。
关于结果存储的问题,这样理解:

由输入A计算输出B;

if          B的最低2字节为 0x0000   then  存入文件_0000.bin;
else if  B的最低2字节为 0x0001   then  存入文件_0001.bin;
......
else if  B的最低2字节为 0xfffe      then  存入文件_fffe.bin;
else                                                    存入文件_ffff.bin;

这样结果分类存入到2^16个文件中,每个文件平均大小为 5 * (2^40 / 2^16) = 80 MB,
2^16个文件总大小:(2^16) * 80 MB  = 5 TB。

这些文件产生好了以后,如何使用呢?全查表方法大致为:
1、通过某种途径得到输出B(比如根据密报的固定底码立即得到乱数,即B);
2、根据B的最低2字节(比如说0xabcd) 找到对应文件_abcd.bin;
3、这样输入A必定存在于文件_abcd.bin中;
4、文件_abcd.bin中平均有2^24个A,到底哪一个A才是真正要求的呢?这时需要其它验证条件才能确定了。

由此可见,原来每次破译都要计算一遍2^40个函数关系,现在:
1、事先计算一遍2^40个函数关系;
2、以后破译时按照上述方法全查表,每次只要做2^24个验证即可,效率自然高得多了。
2008-11-10 20:06
0
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
33
你是准备做产品卖钱啊还是怎么的?几个月时间都花得起啊。你可以生产一部分后用实际数据进行测试一下
2008-11-10 20:09
0
雪    币: 215
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
34
关于结果存储的问题,这样理解:

由输入A计算输出B;

if          B的最低2字节为 0x0000   then  存入文件_0000.bin;
else if  B的最低2字节为 0x0001   then  存入文件_0001.bin;
......
else if  B的最低2字节为 0xfffe      then  存入文件_fffe.bin;
else                                                    存入文件_ffff.bin;

这样结果分类存入到2^16个文件中,每个文件平均大小为 5 * (2^40 / 2^16) = 80 MB,
2^16个文件总大小:(2^16) * 80 MB  = 5 TB。

好方法!!!谢谢了!
2008-11-10 20:12
0
雪    币: 215
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
35
不是做产品卖钱,而是领导给我的一个研究项目。

“不过这5字节是密钥流的最初5字节,在具体利用时可能不是这个位置的5字节,那些网站取的位置比较靠后,并且还不是连续的位置(有间隔),这些都是小问题,根据实际需要调用函数4生产足够长度的密钥流,再提取对应位置的数据即可。”

我从文档中取出全零的5个字节(未加密前的)来做测试行不行?具体方法如下:
1、创建一个doc文件,设置密码;
2、通过程序获取到128比特(即16字节)的密钥K[],然后再获取未加密前5个字节为全零的位置(为ks)。
3、再使用全查表生成程序,输入2步骤中获得的128比特(即16字节)的密钥K[](既A值),然后生成B值,如果B值等于2步骤中获取的ks,那么就说明我的全查表生成程序是正确的。

是否是这样?
2008-11-10 20:14
0
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
36
其实我并没有造这个表,需要5TB存储空间,不是小数目。但从数学进行过论证,写过一篇论文涉及到此内容,所以就给你交流了。
2008-11-10 20:18
0
雪    币: 215
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
37
好的,如果我把这个全查表生成出来并通过验证了,就把研究结果写出来。
2008-11-10 20:23
0
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
38
应该没什么问题,到时再看看。
2008-11-10 20:29
0
雪    币: 215
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
39
谢谢jeffcjh!!!有问题再来请教你。
2008-11-10 20:37
0
雪    币: 215
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
40
“不过这5字节是密钥流的最初5字节,在具体利用时可能不是这个位置的5字节,那些网站取的位置比较靠后,并且还不是连续的位置(有间隔),这些都是小问题,根据实际需要调用函数4生产足够长度的密钥流,再提取对应位置的数据即可。”

意思是不是说获取word文档5字节,不是取连续的全零的地方?而是有可能从5个不同的位置取出5个字节?调用函数4生产的密钥流需要大于5字节?
2008-11-10 22:28
0
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
41
是的,这些位置的选取也有讲究的,不一定是密钥流最前面的几个字节,实际上如果
块号取0x000000的话,不能取前5字节。如果块号取0x00000001的话,可以取前5字节,代码类似,具体如下参考:

  unsigned char byteA[9];        // byteA[]的前5字节赋值为输入A
  unsigned char byteB[16];
  unsigned char ks[5];         // 存储生产的密钥流(乱数), 具体长度自己确定

  blockcnt = 1;             // 加密块编号

  // byteA[]的第5至8字节赋值为块编号
  *(unsigned int *)(byteA + 5) = blockcnt;

  // 对9字节(不是64字节)作标准的MD5 !!!
  MD5Data((unsigned char*)byteA, 9, byteB);

  // 以16字节byteB[]做密钥, 根据RC4算法产生5字节乱数
  RC4(byteB, 16, ks, 5);

这时因为从Word文件的0x400偏移处(对应于块号0x00000001)开始的8字节底码固定为
0x00,故可直接得到乱数,从而可以用上查表方法。

看来,你还不能急着造表,还要把相关细节考虑周到,逻辑上没有问题了才能动手。
2008-11-10 23:12
0
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
42
看了LZ发的贴浏览的不少啊,怎么回复提问的很少呢?
2008-11-10 23:20
0
雪    币: 215
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
43
今天查了一天,还是没有匹配成功,生成的全查表还是未能与从文档中取出的B值匹配成功。现在是不知道我生成的全查表的数据不对还是从文档中取的位置不对。

jeffcjh,您能不能给出一个文档中具体的某个您已经检测成功的位置,从文档中某处取第几个字节?(类似您以前指点的“从“2F 00 36 00 01 00 01 00 01 00”之后开始第几个字节。。。”),我只有确认了从文档中取出的位置是正确的,才好检测生成的全查表是否正确。
谢谢了。
2008-11-11 18:59
0
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
44
建议取Word文件偏移量0x400开始的5字节乱数(因为此处底码固定为0x00,所以乱数直接等于密码数据了),这时造表计算密钥时取块号为0x00000001,代码上面已提示,再说一遍也无妨:

unsigned char byteA[9];        // byteA[]的前5字节赋值为输入A
  unsigned char byteB[16];
  unsigned char ks[5];         // 存储生产的密钥流(乱数)

  blockcnt = 1;             // 加密块编号

  // byteA[]的第5至8字节赋值为块编号
  *(unsigned int *)(byteA + 5) = blockcnt;

  // 对9字节(不是64字节)作标准的MD5 !!!
  MD5Data((unsigned char*)byteA, 9, byteB);

  // 以16字节byteB[]做密钥, 根据RC4算法产生5字节乱数
  RC4(byteB, 16, ks, 5);

以后就是根据5字节ks的最后两字节来分类存入2^16个文件中。

实际破译Word密报时:
1、从word密报文件的0x400偏移处连续提取5字节作为乱数(即所讨论的输出B);
2、根据B的最后2字节对应到2^16个文件中的某个文件_xxxx.bin;
3、根据word密报中的3个16字节随机数(实际只需后两个随机数)顺序验证_xxxx.bin中的每个5字节A(最多2^24个),直至找到正确的A。
2008-11-11 22:23
0
雪    币: 215
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
45
1、从word密报文件的0x400偏移处连续提取5字节作为乱数(即所讨论的输出B);

0x400具体是哪个地方?因为我用的是复合文档来看的,你能否给出一个参照的位置,比如类似您以前指点的“从“2F 00 36 00 01 00 01 00 01 00”之后开始第几个字节。。。
2008-11-11 22:34
0
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
46
你用UltraEdit或WinHex之类的软件用二进制方法打开Word文件(HEX显示),最左边那列就是偏移,定位到0x400偏移处即可。用C函数表示,其实也就是 fseek (fp, 0x400, SEEK_SET)  的地方。
2008-11-11 22:49
0
雪    币: 215
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
47
哦。明白了。
00000400h: 4A 17 A1 ED A7 58 B2 90 81 F1 BB D8 59 39 E3 83
然后就取4A 17 A1 ED A7 这5个字节作为B值,对吧。
2008-11-11 22:57
0
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
48
对头。

如果还有什么问题,请注意VB代码与C代码之间的细微差异,比如数组第一个元素下标是从0开始还是从1开始,VB版的MD算法对传入参数的特点,等等,原理已经讨论得很多了,不会存在什么问题了,也许在编程实现上有些理解与编程代码不一致造成失败。
2008-11-12 10:26
0
雪    币: 1072
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
49
用过一个软件,是要求要联网才行,可能是上网查询!!
2008-11-12 12:28
0
雪    币: 215
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
50
不知道是否我的测试方法错误还是测试数据生成有误。

我的测试方法是(之前已经做好一个暴力破解的程序,并且已经测试通过):
1、先创建一个带有密码的word文档,然后使用那个暴力破解程序获取到最初的40位数(也就是我们之前说的A值);
2、获得这40位数的A值之后,使用我的生成全查表的程序生成对应的B值;
3、使用B值来匹配0x400处开始的5字节。

我的测试数据是:
A值:(49 109 90 10 4)
A值经由md5得到128比特的rc4密钥:(132, 61, 19, 190, 219, 197, 118, 199, 98, 145, 239, 167, 153, 193, 166, 55)
然后通过RC4加密得到B值:(200, 16, 14, 194, 233)

您有没有现成的程序,能不能帮我根据A值来测试128比特及B值是否正确?
2008-11-12 16:25
0
游客
登录 | 注册 方可回帖
返回
//