📄 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 + -