Il vero pericolo per la sicurezza è provare un falso senso di sicurezza!
Cantelmo Software, per non far provare agli Sviluppatori un falso senso di sicurezza, propone, in questo articolo, un semplice Memory Dumper (realizzato 100% in VB.NET). Sebbene l'articolo sia stato considerato riduttivamente semplice, consente, ad un aggressore, di scaricare un Assembly .NET direttamente dalla memoria. Anche in questo caso, risulta inefficace, un qualsiasi approccio crittografico (crypter, ect.) al problema decompilazione & reverse-engineering degli Assembly .NET
A differenza di un unpacker automatico -in cui il suo loader può essere sempre intercettato- nell'esempio allegato viene illustrato come accedere ad un qualsiasi processo in esecuzione per poi effettuare il dump della memoria utilizzata! '[i] Module1.vb Imports CantelmoSoftware.MemoryDumper ' Namespace CantelmoSoftware.MemoryDumper Module Dumper Sub Main() Dim baseAddress As Integer = &H429000 '[i] retrieve you the "base address memory" Dim processMemory As New CantelmoSoftware.MemoryDumper.ProcessMemory Dim processArray As System.Diagnostics.Process() = System.Diagnostics.Process.GetProcessesByName("dotNET_Crypter") 'or other process '<<< If processArray.Length = 0 Then Debug.WriteLine("Process not Found !") Else processMemory.ReadProcess = processArray(0) processMemory.OpenProcess() '-------------------------- Dim bytesToRead As Integer = &H12EFFE Dim totBytesReaded As Integer = 0 Dim buffer As Byte() = processMemory.ReadMemory(CType(baseAddress, IntPtr), bytesToRead, totBytesReaded) '[i] save buffer to disk My.Computer.FileSystem.WriteAllBytes("c:\unpacked.bin", buffer, False) End If End Sub End Module End Namespace
Namespace CantelmoSoftware.MemoryDumper Friend NotInheritable Class ProcessMemory
Friend Shared Function CloseHandle(ByVal hObject As IntPtr) As Integer End Function
Friend Shared Function OpenProcess(ByVal dwDesiredAccess As UInt32, ByVal bInheritHandle As Integer, ByVal dwProcessId As UInt32) As IntPtr End Function
Friend Shared Function ReadProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, <[In](), Out()> ByVal buffer As Byte(), ByVal size As UInt32, ByRef lpNumberOfBytesRead As IntPtr) As Integer End Function
Private Const PROCESS_VM_READ As UInt32 = 16
Private m_hProcess As IntPtr Private m_ReadProcess As Process
Public Sub New() Me.m_ReadProcess = Nothing Me.m_hProcess = IntPtr.Zero End Sub
Friend Sub CloseHandle() If (CloseHandle(Me.m_hProcess) = 0) Then Throw New Exception("Error!") End If End Sub
Friend Sub OpenProcess() Me.m_hProcess = OpenProcess(PROCESS_VM_READ, 1, CType(Me.m_ReadProcess.Id, UInt32)) End Sub
Friend Function ReadMemory(ByVal MemoryAddress As IntPtr, ByVal bytesToRead As UInt32, ByRef bytesReaded As Integer) As Byte() Dim _ptr As IntPtr Dim _buffer As Byte() = New Byte(bytesToRead - 1) {} ReadProcessMemory(Me.m_hProcess, MemoryAddress, _buffer, bytesToRead, _ptr) bytesReaded = _ptr.ToInt32 Return _buffer End Function
Friend Property ReadProcess() As System.Diagnostics.Process Get Return Me.m_ReadProcess End Get Set(ByVal value As Process) Me.m_ReadProcess = value End Set End Property End Class End Namespace
Un obfuscator risulta essere, ad oggi, ancora la migliore scelta per la tutela della proprietà intellettuale dei nostri applicativi basati su piattaforma .NET