简介
偶然候我们会以为某个已经编译好了的程序的功能不是那么完美,我们想要再添加一些额外的功能,但是我们又没有源码,不方便直接进行修改重编译打包,这时间我们就可以考虑给程序添加一个新功能的按钮了...
思路
思路很简单,无非就是使用子类化技术,直接编写DLL,然后注入到程序当中去,固然就一句话但是具体的工作还是比力多,这里我就通过给植物大战僵尸程序为例子仔细说说...
编写DLL
创建按钮
因为我们主要目标是添加一个按钮功能,使用这里主要用到的函数是CreateWindow...
Syntax:
HWND CreateWindow( LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HANDLE hInstance, PVOID lpParam )通过这个函数我们可以创建一个按钮,主要的参数是hWndParent,这个参数表示父窗口句柄,我们可以用FindWindow函数来获取,例如:
#define BUTTON_sir_1 3300HWND hWndParent = FindWindow(NULL,"植物大战僵尸中文版");CreateWindow(TEXT("BUTTON"), TEXT("增加阳光"), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, 600,0,80,30, hWndParent, (HMENU)BUTTON_sir_1, NULL, NULL);子类化
子类化就是用来改变或者扩展一个已存在的窗口的行为、而不用重新开发的有效途径,这是我们添加按钮,给予按钮处理事件的能力的主要方法,主要方法就是通过GetWindowLong()获取窗口旧的消息处理函数(OldWindowProc),然后通过SetWindowLong()设置新的消息处理函数(NewWndProc),进行需要进行的消息处理,其他的交给旧的消息处理函数:
LRESULT CALLBACK NewWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)OldWindowProc = GetWindowLong(hWndParent,GWL_WNDPROC);SetWindowLong(hWndParent,GWL_WNDPROC,(LONG)NewWndProc);新的消息处理函数中只需要写我们感爱好的消息,比如这里我们只关心按键增加阳光的功能,其余我们没有写的消息处理通过CallWindowProc函数交给原来的消息处理函数处理:
LRESULT CALLBACK NewWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam){ int wmId, wmEvent; switch(message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // 分析菜单选择: switch (wmId) { case BUTTON_sir_1: MessageBox(NULL,TEXT("3003"),TEXT("HELLO"),MB_OK); break; default: return CallWindowProc((WNDPROC)OldWindowProc,hWnd,message,wParam,lParam); } break; default: return CallWindowProc((WNDPROC)OldWindowProc,hWnd,message,wParam,lParam); } return 0;}如许我们的按键就有相应消息的能力了,剩下的就是美满dll,然后编写dll注入代码了;
DLL注入
基本步骤是:
- 获取目标进程句柄
- 将要注入的dll路径写入目标进程内存
- 获取LoadLibraryW()API地址
- 在目标进程中运行远程线程
dll注入的代码确实网上确实到处都是,我这里直接贴出参考,用的是CreateRemoteThread的方法;
效果
dll代码
// dllmain.cpp : 界说 DLL 应用程序的入口点。#include "stdafx.h"#include #include #define BUTTON_sir_1 3300#define BUTTON_sir_2 3301#define BUTTON_sir_3 3302//extern "C" _declspec(dllexport)LONG OldWindowProc,Button1Proc;HWND pro_hwnd; //程序句柄HANDLE hpro; //进程句柄DWORD pro_base = NULL; //程序基地址char szBuf[1024] = { 0 };LRESULT CALLBACK NewWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);int kill(){ pro_hwnd = FindWindow(NULL,"植物大战僵尸中文版"); //植物大战僵尸中文版 if (pro_hwnd == NULL){ //如果无法获取句柄则报错 return -1; } DWORD pro_id; GetWindowThreadProcessId(pro_hwnd, &pro_id); //获取进程ID if(pro_id == 0){ //printf("无法获取进程ID\n"); return 0; } //printf("进程id: %d\n",pro_id); //打开进程对象,并获取进程句柄 hpro = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, pro_id); if (hpro == 0){ printf("无法获取进程句柄"); } printf("进程句柄id: %d\n",hpro); // 获取每一个模块加载基址 HMODULE hModule[200] = {0}; DWORD dwRet = 0; int num = 0; int bRet = EnumProcessModulesEx(hpro, (HMODULE *)(hModule), sizeof(hModule),&dwRet,NULL); if (bRet == 0){ printf("EnumProcessModules"); } // 总模块个数 num = dwRet/sizeof(HMODULE); pro_base = (DWORD)hModule[0]; return 0;}void sun_add(){ DWORD sun_addr = pro_base + 0x002A9EC0; printf("阳光基址: 0x%p\n",sun_addr); DWORD sun_value; DWORD new_sun_value; ReadProcessMemory(hpro,(PVOID)sun_addr,&sun_addr,4,0); sun_addr = sun_addr + 0x768; ReadProcessMemory(hpro,(PVOID)sun_addr,&sun_addr,4,0); sun_addr = sun_addr + 0x5560; ReadProcessMemory(hpro,(PVOID)sun_addr,&sun_value,4,0); new_sun_value = sun_value + 2000; WriteProcessMemory(hpro, (LPVOID)sun_addr, &new_sun_value, 4, 0); //修改阳光}void kill_all(){ DWORD kill_1 = pro_base + 0x0013130F; //0x0053130F DWORD code_1 = 0x9090ff29; //0x20247c2b WriteProcessMemory(hpro, (LPVOID)kill_1, (LPVOID)&code_1, 4, 0); //平常僵尸秒杀 DWORD kill_2 = pro_base + 0x00131044; //0x00531044 WORD code_2 = 0xC929; //0xc82b WriteProcessMemory(hpro, (LPVOID)kill_2, (LPVOID)&code_2, 2, 0); //帽子僵尸秒杀}void no_time(){ DWORD no_time = pro_base + 0x00087296; //0x487296 WORD code_3 = 0x9090; //jle 004872AC WriteProcessMemory(hpro, (LPVOID)no_time, (LPVOID)&code_3, 2, 0); //无冷却时间}DWORD APIENTRY Msg(LPVOID lpParameter){ char szBuf[1024] = { 0 }; //hwnd = FindWindow(NULL, TEXT("wintest")); CreateWindow(TEXT("BUTTON"), TEXT("增加阳光"), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, 600,0,80,30, pro_hwnd, (HMENU)BUTTON_sir_1, NULL, //(HINSTANCE)GetWindowLongPtr((HWND)lpParameter,GWLP_HWNDPARENT) NULL); CreateWindow(TEXT("BUTTON"), TEXT("僵尸秒杀"), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, 600,40,80,30, pro_hwnd, (HMENU)BUTTON_sir_2, NULL, NULL); CreateWindow(TEXT("BUTTON"), TEXT("无冷却"), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, 600,80,80,30, pro_hwnd, (HMENU)BUTTON_sir_3, NULL, NULL); OldWindowProc = GetWindowLong(pro_hwnd,GWL_WNDPROC); SetWindowLong(pro_hwnd,GWL_WNDPROC,(LONG)NewWndProc); MSG msg; while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0;}LRESULT CALLBACK NewWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam){ int wmId, wmEvent; switch(message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // 分析菜单选择: switch (wmId) { case BUTTON_sir_1: //MessageBox(NULL,TEXT("3003"),TEXT("HELLO"),MB_OK); sun_add(); break; case BUTTON_sir_2: kill_all(); break; case BUTTON_sir_3: no_time(); break; default: return CallWindowProc((WNDPROC)OldWindowProc,hWnd,message,wParam,lParam); } break; default: return CallWindowProc((WNDPROC)OldWindowProc,hWnd,message,wParam,lParam); } return 0;}BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ){ switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: { kill(); CreateThread(NULL, 0, Msg, hModule, 0, NULL); break; } case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE;}Source.def:
LIBRARY "DLL"EXPORTS Msg
来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |