设为首页 加入收藏

TOP

获取其它进程密码框中的密码(一)
2014-11-23 22:15:46 】 浏览:291
Tags:获取 其它 进程 密码

程序编写的过程中,往往有些功能需要由其它的进程权限才能够完成这些工作,如得到其它进程中某个窗口的标题;建立隐藏的守护进程来监测本进程的运行情况;在Win7下,利用其它有高UAC权限的进程来完成一些功能等等。都需要使用到其它进程来完成这些工作。本文就来讲解如何获取其它进程中密码框中的密码。


以上代码实现及理论均为Win32平台为主。


A. 为什么选择远程线程 ?


我们知道,远程线程就是想让其它线程执行我们自己的代码,如果要想使自己的代码被其它进程执行,首先能想到的就是DLL,因为DLL可以被其它进程附加,并且可以执行所有的功能。但强大的功能也需要一个导火索来给它这个机会爆发,因为在进程运行进来后,LoadLibrary仍然可以使一个动态库附加映射进某个进程,但当我们执行LoadLibrary时,是在自己进程中执行的,无法使其它进程有机会执行这个代码,从而也就没机会使我们的代码附加到其它进程中,结果就是,强大的代码永远没有得到一个可以执行的机会。


而远程线程就是系统提供给我们的一个伯乐,它可以在你创建线程时,指定一个起始运行的入口,这样LoadLibrary就有了执行的机会,从而,DLL里面的代码就是会一气呵成的执行。


所以远程线程是必须的。


B. 一些必须了解的概念


1. 地址空间


在Win32平台下(Linux及主流平台),每个进程拥有4GB独立的地址空间,一般叫做线程地址空间,相对于每个进程来说,在自己的空间内访问一些地址内容,即访问变 量的值及执行一些代码都是非常方便的有效的,每个进程完成自己的工作,相互不会产生任何干扰。


2. 远程线程


一般而言,线程是线程可调试,实际完成一些工作(即执行一些代码)的最小实体,一个进程可以包含一个及以上的线程,这些线程并行工作,完成实际的功能。而远 程线程,故名思议,即非本进程的线程。假设有A,B两个进程,远程线程就是由A进程创建,但运行于B进程的地址空间中,拥有B进程的进程权限。


3. 代码注入


代码注入就是,将精心准备好的代码(即数据)放进某个进程的地址空间中。


C. 为什么不选择DLL的方式 ?


前面已经提到过,DLL里面就是可以执行的代码,我们只需要将DLL附加进进程就得以机会去执行这些代码。但DLL是以文件形式存放在磁盘中,有些功能可能会很 小,或者有些功能需要隐藏一些实现细节,如果附加一个DLL的话,效果并不是那么的友好,所以如果有机会不用DLL,依然能够使远程线程实现强大的功能,那自然 是最佳选择,但这也使得代码编写起来更难,也就需要更强的编程的基本功。


D. 需要使用到的主要API(以Win32平台为例)


OpenProcess:打开一个进程,得到该进程的句柄。


VirtualAllocEx:简言之为在指定的进程中申请一些空间。


WriteProcessMemory:简言之为在指定进程中写入一些数据。


CreateRemoteThread:在指定的进程中创建一个线程。


E. 具体实现 -- Talk is cheap, show me the code! (Linus)


以得到其它进程中某一窗体的标题为例,来简单的介绍远程线程的用法。


得到一个窗口的标题,一般会调用 GetWindowText,它的使用方法如下:


The GetWindowText function copies the text of the specified window's titlebar (if it has one) into a buffer. If the specified window is a control, thetext of the control is copied. However, GetWindowText cannot retrievethe text of a control in another application.


上面的使用方法是摘自MSDN上GetWindowText的描述,从描述中可以看到,GetWindowText不能够得到其它应用程序的标题,即一个进程的程序不能获得其它进程窗口的句柄。但如果那段代码是由其它进程来执行,执行后我们再得到结果,是不是就可以做到了呢。


假设我们的进程为A,我们想得到B进程中某一个控制的标题,要想完成以上功能,首先我们要能让我们的代码放到B进程的地址空间中,其次让B执行这些代码,最后从B进程中得到执行的结果。


代码实现如下(为突出有效代码,合法性检测都没有添加):


#include
#include


using namespace std;


void Test();


void main()
{
Test();
}



__declspec(naked) void __stdcall GetWindowTextSpy(DWORD dwParam)
{
_asm
{
mov eax, [esp + 4] // 得到传入的参数 dwParam, 此时为窗口句柄
push [eax + 0] // 缓冲区长度
mov ebx, eax
add ebx, 8
push ebx // 缓冲区地址
push [eax + 4] // 目标窗口句柄
call GetWindowText
ret 4
}
}


__declspec(naked) void __stdcall EndLabel(DWORD dwParam)
{
}



void Test()
{


// 得到目标窗口所在进程的ID,篇幅原因假设已经知道窗口句柄
HWND hwnd = (HWND)0x000108F8;
DWORD dwProcessID;
DWORD dwTitleSize = 0x20;
DWORD dwDataLen = 0x30;


GetWindowThreadProcessId(hwnd, &dwProcessID);


HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE |
PROCESS_VM_READ, FALSE, dwProcessID);
// 在B 进程中申请空间以存放返回的窗口标题
LPBYTE pData = (LPBYTE)VirtualAllocEx(hProcess, 0, dwDataLen, MEM_COMMIT, PAGE_READWRITE);


// 填充参数
WriteProcessMemory(hProcess, pData, &dwTitleSize, 4, NULL);
WriteProcessMemory(hProcess, pData + 4, &hwnd, 4, NULL);


// 注入的代码长度
DWORD dwCodeLen = 0;


#ifdef _DEBUG
const DWORD dwSpyRealAddr = *(LPDWORD)((LPBYTE)(&GetWindowTextSpy)+1) + (DWORD)(&GetWindowTextSpy) + 5;
const DWORD dwEndReadAddr = *(LPDWORD)((LPBYTE)(&EndLabel)+1) + (DWORD)(&EndLabel) + 5;
#else
const DWORD dwSpyRealAddr = (DWORD)GetWindowTextSpy;
const DWORD dwE

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇可截获到 QQ 密码 键盘记录器源码 下一篇MyEclipse 编写Java代码提示 dead..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目