xsay: add support for sselp and xclip; output error message
[grml-scripts.git] / usr_bin / find-hidden-word-text
1 #!/usr/bin/perl -w
2 =head1 NAME
3
4 find-hidden-word-text - find hidden text in MS Word documents
5
6 =head1 SYNOPSIS
7
8 find-hidden-word-text word.doc > hidden.txt
9
10 =head1 DESCRIPTION
11
12 This is a command-line UNIX tool to ease the task of discovering hidden text
13 in MS Word documents. 
14
15 More specifically, it is an implementation of Method 2 from Simon Byers'
16 paper, _Scalable Exploitation of, and Responses to Information Leakage
17 Through Hidden Data in Published Documents_, at
18 <URL:http://www.user-agent.org/word_docs.pdf>.
19
20 This goes a little further in that it removes some common 'noise' strings,
21 like 'Word.Document.8', 'Title', 'PAGE', 'Microsoft Word Document' and
22 the like.  It will also remove any strings that do not contain at least
23 1 whitespace character.
24
25 =head1 PREREQUISITES
26
27 This tool requires antiword be installed.
28
29 =head1 AUTHOR
30
31 Justin Mason, C<jm dash wordtext at jmason dot org>
32
33 =head1 VERSION
34
35 1.0 Aug 15 2003 jm
36
37 =cut
38
39 my $print_names = 0;
40 if (scalar @ARGV > 1) { $print_names = 1; }
41
42 foreach my $file (@ARGV) {
43   if ($print_names) {
44     print "\n$file\n\n";
45   }
46
47   open (IN, "antiword -t $file |") or die "cannot run antiword";
48   my $aw = join ('', <IN>);
49   close IN or die "cannot run antiword -t $file";
50
51   open (IN, "strings $file |") or die "cannot run strings";
52   my $str = join ('', <IN>);
53   close IN;
54
55   # normalize the antiword version
56   $aw =~ s/\s+/ /gs;
57
58   # get each string from strings, and see if we can find it in the "visible"
59   # text from antiword
60   my %count = ();
61   foreach (split (/\n/, $str)) {
62     s/\s+/ /g; s/^ //gs; s/ $//gs;
63     next if ($aw =~ /\Q$_\E/);
64
65     # killfile.
66     # skip almost-entirely non-alpha 4-byte snippets
67     #next if /^(?:\W\w\W\W|\W\W\w\W|\w\W{3,3}|\W{4,4}|\W{3,3}\w)$/;
68
69     next if (!/ /);     # no spaces!
70
71     # skip 4-to-6-byte snippets with 1 nonalpha and no spaces
72     #next if (/^\S{4,6}$/ && /\W/);
73
74     # common word droppings
75     next if /^\s*PAGE\s*$/;
76     #next if /^Word.Document.\d$/;
77     next if /^Microsoft Word 9.0$/;
78     next if /^Microsoft Word Document$/;
79     #next if /^Normal$/;
80     #next if /^Title$/;
81     #next if /^MSWordDoc$/;
82     next if /^Click to edit Master text styles$/;
83     next if /^Click to edit Master title style$/;
84     next if /^Embedded OLE Servers$/;
85
86     $count{$_}++;
87   }
88
89 # output the strings and their counts
90   foreach (sort keys %count) {
91     my $cnt = $count{$_};
92     print "$cnt|$_\n";
93   }
94 }