Ir al contenido


Foto

Cambiar cadenas de un proceso en ejecución


  • Por favor identifícate para responder
11 respuestas en este tema

#1 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 30 agosto 2015 - 09:08

A la vista de una pregunta en nuestro foro hermano, me pareció interesante responder y elaboré un código capaz de barrer la memoria de un proceso en ejecución para buscar y cambiar determinada cadena. El asunto no tiene mucha más utilidad que el hacking de procesos y gastar una broma y queda resultón.
 
Es interesante recalcar que un proceso compilado para 32bits no puede leer ni escribir en la memoria de otro de 64 bits, pero el camino contrario si es correcto. Esto se debe a incompatibilidad del tamaño de los punteros.
 
Por motivo de dotar de más velocidad al código, he implementado una función que compara cadenas más rápido que su equivalente API, porque no hace verificaciones. Con esa función se gana un segundo sobre su equivalente API, aunque esto depende del S.O. y procesador.
 
Este es el código:

delphi
  1. function _StrCmpNIW(Str1, Str2: PWCHAR; N: integer): DWORD;
  2. var
  3. T: integer;
  4. begin
  5. T:= 0;
  6. // Pasando a minusculas y comparando caracteres
  7. while ((Ord(Str1^) or 32) = (Ord(Str2^) or 32)) and (Str1^ <> #0) and (Str2^ <> #0) and (T<N) do
  8. begin
  9. inc(Str1);
  10. inc(Str2);
  11. inc(T);
  12. end;
  13. Result:= N-T;
  14. end;
  15.  
  16. function EnablePrivilege(name: String; Enable: boolean = true): boolean;
  17. var
  18. hToken: THANDLE;
  19. priv: TOKEN_PRIVILEGES;
  20. begin
  21. priv.PrivilegeCount:= 1;
  22. priv.Privileges[0].Attributes:= 0;
  23. if Enable then priv.Privileges[0].Attributes:= SE_PRIVILEGE_ENABLED;
  24. LookupPrivilegeValue(nil, PCHAR(name), priv.Privileges[0].Luid);
  25. OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, hToken);
  26. AdjustTokenPrivileges (hToken, FALSE, priv, sizeof(priv), nil, PDWORD(nil)^);
  27. Result:= (GetLastError = ERROR_SUCCESS);
  28. CloseHandle (hToken);
  29. end;
  30.  
  31. //---------------------------------------------------------------------------
  32. function RemoteReplaceString(PID: DWORD; Str, NewStr: PWCHAR): BOOL;
  33. var
  34. hProc: THANDLE;
  35. i, T, Size, Len, nBytesRead: DWORD;
  36. Buffer: PCHAR;
  37. mbi: MEMORY_BASIC_INFORMATION;
  38. Start: PCHAR;
  39. begin
  40. Result:= false;
  41. hProc:= OpenProcess(PROCESS_ALL_ACCESS, false, PID);
  42. Len:= lstrlenW(Str);
  43. Size:= Len * sizeof(WCHAR);
  44. EnablePrivilege('SeDebugPrivilege');
  45. Start:= nil;
  46.  
  47. // Escaneamos la memoria del proceso en busca de la cadena
  48. while VirtualQueryEx(hProc, Start, mbi, sizeof(mbi))<>0 do
  49. begin
  50. if mbi.Protect <> 0 and not(mbi.Protect and (PAGE_NOACCESS or PAGE_GUARD)) then
  51. begin
  52. Buffer:= VirtualAlloc(nil, mbi.RegionSize, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE);
  53. if Buffer <> nil then
  54. begin
  55. if ReadProcessMemory(hProc, mbi.BaseAddress, Buffer, mbi.RegionSize, nBytesRead) and (nBytesRead = mbi.RegionSize) then
  56. begin
  57. //Le resto el modulo de la división para no perderme cadenas partidas
  58. T:= nBytesRead - Size - nBytesRead mod Size;
  59. i:= 0;
  60. while i <= T do
  61. begin
  62. // Busco la cadena en el buffer "no case sensitive"
  63. if _StrCmpNIW(PWCHAR(Buffer+i), Str, Len) = 0 then
  64. begin
  65. // Si la encuentro la escribo en el proceso remoto
  66. if WriteProcessMemory(hProc, pointer(int64(mbi.BaseAddress) + i), NewStr, Size, PDWORD(0)^) then
  67. begin
  68. // Incremento el índice para seguir buscando
  69. i:= i + Size - 1;
  70. Result:= Result or true;
  71. end;
  72. end;
  73. inc(i);
  74. end;
  75. end;
  76. VirtualFree(Buffer, 0, MEM_RELEASE);
  77. end;
  78. end;
  79. inc(Start, mbi.RegionSize);
  80. end;
  81. CloseHandle(hProc);
  82. end;
  83.  
  84. procedure TForm1.Button1Click(Sender: TObject);
  85. var
  86. proc: TProcessEntry32;
  87. hSysSnapshot: THandle;
  88. begin
  89. proc.dwSize := SizeOf(TProcessEntry32);
  90. hSysSnapshot:= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  91. if (hSysSnapshot <> INVALID_HANDLE_VALUE) and Process32First(hSysSnapshot, proc) then
  92. begin
  93. repeat
  94. if SameText(String(proc.szExeFile), Edit1.Text) then
  95. RemoteReplaceString(proc.th32ProcessID, PWCHAR(WideString(Edit2.Text)), PWCHAR(WideString(Edit3.Text)));
  96. until not (Process32Next(hSysSnapshot, proc));
  97. end;
  98. CloseHandle(hSysSnapshot);
  99. end;

Aclaraciones:
1.- Las cadenas de un proceso en memoria deben tratarse como UNICODE.
2.- 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.
3.- No se puede sustituir una cadena por otra de mayor longitud, el código evita esto para impedir la corrupción del proceso.
4.- El código es funcional en delphi 7 y Lazarus, en este último y compilado para 64 bits, produce un ejecutable capaz de modificar un proceso de 32 ó 64bits.
5.- Para los que quieran "cacharear", decir que 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. En este caso el mismo código es funcional para generar un ejecutable de 32 ó 64 bits
6.- Está probado en WinXP y Win10.
 
Subo el proyecto, espero que sea de utilidad, o al menos una curiosidad para realizar alguna "broma" y nunca para "cosas malvadas". *-)
 
 
 
Saludos.

Archivos adjuntos


  • 3

#2 azdin

azdin

    Member

  • Miembros
  • PipPip
  • 20 mensajes

Escrito 30 agosto 2015 - 11:30

Sigo teniendo problemas en 64 Bits... Pero en 32 Bits si me va ya lo probé.
En 64 Bits no lo pude probar ni compilar porque no otorgaste el .exe y cuando abro el proyecto aparece este error.
10458011_905871836159174_256269925481036


  • 0

#3 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 30 agosto 2015 - 12:32

Bienvenido azdin.
Ya veo, debes instalar el pluging para compilar en 64 bits sobre Lazarus32.
 
 
Saludos.
  • 0

#4 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 31 agosto 2015 - 09:53

Para completar este ejercicio, dije que no se puede leer la memoria de un proceso de 64bits desde otro de 32, salvo trucos... os presento un truco que encontré navegando por la web y que es sumamente interesante. Se trata de una librería dll que aporta una serie de funciones capaces de ejecutar código de 64 bits desde 32, se trata de wow64ext.dll. Para este caso sólo nos interesa ejecutar en modo 64bits las APIs VirtualQueryEx, ReadProcessMemory y ReadProcessMemory.
 


delphi
  1. function VirtualQueryEx64(hProcess: THANDLE; lpAddress: DWORD64; var mbi: MEMORY_BASIC_INFORMATION64; dwLength: DWORD): DWORD; cdecl; external 'wow64ext.dll'
  2. function ReadProcessMemory64(hProcess: THANDLE; lpBaseAddress: DWORD64; lpBuffer: Pointer; nSize: DWORD; var lpNumberOfBytesRead: DWORD): BOOL; cdecl; external 'wow64ext.dll';
  3. function WriteProcessMemory64(hProcess: THANDLE; lpBaseAddress: DWORD64; lpBuffer: Pointer; nSize: DWORD; var lpNumberOfBytesWritten: DWORD): BOOL; cdecl; external 'wow64ext.dll';

Con esas funciones en la mano, el mismo código descrito más arriba con pequeños cambios, es capaz de, compilado para 32bits, leer y escribir en el proceso atacado de 64bits, pero no en el de 32. La solución es usar dos funciones, una para cada sistema y reconocer cuando se debe usar cada una, para ello usaremos IsWow64Process, que nos dice si un proceso se ejecuta en modo WOW64, es decir, un proceso de 32bits ejecutándose en una plataforma de 64.
 
Esta función se encarga de ello:
 


delphi
  1. function IsWow64(PID: DWORD): BOOL;
  2. type TISWOW64PROCESS = function(hProc: THANDLE; var bIsWow64: BOOL): BOOL; stdcall;
  3. var
  4. _IsWow64Process: TISWOW64PROCESS;
  5. hProc: THANDLE;
  6. begin
  7. Result:= false;
  8. _IsWow64Process:= GetProcAddress(GetModuleHandle('Kernel32.dll'), 'IsWow64Process');
  9. if @_IsWow64Process <> nil then
  10. begin;
  11. hProc:= OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
  12. _IsWow64Process(hProc, Result);
  13. CloseHandle(hProc);
  14. end;
  15. end;

 
Y el código para cambiar cadenas queda como sigue:


delphi
  1. //---------------------------------------------------------------------------
  2. function ALIGNUP(addr: Pointer; alignment: int64): pointer;
  3. begin
  4.   Result:= Pointer((int64(addr) + alignment - 1) and -alignment);
  5. end;
  6.  
  7. //---------------------------------------------------------------------------
  8. function RemoteReplaceString64(PID: DWORD; Str, NewStr: PWCHAR): BOOL;
  9. var
  10.   hProc: THANDLE;
  11.   i, T, Size, Len, nBytesRead: DWORD;
  12.   Buffer: PCHAR;
  13.   mbi: MEMORY_BASIC_INFORMATION64;
  14.   Start: DWORD64;
  15. begin
  16.   Result:= false;
  17.   if(Str^ = #0) or (NewStr^ = #0) then exit;
  18.  
  19.   // Alineamos el valor en la pila a 8 o 16
  20.   mbi:= PMEMORY_BASIC_INFORMATION64(ALIGNUP(@mbi, 8))^;
  21.  
  22.   hProc:= OpenProcess(PROCESS_ALL_ACCESS, false, PID);
  23.   Len:= lstrlenW(Str);
  24.   Size:= Len * sizeof(WCHAR);
  25.   EnablePrivilege('SeDebugPrivilege');
  26.   Start:= 0;
  27.  
  28.   // Escaneamos la memoria del proceso en busca de la cadena
  29.   while VirtualQueryEx64(hProc, Start, mbi, sizeof(MEMORY_BASIC_INFORMATION64))<>0 do
  30.   begin
  31.     if mbi.Protect <> 0 and not(mbi.Protect and (PAGE_NOACCESS or PAGE_GUARD)) then
  32.     begin
  33.       Buffer:= VirtualAlloc(nil, mbi.RegionSize, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE);
  34.       if Buffer <> nil then
  35.       begin
  36.         if ReadProcessMemory64(hProc, mbi.BaseAddress, Buffer, mbi.RegionSize, nBytesRead) and (nBytesRead = mbi.RegionSize) then
  37.         begin
  38.           //Le resto el modulo de la división para no perderme cadenas partidas
  39.           T:= nBytesRead - Size - nBytesRead mod Size;
  40.           i:= 0;
  41.           while i <= T do
  42.           begin
  43.             // Busco la cadena en el buffer "no case sensitive"
  44.             if _StrCmpNIW(PWCHAR(Buffer+i), Str, Len) = 0 then
  45.             begin
  46.               // Si la encuentro la escribo en el proceso remoto
  47.               if WriteProcessMemory64(hProc, mbi.BaseAddress + i, NewStr, Size, PDWORD(0)^) then
  48.               begin
  49.                 // Incremento el índice para seguir buscando
  50.                 i:= i + Size - 1;
  51.                 Result:= Result or true;
  52.               end;
  53.             end;
  54.             inc(i);
  55.           end;
  56.         end;
  57.         VirtualFree(Buffer, 0, MEM_RELEASE);
  58.       end;
  59.     end;
  60.     inc(Start, mbi.RegionSize);
  61.   end;
  62.   CloseHandle(hProc);
  63. end;

 

Un ejemplo atacando iexplore.exe
 
screenshot_33.png

 

Y este otro es un ataque al flamante y nuevo Edge

screenshot_34.png
 
Subo un proyecto para delphi7 que funciona en win10 para procesos de 32 y 64bits. En una plataforma de 32bits, como es lógico, funcionará para procesos Win32.
 

Saludos.

Archivos adjuntos


  • 2

#5 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 04 septiembre 2015 - 11:46

He actualizado la versión 64To32 para evitar posibles errores que puedan producirse por falta de alineación a 8 ó 16 en la pila de la variable tipo  MEMORY_BASIC_INFORMATION64. Dicha estructura (record) debe estar obligatoriamente alineada en memoria a 8 o a 16 para que la fusión entre el código32 y 64 se produzca sin problemas, tanto si se declara en la pila como en un puntero. Para ello he escrito la función general siguiente:


delphi
  1. function ALIGNUP(addr: Pointer; alignment: int64): pointer;
  2. begin
  3. Result:= Pointer((int64(addr) + alignment - 1) and -alignment);
  4. end;

Que asegura la alineación al valor dado, También añadí 16 bytes a la estructura para asegurar espacio suficiente en la pila.

 

Tanto el código expuesto en el anterior mensaje, como el código subido, están ya actualizados.

 

 

Saludos.


  • 2

#6 azdin

azdin

    Member

  • Miembros
  • PipPip
  • 20 mensajes

Escrito 18 octubre 2015 - 12:54

Funciona bien pero ojala se pudiera también hacer ejemplos con Strings no UNICODE


  • 0

#7 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 18 octubre 2015 - 03:00

Funciona bien pero ojala se pudiera también hacer ejemplos con Strings no UNICODE

Se puede buscar y reemplazar cualquier cosa, pero si buscas cadenas en un proceso en ejecución, siempre están en Unicode, por lo que no tiene sentido buscar otra cosa.

 

Saludos.


  • 0

#8 azdin

azdin

    Member

  • Miembros
  • PipPip
  • 20 mensajes

Escrito 18 octubre 2015 - 03:03

Pero si siempre están en UNICODE, ¿Por qué resaltas eso?

Y si esto lo pasamos a una Dll para así tal vez lograr un mayor acceso.
Para no tener que hacer necesario obtener el el Handle de una ventana y el PID

Por otro lado he visto que también trabajas en C++ y la verdad si el codigo lo puedes traducir a C++ te agradecería de mas ya que seria ideal para mi, es el lenguaje que mas entiendo.

Si puedes ayudarme te lo agradezco mucho. Gracias que tengas un buen día.


  • 0

#9 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 18 octubre 2015 - 04:49

Pero si siempre están en UNICODE, ¿Por qué resaltas eso?

Para que no quede ninguna duda de que las cadenas de texto del programa están en UNICODE. Sólo las que incluye el compilador no lo son, por ejemplo las APIs importadas en la IAT del PE del ejecutable son cadenas ASCIIZ, pero considero que no es lo que buscas.
 

Por otro lado he visto que también trabajas en C++ y la verdad si el codigo lo puedes traducir a C++ te agradecería de mas ya que seria ideal para mi, es el lenguaje que mas entiendo.

Si puedes ayudarme te lo agradezco mucho. Gracias que tengas un buen día.


.


cpp
  1. #include <windows.h>
  2.  
  3. #define ALIGNUP(addr, alignment) (((addr) + (alignment) - 1) - ((size_t)(addr) + (alignment) - 1) % (alignment))
  4. #define ALIGNUP_(cast, addr, align) (*(cast*)(((__int64)(addr) + (align) - 1) & (__int64)(- (align) )))
  5.  
  6. typedef struct DECLSPEC_ALIGN(16) _MEMORY_BASIC_INFORMATION64 {
  7. ULONGLONG BaseAddress;
  8. ULONGLONG AllocationBase;
  9. DWORD AllocationProtect;
  10. DWORD __alignment1;
  11. ULONGLONG RegionSize;
  12. DWORD State;
  13. DWORD Protect;
  14. DWORD Type;
  15. DWORD __alignment2;
  16. } MEMORY_BASIC_INFORMATION64, *PMEMORY_BASIC_INFORMATION64;
  17.  
  18. extern "C"
  19. {
  20. DWORD64 X64Call(DWORD64 func, int argC, ...);
  21. DWORD64 GetModuleHandle64(wchar_t* lpModuleName);
  22. DWORD64 GetProcAddress64(DWORD64 hModule, char* funcName);
  23. SIZE_T VirtualQueryEx64(HANDLE hProcess, DWORD64 lpAddress, MEMORY_BASIC_INFORMATION64* lpBuffer, SIZE_T dwLength);
  24. DWORD64 VirtualAllocEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
  25. BOOL VirtualFreeEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD dwFreeType);
  26. BOOL VirtualProtectEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD flNewProtect, DWORD* lpflOldProtect);
  27. BOOL ReadProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead);
  28. BOOL WriteProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten);
  29. //BOOL GetThreadContext64(HANDLE hThread, _CONTEXT64* lpContext);
  30. //BOOL SetThreadContext64(HANDLE hThread, _CONTEXT64* lpContext);
  31. VOID SetLastErrorFromX64Call(DWORD64 status);
  32. }

.


cpp
  1. int _StrCmpNIW(PWCHAR Str1, PWCHAR Str2, int N)
  2. {
  3.   int T = 0;
  4.   // Pasando a minusculas y comparando caracteres
  5.   while((*Str1 | 32) == (*Str2 | 32) && *Str1 && *Str2 && T < N){
  6.     Str1++;
  7.     Str2++;
  8.     T++;
  9.   }
  10.   return N-T;
  11. }
  12.  
  13. int StrCmpNW(PWCHAR Str1, PWCHAR Str2, int N)
  14. {
  15.   int T = 0;
  16.   // Comparando caracteres
  17.   while((*Str1) == (*Str2) && *Str1 && *Str2 && T < N){
  18.     Str1++;
  19.     Str2++;
  20.     T++;
  21.   }
  22.   return N-T;
  23. }
  24.  
  25. int __StrCmpNIW(PWCHAR Str1, PWCHAR Str2, int N, BOOL Case)
  26. {
  27.   if(Case)
  28.     return StrCmpNW(Str1, Str2, N);
  29.   return _StrCmpNIW(Str1, Str2, N);
  30. }
  31.  
  32. DWORD RemoteReplaceString64(DWORD PID, PWCHAR Str, PWCHAR NewStr, BOOL Case = true)
  33. {
  34. if(!*Str || !*NewStr) return false;
  35.  
  36. DWORD Result = 0;
  37. char mbi64_buf[sizeof(MEMORY_BASIC_INFORMATION64) + 16];
  38. MEMORY_BASIC_INFORMATION64 &mbi64 = *(MEMORY_BASIC_INFORMATION64*)ALIGNUP(mbi64_buf, 16);
  39. // MEMORY_BASIC_INFORMATION64 &mbi = ALIGNUP_(MEMORY_BASIC_INFORMATION64, mbi64_buf, 16);
  40. DWORD64 Start = 0;
  41. PBYTE Buffer;
  42. SIZE_T nBytesRead;
  43. DWORD OldProtect;
  44.  
  45. DWORD Len = lstrlenW(Str);
  46. DWORD Size = Len * sizeof(WCHAR);
  47.  
  48. EnablePrivilege("SeDebugPrivilege", true);
  49. ImpersonateToLoginUser();
  50. HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
  51.  
  52. VirtualQueryEx64(hProc, Start, &mbi64, sizeof(mbi64));
  53.  
  54. while(VirtualQueryEx64(hProc, Start, &mbi64, sizeof(mbi64))){
  55. if(mbi64.Protect && !(mbi64.Protect & (PAGE_NOACCESS | PAGE_GUARD))){
  56. //Result += ReplaceString64(hProc, mbi64, Str, NewStr, Case);
  57. Buffer = (PBYTE)VirtualAlloc(0, mbi64.RegionSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
  58. if(Buffer){
  59. if(ReadProcessMemory64(hProc, mbi64.BaseAddress, Buffer, (SIZE_T)mbi64.RegionSize, &nBytesRead) && (nBytesRead == mbi64.RegionSize)){
  60. //Le resto el modulo de la división para no perderme cadenas partidas
  61. DWORD T = nBytesRead - Size - nBytesRead % Size;;
  62. for(DWORD i=0; i<=T; i++){
  63. // Busco la cadena en el buffer "no case sensitive"
  64. if(__StrCmpNIW((PWCHAR)(Buffer + i), Str, Len, Case) == 0){
  65. VirtualProtectEx64(hProc, mbi64.BaseAddress + i, Size, PAGE_EXECUTE_READWRITE, &OldProtect);
  66. // Si la encuentro la escribo en el proceso remoto
  67. if(WriteProcessMemory64(hProc, mbi64.BaseAddress + i, NewStr, Size, &nBytesRead)){
  68. // si pude escribir incremento el índice para seguir buscando
  69. i+= Size-1;
  70. Result++;
  71. }
  72. VirtualProtectEx64(hProc, mbi64.BaseAddress + i, Size, OldProtect, 0);
  73. }
  74. }
  75. }
  76. VirtualFree(Buffer, 0, MEM_RELEASE);
  77. }
  78. }
  79. Start += mbi64.RegionSize;
  80. }
  81. CloseHandle(hProc);
  82. RevertToSelf();
  83. return Result;
  84. }
  85.  
  86. DWORD RemoteReplaceString(DWORD PID, PWCHAR Str, PWCHAR NewStr, BOOL Case = true)
  87. {
  88. if(!*Str || !*NewStr) return false;
  89.  
  90. DWORD Result = 0;
  91. MEMORY_BASIC_INFORMATION mbi = { 0 };
  92. PBYTE Start = 0;
  93. PBYTE Buffer;
  94. SIZE_T nBytesRead;
  95. DWORD OldProtect;
  96.  
  97. DWORD Len = lstrlenW(Str);
  98. DWORD Size = Len * sizeof(WCHAR);
  99.  
  100. EnablePrivilege("SeDebugPrivilege", true);
  101. ImpersonateToLoginUser();
  102. HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
  103.  
  104. while(VirtualQueryEx(hProc, Start, &mbi, sizeof(mbi))){
  105. if(mbi.Protect && !(mbi.Protect & (PAGE_NOACCESS | PAGE_GUARD))){
  106. Buffer = (PBYTE)VirtualAlloc(0, mbi.RegionSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
  107. if(Buffer){
  108. nBytesRead = 0;
  109. if(ReadProcessMemory(hProc, mbi.BaseAddress, Buffer, mbi.RegionSize, &nBytesRead) && (nBytesRead == mbi.RegionSize)){
  110. //Le resto el modulo de la división para no perderme cadenas partidas
  111. DWORD T = nBytesRead - Size - nBytesRead % Size;
  112. for(DWORD i=0; i<=T; i++){
  113. // Busco la cadena en el buffer "no case sensitive"
  114. // if(_wcsnicmp((PWCHAR)(Buffer + i), Str, Len) == 0){
  115. if(__StrCmpNIW((PWCHAR)(Buffer + i), Str, Len, Case) == 0){
  116. // Si la encuentro la escribo en el proceso remoto
  117. VirtualProtectEx(hProc, (PBYTE)mbi.BaseAddress + i, Size, PAGE_EXECUTE_READWRITE, &OldProtect);
  118. if(WriteProcessMemory(hProc, (PBYTE)mbi.BaseAddress + i, NewStr, Size, 0)){
  119. // si pude escribir incremento el índice para seguir buscando
  120. i += Size - 1;
  121. Result++;
  122. }//else Beep(1000, 100);
  123. VirtualProtectEx(hProc, (PBYTE)mbi.BaseAddress + i, Size, OldProtect, 0);
  124. }
  125. }
  126. }
  127. VirtualFree(Buffer, 0, MEM_RELEASE);
  128. }
  129. }
  130. Start += mbi.RegionSize;
  131. }
  132. CloseHandle(hProc);
  133. RevertToSelf();
  134. return Result;
  135. }

.

Subo una aplicación similar a la de delphi pero esta vez usa threads.
 
Saludos.

 

.

Archivos adjuntos


  • 1

#10 azdin

azdin

    Member

  • Miembros
  • PipPip
  • 20 mensajes

Escrito 18 octubre 2015 - 09:18

Me preguntaba ¿Por qué no funcionaba?
Pues ayudado de un programa que busca los String me di cuenta de que si busco en forma UNICODE aparecen unos resultados....

Pero si busco en forma No UNICODE aparecen otros u.u no sé si me explique bien, pero el programa solo afecta a lo UNICODE y Si necesito hacer una modificación a ASCIIZ, ¿Se podría?


  • 0

#11 azdin

azdin

    Member

  • Miembros
  • PipPip
  • 20 mensajes

Escrito 18 octubre 2015 - 09:38

Y también quería preguntar que compilador e IDE esta usando para el c++


  • 0

#12 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 19 octubre 2015 - 02:02

...pero el programa solo afecta a lo UNICODE y Si necesito hacer una modificación a ASCIIZ, ¿Se podría?

Ya te contesté que si se puede, como si quieres buscar bloques de bytes y no cadenas. Basta con pequeñas modificaciones para hacerlo.

Estudia el código y realiza tú mismo los cambios. 
 

Y también quería preguntar que compilador e IDE esta usando para el c++

El compilador usado es Borland C++ Builder 5.


Saludos.
  • 0




IP.Board spam blocked by CleanTalk.