首页
社区
课程
招聘
[求助]关于微软公布的office二进制文档格式
发表于: 2008-9-5 21:10 32473

[求助]关于微软公布的office二进制文档格式

2008-9-5 21:10
32473
收藏
免费 7
支持
分享
最新回复 (76)
雪    币: 215
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
51
应该有关系的吧。
在服务器有个对照表,存放了所有的从客户端发回来的数据A与服务器返回给客户端的数据B的对照关系。只有这样,服务器才不用即时运算,而只是匹配数据A,得出数据B并返回给客户端就行了。
这个对照表有2的40次方条记录,也就是大概一千亿条记录。
2008-10-25 11:16
0
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
52
明白你的意思了。

从本地传给网站的数据中有5个字节(40比特),它不在那48字节的随机数之内。
从服务器传回本地有40比特的密钥。
你所说的A与B分别是上面的50比特,它们之间就是按照word/excel的加密机制建立的函数关系,你还没有弄明白啊?
2008-10-25 11:27
0
雪    币: 732
活跃值: (192)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
53
[QUOTE=lzype;123456]用抓包工具IRIS 4.07.1发现数据传输中与文档相关的内容为:
发送 engine_data 242个字符(应是121字节16进制数)
接收 key 20 个字符 (应是10字节16进制数,用于解密)

[/QUOTE]

说的是这个东东?
http://bbs.pediy.com/showthread.php?p=369640&highlight=word#post369640
2008-10-25 14:15
0
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
54
是的,我们在讨论联网破译的问题。论坛上曾经有人提到过,也给出了部分研究结果,但没有最终完成。

应该说到现在,问题基本都搞清楚了。
2008-10-25 16:58
0
雪    币: 215
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
55
必须在word文件中找到一段固定的5字节或全0处”,这5个字节怎么找?
2008-10-29 16:24
0
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
56
固定的5字节或全0的位置是在未加密之前来看的,你用UltraEdit打开几个没有加密的Word文档,放眼瞧去,这样的地方多得要死啊。

不过以我的观点来看,Word文件偏移0x400开始的8个字节固定为0x00,即可利用之。

但是,那几个网站不是利用的这个位置。
2008-10-29 20:57
0
雪    币: 215
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
57
哦,明白了。谢谢。

那么对照表的生成是不是这样。

//这是rc4加密算法
void rc4(unsigned char *buffer_ptr, int buffer_len, rc4_key *key)
{
  unsigned char t;
  unsigned char x;
  unsigned char y;
  unsigned char* state;
  unsigned char xorIndex;
  short counter;

  x = key->x;
  y = key->y;
  state = &key->state[0];
  for(counter = 0; counter < buffer_len; counter++)
  {
    x = (x + 1) % 256;
    y = (state[x] + y) % 256;
    swap_byte(&state[x], &state[y]);
    xorIndex = (state[x] + state[y]) % 256;
    buffer_ptr[counter] ^= state[xorIndex];
  }
  key->x = x;
  key->y = y;
}

其中:
buffer_ptr:从服务器传回本地有40比特的密钥(范围是0x00 0x00 0x00 0x00 0x00-0xff 0xff 0xff 0xff 0xff)
key:从本地传给网站的数据中有5个字节(40比特)
buffer_len:值总是5

然后做一个2^40个循环(输入buffer_ptr,根据buffer_len来生成key)生成rc4的密钥。是这样吗?
2008-10-29 21:46
0
雪    币: 215
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
58
“但是,那几个网站不是利用的这个位置”那是利用哪个位置呢?
2008-10-29 23:17
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
59
大都看不懂              .
2008-10-30 13:58
0
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
60
To xiaoxinxx:
我认为你提供的rc4算法不完整,缺少了一个阶段。
如果你没意见的话,我可以简单表述一下rc4,并提供我在多个课题中使用过的rc4算法(肯定运算正确)。

如果学术化一点来说的话,rc4加密过程分为两个阶段,第一阶段是密钥调度阶段,将n字节的密钥搅乱成256字节的状态表(最典型的情况是这样);第二阶段是伪随机数(亦称密钥流)生产阶段,即以256字节的状态表为基础,不断交换输出1字节伪随机数(直至满足加密长度的需要)。
2008-10-30 21:36
0
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
61
我改造的rc4算法供参考:

/* rc4.h */
/*
   This source code of RC4 algorithm is rewritten by Jeff Chen.
*/

#ifndef HEADER_RC4_H
#define HEADER_RC4_H

#ifdef  __cplusplus
extern "C" {
#endif

typedef unsigned int UINT4;
typedef unsigned char UCHAR;

/* internal structure used by RC4_KSA & RC4_PRGA */
typedef struct rc4_state
{
        UCHAR S[256];
        UCHAR i;
        UCHAR j;
} RC4_STATE;

void  RC4_KSA(UCHAR *rc4key, int KL, RC4_STATE *state);
void  RC4_KSA_128(UCHAR *rc4key, RC4_STATE *state);
UCHAR RC4_PRGA(RC4_STATE *state);
void  RC4(UCHAR *rc4key, int keylen, UCHAR *keystream, int kslen);

#ifdef  __cplusplus
}
#endif

#endif /* HEADER_RC4_H */
2008-10-30 21:37
0
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
62
/* rc4.c */
/*
*  This source code of RC4 algorithm is rewritten by Jeff Chen.
*/

#include "rc4.h"

/*
* This source code of RC4 algorithm is rewritten by Jeff Chen.
*/

/* 密钥长度为KL字节 */
void RC4_KSA(UCHAR *rc4key, int KL, RC4_STATE *state)
{
        /*
         * 注意: i不能定义为UCHAR, 否则
         * for (i = 0; i < 256; i++)是死循环
         */
        int i;
        UCHAR j, tmp;
        UCHAR *s = state->S;
       
        /* Initialization */
        state->i = 0;  state->j = 0;
        for (i = 0; i < 256; i++)        s[i] = i;

        /* Scrambling */
        j = 0;
        for (i = 0; i < 256; i++)
        {
                j += s[i] + rc4key[i % KL];        // 自动丢弃j的高字节部分
                tmp = s[i];  s[i] = s[j];  s[j] = tmp;
        }
}

/* 密钥长度固定为16字节 */
void RC4_KSA_128(UCHAR *rc4key, RC4_STATE *state)
{
        /*
         * 注意: i不能定义为UCHAR, 否则
         * for (i = 0; i < 256; i++)是死循环
         */
        int i;
        UCHAR j, tmp;
        UCHAR *s = state->S;
       
        /* Initialization */
        state->i = 0;  state->j = 0;
        for (i = 0; i < 256; i++)        s[i] = i;

        /* Scrambling */
        j = 0;
        for (i = 0; i < 256; i++)
        {
                j += s[i] + rc4key[i & 0x0f];        // 自动丢弃j的高字节部分
                tmp = s[i];  s[i] = s[j];  s[j] = tmp;
        }
}

/* output one byte of keystream */
UCHAR RC4_PRGA(RC4_STATE *state)
{
        UCHAR *s, *i, *j, tmp;

        s = state->S;
        i = &(state->i);
        j = &(state->j);

        ++*i;
        *j += s[*i];

        tmp = s[*i];  s[*i] = s[*j];  s[*j] = tmp;

        return s[(s[*i] + s[*j]) & 0xff];        // 注意: 必须加上 "& 0xff"
}

/*
   Combine the two stage of rc4 algorithm.
   output kslen bytes of keystream.
   here keylen is the byte length of rc4 key.
*/
void RC4(UCHAR *rc4key, int keylen, UCHAR *keystream, int kslen)
{
        int n;
        RC4_STATE state;

        if (keylen == 16)        RC4_KSA_128(rc4key, &state);
        else                        RC4_KSA(rc4key, keylen, &state);
       
        for (n = 0; n < kslen; n++)
                keystream[n] = RC4_PRGA(&state);
}
2008-10-30 21:37
0
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
63
现在再来回答你的问题。

word加密。你已基本知道Word的加密过程。给定40比特(5字节)密钥 key 后,经由md5得到128字节的rc4密钥,再通过rc4加密算法(注:包括两个阶段)生产出5字节的伪随机数 ks (密钥流)。

这样就定义出了一个函数关系f,即 5字节key(输入)  映射到  5字节ks(输出)。
按照全查表方式,如果我们事先计算好全部(2^40)个输入的输出结果,这样知道5字节的伪随机数(f的输出),只需一个查表操作就可知f的输入,计算时间为O(1)。

但是全查表方式需要O(2^40)的外存空间,有点大了。所以有人想出了彩虹链时空折衷方式,大大降低了存储空间,但是也增加了计算时间(不过相较于O(2^40)量级,还是要快得多)。这里你读过相关文章,应该了解了。

这样一来,要想快速破解Word密报,问题就归结为如何得到比如5字节的 f 函数的输出,所以进一步追问到Word密报中的固定底码,由它可以立即得到 f 函数的部分输出,通过全查表或者彩虹链查表即可快速得到 f 函数的输入,即5字节密钥。 有了5字节密钥,解密即可瞬间完成。

不知我说清楚了没有?
2008-10-30 21:55
0
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
64
word固定底码的位置问题,只需自己用UE或WinHEX之类的观察几个Word文件就可定出来,不存在啥问题。

那几个网站使用的固定位置在哪里呢?这个需要你去动手调试他们提供的客户端软件,容易搞清楚,我这里就不说了。
2008-10-30 22:00
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
65
学习,不错啊
2008-10-30 22:09
0
雪    币: 215
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
66
谢谢jeffcjh!说得非常清楚,都明白了。
2008-10-30 22:11
0
雪    币: 215
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
67
"给定40比特(5字节)密钥 key 后,经由md5得到128字节的rc4密钥,再通过rc4加密算法(注:包括两个阶段)生产出5字节的伪随机数 ks (密钥流)。这样就定义出了一个函数关系f,即 5字节key(输入)  映射到  5字节ks(输出)。"

这样的话,5字节key(输入)映射到5字节ks(输出)会不会有碰撞?如果有碰撞的话,怎样解决呢?
2008-10-31 15:16
0
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
68
提得有道理!

的确可能发生碰撞,因为这个函数一般并不是一一映射(双射),所以根据某个输出来查表可能会得到若干个输入。此时如果区分呢?当然有办法,因为Word/Excel中本身就设置了密钥验证条件。还记得那3个16字节的随机数吗?快速破译到目前为止,它们还没有派上用场呢,自然有其用处,即用求得的输入(5字节)派生出rc4密钥来解密第2个16字节和第3个16字节,再对解密结果进行判断,若md5(第2个16字节) == md5(第3个16字节)成立,则该输入正确,否则尝试其他输入。这就是区分方法。

上述分析涉及到的具体细节可以参考最早给你阅读的看雪帖子,里面对3个16字节随机数的作用说得非常清楚了。
2008-10-31 20:29
0
雪    币: 215
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
69
1、意思是说全查表中的5字节key(输入)A映射到5字节ks(输出)B的关系中,B发生碰撞是正常的,可以返回多个A值给客户端,然后客户端先验证A 值是否正确,如果正确则解密文件内容。是这样吗?
2、A值的范围是不是从0X00 0X00 0X00 0X00 0X00--0XFF 0XFF 0XFF 0XFF 0XFF,循环这个范围的A值,然后产生5字节ks(输出)B的全查表?
3、由于全查表有2^40条记录,大概是1兆条,如果全部放到某个文件或者放到数据库中都不合适,所以我想采用下面这种方法:
   a、把这1兆条记录按照5字节ks(输出)B的区间范围分别存放到100万个文件中(此文件为txt文件压缩成rar文件,如果不压缩,那么1兆条记录所占用的磁盘空间大概是10T左右,压缩后占用的磁盘空间缩小为原来的近1/40);
   b、把这100万个文件的信息(包括文路径和文件名,以及文件中100万条记录的5字节ks(输出)B的区间范围等信息)都存放到数据库某个表中(称为C表);
   c、服务器接收客户端传递回来的5字节ks(输出)B,就查询C表,然后确认此5字节ks(输出)B对应的A所在的文件名和路径(如果做好了B数据的索引,那么查询速度应该是很快的,大概在1秒左右就可以查询出);
   d、有了路径和文件名,直接解压并打开此文件,查询此文件中的100万条记录(时间大概是几秒)。
    由于我需要的是首先考虑查询速度,其次才是占用的磁盘空间,所以采用此方法,而不采用彩虹链时空折衷方式,此方法有个不好的地方,就是前期要做大量的准备工作,比如对1兆条记录中的5字节ks(输出)B进行排序等。对于此方法,您能不能给点建议和意见?或者有没有其它更加好的方法。再次感谢!
2008-10-31 21:20
0
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
70
1、区分碰撞的工作是网站服务器来做的,所以客户端在提交Doc文件时,会将48字节的随机数发给服务器;
2、f函数的输入(A值)的范围是从0X00 0X00 0X00 0X00 0X00--0XFF 0XFF 0XFF 0XFF 0XFF;
3、记录数2^40不是1兆,而是1024G(即1T)。关于具体实施方法,你已经提出来了,大概差不多,我的意见是:

1)按照(f的输出)B将输入A分类,若存放到100万(2^20)个文件中,那每个文件存有2^20条记录。文件个数是否太多了? 我建议存放到2^16个文件中,每个文件存有2^24条记录比较合适。而每个文件不需以TXT方式保存数据,而是5字节5字节的写入。如果想节省空间,我倒认为可以将文件中的2^24个5字节作一下差分(即相临5字节相减),这样5字节减差的最高2字节绝大多数是0x00(原因你自己思考),不需保存,只需保存3字节;遇到极少数最高2字节不为0x00的,特别处理一下。综合考虑,可以自己设计一个数据结构来保存每个文件的差分序列,使解密时可以还原成原序列,应该不困难;

2)后面你提到的查询计算没啥问题。的确,前期是要做大量的准备工作,但这种工作只做一次,以后就再也不需要了,还是划得来的。
2008-11-1 00:38
0
雪    币: 215
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
71
1、2^40算出的结果是1099511627776,也就是大概1兆条记录啊。
2、“我建议存放到2^16个文件中,每个文件存有2^24条记录比较合适”-- 好的。
3、“而每个文件不需以TXT方式保存数据,而是5字节5字节的写入”--意思是没有文件类型,而只是有文件名?这样有什么好处呢?而5字节5字节的写入,是不是这种方式:
    A                          B
      000102030405    050403020100
      A1B2C3D4E5F6    F6E5D4C3B2A1
      ......
      ......   
4、“如果想节省空间,我倒认为可以将文件中的2^24个5字节作一下差分(即相临5字节相减),这样5字节减差的最高2字节绝大多数是0x00(原因你自己思考),不需保存,只需保存3字节;遇到极少数最高2字节不为0x00的,特别处理一下。”--文件还有没有压缩的必要呢?因为如果压缩的话,所占用的磁盘空间大大缩小了,而如果机器性能好的话,查询速度应该不会有多大的影响吧。
5、由于要对2^40条记录的字节ks(输出)B进行排序,所以事先要做好准备工作,这个准备工作有两种方法:
  a、在完成全查表的生成之后再做进行排序;这样做的好处就是生成全查表的速度快,但是后面的工作就很麻烦了;
  b、在生成全查表的过程中就开始做。比如事先约定好某条记录按照字节ks(输出)B的区间范围来确定它所属的文件,生成这条记录时就插入到所属的文件中。这种方法生成全查表的速度慢,但是一旦生成完,那么排序的工作就几乎完成了。
  我打算选择第二中方法,您的建议呢?或者有没有其它更好的方法?
2008-11-1 10:31
0
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
72
1、通常所说的1兆是指2^20,你是否理解有误?
2、文件名信息不需要存入那2^16个纯数据文件中。每个这样的文件平均保存2^24个记录,这里的所谓记录其实就是(f函数的)输入A,每个都是5字节,所以我说是5字节5字节的写入,当然最后可以对每个文件中的2^24个A进行升序排列。  注意:这个文件中的2^24个A(f的输入)对应的是同一个输出B,所以我们将它们纠集在一个文件中,这样根据B查表的时候,只需在这个文件中进行遍历即可;
3、你所说的对每个文件进行压缩是可以的,具体要看压缩率。我所说的对每个文件的2^24个A(升序排列后)进行差分得到差分序列,序列中的每一项(除第1项外,因为它是原始的)基本上最高三个字节都为0x00(前面说的最高2字节为0x00,有点小错误),这样就只需保存低2字节了。
4、按照前面我说的思路,就不存在“事先就要对2^40个ks(输出)B进行快速排序”这个问题了,因为对2^40条记录已经被摊分到2^16个文件中去了,只需对每个文件中的2^24个A进行排序。当然这个计算有点花时间,不知你能否做得起,一般是要在集群机上才能完成的,单机跑的话时间有点长。
2008-11-1 11:45
0
雪    币: 215
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
73
1、哦。是我理解有误了。在没有压缩和其它任何处理的情况下,产生的全查表大概占多大的磁盘空间呢?
2、因为我还没有生成这个全查表,所以不清楚B记录的关系,按照您说的意思,B记录存在大量的碰撞,也就是说,同一个B值,会有2^24个A值(f的输入)的对应?在2^16个文件中,每个文件中的只需要存放A值就够了,因为这些A值所对应的B值都是一样的?如果这样的话,不会存在根据客户端传回的B值而查询不到A值的情况吧。
3、OK。
4、这样说的话,前期的主要准备工作就不是对B值进行排序,而是把相同的B值划分到同一个文件中了(有什么效率比较高的方法吗)?那么查询速度的瓶颈就在于查询这个有2^24个A的文件上了?

谢谢jeffcjh!如果没有您的帮助,估计我会走很多很多的弯路。而现在节约了非常多的时间!太感谢了!
2008-11-1 12:27
0
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
74
强烈建议LZ重新发一个新贴,因为我们现在讨论的问题与此帖标题“office二进制文件格式”严重不符了。建议以“对office加密的快速破译问题的研究”之类的名字发新贴,我们再讨论之。
2008-11-1 15:53
0
雪    币: 58
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
75
希望楼主在新贴中将你到目前为止的认识简要地按照步骤表述出来,对第一次出现的名词(术语)进行解释,以后就直接引用了。

强烈希望看雪论坛有更多的人能够参与此类讨论和分析。一天到晚谈破解,烦不烦啊。
2008-11-1 15:56
0
游客
登录 | 注册 方可回帖
返回
//