2011-06-05 27 views
5

मुझे किसी प्रक्रिया द्वारा उपयोग की जाने वाली सभी मेमोरी एड्रेस स्पेस को जानने की आवश्यकता है। बाद में मेमोरी स्पेस को प्रक्रिया के भीतर मूल्यों का पता लगाने और उनके स्थान/पतों की पहचान करने के लिए स्कैन किया जाएगा। इसके लिए मेरी वर्तमान प्रक्रिया प्रत्येक मॉड्यूल के मूल पते को इसके आधार (आधार पता + मेमोरी आकार) के माध्यम से लेना है।प्रक्रिया द्वारा उपयोग की जाने वाली सभी मेमोरी एड्रेस स्पेस कैसे प्राप्त करें?

मैं एक ज्ञात पते पर एक ज्ञात मूल्य के साथ एक प्रक्रिया पर इसका परीक्षण कर रहा हूं। जब मैं उस विशिष्ट पते को देखता हूं, तो मुझे वह मूल्य मिलता है जो मैं उम्मीद करता हूं। हालांकि, जब मैं स्कैन करता हूं (जो मैं मानता हूं) प्रक्रिया द्वारा उपयोग की जाने वाली सभी पता स्थान, मुझे कहीं भी मूल्य नहीं मिल रहा है।

मुझे पता है कि एक अंकीय मान "4,143,000" 0x0CF8DC38 और 0x0CF8DDDC पर मौजूद है। जब मैं को पढ़ता हूं ReadMemoryBytes (मॉड्यूल, मॉड्यूल। बेस एड्रेस, 4, (IntPtr) (0x0CF8DC38)) मुझे बाइट्स (152, 55, 63, 0) वापस मिलते हैं। जब मैं बिटकोनवर्टर को कॉल करता हूं। गेटबाइट्स (4143000) मैं बाइट्स का एक ही सेट वापस लेता हूं। जब मैं उस प्रक्रिया पर एक अलग मेमोरी स्कैनर का उपयोग करता हूं, तो मुझे उन पते पर वह मान मिलता है।

हालांकि, जब मैं "ज्ञात पते" स्कैन करता हूं, तो मुझे यह मान कहीं भी नहीं मिलता है। ऐसा लगता है कि मेरा कोड प्रक्रिया के उपयोग में उन पते को भी ढूंढ रहा है।

इसके अतिरिक्त, मेरे सवाल दोहरा है:

  • कैसे मैं इस प्रक्रिया के भीतर इन पतों मिल सकती है?
  • मुझे चिंता है कि मैं एक प्रक्रिया के भीतर सिस्टम मेमोरी बनाम सापेक्ष पते में पूर्ण पते से निपट सकता हूं। क्या मैं इसे ठीक से कर रहा हूं?

// (in the calling method) 
foreach (ProcessModule module in process.Modules) { 
    ParameterizedThreadStart pst = new ParameterizedThreadStart(p => SearchModule(module, value)); 
    Thread t = new Thread(pst); 
    t.Start(); } 

private unsafe void SearchModule(ProcessModule module, string value) 
{ 
Process process = getProcess; 
int iVal; 
double dVal; 
int.TryParse(value, out iVal); 
double.TryParse(value, out dVal); 
for (Int64 addr = (Int64)module.BaseAddress; addr + value.Length < (Int64)module.BaseAddress + module.ModuleMemorySize; addr++) 
{ 
    // Compare ints 
    if (iVal > 0) 
    { 
     byte[] ExpectedBytes = BitConverter.GetBytes(iVal); 
     byte[] ActualBytes = ReadMemoryBytes(module, (IntPtr)addr, (uint)ExpectedBytes.Length, (IntPtr)addr); 

     bool isMatch = true; 
     for (int i = 0; i < ExpectedBytes.Length; i++) 
      if (ExpectedBytes[i] != ActualBytes[i]) 
       isMatch = false; 
     if (isMatch) 
      PossibleAddresses.Add((IntPtr)addr); 
    } 
} 

private byte[] ReadMemoryBytes(ProcessModule mod, IntPtr memAddress, uint size, IntPtr BaseAddress) 
{ 
    byte[] buffer = new byte[size]; 
    IntPtr bytesRead; 
    unsafe 
    { 
     ReadProcessMemory(processPointer, BaseAddress, buffer, size, out bytesRead); 
     return buffer; 
    } 
} 

[DllImport("kernel32.dll")] 
public static extern IntPtr OpenProcess(UInt32 dwDesiredAccess, Int32 bInheritHandle, UInt32 dwProcessId); 
[DllImport("kernel32.dll")] 
public static extern Int32 CloseHandle(IntPtr hObject); 
[DllImport("kernel32.dll")] 
public static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead); 
+0

आपकी दोषपूर्ण धारणा यह है कि (एमएसडीएन से): "मॉड्यूल मेमरीसाइज में कोई अतिरिक्त मेमोरी आवंटन शामिल नहीं होता है जो मॉड्यूल एक बार चल रहा है, इसमें मॉड्यूल फ़ाइल में केवल स्थिर कोड और डेटा का आकार शामिल है।" तो आपका पाश हर जगह नहीं दिखता है। आपको जो चाहिए वह प्रक्रिया का एक संपूर्ण स्मृति मानचित्र है, लेकिन मुझे यकीन नहीं है कि आप सी # में ऐसा कैसे कर सकते हैं। Sysinternals VMMap उपकरण इसे कर सकता है, लेकिन इसके लिए कोई स्रोत उपलब्ध नहीं है ... (http://technet.microsoft.com/en-us/sysinternals/dd535533) – Joe

उत्तर

1

आपके द्वारा प्राप्त किए जा रहे पते प्रबंधित (सीएलआर) ढेर के पॉइंटर्स हैं। वे आम तौर पर पूर्ण मेमोरी पतों पर मैप नहीं करेंगे और वे जीसी को चलाने का फैसला करते हुए कॉल टू कॉल से स्थानांतरित कर सकते हैं।

यदि आप "असुरक्षित" कोड का उपयोग करते हैं, तो आप रिश्तेदार पॉइंटर्स के साथ-साथ अपनी मेमोरी स्पेस प्रबंधित कर सकते हैं। यह अभी भी ढेर पर है लेकिन कम से कम आप गारंटी देते हैं कि जीसी आपके पता स्थान को संशोधित नहीं करेगा।

गैर-सीएलआर कोड से ढेर पर चीजों को व्यापक लपेटने के बिना चीजों तक पहुंचने में सक्षम होने की उम्मीद न करें। सीएलआर-प्रबंधित प्रक्रियाओं के बीच आईपीसी करने के तरीके हैं, लेकिन अगर आप अपनी याददाश्त के लिए गैर-सीएलआर प्रक्रिया चाहते हैं तो आपको "बाहरी दुनिया" में पहुंच प्रॉक्सी लिखना होगा।