• <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>

            聚星亭

            吾笨笨且懶散兮 急須改之而奮進(jìn)
            posts - 74, comments - 166, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
                【前言】
                    夜里失眠,到這個(gè)論壇上泡,發(fā)現(xiàn)這個(gè)編程版塊不是很正規(guī),因?yàn)槲艺J(rèn)為的好的編程版塊應(yīng)該是以討論分享及解決具體問題而存在的,而不是想咱論壇這樣:
            救助的問題不明確,分享就是單純的分享源碼,分享XX成品之類……

                【廢話】
                      前幾天研究外掛了,就我這點(diǎn)破水平,脫機(jī)啊,封包掛啊之類的與我無緣了,只能做做內(nèi)掛,滿足一下自己的虛榮心……
                 這里大概的給大家分享一下做內(nèi)掛編程方面的知識(shí),高手飄過,跟我一樣菜的朋友多多提出您的寶貴意見,相互學(xué)習(xí)、共勉!!!
                 當(dāng)然了,也希望這篇文章能騙個(gè)精華之類的東東,作為我炫耀的資本~~~~
                 內(nèi)掛,其實(shí)不難的,這里主要分享遠(yuǎn)程線程注入相關(guān)的東西,至于其它什么游戲找CALL,功能CALL調(diào)用相關(guān)的東西,可以參考一下我寫的:
                 賺取權(quán)限第三貼,一個(gè)有意思的keygenMe的逆向分析
                      其實(shí)道理都是相同的,當(dāng)然,如果您非常想要了解相關(guān)的東西,請參考別人大牛寫的文章,這里不做詳細(xì)討論。

                 【基礎(chǔ)】
                  我理解的遠(yuǎn)程線程注入,包括注入代碼,注入DLL分為這兩種(如果有不對(duì)的地方希望指正,謝謝),注入DLL就不多廢話了,就是把DLL及所在目錄的名字一些通過寫內(nèi)存的API寫到目標(biāo)進(jìn)程中,我今天主要討論的是向目標(biāo)進(jìn)程寫代碼,是獲取目標(biāo)進(jìn)程的句柄的方法有很多的,比如創(chuàng)建進(jìn)程鏡像,然后遍歷進(jìn)程,再如通過遍歷窗口標(biāo)題,類名之類得到窗口句柄,然后在由窗口句柄得到進(jìn)程的句柄,這里只舉最常用到的通過窗口名的方法,至于遍歷進(jìn)程的方法有很多的,您可以百度一下就能找到……
            void CZHGameDlg::OnShuaxin() 
            {
                    
            //載入游戲
                    DWORD dwZHThreadId;
                    DWORD dwZHProcessId;
                    HWND hZHWnd;
                    DWORD BASE;
                    
            char tmpName[65];
                    
            int i = 0;
                    CString sClassName
            = "";


                    hZHWnd 
            = ::FindWindow("縱橫時(shí)空",NULL);
                    UpdateData(TRUE);
                    m_nChioceGM.ResetContent(); 
                    
            if(hZHWnd != NULL)
                    {
                            
            while(hZHWnd > 0)
                            {
                                    
            if(i >=5)
                                    {
                                            ::AfxMessageBox(
            "因掛機(jī)效率考慮,本掛最多可以控制5個(gè)角色!請關(guān)閉一些角色然后點(diǎn)刷新按鈕!");
                                            
            break;
                                    }
                                    
            int hFunc=GetClassName(hZHWnd,sClassName.GetBuffer(0),2000);
                                    
            if(hFunc != 0 && 0 <= sClassName.Find("縱橫時(shí)空"))
                                    {
                                            
            if( dwZHThreadId = ::GetWindowThreadProcessId(hZHWnd, &dwZHProcessId))
                                            {
                                                    
            try
                                                    {
                                                            m_hZHProcess 
            = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwZHProcessId+1);
                                                            
            if(m_hZHProcess != NULL) 
                                                            {
                                                                    ReadProcessMemory(m_hZHProcess,(LPVOID)ZH_BASE_ADDR,
            &BASE,4,NULL); 
                                                                    ReadProcessMemory(m_hZHProcess,(LPVOID)(BASE
            +0xAC),tmpName,20,NULL); 

                                                                    ProcName[i].Name 
            = tmpName;
                                                                    ProcName[i].hZHhwnd 
            = hZHWnd;
                                                                    ProcName[i].hZHProcess 
            = m_hZHProcess;
                                                                    
            if0> m_nChioceGM.FindStringExact(0,ProcName[i].Name))
                                                                    m_nChioceGM.AddString(ProcName[i].Name);

                                                                    SetDlgItemText(IDC_TISHI,
            "提示: 遍歷游戲角色完畢,請選擇游戲角色");

                                                                    i
            ++;
                                                                    UpdateData(FALSE);
                                                            }
                                                      }
            catch()
                                                      {
                                                            ::AfxMessageBox(
            "出現(xiàn)未知錯(cuò)誤");
                                                    } 
                                            }
                                    }

                                    hZHWnd 
            = ::GetNextWindow(hZHWnd,GW_HWNDNEXT); 
                            } 
                    }
                    
            else
                    {
                            SetDlgItemText(IDC_TISHI,
            "提示: 沒有找到游戲窗口,請確認(rèn)游戲是否已經(jīng)開啟");
                    }
            }

            這樣我們就可以得到同一個(gè)游戲的所有窗口句柄、進(jìn)程句柄,游戲角色名等信息(這里只以縱橫時(shí)空這個(gè)游戲來說,由于不同的游戲,游戲數(shù)據(jù)的存儲(chǔ)用的數(shù)據(jù)結(jié)構(gòu)各不相同,所以,這個(gè)取角色名的位置不能通用!)如果你有其它的方法,歡迎跟帖子分享!


                  【內(nèi)容一:簡單的代碼執(zhí)行】
                   到這里,我們已經(jīng)得到目標(biāo)窗口的句柄了,然后接下來就是調(diào)用游戲中的函數(shù),讓游戲去執(zhí)行它,以達(dá)到我們的通過程序控制的目的!
                  比如,我先要讓我們的程序能夠控制游戲,比如讓我們程序控制的角色簡單的跳一下。假設(shè)我們通過分析游戲的代碼,找到,跳,這個(gè)動(dòng)作的代碼如下:
            //--------->跳<---------//
            DWORD _stdcall JumpA()
            {
                    DWORD RealAddress,Addr;
                    Sell_STR SellParam;

                    RealAddress 
            = 0x00409C80//真正CALL地址
                    Addr = 0x004336F0//加密CALL地址

                    _asm
                    {
                            push 
            0
                            mov eax, dword ptr [
            0x00833C5C//游戲基址
                            add eax, 108
                            push eax
                            lea ecx,SellParam
                            call Addr
                            push eax
                            MOV ecx, 
            0x0084B908
                            call RealAddress
                    }
                    
            return 0;
            }

            只要我們能讓游戲順利的執(zhí)行我們的上述代碼,我們就可以通過傳入不同的參數(shù),來達(dá)到拾取物品的目的!
                     怎么樣來讓游戲執(zhí)行這個(gè)代碼呢?
                     游戲的進(jìn)程跟我們自己的進(jìn)程是兩個(gè)獨(dú)立的實(shí)例,自然的,游戲不會(huì)跑到我們的進(jìn)程空間內(nèi)來執(zhí)行我們程序的代碼,否則Windows就亂套了~~~,我們要做的,就只有兩步!
                     第一步  :  把要讓游戲執(zhí)行的代碼寫入游戲的進(jìn)程空間內(nèi)!
                     第二步 : 給游戲進(jìn)程創(chuàng)建一個(gè)線程,讓它執(zhí)行上述的代碼!

                    其實(shí)要完成上述的兩步不難的,寫目標(biāo)進(jìn)程的API函數(shù)是:WriteProcessMemory  ,具體的定義如下:
            BOOL WriteProcessMemory(
                            HANDLE hProcess, 
            // handle to process whose memory is written to
                            LPVOID lpBaseAddress,
                            
            // address to start writing to
                            LPVOID lpBuffer, // pointer to buffer to write data to
                            DWORD nSize, // number of bytes to write
                            LPDWORD lpNumberOfBytesWritten 
                            
            // actual number of bytes written
            );
            至于在目標(biāo)進(jìn)程創(chuàng)建個(gè)線程的API及定義如下:
            HANDLE CreateRemoteThread(
                            HANDLE hProcess, 
            // handle to process to create thread in
                            LPSECURITY_ATTRIBUTES lpThreadAttributes, // pointer to security attributes
                            DWORD dwStackSize, // initial thread stack size, in bytes
                            LPTHREAD_START_ROUTINE lpStartAddress, // pointer to thread function
                            LPVOID lpParameter, // argument for new thread
                            DWORD dwCreationFlags, // creation flags
                            LPDWORD lpThreadId // pointer to returned thread identifier
            );
            好了,把我寫的一個(gè)遠(yuǎn)程線程注入代碼的函數(shù)貼一下:
            void    InjectToProcess(DWORD (*FunName)())
            {
                    HANDLE TmpHandle;
                    DWORD dwThreadId;
                    DWORD dwProcessId;

                    CString sClassName
            = "";

                    m_hPwnd 
            = ::FindWindow("TForm1","游戲找CALL練習(xí)實(shí)例one");//得到窗口句柄

                    
            if(m_hPwnd == NULL)
                    {
                            MessageBox(
            "沒有找到主程序,請先運(yùn)行主程序");
                    }

                    
            int hFunc=GetClassName(m_hPwnd,sClassName.GetBuffer(0),2000);
                    
            if(hFunc != 0 && 0 <= sClassName.Find("TForm1"))
                    {
                            
            if( dwThreadId = ::GetWindowThreadProcessId(m_hPwnd, &dwProcessId))
                            {
                                    m_hProcess 
            = ::OpenProcess(PROCESS_ALL_ACCESS,FALSE, dwProcessId);
                                    
            if(m_hProcess != NULL) 
                                    {
                                            
            //在目標(biāo)進(jìn)程建立內(nèi)存空間 
                                            LPVOID ThreadAdd = ::VirtualAllocEx(m_hProcess, NULL,0x1024, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
                                            ::WriteProcessMemory(m_hProcess,ThreadAdd ,FunName,
            0x1024,NULL); 
                                            TmpHandle 
            = CreateRemoteThread(m_hProcess, 
                                                                            NULL, 
            0, (LPTHREAD_START_ROUTINE)ThreadAdd, NULL, 
                                                                            
            0, NULL);//獲得注入后過程的句柄ID 

                                            
            if(WaitForSingleObject(TmpHandle,INFINITE) != WAIT_OBJECT_0)
                                            {
                                                    CString StrTmp;
                                                    StrTmp.Format(
            "%d",GetLastError());
                                                    MessageBox(StrTmp);
                                            }
                                            CloseHandle(TmpHandle);
                                            CloseHandle(m_hProcess);
                                            VirtualFreeEx(m_hProcess,ThreadAdd,
            0x1024,MEM_RELEASE);
                                    }
                            }
                    }
            }

            這樣,我們只要在函數(shù)里調(diào)用:InjectToProcess(JumpA)
            就可以搞定了!


                  【內(nèi)容一:關(guān)于參數(shù)的傳遞】

                   其實(shí),絕大多數(shù)游戲里的函數(shù)都是帶有參數(shù)的,遠(yuǎn)程線程里參數(shù)的傳遞其實(shí)也不難的,直接舉個(gè)例子吧,希望對(duì)卡在這里的朋友有所幫助!
                  這里舉自動(dòng)的拾取物品的例子,比如我們通過對(duì)游戲的分析,找到游戲拾取物品的代碼如下:
            //--------->撿取物品<---------//_OK
            void _stdcall JianWuA(PP1_STR P)
            {
                    DWORD SendAddr 
            = ZH_CALL_SEND;
                    DWORD SendEcx 
            = ZH_CALL_ECX;
                    DWORD Addr 
            = ZH_CALL_SHIQU;

                    DWORD WuPos;
                    DWORD XiangZiID;
                    Sell_STR SellParam;

                    DWORD Mubiao 
            = ZH_SQMUBIAO_ADDR;
                    WuPos 
            = P->Param1;
                    XiangZiID 
            = P->Param2;

                    _asm
                    {
                             push WuPos 
            //在物品欄的位置
                            push XiangZiID //要拾取的物品的ID
                            lea ecx,SellParam
                            Call Addr 
            //簡單的封包加密
                            push eax
                            MOV ecx, SendEcx
                            call SendAddr 
            //發(fā)包CALL
                            MOV BYTE PTR [Mubiao],0
                    }
            }

            這里需要的參數(shù)有兩個(gè),一個(gè)是地上箱子的ID,一個(gè)是箱子中物品的位置,這里的遠(yuǎn)程注入的函數(shù)當(dāng)然也不像上一個(gè)函數(shù)那么簡單了,我改成了下面的樣子:

                  初始化部分:
            void CInjectCall::InitPorcess(HANDLE _hProcess)
            {
                m_hProcess 
            = _hProcess;
                
            if(m_hProcess != NULL)  
                {
                    
            //在目標(biāo)進(jìn)程中為函數(shù)名創(chuàng)建空間
                    ThreadAdd  = ::VirtualAllocEx(m_hProcess, NULL,0x128, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
                    
            //在目標(biāo)進(jìn)程中為函數(shù)名創(chuàng)建空間
                    ParamAddr  = ::VirtualAllocEx(m_hProcess, NULL,0x128, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
                    JiNengAddr  
            = ::VirtualAllocEx(m_hProcess, NULL,0x128, MEM_COMMIT,PAGE_EXECUTE_READWRITE);
                }
            }

                  注入部分:
            void CInjectCall::InjectFunc(LPVOID pFun, DWORD *Param, DWORD ParamSize)
            {
                    HANDLE TmpHandle;
                    DWORD lpNumberOfBytes;
                    
            if(m_hProcess != NULL) 
                    {
                            
            // ---- 寫入函數(shù)地址
                    ::WriteProcessMemory(m_hProcess, ThreadAdd, pFun, 0x128&lpNumberOfBytes); 
                            
            // ---- 寫入?yún)?shù)地址
                    ::WriteProcessMemory(m_hProcess, ParamAddr, Param, ParamSize, &lpNumberOfBytes);

                            TmpHandle 
            = ::CreateRemoteThread(m_hProcess, 
                                                            NULL, 
            0, (LPTHREAD_START_ROUTINE)ThreadAdd,
                                                            ParamAddr, 
            //有參數(shù)就寫參數(shù),無參數(shù)就為NULL
                                                            0&lpNumberOfBytes);//獲得注入后過程的句柄ID 

                           ::WaitForSingleObject(TmpHandle,INFINITE);

                            ::CloseHandle(TmpHandle);
                    }
            }
                 內(nèi)存釋放部分:
            void CInjectCall::TheEndPorcess()
            {
                
            if(m_hProcess != NULL)  
                {
                    ::VirtualFreeEx(m_hProcess,JiNengAddr,
            0x128,MEM_RELEASE);
                    ::VirtualFreeEx(m_hProcess,ThreadAdd,
            0x128,MEM_RELEASE);
                    ::VirtualFreeEx(m_hProcess,ParamAddr,
            0x128,MEM_RELEASE);
                }
            }

            我們調(diào)用的方式也就變成了:
            void CInjectCall::JianWu(int WuPosInList, int XiangZiID)
            {
                    P1_STR MyParam;
                    DWORD ParamSum;
                    BYTE tmpid 
            = 0;
                    MyParam.Param1 
            = WuPosInList;
                    MyParam.Param2 
            = XiangZiID;
                    ParamSum 
            = sizeof(MyParam);

                    InjectFunc(JianWuA, (DWORD 
            *)&MyParam,ParamSum);
            }

            P1_STR 的結(jié)構(gòu)體定義如下:
            typedef struct _P1_STR{ 
                    
            int Param1;
                    
            int Param2;
                    
            int Param3;
            }P1_STR,
            *PP1_STR; 
            這樣就可以了~~~~
                  【結(jié)尾】
                   今天要說的東西就這么多,一些沒什么技術(shù)含量的東西,希望對(duì)正需要的朋友帶來幫助,也十分的感謝大家能看完我這又臭又長的破爛文章!
                   感覺,不管匯編也好,Delphi也好,VB,JAVA也罷,還是C順手,極力推薦大家學(xué)C,因?yàn)楹芏嗟臇|西都可以自己控制,而且又簡單明了,真的是簡約而不簡單的·~~~
                         好了,去就說這么多,希望各位大牛不要笑話,同我一樣的菜菜繼續(xù)努力,去睡覺去了~~~~
                     游戲的半成品外掛連接如下:
                     /Files/bester/ZH_Boot/ZHPlg_src.rar
            伊人久久综合无码成人网| 无码AV中文字幕久久专区| 久久66热人妻偷产精品9| 国产亚洲精久久久久久无码77777| 国内精品久久久久久中文字幕| 久久久91精品国产一区二区三区 | 精品久久久久久国产| 久久久高清免费视频| 久久国产欧美日韩精品免费| 三级韩国一区久久二区综合| 亚洲国产成人乱码精品女人久久久不卡| 国产高潮久久免费观看| 久久九九久精品国产| 一本一道久久a久久精品综合 | 99久久精品免费看国产| 国产一区二区精品久久岳 | 久久久久亚洲AV综合波多野结衣| 国产99久久久国产精免费| 久久久久黑人强伦姧人妻| 日日狠狠久久偷偷色综合免费 | 中文字幕精品久久久久人妻| 亚洲精品无码久久久久久| 国产美女久久精品香蕉69| 国产午夜福利精品久久| 无码八A片人妻少妇久久| 久久精品国产亚洲av麻豆小说| 久久99国产精品久久99| 久久久久亚洲AV综合波多野结衣| 久久久久亚洲AV片无码下载蜜桃| 午夜欧美精品久久久久久久| 国内精品久久久久久不卡影院| 亚洲国产日韩欧美久久| 久久人人爽人人爽人人AV东京热| 久久97久久97精品免视看| 色综合久久无码五十路人妻| 久久久久久无码国产精品中文字幕| 97久久婷婷五月综合色d啪蜜芽 | 久久人人爽人人爽人人爽| 亚洲国产成人久久综合碰| 久久水蜜桃亚洲av无码精品麻豆| 欧美久久精品一级c片片|