.Net CLR R2R获取RuntimeFunctions索引

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 found                if ((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;

大致的结果就是这样