🪟 Windows TippsThe Gemini desktop app is now available for Windows(11.09.2026 um 17:06 Uhr)
🕵️ SicherheitslückenBurn Out, Or Fade Away(14.09.2026 um 14:25 Uhr)
⚠️ Malware / Trojaner / VirenWindows 11 just dropped the tool ransomware abused, Microsoft says don’t restore WMIC(10.09.2026 um 20:11 Uhr)
⚠️ Malware / Trojaner / VirenWindows 11: Microsoft entfernt WMIC-Tool gegen Ransomware - ad-hoc-news.de(14.09.2026 um 07:58 Uhr)
🕵️ SicherheitslückenMicrosoft schließt Rekordzahl an Sicherheitslücken - techbook(14.09.2026 um 09:00 Uhr)
🪟 Windows TippsThe Gemini desktop app is now available for Windows(11.09.2026 um 17:06 Uhr)
🕵️ SicherheitslückenBurn Out, Or Fade Away(14.09.2026 um 14:25 Uhr)
⚠️ Malware / Trojaner / VirenWindows 11 just dropped the tool ransomware abused, Microsoft says don’t restore WMIC(10.09.2026 um 20:11 Uhr)
⚠️ Malware / Trojaner / VirenWindows 11: Microsoft entfernt WMIC-Tool gegen Ransomware - ad-hoc-news.de(14.09.2026 um 07:58 Uhr)
🕵️ SicherheitslückenMicrosoft schließt Rekordzahl an Sicherheitslücken - techbook(14.09.2026 um 09:00 Uhr)

🔧 Programmierung 🕛 vor 1 Monat 5 Min Lesezeit
0

Ensamblando DotNet IL

↗ Quelle (dev.to)
🗣️ Stimme:

Vimos en la primera parte de esta serie que podemos fácilmente tomar un ensamblado compilado con C# (o con el lenguaje de .NET que queramos), y desensamblarlo para ver su código.



¿Podemos realizar el paso contrario? No estaría mal poder ensamblar código directamente. Veamos cómo.




CODE
var asm = AssemblyDefinition.CreateAssembly(
new AssemblyNameDefinition( name, new Version( 1, 0, 0, 0 ) ),
"tmp",
ModuleKind.Dll );






Con esto ya tenemos un ensamblado creado. Pero si queremos ver cualquier cosa que hagamos, vamos a tener que referenciar Console.WriteLine().




CODE
var consoleRef = new AssemblyNameReference(
"System.Console",
new Version( 10, 0, 0, 0 ) );

asm.MainModule.AssemblyReferences.Add( consoleRef );






Ahora creemos una clase llamada App (va a tener un constructor vacío):




CODE
var cls = new TypeDefinition(
"",
clsName,
TypeAttrs.Class | TypeAttrs.Public,
asm.MainModule.TypeSystem.Object );

// Add a parameterless constructor
var ctor = new MethodDefinition(
".ctor",
MthAttrs.Public | MthAttrs.HideBySig | MthAttrs.SpecialName | MthAttrs.SpecialName,
asm.MainModule.TypeSystem.Void );

cls.Methods.Add( ctor );

// Import from System.Object type
var objectCtor = asm.MainModule.ImportReference(
typeof(object).
GetConstructor( Type.EmptyTypes ) );

// Constructor body must call base class constructor
var il = ctor.Body.GetILProcessor();

il.Append( il.Create( OpCodes.Ldarg_0 ) ); // load 'this'
il.Append( il.Create( OpCodes.Call, objectCtor ));
il.Append( il.Create( OpCodes.Ret ) );
asm.MainModule.Types.Add( toret );






Sí, el hecho de tener que crear un constructor vacío hace que para crear una clase sea necesario bastante código. En el futuro, meteremos este código en un método reusable, claro. Lo más importante son la primera y la última línea. En la primera, es donde se crea la clase (un TypeDefinition), y en la última se toma el módulo principal del ensamblado, y se añade el nuevo tipo allí.



Además, vemos por primera vez código IL siendo creado para un método. Siempre lo haremos de la misma manera: tomamos de la propiedad Body del método el procesador de IL, mediante el método GetILProcessor().



El código que estamos ensamblando es el siguiente:




CODE
class App {
.method public instance .ctor()
{
ldarg.0 ; cargar "this" en la pila.
call Object.ctor ; base(this)
ret
}
}






Ya sabemos que la pila es el último que entra es el primero que sale o LIFO (last in, first out). También sabemos que los métodos llevan un parámetro oculto que es el objeto que está ejecutando el método, this. Aquellas instrucciones que empiezan por ld (_load) son equivalentes a push, o meter en la pila. Las instrucciones que empiezan por st (store), son equivalentes a pop.



ldarg.0 lo que hace es meter en la pila el primer argumento del método, que ya hemos visto que es this. call permite llamar a un método en un objeto cualquiera. ret termina el método. Todos los métodos deben tener al menos un ret... ¿sabes que si no incluyes un ret, .NET sigue ejecutando la memoria siguiente, tomándola como instrucciones? ¿Un poco "cutre", no?



Así, el constructor de Object es un constructor sin parámetros... si no contamos con this, claro está. Los parámetros deben tomarse de la pila, y en caso, de necesitar más de uno, será necesario meterlos en la pila en el orden inverso.



El código en C# sería el siguiente:




CODE
class App {
public App() : super()
{
}
}






O lo que es lo mismo...




CODE
class App {
}






¿Metemos un "¡Hola, mundo!"? Veamos, las instrucciones que necesitaremos ya las hemos visto en su mayoría. Necesitaremos llamar a Console.WriteLine() con una cadena de caracteres como parámetro. Esta cadena de caracteres tendrá que meterse en la pila, antes de la llamada, claro.




CODE
    class App {
public static void Main()
{
Console.WriteLine( "¡Hola, mundo!" );
}
}






Repasemos entonces lo que es necesario hacer: meter en la pila la cadena de caracteres "¡Hola, mundo!"; hacer la llamada Console.WriteLine(), y finalmente, retornar.




CODE
class App {
.method public static void Main()
{
ldstr "¡Hola, mundo!"
call void [System.Console]System.Console::WriteLine(string)
ret
}
}






Lo primero de todo, necesitamos localizar el método WriteLine() en la consola.




CODE
var consoleRef = this.Assembly.MainModule.AssemblyReferences.
FirstOrDefault( r => r.Name == "System.Console" )
?? throw new TypeLoadException(
"missing System.Console assembly reference" );

var consoleType = new TypeReference(
"System",
"Console",
methodInfo.Module,
consoleRef );

var writeLineMethod = new MethodReference(
"WriteLine",
methodInfo.Module.TypeSystem.Void,
consoleType );

writeLineMethod.Parameters.Add(
new ParameterDefinition( methodInfo.Module.TypeSystem.String ) );






Así que necesitamos crear un método Main, dentro de nuestra clase App. Necesitamos las tres instrucciones que hemos visto un poco más arriba.




CODE
var mth = new MethodDefinition( mthName,
attrs,
cls.Module.TypeSystem.Void );

cls.Methods.Add( mth );
il = mth.Body.GetILProcessor();
il.Append( il.Create( OpCodes.Ldstr, "¡Hola, mundo!" ) );
il.Append( il.Create( OpCodes.Call, writeLineMethod ) );
il.Append( il.Create( OpCodes.Ret ) );






Ahora marcamos el método Main() como el punto de entrada del ensamblado, y escribirmos el ensamblado terminado en disco.




CODE
asm.Assembly.EntryPoint = mth;
asm.Assembly.Write( "hola.dll" );






Vale. Ahora solo queda ejecutarlo, y comprobar que tenemos el ensamblado creado. Y una vez comprobado... ¡lo ejecutamos!




CODE
$ dotnet run
$ ls *.dll
hola.dll
$ dotnet hola.dll
¡Hola, mundo!




¿No te parece fascinante? ¡A mi sí!

Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
1 Quelle
The Gemini desktop app is now available for Windows
1 Quelle
Burn Out, Or Fade Away
1 Quelle
Windows 11 just dropped the tool ransomware abused, Microsoft says don’t restore WMIC
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Ensamblando DotNet IL

Thematisch verwandte Begriffe: Ensamblando, DotNet · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...