5 # Simple attack at unpacking a bootstrap-image again. A smarter way would
6 # probably be if we'd add some clear marks in the image when generating
15 die "Need to give filename!" unless defined $filename;
17 system("arm-linux-objcopy -j .data -O binary $filename unpack.data");
18 die "objcopy failed" if $?;
20 # make it easy, just hold the file parts in memory
23 open(A, "unpack.data") || die "Cannot open: $!";
30 open(A, $filename) || die "Cannot open: $!";
40 die "find_offset: EINVAL" unless defined $vaddr;
42 foreach my $p (@phdrs) {
43 if ($vaddr > @$p{vaddr} && @$p{vaddr} + @$p{memsize} >= $vaddr) {
44 return $vaddr - @$p{vaddr} + @$p{fileoff};
47 die "find_phdr unsuccessful";
52 unpack("Z*", substr($allfile, find_offset(shift)));
59 substr($allfile, find_offset($vaddr), $len);
62 # parse $filename PHDRs
64 my $o = `objdump -p $filename`;
66 foreach (split / LOAD /, $o) {
67 if (/off\s+0x([a-fA-F0-9]+)\s+vaddr\s+0x([a-fA-F0-9]+)\s+paddr\s+0x[a-fA-F0-9]+\s+align\s+\d\*\*\d+\s*.\s+filesz\s+0x([a-fA-F0-9]+)\s+memsz\s+0x([a-fA-F0-9]+)/m) {
68 print "PHDR: off=$1 vaddr=$2 fsz=$3 msz=$4\n";
69 push @phdrs, { fileoff => hex($1), vaddr => hex($2), filesize => hex($3), memsize => hex($4) };
74 my $filesize = -s "$filename";
80 my $modinfo_size = 24;
81 while ($offset < length($unpackdata) - 12 * 4) {
82 my ($start0, $size0, $sizeun0, $name0, $md5comp0, $md5uncomp0,
83 $start1, $size1, $sizeun1, $name1, $md5comp1, $md5uncomp1,
84 $start2, $size2, $sizeun2, $name2, $md5comp2, $md5uncomp2)
85 = unpack("LLLLLLLLLLLLLLLLLL", substr($unpackdata, $offset));
87 if ((!defined $previous || $previous + $modinfo_size == $offset)
91 && (($start0 & 0xfff) == 0)
92 && (($start1 & 0xfff) == 0)
93 && (($start2 & 0xfff) == 0)
94 && ($size0 < $filesize)
95 && ($size1 < $filesize)
96 && ($size2 < $filesize)
97 && ($sizeun0 < (80 << 20))
98 && ($sizeun1 < (80 << 20))
99 && ($sizeun2 < (80 << 20))) {
101 #printf "%x %x %x\n", $start0, $start1, $start2;
102 printf "Found module info at offset %d/0x%x\n", $offset, $offset;
104 $entries{$offset}{addr} = $start0;
105 $entries{$offset}{size} = $size0;
106 $entries{$offset}{usize} = $sizeun0;
107 $entries{$offset}{name} = $name0;
108 $entries{$offset}{md5comp} = $md5comp0;
109 $entries{$offset}{md5uncomp} = $md5uncomp0;
110 $entries{$offset + 1 * $modinfo_size}{addr} = $start1;
111 $entries{$offset + 1 * $modinfo_size}{size} = $size1;
112 $entries{$offset + 1 * $modinfo_size}{usize} = $sizeun1;
113 $entries{$offset + 1 * $modinfo_size}{name} = $name1;
114 $entries{$offset + 1 * $modinfo_size}{md5comp} = $md5comp1;
115 $entries{$offset + 1 * $modinfo_size}{md5uncomp} = $md5uncomp1;
116 $entries{$offset + 2 * $modinfo_size}{addr} = $start2;
117 $entries{$offset + 2 * $modinfo_size}{size} = $size2;
118 $entries{$offset + 2 * $modinfo_size}{usize} = $sizeun2;
119 $entries{$offset + 2 * $modinfo_size}{name} = $name2;
120 $entries{$offset + 2 * $modinfo_size}{md5comp} = $md5comp2;
121 $entries{$offset + 2 * $modinfo_size}{md5uncomp} = $md5uncomp2;
124 $delta = $modinfo_size;
130 print "Scanning at offset $offset\n" if $offset % 1000 == 0;
133 my $dir = "unpack.dir";
136 open(MODLIST, ">$dir/modules.list")
137 || die "Cannot open $dir/unpack.modules.list: $!";
138 print MODLIST "entry unpacked\n";
139 print MODLIST "modaddr 0x01200000\n";
142 open(M, ">md5sums") || die "Cannot create checksum file: $!";
143 foreach my $e (sort { $a <=> $b } keys %entries)
145 my $name = get_string($entries{$e}{name});
146 my $fname = "$dir/$name";
147 open(A, ">$fname") || die "Cannot create file $fname: $!";
148 print A get_blob($entries{$e}{addr}, $entries{$e}{size});
151 print M get_string($entries{$e}{md5uncomp})." $fname\n";
154 system("file $fname");
158 print MODLIST "kernel $name\n";
160 print MODLIST "sigma0 $name\n";
162 print MODLIST "roottask $name\n";
164 print MODLIST "module $name\n";
173 unlink "unpack.data";
175 system("md5sum -c md5sums");