elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Estamos en la red social de Mastodon


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  .NET (C#, VB.NET, ASP)
| | | |-+  Programación Visual Basic (Moderadores: LeandroA, seba123neo)
| | | | |-+  Introduccion a APIs y como evitar el uso de MSWINSCK.OCX con APIs
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Introduccion a APIs y como evitar el uso de MSWINSCK.OCX con APIs  (Leído 4,996 veces)
Achernar


Desconectado Desconectado

Mensajes: 317



Ver Perfil
Introduccion a APIs y como evitar el uso de MSWINSCK.OCX con APIs
« en: 5 Julio 2007, 23:17 pm »

Bueno no espero que esto sea una enciclopedia api, pero espero que esto pueda ser el
primer paso para empezar a usar apis en VB de muchos y dejar de lado el tedioso trabajo
de llevar archivos .OCX a cada lugar donde llevamos nuestra aplicación. Además en mi
caso el haber usado mucho las apis desde VB6 me facilito muchísimo pasar a
MASM32 desde el tasm para ms-dos.... bla bla bla ya parezco una vieja...

como dijeron The Ramones jei jou! letsgou! ;)

***********************************************************************************************
                                                    PRIMER EJEMPLO:  Un ejemplo sencillo
***********************************************************************************************

ACLARACION!!!: todo los ejemplos están hechos en VB6

1) creamos un nuevo proyecto con un formulario Form1 y copiamos el siguiente código

Código:
'<el codigo empieza justo despues de esta etiqueta>
Option Explicit

Private Declare Function MessageBox Lib "user32" Alias "MessageBoxA" (ByVal hwnd As Long, _
                                                                            ByVal lpText As String, _
                                                                              ByVal lpCaption As String, _
                                                                              ByVal wType As Long) As Long

Private Sub Form_Load()
    MessageBox Me.hwnd, "PRIMER EJEMPLO DE APIS HECHO POR ACHERNAR", "Ejemplo API", 0
End Sub
'<el codigo termino justo antes de esta etiqueta>

2) listo... le damos F5 para ejecutarlo y voila... un msgbox con un texto hermoooossssso
   ¿no? a mi me parece muy lindo y esta hecho con una sencilla api... que no te gusta, hey
   no me presiones que estoy ebrio y puedo llegar a decir cosas como que detrás de la simpleza
   de una margarita se haya todo el poder de la naturaleza, pero no te lo voy a decir :P

Bueno dejo mi vaso y vamos a analizar un poco esto

   Primero tenemos lo de "Private Declare Function MessageBox..." acá estamos avisando que
función vamos a usar y en que librería esta (user32 --> user32.dll dentro de System32),
si usamos Alias quiere decir que dentro de la dll la función se llama MessageBoxA, pero
nosotros la vamos a llamar MessageBox para que VB sepa que estamos diciendo cuando llamemos
a una función MessageBox.

Este alias por ejemplo se usa en la función Winsock select para verificar el estado de
un socket si esta en alguna combinacion de lectura/escritura/error. Como No se puede
usar una función select en vb (porque es una palabra reservada "Select Case") se la
puede llamar vbSelect

Volviendo a MessageBox vemos que a la derecha esta los parametros hwnd, lpText,
lpCaption y WType

hwnd: este es el MANEJADOR (o handle) de la ventana padre (la que crea la ventanita msgbox hija).
      en este ejemplo la ventana padre seria el form1. En windows las ventanas son creadas en
      algún momento (no existe una ventana dios que existe y existirá por siempre... a menos
      que Bill nos haya ocultado algo), bueno y cuando se crea una ventana, esta tiene un
      numero que la identifica como cuando creamos un archivo algo así:

      Open "archivo.txt" for Random as #1 Len = Len(Registro)
      Put #1,,Registro
      close #1

      puede verse que para grabar un registro en el archivo o cerrarlo no usa "archivo.txt"
      para referirse al archivo, sino el numero #1 que es el MANEJADOR del archivo

      Volviendo al ejemplo del msgbox... este argumento hwnd puede ser nulo indicando que el
      msgbox no tiene ventana padre (no genera ningún problema).

lpText: este argumento es el mensaje propiamente dicho, en vb se pasa una cadena, pero vale
      aclarar este detalle: si ven el nombre de la variable comienza con lp eso se usa en
      otros lenguajes (como masm32) para destacar que dicha variable es un puntero y en dichos
      lenguajes no se pasa una cadena, sino la dirección de memoria donde esta guardada la
      cadena, en este caso, en VB ,se facilita bastante, pero muchas veces hay problemas con las
      apis porque VB no permite manipular tan bien la memoria como C++ o MASM32 entonces hay
      que recurrir a ciertos artilugios.

lpCaption: similar al anterior fíjense que también empieza con lp, es un puntero, pero nosotros
      solo pasamos una cadena y listo... casi me olvido, este es el titulo de la ventana

wType: esto indica el tipo de ventana msgbox... o sea.. con solo un botón OK o Yes/NO
     o Yes/No/Cancel etc el valor cero = solo OK, podemos experimentar agregando las
     siguientes constantes a nuestro proyecto anterior y sustituyéndolas por el ultimo termino

        Private Const MB_OK = 0
   Private Const MB_OKCANCEL = 1
   Private Const MB_ABORTRETRYIGNORE = 2
   Private Const MB_YESNOCANCEL = 3
   Private Const MB_YESNO = 4
   Private Const MB_RETRYCANCEL = 5

    luego la llamada a la función podría quedar algo así

   MessageBox Me.hwnd, "Este Es El Primer Ejemplo", "Ejemplo API", MB_ABORTRETRYIGNORE



En línea

Achernar


Desconectado Desconectado

Mensajes: 317



Ver Perfil
Re: Introduccion a APIs y como evitar el uso de MSWINSCK.OCX con APIs
« Respuesta #1 en: 5 Julio 2007, 23:20 pm »

Bueno como al primer ejemplo de api lo llevamos fácil como nene para la escuela, antes de
que se enfríen las articulaciones vamos a meter un ejemplo un poco mas elaborado pero facilito

***********************************************************************************************
                                              SEGUNDO EJEMPLO:  Un ejemplo mas elaborado ;)
***********************************************************************************************
lo que vamos a hacer acá es un programa para cambiarle el titulo a otra ventana cualquiera
si... podes hacer eso... a cualquier programa le podes hacer lo que quieras... como dijo
el DR. Octopus en SpiderMan II  "The power of the sun in the palm of my hand"

1) lo de siempre creamos un proyecto con un formulario Form1, un botón Command1 y un
   timer Timer1 y le copiamos el siguiente código

Código:
'<el codigo empieza justo despues de esta etiqueta>

Option Explicit

'para este ejemplo se necesita un form1 con un command1 y un timer1

'con las siguientes 5 apis nos va a alcanzar para este ejemplo

'la funcion MessageBox crea un msgbox
'Esta funcion esta dentro de User32.dll que esta dentro de la carpeta System32
Private Declare Function MessageBox Lib "user32" Alias "MessageBoxA" (ByVal hwnd As Long, _
                                                                      ByVal lpText As String, _
                                                                      ByVal lpCaption As String, _
                                                                      ByVal wType As Long) As Long

'con la funcion WinExec vamos a poder ejecutar un programa
'lpCmdLine es el path del programa (tendria que ser un puntero,
'          pero para nosotros es mas facil)
'          como voy a ejecutar el notepad.exe creo que alcanza poner
'          "notepad.exe" porque esta dentro de la carpeta System32
'nCmdShow es el modo en que se va a mostrar la pantalla
'         0 = hide, o sea, la ventana esta pero no se ve
'         1 = cuando no esta entre minimizado y maximizado... no se como se llama :P
'         2 = minimizado
'         3 = maximizado
'Esta funcion esta dentro de Kernel32.dll que esta dentro de la carpeta System32
Private Declare Function WinExec Lib "kernel32" (ByVal lpCmdLine As String, _
                                                 ByVal nCmdShow As Long) As Long

'con la funcion Beep puede emitirse una señal sonora de cierta duracion y frecuencia
'por el diminuto parlantito que hay dentro de la cpu (no importa que bajes el volumen
'a ese no lo bajas... no se ocurra usar esto para hacer programas para fastidiar a
'la gente con bucles infinitos!! XDDD )
'dwFreq es la frecuencia en Hertz (Ciclos por segundo)
'dwDuration es la duracion en milisegundos
'Esta funcion esta dentro de Kernel32.dll que esta dentro de la carpeta System32
Private Declare Function Beep Lib "kernel32" (ByVal dwFreq As Long, _
                                              ByVal dwDuration As Long) As Long

'la funcion GetForegroundWindow nos devuelve el MANEJADOR de la ventana que se
'encuetra sobre toda las demas... foreground window. En el ejemplo anterior explicaba
'un poco sobre el manejador de las ventanas suele llamarse tambien hWnd.
'Esta funcion no necesita argumentos
'Esta funcion esta dentro de Kernel32.dll que esta dentro de la carpeta System32
Private Declare Function GetForegroundWindow Lib "user32" () As Long

'con la funcion SetWindowText se puede modificar el texto de una ventana, los botones
'tambien son ventanas... tienen manejadores como cualquier ventana, los textbox, los
'listboxs y los checkboxs tambien son ventanas y muchos mas tambien todos estos elementos
'puedes ser manipulados y modificados...
'Esta funcion esta dentro de Kernel32.dll que esta dentro de la carpeta System32
Private Declare Function SetWindowText Lib "user32" Alias "SetWindowTextA" (ByVal hwnd As Long, _
                                                                            ByVal lpString As String) As Long


Private CuentaSegundos      As Integer

Private Sub Form_Load()
    Timer1.Enabled = False
    Timer1.Interval = 1000 'llama a la funcion del tiemer cada un segundo
    CuentaSegundos = 0
End Sub

Private Sub Command1_Click()
    'al apretar el boton, abre el block de nota
    'este aparece sobre todas las demas ventanas (ForeGroundWindow)
    'y comienza a ejecutarse el timer para luego de 3 segundos
    'buscar la ventana que se encuentra sobre todas y cambiarle el titulo
    WinExec "notepad.exe", 3
    Timer1.Enabled = True
End Sub


Private Sub Timer1_Timer()
    Dim Manejador       As Long
   
    'emite un sonido de 500 Hz durante 200 miliSegundos
    Beep 500, 200
   
    CuentaSegundos = CuentaSegundos + 1
   
    If CuentaSegundos = 5 Then
        Manejador = GetForegroundWindow
        SetWindowText Manejador, "ESTE ES EL SEGUNDO EJEMPLO DE APIS HECHO POR ACHERNAR"
        MessageBox Me.hwnd, "El Texto ha sido modificado", "Boom!!", 0
        Timer1.Enabled = False
    End If
End Sub

'<el codigo termino justo antes de esta etiqueta>

2) le damos F5 para ejecutar... si hacemos click en el botón se abre el block de notas
   y cada segundo va a sonar un beep, luego de 5 segundos (5 beeps) el titulo de la
   ventana del block de notas se va a modificar por otro texto.

esto me hace acordar un programa que hice y fue como me di cuenta que la fuerza bruta no
no ayuda de mucho... era un programa de fuerza bruta para un programa que se llama
UniversalShield y sirve para guardar archivos y carpetas bajo un password. Cuando el
UniversalShield pide el pass no hace como otros que luego de unos errores cierra la ventana,
lo cual demoraría la fuerza bruta así que no era muy difícil de programar. Otra cosa era que
el botón ok del UniversalShield para aceptar el pass estaba deshabilitada y se habilitaba cuando
se escribía el pass correcto.
Mi programa tenia 256 o 255 checkboxs con distintos símbolos ascii, de ahí elegía los que me
parecía que podría contener el pass, por ejemplo solo los 10 numero, ingresaba el caption de
la ventana que me pedía el pass. El programa buscaba una ventana (acá ya se mostró como buscar
la foreground window) con el caption ingresado. En esa ventana buscaba el textbox y le mandaba
pulsaciones de teclas sintetizadas (también se puede simular con apis) cada vez que el programa
tecleaba un posible pass verificaba si el botón estaba enabled o disabled (también se puede
hacer con apis) y si el botón estaba enabled (habilitado) era que había encontrado el password
Era un programa muy pobre pero era bueno para practicar el uso de apis y en esa época estaba
viendo los mensajes entre ventanas y era el modo en que sintetizaba las pulsaciones sobre
el textbox.



En línea

Achernar


Desconectado Desconectado

Mensajes: 317



Ver Perfil
Re: Introduccion a APIs y como evitar el uso de MSWINSCK.OCX con APIs
« Respuesta #2 en: 5 Julio 2007, 23:28 pm »

  Al igual que se usan estas funciones, windows tiene infinidad (bueno, no lo tomes literal...
muchas, muchisimas) funciones para hacer una cantidad impresionante de cosas. Todo lo que hacen
los archivos OCX es llamando a apis asi que es posible sustituir estos archivos por código
hecho por nosotros con llamadas a apis. Lo que voy a explicar es como usar apis para evitar
el uso del Microsoft winsock Control 6.0 (MSWINSCK.OCX) con no mas de 11 apis WOW!!!! XDD

***********************************************************************************************
                                       UN POCO DE TEORIA EMINENTEMENTE PRACTICA ¿? ;)
                                (la música de fondo es "Children of the Grave" de Black Sabbath)
***********************************************************************************************

Acá es donde la cosa se complica... porque yo estudio Ingeniería Mecánica XDDDD

Mejor no me voy a poner a explicar que es un socket porque sino la cago :P supongo que si
alguien venia usando el control winsock de VB debe conocer algo de esto... personalmente conocí
winsock vía api y nunca use dicho control :/  .Todas estas funciones explicadas de acá en
adelante están en wsock32.dll que esta dentro de la carpeta System32

Creo que lo voy a explicar mejor con un diagrama

   así funciona un cliente:

         1) iniciamos una sesión Winsock (avisamos que vamos a usar winsock)
           Esto se hace con la funcion WSAStartp

        2) creamos un socket (digamos una terminal de entrada y salida de datos)
      Esto se hace con la funcion soket

        3) conectamos el socket a una dirección remota en un cierto puerto
           Esto se hace con la función Connect, pero son necesarias un par
      de funciones mas para condimentar un poco el asunto

        4) si la conexión se realizo ya se pueden enviar mensajes, pero
           también hay que verificar si hay mensajes entrantes para leer
           Leer se hace con la función recv
           Escribir se hace con la función send

        5) para terminar se puede cerrar el socket y terminar la sesión winsock
           o directamente terminar la sesion winsock y esta elimina todos los
           sockets creados por el proceso que llame a esta función
         Un socket se cierra con la función closesocket
           Una sesión se termina con WSACleanup


Un servidor es levemente distinto, el paso 3 no es conectarse, sino poner el socket en modo escucha
para esto se usa la función bind para enlazar el socket con la IP local y el puerto donde se quiere
dar el servicio y luego la función listen para poner el socket a la espera de una conexión

A explicar un poco como funcionan estas funciones
("FUNCINAN ESTAS FUNCIONES" que recursivo!!!XDDD ah a propósito de esto leí que la RAE no acepta este
termino tan utilizado en informática, por ejemplo GNU es un acrónimo recursivo o sea una especie de
sigla que hace referencia a si misma --> GNU = GNU is Not Unix, la RAE propone otra palabra para
sustituir por recursivo que ahora no recuerdo)

* WSAStartup: (avisa que este proceso inicia una sesión winsock)

Declare Function WSAStartup Lib "WSOCK32" (ByVal wVersionRequired As Long, _
                                           lpWSADATA As WSAData) As Long

wVersionRequired es la versión mas alta que soporta quien llama a esta función y esta se pasa
                 teniendo en cuenta lo siguiente supongamos la versión ficticia v5.7, 5 es la
                 versión y 7 la revisión, bueno como las variables que empezaban con lp eran
                 punteros ahora puede verse que wVersionRequired empieza con w es un word, o
                 sea, un par de bytes de los cuales el de mayor orden va a representar la
                 revisión y el de menor orden la versión casi nunca vas a tener error si usas
                 la versión de de Windows Sockets 2.2 o sea pasarle el valor &H202 como
                 primer argumento a esta función

lpWSADATA        Seria un puntero a una estructura tipo WSAData, pero como en VB es mas fácil
                 directamente pasamos el nombre de la estructura

                 este tipo se declara de este modo

   Type WSAData
         wVersion       As Integer
         wHighVersion   As Integer
         szDescription  As String * 257
         szSystemStatus As String * 129
         iMaxSockets    As Integer
         iMaxUdpDg      As Integer
         lpVendorInfo   As Long
   End Type

  Generalmente todo esto no nos va a importar mucho.. digo, si estas por crear un cliente de
IRC solo queres iniciar winsock y nada más

Si la llamada a esta función es satisfactoria, el valor de retorno será CERO



* WSACleanup: (avisa que este proceso termina una sesión winsock)

Declare Function WSACleanup Lib "WSOCK32" () As Long

no tiene argumentos

* socket: (crea un socket)

Declare Function socket Lib "wsock32.dll" (ByVal af As Long, _
                                           ByVal s_type As Long, _
                                           ByVal protocol As Long) As Long

af        es AddressFamily (la familia de direccion)
s_type    es el tipo de socket
protocol  es el protocolo que operara con el socket

valores comunes (troyanos, bots, clientes para keyloggers remotos, no se.. cosas comunes) son
af = AF_INET = 2
s_type = SOCK_STREAM = 1
protocol = IPROTO_TCP = 6

Si la llamada a la función es satisfactoria retorna un valor mayor a cero que es el manejador
del socket (ese valor para operar sobre el socket como con los archivos y las ventanas) y si
hay algún error y no se puede crear retorna -1


* closesocket: (cierra un socket)

Declare Function closesocket Lib "wsock32.dll" (ByVal s As Long) As Long

s es el manejador del socket que se quiere cerrar

ahora viene una explicación peque peque para la conexión

esta es la declaración de la función connect, la que establece la conexión, así
esta en la Api Guide (después voy a dar la dirección para que busque quien quiera la api
que quiera... también toda la info sobre esto esta en el msdn de microsoft pasen por ahí que
siempre atienden bien con café, torta, constantes, estructuras, funciones y códigos fuente ;)

Declare Function Connect Lib "wsock32.dll" Alias "connect" (ByVal s As Long, addr As sockaddr, _
                                                            ByVal namelen As Long) As Long

que tenemos... s = manejador del socket (ya usamos manejadores como si en lugar de nombres
                   tuviesemos manejadores no?)
despues...  addr = es otra estructura... muchas veces se usan estructuras con las apis tanto
                   para pasar info a la función como para recibir info. A veces esta info no
                   es importante y por ejemplo en masm32 suelo crear un buffer sin nada y
                   y en lugar de declarar tantas estructuras directamente paso la dirección
                   de memoria del buffer... dirección de memoria... mmm si!! punteros!!!

  esta estructura se declara de este modo

    Type sockaddr
          sin_family As Integer       
          sin_port As Integer
          sin_addr As Long
          sin_zero As String * 8
    End Type

en sin_family va la familia del socket, ¿como que socket? el que vamos a conectar, el que creamos
con la función socket mas arriba y como argumento AddressFamily le pasamos 2 que es AF_INET, acá
también. Que dolores de cabeza me estas dando niño!!! tu madre que dice de todo esto???!!! XD!

en sin_port va el puerto, pero acá empieza a haber algunos detalles extras, porque si te vas a
conectar al puerto 6667 por ejemplo de un servidor de IRC no hay que pasar el numero así como así.
hay ciertos tipos de ordenamientos de bytes (byte order) uno es el de red (network) y el otro
es el de host (JOST XDDD, lo de este paréntesis es broma no se confundan)
para pasar de ordenamiento de red al de host se usa la función ntohs y para lo opuesto htons
hey siempre me habían parecido letras a azar pero miren ntohs = Network to Host.. y la s? :S

nosotros vamos a hacer que estos datos viajen a través de la red para hacer una petición de
conexión y tenemos que cambiar el ordenamiento a NetWork con htons, pero antes viene uno de esos
problemitas con el tamaño de la variable que no sucede en otros lenguajes, antes de usar la
función htons hay que modificar el valor del puerto del siguiente modo

   If Not Valor <= 32767 Then
       Valor = Valor - 65536
   End If

o sea la función para cambiar el ordenamiento podría ser así (sin la declaración de htons)

   Private Function CambiarOrdenamiento(ByVal Valor As Long) As Integer
       If Not Valor <= 32767 Then
           Valor = Valor - 65536
       End If
       CambiarOrdenamiento = htons(Valor)
   End Function

continuando con la estructura sockaddr tenesmos la variable sin_addr, para la cual también
hay que hacer ciertas cositas. Como se sabe una maquina en una red puede ser referida mediante
un Hostname o una direccion IP, el primero es algo como achernar.com y el segundo es algo como
207.46.104.20.

1) partiendo de una ip:  suponiendo 207.46.104.20 -->
 --> sin_addr = 20 * 256^0 + 104 * 256^1 + 46 * 256^2 + 207 * 256^3

2) partiendo de un hostname:
aca hay que usar una api para manipular memoria (RtlMoveMemory) esta funcion guarda en una
variable, una cierta cantidad de bytes copiados a partir de una direccion de memoria. Vamos
a tener que usar esto porque hay funciones que retornan punteros y ahí es donde los VBoys estamos
medio en p#lotas.

la función gethostbyname toma una cadena con el hostname y retorna un puntero a una estructura
HOSTENT, o sea los datos que queremos estan en alguna parte de la memoria y esta función nos
da dicha dirección... después con RtlMoveMemory copiamos estos datos a una variable para poder
manipular mejor estos datos.

la estructura HOSTENT es esta

Private Type HOSTENT
    Nombre              As Long
    Alias               As Long
    TipoDeDireccion     As Integer
    Longitud            As Integer
    ListaDeDirecciones  As Long
End Type

en ListaDeDirecciones hay un puntero (una dirección de memoria) que apunta a un lugar donde
hay otro puntero mas... si es una locura... y este ultimo puntero apunta a un lugar
de la memoria donde esta la IP del host que estamos buscando lista para guardar en
la variable sin_addr de la estructura sockaddr porque es para eso que estamos haciendo esto..
ya te habías olvidado... no te culpo... todo esto es para poder hacer una simple conexión TCP
A causa de tener que manipular tantos punteros se usa varias veces RtlMoveMemory.

NOTA: creo que, no estoy muy seguro, gethostbyname puede tomar también cadenas tipo IP
             (xxx.xxx.xxx.xxx) pero quería mostrar la transformación por potencias que puse antes.
             (a la IP 127.0.0.1 si la acepta perfectamente)

volviendo a la estructura sockaddr queda ver el ultimo termino que es sin_zero y esto es fácil
sencillamente no se toca... porque esta reservado.

las declaraciones de estas funciones son las siguientes

Declare Function Connect Lib "wsock32.dll" Alias "connect" (ByVal s As Long, _
                                                            addr As sockaddr, _
                                                            ByVal namelen As Long) As Long

Declare Function htons Lib "wsock32.dll" (ByVal hostshort As Long) As Integer

Declare Function gethostbyname Lib "WSOCK32" (ByVal szHost As String) As Long

Private Declare Sub RtlMoveMemory Lib "kernel32" (hpvDest As Any, _
                                                  ByVal hpvSource As Long, _
                                                  ByVal cbCopy As Long)

con esto ya podemos conectarnos por ejemplo a un servidor telnet... o por ejemplo cuando el
netcat da una shell directa (no inversa) nos podemos conectar y hacernos una interfaz con letras
tipo Papyrus (me encanta, me imagino revisando el correo en una carabela :P )




ahora luego de conectarnos tenemos que tener algún método para ver si hay algún mensaje entrante
o si el host remoto se desconecto o si podemos escribir Hello Internet!

la función que se utiliza para esto es select


* select: ( retorna el estado del socket en cuestión [lectura/escritura/error] )

Declare Function vbselect Lib "ws2_32.dll" Alias "select" (ByVal nfds As Long, _
                                                           ByRef readfds As Any, _
                                                           ByRef writefds As Any, _
                                                           ByRef exceptfds As Any, _
                                                           ByRef timeout As Long) As Long

esta función se usa de la siguiente manera...
primero los 3 argumentos declarados tipo any son 3 estructuras fd_set que son así

   Private Type fd_set
     Contador                      As Long 'Cuantos sockets están en este estado?
     Arreglo(1 To 64)              As Long 'Arreglo con los manejadores en cuestión.
   End Type

son 3 estructuras una para información de lectura otra para escritura y otra para error
cuando llamamos la función en el arreglo de cada una de estas estructuras metemos el manejador
de nuestro socket (supongo que se pueden meter mas) y después de llamar la función leemos
los contadores de estas estructuras... si el contador de la estructura de escritura esta en
1 (uno) es que hay datos para leer en el socket, si esta en 0 (cero es que no hay nada para
leer) igual con la estructura de escritura o error.

esta función me ha dado buenos resultados con error... cuando el host remoto se desconecta
me responde como si tuviera un mensaje para leer, pero con la diferencia que cuando lo leo
me dice que la longitud del mensaje es cero bytes... así que así hago para ver si se terminó
la conexión con el host remoto.

a los otros dos parámetro que quedan para llamar a esta función les pasamos cero como valor

bueno ahora tenemos una conexión y sabemos fehacientemente que tenemos un mensaje para leer
como hacemos? ahora lo explico, pero esperen unos minutos que tengo un llamado urgente de la
naturaleza que no puedo eludir..................
...
...
..
.
..
.
...
.
listo... uhh que alivio :P

bueno acá vamos a terminar con la recepción y envío de datos con send y recv

* recv: (recibe la data y la guarda en un buffer)

Declare Function recv Lib "wsock32.dll" (ByVal s As Long, _
                                         buf As Any, _
                                         ByVal buflen As Long, _
                                         ByVal flags As Long) As Long

s = el manejador del socket
buf = un buffer, una matriz tipo byte que yo suelo usar de 1 a 8192
buflen = tamaño del buffer... 8192 bytes
flags = se pone a cero

si todo sale bien retorna un valor que es la cantidad de bytes leídos, si retorna
cero hubo algún error y ya explique que es como yo verifico si se corto la conexión
con el host remoto. fácil no?

hay un detallito... como la data la recibimos en un buffer tipo bytes hay que pasarla
a una cadena de texto... y se hace asi

   StringBuffer = StrConv(ByteBuffer, vbUnicode)
        StringBuffer = Left$(StringBuffer, BytesRecibidos)

acá no hay ninguna api StrConv, Left$ y vbUnicode son dos funciones y una constante
todas de VB6

ufff y acá tomamos la recta final.... de esta TEORIA EMINENTEMENTE PRACTICA

* send: (envía datos al host remoto tomándolos de un buffer)

Declare Function Send Lib "wsock32.dll" Alias "send" (ByVal s As Long, _
                                                      buf As Any, _
                                                      ByVal buflen As Long, _
                                                      ByVal flags As Long) As Long

funciona igual que send

s = el manejador del socket
buf = un buffer, una matriz tipo byte que yo suelo usar de 1 a 8192, pero ahora
      tomamos datos de este buffer....
buflen = tamaño del buffer... 8192 bytes
flags = se pone a cero


listo ya esta todo explicado como para hacer un cliente en una conexión TCP

En línea

Achernar


Desconectado Desconectado

Mensajes: 317



Ver Perfil
Re: Introduccion a APIs y como evitar el uso de MSWINSCK.OCX con APIs
« Respuesta #3 en: 5 Julio 2007, 23:30 pm »

el siguiente es el código que debe ponerse en un modulo de VB y se agrega a cada
proyecto que se quiera usar winsock y así no usamos fastidiosos OCX's


Código:
'<el codigo empieza justo despues de esta etiqueta>

Option Explicit

'Funciones PUBLICAS en este modulo:
'
'IniciarSesionSocket
'TeminarSesionSocket
'CrearSocket
'CerrarSocket
'Conectar
'Recibir
'Enviar
'EstadoSocket <-- no da buenos resultados
'MensajeEntrante
'
'(NOTA: estan declaradas en el orden mostrado)
'
'Ademas hay una variable publica booleana que indica si winsock fue iniciado
'(Public WinsockIniciado  As Boolean)

'
Private Declare Function WSAStartup Lib "ws2_32.dll" (ByVal wVersionRequired As Long, _
                                                      lpWSAData As WSAData) As Long

Private Declare Function WSACleanup Lib "ws2_32.dll" () As Long

Private Declare Function Socket Lib "ws2_32.dll" Alias "socket" (ByVal Familia As Long, _
                                                                 ByVal Tipo As Long, _
                                                                 ByVal Protocolo As Long) As Long
Private Declare Function closesocket Lib "ws2_32.dll" (ByVal s As Long) As Long

Private Declare Function htons Lib "ws2_32.dll" (ByVal hostshort As Integer) As Integer

Private Declare Function gethostbyname Lib "ws2_32.dll" (ByVal host_name As String) As Long

Private Declare Sub RtlMoveMemory Lib "kernel32" (hpvDest As Any, _
                                                  ByVal hpvSource As Long, _
                                                  ByVal cbCopy As Long)
Private Declare Function connect Lib "ws2_32.dll" (ByVal s As Long, _
                                                   ByRef name As sockaddr_in, _
                                                   ByVal namelen As Long) As Long
Private Declare Function recv Lib "wsock32.dll" (ByVal s As Long, _
                                                 buf As Any, _
                                                 ByVal buflen As Long, _
                                                 ByVal flags As Long) As Long
Private Declare Function send Lib "ws2_32.dll" (ByVal s As Long, _
                                                ByRef buf As Any, _
                                                ByVal buflen As Long, _
                                                ByVal flags As Long) As Long
Private Declare Function vbselect Lib "ws2_32.dll" Alias "select" (ByVal nfds As Long, _
                                                                   ByRef readfds As Any, _
                                                                   ByRef writefds As Any, _
                                                                   ByRef exceptfds As Any, _
                                                                   ByRef timeout As Long) As Long
               
Private Type WSAData
   Version              As Integer
   MayorVersion         As Integer
   Descripcion          As String * 257
   EstadoDelSistema     As String * 129
   MaximosSockets       As Integer
   MaximaUPDData        As Integer
   InfoDelVendedor      As Long
End Type

Private Type HOSTENT
    Nombre              As Long
    Alias               As Long
    TipoDeDireccion     As Integer
    Longitud            As Integer
    ListaDeDirecciones  As Long
End Type

Private Type sockaddr_in
    Familia             As Integer
    Puerto              As Integer
    Direccion           As Long
    Cero(1 To 8)        As Byte
End Type

Private Type fd_set
  Contador                      As Long 'Cuantos sockets estan en este estado?
  Arreglo(1 To 64)              As Long 'Arreglo con los manejadores en cuestion.
End Type

'esta es una bandera usada para cuando se llama a TeminarSesionSocket
'para saber si la sesion fue iniciada o no (en tal caso no abria que terminar nada)
Private WinsockIniciado   As Boolean

'*****************************************************************
'*****************************************************************
'*****************************************************************

Public Function IniciarSesionSocket() As Boolean
    'IniciarSesionSocket por ACHERNAR 7/2007
    'para el foro de www.elhacker.net
    '
    'La funcion inicia una sesion socket
    'si todo sale bien retorna True
    'Si hay error retorna False
    Dim MiEstructuraWinsockData     As WSAData
    Dim Retorno                     As Long
   
    Retorno = WSAStartup(&H202, MiEstructuraWinsockData)
   
    If Retorno = 0 Then
        WinsockIniciado = True
        IniciarSesionSocket = True
    Else
        WinsockIniciado = False
        IniciarSesionSocket = False
    End If
End Function

Public Function TeminarSesionSocket()
    'TeminarSesionSocket por ACHERNAR 7/2007
    'para el foro de www.elhacker.net
    '
    'Termina sesion Winsock
    If WinsockIniciado Then
        WSACleanup
    End If
End Function

'*****************************************************************
'*****************************************************************
'*****************************************************************

Public Function CrearSocket() As Long
    'CrearSocket por ACHERNAR 7/2007
    'para el foro de www.elhacker.net
    '
    'La funcion abre un socket AF_INET , SOCK_STREAM, IPROTO_TCP
    'si no hay errores retorna un manejador del socket > 0,
    'si hubo errores retorna cero
    CrearSocket = Socket(2, 1, 6)
    If CrearSocket <= 0 Then
        CrearSocket = 0
    End If
End Function

Public Function CerrarSocket(ByVal ManejadorSocket As Long) As Boolean
    'CerrarSocket por ACHERNAR 7/2007
    'para el foro de www.elhacker.net
    '
    'La Funcion cierra un socket abierto
    'Si todo sale bien retorna True
    'Si hay error retorna False
    If Not closesocket(ManejadorSocket) Then
        CerrarSocket = True
    Else
        CerrarSocket = False
    End If
End Function

'*****************************************************************
'*****************************************************************
'*****************************************************************

Private Function CambiarOrdenamiento(ByVal Valor As Long) As Integer
    'CambiarOrdenamiento por ACHERNAR 7/2007
    'para el foro de www.elhacker.net
    '
    If Not Valor <= 32767 Then
        Valor = Valor - 65536
    End If
    CambiarOrdenamiento = htons(Valor)
End Function

'*****************************************************************
'*****************************************************************
'*****************************************************************

Private Function ObtenerIPDelNombre(ByVal Nombre As String) As Long
    'ObtenerIPDelNombre por ACHERNAR 7/2007
    'para el foro de www.elhacker.net
    '
    Dim PunteroAEstructura          As Long
    Dim PunteroAUnaIP               As Long
    Dim MiEstructuraHOSTENT         As HOSTENT
    Dim DireccionIP                 As Long
       
    PunteroAEstructura = gethostbyname(Trim$(Nombre))
   
    If PunteroAEstructura = 0 Then
        DireccionIP = 0
    Else
        RtlMoveMemory MiEstructuraHOSTENT, PunteroAEstructura, LenB(MiEstructuraHOSTENT)
        '
        'ahora MiEstructuraHOSTENT.ListaDeDirecciones contiene un arreglo de direccion IP
        'y es necesario obtener un puntero a la primera IP del arreglo
        '
        RtlMoveMemory PunteroAUnaIP, MiEstructuraHOSTENT.ListaDeDirecciones, 4

        If Not PunteroAUnaIP = 0 Then
            '
            'Paso los valores de la IP a una variable Long
            '
            RtlMoveMemory DireccionIP, PunteroAUnaIP, MiEstructuraHOSTENT.Longitud
            '
        Else
            DireccionIP = 0
        End If
    End If
   
    ObtenerIPDelNombre = DireccionIP
   
End Function

'*****************************************************************
'*****************************************************************
'*****************************************************************

Public Function Conectar(ByVal ManejadorSocket As Long, _
                         ByVal NombreHost_IP As String, _
                         ByVal PuertoRemoto As Long, _
                         IP As Boolean) As Long
                         
    'Conectar por ACHERNAR 7/2007
    'para el foro de www.elhacker.net
    '
    'Esta funcion realiza una conexión a un host remoto
    'si el argumento ip es true es que el argumento NombreHost_IP contiene una ip
    'si el argumento ip es false es que el argumento NombreHost_IP contiene el
    'nombre del host
    'Si todo sale bien retorona True
    'Si hay error retorna False
   
    Dim EstructuraDireccion     As sockaddr_in
    Dim Posicion1               As Integer
    Dim Posicion2               As Integer
    Dim IpNumero                As Long
    Dim i                       As Integer
       
    If IP = True Then
        Posicion1 = 1
        IpNumero = 0
        For i = 1 To 4
            Posicion2 = InStr(Posicion1, NombreHost_IP, ".", vbBinaryCompare)
            If Posicion2 = 0 Then
                Posicion2 = Len(NombreHost_IP) + 1
            End If
            IpNumero = IpNumero + CLng(Mid(NombreHost_IP, Posicion1, _
                                           Posicion2 - Posicion1)) * 256 ^ (i - 1)
            Posicion1 = Posicion2 + 1
        Next i
        EstructuraDireccion.Direccion = IpNumero
    Else
        EstructuraDireccion.Direccion = ObtenerIPDelNombre(NombreHost_IP)
    End If
   
    EstructuraDireccion.Familia = 2
    EstructuraDireccion.Puerto = CambiarOrdenamiento(PuertoRemoto)
       
    If connect(ManejadorSocket, EstructuraDireccion, Len(EstructuraDireccion)) Then
        Conectar = False
    Else
        Conectar = True
    End If
   
End Function

'*****************************************************************
'*****************************************************************
'*****************************************************************

Public Function Recibir(ByVal ManejadorSocket As Long, _
                        StringBuffer As String) As Long
                       
    'ObtenerIPDelNombre por ACHERNAR 7/2007
    'para el foro de www.elhacker.net
    '
    'Esta funcion coloca los datos que arriban en un buffer
    'Si no hay errores retorna un valor mayor que cero
    'que es la cantidad de bytes recibidos
    Dim ByteBuffer(1 To 8192)               As Byte
    Dim BytesRecibidos                      As Long
   
    BytesRecibidos = recv(ManejadorSocket, ByteBuffer(1), 8192, 0&)
    If BytesRecibidos > 0 Then
        StringBuffer = StrConv(ByteBuffer, vbUnicode)
        StringBuffer = Left$(StringBuffer, BytesRecibidos)
    End If
    Recibir = BytesRecibidos
End Function

Public Function Enviar(ByVal ManejadorSocket As Long, _
                       StringBuffer As String) As Long
   
    'ObtenerIPDelNombre por ACHERNAR 7/2007
    'para el foro de www.elhacker.net
    '
    'Esta funcion envia los datos colocados en el buffer
    'Si no hay errores retorna un valor mayor que cero
    'que es la cantidad de bytes enviados
    Dim ByteBuffer()                        As Byte
    Dim BytesAEnviar                        As Long
    Dim BytesEnviados                       As Long
   
    BytesAEnviar = Len(StringBuffer)
   
    If BytesAEnviar > 0 Then
        ByteBuffer = StrConv(StringBuffer, vbFromUnicode)
        BytesEnviados = send(ManejadorSocket, ByteBuffer(0), BytesAEnviar, 0&)
        Enviar = BytesEnviados
    Else
        Enviar = 0
    End If
End Function

Public Function EstadoSocket(ByVal Manejador As Long) As Integer
    'EstadoSocket por ACHERNAR 7/2007
    'para el foro de www.elhacker.net
    '
    'esta funcion muestra el estado de un socket
    'retorna valores entre 0 y 7
    '           0 - Desconectado
    '           1 - Lectura(se puede leer)
    '           2 - Escritura(se puede escribir)
    '           3 - Lectura y Escritura
    '           4 - Error
    '           5 - Error y Lectura
    '           6 - Error y Escritura
    '           7 - Error, Lectura y Escritura
   
    Dim Retorno                 As Long
    Dim Lectura                 As fd_set
    Dim Escritura               As fd_set
    Dim Error                   As fd_set
   
    Lectura.Contador = 1
    Escritura.Contador = 1
    Error.Contador = 1
    Lectura.Arreglo(1) = Manejador
    Escritura.Arreglo(1) = Manejador
    Error.Arreglo(1) = Manejador
       
    Retorno = vbselect(0&, Lectura, Escritura, Error, 0&)
   
    If Retorno <= 0 Then
        EstadoSocket = 0
        GoTo Final
    Else
        '
        'Si el socket se encuentra en estado de Lectura, Escritura o Error
        'la funcion vbSelect retorna un valor MAYOR  que cero (0)
        '
        If Lectura.Contador > 0 Then
            EstadoSocket = EstadoSocket + 1
        End If
        If Escritura.Contador > 0 Then
            EstadoSocket = EstadoSocket + 2
        End If
        If Error.Contador > 0 Then
            EstadoSocket = EstadoSocket + 4
        End If
    End If
Final:
End Function

Public Function MensajeEntrante(Socket As Long) As Boolean
    'MensajeEntrante por ACHERNAR 7/2007
    'para el foro de www.elhacker.net
    '
    'Esta funcion indica si el socket está en estado
    'De Lectura. si lo está retorna True.
    'Si no hay datos para leer en el socket retorna False.
    MensajeEntrante = False
    Select Case EstadoSocket(Socket)
            Case Is = 1
                MensajeEntrante = True
            Case Is = 3
                MensajeEntrante = True
            Case Is = 5
                MensajeEntrante = True
            Case Is = 7
                MensajeEntrante = True
    End Select
End Function

'*****************************************************************
'*****************************************************************
'*****************************************************************

'<el codigo termino justo antes de esta etiqueta>

hay un par de funciones que tienen cosas al pedo pero funcionan igual
como la de conectar y la de ver el estado del socket... le puse un par
de cosas mas para mostrarlas, pero no son necesarias para que funcione
En línea

Achernar


Desconectado Desconectado

Mensajes: 317



Ver Perfil
Re: Introduccion a APIs y como evitar el uso de MSWINSCK.OCX con APIs
« Respuesta #4 en: 5 Julio 2007, 23:41 pm »

ahora pongo un código para un formulario que use este modulo...
es una terminal multipropósito... seria como una especie de telnet

Código:
'<el codigo empieza justo despues de esta etiqueta>

Option Explicit

'Este proyecto necesita que se le agrege el modulo que esta en el tutorial

'Este codigo va en un formulario form1 con 4 textboxs (Text1, Text2, Text3, Text4)
'el text4 debe tener scrollbars horizontal y vertical y estar en modo Multiline
'ademas se necesitan 2 botones command1 y command2
'tambien un timer Timer1
'
'compilado tenemos una especie te telnet.. que pesa 28 KB y no necesita ningun ocx
'y comprimido con el upx pesa 10 kb... entra mas veces en un diskette que granos de
'arena en tu bolsillo XD

Private MiSocket As Long


Private Sub Command2_Click()
    On Error GoTo SalidaCommand2
    If Enviar(MiSocket, Trim$(Text3.Text) + vbCrLf) > 0 Then
        Text4.Text = Text4.Text + "ENVIADO: " + Trim$(Text3.Text) + vbCrLf
    Else
        Text4.Text = Text4.Text + "% Error al intentar enviar el mensaje " + vbCrLf
    End If
SalidaCommand2:
End Sub

Private Sub Form_Load()
    Timer1.Interval = 100
    Timer1.Enabled = False
    Me.Width = 5280
    Me.Height = 4170
    Me.Caption = "Terminal Multiproposito por Achernar"
    With Text1
        .Height = 285
        .Left = 120
        .Top = 120
        .Width = 3975
    End With
    With Text2
        .Height = 285
        .Left = 120
        .Top = 480
        .Width = 3975
    End With
    With Text3
        .Height = 285
        .Left = 120
        .Top = 1320
        .Width = 3975
    End With
    With Text4
        .Height = 1815
        .Left = 120
        .Top = 1800
        .Width = 4935
    End With
    With Command1
        .Caption = "Conectar"
        .Height = 615
        .Left = 4200
        .Top = 120
        .Width = 855
    End With
    With Command2
        .Caption = "Enviar"
        .Enabled = False
        .Height = 255
        .Left = 4200
        .Top = 1320
        .Width = 855
    End With
   
End Sub

Private Sub Command1_Click()
    On Error GoTo SalidaCommand1
    Dim EsIP            As VbMsgBoxResult
    Dim VerdaderoFalso  As Boolean
    If IniciarSesionSocket Then
        Text4.Text = Text4.Text + "% Winsock iniciado" + vbCrLf
        DoEvents
        MiSocket = CrearSocket
        If MiSocket <> 0 Then
            Text4.Text = Text4.Text + "% Socket creado" + vbCrLf
            DoEvents
            EsIP = MsgBox("Si el host remoto fue ingresado como una ip --> Si" _
                    + vbCrLf + "sino --> NO", vbYesNo, "Ingrese el tipo de host")
            If EsIP = 6 Then
                VerdaderoFalso = True
            Else
                VerdaderoFalso = False
            End If
            If Conectar(MiSocket, _
                        Trim$(Text1.Text), _
                        CLng(Trim$(Text2.Text)), _
                        VerdaderoFalso) Then
                Text4.Text = Text4.Text + "% Conetado con el Host Remoto" + vbCrLf
                DoEvents
                Command1.Enabled = False
                Command2.Enabled = True
                Timer1.Enabled = True
            Else
                Text4.Text = Text4.Text + "% Error al conectar con el Host Remoto" + vbCrLf
                DoEvents
                TeminarSesionSocket
            End If
        Else
            Text4.Text = Text4.Text + "% Error al crear Socket" + vbCrLf
            DoEvents
            TeminarSesionSocket
        End If
    Else
        Text4.Text = Text4.Text + "% Error al iniciar Winsock" + vbCrLf
    End If
    GoTo Salida2Command1
SalidaCommand1:
    Text4.Text = Text4.Text + "% Hubo algun error :/" + vbCrLf
    DoEvents
    TeminarSesionSocket
Salida2Command1:
End Sub

Private Sub Timer1_Timer()
    Dim Buffer As String
    If MensajeEntrante(MiSocket) Then
        If Recibir(MiSocket, Buffer) > 0 Then
            Text4.Text = Text4.Text + "RECIBIDO: " + Buffer
        Else
            Text4.Text = Text4.Text + "% Se ha perdido la conexión con el host" + vbCrLf
            Command1.Enabled = True
            Command2.Enabled = False
            Timer1.Enabled = False
            TeminarSesionSocket
        End If
    End If
End Sub

'<el codigo termino justo antes de esta etiqueta>

En línea

Achernar


Desconectado Desconectado

Mensajes: 317



Ver Perfil
Re: Introduccion a APIs y como evitar el uso de MSWINSCK.OCX con APIs
« Respuesta #5 en: 5 Julio 2007, 23:43 pm »

DIRECCIONES PARA INVESTIGAR MAS Y MAS Y.... BUENO

Esta es la api guide es un programa que contiene muchisimas apis
Con ejemplos y declaraciones para VB

http://www.soft-ware.net/hobby/programmierung/referenz/p03951.asp


acá estan las funciones winsock en el MSDN de Microsoft… si aprenden
a no perderse en ese mar de información les va a servir de mucho,

http://msdn2.microsoft.com/en-us/library/ms741394.aspx

y como siempre …. http://www.google.com.ar


bufff que largo... esta es la despedida... hagámoslo rápido que no estamos en un aeropuerto. Salu2.
« Última modificación: 5 Julio 2007, 23:48 pm por Achernar » En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Linkear APIS librerias como lo quieran llamar.
Programación C/C++
anonimo12121 4 4,002 Último mensaje 16 Marzo 2011, 17:50 pm
por anonimo12121
Importar APIs
.NET (C#, VB.NET, ASP)
Lekim 0 2,496 Último mensaje 24 Noviembre 2015, 00:45 am
por Lekim
Duda con algunas APIS de VB
Ingeniería Inversa
.:UND3R:. 1 2,264 Último mensaje 25 Abril 2016, 07:47 am
por fary
Ayuda con las APIS de windows, soy principiante
Ingeniería Inversa
papelito 4 3,240 Último mensaje 12 Enero 2020, 12:13 pm
por xor.pt
¿Como crear un API gateway forntend para relacionarlo con las APIs de la parte de backend?
Desarrollo Web
aitorBoole 1 2,533 Último mensaje 3 Noviembre 2021, 18:47 pm
por MinusFour
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines