Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Conexión con bases de datos (https://www.clubdelphi.com/foros/forumdisplay.php?f=2)
-   -   extraer ficheros de base de datos sqlite campo blob (https://www.clubdelphi.com/foros/showthread.php?t=84163)

juank1971 16-09-2013 23:11:48

extraer ficheros de base de datos sqlite campo blob
 
Hola amigos:

Tengo guardado en sqlite en un campo blob ficheros .pdf, .doc, etc, existe alguna manera de estraer el contenido de ese campo blob en memoria y ejecutar el fichero o necesariamente para extrarer el fichero debo sacarlo del sqlite al disco duro verlo y luego lo elimino??

gracias juank

juank1971 16-09-2013 23:19:59

por si no me expliqué bien cuando digo verlo, quise decir ejecutarlo o sea abrirlo con la aplicacaion que le corresponda.

Pericles 01-10-2013 23:47:02

Hola, lo aconsejable seria crear un Stream con los datos y bajarlos en un archivo temporal para ejecutarlo(luego se elimina)
De otra manera es un problema por el tema de seguridad de los sistemas operativos entre otras cosas(ademas de ser una tarea ardua de realizar)

Estuve revisando bastante... encontre esta clase.. y probe con la siguiente llamada.. pero solo problemas! jaja
creo que es muy complicado y no tiene mucho sentido (quizas exista algun requerimiento lo exija? ya seria casi como programar un virus.. no será para eso? jajaj)

Código Delphi [-]
{
  Unit Name: uExecFromMem
  Author: steve10120
  Description: Run an executable from another's memory.
  Credits: Tan Chew Keong: Dynamic Forking of Win32 EXE; Author of BTMemoryModule: PerformBaseRelocation().
  Reference: security.org.sg/code/loadexe.html
  Release Date: 26th August 2009
  Website: hackhound.org
  History: First try
}

unit uExecFromMem;

interface

uses Windows;

function ExecuteFromMem(szFilePath:string; pFile:Pointer):  DWORD;

type
  PImageBaseRelocation = ^TImageBaseRelocation;
  TImageBaseRelocation = packed record
     VirtualAddress: DWORD;
     SizeOfBlock: DWORD;
  end;

function NtUnmapViewOfSection(ProcessHandle:DWORD; BaseAddress:Pointer): DWORD; stdcall; external 'ntdll';

implementation

procedure PerformBaseRelocation(f_module: Pointer; INH:PImageNtHeaders; f_delta: Cardinal); stdcall;
var
  l_i: Cardinal;
  l_codebase: Pointer;
  l_relocation: PImageBaseRelocation;
  l_dest: Pointer;
  l_relInfo: ^Word;
  l_patchAddrHL: ^DWord;
  l_type, l_offset: integer;
begin
  l_codebase := f_module;
  if INH^.OptionalHeader.DataDirectory[5].Size > 0 then
  begin
    l_relocation := PImageBaseRelocation(Cardinal(l_codebase) + INH^.OptionalHeader.DataDirectory[5].VirtualAddress);
    while l_relocation.VirtualAddress > 0 do
    begin
      l_dest := Pointer((Cardinal(l_codebase) + l_relocation.VirtualAddress));
      l_relInfo := Pointer(Cardinal(l_relocation) + 8);
      for l_i := 0 to (trunc(((l_relocation.SizeOfBlock - 8) / 2)) - 1) do
      begin
        l_type := (l_relInfo^ shr 12);
        l_offset := l_relInfo^ and $FFF;
        if l_type = 3 then
        begin
          l_patchAddrHL := Pointer(Cardinal(l_dest) + Cardinal(l_offset));
          l_patchAddrHL^ := l_patchAddrHL^ + f_delta;
        end;
        inc(l_relInfo);
      end;
      l_relocation := Pointer(cardinal(l_relocation) + l_relocation.SizeOfBlock);
    end;
  end;
end;

function AlignImage(pImage:Pointer):Pointer;
var
  IDH:          PImageDosHeader;
  INH:          PImageNtHeaders;
  ISH:          PImageSectionHeader;
  i:            WORD;
begin
  IDH := pImage;
  INH := Pointer(DWORD(pImage) + IDH^._lfanew);
  GetMem(Result, INH^.OptionalHeader.SizeOfImage);
  ZeroMemory(Result, INH^.OptionalHeader.SizeOfImage);
  CopyMemory(Result, pImage, INH^.OptionalHeader.SizeOfHeaders);
  for i := 0 to INH^.FileHeader.NumberOfSections - 1 do
  begin
    ISH := Pointer(DWORD(pImage) + IDH^._lfanew + 248 + i * 40);
    CopyMemory(Pointer(DWORD(Result) + ISH^.VirtualAddress), Pointer(DWORD(pImage) + ISH^.PointerToRawData), ISH^.SizeOfRawData);
  end;
end;

function ExecuteFromMem(szFilePath:string; pFile:Pointer):DWORD;
var
  PI:           TProcessInformation;
  SI:           TStartupInfo;
  CT:           TContext;
  IDH:          PImageDosHeader;
  INH:          PImageNtHeaders;
  dwImageBase:  DWORD;
  pModule:      Pointer;
  dwNull:       DWORD;
begin
  Result := 0;
  IDH := pFile;
  if IDH^.e_magic = IMAGE_DOS_SIGNATURE then
  begin
    INH := Pointer(DWORD(pFile) + IDH^._lfanew);
    if INH^.Signature = IMAGE_NT_SIGNATURE then
    begin
      FillChar(SI, SizeOf(TStartupInfo), #0);
      FillChar(PI, SizeOf(TProcessInformation), #0);
      SI.cb := SizeOf(TStartupInfo);
      if CreateProcess(nil, PChar(szFilePath), nil, nil, FALSE, CREATE_SUSPENDED, nil, nil, SI, PI) then
      begin
        CT.ContextFlags := CONTEXT_FULL;
        if GetThreadContext(PI.hThread, CT) then
        begin
          ReadProcessMemory(PI.hProcess, Pointer(CT.Ebx + 8), @dwImageBase, 4, dwNull);
          if dwImageBase = INH^.OptionalHeader.ImageBase then
          begin
            if NtUnmapViewOfSection(PI.hProcess, Pointer(INH^.OptionalHeader.ImageBase)) = 0 then
              pModule := VirtualAllocEx(PI.hProcess, Pointer(INH^.OptionalHeader.ImageBase), INH^.OptionalHeader.SizeOfImage, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE)
            else
              pModule := VirtualAllocEx(PI.hProcess, nil, INH^.OptionalHeader.SizeOfImage, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
          end
          else
            pModule := VirtualAllocEx(PI.hProcess, Pointer(INH^.OptionalHeader.ImageBase), INH^.OptionalHeader.SizeOfImage, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
          if pModule <> nil then
          begin
            pFile := AlignImage(pFile);
            if DWORD(pModule) <> INH^.OptionalHeader.ImageBase then
            begin
              PerformBaseRelocation(pFile, INH, (DWORD(pModule) - INH^.OptionalHeader.ImageBase));
              INH^.OptionalHeader.ImageBase := DWORD(pModule);
              CopyMemory(Pointer(DWORD(pFile) + IDH^._lfanew), INH, 248);
            end;
            WriteProcessMemory(PI.hProcess, pModule, pFile, INH.OptionalHeader.SizeOfImage, dwNull);
            WriteProcessMemory(PI.hProcess, Pointer(CT.Ebx + 8), @pModule, 4, dwNull);
            CT.Eax := DWORD(pModule) + INH^.OptionalHeader.AddressOfEntryPoint;
            SetThreadContext(PI.hThread, CT);
            ResumeThread(PI.hThread);
            FreeMem(pFile, INH^.OptionalHeader.SizeOfImage);
            Result := PI.hThread;
          end;
        end;
      end;
    end;
  end;
end;

end.


Código Delphi [-]

procedure TForm1.Button1Click(Sender: TObject);
var
 ms:TMemoryStream;

begin

  ms:=TMemoryStream.Create;
  TBlobField(ADOQuery1archivos).SaveToStream(ms);
  ms.Position := 0;

  // ?????
//ExecuteFromMem(Application.ExeName,'',ms.Memory); // pointing to an existing executable

ExecuteFromMem(Application.ExeName,ms.Memory); // pointing to an existing executable

  //prueba de bajada a archivo para ver si se grabo correctamente y funciona...
  //ms.SaveToFile('c:\prueba.exe');
  //winexec('c:\prueba.exe',SW_SHOWNORMAL);

  ms.Free;
 end;



Saludos
Nicolas Perichon

juank1971 03-10-2013 22:55:34

no es virus es para mi hermano de electrónica
 
Ja, No NO es para un virus:
Gracias amigo voy a probar esta noche si mi hija me deja un tiempo de máquina, Gracias.


Ees para una aplicación que le estoy haciendo a mi hermano que me dijo que quería tener todo lo que el necesita de electrónica en una sola base de datos, que sea portable, y tener siempre a donde quiera que va su minienciclopedia que el le pueda agregar cosas y hacer búsquedas. En eso incluye .doc, pdf, html, exe,jpg,bmp etc todo lo que usa para su trabajo de electrónica.

Le programé la aplicación en delphi XE4 todo con la base de datos en sqlite3 funciona muy bien, lo que mejor me quedo es que, escaneo el texto de todos los ficheros pdf,word,xls y lo guardo en un campo aparte entonces se pueden hacer búsquedas de subcadenas de textos en cualquier tipo de fichero y eso lo hace muy rápido incluso mejor que windows porque windows no busca txt dentro de los pdf.

Con este procedimiento que te pongo abajo, extraigo los ficheros (campo blob) de la base de datos al hacer dbclick en el grid que muestra los nombres, y funciona bien pero tengo que crearlo en el disco, o sea lo saco de la base sqlite para el disco duro y luego lo ejecuto con el ShellExecute, todo ok, pero después tengo que eliminar el fichero, y si esta en uso no puedo, lo tengo que ir guardando en un arreglo los nombres con los caminos respectivos y los elimino al cerrar la aplicación que es un poco incómodo, y si hay muchos abiertos se demora cerrando, por eso estaba tratando de buscar algo como lo que me mandas a ver cómo funciona en memoria, o quizás combinados a ver que pasa.

Gracias muchas , como decía mi abuelo Salud y Pesetas para ti


Código Delphi [-]
.........................

  File1 := datamodule1.Qfichero.CreateBlobStream( datamodule1.Qfichero.FieldByName('fichero'), bmReadWrite);

try
  File1.Seek(0, 0);
   try
     FS := TFileStream.Create(n, fmCreate);
   except
      //on E: Exception do showmessage('dd');

   end;

  FechaFicheros[indice].Nombre := ExtractFileName(n);

  try
    // Copiar el contenido
    try
     FS.CopyFrom(File1, File1.Size);
    except

    end;

    ShellExecute(Form2.Handle,nil,PChar(n),'','',SW_SHOWNORMAL);

  finally
   try
     FS.free;
   except

   end;

  end;
finally
  try
    File1.free;
  except

  end;

end;
end;


La franja horaria es GMT +2. Ahora son las 17:15:24.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi