public void Inject() { EnsureNotDisposed(); if (_injected) { throw new InvalidOperationException(); } // TODO: atomic substitute if (CanMakeRelativeJump(_target, _subst)) { const int jmpSize = 5; int jmpDistance = GetRelativeJumpDistance(_target, _subst); var ptr = Utils.FindNearestOp(_target, jmpSize); _size = (int)(ptr.ToInt64() - _target.ToInt64()); Debug.Assert(_size <= 16); _oldCode = CodeBlock.FromPtr(_target, _size); var reJmp = new CodeBlock(_oldCode); reJmp.Append(0xE9); reJmp.AppendInt(GetRelativeJumpDistance(_relocated, _target)); reJmp.WriteTo(_relocated); var jmp = new CodeBlock(); jmp.Append(0xE9); jmp.AppendInt(jmpDistance); for (int i = 0; i < _size - jmpSize; ++i) { jmp.Append(0x90); } Debug.Assert(jmp.Length == _size); jmp.WriteTo(_target); } else { // TODO: absolute jmp to subst code throw new NotImplementedException(); } _injected = true; }
private static void WriteCode(MemoryBlock mem, IntPtr md) { // DoPreStub uses __fastcall // so we need to put it's first argument (methodDesc) in rcx/ecx // and the second (methodTable, should be NULL) in rdx/edx var code = new CodeBlock(); // mov rax, DoPreStubAdderss code.Append(0x48).Append(0xB8).AppendLong(_doPreStubPtr.Value.ToInt64()); // mov rcx, methodDesc code.Append(0x48).Append(0xB9).AppendLong(md.ToInt64()); // xor rdx, rdx code.Append(0x48).Append(0x31).Append(0xD2); // jmp rax code.Append(0xFF).Append(0xE0); code.WriteTo(mem.Address); }