Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: Destro- en 28 Noviembre 2014, 01:39 am



Título: Offset inicio/fin de .data
Publicado por: Destro- en 28 Noviembre 2014, 01:39 am
Buenas :)


Necesito reemplazar un string en la memoria de otro modulo cargado en el mismo proceso.
Arme algo así:
Código:
	MODULEINFO mInfo;
int base, start, end;
GetModuleInformation(GetCurrentProcess(),GetModuleHandle("swds.dll"),&mInfo,sizeof(mInfo));

start = (int)mInfo.lpBaseOfDll;
end = start+mInfo.SizeOfImage;

char find_stats[18] = { 'm', 'o', 't', 'd', '_', 'w', 'r', 'i', 't', 'e', 0, 0, 's', 't', 'a', 't', 's', 0 };
for(int p=0; (start+p) < (end-sizeof(find_stats)); p++)
{
if(memcmp((void*)(start+p), &find_stats, sizeof(find_stats)) == 0)
{
memcpy((void*)(start+p+15), &"l", 1);
//char *p = (char *)(start+p+15);
//*p = 'l';
}
}
Funciona perfecto, pero buscaría en todo el modulo y no donde importa. Hay alguna forma de obtener el start y end addres de la sección .data ?.
Estuve buscando en stackoverflow pero no encontré casi nada (tal vez busque mal xd) y lo que encontré no lo entendí :\.

Y otra duda, la parte que esta comentada, porque me crashea ?, creería yo que tendría que funcionar o.O.


Título: Re: Offset inicio/fin de .data
Publicado por: Eternal Idol en 28 Noviembre 2014, 02:39 am
http://en.wikipedia.org/wiki/Portable_Executable

En la base del modulo hay una IMAGE_DOS_HEADER, con el offset en el campo e_lfanew llegas a la IMAGE_NT_HEADERS, ahi tenes el campo: NumberOfSections
The number of sections. This indicates the size of the section table, which immediately follows the headers.

Un array de IMAGE_SECTION_HEADERs, ahi estan todas las secciones del PE.

Tenes dos variables p ahi ... y el codigo usa la segunda para sumar que es el puntero indefinido.

warning C4700: uninitialized local variable 'p' used


Título: Re: Offset inicio/fin de .data
Publicado por: Destro- en 28 Noviembre 2014, 04:02 am
tengo que sacar un turno para el oculista ya!, jaja :P

Gracias :D
Me quedo algo así:
Código:
void get_data_offset(HMODULE hModule, unsigned int &DataStart, unsigned int &DataEnd)
{
char *dllImageBase = (char*)hModule;

IMAGE_NT_HEADERS *pNtHdr = ImageNtHeader(hModule);

IMAGE_SECTION_HEADER *pSectionHdr = (IMAGE_SECTION_HEADER *)(pNtHdr+1);

for(int i = 0 ; i < pNtHdr->FileHeader.NumberOfSections; i++)
{
char *name = (char*) pSectionHdr->Name;
if(memcmp(name, ".data", 5) == 0)
{
DataStart = (unsigned int)dllImageBase + pSectionHdr->VirtualAddress;
DataEnd = DataStart + pSectionHdr->Misc.VirtualSize;
break;
}
pSectionHdr++;
}
}

// ======================================================

unsigned int start, end;
get_data_offset(GetModuleHandle("swds.dll"), start, end);


char find_stats[] = { 'm', 'o', 't', 'd', '_', 'w', 'r', 'i', 't', 'e', 0, 0, 's', 't', 'a', 't', 's', 0 };

for(unsigned int p=0; (start+p) < (end-sizeof(find_stats)); p++)
{
if(memcmp((void*)(start+p), &find_stats, sizeof(find_stats)) == 0)
{
//memcpy((void*)(start+p+15), &"l", 1);
char *pChar = (char *)(start+p+15);
*pChar = 'l';

//SERVER_PRINT("Pached: stats\n");
}
}
algo para mejorar ?.
____________________
Una duda, para almacenar punteros/direcciones de memoria es correcto utilizar int/unsigned int  ?. porque por ejemplo dllImageBase es un puntero char, es lo mismo ?.





Título: Re: Offset inicio/fin de .data
Publicado por: MCKSys Argentina en 28 Noviembre 2014, 04:57 am
Una duda, para almacenar punteros/direcciones de memoria es correcto utilizar int/unsigned int  ?. porque por ejemplo dllImageBase es un puntero char, es lo mismo ?.

Los punteros te conviene guardarlos sin signo. Si estás en 32 bits puedes usar DWORD (unsigned long) y en 64 bits DWORD64 (unsigned long long)

Saludos!


Título: Re: Offset inicio/fin de .data
Publicado por: Eternal Idol en 28 Noviembre 2014, 10:06 am
Una duda, para almacenar punteros/direcciones de memoria es correcto utilizar int/unsigned int  ?. porque por ejemplo dllImageBase es un puntero char, es lo mismo ?.

Si queres guardar la direccion en una variable entera mejor usar ULONG_PTR que ocupara los bytes correspondientes a la plataforma (4 bytes en x86 y 8 bytes en x64) y no tendra signo.


Título: Re: Offset inicio/fin de .data
Publicado por: MCKSys Argentina en 28 Noviembre 2014, 16:41 pm
Si queres guardar la direccion en una variable entera mejor usar ULONG_PTR que ocupara los bytes correspondientes a la plataforma (4 bytes en x86 y 8 bytes en x64) y no tendra signo.

jejeje, que grande Eternal Idol! También agradezco el dato (recién estoy emezando con VC++)

Saludos!


Título: Re: Offset inicio/fin de .data
Publicado por: Eternal Idol en 28 Noviembre 2014, 17:01 pm
jejeje, que grande Eternal Idol! También agradezco el dato (recién estoy emezando con VC++)

Saludos!

De nadas  ::)


Título: Re: Offset inicio/fin de .data
Publicado por: x64core en 28 Noviembre 2014, 17:31 pm
algo para mejorar ?.
____________________
Una duda, para almacenar punteros/direcciones de memoria es correcto utilizar int/unsigned int  ?. porque por ejemplo dllImageBase es un puntero char, es lo mismo ?.


Sí, para de usar este tipo de hardcoding:
Código:
IMAGE_SECTION_HEADER *pSectionHdr = (IMAGE_SECTION_HEADER *)(pNtHdr+1);
Hace que tu código sea generico además de que no tiene sentido si haces luego una comparación del nombre, en lugar de escribir funciones para recuperar un puntero a una determinada sección (PIMAGE_SECTION_HEADER) que luego podes usar en otros códigos;
Lo mismo aquí:
Código:
memcmp(name, ".data", 5) == 0)
Mejor utiliza sizeof para IMAGE_SECTION_HEADER.Name.



Título: Re: Offset inicio/fin de .data
Publicado por: Destro- en 29 Noviembre 2014, 00:15 am
Si queres guardar la direccion en una variable entera mejor usar ULONG_PTR que ocupara los bytes correspondientes a la plataforma (4 bytes en x86 y 8 bytes en x64) y no tendra signo.
Gracias por la info :P.
Puede ser que muy pocos utilicen ULONG_PTR ?, soy nuevo en C pero soy de leer mucho code y hasta ahora no recuerdo haber visto utilizar ULONG_PTR o.O.


Sí, para de usar este tipo de hardcoding:
Código:
IMAGE_SECTION_HEADER *pSectionHdr = (IMAGE_SECTION_HEADER *)(pNtHdr+1);
Hace que tu código sea generico además de que no tiene sentido si haces luego una comparación del nombre, en lugar de escribir funciones para recuperar un puntero a una determinada sección (PIMAGE_SECTION_HEADER) que luego podes usar en otros códigos;
Lo mismo aquí:
Código:
memcmp(name, ".data", 5) == 0)
Mejor utiliza sizeof para IMAGE_SECTION_HEADER.Name.
no entendí cuando decís que devuelva el puntero de IMAGE_SECTION_HEADER

por lo demás te referías a que haga algo así ?:
Código:
void get_setion_offset(HMODULE hModule, char *SetionName, ULONG_PTR &SetionStart, ULONG_PTR &SetionEnd)
{
IMAGE_NT_HEADERS *pNtHdr = ImageNtHeader(hModule);
PIMAGE_SECTION_HEADER pSectionHdr = (PIMAGE_SECTION_HEADER)(pNtHdr+1);

for(int i = 0 ; i < pNtHdr->FileHeader.NumberOfSections; i++, pSectionHdr++)
{
if(strcmp((char *)pSectionHdr->Name, SetionName) == 0)
{
SetionStart = (ULONG_PTR)hModule + pSectionHdr->VirtualAddress;
SetionEnd = SetionStart + pSectionHdr->Misc.VirtualSize;
break;
}
}
}



Título: Re: Offset inicio/fin de .data
Publicado por: Eternal Idol en 29 Noviembre 2014, 01:07 am
Gracias por la info :P.
Puede ser que muy pocos utilicen ULONG_PTR ?, soy nuevo en C pero soy de leer mucho code y hasta ahora no recuerdo haber visto utilizar ULONG_PTR o.O.

Ni idea, esta entre los Migrations Tips de Microsoft para x64: Storing a 64-bit Value (http://msdn.microsoft.com/en-us/library/windows/desktop/aa384255%28v=vs.85%29.aspx).


Título: Re: Offset inicio/fin de .data
Publicado por: x64core en 29 Noviembre 2014, 02:19 am
Gracias por la info :P.
Puede ser que muy pocos utilicen ULONG_PTR ?, soy nuevo en C pero soy de leer mucho code y hasta ahora no recuerdo haber visto utilizar ULONG_PTR o.O.
La mayoria de "reversers", me refiero a los que aprenden primero a depurar programas con algun lenguaje de alto nivel como VB6 y luego intentan aprender un verdadero lenguaje como C/C++ es normal que recomienden/usen variables DWORD, DWORD64 para almacenar punteros, ellos deberian de aprender a programar de la manera correcta.

Usando ULONG_PTR no es la unica manera, también es posible usar BYTE*/PBYTE aunque yo también me siento mejor usando ULONG_PTR.

no entendí cuando decís que devuelva el puntero de IMAGE_SECTION_HEADER

por lo demás te referías a que haga algo así ?:
Código:
void get_setion_offset(HMODULE hModule, char *SetionName, ULONG_PTR &SetionStart, ULONG_PTR &SetionEnd)
{
IMAGE_NT_HEADERS *pNtHdr = ImageNtHeader(hModule);
PIMAGE_SECTION_HEADER pSectionHdr = (PIMAGE_SECTION_HEADER)(pNtHdr+1);

for(int i = 0 ; i < pNtHdr->FileHeader.NumberOfSections; i++, pSectionHdr++)
{
if(strcmp((char *)pSectionHdr->Name, SetionName) == 0)
{
SetionStart = (ULONG_PTR)hModule + pSectionHdr->VirtualAddress;
SetionEnd = SetionStart + pSectionHdr->Misc.VirtualSize;
break;
}
}
}
Usando esto no es lo correcto:
Código:
		if(strcmp((char *)pSectionHdr->Name, SetionName) == 0)
IMAGE_SECTION_HEADER.Name es de tipo BYTE no una cadena asi que es totalmente valido que el nombre de la sección contenga
valores nulos o la longitud del nombre sea el maximo numero de bytes, en este caso 8; strcmp retornará un valor incorrecto en esos casos
memcmp estaba bien.

Me referia a algo como esto:
Código
  1. #define SIZE_OF_MEMBER(Type,Member) (SIZE_T)(sizeof(((Type*)0)->Member))
  2.  
  3. PIMAGE_SECTION_HEADER FindPESectionByName(IN PIMAGE_NT_HEADERS NT, IN BYTE SectionName[8])
  4. {
  5.    if (NT &&
  6.        SectionName)
  7.    {
  8.        PIMAGE_SECTION_HEADER pFirstSection;
  9.        pFirstSection = IMAGE_FIRST_SECTION(NT);
  10.        for (ULONG s = 0; s < NT->FileHeader.NumberOfSections; s++)
  11.        {
  12.            if (!memcmp(
  13.                SectionName,
  14.                pFirstSection[s].Name,
  15.                SIZE_OF_MEMBER(IMAGE_SECTION_HEADER, Name)))
  16.            {
  17.                return &pFirstSection[s];
  18.            }
  19.  
  20.        }
  21.    }
  22.    return NULL;
  23. }
Es sólo una función para obtener un puntero a la sección.

-
Códigos que parsean el formato PE deberían de ser escritos bajo un manejador de excepciónes en el mayor de los casos, sino fijate el monton de programas para parsear PE/PE32+ que se cierran cuando se abren imagenes PE "malformadas".




Título: Re: Offset inicio/fin de .data
Publicado por: MCKSys Argentina en 29 Noviembre 2014, 03:21 am
La mayoria de "reversers", me refiero a los que aprenden primero a depurar programas con algun lenguaje de alto nivel como VB6 y luego intentan aprender un verdadero lenguaje como C/C++ es normal que recomienden/usen variables DWORD, DWORD64 para almacenar punteros, ellos deberian de aprender a programar de la manera correcta.

Por Horus. En verdad, no sabes cómo hacer para ridiculizar a la gente, eh?

Si miras bien, verás que entre paréntesis están los tipos compatibles con los dados (unsigned long y unsigned long long). Que diga que estoy aprendiendo el lenguaje, no significa que sea un neófito en el tema. Simplemente no se puede saber todo acerca de todo.

La verdad, no sé para qué me todo el tiempo de escribir ésto.

Considéralo un recordatorio final.


Título: Re: Offset inicio/fin de .data
Publicado por: x64core en 29 Noviembre 2014, 03:36 am
Por Horus. En verdad, no sabes cómo hacer para ridiculizar a la gente, eh?

Si miras bien, verás que entre paréntesis están los tipos compatibles con los dados (unsigned long y unsigned long long). Que diga que estoy aprendiendo el lenguaje, no significa que sea un neófito en el tema. Simplemente no se puede saber todo acerca de todo.

La verdad, no sé para qué me todo el tiempo de escribir ésto.

Considéralo un recordatorio final.
No sé a qué te refieres...