📄 parsecrash420.pl
字号:
croak "specify virtual address with -d\n" if (!defined $addr);
for (my $i= 0 ; $i<256 ; $i+=4) {
printf("%08lx: ", $addr+$i) if (($i%16)==0);
printf(" %08lx", $vimg->ReadDword($addr+$i));
printf("\n") if (($i%16)==12);
}
}
if ($doSaveSection == 1) {
croak "specify virtual address with -s\n" if (!@ARGV);
my $addr= eval(shift);
croak "specify virtual address with -s\n" if (!defined $addr);
my $length= eval(shift);
croak "specify length with -s\n" if (!defined $length);
my $savefile= shift;
croak "specify savefile with -s\n" if (!$savefile);
my $fh= IO::File->new($savefile, "w") or croak "$savefile: $!\n";
binmode $fh;
for (my $ofs= $addr ; $ofs < $addr + $length ; $ofs += 0x1000)
{
my $data;
eval {
$data= $vimg->ReadData($ofs, 0x1000);
};
if (!$@) {
$fh->print($data);
}
else {
$fh->seek(0x1000, SEEK_CUR);
}
}
}
if ($doSaveSection == 2) {
SaveAllSections();
}
if ($doSectionOverview) {
PrintSectionOverview();
}
if ($doListHandles) {
ListHandles();
}
exit(0);
sub isStartPtr {
my $ofs= shift;
return ((struct('HDATA.hValue', $ofs)&3)!=2);
}
sub handle2HData {
my $h= shift;
return kdata('handleBase')+($h&0x1ffffffc);
}
sub handleFFSD {
my ($vmbase, $obj)= @_;
return struct("FFSDinfo.pFileinfo->pFilename->name", $obj, $vmbase);
}
sub handleHFSD {
my ($vmbase, $obj)= @_;
return struct("FFSDinfo.pGtgtInfo->pWStrName->str", $obj, $vmbase);
}
sub handleW32D {
my ($vmbase, $obj)= @_;
return sprintf("%s%d:",
struct("fsopendev_t.lpDev->type", $obj, $vmbase),
struct("fsopendev_t.lpDev->index", $obj, $vmbase)
);
}
sub handleW32H {
my ($vmbase, $obj)= @_;
return sprintf("oid %08lx", struct("W32Hinfo.oid", $obj, $vmbase));
}
sub handlePFSD {
my ($vmbase, $obj)= @_;
return "" if ($obj==1);
return struct("FFSDinfo.name", $obj, $vmbase);
}
sub handleBDEV {
my ($vmbase, $obj)= @_;
return sprintf("%s - %s",
struct("BDEVinfo.name1", $obj, $vmbase),
struct("BDEVinfo.name2", $obj, $vmbase));
}
sub handleSTRG {
my ($vmbase, $obj)= @_;
return sprintf("%s %s %s",
struct("STRGinfo.pstorageinfo->devname", $obj, $vmbase),
struct("STRGinfo.pstorageinfo->desc1", $obj, $vmbase),
struct("STRGinfo.pstorageinfo->desc2", $obj, $vmbase));
}
sub handleFMAP {
my ($vmbase, $obj)= @_;
return struct("FSMAP.name->name", $obj, $vmbase);
}
sub structdumper {
my ($type, $vmbase, $ofs, $parent)= @_;
return "(null)" if ($ofs==0);
return sprintf("(null_%04lx)",$ofs) if ($ofs<0x10000);
if ($type eq "CINFO") {
# special handling for cinfo.
$vmbase= struct("CINFO.pServer->dwVMBase", $ofs);
}
if ( exists $dumptypes{vmofs($ofs,$vmbase)} && $dumptypes{vmofs($ofs,$vmbase)} ne $type
&& $dumptypes{vmofs($ofs,$vmbase)} ne "APISET" && $type ne "CINFO") {
# APISET = { CINFO + dword }
warn sprintf("\n!%08lx : %s != %s - %s {%s}\n", $ofs, $dumptypes{vmofs($ofs,$vmbase)}, $type, $parent, join(", ", @{$dumpoffsets{vmofs($ofs,$vmbase)}}) );
}
else {
$dumptypes{vmofs($ofs,$vmbase)}= $type;
}
$dumpedstructs{vmofs($ofs, $vmbase)}++;
my @itemstrs;
for my $item (sort { $a->{ofs} <=> $b->{ofs} } values %{$structs{$type}{items}}) {
my $dumppath= sprintf("%s->%s.%s:%08lx", $parent, $type, $item->{name}, $ofs);
if (exists $item->{ptype}) {
my @values= struct("$type.$item->{name}", $ofs, $vmbase);
for my $ixval (0..$#values) {
my $val= $values[$ixval];
next if (!$vimg->isValidPtr(vmofs($val, $vmbase)));
push @{$dumpoffsets{vmofs($val,$vmbase)}}, sprintf("%s[%d]", $dumppath, $ixval);
if ( exists $dumptypes{vmofs($val,$vmbase)} && $dumptypes{vmofs($val,$vmbase)} ne $item->{ptype} ) {
warn sprintf("\n!%s:%08lx %s=%08lx: %s != %s - %s {%s}\n",
$type, $ofs, $item->{name}, vmofs($val,$vmbase),
$dumptypes{vmofs($val,$vmbase)}, $item->{ptype}, $parent, join(", ", @{$dumpoffsets{vmofs($ofs,$vmbase)}}) );
}
else {
$dumptypes{vmofs($val,$vmbase)}= $item->{ptype};
}
}
}
elsif ($item->{type} eq "DWORD") {
my @values= struct("$type.$item->{name}", $ofs, $vmbase);
for my $ixval (0..$#values) {
my $val= $values[$ixval];
next if (!$vimg->isValidPtr(vmofs($val, $vmbase)));
# todo: add value index to offset string for items.count>1
push @{$dumpoffsets{vmofs($val,$vmbase)}}, sprintf("%s[%d]", $dumppath, $ixval);
}
}
if (exists $structs{$item->{type}}{format}) {
my @value= struct("$type.$item->{name}", $ofs, $vmbase);
push @itemstrs, sprintf("%s=[%s]", $item->{name}, join(",", map { sprintf($structs{$item->{type}}{format}, $value[$_]) } (0..$#value)));
}
else {
push @itemstrs, sprintf("%s=[%s]", $item->{name}, join(",", map {
structdumper($item->{type}, $vmbase, structofs("$type.$item->{name}", $ofs, $vmbase)+$structs{$item->{type}}{size}*$_,
sprintf("%s[%d]", $dumppath, $_))
} (0..$item->{count}-1)));
}
}
return sprintf("%s:%s", $type, join(", ", @itemstrs));
}
sub ListHandles
{
my $ha= handle2HData(kdata('hCurProc'));
my $hi= $ha;
do {
if (isStartPtr($ha)) {
$ha= struct('HDATA.fwd', $ha);
}
my $acname= struct('HDATA.pci->acName', $ha);
printf("%08lx %-4s %08lx %08lx", $ha, $acname, struct('HDATA.hValue', $ha), struct('HDATA.pvObj', $ha));
$dumptypes{$ha}= "HDATA";
$dumpedstructs{$ha}++;
if (!exists $handletypes{$acname}) {
}
else {
if ($g_verbose) {
print " ", structdumper($handletypes{$acname}{structtype},
struct('HDATA.pci->pServer', $ha) ? struct('HDATA.pci->pServer->dwVMBase', $ha) : 0,
struct('HDATA.pvObj', $ha), sprintf("HDATA[%08lx].pvObj", $ha));
}
elsif (exists $handletypes{$acname}{simpledump}) {
print " ", $handletypes{$acname}{simpledump}(
struct('HDATA.pci->pServer', $ha) ? struct('HDATA.pci->pServer->dwVMBase', $ha) : 0,
struct('HDATA.pvObj', $ha));
}
}
print "\n";
$ha= struct('HDATA.fwd', $ha);
} while ($hi != $ha);
if ($g_verbose) {
my $newcount;
do {
$newcount=0;
for my $ofs (keys %dumpoffsets) {
if (!exists $dumpedstructs{$ofs}) {
eval {
if (exists $dumptypes{$ofs}) {
printf("%08lx##:%s{%s} %s\n", $ofs, $dumptypes{$ofs}, join(", ", @{$dumpoffsets{$ofs}}), structdumper($dumptypes{$ofs}, ofsvm($ofs), $ofs, sprintf("%s", $dumpoffsets{$ofs}[0])));
}
else {
printf("%08lx##{%s} %s\n", $ofs, join(", ", @{$dumpoffsets{$ofs}}), structdumper("DWLIST", ofsvm($ofs), $ofs, sprintf("%s", $dumpoffsets{$ofs}[0])));
}
};
if ($@) { printf("%08lx!!!!!%s %s\n", $ofs, exists $dumptypes{$ofs}?$dumptypes{$ofs}:"", $@); }
$dumpedstructs{$ofs}++;
$newcount++;
}
}
} while ($newcount);
}
}
sub SaveAllSections
{
}
sub PrintSectionOverview
{
my %phys;
for my $ixSection (1..63, 0xb3) {
my $pscn = $vimg->ReadDword(kdata('KINX_SECTIONS') + 4*$ixSection);
if ($pscn!=0) {
for my $ixBlock (0..511) {
my $pmb = $vimg->ReadDword($pscn+4*$ixBlock);
if ($pmb!=0 && $pmb!=1) {
my $apages= struct("MemBlock.aPages", $pmb);
for my $ixPage (0..15) {
my $dwPage= $vimg->ReadDword($apages+4*$ixPage);
if ($dwPage!=~0xf && $dwPage!=0) {
if (exists $phys{$dwPage&0xfffff000} && $phys{$dwPage&0xfffff000}!=$ixSection) {
printf("phys: %08lx = %02x %02x\n", $dwPage&0xfffff000, $ixSection, $phys{$dwPage&0xfffff000});
}
$phys{$dwPage&0xfffff000}= $ixSection;
}
}
}
}
}
}
my $prevval;
my $previx;
my $lastix;
for my $ofs (sort {$a<=>$b} keys %phys)
{
if (!defined $prevval || $prevval!=$phys{$ofs}) {
if (defined $prevval) {
printf("%08lx-%08lx %02x\n", $previx, $lastix+0x1000, $prevval);
}
$prevval= $phys{$ofs};
$previx= $ofs;
}
$lastix= $ofs;
}
printf("%08lx-%08lx %02x\n", $previx, $lastix+0x1000, $prevval);
}
sub DumpOpenExe {
my $addr= shift;
my $type= struct('openexe_t.filetype', $addr);
my $isoid= struct('openexe_t.bIsOID', $addr);
if ($type==2) { # objstore
printf("openexe: objectstore handle=%08lx pm=%04x %08lx",
struct('openexe_t.handle', $addr),
struct('openexe_t.pagemode', $addr),
struct('openexe_t.offset', $addr));
}
elsif ($type==3) {# romimage
printf("openexe: TOCentry=%08lx pm=%04x %08lx",
struct('openexe_t.handle', $addr),
struct('openexe_t.pagemode', $addr),
struct('openexe_t.offset', $addr));
}
elsif ($type==4) {# extimage
printf("openexe: ppfs handle=%08lx pm=%04x %08lx",
struct('openexe_t.handle', $addr),
struct('openexe_t.pagemode', $addr),
struct('openexe_t.offset', $addr));
}
if ($isoid) {
printf(" oid=%08lx\n", struct('openexe_t.name', $addr));
}
else {
printf(" name=%s\n", struct('openexe_t.name->name', $addr));
}
}
sub DumpProcessEntry {
my $addr= shift;
return if (struct('PROCESS.dwVMBase', $addr)==0);
my $nameptr= struct('PROCESS.lpszProcName', $addr);
my $cmdlineptr= struct('PROCESS.pcmdline', $addr);
#todo:
# create object that translates process memory.
printf("slot%02lx vmbase=%08lx hProc= %08lx name=%08lx:%s cmd=%08lx:%s\n",
struct('PROCESS.procnum', $addr),
struct('PROCESS.dwVMBase', $addr),
struct('PROCESS.hProc', $addr),
$nameptr,
$vimg->ReadWString($nameptr),
$cmdlineptr,
$vimg->ReadWString($cmdlineptr));
DumpOpenExe(structofs('PROCESS.oe', $addr));
if (struct('PROCESS.pTh', $addr)) {
DumpThreads(struct('PROCESS.pTh', $addr));
}
}
sub DumpThreads {
my $firstaddr= shift;
my $addr= $firstaddr;
while (1) {
DumpThread($addr);
$addr= struct('THREAD.pNextInProc', $addr);
last if ($addr==0 || $addr==$firstaddr);
}
}
sub DumpThread {
my $addr= shift;
printf(" hTh=%08lx SP=%08lx LR=%08lx PC=%08lx prio=%02x.%02x start=%08lx kern=%08lx user=%08lx\n",
struct('THREAD.hTh', $addr),
struct('THREAD.ctx.reg_Sp', $addr),
struct('THREAD.ctx.reg_Lr', $addr),
struct('THREAD.ctx.reg_Pc', $addr),
struct('THREAD.bBPrio', $addr),
struct('THREAD.bCPrio', $addr),
struct('THREAD.dwStartAddr', $addr),
struct('THREAD.dwKernTime', $addr),
struct('THREAD.dwUserTime', $addr)
);
if ($g_verbose) {
for (my $cs= struct('THREAD.pcstkTop', $addr) ; $cs ; $cs = struct('CALLSTACK.pcstkNext', $cs)) {
printf("CALLSTACK proc=%08lx addr=%08lx sp=%08lx\n",
struct('CALLSTACK.pprcLast',$cs)?struct('PROCESS.hProc',struct('CALLSTACK.pprcLast',$cs)):0,
struct('CALLSTACK.retAddr',$cs),
struct('CALLSTACK.dwPrevSP',$cs));
}
}
}
package PhysicalMemory;
use Carp;
sub new {
my ($class)= @_;
return bless {}, $class;
}
sub Load {
my ($self, $fn, $base)= @_;
my $fh= IO::File->new($fn, "r") or croak "Physmem::Load $fn: $!\n";
binmode $fh;
$self->{$base}= $fh;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -