C#如何獲取其他程序ListView控件中的內容


源碼下載:http://download.csdn.net/detail/php_fly/4923388

需求:獲取其他程序中的ListView控件的文本內容

原理進程之間是相互隔離的,數據是不能共享的(有些特例)

   LVM_GETTITEMTEXT:將一個數據緩沖區提供給listview32控件,你不能把你的進程的數據緩沖提供給另外的程序,所以要用openprocess 打開“任務管理器”進程, 然后     在“任務管理器進程”中申請足夠長度的內存(VirualAllocEx),將這個內存地址提供給listview32,使用 sendmessage 發送LVM_GETTITEMTEXT消息,待sendmessage返        回后,用readprocessmemory 讀取這段內存的數據,即listview控件的文本內容

【視頻+課件+實驗程序】小甲魚逆向破解教程之OD使用教程

API函數

 

  • FindWindow                    //查找窗口
  • FindWindowEx                    ////在窗口列表中尋找與指定條件相符的第一個子窗口
  • SendMessage
  • GetWindowThreadProcessId//找出某個窗口的創建者(線程或進程),返回創建者的標志符
  • OpenProcess          //打開一個已存在的進程對象,並返回進程的句柄
  • VirtualAllocEx                    //為指定的進程分配內存地址:成功則返回分配內存的首地址
  • ReadProcessMemory          //從指定內存中讀取字節集數據
  • WriteProcessMemory         //將數據寫入內存中
  • CloseHandle
  • VirtualFreeEx                   //在其它進程中釋放申請的虛擬內存空間

 

 程序演示

 代碼

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace 讀取其他軟件listview控件的內容
{
    public partial class Form1 : Form
    {
        int hwnd;   //窗口句柄
        int process;//進程句柄
        int pointer;
        private const uint LVM_FIRST = 0x1000;
        private const uint LVM_GETHEADER = LVM_FIRST + 31;
        private const uint LVM_GETITEMCOUNT = LVM_FIRST + 4;//獲取列表行數
        private const uint LVM_GETITEMTEXT = LVM_FIRST + 45;//獲取列表內的內容
        private const uint LVM_GETITEMW = LVM_FIRST + 75;

        private const uint HDM_GETITEMCOUNT = 0x1200;//獲取列表列數

        private const uint PROCESS_VM_OPERATION = 0x0008;//允許函數VirtualProtectEx使用此句柄修改進程的虛擬內存
        private const uint PROCESS_VM_READ = 0x0010;//允許函數訪問權限
        private const uint PROCESS_VM_WRITE = 0x0020;//允許函數寫入權限

        private const uint MEM_COMMIT = 0x1000;//為特定的頁面區域分配內存中或磁盤的頁面文件中的物理存儲
        private const uint MEM_RELEASE = 0x8000;
        private const uint MEM_RESERVE = 0x2000;//保留進程的虛擬地址空間,而不分配任何物理存儲

        private const uint PAGE_READWRITE = 4;

        private int LVIF_TEXT = 0x0001;  

        [DllImport("user32.dll")]//查找窗口
        private static extern int FindWindow(
                                            string strClassName,    //窗口類名
                                            string strWindowName    //窗口標題
        );
        
        [DllImport("user32.dll")]//在窗口列表中尋找與指定條件相符的第一個子窗口
        private static extern int FindWindowEx(
                                              int hwndParent, // handle to parent window
                                            int hwndChildAfter, // handle to child window
                                              string className, //窗口類名            
                                              string windowName // 窗口標題
        );
        [DllImport("user32.DLL")]
        private static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);
        [DllImport("user32.dll")]//找出某個窗口的創建者(線程或進程),返回創建者的標志符
        private static extern int GetWindowThreadProcessId(int hwnd,out int processId);
        [DllImport("kernel32.dll")]//打開一個已存在的進程對象,並返回進程的句柄
        private static extern int OpenProcess(uint dwDesiredAccess, bool bInheritHandle,int processId);
        [DllImport("kernel32.dll")]//為指定的進程分配內存地址:成功則返回分配內存的首地址
        private static extern int VirtualAllocEx(int hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
        [DllImport("kernel32.dll")]//從指定內存中讀取字節集數據
        private static extern bool ReadProcessMemory(
                                            int hProcess, //被讀取者的進程句柄
                                            int lpBaseAddress,//開始讀取的內存地址
                                            IntPtr lpBuffer, //數據存儲變量
                                            int nSize, //要寫入多少字節
                                            ref uint vNumberOfBytesRead//讀取長度
        );
        [DllImport("kernel32.dll")]//將數據寫入內存中
        private static extern bool WriteProcessMemory(
                                            int hProcess,//由OpenProcess返回的進程句柄
                                            int lpBaseAddress, //要寫的內存首地址,再寫入之前,此函數將先檢查目標地址是否可用,並能容納待寫入的數據
                                            IntPtr lpBuffer, //指向要寫的數據的指針
                                            int nSize, //要寫入的字節數
                                            ref uint vNumberOfBytesRead
        );
        [DllImport("kernel32.dll")]
        private static extern bool CloseHandle(int handle);
        [DllImport("kernel32.dll")]//在其它進程中釋放申請的虛擬內存空間
        private static extern bool VirtualFreeEx(
                                    int hProcess,//目標進程的句柄,該句柄必須擁有PROCESS_VM_OPERATION的權限
                                    int lpAddress,//指向要釋放的虛擬內存空間首地址的指針
                                    uint dwSize,
                                    uint dwFreeType//釋放類型
        );
        /// <summary>
        /// LVITEM結構體,是列表視圖控件的一個重要的數據結構
        /// 占空間:4(int)x7=28個byte
        /// </summary>
        private struct LVITEM  //結構體
        {
            public int mask;//說明此結構中哪些成員是有效的
            public int iItem;//項目的索引值(可以視為行號)從0開始
            public int iSubItem; //子項的索引值(可以視為列號)從0開始
            public int state;//子項的狀態
            public int stateMask; //狀態有效的屏蔽位
            public IntPtr pszText;  //主項或子項的名稱
            public int cchTextMax;//pszText所指向的緩沖區大小
        }

        public Form1()
        {
            InitializeComponent();
        }

        /// <summary>  
        /// LV列表總行數
        /// </summary>
        private int ListView_GetItemRows(int handle)
        {
            return SendMessage(handle,LVM_GETITEMCOUNT,0,0);
        }
        /// <summary>  
        /// LV列表總列數
        /// </summary>
        private int ListView_GetItemCols(int handle)
        {
            return SendMessage(handle, HDM_GETITEMCOUNT, 0, 0);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            int headerhwnd; //listview控件的列頭句柄
            int rows,cols;  //listview控件中的行列數
            int processId; //進程pid  

            hwnd = FindWindow("#32770", "Windows 任務管理器");
            hwnd = FindWindowEx(hwnd, 0, "#32770",null);
            hwnd = FindWindowEx(hwnd, 0, "SysListView32",null);//進程界面窗口的句柄,通過SPY獲取
            headerhwnd = SendMessage(hwnd, LVM_GETHEADER, 0, 0);//listview的列頭句柄

            rows=ListView_GetItemRows(hwnd);//總行數,即進程的數量
            cols = ListView_GetItemCols(headerhwnd);//列表列數
            GetWindowThreadProcessId(hwnd, out processId);

            //打開並插入進程
            process = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, false,processId);
            //申請代碼的內存區,返回申請到的虛擬內存首地址
            pointer = VirtualAllocEx(process, IntPtr.Zero, 4096, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
            string[,] tempStr;//二維數組
            string[] temp = new string[cols];

            tempStr=GetListViewItmeValue(rows,cols);//將要讀取的其他程序中的ListView控件中的文本內容保存到二維數組中

            listView1.Items.Clear();//清空LV控件信息
            //輸出數組中保存的其他程序的LV控件信息
            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < cols;j++ )
                {
                    temp[j]=tempStr[i,j];
                }
                ListViewItem lvi = new ListViewItem(temp);
                listView1.Items.Add(lvi);
            }
        }
            
        /// <summary>
        /// 從內存中讀取指定的LV控件的文本內容
        /// </summary>
        /// <param name="rows">要讀取的LV控件的行數</param>
        /// <param name="cols">要讀取的LV控件的列數</param>
        /// <returns>取得的LV控件信息</returns>
        private string[,] GetListViewItmeValue(int rows,int cols)
        {
            string[,] tempStr = new string[rows,cols];//二維數組:保存LV控件的文本信息
            for (int i = 0; i < rows;i++ )
            {
                for (int j = 0; j < cols;j++ )
                {
                    byte[] vBuffer = new byte[256];//定義一個臨時緩沖區
                    LVITEM[] vItem = new LVITEM[1];
                    vItem[0].mask = LVIF_TEXT;//說明pszText是有效的
                    vItem[0].iItem = i;     //行號
                    vItem[0].iSubItem = j;  //列號
                    vItem[0].cchTextMax = vBuffer.Length;//所能存儲的最大的文本為256字節
                    vItem[0].pszText = (IntPtr)((int)pointer + Marshal.SizeOf(typeof(LVITEM)));                    
                    uint vNumberOfBytesRead = 0;
                    
                    //把數據寫到vItem中
                    //pointer為申請到的內存的首地址
                    //UnsafeAddrOfPinnedArrayElement:獲取指定數組中指定索引處的元素的地址
                    WriteProcessMemory(process,pointer,Marshal.UnsafeAddrOfPinnedArrayElement(vItem,0),Marshal.SizeOf(typeof(LVITEM)), ref vNumberOfBytesRead);
                    
                    //發送LVM_GETITEMW消息給hwnd,將返回的結果寫入pointer指向的內存空間
                    SendMessage(hwnd, LVM_GETITEMW,i,pointer);

                    //從pointer指向的內存地址開始讀取數據,寫入緩沖區vBuffer中
                    ReadProcessMemory(process,((int)pointer + Marshal.SizeOf(typeof(LVITEM))),Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer,0),vBuffer.Length, ref vNumberOfBytesRead);                    
                    
                    string vText = Encoding.Unicode.GetString(vBuffer, 0, (int)vNumberOfBytesRead); ;                    
                    tempStr[i,j] = vText;
                }
            }
            VirtualFreeEx(process, pointer, 0, MEM_RELEASE);//在其它進程中釋放申請的虛擬內存空間,MEM_RELEASE方式很徹底,完全回收
            CloseHandle(process);//關閉打開的進程對象
            return tempStr;
        }
    }
}

原創文章,轉載請注明出處:http://www.cnblogs.com/hongfei/archive/2012/12/23/2829799.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM