Ejecución de Archivos desde Memoria [Base Relocation]

Iniciado por [Zero], 18 Agosto 2009, 19:32 PM

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

[Zero]

Pero estás usando el primero o el segundo ejemplo? Yo tuve problemas con el primero pero lo solucioné con RtlAdjustTokenPrivileges, dando permisos a esa zona de SeDebugPrivilege. Con el primero no tuve problema, VirtualAlloc debería de dejar bien los permisos en esa zona, prueba a llamar a VirtualProtect a ver, pero es extraño  :P.

Saludos

"El Hombre, en su orgullo, creó a Dios a su imagen y semejanza.”
Nietzsche

plaganegra

use VirtualProtect y RtlAdjustTokenPrivileges pero nada.
A que te refieres con el primero o el segundo ejemplo, no se cual es cada uno  ;D
De pronto uno es el que llamaste Loader y el otro es el ExecutableRunner, el que carga el loader?
Saludos ;)

[Zero]

Si te fijas en el post principal hay dos apartados, un Ejecucion de Archivos con Relocation Table y otro sin ella. Por lo que dices del "Loader" supongo que te bajaste el segundo. Ese código es bastante inestable, tendrás que depurarlo bastante si quieres que funcione con todos los ejecutables. Por ejemplo falla obteniendo las apis de la IAT y al cargar la IAT, y supongo habrá algun otro fallo  :P. Lo mejor es que intentes hacer uno de 0 basándote en ese, ya que no es un código ejemplar  :xD.

Saludos  :P

"El Hombre, en su orgullo, creó a Dios a su imagen y semejanza.”
Nietzsche


The Swash

#14
A mi parecer la dependencia exacta de que todas las direcciónes físicas sean realocadas da un porcentaje muy alto de fallar al cargar un ejecutable en otro espacio de memoria diferente a su ImageBase, tenía que prácticar Relocations así que decidí intentarlo en Delphi y vaya trabajo me ha dado. Gracias [Zero]
Código (delphi) [Seleccionar]
IMAGE_IMPORT_DESCRIPTOR = packed record
    OriginalFirstThunk: DWORD;
    TimeDateStamp: DWORD;
    ForwarderChain: DWORD;
    Name: DWORD;
    FirstThunk: DWORD;
end;

IMAGE_RELOCATIONS = packed record
    PageRVA: DWORD;
    Size:    DWORD;
end;

type
TArrayOfByte = array of byte;
TArrayOfISH = array of TIMAGESECTIONHEADER;
PIMAGEIMPORTDESCRIPTOR = ^IMAGE_IMPORT_DESCRIPTOR;
PIMAGERELOCATIONS = ^IMAGE_RELOCATIONS;

function RVATOOFFSET(RVA:DWORD): DWORD;
var
i,n: integer;
begin
     for i:= 0 to IFH.NumberOfSections-1 do
     begin
          n:= (ish[i].VirtualAddress + ish[i].SizeOfRawData)-RVA ;
          if n > 0 then
          begin
               Result:=(RVA - ish[i].VirtualAddress) + ish[i].PointerToRawData;
               break;
          end;
     end;
     if RVA < ish[0].VirtualAddress then Result:= RVA;
end;


procedure Execute();
var
IDH:         PIMAGEDOSHEADER;
IOH:         PIMAGEOPTIONALHEADER;
IDD:         Array[0..15] of PIMAGEDATADIRECTORY;
IID:         PIMAGEIMPORTDESCRIPTOR;
IR:          PIMAGERELOCATIONS;
aBuffer:     TArrayOfByte;
FileLen:     DWORD;
hFile:       THANDLE;
BytesRead:   DWORD;
Signature:   PDWORD;
i:           DWORD;
Acumulador:  DWORD;
BaseAddress: Pointer;
lFunction:   PDWORD;
TempAddress: DWORD;
EP:          DWORD;
aBlock:      DWORD;
rBlock:      PWORD;
dType:       DWORD;
Offset:      PDWORD;
Delta:       DWORD;
rOffset:     DWORD;
Ordinal:     DWORD;
GPA:         function(hModule: Cardinal; Ordinal: Cardinal): Pointer; stdcall;
begin
     hFile:= CreateFileA('C:\Archivos de programa\Opera\opera.exe',GENERIC_READ, FILE_SHARE_READ,nil, OPEN_EXISTING,0,0);
     If hFile <> INVALID_HANDLE_VALUE then
     begin
          FileLen:= GetFileSize(hFile,nil);
          SetLength(aBuffer,FileLen);
          ReadFile(hFile,aBuffer[0],FileLen,BytesRead,nil);
     end;
     GPA:= GetProcAddress(GetModuleHandle('kernel32'),'GetProcAddress');
     CloseHandle(hFile);
     IDH:= Pointer(aBuffer);
     if IDH.e_magic = IMAGE_DOS_SIGNATURE then
     begin
          Signature := @aBuffer[IDH._lfanew];
          if Signature^ = IMAGE_NT_SIGNATURE then
          begin
               IFH:= @aBuffer[IDH._lfanew + 4];
               IOH:= @aBuffer[IDH._lfanew + 24];
               Acumulador:= 0;
               for i:=0 to 15 do
               begin
                    IDD[i]:= @aBuffer[IDH._lfanew + 120 + Acumulador];
                    Acumulador:= Acumulador+8;
               end;
               SetLength(ISH, IFH.NumberOfSections-1);
               Acumulador := 0;
               for i:=0 to IFH.NumberOfSections-1 do
               begin
                    CopyMemory(@ISH[i], @aBuffer[IDH._lfanew + 248 + Acumulador], 40);
                    Acumulador:= Acumulador + 40;
               end;
               BaseAddress:= VirtualAlloc(nil, IOH.SizeOfImage, MEM_RESERVE or MEM_COMMIT, PAGE_EXECUTE_READWRITE);
               CopyMemory(BaseAddress, @aBuffer[0], IOH.SizeOfHeaders);
               for i:=0 to IFH.NumberOfSections-1 do
               begin
                    CopyMemory(Pointer(DWORD(BaseAddress)+ISH[i].VirtualAddress), @aBuffer[ISH[i].PointerToRawData], ISH[i].SizeOfRawData);
               end;
                              Delta:= DWORD(BaseAddress) - IOH.ImageBase;
               rOffset:= RVATOOFFSET(IDD[5].VirtualAddress);
               IR:= @aBuffer[rOffset];
               While(IR.PageRVA <> 0) do
               begin
                    aBlock:= (IR.Size - 8)div 2;
                    rBlock:= Pointer(DWORD(IR) + 8);
                    While(aBlock > 0) do
                    begin
                         dType:= (rBlock^ and $F000) div $1000;
                         Offset:= Pointer(DWORD(rBlock^ and $FFF) + IR.PageRVA + DWORD(BaseAddress));
                         if dType = 3 then
                         begin
                              Offset^:= Offset^ + Delta;
                         end;
                         rBlock:= Pointer(DWORD(rBlock)+ 2);
                         aBlock:= aBlock - 1;
                    end;
                    IR:= Pointer(DWORD(IR)+ IR.Size);
               end;
               IID:= @aBuffer[RVATOOFFSET(IDD[1].VirtualAddress)];
               While(IID.Name <> 0) do
               begin
                    lFunction:= Pointer(DWORD(BaseAddress) + IID.FirstThunk);
                    While(lFunction^ <> 0) do
                    begin
                         if lFunction^ > $80000000 then
                         begin
                              Ordinal:= lFunction^-$80000000;
                              TempAddress:= DWORD(GPA(LoadLibraryA(@aBuffer[RVATOOFFSET(IID.Name)]),Ordinal));
                         end else
                         begin
                              TempAddress:= DWORD(GetProcAddress(LoadLibraryA(@aBuffer[RVATOOFFSET(IID.Name)]),@aBuffer[RVATOOFFSET(lFunction^+2)]));
                         end;
                         lFunction^:= TempAddress;
                         lFunction:= Pointer(DWORD(lFunction)+4);
                    end;
                    IID:= Pointer(DWORD(IID)+20);
               end;
               EP:= IOH.AddressOfEntryPoint + DWORD(BaseAddress);
               asm
               mov eax, EP
               jmp eax;
               end;
          end;
     end;
end;


PD: Algunos errores corregidos, añadido soporte para importación por ordinales.

roilivethelife

¿Seria posible que resubieseis los links? Gracias y un saludo

[Zero]

Que faena, no  conservo los archivos, si alguien los conserva y los pudiera resubir sería perfecto. De todas formas, con el código puedes compilarlo perfectamente, croe que no faltaba nada, incluso el ejemplo está.

Saludos

"El Hombre, en su orgullo, creó a Dios a su imagen y semejanza.”
Nietzsche

roilivethelife

Que rabia... yo lo tuve hace tiempo en el pc pero formateé  :( :(

Intentaré compilarlo entonces, pero ¿que programa uso? Visual Studio?

salu2

[Zero]

Sí, con Visual Studio, la 2008 o la 2010 deberían de ir perfectas.

Saludos

"El Hombre, en su orgullo, creó a Dios a su imagen y semejanza.”
Nietzsche

Karman

#19
hay dos problemas con el código, 1º que no tiene en cuenta los imports que usan ordinal en vez de nombres y el segundo son los Forwarder imports

acá tienen una versión que hice de un "full"  GetProcAddress manual:

FARPROC WINAPI GetProcAddress(HMODULE hModule,LPCSTR lpProcName){
 DWORD index,dwExportSize,dwOrdinal=0;
 if(!hModule)return NULL;
 PIMAGE_DOS_HEADER pDosHeader;
 PIMAGE_NT_HEADERS pNTHeader;
 PIMAGE_EXPORT_DIRECTORY pExportDir;
pDosHeader=(PIMAGE_DOS_HEADER)hModule;
if(pDosHeader->e_magic!=IMAGE_DOS_SIGNATURE)
return NULL;
 pNTHeader=RVAPTR(PIMAGE_NT_HEADERS,pDosHeader,pDosHeader->e_lfanew);
if(pNTHeader->Signature!=IMAGE_NT_SIGNATURE)
return NULL;
 pExportDir=RVAPTR(PIMAGE_EXPORT_DIRECTORY,pDosHeader,pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
 dwExportSize=pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
 if(!pExportDir)
   return NULL;
 PCHAR* pszName=RVAPTR(PCHAR*,pDosHeader,pExportDir->AddressOfNames);
 PDWORD pdwAddress=RVAPTR(PDWORD,pDosHeader,pExportDir->AddressOfFunctions);
 PWORD pwOrdinals=RVAPTR(PWORD,pDosHeader,pExportDir->AddressOfNameOrdinals);
 if(!pszName||!pwOrdinals||!pdwAddress)
   return NULL;
 if(HIWORD(lpProcName)==0){
   // Look up by ordinal
   dwOrdinal=(LOWORD((DWORD)lpProcName)-pExportDir->Base);
 }else{
   // Look up by name
   for(index=0;index<pExportDir->NumberOfNames;index++){
     if(!lstrcmpA(RVAPTR(PCHAR,pDosHeader,pszName[index]),lpProcName)){
       dwOrdinal=pwOrdinals[index];
       break;
     }
   }
 }
 //Get Func Address
 DWORD dwFunction=RVAPTR(DWORD,pDosHeader,pdwAddress[dwOrdinal]);
 // Let's Check if is Forwarder
 if((dwFunction>(ULONG_PTR)pExportDir)&&(dwFunction<((ULONG_PTR)pExportDir+dwExportSize))){
   CHAR ForwarderDllName[MAX_PATH],*ForwardImportName;USHORT len;
   ForwardImportName=strchr((LPSTR)dwFunction,'.');
   len=ForwardImportName++-(LPSTR)dwFunction;
   strncpy(ForwarderDllName,(LPSTR)dwFunction,len);
   strcpy(&ForwarderDllName[len],".dll");
   // Find the module associated to it (should be already loaded)
   return GetProcAddress(GetModuleHandleA(ForwarderDllName),ForwardImportName);
 }
 return (FARPROC)dwFunction;
}


capaz lo pueden adaptar...

S2