参考地址维基泄密 vault7 Scribbles CIA机密文档追踪工具Scribbles详细分析 
Scribbles,涂鸦,office文档指纹原理,ppt有警告
在word2007上的.docx插入一张图片 解压后 word/document.xml代码如下
1 2 3 <a:blip  r:embed ="rId4"  cstate ="print" /> 改为 <a:blip  r:link ="rId8"  xmlns:r ="http://schemas.openxmlformats.org/officeDocument/2006/relationships" /> 
 
在word/_rels文件夹document.xml.rels中加入指向地址
1 <Relationship  Id ="rId8"  Type ="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"  Target ="http://52spider.com/u/?url=https://i.ytimg.com/vi/NemvyCnUZiM/hqdefault.jpg"  TargetMode ="External" /> 
 
重新zip打包成docx后 打开文档会默认请求地址,无任何提示,excel异同 在excel2007上的.xlsx插入一张图片 解压后 xl/drawingsdocument.xml代码如下
1 2 3 <a:blip  r:embed ="rId4"  cstate ="print" /> 改为 <a:blip  r:link ="rId8"  xmlns:r ="http://schemas.openxmlformats.org/officeDocument/2006/relationships" /> 
 
在xl/drawings/_rels文件夹drawing1.xml.rels中加入指向地址
1 <Relationship  Id ="rId8"  Type ="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"  Target ="http://52spider.com/u/?url=https://i.ytimg.com/vi/NemvyCnUZiM/hqdefault.jpg"  TargetMode ="External" /> 
 
Scribbles水印的参数为 url_Scheme:协议类型,可为HTTP和HTTPS hostServerName:发起请求的域名 hostRootPath:发起请求的域的根路径 hostSubDirs:发起请求的域的子路径 hostFileName:发起请求的文件名 hostFileExtList:发起请求的文件类型后缀 output_Directory:已嵌入水印的文件输出路径 output_WatermarkLog:输出构造水印日志
这个地址可以是文件名、文件备注、发起人、时间做的一个哈希映射地址
图片可以加载文档页眉1像素隐藏
可以在一定程度上防止文件泄露、钓鱼获取目标人ip、阅后即焚文档
以下是请求ua
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; MSOffice 12)
 
分析ua 浏览器名称	IE 浏览器版本号	7.0 渲染引擎	Trident 4.0 操作系统	Windows 7
python实现参考,不保证代码可用,原理就是解压添加,不使用openxml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 import  osfrom  util import  ziperfrom  Scr_xlsx import  Scr_xlsxfrom  Scr_docx import  Scr_docxclass  Scrice ():    url='https://www.baidu.com'      resources='resources'      def  bute (self ):         ext=os.path.splitext(self .name)[1 ]         if  ext == '.xlsx' :             Scr_xlsx(self .url,self .name,self .name1,self .resources)         if  ext == '.docx' :             Scr_docx(self .url,self .name,self .name1,self .resources)     def  build (self,name,name1 ):         self .name=name         self .name1=name1         ziper(name)         self .bute()         ziper(name,name1,False ) if  __name__ == '__main__' :     s=Scrice()     s.url='http://www.eooall.io'      s.build('Book2.xlsx' ,'Book3.xlsx' )      
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 import  os,shutilfrom  util import  copytreefrom  fleader import  fleader as  rqfrom  bs4 import  BeautifulSoupclass  Scr_docx ():    def  __init__ (self,url,name,name1,resources ):         self .url=url         self .name=name         self .name1=name1         self .resources=resources         self .path=os.path.splitext(name)[0 ]         copytree(r'./' +self .resources+'/word/word/drawings' ,self .path+'/word/drawings' )         self .hook_Content_Types_xml()         self .hook_xl_worksheets_sheet1_xml()         self .hook_xl_worksheets__rels_sheet1_xml_rels()         self .hook_xl_drawings__rels_drawing1_xml_rels()     def  hook_Content_Types_xml (self ):         f=self .path+'/[Content_Types].xml'          rt=rq.rw(f)         soup = BeautifulSoup(rt,'xml' )         soup.find('Types' ).append(soup.new_tag("Override" , PartName="/word/drawings/drawing1.xml" ,ContentType="application/vnd.openxmlformats-officedocument.drawing+xml" ))         rq.rw(f,str (soup),aw='w' )     def  hook_xl_worksheets_sheet1_xml (self ):         f=self .path+'/word/document.xml'          rt=rq.rw(f)         soup = BeautifulSoup(rt,'xml' )         s=soup.new_tag("drawing" )         s['r:id' ] = 'rId10'          soup.find('w:document' ).append(s)         rq.rw(f,str (soup),aw='w' )     def  hook_xl_worksheets__rels_sheet1_xml_rels (self ):         f=self .path+'/word/_rels/document.xml.rels'          if  os.path.isfile(f):             rt=rq.rw(f)             soup = BeautifulSoup(rt,'xml' )             soup.find('Relationships' ).append(soup.new_tag("Relationship" ,Id="rId10" ,Type ="http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing" ,Target="../drawings/drawing1.xml" ))             rq.rw(f,str (soup),aw='w' )     def  hook_xl_drawings__rels_drawing1_xml_rels (self ):         f=self .path+'/word/drawings/_rels/drawing1.xml.rels'          rt=rq.rw(f)         soup = BeautifulSoup(rt,'xml' )         soup.find('Relationship' )['Target' ] = self .url         rq.rw(f,str (soup),aw='w' ) 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 import  os,shutilfrom  util import  copytreefrom  fleader import  fleader as  rqfrom  bs4 import  BeautifulSoupclass  Scr_xlsx ():    def  __init__ (self,url,name,name1,resources ):         self .url=url         self .name=name         self .name1=name1         self .resources=resources         self .path=os.path.splitext(name)[0 ]         copytree(r'./' +self .resources+'/excel/xl/drawings' ,self .path+'/xl/drawings' )         self .hook_Content_Types_xml()         self .hook_xl_worksheets_sheet1_xml()         self .hook_xl_worksheets__rels_sheet1_xml_rels()         self .hook_xl_drawings__rels_drawing1_xml_rels()     def  hook_Content_Types_xml (self ):         f=self .path+'/[Content_Types].xml'          rt=rq.rw(f)         soup = BeautifulSoup(rt,'xml' )         soup.find('Types' ).append(soup.new_tag("Override" , PartName="/xl/drawings/drawing1.xml" ,ContentType="application/vnd.openxmlformats-officedocument.drawing+xml" ))         rq.rw(f,str (soup),aw='w' )     def  hook_xl_worksheets_sheet1_xml (self ):         f=self .path+'/xl/worksheets/sheet1.xml'          rt=rq.rw(f)         soup = BeautifulSoup(rt,'xml' )         soup.find('worksheet' ).append(soup.new_tag("drawing" ))         soup.find('drawing' )['r:id' ] = 'rId2'          rq.rw(f,str (soup),aw='w' )     def  hook_xl_worksheets__rels_sheet1_xml_rels (self ):         f=self .path+'/xl/worksheets/_rels/sheet1.xml.rels'          if  not  os.path.isfile(f):             f_rels=self .path+'/xl/worksheets/_rels'              if  not  os.path.isdir(f_rels):                 os.mkdir(f_rels)             shutil.copyfile(r'./' +self .resources+'/excel/xl/worksheets/_rels/sheet1.xml.rels' ,f)         else :             pass      def  hook_xl_drawings__rels_drawing1_xml_rels (self ):         f=self .path+'/xl/drawings/_rels/drawing1.xml.rels'          rt=rq.rw(f)         soup = BeautifulSoup(rt,'xml' )         soup.find('Relationship' )['Target' ] = self .url         rq.rw(f,str (soup),aw='w' ) 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 import  os,shutil,zipfiledef  md5 (*arg ):    import  hashlib        hl = hashlib.md5()     line='' .join(list (map (lambda  x:str (x),arg)))     hl.update(line.encode(encoding='utf-8' ))         return  hl.hexdigest() def  ziper (name,name1='' ,rm=True ,rp=True  ):    if  name1=='' :         rw='r'      else :         rw='w'      if  rw=='r' :         path=os.path.splitext(name)[0 ]         if  os.path.isdir(path):             shutil.rmtree(path)         z = zipfile.ZipFile(name)         path=os.path.splitext(name)[0 ]         z.extractall(path=path)         z.close()     if  rw=='w' :         path=os.path.splitext(name)[0 ]         namemd5=md5(name)         if  os.path.isdir(path):             if  os.path.isdir(namemd5):                 shutil.rmtree(md5(name))             shutil.move(path,namemd5)         z = zipfile.ZipFile(name1,'w' )         for  root, dirs, fs in  os.walk(namemd5):             for  f in  fs:                 if  rp:                     rpath=root.replace(namemd5,'' )                 else :                     rpath=root.replace(namemd5,path)                 pt=os.path.join(root,f)                 pt1=os.path.join(rpath,f)                 z.write(pt,pt1)         z.close()         if  rm:             shutil.rmtree(md5(name))         else :             shutil.move(namemd5,path)  def  copytree (src, dst, symlinks=False  ):    names = os.listdir(src)     if  not  os.path.isdir(dst):         os.makedirs(dst)                errors = []     for  name in  names:         srcname = os.path.join(src, name)         dstname = os.path.join(dst, name)         try :             if  symlinks and  os.path.islink(srcname):                 linkto = os.readlink(srcname)                 os.symlink(linkto, dstname)             elif  os.path.isdir(srcname):                 copytree(srcname, dstname, symlinks)             else :                 if  os.path.isdir(dstname):                     os.rmdir(dstname)                 elif  os.path.isfile(dstname):                     os.remove(dstname)                 shutil.copy2(srcname, dstname)                      except  (IOError, os.error) as  why:             errors.append((srcname, dstname, str (why)))                           except  OSError as  err:             errors.extend(err.args[0 ])