Ir para o conteúdo
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

fLaSh_PT

Chamadas API Dinamicamente [transferido para wiki]

Mensagens Recomendadas

fLaSh_PT

Ora viva;

Vou mostrar como fazer chamadas API sem as declarar..

Apenas necessita de três chamadas:

LoadLibrary

SetLastError

GetProcAddress

Este conceito não é muito complicado.. mas em grandes projectos com muitas API's pode ficar um pouco "HardCode"..

Porque alguns executáveis utilizam este método?

Bem a resposta é simples, são utilizados por os Runtime Crypters, Packers mais sofisticados.. isto porque a maioria dos AV's lêem o source do executável e com alguns algoritmos conseguem detectar se o executável faz chamadas API utilizadas por este tipo de softwares..

Este método também é muito útil para o desenvolvimento de aplicações que suportem plugins ou scripts.. assim podemos criar e carregar dll's dinamicamente!

'========================================
'       Codificado por Carlos.DF
'           fLaSh - 2010-03
'   	  c4rl0s.pt@gmail.com
'========================================
Imports System.Security.Permissions
Imports Microsoft.Win32.SafeHandles
Imports System.Runtime.InteropServices
Imports System.Runtime.ConstrainedExecution
Public Class NativeDllCalls
    ''' <summary>
    ''' Executa um API dinamicamente
    ''' </summary>
    ''' <param name="sLib">O nome ou directoria da DLL</param>
    ''' <param name="sMethod">O nome do metodo a executar</param>
    ''' <param name="oType">O tipo de delegate</param>
    ''' <returns>O delegate associado a chamada API</returns>
    ''' <remarks></remarks>
    Public Function DynamicCall _
            ( _
                ByVal sLib As String, _
                ByVal sMethod As String, _
                ByVal oType As System.Type _
            ) As [Delegate]
        ' Carrega a DLL
        Dim oLibrary As SafeLibraryHandle = Methods.LoadLibrary(sLib)
        Dim dRet As [Delegate] = Nothing
        ' Verifica se foi bem carregada..
        If Not oLibrary.IsInvalid AndAlso Not oLibrary.IsClosed Then
            ' Obtem o enderesso do processo para a função prentendida..
            Dim iProcess As IntPtr = Methods.GetProcAddress(oLibrary, sMethod)
            If Not iProcess = 0 Then
                ' Obtem o ponto do delegate.. 
                dRet = Marshal.GetDelegateForFunctionPointer(iProcess, oType)
            End If
            ' Fecha o objecto..
            oLibrary.Close()
        End If
        ' Retorna o delegate..
        Return dRet
    End Function

    ''' <summary>
    ''' Classe utilizada por os novos mecanismos do .NET
    ''' para carregar as DLL's com segurança..
    ''' </summary>
    ''' <remarks></remarks>
    <SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode:=True)> _
    Public NotInheritable Class SafeLibraryHandle
        Inherits SafeHandleZeroOrMinusOneIsInvalid
        Private Sub New()
            MyBase.New(True)
        End Sub
        Protected Overloads Overrides Function ReleaseHandle() As Boolean
            Return Methods.FreeLibrary(handle)
        End Function
    End Class

    ''' <summary>
    ''' Classe para o metodos Nativos (API)
    ''' </summary>
    ''' <remarks></remarks>
    Public NotInheritable Class Methods
        Private Const KERNEL32 As String = "kernel32"

        <DllImport(KERNEL32, CharSet:=CharSet.Auto, BestFitMapping:=False, SetLastError:=True)> _
        Public Shared Function LoadLibrary _
                    (ByVal fileName As String) As SafeLibraryHandle
        End Function

        <ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)> _
        <DllImport(KERNEL32, SetLastError:=True)> _
        Public Shared Function FreeLibrary _
                    (ByVal hModule As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function

        <DllImport(KERNEL32)> _
        Public Shared Function GetProcAddress _
                    (ByVal hModule As SafeLibraryHandle, _
                     ByVal procname As String) As IntPtr
        End Function
    End Class

End Class

Simple teste .. crie novo projecto e no Form1 adicione este código..

Public Class Form1

    ''' <summary>
    ''' Numerador do tipo de Beep's
    ''' usado neste teste..
    ''' </summary>
    ''' <remarks></remarks>
    Public Enum BeepType
        SimpleBeep = -1
        OK = &H0
        Question = &H20
        Exclamation = &H30
        Asterisk = &H40
    End Enum

    ' ATENÇÃO, em ves da chamda API, criamos um delegate com os mesmo parametros!
    '<DllImport("User32.dll", ExactSpelling:=True)> _
    'Private Shared Function MessageBeep(ByVal type As UInteger) As Boolean
    'End Function
    Private Delegate Function MessageBeep(ByVal type As UInteger) As Boolean

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ' Cria a instancia do objecto..
        Dim oNativeDllCalls As New NativeDllCalls
        ' Associa o delegate ao ponto da função da DLL..
        Dim oMessageBeep As MessageBeep = _
                oNativeDllCalls.DynamicCall("User32", "MessageBeep", GetType(MessageBeep))
        ' Invoca a chamda
        oMessageBeep.Invoke(BeepType.Asterisk)
    End Sub

End Class

Compr.


Making the impossible possible and pwing the world on db at a time.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
ribeiro55

Excelente contribuição, aliás, como sempre ;)

Wikas tu ou wikos eu?


Sérgio Ribeiro


"Great coders aren't born. They're compiled and released"
"Expert coders do not need a keyboard. They just throw magnets at the RAM chips"

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
BrunoMaestro

Parabéns pelo artigo, e gostaria de saber se com esse código consigo acessar dlls de outros compiladores tipo Delphi, C++, etc...

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
fLaSh_PT

Parabéns pelo artigo, e gostaria de saber se com esse código consigo acessar dlls de outros compiladores tipo Delphi, C++, etc...

Sim consegues, utilizar qualquer DLL codificado em qualquer linguagem desde que seja DLL Standard..

delegate_usado = DynamicCall("directoria_da_dll", "nome_da_funcao", GetType(delegate_usado))

PS: se a DLL estiver na Dir do sistema (System32) ou na mesma Dir do executável.. basta o nome da DLL.. caso contrario tens de indicar o caminho completo da DLL..

Compr.


Making the impossible possible and pwing the world on db at a time.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!

Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.

Entrar Agora

×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.