Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Temas - 85

#1
Nico Karman el creador de inexinferis.com y el soft iApp, plataforma de cheats para Counter-Strike 1.5 y 1.6, se retira y publica el código fuente de su proyecto.

Recordemos que Nico se inició en este mismo foro (Karman) , aún se pueden encontrar sus posts si se busca. bueno, la publicación incluye varios códigos fuente en c/c++ y entre ellos está iApp o Inexinferis Application, con la librería para tunear aplicaciones gráficas de Windows (winapi gui apps). Con esta librería se tuneó la iApp

foto

https://imageshack.com/i/poT3zB3op
https://imageshack.com/a/img924/9106/T3zB3o.png

[youtube=640,360]https://www.youtube.com/watch?v=v81nqXGx5U8[/youtube]

links de los códigos fuente en GitHub
Citarhttps://github.com/inexinferis
https://github.com/inexinferis/iApp
https://github.com/inexinferis/revolution
https://github.com/inexinferis/sXeMu

Cómo coAdmin del sitio y único colaborador tengo el permiso de Nico Karman de publicar esto en este sitio y en otros, para desmistificar cómo se hizo el iApp y el Inexinferis Revolution tan conocido en la comunidad del cheat de Counter-Strike

bueno un saludo


MOD: Imagen adaptada a lo permitido.
#2
Primero que nada quiero decir que voy a postear el código fuente público de un hack de karman, llamado Inexinferis FX de finales del 2010.
Es un código ya publicado sólo que no se observa demasiado por internet XD

Lo posteo porque es parte de los métodos que se estaban comentando en el foro últimamente, y se trata de utilizar 'detours' pero a un nivel más profundo que el que ofrece Openg32.dll, siendo Opengl32.dll el nivel más alto y el driver de la tarjeta gráfica lo más bajo. Intermediamente se tiene otra DLL de relacionada con Opengl32 pero perteneciente a la firma de la tarjeta gráfica, pero el tema es que hay muchas marcas de tarjetas gráficas y por lo tanto muchos drivers. Por lo que cada uno sabe lo que tiene XD

Esta es la información que se necesita manejar para poder entender como se determinan las direcciones de bajo nivel para Opengl por medio de lo que se llama TEB (Thread Environment Block), también conocido como TIB (Thread Information Block) por algunos, aunque otros insisten en que el TIB es miembro del TEB (Ver link de undocumented.ntinternals.net).
http://es.wikipedia.org/wiki/Win32_Thread_Information_Block
http://en.wikipedia.org/wiki/Win32_Thread_Information_Block
http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/Thread/TEB.html

Otros links
http://www.snoxd.net/index.php/topic/377-finding-the-thread-id-from-the-executable-name/
http://www.alex-ionescu.com/part1.pdf
http://www.ciphermonk.net/teb.php
http://nasutechtips.blogspot.com.ar/2011/01/thread-information-block-tib-and-fs.html
http://skypher.com/wiki/index.php/Hacking/Windows_internals/Process/Memory/TEB
http://stackoverflow.com/questions/9964236/tib-access-in-win32
http://software.intel.com/sites/products/documentation/doclib/stdxe/2013composerxe/compiler/cpp-win/GUID-F90BD123-AE25-4DC2-ADFB-B59067E77728.htm

Otros links que se pueden tomar en cuenta
http://www.nynaeve.net/?p=180
http://msdn.microsoft.com/es-ar/library/6yh4a9k1.aspx
http://msdn.microsoft.com/en-us/library/6yh4a9k1.aspx
http://msdn.microsoft.com/es-ar/library/y6h8hye8.aspx
http://msdn.microsoft.com/es-ar/library/2s9wt68x.aspx


En Opengl32.DLL básicamente se encuentran funciones que sólo hacen saltos hacia el nivel más bajo de Opengl, y para obtener las direcciones correctas del driver, se hace con este método del TEB.

Este es el ejemplo de glBegin

Citar
Pos: FS:[0x18]      Len: 4   Ver: Win9x y NT   -> Dirección lineal del TIB

con esos parámetros se consigue hacer un salto hacia el nivel bajo del que hablábamos (nvoglnt.dll en mi caso que tengo una tarjeta NVIDIA)


Luego hace otro salto hacia la función en sí.
Con OllyDBG se puede observar el estado de los registros para tener una mejor idea de como se obtienen las direcciones.
Mejor aún, para aquellos que prefieren leer una buena explicación les dejo este manual al respecto:
http://www.mediafire.com/?kmru385gmmcik46

Código (cpp) [Seleccionar]

//

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma comment(lib,"OpenGL32.lib")
#pragma comment(lib, "Version.lib")
#define _WIN32_WINNT 0x0500
#undef UNICODE
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <shlwapi.h>
#include <stdio.h>

#include "nt.h"

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

HANDLE hThread=NULL;
PBYTE dwFSBase,dwFSBase2;

HWND hdHalfLife;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

typedef void (APIENTRY* glBlendFunc_t)(GLenum,GLenum);
typedef void (APIENTRY* glClear_t)(GLbitfield);
typedef void (APIENTRY* glVertex2f_t)(GLfloat,GLfloat);
typedef void (APIENTRY* glVertex3f_t)(GLfloat,GLfloat,GLfloat);
typedef void (APIENTRY* glVertex3fv_t)(const GLfloat*);
typedef void (APIENTRY* glBegin_t)(GLenum);
glBlendFunc_t pglBlendFunc=0;
glClear_t pglClear=0;
glVertex2f_t pglVertex2f=0;
glVertex3f_t pglVertex3f=0;
glVertex3fv_t pglVertex3fv=0;
glBegin_t pglBegin=0;

BOOL bFlash=FALSE;
BOOL bSky=FALSE;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void APIENTRY New_glBegin(GLenum mode){

if(mode==GL_TRIANGLE_STRIP||mode==GL_TRIANGLE_FAN)
glDisable(GL_DEPTH_TEST);
else if(mode!=GL_QUADS&&mode!=GL_LINES)
glEnable(GL_DEPTH_TEST);

if(mode==GL_QUADS){
float col[4];
       glGetFloatv(GL_CURRENT_COLOR, col);
       bFlash=(col[0]==1.0&&col[1]==1.0&&col[2]==1.0&&col[3]>0.2);
bSky=TRUE;
   }
else
bSky=FALSE;
pglBegin(mode);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void APIENTRY New_glClear(GLbitfield mask){

if(mask==GL_DEPTH_BUFFER_BIT){
mask+=GL_COLOR_BUFFER_BIT;
glClearColor(0.0f,0.0f,0.0f,0.0f);
}
pglClear(mask);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void APIENTRY New_glVertex3fv(const GLfloat* v){

if(bSky) return;
pglVertex3fv(v);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void APIENTRY New_glVertex2f(GLfloat x, GLfloat y){

if(bFlash&&x==0.0&&y==0.0) glColor4f(1.0f,1.0f,1.0f,0.2f);
   pglVertex2f(x,y);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void APIENTRY New_glVertex3f(GLfloat x, GLfloat y, GLfloat z){

glColor3f(1.0f,1.0f,1.0f);
pglVertex3f(x,y,z);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

BOOL GetDllVersion(HMODULE hLibModule, DLLVERSIONINFO* aVersion){
 
   CHAR fileName[MAX_PATH];
   UINT len=0;
   VS_FIXEDFILEINFO* vsfi=NULL;
   DWORD handle=0;
   DWORD size=GetModuleFileName(hLibModule,fileName,MAX_PATH);
   fileName[size]=0;
   size=GetFileVersionInfoSize(fileName, &handle);
   BYTE* versionInfo=new BYTE[size];
   if(!GetFileVersionInfo(fileName,handle,size,versionInfo)){
delete[] versionInfo;
       return FALSE;
   }
   VerQueryValue(versionInfo,"\\",(PVOID*)&vsfi,&len);
   aVersion->dwMajorVersion=HIWORD(vsfi->dwFileVersionMS);
   aVersion->dwMinorVersion=LOWORD(vsfi->dwFileVersionMS);
   aVersion->dwBuildNumber=HIWORD(vsfi->dwFileVersionLS);
   aVersion->dwPlatformID=LOWORD(vsfi->dwFileVersionLS);
   delete[] versionInfo;
   return TRUE;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void* Detour1(BYTE* src, const BYTE* dst, const int len){
BYTE* jmp = (BYTE*)malloc(len+5);
DWORD dwback;
while(!VirtualProtect(src, len, PAGE_READWRITE, &dwback));
memcpy(jmp, src, len);jmp+=len;
jmp[0] = 0xE9;
*(DWORD*)(jmp+1)=(DWORD)(src+len-jmp)-5;
src[0] = 0xE9;
*(DWORD*)(src+1)=(DWORD)(dst-src)-5;
while(!VirtualProtect(src, len, dwback, &dwback));
return (jmp-len);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/*
DWORD GetProcessThreadId(unsigned long ProcessId)
{
   HANDLE hSnapThread = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, ProcessId);
   if(hSnapThread == INVALID_HANDLE_VALUE) return NULL;
   THREADENTRY32 te;
   te.dwSize = sizeof(THREADENTRY32);
   if(Thread32First(hSnapThread, &te))
   {
      do
      {
           if(te.th32OwnerProcessID == ProcessId) {
               CloseHandle(hSnapThread);
               return te.th32ThreadID;
           }

      } while(Thread32Next(hSnapThread, &te));
   }
   CloseHandle(hSnapThread);
   return 0;
}*/

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

DWORD WINAPI Thread(LPVOID lpParam){

   DWORD dwThreadId,dwProcessId,dwOGLOffset;
   CONTEXT Context;
   LDT_ENTRY SelEntry;
   HMODULE hModule;
   Context.ContextFlags=CONTEXT_FULL|CONTEXT_DEBUG_REGISTERS;
   DWORD dwTLSIndex=0;
   DLLVERSIONINFO oglVersion;

   while(((hdHalfLife=FindWindow("Valve001",NULL))==NULL)
             &&((hdHalfLife=FindWindow(NULL,"Counter-Strike"))==NULL))
                     Sleep(100);

   while((hModule=GetModuleHandle("Opengl32.dll"))==NULL)
             Sleep(100);

   if(GetDllVersion(hModule,&oglVersion)){

       if(oglVersion.dwMajorVersion==5&&oglVersion.dwMinorVersion==1){
           dwTLSIndex=0xAC80C;
}
else if(oglVersion.dwMajorVersion==6&&oglVersion.dwMinorVersion==0){
           dwTLSIndex=0xAB958;
}
else if(oglVersion.dwMajorVersion==6&&oglVersion.dwMinorVersion==1){
           dwTLSIndex=0xA100C;
}
       else
       {
            //MessageBox(hdHalfLife,"Incompatible OpenGL Version...\n\nSorry man...","Inexinferis FX Series - Karman",0);
           ExitThread(0);
           return 0;
       }
   }
   else
   {
       //MessageBox(hdHalfLife,"Can't Get OpenGL Version...\n\nWrong OpenGL???","Inexinferis FX Series - Karman",0);
ExitThread(0);
       return 0;
   }

   //DWORD ProcessId = GetCurrentProcessId();
   //DWORD ProcessThreadId = GetProcessThreadId(ProcessId);
   dwThreadId=GetWindowThreadProcessId(hdHalfLife,&dwProcessId);
   HANDLE hThread=OpenThread(THREAD_GET_CONTEXT|THREAD_SUSPEND_RESUME|THREAD_QUERY_INFORMATION,FALSE,dwThreadId);

   if(!hThread){
       //MessageBox(hdHalfLife,"Couldn't Get Proccess Info...\n\nAntivirus???","Inexinferis FX Series - Karman",0);
       CloseHandle(hThread);
       ExitThread(0);
       return 0;
   }

   GetThreadContext(hThread,&Context);
   GetThreadSelectorEntry(hThread, Context.SegFs, &SelEntry);
   dwFSBase = (PBYTE)((SelEntry.HighWord.Bits.BaseHi<<24)|(SelEntry.HighWord.Bits.BaseMid<<16)|SelEntry.BaseLow);

   if(!dwFSBase||IsBadReadPtr((PVOID)dwFSBase,sizeof(DWORD))){
       //MessageBox(hdHalfLife,"Couldn't Get TEB From Opengl32.dll\n\nMake Sure that you are Running the Game in OpenGl Mode...","Inexinferis FX Series - Karman",0);
       CloseHandle(hThread);
       ExitThread(0);
       return 0;
   }

   dwOGLOffset=((DWORD)hModule)+dwTLSIndex;
   if(!dwTLSIndex||IsBadReadPtr((PVOID)dwOGLOffset,sizeof(DWORD))){
       //MessageBox(hdHalfLife,"Couldn't Read From Opengl32.dll Address\n\nMaybe your OpenGL driver is not compatible...","Inexinferis FX Series - Karman",0);
      CloseHandle(hThread);
      ExitThread(0);
      return 0;
   }
   //multiple redirect...
   do{
          Sleep(10);
          dwFSBase2=(PBYTE)(*(PDWORD)((DWORD)dwFSBase+(*(PDWORD)dwOGLOffset)));
   }while(dwFSBase2==NULL);

/*
  dwFSBase2=(PBYTE)(*(PDWORD)((DWORD)dwFSBase+(*(PDWORD)0x5F1CC80C)));
  if(!dwFSBase2){
      CloseHandle(hThread);
      ExitThread(0);
      return 0;
  }*/

               


  //MessageBox(hdHalfLife,"http://www.inexinferis.com.ar/foro","Inexinferis FX Series - Karman",0);
  SuspendThread(hThread);

  ////////
  // Hooks

  // 0x01D46862  opengl32.glClear [EAX+32C] -> 0x69609A20 [12]
  pglClear= (glClear_t)Detour1((PBYTE)(*(PDWORD)(dwFSBase2+0x32C)),(PBYTE)New_glClear,12);
   
  // 0x01D3CF1D  opengl32.glVertex2f [EAX+92C] -> 0x69606320 [12]
  pglVertex2f= (glVertex2f_t)Detour1((PBYTE)(*(PDWORD)(dwFSBase+0x92C)),(PBYTE)New_glVertex2f,12);
   
  pglVertex3f= (glVertex3f_t)Detour1((PBYTE)(*(PDWORD)(dwFSBase+0x94C)),(PBYTE)New_glVertex3f,12);
   
  // 0x01D936C5 opengl32.glVertex3fv [EAX+950] -> 0x696073F0 [12]
  pglVertex3fv= (glVertex3fv_t)Detour1((PBYTE)(*(PDWORD)(dwFSBase+0x950)),(PBYTE)New_glVertex3fv,12);
   
  // 0x01D93681 opengl32.glBegin [EAX+7CC] -> 0x695FD250 [8]
  pglBegin= (glBegin_t)Detour1((PBYTE)(*(PDWORD)(dwFSBase+0x7CC)),(PBYTE)New_glBegin, 8);

   ////////

   ResumeThread(hThread);
   CloseHandle(hThread);

   ExitThread(0);
   return 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, LPVOID lpvReserved){
 
if(fdwReason==DLL_PROCESS_ATTACH){
   
DisableThreadLibraryCalls(hInstance);
hThread=CreateThread(NULL,0,Thread,NULL,0,NULL);
}
return (TRUE);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



PROYECTO MS Visual C++ 2010 Express
http://www.mediafire.com/?yttdt8712ymvj2r
#3
Para terminar de redondear el tema de interceptar Opengl32 usando detours, muestro una pequeña base para crear un WH, utiliza una función personalizada para instalar un hook del tipo DETOUR.
Habíamos visto en otros tutoriales como se hace, y que se trata de una técnica intrusiva porque requiere parchear la memoria (código) del proceso víctima.
http://foro.elhacker.net/programacion_cc/detours-t168884.0.html
No tiene nada que ver con otros tutoriales que muestran como se modifican los valores de algunos punteros que corresponden a datos en el proceso.
Ej: http://foro.elhacker.net/programacion_cc/codigo_fuente_cheat_cs_16-t387341.0.html

Dejo el código funcional y el proyecto para descargar como siempre, dejo unas imágenes..

En este caso para diferenciarnos de otros tutoriales, explico la forma en que se puede cargar esta DLL en el proceso "hl.exe" que corresponde al juego Counter-Strike.

Se trata de ir a la carpeta del juego, y buscar una DLL de las que sabemos que no son necesarias en el juego pero de todas formas son cargadas al proceso.
Hay otras DLLs que son cargadas y algunas de sus funciones o todas, son utilizadas en el proceso, por lo que no se puede quitarlas, sino más bien hacer un 'wrapper' de ellas. Pero no quitarlas.

Vamos a ver una DLL que si la podemos quitar que se llama "DemoPlayer.dll". Vamos a quitarla y poner nuestra DLL con el WH en su lugar. Obviamente la tenemos que renombrar a "demoplayer.DLL" si es que no tiene ese nombre toda via.





Al final quiero decir que los sistemas de seguridad suelen escanear en la memoria, por ejemplo los primeros 5 bytes de algunas funciones para determinar si tienen 'detours'.
Pero a veces hacen otras comprobaciones como CRC32 de toda una función, o quien sabe que otras comprobaciones.. el tema es que este es un método intrusivo.

Código (cpp) [Seleccionar]


//
// Modifications: By 85
// Credits: gamedeception (detour function), SharkBoy999 base
// elhacker.net
// etalking.com.ar
// david_bs@live.com
// 2013
//

///////////////////////////////////////////////////////////////////////////////////////

#pragma comment(lib,"OpenGL32.lib")
#include <windows.h>
#include <gl/gl.h>
#include <tlhelp32.h>
#include<stdio.h>

///////////////////////////////////////////////////////////////////////////////////////

#define wallhack_key     GetAsyncKeyState(VK_NUMPAD1) &1
#define lambert_key GetAsyncKeyState(VK_NUMPAD2) &1
#define nosmoke_key GetAsyncKeyState(VK_NUMPAD3) &1
#define noflash_key GetAsyncKeyState(VK_NUMPAD4) &1

bool wallhack = true;
bool lambert = true;
bool nosmoke = true;
bool noflash = true;

bool bDrawingSmoke = false;
bool bDrawingFlash = false;

///////////////////////////////////////////////////////////////////////////////////////

typedef FARPROC (APIENTRY* GetProcAddress_t)(HMODULE, LPCSTR);
typedef void (APIENTRY* glBegin_t)(GLenum mode);
typedef void (APIENTRY* glViewport_t)(GLint x, GLint y, GLsizei width, GLsizei height);
typedef void (APIENTRY* glVertex3fv_t)(const GLfloat* v);
typedef void (APIENTRY* glVertex2f_t)(GLfloat,GLfloat);

///////////////////////////////////////////////////////////////////////////////////////

GetProcAddress_t pGetProcAddress = 0;
glBegin_t pglBegin;
glViewport_t pglViewport;
glVertex3fv_t pglVertex3fv;
glVertex2f_t pglVertex2f;

///////////////////////////////////////////////////////////////////////////////////////

void toggle(bool var)
{
   var = !var;
}

///////////////////////////////////////////////////////////////////////////////////////

void* Detour1(BYTE* src, const BYTE* dst, const int len)
{
BYTE* jmp = (BYTE*)malloc(len+5);
DWORD dwback;
while(!VirtualProtect(src, len, PAGE_READWRITE, &dwback));
memcpy(jmp, src, len);jmp+=len;
jmp[0] = 0xE9;
*(DWORD*)(jmp+1)=(DWORD)(src+len-jmp)-5;
src[0] = 0xE9;
*(DWORD*)(src+1)=(DWORD)(dst-src)-5;
while(!VirtualProtect(src, len, dwback, &dwback));
return (jmp-len);
}

///////////////////////////////////////////////////////////////////////////////////////

FARPROC APIENTRY new_GetProcAddress(HMODULE hModule, LPCSTR lpProcName)
{
//FARPROC fpResult = (*pGetProcAddress)(hModule, lpProcName);
FARPROC fpResult = pGetProcAddress(hModule, lpProcName);
if(HIWORD(lpProcName))
{
if(!lstrcmp(lpProcName,"GetProcAddress"))
return((FARPROC)&new_GetProcAddress);
}
return fpResult;
}

///////////////////////////////////////////////////////////////////////////////////////

void APIENTRY new_glBegin(GLenum mode)
{
if(wallhack)
{
if(mode == GL_TRIANGLE_STRIP || mode == GL_TRIANGLE_FAN)
glDepthRange( 0, 0.5 );
else
glDepthRange( 0.5, 1 );
}

if(lambert)
{
if(mode == GL_TRIANGLE_STRIP || mode == GL_TRIANGLE_FAN)
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
}

if(nosmoke)
{
if(mode==GL_QUADS)
{
GLfloat curcol[4];
glGetFloatv(GL_CURRENT_COLOR, curcol);
if(mode==GL_QUADS
&& (curcol[0]==curcol[1])
&& (curcol[0]==curcol[2])
&& (curcol[0]!=0.0)
&& (curcol[0]!=1.0))
{
bDrawingSmoke = true;
}
else
bDrawingSmoke = false;
}
}

if(noflash)
{
GLfloat color[4];
glGetFloatv(GL_CURRENT_COLOR, color);
if(mode == GL_QUADS && (color[0]==1 && color[1]==1 && color[2]==1) )
{
bDrawingFlash = true;
}
else
bDrawingFlash = false;
}
pglBegin(mode);
}

///////////////////////////////////////////////////////////////////////////////////////

void APIENTRY new_glViewport(GLint x, GLint y, GLsizei w, GLsizei h)
{
if(wallhack_key)
toggle(wallhack);
if(lambert_key)
toggle(lambert);
if(nosmoke_key)
toggle(nosmoke);
if(noflash_key)
toggle(noflash);
pglViewport(x,y,w,h);
}

///////////////////////////////////////////////////////////////////////////////////////

void APIENTRY new_glVertex3fv(const GLfloat* v)
{
if(bDrawingSmoke)
return;

pglVertex3fv(v);
}

///////////////////////////////////////////////////////////////////////////////////////

void APIENTRY new_glVertex2f(GLfloat x,GLfloat y)
{
/* if (bDrawingFlash)
{
GLfloat color[4];
glGetFloatv(GL_CURRENT_COLOR, color);
//color[0]=0, color[1]=0, color[2]=0;
glDisable(GL_TEXTURE_2D);
glColor4f(color[0], color[1], color[2], 0.01f);
}*/
pglVertex2f(x,y);
}

///////////////////////////////////////////////////////////////////////////////////////

void Hook(void)
{
pglBegin =        (glBegin_t)       Detour1((LPBYTE)glBegin,       (LPBYTE)new_glBegin, 6);
pglViewport =     (glViewport_t)    Detour1((LPBYTE)glViewport,    (LPBYTE)new_glViewport, 7);
pglVertex3fv =    (glVertex3fv_t)   Detour1((LPBYTE)glVertex3fv,   (LPBYTE)new_glVertex3fv, 6);
pglVertex2f =     (glVertex2f_t)    Detour1((LPBYTE)glVertex2f,    (LPBYTE)new_glVertex2f, 6);
}

///////////////////////////////////////////////////////////////////////////////////////

bool APIENTRY DllMain(HANDLE hModule, DWORD  dwReason, LPVOID lpReserved)
{
if(dwReason == DLL_PROCESS_ATTACH)
{
// No es necesario este Detour para la demostración..
pGetProcAddress = (GetProcAddress_t)Detour1((LPBYTE)GetProcAddress,
(LPBYTE)new_GetProcAddress, 5);

if(GetModuleHandle("Opengl32.dll"))
Hook();
}
else if(dwReason == DLL_PROCESS_DETACH)
{
// Restaurar bytes en GPA

// (no hace falta suspender el mismo hilo! no sirve para nada XD)

// Salida con retardo.
// Permite que se ejecuten los últimos llamados a GPA
// (Y no hace falta restaurar los bytes parcheados XD)
ExitProcess(100);
}
return (true);
}

///////////////////////////////////////////////////////////////////////////////////////



otra cosa que quiero agregar, es que el 'hook' a GetProcAddress no es necesario, pero está hecho y sirve para demostrar algo importante.

cuando salimos del juego, osea del proceso, antes se descargan las DLLs entre otras cosas, pero cuando se descarga nuestra DLL la memoria del proceso continua parcheada (los hooks que instalamos), y las referencias a los hooks son inválidas ya que la DLL se ha descargado.

Esto no importa para Opengl32 porque nadie va a utilizar Opengl32 al salir, pero con GetProcAddress si pasa esto. Por eso se debería considerar restaurar los bytes parcheados en GetProcAddress, o más fácil es hacer que la DLL se descargue cuando ya no sea necesaria (cuando no se haga más referencia a los hooks). Con un ExitProcess(100) queda resuelto, en realidad no investigué acerca de este tema, sólo traté de arreglarlo de alguna forma. Pero es un detalle a considerar.

PROYECTO
http://www.mediafire.com/?qfb65fsfgaf5doa

#4
By: Shabbir (Go4Expert)
http://www.go4expert.com/articles/st...ration-t29601/

Captcha, reCaptcha as well as Question and Answer does not stop vBulletin Spam registrations and so I have come up with yet another solution to stop vBulletin Spam for Registration. This works with any kind of site and is based on Cookies for Comments Wordpress Plugin.

The idea and implementation is completely based on the plugin and so the credit completely goes to the Authors of the above plugin. I have just used it for vBulletin and shared it here so you can apply the same for your forums. It is very simple and yet so effective that it can be applied to almost any website.

Step 1
Download the above plugin and extract into a folder. Upload css.php file to your forum root directory. Browse to the css.php file in your browser and copy the link to the css.php file.

Step 2
Now add the following lines to your headinclude template in each of your vBulletin style.


<link rel="stylesheet" type="text/css" href="LINK_TO_FILE UPLOADED_IN_STEP1?k=SOME_RANDOM_STRING_OF_YOUR_CHOICE" />


Replace the SOME_RANDOM_STRING_OF_YOUR_CHOICE with anything of your choice.

If you don't want to add stylesheet declaration in your template, you can also opt for blank image. For this you have to upload the blank.gif image from the above plugin to your site and then add the following blank image code in header or footer template of each of your vBulletin style.


<img src="LINK_TO_FILE UPLOADED_IN_STEP1?k=SOME_RANDOM_STRING_OF_YOUR_CHOICE&o=img" width="0" height="0" border="0" style="display:none;" />


Step 3
Now Add the following into your .htaccess file.


RewriteCond %{HTTP_COOKIE} !^.*SOME_RANDOM_STRING_OF_YOUR_CHOICE.*$
RewriteRule ^register.php - [F,L]


Remember the above rules goes right at the top. Even above the vBSEO Rules if any.

Now any user visiting your register.php file without visiting any of your pages on your forum will get a 403 forbidden error message.

There can be issues if you have multiple CMSes like may be Wordpress and vBulletin or any other static pages and genuine users can click on registration link from those pages. The solution is to make the call to the above CSS/image file from every page of your site.

I hope it helps reduce the spam registration considerably.

The above solution can even be applied to any other custom CMS of your choice as well. You have to just block your registration pages with the needed cookie and set the cookies in header or footer of your site for genuine users who visit your site.

Further Spam Prevention Options for vBulletin
You can also opt for some more spam prevention options that I have mentioned on my blog here as well as opt for a Block vBulletin Spam Posts Plugin to stop spam posts in forums.

NOTA: Si está en inglés, pueden usar el traductor de google XD
http://translate.google.com.ar/

Pero si esto funciona como dice, es super importante para los que tienen vBulletin por el gran problema de los bots :/
Supuestamente sirve para cualquier sitio.
#5
http://research.microsoft.com/en-us/projects/detours/
Citar
Overview
Innovative systems research hinges on the ability to easily instrument and extend existing operating system and application functionality. With access to appropriate source code, it is often trivial to insert new instrumentation or extensions by rebuilding the OS or application. However, in today's world systems researchers seldom have access to all relevant source code.

Detours is a library for instrumenting arbitrary Win32 functions Windows-compatible processors. Detours intercepts Win32 functions by re-writing the in-memory code for target functions. The Detours package also contains utilities to attach arbitrary DLLs and data segments (called payloads) to any Win32 binary.

Detours preserves the un-instrumented target function (callable through a trampoline) as a subroutine for use by the instrumentation. Our trampoline design enables a large class of innovative extensions to existing binary software.

We have used Detours to create an automatic distributed partitioning system, to instrument and analyze the DCOM protocol stack, and to create a thunking layer for a COM-based OS API. Detours is used widely within Microsoft and within the industry.

Bueno, la intención no es contar toda la historia sino publicar un código fuente XD.

En síntesis, con esta librería se pueden interceptar funciones. Es una librería de MS que no es pública en su versión completa, pero si tiene una versión de prueba para el público.
Se usaba desde hace años para construir los hacks de distintos juegos, por ejemplo para el Counter-Strike.
En este enlace se puede encontrar una base para un hook de Opengl32 que fue muy conocida cuando salió.
http://board.cheat-project.com/showthread.php?t=9232

Algunas de estas bases se hicieron primero con Detours 1.5 y después se actualizaron a Detours 2.1. Ahora está disponible la versión pública de Detours 3.0.

Lo que hice yo, fue organizar la base publicada en ese enlace que he mostrado. originalmente no compilaba, tenía errores, faltaban archivos, y tenía mucho código que no era necesario para una simple demostración.
Por eso el código fue organizado y arreglado para que funcione, el proyecto es de una librería de vínculos dinámicos (DLL), que debe ser cargada en el juego Counter-Strike (En modo Opengl32).
Al cargarse la DLL se instalan los hooks ('detours'), y se obtiene un "Wallhack" funcionando.

El creador de esta base es un tal Xantrax, el link ya lo he mostrado.
Esto se trata de ver como se implementa esta librería.
Dejo el código completo y al final un enlace de descarga.
La descarga fue preparada especialmente, porque incluye los archivos de instalación de Detours 2.1, el .h y la librería estática .lib.
Y se incluye también el .h y la librería estática .lib correspondiente a Detours 1.5.
El tema es que estos archivos no se consiguen fácilmente porque son versiones anteriores de 'Detours'.
Otra cosa es que para obtener la librería estática .lib se tiene que compilar 'Detours' para que la produzca.

Código (cpp) [Seleccionar]


//
// Modifications: By 85
// Credits: Xantrax, MS Detours 2.1
// elhacker.net
// etalking.com.ar
// david_bs@live.com
// 2013
//

///////////////////////////////////////////////////////////////////////////////////////

#pragma comment(lib,"detours.lib")// 1.5
#pragma comment(lib,"OpenGL32.lib")
#include <windows.h>
#include <gl/gl.h>
#include<stdio.h>

#include "detours.h"

///////////////////////////////////////////////////////////////////////////////////////

bool bOGLSubtractive = false;
bool g_bSky = false;

///////////////////////////////////////////////////////////////////////////////////////

class CDraw {
public:
CDraw();
int m_iVpCounter;
bool m_bDrawing;
void DrawPanel();
};

CDraw::CDraw( ){
m_iVpCounter = 0;
m_bDrawing = false;
}

void CDraw::DrawPanel( ) {

//Drawing Every 5th here
}

CDraw* pDraw = new CDraw();

///////////////////////////////////////////////////////////////////////////////////////

/* function prototype and original target */

DETOUR_TRAMPOLINE( VOID WINAPI Trampoline_glBegin( GLenum mode ), glBegin );
DETOUR_TRAMPOLINE( VOID WINAPI Trampoline_glViewport( GLint x,  GLint y,  GLsizei width,  GLsizei height ), glViewport );
DETOUR_TRAMPOLINE( VOID WINAPI Trampoline_glVertex3fv( const GLfloat *v ), glVertex3fv  );
DETOUR_TRAMPOLINE( VOID WINAPI Trampoline_glVertex3f( GLfloat x, GLfloat y, GLfloat z ), glVertex3f );
DETOUR_TRAMPOLINE( VOID WINAPI Trampoline_glShadeModel( GLenum mode ), glShadeModel );
DETOUR_TRAMPOLINE( VOID WINAPI Trampoline_glClear( GLbitfield mask ), glClear );
DETOUR_TRAMPOLINE( VOID WINAPI Trampoline_glColor3f( GLfloat red, GLfloat green, GLfloat blue ), glColor3f );
typedef void (WINAPI* wglSwapBuffers_t)(HDC);

///////////////////////////////////////////////////////////////////////////////////////

//#define HIWORD(l)           ((WORD)((DWORD_PTR)(l) >> 16))

DETOUR_TRAMPOLINE(FARPROC WINAPI Trampoline_GetProcAddress(HMODULE hModule,
 LPCSTR lpProcName), GetProcAddress);

///////////////////////////////////////////////////////////////////////////////////////

VOID WINAPI glBeginDetour(GLenum mode)
{
if(mode == GL_TRIANGLE_STRIP || mode == GL_TRIANGLE_FAN)
glDepthRange( 0, 0.5 );
else
glDepthRange( 0.5, 1 );

if(mode == GL_TRIANGLE_STRIP || mode == GL_TRIANGLE_FAN)
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);

if( mode == GL_QUADS )
g_bSky = true;
else
g_bSky = false;

Trampoline_glBegin(mode);
}

///////////////////////////////////////////////////////////////////////////////////////

VOID WINAPI glClearDetour(GLbitfield mask)
{
if(mask==GL_DEPTH_BUFFER_BIT)
{
mask+=GL_COLOR_BUFFER_BIT;
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

Trampoline_glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
return;
}

Trampoline_glClear(mask);
}

///////////////////////////////////////////////////////////////////////////////////////

VOID WINAPI glShadeModelDetour(GLenum mode)
{
//XQZ2 wallhack
if( mode == GL_SMOOTH ){
__asm {
push 0x00000100 //GL_DEPTH_BUFFER_BIT
call dword ptr[ Trampoline_glClear ]
}
}

Trampoline_glShadeModel(mode);
}

///////////////////////////////////////////////////////////////////////////////////////

VOID WINAPI glViewportDetour(GLint x, GLint y, GLsizei width, GLsizei height)
{
pDraw->m_iVpCounter++;
if( pDraw->m_iVpCounter >= 5 ){
pDraw->m_bDrawing = true;
}
Trampoline_glViewport(x, y, width, height);
}

///////////////////////////////////////////////////////////////////////////////////////

VOID WINAPI glColor3fDetour(GLfloat red, GLfloat green, GLfloat blue)
{
Trampoline_glColor3f(red, green, blue);
}

///////////////////////////////////////////////////////////////////////////////////////

VOID WINAPI glVertex3fvDetour(const GLfloat* v)
{
if(g_bSky && v[2]>300){

return;
/*float flZero = 0.0f;
__asm {
push flZero
push flZero
push flZero
call dword ptr[ Trampoline_glColor3f ]
}*/
}
Trampoline_glVertex3fv(v);
}

///////////////////////////////////////////////////////////////////////////////////////

VOID WINAPI glVertex3fDetour(GLfloat x, GLfloat y, GLfloat z)
{
Trampoline_glVertex3f(x, y, z);
}

///////////////////////////////////////////////////////////////////////////////////////

wglSwapBuffers_t pwglSwapBuffers = NULL;
// DETOUR_TRAMPOLINE(void WINAPI _wglSwapBuffers(HDC hDC), wglSwapBuffers);
// since wglSwapBuffers is undefined, the macro wont work. this is, what it basically does:
static PVOID __fastcall _Detours_GetVA_wglSwapBuffers(VOID)
{
   return pwglSwapBuffers;
}

///////////////////////////////////////////////////////////////////////////////////////

__declspec(naked) void WINAPI _Trampoline_wglSwapBuffers(HDC hDC)
{
   __asm { nop };
   __asm { nop };
   __asm { call _Detours_GetVA_wglSwapBuffers };
   __asm { jmp eax };
   __asm { ret };
   __asm { nop };
   __asm { nop };
   __asm { nop };
   __asm { nop };
   __asm { nop };
   __asm { nop };
   __asm { nop };
   __asm { nop };
   __asm { nop };
   __asm { nop };
   __asm { nop };
   __asm { nop };
   __asm { nop };
   __asm { nop };
   __asm { nop };
   __asm { nop };
   __asm { nop };
   __asm { nop };
   __asm { nop };
   __asm { nop };
   __asm { nop };
   __asm { nop };
}

///////////////////////////////////////////////////////////////////////////////////////

VOID WINAPI _wglSwapBuffers(HDC hDC)
{
pDraw->m_iVpCounter = 0;
_Trampoline_wglSwapBuffers( hDC );
}

///////////////////////////////////////////////////////////////////////////////////////

void DetourOpenGL()
{
#define Detour( pbTrampFunc, pbDetourFunc )\
DetourFunctionWithTrampoline( (PBYTE)##pbTrampFunc,( PBYTE )##pbDetourFunc )

Detour( Trampoline_glBegin, glBeginDetour );
Detour( Trampoline_glVertex3fv, glVertex3fvDetour );
Detour( Trampoline_glClear, glClearDetour );
/*
Detour( Trampoline_glShadeModel, glShadeModelDetour );
Detour( Trampoline_glViewport, glViewportDetour );
Detour( Trampoline_glVertex3f, glVertex3fDetour );

// Because wglSwapBuffers isnt declared in GL\GL.h...
pwglSwapBuffers = (wglSwapBuffers_t)GetProcAddress(LoadLibrary("opengl32.dll"),
"wglSwapBuffers");
Detour( _Trampoline_wglSwapBuffers, _wglSwapBuffers);

Detour( Trampoline_glColor3f, glColor3fDetour );*/
}

///////////////////////////////////////////////////////////////////////////////////////

void RemoveOpenGLDetour()
{
#define Destroy( pbTrampFunc, pbDetourFunc )\
DetourRemove( (PBYTE)##pbTrampFunc,( PBYTE )##pbDetourFunc )

Destroy( Trampoline_glBegin, glBeginDetour );
Destroy( Trampoline_glVertex3fv, glVertex3fvDetour );
Destroy( Trampoline_glClear, glClearDetour );
/*
Destroy( Trampoline_glShadeModel, glShadeModelDetour );
Destroy( Trampoline_glViewport, glViewportDetour );
Destroy( Trampoline_glVertex3f, glVertex3fDetour );

Destroy( Trampoline_glColor3f, glColor3fDetour );*/
}

///////////////////////////////////////////////////////////////////////////////////////

FARPROC WINAPI GetProcAddressDetour(HMODULE hModule, LPCSTR lpProcName)
{
FARPROC retval = Trampoline_GetProcAddress(hModule, lpProcName);
return retval;
}

///////////////////////////////////////////////////////////////////////////////////////

BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH://Let the magic happen...:->
DetourOpenGL();
//Extras
/* DetourFunctionWithTrampoline((PBYTE)Trampoline_GetProcAddress,
(PBYTE)GetProcAddressDetour);*/
break;
case DLL_PROCESS_DETACH:
RemoveOpenGLDetour();
break;
}
   return TRUE;
}

///////////////////////////////////////////////////////////////////////////////////////


PROJECT VCPP6
http://www.mediafire.com/?tl9qprjaytk77v7

#6
Algunos sitios web que ofrecen la posibilidad de compilar, depurar y ejecutar un programa en C/C++

http://codepad.org/

Me gusta XD
http://www.compileonline.com/compile_cpp_online.php

http://isocpp.org/blog/2013/01/online-c-compilers

http://liveworkspace.org/

http://gcc.godbolt.org/

https://compilr.com/c-compiler

mucho mejor para hacer pruebas rápidas de los códigos que aparecen por el foro  >:D




#7
Hola, como había estado comentado algunas cosas acerca de reemplazar DLLs existentes con versiones propias,
http://foro.elhacker.net/programacion_cc/dll_wrapper_1_creando_nuestra_psapidll_con_def-t386996.0.html

justo me había acordado de una 'wrapper' muy famosa en el ambiente del hacking de juegos.
Es del 2002 de un programador llamado Crusader, y durante un tiempo esto había servido para utilizar wallhacks en el Counter-Strike, aunque se debería poder usarse en otros juegos basados en Opengl32.

este es el link del proyecto
http://www.mediafire.com/?zad5ce1gd8lr8k2

Lo que hice fue agregar algunas líneas para remover el cielo y para un wallhack. La DLL de reemplazo (wrapper) se debe poner en la carpeta del juego (ver imagen 1).

Esto es detectado por los sistemas antitrampas, validan los archivos y las rutas. Pero puede servir a alguien para practicar con Opengl32.
Con los hacks se aprende XD



#8
NIVEL: Beginner
Test: WinXP SP3 32BITS

Tomando en cuenta el tutorial anterior acerca del creamiento de una versión propia de una DLL conocida,
http://foro.elhacker.net/programacion_cc/dll_wrapper_1_creando_nuestra_psapidll_con_def-t386996.0.html

Algo que se denominaba 'wrapper', en este caso vamos a hacer lo mismo pero sin la necesidad de usar un archivo .DEF para los símbolos exportados.
El tema es que para hacer la exportación de símbolos en este caso sin usar .DEF tenemos que utilizar en nuestras funciones de reemplazo, el nombre completo y correcto de las funciones originales.

Primero vayamos a las opciones del proyecto, y veamos que la opción de la convención de llamada  esté en __cdecl, porque si bien sabíamos que PSAPI usaba __stdcall, pero lo que vamos a hacer en esta ocasión es especificarlo explícitamente en el código, para cada función.
Por defecto siempre esta opción se encuentra en __cdecl, en otras palabras lo que quiero decir es que lo dejen así..



Empecemos diciendo en lo que es similar al anterior método, por ejemplo los prototipos de las funciones. Veamos una definición de tipo para la función EnumProcesses en main.cpp

Código (cpp) [Seleccionar]
typedef BOOL (WINAPI* EnumProcesses_t)(DWORD*,DWORD,DWORD*);

Una declaración de puntero a función
Código (cpp) [Seleccionar]
BOOL (WINAPI* pEnumProcesses)(DWORD*,DWORD,DWORD*);

Veamos como se expecifica explícitamente la convención de llamada __stdcall (WINAPI).
La definición de nuestra función de reemplazo, que como habíamos visto antes, retorna el puntero a función original. En este caso a la EnumProcesses original en la DLL original que renombramos PSAPI2.DLL
Código (cpp) [Seleccionar]
BOOL WINAPI newEnumProcesses(DWORD* pProcessIds, DWORD cb, DWORD* pBytesReturned)
{
     return pEnumProcesses(pProcessIds, cb, pBytesReturned);
}


El tema es que como no estamos usando un .DEF tenemos que especificar en el código, qué funciones son las que van a ser exportadas. Esto se hace con __declspec (dllexport)

Veamos una macro que al mismo tiempo también especifica que se trata de un estilo de función de C con lo cual evitamos el planchado de nombres en los símbolos exportados.
Código (cpp) [Seleccionar]
#define DLLEXPORTING extern "C" __declspec (dllexport)

Más información acerca de esto:
http://msdn.microsoft.com/es-es/library/a90k134d(v=vs.80).aspx
http://msdn.microsoft.com/en-us/library/a90k134d(v=vs.80).aspx
http://msdn.microsoft.com/es-AR/library/0603949d(v=vs.80).aspx
http://msdn.microsoft.com/en-us/library/aa278942(v=vs.60).aspx

En el compilador vamos a dejar que la convención de llamada por defecto sea __cdecl, y vamos a valernos de especificar __stdcall en los prototipos o definiciones de tipos y en los punteros a función, como ya vimos.
En el anterior tutorial, teníamos 2 instancias de funciones de reemplazo para cada función que íbamos a exportar. Y vimos que la segunda instancia no era necesaria antes, pero ahora si lo va a ser.

Veamos exports.cpp
Esta es la segunda instancia, debe ser del tipo __cdecl para ser compatible con la directiva extern "C", y al mismo tiempo debe ser el símbolo marcado para ser exportado, eso se hace con __declspec (dllexport) como dijimos antes. Y por último, el nombre de esta función debe ser exactamente igual al de la original.

Código (cpp) [Seleccionar]
DLLEXPORTING BOOL EnumProcesses(DWORD* pProcessIds, DWORD cb, DWORD* pBytesReturned)
{
      //return newEnumProcesses(pProcessIds, cb, pBytesReturned);
}


Por eso si la convención de llamada por defecto es __cdecl entonces esta función tendría esa convención.
Por eso dije antes que la dejen como estaba a la opción esa. De otra forma debería especificar __cdecl
explícitamente en la definición de la función.

En teoría debería deberíamos usar el puntero a la función original a modo de una llamada a función por puntero (ya sea como return+puntero o sólo el puntero si se trata de una función de tipo void).

Es en este punto donde necesitamos ver este tutorial anterior en el cual se comentaba un caso en el cual el compilador genera código de stack frame dentro de la función lo cual altera la pila y el registro EBP.
Link:
http://foro.elhacker.net/programacion_cc/gltest1_problema_con_la_convencion_de_llamada-t384879.0.html

Esta situación no es diferente a la del enlace anterior, por lo que la solución es la misma; nuestra función de reemplazo de tipo __cdecl va a tener que restaurar el registro EBP antes de saltar a la función original.
Vamos a utilizar la instrucción JMP para ir a la original y no la instrucción CALL (aunque vimos que se puede).
Código (cpp) [Seleccionar]

DLLEXPORTING BOOL EnumProcesses(DWORD* pProcessIds, DWORD cb, DWORD* pBytesReturned)
{
            int a = 85;
            a = 85 - 85 + 85;
            // usa ebp
            // agrega edi al stack
            // add esp, 0x14

            __asm mov eax,[esp+0x10]
            __asm mov EnumProcesses_ebp_save,eax
            __asm mov ebp,EnumProcesses_ebp_save
            __asm add esp,0x14//debe borrar hasta ebp, no más que eso (no el retaddress ni los argumentos)
            __asm jmp newEnumProcesses
            //return newEnumProcesses(pProcessIds, cb, pBytesReturned);
}


El fix con ensamblador en línea (inline ASM), guarda el registro EBP y lo restaura antes de saltar a la función original, también se deja la pila equilibrada con ADD ESP, X
Tanto la ubicación del EBP original en la pila como la cantidad de espacios que se deben reducir para equilibrar la misma, se deben obtener de un desensamblador por ejemplo. Sino, pueden utilizar un depurador como el OllyDBG.

Veamos igualmente una imagen de como resulta el código de ensamblador:



Citar
10001000 >  55                           PUSH EBP
10001001    8BEC                        MOV EBP,ESP
10001003    51                            PUSH ECX
10001004    53                            PUSH EBX
10001005    56                            PUSH ESI
10001006    57                            PUSH EDI
10001007    C745 FC 5500000>      MOV DWORD PTR SS:[EBP-4],55
1000100E    C745 FC 5500000>      MOV DWORD PTR SS:[EBP-4],55
10001015    8B4424 10                 MOV EAX,DWORD PTR SS:[ESP+10]
10001019    A3 D0320010             MOV DWORD PTR DS:[100032D0],EAX
1000101E    8B2D D0320010          MOV EBP,DWORD PTR DS:[100032D0]
10001024    83C4 14                    ADD ESP,14
10001027    E9 64040000             JMP psapi.10001490
1000102C    5F                           POP EDI
1000102D    5E                           POP ESI
1000102E    5B                           POP EBX
1000102F    8BE5                        MOV ESP,EBP
10001031    5D                           POP EBP
10001032    C3                           RETN

Como ustedes pueden ver se genera al final este código:
Citar
1000102C 5F POP EDI
1000102D 5E POP ESI
1000102E 5B POP EBX
1000102F 8BE5 MOV ESP,EBP
10001031 5D POP EBP
Lo cual es una correcta liberación de pila, pero el problema es que este código no se genera sino usamos el fix.

Como ya dije, es la misma situación que la del tutorial de convención de llamada para un caso con Opengl32.

El resultado es una DLL wrapper de PSAPI.DLL que no requiere .DEF para realizar las exportaciones.
Psapi.lib tampoco es requerida, recordemos que hacemos un enlazamiento dinámico con la DLL PSAPI.DLL original (que renombramos a PSAPI2.DLL).

Y los nombres de los EXPORTS no resultan cambiados.



Funciona.



Proyecto VC++6:
http://www.mediafire.com/?8su3luoh0r72ypf

Saludos
#9
NIVEL: Beginner
Test: WinXP SP3

Este tutorial te va a enseñar como crear algo conocido como 'Wrapper' de una DLL, cuya traducción es 'envoltura' pero se conoce con el término del inglés directamente. Las wrappers son versiones propias de DLL's conocidas. En este caso vamos a hacer un wrapper de una DLL muy conocida llamada PSAPI.DLL.
Si no la conocen investíguenla XD, pero se trata de una DLL bastante común encontrarla cargada en muchos procesos.
La técnica de construir wrappers tiene al menos 2 objetivos:
1: Hooking. ya que nuestra propia versión de la DLL va a contener nuestras propias versiones de las funciones originales, y al mismo
Tiempo necesitamos llamar a las originales dentro de las nuestras.
El tema es que podemos ejecutar nuestro código antes de que se ejecute el código original.
2: Cargar una DLL. Lo que estamos haciendo al crear nuestra propia versión de una DLL conocida es hacer que al programa víctima se le cargue nuestra DLL en lugar de la original. Esta carga no la hace el programa víctima sino el sistema operativo. El SO detecta nuestra DLL en la misma ubicación que el archivo ejecutable del programa y la carga automáticamente, ya que existe una dependencia real con la DLL.

En cuanto a seguridad, es una técnica no efectiva para crear un hack para un programa que tenga seguridad. Sería muy fácil validar los archivos en disco que se cargan al proceso (con MD5 por ejemplo), o validar las rutas, etc etc
Mientras no sea para nada de hacking, tiene cierto atractivo esta idea XD.

Acerca de como se crea algo así.. Bueno lo primero es conocer la DLL original que queremos reemplazar, es decir todas sus funciones o al menos las que el proceso víctima utilice (dependencias).

Esto significa que debemos conocer los prototipos de estas funciones, incluyendo su convención de llamada y demás.
Teniendo eso en primer lugar, vamos a considerar que también necesitamos usar la DLL original porque dependemos de las funciones originales. Esto se resuelve cambiándole el nombre a la DLL original. En el caso de PSAPI.DLL lo podemos cambiar a PSAPI2.DLL.
Luego vamos a necesitar cargar la DLL original renombrada y hacer un enlazamiento dinámico con ella,  y conseguir las direcciones originales de las funciones que necesitamos. Obviamente esto lo hacemos con LoadLibrary + GetProcAddress.
Luego en nuestra propia DLL ponemos las funciones de reemplazo respetando los prototipos y le ponemos las direcciones de retorno a las originales que importamos dinámicamente con GetProcAddress.
Utilizamos obviamente punteros a función para los retornos en las funciones de reemplazo (hooks).

La convención de llamada usada en PSAPI.DLL para las funciones es __stdcall, por eso podemos hacer que todas las funciones en nuestro proyecto sean por defecto __stdcall para no tener que especificarlo explícitamente en cada una.


Veamos a PSAPI.DLL


Veamos sus exportaciones.


Vamos a concentrarnos en una de sus funciones sólamente, por ejemplo EnumProcesses


Necesitamos un prototipo de función, definamos un tipo de dato correspondiente a esta función.
Código (cpp) [Seleccionar]
typedef BOOL (* EnumProcesses_t)(DWORD*,DWORD,DWORD*);

Creamos un puntero a función que va a servir de retorno a la original dentro de la función de reemplazo.
Código (cpp) [Seleccionar]
BOOL (* pEnumProcesses)(DWORD*,DWORD,DWORD*);

Creamos la función de reemplazo (vemos que retorna con el puntero a la original)
Código (cpp) [Seleccionar]
BOOL  newEnumProcesses(DWORD* pProcessIds, DWORD cb, DWORD* pBytesReturned)
{
    return pEnumProcesses(pProcessIds, cb, pBytesReturned);
}


Ahora creamos otra instancia más (no realmente necesaria en este caso), esta función va a ser la que se exporte para que pueda ser usada por el programa víctima.
Código (cpp) [Seleccionar]
BOOL  _EnumProcesses(DWORD* pProcessIds, DWORD cb, DWORD* pBytesReturned)
{
    return newEnumProcesses(pProcessIds, cb, pBytesReturned);
}


Y básicamente hacer lo mismo con las demás funciones XD.
Para compilar este proyecto se requiere del archivo psapi.h que contiene los tipos de datos usados en las funciones de reemplazo. No se requiere psapi.lib que es una librería de enlazamiento estático.

Vamos a necesitar un archivo .DEF que debe ser incluído en el proyecto.
Hay unas reglas para usar el .DEF y estas son:
1: se debe empezar poniendo LIBRARY y seguido el nombre de la DLL.
2: se debe poner EXPORTS
3: se deben poner uno por uno, los nombres que deseamos para cada símbolo, seguido de cada
Nombre debe ir el signo '=' y el nombre real del símbolo, el cual obtenemos del desensamblado.
4: seguido a lo anterior se deja un espacio y se coloca un 'arroba' y el número de índice de exportación.

Pero veamos una imagen para entender como se hace:


Veamos el código de la DLL:

En main.cpp se encuentran los prototipos de las funciones y los punteros a funciones. Para no poner todo veamos sólo el caso de EnumProcesses

Código (cpp) [Seleccionar]

typedef BOOL (* EnumProcesses_t)(DWORD*,DWORD,DWORD*);


Código (cpp) [Seleccionar]

BOOL (* pEnumProcesses)(DWORD*,DWORD,DWORD*);


Luego tenemos las funciones de reemplazo. Estas retornan un puntero a función.
Código (cpp) [Seleccionar]

BOOL  newEnumProcesses(DWORD* pProcessIds, DWORD cb, DWORD* pBytesReturned)
{
    return pEnumProcesses(pProcessIds, cb, pBytesReturned);
}



Luego se muestra un código que se trata de una clase y la creación de un objeto de tipo de la clase, esto busca que se inicializen los punteros a función cuando el programa es ejecutado, ya que cuando se crea el objeto se ejecuta la rutina que inicializa los punteros a función.
Código (cpp) [Seleccionar]

/*
class Inicializar
{
public:
   Inicializar()
   {
       pEnumProcesses = 0;
       pEnumProcessModules = 0;
       pGetModuleBaseNameA = 0;
       pGetModuleBaseNameW = 0;
       pGetModuleFileNameExA = 0;
       pGetModuleFileNameExW = 0;
       pGetModuleInformation = 0;
       pEmptyWorkingSet = 0;
       pQueryWorkingSet = 0;
       pInitializeProcessForWsWatch = 0;    
       pGetWsChanges = 0;
       pGetMappedFileNameW = 0;
       pGetMappedFileNameA = 0;
       pEnumDeviceDrivers = 0;
       pGetDeviceDriverBaseNameA = 0;
       pGetDeviceDriverBaseNameW = 0;
       pGetDeviceDriverFileNameA = 0;
       pGetDeviceDriverFileNameW = 0;
       pGetProcessMemoryInfo = 0;
       pEnumPageFilesA =0;
       pEnumPageFilesW =0;
       pGetPerformanceInfo =0;
       pGetProcessImageFileNameA =0;
       pGetProcessImageFileNameW=0;

       HINSTANCE myDLL;
       myDLL = LoadLibrary("psapi2.dll");

       if(myDLL != NULL)
       {
          pEnumProcesses = (EnumProcesses_t)GetProcAddress(myDLL, "EnumProcesses");
          pEnumProcessModules = (EnumProcessModules_t)GetProcAddress(myDLL, "EnumProcessModules");
          pGetModuleBaseNameA = (GetModuleBaseNameA_t)GetProcAddress(myDLL, "GetModuleBaseNameA");
          pGetModuleBaseNameW = (GetModuleBaseNameW_t)GetProcAddress(myDLL, "GetModuleBaseNameW");
          pGetModuleFileNameExA = (GetModuleFileNameExA_t)GetProcAddress(myDLL, "GetModuleFileNameExA");
          pGetModuleFileNameExW = (GetModuleFileNameExW_t)GetProcAddress(myDLL, "GetModuleFileNameExW");
          pGetModuleInformation = (GetModuleInformation_t)GetProcAddress(myDLL, "GetModuleInformation");
          pEmptyWorkingSet = (EmptyWorkingSet_t)GetProcAddress(myDLL, "EmptyWorkingSet");
          pQueryWorkingSet = (QueryWorkingSet_t)GetProcAddress(myDLL, "QueryWorkingSet");
          pInitializeProcessForWsWatch = (InitializeProcessForWsWatch_t)GetProcAddress(myDLL, "InitializeProcessForWsWatch");        
          pGetWsChanges = (GetWsChanges_t)GetProcAddress(myDLL, "GetWsChanges");
          pGetMappedFileNameW = (GetMappedFileNameW_t)GetProcAddress(myDLL, "GetMappedFileNameW");
          pGetMappedFileNameA = (GetMappedFileNameA_t)GetProcAddress(myDLL, "GetMappedFileNameA");
          pEnumDeviceDrivers = (EnumDeviceDrivers_t)GetProcAddress(myDLL, "EnumDeviceDrivers");
          pGetDeviceDriverBaseNameA = (GetDeviceDriverBaseNameA_t)GetProcAddress(myDLL, "GetDeviceDriverBaseNameA");
          pGetDeviceDriverBaseNameW = (GetDeviceDriverBaseNameW_t)GetProcAddress(myDLL, "GetDeviceDriverBaseNameW");
          pGetDeviceDriverFileNameA = (GetDeviceDriverFileNameA_t)GetProcAddress(myDLL, "GetDeviceDriverFileNameA");
          pGetDeviceDriverFileNameW = (GetDeviceDriverFileNameW_t)GetProcAddress(myDLL, "GetDeviceDriverFileNameW");
          pGetProcessMemoryInfo = (GetProcessMemoryInfo_t)GetProcAddress(myDLL, "GetProcessMemoryInfo");
          pEnumPageFilesA =(EnumPageFilesA_t)GetProcAddress(myDLL, "EnumPageFilesA");
          pEnumPageFilesW =(EnumPageFilesW_t)GetProcAddress(myDLL, "EnumPageFilesW");
          pGetPerformanceInfo =(GetPerformanceInfo_t)GetProcAddress(myDLL, "GetPerformanceInfo");
          pGetProcessImageFileNameA =(GetProcessImageFileNameA_t)GetProcAddress(myDLL, "GetProcessImageFileNameA");
          pGetProcessImageFileNameW =(GetProcessImageFileNameW_t)GetProcAddress(myDLL, "GetProcessImageFileNameW");
       }
   }
};


//
Inicializar Init;
*/



Eso está comentado porque ya se hace en 'DllMain' directamente, junto con un LOG de información.
Código (cpp) [Seleccionar]


BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved )
{
   switch (ul_reason_for_call)
   {
       case DLL_PROCESS_ATTACH:
           {
               pEnumProcesses = 0;
               pEnumProcessModules = 0;
               pGetModuleBaseNameA = 0;
               pGetModuleBaseNameW = 0;
               pGetModuleFileNameExA = 0;
               pGetModuleFileNameExW = 0;
               pGetModuleInformation = 0;
               pEmptyWorkingSet = 0;
               pQueryWorkingSet = 0;
               pInitializeProcessForWsWatch = 0;    
               pGetWsChanges = 0;
               pGetMappedFileNameW = 0;
               pGetMappedFileNameA = 0;
               pEnumDeviceDrivers = 0;
               pGetDeviceDriverBaseNameA = 0;
               pGetDeviceDriverBaseNameW = 0;
               pGetDeviceDriverFileNameA = 0;
               pGetDeviceDriverFileNameW = 0;
               pGetProcessMemoryInfo = 0;
               pEnumPageFilesA =0;
               pEnumPageFilesW =0;
               pGetPerformanceInfo =0;
               pGetProcessImageFileNameA =0;
               pGetProcessImageFileNameW=0;

               HINSTANCE myDLL;
               myDLL = LoadLibrary("psapi2.dll");

               if(myDLL != NULL)
               {
                  pEnumProcesses = (EnumProcesses_t)GetProcAddress(myDLL, "EnumProcesses");
                  pEnumProcessModules = (EnumProcessModules_t)GetProcAddress(myDLL, "EnumProcessModules");
                  pGetModuleBaseNameA = (GetModuleBaseNameA_t)GetProcAddress(myDLL, "GetModuleBaseNameA");
                  pGetModuleBaseNameW = (GetModuleBaseNameW_t)GetProcAddress(myDLL, "GetModuleBaseNameW");
                  pGetModuleFileNameExA = (GetModuleFileNameExA_t)GetProcAddress(myDLL, "GetModuleFileNameExA");
                  pGetModuleFileNameExW = (GetModuleFileNameExW_t)GetProcAddress(myDLL, "GetModuleFileNameExW");
                  pGetModuleInformation = (GetModuleInformation_t)GetProcAddress(myDLL, "GetModuleInformation");
                  pEmptyWorkingSet = (EmptyWorkingSet_t)GetProcAddress(myDLL, "EmptyWorkingSet");
                  pQueryWorkingSet = (QueryWorkingSet_t)GetProcAddress(myDLL, "QueryWorkingSet");
                  pInitializeProcessForWsWatch = (InitializeProcessForWsWatch_t)GetProcAddress(myDLL, "InitializeProcessForWsWatch");        
                  pGetWsChanges = (GetWsChanges_t)GetProcAddress(myDLL, "GetWsChanges");
                  pGetMappedFileNameW = (GetMappedFileNameW_t)GetProcAddress(myDLL, "GetMappedFileNameW");
                  pGetMappedFileNameA = (GetMappedFileNameA_t)GetProcAddress(myDLL, "GetMappedFileNameA");
                  pEnumDeviceDrivers = (EnumDeviceDrivers_t)GetProcAddress(myDLL, "EnumDeviceDrivers");
                  pGetDeviceDriverBaseNameA = (GetDeviceDriverBaseNameA_t)GetProcAddress(myDLL, "GetDeviceDriverBaseNameA");
                  pGetDeviceDriverBaseNameW = (GetDeviceDriverBaseNameW_t)GetProcAddress(myDLL, "GetDeviceDriverBaseNameW");
                  pGetDeviceDriverFileNameA = (GetDeviceDriverFileNameA_t)GetProcAddress(myDLL, "GetDeviceDriverFileNameA");
                  pGetDeviceDriverFileNameW = (GetDeviceDriverFileNameW_t)GetProcAddress(myDLL, "GetDeviceDriverFileNameW");
                  pGetProcessMemoryInfo = (GetProcessMemoryInfo_t)GetProcAddress(myDLL, "GetProcessMemoryInfo");
                  pEnumPageFilesA =(EnumPageFilesA_t)GetProcAddress(myDLL, "EnumPageFilesA");
                  pEnumPageFilesW =(EnumPageFilesW_t)GetProcAddress(myDLL, "EnumPageFilesW");
                  pGetPerformanceInfo =(GetPerformanceInfo_t)GetProcAddress(myDLL, "GetPerformanceInfo");
                  pGetProcessImageFileNameA =(GetProcessImageFileNameA_t)GetProcAddress(myDLL, "GetProcessImageFileNameA");
                  pGetProcessImageFileNameW =(GetProcessImageFileNameW_t)GetProcAddress(myDLL, "GetProcessImageFileNameW");
               
                  DisableThreadLibraryCalls (myDLL);
               }

               if(!pEnumProcesses||!pEnumProcessModules ||!pGetModuleBaseNameA ||!pGetModuleBaseNameW
                   ||!pGetModuleFileNameExA ||!pGetModuleFileNameExW ||!pGetModuleInformation
                   ||!pEmptyWorkingSet ||!pQueryWorkingSet
                   
                   ||!pInitializeProcessForWsWatch ||!pGetWsChanges ||!pGetMappedFileNameW
                   ||!pGetMappedFileNameA
                   ||!pEnumDeviceDrivers ||!pGetDeviceDriverBaseNameA ||!pGetDeviceDriverBaseNameW
                   ||!pGetDeviceDriverFileNameA ||!pGetDeviceDriverFileNameW ||!pGetProcessMemoryInfo
                   ||!pEnumPageFilesA ||!pEnumPageFilesW
                   ||!pGetPerformanceInfo ||!pGetProcessImageFileNameA ||!pGetProcessImageFileNameW)
               {
                   printf("Wrapper not installed!\n");
                   system("pause");
               }
               else
               {
                   extern DWORD AddEnumProcesses;
                   printf("DLL\n");
                   printf("EnumProcesses 0x%x\n",AddEnumProcesses);
                   printf("newEnumProcesses 0x%x\n",newEnumProcesses);
                   printf("hModule 0x%x\n",hModule);
                   printf("PSAPI2.DLL 0x%x\n",GetModuleHandle("psapi2.dll"));
                   printf("pEnumProcesses 0x%x\n",pEnumProcesses);
                   system("pause");
               }
           }
           break;

       case DLL_THREAD_ATTACH:
       case DLL_THREAD_DETACH:
       case DLL_PROCESS_DETACH:
       break;
   }
   return TRUE;
}

///////////////////////////////


En exports.cpp sólamente tenemos las funciones de exportación, son las cuales son referenciadas en el archivo .DEF. Estas funciones retornan las funciones de reemplazo. Esto de tener 2 instancias no es necesario como ya se dijo, pero si lo es si se desea utilizar otro método que después voy a exponer.
Código (cpp) [Seleccionar]

BOOL  _EnumProcesses(DWORD* pProcessIds, DWORD cb, DWORD* pBytesReturned)
{
    return newEnumProcesses(pProcessIds, cb, pBytesReturned);
}


Veamos el código del programa 'Dummy' que actúa como el programa víctima:
Código (cpp) [Seleccionar]

//
// By 85
// elhacker.net
// etalking.com.ar
// david_bs@live.com
// 2013
//

#pragma comment(lib,"psapi.lib")
#include<windows.h>
#include<stdio.h>

//////////////////////

#define DLLIMPORTING extern "C" __declspec (dllimport)
DLLIMPORTING BOOL WINAPI EnumProcesses(DWORD *,DWORD,DWORD *);
DLLIMPORTING BOOL WINAPI EnumProcessModules(HANDLE,HMODULE *,DWORD,LPDWORD);
DLLIMPORTING DWORD WINAPI GetModuleFileNameExA(HANDLE,HMODULE,LPSTR,DWORD);
DLLIMPORTING DWORD WINAPI GetModuleFileNameExW(HANDLE,HMODULE,LPWSTR,DWORD);

DLLIMPORTING DWORD WINAPI GetModuleBaseNameA(HANDLE hProcess, HMODULE hModule, LPSTR lpBaseName, DWORD nSize);
DLLIMPORTING DWORD WINAPI GetModuleBaseNameW(HANDLE hProcess,HMODULE hModule,LPWSTR lpwBaseName,DWORD nSize);

#ifdef UNICODE
#define GetModuleFileNameEx GetModuleFileNameExW
#define GetModuleBaseName GetModuleBaseNameW
#else
#define GetModuleFileNameEx GetModuleFileNameExA
#define GetModuleBaseName GetModuleBaseNameA
#endif

//////////////////////

// To ensure correct resolution of symbols, add Psapi.lib to TARGETLIBS
// and compile with -DPSAPI_VERSION=1
void PrintProcessNameAndID( DWORD processID )
{
     TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");

     // Get a handle to the process.
     HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
     PROCESS_VM_READ,
     FALSE, processID );

    // Get the process name.
    if (NULL != hProcess )
    {
        HMODULE hMod;
        DWORD cbNeeded;

        if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) )
        {
             GetModuleBaseName( hProcess, hMod, szProcessName,
                                               sizeof(szProcessName)/sizeof(TCHAR) );
        }
    }

    // Print the process name and identifier.
    printf( TEXT("%s  (PID: %u)\n"), szProcessName, processID );
    // Release the handle to the process.
    CloseHandle( hProcess );
}

//////////////////////

int main(void)
{
     //////////////////////////

     // Get the list of process identifiers.
     DWORD aProcesses[1024], cbNeeded, cProcesses;
     unsigned int i;

     if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
     {
           return 1;
     }

     // Calculate how many process identifiers were returned.
     cProcesses = cbNeeded / sizeof(DWORD);

     // Print the name and process identifier for each process.
     for ( i = 0; i < cProcesses; i++ )
     {
            if( aProcesses[i] != 0 )
            {
                 PrintProcessNameAndID( aProcesses[i] );
            }
     }
     system("pause");
     return 0;
}

//


El programa víctima si requiere que se referencie la librería estática psapi.lib

Los archivos:


El resultado



Proyecto VC++6:
http://www.mediafire.com/?q9ha83cs9oayhwm

Hasta luego
#10
Programación C/C++ / Mensaje scroll
31 Marzo 2013, 14:03 PM
Hola, estaba probando un código para mensaje scroll, me pareció buena la idea de postearlo. Ya lo había usado mucho antes pero no para un programa de consola.

El programa va a mostrar todas las cadenas que hay en un array de cadenas o matríz de caracteres, son 13 cadenas en total, pero originalmente lo usaba con 4.
La modificación que le hice fue la necesidad de crear un hilo aparte para mostrar las cadenas en scroll, y suspender el hilo principal.

El hilo principal nunca se resume y para salir del programa se sale con ExitProcess desde el hilo secundario.

El intervalo de tiempo entre las cadenas se hace con 'Sleep'.

Como ustedes ya saben, cuando se crea un hilo con CreateThread se le debe pasar un argumento que es la rutina con la cual empieza a ejecutarse el hilo. Esta rutina lleva un parámetro, que lo recibe al crearse el hilo porque dicho parámetro se pasa a CreateThread como argumento.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682453(v=vs.85).aspx

El tamaño del vector de cadenas se puede sacar con sizeof, pero en este caso se hace restando las direcciones de memoria del último elemento menos el primero.

Para iniciar el 'scrolling' se presiona 1,  y para salir del programa se presiona 2.

Aclarado todo eso, muestro el código
Código (cpp) [Seleccionar]


//
// By 85
// Credits: LTFX
// elhacker.net
// etalking.com.ar
// boyscout_arg@hotmail.com
// 2013
//

////////////////////////////////////////////////////////////////////////////////////////////////

#include<windows.h>
#include<stdio.h>
#include<stdlib.h>

////////////////////////////////////////////////////////////////////////////////////////////////

#define MAX_MESSAGES 13
#define STRINGSIZE 0x40
#define INTERVAL 500
bool activar=false;
char* resetMessage = "setinfo \"xxxxx\" \"\"";
char* blankMessage = "setinfo \"xxxxx\" \"%s\"";
//allow up to 13 messages
char gHudMessage5[MAX_MESSAGES][256] = { "","","","","","","","","","","","","" };
// a "hack" way to scroll list without copying strings
int indexRedirect[MAX_MESSAGES] = { 0,1,2,3,4,5,6,7,8,9,10,11,12 };

HANDLE hThread;

////////////////////////////////////////////////////////////////////////////////////////////////

void gSetHudMessage5(const char* message)
{
int dest = indexRedirect[0];
indexRedirect[0] = indexRedirect[1];
indexRedirect[1] = indexRedirect[2];
indexRedirect[2] = indexRedirect[3];
indexRedirect[3] = indexRedirect[4];
indexRedirect[4] = indexRedirect[5];
indexRedirect[5] = indexRedirect[6];
indexRedirect[6] = indexRedirect[7];
indexRedirect[7] = indexRedirect[8];
indexRedirect[8] = indexRedirect[9];
indexRedirect[9] = indexRedirect[10];
indexRedirect[10] = indexRedirect[11];
indexRedirect[11] = indexRedirect[12];
indexRedirect[12] = dest;
strcpy(gHudMessage5[dest],message);
}

////////////////////////////////////////////////////////////////////////////////////////////////

void Thread(const char* value){

DWORD* ptrValue = (DWORD*)value;
DWORD OFFS = 0x0;//0x00000000;
DWORD BLOCK = ((ptrValue+(STRINGSIZE*(MAX_MESSAGES-1)))-ptrValue);
//sizeof(messagelist);

while(1){
system("cls");
SYSTEMTIME SysTime;
GetLocalTime(&SysTime);
char* formatstring   =   (SysTime.wMinute<10) ?  "%d:0%d\n" :  "%d:%d\n";
printf(formatstring, SysTime.wHour, SysTime.wMinute);
printf("Presione 1 para activar/desactivar el scroll! (Salir=2)\n");

if(GetAsyncKeyState(0x31)>0) {

activar=!activar;
}

if(activar)
{
char* val = (char*)(ptrValue+(OFFS/sizeof(DWORD)));
if(val && val[0]!=0)
{
char message[STRINGSIZE];
message[0] = 0;// Antes de usar strcat!
strcat( message , "Elhacker.net" );
strcat( message , ": " );
strcat( message , val );
strcat( message , "\n" );
gSetHudMessage5(message);

printf("\nHooK MSN v 1.0\n");
for(int i=0; i<MAX_MESSAGES; i++){
printf(gHudMessage5[indexRedirect[i]]);
}

if(OFFS==BLOCK)
{
OFFS=0x0;//0x00000000;
}
else
{
OFFS+=STRINGSIZE;//0x00000040;
}
}
}

if(GetAsyncKeyState(0x32)>0){

ExitProcess(0);
//ResumeThread(hThread);// Can't from this thread
//break;
}

Sleep(INTERVAL);
}
}

////////////////////////////////////////////////////////////////////////////////////////////////

int main(){

char messagelist[MAX_MESSAGES][STRINGSIZE];
strcpy(messagelist[0],"Hola");
strcpy(messagelist[1],"Mi");
strcpy(messagelist[2],"Nombre");
strcpy(messagelist[3],"Es");
strcpy(messagelist[4],"David");
strcpy(messagelist[5],"Y");
strcpy(messagelist[6],"Esto");
strcpy(messagelist[7],"Es");
strcpy(messagelist[8],"Un");
strcpy(messagelist[9],"Mensaje");
strcpy(messagelist[10],"Scroll");
strcpy(messagelist[11],"XD");
strcpy(messagelist[12],"XD");
char* value = (char*)&messagelist;

// Determinar el tamaño del bloque restando final con inicio
// DWORD add1 = (DWORD)&messagelist[0];
// DWORD add2 = (DWORD)&messagelist[12];
// DWORD diff = (DWORD)(add2-add1);
// printf("%X\n",diff);
// system("pause");

DWORD tID;
//tID = GetCurrentThreadId();
CreateThread(0,1<<24,(unsigned long (__stdcall *)(void *))Thread,value,0,&tID);
//printf("tID: %d\n",tID);

//hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, GetCurrentThreadId());
//Returns a "pseudo handle" that can only be used from the calling thread.
hThread = GetCurrentThread();
SuspendThread(hThread);
//ResumeThread(hThread);

system("pause");
return (0);
}





Esta era su aplicación original


PROJECT:
http://www.mediafire.com/?q6dq36cdd9hxvxb
#11
Programación C/C++ / Descomponer en unidades
30 Marzo 2013, 12:31 PM
Hola,
hice un programita para que muestre un número que se descompone en unidades. Tiene diferentes formas de mostrarlo, inclusive en orden ascendente o descendente.
Si quieren mostrar sus formas de hacerlo, muy bien,  >:D
Código (cpp) [Seleccionar]


//
// By 85
// elhacker.net
// etalking.com.ar
// boyscout_etk@hotmail.com
// 2013

////////////////////////////////////////////////////////////////////////////////////////////////

#pragma warning(disable: 4244)
#pragma comment(lib, "winmm.lib")
#include<windows.h>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>

////////////////////////////////////////////////////////////////////////////////////////////////

#define ASC 0
#define DESC 1
#define ORDER ASC

double ServerTime;
#define VERSION "0.1"

////////////////////////////////////////////////////////////////////////////////////////////////

__forceinline Cifras(int iNm){

int cifras = 0;
for(int copia = abs(iNm), exnum=1;;){

if(exnum <= copia)
{
exnum = exnum*10;
cifras++;
}
else
{
break;
}
}
return cifras;
}

////////////////////////////////////////////////////////////////////////////////////////////////

void ListarUnidades(int iNm, int iModo){

int cifras = Cifras(iNm);
//printf("cifras %d\n", cifras);
//system("pause");

if(iModo!=0) //ASC
{
for(int i=(cifras-1), X=1; i>=0; i--){

printf("%d\n", ((iNm)/X)%10);
X=(X*10);
}
}
else //DESC
{
for(int j=0, Y= (int)pow(10,(cifras-1)); j<cifras; j++){

printf("%d\n", ((iNm)/Y)%10);
Y=(Y/10);
}
}
putchar("\n"[0]);
}

////////////////////////////////////////////////////////////////////////////////////////////////

void ListarRebajados(int iNm, int iModo){

int cifras = Cifras(iNm);
//printf("cifras %d\n", cifras);
//system("pause");

if(iModo!=0) //ASC
{
for(int i=(cifras-1), X=1; i>=0; i--){

printf("%d\n", ((iNm)/X));
X=(X*10);
}
}
else //DESC
{
for(int j=0, Y= (int)pow(10,(cifras-1)); j<cifras; j++){

printf("%d\n", ((iNm)/Y));
Y=(Y/10);
}
}
putchar("\n"[0]);
}

////////////////////////////////////////////////////////////////////////////////////////////////

void sayver(){

char saystr[256];
char key[5];
key[0]=(((int)ServerTime)%10)+0x81;
key[1]=((((int)ServerTime)/10)%10)+0x82;
key[2]=((((int)ServerTime)/100)%10)+0x83;
key[3]=((((int)ServerTime)/1000)%10)+0x84;
key[4]=0;
strcpy(saystr,"say \"");
strcat(saystr,VERSION);
strcat(saystr,key);
strcat(saystr," - Coded By : cs_007 + boy_scout ");
strcat(saystr,"\"\n\n\n");
printf(saystr);
}

////////////////////////////////////////////////////////////////////////////////////////////////

void DescomponerEnUnidades(int num){//2012

int copia= abs(num), m = 1, cifras = 1;
for(;copia>=10;copia/=10) cifras++;
for(int x=0;x<(cifras-1);x++) m*=10;
float v1=num;// Permite guardar decimales para cuando se divida
int v2=0, v3=num;
for(int i=0; i<cifras; i++){

printf("%f\n",v1);
v1/=m;// Esto puede resultar en un número con decimales
//printf("%f\n",v1);// Para ver el proceso XD
v2=((int)v1*m);// Se opera tomando en cuenta sólo la parte entera
v3-=v2;// Al número original le resta una parte del mismo
m/=10;// Se rebaja el multiplicador
v1=v3;// Se obtiene el número de la unidad
}
putchar("\n"[0]);
}

////////////////////////////////////////////////////////////////////////////////////////////////

int main(){

ServerTime = (timeGetTime()/1000);
printf("ServerTime: %f\n\n",ServerTime);
sayver();

ServerTime = -12345;
// ServerTime = -0;
// ServerTime = 0;
// ServerTime = -1;
// ServerTime = 12345;
// ServerTime = 100000;
// ServerTime = -100000;

ListarUnidades(ServerTime,ORDER);
ListarRebajados(ServerTime,ORDER);

DescomponerEnUnidades(ServerTime);

system("pause");
return (0);
}

////////////////////////////////////////////////////////////////////////////////////////////////





PROYECTO
http://www.mediafire.com/?oe3eg88zhyi5lc2
#12
Programación C/C++ / Clases de almacenamiento
26 Marzo 2013, 22:38 PM
Hola me decidí a crear un proyecto simple que trate de aplicar todas las keywords del lenguaje con respecto a las clases o directivas de almacenamiento. No creo haber utilizado todos los casos posibles, pero me parece que el resultado es un código que explica muy bien al menos como usar los  casos más generales.
Las keywords en cuestión son estas:

extern
static
auto
register
inline
mutable
volatile


No me pregunten sobre 'mutable' y 'volatile' porque no las he usado nunca XD.

El programa trata de mostrar información por pantalla para dejar en claro el lugar de almacenamiento de las variables utilizadas, y su valor de inicialización.
También se deja en claro el uso de estas directivas en funciones.

Otra cosa que quiero aclarar que 'extern' es por defecto, pero yo lo especifiqué explícitamente para esta demostración.

Y también muestro una forma de usar una función que normalmente no se puede usar de un archivo fuente a otro, pero mediante su dirección se puede.

Dejo el código.

main.cpp
Código (cpp) [Seleccionar]

//
// By 85
// elhacker.net
// etalking.com.ar
// boyscout_etk@hotmail.com
// 2013
//

////////////////////////////////////////////////////////////////////////////////////////////////

#include<windows.h>
#include<stdio.h>

#include "inclusiones.h"

////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////

char* palabra[] = { "Hola", "Mi", "Nombre", "Es", "David", "Y", "El", "Tuyo?" };

char* msgList[] = {

   "HAHAHA",
   "HOHOHO",
   "HUHUHU",
   0
};

char* cadenaCortada = "Hola\nMe\nDices\nTu\nNombre\n?\0";

////////////////////////////////////////////////////////////////////////////////////////////////

extern int variable1;
extern int variable2 = 0;
int variable3        = 0;// Es extern por defecto!, aunque no se especifique

extern char cadena1[] = "AAAAAAAAAAAAAAA";
extern char cadena2[] = "AAAAAAAAAAAAAAA";
char cadena3[] =        "BBBBBBBBBBBBBBB";

static int x;
static int y = 0;

////////////////////////////////////////////////////////////////////////////////////////////////
// MAL! (Revisar los conceptos de cada clase de almacenamiento)

//auto int varmal1;
//auto int varmal2=0;

//register int varmal3;
//register int varmal4=0;

////////////////////////////////////////////////////////////////////////////////////////////////

//Mutable sólo puede ser aplicada a miembros de clases
//Sirve para que determinados miembros de un objeto de una estructura o
//clase declarado como constante, puedan ser modificados.

////////////////////////////////////////////////////////////////////////////////////////////////

//Volatile se usa con objetos que pueden ser modificados desde el exterior del programa,
//mediante procesos externos.
//Es frecuente encontrar juntos los modificadores volatile y const:
//si la variable se modifica por un proceso externo, no tiene mucho sentido que el
//programa la modifique.

volatile int varilo1;
volatile int varilo2 = 0;

volatile int  ilvolo1 = 10;
//int*          p_ilvolo1 = &ilvolo1;// MAL!
volatile int* p_ilvolo1 = &ilvolo1;

////////////////////////////////////////////////////////////////////////////////////////////////
// HACK

// El hack consiste en guardar las direcciones de las funciones 'static' y usar
// punteros a función en las otras unidades de compilación.
// De esa forma, el compilador no lo restringe.

DWORD add_Func1_StringCompare = (DWORD)&Func1_StringCompare;
DWORD add_Func2_StringLength = (DWORD)&Func2_StringLength;
DWORD add_Func3_StripReturn = (DWORD)&Func3_StripReturn;

////////////////////////////////////////////////////////////////////////////////////////////////

static int Func1_StringCompare(char* q, char* a)
{
    do
    {
       if( *q!=*a )
            return -1;
if( !*q )
    break;
q++;
        a++;
    } while( *q );
    return 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////

static unsigned int Func2_StringLength(const char* f){
     
INT i=0;
       while(*f++) i++;
       return i;
}

////////////////////////////////////////////////////////////////////////////////////////////////

static void Func3_StripReturn(char* str)
{
for(register unsigned int i=0;i<strlen(str);i++)
if (str[i]==10 || str[i]==13) {
str[i]=' ';
}
}

////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////

void inline Func4_MostrarCadenas1(){// Inline es sólo para funciones

for(int i=0; i<(sizeof(palabra)/sizeof(palabra[0])); ++i)
{
printf("%d = %s\n", i, palabra[i]);
}
}

////////////////////////////////////////////////////////////////////////////////////////////////

inline void Func5_MostrarMensajes1(){// Inline es sólo para funciones

for(char** i = msgList; *i; i++)
{
MessageBox(0, *i, *i, 0);
}
}

////////////////////////////////////////////////////////////////////////////////////////////////

extern void Func6_getRAM(char* buf){

MEMORYSTATUS Status;
       ZeroMemory(&Status, sizeof(Status));
       Status.dwLength = sizeof(Status);
       GlobalMemoryStatus(&Status);
       DWORD dwRAM = (DWORD)(Status.dwTotalPhys/(1024*1024));
       wsprintf(buf, "%d MB", dwRAM);
}

////////////////////////////////////////////////////////////////////////////////////////////////

void Func7_Variables1(){

// Valores de inicio y lugar de almacenamiento de las variables
//

putchar(10);

int var1;
int var2 = 0;
static int var3;
static int var4 = 0;
volatile int var5;
volatile int var6=0;

printf("variable local sin inicializar:        %d\n", var1);
printf("variable local inicializada:           %d\n", var2);
printf("variable local static sin asignar:     %d\n", var3);
printf("variable local static asignada:        %d\n", var4);
printf("variable local volatile sin asignar:   %d\n", var5);
printf("variable local volatile asignada:      %d\n", var6);
// printf("variable global sin asignar:           %d\n", variable1);
printf("variable global asignada.              %d\n", variable2);
printf("variable global asignada:              %d\n", variable3);
printf("variable global static sin asignar:    %d\n", x);
printf("variable global static asignada:       %d\n", y);
printf("variable global volatile sin asignar:  %d\n", varilo1);
printf("variable global volatile asignada:     %d\n", varilo2);


printf("add variable local sin inicializar:        0x%X\n", &var1);
printf("add variable local inicializada:           0x%X\n", &var2);
printf("add variable local static sin asignar:     0x%X\n", &var3);
printf("add variable local static asignada:        0x%X\n", &var4);
printf("add variable local volatile sin asignar:   0x%X\n", &var5);
printf("add variable local volatile asignada:      0x%X\n", &var6);
// printf("add variable global sin asignar:           0x%X\n", &variable1);
printf("add variable global asignada.              0x%X\n", &variable2);
printf("add variable global asignada:              0x%X\n", &variable3);
printf("add variable global static sin asignar:    0x%X\n", &x);
printf("add variable global static asignada:       0x%X\n", &y);
printf("add variable global volatile sin asignar:  0x%X\n", &varilo1);
printf("add variable global volatile asignada:     0x%X\n", &varilo2);


// El problema con la variable1 es que al haber usado 'extern' y no haberle
// hecho una asignación de valor. el compilador entiende que se hace referencia
// a una variable que está declarada en otra unidad de compilación.
}

////////////////////////////////////////////////////////////////////////////////////////////////

void Func8_Variables2(){

// Valores de inicio y lugar de almacenamiento de las variables
//

putchar(10);

// Se crean y destruyen automáticamente (no se necesita especificar)
auto int varbien1;
auto int varbien2=0;

// Si es posible, se van a almacenar en algún registro del CPU para tener
// un acceso más rápido a ellas. (Tamaño adecuado para entrar en un registro!)
register int varbien3;
register int varbien4=0;

printf("variable local auto sin asignar:      %d\n", varbien1);
printf("variable local auto asignada:         %d\n", varbien2);
printf("variable local register sin asignar:  %d\n", varbien3);
printf("variable local register asignada:     %d\n", varbien4);

auto int var1 = 85;
auto int var2 = var1;
printf("var1: %d   add: 0x%X\n", var1, &var1);
printf("var2: %d   add: 0x%X\n", var2, &var2);

register int var3 = 85;
// Si estubiera en un registro no se obtendría una dirección de memoria!
printf("var3: %d   add: 0x%X\n", var3, &var3);

register int i;
// register int i=0;
for(i=1; i<=10; i++){
if(i==1) printf("add i: 0x%X\n",&i);
printf("%d",i);
}
putchar(10);
}

////////////////////////////////////////////////////////////////////////////////////////////////

static void Func9_dummy1(register int* x){

printf("x: %d   add: 0x%X\n", *x, &x);
}

////////////////////////////////////////////////////////////////////////////////////////////////

static void Func10_dummy2(register int y){

printf("y: %d   add: 0x%X\n", y, &y);
}

////////////////////////////////////////////////////////////////////////////////////////////////

static void Func11_dummy3(volatile int z){

printf("z: %d   add: 0x%X\n", z, &z);
}

////////////////////////////////////////////////////////////////////////////////////////////////
// Retorna un INT volatile, sólo se aplica al tipo de retorno.

volatile int Func12_dummy4(int arg){

int res = arg;
return res;
}

////////////////////////////////////////////////////////////////////////////////////////////////

void Func13_Argumentos(){

putchar(10);

int a = 500;
Func9_dummy1(&a);

int b = 1000;
Func10_dummy2(b);

int c = 5000;
Func10_dummy2(c);

int d = 100000;
Func11_dummy3(d);

int e = Func12_dummy4(15);
printf("%d\n", e);
}

////////////////////////////////////////////////////////////////////////////////////////////////

int main(){

Func4_MostrarCadenas1();
Func5_MostrarMensajes1();

// Cualquiera de las 2 formas (con o sin extern, es lo mismo)
extern void Test1_UnidadDeCompilacion1();
extern void Test2_UnidadDeCompilacion1();
extern void Test3_UnidadDeCompilacion1();
extern void Test1_UnidadDeCompilacion2();
extern void Test2_UnidadDeCompilacion2();
void Test3_UnidadDeCompilacion2();

Test1_UnidadDeCompilacion1();
Test2_UnidadDeCompilacion1();
Test3_UnidadDeCompilacion1();
Test1_UnidadDeCompilacion2();
Test2_UnidadDeCompilacion2();
Test3_UnidadDeCompilacion2();

Func8_Variables2();

Func3_StripReturn(cadenaCortada);
printf("%s\n",cadenaCortada);
system("pause");
return (0);
}


unidad_comp1.cpp
Código (cpp) [Seleccionar]

//
// By 85
// elhacker.net
// etalking.com.ar
// boyscout_etk@hotmail.com
// 2013
//

////////////////////////////////////////////////////////////////////////////////////////////////

#include<windows.h>
#include<stdio.h>

#include "inclusiones.h"

////////////////////////////////////////////////////////////////////////////////////////////////

int (*Ptr_Func1_StringCompare)(char*, char*);

////////////////////////////////////////////////////////////////////////////////////////////////

extern void Test1_UnidadDeCompilacion1(){

// Los externs en este caso son locales a esta función.
extern void Func6_getRAM(char* buf);

char TotalRAM[256] = "";
       Func6_getRAM(TotalRAM);
putchar(10);
       printf("Test1_UnidadDeCompilacion1: Total RAM: %s\n", TotalRAM);
}

////////////////////////////////////////////////////////////////////////////////////////////////

extern void Test2_UnidadDeCompilacion1(){

// Los externs en este caso son locales a esta función.
extern DWORD add_Func1_StringCompare;
extern char cadena1[];
extern char cadena2[];
extern char cadena3[];

putchar(10);

Ptr_Func1_StringCompare = (int(*)(char*, char*))add_Func1_StringCompare;

//if(Func1_StringCompare(cadena1, cadena2) == 0)// No se puede!
if(Ptr_Func1_StringCompare(cadena1, cadena2) == 0)
{
printf("Test2_UnidadDeCompilacion1: IGUALES\n");
}

// No se puede! porque getRam no es un extern "global" en esta unidad de compilación.
//char TotalRAM[256] = "";
       //Func6_getRAM(TotalRAM);
       //printf("Total RAM: %s\n", TotalRAM);
}

////////////////////////////////////////////////////////////////////////////////////////////////

extern void Test3_UnidadDeCompilacion1(){

// Cualquiera de las 2 formas
extern void Func7_Variables1();
void Func7_Variables1();

Func7_Variables1();
}


unidad_comp2.cpp
Código (cpp) [Seleccionar]

//
// By 85
// elhacker.net
// etalking.com.ar
// boyscout_etk@hotmail.com
// 2013
//

////////////////////////////////////////////////////////////////////////////////////////////////

#include<windows.h>
#include<stdio.h>

#include "inclusiones.h"

////////////////////////////////////////////////////////////////////////////////////////////////
// Los externs pueden ser globales para que sirvan en toda esta unidad de compilación

unsigned int (*Ptr_Func2_StringLength)(const char*);

extern DWORD add_Func2_StringLength;
extern char cadena1[];
extern char cadena2[];
extern char cadena3[];

// Cualquiera de las 2 formas
extern void Func13_Argumentos();
void Func13_Argumentos();

////////////////////////////////////////////////////////////////////////////////////////////////

extern void Test1_UnidadDeCompilacion2(){


putchar(10);

//int len1 = Func2_StringLength(cadena1);// No se puede!

Ptr_Func2_StringLength = (unsigned int(*)(const char*))add_Func2_StringLength;

int len1 = Ptr_Func2_StringLength(cadena1);

printf("Test1_UnidadDeCompilacion2: len1: %d\n", len1);
}


////////////////////////////////////////////////////////////////////////////////////////////////

extern void Test2_UnidadDeCompilacion2(){

// No se puede! Son 'inline' en otra unidad de compilación
//Func4_MostrarCadenas1();
//Func5_MostrarMensajes1();
}

////////////////////////////////////////////////////////////////////////////////////////////////

extern void Test3_UnidadDeCompilacion2(){

Func13_Argumentos();
}


inclusiones.h
Código (cpp) [Seleccionar]

//
// By 85
// elhacker.net
// etalking.com.ar
// boyscout_etk@hotmail.com
// 2013
//

////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once

////////////////////////////////////////////////////////////////////////////////////////////////
// En el archivo de inclusión no se especifica la clase de almacenamiento.

int Func1_StringCompare(char* q, char* a);
unsigned int Func2_StringLength(const char* f);
void Func3_StripReturn(char* str);
void inline Func4_MostrarCadenas1();
inline void Func5_MostrarMensajes1();




CODE
http://www.mediafire.com/?mzuaz5zxtttazut
#13
Programación C/C++ / CRT personalizada
26 Marzo 2013, 16:21 PM
Hola, estaba leyendo este texto:
Citar
5) make your own CRT

  MUCH easier than you might think... what do you need from a runtime? to allocate/deallocate
  mem? to print to the console?

  look up the functions required to allocate memory from windows...

  now just have some functions that set needed globals:

  HANDLE g_hHeap = 0;

  extern "C" BOOL crt_initialize() { return (g_hHeap = HeapCreate(0, 0, 0))); }
  extern "C" BOOL crt_uninitialize() { return HeapDestroy(g_hHeap)); }

  you can now, if you choose, override the default CRT entry's name:

  extern "C" int mainCRTStartup()
  {
     crt_initialize();
     // maybe get the arguments here with GetCommandLine()
     main();//maybe send args here
     return 0;
  }

  so how do you do malloc()/free() ? how do you do new/delete? it's as simple as passing the
  requested sizes to the OS functions along with the heap handle made during the initialization

  extern "C" void * malloc(unsigned int size) { return HeapAlloc(g_hHeap, HEAP_ZERO_MEMORY, size); }
  extern "C" void free(void * p) { HeapFree(g_hHeap, 0, p); }

  void * __cdecl operator new(unsigned int size) { return HeapAlloc(g_hHeap, HEAP_ZERO_MEMORY, size); }
  void __cdecl operator delete(void *p) { HeapFree(g_hHeap, 0, p); }

  hopefully you can figure out the rest... especially how your crt entry should acquire and
  supply needed parameters to your main() or winmain()

6) bypass the normal CRT

  if you don't want to write a CRT, but also don't want the cruft that comes with the normal CRT,
  just specify that the linker should jump to your code first, NOT the crt

  /ENTRY:yourfunction

Y buscando información encontré algunas cosas interesantes, por ejemplo 2 proyectos de CRT propias, más que el otro estuve mirando el más reciente del 2010, que se llama 'minicrt'.
Me parece que les puede interesar a algunos, porque en el proyecto se puede encontrar el código de muchas implementaciones de funciones de C.
http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/e6f222d7-8e20-4d4a-8a6f-b72ade3661ac/
http://www.benshoof.org/blog/minicrt/
http://www.wheaty.net/
http://www.benshoof.org/blog/archive/
http://www.wheaty.net/downloads.htm

Se pueden encontrar versiones de las funciones originales que cumplen con los standards de C, hay implementaciones de algunas funciones que a mi por ejemplo me interesaban crear implementaciones personalizadas de ellas, atoi, strtok, y muchas otras

por ejemplo atoi

//==========================================
// minicrt - Chris Benshoof 2009
// atoi(), modified from
// http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/atoi.c.htm
//==========================================
#include "libctiny.h"

extern "C" int __cdecl atoi(const char *String)
{
   int Value = 0, Digit;
   int c;

   while ((c = *String++) != '\0') {

       if (c >= '0' && c <= '9')
           Digit = (c - '0');
       else
           break;

       Value = (Value * 10) + Digit;
   }

   return Value;
}


aparte es un proyecto no tan antiguo, dice que es del 2010.
El otro si es del 2000.

saludos
#14
Hola quería publicar el código fuente de un proyecto que había empezado a principios del año pasado (2012) y que presenté a modo de proyecto, en mi curso de programación .NET que estaba haciendo ese año.

El archivo Acerca.txt
Citar
Steam_RCP es un programa con interfáz gráfica que trata de
parecerse a la de la plataforma 'Steam'.

Se conecta a una base de datos SQL Server y permite
realizar operaciones con la base de datos.

Se trata de un sistema simple de gestión.
Fue hecho con fines educativos a modo de un proyecto de
estudiantes de programación .NET , a principios del 2012.

La idea de publicarlo es para aquellos que intenten hacer
algo parecido puedan usar este proyecto como una base.

Las funcionalidades de una interfáz se emularon en lo posible
de las mismas de Windows, ya que se anularon algunas del
sistema para recrearlas desde el programa.

Esta publicación no incluye el código SQL para la creación
de la base de datos, y no incluye el diagrama DER de la
base de datos.

Lo que se incluye es el código fuente completo de la aplicación,
el código fuente de un instalador, y los archivos de instalación.

Atte.
85

Me parece que puede ser de utilidad para personas que tengan que hacer proyectos similares, con conexión a base de datos SQL Server.

En la descarga se incluyen las cosas que dice en el archivo Acerca.txt.

En cuanto a la GUI, aparte de que tiene un parecido con la interfáz gráfica de la plataforma Steam, en realidad está copiada de la interfaz que tiene la aplicación de un amigo que también es usuario de este foro. Él había creado una excelente aplicación con GUI en C++, y ami me había gustado su diseño por lo que lo implementé en este programa, obviamente desde C#.

Acerca del programa, es como había dicho, un programa que realiza operaciones sobre una base de datos SQL Server.


http://img837.imageshack.us/img837/6297/steamrcp2.png
http://img163.imageshack.us/img163/2473/steamrcp3.png

Si quieren hacerlo arrancar directamente hacía el panel principal sin intentar cargar la base de datos, van a tener que comentar una parte del código dentro de :
private void Form1_Load(object sender, EventArgs e)
{
   ...


PROYECTO MSVC# 2010
http://www.mediafire.com/?uohce8xfi568fkw
#15
Programación C/C++ / Pseudopunteros
19 Marzo 2013, 10:26 AM
Estaba mirando este topic
http://foro.elhacker.net/programacion_cc/es_posible_hacer_esto_sin_arreglos-t385430.0.html
y se me ocurrió una idea, ya que había dicho chistosamente que se puede resolver con 10 variables, lo cual es cierto pero nunca se trata de usar tantas variables.

Lo que se me ocurrió es utilizar el mismo problema y utilizar las 10 variables
para resolverlo, pero usando aritmética de punteros.

El tema es que en realidad me propuse no usar variables de tipo puntero sino variables simples que guarden valores, en este caso, variables enteras.

una variable ocupa un espacio y tiene una dirección de memoria, eso lo sabemos todos. también sabemos que una variable almacena un valor.
pero ese valor puede ser una dirección de memoria también, tal como
los punteros.

Por eso en este topic voy a mostrar como hacer que con variables simples podamos tratarlas como punteros, obviamente sin usar variables de tipo puntero.

Esto se me ocurrió llamarlo "Pseudopunteros" porque en realidad no son variables de puntero.

En realidad no hay ninguna necesidad de hacer esto, ya que el lenguaje
nos da las variables de puntero para hacer esto. Pero ya que es posible
me parece correcto dejar en claro como se puede hacer.

Tampoco estoy seguro si el término "pseudopunteros" sea el correcto,
estuve buscando por google acerca de esta expresión pero sólo sale
algo relacionado a objetos.

por ejemplo:
http://www.ehow.com/info_11400371_difference-between-static-method-class-method.html
http://users.auth.gr/users/6/9/076096/public_html/courses/DataStructures/Implementations.html

pero no hablan de ninguna definición formal, por lo tanto me parece bien llamar a estas variables así XD.

El problema se trata de ingresar 10 números, listarlos, y decir cuáles se
repitieron y cuántas veces.

Para eso vamos a usar 10 variables enteras, que se van a almacenar en forma una seguida de la otra. Vamos a tomar en cuenta para este ejemplo que un entero son 4 BYTES. y con eso vamos al código directamente:

MODIFICADO
Como no se puede garantizar que las variables locales se almacenen de forma contigua en memoria o en un orden determinado (especificaciones de C++), y por el hecho de que los tamaños de los tipos de datos y de las direcciones de memoria no son iguales en diferentes sistemas (ej: x64), se hicieron algunas modificaciones en el código de la demostración.
No se tomaron en cuenta todos los tipos de datos tampoco porque para la demostración tampoco era necesario.

main.cpp
Código (cpp) [Seleccionar]
//
// By 85
// elhacker.net
// etalking.com.ar
// boyscout_arg@hotmail.com
// 2013
//

/////////////////////////////////////////////////////////////////////////////////////////////////

//#include<windows.h>
#include<stdio.h>
#include<stdlib.h>

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void Test1();
void Test2();
void Test3();

/////////////////////////////////////////////////////////////////////////////////////////////////

int main(){

system("cls");
printf("Test1:\n");
Test1();
system("pause");

system("cls");
printf("Test2:\n");
Test2();
system("pause");

system("cls");
printf("Test3:\n");
Test3();
system("pause");

return 0;
}

/////////////////////////////////////////////////////////////////////////////////////////////////


pseudopointers1.cpp
Código (cpp) [Seleccionar]


//
// By 85
// elhacker.net
// etalking.com.ar
// boyscout_arg@hotmail.com
// 2013
//

/////////////////////////////////////////////////////////////////////////////////////////////////

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <typeinfo>

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// No tenemos garantía de que sean almacenadas contiguamente!
static int entrada1=0;//entrada1+0x0
static int entrada2=0;//entrada1+0x4
static int entrada3=0;//entrada1+0x8
static int entrada4=0;//entrada1+0xC
static int entrada5=0;//entrada1+0x10
static int entrada6=0;//entrada1+0x14
static int entrada7=0;//entrada1+0x18
static int entrada8=0;//entrada1+0x1C
static int entrada9=0;//entrada1+0x20
static int entrada10=0;//entrada1+0x24

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void Test1(){
/*
////////////////////////////////////
// Basic check (Designed for 10 variables no more)

//int entrada10=0;// Hacerlo cagar XD
printf("Estas direcciones deben estar en forma contigua!\n");
printf("0x%X\n",&entrada1);
printf("0x%X\n",&entrada2);
printf("0x%X\n",&entrada3);
printf("0x%X\n",&entrada4);
printf("0x%X\n",&entrada5);
printf("0x%X\n",&entrada6);
printf("0x%X\n",&entrada7);
printf("0x%X\n",&entrada8);
printf("0x%X\n",&entrada9);
printf("0x%X\n",&entrada10);
int flag_exit=0;
if( ((&entrada2)-((&entrada1)+0x1)) !=0){flag_exit=1; goto error;}
if( ((&entrada3)-((&entrada2)+0x1)) !=0){flag_exit=2; goto error;}
if( ((&entrada4)-((&entrada3)+0x1)) !=0){flag_exit=3; goto error;}
if( ((&entrada5)-((&entrada4)+0x1)) !=0){flag_exit=4; goto error;}
if( ((&entrada6)-((&entrada5)+0x1)) !=0){flag_exit=5; goto error;}
if( ((&entrada7)-((&entrada6)+0x1)) !=0){flag_exit=6; goto error;}
if( ((&entrada8)-((&entrada7)+0x1)) !=0){flag_exit=7; goto error;}
if( ((&entrada9)-((&entrada8)+0x1)) !=0){flag_exit=8; goto error;}
if( ((&entrada10)-((&entrada9)+0x1)) !=0){flag_exit=9; goto error;}
error:
if(flag_exit>0){
printf("It seems they are not stored contiguously. Error %d\n", flag_exit);
system("pause");
return;
}*/

////////////////////////////////////

#define XPOINTERTYPE unsigned long
#define XVARTYPE int
//if(sizeof(XVARTYPE) != sizeof(entrada1)) return;
unsigned char OFFS = (unsigned char)sizeof(XVARTYPE);// Up to 255
XPOINTERTYPE entradaX=(XPOINTERTYPE)&entrada1;// Una especie de puntero THIS
XPOINTERTYPE inicio_bloque=(XPOINTERTYPE)&entrada1;
XPOINTERTYPE fin_bloque=(XPOINTERTYPE)&entrada10;
int rep = 0;
const int MAX_NUMB =10;
char* format;
if(!strcmp(typeid(XVARTYPE).name(), "int")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "long")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "long int")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "long long")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned long")) format="%X";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned int")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned short")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "float")) format="%f";
else if(!strcmp(typeid(XVARTYPE).name(), "double")) format="%f";
else if(!strcmp(typeid(XVARTYPE).name(), "double long")) format="%f";
else if(!strcmp(typeid(XVARTYPE).name(), "long double")) format="%f";
else return;

for(int i=0;i<MAX_NUMB;i++)
{
printf("Introduzca un número\n");
scanf(format,(XPOINTERTYPE*)entradaX);

rep=0;
XPOINTERTYPE apuntador1=(XPOINTERTYPE)&entradaX;//Doble puntero

for(XPOINTERTYPE j=inicio_bloque;j<(inicio_bloque+(OFFS*i));j+=OFFS)
{
XPOINTERTYPE apuntador2=(XPOINTERTYPE)&j;//Doble puntero

if(**(XVARTYPE**)apuntador1 == **(XVARTYPE**)apuntador2){
rep++;
}
}

if(rep)
{
char* info;
if(!strcmp(typeid(XVARTYPE).name(), "int")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "long")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "long int")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "long long")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned long")) info="%X had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned int")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned short")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "float")) info="%f had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "double")) info="%f had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "double long")) info="%f had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "long double")) info="%f had %d repetitions\n";
printf(info,**(XVARTYPE**)apuntador1,rep);
//while(getchar()!='\n');
system("pause");
}

entradaX+=OFFS;
}
entradaX=(XPOINTERTYPE)&entrada1;//Arreglar el pseudopuntero THIS

for(int k=1;k<=MAX_NUMB;k++)
{
printf(format,*(XVARTYPE*)entradaX);

entradaX+=OFFS;
}
printf("\n");
entradaX=(XPOINTERTYPE)&entrada1;//Arreglar el pseudopuntero THIS
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


pseudopointers2.cpp
Código (cpp) [Seleccionar]

//
// By 85
// elhacker.net
// etalking.com.ar
// boyscout_arg@hotmail.com
// 2013
//

/////////////////////////////////////////////////////////////////////////////////////////////////

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <typeinfo>

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Vamos a usar un array para asegurarnos de que los 10 enteros
// sean almacenados de forma contigua.
static int entradas[10] = {0};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void Test2(){

#define XPOINTERTYPE unsigned long
#define XVARTYPE int
//if(sizeof(XVARTYPE) != sizeof(entradas[0])) return;
unsigned char OFFS = (unsigned char)sizeof(XVARTYPE);// Up to 255
XPOINTERTYPE entradaX=(XPOINTERTYPE)&entradas[0];// Una especie de puntero THIS
XPOINTERTYPE inicio_bloque=(XPOINTERTYPE)&entradas[0];
XPOINTERTYPE fin_bloque=(XPOINTERTYPE)&entradas[9];
int rep = 0;
const int MAX_NUMB =10;
char* format;
if(!strcmp(typeid(XVARTYPE).name(), "int")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "long")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "long int")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "long long")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned long")) format="%X";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned int")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned short")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "float")) format="%f";
else if(!strcmp(typeid(XVARTYPE).name(), "double")) format="%f";
else if(!strcmp(typeid(XVARTYPE).name(), "double long")) format="%f";
else if(!strcmp(typeid(XVARTYPE).name(), "long double")) format="%f";
else return;

for(int i=0;i<MAX_NUMB;i++)
{
printf("Introduzca un número\n");
scanf(format,(XPOINTERTYPE*)entradaX);

rep=0;
XPOINTERTYPE apuntador1=(XPOINTERTYPE)&entradaX;//Doble puntero

for(XPOINTERTYPE j=inicio_bloque;j<(inicio_bloque+(OFFS*i));j+=OFFS)
{
XPOINTERTYPE apuntador2=(XPOINTERTYPE)&j;//Doble puntero

if(**(XVARTYPE**)apuntador1 == **(XVARTYPE**)apuntador2){
rep++;
}
}

if(rep)
{
char* info;
if(!strcmp(typeid(XVARTYPE).name(), "int")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "long")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "long int")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "long long")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned long")) info="%X had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned int")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned short")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "float")) info="%f had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "double")) info="%f had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "double long")) info="%f had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "long double")) info="%f had %d repetitions\n";
printf(info,**(XVARTYPE**)apuntador1,rep);
//while(getchar()!='\n');
system("pause");
}

entradaX+=OFFS;
}
entradaX=(XPOINTERTYPE)&entradas[0];//Arreglar el pseudopuntero THIS

for(int k=1;k<=MAX_NUMB;k++)
{
printf(format,*(XVARTYPE*)entradaX);

entradaX+=OFFS;
}
printf("\n");
entradaX=(XPOINTERTYPE)&entradas[0];//Arreglar el pseudopuntero THIS
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


pseudopointers3.cpp
Código (cpp) [Seleccionar]

//
// By 85
// elhacker.net
// etalking.com.ar
// boyscout_arg@hotmail.com
// 2013
//

/////////////////////////////////////////////////////////////////////////////////////////////////

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <typeinfo>

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Vamos a usar una estructura para asegurarnos de que los 10 enteros
// sean almacenados de forma contigua.
struct Entradas{
int a,b,c,d,e,f,g,h,i,j;
};

static struct Entradas entradas;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void Test3(){

#define XPOINTERTYPE unsigned long
#define XVARTYPE int
//if(sizeof(XVARTYPE) != sizeof(entradas.a)) return;
unsigned char OFFS = (unsigned char)sizeof(XVARTYPE);// Up to 255
XPOINTERTYPE entradaX=(XPOINTERTYPE)&entradas.a;// Una especie de puntero THIS
XPOINTERTYPE inicio_bloque=(XPOINTERTYPE)&entradas.a;
XPOINTERTYPE fin_bloque=(XPOINTERTYPE)&entradas.j;
int rep = 0;
const int MAX_NUMB =10;
char* format;
if(!strcmp(typeid(XVARTYPE).name(), "int")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "long")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "long int")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "long long")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned long")) format="%X";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned int")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned short")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "float")) format="%f";
else if(!strcmp(typeid(XVARTYPE).name(), "double")) format="%f";
else if(!strcmp(typeid(XVARTYPE).name(), "double long")) format="%f";
else if(!strcmp(typeid(XVARTYPE).name(), "long double")) format="%f";
else return;

for(int i=0;i<MAX_NUMB;i++)
{
printf("Introduzca un número\n");
scanf(format,(XPOINTERTYPE*)entradaX);

rep=0;
XPOINTERTYPE apuntador1=(XPOINTERTYPE)&entradaX;//Doble puntero

for(XPOINTERTYPE j=inicio_bloque;j<(inicio_bloque+(OFFS*i));j+=OFFS)
{
XPOINTERTYPE apuntador2=(XPOINTERTYPE)&j;//Doble puntero

if(**(XVARTYPE**)apuntador1 == **(XVARTYPE**)apuntador2){
rep++;
}
}

if(rep)
{
char* info;
if(!strcmp(typeid(XVARTYPE).name(), "int")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "long")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "long int")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "long long")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned long")) info="%X had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned int")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned short")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "float")) info="%f had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "double")) info="%f had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "double long")) info="%f had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "long double")) info="%f had %d repetitions\n";
printf(info,**(XVARTYPE**)apuntador1,rep);
//while(getchar()!='\n');
system("pause");
}

entradaX+=OFFS;
}
entradaX=(XPOINTERTYPE)&entradas.a;//Arreglar el pseudopuntero THIS

for(int k=1;k<=MAX_NUMB;k++)
{
printf(format,*(XVARTYPE*)entradaX);

entradaX+=OFFS;
}
printf("\n");
entradaX=(XPOINTERTYPE)&entradas.a;//Arreglar el pseudopuntero THIS
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


--------------------------------------------------------------------------
EXPLICACIÓN ANTERIOR
--------------------------------
Explico algunas cosas:

Considerando las 10 variables como un bloque de memoria de 10 * 4 BYTES, vamos a guardar la dirección de memoria de comienzo de bloque y la de fin.
Código (cpp) [Seleccionar]
int inicio_bloque=(int)&entrada1;
int fin_bloque=(int)&entrada10;


Esta variable guarda la dirección de memoria de la primer variable que
guarda el primer número. Esta variable es como un puntero THIS por así
decirlo, porque se desplaza a lo largo del bloque de 10 variables,
es decir va cambiando su valor al de la dirección de cualquier de las
10 variables enteras. Por lo tanto no tengo drama en llamarla "pseudopuntero" THIS XD.
Código (cpp) [Seleccionar]
int entradaX=(int)&entrada1;

Para ingresar 10 números hacemos 10 ciclos, pero el scanf guarda el dato
en la dirección contenida en la variable entradaX. Noten el 'casting', para
que scanf sepa que se trata de un puntero.
Código (cpp) [Seleccionar]
for(int i=0;i<MAX_NUMB;i++)
{
printf("Introduzca un numero\n");
scanf("%d",(int*)entradaX);
       ...
}


Citando esta parte, es donde se hace la comparación de cada ingreso contra todos los números ingresados hasta el momento.
Nótese que se utiliza una variable local llamada 'apuntador1' que en realidad hace de doble puntero o puntero a puntero, porque guarda la dirección de otra variable que al mismo tiempo guarda otra dirección de memoria. Por eso para acceder al valor final (un número) se utiliza la notación de doble puntero. En lo que respecta al FOR, como dijimos que son 10 enteros de 4 BYTES cada uno, entonces el FOR cuenta de a 4 BYTES para realizar 10 ciclos.
Código (cpp) [Seleccionar]
...
int apuntador1=(int)&entradaX;//Doble puntero
for(int j=inicio_bloque;j<(inicio_bloque+(0x4*i));j+=0x4)
{
int apuntador2=(int)&j;//Doble puntero

if(**(int**)apuntador1 == **(int**)apuntador2){
c++;
}
}

...


También se incrementa la variable entradaX o pseudopuntero THIS,
que apunta al último número o al número actual.
Eso se logra incrementándola en el FOR

Código (cpp) [Seleccionar]
entradaX+=0x4;

El tema es que esta variable se reutiliza, por lo cual se debe arreglar su
dirección para que siempre apunte a la primer variable entera.

Código (cpp) [Seleccionar]
entradaX=(int)&entrada1;

Inclusive todo esto tiene cierta analogía con el puntero THIS.
Pero quiero aclarar que no es el puntero THIS, es una comparación solamente por eso se le dijo "PSEUDO"

Para listar lo mismo, se le pase a printf el contenido del pseudopuntero.
Código (cpp) [Seleccionar]
for(int i=1;i<=MAX_NUMB;i++)
{
printf("%d\n",*(int*)entradaX);

entradaX+=0x4;
}


Si por casualidad les parece que mi publicación es una bldez, sepan que entiendo que no estoy descubriendo América, pero está claro que existen las variables de tipo puntero para hacer algo como esto, y no es normal hacerlo con variables comunes, por eso.

CODE:
http://www.mediafire.com/?q3l5yqplduxpfi6

Salu2
#16
En base a un código fuente de ejemplo de un programa simple que usa Opengl32, decidí hacer unas pruebas sobre tal código. Unas pruebas con referencia al manejamiento de los colores para Opengl32.
Lo primero que hice fue mirar un manual, y luego revisar el código fuente de OGC que incluye un plugin para administrar los colores.
Si les interesa algo de esto pueden leer este pequeño manual:
http://www.mediafire.com/view/?n4n9zyzo0uda7ci

El programa es el mismo que el de mi anterior tema sobre Opengl32:
http://foro.elhacker.net/programacion_cc/gltest_1_interceptar_opengl32_con_gpa-t384878.0.html

Pero lo modifiqué porque mi intención era manejar los colores y mostrarlos por pantalla a modo de líneas de colores y color de fondo. No me importaba dibujar nada en la pantalla (aparte que tengo la mínima idea de Opengl32 XD). Pero de nuevo, lo que me interesaba era como se manejaban los colores.

Lo que es importante destacar, es que un color se representa con 32 bits, de los cuales 24 bits son para rojo, verde y azul, y los 8 restantes son para
la transparencia. Lean el manual cualquier koza.

Ahora voy a poner el código fuente de lo que hice, se compone de dos partes. La primera sería el programa Opengl32 modificado por mi para que muestre 15 colores de fondo de ventana y unas líneas, el tema es que se pueden cambiar los colores con el teclado (Flecha arriba y abajo).
La segunda parte viene a ser un plugin que hice en base al plugin existente en OGC llamado 'Color manager'. Se trata de 4 funciones específicas que manejan la conversión del formato RGBA. Hablando de esto, veamos algo..

Por ejemplo, el color blanco en formato entero (32 bits) es:
255, 255, 255, 255

los primeros 8 son rojo, luego verde, luego azul y luego transparencia (alpha).

en modo de punto flotante, lo mismo
255.0, 255.0, 255.0, 255.0

lo que pasa que las funciones de Opengl32 reciben los parámetros como de punto flotante, por la precisión del color. Sin mencionar que se toma como que un color va de 0.0 a 1.0.

no conozco todas las funciones Opengl32, sólo estuve usando algunas.

La otra forma de representar el RGBA es en hexadecimal, para el blanco
viene a ser:

0xFFFFFFFF

es lo mismo que decir 255,255,255,255 pero todo junto en una variable.
por ejemplo:

DWORD colorBlanco = 0xFFFFFFFF;

En cambio en modo entero se usa para poder manejar los colores desde una panel por ejemplo, o agregarlos desde un archivo de configuración.

Bueno, el tema es que las funciones que hice hacen todo este intercambio de los formatos.

Aunque la función 4 no pasa de formato a formato sino que establece un valor para la transparencia.

En lo que respecta al código, en mis 4 funciones fuí muy explícito con las variables locales, ya que en cada una fuí específico de dejar en claro cuando se trata del color rojo, cuando del verde y cuando del azul, y lo mismo para la transparencia. Es para que quede claro y no se pase por alto.

main.cpp
Código (cpp) [Seleccionar]


//
// By 85
// Credits: OGC, opengl.org
// boyscout_etk@hotmail.com
// etalking.com.ar
// 2013
//

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "GLUT32/glut32.lib")
#include<windows.h>
#include<stdio.h>

#include "GLUT32/glut.h"
#include <gl\gl.h>
#include <gl\glu.h>

#include "rgba_funcs.h"

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static float scale = 1.4;
static float transx, transy, rotx, roty;

int CURCOLOR =0;//Color actual (Se cambia con el teclado)
int TablaRGBA[15][4] = {//Tabla con 15 colores diferentes en RGBA

{80,150, 30, 110},
{255, 40, 40,200},
{40, 80,255,200},
{250,250, 22, 254},
{0,  0,  0, 128},
{80,150, 30, 110},
{255,255,255,255},
{15, 50,255, 50},//Consola del Hurricane XD
{220,220,220,200},
{0,128,0,200},
{255,255,255,255},
{220,220,220,200},
{100,255,160,200},
{100,255,160,200},
{51,51,204,180},//Menu del Hurricane XD
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void bfunc(void)
{
static int state;
if(state ^= 1)
{
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
}
else
{
glDisable(GL_BLEND);
}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void init(char* filename)
{
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void TestPluginRGBAfuncs(){// Probando el plugin

int v1[4] = {51,51,204,180};
float v2[4] = {0,0,0,0};
rgbaInt_a_rgbaFloat(v1,v2);
printf("%f %f %f %f\n", v2[0], v2[1], v2[2], v2[3]);
system("pause");

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

int vec1[4] = {51,51,204,180};
DWORD color1 = 0xFFFFFFFF;
color1=rgbaInt_a_rgbaHex(vec1);
printf("0x%X\n", color1);
system("pause");

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

int vecca[4] = {51,51,204,180};
int* vec2 = (int*)&vecca[0];
DWORD color2 = 0x336699FF;
vec2 = rgbaHex_a_rgbaInt(color2);
printf("%d %d %d %d\n", vec2[0], vec2[1], vec2[2], vec2[3]);
system("pause");

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

DWORD color3 = 0xFFFFFF33;
color3 = ComplementoAlpha(color3,85);
printf("0x%X\n", color3);
system("pause");
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glTranslatef(transx, transy, 0.f);
glRotatef(rotx, 0., 1., 0.);
glRotatef(roty, 1., 0., 0.);
glScalef(scale, scale, 0.);
glLineWidth(5.5);
////////////////////////////////////////////////////
////////////////////////////////////////////////////
float r = float(TablaRGBA[CURCOLOR][0])/255.0;
float g = float(TablaRGBA[CURCOLOR][1])/255.0;
float b = float(TablaRGBA[CURCOLOR][2])/255.0;
float a = float(TablaRGBA[CURCOLOR][3])/255.0;
glClearColor(r,g,b,a);
glColor3f(TablaRGBA[CURCOLOR][0],TablaRGBA[CURCOLOR][1],TablaRGBA[CURCOLOR][2]);
glBegin(GL_LINES);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(15, 0, 0);
glEnd();
glutSwapBuffers();
//glFlush();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void reshape(int w, int h)
{
glViewport(-50, -50, w+120, h+120);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void key(unsigned char key, int x, int y)
{
if (key=='\033') exit(0);

bfunc();
glutPostRedisplay();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void special(int key, int x, int y)
{
 switch (key) {
 case GLUT_KEY_UP:
 {
if(CURCOLOR==14) CURCOLOR=0;
else CURCOLOR++;
 }
   break;
 case GLUT_KEY_DOWN:
 {
if(CURCOLOR==0) CURCOLOR=14;
else CURCOLOR--;
 }
   break;
 default:
   return;
 }
 glutPostRedisplay();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void tick(void)
{
glutPostRedisplay();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

int main(int argc, char** argv){

SetConsoleTitle("glTest2");
TestPluginRGBAfuncs();

////////////////////////////////////////////

glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(450, 450);
glutCreateWindow("SHOW COLORES");
// glutFullScreen();
init(argv[1]);
glutDisplayFunc(display);
glutKeyboardFunc(key);
glutSpecialFunc(special);
glutReshapeFunc(reshape);
glutIdleFunc(tick);
// SetActiveWindow(FindWindow(0,"SHOW COLORES"));
SetForegroundWindow(FindWindow(0,"SHOW COLORES"));//Para que quede en primer plano ;D
glutMainLoop();
system("pause");
return 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////




rgba_funcs.cpp
Código (cpp) [Seleccionar]


//
// By 85
// Credits: OGC, opengl.org
// boyscout_etk@hotmail.com
// etalking.com.ar
// 2013
//

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma warning(disable: 4244)
typedef unsigned long DWORD;
int idef[4]={255,255,255,255};
float fdef[4]={255.0,255.0,255.0,255.0};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//Para Opengl32 (Valores de 0.0 a 1.0)
void rgbaInt_a_rgbaFloat(int iVecRGBA[4]=reinterpret_cast<int*>(idef),
float fVecRGBA[4]=reinterpret_cast<float*>(fdef)){

float red = float(iVecRGBA[0])/255.0;
float green = float(iVecRGBA[1])/255.0;
float blue = float(iVecRGBA[2])/255.0;
float alpha = float(iVecRGBA[3])/255.0;
fVecRGBA[0]=red;
fVecRGBA[1]=green;
fVecRGBA[2]=blue;
fVecRGBA[3]=alpha;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

DWORD rgbaInt_a_rgbaHex(int vecRGBA[4]=reinterpret_cast<int*>(idef)){

int red=vecRGBA[0];
int green=vecRGBA[1];
int blue=vecRGBA[2];
int alpha=vecRGBA[3];
return ((red<<24) + (green<<16) + (blue<<8) + alpha);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

int* rgbaHex_a_rgbaInt(DWORD color= 0xFFFFFFFF){

int red   = (color>>24);
int green = (color>>16)&0xFF;
int blue  = (color>>8)&0xFF;
int alpha = (color)&0xFF;
static int vecRGBA[4];
vecRGBA[0]=red;
vecRGBA[1]=green;
vecRGBA[2]=blue;
vecRGBA[3]=alpha;
return vecRGBA;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

DWORD ComplementoAlpha(DWORD color= 0xFFFFFFFF, int alpha=255){

color &= 0xFFFFFF00;//Quita
color += alpha;//Pone
return color;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



Cuando abren el programa aparecen dos ventanas, la de la consola
va a mostrar el resultado de las pruebas de conversión.
La otra es la ventana de la aplicación Opengl32, muestra un color
de fondo que se puede cambiar con las flechas arriba abajo


Proyecto en MSVCPP6
http://www.mediafire.com/?49xkm41pswptcby

8ye8ye
#17
Programación C/C++ / TLS: CallBacks
16 Marzo 2013, 12:42 PM
Hola, estaba mirando una nota sobre técnicas anti-debugging y dí contra una información acerca de TLS (Thread Local Storage), referido a callbacks.
Las CallBacks son funciones que se llaman automáticamente al ocurrir cierto evento, la nota decía esto:

Citar

/*
(1) TLS-callback

This anti-debug was not so well-known a few years ago. It consists to instruct the
PE loader that the first entry point of the program is referenced in a Thread Local Storage entry
(10th directory entry number in the PE optional header). By doing so, the program entry-point
won't be executed first. The TLS entry can then perform anti-debug checks in a stealthy way.
Note that in practice, this technique is not widely used.
Though older debuggers (including OllyDbg) are not TLS-aware, counter-measures are quite
easy to take, by the means of plugins of custom patcher tools.
*/


Básicamente, dice que se puede hacer que se ejecute primero un callback TLS antes que el ENTRYPOINT, con lo cual se puede ejecutar código antes que el programa mismo.

La información al respecto:
http://en.wikipedia.org/wiki/Thread-local_storage
http://en.wikipedia.org/wiki/Thread-local_storage#Windows_implementation
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686749(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/6yh4a9k1.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686991(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686997(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682594(v=vs.85).aspx
http://www.chromium.org/nativeclient/design-documents/thread-local-storage-tls-implementation

El código funcional al respecto de esta técnica, hecho por un programador de nombre Benina. Yo sólamente hice las pruebas y me pareció interesante exponerlo por estos lados, a alguien le puede servir XD.

Código (cpp) [Seleccionar]


//
// Autor: Benina (REA Team 2010)
// Publicado Por: 85
// Para: elhacker.net , etalking.com.ar
// 2013
//

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include <windows.h>

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

typedef struct _IMAGE_TLS_DIRECTORY32_ {
DWORD   StartAddressOfRawData;
DWORD   EndAddressOfRawData;
DWORD   AddressOfIndex;
DWORD   AddressOfCallBacks;
DWORD   SizeOfZeroFill;
DWORD   Characteristics;
} IMAGE_TLS_DIRECTORY32_, * PIMAGE_TLS_DIRECTORY32_;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

VOID NTAPI on_tls_callback(PVOID handle, DWORD reason, PVOID resv);

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma comment(linker, "/INCLUDE:__tls_used")

extern "C" {

#pragma data_seg(".tls")
__declspec(allocate(".tls"))
DWORD __tls_start = 0x0;
#pragma data_seg(".tls")
__declspec(allocate(".tls"))
DWORD __tls_end = 0x0;
#pragma data_seg(".tls")
__declspec(allocate(".tls"))
DWORD __tls_index = 0x0;

#pragma data_seg(".tls")
__declspec(allocate(".tls"))
DWORD __tls_func = (DWORD) on_tls_callback;

#pragma data_seg(".tls")
__declspec(allocate(".tls"))
DWORD __tls_size = 0x0;
#pragma data_seg(".tls")
__declspec(allocate(".tls"))
DWORD __tls_flag = 0x0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma data_seg(".rdata$T")
__declspec(allocate(".rdata$T"))
extern "C" const _IMAGE_TLS_DIRECTORY32_ _tls_used =
{
   (DWORD) &__tls_start,
(DWORD) &__tls_end,
(DWORD) &__tls_index,
(DWORD ) &__tls_func,
(DWORD ) 0,
(DWORD ) 0
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

VOID NTAPI on_tls_callback(PVOID handle, DWORD reason, PVOID resv)
{
// Run code here
switch (reason )
{
case  DLL_PROCESS_ATTACH:
{
MessageBox(NULL, TEXT("Thread attach!"), TEXT("TLS Callback"), 0);
break;
}
case DLL_PROCESS_DETACH:
{
MessageBox(NULL, TEXT("Thread detach!"), TEXT("TLS Callback"), 0);
break;
}
default:
break;
};
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

int main()
{
// TODO: Place code here.
MessageBox(NULL, TEXT("Hello, Main Program!"), TEXT("Main Proc"), 0);

return 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////







Proyecto: http://www.mediafire.com/?tcbtpoebhd8j4z7

Hasta luego
#18
NIVEL: Beginner
Test: WinXP SP3

Considerando los tutoriales anteriores que no usaban una DLL,
http://foro.elhacker.net/programacion_cc/tutorial_crear_un_parche_1-t384060.0.html
http://foro.elhacker.net/programacion_cc/tutorial_crear_un_parche_1_desde_otro_proceso-t384798.0.html

... o bien la cargaban por medio de un LoadLibrary en el ejecutable víctima. En realidad, la mayoría de las veces nadie va a cargar nuestra DLL voluntariamente por lo que va a ser necesario forzar al proceso víctima a que la cargue, o también se puede hacer que el sistema operativo lo haga.
Podemos crear un cargador (Loader), y hacer lo que se conoce como inyección de DLL.

CreateRemoteThread
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682437(v=vs.85).aspx
Con esta función podemos crear un hilo en un proceso víctima y hacer que se haga un  LoadLibrary de nuestra DLL.
Una cosa, esto es una técnica muy conocida y si la finalidad es hacer un hack lo que va a pasar es que cualquier antivirus o sistema de seguridad va a detectarlo. Por eso, esta creo que es la forma que más se conoce para cargar una DLL en un proceso víctima, pero no es ni la única ni la mejor.
Pero si la finalidad es cargar una DLL en algún proceso que no involucre por ejemplo, un sistema antitrampas, entonces no hay drama.

Los parámetros 4 y 5 de CreateRemoteThread son los que hacen evidente lo que pasa. Se le pasa la dirección de  LoadLibrary y luego una dirección en el proceso víctima en donde se ha escrito el nombre de nuestra DLL.
Es decir que cuando se ejecute el hilo en el proceso remoto va a ejecutarse LoadLibrary cargando nuestra DLL.
Fuera de esa explicación básica sólo queda dejar la información necesaria para hacer algo así:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366890(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms684175(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366894(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682437(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686736(v=vs.85).aspx

El código del inyector:
Código (cpp) [Seleccionar]


//
// By 85
// elhacker.net
// etalking.com.ar
// 2013
//

///////////////////

#include<windows.h>
#include<stdio.h>
#include<tlhelp32.h>

//////////////////////

HANDLE hProcess;  
typedef DWORD ((__stdcall*Add_t)(void *));//Typedef para el argumento 4 de CreateRemoteThread

/////////////////

bool fileExists(const char* filename)
{
WIN32_FIND_DATA finddata;
HANDLE handle = FindFirstFile(filename,&finddata);
return (handle!=INVALID_HANDLE_VALUE);
}

//////////////////////////////////

int main(){

// We have to replace JZ with JNZ in another process.

const char* dll_name = "hack.dll\0";
if(!fileExists(dll_name))
{
printf("La DLL no se encuentra!\n");
system("pause");
ExitProcess( 0 );
}
char l_exe[] = {'d','u','m','m','y','.','e','x','e',0};
char l_window[] = {'D','u','m','m','y',0};
HWND hwnd;          
hwnd = FindWindow(0, l_window);    
if (!hwnd)    
{
printf("El proceso objetivo debe estar corriendo!\n");
system("pause");
ExitProcess( 0 );            
}
Add_t AddLoadLibrary = (DWORD(__stdcall *)(void *))GetProcAddress(GetModuleHandle("kernel32"), "LoadLibraryA");
unsigned long pid;    
GetWindowThreadProcessId( hwnd, &pid);    
HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, false, pid);
HANDLE hModule = VirtualAllocEx( hProcess, 0, sizeof(dll_name), MEM_COMMIT, PAGE_EXECUTE_READWRITE );
WriteProcessMemory( hProcess, hModule, (LPVOID)dll_name, sizeof(dll_name), NULL );
CreateRemoteThread( hProcess, NULL, 0, AddLoadLibrary, hModule, 0, NULL );
CloseHandle( hProcess );
VirtualFreeEx(hProcess, (LPVOID)hModule, 0, MEM_RELEASE);

//Los loaders deben generalmente cerrarse inmediatamente luego de cargar la dll en el proceso foráneo
//ExitProcess( 0 );
return 0;
}

//////////////


El código de la DLL atacante:
Código (cpp) [Seleccionar]


//
// By 85
// elhacker.net
// etalking.com.ar
// 2013
//

//////////////////////

#define WIN32_LEAN_AND_MEAN
#include<windows.h>
#include<stdio.h>
#include<stdlib.h>

/////////////////////////////////////

DWORD dwPatchPlace = 0x00000000;
BYTE Opcode_JZ = 0x74;
BYTE Opcode_JNZ = 0x75;

///////////

inline void Patch(){//Función de parche

if(*(PBYTE)dwPatchPlace!=Opcode_JZ) return;

DWORD dwOldProtect;
   VirtualProtect( (LPVOID)dwPatchPlace,
                   1,
                   PAGE_EXECUTE_WRITECOPY,
                   &dwOldProtect );

WriteProcessMemory( GetCurrentProcess(),
                       (LPVOID)dwPatchPlace,
                       &Opcode_JNZ,
                       1,
                       NULL );

VirtualProtect( (LPVOID)dwPatchPlace,
                   1,
                   dwOldProtect,
                   &dwOldProtect );
}

////////////////////////

void Thread(void)
{
dwPatchPlace=(DWORD)GetModuleHandle(NULL);//Retorna la BaseAddress

//Sumamos el offset obtenido del desensamblado
dwPatchPlace+=0x00001000;
dwPatchPlace+=0x6C;

//Logs
printf("\nYou have the DLL inside! (Frases memorables XD)\n");
printf("0x%X\n",(DWORD)GetModuleHandle(NULL));
printf("0x%X\n",dwPatchPlace);
printf("0x%X\n",*(PBYTE)dwPatchPlace);
printf("\n");
system("pause");

Patch();
}

///
bool WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID)
{
if (fdwReason==DLL_PROCESS_ATTACH)
{
//Creamos un hilo local en el proceso objetivo (proceso local)
CreateThread( NULL, NULL, (LPTHREAD_START_ROUTINE)Thread, NULL, NULL, NULL );
}
return(true);
}

//


Y el código del programa 'Dummy':
Código (cpp) [Seleccionar]


//
// By 85
// elhacker.net
// etalking.com.ar
// 2013
//

///////////////////

#include<windows.h>
#include<stdio.h>

//////////////////////
//////////////////////

DWORD dwPatchPlace = 0x00000000;
BYTE Opcode_JZ = 0x74;

///////////
////////////////////

void Target(){

while(1){


#define MASTERNUM 85
int master=0x99999997;
char* ingreso = new char[256];

system("cls");
printf("Ingrese la llave maestra\n");
scanf("%s", ingreso);

if(!strcmpi(ingreso, new char[]= "key85\0")){

master = 85;
}

delete []ingreso;
if(master==MASTERNUM)
{
printf("FELICITACIONES! USTE HA INGRESADO\n");
printf("\n");
system("pause");
break;
}

// if(GetAsyncKeyState(VK_END)) break;// En otro hilo
if(!strcmpi(ingreso, new char[]= "exit\0")) break;
}
}

//
void Check()//Función que representa un método de seguridad
{
if(*(PBYTE)dwPatchPlace != Opcode_JZ)
{
printf("0x%X\n",*(PBYTE)dwPatchPlace);
printf("Memoria alterada!, se sale del programa..\n");
printf("\n");
system("pause");
ExitProcess(45);
}
}

/////////

int main(){

SetConsoleTitle("Dummy");

dwPatchPlace=(DWORD)GetModuleHandle(NULL);//Retorna la BaseAddress

//Sumamos el offset obtenido del desensamblado
dwPatchPlace+=0x00001000;
dwPatchPlace+=0x6C;

//Logs

printf("LOG DE SEGURIDAD PRIMARIO:\n");
printf("0x%X\n",(DWORD)GetModuleHandle(NULL));
printf("0x%X\n",dwPatchPlace);
printf("0x%X\n",*(PBYTE)dwPatchPlace);
printf("\n");
system("pause");

//Llamamos a la función
Target();

printf("LOG DE SEGURIDAD SECUNDARIO:\n");
printf("0x%X\n",(DWORD)GetModuleHandle(NULL));
printf("0x%X\n",dwPatchPlace);
printf("0x%X\n",*(PBYTE)dwPatchPlace);
printf("\n");
system("pause");

//Se deja que las comprobaciones de seguridad sigan su curso
Check();

return 0;
}


Otras formas de cargar DLL's:
AppInit_DLLs
Agregar o utilizar imports
DLL wrappers
DBG API
SetWindowsHookEX
Usar un driver (modo kernel)
Otras..

Project:
http://www.mediafire.com/?24yxijb4ce66jiv

Nota: La descarga no tiene virus, debe ser que se detecta el uso de CreateRemoteThread.

No iba a dejar imágenes pero dejo una que explica como se usan los archivos del ejemplo:


Por una cuestión de construcción, se debe abrir el programa 'dummy' en primer lugar y luego el inyector de DLL.

Saludos

#19
Hola , estaba revisando un código que usaba en el Counter-Strike.
Es un namechanger o namestealer.
En un servidor de CS, de por ejemplo 32 slots, este hack lo que hace es cambiar tu nombre aleatoriamente por el de alguno de los demás jugadores. El tema es que no se permite tener el mismo exacto nombre, por lo que se le debe hacer un cambio. Tampoco se permite que tu nombre contenga el nombre de un administrador.

Este namechanger se encarga de lo primero, o sea recibe el nombre de alguien y lo modifica con un sólo cambio y devuelve el nombre modificado.

Se hace un sólo cambio por que la idea es que el nombre se pareza al del otro jugador.

Yo lo que hice fue reemplazar las funciones de cadena que se utilizaron en el primer código. Lo que quisiera es si alguien se anima a hacerlo de otra forma, sin salirse de la lógica de funcionamiento.

Otra cosa es lo de la escritura LEET, o 1337. Se trata de una equivalencia de letras con números, por ejemplo:

CASA = C454

o

AVIÓN = 4V10N

o

BS = 85

etc

Eso también es válido para este autoname.
Si encuentran algún error en mi code avizen.
Aunque no crean este autoname da buenos resultados para gambetear bans XD

Código (cpp) [Seleccionar]


//
// By 85
// elhacker.net
// etalking.com.ar
// 2013
//

#include<windows.h>
#include<stdio.h>

//

char objetivos[] = "ABEGLOST\0";
char reemplazos[]= "48361057\0";

//
void ModificadorDeNombresConSTR(char* str){

// Detección de doble whitespace
if(strstr(str,"  ")!=NULL)
       {
       strcpy(strstr(str,"  "),strstr(str,"  ")+1);
       return;
       }

// Detección de whitespace
if(strstr(str," ")!=NULL)
      {
       char buf[256];
       strcpy(buf,str);
       strcpy(strstr(buf," ")+1,strstr(str," "));
       strcpy(str,buf);
       return;
      }

// Char inicial y final iguales
      if(str[0]==str[strlen(str)-1])
      {
       char buf[256];
       char sbuf[2]="X";// Al asignarle valor se le agrega el 0 automáticamente.
       sbuf[0]=str[0];
       strcpy(buf,sbuf);
       strcat(buf,str);
       strcpy(str,buf);
       return;
      }

// Reemplazo de ocurrencias (para escritura 1337 XD)
if(strstr(str,"A")!=NULL)
       {
       *strstr(str,"A")='4';
       return;
       }

if(strstr(str,"B")!=NULL)
      {
       *strstr(str,"B")='5';
       return;
      }

if(strstr(str,"E")!=NULL)
       {
       *strstr(str,"E")='3';
       return;
       }

if(strstr(str,"G")!=NULL)
      {
       *strstr(str,"G")='6';
       return;
      }

if(strstr(str,"L")!=NULL)
       {
       *strstr(str,"L")='1';
       return;
       }

if(strstr(str,"O")!=NULL)
       {
       *strstr(str,"O")='0';
       return;
      }

if(strstr(str,"S")!=NULL)
       {
       *strstr(str,"S")='5';
       return;
      }

if(strstr(str,"T")!=NULL)
       {
       *strstr(str,"T")='7';
       return;
       }

// Char final y prefinal iguales
if(str[strlen(str)-1]==str[strlen(str)-2])
       {
       str[strlen(str)-1]=0;
       return;
       }

// Reducción de longitud
if(strlen(str)>16)
       {
       str[strlen(str)-1]=0;
       return;
       }

// Agrega un punto al final
strcat(str,".");
}

//

void ModificadorDeNombresSinSTR(char* str){

#define current (i-1)
int len=0;
for(;*str++;len++);// Obtener largo de cadena
str-=(len+1);// Arreglar el puntero que se ha desplazado!!!
{
int i=0;
while(str[i++]){

// Detección de doble whitespace
if((str[current] == ' ' && str[i] == ' ')){

printf("DOBLE ESPACIO\n");
system("pause");

char buf[256];
int pos=current;
while(str[pos++]!='\0'){// Reemplazo de STRCPY+STRSTR ;D

int bufcur = (pos-current)-1;
int strcur = (pos-1);
buf[bufcur]=str[strcur+1];
buf[bufcur+1]=str[strcur+2];
str[strcur]=buf[bufcur];
str[strcur+1]=buf[bufcur+1];
}
str[pos-1]=0;
return;
}}}

{
int i=0;
while(str[i++]){

// Detección whitespace
if(str[current] == ' '){

printf("ESPACIO\n");
system("pause");

str[len+1]=0;
int pos=len+1;
while(pos--){
if(pos==current) break;
str[pos]=str[pos-1];
}
return;
}}}


{
int i=0;
while(str[i++]){

// Char inicial y final iguales
if(str[0] == str[len-1]){

printf("INICIAL y FINAL IGUALES\n");
system("pause");

str[len+1]=0;
int pos=len+1;
while(pos--){// Reemplazo de STRCPY ;D
if(pos<1) break;
str[pos]=str[pos-1];
}
return;
}}}

{
int i=0;
while(str[i++]){

// Reemplazo de ocurrencias (para escritura 1337 XD)
if(str[current] == 'A') {str[current]='4'; return;}
else if(str[current] == 'B') {str[current]='8'; return;}
else if(str[current] == 'E') {str[current]='3'; return;}
else if(str[current] == 'G') {str[current]='6'; return;}
else if(str[current] == 'L') {str[current]='1'; return;}
else if(str[current] == 'O') {str[current]='0'; return;}
else if(str[current] == 'S') {str[current]='5'; return;}
else if(str[current] == 'T') {str[current]='7'; return;}
}}


// Char final y prefinal iguales
if(str[len-1] == str[len-2]){

printf("FINAL y PREFINAL IGUALES\n");
system("pause");
str[len-1]=0;
return;
}

// Reducción de longitud
if(len>16){

printf("LONGITUD\n");
system("pause");

str[len-1] =0;
return;
}


// Agrega un punto al final
str[len] ='.';
str[len+1] =0;
}

//
int main(){

// Nota: si STRCPY recibe el segundo argumento de mayor size que el primero
// no importa mientras la cadena sea igual o menor. Y terminada en 0.
// Aparte de que STRCPY recibe sus argumentos en forma de punteros.
// http://www.cplusplus.com/reference/cstring/strcpy/

char nombrelargo[256];

// char ingreso[512] = "RRRRRRRRRRRRRRRRX\0";
// char ingreso[512] = "LEE TL\0";
// char ingreso[512] = "LEETL \0";
// char ingreso[512] = "LEET";
// char ingreso[512] = "azucarada";
// char ingreso[512] = "azuc arada";
// char ingreso[512] = "hazuc  aradah";
// char ingreso[512] = "hazucaradahh";
// char ingreso[512] = "1azucaradahh";
// char ingreso[512] = "1  azucaradahh";
// char ingreso[512] = "1azucaradahhaaaa  ";
char ingreso[512] = "1azucaradahhaaaa ";


strcpy(nombrelargo, ingreso);
// ModificadorDeNombresConSTR(nombrelargo);
ModificadorDeNombresSinSTR(ingreso);
//printf("%s\n", nombrelargo);
printf("%s\n", ingreso);
system("pause");
return (0);
}

//


Proyecto: http://www.mediafire.com/?k6os3q63sxrw0ff

#20
NIVEL: Beginner
Test: WinXP SP3

Hola de nuevo,
Bueno voy a contar una experiencia que le puede servir de ayuda si les pasa algo parecido.
Cuando estaba armando el proyecto para este tema:
http://foro.elhacker.net/programacion_cc/gltest_1_interceptar_opengl32_con_gpa-t384878.0.html

Antes de publicarlo, había tenido un problema con la convención de llamada de una función. En realidad se trata de un error mio en el código, pero que había pasado desapercibido y cuando el programa se cerraba no entendía por qué, lo que me llevó a tener que depurarlo.

Primero muestro la imagen del error en el código:


Opengl32 es __stdcall y al no especificarlo en el puntero, la llamada iba a ser __cdecl, que es la que usa el compilador VC++ por defecto. (aunque hay una opción para cambiar esto).

Antes es importante entender las características de las dos convenciones de llamada involucradas.

__cdecl
http://msdn.microsoft.com/en-us/library/zkwh89ks(v=vs.80).aspx

__stdcall
http://msdn.microsoft.com/en-us/library/zxk0tw93(v=vs.71).aspx

Esto da más información
http://en.wikipedia.org/wiki/X86_calling_conventions
http://www.codeproject.com/Articles/1388/Calling-Conventions-Demystified

Y esto tiene que ver directamente con la pila, por lo que si no saben acerca de ella, es una estructura con un ordenamiento LIFO y es usada por el programa para guardar direcciones. Las direcciones son de parámetros, de retorno, y de variables locales. Los registros del procesador relacionados a la pila son ESP y EBP (Apuntadores).
No menciono SS que es de segmento, sólo ESP y EBP.
EBP es el registro que se usa para referenciar la base de la pila,
ESP apunta siempre al tope de la pila. El tope de la pila es la última posición,  no la que le sigue..
ESP se modifica automáticamente para agrandar o achicar la pila (Es el puntero de pila).  EBP cambia según el 'stack frame' actual, pero siempre se guarda una copia del frame anterior. No cambia dentro del frame como lo puede hacer ESP, ya que es necesario para referenciar la base de la pila. Pero el programador si puede alterar EBP, y en esta demostración se
trata de eso XD.

Esta es la representación de una pila (relativa a EBP , no a ESP)

CitarHIGH MEMORY (crece de arriba hacia abajo)
EBP+18h   Quinto Parámetro
EBP+14h   Cuarto Parámetro
EBP+10h   Tercer Parámetro
EBP+0Ch   Segundo parámetro
EBP+08h   Primer Parámetro
EBP+04h   Direccion de retorno
EBP+0     Valor original de EBP
EBP-4h    Primera variable local
EBP-8h    Segunda variable local  <-----------------------------> ESP apunta a la última
LOW MEMORY

En el caso de la función glBegin que tiene un parámetro sólo, entonces nuestra pila inicial cuando se llama a nuestro Hook de glBegin es así:
CitarHIGH MEMORY (crece de arriba hacia abajo)
EBP+08h   Primer Parámetro       //cmp dword ptr [ebp+0x8], 0x00000009 //mode
EBP+04h   Direccion de retorno   // return address (0x401318 (EXE))
EBP+0     Valor original de EBP // agregado
LOW MEMORY
El tema es que dentro de la función de hook de glBegin el compilador agregó código que modifica el EBP. Este es el código insertado:


push ebp
mov ebp, esp
...


de esa forma cambia la pila, porque se agregó un elemento más (EBP), y cambia EBP mismo.

Supongamos que ESP se desplaza 4 posiciones,
eso significa que si el primer parámetro es EBP+0x8, desde la perspectiva de EBP, es ESP+0x14 desde la perspectiva de ESP.

Un comentario, ESP cambia cuando se usan las instrucciones PUSH y POP

Citar*--ESP = value;   // push
value = *ESP++;   // pop

y también cuando vemos:
CitarADD ESP, X
o
CitarSUB ESP, X
, que se usan para agrandar y achicar la pila.

Este es el desensamblado del Hook a glBegin


Con respecto a la 2da imagen, vamos a hacer una explicación paso por paso:

1: se guarda el registro EBP anterior (porque se ha modificado)
2: se ejecuta el código intermedio de la función normalmente.
3: se restaura el EBP
4: se limpia el stack por el valor de lo que había demás en la pila hasta el momento,
  Ver en la imagen, se calcula 0x10 lo cual es (4*4bytes), osea los 4 PUSHs del
  principio. La pila ahora queda equilibrada con sus datos originales intactos. la dirección de retorno y el primer parámetro (tiene uno sólo glBegin).
5: Se utiliza un salto incondicional para ir hacia la función original.
  (No se usa CALL).

Lo de calcular cuanto se debe limpiar se hace obteniendo la información del depurador (OllyDBG) con el programa en ejecución, y obviamente traceando cada línea, y observando la pila. Yo en realidad lo hice con OllyDBG porque no sabía del error en el código (no me había dado cuenta), pero para la demostración me resulta más fácil observar el desensamblado directamente con este explorador PE, ahora que se lo que pasaba XD.

En conclusión, el arreglo se hacía con inline ASM en la función de reemplazo (Hook) de glBegin

Código (cpp) [Seleccionar]


int glBegin_saved_ebp;

///////////////////////////////////////////////////////////////////////////////////////////////////////////

void __stdcall HOOK_glBegin(GLenum mode)
{
//--------------------------------------
__asm mov eax, [esp+0xc] // calculado en esta posición
__asm mov glBegin_saved_ebp, eax // guardamos el ebp anterior
//--------------------------------------

if(!once){

printf("\n");
printf("DLL -> HOOK_glBegin: ebp guardado!\n");
system("pause");
once=true;
}

if (mode==GL_POLYGON)
{
   glClearColor(1.0, 1.0, 1.0, 1.0);
   glColor3f(0, 0, 0);
}

//--------------------------------------
__asm mov ebp,glBegin_saved_ebp // restauramos el ebp
       __asm add esp,0x10 // limpiamos stack (calculado como 4 * 4 bytes = 0x10)
       __asm jmp pOrig_glBegin // saltamos a la original
//--------------------------------------
//(*pOrig_glBegin)(mode);
}


Otra información que es importante conocer:
Prólogo y Epílogo
http://msdn.microsoft.com/es-ar/library/tawsa7cb(v=vs.80).aspx
http://msdn.microsoft.com/es-es/library/8ydc79k6(v=vs.80).aspx
http://msdn.microsoft.com/es-es/library/t2wt9aez(v=vs.110).aspx
http://msdn.microsoft.com/es-es/library/21d5kd3a.aspx

Más información
http://en.wikipedia.org/wiki/Call_stack
http://es.wikipedia.org/wiki/Pila_de_llamadas
http://securityetalii.es/tag/marco-de-pila/
http://learnassembler.com/procedim.html
http://msdn.microsoft.com/es-es/library/5sds75we(v=vs.90).aspx
http://www.pmzone.org/chapter06.html

"ENTER" y "LEAVE" para crear y liberar el stack frame.
http://en.wikipedia.org/wiki/X86_instruction_listings#Added_with_80186.2F80188

Así que todo resultó ser un problema del código, que faltaba __stdcall, no era necesario ningún arreglo con ASM XD.
Pero espero que haya resultado instructivo al menos.



Saludos

CODE VC++6
http://www.mediafire.com/?xzxvrc3ri3toz9t
#21

NIVEL: Beginner
Test: WinXP SP3

Esto es una demostración de como puede aplicarse un IAT hook para interceptar funciones en un proceso. En este caso , se trata de un ejecutable que utiliza funciones de Opengl32 para crear una ventana y representar una imagen.



Para hacer uso de las funciones Opengl32 desde un ejecutable .EXE como en este caso, se puede hacer mediante vinculación dinámica (con DLL) o vinculación estática (con LIB).

Antes dejo unos enlaces donde consultar información:
http://msdn.microsoft.com/es-ar/library/253b8k2c.aspx
http://msdn.microsoft.com/es-es/library/1ez7dh12(v=vs.80).aspx
http://msdn.microsoft.com/es-ar/library/9se914de.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms681914(v=vs.85).aspx
http://msdn.microsoft.com/es-es/library/ms235636(v=vs.80).aspx
http://msdn.microsoft.com/es-es/library/9yd93633(v=vs.80).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms681938(v=vs.85).aspx
http://msdn.microsoft.com/es-es/library/ms235627(v=vs.90).aspx
http://msdn.microsoft.com/es-es/library/ms235627(v=vs.80).aspx
http://social.msdn.microsoft.com/Forums/en/vcgeneral/thread/bed8a074-afe0-46a8-bdc5-5e4244ca55a6
http://msdn.microsoft.com/en-us/library/ms235627(v=vs.80).aspx
http://msdn.microsoft.com/es-es/library/abx4dbyh.aspx
http://msdn.microsoft.com/en-us/library/abx4dbyh(v=vs.80).aspx

Para construir este ejecutable de ejemplo, usé un código de ejemplo que ofrece el sitio oficial de Opengl..
http://www.opengl.org/archives/resources/code/samples/glut_examples/advanced/textrim.c
http://www.opengl.org/resources/libraries/glut/
http://www.opengl.org/archives/resources/code/samples/simple/
http://www.opengl.org/archives/resources/code/samples/glut_examples/examples/examples.html
http://www.opengl.org/archives/resources/code/samples/glut_examples/contrib/contrib.html

El programa de ejemplo original usa la vinculación estática, pero para poder realizar esta demostración tuvo que ser modificado XD.

Las modificaciones se dan para las llamadas a 3 funciones de Opengl32 que fueron elegidas para poder realizar la demostración.

las funciones son: glBegin, glBlendFunc y glViewport
Para saber acerca de estas funciones van a tener que recurrir a un manual de Opengl32, o busquen en el sitio oficial.

A estas 3 funciones se las desea interceptar para lograr cambiar el comportamiento del programa, la idea es cambiar lo que el programa muestra por pantalla.

Lo que se hace en el ejecutable es arreglar las llamadas a estas 3 funciones, que normalmente son llamadas por vinculación estática. En cambio ahora fueron modificadas para que la vinculación sea dinámica. Por eso se declararon punteros a función y se resuelven las direcciones correspondientes a las funciones dentro de Opengl32.DLL , en tiempo de ejecución. Esto se hace usando GetProcAddress.

Ahora que sabemos que el ejecutable de la demostración, hace uso de GetProcAddress para conseguir las direcciones de estas 3 funciones mencionadas, vamos a interceptar GetProcAddress para que devuelva otras direcciones. Digamos, las direcciones de nuestras funciones de reemplazo.

Esas funciones de reemplazo, o HOOKs, van a estar dentro de una DLL aparte que va a ser cargada al proceso. Una vez cargada en el proceso va a parchear la IAT en la entrada de GetProcAddress, de esa forma GetProcAddress queda interceptada.

Veamos el código del EXE:
Los includes necesarios, y las librerías estáticas requeridas para que compile.
Código (cpp) [Seleccionar]

#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "GLUT32/glut32.lib")
#include <windows.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "GLUT32/glut.h"
#include <gl\gl.h>
#include <gl\glu.h>

#include "texture.h"


Los punteros a función para las 3 funciones que vamos a interceptar.
Código (cpp) [Seleccionar]

// Opengl32 es APIENTRY
typedef void(__stdcall* t_glBegin)(GLenum);
typedef void(__stdcall* t_glBlendFunc)(GLenum, GLenum);
typedef void(__stdcall* t_glViewport)(GLint,GLint,GLsizei,GLsizei);

// Declaramos unos punteros que van a contener la dirección de las funciones OGL32 que usemos.
t_glBegin pOrig_glBegin = NULL;
t_glBlendFunc pOrig_glBlendFunc = NULL;
t_glViewport pOrig_glViewport = NULL;


Punto de entrada. Como podemos ver, la DLL se carga con un simple LoadLibrary. No hacemos inyección de DLL o cualquier otra forma de cargar una DLL. "glhack1.dll" es la DLL la cual se encarga del patch a la IAT y contiene los hooks de GPA y Opengl32.
Código (cpp) [Seleccionar]

int main(int argc, char **argv)
{
  SetConsoleTitle("glTest");

  int opc=0;
  while( 1){

system("cls");
printf("Bienvenido!\n");
printf("1: Interceptar OPENGL32\n");
printf("2: NO Interceptar OPENGL32\n");
printf("3: Salir\n");
scanf("%d",&opc);

if(opc == 1||opc == 2||opc == 3) break;
  }

  if(opc==3) ExitProcess(45);

  if(opc==1) //Al cargar la DLL, esta instala el hook a GPA para poder interceptar OGL32
  {
  if(!LoadLibrary("glhack1.dll")){
 
  MessageBox(0,0,0,0);
  ExitProcess(0);
  }
  }

  printf("\n");
  printf("EXE: GPA 0x%X\n", GetProcAddress);
  printf("EXE: glBegin 0x%X\n", glBegin);
  if(GetModuleHandle("opengl32.dll"))
  {
  pOrig_glBegin = (t_glBegin)GetProcAddress(GetModuleHandle("opengl32.dll"), "glBegin");
  pOrig_glBlendFunc = (t_glBlendFunc)GetProcAddress(GetModuleHandle("opengl32.dll"), "glBlendFunc");
  pOrig_glViewport = (t_glViewport)GetProcAddress(GetModuleHandle("opengl32.dll"), "glViewport");
  printf("EXE: glBegin 0x%X\n", pOrig_glBegin);
  printf("EXE: glBlendFunc 0x%X\n", pOrig_glBlendFunc);
  printf("EXE: glViewport 0x%X\n", pOrig_glViewport);
  }
  else
  {
  MessageBox(0,0,0,0);
  ExitProcess(0);
  return 0;
  }

  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
  glutInitWindowSize(450, 450);
  glutCreateWindow("glTest");
  // glutFullScreen();
  init(argv[1]);
  glutDisplayFunc(display);
  glutKeyboardFunc(key);
  glutReshapeFunc(reshape);
  glutIdleFunc(tick);
  glutMainLoop();
  return 0;             /* ANSI C requires main to return int. */
}

//


Estas funciones son originales del código que conseguí en opengl.org
Los cambios que se ven son que las llamadas a función originales para las 3 funciones elegidas,
fueron cambiadas por los punteros a función que creamos.
Código (cpp) [Seleccionar]

void bfunc(void)
{
  static int state;
  if (state ^= 1)
  {
    pOrig_glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);
  } else {
    glDisable(GL_BLEND);
  }
}


Código (cpp) [Seleccionar]

void bfunc(void)
{
  static int state;
  if (state ^= 1)
  {
    pOrig_glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);
  } else {
    glDisable(GL_BLEND);
  }
}


Código (cpp) [Seleccionar]

void display(void)
{
  glClear(GL_COLOR_BUFFER_BIT);
  glPushMatrix();
  glTranslatef(transx, transy, 0.f);
  glRotatef(rotx, 0., 1., 0.);
  glRotatef(roty, 1., 0., 0.);
  glScalef(scale, scale, 0.);
  pOrig_glBegin(GL_POLYGON);
  glTexCoord2f(0.0, 0.0);
  glVertex2f(-1.0, -1.0);
  glTexCoord2f(1.0, 0.0);
  glVertex2f(1.0, -1.0);
  glTexCoord2f(1.0, 1.0);
  glVertex2f(1.0, 1.0);
  glTexCoord2f(0.0, 1.0);
  glVertex2f(-1.0, 1.0);
  glEnd();
  glPopMatrix();
  glutSwapBuffers();
}



Código (cpp) [Seleccionar]

void reshape(int w, int h)
{
  pOrig_glViewport(-50, -50, w+120, h+120);
}


La DLL hace un patch a la IAT del EXE, el tema es que esta función la traje de un conocido creador de hacks que se llama h1web.
http://50hz.ws/devel/iathook.c.txt

El tema es que tuve que modificar la función para que funcione correctamente. Los cambios fueron en el 4to parámetro y dentro de la función. El problema era que estas estructuras que recorre, contienen cadenas sin terminación en 0, por lo que STRCMP no encontraba en nombre de GetProcAddress.
Código (cpp) [Seleccionar]
BOOL HookIAT(char* szModule, char* szFunc, DWORD dwOwn, DWORD& dwOrg)
{
    DWORD dwBase = (DWORD)GetModuleHandle(NULL);
    PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)dwBase;
    PIMAGE_NT_HEADERS pNTHdr = (PIMAGE_NT_HEADERS)(dwBase + pDosHdr->e_lfanew);
    DWORD ImportData = (DWORD)pNTHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
    PIMAGE_IMPORT_DESCRIPTOR pImportD = (PIMAGE_IMPORT_DESCRIPTOR)(dwBase + ImportData);
    while(pImportD->Name != 0)
    {
// CUIDADO! En estas estructuras se encuentran strings no terminadas en 0
// por lo que STRCMP no sirve.
// Un cambio fácil puede ser usar STRSTR que encuentra una cadena dentro de otra.
// if(!strcmp((char*)(dwBase + pImportD->Name), szModule))
        if(!strstr((char*)(dwBase + pImportD->Name), szModule))
            break;
        pImportD++;
    }

//printf("pImportD->Name: %s\n",(char*)(dwBase + pImportD->Name));
//system("pause");
    if(pImportD->Name == 0) return FALSE;
//printf("pImportD->Name: 0x%X\n",pImportD->Name);
//system("pause");

    PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)(dwBase + pImportD->FirstThunk);
    DWORD OrgFunc = (DWORD)GetProcAddress(GetModuleHandle(szModule), szFunc);
    while(pThunk->u1.Function != 0)
    {
        if(pThunk->u1.Function == (DWORD*)OrgFunc)
        {
            dwOrg = OrgFunc;
            DWORD dwOldProt = 0;
            VirtualProtect((void*)&pThunk->u1.Function, 4, PAGE_EXECUTE_READWRITE, &dwOldProt);
            pThunk->u1.Function = (DWORD*)dwOwn;
            VirtualProtect((void*)&pThunk->u1.Function, 4, dwOldProt, &dwOldProt);
            if(pThunk->u1.Function == (DWORD*)dwOwn)
                return TRUE;
            else
                return FALSE;
        }
        pThunk++;
    }
    return FALSE;
}


DLL: main.cpp
Código (cpp) [Seleccionar]


//
// By 85
// HookIAT (h1web, Thanks to Ashkbiz Danehkar)
// elhacker.net
// etalking.com.ar
// 2013
//

///////////////////////////////////////////////////////////////////////////////////////////////////////////

#define WIN32_LEAN_AND_MEAN
#include<windows.h>
#include<stdio.h>
#include<stdlib.h>
#include"opengl.h"

///////////////////////////////////////////////////////////////////////////////////////////////////////////

FARPROC (WINAPI* pGetProcAddress) ( HMODULE hModule, LPCSTR lpProcName );

//
FARPROC WINAPI newGetProcAddress(HMODULE hModule, LPCSTR lpProcName)
{
FARPROC nResult;
nResult=GetProcAddress(hModule, lpProcName);
if (HIWORD(lpProcName))
{
if (!lstrcmp(lpProcName, "GetProcAddress"))
{
return (FARPROC) &newGetProcAddress;
}
else
{
CheckForOpenGlHook(&nResult, lpProcName);
        }
}
return nResult;
}

//
BOOL HookIAT(char* szModule, char* szFunc, DWORD dwOwn, DWORD& dwOrg)
{
     // Ya mostrado
}

//
bool WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
if (fdwReason==DLL_PROCESS_ATTACH)
{
//printf("GetProcAddress 0x%X\n", GetProcAddress);// No refenciar GPA antes!
if(!HookIAT("kernel32.dll","GetProcAddress",(DWORD)newGetProcAddress,
(DWORD&)pGetProcAddress)){

MessageBox(0,0,0,0);
return (false);
}

printf("\n");
printf("DLL: newGetProcAddress 0x%X\n", newGetProcAddress);
printf("DLL: GetProcAddress 0x%X\n", GetProcAddress);
printf("DLL: pGetProcAddress 0x%X\n", pGetProcAddress);

}
return (true);
}


Los Hooks o funciones de gancho, como quieran decirles, son estas siguientes. Vemos que dentro de las de Opengl32 se hicieron cambios para modificar el resultado del programa.
El Hook de GetProcAddress se encarga de cambiar la dirección de retorno por una de los Hooks de Opengl32, y de inicializar los punteros a función con las direcciones de las originales.

DLL: opengl32.cpp
Código (cpp) [Seleccionar]

//
// By 85
// elhacker.net
// etalking.com.ar
// 2013
//

///////////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma comment(lib, "opengl32.lib")
#include<windows.h>
#include<stdio.h>
#include "opengl.h"

///////////////////////////////////////////////////////////////////////////////////////////////////////////

// Opengl32 es APIENTRY
typedef void(__stdcall* t_glBegin)(GLenum);
typedef void(__stdcall* t_glBlendFunc)(GLenum, GLenum);
typedef void(__stdcall* t_glViewport)(GLint,GLint,GLsizei,GLsizei);

t_glBegin pOrig_glBegin = NULL;
t_glBlendFunc pOrig_glBlendFunc = NULL;
t_glViewport pOrig_glViewport = NULL;

bool once=false;
bool oglSubtractive = false;
bool NewDimension = true;

int posx = 200;
int posy = 200;
int neww = 50;
int newh = 50;

//
void __stdcall HOOK_glBegin(GLenum mode)
{
if(!once){
once=true;
}

if (mode==GL_POLYGON)
{
    glClearColor(1.0, 1.0, 1.0, 1.0);
    glColor3f(0, 0, 0);
}

(*pOrig_glBegin)(mode);
}

void __stdcall HOOK_glBlendFunc(GLenum sfactor, GLenum dfactor)
{
if(oglSubtractive){
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

} else {
glBlendFunc(sfactor,dfactor);
}
}

void __stdcall HOOK_glViewport( GLint x,GLint y,GLsizei width,GLsizei height )
{
if(NewDimension){

(*pOrig_glViewport)(posx,posy,neww,newh);
}
else
{
(*pOrig_glViewport)(x,y,width,height);
}
}

void CheckForOpenGlHook(FARPROC* pProc,LPCTSTR lpProcName)
{
if (!strcmp(lpProcName,"glBegin"))
{
pOrig_glBegin = (t_glBegin)*pProc;
*pProc = (FARPROC)&HOOK_glBegin;
}
else if(!strcmp(lpProcName,"glBlendFunc"))
{
pOrig_glBlendFunc = (t_glBlendFunc)*pProc;
*pProc = (FARPROC)&HOOK_glBlendFunc;
}
else if(!strcmp(lpProcName,"glViewport"))
{
pOrig_glViewport = (t_glViewport)*pProc;
*pProc = (FARPROC)&HOOK_glViewport;
}
}


Espero que les haya gustado. Es un tutorial básico por lo tanto sólamente usé un parche a la IAT. Se puede experimentar con otro tipo de Hook más avanzado.

El programa ofrece la opción de interceptar Opengl32 o no:


Archivos utilizados:


Resultados:


Si me preguntan por qué hacer que usen GetProcAddress cuando no era necesario, la respuesta es que algunos juegos lo han hecho así, y servía para demostrar la utilidad de interceptar GPA.
Interceptar Opengl32 se podía haber hecho parcheando la IAT en las entradas de Opengl32 también.

Proyecto vc6:
http://www.mediafire.com/?p673twh7in70ys1
#22
NIVEL: Beginner
La continuación de este tutorial:
http://foro.elhacker.net/programacion_cc/tutorial_crear_un_parche_1-t384060.0.html

En este caso contamos con 2 ejecutables .EXE ;
dummy.EXE va a ser el proceso víctima y parche1_externo.EXE
va a ser el proceso atacante, por decirlo así..


Cuando se abre el 2do ejecutable mencionado, el proceso atacante queda a la espera de encontrar al proceso víctima.








Dummy.EXE
Código (cpp) [Seleccionar]


//
// By 85
// elhacker.net
// etalking.com.ar
// 2013
//

///////////////////

#include<windows.h>
#include<stdio.h>

//////////////////////
//////////////////////

DWORD dwPatchPlace = 0x00000000;
BYTE Opcode_JZ = 0x74;

///////////
////////////////////

void Target(){

while(1){


#define MASTERNUM 85
int master=0x99999997;
char* ingreso = new char[256];

system("cls");
printf("Ingrese la llave maestra\n");
scanf("%s", ingreso);

if(!strcmpi(ingreso, new char[]= "key85\0")){

master = 85;
}

delete []ingreso;
if(master==MASTERNUM)
{
printf("FELICITACIONES! USTE HA INGRESADO\n");
printf("\n");
system("pause");
break;
}

// if(GetAsyncKeyState(VK_END)) break;// En otro hilo
if(!strcmpi(ingreso, new char[]= "exit\0")) break;
}
}

//
void Check()//Función que representa un método de seguridad
{
if(*(PBYTE)dwPatchPlace != Opcode_JZ)
{
printf("0x%X\n",*(PBYTE)dwPatchPlace);
printf("Memoria alterada!, se sale del programa..\n");
printf("\n");
system("pause");
ExitProcess(45);
}
}

/////////

int main(){

SetConsoleTitle("Dummy");

dwPatchPlace=(DWORD)GetModuleHandle(NULL);//Retorna la BaseAddress

//Sumamos el offset obtenido del desensamblado
dwPatchPlace+=0x00001000;
dwPatchPlace+=0x6C;

//Logs

printf("LOG DE SEGURIDAD PRIMARIO:\n");
printf("0x%X\n",(DWORD)GetModuleHandle(NULL));
printf("0x%X\n",dwPatchPlace);
printf("0x%X\n",*(PBYTE)dwPatchPlace);
printf("\n");
system("pause");

//Llamamos a la función
Target();

printf("LOG DE SEGURIDAD SECUNDARIO:\n");
printf("0x%X\n",(DWORD)GetModuleHandle(NULL));
printf("0x%X\n",dwPatchPlace);
printf("0x%X\n",*(PBYTE)dwPatchPlace);
printf("\n");
system("pause");

//Se deja que las comprobaciones de seguridad sigan su curso
Check();

return 0;
}


parche1_externo.EXE
Código (cpp) [Seleccionar]


//
// By 85
// GetModuleBase (googleada en 5 segundos XD)
// elhacker.net
// etalking.com.ar
// 2013
//

///////////////////

#include<windows.h>
#include<stdio.h>
#include<tlhelp32.h>

//////////////////////

HANDLE hProcess;  
HANDLE hModule;
DWORD dwPatchPlace = 0x00000000;
BYTE Opcode_JZ = 0x74;
BYTE Opcode_JNZ = 0x75;
BYTE pReaden;

///////////

VOID Patch() {

// printf("0x%X\n",pReaden);
// system("pause");

if(!hProcess) return;
if(pReaden!=Opcode_JZ) return;

DWORD dwOldProtect;
   VirtualProtect( (LPVOID)dwPatchPlace,
                   1,
                   PAGE_EXECUTE_WRITECOPY,
                   &dwOldProtect );

   WriteProcessMemory( hProcess,
                       (LPVOID)dwPatchPlace,
                       &Opcode_JNZ,
                       1,
                       NULL );

   VirtualProtect( (LPVOID)dwPatchPlace,
                   1,
                   dwOldProtect,
                   &dwOldProtect );
}

//
////////////////////

DWORD GetModuleBase(LPSTR lpModuleName, DWORD dwProcessId)
{
  MODULEENTRY32 lpModuleEntry = {0};
  HANDLE hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwProcessId );

  if(!hSnapShot)
     return NULL;
  lpModuleEntry.dwSize = sizeof(lpModuleEntry);
  BOOL bModule = Module32First( hSnapShot, &lpModuleEntry );
  while(bModule)
  {
  //printf("%s\n",lpModuleEntry.szModule);
     if(!strcmp( lpModuleEntry.szModule, lpModuleName ) )
     {
        CloseHandle( hSnapShot );
        return (DWORD)lpModuleEntry.modBaseAddr;
     }
     bModule = Module32Next( hSnapShot, &lpModuleEntry );
  }
  CloseHandle( hSnapShot );
  return NULL;
}

int main(){

// We have to replace JZ with JNZ.

//TODO: Obtener privilegios
//

char l_exe[] = {'d','u','m','m','y','.','e','x','e',0};
char l_window[] = {'D','u','m','m','y',0};
HWND hwnd;          
hwnd = FindWindow(0, l_window);    
if (!hwnd)    
{        
printf("Abre %s ahora.\n", l_exe);        
while (1)      
{            
Sleep(1000);            
hwnd = FindWindow(0, l_window);            
if (hwnd) break;
if (GetAsyncKeyState(VK_END)>0) ExitProcess(45);
}            
}

unsigned long pid;    
GetWindowThreadProcessId( hwnd, &pid);    
// hProcess=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_QUERY_INFORMATION,0,pid);
// hProcess=OpenProcess(PROCESS_VM_WRITE|PROCESS_VM_OPERATION,0,pid);
hProcess=OpenProcess(PROCESS_ALL_ACCESS,0,pid);

HANDLE baseAddress = (HANDLE)GetModuleBase(l_exe, pid);
if(!baseAddress)
{
printf("No se obtubo la baseAddress!\n");
system("pause");
ExitProcess(45);
}

//Lugar del parche
dwPatchPlace=(DWORD)baseAddress;
dwPatchPlace+=0x00001000;
dwPatchPlace+=0x6C;

//Logs
printf("hProcess: 0x%X\n",hProcess);
printf("pid: %d\n",pid);
printf("dwPatchPlace: 0x%X\n",dwPatchPlace);
// printf("0x%X\n",*(PBYTE)dwPatchPlace);//No se puede hacer esto para otro proceso
if(ReadProcessMemory(hProcess,(void*)(dwPatchPlace),&pReaden,sizeof(pReaden),0))
{
printf("Lugar antes de parchear: 0x%X\n",pReaden);
}
else
printf("ReadProcessMemory failed: %d\n",GetLastError());

system("pause");

//Se procede a parchear el proceso objetivo
Patch();

if(ReadProcessMemory(hProcess,(void*)(dwPatchPlace),&pReaden,sizeof(pReaden),0))
{
printf("Lugar luego de parchear: 0x%X\n",pReaden);
}
else
printf("ReadProcessMemory failed: %d\n",GetLastError());


CloseHandle(hProcess);
system("pause");
return 0;
}

//


La finalidad es la misma que la primer parte del tutorial, es decir parchear un OPCODE en la memoria del proceso víctima. Las novedades son que se hizo desde otro proceso por lo que SI se tuvo que usar ReadProcessMemory y WriteProcessMemory (Sin mencionar las otras API's).

Para detectar si la ventana del proceso víctima se encuentra abierta se ha usado FindWindow.

Para obtener un manejador (handle) del proceso víctima usamos OpenProcess.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms684320(v=vs.85).aspx

Algo también que van a querer saber:
Citar
To open a handle to another local process and obtain full access rights, you must enable the SeDebugPrivilege privilege. For more information, see Changing Privileges in a Token.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms717797(v=vs.85).aspx

y conocer los posibles derechos de acceso a un proceso:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms684880(v=vs.85).aspx

Al terminar las operaciones se debe cerrar el handle del proceso.

Sobre la forma de buscar los procesos activos, se usó la función googleada 'GetModuleBase' que utiliza TOOLHELP32, para obtener la dirección base:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686832(v=vs.85).aspx

Recuerden que son dos procesos separados con sus espacios de direcciones respectivos, por lo cual se requiere ReadProcessMemory para leer la memoria de otro proceso, y para modificarla, WriteProcessMemory.

O sea que algo como esto:

printf("0x%X\n",*(PBYTE)dwPatchPlace);//No se puede hacer esto para otro proceso


No sirve porque la dirección guardada en dwPatchPlace es del proceso víctima, no del proceso atacante.
Por eso se pasa como parámetro a ReadProcessMemory.

Si quieren saber como obtener su propia 'dwPatchPlace' de un programa cualquiera, van a tener que desensamblarlo (mejor si no está protegido) o en otro caso depurarlo en funcionamiento con un depurador como el OllyDBG.
Es decir, el tutorial da por sabido que cada uno ya sabe lo que quiere parchear y adonde debe parchear. El tutorial apunta a cómo se parchea.

Disculpen si faltan cosas en este humilde tutorial, pero es para beginners por lo tanto si faltan cosas pueden aportarlas  ;D.

Proyecto vc6: http://www.mediafire.com/?8a65cuufh2dd4um
#23
Programación C/C++ / Flotantes aleatorios
6 Marzo 2013, 03:18 AM
Hola,
hacía un tiempo había creado una optimización para un código que permitía obtener números flotantes aleatorios, que se usaban en una funcionalidad de un hack para Counter-Strike.
En realidad se necesitan 4 valores aleatorios para usarse en el hack y lo que hice fue optimizar el código original, que daba muchas vueltas antes de hacer la operación real. Supongo que para confundir a los hackers XD

pero fuera de lo que tiene que ver con el Counter-Strike, esto sirve para generar números aleatorios (de punto flotante), por eso el título..

Tengan en cuenta que se puede modificar la función que genera los números aleatorios, para que devuelva un sólo número en lugar de un vector de 4. También pueden hacer las modificaciones que quieran, pero tengan en cuenta que así como está es como sirve para el hack.
Para más información:
http://www.gamedeception.net/threads/26109-85-Customized-Spread-Class

Este es un programa demostrativo que hice para ver los resultados:


//
// By 85
// Credits: HL1 SDK, Paul Upton, Snipity (Tad)
// elhacker.net
// etalking.com.ar
// David Riedel
// 2013

#pragma warning(disable: 4390)
#include<windows.h>
#include<iostream>
#include<stdio.h>
#include<time.h>

//

class Random{

public:
Random()
{
Init();
}
private:
void Init();
float RandomFloat[4];
unsigned int glSeed;
unsigned int seed_table[ 256 ];
public:
void SetRandomFloatVector(unsigned int seed, int future);
float* getRandomFloatVector() { return RandomFloat; }
};

//

Random random;

//
void Random::Init(){
glSeed = 0;
int i=0;
seed_table[i] = 28985; i++;
seed_table[i] = 27138; i++;
seed_table[i] = 26457; i++;
seed_table[i] = 9451; i++;
seed_table[i] = 17764; i++;
seed_table[i] = 10909; i++;
seed_table[i] = 28790; i++;
seed_table[i] = 8716; i++;
seed_table[i] = 6361; i++;
seed_table[i] = 4853; i++;
seed_table[i] = 17798; i++;
seed_table[i] = 21977; i++;
seed_table[i] = 19643; i++;
seed_table[i] = 20662; i++;
seed_table[i] = 10834; i++;
seed_table[i] = 20103; i++;
seed_table[i] = 27067; i++;
seed_table[i] = 28634; i++;
seed_table[i] = 18623; i++;
seed_table[i] = 25849; i++;
seed_table[i] = 8576; i++;
seed_table[i] = 26234; i++;
seed_table[i] = 23887; i++;
seed_table[i] = 18228; i++;
seed_table[i] = 32587; i++;
seed_table[i] = 4836; i++;
seed_table[i] = 3306; i++;
seed_table[i] = 1811; i++;
seed_table[i] = 3035; i++;
seed_table[i] = 24559; i++;
seed_table[i] = 18399; i++;
seed_table[i] = 315; i++;
seed_table[i] = 26766; i++;
seed_table[i] = 907; i++;
seed_table[i] = 24102; i++;
seed_table[i] = 12370; i++;
seed_table[i] = 9674; i++;
seed_table[i] = 2972; i++;
seed_table[i] = 10472; i++;
seed_table[i] = 16492; i++;
seed_table[i] = 22683; i++;
seed_table[i] = 11529; i++;
seed_table[i] = 27968; i++;
seed_table[i] = 30406; i++;
seed_table[i] = 13213; i++;
seed_table[i] = 2319; i++;
seed_table[i] = 23620; i++;
seed_table[i] = 16823; i++;
seed_table[i] = 10013; i++;
seed_table[i] = 23772; i++;
seed_table[i] = 21567; i++;
seed_table[i] = 1251; i++;
seed_table[i] = 19579; i++;
seed_table[i] = 20313; i++;
seed_table[i] = 18241; i++;
seed_table[i] = 30130; i++;
seed_table[i] = 8402; i++;
seed_table[i] = 20807; i++;
seed_table[i] = 27354; i++;
seed_table[i] = 7169; i++;
seed_table[i] = 21211; i++;
seed_table[i] = 17293; i++;
seed_table[i] = 5410; i++;
seed_table[i] = 19223; i++;
seed_table[i] = 10255; i++;
seed_table[i] = 22480; i++;
seed_table[i] = 27388; i++;
seed_table[i] = 9946; i++;
seed_table[i] = 15628; i++;
seed_table[i] = 24389; i++;
seed_table[i] = 17308; i++;
seed_table[i] = 2370; i++;
seed_table[i] = 9530; i++;
seed_table[i] = 31683; i++;
seed_table[i] = 25927; i++;
seed_table[i] = 23567; i++;
seed_table[i] = 11694; i++;
seed_table[i] = 26397; i++;
seed_table[i] = 32602; i++;
seed_table[i] = 15031; i++;
seed_table[i] = 18255; i++;
seed_table[i] = 17582; i++;
seed_table[i] = 1422; i++;
seed_table[i] = 28835; i++;
seed_table[i] = 23607; i++;
seed_table[i] = 12597; i++;
seed_table[i] = 20602; i++;
seed_table[i] = 10138; i++;
seed_table[i] = 5212; i++;
seed_table[i] = 1252; i++;
seed_table[i] = 10074; i++;
seed_table[i] = 23166; i++;
seed_table[i] = 19823; i++;
seed_table[i] = 31667; i++;
seed_table[i] = 5902; i++;
seed_table[i] = 24630; i++;
seed_table[i] = 18948; i++;
seed_table[i] = 14330; i++;
seed_table[i] = 14950; i++;
seed_table[i] = 8939; i++;
seed_table[i] = 23540; i++;
seed_table[i] = 21311; i++;
seed_table[i] = 22428; i++;
seed_table[i] = 22391; i++;
seed_table[i] = 3583; i++;
seed_table[i] = 29004; i++;
seed_table[i] = 30498; i++;
seed_table[i] = 18714; i++;
seed_table[i] = 4278; i++;
seed_table[i] = 2437; i++;
seed_table[i] = 22430; i++;
seed_table[i] = 3439; i++;
seed_table[i] = 28313; i++;
seed_table[i] = 23161; i++;
seed_table[i] = 25396; i++;
seed_table[i] = 13471; i++;
seed_table[i] = 19324; i++;
seed_table[i] = 15287; i++;
seed_table[i] = 2563; i++;
seed_table[i] = 18901; i++;
seed_table[i] = 13103; i++;
seed_table[i] = 16867; i++;
seed_table[i] = 9714; i++;
seed_table[i] = 14322; i++;
seed_table[i] = 15197; i++;
seed_table[i] = 26889; i++;
seed_table[i] = 19372; i++;
seed_table[i] = 26241; i++;
seed_table[i] = 31925; i++;
seed_table[i] = 14640; i++;
seed_table[i] = 11497; i++;
seed_table[i] = 8941; i++;
seed_table[i] = 10056; i++;
seed_table[i] = 6451; i++;
seed_table[i] = 28656; i++;
seed_table[i] = 10737; i++;
seed_table[i] = 13874; i++;
seed_table[i] = 17356; i++;
seed_table[i] = 8281; i++;
seed_table[i] = 25937; i++;
seed_table[i] = 1661; i++;
seed_table[i] = 4850; i++;
seed_table[i] = 7448; i++;
seed_table[i] = 12744; i++;
seed_table[i] = 21826; i++;
seed_table[i] = 5477; i++;
seed_table[i] = 10167; i++;
seed_table[i] = 16705; i++;
seed_table[i] = 26897; i++;
seed_table[i] = 8839; i++;
seed_table[i] = 30947; i++;
seed_table[i] = 27978; i++;
seed_table[i] = 27283; i++;
seed_table[i] = 24685; i++;
seed_table[i] = 32298; i++;
seed_table[i] = 3525; i++;
seed_table[i] = 12398; i++;
seed_table[i] = 28726; i++;
seed_table[i] = 9475; i++;
seed_table[i] = 10208; i++;
seed_table[i] = 617; i++;
seed_table[i] = 13467; i++;
seed_table[i] = 22287; i++;
seed_table[i] = 2376; i++;
seed_table[i] = 6097; i++;
seed_table[i] = 26312; i++;
seed_table[i] = 2974; i++;
seed_table[i] = 9114; i++;
seed_table[i] = 21787; i++;
seed_table[i] = 28010; i++;
seed_table[i] = 4725; i++;
seed_table[i] = 15387; i++;
seed_table[i] = 3274; i++;
seed_table[i] = 10762; i++;
seed_table[i] = 31695; i++;
seed_table[i] = 17320; i++;
seed_table[i] = 18324; i++;
seed_table[i] = 12441; i++;
seed_table[i] = 16801; i++;
seed_table[i] = 27376; i++;
seed_table[i] = 22464; i++;
seed_table[i] = 7500; i++;
seed_table[i] = 5666; i++;
seed_table[i] = 18144; i++;
seed_table[i] = 15314; i++;
seed_table[i] = 31914; i++;
seed_table[i] = 31627; i++;
seed_table[i] = 6495; i++;
seed_table[i] = 5226; i++;
seed_table[i] = 31203; i++;
seed_table[i] = 2331; i++;
seed_table[i] = 4668; i++;
seed_table[i] = 12650; i++;
seed_table[i] = 18275; i++;
seed_table[i] = 351; i++;
seed_table[i] = 7268; i++;
seed_table[i] = 31319; i++;
seed_table[i] = 30119; i++;
seed_table[i] = 7600; i++;
seed_table[i] = 2905; i++;
seed_table[i] = 13826; i++;
seed_table[i] = 11343; i++;
seed_table[i] = 13053; i++;
seed_table[i] = 15583; i++;
seed_table[i] = 30055; i++;
seed_table[i] = 31093; i++;
seed_table[i] = 5067; i++;
seed_table[i] = 761; i++;
seed_table[i] = 9685; i++;
seed_table[i] = 11070; i++;
seed_table[i] = 21369; i++;
seed_table[i] = 27155; i++;
seed_table[i] = 3663; i++;
seed_table[i] = 26542; i++;
seed_table[i] = 20169; i++;
seed_table[i] = 12161; i++;
seed_table[i] = 15411; i++;
seed_table[i] = 30401; i++;
seed_table[i] = 7580; i++;
seed_table[i] = 31784; i++;
seed_table[i] = 8985; i++;
seed_table[i] = 29367; i++;
seed_table[i] = 20989; i++;
seed_table[i] = 14203; i++;
seed_table[i] = 29694; i++;
seed_table[i] = 21167; i++;
seed_table[i] = 10337; i++;
seed_table[i] = 1706; i++;
seed_table[i] = 28578; i++;
seed_table[i] = 887; i++;
seed_table[i] = 3373; i++;
seed_table[i] = 19477; i++;
seed_table[i] = 14382; i++;
seed_table[i] = 675; i++;
seed_table[i] = 7033; i++;
seed_table[i] = 15111; i++;
seed_table[i] = 26138; i++;
seed_table[i] = 12252; i++;
seed_table[i] = 30996; i++;
seed_table[i] = 21409; i++;
seed_table[i] = 25678; i++;
seed_table[i] = 18555; i++;
seed_table[i] = 13256; i++;
seed_table[i] = 23316; i++;
seed_table[i] = 22407; i++;
seed_table[i] = 16727; i++;
seed_table[i] = 991; i++;
seed_table[i] = 9236; i++;
seed_table[i] = 5373; i++;
seed_table[i] = 29402; i++;
seed_table[i] = 6117; i++;
seed_table[i] = 15241; i++;
seed_table[i] = 27715; i++;
seed_table[i] = 19291; i++;
seed_table[i] = 19888; i++;
seed_table[i] = 19847;
}

//
// Misma funcionalidad que random.cpp y nospread.cpp (Snipity Hook)
void Random::SetRandomFloatVector(unsigned int seed, int future){// By 85
for(int i=0; i<4; i++){
glSeed = seed_table[(int)(seed+future+i)&0xff];
for(int j=0; j<3;j++){
glSeed *= 69069;
glSeed += seed_table[glSeed&0xff];
(++glSeed & 0x0fffffff);
}
RandomFloat[i]=(-0.5+(float)(((glSeed&0x0fffffff)&65535)/65536.0f));
}
}

//
int main(){

unsigned int seed;
int future;
seed = time(NULL);
future=1;
int i =0;

while(1)
{
seed = time(NULL);//No es la seed original (Original es me.spread.random_seed)
       random.SetRandomFloatVector(seed, future);
printf("RandomFloat[0] %f\n",random.getRandomFloatVector()[0]);
printf("RandomFloat[1] %f\n",random.getRandomFloatVector()[1]);
printf("RandomFloat[2] %f\n",random.getRandomFloatVector()[2]);
printf("RandomFloat[3] %f\n",random.getRandomFloatVector()[3]);
printf("\n");

std::cout << "Press the ENTER key\n";
if (std::cin.get() == '\n');

if(i++==10) break;
}

system("pause > nul");
return 0;
}

//


Proyecto vc6: http://www.mediafire.com/?a93dsydc3gvrrdj

#24
NIVEL: Beginner
TEST: win XP SP3

Esta es la continuación de esta especie de tutorial que había
comenzado en este hilo:

http://foro.elhacker.net/programacion_cc/parchear_la_iat_para_interceptar_gpa-t384232.0.html


En este caso, vamos a utilizar el desensamblador que veníamos usando
para obtener ciertos datos acerca de una librería llamada kernel32.dll
para los que no la conocen, es una librería (DLL) del sistema Windows
y la pueden encontrar en la carpeta system32.
Más información:
http://en.wikipedia.org/wiki/Microsoft_Windows_library_files

Usamos el desensamblador (O un explorador PE) para observar los detalles del archivo. Y también cierta información que vamos a utilizar.















Luego el código del programa..
En este programa contamos con dos rutinas que realizan el mismo
objetivo: Parchear la EAT de kernel32.dll

La diferencia es que la primera hace las operaciones automáticamente
valiéndose de cierta información obtenida del siguiente tutorial:
http://www.mediafire.com/?6nzmp28x2pb9b4n

y de esto:
http://www.cyvera.com/how-injected-code-finds-exported-functions/

Realiza algunas operaciones con ensamblador en línea y luego parchea la EAT.

La segunda rutina cumple con el objetivo pero sin usar ensamblador
en línea.

Con respecto al por qué de usar ASM, es para mostrar algo diferente
del anterior tutorial en el que se hacía todo automáticamente y con
C/C++.
http://foro.elhacker.net/programacion_cc/parcheo_de_eat_y_de_iat_automatico-t384486.0.html

NOTA: El objetivo es como se puede usar una herramienta como puede
ser un explorador de PE, o un desensamblador cualquiera, para obtener
estos datos.

Inclusive este tipo de cosas se puede hacer sin necesidad de código, es decir simplemente usando este tipo de herramientas pero para parchear los archivos en disco. Pero la idea era codificar algo XD

El código del programa:
Código (cpp) [Seleccionar]


//
// By 85
// elhacker.net
// etalking.com.ar
// boyscout_arg@hotmail.com
// 2013
//

#include<windows.h>
#include<stdio.h>

//
FARPROC (WINAPI* pGetProcAddress) ( HMODULE hModule, LPCSTR lpProcName );

typedef FARPROC (WINAPI* GetProcAddress_t) ( HMODULE hModule, LPCSTR lpProcName );

//
FARPROC WINAPI newGetProcAddress(HMODULE hModule, LPCSTR lpProcName)
{
FARPROC nResult;
nResult=pGetProcAddress(hModule, lpProcName);
if (HIWORD(lpProcName))
{
if (!lstrcmp(lpProcName, "GetProcAddress"))
{
return (FARPROC) &newGetProcAddress;
}
}
return nResult;
}

//
DWORD PatchEAT( DWORD pOrgFunction, DWORD pNewFunction )
{
DWORD dwOldProtect;
DWORD dwOldProtect2;
DWORD pOldFunction = ((DWORD*)pOrgFunction)[0];

VirtualProtect( reinterpret_cast< void * >( pOrgFunction ), sizeof( DWORD ), PAGE_EXECUTE_READWRITE, &dwOldProtect );
((DWORD*)pOrgFunction)[0] = pNewFunction;
VirtualProtect( reinterpret_cast< void * >( pOrgFunction ), sizeof( DWORD ), dwOldProtect, &dwOldProtect2 );
return pOldFunction;
}

//
void PatchEatConInlineASM(){

char* gpastr = "GetProcAddress";
DWORD k32base = (DWORD)GetModuleHandle("kernel32.dll");

// Logs
   DWORD peheader=0;
DWORD rva_exports_dir=0;
DWORD rva_exports_funcs=0;
DWORD rva_exports_fnames=0;
DWORD va_exports_fnames=0;
DWORD va_eat=0;
int savedeax;
DWORD rEDX;

__asm{
mov ebx, k32base                      //EBX = kernel32.dll's base address
mov edx,dword ptr ds:[ebx+3Ch]        //PE header
mov peheader, edx
mov edx,dword ptr ds:[edx+ebx+78h]    //EDX = kernel32.dll's export directory (RVA)
mov rva_exports_dir, edx
mov eax,dword ptr ds:[edx+ebx+1Ch]    //Address of exported funcs (EAX = EAT (RVA))
mov rva_exports_funcs, eax
mov edx,dword ptr ds:[edx+ebx+20h]    //EDX = Address of function names (RVA)
mov rva_exports_fnames, edx
add edx,ebx                           //EDX = Address of function names (VA)
mov va_exports_fnames, edx
add eax,ebx                           //EAX = EAT (VA)
mov va_eat, eax
}

__asm{

get_exports:
xor ecx, ecx
mov esi,gpastr              //Address of string "GetProcAddress" (not null-terminated)
mov edi,dword ptr ds:[edx]  //EDI = *(EDX = VA of function names)
add edi,ebx                 //Address of string (Exported function name) (k32+offs en edi)
mov cl,0Eh                  //14 chars
repe cmpsb                  //recibe dos direcciones de 2 strings (ESI,EDI)
je short found_set_context  //Jump if this is our function
add edx,4                   //Next function name
add eax,4                   //Next function address
jmp short get_exports
found_set_context:
mov savedeax, eax
mov edx,dword ptr ds:[eax]
add edx,ebx  
mov rEDX, edx
}


printf("k32 0x%X\n",k32base);
printf("peheader 0x%X\n",peheader);
printf("rva_exports_dir 0x%X\n",rva_exports_dir);
printf("rva_exports_funcs 0x%X\n",rva_exports_funcs);
printf("rva_exports_fnames 0x%X\n",rva_exports_fnames);
printf("va_exports_fnames 0x%X\n",va_exports_fnames);
printf("va_eat 0x%X\n",va_eat);
printf("primer entrada de va_eat 0x%X\n",*(DWORD*)va_eat);//da un rva
printf("savedeax 0x%X\n",savedeax);// eat entry para gpa
printf("savedeax 0x%X\n",*(DWORD*)savedeax);// el rva en el eat entry correspondiente a gpa
printf("GetProcAddress 0x%X\n",GetProcAddress);
printf("rEDX 0x%X\n",rEDX);
system("pause");

/////////////////////////////////////////////////

// Calcular el rva con mi gpa
DWORD rvaMiGPA = (((DWORD)newGetProcAddress)-DWORD(k32base));

// Inicializar puntero de retorno a la original
pGetProcAddress = (GetProcAddress_t)rEDX;

// Parche
PatchEAT( savedeax, rvaMiGPA );// savedeax = eat entry para gpa

printf("newGetProcAddress 0x%X\n",newGetProcAddress);
// printf("GetProcAddress 0x%X\n",GetProcAddress);
system("pause");
}

//
void PatchEatSinInlineASM(){

DWORD k32base = (DWORD)GetModuleHandle("kernel32.dll");
DWORD exports = k32base+0x262C;
DWORD* dwEAT = (DWORD*)(exports+0x28);//953 entradas
printf("EAT 0x%X\n",dwEAT);

//for(int i=0;i<409-1;i++) dwEAT+=0x1;
//printf("GPA EAT 0x%X\n",dwEAT);
//printf("*GPA EAT 0x%X\n",*(dwEAT));

DWORD dwEATgpa = (DWORD)(dwEAT+0x198);
printf("GPA EAT 0x%X\n",(dwEAT+0x198));//0x199 = 409
printf("*GPA EAT 0x%X\n",*(dwEAT+0x198));

DWORD rvaGPA = dwEAT[409-1];//409 = gpa index
DWORD dwGPA = k32base+rvaGPA;

printf("rvaGPA 0x%X\n",rvaGPA);
printf("dwGPA 0x%X\n",dwGPA);
// printf("GetProcAddress 0x%X\n",GetProcAddress);
//system("pause");

/////////////////////////////////////////////////

// Calcular el rva de mi gpa
DWORD rvaMiGPA = (((DWORD)newGetProcAddress)-DWORD(k32base));

printf("dwEATgpa 0x%X\n",dwEATgpa);
printf("rvaMiGPA 0x%X\n",rvaMiGPA);

// Inicializar puntero de retorno a la original
pGetProcAddress = (GetProcAddress_t)dwGPA;

// Parche
PatchEAT( dwEATgpa, rvaMiGPA );

printf("newGetProcAddress 0x%X\n",newGetProcAddress);
// printf("GetProcAddress 0x%X\n",GetProcAddress);
system("pause");
}

//
int main(){

// 1
// PatchEatConInlineASM();

// 2
PatchEatSinInlineASM();

/////////////////////////////////////////////////
// Test

DWORD test = (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"),"GetProcAddress");
printf("test 0x%X\n",test);
printf("pGetProcAddress 0x%X\n",pGetProcAddress);// retorno a la original

system("pause");
return 0;
}

//


PROYECTO VC6
http://www.mediafire.com/?t87q7m7b7give3b

hasta luego
#25
NIVEL: Beginner
TEST: win XP SP3

En este post a modo de tutorial se han utilizado dos rutinas, googleadas de las miles que hay, que hacen los parches respectivos (EAT e IAT), automáticamente,  encontrando la ubicación de la entrada correspondiente a una función, dentro de estas tablas. Para el ejemplo del parcheo de IAT se procede a usar la IAT local  del ejecutable, mientras que para el parcheo de EAT se hace en la EAT de la librería (DLL) kernel32.dll.

El objetivo de esta demostración es interceptar la función
GetProcAddress con ningún propósito más que demostrar como
se puede interceptar una función.

Se pueden valorar los casos que se pueden dar en los siguientes
dos ejemplos de programas:

En el primer programa contamos con un EXE el cual tiene dos opciones
que se le ofrecen al usuario:

1_ parchear la eat de kernel32.dll
2_ parchear la iat local


luego de elegir una de ambas opciones, se procede a cargar una DLL
en el proceso (ver el código de la DLL para ver que hace).

DEMO 1

EXE
Código (cpp) [Seleccionar]

//
// By 85
// PatchEAT, PatchIAT (Googleadas en 5 segundos XD)
// elhacker.net
// etalking.com.ar
// 2013
//

#include<windows.h>
#include<stdio.h>

//
FARPROC (WINAPI* pGetProcAddress) ( HMODULE hModule, LPCSTR lpProcName );

typedef FARPROC (WINAPI* GetProcAddress_t) ( HMODULE hModule, LPCSTR lpProcName );

//
FARPROC WINAPI newGetProcAddress(HMODULE hModule, LPCSTR lpProcName)
{
FARPROC nResult;
nResult=pGetProcAddress(hModule, lpProcName);
if (HIWORD(lpProcName))
{
if (!lstrcmp(lpProcName, "GetProcAddress"))
{
return (FARPROC) &newGetProcAddress;
}
}
return nResult;
}

//
bool PatchEAT(HMODULE hTargetMod,CHAR* FuncName,VOID* newAdd,VOID** OrigAdd)
{

#define _sword sizeof(WORD) //AddressOfNameOrdinals
#define _sdword sizeof(DWORD)
   DWORD addEAT,beforeProtection;
   IMAGE_DOS_HEADER* dos_header=(IMAGE_DOS_HEADER*)hTargetMod;
   IMAGE_NT_HEADERS* nt_header=NULL;
   if(dos_header->e_magic!=IMAGE_DOS_SIGNATURE)
return false;

nt_header=((PIMAGE_NT_HEADERS)((DWORD)(dos_header)+(DWORD)(dos_header->e_lfanew)));
if(nt_header->Signature!=IMAGE_NT_SIGNATURE)
return false;

   addEAT=nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
   IMAGE_EXPORT_DIRECTORY* pEAT=(IMAGE_EXPORT_DIRECTORY*)((DWORD)addEAT+(DWORD)hTargetMod);
   for(DWORD i=0;i<pEAT->NumberOfFunctions;i++){
       DWORD* pName=(DWORD*)((DWORD)hTargetMod+((DWORD)pEAT->AddressOfNames+(_sdword*i)));
//printf("add nombre 0x%X\n",pName);
//system("pause");
       if(strcmp((char*)((DWORD)hTargetMod+*pName),FuncName) == 0){
           WORD* AddNamePtrs=(WORD*)((DWORD)hTargetMod+((DWORD)pEAT->AddressOfNameOrdinals+(i*_sword)));
           DWORD* AddFuncRVA=(DWORD*)((DWORD)hTargetMod+((DWORD)pEAT->AddressOfFunctions+(_sdword**AddNamePtrs)));
           

//if(!strcmp((char*)((DWORD)hTargetMod+*pName),"GetProcAddress")){
//printf("AddNamePtrs 0x%X\n",AddNamePtrs);
// printf("Add de la func rva 0x%X\n",AddFuncRVA);
// printf("Add func 0x%X\n",*AddFuncRVA+DWORD(hTargetMod));
// system("pause");
//}

if(!VirtualProtect(AddFuncRVA,_sdword,PAGE_READWRITE,&beforeProtection))
return false;

*OrigAdd=(void*)(*AddFuncRVA+DWORD(hTargetMod));
           *AddFuncRVA=(((DWORD)newAdd)-DWORD(hTargetMod));//copia el nuevo rva
           if(!VirtualProtect(AddFuncRVA,_sdword,beforeProtection,&beforeProtection))
return false;

break;
       }
   }
   return true;
}

//
BOOL PatchIAT(HMODULE ModHandle, DWORD OriginalFunc, DWORD HookFunc, void **pOriginalFunc)
{
DWORD pe_offset,CurAddr,CurPointer,IATanfang,IATende,base;
BOOL Hooked=FALSE;
IMAGE_NT_HEADERS *pehdr;

if(!ModHandle || !OriginalFunc || !HookFunc)
return FALSE;

base=(DWORD)ModHandle;

memcpy(&pe_offset,(void *)(base+0x3C),sizeof(DWORD));
pehdr=(IMAGE_NT_HEADERS *)((DWORD)base + pe_offset);

IATanfang=(DWORD)base+pehdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress;
IATende=IATanfang+pehdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size;

CurAddr=IATanfang;

while(CurAddr<IATende)
{
memcpy(&CurPointer,(void *)CurAddr,sizeof(DWORD));

if(CurPointer==OriginalFunc)
{
if(pOriginalFunc)
*pOriginalFunc=(PVOID)CurPointer;
DWORD old_attributes,old_attributes2;
if(!VirtualProtect((void *)CurAddr,sizeof(DWORD), PAGE_EXECUTE_READWRITE, &old_attributes))
return FALSE;
memcpy((void *)CurAddr,&HookFunc,sizeof(DWORD));
if(!VirtualProtect((void *)CurAddr,sizeof(DWORD), old_attributes, &old_attributes2))
return FALSE;
Hooked=TRUE;
}

CurAddr+=sizeof(DWORD);
}
return Hooked;
}

//
int main(){

/*DWORD test0a = (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"),"GetProcAddress");
DWORD test0b = (DWORD)GetProcAddress(GetModuleHandle(NULL),"GetProcAddress");
//printf("GPA original: 0x%X\n",pGetProcAddress);
printf("GPA hook: 0x%X\n",newGetProcAddress);
printf("GPA es ahora (k32): 0x%X\n",test0a);
printf("GPA es ahora (EXE): 0x%X\n",test0b);
system("pause");*/
////////////////////////////////

HINSTANCE lib;
int Res=0;
int hookmode=0;
while( hookmode<1||hookmode>3){

system("cls");
printf("Bienvenido!\n");
printf("Ingrese 1 para realizar un EAT HOOK\n");
printf("Ingrese 2 para realizar un IAT HOOK\n");
scanf("%d",&hookmode);
}

if(hookmode == 1) __asm jmp eathook;
else if(hookmode == 2) __asm jmp iathook;
else if(hookmode == 3) __asm jmp salida;

/////////////////////////////////////////////////
// EAT HOOK

eathook:
Res = PatchEAT(GetModuleHandle("kernel32.dll"),"GetProcAddress",
((VOID*)(&newGetProcAddress)),((VOID**)(&pGetProcAddress)));

if(!Res){

printf("No se ha modificado la EAT objetivo!\n");
ExitProcess(0);
}

// Test 1
DWORD test1a = (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"),"GetProcAddress");
DWORD test1b = (DWORD)GetProcAddress(GetModuleHandle(NULL),"GetProcAddress");
printf("GPA original: 0x%X\n",pGetProcAddress);
printf("GPA hook: 0x%X\n",newGetProcAddress);
printf("GPA es ahora (k32): 0x%X\n",test1a);
printf("GPA es ahora (EXE): 0x%X\n",test1b);
system("pause");

lib = LoadLibrary("loaddll.dll");
FreeLibrary(lib);
return 0;
//

////////////////////////////////////////////////
// IAT HOOK

iathook:
Res = PatchIAT(GetModuleHandle(NULL),(DWORD)GetProcAddress,
(DWORD)newGetProcAddress,(void **)&pGetProcAddress);

if(!Res){

printf("No se ha modificado la IAT objetivo!\n");
ExitProcess(0);
}

// Test 2
DWORD test2a = (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"),"GetProcAddress");
DWORD test2b = (DWORD)GetProcAddress(GetModuleHandle(NULL),"GetProcAddress");
printf("GPA original: 0x%X\n",pGetProcAddress);
printf("GPA hook: 0x%X\n",newGetProcAddress);
printf("GPA es ahora (k32): 0x%X\n",test2a);
printf("GPA es ahora (EXE): 0x%X\n",test2b);
system("pause");

lib = LoadLibrary("loaddll.dll");
FreeLibrary(lib);
return 0;
//

/////////////////////////////////////////////////
//
salida:
return 0;
}

//


DLL
Código (cpp) [Seleccionar]


//
// By 85
// PatchEAT, PatchIAT (googleadas en 5 segundos XD)
// elhacker.net
// etalking.com.ar
// 2013
//

#include<windows.h>
#include<stdio.h>

//////////////////////////

BOOL APIENTRY DllMain(
HANDLE hModule, // Handle to DLL module
DWORD ul_reason_for_call,
LPVOID lpReserved ) // Reserved
{
switch ( ul_reason_for_call )
{
case DLL_PROCESS_ATTACH:
// A process is loading the DLL.

{

DWORD res1 = (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"),"GetProcAddress");
DWORD res2 = (DWORD)GetProcAddress(GetModuleHandle(NULL),"GetProcAddress");
printf("GPA desde la dll mod=k32 0x%X\n", res1);
printf("GPA desde la dll mod=EXE 0x%X\n", res2);
system("pause");
}


break;
case DLL_THREAD_ATTACH:
// A process is creating a new thread.
break;
case DLL_THREAD_DETACH:
// A thread exits normally.
break;
case DLL_PROCESS_DETACH:
// A process unloads the DLL.
break;
}
return TRUE;
}

////////////////


En el segundo programa, contamos con un EXE el cual es un programa
simple. Sólo carga una DLL (Ver código de la DLL).

El código de la DLL se trata de realizar una de dos opciones.

1_ parchear la EAT kernel32.dll
2_ parchear la IAT del ejecutable

En realidad, se propone sólamente modificar la IAT del ejecutable,
el código del otro parche está deshabilitado.

En realidad el segundo programa no tiene mucho sentido tal cual está
expuesto, pero cobra sentido si nosotros quisiéramos aplicar este
método para algo relacionado al hacking.

Si queremos cambiar algo dentro de un proceso (por ejemplo un juego),
entonces una posible idea sería cargar una DLL en dicho proceso y
realizar un parche a la IAT del EXE. Siempre que sepamos que el EXE
hace uso de GetProcAddress para resolver alguna dirección interesante
para nosotros XD.

Un escenario en el cual se puede encontrar utilidad para esto pueder
ser, por ejemplo un programa (EXE) que utilice GetProcAddress para
resolver la dirección de ciertas funciones en una DLL que está cargada
en el proceso.

Al estár interceptada GetProcAddress, nosotros podemos arreglar que
retorne las direcciones de nuestros hooks en lugar de las direcciones
originales.

DEMO 2

EXE
Código (cpp) [Seleccionar]


//
// By 85
// elhacker.net
// etalking.com.ar
// 2013
//

#include<windows.h>
#include<stdio.h>

//
int main(){


HINSTANCE lib = LoadLibrary("loaddll2.dll");
FreeLibrary(lib);

printf("GPA original desde el EXE: 0x%X\n", GetProcAddress);
system("pause");
return 0;
}

//



DLL
Código (cpp) [Seleccionar]


//
// By 85
// PatchEAT, PatchIAT (googleadas en 5 segundos XD)
// elhacker.net
// etalking.com.ar
// 2013
//

#include<windows.h>
#include<stdio.h>

/////////////////////

FARPROC (WINAPI* pGetProcAddress) ( HMODULE hModule, LPCSTR lpProcName );

typedef FARPROC (WINAPI* GetProcAddress_t) ( HMODULE hModule, LPCSTR lpProcName );

//
FARPROC WINAPI newGetProcAddress(HMODULE hModule, LPCSTR lpProcName)
{
FARPROC nResult;
// nResult=pGetProcAddress(hModule, lpProcName);
nResult=GetProcAddress(hModule, lpProcName);
if (HIWORD(lpProcName))
{
if (!lstrcmp(lpProcName, "GetProcAddress"))
{
return (FARPROC) &newGetProcAddress;
}
}
return nResult;
}

//
bool PatchEAT(HMODULE hTargetMod,CHAR* FuncName,VOID* newAdd,VOID** OrigAdd)
{
       // misma que el anterior programa
...
}

//
BOOL PatchIAT(HMODULE ModHandle, DWORD OriginalFunc, DWORD HookFunc, void **pOriginalFunc)
{
// misma que el anterior programa
...
}

//
//////////////////////////

BOOL APIENTRY DllMain(
HANDLE hModule, // Handle to DLL module
DWORD ul_reason_for_call,
LPVOID lpReserved ) // Reserved
{
switch ( ul_reason_for_call )
{
case DLL_PROCESS_ATTACH:
// A process is loading the DLL.

{
int Res=0;
//

//////////////////////////
// EAT HOOK

/* Res = PatchEAT(GetModuleHandle("kernel32.dll"),"GetProcAddress",
((VOID*)(&newGetProcAddress)),((VOID**)(&pGetProcAddress)));

if(!Res){

printf("No se ha modificado la EAT objetivo!\n");
ExitProcess(0);
}

// Test 1
DWORD test1a = (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"),"GetProcAddress");
DWORD test1b = (DWORD)GetProcAddress(GetModuleHandle(NULL),"GetProcAddress");
//DWORD test1b = (DWORD)GetProcAddress(GetModuleHandle("loaddll2.dll"),"GetProcAddress");//NO
printf("DLL: GPA original: 0x%X\n",pGetProcAddress);
printf("DLL: GPA original: 0x%X\n",GetProcAddress);
printf("DLL: GPA hook: 0x%X\n",newGetProcAddress);
printf("DLL: GPA es ahora (k32): 0x%X\n",test1a);
printf("DLL: GPA es ahora (EXE): 0x%X\n",test1b);
system("pause");*/

/////////////////////////
// IAT HOOK


Res = PatchIAT(GetModuleHandle(NULL),(DWORD)GetProcAddress,
(DWORD)newGetProcAddress,(void **)&pGetProcAddress);

if(!Res){

printf("No se ha modificado la IAT objetivo!\n");
ExitProcess(0);
}

// Test 2
DWORD test2a = (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"),"GetProcAddress");
DWORD test2b = (DWORD)GetProcAddress(GetModuleHandle(NULL),"GetProcAddress");
//DWORD test2b = (DWORD)GetProcAddress(GetModuleHandle("loaddll2.dll"),"GetProcAddress");//NO
printf("DLL: GPA original: 0x%X\n",pGetProcAddress);
printf("DLL: GPA original: 0x%X\n",GetProcAddress);
printf("DLL: GPA hook: 0x%X\n",newGetProcAddress);
printf("DLL: GPA es ahora (k32): 0x%X\n",test2a);
printf("DLL: GPA es ahora (EXE): 0x%X\n",test2b);
system("pause");

}


break;
case DLL_THREAD_ATTACH:
// A process is creating a new thread.
break;
case DLL_THREAD_DETACH:
// A thread exits normally.
break;
case DLL_PROCESS_DETACH:
// A process unloads the DLL.
break;
}
return TRUE;
}

////////////////


Dejo ambos proyectos en MSVC++ 6.0
http://www.mediafire.com/?ha8768ul77a300z
http://www.mediafire.com/?cdeog97h39c770i

Más información
http://msdn.microsoft.com/en-us/magazine/cc301805.aspx
http://www.reverse-engineering.info/SystemHooking/export.htm
http://www.masmforum.com/board/index.php?PHPSESSID=8d46cd4ecb1688be429ab49694ec53e6&topic=4286.0


hasta luego
#26
Hola, quería mostrar algo básico que puede aportar algunos conceptos. Más que nada, gente que está en sus comienzos con la programación y puede interesarse en algunos detalles técnicos.

NIVEL: Beginner
No consideren esto de nivel avanzado.

Lo primero:
IAT = IMPORT ADDRESS TABLE
http://sandsprite.com/CodeStuff/Understanding_imports.html
http://www.karmany.net/index.php/ingenieria-inversa/19-ingenieria-inversa-novatos/146-pe-header-que-es-la-iat-import-address-table
http://cboard.cprogramming.com/cplusplus-programming/99240-import-address-table-iat.html

La iat es un lugar que puede accederse fácilmente con un desensamblador y se pueden observar todos los símbolos que el ejecutable importa de ciertos módulos. Hay una forma de hacer que el ejecutable no contenga imports, pero fuera de esa técnica los ejecutables la utilizan.
Generalmente se dice que los EXE usan la IAT y las DLL las EAT,
véase EAT = EXPORT ADDRESS TABLA , es para exportar símbolos.

Más información
http://www.rohitab.com/discuss/topic/33541-assembling-an-executable-with-no-imports/
http://www.etalking.com.ar/showthread.php?400-llamar-funciones-winapi32-sin-imports


Volviendo al tema, veamos lo que uno puede hacer fácilmente, con un desensamblador:









Obteniendo la dirección específica en la IAT se puede proceder a crear el parche con el cual se logra interceptar GetProcAddress.
Se trata sólo de cambiar el valor de un puntero, poniéndole la dirección de nuestra función "de gancho" o hook, para que sea llamada en lugar de la original.



//
// By 85
// PatchIAT LTFX
// elhacker.net
// etalking.com.ar
// 2013
//

#include<windows.h>
#include<stdio.h>

FARPROC (WINAPI* pGetProcAddress) ( HMODULE hModule, LPCSTR lpProcName );

typedef FARPROC (WINAPI* GetProcAddress_t) ( HMODULE hModule, LPCSTR lpProcName );

FARPROC WINAPI newGetProcAddress(HMODULE hModule, LPCSTR lpProcName)
{
FARPROC nResult;
nResult=pGetProcAddress(hModule, lpProcName);
if (HIWORD(lpProcName))
{
if (!lstrcmp(lpProcName, "GetProcAddress"))
{
return (FARPROC) &newGetProcAddress;
}
}
return nResult;
}

DWORD PatchIAT( DWORD pOrgFunction, DWORD pNewFunction )
{
DWORD dwOldProtect;
DWORD dwOldProtect2;
DWORD pOldFunction = ((DWORD*)pOrgFunction)[0];

VirtualProtect( reinterpret_cast< void * >( pOrgFunction ), sizeof( DWORD ), PAGE_EXECUTE_READWRITE, &dwOldProtect );
((DWORD*)pOrgFunction)[0] = pNewFunction;
VirtualProtect( reinterpret_cast< void * >( pOrgFunction ), sizeof( DWORD ), dwOldProtect, &dwOldProtect2 );
return pOldFunction;
}

int main(){

//400000+2004= GPA IAT ENTRY (En este programa x64core!, no lo modifiques!)
DWORD dwGPA = (DWORD)(GetModuleHandle(NULL));
dwGPA+=0x2004;

// x64core lo quiere en ASM inline..
__asm {
mov ebx, dwGPA
mov edx, [ebx]
mov pGetProcAddress, edx
}

// pGetProcAddress = *(GetProcAddress_t*)dwGPA;// Ajam..

printf("pGetProcAddress 0x%X\n\n",pGetProcAddress);
printf("GetProcAddress antes 0x%X\n\n",*(DWORD*)dwGPA);
// printf("GetProcAddress antes 0x%X\n\n",GetProcAddress);//No referenciar GPA antes del parche!

// Parchear IAT
PatchIAT( dwGPA, (DWORD)&newGetProcAddress );

// Sin PatchIAT:
//Desproteger
//DWORD* pGPA=(DWORD*)0x00402004;//400000+2004= GPA IAT ENTRY
//*pGPA=(DWORD)&newGetProcAddress;
//Proteger

printf("dwGPA 0x%X\n",dwGPA);
printf("*dwGPA 0x%X\n",*(DWORD*)dwGPA);
printf("GetProcAddress ahora 0x%X\n",GetProcAddress);
printf("newGetProcAddress 0x%X\n",newGetProcAddress);
system("pause");

DWORD test = (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"),"GetProcAddress");
printf("test 0x%X\n",test);
printf("GetProcAddress ahora 0x%X\n",GetProcAddress);
system("pause");
return 0;
}

//


Dejo el proyectito para descargar
http://www.mediafire.com/?2sowg12a6vora4n

Hasta Luego
#27
Programación C/C++ / Tutorial: Crear un parche 1
25 Febrero 2013, 09:12 AM
Estaba mirando un tema acerca de como se pasaba por alto la detección de un anticheat y se me ocurrió la idea de mostrar como se puede hacer un parche básico dentro de un mismo proceso. Es decir tenemos un ejecutable, lo ejecutamos y parcheamos nuestra propia memoria. Esto se puede hacer de varias formas, una de ellas es inyectando una DLL , pero esto es algo más fácil :p

Cómo es una demostración el propio programa se parchea así mismo, por lo que necesitamos saber en que lugar vamos a querer modificar las cosas.
Para eso en el programa puse un bloque condicional que es el que me interesa parchear para poder accederlo aunque no se cumpla la condición.
Por Ejemplo:

if( 0 == 1){ /* no se cumple */ }

Eso no se cumple, pero parcheándolo se logra acceder de todas formas..

Con un desensamblador, abro el ejecutable (el archivo EXE) y procedo a mirar el código ensamblador.


Identifico el OPCODE que me interesa cambiar, en este caso es JZ (0x74), y procedo a obtener la posición en donde se encuentra (dirección de memoria).

Es 0x40106C

En realidad lo que nos interesa es saber el desplazamiento en bytes que hay desde la dirección base del ejecutable hasta el punto en el que queremos parchear.
Se puede tomar en cuenta la sección de código también pero no es la base del ejecutable, recordar al momento de hacer la cuenta..


Bueno el offset (desplazamiento) es 0x6C y 0x1000 de la sección de código.

Bueno sabiendo estas cosas, ya vamos al código..
Con respecto al código, como decía antes, la idea viene de algo que estaba mirando sobre llamadas seguras a funciones para evitar detecciones de un anticheat por ejemplo,,
Por eso fui a crear una función (Check()) que trata de ser en forma figurativa la detección de modificaciones en la memoria.
Aunque en realidad una función de este tipo no tiene mucho sentido en el mismo hilo de ejecución, se debería hacer desde otro..

Y otro concepto que se puede apreciar en todo esto, es la importancia de restaurar la memoria luego de modificarla y lograr lo deseado.
Por eso , en este programa luego de realizar el parche y de llamar a la función de prueba (Target()) , se procede a restaurar la memoria a como estaba antes, para que las detecciones no se disparen.

Véase el bloque condicional donde se desea poder ingresar

...
if(master==MASTERNUM)//Aquí es donde queremos entrar XD
{ ...


Código (cpp) [Seleccionar]


//
// By 85
// Credits: Organner
// elhacker.net
// etalking.com.ar
// 2013
//

///////////////////

#include<windows.h>
#include<stdio.h>

//////////////////////

DWORD dwPatchPlace = 0x00000000;
BYTE Opcode_JZ = 0x74;
BYTE Opcode_JNZ = 0x75;

///////////

inline void Patch(){//Función de parcheadora

if(*(PBYTE)dwPatchPlace!=Opcode_JZ) return;

DWORD dwOldProtect;
   VirtualProtect( (LPVOID)dwPatchPlace,
                   1,
                   PAGE_EXECUTE_WRITECOPY,
                   &dwOldProtect );

WriteProcessMemory( GetCurrentProcess(),
                       (LPVOID)dwPatchPlace,
                       &Opcode_JNZ,
                       1,
                       NULL );

VirtualProtect( (LPVOID)dwPatchPlace,
                   1,
                   dwOldProtect,
                   &dwOldProtect );
}

//
inline void UnPatch(){//Función restauradora

if(*(PBYTE)dwPatchPlace!=Opcode_JNZ) return;

DWORD dwOldProtect;
   VirtualProtect( (LPVOID)dwPatchPlace,
                   1,
                   PAGE_EXECUTE_WRITECOPY,
                   &dwOldProtect );

WriteProcessMemory( GetCurrentProcess(),
                       (LPVOID)dwPatchPlace,
                       &Opcode_JZ,
                       1,
                       NULL );

VirtualProtect( (LPVOID)dwPatchPlace,
                   1,
                   dwOldProtect,
                   &dwOldProtect );
}

////////////////////

void Target(){//Función objetivo para ser alterada

while(1){

#define MASTERNUM 85
int master=0x99999997;
char* ingreso = new char[256];

system("cls");
printf("Ingrese la llave maestra\n");
scanf("%s", ingreso);

if(!strcmpi(ingreso, new char[]= "key85\0")){

master = 85;
}

delete []ingreso;
if(master==MASTERNUM)//Aquí es donde queremos entrar XD
{
printf("FELICITACIONES! USTED HA INGRESADO\n");
printf("\n");
system("pause");
break;
}

// if(GetAsyncKeyState(VK_END)) break;// En otro hilo
if(!strcmpi(ingreso, new char[]= "exit\0")) break;
}
}

//
void Check()//Función que representa un método de seguridad
{
if(*(PBYTE)dwPatchPlace != Opcode_JZ)
{
printf("0x%X\n",*(PBYTE)dwPatchPlace);
printf("Memoria alterada!, se sale del programa..\n");
printf("\n");
system("pause");
ExitProcess(45);
}
}

/////////

int main(){

// We have to replace JZ with JNZ.

dwPatchPlace=(DWORD)GetModuleHandle(NULL);//Retorna la BaseAddress

//Sumamos el offset obtenido del desensamblado
dwPatchPlace+=0x00001000;
dwPatchPlace+=0x6C;

//Logs
printf("0x%X\n",(DWORD)GetModuleHandle(NULL));
printf("0x%X\n",dwPatchPlace);
printf("0x%X\n",*(PBYTE)dwPatchPlace);
printf("\n");
system("pause");

//Parcheamos la memoria antes de llamar a la función
Patch();

//Llamamos a la función objetivo
Target();

//Volvemos a dejar la memoria como estaba antes
// UnPatch();

//Se deja que las comprobaciones de seguridad sigan su curso normalmente
Check();

return 0;
}


Unas imágenes, aunque voy a dejar el proyecto para descargar.


La llamada a UnPatch() está comentada, por eso la detección se dispara..


Un comentario acerca del uso de WriteProcessMemory, no es necesario,,
ya que con simplemente hacer esto:
*(PBYTE)dwPatchPlace= Opcode_JNZ;
es suficiente, ya que es un mismo proceso.
lo que pasa que ambas funciones fueron sacadas de un post de un tal Organner, que algunos deben saber quien es, sólo les cambié una cosa y listo, aunque tampoco son algo especial como para que deban tener un autor XD

Proyecto MSVC6
http://www.mediafire.com/?j7s6a85bp4k5p3t

Este tutorial está orientado a gente principiante en la programación, no sea considerado un tutorial avanzado  ;D

Hasta Luego
#28
Programación C/C++ / MSVCRT hook
24 Febrero 2013, 18:50 PM
Un ejemplo interesante en donde se intercepta a modo de prueba la función STRLWR , no voy a tomar crédito del hook ya que se trata de un simple parche que lo he googleado en 5 segundos XD, lo que si voy a mostrar un par de fotos al respecto..

Como se compiló el ejecutable, para que sea dependiente de la DLL msvcrt


Como se buscó el export en la DLL, se puede observar su índice y su símbolo.


El resto del código no es nada especial, dejo el proyecto en vc6
http://www.mediafire.com/?s9vic23mvrjxrwg


//
// By 85
// elhacker.net
// InterceptAPI: (googleado en 5 segundos XD)
// 2013
//


#pragma comment (lib,"Shlwapi.lib")
#include<windows.h>
#include <Shlwapi.h>
#include<stdio.h>

///////////////////////////////////////////////////////////

char* mystrlwr(char* a){

static bool onlyonce=false;
if(!onlyonce){
onlyonce=true;
printf("\nSTRLWR INTERCEPTADA!\n");
// MessageBox(0,0,0,0);
}
return a;
}

//
BOOL InterceptAPI(HMODULE hLocalModule,const char* c_szDllName,const char* c_szApiName, DWORD dwReplaced)
{
   DWORD dwOldProtect;
   DWORD dwAddressToIntercept=(DWORD)GetProcAddress(GetModuleHandle((char*)c_szDllName),(char*)c_szApiName);
printf("add: %x\n", dwAddressToIntercept);
printf("dll: %s\n", c_szDllName);
printf("api: %s\n", c_szApiName);
// system("pause");
if(!dwAddressToIntercept) return false;
   BYTE *pbTargetCode = (BYTE *) dwAddressToIntercept;
   BYTE *pbReplaced = (BYTE *) dwReplaced;
   VirtualProtect((void *) dwAddressToIntercept, 5, PAGE_WRITECOPY, &dwOldProtect);
   *pbTargetCode++ = 0xE9;        // jump rel32
   *((signed int *)(pbTargetCode)) = pbReplaced - (pbTargetCode +4);
   VirtualProtect((void *) dwAddressToIntercept, 5, PAGE_EXECUTE, &dwOldProtect);
   FlushInstructionCache(GetCurrentProcess(), NULL, NULL);
   return TRUE;
}

//
void Dummy(){

strlwr(new char[] = "85 de elhacker.net :D\0");
}

//
int main(){

Sleep(500);
char l_s11[] = {'m','s','v','c','p','6','0','.','d','l','l',0};
char l_s12[] = {'m','s','v','c','p','7','1','.','d','l','l',0};
char l_s13[] = {'m','s','v','c','p','1','0','0','.','d','l','l',0};
char l_s[] = {'m','s','v','c','r','t','.','d','l','l',0};
char l_api[] = {'_','s','t','r','l','w','r',0};
char l_exe[] = {'m','s','v','c','r','t','_','h','o','o','k','.','e','x','e',0};
char FileName[256];
if(!GetModuleHandle(l_s)) ExitProcess(0);
GetModuleFileName(GetModuleHandle(NULL), FileName, sizeof(FileName));
PathStripPath(FileName);
if (strcmp(FileName, l_exe) == 0){
InterceptAPI(GetModuleHandle(NULL), l_s, l_api, (DWORD)mystrlwr);
               /* else: no se ha interceptado ! */
}
else
{ /* no se ha interceptado ! */ return 0;}
Dummy();
printf("\n");
system("pause");
return 0;
}
#29
Ingeniería Inversa / crackeáte esta cuenta
24 Febrero 2013, 01:15 AM
Bueno este es un crackme , supongo que para muchos puede resultar de nivel principiante. En realidad yo no estoy familiarizado con el cracking, pero encontré un código con una rutina interesante y me pareció que podía servir para un crackme. Si y sólo si están interesados en resolver un crackme más en sus vidas, háganlo , no es mi intención quitarles su tiempo XD. Disculpen si falta algo XD

Nivel:
Principiante, conocimiento de hooking/patching, desensamblado, depurado, etc

Objetivo:
Que salga un cartel contando que el resultado fue exitoso. Se requiere mostrar los datos de usuario que fueron encontrados y explicar como se resolvió. Los datos son un nombre de usuario y la contraseña. Pueden exponer un código si lo desean.

Elementos:
XP SP3 x86, MSVCPP6

Premio: Ninguno. Un código con la rutina utilizada.

Necesitan algo más ? avisen.
http://www.mediafire.com/?bb4xz7ta4qrfr6e

#30
Estaba mirando cuando uno desensambla un programa en c++, no protegido obviamente.... no hablo de un editor hexadecimal ni de ollyDBG, un desensamblado normal que muestre el código  ensamblador.
Algunas strings son detectadas y otras no, en realidad no se si esto se llama ghostwriting porque parece que ghostwriting es otra cosa aparte.

Suponiendo el siguiente código que muestra algunas de las formas más conocidas de declarar cadenas:


//
// By 85
// elhacker.net
// 2013
//

#include<windows.h>
#include<stdio.h>

void Test(){
char test1[] = {'o','c','h','e','n','t','a','y','c','i','n','c','o',0};
char test11[] = {'o','c','h','e','n','t','a','y','c','i','n','c','o',0};
char test111[] = {'o','c','h','e','n','t','a','y','c','i','n','c','o',0};
char test1111[] = {'o','c','h','e','n','t','a','y','c','i','n','c','o',0};
char test11111[] = {'o','c','h','e','n','t','a','y','c','i','n','c','o',0};
char testA[256];
strcat(testA,test1);
strcat(testA," 85\0");
printf(test1);
printf("\n\n");
char test2[] = "ochentaycinco1\0";
char test22[] = "ochentaycinco2\0";
char test222[] = "ochentaycinco3\0";
char test2222[] = "ochentaycinco4\0";
char test22222[] = "ochentaycinco5\0";
const char* testX = "ASD\0";
char testB[256];
strcat(testB,test2);
strcat(testB," 85\0");
printf(test2);
printf("\n\n");
printf(testX);
printf("\n\n");
}

int main()
{
Test();

char test11111[] = {'o','c','h','e','n','t','a','y','c','i','n','c','o',0};
char test22222[] = "ochentaycinco11\0";
const char* testX = "WWW\0";
printf("TEST1\n");
printf(testX);
printf("\n");
printf(new char[] = "wwwwwww\n");
printf(new char[] = "xxxxxxx\n");
printf(new char[] = "AAAAAAA\n");
system("pause");
return 0;
}



podemos ver las cadenas que son detectadas y las que no:




Si alguno quiere agregar algo con referencia al tema XD, en realidad yo si tuviera que recurrir a ocultar cadenas utilizaría algún tipo de encriptamiento interno, como XORSTR, pero esto se usa también



#31
Programación C/C++ / Cadena de bytes a string
22 Febrero 2013, 03:51 AM
Bueno , en realidad el título puede que no lo exprese tal como es..
En este tema alguien había preguntado cómo se pasaba de un array de bytes a convertirlo en un array de chares por decirlo así, y la operación inversa también.
http://foro.elhacker.net/programacion_cc/variable_char_a_byte-t383683.0.html

Entonces usando una lógica que suelo utilizar, lo que hice fue crear una tabla con los 256 bytes, en realidad dos tablas. Una para obtener los bytes y la otra para obtener la posición de un byte en la tabla.
Luego de eso fue tan sólo crear 2 funciones separadas que hagan las operaciones, la una y la inversa, y probarlo


/********************************************************************************************************

// By 85
// boyscout_arg@hotmail.com
// etalking.com.ar
// David Riedel
// 2013

*********************************************************************************************************/

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>

/////
/////////////////////////////////////

char* hextabla[] = { //256 BYTES
"00","01","02","03","04","05","06","07","08","09",
"0A","0B","0C","0D","0E","0F","10","11","12","13",
"14","15","16","17","18","19","1A","1B","1C","1D",
"1E","1F","20","21","22","23","24","25","26","27",
"28","29","2A","2B","2C","2D","2E","2F","30","31",
"32","33","34","35","36","37","38","39","3A","3B",
"3C","3D","3E","3F","40","41","42","43","44","45",
"46","47","48","49","4A","4B","4C","4D","4E","4F",
"50","51","52","53","54","55","56","57","58","59",
"5A","5B","5C","5D","5E","5F","60","61","62","63",
"64","65","66","67","68","69","6A","6B","6C","6D",
"6E","6F","70","71","72","73","74","75","76","77",
"78","79","7A","7B","7C","7D","7E","7F","80","81",
"82","83","84","85","86","87","88","89","8A","8B",
"8C","8D","8E","8F","90","91","92","93","94","95",
"96","97","98","99","9A","9B","9C","9D","9E","9F",
"A0","A1","A2","A3","A4","A5","A6","A7","A8","A9",
"AA","AB","AC","AD","AE","AF","B0","B1","B2","B3",
"B4","B5","B6","B7","B8","B9","BA","BB","BC","BD",
"BE","BF","C0","C1","C2","C3","C4","C5","C6","C7",
"C8","C9","CA","CB","CC","CD","CE","CF","D0","D1",
"D2","D3","D4","D5","D6","D7","D8","D9","DA","DB",
"DC","DD","DE","DF","E0","E1","E2","E3","E4","E5",
"E6","E7","E8","E9","EA","EB","EC","ED","EE","EF",
"F0","F1","F2","F3","F4","F5","F6","F7","F8","F9",
"FA","FB","FC","FD","FE","FF",
};
//////////////

BYTE poshextabla[] = { //256 BYTES
/*1*/(BYTE)'\x00',(BYTE)'\x01',(BYTE)'\x02',(BYTE)'\x03',(BYTE)'\x04',(BYTE)'\x05',(BYTE)'\x06',(BYTE)'\x07',(BYTE)'\x08',(BYTE)'\x09',
/*2*/(BYTE)'\x0A',(BYTE)'\x0B',(BYTE)'\x0C',(BYTE)'\x0D',(BYTE)'\x0E',(BYTE)'\x0F',(BYTE)'\x10',(BYTE)'\x11',(BYTE)'\x12',(BYTE)'\x13',
/*3*/(BYTE)'\x14',(BYTE)'\x15',(BYTE)'\x16',(BYTE)'\x17',(BYTE)'\x18',(BYTE)'\x19',(BYTE)'\x1A',(BYTE)'\x1B',(BYTE)'\x1C',(BYTE)'\x1D',
/*4*/(BYTE)'\x1E',(BYTE)'\x1F',(BYTE)'\x20',(BYTE)'\x21',(BYTE)'\x22',(BYTE)'\x23',(BYTE)'\x24',(BYTE)'\x25',(BYTE)'\x26',(BYTE)'\x27',
/*5*/(BYTE)'\x28',(BYTE)'\x29',(BYTE)'\x2A',(BYTE)'\x2B',(BYTE)'\x2C',(BYTE)'\x2D',(BYTE)'\x2E',(BYTE)'\x2F',(BYTE)'\x30',(BYTE)'\x31',
/*6*/(BYTE)'\x32',(BYTE)'\x33',(BYTE)'\x34',(BYTE)'\x35',(BYTE)'\x36',(BYTE)'\x37',(BYTE)'\x38',(BYTE)'\x39',(BYTE)'\x3A',(BYTE)'\x3B',
/*7*/(BYTE)'\x3C',(BYTE)'\x3D',(BYTE)'\x3E',(BYTE)'\x3F',(BYTE)'\x40',(BYTE)'\x41',(BYTE)'\x42',(BYTE)'\x43',(BYTE)'\x44',(BYTE)'\x45',
/*8*/(BYTE)'\x46',(BYTE)'\x47',(BYTE)'\x48',(BYTE)'\x49',(BYTE)'\x4A',(BYTE)'\x4B',(BYTE)'\x4C',(BYTE)'\x4D',(BYTE)'\x4E',(BYTE)'\x4F',
/*9*/(BYTE)'\x50',(BYTE)'\x51',(BYTE)'\x52',(BYTE)'\x53',(BYTE)'\x54',(BYTE)'\x55',(BYTE)'\x56',(BYTE)'\x57',(BYTE)'\x58',(BYTE)'\x59',
/*10*/(BYTE)'\x5A',(BYTE)'\x5B',(BYTE)'\x5C',(BYTE)'\x5D',(BYTE)'\x5E',(BYTE)'\x5F',(BYTE)'\x60',(BYTE)'\x61',(BYTE)'\x62',(BYTE)'\x63',
/*11*/(BYTE)'\x64',(BYTE)'\x65',(BYTE)'\x66',(BYTE)'\x67',(BYTE)'\x68',(BYTE)'\x69',(BYTE)'\x6A',(BYTE)'\x6B',(BYTE)'\x6C',(BYTE)'\x6D',
/*12*/(BYTE)'\x6E',(BYTE)'\x6F',(BYTE)'\x70',(BYTE)'\x71',(BYTE)'\x72',(BYTE)'\x73',(BYTE)'\x74',(BYTE)'\x75',(BYTE)'\x76',(BYTE)'\x77',
/*13*/(BYTE)'\x78',(BYTE)'\x79',(BYTE)'\x7A',(BYTE)'\x7B',(BYTE)'\x7C',(BYTE)'\x7E',(BYTE)'\x7F',(BYTE)'\x80',(BYTE)'\x81',(BYTE)'\x82',
/*14*/(BYTE)'\x83',(BYTE)'\x84',(BYTE)'\x85',(BYTE)'\x86',(BYTE)'\x87',(BYTE)'\x88',(BYTE)'\x89',(BYTE)'\x8A',(BYTE)'\x8B',(BYTE)'\x8C',
/*15*/(BYTE)'\x8D',(BYTE)'\x8E',(BYTE)'\x8F',(BYTE)'\x90',(BYTE)'\x91',(BYTE)'\x92',(BYTE)'\x93',(BYTE)'\x94',(BYTE)'\x95',(BYTE)'\x96',
/*16*/(BYTE)'\x97',(BYTE)'\x98',(BYTE)'\x99',(BYTE)'\x9A',(BYTE)'\x9B',(BYTE)'\x9C',(BYTE)'\x9D',(BYTE)'\x9E',(BYTE)'\x9F',(BYTE)'\xA0',
/*17*/(BYTE)'\xA1',(BYTE)'\xA2',(BYTE)'\xA3',(BYTE)'\xA4',(BYTE)'\xA5',(BYTE)'\xA6',(BYTE)'\xA7',(BYTE)'\xA8',(BYTE)'\xA9',(BYTE)'\xAA',
/*18*/(BYTE)'\xAB',(BYTE)'\xAC',(BYTE)'\xAD',(BYTE)'\xAE',(BYTE)'\xAF',(BYTE)'\xB0',(BYTE)'\xB1',(BYTE)'\xB2',(BYTE)'\xB3',(BYTE)'\xB4',
/*19*/(BYTE)'\xB5',(BYTE)'\xB6',(BYTE)'\xB7',(BYTE)'\xB8',(BYTE)'\xB9',(BYTE)'\xBA',(BYTE)'\xBB',(BYTE)'\xBC',(BYTE)'\xBD',(BYTE)'\xBE',
/*20*/(BYTE)'\xBF',(BYTE)'\xC0',(BYTE)'\xC1',(BYTE)'\xC2',(BYTE)'\xC3',(BYTE)'\xC4',(BYTE)'\xC5',(BYTE)'\xC6',(BYTE)'\xC7',(BYTE)'\xC8',
/*21*/(BYTE)'\xC9',(BYTE)'\xCA',(BYTE)'\xCB',(BYTE)'\xCC',(BYTE)'\xCD',(BYTE)'\xCE',(BYTE)'\xCF',(BYTE)'\xD0',(BYTE)'\xD1',(BYTE)'\xD2',
/*22*/(BYTE)'\xD3',(BYTE)'\xD4',(BYTE)'\xD5',(BYTE)'\xD6',(BYTE)'\xD7',(BYTE)'\xD8',(BYTE)'\xD9',(BYTE)'\xDA',(BYTE)'\xDB',(BYTE)'\xDC',
/*23*/(BYTE)'\xDD',(BYTE)'\xDE',(BYTE)'\xDF',(BYTE)'\xE0',(BYTE)'\xE1',(BYTE)'\xE2',(BYTE)'\xE3',(BYTE)'\xE4',(BYTE)'\xE5',(BYTE)'\xE6',
/*24*/(BYTE)'\xE7',(BYTE)'\xE8',(BYTE)'\xE9',(BYTE)'\xEA',(BYTE)'\xEB',(BYTE)'\xEC',(BYTE)'\xED',(BYTE)'\xEE',(BYTE)'\xEF',(BYTE)'\xF0',
/*25*/(BYTE)'\xF1',(BYTE)'\xF2',(BYTE)'\xF3',(BYTE)'\xF4',(BYTE)'\xF5',(BYTE)'\xF6',(BYTE)'\xF7',(BYTE)'\xF8',(BYTE)'\xF9',(BYTE)'\xFA',
/*26*/(BYTE)'\xFB',(BYTE)'\xFC',(BYTE)'\xFD',(BYTE)'\xFE',(BYTE)'\xFF'
};

/////


El usuario ingresa una array de bytes y la función arregla el resultado en una cadena de chares, lo hace por medio de buscar en una tabla diseñada específicamente para esta situación.

void Test1(){ //Cadena de bytes a string

BYTE* cadena_de_bytes = (BYTE*)"\x68\x68\x68\x68\x68\x68\xFF\xFF\xFF\xFF\x69";
int largo_de_la_cadena_de_bytes = strlen( (char*)cadena_de_bytes);
char* cadena_de_bytes_en_formato_string = (char*)"000000000000000000000\0";
int pos_string=0;

int i;
for(i=0; i<largo_de_la_cadena_de_bytes; i++)
{
for(int j=0; j<256; j++)
{
if(cadena_de_bytes[i] == poshextabla[j])
{
int pos = j;
for(int k=0;k<2;k++){
cadena_de_bytes_en_formato_string[pos_string++]=hextabla[pos][k];
}
}
}
}
printf(cadena_de_bytes_en_formato_string);
printf("\n");
system("pause");
}

//////////


El usuario ingresa una cadena con números que representan bytes,
la función convierte la cadena a un array de bytes.


void Test2(){//String a cadena de bytes

char* cadena_de_bytes = (char*)"686868686868FFFFFFFF69\0";
BYTE* cadena_de_bytes_resultante = (BYTE*)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
int largo_de_la_cadena_de_bytes = strlen( cadena_de_bytes);
int pos_bytes=0;

int i;
for(i=0; i<largo_de_la_cadena_de_bytes; i+=2)
{
for(int j=0; j<256; j++)
{
if(cadena_de_bytes[i] == hextabla[j][0] && cadena_de_bytes[i+1] == hextabla[j][1])
{
int pos = j;

cadena_de_bytes_resultante[pos_bytes++]=poshextabla[pos];
}
}
}

for(int x=0; x<largo_de_la_cadena_de_bytes/2; x++){
printf("%X",*(cadena_de_bytes_resultante+x));
}
printf("\n");
system("pause");
}

///////



int main(){


Test1();
Test2();

return 0;
}


voy a dejar el proyecto en MSVCPP 6
DESCARGA

está listo para compilar en modo 'Release', pero si sólo quitan el archivo .cpp para usarlo en otro compilador, compilen en modo Release también..

//////////////////////////////////////////////////////////////////////

EDITADO:

Debido a que mi código dejó de ser algo didáctico para ser criticado por ser costoso con la utilización de recursos, entonces lo que hice fue simplificar mi código siguiendo la misma lógica con la cual venía trabajando.

Ahora sólo se dispone de una tabla, dicha tabla se usa como lookup en la primera función y en la segunda se requiere recorrerla pero no más de lo necesario.


atte


/********************************************************************************************************

// By 85
// boyscout_arg@hotmail.com
// etalking.com.ar
// David Riedel
// 2013

*********************************************************************************************************/

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>

/////
/////////////////////////////////////

char* hextabla[] = { //256 BYTES
"00","01","02","03","04","05","06","07","08","09",
"0A","0B","0C","0D","0E","0F","10","11","12","13",
"14","15","16","17","18","19","1A","1B","1C","1D",
"1E","1F","20","21","22","23","24","25","26","27",
"28","29","2A","2B","2C","2D","2E","2F","30","31",
"32","33","34","35","36","37","38","39","3A","3B",
"3C","3D","3E","3F","40","41","42","43","44","45",
"46","47","48","49","4A","4B","4C","4D","4E","4F",
"50","51","52","53","54","55","56","57","58","59",
"5A","5B","5C","5D","5E","5F","60","61","62","63",
"64","65","66","67","68","69","6A","6B","6C","6D",
"6E","6F","70","71","72","73","74","75","76","77",
"78","79","7A","7B","7C","7D","7E","7F","80","81",
"82","83","84","85","86","87","88","89","8A","8B",
"8C","8D","8E","8F","90","91","92","93","94","95",
"96","97","98","99","9A","9B","9C","9D","9E","9F",
"A0","A1","A2","A3","A4","A5","A6","A7","A8","A9",
"AA","AB","AC","AD","AE","AF","B0","B1","B2","B3",
"B4","B5","B6","B7","B8","B9","BA","BB","BC","BD",
"BE","BF","C0","C1","C2","C3","C4","C5","C6","C7",
"C8","C9","CA","CB","CC","CD","CE","CF","D0","D1",
"D2","D3","D4","D5","D6","D7","D8","D9","DA","DB",
"DC","DD","DE","DF","E0","E1","E2","E3","E4","E5",
"E6","E7","E8","E9","EA","EB","EC","ED","EE","EF",
"F0","F1","F2","F3","F4","F5","F6","F7","F8","F9",
"FA","FB","FC","FD","FE","FF",
};





void Test1(BYTE* array_de_bytes, char* cadena_de_bytes_en_formato_string){ //Cadena de bytes a string

for(int i=0; i<(int)strlen( (char*)array_de_bytes); i++)
strcat(cadena_de_bytes_en_formato_string,hextabla[(int)array_de_bytes[i]]);
printf(cadena_de_bytes_en_formato_string);
printf("\n");
}

//////////

void Test2(char* cadena_de_bytes, BYTE* cadena_de_bytes_resultante){//String a cadena de bytes

int bytes=0;
for(int i=0; i<(int)strlen( cadena_de_bytes); i+=2){
for(int j=0; j<256; j++){
if( cadena_de_bytes[i]==hextabla[j][0] && cadena_de_bytes[i+1]==hextabla[j][1] ){
cadena_de_bytes_resultante[bytes++]=j;
j=256;
}
}
}
for(int x=0; x<(int)strlen( cadena_de_bytes)/2; x++)
printf("%X",*(cadena_de_bytes_resultante+x));
printf("\n");
}

///////

int main(){//Programa

BYTE* array_de_bytes = (BYTE*)"\x68\x68\x68\x68\x68\x68\xFF\xFF\xFF\xFF\x69";
char cadena_de_bytes_en_formato_string[256];
memset(cadena_de_bytes_en_formato_string,0,sizeof(cadena_de_bytes_en_formato_string));
printf("TEST1:\n");
Test1(array_de_bytes, cadena_de_bytes_en_formato_string);
system("pause");

char* cadena_de_bytes = (char*)"686868686868FFFFFFFF69\0";
BYTE* cadena_de_bytes_resultante = (BYTE*)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
printf("TEST2:\n");
Test2(cadena_de_bytes, cadena_de_bytes_resultante);
system("pause");

return 0;
}
#32
Programación C/C++ / ATOI + ITOA remake
22 Febrero 2013, 03:32 AM
EDITADO
SE AGREGARON VERSIONES MEJORADAS PARA NO HACER USO DE TABLAS, NI DE FUNCIONES INNECESARIAS COMO LOG, POW, STRLEN, de CTYPE, de STRING, etc
SIN ASIGNACIONES DINÁMICAS, y USANDO MACROS PARA HACER EL CÓDIGO MÁS LEGIBLE..

//////////////////

Estaba repasando un poco cómo había hecho las implementaciones personales de estas funciones,
http://foro.elhacker.net/programacion_cc/atoi_itoa_personalizadas-t358459.0.html;msg1734670#msg1734670

..pero antes de hacer una implementación lo primero es saber como funciona realmente la original.. en base a esto es que decidí arreglar estas funciones siguiendo la misma lógica de construcción, que por cierto es una que suelo usar seguido.

Empezando por ATOI
Código (cpp) [Seleccionar]

/********************************************************************************************************

// By 85
// boyscout_arg@hotmail.com
// etalking.com.ar
// David Riedel
// 2013

*********************************************************************************************************/

#pragma warning (disable:4305)
#pragma warning (disable:4309)
#pragma warning (disable:4244)
#pragma warning (disable:4018)
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>

/////

// Sin necesidad de llamadas innecesarias a funciones de CTYPE, MATH, STRING, etc
// Sin necesidad de Tablas, solo un array con los números enteros que tampoco es necesario
// pero no hace la gran diferencia ;-D

//////////////////////////////////////////////////

//Se requiere pasar una cadena terminada en CERO!.
//Si no se le pasa una cadena terminada en CERO, la función va a buscar el
//primer 0 que encuentre y puede terminar en una sección de memoria contigua
//que no pertenece a la cadena pasada como parámetro.
int mi_atoi(const char* str)//Respetar el tipo de parámetro (Sólo cadenas)
{
int len, ocurrencias =0, sig=0;
for(len=0; str[len]; len++);
for(int a=0; a<len;a++) if((str[a]>=48&&str[a]<=57)) ocurrencias++;
if(ocurrencias==0) return 0;
if((sig=str[0]=='+')||(sig=str[0]=='-')) ocurrencias+=1;
if(ocurrencias<len) return 0;//Casos "11f" son 0
if(len==1) return str[0]-'0';
int ac=0, v1, cifras = len,m = 1;
for(int x=0;x<((cifras-1)-sig);x++) m*=10;
for(int i=sig;i<cifras;i++){//Factoriza y acumula
v1=str[i]-'0';
v1*=m;
ac+=v1;
m/=10;
}
if(str[0]=='-') ac*=-1;
return ac;
}

////////////////////

int main(){

// char str = 'B';
// int entero = mi_atoi(&str);

// char* str = "asdasd\0";
// int entero = mi_atoi(str);

// char* str = "8a3\0";
// int entero = mi_atoi(str);

// char* str = "83312321\0";
// int entero = mi_atoi(str);

// char* str = "000000099\0";
// int entero = mi_atoi(str);

// char* str = "9\0";
// int entero = mi_atoi(str);

// char* str = "20\0";
// int entero = mi_atoi(str);

// char* str = "500\0";
// int entero = mi_atoi(str);

// char* str = "+500\0";
// int entero = mi_atoi(str);

// char* str = "0500\0";
// int entero = mi_atoi(str);

// char* str = "0\0";
// int entero = mi_atoi(str);

// char* str = "10f\0";
// int entero = mi_atoi(str);

// char* str = "01ff\0";
// int entero = mi_atoi(str);

// char* str = "0f\0";
// int entero = mi_atoi(str);

// char* str = "+12\0";
// int entero = mi_atoi(str);

// char* str = "+12\0";
// int entero = mi_atoi(str);

// char* str = "03232\0";
// int entero = mi_atoi(str);

// printf("%d", entero);


printf("%d\n",mi_atoi("-110"));
printf("%d\n",mi_atoi("-10"));
printf("%d\n",mi_atoi("0"));
printf("%d\n",mi_atoi("1"));
printf("%d\n",mi_atoi("-1"));
printf("%d\n",mi_atoi("-11"));
printf("%d\n",mi_atoi("-2"));
printf("%d\n",mi_atoi("-200"));
printf("%d\n",mi_atoi("-220"));
printf("%d\n",mi_atoi("+0"));
printf("%d\n",mi_atoi("-0"));
printf("%d\n",mi_atoi("+1"));
printf("%d\n",mi_atoi("+33"));
printf("%d\n",mi_atoi("-330"));
printf("%d\n",mi_atoi("-3000"));
// printf("%d\n",mi_atoi("-1"));
// printf("%d\n",mi_atoi("-200"));
// printf("%d\n",mi_atoi("-220"));
printf("%d\n",mi_atoi("+12"));

printf("\n");
system("pause");
return 0;
}


El problema que enfrenta esta función es cuando alguien trata de pasarle un parámetro que no es una cadena, por ejemplo un 'char'


char str = 'B';
int entero = mi_atoi(&str);


se lo hace de esa forma especificando la dirección de la variable, pero en la función original ATOI esto devuelve 0, según mis pruebas.

y al respecto revisaba también unos post en los cuales se hablaba acerca de la utilidad del operador ternario, como se puede observar son muy útiles para usarlos como índices en matrices y vectores.

http://foro.elhacker.net/programacion_cc/calcular_el_maximo_usando_operador-t383707.0.html
http://foro.elhacker.net/programacion_cc/aporte_operador_condicional-t383420.0.html


int tab1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
val1 =  tab1[(str[i]=='0' ? 9:(((int)str[i]-48)-1))];


para los principiantes les explico que la evaluación que se hace es que si el caractér es 0 se procede a usar el número 9 como índice, de otra forma se usa otro índice..

Bueno y la implementación de ITOA es esta:
Código (cpp) [Seleccionar]

/********************************************************************************************************

// By 85
// boyscout_arg@hotmail.com
// etalking.com.ar
// David Riedel
// 2013

*********************************************************************************************************/

#pragma warning (disable:4305)
#pragma warning (disable:4309)
#pragma warning (disable:4244)
#pragma warning (disable:4018)
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>

/////

// Sin necesidad de llamadas innecesarias a funciones de CTYPE, MATH, STRING, etc
// Sin necesidad de Tablas, sólo un array con los números enteros que tampoco es necesario
// pero no hace la gran diferencia ;-D

//////////////////////////////////////////////////

char* mi_itoa(int num, char* str)
{
int sig = -1;
if(num<0){
num*=-1;
if(num<10){
str[0]='-'; str[1]='0'+num; str[2]=0; return str;
} else {
sig=1;
}
}
else if(num==0){
str[0]='0'; str[1]=0; return str;
} else {
if(num<10){
str[0]='0'+num; str[1]=0; return str;
} else {
sig=0;
}
}
if(sig!=-1){
int copia= num, m = 1, cifras = 1;
for(;copia>=10;copia/=10) cifras++;
for(int x=0;x<(cifras-1);x++) m*=10;
float v1=num;
int v2=0, v3=num;
if(sig) str[0]='-';
for(int i=0; i<cifras; i++){//Descompone en factores
v1/=m;
v2=(int)v1*m;
v3-=v2;
m/=10;
str[i+sig]=48+(int)v1;
v1=v3;
}
str[i+sig]=0;//Si str está a 0 no es necesario..
}
return str;
}

///////////////////

int main(){


char str[256];

// mi_itoa(321312,str);
// printf(str);

// itoa(02321,str,10);
// printf(str);

// mi_itoa(02321,str);
// printf(str);

// mi_itoa(-12321,str);
// printf(str);

// itoa(-012321,str,10);
// printf(str);

// mi_itoa(-012321,str,10);
// printf(str);

// mi_itoa(555,str);
// printf(str);

// mi_itoa(0,str);
// printf(str);

// mi_itoa(1,str);
// printf(str);

// mi_itoa(500,str);
// printf(str);

printf(mi_itoa(+321312,str));printf("\n");
printf(mi_itoa(-321312,str));printf("\n");
printf(mi_itoa(321312,str));printf("\n");
printf(mi_itoa(+0,str));printf("\n");
printf(mi_itoa(0,str));printf("\n");
printf(mi_itoa(-0,str));printf("\n");
printf(mi_itoa(+1,str));printf("\n");
printf(mi_itoa(1,str));printf("\n");
printf(mi_itoa(-1,str));printf("\n");
printf(mi_itoa(10,str));printf("\n");
printf(mi_itoa(+10,str));printf("\n");
printf(mi_itoa(-10,str));printf("\n");
printf(mi_itoa(-110,str));printf("\n");
printf(mi_itoa(-100,str));printf("\n");

printf(mi_itoa(-5000,str));printf("\n");
printf(mi_itoa(-55555,str));printf("\n");
printf(mi_itoa(550,str));printf("\n");
printf(mi_itoa(500,str));printf("\n");
printf(mi_itoa(+330,str));printf("\n");

printf(mi_itoa(-000,str));printf("\n");
printf(mi_itoa(+000,str));printf("\n");
// printf(mi_itoa(+00009,str));printf("\n");
printf(mi_itoa(+109,str));printf("\n");
printf(mi_itoa(-109,str));printf("\n");
// printf(mi_itoa(-09,str));printf("\n");
// printf(mi_itoa(+09,str));printf("\n");
printf(mi_itoa(-999,str));printf("\n");
// printf(mi_itoa(-00000999,str));printf("\n");

printf("\n");
system("pause");
return 0;
}

/////



cualquier problema diganme, sólo trataba de crear un par de funciones que funcionen tal cual las originales, y usando la misma lógica que venía usando.

les dejo el proyecto en MSVC++ 6 ya que es el compilador que tengo para esta clase de minipruebas, tengo el 2010 también..

http://www.mediafire.com/?wbscy4bu2vrq273
#33
Hola, estaba mirando casualmente dos temas, uno que se refiere al operador ternario y otro sobre como obtener el mayor de 3 números..

y en el tema del operador ternario se hablaba acerca de la utilidad de este operador, en este caso compruebo que resulta conveniente usarlo..
por eso vean la función 2 parece la más conveniente aunque en realidad a mi forma de verlo las 3 terminan realizando comparaciones, que a nivel de ensamblador resultan simples restas..
si alguno sabe como el procesador procesa la información o al menos sabe como se realizan las comparaciones, sabrá a que me refiero.


int max_valor_de_tres_1(int a,int b,int c){

if(a>b)
if(a>c)
return a;
if(b>a)
if(b>c)
return b;
if(c>a)
if(c>b)
return c;
return 0;
}



int max_valor_de_tres_2(int a,int b,int c){

return a>b? (a>c?a:(b>c?b:c)) : (b>c?b:c);
}



int max_valor_de_tres_3(int a,int b,int c){

if((a-b>0)&&(a-c>0)){return a;}
if((b-a>0)&&(b-c>0)){return b;}
if((c-a>0)&&(c-b>0)){return c;}
return 0;
}






int main(){
int a,b,c;
a = 3;
b=4;
c=5;
int res = max_valor_de_tres_3(a,b,c);
printf("%d",res);
printf("\n");
system("pause");

return 0;
}


Estos eran los temas
http://foro.elhacker.net/programacion_cc/aporte_operador_condicional-t383420.0.html

http://foro.elhacker.net/programacion_cc/help_calcular_maximo_de_3_numeros_usando_funcion-t383403.0.html