📄 parsecrash420.pl
字号:
}
sub FindFile {
my ($self, $pofs)= @_;
for (keys %$self) {
if ($_ <= $pofs && $pofs < $_ + -s $self->{$_}) {
return ($_, $self->{$_});
}
}
croak sprintf("PhysicalMemory::FileFile(%08lx) address is not mapped\n", $pofs);
}
sub ReadData {
my ($self, $addr, $size)= @_;
my @chunks;
while ($size>0) {
my ($base, $fh)= $self->FindFile($addr);
if (!$fh) {
croak sprintf("PhysicalMemory::ReadData(%08lx) address is not mapped\n", $addr);
}
$fh->seek($addr-$base, 0) or croak sprintf("PhysicalMemory::ReadData(%08lx): seek %08lx: %s\n", $addr, $addr-$base, $!);
my $data;
$fh->read($data, $size) or croak sprintf("PhysicalMemory::ReadData(%08lx): read %08lx: %s\n", $addr, $size, $!);
push @chunks, $data;
$size -= length($data);
$addr += length($addr);
}
return join("", @chunks);
}
sub ReadByte {
my ($self, $addr)= @_;
return unpack("C", $self->ReadData($addr, 1));
}
sub ReadWord {
my ($self, $addr)= @_;
return unpack("v", $self->ReadData($addr, 2));
}
sub ReadDword {
my ($self, $addr)= @_;
return unpack("V", $self->ReadData($addr, 4));
}
sub ReadString {
my ($self, $addr)= @_;
my $data= $self->ReadData($addr, 64);
$data =~ s/\x00.*//;
return $data;
}
sub ReadWString {
my ($self, $addr)= @_;
if ($addr==0) {
return "(pnull)";
}
my $data= $self->ReadData($addr, 128);
$data= substr($data, 0, index($data, "\x00\x00\x00")+1);
$data= pack("C*", unpack("v*", $data));
return "\"".$data."\"";
}
package VirtualMemory;
use Carp;
# fedcba9876543210fedcba9876543210
# .ssssssbbbbbbbbbpppp............
sub VA_SECTION { 25 }
sub SECTION_MASK { 0x3f }
sub VA_BLOCK { 16 }
sub BLOCK_MASK { 0x1ff }
sub VA_PAGE { 12 }
sub PAGE_MASK { 0xf }
sub BAD_PAGE { ~0xf }
sub NULL_BLOCK { 0 }
sub RESERVED_BLOCK { 1 }
sub new {
my ($class, $img, $physTLBOfs, $virtSectionsOfs)= @_;
my $self= bless {
img=>$img,
physTLBOfs=>$physTLBOfs,
}, $class;
return $self;
}
sub SetSectionTable {
my ($self, $vofs)= @_;
$self->{virtSectionsOfs}= $vofs;
}
sub PhysicalToVirtual {
}
sub VirtualToPhysical {
my ($self, $vofs)= @_;
if ($vofs<0x80000000 || ($vofs>=0xc2000000 && $vofs<0xc4000000)) {
return $self->SectionVirtualToPhysical($vofs);
}
else {
return $self->TLBVirtualToPhysical($vofs);
}
}
sub SectionVirtualToPhysical {
my ($self, $vofs)= @_;
my $ixSection= ($vofs >> VA_SECTION);
$ixSection= 0xb3 if ($ixSection==0x62); # SECURE_SECTION -> KINX_NKSECTION
my $ixBlock = ($vofs >> VA_BLOCK) & BLOCK_MASK;
my $ixPage = ($vofs >> VA_PAGE) & PAGE_MASK;
my $pscn = $self->ReadDword($self->{virtSectionsOfs} + 4*$ixSection);
my $pmb = $self->ReadDword($pscn+4*$ixBlock);
if ($pmb==NULL_BLOCK) {
croak sprintf("SectionVirtualToPhysical(%08lx) : NULL_BLOCK", $vofs);
}
if ($pmb==RESERVED_BLOCK) {
croak sprintf("SectionVirtualToPhysical(%08lx) : RESERVED_BLOCK", $vofs);
}
my $apages= main::struct("MemBlock.aPages", $pmb);
my $dwPageentry= $self->ReadDword($apages+4*$ixPage);
if ($dwPageentry==BAD_PAGE) {
croak sprintf("SectionVirtualToPhysical(%08lx) : BAD_PAGE", $vofs);
}
if ($dwPageentry==0 ) {
croak sprintf("SectionVirtualToPhysical(%08lx) : NULL_PAGE", $vofs);
}
if (($dwPageentry&0xfff00000)==0xfff00000) {
croak sprintf("SectionVirtualToPhysical(%08lx) : invalid memory", $vofs);
}
return ($vofs&0xfff)|($dwPageentry&0xfffff000);
}
sub isValidPtr {
my ($self, $vofs)= @_;
return 0 if ($vofs<0x10000);
return 0 if ($vofs&3);
eval { $self->VirtualToPhysical($vofs); };
return (!$@);
}
sub TLBVirtualToPhysical {
my ($self, $vofs)= @_;
my $firstLevelIndex= $vofs>>20;
my $firstLevelDescriptor= $self->{img}->ReadDword($self->{physTLBOfs}+$firstLevelIndex*4);
for ($firstLevelDescriptor&3) {
if ($_==0) {
croak sprintf("v2p1 %08lx : %08lx -> ignore entry\n", $vofs, $firstLevelDescriptor);
}
elsif ($_==1) {
return $self->CoarseEntry($vofs, $firstLevelDescriptor);
}
elsif ($_==2) {
return $self->SectionEntry($vofs, $firstLevelDescriptor);
}
elsif ($_==3) {
return $self->FineEntry($vofs, $firstLevelDescriptor);
}
}
}
sub CoarseEntry {
my ($self, $vofs, $firstLevelDescriptor)= @_;
my $secondLevelIndex= ($vofs>>12)&0xff;
my $pagetable= $firstLevelDescriptor&0xfffffc00;
my $secondLevelDescriptor= $self->{img}->ReadDword($pagetable+$secondLevelIndex*4);
return $self->SecondLevelPagetable($vofs, $secondLevelDescriptor);
}
sub SectionEntry {
my ($self, $vofs, $firstLevelDescriptor)= @_;
my $sectionbase= $firstLevelDescriptor&0xfff00000;
return $sectionbase | ($vofs&0xfffff);
}
sub FineEntry {
my ($self, $vofs, $firstLevelDescriptor)= @_;
my $secondLevelIndex= ($vofs>>10)&0x3ff;
my $pagetable= $firstLevelDescriptor&0xfffff000;
my $secondLevelDescriptor= $self->{img}->ReadDword($pagetable+$secondLevelIndex*4);
return $self->SecondLevelPagetable($vofs, $secondLevelDescriptor);
}
sub SecondLevelPagetable {
my ($self, $vofs, $secondLevelDescriptor)= @_;
for ($secondLevelDescriptor&3) {
if ($_==0) {
croak sprintf("v2p2: %08lx : %08lx -> ignore entry\n", $vofs, $secondLevelDescriptor);
}
elsif ($_==1) {
return $self->LargePage($vofs, $secondLevelDescriptor);
}
elsif ($_==2) {
return $self->SmallPage($vofs, $secondLevelDescriptor);
}
elsif ($_==3) {
return $self->TinyPage($vofs, $secondLevelDescriptor);
}
}
}
sub LargePage {
my ($self, $vofs, $secondLevelDescriptor)= @_;
return ($secondLevelDescriptor&0xffff0000) | ($vofs&0xffff);
}
sub SmallPage {
my ($self, $vofs, $secondLevelDescriptor)= @_;
return ($secondLevelDescriptor&0xfffff000) | ($vofs&0xfff);
}
sub TinyPage {
my ($self, $vofs, $secondLevelDescriptor)= @_;
return ($secondLevelDescriptor&0xfffffc00) | ($vofs&0x3ff);
}
###############################
# todo: these functions don't handle page boundaries.
sub ReadData {
my ($self, $vofs, @args)= @_;
return $self->{img}->ReadData($self->VirtualToPhysical($vofs), @args);
}
sub ReadByte {
my ($self, $vofs, @args)= @_;
return $self->{img}->ReadByte($self->VirtualToPhysical($vofs), @args);
}
sub ReadWord {
my ($self, $vofs, @args)= @_;
return $self->{img}->ReadWord($self->VirtualToPhysical($vofs), @args);
}
sub ReadDword {
my ($self, $vofs, @args)= @_;
return $self->{img}->ReadDword($self->VirtualToPhysical($vofs), @args);
}
sub ReadString {
my ($self, $vofs, @args)= @_;
return $self->{img}->ReadString($self->VirtualToPhysical($vofs), @args);
}
sub ReadWString {
my ($self, $vofs, @args)= @_;
if ($vofs==0) {
return "(vnull)";
}
my $str;
eval {
$str= $self->{img}->ReadWString($self->VirtualToPhysical($vofs), @args);
};
if ($@) {
return "(invalid)";
}
return $str;
}
package main;
__DATA__
!kdata
0xFFFD0000 firstpagetabel
0xFFFE0000 secondpagetabel
0xFFFF0000 exceptionvectors
0xFFFFC800 lpvTls Current thread local storage pointer
0xFFFFC804 ahSys_W32
0xFFFFC808 hCurThread
0xFFFFC80C hCurProc
0xFFFFC810 ahSys_KW32
0xFFFFC884 bResched reschedule flag
0xFFFFC885 cNest kernel exception nesting
0xFFFFC886 bPowerOff TRUE during "power off" processing
0xFFFFC887 bProfileOn TRUE if profiling enabled
0xFFFFC888 unused
0xFFFFC88C rsvd2 was DiffMSec
0xFFFFC890 pCurPrc ptr to current PROCESS struct
0xFFFFC894 pCurThd ptr to current THREAD struct
0xFFFFC898 dwKCRes
0xFFFFC89C handleBase handle table base address
0xFFFFC8A0 aSections section table for virutal memory
0xFFFFC9A0 alpeIntrEvents
0xFFFFCA20 alpvIntrData
0xFFFFCAA0 pAPIReturn direct API return address for kernel mode
0xFFFFCAA4 pMap ptr to MemoryMap array
0xFFFFCAA8 dwInDebugger !0 when in debugger
0xFFFFCAAC pCurFPUOwner current FPU owner
0xFFFFCAB0 pCpuASIDPrc current ASID proc
0xFFFFCAB4 nMemForPT Memory used for PageTables
0xFFFFCAB8 alPad
0xFFFFCB00 KINX_PROCARRAY address of process array
0xFFFFCB04 KINX_PAGESIZE system page size
0xFFFFCB08 KINX_PFN_SHIFT shift for page # in PTE
0xFFFFCB0C KINX_PFN_MASK mask for page # in PTE
0xFFFFCB10 KINX_PAGEFREE # of free physical pages
0xFFFFCB14 KINX_SYSPAGES # of pages used by kernel
0xFFFFCB18 KINX_KHEAP ptr to kernel heap array
0xFFFFCB1C KINX_SECTIONS ptr to SectionTable array
0xFFFFCB20 KINX_MEMINFO ptr to system MemoryInfo struct
0xFFFFCB24 KINX_MODULES ptr to module list
0xFFFFCB28 KINX_DLL_LOW lower bound of DLL shared space
0xFFFFCB2C KINX_NUMPAGES total # of RAM pages
0xFFFFCB30 KINX_PTOC ptr to ROM table of contents points to ROMHDR struct
0xFFFFCB34 KINX_KDATA_ADDR kernel mode version of KData
0xFFFFCB38 KINX_GWESHEAPINFO Current amount of gwes heap in use
0xFFFFCB3C KINX_TIMEZONEBIAS Fast timezone bias info
0xFFFFCB40 KINX_PENDEVENTS bit mask for pending interrupt events
0xFFFFCB44 KINX_KERNRESERVE number of kernel reserved pages
0xFFFFCB48 KINX_API_MASK bit mask for registered api sets
0xFFFFCB4C KINX_NLS_CP hiword OEM code page, loword ANSI code page
0xFFFFCB50 KINX_NLS_SYSLOC Default System locale
0xFFFFCB54 KINX_NLS_USERLOC Default User locale
0xFFFFCB58 KINX_HEAP_WASTE Kernel heap wasted space
0xFFFFCB5C KINX_DEBUGGER For use by debugger for protocol communication
0xFFFFCB60 KINX_APISETS APIset pointers
0xFFFFCB64 KINX_MINPAGEFREE water mark of the minimum number of free pages
0xFFFFCB68 KINX_CELOGSTATUS CeLog status flags
0xFFFFCB6C KINX_NKSECTION Address of NKSection
0xFFFFCB70 KINX_PWR_EVTS Events to be set after power on
0xFFFFCB74 KINX_29
0xFFFFCB78 KINX_30
0xFFFFCB7C KINX_NKSIG last entry of KINFO -- signature when NK is ready
!handletypes
0x00 SH_WIN32
0x01 SH_CURTHREAD
0x02 SH_CURPROC
0x04 HT_EVENT // Event handle type
0x05 HT_MUTEX // Mutex handle type
0x06 HT_APISET // kernel API set handle type
0x07 HT_FILE // open file handle type
0x08 HT_FIND // FindFirst handle type
0x09 HT_DBFILE // open database handle type
0x0a HT_DBFIND // database find handle type
0x0b HT_SOCKET // WinSock open socket handle type
0x0c HT_INTERFACE
0x0d HT_SEMAPHORE // Semaphore handle type
0x0e HT_FSMAP // mapped files
0x0f HT_WNETENUM // Net Resource Enumeration
0x10 SH_GDI
0x11 SH_WMGR
0x12 SH_WNET
0x13 SH_COMM
0x14 SH_FILESYS_APIS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -