Building Finalizable and Disposable Types
If the caller forgets to call Dispose(), the unmanaged resources may be held in memory indefinitely.
class MyResourceWrapper : IDisposable
{
// The gc will call this method if the object user forgets to call Dispose()
~MyResourceWrapper()
{
// Clean up any internal unmanaged resources
// Do **not** call Dispose() on any managed objects
}
// The object user will call this method to clean up resoucres ASAP.
public void Dispose()
{
// Cleanup unmanaged resources here.
// Call Dispose() on other contained disposable objects.
// No need to finalize if user called Dispose(), so suppress finalization.
GC.SuppressFinalize(this);
}
}
Understanding Lazy Object Instantiation
Don't create the object until you need it.
Lazy<MyClass> obj = new Lazy<MyClass>();
Value -> returns the object (creates on first call)
IsValueCreated -> True if already created, false if not.
Lazy<HttpClient> obj = new Lazy<HttpClient>(() =>
{
return new HttpClient();
});
Offensive C# style:
- Implant starts with small memory footprint.
- Modules load only WHEN operator requests them.
- AV/EDT memory scan sees less suspicious code.
Normal : Agent starts -> All Modules in memory -> Heavy -> Detected
Lazy : Agent starts -> ZERO Modules loaded -> Light -> Stealthy
Operator says "hashdump" -> mimikatz loads -> executes -> done.
Lazy<T> is thread-safe by default.