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

📄 rdmsflsh.pl

📁 dumprom source code,use for learning the dumprom.exe tool for wince
💻 PL
📖 第 1 页 / 共 3 页
字号:
    $o32obj{name} = $segtype;
    $o32obj{vsize}= $o32rom->{vsize};
    if (($o32rom->{flags}&IMAGE_SCN_TYPE_NOLOAD)!=0 && $o32rom->{realaddr}==0) {
        # most likely fixup
        $o32obj{rva}  = $o32rom->{rva};
    }
    else {
        $o32obj{rva}  = $o32rom->{realaddr} - $e32rom->{vbase};
    }
    $o32obj{psize}= $o32rom->{psize};
    $o32obj{dataptr}= 0;  # *** set at a later moment
    $o32obj{realaddr}= 0; # file pointer to relocation table
    $o32obj{access}= 0;   # file pointer to line numbers
    $o32obj{temp3}= 0;    # number of relocations + number of line numbers
    $o32obj{flags}= $o32rom->{flags} & ~IMAGE_SCN_COMPRESSED;

    return \%o32obj;
}

sub convert_rom_to_exe {
    my ($perom)= @_;

    my %peexe;
    $peexe{e32exe}= convert_e32rom_to_e32exe($perom->{e32rom}, @{$perom->{o32rom}});
    
    my $fileofs= $peexe{e32exe}{hdrsize};
    for (@{$perom->{o32rom}}) {
        my $o32obj= convert_o32rom_to_o32obj($_, $perom->{e32rom});
        push @{$peexe{o32obj}}, $o32obj;

        $o32obj->{dataptr}= $fileofs;

        $peexe{rvamap}{$_->{rva}}= { rva=>$o32obj->{rva}, size=>$o32obj->{vsize} };

        $fileofs += round_to_page($o32obj->{psize}, $peexe{e32exe}{filealign})
    }

    return \%peexe;
}
sub RvaToFileOfs {
    my ($rva, @o32obj)= @_;
    for (@o32obj) {
        if ($_->{rva}<=$rva && $rva < $_->{rva} + $_->{vsize}) {
            return $_->{dataptr}+$rva-$_->{rva};
        }
    }
}
sub strread_dword {
    my ($pstr, $ofs)= @_;
    return unpack("V", substr($$pstr, $ofs, 4));
}
sub strwrite_dword {
    my ($pstr, $ofs, $dword)= @_;
    substr($$pstr, $ofs, 4)= pack("V", $dword);
}

# rvamap maps romrva's to objrva's
sub find_rva_patch {
    my ($rva, $rvamap)= @_;
        #$peexe{rvamap}{$_->{rva}}= { rva=>$o32obj->{rva}, size=>$o32obj->{vsize} };
    for (keys %$rvamap) {
        my $info= $rvamap->{$_};
        if ($_ <= $rva && $rva < $_+$info->{size}) {
            return $rva-$_+$info->{rva};
        }
    }
    return $rva;
}

sub reconstruct_binary {
    my ($file)= @_;

    my $perom= parse_pe_data($file->{data});

    my $peexe= convert_rom_to_exe($perom);

    my $mz_data = pack_mz_header();
    # $file->{sections}[$i]{data}  contains the section data

    my $e32exe_data = pack_e32exe($peexe->{e32exe});
    my @o32exe_data = map { pack_o32obj($_) } @{$peexe->{o32obj}};

    my $image= $mz_data;
    $image .= $e32exe_data;
    $image .= $_ for (@o32exe_data);

    # page to filealign
    $image .= "\x00" x ($peexe->{e32exe}{hdrsize} - length($image));

    for my $i (0 .. $#{$file->{sections}}) {
        my $section = $file->{sections}[$i];
        my $o32= $peexe->{o32obj}[$i] if ($i<@{$peexe->{o32obj}});
        $image .= $section->{data};
#       if ($o32 && $o32->{name} eq ".reloc") {
#           printf("reloc %-20s %s %08lx-%08lx-%08lx (%04x): %s\n", 
#               $file->{name},
#               $section->{name},
#               $o32->{rva}, $o32->{rva}+$o32->{psize}, $o32->{rva}+$o32->{vsize},
#               length($section->{data}), unpack("H*", $section->{data}));
#       }
        $image .= "\x00" x round_padding(length($section->{data}), $peexe->{e32exe}{filealign});
    }

    # repair import table.
    my $impofs= RvaToFileOfs($peexe->{e32exe}{IMP_rva}, @{$peexe->{o32obj}});
    while (1) {
        my $impaddr= strread_dword(\$image, $impofs+0x10);
        last if ($impaddr==0);

        my $newimpaddr = find_rva_patch($impaddr, $peexe->{rvamap});

        strwrite_dword(\$image, $impofs+0x10, $newimpaddr);

        $impofs += 0x14;
    }

    return $image;
}

# 0000: magic  0xFFFFF6FD
# 0004: DWORD dwNextDataTableOffset;
# 0008: DWORD dwNextStreamHeaderOffset;
# 000c: FS_NAME fsName; : cchName + wFlags
# 0010:                 : wszShortName[4]
# 0014:
# 0018: DWORD dwStreamSize;
# 001c: FS_DATA_RUN dataTable[1];
# 0020:
# 0024:
# 0028:
# 002c:
# 0030:
sub process_sectionentry {
    my ($dirent, $file)= @_;
    my %section;

    my $magic;

    (
        $magic,
        $section{unk}[0],        # 0  always 0   : nextdatatable offset
        $section{next},          # 1  dirptr to next section entry
        $section{unk}[1],        # 2  always 4   == name flags
        $section{name},          # 3,4  WCHAR[4] == sectionname
        $section{size},          # 5  total section size
        $section{indexblock},    # 6,7  dataptr,size  ptr  to index block of section data
        $section{indexsize},
        @{$section{unk}}[2..5],     # 8-b  always 0
    ) = unpack("VVVVa8VVVVVVV", $dirent);
    if ($magic != 0xfffff6fd && $magic != 0xfffffcfd) {
        croak sprintf("invalid magic %08lx in section entry for %s\n", $magic, $file->{name});
    }
    $section{name} = unicode2string($section{name});
    $section{name} =~ s/\x00+$//g;

    my $sdesc= sprintf("indexblock section %s for %s", $section{name}, $file->{name});
    $section{data}= process_indexed_data($rd->ReadData($section{indexblock}, $section{indexsize}, $sdesc), $sdesc);

    #printf("file %s section %s: %s\n", $file->{name}, $section{name}, $section{data});

    return \%section;
}


# magic: 0xfffffefe or 0xfffff6fe
# 0000: magic
# 0004: DWORD dwNextDataTableOffset;
# 0008: DWORD dwNextStreamHeaderOffset;
# 000c: FS_NAME fsName.cchName;
# 000e: FS_NAME fsName.wFlags;
# 0010: FS_NAME fsName.szShortName;
# 0014: FS_NAME fsName.longName;
# 0018: DWORD dwStreamSize;
# 001c: DWORD dwFileAttributes;
# 0020: _FILETIME fileTime;
# 0028: DWORD dwReserved;
# 002c: FS_DATA_RUN dataTable[1];
# 0030:
sub process_fileentry {
    my ($dirent, $desc)= @_;
    my $magic;
    my %file;
    (
        $magic,
        $file{unk}[0],          # 0  always 0
        $file{firstsection},    # 1  dirptr to first section file
        $file{namelength},      # 2  WORD  filename length  : <=4 -> char[4]+ptr = literal filename.
        $file{nameflags},       #    WORD  flag: 2= filename ptr is direntry, 0= filenameptr is datablock
        $file{namehash},        # 3  char[4]
        $file{filenameptr},     # 4  ptr to filename file ( see flag for type )
        $file{size},            # 5  total file length
        $file{attributes},      # 6  file attributes
        $file{timestamp},       # 7,8  timestamp
        $file{unk}[1],          # 9  always 0
        $file{indexblock},    # a,b  dataptr,length  to index block of file data
        $file{indexsize},
    ) = unpack("VVVvva4VVVa8VVV", $dirent);

    $file{timestamp}= cvtime::convert2unixtime($file{timestamp});
    if ($magic!=0xfffffefe && $magic!=0xfffff6fe) {
        croak sprintf("invalid magic: %08lx in fileent\n", $magic);
    }
    if ($file{nameflags}&2) {
        $file{name}= process_nameentry($rd->ReadData($file{filenameptr}, 4*13, "name entry $desc"));
    }
    elsif ($file{namelength}<=4) {
        $file{name}= unicode2string(substr($dirent, 16, 8));
        $file{filenameptr}= 0;
        $file{namehash}= "";
    }
    else {
        $file{name}= unicode2string($rd->ReadData($file{filenameptr}, $file{namelength}*2, "filenameblock $desc"));
    }
    $file{name} =~ s/\x00+$//g;

    if ($file{firstsection}) {
        $stats{modules}++;
    }
    else {
        $stats{files}++;
    }
    printf("%s: %s\n", $desc, $file{name}) if ($main::verbose);
    for (my $ofs= $file{firstsection} ; $ofs ; $ofs= $file{sections}[-1]{next})
    {
        $stats{sections}++;
        push @{$file{sections}}, process_sectionentry($rd->ReadData($ofs, 4*13, sprintf("sectionentry %d for %s", scalar @{$file{sections}}, $file{name})), \%file);
    }
    if ($file{indexblock}) {
        my $fdesc= sprintf("indexblock filedata for %s", $file{name});
        $stats{datablocks}++;
        $file{data}= process_indexed_data($rd->ReadData($file{indexblock}, $file{indexsize}, $fdesc), $fdesc);
    }
    else {
        printf("no index block %08lx %08lx for %s\n", $file{indexblock}, $file{indexsize}, $file{name});
    }

    #printf("file %s: %s\n", $file{name}, $file{data});

    return \%file;
}
sub process_indexed_data {
    my ($index, $desc)= @_;
    my $data= "";
    for (my $iofs=0 ; $iofs<length($index) ; $iofs+=8) {
        $stats{datablocks}++;
        my ($compsize, $fullsize, $dataofs)= unpack("vvV", substr($index, $iofs, 8));
        last if ($dataofs==0);
        my $block= $rd->ReadData($dataofs, $compsize, sprintf("datablock %d for %s", $iofs/8, $desc));
        if (!defined $block) {
            printf("error reading data from %08lx l=%08lx : datablock %d for %s\n", $dataofs, $compsize, $iofs/8, $desc);
        }
        elsif ($fullsize==$compsize) {
            $data .= $block;
            $stats{uncompressed}++;
        }
        elsif ($imgfs_hdr->{compression} eq "XPR") {
            $stats{compressed}++;
            my $decomp= XdaDevelopers::CompressUtils::XPR_DecompressDecode($block.("\x00" x 16), $fullsize);
            if (!defined $decomp) {
                printf("no decomp !!!: %08lx->%08lx %s\n", $compsize, $fullsize, $desc);
                $data .= $block;
            }
            else {
                $data .= $decomp;
            }
        }
        elsif ($imgfs_hdr->{compression} eq "LZX") {
            $stats{compressed}++;
            my $decomp= XdaDevelopers::CompressUtils::LZX_DecompressDecode($block.("\x00" x 16), $fullsize);
            if (!defined $decomp) {
                printf("no decomp !!!: %08lx->%08lx %s\n", $compsize, $fullsize, $desc);
                $data .= $decomp;
            }
            else {
                $data .= $decomp;
            }
        }
    }
    return $data;
}
sub unicode2string {
    my ($data)= @_;
    return pack("U*", unpack("v*", $data));
}

# magic 0xfffffefb
sub process_nameentry {
    my ($nameent)= @_;
    my ($magic, $name)= unpack("Va*", $nameent);
    if ($magic!=0xfffffefb) {
        croak "unexpected: no nameentry magic\n";
    }
    return unicode2string($name);
}

⌨️ 快捷键说明

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