找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 383|回复: 2

Windows下如何改写目标进程的窗口函数来注入DL

[复制链接]

30

主题

1

回帖

0

积分

版主

积分
0
发表于 2013-7-8 21:06:28 | 显示全部楼层 |阅读模式

[bgcolor=#f5f5f5]其创建的窗口都有窗口函数,在这里,我介绍一个改写[/bgcolor]

[bgcolor=#f5f5f5]UI线程窗口过程来注入DLL的方法:[/bgcolor]

[bgcolor=#f5f5f5]一:获取一个进程的窗口句柄,例如Notepad.exe进程的主窗口类名是 “NOTEPAD”[/bgcolor]

[bgcolor=#f5f5f5]      通过 FindWindowW(L"NOTEPAD",NULL) 就可以得到运行的 Notepad.exe 的[/bgcolor]

[bgcolor=#f5f5f5]      主窗口的句柄设为 hWndNotepad, 通过 GetWindowThreadProcessId()[/bgcolor]

[bgcolor=#f5f5f5]      就可以获取到 创建该窗口的线程ID和Notepad.exe进程ID,通过 GetClassLongW([/bgcolor]

[bgcolor=#f5f5f5]      hWndNotepad,GCL_WNDPROC)可以得到窗口过程函数地址。[/bgcolor]

[bgcolor=#f5f5f5]      代码大致如下:[/bgcolor]

[bgcolor=#f5f5f5]       HWND hWndNotepad = ::FindWindowW(L"NOTEPAD",NULL);[/bgcolor]

[bgcolor=#f5f5f5]       DWORD proID;[/bgcolor]

[bgcolor=#f5f5f5]       DWORD dThreadID = ::GetWindowThreadProcessId(hWndNotepad ,&proID);[/bgcolor]

[bgcolor=#f5f5f5]       HANDLE hPRocess = ::OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE ,FALSE,proID);[/bgcolor]

[bgcolor=#f5f5f5]       HANDLE hThread = ::OpenThread(THREAD_ALL_ACCESS,dThreadID);[/bgcolor]

[bgcolor=#f5f5f5]       [/bgcolor]

[bgcolor=#f5f5f5]       //注意必须用UNICODE,否则取出来的不是窗口函数地址,而是一个HANDLE值[/bgcolor]

[bgcolor=#f5f5f5]       DWORD dWndProc = ::GetClassLongW(hWndNotepad,GCL_WNDPROC); [/bgcolor]

[bgcolor=#f5f5f5]       //更改窗口函数地址所在内存页面的控制标志,使之能够被覆盖[/bgcolor]

[bgcolor=#f5f5f5]       DWORD dpOld;[/bgcolor]

[bgcolor=#f5f5f5]       ::VirtualProtectEx(hPRocess,LPVOID(dWndProc),8192,PAGE_EXECUTE_READWRITE,&dpOld)[/bgcolor]

[bgcolor=#f5f5f5]二:创建注入的函数[/bgcolor]

[bgcolor=#f5f5f5]      typedef HMODULE (__stdcall *pLoadLibrary)(LPCSTR lpLibFileName);[/bgcolor]

[bgcolor=#f5f5f5]     //必须定义如下4个参数,否则目标线程会发生函数调用错误[/bgcolor]
[bgcolor=#f5f5f5]      void test(HWND hwnd,UINT uMsg,WPARAM wPAram,LPARAM lParam)[/bgcolor]
[bgcolor=#f5f5f5]     {[/bgcolor]
[bgcolor=#f5f5f5]          //不能直接使用常量字符串,否则会引起目标进程读取数据异常。[/bgcolor]
[bgcolor=#f5f5f5]         char dllname[] = {'c',':','\\','d','l','l','t','e','s','t','.','d','l','l','\0'};[/bgcolor]
[bgcolor=#f5f5f5]         //必须用2088770939这个 LoadLibrary 函数的绝对地址(在我的xp下是这个地址,使用时应该在自己的windows下获取)[/bgcolor]
[bgcolor=#f5f5f5]          pLoadLibrary pFunc = pLoadLibrary(2088770939);[/bgcolor]
[bgcolor=#f5f5f5]         //调用LoadLibrary,因为LoadLibrary函数在windows下每个进程中绝对地址都是一样的。[/bgcolor]
[bgcolor=#f5f5f5]        pFunc(dllname);[/bgcolor]
[bgcolor=#f5f5f5]        return;[/bgcolor]
[bgcolor=#f5f5f5]     }[/bgcolor]
[bgcolor=#f5f5f5]     然后将目标线程挂起,取得其当前的CPU CONTEXT(注意,我们的注入控制程序仅仅获取,并不设置),[/bgcolor]

[bgcolor=#f5f5f5]    ::SuspendThread(hThread );[/bgcolor]

[bgcolor=#f5f5f5]     CONTEXT context;[/bgcolor]

[bgcolor=#f5f5f5]     memset(&context,0,sizeof(context));[/bgcolor]
[bgcolor=#f5f5f5]     context.ContextFlags = CONTEXT_CONTROL;[/bgcolor]

[bgcolor=#f5f5f5]     ::GetThreadContext(hThread,&context);[/bgcolor]

[bgcolor=#f5f5f5]     接着将目标窗口过程一部分或全部读出来[/bgcolor]

[bgcolor=#f5f5f5]     BYTE sCodes[1024];[/bgcolor]

[bgcolor=#f5f5f5]     DWORD dLen;[/bgcolor]

[bgcolor=#f5f5f5]     ::ReadProcessMemory(hPRocess,(LPVOID)dWndProc,sCodes,1024, &dLen);[/bgcolor]

[bgcolor=#f5f5f5]     将目标窗口过程一部分或全部用我们的函数覆盖[/bgcolor]

[bgcolor=#f5f5f5]     ::WriteProcessMemory(hProcess,pRemote,(LPVOID)test,1024,&dWriten);[/bgcolor]

[bgcolor=#f5f5f5]     此时目标窗口函数已经被我们改写了,如果唤醒目标线程的话,单击TASKBAR上的记事本窗口[/bgcolor]

[bgcolor=#f5f5f5]     我们的dll就会被自动装载了,但此时目标线程的窗口过程已经无法恢复了,我们需要做恢复工作[/bgcolor]

[bgcolor=#f5f5f5]     恢复工作思路是 在装载的dll里DllMain函数编写代码获取到之前保存的CPU CONTEXT数据和[/bgcolor]

[bgcolor=#f5f5f5]     备份的目标窗口函数的1024字节内容,将我们覆盖的1024字节恢复,同时调用[/bgcolor]

[bgcolor=#f5f5f5]     SetThreadContext()产生时光倒流,让窗口过程恢复之前的工作。[/bgcolor]

[bgcolor=#f5f5f5]     如何获取呢?.....对了,使用共享内存,主控程序建立有名称的共享内存(FileMapping),将上述[/bgcolor]

[bgcolor=#f5f5f5]     数据写入共享内存中,恢复的时候就从共享内存中读取数据,代码如下:[/bgcolor]

[bgcolor=#f5f5f5]     [/bgcolor]

[bgcolor=#f5f5f5]     HANDLE hfileMap = ::CreateFileMappingW(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,\[/bgcolor]

[bgcolor=#f5f5f5]                                    0,4096,L"注入DLL的测试");[/bgcolor]

[bgcolor=#f5f5f5]     LPVOID lpAddr = ::MapViewOfFile(hfileMap,FILE_MAP_WRITE,0,0,4096)//映射整个4096字节范围。[/bgcolor]

[bgcolor=#f5f5f5]     //将窗口句柄写入[/bgcolor]

[bgcolor=#f5f5f5]     BYTE *pStart = (BYTE*)lpAddr;[/bgcolor]

[bgcolor=#f5f5f5]     memcpy(pStart,&hWndNotepad,sizeof(HWND));[/bgcolor]

[bgcolor=#f5f5f5]    //将CPU Context写入[/bgcolor]

[bgcolor=#f5f5f5]    pStart += sizeof(HWND);[/bgcolor]

[bgcolor=#f5f5f5]    memcpy(pStart,&context,sizeof(CONTEXT));[/bgcolor]

[bgcolor=#f5f5f5]    //将备份的目标窗口函数的1024字节内容写入[/bgcolor]

[bgcolor=#f5f5f5]    pStart += sizeof(CONTEXT);[/bgcolor]

[bgcolor=#f5f5f5]    memcpy(pStart,sCodes,1024);[/bgcolor]

[bgcolor=#f5f5f5]    //等待第三步创建好dll后,唤醒目标线程[/bgcolor]

[bgcolor=#f5f5f5]    ::ResumeThread(hThread);[/bgcolor]

[bgcolor=#f5f5f5]    //发送windows消息使得目标线程执行覆盖的窗口函数[/bgcolor]

[bgcolor=#f5f5f5]    ::SendMessage(hWndNotepad,99999999,0,0)[/bgcolor]

[bgcolor=#f5f5f5]    //注意不能立即结束控制进程,必须等待到dll装载后才能结束控制进程,否则[/bgcolor]

[bgcolor=#f5f5f5]    //之前创建的共享内存将不能够被映射,这里仅仅是调用Sleep[/bgcolor]

[bgcolor=#f5f5f5]    ::Sleep(9999999);[/bgcolor]

[bgcolor=#f5f5f5]三:编写我们的dll[/bgcolor]

[bgcolor=#f5f5f5]     #include <windows.h>[/bgcolor]

[bgcolor=#f5f5f5]     BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved[/bgcolor]
[bgcolor=#f5f5f5]     {[/bgcolor]

[bgcolor=#f5f5f5]            if(DLL_PROCESS_ATTACH == ul_reason_for_call)[/bgcolor]

[bgcolor=#f5f5f5]            {[/bgcolor]

[bgcolor=#f5f5f5]                   //不能调用messagebox等UI函数,这样会导致窗口过程函数重入,导致崩溃[/bgcolor]

[bgcolor=#f5f5f5]                   //写log到文件中便于观察[/bgcolor]

[bgcolor=#f5f5f5]                   HANDLE hFile = ::CreateFile("C:\\dllTest.log",GENERIC_READ|GENERIC_WRITE, \[/bgcolor]

[bgcolor=#f5f5f5]                                                              FILE_SHARE_READ,NULL,OPEN_ALWAYS, \[/bgcolor]

[bgcolor=#f5f5f5]                                                              FILE_ATTRIBUTE_NORMAL,NULL);[/bgcolor]

[bgcolor=#f5f5f5]                   //移动文件指针到文件尾[/bgcolor]

[bgcolor=#f5f5f5]                   ::SetFilePointer(hFile,0,0,FILE_END)[/bgcolor]

[bgcolor=#f5f5f5]                   DWORD dLen;[/bgcolor]

[bgcolor=#f5f5f5]                   const char *pData = "this is a test \r\n";[/bgcolor]

[bgcolor=#f5f5f5]                   ::WriteFile(hFile,pData ,strlen(pData ),&dLen,NULL);[/bgcolor]

[bgcolor=#f5f5f5]                   ::CloseHandle(hFile);[/bgcolor]

[bgcolor=#f5f5f5]                  [/bgcolor]

[bgcolor=#f5f5f5]                  //下面是恢复的工作[/bgcolor]

[bgcolor=#f5f5f5]                  HANDLE hfileMap = ::OpenFileMappingW(FILE_MAP_READ,FALSE,L"注入DLL的测试");[/bgcolor]

[bgcolor=#f5f5f5]                  LPVOID lpAddr = ::MapViewOfFile(hfileMap,FILE_MAP_READ,0,0,4096)//映射整个4096字节范围。[/bgcolor]

[bgcolor=#f5f5f5]                  [/bgcolor]

[bgcolor=#f5f5f5]                  //取出恢复工作需要的数据[/bgcolor]

[bgcolor=#f5f5f5]                  HWND hWndMain;[/bgcolor]

[bgcolor=#f5f5f5]                  CONTEXT context;[/bgcolor]

[bgcolor=#f5f5f5]                  BYTE sCodes[1024];[/bgcolor]

[bgcolor=#f5f5f5]                  [/bgcolor]

[bgcolor=#f5f5f5]                  BYTE* pStart = (BYTE*)lpAddr;[/bgcolor]

[bgcolor=#f5f5f5]                  memcpy(&hWndMain,pStart,sizeof(HWND));[/bgcolor]

[bgcolor=#f5f5f5]                  pStart  += sizeof(HWND);[/bgcolor]

[bgcolor=#f5f5f5]                  memcpy(&context,pStart,sizeof(CONTEXT ));[/bgcolor]

[bgcolor=#f5f5f5]                  pStart  += sizeof(CONTEXT );[/bgcolor]

[bgcolor=#f5f5f5]                  memcpy(sCodes,pStart,1024);[/bgcolor]

[bgcolor=#f5f5f5]                 [/bgcolor]

[bgcolor=#f5f5f5]                  //释放共享内存[/bgcolor]

[bgcolor=#f5f5f5]                  ::UnmapViewOfFile(lpAddr);[/bgcolor]

[bgcolor=#f5f5f5]                  ::CloseHandle(hfileMap);[/bgcolor]

[bgcolor=#f5f5f5]                  [/bgcolor]

[bgcolor=#f5f5f5]                   //这里仅仅在dllMain里做恢复,或许不妥,最好的[/bgcolor]

[bgcolor=#f5f5f5]                  //办法是创建一个线程,在线程里恢复,因为[/bgcolor]

[bgcolor=#f5f5f5]                  //memcpy((LPVOID)wndProc,sCodes,1024); 可能会导致下面的代码应经不存在了(微笑)[/bgcolor]

[bgcolor=#f5f5f5]                  //只是可能,就看dllMain函数与窗口函数的偏移量是多少了,应该大于1024字节的。[/bgcolor]

[bgcolor=#f5f5f5]                   [/bgcolor]

[bgcolor=#f5f5f5]                  //恢复窗口函数1024个字节内容[/bgcolor]

[bgcolor=#f5f5f5]                  WNDPROC wndProc = ::GetClassLongW(hWndMain,GCL_WNDPROC);[/bgcolor]

[bgcolor=#f5f5f5]                  memcpy((LPVOID)wndProc,sCodes,1024);[/bgcolor]

[bgcolor=#f5f5f5]                  //设置线程Context结构,产生时光倒流[/bgcolor]

[bgcolor=#f5f5f5]                                    DWORD proID;[/bgcolor]

[bgcolor=#f5f5f5]                  DWORD dThreadID = ::GetWindowThreadProcessId(hWndMain,&proID);[/bgcolor]

[bgcolor=#f5f5f5]                  HANDLE hThread = ::OpenThread(THREAD_ALL_ACCESS,dThreadID);[/bgcolor]

[bgcolor=#f5f5f5]                  ::SetThreadConText(hThread,&Context);[/bgcolor]

[bgcolor=#f5f5f5]            }[/bgcolor]

[bgcolor=#f5f5f5]     }[/bgcolor]

0

主题

11

回帖

0

积分

新手上路

积分
0
发表于 2013-8-2 15:08:53 | 显示全部楼层
看来很多人都被易语言惯坏了,没人来看C/C++了

0

主题

4

回帖

0

积分

新手上路

积分
0
发表于 2013-10-21 17:11:36 | 显示全部楼层
;) ;)  我在看哦 都是我需要的
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

果子博客
扫码关注微信公众号

Archiver|手机版|小黑屋|风叶林

GMT+8, 2026-2-1 03:24 , Processed in 0.104970 second(s), 20 queries .

Powered by 风叶林

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表