参考地址维基泄密 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 ])