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

            聚星亭

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

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

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


                    hZHWnd 
            = ::FindWindow("縱橫時空",NULL);
                    UpdateData(TRUE);
                    m_nChioceGM.ResetContent(); 
                    
            if(hZHWnd != NULL)
                    {
                            
            while(hZHWnd > 0)
                            {
                                    
            if(i >=5)
                                    {
                                            ::AfxMessageBox(
            "因掛機效率考慮,本掛最多可以控制5個角色!請關(guān)閉一些角色然后點刷新按鈕!");
                                            
            break;
                                    }
                                    
            int hFunc=GetClassName(hZHWnd,sClassName.GetBuffer(0),2000);
                                    
            if(hFunc != 0 && 0 <= sClassName.Find("縱橫時空"))
                                    {
                                            
            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)未知錯誤");
                                                    } 
                                            }
                                    }

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

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


                  【內(nèi)容一:簡單的代碼執(zhí)行】
                   到這里,我們已經(jīng)得到目標(biāo)窗口的句柄了,然后接下來就是調(diào)用游戲中的函數(shù),讓游戲去執(zhí)行它,以達到我們的通過程序控制的目的!
                  比如,我先要讓我們的程序能夠控制游戲,比如讓我們程序控制的角色簡單的跳一下。假設(shè)我們通過分析游戲的代碼,找到,跳,這個動作的代碼如下:
            //--------->跳<---------//
            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ù),來達到拾取物品的目的!
                     怎么樣來讓游戲執(zhí)行這個代碼呢?
                     游戲的進程跟我們自己的進程是兩個獨立的實例,自然的,游戲不會跑到我們的進程空間內(nèi)來執(zhí)行我們程序的代碼,否則Windows就亂套了~~~,我們要做的,就只有兩步!
                     第一步  :  把要讓游戲執(zhí)行的代碼寫入游戲的進程空間內(nèi)!
                     第二步 : 給游戲進程創(chuàng)建一個線程,讓它執(zhí)行上述的代碼!

                    其實要完成上述的兩步不難的,寫目標(biāo)進程的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)進程創(chuàng)建個線程的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
            );
            好了,把我寫的一個遠程線程注入代碼的函數(shù)貼一下:
            void    InjectToProcess(DWORD (*FunName)())
            {
                    HANDLE TmpHandle;
                    DWORD dwThreadId;
                    DWORD dwProcessId;

                    CString sClassName
            = "";

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

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

                    
            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)進程建立內(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ù)的傳遞其實也不難的,直接舉個例子吧,希望對卡在這里的朋友有所幫助!
                  這里舉自動的拾取物品的例子,比如我們通過對游戲的分析,找到游戲拾取物品的代碼如下:
            //--------->撿取物品<---------//_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ù)有兩個,一個是地上箱子的ID,一個是箱子中物品的位置,這里的遠程注入的函數(shù)當(dāng)然也不像上一個函數(shù)那么簡單了,我改成了下面的樣子:

                  初始化部分:
            void CInjectCall::InitPorcess(HANDLE _hProcess)
            {
                m_hProcess 
            = _hProcess;
                
            if(m_hProcess != NULL)  
                {
                    
            //在目標(biāo)進程中為函數(shù)名創(chuàng)建空間
                    ThreadAdd  = ::VirtualAllocEx(m_hProcess, NULL,0x128, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
                    
            //在目標(biāo)進程中為函數(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ù)含量的東西,希望對正需要的朋友帶來幫助,也十分的感謝大家能看完我這又臭又長的破爛文章!
                   感覺,不管匯編也好,Delphi也好,VB,JAVA也罷,還是C順手,極力推薦大家學(xué)C,因為很多的東西都可以自己控制,而且又簡單明了,真的是簡約而不簡單的·~~~
                         好了,去就說這么多,希望各位大牛不要笑話,同我一樣的菜菜繼續(xù)努力,去睡覺去了~~~~
                     游戲的半成品外掛連接如下:
                     /Files/bester/ZH_Boot/ZHPlg_src.rar
            久久这里只精品国产99热| 国产99久久久国产精品小说| 青青草国产成人久久91网| 91精品国产综合久久香蕉| 97香蕉久久夜色精品国产| 99久久无码一区人妻a黑| 久久久久综合国产欧美一区二区| 久久精品人人做人人爽电影| 久久久久四虎国产精品| 亚洲日韩欧美一区久久久久我 | 亚洲国产小视频精品久久久三级| 亚洲午夜久久久久久噜噜噜| 久久精品这里只有精99品| 久久久久久亚洲精品成人| 亚洲精品第一综合99久久| 久久这里只精品国产99热| 久久亚洲精品无码AV红樱桃| 污污内射久久一区二区欧美日韩| 精品久久久久久国产潘金莲| 伊人久久精品影院| 久久99精品久久久久久噜噜| 国产成人精品白浆久久69| 精品久久久久久国产| 亚洲国产高清精品线久久| 久久WWW免费人成—看片| 亚洲国产天堂久久综合网站| 久久国产精品77777| 久久综合给合久久狠狠狠97色| 香港aa三级久久三级老师2021国产三级精品三级在 | 久久久久久亚洲Av无码精品专口 | 久久婷婷成人综合色综合| 香蕉久久夜色精品国产2020| 久久99国产精品成人欧美| 国产精品成人精品久久久| 国产成人综合久久精品尤物| 青青草国产成人久久91网| 久久久久久a亚洲欧洲aⅴ| 久久99精品国产| 爱做久久久久久| 久久综合一区二区无码| 久久受www免费人成_看片中文|