private static bool TryGetSimilarSymbol(ImportedSymbol symbol, IImportedModule module, out ImportedSymbol existingSymbol) { for (int i = 0; i < module.Symbols.Count; i++) { var s = module.Symbols[i]; if (symbol.IsImportByName != s.IsImportByName) { continue; } if (symbol.IsImportByName) { if (symbol.Name == s.Name) { existingSymbol = s; return(true); } } else // if (symbol.IsImportByOrdinal) { if (symbol.Ordinal == s.Ordinal) { existingSymbol = s; return(true); } } } existingSymbol = null; return(false); }
public void DuplicateImportedSymbolsShouldResultInSameImportInImage() { // Create native body. var body = CreateDummyBody(true, false); body.Code = new byte[] { /* 00: */ 0x48, 0x83, 0xEC, 0x28, // sub rsp, 0x28 /* 04: */ 0x48, 0x8D, 0x0D, 0x18, 0x00, 0x00, 0x00, // lea rcx, [rel str] /* 0B: */ 0xFF, 0x15, 0x00, 0x00, 0x00, 0x00, // call [rel puts] /* 11: */ 0x48, 0x8D, 0x0D, 0x0B, 0x00, 0x00, 0x00, // lea rcx, [rel str] /* 18: */ 0xFF, 0x15, 0x00, 0x00, 0x00, 0x00, // call [rel puts] /* 24: */ 0xC3, // ret // str: 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x66, // "Hello f" 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, // "rom the" 0x20, 0x75, 0x6e, 0x6d, 0x61, 0x6e, 0x61, // "unmanag" 0x67, 0x65, 0x64, 0x20, 0x77, 0x6f, 0x72, // "ed worl" 0x6c, 0x64, 0x21, 0x00 // "d!" }; // Add reference to ucrtbased.dll!puts at offset 0xD. var ucrtbased1 = new ImportedModule("ucrtbased.dll"); var puts1 = new ImportedSymbol(0x4fc, "puts"); ucrtbased1.Symbols.Add(puts1); body.AddressFixups.Add(new AddressFixup( 0xD, AddressFixupType.Relative32BitAddress, puts1 )); // Add second (duplicated) reference to ucrtbased.dll!puts at offset 0x20. var ucrtbased2 = new ImportedModule("ucrtbased.dll"); var puts2 = new ImportedSymbol(0x4fc, "puts"); ucrtbased2.Symbols.Add(puts2); body.AddressFixups.Add(new AddressFixup( 0x20, AddressFixupType.Relative32BitAddress, puts2 )); // Serialize module to PE image. var module = body.Owner.Module; var image = module.ToPEImage(); // Verify import is added to PE image. var importedModule = Assert.Single(image.Imports); Assert.NotNull(importedModule); Assert.Equal(ucrtbased1.Name, importedModule.Name); var importedSymbol = Assert.Single(importedModule.Symbols); Assert.NotNull(importedSymbol); Assert.Equal(puts1.Name, importedSymbol.Name); }
public void NativeBodyWithCall() { Skip.IfNot(RuntimeInformation.IsOSPlatform(OSPlatform.Windows), NonWindowsPlatform); Skip.IfNot(Environment.Is64BitOperatingSystem, Non64BitPlatform); // Read image var image = PEImage.FromBytes(Properties.Resources.TheAnswer_NetFx); var module = new ImportedModule("api-ms-win-crt-stdio-l1-1-0.dll"); image.Imports.Add(module); var function = new ImportedSymbol(0x4fc, "puts"); module.Symbols.Add(function); var body = new CodeSegment(image.ImageBase, new byte[] { /* 00: */ 0x48, 0x83, 0xEC, 0x28, // sub rsp, 0x28 /* 04: */ 0x48, 0x8D, 0x0D, 0x10, 0x00, 0x00, 0x00, // lea rcx, qword [rel str] /* 0B: */ 0xFF, 0x15, 0x00, 0x00, 0x00, 0x00, // call qword [rel puts] /* 11: */ 0xB8, 0x37, 0x13, 0x00, 0x00, // mov eax, 0x1337 /* 16: */ 0x48, 0x83, 0xC4, 0x28, // add rsp, 0x28 /* 1A: */ 0xC3, // ret // str: 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x66, // "Hello f" 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, // "rom the" 0x20, 0x75, 0x6e, 0x6d, 0x61, 0x6e, 0x61, // " unmana" 0x67, 0x65, 0x64, 0x20, 0x77, 0x6f, 0x72, // "ged wor" 0x6c, 0x64, 0x21, 0x00 // "ld!" }); // Fixup puts call. body.AddressFixups.Add(new AddressFixup( 0xD, AddressFixupType.Relative32BitAddress, function )); // Replace body. ReplaceBodyWithNativeCode(image, body, false); // Rebuild var builder = new ManagedPEFileBuilder(); var peFile = builder.CreateFile(image); // Verify string expectedOutput = "Hello from the unmanaged world!\r\nThe answer to life, universe and everything is 4919\r\n"; _fixture .GetRunner <FrameworkPERunner>() .RebuildAndRun(peFile, "TheAnswer", expectedOutput); }
public void NativeBodyWithCallX86() { Skip.IfNot(RuntimeInformation.IsOSPlatform(OSPlatform.Windows), NonWindowsPlatform); // Read image var image = PEImage.FromBytes(Properties.Resources.TheAnswer_NetFx); var module = new ImportedModule("api-ms-win-crt-stdio-l1-1-0.dll"); image.Imports.Add(module); var function = new ImportedSymbol(0x4fc, "puts"); module.Symbols.Add(function); var body = new CodeSegment(image.ImageBase, new byte[] { /* 00: */ 0x55, // push ebp /* 01: */ 0x89, 0xE5, // mov ebp,esp /* 03: */ 0x6A, 0x6F, // push byte +0x6f ; H /* 05: */ 0x68, 0x48, 0x65, 0x6C, 0x6C, // push dword 0x6c6c6548 ; ello /* 0A: */ 0x54, // push esp /* 0B: */ 0xFF, 0x15, 0x00, 0x00, 0x00, 0x00, // call [dword puts] /* 11: */ 0x83, 0xC4, 0x0C, // add esp,byte +0xc /* 14: */ 0xB8, 0x37, 0x13, 0x00, 0x00, // mov eax,0x1337 /* 19: */ 0x5D, // pop ebp /* 1A: */ 0xC3, // ret }); // Fix up puts call. body.AddressFixups.Add(new AddressFixup( 0xD, AddressFixupType.Absolute32BitAddress, function )); image.Relocations.Clear(); image.Relocations.Add(new BaseRelocation(RelocationType.HighLow, new RelativeReference(body, 0xD))); // Replace body. ReplaceBodyWithNativeCode(image, body, true); // Rebuild var builder = new ManagedPEFileBuilder(); var peFile = builder.CreateFile(image); // Verify string expectedOutput = "Hello\r\nThe answer to life, universe and everything is 4919\r\n"; _fixture .GetRunner <FrameworkPERunner>() .RebuildAndRun(peFile, "TheAnswer", expectedOutput); }
/// <summary> /// Creates a thunk for the specified member, and adds it to the table. /// </summary> /// <param name="entry">The member to add.</param> public void AddMember(ImportedSymbol entry) { uint relativeOffset = _length - ThunkSize; if (_isIat) { entry.AddressTableEntry = new RelativeReference(this, (int)relativeOffset); } _memberOffsets.Add(entry, relativeOffset); _members.Add(entry); _length += ThunkSize; }
public TypeScriptVariableReference AddDefaultSymbolImport(string localName, string path) { var importedSymbol = new ImportedSymbol("default", localName, path); if (!symbolImports.ContainsKey(importedSymbol)) { symbolImports.Add(importedSymbol, new TypeScriptImportDefaultFromPathStatement { TypeName = localName, CurrentUnit = this, PathToUnit = path, }); } return(new TypeScriptVariableReference(localName)); }
public void Native32BitMethodShouldResultInBaseRelocation() { // Create native body. var body = CreateDummyBody(false, true); body.Code = new byte[] { /* 00: */ 0x55, // push ebp /* 01: */ 0x89, 0xE5, // mov ebp,esp /* 03: */ 0x6A, 0x6F, // push byte +0x6f ; H /* 05: */ 0x68, 0x48, 0x65, 0x6C, 0x6C, // push dword 0x6c6c6548 ; ello /* 0A: */ 0x54, // push esp /* 0B: */ 0xFF, 0x15, 0x00, 0x00, 0x00, 0x00, // call [dword puts] /* 11: */ 0x83, 0xC4, 0x0C, // add esp,byte +0xc /* 14: */ 0xB8, 0x37, 0x13, 0x00, 0x00, // mov eax,0x1337 /* 19: */ 0x5D, // pop ebp /* 1A: */ 0xC3, // ret }; // Fix up reference to ucrtbased.dll!puts var ucrtbased = new ImportedModule("ucrtbased.dll"); var puts = new ImportedSymbol(0x4fc, "puts"); ucrtbased.Symbols.Add(puts); body.AddressFixups.Add(new AddressFixup( 0xD, AddressFixupType.Absolute32BitAddress, puts )); // Serialize module to PE image. var module = body.Owner.Module; var image = module.ToPEImage(); // Verify import is added to PE image. Assert.Contains(image.Imports, m => m.Name == ucrtbased.Name && m.Symbols.Any(s => s.Name == puts.Name)); // Verify relocation is added. var segment = GetNewCodeSegment(image); Assert.Contains(image.Relocations, r => r.Location is RelativeReference relativeRef && relativeRef.Base == segment && relativeRef.Offset == 0xD); }
public void NativeMethodBodyImportedSymbolShouldEndUpInImportsDirectory() { // Create native body. var body = CreateDummyBody(false, false); body.Code = new byte[] { /* 00: */ 0x48, 0x83, 0xEC, 0x28, // sub rsp, 0x28 /* 04: */ 0x48, 0x8D, 0x0D, 0x10, 0x00, 0x00, 0x00, // lea rcx, [rel str] /* 0B: */ 0xFF, 0x15, 0x00, 0x00, 0x00, 0x00, // call [rel puts] /* 11: */ 0xB8, 0x37, 0x13, 0x00, 0x00, // mov eax, 0x1337 /* 16: */ 0x48, 0x83, 0xC4, 0x28, // add rsp, 0x28 /* 1A: */ 0xC3, // ret // str: 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x66, // "Hello f" 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, // "rom the" 0x20, 0x75, 0x6e, 0x6d, 0x61, 0x6e, 0x61, // "unmanag" 0x67, 0x65, 0x64, 0x20, 0x77, 0x6f, 0x72, // "ed worl" 0x6c, 0x64, 0x21, 0x00 // "d!" }; // Fix up reference to ucrtbased.dll!puts var ucrtbased = new ImportedModule("ucrtbased.dll"); var puts = new ImportedSymbol(0x4fc, "puts"); ucrtbased.Symbols.Add(puts); body.AddressFixups.Add(new AddressFixup( 0xD, AddressFixupType.Relative32BitAddress, puts )); // Serialize module to PE image. var module = body.Owner.Module; var image = module.ToPEImage(); // Verify import is added to PE image. Assert.Contains(image.Imports, m => m.Name == ucrtbased.Name && m.Symbols.Any(s => s.Name == puts.Name)); }
private ImportedSymbol GetImportedSymbol(ImportedSymbol symbol) { if (symbol.DeclaringModule is null) { throw new ArgumentException($"Symbol {symbol} is not added to a module."); } // Find declaring module. var module = GetModuleByName(symbol.DeclaringModule.Name); // See if we have already imported this symbol before. if (TryGetSimilarSymbol(symbol, module, out var existing)) { return(existing); } // If not, create a copy of the symbol and register it. var newSymbol = symbol.IsImportByName ? new ImportedSymbol(symbol.Hint, symbol.Name) : new ImportedSymbol(symbol.Ordinal); module.Symbols.Add(newSymbol); return(newSymbol); }
/// <summary> /// Obtains the relative virtual address of the thunk associated to an imported member in the thunk table. /// </summary> /// <param name="member">The member to get the thunk entry RVA for.</param> /// <returns>The virtual address</returns> /// <remarks> /// This method should only be used after the thunk table has been relocated to the right location in the /// PE file. /// </remarks> public uint GetMemberThunkRva(ImportedSymbol member) => Rva + _memberOffsets[member];
/// <summary> /// Creates a thunk for the specified member, and adds it to the table. /// </summary> /// <param name="entry">The member to add.</param> public void AddMember(ImportedSymbol entry) { _memberOffsets.Add(entry, _length - ThunkSize); _members.Add(entry); _length += ThunkSize; }
private bool Equals(ImportedSymbol other) { return(string.Equals(SourceName, other.SourceName) && string.Equals(LocalName, other.LocalName) && string.Equals(Path, other.Path)); }
/// <summary> /// Gets the virtual address to the beginning of the hint-name pair associated to an imported member. /// </summary> /// <param name="member">The member to obtain the hint-name RVA for.</param> /// <returns>The virtual address.</returns> /// <remarks> /// This method should only be used after the hint-name table has been relocated to the right location in the /// PE file. /// </remarks> public uint GetHintNameRva(ImportedSymbol member) => Rva + _hintNameOffsets[member];