Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 27-08-2015
deliriun deliriun is offline
Miembro
 
Registrado: ago 2014
Posts: 51
Poder: 10
deliriun Va por buen camino
Question Buscando texto en la memoria de un programa.

Hola qué tal?

Pues me supongo que ha muchos les sonara conocido el programa "Cheat Engine" y las multiples funciones que tiene y no
solamente que se usan para crear Trainers ( aunque siendo sinceros es lo más típico ) de hecho tiene varias funciones que me
han llamado la atención como por ejemplo la opción que sirve para acelerar un programa seleccionado a cierta velocidad...
Pero realmente vengo a hacer la consulta por la busqueda de "String" ... En Cheat Engine se selecciona un programa y se puede buscar
distintos tipos de variables, Floats, Double, Strings entre otros...

Quisiera saber como hacer un programa similar que busque un String y que halle su address para posteriormente modificar su valor..
Espero no sea mucho pedir...

Gracias
Responder Con Cita
  #2  
Antiguo 27-08-2015
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.039
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Ábrelo en modo binario, hay varios ejemplos por los foros.
Responder Con Cita
  #3  
Antiguo 27-08-2015
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Hola.

Si como dice Casimiro, se ha tratado varias veces. Ahora mismo recuerdo este ejemplo.

Saludos
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....
Responder Con Cita
  #4  
Antiguo 27-08-2015
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.039
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Buena memoria
Responder Con Cita
  #5  
Antiguo 27-08-2015
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Creo que a lo que se refiere deliriun es a buscar y reemplazar texto el la memoria de otro proceso.

Para ello deberás abrir el proceso y usar las AIPs ReadProcessMemory y WriteProcessMemory. Con la primera lees un bloque de memoria del proceso "atacado" en él debes buscar tu cadena, reemplazarla (en este caso el número de caracteres reemplazados no puede superar NUNCA a la cadena original) y luego escribir el bloque de nuevo en el proceso en cuestión con WriteProcessMemory. Para buscar y reemplazar el texto puedes usar el código que propone ecfisa o este.


Saludos.

Última edición por escafandra fecha: 27-08-2015 a las 01:26:56.
Responder Con Cita
  #6  
Antiguo 27-08-2015
deliriun deliriun is offline
Miembro
 
Registrado: ago 2014
Posts: 51
Poder: 10
deliriun Va por buen camino
Aclaración

Cuando puse de ejemplo el programa Cheat Engine me refería cuando el programa este corriendo
abrirlo desde el proceso ( como lo hace el Cheat Engine ) y una vez ahí hacer una búsqueda en memoria pero solo de String..
Obtener el address y cambiar su valor...
Responder Con Cita
  #7  
Antiguo 27-08-2015
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Hola deliriun.
Cita:
Empezado por deliriun Ver Mensaje
Cuando puse de ejemplo el programa Cheat Engine me refería cuando el programa este corriendo
abrirlo desde el proceso ( como lo hace el Cheat Engine ) y una vez ahí hacer una búsqueda en memoria pero solo de String..
Obtener el address y cambiar su valor...
A... había interpretado otra cosa, ahora entiendo. Entonces escafandra ya te dió las pautas correctas de como encararlo en el mensaje #5.

Saludos
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....
Responder Con Cita
  #8  
Antiguo 27-08-2015
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Lee el mensaje 5

Saludos.
Responder Con Cita
  #9  
Antiguo 27-08-2015
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Caramba, ecfisa, ya nos hemos pisado

Saludos.
Responder Con Cita
  #10  
Antiguo 27-08-2015
deliriun deliriun is offline
Miembro
 
Registrado: ago 2014
Posts: 51
Poder: 10
deliriun Va por buen camino
Red face Un ejemplo.

Alguien me podría dar un ejemplo de como emplear... No entiendo mucho las paginas de Microsoft
Responder Con Cita
  #11  
Antiguo 27-08-2015
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.039
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
No te lo tomes a mal, pero si dices eso es que quizás no estés preparado todavía para hacer algo así.
Responder Con Cita
  #12  
Antiguo 27-08-2015
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Hola.

Seguramente... y por otro lado:
Saludos
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....
Responder Con Cita
  #13  
Antiguo 27-08-2015
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Independientemente de que sea o no capaz de llegar a entender el uso de esas API y que les de un uno eficaz para su problema, yo quisiera saber cual es el interés particular de deliriun en alterar las cadenas de un proceso y cual es el proceso que quiere alterar.


Saludos.
Responder Con Cita
  #14  
Antiguo 28-08-2015
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Vamos a dar un empujoncito al tema. He escrito una función un poco a lo bruto para cambiar una cadena en un proceso. He de aclarar que está escrito en delphi7, que se compila para 32bits, esto quiere decir que no se pueden atacar de esta forma procesos de 64bits. Lo he probado en winXP y en Win10:

Código Delphi [-]
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, TLHelp32;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Label1: TLabel;
    Edit2: TEdit;
    Label2: TLabel;
    Label3: TLabel;
    Edit3: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

function  _wcsnicmp(wstr1, wstr2: PWCHAR; Size: integer): Integer; cdecl external 'crtdll';
function  wcslen(wstr: PWCHAR): Integer; cdecl external 'crtdll';


var
  Form1: TForm1;

implementation

{$R *.dfm}

//---------------------------------------------------------------------------
function EnablePrivilege(name: String; Enable: boolean = true): boolean;
var
  hToken: Cardinal;
  priv: TOKEN_PRIVILEGES;
begin
  priv.PrivilegeCount:= 1;
  priv.Privileges[0].Attributes:= 0;
  if Enable then priv.Privileges[0].Attributes:= SE_PRIVILEGE_ENABLED;
  LookupPrivilegeValue(nil, PCHAR(name), priv.Privileges[0].Luid);
  OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, hToken);
  AdjustTokenPrivileges (hToken, FALSE, priv, sizeof(priv), nil, PDWORD(nil)^);
  Result:= (GetLastError = ERROR_SUCCESS);
  CloseHandle (hToken);
end;

//---------------------------------------------------------------------------
function RemoteReplaceString(PID: DWORD; Str, NewStr: PWCHAR): BOOL;
const
  nBytes = $16000;
var
  hProc: THANDLE;
  n, i, T, Len, nBytesRead: DWORD;
  Buffer, RemoteAddr: PBYTE;
  bi: MEMORY_BASIC_INFORMATION;
begin
  Result:= false;
  hProc:= OpenProcess(PROCESS_ALL_ACCESS, false, PID);
  Len:= wcslen(Str) * sizeof(WCHAR);
  GetMem(Buffer, nBytes);

  EnablePrivilege('SeDebugPrivilege');

  // Escaneamos la memoria del proceso en busca de la cadena
  for n:= 0 to $1000 do
  begin
     RemoteAddr:= PBYTE(n*nBytes-Len);
     ReadProcessMemory(hProc, RemoteAddr, Buffer, nBytes, nBytesRead);
     if nBytesRead > 0 then
     begin
       //Le resto el modulo de la división para no perderme cadenas partidas
       T:= nBytesRead - (nBytesRead mod wcslen(Str));
       i:= 0;
       while i <= T do
       begin
         // Busco la cadena en el buffer "no case sensitive"
         if _wcsnicmp(PWCHAR(DWORD(Buffer)+i), Str, wcslen(Str)) = 0 then
         begin
            // Si la encuentro la escribo en el proceso remoto
            if WriteProcessMemory(hProc, pointer(DWORD(RemoteAddr) + i), NewStr, Len, nBytesRead) then
              // si pude escribir incremento el índice para seguir buscando
              i:= i + wcslen(Str);
         end;
         inc(i);
       end;
     end;
   end;
   FreeMem(Buffer);
   CloseHandle(hProc);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  proc: TProcessEntry32;
  hSysSnapshot: THandle;
begin
  proc.dwSize := SizeOf(TProcessEntry32);
  hSysSnapshot:= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if (hSysSnapshot <> INVALID_HANDLE_VALUE) and Process32First(hSysSnapshot, proc) then
  begin
    repeat
      if SameText(String(proc.szExeFile), Edit1.Text) then
        RemoteReplaceString(proc.th32ProcessID, PWCHAR(WideString(Edit2.Text)), PWCHAR(WideString(Edit3.Text)));
    until not (Process32Next(hSysSnapshot, proc));
  end;
  CloseHandle(hSysSnapshot);
end;

end.


He de comentar lo siguiente:

1- Las cadenas de un proceso en memoria deben tratarse como UNICODE
2- He usado funciones "C" de la librería crtdll.dll que trae Windows como parte del S.O. para faciñitar la búsquede de cadenas a bajo nivel
- wcslen devuelve el número de caracteres de una cadena tipo WCHAR
- _wcsnicmp compara una cadena WCHAR con otra en una longitud máxima dada y sin ser sensible a mayúsculas/minúsculas
3- Un código para 32bits no puede leer la memoria de un proceso 64 bits sin más, se precisa un driver o trucos especiales, esto es debido a la incompatibilidad de los punteros que definen el rango de direcciones que son capaces de direccionar.
4- No se puede sustituir una cadena por otra de mayor longitud.

Espero aclarar alguna duda a deliriun.


Saludos.

Última edición por escafandra fecha: 09-03-2020 a las 08:00:24.
Responder Con Cita
  #15  
Antiguo 28-08-2015
deliriun deliriun is offline
Miembro
 
Registrado: ago 2014
Posts: 51
Poder: 10
deliriun Va por buen camino
Unicode y 64 Bits

El código me funciona muy bien en 32 Bits... sin embargo estoy seguro que todo programador quiere que sus programas corran en cualquier PC por eso pregunto si es posible convertirlo a 64 Bits.

Por otro lado me funciona con Unicode... pero si ese no es el caso... Cómo se debería emplear...

Muchas Gracias de antemano por su ayuda...
Responder Con Cita
  #16  
Antiguo 29-08-2015
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
deliriun, ReadProcessMemory y WriteProcessMemory funcionan para un código de 64biits atacando otro también de 64 bits o de 32 bits, las que no te van a funcionar si compilas mi código en 64 bits (lazarus, por ejemplo) son wcslen y _wcsnicmp puesto que la librería crtdll.dll es se Win32. Te he dado las pautas, aunque pueden complicarse un poco más incorporando VirtualQueryEx. Puedes empezar a trabajar y nos cuetas.

Saludos.
Responder Con Cita
  #17  
Antiguo 30-08-2015
deliriun deliriun is offline
Miembro
 
Registrado: ago 2014
Posts: 51
Poder: 10
deliriun Va por buen camino
Problema con String Unicode

Pues la verdad el código que me ha dado funciona bien... pero siendo sinceros no tengo experiencia programando con Delphi... Yo uso más vb.net por su sencillez pero admito que Delphi es mucho más potente y también hay mucho asesoramiento y ayuda como esta pagina por ejemplo así que hice la pregunta en este Foro y solo me gustaría ver como es posible hacer la búsqueda del String sin que sea UNICODE... ya que esa es mi dificultad... Y sé que este no es el sitio adecuado para preguntar pero si alguien conociera un Foro como este pero destinado a vb.net se lo agradecería mucho.

Gracias
Responder Con Cita
  #18  
Antiguo 30-08-2015
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Hola deliriun.
Cita:
Empezado por deliriun Ver Mensaje
... Y sé que este no es el sitio adecuado para preguntar pero si alguien conociera un Foro como este pero destinado a vb.net se lo agradecería mucho.
Supongo que Msdn foros - Lenguaje VB.NET - Microsoft debería ser suficientemente serio.

En la búsqueda, aparecen varios mas:Pero como no conozco nada acerca de vb.net, no puedo evaluar el nivel de esos foros como para recomendarte alguno en especial.

Saludos
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....
Responder Con Cita
  #19  
Antiguo 30-08-2015
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Cita:
Empezado por deliriun Ver Mensaje
Pues la verdad el código que me ha dado funciona bien... pero siendo sinceros no tengo experiencia programando con Delphi... Yo uso más vb.net por su sencillez pero admito que Delphi es mucho más potente y también hay mucho asesoramiento y ayuda como esta pagina por ejemplo así que hice la pregunta en este Foro y solo me gustaría ver como es posible hacer la búsqueda del String sin que sea UNICODE... ya que esa es mi dificultad... Y sé que este no es el sitio adecuado para preguntar pero si alguien conociera un Foro como este pero destinado a vb.net se lo agradecería mucho.

Gracias
Bueno, vista la dificultad y siendo éste un foro para responder preguntas, te muestro este nuevo código, mucho más elaborado, que funciona en delphi y Lazarus. En Lazarus compilado para 64bits encuentra y cambia cadenas en procesos de 32 y 64 bits:
Código Delphi [-]
function _StrCmpNIW(Str1, Str2: PWCHAR; N: integer): DWORD;
var
  T: integer;
begin
  T:= 0;
  // Pasando a minusculas y comparando caracteres
  while ((Ord(Str1^) or 32) = (Ord(Str2^) or 32)) and (Str1^ <> #0) and (Str2^ <> #0) and (T < N) do
  begin
    inc(Str1);
    inc(Str2);
    inc(T);
  end;
  Result:= N-T;
end;

function EnablePrivilege(name: String; Enable: boolean = true): boolean;
var
  hToken: THANDLE;
  priv: TOKEN_PRIVILEGES;
begin
  priv.PrivilegeCount:= 1;
  priv.Privileges[0].Attributes:= 0;
  if Enable then priv.Privileges[0].Attributes:= SE_PRIVILEGE_ENABLED;
  LookupPrivilegeValue(nil, PCHAR(name), priv.Privileges[0].Luid);
  OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, hToken);
  AdjustTokenPrivileges (hToken, FALSE, priv, sizeof(priv), PTOKEN_PRIVILEGES(0)^, PDWORD(nil)^);
  Result:= (GetLastError = ERROR_SUCCESS);
  CloseHandle (hToken);
end;

//---------------------------------------------------------------------------
function RemoteReplaceString(PID: DWORD; Str, NewStr: PWCHAR): BOOL;
var
  hProc: THANDLE;
  i, T, Size, Len, nBytesRead: DWORD;
  Buffer: PCHAR;
  mbi: MEMORY_BASIC_INFORMATION;
  Start: PCHAR;
begin
  Result:= false;
  hProc:= OpenProcess(PROCESS_ALL_ACCESS, false, PID);
  Len:= lstrlenW(Str);
  Size:= Len * sizeof(WCHAR);
  EnablePrivilege('SeDebugPrivilege');
  Start:= nil;

  // Escaneamos la memoria del proceso en busca de la cadena
  while VirtualQueryEx(hProc, Start, mbi, sizeof(mbi))<>0 do
  begin
    if mbi.Protect <> 0 and not(mbi.Protect and (PAGE_NOACCESS or PAGE_GUARD)) then
    begin
      Buffer:= VirtualAlloc(nil, mbi.RegionSize, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE);
      if Buffer <> nil then
      begin
        ReadProcessMemory(hProc, mbi.BaseAddress, Buffer, mbi.RegionSize, nBytesRead);
        if nBytesRead > 0 then
        begin
          //Le resto el modulo de la división para no perderme cadenas partidas
          T:= nBytesRead - Size - nBytesRead mod Size;
          i:= 0;
          while i <= T do
          begin
            // Busco la cadena en el buffer "no case sensitive"
            if _StrCmpNIW(PWCHAR(Buffer+i), Str, Len) = 0 then
            begin
              // Si la encuentro la escribo en el proceso remoto
              if WriteProcessMemory(hProc, pointer(mbi.BaseAddress + i), NewStr, Size, PDWORD(0)^) then
              begin
                // Incremento el índice para seguir buscando
                //i:= i + Size - 1;
                Result:= Result or true;
              end;
            end;
            inc(i);
          end;
        end;
        VirtualFree(Buffer, 0, MEM_RELEASE);
      end;
    end;
    inc(Start, mbi.RegionSize);
  end;
  CloseHandle(hProc);
end;

Al escribir código a bajo nivel para 64bits hay que tener mucho cuidado con la aritmética de punteros y conversiones, ya que su tamaño es de 64bits y no de 32, como estamos acostumbrados.
Aprovecho para mostrar una función, _StrCmpNIW, simple y más rápida que la API del mismo nombre. Es importante dotar de velocidad al barrido de memoria.

Saludos.

Última edición por Casimiro Notevi fecha: 30-08-2015 a las 20:01:21.
Responder Con Cita
  #20  
Antiguo 30-08-2015
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Nota de última hora:

Al ver el código, subí una versión en la que comenté una línea para hacer pruebas, se debe "descomentar" para ganar algo de velocidad. Esta es la parte del código:
Código Delphi [-]
               if WriteProcessMemory(hProc, pointer(mbi.BaseAddress + i), NewStr, Size, PDWORD(0)^) then
               begin
                 // Incremento el índice para seguir buscando
       //==>     //i:= i + Size - 1;                 
                 Result:= Result or true;
               end;

Debe quedar así:
Código Delphi [-]
               if WriteProcessMemory(hProc, pointer(mbi.BaseAddress + i), NewStr, Size, PDWORD(0)^) then
               begin
                 // Incremento el índice para seguir buscando
                 i:= i + Size - 1;
                 Result:= Result or true;
               end;


Saludos.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
programa residente en memoria elcigarra OOP 5 28-04-2008 18:39:48
Buscando programa de cadetil Novás Varios 1 01-11-2006 12:23:50
programa residente en memoria Jorge Ramirez Varios 1 25-04-2004 06:10:49
Programa residente en memoria naker Varios 2 10-11-2003 00:35:10
Programa de Consola en memoria.... jcgarcia Varios 2 04-06-2003 02:05:51


La franja horaria es GMT +2. Ahora son las 11:39:03.


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
Copyright 1996-2007 Club Delphi