¿Generar un ejecutable con configuraciones personalizadas desde otro ejecutable?

Iniciado por Crazy.sx, 24 Noviembre 2012, 08:40 AM

0 Miembros y 1 Visitante están viendo este tema.

Crazy.sx

Hola. Hace unos años atrás había hecho una pregunta parecida a esta pero con VB6, la cosa es que no encuentro el post y creo que la respuesta me la había dado E0N en aquella oportunidad y lo quería ver de nuevo como para usarlo de guía.

Ahora ya no uso VB6 sino VB .NET 2010, y lo que quiero hacer es hacer algo similar a lo que hace, por ejemplo, el bifrost en cuanto a generar un "servidor" con las configuraciones para la conexión, etc., que han sido especificadas de antemano desde el "cliente".

A ver, si me explico mejor. Por ejemplo, tener un programa que tenga dos textbox y un botón y que al hacer clic en ese botón se genere automáticamente otro ejecutable que al ser ejecutado (valga la redundancia) muestre como mensaje los textos que haya ingresado en los textbox del primero.

Aquella vez, E0N, había usado la función Split y un string que servía como delimitador pero tomaba al archivo binario... bueno, algo así, que se yo.   :-\

No se si me he sabido explicar, pero espero que me hayan entendido.

¿Cómo se haría esto?

Espero que me puedan ayudar, gracias.

PD: No estoy haciendo troyano ni nada de eso, solo lo puse como ejemplo al bifrost porqu es lo primero que se me vino a la cabeza y que es exactamente lo que me gustaría hacer.
Destruir K. LOL

seba123neo

si me acuerdo que escribia esa informacion al final del archivo o en una sección, pero habia que saber donde segun la estructura del ejecutable PE. creo que los de visual basic .NET al compilarse a un codigo intermedio no se si eso afectara en la estructura y ese codigo sigue funcionando.
La característica extraordinaria de las leyes de la física es que se aplican en todos lados, sea que tú elijas o no creer en ellas. Lo bueno de las ciencias es que siempre tienen la verdad, quieras creerla o no.

Neil deGrasse Tyson

Keyen Night

Puedes agregar la información a los recursos del ejecutable como array de bytes, si la serializas, haciendo uso de las API:

Código (vb.net) [Seleccionar]

    <DllImport("kernel32.dll", SetLastError:=True)> _
       Public Function BeginUpdateResource(ByVal pFileName As String, _
       <MarshalAs(UnmanagedType.Bool)> ByVal bDeleteExistingResources As Boolean) As IntPtr
    End Function

    <DllImport("kernel32.dll", SetLastError:=True)> _
        Public Function UpdateResource(ByVal hUpdate As IntPtr, _
                                       ByVal lpType As Integer, _
                                       ByVal lpName As Integer, _
                                       ByVal wLanguage As Integer, _
                                       ByVal lpData As Object, _
                                       ByVal cbData As Integer) As Boolean
    End Function

    <DllImport("kernel32.dll", setlasterror:=True)> _
    Public Function EndUpdateResource(ByVal hUpdate As IntPtr, _
                                      ByVal fDiscard As Boolean) As Boolean
    End Function

    <DllImport("kernel32.dll", SetLastError:=True)> _
Public Function LoadResource(ByVal hModule As IntPtr, _
                             ByVal hResInfo As IntPtr) As IntPtr
    End Function

    <DllImport("kernel32.dll", SetLastError:=True)> _
Public Function LoadLibrary(ByVal lpFileName As String) As IntPtr
    End Function

    <DllImport("kernel32.dll")> _
Public Function FindResource(ByVal hModule As IntPtr, _
                             ByVal lpName As Integer, _
                             ByVal lpType As Integer) As IntPtr
    End Function

    <DllImport("kernel32.dll")> _
Public Function LockResource(ByVal hResData As IntPtr) As IntPtr
    End Function

    <DllImport("kernel32.dll", SetLastError:=True, EntryPoint:="FreeLibrary")> _
Public Function FreeLibrary(ByVal hModule As IntPtr) As Boolean
    End Function

    <DllImport("kernel32.dll", SetLastError:=True)> _
Public Function SizeofResource(ByVal hModule As IntPtr, _
                               ByVal hResInfo As IntPtr) As UInteger
    End Function

    <DllImport("kernel32.dll", CharSet:=CharSet.Unicode, EntryPoint:="EnumResourceNamesW", SetLastError:=True)> _
Public Function EnumResourceNames(ByVal hModule As IntPtr, _
                              ByVal lpszType As Integer, _
                              ByVal lpEnumFunc As EnumResNameProcDelegate, _
                              ByVal lParam As IntPtr) As Boolean
    End Function

    Public Delegate Function EnumResNameProcDelegate(ByVal hModule As IntPtr, _
                                                     ByVal lpszType As IntPtr, _
                                                     ByVal lpszName As IntPtr, _
                                                     ByVal lParam As IntPtr) As Boolean


Puedes prepar el ejecutable a generar para buscar en el mismo el recurso, que no existe en el momento que generas el ejecutable, sino que se le agrega después de que se genera. Puedes buscar información de como se usan estas API, espero que te sirva de algo, si no logras dar con la funcionalidad avisas y te doy un ejemplo ;)
La Fé Mueve Montañas...
                                    ...De Dinero

La programación es más que un trabajo es más que un hobby es una pasión...

Crazy.sx

Cita de: seba123neo en 24 Noviembre 2012, 15:03 PM
si me acuerdo que escribia esa informacion al final del archivo o en una sección, pero habia que saber donde segun la estructura del ejecutable PE. creo que los de visual basic .NET al compilarse a un codigo intermedio no se si eso afectara en la estructura y ese codigo sigue funcionando.

Creo que por ahi era la cosa, agregando los datos al final (EOF). Mmm, ahora que me acuerdo se trataban de tres cosas, había un "juntador", "cliente", "servidor" y era el juntador quien unificaba las cosas, pero el cliente y el servidor debían coincidir en los datos para que funcionara.

Seguiré buscando  :silbar:




Cita de: Keyen Night en 24 Noviembre 2012, 15:59 PM
Puedes agregar la información a los recursos del ejecutable como array de bytes, si la serializas, haciendo uso de las API:

Código (vb.net) [Seleccionar]

.
.
.


Puedes prepar el ejecutable a generar para buscar en el mismo el recurso, que no existe en el momento que generas el ejecutable, sino que se le agrega después de que se genera. Puedes buscar información de como se usan estas API, espero que te sirva de algo, si no logras dar con la funcionalidad avisas y te doy un ejemplo ;)

:o No entendí esto Keyen Night, disculpa. ¿Dices sobre agregar el ejecutable a generar dentro del proyecto y enviarle los datos para configurarlo? :S
Destruir K. LOL

Keyen Night

Puedes intentar agregar los datos al final del ejecutable, y que los últimos 4 Bytes sean un Int32 que de el tamaño de los mismo, pero no se hasta que punto esto pueda dañar el ensamblado por eso te recomiendo los Resources.

Aquí esta un ejemplo, en Debug no funciona, vaya a saber quien por que :xD

Código (vb.net) [Seleccionar]
Module Module1

   Sub Main()

       'El File.Exists es solo es para que el generador y la prueba sean el mismo archivo'
       'en tu proyecto obviamente una cosa es el generador y otra es el ejecutable'
       'que se genera, esto como es un ejemplo están las dos cosas juntas.'
       If Not IO.File.Exists("C:\ejemplo.exe") Then

           'Hacemos una copia de nosotros mismos'
           IO.File.Copy(Process.GetCurrentProcess.MainModule.FileName, "C:\ejemplo.exe")

           Dim mensaje As String = "Este mensaje fue introducido al final del ensamblado..."
           Dim tamaño As Integer = mensaje.Length

           Dim ejemplo As New IO.FileStream("C:\ejemplo.exe", IO.FileMode.Open, IO.FileAccess.Write)

           'Nos vamos al final del archivo'
           ejemplo.Seek(0, IO.SeekOrigin.End)

           'Escribimos un margen de 8 bytes vacíos, para evitar errores'
           ejemplo.Write(New Byte(8 - 1) {}, 0, 7)

           'Escribimos el mensaje'
           ejemplo.Write(System.Text.Encoding.Default.GetBytes(mensaje), 0, tamaño)

           'Escribimos la longitud del mismo'
           ejemplo.Write(BitConverter.GetBytes(tamaño), 0, 4)

           ejemplo.Flush()
           ejemplo.Close()

           'Iniciamos el ejecutable con el mensaje'
           Process.Start("C:\ejemplo.exe")

       Else

           'Abrimos el archivo de nuestro propio proceso'
           Dim Ensamblado As New IO.FileStream(Process.GetCurrentProcess.MainModule.FileName, IO.FileMode.Open, IO.FileAccess.Read)

           'Nos ubicamos 4 posiciones hacia atras desde el final'
           Ensamblado.Seek(-4, IO.SeekOrigin.End)

           Dim Buffer As Byte() = New Byte(4 - 1) {}

           Dim TamañoDatos As Integer = 0

           'Leemos los ultimos 4 bytes'
           Ensamblado.Read(Buffer, 0, 4)

           'Estos 4 bytes corresponden al tamaño del mensaje, estan Int32'
           TamañoDatos = BitConverter.ToInt32(Buffer, 0)

           'Redimensionamos el buffer para recibir los datos'
           ReDim Buffer(TamañoDatos - 1)

           'Nos colocamos al inicio del mensaje, tomando en cuenta que contamos'
           'de atras hacia adelante el tamaño del mensaje y los 4 bytes que ocupaba'
           'el tamaño del mismo'
           Ensamblado.Seek(-TamañoDatos - 4, IO.SeekOrigin.End)

           'Leemos el mensaje'
           Ensamblado.Read(Buffer, 0, TamañoDatos)

           Ensamblado.Close()

           'Imprimimos el mensaje'
           Console.WriteLine(String.Format("Este ensamblado contiene el siguiente mensaje: {0}", _
                                           System.Text.Encoding.Default.GetString(Buffer)))

           Console.Read()

       End If

   End Sub

End Module

La Fé Mueve Montañas...
                                    ...De Dinero

La programación es más que un trabajo es más que un hobby es una pasión...

Crazy.sx

Ok, gracias. Voy a probar a ver que me sale.

Encontré: El post del cual les comentaba pero el archivo ya no existe por lo que sigo en la misma :P
http://foro.elhacker.net/programacion_vb/source_editor_de_servers_completo-t171824.0.html;msg812090

Y aquí algo parecido pero no se cómo se lo pasaría a .NET: http://www.antrax-labs.org/2012/05/server-builder-vb6.html
Destruir K. LOL

Novlucker

Lo agregaría como recurso embebido al ejecutable con Mono.Cecil :P
http://hintdesk.com/c-how-to-edit-resource-of-an-assembly/

Otra opción es ver como lo han implementado en el código de flu :P

Saludos
Contribuye con la limpieza del foro, reporta los "casos perdidos" a un MOD XD

"Hay dos cosas infinitas: el Universo y la estupidez  humana. Y de la primera no estoy muy seguro."
Albert Einstein