📄 dumprom.cpp
字号:
if (buflen!=CEDECOMPRESS_FAILED)
{
buf= dcbuf;
}
else {
printf("error decompressing %s\n", filename);
buflen= end-start;
delete dcbuf;
bCompressed=false;
}
}
char fn[1024];
if (regnr<0)
_snprintf(fn, 1024, "%s/%s", g_outputdirectory, filename);
else
_snprintf(fn, 1024, "%s/%s-%d-%08lx", g_outputdirectory, filename, regnr, realofs);
FILE *f= fopen(fn, "w+b");
if (f==NULL)
{
perror(fn);
if (bCompressed)
delete buf;
return;
}
DWORD nWritten= fwrite(buf, 1, buflen, f);
if (nWritten!=buflen)
{
printf("error writing %ld bytes - wrote %ld\n", buflen, nWritten);
perror(fn);
}
fclose(f);
if (bCompressed)
delete buf;
}
bool isObjectContainsSection(const o32_rom& o32, const info& inf)
{
return o32.o32_rva <= inf.rva && inf.rva+inf.size <= o32.o32_rva + o32.o32_vsize;
}
void CreateOriginalFile(const ROMHDR *rom, const TOCentry *t, const char *filename, const e32_rom *e32, const o32_rom *o32)
{
char fn[1024];
_snprintf(fn, 1024, "%s/%s", g_outputdirectory, filename);
FILE *f= fopen(fn, "w+b");
if (f==NULL)
{
perror(fn);
return;
}
WriteDummyMZHeader(f);
DWORD dwE32Ofs= ftell(f);
WriteE32Header(f, rom, e32, t, o32);
vector<DWORD> o32ofslist; // list of file offsets to o32_obj structs
vector<DWORD> dataofslist; // list of file offsets to start of data objects
vector<DWORD> datalenlist;
typedef map<DWORD, std::pair<DWORD,DWORD> > RvaRvaSizeMap;
RvaRvaSizeMap rvamap; // map of rva -> adjusted rva
memset(g_segmentNameUsage, 0, sizeof(g_segmentNameUsage));
int i;
for (i=0 ; i<e32->e32_objcnt ; i++)
{
o32ofslist.push_back(ftell(f));
DWORD rva= WriteO32Header(f, e32, &o32[i]);
if (rva != o32[i].o32_rva)
printf("NOTE: section at %08lx iso %08lx for %s\n", rva, o32[i].o32_rva, filename);
rvamap[o32[i].o32_rva]= std::pair<DWORD,DWORD>(rva, o32[i].o32_vsize);
}
WriteAlignment(f, 0x200);
DWORD dwHeaderSize= ftell(f);
for (i=0 ; i<e32->e32_objcnt ; i++)
{
dataofslist.push_back(ftell(f));
DWORD datalen= WriteUncompressedData(f, o32[i].o32_dataptr, min(o32[i].o32_vsize, o32[i].o32_psize), o32[i].o32_flags&IMAGE_SCN_COMPRESSED, o32[i].o32_vsize);
datalenlist.push_back(datalen);
WriteAlignment(f, 0x200);
}
DWORD dwTotalFileSize= ftell(f);
// fix rawdatalen + dataoffsets in segment list
for (i=0 ; i<e32->e32_objcnt ; i++)
{
fseek(f, o32ofslist[i]+16, SEEK_SET);
fwrite(&datalenlist[i], 1, sizeof(DWORD), f); // ofs to o32_psize
fwrite(&dataofslist[i], 1, sizeof(DWORD), f); // ofs to o32_dataptr
// update imp_address's in IMP section
if (b_use_negative_rva && isObjectContainsSection(o32[i], e32->e32_unit[IMP])) {
fseek(f, dataofslist[i]+ e32->e32_unit[IMP].rva -o32[i].o32_rva+0x10, SEEK_SET );
while (1) {
DWORD imp_addr;
fread(&imp_addr, 1, sizeof(DWORD), f); // read ImpHdr.imp_address
if (imp_addr==0)
break;
// this finds the next rva
RvaRvaSizeMap::iterator s= rvamap.upper_bound(imp_addr);
if (s!=rvamap.end() && s!=rvamap.begin()) {
s--;
if (imp_addr < (*s).first+(*s).second.second) {
// printf("moving imp %08lx from rva[%08lx-%08lx] -> %08lx-%08lx : %08lx\n",
// imp_addr, (*s).first, (*s).first+(*s).second.second,
// (*s).second.first, (*s).second.first+(*s).second.second,
// imp_addr-(*s).first +(*s).second.first);
imp_addr -= (*s).first -(*s).second.first;
fseek(f, -4, SEEK_CUR);
fwrite(&imp_addr, 1, sizeof(DWORD), f);
fseek(f, 0x10, SEEK_CUR);
}
else {
printf("!!! %08lx after %08lx but not before %08lx\n", imp_addr, (*s).first, (*s).first+(*s).second.second);
}
}
}
}
}
fseek(f, dwE32Ofs+0x54, SEEK_SET); // ofs to e32_hdrsize
fwrite(&dwHeaderSize, 1, sizeof(DWORD), f);
fseek(f, dwTotalFileSize, SEEK_SET);
fclose(f);
//todo: set fileattributes + datetime.
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
void DumpXIPChainEntry(int xipnr, XIPCHAIN_ENTRY *xip)
{
g_regions.MarkRegion(g_mem.GetOfs(xip), sizeof(XIPCHAIN_ENTRY), "xip%d : %s", xipnr, xip->szName);
g_regions.MarkRegion((DWORD)xip->pvAddr, 0, "start xip%d : %s", xipnr, xip->szName);
if (g_verbose)
g_regions.MarkRegion((DWORD)xip->pvAddr+xip->dwLength, 0, "end xip%d : %s", xipnr, xip->szName);
}
void DumpXIPChain(DWORD dwXipOffset)
{
XIPCHAIN_INFO *xipchain= (XIPCHAIN_INFO *)g_mem.GetPtr(dwXipOffset);
if (xipchain==NULL)
return;
if (xipchain->cXIPs > MAX_ROM)
{
printf("ERROR - invalid xipchain\n");
return;
}
g_regions.MarkRegion(dwXipOffset, sizeof(DWORD), "xipchain head");
XIPCHAIN_ENTRY *xip= &xipchain->xipEntryStart;
for (DWORD i=0 ; i<xipchain->cXIPs ; ++i)
{
DumpXIPChainEntry(i, &xip[i]);
}
}
typedef std::set<DWORD> DwordSet;
DwordSet g_extensions_processed;
bool extensionAlreadyProcessed(DWORD dwOffset)
{
DwordSet::iterator it = g_extensions_processed.find(dwOffset);
return it != g_extensions_processed.end();
}
void recordExtensionProcessed(DWORD dwOffset)
{
g_extensions_processed.insert(dwOffset);
}
void DumpExtensions(DWORD dwPidOffset)
{
if (extensionAlreadyProcessed(dwPidOffset))
return;
recordExtensionProcessed(dwPidOffset);
ROMPID *pid= (ROMPID *)g_mem.GetPtr(dwPidOffset);
if (pid==NULL)
return;
// first is inside nk.exe
pid= (ROMPID*)g_mem.GetPtr(dwPidOffset=(DWORD)pid->pNextExt);
while (pid) {
g_regions.MarkRegion(dwPidOffset, sizeof(ROMPID), "rom extension entry %s", pid->s.name);
g_regions.MarkRegion((DWORD)pid->s.pdata, pid->s.length, "rom extension data %s", pid->s.name);
pid= (ROMPID*)g_mem.GetPtr(dwPidOffset=(DWORD)pid->pNextExt);
}
}
void DumpModuleTOCentry(const ROMHDR *rom, int modnr, DWORD ofs)
{
TOCentry *t= (TOCentry *)g_mem.GetPtr(ofs);
if (t==NULL)
{
printf("invalid modtoc ofs %08lx\n", ofs);
return;
}
char *filename= (char *)g_mem.GetPtr((DWORD)t->lpszFileName);
if (filename==NULL)
return;
g_regions.MarkRegion(ofs, sizeof(TOCentry), "modent %3d %08lx %08lx%08lx %8d %08lx %s",
modnr, t->dwFileAttributes, t->ftTime.dwHighDateTime, t->ftTime.dwLowDateTime, t->nFileSize, t->ulLoadOffset, filename);
g_regions.MarkRegion((DWORD)t->lpszFileName, strlen(filename)+1, "modname %s", filename);
e32_rom *e32= (e32_rom *)g_mem.GetPtr((DWORD)t->ulE32Offset);
if (e32==NULL)
return;
if (b_wm2005_rom) {
printf("NOTE: removing %08lx from e32 struct for %s\n", *(DWORD*)e32->e32_unit, filename);
memmove((BYTE*)e32->e32_unit, (BYTE*)e32->e32_unit+4, ROM_EXTRA*sizeof(struct info)+sizeof(DWORD));
}
MemRegion &m= g_regions.MarkRegion((DWORD)t->ulE32Offset, sizeof(e32_rom)+(b_wm2005_rom?4:0), "e32 struct %d objs, img=%04x entrypt=%08lx base=%08lx v%d.%d tp%d %s",
e32->e32_objcnt, e32->e32_imageflags, e32->e32_entryrva, e32->e32_vbase, e32->e32_subsysmajor, e32->e32_subsysminor, e32->e32_subsys, filename);
o32_rom *o32= (o32_rom *)g_mem.GetPtr((DWORD)t->ulO32Offset);
if (o32==NULL)
return;
if (g_verbose) {
*m.description += dworddumpasstring(t->ulE32Offset, t->ulE32Offset+sizeof(e32_rom)+(b_wm2005_rom?4:0));
}
m= g_regions.MarkRegion((DWORD)t->ulO32Offset, e32->e32_objcnt*sizeof(o32_rom), "o32 struct %s", filename);
for (int i= 0 ; i<e32->e32_objcnt ; ++i)
{
m= g_regions.MarkRegion(o32[i].o32_dataptr ? o32[i].o32_dataptr : ofs, min(o32[i].o32_vsize, o32[i].o32_psize),
"o32 region_%d rva=%08lx vsize=%08lx real=%08lx psize=%08lx f=%08lx for %s", i, o32[i].o32_rva, o32[i].o32_vsize, o32[i].o32_realaddr, o32[i].o32_psize, o32[i].o32_flags, filename);
// if (g_outputdirectory)
// UncompressAndWrite(m.start, m.end, filename, i, o32[i].o32_flags&IMAGE_SCN_COMPRESSED, o32[i].o32_vsize, o32[i].o32_realaddr);
}
if (g_outputdirectory)
CreateOriginalFile(rom, t, filename, e32, o32);
}
void DumpFileTOCentry(int filenr, DWORD ofs)
{
FILESentry *t= (FILESentry *)g_mem.GetPtr(ofs);
if (t==NULL)
{
printf("invalid filetoc ofs %08lx\n", ofs);
return;
}
char *filename= (char *)g_mem.GetPtr((DWORD)t->lpszFileName);
if (filename==NULL)
return;
g_regions.MarkRegion(ofs, sizeof(FILESentry), "filent %3d %08lx %08lx%08lx %8d %8d %08lx %s",
filenr, t->dwFileAttributes, t->ftTime.dwHighDateTime, t->ftTime.dwLowDateTime, t->nRealFileSize, t->nCompFileSize, t->ulLoadOffset, filename);
g_regions.MarkRegion((DWORD)t->lpszFileName, strlen(filename)+1, "filename %s", filename);
MemRegion &m= g_regions.MarkRegion((DWORD)t->ulLoadOffset, t->nCompFileSize, "filedata %s", filename);
if (g_outputdirectory)
UncompressAndWrite(m.start, m.end, filename, -1, t->nCompFileSize!=t->nRealFileSize, t->nRealFileSize, t->ulLoadOffset);
}
void DumpRomHdr(int romnr, DWORD ofs)
{
ROMHDR *r= (ROMHDR *)g_mem.GetPtr(ofs);
if (r==NULL)
{
printf("invalid romhdr ofs %08lx\n", ofs);
return;
}
// r->ulRAMFree r->ulFSRamPercent,
MemRegion &m= g_regions.MarkRegion(ofs, sizeof(ROMHDR),
"rom_%02d header: dlls=%08lx-%08lx phys=%08lx-%08lx, %d modules, %d files, %d copyentries ext=%08lx ram=%08lx-%08lx cputype=%08lx",
romnr, r->dllfirst, r->dlllast, r->physfirst, r->physlast,
r->nummods, r->numfiles, r->ulCopyEntries, r->pExtensions,
r->ulRAMStart, r->ulRAMEnd, r->usCPUType);
if (g_verbose) {
*m.description += dworddumpasstring(ofs, ofs+sizeof(ROMHDR));
}
g_regions.MarkRegion(r->physfirst, 0, "rom_%02d start", romnr);
g_regions.MarkRegion(r->physlast, 0, "rom_%02d end", romnr);
if (r->pExtensions)
DumpExtensions((DWORD)r->pExtensions);
DWORD i;
TOCentry *tm= (TOCentry *)&r[1];
for (i=0 ; i<r->nummods; i++)
{
DumpModuleTOCentry(r, i, g_mem.GetOfs(&tm[i]));
}
FILESentry *tf= (FILESentry *)&tm[r->nummods];
for (i=0 ; i<r->numfiles; i++)
{
DumpFileTOCentry(i, g_mem.GetOfs(&tf[i]));
}
if (r->ulCopyEntries) {
COPYentry *cp= (COPYentry *)g_mem.GetPtr(r->ulCopyOffset);
if (cp==NULL)
return;
MemRegion &m= g_regions.MarkRegion(r->ulCopyOffset, sizeof(COPYentry)*r->ulCopyEntries, "rom_%02d copy to ram: ", romnr);
for (DWORD i=0 ; i<r->ulCopyEntries ; ++i)
{
char buf[64];
_snprintf(buf, 64, " %08lxL%06lx -> %08lxL%06lx", cp->ulSource, cp->ulCopyLen, cp->ulDest, cp->ulDestLen);
*m.description += buf;
}
}
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
typedef map<DWORD,DWORD> MapDwordDword;
struct ScoreCmp {
ScoreCmp(const MapDwordDword& map) : m_map(map) {}
bool operator()(DWORD a, DWORD b) {
return m_map[a] > m_map[b];
}
MapDwordDword m_map;
};
DWORD FindXipRegion()
{
// find all occurrences of 'RSA1'
// '0x48' = offset in struct + xip header
vector<DWORD> pos;
for (MemoryMapIterator i(g_mem.begin()) ; i!=g_mem.end() ; i+=4)
{
if (i.GetDword()==0x31415352)
pos.push_back(i.m_ofs-0x48);
}
// look for sequence of 'RSA1'
MapDwordDword posscore;
DWORD start=0;
for(vector<DWORD>::iterator i= pos.begin() ; i!=pos.end() ; ++i)
{
if (!start || *i != start+0x290) {
start= *i;
posscore[start]++;
}
else {
posscore[start]++;
}
}
sort(pos.begin(), pos.end(), ScoreCmp(posscore));
// try in descending nr of hits
for (MapDwordDword::iterator i= posscore.begin() ; i!=posscore.end() ; ++i)
{
if ((*i).first % 0x1000)
continue;
DWORD nxips= g_mem.GetDword((*i).first);
if (nxips>= (*i).second)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -