⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 loader.c

📁 可用于嵌入式编程学习
💻 C
📖 第 1 页 / 共 5 页
字号:
			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 + -