;...................................; ; ; ; Charla sobre injertos en PE32 ; ; Autor: Tornamen ; ; ; ; Canal: #crackers IRC-HISPANO. ; ; Fecha: Fri Jan 20 2006 ; ; Duración: 1:30h ; ; ; ;...................................; <@Tornamen> Probando... <@Tornamen> 1, 2, 3 <@Tornamen> bien <@Tornamen> Hola y bienvenidos a esta charla sobre injertos en PE32, el guión lo tienen en la web http://www.fr33project.org/charla.htm <@Tornamen> agradezco mucho la asistencia a la charla <@Tornamen> y esperemos que todo salga bien <@Tornamen> las dudas irán de siguiente modo <@Tornamen> cuando les surgan abrirán un privado a S-P-A-R-K <@Tornamen> y le pediran turno para preguntar <@Tornamen> cada cierto tiempo ire dando tandas <@Tornamen> y S-P-A-R-K dará paso en orden a los que le hayan pedido vez con un voice <@Tornamen> para entender la charla se tendrán que tener un mínimo de conocimientos <@Tornamen> aunque sin estos puede llegarse a entender la idea de la misma <@Tornamen> intentaré que sea fácil de entender <@Tornamen> los conocimientos previos vienen a ser: <@Tornamen> 1. Saber ASM <@Tornamen> 2. Conocer los PE32 <@Tornamen> 3. Saber algo sobre ingenieira inversa <@Tornamen> y poco más se me ocurre <@Tornamen> pero repito que sin estos conocimientos será posible entenderlo <@Tornamen> Vamos por partes: <@Tornamen> 2) ¿Qué es un injerto? <@Tornamen> Un injerto o como yo los denomino, es una implantación de un código donde ese código antes no estaba <@Tornamen> así de simple <@Tornamen> me he tomado la libertad de clasificarlos de dos maneras básicas <@Tornamen> no se si existirá esto, pero creo que es una buena forma de verlo <@Tornamen> tenemos injerto de reemplazamiento y de inserción <@Tornamen> comentaré un poco cada uno: <@Tornamen> reemplazamiento: sustituimos unos bytes donde antes había otros. <@Tornamen> inserción: metemos unos bytes donde antes no había sin destruir nada. <@Tornamen> pondré un ejemplo de como sería cada uno, a ver que piense... <@Tornamen> vale ya se, imaginemos la siguiente instruccion: MOV EAX, 3 <@Tornamen> pues un injerto de esta otra instruccion: MOV EAX, 5 por reemplazamiento sería: <@Tornamen> MOV EAX, 5 <@Tornamen> al final quedaría eso <@Tornamen> y por inserción podría quedar: <@Tornamen> MOV EAX, 3 <@Tornamen> MOV EAX, 5 <@Tornamen> o <@Tornamen> MOV EAX, 5 <@Tornamen> MOV EAX, 3 <@Tornamen> depende de si lo metemos antes o después <@Tornamen> en mi opinión los injertos por inserción (recuerdo que este término me lo he inventado para darle claridad al asunto y el otro también) <@Tornamen> son más complicados de llevar a cabo <@Tornamen> por un simple motivo, que hay que añadir algo y puede no entrar donde queremos por ejemplo <@Tornamen> bien, hasta aquí doy tanda de preguntas <@Tornamen> recordar que para preguntar, abris privado a S-P-A-R-K y el os dará paso en orden con un voice <@Tornamen> S-P-A-R-K alguna duda? <@Tornamen> vaya siento el pequeño imprevisto <@Tornamen> ha sido bastante molesto <@Tornamen> S-P-A-R-K está ahí? <@Tornamen> joer... <@Tornamen> bueno continuo con el tema, supongo que de momento todo claro <@Tornamen> 3) Cosas a tener en cuenta para realizar un injerto. <@Tornamen> Para realizar un injerto hay que tener en cuenta diversos factores <@Tornamen> El primero es: en que tipo de ejecutable quiero hacerlo? <@Tornamen> como sabeis hay varios tipos de binarios: ELF, PE32.. <@Tornamen> una vez elegido el tipo de ejecutable <@Tornamen> tenemos que saber en que sistema operativo <@Tornamen> y como funciona ese sistema operativo <@Tornamen> para conocer nuestras reestricciones <@Tornamen> o a veces ventajas ;) <@Tornamen> lo que hay que plantearse después es lo siguiente: <@Tornamen> ¿Qué quiero hacer? <@Tornamen> dependiendo de lo que queramos hacer será mas o menos dificil <@Tornamen> ahora voy a plantear un par de injertos y os diré como solucionarlos <@Tornamen> agradecería que los que saben del tema preguntaran o aclararan cosas que no han quedado claras <@Tornamen> por que siempre hay cosas que a uno se le escapan <@Tornamen> 4) Planteamiento de un problema para realizar varios injertos. <@Tornamen> un segundo que tengo un pequeño problema tecnico <@Tornamen> bien, ya está <@Tornamen> vamos a plantear varios problemas: <@Tornamen> Primero: Injerto por reemplazo en una sección. <@Tornamen> imaginemos que en la sección .text de nuestro PE32 <@Tornamen> tenemos el código como se suele ver <@Tornamen> por cierto solo vamos a hablar de los injertos en los .EXE, si quieren puedo otro día dar otra charla de otro formato <@Tornamen> la forma más sencillas de hacer un injerto por reemplazo es en los bytes de alineacion de sección <@Tornamen> que es esto se preguntarán? <@Tornamen> muy sencillo: cada sección tiene un alineamiento <@Tornamen> esto es necesario por varios motivos <@Tornamen> que no vamos a explicar por que nos vamos del tema <@Tornamen> que es lo que contienen estos bytes? <@Tornamen> Nada, solo ceros <@Tornamen> son útiles? No. <@Tornamen> solo están para que la sección tenga un tamaño <@Tornamen> así que puede darse que el 90% de una sección sea código <@Tornamen> y el 10% bytes de alineamiento <@Tornamen> lo más sencillo para probar un injerto es con un editor hexadecimal <@Tornamen> abrirlo un .EXE ir al final de la seccion de codigo <@Tornamen> y si hay bytes de alineamiento meter un código <@Tornamen> que luego podríamos usar <@Tornamen> solo reemplazando esos ceros con lo que nos interese <@Tornamen> pero OJO, cuidado con pasarse a la sección de debajo <@Tornamen> y una vez que tengamos nuestro código en bytes de alineamiento que hacemos? <@Tornamen> muy simple, podemos meter un JMP a esa zona <@Tornamen> sustituyendo cualquier cosa en la seccion de código, por ejemplo otro JMP <@Tornamen> y una vez que vaya a nuestra zona <@Tornamen> y haga lo que nos interesa <@Tornamen> restaurar el flujo normal <@Tornamen> (al final veremos como hacer esto que digo no os preocupeis) <@Tornamen> Imaginemos que no tenemos bytes de alineamiento de sección, <@Tornamen> ¿Qué podemos hacer? <@Tornamen> hay varias posibilidades <@Tornamen> aumentar el alineamiento de seccion <@Tornamen> y restaurar la cabecera de secciones y algun miembro de una cabecera que haga falta para que funcione <@Tornamen> y meterlo en ese nuevo alineamiento <@Tornamen> y claro también haría falta insertar ceros como bytes de alineamiento <@Tornamen> pero esta técnica puede ser algo complicada <@Tornamen> así que puede ser una buena idea buscar otras opciones <@Tornamen> en mi experiencia con los PE, aun no he visto una cabecera de secciones completa <@Tornamen> y esto que quiere decir? <@Tornamen> que tiene una especie de bytes de alineamiento donde podemos meter la cabecera de una nueva sección <@Tornamen> para no complicarnos la vida, metelos la cabecera de nuestra nueva sección la última <@Tornamen> y la sección la pondremos al final del fichero <@Tornamen> de esta forma es mucho más fácil <@Tornamen> pero hay más optativas (seguro que al final me dejo alguna) <@Tornamen> otra opción que podemos considerar <@Tornamen> es hacer un <@Tornamen> injerto de insercción <@Tornamen> estos injertos son bastante complicados por que suelen traer problemas <@Tornamen> voy a explicar el motivo <@Tornamen> dado este ejemplo: <@Tornamen> ( un segundo que cojo un depurador) <@Tornamen> 00401000 > B8 02000000 MOV EAX,2 <@Tornamen> 00401005 E8 16000000 CALL eee.00401020 <@Tornamen> imaginemos que queremos hacer un injerto <@Tornamen> en este código <@Tornamen> tenemos un problema <@Tornamen> si metemos los bytes con el código que queramos <@Tornamen> antes del MOV EAX, 2 <@Tornamen> no pasará nada <@Tornamen> (teoricamente solo a lo que esas dos instrucciones de refiere ) <@Tornamen> si lo metemos entre el MOV y el CALL tampoco pasará nada <@Tornamen> pero que ocurre si lo hacemos debajo del CALL? <@Tornamen> pues muy sencillo saberlo <@Tornamen> si nos fijamos el CALL está en la direccion de memoria 00401005 <@Tornamen> y llama a 00401020 <@Tornamen> una direccion superior <@Tornamen> así que en memoria la tendriamos por debajo: <@Tornamen> 00401000 > B8 02000000 MOV EAX,2 <@Tornamen> 00401005 E8 16000000 CALL eee.00401020 <@Tornamen> ... <@Tornamen> 00401005 ... <@Tornamen> perdón <@Tornamen> 00401000 > B8 02000000 MOV EAX,2 <@Tornamen> 00401005 E8 16000000 CALL eee.00401020 <@Tornamen> .... <@Tornamen> 00401020 <@Tornamen> estaría debajo <@Tornamen> si insertamos unos bytes debajo de ese CALL <@Tornamen> lo que habia en la posicion 00401020 <@Tornamen> se desplazará hacia abajo tantos bytes como metamos <@Tornamen> y el CALL ya no irá donde tendría que ir <@Tornamen> y el resultado puede ser caótico <@Tornamen> y si tenemos que hacerlo así por obligación y por que no tenemos otra opción? <@Tornamen> pues tenemos que reparar el CALL <@Tornamen> de una forma muy sencilla <@Tornamen> si metemos 3 bytes <@Tornamen> sustituimos CALL 00401020 <@Tornamen> por <@Tornamen> sustituimos CALL 00401023 <@Tornamen> y ya funcionará otra vez <@Tornamen> así parece facil <@Tornamen> pero si tenemos 200 CALL (quien dice CALL dice salto condicional e incondicional) debajo¿? <@Tornamen> tendríamos que reparar 200 instrucciones! <@Tornamen> y una de dos <@Tornamen> o tenemos mucha paciencia y lo hacemos a mano <@Tornamen> o hacemos un programa que nos lo auto - repare * Tornamen piensa que mas puede decir antes de pasar a los injertos en memoria... <@Tornamen> S-P-A-R-K alguna duda? <@S-P-A-R-K> nop <@Tornamen> bien <@Tornamen> S-P-A-R-K se me queda algo de momento? <@S-P-A-R-K> no, va bien :) <@Tornamen> bien voy a hacer un pequeño ejemplo para que esto ultimo quede bien claro <@Tornamen> y luego explico que pasa con los saltos negativos <@Tornamen> darme un segundo :) <@Tornamen> bien ya está <@Tornamen> imaginemos lo siguiente: <@Tornamen> 00401000 > 33C0 XOR EAX,EAX <@Tornamen> 00401002 8BC0 MOV EAX,EAX <@Tornamen> 00401004 ^EB FA JMP SHORT eee. <+ModuleEntryPoint> <@Tornamen> 00401006 E8 F7FFFFFF CALL eee.00401002 <@Tornamen> el entry point es 00401000 <@Tornamen> bien <@Tornamen> imaginemos que queremos hacer un injerto de 2 instrucciones <@Tornamen> justo después del 00401000 > 33C0 XOR EAX,EAX <@Tornamen> para probar el injerto serán estas instrucciones: <@Tornamen> XOR ECX, ECX <@Tornamen> MOV EDX, ECX <@Tornamen> bien, una vez insertadas en el código, el código quedaría así: <@Tornamen> 00401000 > 33C0 XOR EAX,EAX <@Tornamen> 00401002 33C9 XOR ECX,ECX <@Tornamen> 00401004 8BD1 MOV EDX,ECX <@Tornamen> 00401006 8BC0 MOV EAX,EAX <@Tornamen> 00401008 ^EB F6 JMP SHORT eee. <+ModuleEntryPoint> <@Tornamen> 0040100A E8 F3FFFFFF CALL eee.00401002 <@Tornamen> esto quedaría así <@Tornamen> ah una cosa, es obvio por que queremos que los saltos y CALL esten reparados no? <@Tornamen> por que puede ser un CALL que llame a GetModuleHandle y es vital <@Tornamen> para el funcionamiento del programa <@Tornamen> entonces, el objetivo es insertar un código propio, que haga lo que tenga que hacer <@Tornamen> y luego el funcionamiento del programa siga intacto <@Tornamen> como vemos el injerto que he puesto arriba no está reparado <@Tornamen> para repararlo es muy simple <@Tornamen> vamos al CALL eee.00401002 <@Tornamen> como vemos está en la dirección 0040100A <@Tornamen> y llamada a 00401002 <@Tornamen> es una llamada negativa <@Tornamen> para repararlo hay que aplicar la lógica <@Tornamen> hemos insertado <@Tornamen> 4 bytes <@Tornamen> 00401002 33C9 XOR ECX,ECX <@Tornamen> 00401004 8BD1 MOV EDX,ECX <@Tornamen> aquí se ve claramente <@Tornamen> bien <@Tornamen> antes iba a 00401002 <@Tornamen> el ultimo bytes del injerto está en 00401004 <@Tornamen> 00401004 es mayor que 00401002? sí <@Tornamen> por lo cual tenemos que reparar <@Tornamen> simplemente es sumar al valor del CALL <@Tornamen> los bytes de injerto <@Tornamen> CALL eee.00401002 + 4 <@Tornamen> = 00401006 <@Tornamen> entonces el CALL reparado es CALL eee.00401006 <@Tornamen> y el injerto queda así: <@Tornamen> 00401000 > 33C0 XOR EAX,EAX <@Tornamen> 00401002 33C9 XOR ECX,ECX <@Tornamen> 00401004 8BD1 MOV EDX,ECX <@Tornamen> 00401006 8BC0 MOV EAX,EAX <@Tornamen> 00401008 ^EB F6 JMP SHORT eee. <+ModuleEntryPoint> <@Tornamen> 0040100A E8 F7FFFFFF CALL eee.00401006 <@Tornamen> de esta forma <@Tornamen> se hace el XOR EAX, EAX <@Tornamen> luego nuestro código <@Tornamen> el JMP ese <@Tornamen> y el CALL va donde iba al princpio <@Tornamen> como veis va a la posicion 00401006 que hay: 00401006 8BC0 MOV EAX,EAX <@Tornamen> y antes del injerto el tema estaba así: <@Tornamen> 00401000 > 33C0 XOR EAX,EAX <@Tornamen> 00401002 8BC0 MOV EAX,EAX <@Tornamen> 00401004 ^EB FA JMP SHORT eee. <+ModuleEntryPoint> <@Tornamen> 00401006 E8 F7FFFFFF CALL eee.00401002 <@Tornamen> aqui iba a la posicion 00401002 que estaba MOV EAX,EAX <@Tornamen> como vemos, despues de reparado va al mismo sitio <@Tornamen> bien, esto no se puede hacer en memoria de esta manera <@Tornamen> esto se hace sobre un PE32 que este en el disco <@Tornamen> pero ojo <@Tornamen> una vez que haces un injerto de insercción tienes que borrar los mismos bytes que añadas <@Tornamen> de los bytes de alineamiento <@Tornamen> para que el alineamiento siga igual <@Tornamen> o tambien puedes borrar algunas instrucciones o lo que son datos <@Tornamen> pero el tamaño de la sección tiene que quedar el mismo <@Tornamen> y según que decision para hacer el injerto tomemos tendremos que reparar más o menos <@Tornamen> el metodo para CALL o saltos positivos es lo mismop <@Tornamen> siempre es usar la lógica <@Tornamen> tanda de preguntas <@Tornamen> S-P-A-R-K da voice a quien tenga :) * S-P-A-R-K sets mode: +v Sha0 <@Tornamen> Sha0 hola buenas noches, tu dirás :) <+Sha0> es posible realizar saltos relativos positivos sin hacer bytes nulos?Ç <@Tornamen> no entiendo eso de hacer bytes nulos <+Sha0> negativos como sale 0xff .. no hay problema con los relativos <@Tornamen> podrías explicarlo mejor? <+Sha0> si injertas a traves de otra aplicación, <+Sha0> y esta te corta los bytes nulos <@Tornamen> A injerta a B <+Sha0> si usas saltos absolutos <+Sha0> has de saber las direccciones <+Sha0> mejor relativos, no? <@Tornamen> hombre <+Sha0> pues relativo hacia delante .. chungo <@Tornamen> tu con el depurador ves los saltos y tal <@Tornamen> a direcciones absolutas <@Tornamen> pero al ver el PE32 con un editor hexadecimal <@Tornamen> hay muy pocos saltos absolutos <@Tornamen> los absolutos suelen ser los de la IAT por ejemplo <@Tornamen> entonces no tienen mayor problema <@Tornamen> pero a la hora de reparar es sencillo <@Tornamen> a las direcciones absolutas aplicas la misma formula <@Tornamen> solo que antes de hacer nada <@Tornamen> le restas la direccion base <@Tornamen> y la direccion de seccion <@Tornamen> para que se quede en un simple relativo <@Tornamen> no se si me explico <+Sha0> oks <+Sha0> haces un delta me imagino <@Tornamen> tienes más dudas? <+Sha0> nop <@Tornamen> o alguna cosa que añadir? <+Sha0> no <@Tornamen> okey, gracias por tu colaboración <@Tornamen> S-P-A-R-K más dudas <@S-P-A-R-K> no * S-P-A-R-K sets mode: -v Sha0 <@Tornamen> bueno yo creo que ya puedo pasar a injertos en memoria <@Tornamen> pero antes, S-P-A-R-K algo que añadir? <@Tornamen> (injertos en la IAT no voy a tratar pero no os preocupeis e hecho un documento donde explico todo esto detalladamente de unas 70 paginas con ejemplos practicos) <@Tornamen> bueno, continuo entonces * Tornamen bebe agua <@Tornamen> alguien parece que tiene una duda * S-P-A-R-K sets mode: +v MrEslao <@Tornamen> MrEslao adelante :) <+MrEslao> OK <+MrEslao> no es mejor <+MrEslao> irte de donde estes <+MrEslao> injertar, restaurar lo que te comas y volver??? <@Tornamen> si lo que tu dices <@Tornamen> de reemplazar EP <@Tornamen> hacer tal cosa <@Tornamen> restaurar OEP <@Tornamen> y a correr <@Tornamen> como hacen algunos pakers no? <+MrEslao> no <+MrEslao> digo que da igual las instrucciones que te comas <@Tornamen> ah vale vale <@Tornamen> si si te he entendido <@Tornamen> pero para eso necesitas poder escribir en la seccion <@Tornamen> y usas cosas como virtualprotect <@Tornamen> o modificarlo en el disco los permisos de seccion <+MrEslao> claro <@Tornamen> yo no suelo ver secciones de código con permisos de escrituras <@Tornamen> no habría problema <@Tornamen> :) <@Tornamen> es una buena forma <@Tornamen> pero no me quería meter en eso <+MrEslao> OK <@Tornamen> por que es algo más avanzado <@Tornamen> y quiero dar una idea más general <@Tornamen> y no más especifica <@Tornamen> me gustaría que si tienes algo que añadir lo hicieras o alguna cosa <+MrEslao> Ok <@Tornamen> algo más? <+MrEslao> nada solo eso * S-P-A-R-K sets mode: -v MrEslao <@Tornamen> okey gracias por su colaboración <@Tornamen> S-P-A-R-K más?¿ <@S-P-A-R-K> no <@Tornamen> Recuerdo que para dudas abris privado a S-P-A-R-K y el en las tandas os dará paso en orden. <@Tornamen> pues darme un par de segundos de descanso y pasamos a injertos en memoria <@Tornamen> siento no haberme podido preparar nada la charla <@Tornamen> pero estoy con examenes <@Tornamen> y no se puede hacer todo, aún así espero que se me vaya entendiendo, es un tema apasionante y el que quiera profundizar va a poder, luego diré como. <@Tornamen> Puede que alguna de estas tecnicas se puedan usar en otro formatos <@Tornamen> como los ELF, no lo sé, nunca los he visto <@Tornamen> pero es probable <@Tornamen> /* Minuto de descanso */ * S-P-A-R-K pone musica de relax.... y se tira hacia atras en el asiento.... <@S-P-A-R-K> xD <@Tornamen> por cierto en crackslatinos mi nick es \0x90\ por si alguien no lo sabe <@Tornamen> weno S-P-A-R-K preparado? <@S-P-A-R-K> si <@S-P-A-R-K> go ahead dude xD <@Tornamen> bien, el último punto es el de injertos en memoria <@Tornamen> ya que salió el tema de VirtualProtect y tal <@Tornamen> voy a usarlo como ejemplo <@Tornamen> ¿Qué es un injerto en memoria? <@Tornamen> Un injerto en memoria se produce cuando reemplazamos unos bytes de un programa en memoria por unos que nos interesan <@Tornamen> es decir, es un injerto por reemplazo en memoria <@Tornamen> como podemos realizar un injerto en memoria? <@Tornamen> pues eso depende del S.O en primer lugar <@Tornamen> y de los permisos que tengamos y varios factores <@Tornamen> nosotros vamos a ver como hacer un injerto en memoria muy muy específico <@Tornamen> Un injerto en memoria en win32, en un programa en memoria, con la WIN 32 API. <@Tornamen> Como sabeis (esto es una coletilla, no teneis por que saberlo) windows tiene unas funciones ya hechas <@Tornamen> para que los usen los programadores en su Sistema Operativo <@Tornamen> estas funciones residen en diversas DLL <@Tornamen> como kernel32.dll user23.dll <@Tornamen> el programa que esta en memoria está en modo aplicacion es decir anillo 3 (ring 3) <@Tornamen> el máximo nivel de privlegio en win32 es ring 0 <@Tornamen> hay 2 funciones que nos interesan especialmente para hacer un injerto en memoria de la WIN32 API * Tornamen mire en msdn como eran las declaraciones... <@Tornamen> las dos son VirtualQuery y VirtualProtect <@Tornamen> y nos serán de mucha ayuda <@Tornamen> no voy a explicar como hacer un injerto desde un programa ageno (royo loader) por que eso ya viene en el documento <@Tornamen> vamos a ver en que consisten estas dos funciones segun microsoft: <@Tornamen> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/memory/base/virtualquery.asp <@Tornamen> SIZE_T VirtualQuery( <@Tornamen> LPCVOID lpAddress, <@Tornamen> PMEMORY_BASIC_INFORMATION lpBuffer, <@Tornamen> SIZE_T dwLength <@Tornamen> ); <@Tornamen> esto es lo que nos interesa <@Tornamen> voy a explicar cada campo un poco, (puede que me equivoco que me corrijan si es así ) <@Tornamen> lpAddress es la dirección base de donde queremos realizar el injerto <@Tornamen> cuando programamos con MASM32 por ejemplo <@Tornamen> vemos que usamos: <@Tornamen> .code <@Tornamen> start: <@Tornamen> habría que pasarle addr start <@Tornamen> en este caso <@Tornamen> lpBuffer es una estructura donde tiene el MEMORY_BASIC_INFORMATION <@Tornamen> en MASM32 podemos usar: mbi MEMORY_BASIC_INFORMATION <+> <@Tornamen> y listo en .data? <@Tornamen> no tiene mayor complicación <@Tornamen> y luego el tamaño del MEMORY_BASIC_INFORMATION, que es un sizeof <@Tornamen> a mbi <@Tornamen> vamos, la cosa quedaría así: <@Tornamen> .data? <@Tornamen> mbi MEMORY_BASIC_INFORMATION <+> <@Tornamen> .code <@Tornamen> start: <@Tornamen> invoke VirtualQuery, addr start, addr mbi, sizeof mbi <@Tornamen> y ya podemos usar esta funcion <@Tornamen> asi de fácil <@Tornamen> esta funcion nos da una informacion que necesita VirtualProtect y gracias a ella <@Tornamen> podemos cambiar los permisos de seccion <@Tornamen> y escribir bytes sobre ella <@Tornamen> ahora vamos a ver la función VirtualProtect * Tornamen mirando en msdn... <@Tornamen> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/memory/base/virtualprotect.asp <@Tornamen> aquí está: <@Tornamen> BOOL VirtualProtect( <@Tornamen> LPVOID lpAddress, <@Tornamen> SIZE_T dwSize, <@Tornamen> DWORD flNewProtect, <@Tornamen> PDWORD lpflOldProtect <@Tornamen> ); <@Tornamen> vamos a explicar cada campo <@Tornamen> lpAddress es lo mismo que antes <@Tornamen> si antes usamos addr start <@Tornamen> ahora también <@Tornamen> el dwSize, corresponde a lo que nos dejo el VirtualQuery en mbi.RegionSize <@Tornamen> flNewProtect esto son los flags <@Tornamen> en MASM32 podemos usar algo como: PAGE_EXECUTE_READWRITE <@Tornamen> para cambiar los permisos a esos <@Tornamen> y podes escribir en seccion <@Tornamen> lpflOldProtect son los permisos que tenían antes, cosa que nos dejo el VirtualQuery en EAX al llamarlo <@Tornamen> pero no podemos llamarlo desde EAX <@Tornamen> así que por ejemplo dejamos el dato de eax en la pila <@Tornamen> con un PUSH EAX <@Tornamen> y según lo dicho esto va así: <@Tornamen> .data? <@Tornamen> mbi MEMORY_BASIC_INFORMATION <+> <@Tornamen> .code <@Tornamen> start: <@Tornamen> invoke VirtualQuery, addr start, addr mbi, sizeof mbi <@Tornamen> PUSH EAX <@Tornamen> invoke VirtualProtect, addr start, mbi.RegionSize, PAGE_EXECUTE_READWRITE, ESP <@Tornamen> y listo, ya podemos escribir en la sección de código <@Tornamen> ahora para escribir necesitamos usar otra función <@Tornamen> necesitamos usar WriteProcessMemory * @Tornamen mirando msdn.. <@Tornamen> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/writeprocessmemory.asp <@Tornamen> BOOL WriteProcessMemory( <@Tornamen> HANDLE hProcess, <@Tornamen> LPVOID lpBaseAddress, <@Tornamen> LPCVOID lpBuffer, <@Tornamen> SIZE_T nSize, <@Tornamen> SIZE_T* lpNumberOfBytesWritten <@Tornamen> ); <@Tornamen> vamos a explicar cada campo <@Tornamen> hProcess es el handle del proceso <@Tornamen> buscarlo es un trabajo que se escapa del objetivo <@Tornamen> de esta charla <@Tornamen> lpBaseAddress es el sitio donde queremos escribir <@Tornamen> lpBuffer es un puntero a un buffer <@Tornamen> con lo que queremos escribir <@Tornamen> nSize es un sizeof a ese buffer <@Tornamen> lpNumberOfBytesWritten es un buffer por ejemplo donde nos dicen <@Tornamen> los bytes que se han podido escribir <@Tornamen> normalmente si sabemos que lo que hacemos está bien <@Tornamen> aquí yo siempre uso un NULL <@Tornamen> un ejemplo de un posible uso de WriteProccessMemory usando MASM32 es: <@Tornamen> .data <@Tornamen> programa db "injerto3.exe", 0 <@Tornamen> .data? <@Tornamen> startinfo STARTUPINFO <+> <@Tornamen> pi PROCESS_INFORMATION <+> <@Tornamen> DBEvent DEBUG_EVENT <+> <@Tornamen> .code <@Tornamen> start: <@Tornamen> invoke CreateProcess, addr programa, NULL, NULL, NULL, FALSE, DEBUG_PROCESS + DEBUG_ONLY_THIS_PROCESS, NULL, NULL, addr startinfo, addr pi <@Tornamen> <@Tornamen> .while TRUE <@Tornamen> invoke WaitForDebugEvent, addr DBEvent, INFINITE <@Tornamen> .if DBEvent.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT <@Tornamen> .break <@Tornamen> <@Tornamen> .elseif DBEvent.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT <@Tornamen> MOV EBX, DBEvent.u.CreateProcessInfo.lpStartAddress <@Tornamen> ADD EBX, 2000h <@Tornamen> ADD EBX, 0E0h <@Tornamen> invoke WriteProcessMemory, DBEvent.u.CreateProcessInfo.hProcess, EBX, addr buffer, sizeof buffer, NULL <@Tornamen> .elseif DBEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT <@Tornamen> .if DBEvent.u.Exception.pExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT <@Tornamen> invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_CONTINUE <@Tornamen> .continue <@Tornamen> .endif <@Tornamen> <@Tornamen> .endif <@Tornamen> invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED <@Tornamen> .endw <@Tornamen> invoke CloseHandle, pi.hProcess <@Tornamen> invoke CloseHandle, pi.hThread <@Tornamen> invoke ExitProcess, 0 <@Tornamen> end start <@Tornamen> este es el loader <@Tornamen> que uso en mi tutorial <@Tornamen> para explicarlo y ver que funciona <@Tornamen> solo es una muestra para que veais como funciona <@Tornamen> no quiero entrar más en detalle sobre esto por que nos tirariamos toda la noche <@Tornamen> y ya nos hemos pasado del tiempo estimado <@Tornamen> S-P-A-R-K alguna duda? <@Tornamen> bueno paso al último punto y luego si hay dudas resuelvo <@Tornamen> 5) Despedida y agradecimientos. <@Tornamen> Bueno, ha sido un placer para mi haber podido dar esta charla en un canal como este <@Tornamen> me ha encantado que la gente haya preguntado y demás, hemos tenido imprevisto y han aguantado ahí <@Tornamen> y eso es lo más importante <@Tornamen> espero que hos haya gustado tanto como a mi <@Tornamen> pero aún no se vayan que les diré donde encontrar información <@Tornamen> Antes del momento publicidad los agradecimientos: <@Tornamen> al canal #crackers por supuesto, a crackslatinos y a su gente por que tienen material que es de lo mejor y a toda la gente que me apoya <@Tornamen> la tutorial sobre injertos en pe32 que he realizado está en: http://www.fr33project.org/PE32/Jugando%20con%20PE32.pdf <@Tornamen> y el material que usa en http://www.fr33project.org/PE32 <@Tornamen> está todo lo explicado, más injertos en IAT y demás cosas, con otros ejemplo <@Tornamen> cualquier duda o comentario pueden enviarmelo a 0x90@enye-sec.org <@Tornamen> y bueno <@Tornamen> si alguien tiene una ultima duda, estaré encantado de responder <@Tornamen> S-P-A-R-K :=? <@Tornamen> S-P-A-R-K no está, así que las dudas me las decis por query mejor :) * Tornamen sets mode: -o S-P-A-R-K * Tornamen sets mode: +v Sha0 <@Tornamen> Sha0 dime <+Sha0> oks <+Sha0> que permisos tienen <+Sha0> por defecto <+Sha0> las paginas de la seccion de codigo <+Sha0> pila <+Sha0> y heap <+Sha0> ? <+Sha0> en win32 <+Sha0> es decir <+Sha0> estan protegidas? <+Sha0> como en linux? <@Tornamen> si <+Sha0> code rx <@Tornamen> están protegidas por defecto <+Sha0> etc <@Tornamen> pero con cosas como ollydbg, studpe, a mano <@Tornamen> se pueden cambiar <@Tornamen> sin problema <@Tornamen> tanto en memoria <+Sha0> oks <@Tornamen> como en el disco duro <@Tornamen> tiene en el tutorial como van los permisos <@Tornamen> si tal échale un vistazo <@Tornamen> alguna cosa más? <+Sha0> mola <+Sha0> no <@Tornamen> bien <@Tornamen> si alguien tiene más dudas por privado... * Tornamen sets mode: -v Sha0 <@Tornamen> parece que no, pues doy por finalizada la charla, gracias por asistir en serio, espero que les haya gustado. *** modo: Tornamen pone [-m ] ;...................................; ; FIN ; ; http://www.enye-sec.org ; ;...................................;