R2R的原理是在DLL里面添加一个Native Header项,此项包含了:
1.编译器标识符(CompilerIdentifier)
2.导入方法段(ImportSections)
3.运行时方法(RuntimeFunctions)
4.方法入口点(MethodDefEntryPoints)
5.异常信息(ExceptionInfo)
6.调试信息(DebugInfo)
7.延迟加载方法调用块(DelayLoadMethodCallThunks)
等等总共高达18项信息,由于这些东西过于复杂此处只列出其中的前面几个。构成了NH。.
可以看到RuntimeFunctions是运行时方法,要获取到它的索引,则必须首先获取到方法入口点(MethodDefEntryPoints)。
方法入口点是在方法: ReadyToRunInfo::Initialize 里面获取。
Module::Initialize---->
ReadyToRunInfo::Initialize--->
new(pMemory)ReadyToRunInfo---->
m_methodDefEntryPoints=NativeArray(&m_nativeReader,pEntryPointsDir>VirtualAddress)
NativeArray里面:
NativeArray(PTR_NativeReader pReader, uint offset): _pReader(pReader){uint val;_baseOffset = pReader->DecodeUnsigned(offset, &val);_nElements = (val >> 2);_entryIndexSize = (val & 3);}
此后
bool TryGetAt(uint index, uint * pOffset){if (index >= _nElements)return false;uint offset;if (_entryIndexSize == 0){offset = _pReader->ReadUInt8(_baseOffset + (index / _blockSize));}else if (_entryIndexSize == 1){offset = _pReader->ReadUInt16(_baseOffset + 2 * (index / _blockSize));}else{offset = _pReader->ReadUInt32(_baseOffset + 4 * (index / _blockSize));}offset += _baseOffset;for (uint bit = _blockSize >> 1; bit > 0; bit >>= 1){uint val;uint offset2 = _pReader->DecodeUnsigned(offset, &val);if (index & bit){if ((val & 2) != 0){offset = offset + (val >> 2);continue;}}else{if ((val & 1) != 0){offset = offset2;continue;}}// Not foundif ((val & 3) == 0){// Matching special leaf node?if ((val >> 2) == (index & (_blockSize - 1))){offset = offset2;break;}}return false;}*pOffset = offset;return true;}};
offset = m_nativeReader.DecodeUnsigned(offset, &id);if (id & 1){id >>= 2;}else{id >>= 1;}
pEntryPoint = dac_cast<TADDR>(GetImage()->GetBase()) + m_pRuntimeFunctions[id].BeginAddress;大致的结果就是这样