📄 rdmsflsh.pl
字号:
$fh->print($data) if (defined $data && length($data));
$fh->close();
}
sub save_file {
my ($dirpath, $file)= @_;
my $filepath= sprintf("%s/%s", $dirpath, $file->{name});
if ($file->{sections} && @{$file->{sections}}) {
my $exedata= reconstruct_binary($file);
save_data($filepath, $exedata);
}
else {
save_data($filepath, $file->{data});
}
}
sub unpack_e32rom {
my ($data)= @_;
my %e32rom;
(
$e32rom{objcnt}, # 0x00
$e32rom{imageflags}, # 0x02
$e32rom{entryrva}, # 0x04
$e32rom{vbase}, # 0x08
$e32rom{subsysmajor}, # 0x0C
$e32rom{subsysminor}, # 0x0E
$e32rom{stackmax}, # 0x10
$e32rom{vsize}, # 0x14
$e32rom{sect14rva}, # 0x18
$e32rom{sect14size}, # 0x1C
$e32rom{timestamp}, # 0x20
$e32rom{EXP_rva}, $e32rom{EXP_size}, # 0x24
$e32rom{IMP_rva}, $e32rom{IMP_size}, # 0x2c
$e32rom{RES_rva}, $e32rom{RES_size}, # 0x34
$e32rom{EXC_rva}, $e32rom{EXC_size}, # 0x3c
$e32rom{SEC_rva}, $e32rom{SEC_size}, # 0x44
$e32rom{FIX_rva}, $e32rom{FIX_size}, # 0x4c
$e32rom{DEB_rva}, $e32rom{DEB_size}, # 0x54
$e32rom{IMD_rva}, $e32rom{IMD_size}, # 0x5c
$e32rom{MSP_rva}, $e32rom{MSP_size}, # 0x64
$e32rom{subsys}, # 0x6c
)= unpack("v2V2v2V23v", $data);
return \%e32rom;
}
sub unpack_o32rom {
my ($data)= @_;
my %o32rom;
(
$o32rom{vsize},
$o32rom{rva},
$o32rom{psize},
$o32rom{dataptr},
$o32rom{realaddr},
$o32rom{flags},
) = unpack("V6", $data);
return \%o32rom;
}
sub parse_pe_data {
my ($data)= @_;
my %pe;
if (length($data) < 0x70) {
printf("WARNING: PE data block too small\n");
}
$pe{e32rom}= unpack_e32rom(substr($data, 0, 0x70));
if (length($data) < 0x70 + $pe{e32rom}{objcnt}*0x18) {
printf("WARNING: PE data block too small\n");
}
elsif (length($data) > 0x70 + $pe{e32rom}{objcnt}*0x18) {
printf("WARNING: PE data block too large: %s\n", unpack("H*", substr($data, 0x70+0x18*$pe{e32rom}{objcnt})));
}
for (my $i=0 ; $i<$pe{e32rom}{objcnt} ; $i++) {
push @{$pe{o32rom}}, unpack_o32rom(substr($data, 0x70+0x18*$i, 0x18));
}
return \%pe;
}
sub pack_mz_header {
return pack("H*", "4d5a90000300000004000000ffff0000").
pack("H*", "b8000000000000004000000000000000").
pack("H*", "00000000000000000000000000000000").
pack("H*", "00000000000000000000000080000000").
pack("H*", "0e1fba0e00b409cd21b8014ccd215468").
pack("H*", "69732070726f6772616d2063616e6e6f").
pack("H*", "742062652072756e20696e20444f5320").
pack("H*", "6d6f64652e0d0d0a2400000000000000");
}
sub pack_e32exe {
my ($e32exe)= @_;
my @info= qw(EXP IMP RES EXC SEC FIX DEB IMD MSP TLS CBK RS1 RS2 RS3 RS4 RS5);
return pack("a4vvVVVvvvCCVV8v6V4v2V6",
$e32exe->{magic},
$e32exe->{cpu},
$e32exe->{objcnt},
$e32exe->{timestamp},
$e32exe->{symtaboff},
$e32exe->{symcount},
$e32exe->{opthdrsize},
$e32exe->{imageflags},
$e32exe->{coffmagic},
$e32exe->{linkmajor},
$e32exe->{linkminor},
$e32exe->{codesize},
$e32exe->{initdsize},
$e32exe->{uninitdsize},
$e32exe->{entryrva},
$e32exe->{codebase},
$e32exe->{database},
$e32exe->{vbase},
$e32exe->{objalign},
$e32exe->{filealign},
$e32exe->{osmajor},
$e32exe->{osminor},
$e32exe->{usermajor},
$e32exe->{userminor},
$e32exe->{subsysmajor},
$e32exe->{subsysminor},
$e32exe->{res1},
$e32exe->{vsize},
$e32exe->{hdrsize},
$e32exe->{filechksum},
$e32exe->{subsys},
$e32exe->{dllflags},
$e32exe->{stackmax},
$e32exe->{stackinit},
$e32exe->{heapmax},
$e32exe->{heapinit},
$e32exe->{res2},
$e32exe->{hdrextra},
). join("", map { pack("VV", $e32exe->{"${_}_rva"}||0, $e32exe->{"${_}_size"}||0) } @info);
}
sub pack_o32obj {
my ($o32obj)= @_;
return pack("a8V8",
$o32obj->{name},
$o32obj->{vsize},
$o32obj->{rva},
$o32obj->{psize},
$o32obj->{dataptr},
$o32obj->{realaddr},
$o32obj->{access},
$o32obj->{temp3},
$o32obj->{flags});
}
sub IMAGE_FILE_RELOCS_STRIPPED { 1 };
sub IMAGE_SCN_COMPRESSED { 0x00002000 }
sub IMAGE_SCN_CNT_CODE { 0x00000020 }
sub IMAGE_SCN_CNT_INITIALIZED_DATA { 0x00000040 }
sub IMAGE_SCN_CNT_UNINITIALIZED_DATA { 0x00000080 }
sub IMAGE_SCN_TYPE_NOLOAD { 0x00000002 }
sub IMAGE_SCN_MEM_DISCARDABLE { 0x02000000 }
sub IMAGE_SCN_MEM_EXECUTE { 0x20000000 }
sub IMAGE_SCN_MEM_READ { 0x40000000 }
sub IMAGE_SCN_MEM_WRITE { 0x80000000 }
sub STD_EXTRA { 16 }
sub IMAGE_FILE_MACHINE_ARM { 0x01c0 }
sub FindFirstSegment {
my ($segtypeflag, @o32rom)= @_;
for (@o32rom) {
if ($_->{flags} & $segtypeflag) {
return $_->{rva};
}
}
return 0;
}
sub CalcSegmentSizeSum {
my ($segtypeflag, @o32rom)= @_;
my $size= 0;
for (@o32rom) {
# vsize is not entirely correct, I should use the uncompressed size,
# but, I don't know that here yet.
if ($_->{flags}&$segtypeflag) {
$size += $_->{vsize};
}
}
return $size;
}
sub round_to_page {
my ($val, $page)= @_;
if ($val%$page) {
return (int($val/$page)+1)*$page;
}
return $val;
}
sub round_padding {
my ($val, $page)= @_;
if ($val%$page) {
return $page - ($val%$page);
}
return 0;
}
sub convert_e32rom_to_e32exe {
my ($e32rom, @o32rom)= @_;
my %e32exe;
$e32exe{magic}= "PE";
$e32exe{cpu}= IMAGE_FILE_MACHINE_ARM; # todo: get this from romhdr.
$e32exe{objcnt}= $e32rom->{objcnt};
$e32exe{timestamp}= $e32rom->{timestamp};
$e32exe{symtaboff}=0;
$e32exe{symcount}=0;
$e32exe{opthdrsize}= 0xe0; # fixed.
$e32exe{imageflags}= $e32rom->{imageflags} | IMAGE_FILE_RELOCS_STRIPPED;
$e32exe{coffmagic}= 0x10b;
$e32exe{linkmajor}= 6;
$e32exe{linkminor}= 1;
$e32exe{codesize}= CalcSegmentSizeSum(IMAGE_SCN_CNT_CODE, @o32rom);
$e32exe{initdsize}= CalcSegmentSizeSum(IMAGE_SCN_CNT_INITIALIZED_DATA, @o32rom);
$e32exe{uninitdsize}= CalcSegmentSizeSum(IMAGE_SCN_CNT_UNINITIALIZED_DATA, @o32rom);
$e32exe{entryrva}= $e32rom->{entryrva};
$e32exe{codebase}= FindFirstSegment(IMAGE_SCN_CNT_CODE, @o32rom);
$e32exe{database}= FindFirstSegment(IMAGE_SCN_CNT_INITIALIZED_DATA, @o32rom);
$e32exe{vbase}= $e32rom->{vbase};
$e32exe{objalign}= 0x1000;
$e32exe{filealign}= 0x200;
$e32exe{osmajor}= 4;
$e32exe{osminor}= 0;
$e32exe{usermajor}= 0;
$e32exe{userminor}= 0;
$e32exe{subsysmajor}= $e32rom->{subsysmajor};
$e32exe{subsysminor}= $e32rom->{subsysminor};
$e32exe{res1}= 0; # 'Win32 version' according to dumpbin
$e32exe{vsize}= $e32rom->{vsize};
$e32exe{hdrsize}= round_to_page(0x80+0xf8+@o32rom*0x28, $e32exe{filealign});
$e32exe{filechksum}= 0;
$e32exe{subsys}= $e32rom->{subsys};
$e32exe{dllflags}= 0;
$e32exe{stackmax}= $e32rom->{stackmax};
$e32exe{stackinit}=0x1000; # ?
$e32exe{heapmax}=0x100000; # ?
$e32exe{heapinit}=0x1000; # ?
$e32exe{res2}= 0; # 'loader flags' according to dumpbin
$e32exe{hdrextra}= STD_EXTRA; # nr of directories
$e32exe{EXP_rva}= $e32rom->{EXP_rva}; $e32exe{EXP_size}= $e32rom->{EXP_size};
$e32exe{IMP_rva}= $e32rom->{IMP_rva}; $e32exe{IMP_size}= $e32rom->{IMP_size};
$e32exe{RES_rva}= $e32rom->{RES_rva}; $e32exe{RES_size}= $e32rom->{RES_size};
$e32exe{EXC_rva}= $e32rom->{EXC_rva}; $e32exe{EXC_size}= $e32rom->{EXC_size};
$e32exe{SEC_rva}= $e32rom->{SEC_rva}; $e32exe{SEC_size}= $e32rom->{SEC_size}; # always 0
# ...fixup segment does not look like a real fixup seg.
# so we do include the data, but don't do anything with it.
#$e32exe{FIX_rva}= $e32rom->{FIX_rva}; $e32exe{FIX_size}= $e32rom->{FIX_size};
$e32exe{DEB_rva}= $e32rom->{DEB_rva}; $e32exe{DEB_size}= $e32rom->{DEB_size};
$e32exe{IMD_rva}= $e32rom->{IMD_rva}; $e32exe{IMD_size}= $e32rom->{IMD_size}; # always 0
$e32exe{MSP_rva}= $e32rom->{MSP_rva}; $e32exe{MSP_size}= $e32rom->{MSP_size}; # always 0
$e32exe{RS4_rva}= $e32rom->{sect14rva}; $e32exe{RS4_size}= $e32rom->{sect14size};
return \%e32exe;
}
sub convert_o32rom_to_o32obj {
my ($o32rom, $e32rom)= @_;
my $segtype;
if ($e32rom->{RES_rva} == $o32rom->{rva} && $e32rom->{RES_size} == $o32rom->{vsize}) {
$segtype= ".rsrc";
}
elsif ($e32rom->{EXC_rva} == $o32rom->{rva} && $e32rom->{EXC_size} == $o32rom->{vsize}) {
$segtype= ".pdata";
}
elsif ($e32rom->{FIX_rva} == $o32rom->{rva} && $e32rom->{FIX_size} == $o32rom->{vsize}) {
$segtype= ".reloc";
}
elsif ($o32rom->{flags}&IMAGE_SCN_CNT_CODE) {
$segtype= ".text";
}
elsif ($o32rom->{flags}&IMAGE_SCN_CNT_INITIALIZED_DATA) {
$segtype= ".data";
}
elsif ($o32rom->{flags}&IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
$segtype= ".pdata";
}
else {
$segtype= ".other";
}
my %o32obj;
# todo: add sequence nrs to identically named sections
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -