Hola!
Estoy armando un programa que modifica la sección .text de un ejecutable..
Uso las estructuras:
PIMAGE_DOS_HEADER
PIMAGE_NT_HEADERS
PIMAGE_OPTIONAL_HEADER
PIMAGE_SECTION_HEADER
Por lo que entiendo si hago esto:
// Ajusto el punto de inicio a lo que necesito...
//IOH->AddressOfEntryPoint += 16;
IOH->AddressOfEntryPoint = IOH->BaseOfCode + 16;
Cualquiera de esas dos variantes deberían hacer lo mismo, verdad? Bueno, el problema es que en mi programa de pruebas funciona bien, pero en otros no funciona,, el entrypoint no cambia, y si cambia, lo hace mal..
La pregunta: ¿Puede verse afectado esto por algo asi como un relloc, o hay algo que no tengo en cuanta?
Gracias! Saludos!
Si la primera instruccion de codigo en la sección no es el entry point no es lo mismo, es decir siempre que AddressOfEntryPoint sea diferente de BaseOfCode.
DUMPBIN /headers calc.exe
...
OPTIONAL HEADER VALUES
10B magic # (PE32)
9.00 linker version
52E00 size of code
6A600 size of initialized data
0 size of uninitialized data
12D6C entry point (01012D6C)
1000 base of code
52000 base of data
1000000 image base (01000000 to 010BFFFF)
...
AddressOfEntryPoint
A pointer to the entry point function, relative to the image base address. For executable files, this is the starting address.
BaseOfCode
A pointer to the beginning of the code section, relative to the image base.
¿Estas escribiendo en disco o en memoria?
Hi! Gracias por responder EI!
CitarAddressOfEntryPoint
A pointer to the entry point function, relative to the image base address. For executable files, this is the starting address.
BaseOfCode
A pointer to the beginning of the code section, relative to the image base.
Con que ahí esta el asunto.. pero cambie el que cambie, no queda en la dirección que quiero..
Citar¿Estas escribiendo en disco o en memoria?
En memoria.. tengo una imagen sacada con CreateFileMapping y MapViewOfFile..
Puntualmente entonces lo que necesitaría es que el entrypoint sea siempre desde baseofcode + 16, siendo (generalmente) 0040100.. pero baseofcode puede cambiar, no puedo poner eso como una constante :silbar:
Y no me funciono..
Gracias! Saludos!
No se muy bien que estas tratando de hacer, te recomiendo usar el WinDbg (!dh direccion te ayudara) para ir depurando tu codigo.
Bueno, después de darle vueltas al asunto me parece que lo mejor va a ser modificar "la lógica" del mismo...
El problema radica en que yo al principio de la sección .text pongo X código, al final pongo otro Z código.. mi intención era ejecutar código X y Z primero, para luego saltar al código del ejecutable..
Bueno, si EntryPoint de ejecutable es 0040100 me "pisa" el código X, y si EntryPoint es distinto pasa otra cosa...
Voy a hacer unas pruebas, si todo sale bien pongo el resultado, sino pregunto :xD
CitarNo se muy bien que estas tratando de hacer, te recomiendo usar el WinDbg (!dh direccion te ayudara) para ir depurando tu codigo.
Gracias EI, me sirvió para razonar otras posibles situaciones..
Saludos!
Bueno.. no di con la solucion.. algo me esta faltando,, pongo el code a ver si alguien ve algo malo..
if(strcmp((char *)ISH->Name, ".text") == 0)
{
// Se agranda la sección para ocupar hasta un bloque de 16 justo
while(ISH->Misc.VirtualSize%16 != 0) ISH->Misc.VirtualSize++;
// Funcion "Cifradora", se cifra la sección .text
Cifra((DWORD)(lpFileMap + ISH->PointerToRawData), ISH->Misc.VirtualSize);
// Una copia de la sección .text cifrada (+ align 16)
char *lptextsect = new char[ISH->Misc.VirtualSize];
memset(lptextsect, 0, ISH->Misc.VirtualSize);
memcpy(lptextsect, (void *)(DWORD)(lpFileMap + ISH->PointerToRawData), ISH->Misc.VirtualSize);
// Se guarda el punto de inicio ** push Entrypoint **
ASize = IOH->ImageBase + IOH->AddressOfEntryPoint;
__asm { mov eax, ASize }
__asm { mov dword ptr[opcodes + 11h], eax }
// VirtualSize a EAX y se ajustan los jmps, calls y cmp
// ****************************************************
ASize = ISH->Misc.VirtualSize;
__asm { mov eax, ASize }
__asm { mov dword ptr[opcodes + 44h], eax } // -> call endopcodes
__asm { mov dword ptr[endopcodes + 5], eax } // -> RETADDR, ???? (Size To Decrypt)
__asm { neg eax }
__asm { mov dword ptr[opcodes + 38h], eax } // -> cmp ebx, -????
ASize = sizeof(opcodes)-8;
__asm { sub eax, ASize }
__asm { mov dword ptr[endopcodes + 0Ch], eax } // -> jmp -????
// ****************************************************
// Se Copia todo al PE!
DWORD StartOffset = (DWORD)lpFileMap + ISH->PointerToRawData;
memcpy((void *)(StartOffset), (void *)opcodes, sizeof(opcodes));
memcpy((void *)(StartOffset + sizeof(opcodes)-1), (void *)(lptextsect), ISH->Misc.VirtualSize);
memcpy((void *)(StartOffset + ISH->Misc.VirtualSize + sizeof(opcodes)-1), (void *)endopcodes, sizeof(endopcodes));
// ***************************************************************
// Se ajusta la sección
ISH->Characteristics = 0xE0000020; // Lectura, Ejecucion y escritura!
IOH->AddressOfEntryPoint = (DWORD)IOH->BaseOfCode + 16; // Empezar despues de la clave de 16 digitos
}
Bueno, la idea es ir recorriendo las secciones (Funciona), e ir buscando la sección ".text", una vez encontrada, cifrarla y ponerle su respectiva función descifradora (opcodes y endopcodes)
Desde la linea 15 a la 35 lo que hago es ajustar esos "opcodes", (que funciona tambien)..
El Problema: Si el EntryPoint es 00401000 lo cambio por 00401010 y todo bien! Si el EntryPoint es otro cualquiera, no lo puedo modificar a 00401010! Queda el que tenia antes, y lo raro, el olly me indica con rojo la direccion 00401010 pero igual inicia en donde era el EntryPoint..
Gracias por su tiempo! Saludos!
¿Que se supone que haces con esto al final? ¿Escribir un nuevo ejecutable cifrado en disco?
Citar¿Que se supone que haces con esto al final? ¿Escribir un nuevo ejecutable cifrado en disco?
Upss.. perdón,, pensé que había dicho al principio.. Es un crypter, no creo un nuevo archivo no :silbar:
Trabajo sobre la imagen del mismo PE, la abro con CreateFile,, uso CreateFileMapping y cierro la imagen... Capaz que la *** ahí?! :rolleyes:
Saludos!
No pero entonces mira el resultado con DUMPBIN (/headers). Otra cargalo en WinDbg - File>>Open Executable/ Ctrl + E) y antes de nada hace !dh modulo. ¿Es correcto el entry point o no segun esas herramientas?
Huu.. si.. cualquiera.. Con Olly que es la única herramienta que tengo ahora a mano me dice esto como EntryPoint
ASCII = rC
HEX = 09 72 43
Ahora si que me descoloco, pero es una buena pista.. en casa lo tendré que ver con DUMPBIN y WinDbg
Que raro.. en un ejecutable simple, con 3 secciones funciona.. Bue, reviso y posteo..
Gracias Genio!
Actualizo:Bueno.. creo haber encontrado algo.. pero por que lo hace??
Netcat antes de cifrar (dumpbin /HEADERS):CitarName: .text
VirtualSize: 5234
VirtualAddress: 1000
SizeOfRawData: 5400
FilePointerToRawData: 400
SizeOfCode: 5400
RVA EntryPoint: 1160
Summary: 6000
Netcat después de cifrar (dumpbin /HEADERS):CitarName: .text
VirtualSize: 5240 (Aumento para alinear el code)
VirtualAddress: 1000
SizeOfRawData: 5400
FilePointerToRawData: 400
SizeOfCode: 5400
RVA EntryPoint: 1010 (Empiezo donde necesito empezar, pero no funca)
Netcat antes de cifrar (WinDbg !dh):Citar.text
AddressOfEntryPoint: 1160
BaseOfCode: 1000
Align 16
Netcat después de cifrar (WinDbg !dh):Citar.text
AddressOfEntryPoint: 1160
BaseOfCode: 1000
Align (no align specified) --> :o
Bueno.. ahí esta.. Ese align debe estar *!&*"·$ el formato.. Perché ?
Gracias!! Saludos!
Bueno.. como no funciona y ya no entiendo que pasa, hice un codigo ejemplo..
Alguien se anima a probar este codigo?
int Crypt(char *filename, char *section)
{
LPBYTE Start;
HANDLE hFile = CreateFile(filename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile == INVALID_HANDLE_VALUE)
return -1;
HANDLE hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
if (hFileMapping == 0){
CloseHandle(hFile);
return -1;
}
LPBYTE lpFileMap = (LPBYTE)MapViewOfFile(hFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (lpFileMap == 0){
CloseHandle(hFileMapping);
CloseHandle(hFile);
return -1;
}
PIMAGE_DOS_HEADER IDH = (PIMAGE_DOS_HEADER) lpFileMap;
PIMAGE_NT_HEADERS INH = (PIMAGE_NT_HEADERS)((BYTE *)IDH + IDH->e_lfanew);
PIMAGE_OPTIONAL_HEADER IOH = (PIMAGE_OPTIONAL_HEADER)&INH->OptionalHeader;
PIMAGE_SECTION_HEADER ISH;
for (byte i = 0; i < INH->FileHeader.NumberOfSections; i++)
{
ISH = (PIMAGE_SECTION_HEADER)(lpFileMap + IDH->e_lfanew + sizeof(IMAGE_NT_HEADERS)+ sizeof(IMAGE_SECTION_HEADER)*i);
Start = lpFileMap + ISH->PointerToRawData;
if (strcmp((char *)ISH->Name, section) == 0)
{
for(DWORD i=0; i<ISH->Misc.VirtualSize; i++)
Start[i] ^= 'a';
}
}
UnmapViewOfFile((LPCVOID)lpFileMap);
CloseHandle(hFileMapping);
CloseHandle(hFile);
return 0;
}
El problema que tengo yo con esto es que al cifrar el programa Netcat, le cambia el EntryPoint a 4057F2 cuando debería ser otro..
Esta claro, pero por las dudas...
Crypt("nc.exe", ".text");
Gracias! Saludos!
Mmm al parecer te estas pasando de rango ... ¿Donde se supone que estas cambiando el entry point en ese codigo exactamente? ¿O es un efecto no deseado?
Tendrias que usar SizeOfRawData.
Citar¿Donde se supone que estas cambiando el entry point en ese codigo exactamente? ¿O es un efecto no deseado?
Es un
defecto no deseado :xD
Así como esta no le cambio el EP, se cambia solo.. :rolleyes:
Citar¿No sera que Start deberia usar VirtualAddress en realidad?:
Start = lpFileMap + ISH->PointerToRawData;
Ya probé hasta con la dirección psíquica!
CitarMmm al parecer te estas pasando de rango
Ya no tengo ni idea que puede ser.. hace rato que estoy con esto, y me estoy por decantar a que es "problema" del netcat.. :¬¬
Saludos! Gracias!
No, Start estaba bien (no lo estas mappeando con SEC_IMAGE), pero entonces deberias usar SizeOfRawData. No tengo ese ejecutable a mano, pero con unos simples printfs podrias ver a que equivale lpFileMap, Start e IOH que es lo que estas tocando sin querer.
Citarentonces deberias usar SizeOfRawData
Oky, cambiado..
CitarNo tengo ese ejecutable a mano, pero con unos simples printfs podrias ver a que equivale lpFileMap, Start e IOH que es lo que estas tocando sin querer.
Ya imprimí, use dumpbin, windgb, olly, la mar en coche, etc, etc :xD
Ya creo que es con nc, voy a probar con otros ejecutables grandes.. a ver que pasa..
Salu2!
Cita de: Vaagish en 17 Octubre 2014, 00:43 AMYa imprimí, use dumpbin, windgb, olly, la mar en coche, etc, etc :xD
¿Y que te dio? Start deberia ser muy cercano a IOH para que se produzca el problema ... o es otra parte del programa de la cual no tenemos el codigo. ¿Probaste a aislar esto solo y ya genera el problema?
Mira:
Valores de Start Citar900098 -> IOH
900400 -> .text
905800 -> .data
905A00 -> .rdata
900000 -> .bss
906C00 -> .idata
907800 -> .CRT
907A00 -> .tls
Si comento esto:
for(DWORD i=0; i<ISH->SizeOfRawData; i++)
Start[i] ^= 'a';
El EP no cambia,, pero claro.. tampoco se cifra :silbar:
Ahora que veo bien... porque va a estar IOH en ese lugar ???? No esta mal eso?
Salu2
Si tu Start arranca en 0x900400 no veo como puede escribir en 0x9000A8 ... ¿El nc.exe es el mismo que esta aca? http://eternallybored.org/misc/netcat/ Con ese no me pasa lo que decis ... ¿Tu programa es de 32 o 64 bits? ¿Estas viendo el EP con DUMPBIN, no?
Yo tampoco.. voy a bajar ese nc a ver si es por eso.. tengo una version de nc con su codigo, pero jamas pense que fuera eso.. va.. ya dudaba de todo en realidad..
Es de 32 bits (nc y crypter)
Mañana actualizo..
Saludos!
Bueno, no programo en C++ (sólo lo sé leer) pero si sé algo sobre este tema.
Agrandar una sección (y más aún, la sección de código) es un dolor de cabeza bastante grande. Quizás, si el código del cripter es pequeño, podrías encontrar algún code-cave en la sección e insertarlo ahí. Pero esto no siempre es posible.
Lo que normalmente se hace es agregar una nueva sección ejecutable al EXE y desde ahi puedes reconstruir el ejecutable tal cual estaba.
Si quieres un ejemplo, puedes revisar lo que hace el packer UPX (http://upx.sourceforge.net/).
De ahí seguro sacarás ideas interesantes...
Saludos!
Citar¿El nc.exe es el mismo que esta aca? http://eternallybored.org/misc/netcat/ Con ese no me pasa lo que decis
Ya lo baje, esa version 1.12 pesa un poco mas, (yo tenia la 1.11) A vos no te pasa EI pusiste ahi.. el mio sigue igual..
Debe ser un problema de tamaño y sino dejo la computación y me dedico a la mecánica :xD
Vos tenes 64bits.. yo 32.. es la única diferencia que noto..
@MCKSys: En ese code no se cambia el tamaño, pero en el otro crypter si, voy a revisar el UPX a ver que trae.. a lo mejor sea agregar una sección mas la solución.. como decís..
Saludos! Gracias!!
Cita de: Vaagish en 17 Octubre 2014, 19:25 PM
Ya lo baje, esa version 1.12 pesa un poco mas, (yo tenia la 1.11) A vos no te pasa EI pusiste ahi.. el mio sigue igual..
1290 entry point (00401290)¿Te sigue pasando con esa version? Vos tomas el ejecutable original, lo pasas por la funcion Crypt y despues el DUMPBIN te dice que cambio el EP. ¿Correcto? No puede ser ;D Tu codigo no puede ser el mismo, debes estar haciendo algo mas. Lo unico que yo hice fue sumar un miserable main:
void main(int argc, char **argv)
{
Crypt(argv[1], argv[2]);
}
Cita de: Vaagish en 17 Octubre 2014, 19:25 PMDebe ser un problema de tamaño y sino dejo la computación y me dedico a la mecánica :xD
No, de alguna manera estas escribiendo donde no debes, no hay otra forma para que cambie el EP, es un campo en una estructura que no cambia de lugar ... a menos que la estes haciendo apuntar a otro lado ;D
Cita de: Vaagish en 17 Octubre 2014, 19:25 PMVos tenes 64bits.. yo 32.. es la única diferencia que noto..
El S.O. es 64 si pero originalmente compile el programa en 32 bits, solo lo compile en 64 para ver si asi explotaba, cosa que no hizo.
Citar1290 entry point (00401290)
¿Te sigue pasando con esa version? Vos tomas el ejecutable original, lo pasas por la funcion Crypt y despues el DUMPBIN te dice que cambio el EP. ¿Correcto?
Mmm.. Si / No.. Resultados de dumpbin:
Antes de cifrar: 1290 EntryPoint
Después de cifrar: 1290 EntryPoint
Según dumpbin queda igual.. pero en ollydbg empieza en 00405822, ademas, si inserto la rutina descifradora, windows dice que "dejo de funcionar" (suponiendo que todo esta bien,,, menos ese maldito EP!)
Yo llamo así a la función (pero uso CommandLineToArgvW):
Crypt(filenin, ".text");
Igual con una simple pausa puedo ver que los parámetros de Crypt están bien...
EDITO: Tengo otros PE's que NO pasa lo mismo.. :rolleyes:
Cita de: Vaagish en 17 Octubre 2014, 20:37 PM
Mmm.. Si / No.. Resultados de dumpbin:
Entonces no tenes ese problema que decis realmente; tendras otro, te recomiendo usar el WinDbg.