• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            記錄一些學習小事

            Work hard

            統計

            留言簿

            閱讀排行榜

            評論排行榜

            spy++和游戲修改器

            這幾天做了兩個東西,spy++ 和游戲修改器。 spy++ 就是模仿 vs的那個工具spy++ 。游戲修改器,就是暴力搜索內存,找到我們關心的數據,然后進行更改。
            總之這些東西做過之后感覺就是都不難,但是在做的時候多少會感覺點吃力。唉,功力不夠啊。繼續修煉……
            閑下來無事,記錄下它們的過程吧。
            spy++ 分析(用vs2005做的——)
            spy++ 需要拖動一個小圖標 然后移動到別的窗口上(本窗口也可以),然后畫出窗口的矩形,得到窗口的一些信息。
            拖動的這個小圖標,是一個picture conctrl控件 ,屬性的type改成icon 也就是加載一個icon圖標,在屬性imag里把圖標選上。
            給這個控件添加一個類,在這個類里做這個控件的 小圖標拖動操作,即 lbuttondown的時候 把鼠標加載成 小圖標,把picture里的icon換成空心的。
            當鼠標抬起的時候把鼠標換回來原先的光標,然后再把picture里的icon換成有小圖標的那個圖標。
            這里要主次 要把鼠標設成全局有效,要不然的話,鼠標位置出了這個picture的范圍就失效了。函數是 SetCapture()
            然后再lbuttonup的時候記得 要釋放。ReleaseCapture();
                       就是這幾個圖標。吼吼。
            把這個小圖標托到 窗口上的時候怎么在窗口上畫出矩形呢? 
            當然是先得到這個矩形了。我要先得到這個窗口的句柄,我們才能得到windowrect 然后才能畫。
            所以各 下一步就是WindowFromPoint(Point)傳一個鼠標點 然后得到這個點的window的hWnd了 哈,很強大的函數啊。
            得到窗口句柄就好辦了。GetWindowRect得到矩形區域啊,然后用windowdc 畫,用windowdc的原因就是,我們要在整個桌面上都能畫。
            這里畫這個矩形有個技巧,我們要畫出來,但是當我們不需要這個矩形的時候我們還要給這個顏色畫回原來的背景色。這里算是整個程序的一個難點,考驗畫圖工夫。
            dc設備中默認選入的是一個黑色畫筆,一個白色畫刷,也就是說正常我們畫矩形的話會畫出黑邊白底得矩形,現在我們要透明的底,然后畫的黑邊還要可畫回原先的背景色。有一個函數通過dc調用  dc.SetROP2(R2_NOTXORPEN);參數傳這個同或運算,這個函數的意思就是,拿你設備中的畫筆畫刷 去跟背景色運算,同或運算。
            比如背景有個顏色是10010100011   你的畫刷顏色是白色 也就是111111111111(比如就這么多位)  白色因為是255,255,255所以都是1  
            然后進行同或運算得到的是什么?是10010100011(同或,同則1,不同則0)!也就說 還是背景色,這就做到了畫刷透明。然后畫筆是黑色,0000000000
            跟背景色同或運算的到得是01101011100 這個。然后這個就是真正畫到屏幕上顯示出來的顏色。怎么在把這個顏色畫沒呢?大家在用這個黑色的畫筆畫一下,在同或運算看看結果是什么?10010100011 看看是不是又變回去了?吼吼。等會下面貼代碼畫圖這里的。
            這個畫圖就完事了。而且窗口句柄我們也通過windowfrompoint得到了。有了窗口句柄我們能得到很多東西了。
            比如說窗口類名GetClassName
            窗口標題GetWindowText
            窗口矩形GetWindowRect
            窗口id等信息GetWindowLong
            進程id   GetWindowThreadProcessId
            進程路徑 OpenProcess()   GetModuleFileNameEx();

            還可以向窗口中發消息 sendmessage(這個比較好玩,可以拿你的spy++去關閉別人的窗口。
            然后把他設置到窗口上就可以了。
            代碼貼一小段。

            void CMyPic::OnTimer(UINT_PTR nIDEvent)
            {
                POINT p;
                ::GetCursorPos(
            &p);
                hWnd
            =::WindowFromPoint(p);
                CRect rect;
                ::GetWindowRect(hWnd,
            &rect);
                CWindowDC dc(NULL);
                CPen redpen(PS_SOLID,
            3,RGB(255,0,0));
                dc.SelectObject(
            &redpen);
                dc.SetROP2(R2_NOTXORPEN);
                dc.Rectangle(rect);
                
            //顯示回去 就向沒畫一樣
                Sleep(300);
                dc.Rectangle(rect);
                ReleaseDC(
            &dc);
                CStatic::OnTimer(nIDEvent);
            }

            這個畫圖在timer里畫,能做到 閃動的巨型。(我選的紅色畫筆,你可以把紅色跟背景同或算算,跟黑色是一樣的,在畫一次就能畫回來背景色)
            下面的代碼是 寫我的spy++的第一頁的代碼

            void CMyspyDlg::UpdataWindowNormal(HANDLE hWnd)
            {
             CString str;
             int state=((CButton *)GetDlgItem(IDC_CHECK1))->GetCheck();
             //窗口句柄
             if (state==BST_CHECKED)
             {
              str.Format(_T("%p"),hWnd);
             }
             else
             {
              str.Format(_T("%d"),hWnd);
             }
             m_TabCtrl.m_dlg[0].GetDlgItem(IDC_EDIT_HANDLE)->SetWindowText(str);
             //窗口類名
             TCHAR tempTC[50];
             GetClassName((HWND)hWnd,tempTC,49);
             m_TabCtrl.m_dlg[0].GetDlgItem(IDC_EDIT_CLASSNAME)->SetWindowText(tempTC);
             //窗口標題
             ZeroMemory(tempTC,100);
             ::GetWindowText((HWND)hWnd,tempTC,49);
             if (*tempTC==_T('\0'))
             {
              m_TabCtrl.m_dlg[0].GetDlgItem(IDC_EDIT_TITLE)->SetWindowText(_T("無"));
             }
             else
             {
              m_TabCtrl.m_dlg[0].GetDlgItem(IDC_EDIT_TITLE)->SetWindowText(tempTC);
             }
             //窗口矩形
             CRect rect;
             ::GetWindowRect((HWND)hWnd,&rect);
             str.Empty();
             if (state==BST_CHECKED)
             {
              str.Format(_T("x=%x,y=%x,width=%x,hight=%x"),rect.left,rect.top,rect.Width(),rect.Height());
             }
             else
             {
              str.Format(_T("x=%d,y=%d,width=%d,hight=%d"),rect.left,rect.top,rect.Width(),rect.Height());
             }
             m_TabCtrl.m_dlg[0].GetDlgItem(IDC_EDIT_WINRECT)->SetWindowText(str);
             //窗口id
             str.Empty();
             LONG l=::GetWindowLong((HWND)hWnd,GWL_ID);
             str.Format(_T("%ld"),l);
             m_TabCtrl.m_dlg[0].GetDlgItem(IDC_EDIT_WINID)->SetWindowText(str);
             //進程id
             DWORD dword;
             ::GetWindowThreadProcessId((HWND)hWnd,&dword);
             str.Empty();
             if (state==BST_CHECKED)
             { 
              str.Format(_T("%p"),dword);
             }
             else
             {
              str.Format(_T("%d"),dword);
             }
             m_TabCtrl.m_dlg[0].GetDlgItem(IDC_EDIT_PROCESSID)->SetWindowText(str);
             //程序路徑
             HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,dword);
             TCHAR src[200];
             GetModuleFileNameEx(hProcess,NULL,src,199);
              m_TabCtrl.m_dlg[0].GetDlgItem(IDC_EDIT_PROSRC)->SetWindowText(src);
            }

            ======================================================================
            效果圖

            ======================================================================

            好了 下面記錄下游戲修改器
            其實我用的方法很笨的,但是比較簡單。改成功了植物大戰僵尸中的太陽值。
            =======================================================================
            效果圖

            =======================================================================
            這個游戲修改 就是讀內存,值進行比較,然后找到一些跟你輸入的值相同的地址,記錄在鏈表中,然后讓這個值變化,在對鏈表進行搜索
            如果鏈表中的地址中的值也變化了,正確的地址就在這鏈表里,繼續變化值,之后最后地址確定下來為止,地址確定下來之后就可以修改了。
            其中用到得函數 先是 快照,(我在前面做任務管理器中寫到過) 得到進程id 進程名等。
            然后用openprocess打開方式用要可讀,可寫,或者獲得所有權PROCESS_ALL_ACCESS。得到進程的句柄。
            然后通過進程的句柄讀進程中的數據ReadProcessMemory因為虛擬內存共有4gb  后2gb是系統用,還有前多少K(不同系統不一樣)也系統用。所以我們只搜索前兩gb ,但是前面那些系統的我們就忽略了,畢竟是小數,不在乎多讀那點了。
            ReadProcessMemory這個函數第一個參數是進程handle,第二個參數 是基址(即從那個位置開始讀,是一個地址),第三個參數是讀出的buff 第四個是讀的大小。 由于內存頁是4kb 我們為了讀的速度快 所以我們每次就讀4kb。 讀出這4kb 放入buff中 然后 拿我們要找的數值比如是100,(我們假定我們的數是2字節),在4kb中1字節1字節的向后走,兩字節兩字節的比較 如果等于100則加入鏈表
            DWORD dOneGB=1024*1024*1024;//1gb的地址
             DWORD dBase=0;//基址是0
             DWORD dOnePage=4*1024;//一個內存頁4kb
             BYTE buffer[4*1024];//裝一個內存也
             WORD value;
             CString str;
             int pos=0;
             POSITION listpos;
            //得到我們窗口上輸入的值 value
             GetDlgItem(IDC_EDIT_INPUT)->GetWindowText(str);
             value=_wtoi(str);
             for (dBase;dBase<dOneGB*2;dBase+=dOnePage)//遍歷2gb每次 加一頁  4kb
             {
              if(ReadProcessMemory(hProcess,(LPCVOID)dBase,buffer,4*1024,NULL))//讀一個頁,因為這個讀取是不一定成功的所以加if(有的內存系統不讓你讀)
              { 
            //進行比較 如果相同加入鏈表CList m_Data;
               for(DWORD b=0;b<dOnePage-1;b++)
               {
                WORD tempword=*((WORD *)(buffer+b));
                if (tempword==value)
                {
                 if (pos==0)//如果是頭結點就 加在頭上,之后就加在后邊
                 {
                  listpos = m_Data.AddHead(dBase+b);
                  pos++;
                 }
                 else
                 {
                  listpos = m_Data.InsertAfter(listpos,dBase+b);
                 }
                }
               }
              }
             }

            這樣這個第一次搜索就完成了。搜出了一堆 等于100的值 的地址,放入了鏈表
            下次就是   改變100為150,然后再鏈表中搜索等于150的。
            int dataCount=m_Data.GetCount();
             pp=m_Data.GetHeadPosition();
              for (int i=0;i<dataCount;i++)
              {
               DWORD tempvalue=m_Data.GetNext(pp);
            //根據基址讀出兩個字節的數,然后跟value比較
               ReadProcessMemory(hProcess,(LPCVOID)tempvalue,&buff,2,NULL);
               if(buff==value)
               {
               if (head)
               {
                li.AddHead(tempvalue);
                head=FALSE;
               }
               else
               {
                li.AddTail(tempvalue);
               }
               }
              }
            哈哈,然后最后就搜到了那個值得地址,,然后根據這個地址改變 其中的值就行了

            WriteProcessMemory(hProcess,(LPVOID)address,&newValue,2,NULL);
            思路倒是很簡單,寫的時候總會出錯誤,或是內存錯誤或是中斷的,要耐心調調。
            為了植物大戰講師的無限陽光,吼吼。go


             

            posted on 2011-08-09 15:06 陳曉 閱讀(4025) 評論(8)  編輯 收藏 引用

            評論

            # re: spy++和游戲修改器 2011-08-10 10:05 zuhd

            改變100為150,然后再鏈表中搜索等于150的。

            這樣啊,牛!  回復  更多評論   

            # re: spy++和游戲修改器[未登錄] 2011-08-10 12:09 heroboy

            先用VirtualQueryEx得到內存的屬性。有些內存區域可能是代碼或者文件的映射,不需要查詢。  回復  更多評論   

            # re: spy++和游戲修改器[未登錄] 2011-08-10 12:50 陳曉

            對!這位兄臺說的很對,呵呵,當時就為了練讀取函數了,沒有弄這些細節,如果把你這個條件方里的話會快一些的。@heroboy
              回復  更多評論   

            # re: spy++和游戲修改器[未登錄] 2011-08-10 12:51 陳曉

            恩呢,如果用150搜了之后還是還有好些地址的話,那么就繼續改變這個值,在搜,我搜植物大戰講師里的陽光值的話,一般3次就能找到正確的那個。@zuhd
              回復  更多評論   

            # re: spy++和游戲修改器 2011-08-10 14:02 coolypf

            可以做個金山游俠2012版!  回復  更多評論   

            # re: spy++和游戲修改器[未登錄] 2011-08-10 14:57 陳曉

            @coolypf
            額樓上的哥們說笑啦,哈哈,小弟水平不行啊,哈哈。我寫的這點東西都是很簡單的,難得也不會啊- -我是現學現賣。。。  回復  更多評論   

            # re: spy++和游戲修改器 2011-08-10 17:23 他她女鞋

            看起來還挺不錯的東東。  回復  更多評論   

            # re: spy++和游戲修改器[未登錄] 2011-08-12 21:41 陳曉

            @他她女鞋
            謝謝支持…  回復  更多評論   

            久久精品国产精品国产精品污| 国内精品久久久久久久涩爱| 国产一区二区三精品久久久无广告| 久久精品中文闷骚内射| 国产成人精品久久亚洲高清不卡 | 久久精品国产精品亜洲毛片| 久久久无码精品亚洲日韩蜜臀浪潮| 亚洲国产另类久久久精品黑人| 久久综合九色综合精品| 久久精品国产免费观看三人同眠| 人妻精品久久无码区| 久久91精品国产91| 亚洲欧美精品伊人久久| 77777亚洲午夜久久多喷| 久久福利片| 久久99精品久久久久子伦| 久久亚洲精品无码aⅴ大香| 狠狠色婷婷久久一区二区三区 | 理论片午午伦夜理片久久| 国产精品美女久久久m| 综合久久精品色| 欧美久久亚洲精品| 久久毛片免费看一区二区三区| 亚洲αv久久久噜噜噜噜噜| 国内精品久久久久影院网站 | 嫩草伊人久久精品少妇AV| 精品水蜜桃久久久久久久| 99久久精品日本一区二区免费| 色狠狠久久综合网| 亚洲国产成人精品91久久久| 99久久伊人精品综合观看| 日韩人妻无码一区二区三区久久 | 日日狠狠久久偷偷色综合96蜜桃| 精品久久久久久久无码 | 久久久精品视频免费观看| 丰满少妇高潮惨叫久久久| 久久99久国产麻精品66| 久久亚洲精品成人无码网站| 久久婷婷五月综合97色直播| 国内精品久久久久久久久电影网| 久久亚洲sm情趣捆绑调教|