📄 loader.c
字号:
blockptr = (struct info *)(((ulong)blockptr)+blockptr->size);
continue;
}
dataptr = 0;
while ((ulong)currptr < ((ulong)blockptr+blockptr->size)) {
curroff = *currptr&0xfff;
if (!curroff && !blockptr->rva) {
currptr++;
continue;
}
if (!dataptr || (dataptr->o32_rva > blockptr->rva + curroff) ||
(dataptr->o32_rva + dataptr->o32_vsize <= blockptr->rva + curroff)) {
for (loop = 0; loop < eptr->e32_objcnt; loop++) {
dataptr = &oarry[loop];
if ((dataptr->o32_rva <= blockptr->rva + curroff) &&
(dataptr->o32_rva+dataptr->o32_vsize > blockptr->rva + curroff))
break;
}
}
DEBUGCHK(loop != eptr->e32_objcnt);
FixupAddress = (LPDWORD)(blockptr->rva - dataptr->o32_rva + curroff + dataptr->o32_realaddr);
DEBUGMSG(ZONE_LOADER2,(TEXT("type %d, low %8.8lx, page %8.8lx, addr %8.8lx, op %8.8lx\r\n"),
(*currptr>>12)&0xf, (*currptr)&0x0fff,blockptr->rva,FixupAddress,*FixupAddress));
switch (*currptr>>12) {
case IMAGE_REL_BASED_ABSOLUTE: // Absolute - no fixup required.
break;
case IMAGE_REL_BASED_HIGH: // Save the address and go to get REF_LO paired with this one
FixupAddressHi = (LPWORD)FixupAddress;
MatchedReflo = TRUE;
break;
case IMAGE_REL_BASED_LOW: // Low - (16-bit) relocate high part too.
if (MatchedReflo) {
FixupValue = (DWORD)(long)((*FixupAddressHi) << 16) +
*(LPWORD)FixupAddress + offset;
*FixupAddressHi = (short)((FixupValue + 0x8000) >> 16);
MatchedReflo = FALSE;
} else
FixupValue = *(short *)FixupAddress + offset;
*(LPWORD)FixupAddress = (WORD)(FixupValue & 0xffff);
break;
case IMAGE_REL_BASED_HIGHLOW: // Word - (32-bits) relocate the entire address.
if ((DWORD)FixupAddress & 0x3)
*(UNALIGNED DWORD *)FixupAddress += (DWORD)offset;
else
*FixupAddress += (DWORD)offset;
break;
case IMAGE_REL_BASED_HIGHADJ: // 32 bit relocation of 16 bit high word, sign extended
DEBUGMSG(ZONE_LOADER2,(TEXT("Grabbing extra data %8.8lx\r\n"),*(currptr+1)));
*(LPWORD)FixupAddress += (WORD)((*(short *)(++currptr)+offset+0x8000)>>16);
break;
case IMAGE_REL_BASED_MIPS_JMPADDR: // jump to 26 bit target (shifted left 2)
FixupValue = ((*FixupAddress)&0x03ffffff) + (offset>>2);
*FixupAddress = (*FixupAddress & 0xfc000000) | (FixupValue & 0x03ffffff);
break;
#if defined(MIPS16SUPPORT)
case IMAGE_REL_BASED_MIPS_JMPADDR16: // MIPS16 jal/jalx to 26 bit target (shifted left 2)
FixupValue = (*(LPWORD)FixupAddress) & 0x03ff;
FixupValue = (((FixupValue >> 5) | ((FixupValue & 0x1f) << 5)) << 16) | *((LPWORD)FixupAddress+1);
FixupValue += offset >> 2;
*((LPWORD)FixupAddress+1) = (WORD)(FixupValue & 0xffff);
FixupValue = (FixupValue >> 16) & 0x3ff;
*(LPWORD)FixupAddress = (WORD) ((*(LPWORD)FixupAddress & 0x1c00) | (FixupValue >> 5) | ((FixupValue & 0x1f) << 5));
break;
#endif
default :
DEBUGMSG(ZONE_LOADER1,(TEXT("Not doing fixup type %d\r\n"),*currptr>>12));
DEBUGCHK(0);
break;
}
DEBUGMSG(ZONE_LOADER2,(TEXT("reloc complete, new op %8.8lx\r\n"),*FixupAddress));
currptr++;
}
blockptr = (struct info *)(((ulong)blockptr)+blockptr->size);
}
return TRUE;
}
DWORD ResolveImpOrd(PMODULE pMod, DWORD ord);
DWORD ResolveImpStr(PMODULE pMod, LPCSTR str);
DWORD ResolveImpHintStr(PMODULE pMod, DWORD hint, LPCHAR str);
#define MAX_AFE_FILESIZE 32
DWORD Katoi(LPCHAR str) {
DWORD retval = 0;
while (*str) {
retval = retval * 10 + (*str-'0');
str++;
}
return retval;
}
// Get address from export entry
DWORD AddrFromEat(PMODULE pMod, DWORD eat) {
WCHAR filename[MAX_AFE_FILESIZE];
PMODULE pMod2;
LPCHAR str;
int loop;
if ((eat < pMod->e32.e32_unit[EXP].rva) ||
(eat >= pMod->e32.e32_unit[EXP].rva + pMod->e32.e32_unit[EXP].size))
return eat+ (pMod->DbgFlags & DBG_IS_DEBUGGER ? (DWORD)pMod->BasePtr : ZeroPtr(pMod->BasePtr));
else {
str = (LPCHAR)(eat + (ulong)pMod->BasePtr);
for (loop = 0; loop < MAX_AFE_FILESIZE-1; loop++)
if ((filename[loop] = (WCHAR)*str++) == (WCHAR)'.')
break;
filename[loop] = 0;
if (!(pMod2 = LoadOneLibraryPart2(filename,1,0)))
return 0;
if (*str == '#')
return ResolveImpOrd(pMod2,Katoi(str));
else
return ResolveImpStr(pMod2,str);
}
}
// Get address from ordinal
DWORD ResolveImpOrd(PMODULE pMod, DWORD ord) {
struct ExpHdr *expptr;
LPDWORD eatptr;
DWORD hint;
DWORD retval;
if (!pMod->e32.e32_unit[EXP].rva)
return 0;
expptr = (struct ExpHdr *)((ulong)pMod->BasePtr+pMod->e32.e32_unit[EXP].rva);
eatptr = (LPDWORD)(expptr->exp_eat + (ulong)pMod->BasePtr);
hint = ord - expptr->exp_ordbase;
retval = (hint >= expptr->exp_eatcnt ? 0 : AddrFromEat(pMod,eatptr[hint]));
// ERRORMSG(!retval,(TEXT("Can't find ordinal %d in module %s\r\n"),ord,pMod->lpszModName));
return retval;
}
// Get address from string
DWORD ResolveImpStr(PMODULE pMod, LPCSTR str) {
struct ExpHdr *expptr;
LPCHAR *nameptr;
LPDWORD eatptr;
LPWORD ordptr;
DWORD retval;
ulong loop;
if (!pMod->e32.e32_unit[EXP].rva)
return 0;
expptr = (struct ExpHdr *)((ulong)pMod->BasePtr+pMod->e32.e32_unit[EXP].rva);
nameptr = (LPCHAR *)(expptr->exp_name + (ulong)pMod->BasePtr);
eatptr = (LPDWORD)(expptr->exp_eat + (ulong)pMod->BasePtr);
ordptr = (LPWORD)(expptr->exp_ordinal + (ulong)pMod->BasePtr);
for (loop = 0; loop < expptr->exp_namecnt; loop++)
if (!strcmp(str,nameptr[loop]+(ulong)pMod->BasePtr))
break;
if (loop == expptr->exp_namecnt)
retval = 0;
else
retval = (loop >= expptr->exp_eatcnt ? 0 : AddrFromEat(pMod,eatptr[ordptr[loop]]));
// ERRORMSG(!retval,(TEXT("Can't find import %a in module %s\r\n"),str,pMod->lpszModName));
return retval;
}
// Get address from hint and string
DWORD ResolveImpHintStr(PMODULE pMod, DWORD hint, LPCHAR str) {
struct ExpHdr *expptr;
LPCHAR *nameptr;
LPDWORD eatptr;
LPWORD ordptr;
DWORD retval;
if (!pMod->e32.e32_unit[EXP].rva)
return 0;
expptr = (struct ExpHdr *)((ulong)pMod->BasePtr+pMod->e32.e32_unit[EXP].rva);
nameptr = (LPCHAR *)(expptr->exp_name + (ulong)pMod->BasePtr);
eatptr = (LPDWORD)(expptr->exp_eat + (ulong)pMod->BasePtr);
ordptr = (LPWORD)(expptr->exp_ordinal + (ulong)pMod->BasePtr);
if ((hint >= expptr->exp_namecnt) || (strcmp(str,nameptr[hint] + (ulong)pMod->BasePtr)))
retval = ResolveImpStr(pMod,str);
else
retval = AddrFromEat(pMod,eatptr[ordptr[hint]]);
// ERRORMSG(!retval,(TEXT("Can't find import %a (hint %d) in %s\r\n"),str,hint,pMod->lpszModName));
return retval;
}
// Increment process reference count to module, return old count
WORD IncRefCount(PMODULE pMod) {
if (!(pMod->inuse & (1<<pCurProc->procnum))) {
pMod->inuse |= (1<<pCurProc->procnum);
pMod->calledfunc &= ~(1<<pCurProc->procnum);
}
return pMod->refcnt[pCurProc->procnum]++;
}
// Decrement process reference count to module, return new count
WORD DecRefCount(PMODULE pMod) {
if (!(--pMod->refcnt[pCurProc->procnum]))
pMod->inuse &= ~(1<<pCurProc->procnum);
return pMod->refcnt[pCurProc->procnum];
}
typedef BOOL (*entry_t)(HANDLE,DWORD,LPVOID);
typedef BOOL (*comentry_t)(HANDLE,DWORD,LPVOID,LPVOID,DWORD,DWORD);
// Remove module from linked list
void UnlinkModule(PMODULE pMod) {
PMODULE ptr1, ptr2;
EnterCriticalSection(&ModListcs);
if (pModList == pMod)
pModList = pMod->pMod;
else if (pModList) {
ptr1 = pModList;
ptr2 = pModList->pMod;
while (ptr2 && (ptr2 != pMod)) {
ptr1 = ptr2;
ptr2 = ptr2->pMod;
}
if (ptr2)
ptr1->pMod = ptr2->pMod;
}
LeaveCriticalSection(&ModListcs);
}
// Unmap module from process
void UnCopyRegions(PMODULE pMod) {
long basediff = pCurProc->dwVMBase - ProcArray[0].dwVMBase;
VirtualFree((LPVOID)((long)pMod->BasePtr+basediff),pMod->e32.e32_vsize,MEM_DECOMMIT|0x80000000);
VirtualFree((LPVOID)((long)pMod->BasePtr+basediff),0,MEM_RELEASE);
}
void FreeModuleMemory(PMODULE pMod) {
UnlinkModule(pMod);
VirtualFree(pMod->BasePtr,pMod->e32.e32_vsize,MEM_DECOMMIT|0x80000000);
if (ZeroPtr(pMod->BasePtr) < pTOC->dllfirst)
VirtualFree(pMod->BasePtr,0,MEM_RELEASE);
if ((ZeroPtr(pMod->BasePtr) > ZeroPtr(pMod->lpszModName)) ||
(ZeroPtr(pMod->BasePtr) + pMod->e32.e32_vsize <= ZeroPtr(pMod->lpszModName)))
VirtualFree(pMod->lpszModName,0,MEM_RELEASE);
if ((ZeroPtr(pMod->BasePtr) > ZeroPtr(pMod->o32_ptr)) ||
(ZeroPtr(pMod->BasePtr) + pMod->e32.e32_vsize <= ZeroPtr(pMod->o32_ptr)))
VirtualFree(pMod->o32_ptr,0,MEM_RELEASE);
CloseExe(&pMod->oe);
FreeMem(pMod,HEAP_MODULE);
}
void FreeLibraryByName(LPCHAR lpszName);
// Free library from proc (by name), zeroing reference count
VOID FreeLibraryFromProc(PMODULE pMod, PPROCESS pproc) {
if (pMod->refcnt[pproc->procnum]) {
pMod->refcnt[pproc->procnum] = 0;
pMod->inuse &= ~(1 << pproc->procnum);
if (SystemAPISets[SH_PATCHER])
FreeDllPatch(pproc,pMod);
if (!pMod->inuse) {
KDUpdateSymbols(((DWORD)pMod->BasePtr)+1, TRUE);
CELOG_ModuleFree(pCurProc->hProc, (HANDLE)pMod, TRUE);
FreeModuleMemory(pMod);
}
}
}
// Free all libraries from proc
VOID FreeAllProcLibraries(PPROCESS pProc) {
PMODULE pMod, pNext;
EnterCriticalSection(&LLcs);
pMod = pModList;
while (pMod) {
pNext = pMod->pMod;
FreeLibraryFromProc(pMod,pProc);
pMod = pNext;
}
LeaveCriticalSection(&LLcs);
}
// Pass Reason/Reserved to DLL entry point for pMod
BOOL CallDLLEntry(PMODULE pMod, DWORD Reason, LPVOID Reserved) {
BOOL retval = TRUE;
DWORD LastError = KGetLastError(pCurThread);
DWORD dwOldMode;
if (pMod->startip && !(pMod->wFlags & DONT_RESOLVE_DLL_REFERENCES)) {
if ((dwOldMode = GET_TIMEMODE(pCurThread)) == TIMEMODE_KERNEL)
GoToUserTime();
if (Reason == DLL_PROCESS_ATTACH) {
if (pMod->calledfunc & (1<<pCurProc->procnum))
goto DontCall;
pMod->calledfunc |= (1<<pCurProc->procnum);
} else if (Reason == DLL_PROCESS_DETACH) {
if (!(pMod->calledfunc & (1<<pCurProc->procnum)))
goto DontCall;
pMod->calledfunc &= ~(1<<pCurProc->procnum);
}
__try {
if (pMod->e32.e32_sect14rva)
retval = ((comentry_t)pMod->startip)((HANDLE)pMod,Reason,Reserved,
(LPVOID)ZeroPtr(pMod->BasePtr),pMod->e32.e32_sect14rva,pMod->e32.e32_sect14size);
else
retval = ((entry_t)pMod->startip)((HANDLE)pMod,Reason,Reserved);
} __except (EXCEPTION_EXECUTE_HANDLER) {
retval = FALSE;
}
DontCall:
if (dwOldMode == TIMEMODE_KERNEL)
GoToUserTime();
}
KSetLastError(pCurThread,LastError);
return retval;
}
BOOL UnDoDepends(PMODULE pMod);
// Decrement ref count on pMod (from hCurProc), freeing if needed
BOOL FreeOneLibraryPart2(PMODULE pMod, BOOL bCallEntry) {
struct ImpHdr *blockptr;
CELOG_ModuleFree(pCurProc->hProc, (HANDLE)pMod, FALSE);
if (HasBreadcrumb(pMod))
return TRUE;
SetBreadcrumb(pMod);
if (HasModRefProcPtr(pMod,pCurProc)) {
if (!DecRefCount(pMod)) {
if (bCallEntry)
CallDLLEntry(pMod,DLL_PROCESS_DETACH,0);
if (pMod->e32.e32_sect14size)
FreeLibraryByName("mscoree.dll");
pMod->dwNoNotify &= ~(1 << pCurProc->procnum);
if(pMod->pmodResource) {
FreeOneLibraryPart2(pMod, 0); // DONT call dllentry of RES dll
pMod->pmodResource = 0;
}
if (!(pMod->wFlags & DONT_RESOLVE_DLL_REFERENCES))
UnDoDepends(pMod);
UnCopyRegions(pMod);
if (SystemAPISets[SH_PATCHER])
FreeDllPatch(pCurProc, pMod);
if (pCurThread->pThrdDbg && ProcStarted(pCurProc) && pCurThread->pThrdDbg->hEvent) {
pCurThread->pThrdDbg->dbginfo.dwProcessId = (DWORD)hCurProc;
pCurThread->pThrdDbg->dbginfo.dwThreadId = (DWORD)hCurThread;
pCurThread->pThrdDbg->dbginfo.dwDebugEventCode = UNLOAD_DLL_DEBUG_EVENT;
pCurThread->pThrdDbg->dbginfo.u.UnloadDll.lpBaseOfDll = (LPVOID)ZeroPtr(pMod->BasePtr);
SetEvent(pCurThread->pThrdDbg->hEvent);
SC_WaitForMultiple(1,&pCurThread->pThrdDbg->hBlockEvent,FALSE,INFINITE);
}
} else {
if (!(pMod->wFlags & DONT_RESOLVE_DLL_REFERENCES))
UnDoDepends(pMod);
}
if (!pMod->inuse) {
CELOG_ModuleFree(pCurProc->hProc, (HANDLE)pMod, TRUE);
KDUpdateSymbols(((DWORD)pMod->BasePtr)+1, TRUE);
if (pMod->e32.e32_unit[IMP].rva) {
blockptr = (struct ImpHdr *)((long)pMod->BasePtr+pMod->e32.e32_unit[IMP].rva);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -