ما هي اسرع الطرق لبحث عن بايتات في الذاكرة ؟
#1
السلام عليكم ورحمة الله وبركاتة

قبل فترة عملت برنامج ... شبيه بـ Cheat Engine وكان الهدف لزيادة الخبرة وإنتاج برنامج غير مكشوف من بعض الحمايات ...

ولكن كان يحتوي على بعض الاخطاء التي بعض الأوقات تسبب تدمير(Crash) للبرنامج رغم ان البرنامج
لا يحتوي على اي خطاء برمجي ...
حيث اني كنت اقرء الذاكرة واعيد العنوان والقيمة في Array إذا تطباقت القيمة التي تم قرائتها مع
القيمة التي ابحث عنها ... وعملت دالة تقوم بذلك لتسهيل العملية ... وكتبتها بهذا الشكل :
PHP كود :
type
  dwArray 
= Array[0..1] of array of Cardinal;
function 
FindValueDWORD(hProcess : NativeUInt; dwStartAddress, dwEndAddress : Cardinal; Value : Cardinal): dwArray ;
var
  
TempAddress : Cardinal;
  
I : Integer;
  
BytesRead : NativeUInt;
  
dwResult : Cardinal;
  
LenArray : Integer;
begin
  LenArray 
:= 0;
  
SetLength(Result[0],1);
  
SetLength(Result[1],1);

  if 
not ( hProcess <> 0 ) then Exit;
  if ( 
dwStartAddress > dwEndAddress ) then
  begin
    TempAddress 
:= dwEndAddress;
    
dwEndAddress := dwStartAddress;
    
dwStartAddress := TempAddress;
  
end;

  
SetLength(Result[0],0);
  
SetLength(Result[1],0);

  for 
I := dwStartAddress to dwEndAddress do
  
begin
    ReadProcessMemory
(hProcess, Pointer(I), @dwResult, 4, BytesRead);
    if ( 
dwResult = Value ) then
    begin
      LenArray 
:= LenArray + 1;
      
SetLength(Result[0],LenArray);
      
SetLength(Result[1],LenArray);
      
Result[0][LenArray -1] := I;
      
Result[1][LenArray -1] := dwResult;
    
end;
  
end;
end; 
لكن عندما اقارن سرعة البحث في برنامجي وسرعة البحث في برنامج Cheat Engine
اجد برنامج Cheat Engine سريع جداً بينما برنامجي بطئ مقارنة مع Cheat Engine

وهنا اعيد طرح السؤال ... ما هي اسرع الطرق لعملية بحث في الذاكرة ؟

اتمنى وضحت المطلوب ...

وشكراً لحسن القراءة
والسلام عليكم ورحمة الله وبركاتة
الرد
#2
بالطبع يا أخي ستكون الدالة بطيئة لسببين
السبب الأول أنك تستخدم مصفوفة ذات بعد ثنائي
السبب الثاني الحلقة التي تستخدمها لقراءة الذاكرة
-------------------------------------
ليس هناك داعي لمصفوفة ثنائية طالما قيمة Value ثابة !!
+ القراءة من الذاكرة باستخدام حلقة سيبطأ الدالة
-----------------------------------
هذا مثال سريع :
PHP كود :
type dwArray2= array of Cardinal;
function 
FindValueDWORD2(hProcess : Cardinal;
dwStartAddress, dwEndAddress : Cardinal;
Value : Integer): dwArray2 ;
type PCardinalArray = ^TCardinalArray;
  
TCardinalArray    = array[0..16383] of Cardinal ;
  var 
nCount,i,Len:Integer;
     
dwResult:PCardinalArray;
     
TempAddress:Cardinal;
     
nb:Cardinal;

begin
  nCount
:=0;
  
SetLength(Result,nCount+1);
  
Result[nCount]:=0;
if   
hProcess = 0 then Exit;
  if ( 
dwStartAddress > dwEndAddress ) then
  begin
    TempAddress 
:= dwEndAddress;
    
dwEndAddress := dwStartAddress;
    
dwStartAddress := TempAddress;
  
end;
  
Len:=dwEndAddress -dwStartAddress;

  
GetMem(dwResult,Len);
  
ReadProcessMemory(hProcess, Pointer(dwStartAddress), dwResult,Len, nb);
  for 
i:=0 to nb do begin
    
if (dwResult[i] = Value) then
     begin
      Inc
(nCount);
      
SetLength(Result,nCount);
      
Result[nCount-1]:=dwStartAddress+i;
     
end;
  
end;
  
FreeMem(dwResult,Len);
end; 
الرد
#3
السلام عليكم ...

اعرف ان الرد اتى متأخراً , لاني انشغلت في اموار آخرى ...

احببت ان اسئل عن الدالة GetMem ما وضيفته بالضبط ؟
هل لك ان تشرح لي الطريقة المتبعه في جلب القيمة في الدالة التي كتبتها .. لان لدي بعض الاستفهامات Smile

وشكراً لك من جديد اخي SMP3
الرد
#4
السلام عليكم ...

لدي سؤال آخر وهو عن هذا التعريف :
PHP كود :
type PCardinalArray = ^TCardinalArray;
     
TCardinalArray = array[0..16383] of Cardinal ; 
لماذا وضعت القيمة 16383 تحديداً ؟؟
الرد
#5
ALmuhhnad كتب :هل لك ان تشرح لي الطريقة المتبعه في جلب القيمة في الدالة التي كتبتها ..
الدالة GetMem تقوم بحجز مكان لمؤشر في الذاكرة
عند تعاملنا مع المؤشرات يجب أن نقوم بحجز مكان لها في الذاكرة تماما مثل SetLength
-------------------
نفس التمرير للدالة Big Grin
ALmuhhnad كتب :لدي سؤال آخر وهو عن هذا التعريف :
أنت استخدمت 2 بايت للقراءة لأنك تقوم بالقراءة باستخدام Loop .. أما استخدامي 16383 فهو بسبب قراءة الذاكرة بحجم معين وتخزن القيمة في مصفوفة .. يعني القراءة مرة واحدة لذلك يجب أن تكون المصفوفة طويلة .
الرد
#6
إقتباس :أنت استخدمت 2 بايت للقراءة لأنك تقوم بالقراءة باستخدام Loop ..
انا استخدمت 4 بايت ... لكن بسبب الـ loop على ما اضن اني اقرى بايت بايت ... أي اني اقرى 4 بايت وبعد لذلك اتأكد من مطابقتها للقيمة
ثم اقرى العنوان الذي يليه ببايت واحد ...إلخ

إقتباس :أما استخدامي 16383 فهو بسبب قراءة الذاكرة بحجم معين وتخزن القيمة في مصفوفة
طيب لو حصل وان كان المراد قرائته اطول من الطول المحدد ... ماذا افعل لكي اضع الطول مفتوح وعلى حسب الـ dwStartAddress
و dwEndAddress ?
الرد
#7
ALmuhhnad كتب :انا استخدمت 4 بايت ... لكن بسبب الـ loop على ما اضن اني اقرى بايت بايت ... أي اني اقرى 4 بايت وبعد لذلك اتأكد من مطابقتها للقيمة
ثم اقرى العنوان الذي يليه ببايت واحد ...إلخ


طيب لو حصل وان كان المراد قرائته اطول من الطول المحدد ... ماذا افعل لكي اضع الطول مفتوح وعلى حسب الـ dwStartAddress
و dwEndAddress ?

في هذه الحالة عليك باستخدام Dynamic Arrays
الرد
#8
هل تقصد بـ Dynamic Arrays هكذا :
PHP كود :
dwArray2 = array of Cardinal; 
عذراً فانا لا احفظ المصطلحات العلمية كثيراً P:

ايضاً عند إستعمالي بهذه الطريقة سيحصل خطاء في GetMem
ايضاً يا حبذ ان تكتب المثال في XE3 لاني اواجه صعوبة في تحولي الكود @@"
فالمصفوفات لم يسبق لي ان تعاملت معها ... إلا في هذا المثال ... لذلك كان احد اهدافي ان ازيد خبرتي Smile
الرد
#9
نسيت ان اذكر .... :
( الكود يعمل مع d7 )

في الرد السابق كنت اتكلم عن xe3 ...
الرد
#10
السلام عليكم ...
الحمد لله استطعت بفضل الله ثم مساعدت اخي المبرمج SMP3 وضع دالة للقراءة ( لم اجرب سرعتها بعد )
هذه الدالة بـ Delphi XE3 :
PHP كود :
type
  DWORDOfArray 
= Array of Cardinal;
  
ByteOfArray = array of byte;
function 
FindVale_Byte(hProcess, dwStartAddress, dwEndAddress : Cardinal; Value : Byte; ProgressSearching : TGauge): DWORDOfArray;
var
  
I, Len, iCount : Integer;
  
NumReadBytes : NativeUInt;
  
TempAddress : Cardinal;
  
aResult : ByteOfArray;
begin
  iCount 
:= 0;
  
SetLength(Result,iCount + 1);
  
Result[iCount] := 0;
  if 
hProcess = 0  then Exit;
  if 
dwStartAddress > dwEndAddress then
  begin
    TempAddress 
:= dwEndAddress;
    
dwEndAddress := dwStartAddress;
    
dwStartAddress := TempAddress;
  
end;
  
Len := (dwEndAddress - dwStartAddress) + 1;
  
SetLength(aResult,Len);
  
ReadProcessMemory(hProcess,Pointer(dwStartAddress),aResult,Len,NumReadBytes);
  
ProgressSearching.MaxValue := NumReadBytes;
  
ProgressSearching.Progress := 0;
  
ProgressSearching.MinValue := ProgressSearching.Progress;
  for 
I := 0 to NumReadBytes do
  
begin
    
if aResult[i] = Value then
    begin
      Inc
(iCount);
      
SetLength(Result,iCount);
      
Result[iCount-1] := dwStartAddress + i;
    
end;
    
ProgressSearching.Progress := i;
  
end;
end; 
اضفت لها اوامر إخبار المستخدم اين وصل البحث من خلال المكون TGauge

طريقة الإستعمال :
PHP كود :
procedure TMain.btnFirstScanClick(Sender: TObject);
var
  
I, Len : Integer;
  
hProcess : Cardinal;
  
dwResult : DWORDOfArray;
  
StartAddress, EndAddress : Cardinal;
  
iValue : integer;
begin
  iValue 
:= StrToInt(edtValue.Text);
  
StartAddress := sHexToInt(edtStartAddress.Text);
  
EndAddress := sHexToInt(edtEndAddress.Text);
  
hProcess := OpenProcess(PROCESS_VM_READ,False,StrToInt(edtPID.Text));
  
dwResult := FindVale_Byte(hProcess,StartAddress,EndAddress,iValue,gagPrograssSreaching);
  
Len := Length(dwResult);
  for 
I := 0 to Len -1 do
  
begin
    Memo1
.Lines.Add(IntToHex(dwResult[i],8) + ' = ' + IntToStr(iValue));
  
end;
end; 

الآن ما الملاحظات على الدالة Tongue إن امكن ...
وبعد قليل ساجرب سرعة الدالة Smile
الرد


التنقل السريع :


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم