⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dumpxip.pl

📁 wince 内核dump程序
💻 PL
📖 第 1 页 / 共 3 页
字号:
                "v%07lx r%07lx %smodule data %s", $o32ent->{rva}, $o32ent->{realaddr}, ($o32ent->{flags}&0x2000)?"compressed ":"", $desc) if ($o32ent->{dataptr});        }    }}sub GetUniqueFilename {    my ($dir, $filename)= @_;    my $fn= "$dir/$filename";    my $i= 1;    while (-e $fn) {        $fn= sprintf("%s/%s-%d", $dir, $filename, $i++);    }    return $fn;}sub GetUncompressedData {    my ($rom, $ofs, $size, $fullsize, $compressed)= @_;    return "" if ($size==0);    my $data= $rom->GetVData($ofs, $size);    if ($compressed) {        if ($g_use_wince3_compression && $size==$fullsize) {            # BUG in wince3  ... often compress flag is set, while data is not compressed.            return $data;        }        #printf("decompress %08lx:%08lx %08lx -> %08lx : %s\n", $ofs, $size, length($data), $fullsize, unpack("H*", $data));        # .. append some extra data, so the (buggy) dll can read beyond the end of its input buffer.require XdaDevelopers::CompressUtils;        my $decomp= $g_use_wince3_compression                ? XdaDevelopers::CompressUtils::rom3uncompress($data.("\x00" x 16), $fullsize)                : XdaDevelopers::CompressUtils::rom4uncompress($data.("\x00" x 16), $fullsize);        if (!defined $decomp) {            #printf(".. error\n");            return undef;        }        #printf(".. ok\n");        return $decomp;    }    return $data;}sub IMAGE_SCN_COMPRESSED { 0x2000; }sub FILE_ATTRIBUTE_COMPRESSED{ 0x0800; }sub SaveFile {    my $self= shift;    my $rom= $self->{rom};    my $file= shift;    my $savedir= shift;    my $data= GetUncompressedData($rom, $file->{ulLoadOffset}, $file->{nCompFileSize}, $file->{nRealFileSize}, $file->{dwFileAttributes}&FILE_ATTRIBUTE_COMPRESSED);    if (!defined $data) {        printf("ERROR decompressing file (%d -> %d) '%s'\n", $file->{nCompFileSize}, $file->{nRealFileSize}, $file->{filename});        return;    }    my $filename= GetUniqueFilename($savedir, $file->{filename});    my $fh= IO::File->new($filename, "w+") or die "$filename: $!\n";    binmode $fh;    $fh->print($data);    $fh->close();}sub SaveModule {    my ($self, $module, $savedir)= @_;    my $exe= ExeFile->new($self->{romhdr}{usCPUType});    for my $o32ent (@{$module->{o32}}) {        my $size= $o32ent->{vsize}; $size= $o32ent->{psize} if ($size>$o32ent->{psize});        $o32ent->{data}= GetUncompressedData($rom, $o32ent->{dataptr}, $size, $o32ent->{vsize}, $o32ent->{flags} & IMAGE_SCN_COMPRESSED);        if (!defined $o32ent->{data}) {            printf("ERROR decompressing section %08lx-%08lx (%d -> %d) of '%s'\n",                 $o32ent->{dataptr}, $o32ent->{dataptr}+$size,                 $size, $o32ent->{vsize},                $module->{filename});            return;        }        $exe->addo32($o32ent);    }    $exe->adde32($module->{e32});    my $filename= GetUniqueFilename($savedir, $module->{filename});    $exe->SaveToFile($filename);}# ... these are class methods / static functions# finds the rom header, which points back to the specified start offset.sub FindRomHdr {    my ($rom, $firstofs)= @_;#   if ($have_xiputils) {#       return XdaDevelopers::XipUtils::findromhdr($rom->{data}, $firstofs)#   }    my $hdrptr= $rom->GetPDword($firstofs+0x44);    #printf("searching for header at ptr=%08lx from ofs=%08lx\n", $hdrptr, $firstofs+0x48);    # search for romheader, starting directly after 'ECEC', until end of rom.    for(my $hdrofs=$firstofs+0x48 ; $hdrofs < $rom->{size}-0x54 ; $hdrofs+=4)    {        my $firstptr= $rom->GetPDword($hdrofs+8);        if ($hdrptr-$firstptr==$hdrofs-$firstofs) {            #printf("found romheader at ptr:f=%08lx, h=%08lx  | ofs:f=%08lx, h=%08lx\n",            #    $firstptr, $hdrptr, $firstofs, $hdrofs);            return $hdrofs;        }    }    return -1;}# finds the rom header, which points back to the specified start offset.# this is optimized by looking for the cpuidsub FindRomHdrByCpu {    my $rom= shift;    my $firstofs= shift;    my $cpuid= pack("V",shift);    my $hdrptr= $rom->GetPDword($firstofs+0x44);    #printf("searching for cpuid in header at ptr=%08lx from ofs=%08lx\n", $hdrptr, $firstofs+0x48);    # search for romheader, starting directly after 'ECEC', until end of rom.    #   ( 0x48 = ofs directly ofter romhdr-ptr, 0x44 is ofs of cpuid in romhdr )    my $ofs=$rom->find($cpuid, $firstofs+0x48+0x44);    #   0x10 is size of rest of romhdr of cpuid.    while ($ofs!=-1 && $ofs < $rom->{size}-0x10)    {        my $hdrofs= $ofs-0x44;        my $firstptr= $rom->GetPDword($hdrofs+8);        #print unpack("H*", $rom->GetPData($hdrofs, 0x50)), "\n";        #printf(" cpuid at %08lx  ptr:f=%08lx, h=%08lx  | ofs:f=%08lx, h=%08lx\n",        #    $ofs, $firstptr, $hdrptr, $firstofs, $hdrofs);        if ($hdrptr-$firstptr==$hdrofs-$firstofs) {            #printf("found romheader at ptr:f=%08lx, h=%08lx  | ofs:f=%08lx, h=%08lx\n",            #    $firstptr, $hdrptr, $firstofs, $hdrofs);            return $hdrofs;        }        $ofs=$rom->find($cpuid, $ofs+4);    }    return -1;}sub FindXipBlocks {    my $rom= shift;    my $cpuid;    my @xiplist;    my $ofs= 0;    while ($ofs < $rom->{size}) {        my $ececofs= $rom->find("ECEC", $ofs);        last if ($ececofs==-1);        my $firstofs= $ececofs-0x40;        my $hdrptr= $rom->GetPDword($firstofs+0x44);        my $hdrofs= $cpuid? FindRomHdrByCpu($rom, $firstofs, $cpuid) : FindRomHdr($rom, $firstofs);        if ($hdrofs==-1) {            $ofs= $ececofs+4;        }        else {            my $firstptr= $rom->GetPDword($hdrofs+8);            my $lastptr= $rom->GetPDword($hdrofs+12);            $cpuid= $rom->GetPDword($hdrofs+68);            my $lastofs= $lastptr-$hdrptr+$hdrofs;            push @xiplist, { ofs=>$firstofs, len=>$lastptr-$firstptr, base=>$firstptr };            $ofs= $lastofs+0x40;        }    }    #printf("found %d xip blocks\n", scalar @xiplist);    return \@xiplist;}##########################################################################################################################################################package ROM;use strict;use Carp;sub new {    my $class= shift;    my $data= shift;    my $base= shift;    return bless { data=>$data, size=>length($data) }, $class;}sub setbase {    my ($self, $dataofs, $base)= @_;    $self->{base}= $base- $dataofs;}sub IsInRange {    my ($self, $ofs)= @_;    return $ofs-$self->{base}>=0 && $ofs-$self->{base}<$self->{size};}sub find {    my ($self, $str, $ofs)= @_;    return index($self->{data}, $str, $ofs);}sub GetDword {    my ($self, $ofs)= @_;    return unpack("V", $self->GetVData($ofs, 4));}# get data by virtual offsetsub GetVData {    my ($self, $ofs, $len)= @_;    if ($ofs-$self->{base}<0 || $ofs-$self->{base}+$len > length($self->{data})) {        croak sprintf("%08lx l=%08lx beyond size : base=%08lx l=%08lx\n", $ofs, $len, $self->{base}, length($self->{data}));    }    return substr($self->{data}, $ofs-$self->{base}, $len)}# get data by physical offsetsub GetPData {    my ($self, $ofs, $len)= @_;    return substr($self->{data}, $ofs, $len)}# get dword by physical offsetsub GetPDword {    my ($self, $ofs)= @_;    return unpack("V", $self->GetPData($ofs, 4));}sub GetString {    my ($self, $ofs)= @_;    if ($ofs==0) {        return "((null))";    }    my $nulpos= $self->{base}+index($self->{data}, "\x00", $ofs-$self->{base});    return $self->GetVData($ofs, $nulpos-$ofs);}##########################################################################################################################################################package MemSpace;use strict;use Carp;sub new {    return bless {}, shift;}sub setvbase {    my ($self, $physical, $virtual)= @_;    $self->{base}= $virtual - $physical;    # virtualaddr = physical + base}# add region by virtual address.sub vadd {    my ($self, $vstart, $len, $fmt, @args)= @_;    if ($vstart==0) {        carp "vadd: v=NULL\n";        return;    }    my $paddr= $vstart-$self->{base};    push @{$self->{items}{$paddr}}, {        pstart=>$paddr,        vstart=>$vstart,        len=>$len,        desc=>sprintf($fmt, @args)    };}# fill blanks in virtual region.sub vfillblanks {    my ($self, $rom, $first, $last)= @_;    my $vprev;    for my $pofs (sort {$a<=>$b} keys %{$self->{items}}) {        my $vofs= $pofs+$self->{base};        next if ($vofs<$first);        last if ($vofs>$last);        #printf("adding unknown first=%08lx last=%08lx vofs=%08lx vprev=%08lx pofs=%08lx\n", $first, $last, $vofs, $vprev, $pofs);        $self->vadd_unknown($rom, $first, $vofs-$first) if (!$vprev && $vofs>$first);        $self->vadd_unknown($rom, $vprev, $vofs-$vprev) if ($vprev && $vofs>$vprev);        my $maxlen;        for my $item (sort {$a->{len}<=>$b->{len}} @{$self->{items}{$pofs}}) {            $maxlen= $item->{len} if (!defined $maxlen || $maxlen < $item->{len});        }        $vprev= $vofs+$maxlen;    }    #printf("adding last unknown first=%08lx last=%08lx vprev=%08lx\n", $first, $last, $vprev);    $self->vadd_unknown($rom, $vprev, $last-$vprev) if ($vprev && $last > $vprev);}sub vadd_unknown {    my ($self, $rom, $start, $len)= @_;    my $data= $rom->GetVData($start, $len);    my $desc;    if ($data =~ /^\x00+$/) {        $desc= "NUL";    }    elsif ($data =~ /^\xff+$/) {        $desc= "ONE";    }    elsif ($data =~ /^...\xea\x00+$/) {        my $target=unpack("V", $data);        $desc= sprintf("kernel entry point : branch to %08lx", $start+4*($target&0xffffff)+8);    }    else {        if (length($data)>64) {            $desc= "unknown-large: ".unpack("H*", substr($data, 0, 64));        }        else {            $desc= "unknown: ".unpack("H*", $data);        }    }    #printf("... unknown %08lx-%08lx L%08lx\n", $start, $start+$len, $len);    $self->vadd($start, $len, $desc);}# functions dealing with physical offsets.sub padd {    my ($self, $pstart, $len, $fmt, @args)= @_;    push @{$self->{items}{$pstart}}, {        pstart=>$pstart,        len=>$len,        desc=>sprintf($fmt, @args)    };}# fill blanks in physical region.sub pfillblanks {    my ($self, $rom, $first, $last)= @_;    my $pprev;    for my $pofs (sort {$a<=>$b} keys %{$self->{items}}) {        next if ($pofs<$first);        last if ($pofs>$last);        $self->padd_unknown($rom, $first, $pofs-$first) if (!$pprev && $pofs>$first);        $self->padd_unknown($rom, $pprev, $pofs-$pprev) if ($pprev && $pofs>$pprev);        my $maxlen;        for my $item (sort {$a->{len}<=>$b->{len}} @{$self->{items}{$pofs}}) {            $maxlen= $item->{len} if (!defined $maxlen || $maxlen < $item->{len});        }        $pprev= $pofs+$maxlen;    }    $self->padd_unknown($rom, $pprev, $last-$pprev) if ($pprev && $last > $pprev);}# add unknown region by physical addresssub padd_unknown {    my ($self, $rom, $start, $len)= @_;    my $data= $rom->GetPData($start, $len);    my $desc;    if ($data =~ /^(\x00*)(\xff*)$/) {        my $l_nul= length($1);        my $l_one= length($2);        #printf("adding NULONE section: %08lx l %08lx\n", $start, $len); ###        $self->padd($start, $l_nul, "NUL") if ($l_nul);        $self->padd($start+$l_nul, $l_one, "ONE") if ($l_one);    }    else {        my $bofs= 0;        pos($data)= $bofs;        if ($data =~ /\G\x00+/) {            if (length($&)>16) {                $self->padd($start+$bofs, length($&), "NUL");                $bofs += length($&);            }        }        pos($data)= $bofs;        if ($data =~ /\G\xff+/) {            if (length($&)>16) {                #printf("adding ONE section: %08lx l %08lx : %08lx l %08lx\n", $start, $len, $start+$bofs, length($&)); ###                $self->padd($start+$bofs, length($&), "ONE");                $bofs += length($&);            }        }        my $eofs= length($data);        if ($eofs < 0x1000) {# !!! this regex takes a very long time for large data.#  .. and the remainder unknown is not calculated correctly             pos($data)= $eofs;            if ($data =~ /\xff+\G/) {                if (length($&)>16) {                    $eofs -= length($&);                    if ($eofs>$bofs) {                        $self->padd($start+$eofs, length($&), "ONE");                    }                }            }            pos($data)= $eofs;            if ($data =~ /\x00+\G/) {                if (length($&)>16) {                    $eofs -= length($&);                    if ($eofs>$bofs) {                        $self->padd($start+$eofs, length($&), "NUL");                    }                }            }        }        #printf("punknown: start=%08lx len=%08lx eofs=%08lx bofs=%08lx\n", $start, $len, $eofs, $bofs);# removed this restriction:  $len-$bofs==0x2000 &&         if (substr($data, $bofs+0x48, 4) eq "RSA1") {            $desc= "xip-chain";            $self->ParseXipChain(substr($data, $bofs, $eofs-$bofs));        }        elsif ($eofs-$bofs>64) {            $desc= "unknown-large: ".unpack("H*", substr($data, $bofs, 64));        }        else {            $desc= "unknown: ".unpack("H*", substr($data, $bofs, $eofs-$bofs));        }        $self->padd($start+$bofs, $eofs-$bofs, $desc) if ($eofs>$bofs);    }}sub ParseXipChainEntry {    my $xipentry= shift;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -