VC++远程调用与禁用Ctrl+Alt+Delete热键
场景一:有某一bingdu会保护某一文件,不让其他进程访问它,只允许自己对它的访问,而这个文件这是破解,清除bingdu的关键,这时怎么办呢?进入dos下拷贝,嗯这是种方法,但是太复杂了。这里我们假设在windows下没有其他软件可以进行拷贝。对于一般编程人员来说可能有些并没有接触ark,甚至不知道这是个什么东西的人大有人在。场景二:我以前用VB写了一个锁屏软件,但是遇到了一大难题,用户可以使用热键“Ctrl+Alt+Delete”来唤起进程管理器来终止我的进程,然后让我的程序失效,这时我想了好多办法,比如监控窗体发现是进程管理器把它关闭掉什么的,但是发觉这样做确实解决了问题,但是给人的感觉很不好。后来就想我能不能把这个热键禁止掉呢?嗯,最先想到的是全局键盘钩子,后面写了代码一试才知道不行。然后google搜索才确定键盘钩子是不行,网上介绍了很多种方法,比如替换系统的GINA.dll,替换winlogon.exe这些都是很复杂的,实现难度太高了,还有实现简单点的就是需要注入dll到winlogon里面去,我不想注入dll因为想纯vb实现。这时我留意了下dll的实现方法,主要有两种,一种是拦截WM_HOTKEY消息,然后发现是热键“Ctrl+Alt+Delete”就阻止掉,还有就是使用api函数UnregisterHotKey把热键注销掉。实现的方法很简单,但是想用纯vb来实现就有点难了,首先,这两种实现方法都需要找到热键“Ctrl+Alt+Delete”注册的窗体("SAS Window")句柄,而winlogon和我们所在的桌面是不一样的,所以使用FindWindow来查找是不行的。切换桌面在FindWindow嗯这是可行的,但是切换桌面需要system用户进程,vb又不能,后来想来想去,想到一个解决方法,既然能注入dll,那么我们就注入一段Shell code不是一样可行?
基于以上场景,当然这样的应用还有很多,所以我对这个功能(“远程调用”)进行了重新封装,可以让大家更方便的像调用API函数一样来跨进程执行API函数,所以就有了今天的这篇文章和代码。
因为代码需要创建远程线程和写内存,所以一些安全软件可能会报bingdu或者可疑,请大家放心,函数本身提供了强大的功能至于您怎么用就是各自想法了,你想把它应用在正常软件上,那么可能会对你有很大的帮助,如果你运用在bingdu上,那么就可能对大家造成危害,所以请大家合理,正确的应用代码,我对此份代码造成的后果不负责任。
这份代码是基于shell code+创建远程线程(执行机会)来实现功能的,shell code里是对你需要执行api的一个封装采用的方式是标准的__stdcall方式,函数没有进行优化为了方便构造和处理,每个参数都是5个字节对齐(在内存里,因为都是0x68 push方式).比如我要调用FindWindow可能在内存中的代码就是这样了。
0x68 0x00 0x00 0x00 0x00 0x68 0x00 0x00 0x00 0x00 0xB8 0x00 0x00 0x00 0x00 0xFF 0xD0
对应汇编代码类似:
__asm{
push "SAS Window"
push 0
mov eax,FindWindowA
call eax
}
本帖隐藏的内容//创建远程线程执行shell code(我们的api函数)
hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)RemoteExeBase, NULL, 0, &dwThreadId);
if (!hThread){
goto ExitLoop;
}
//等待线程执行结束
WaitForSingleObject(hThread, INFINITE);
GetExitCodeThread(hThread, (LPDWORD)&pRetValue); //获取返回值
好像不能上传附件,郁闷,发下关键代码:
//第五个参数开始。每四个参数为一组,实际上是原始API里的一个参数
//第一个参数表示在目标进程是否需要申请内存
//第二个参数表示参数是否会返回值
//第三个参数是值,如果需要申请内存的话,这个值是一个地址
//第四参数是第三个值的长度,目前函数只支持x86所以如果不是需要申请内存的话这个值永远是4
PVOID
WINAPI
RemoteCallFunction(DWORD ProcessId,
LPSTR lpszLibName,
LPSTR lpszFunName,
ULONG ParametersCount,
...
)
{
HANDLE hProcess=NULL; //进程句柄
HANDLE hThread=NULL; //线程句柄
PUCHAR ShellCode=NULL;
PVOID pFunAddress; //函数地址
HMODULE hMod; //模块基址
ULONG i;
PVOID ParameterValue; //参数值
PUCHAR ParameterBase; //对应ebp+8所在的地址
ULONG ParameterSize; //参数大小
BOOL NeedAlloc; //是否需要分配内存
BOOL NeedRet; //是否需要反悔
PVOID MemBase=NULL; //参数对应的内存地址
ULONG Index;
ULONG ShellCodeSize; //shell code 长度
PUCHAR RemoteExeBase=NULL; //shell code基址,程序从这里开始执行
ULONG NeedAllocCount; //需要申请内存的参数个数
PVOID *AllocBuffers=NULL; //存放需要申请内存后的地址
ULONG *AllocBufferSize=NULL; //存放需要申请内存长度
DWORD dwThreadId; //线程ID
PVOID pRetValue=NULL; //返回值
hMod = GetModuleHandle(lpszLibName); //获取模块基址
if (!hMod){
return NULL;
}
pFunAddress = (PVOID)GetProcAddress(hMod,lpszFunName); //获取函数地址
if (!pFunAddress){
return NULL;
}
hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,ProcessId); //打开进程
if (!hProcess){
return NULL;
}
ShellCode = GetShellCode(ParametersCount,&ShellCodeSize); //获取初始化的shell code
if (!ShellCode){
goto ExitLoop;
}
//申请内存用于执行shell code(我们对应的函数)
RemoteExeBase = (PUCHAR)VirtualAllocEx(hProcess,NULL,ShellCodeSize,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
if (!RemoteExeBase){
goto ExitLoop;
}
//把shell code写入目标进程中
if (!WriteProcessMemory(hProcess,RemoteExeBase,ShellCode,ShellCodeSize,NULL)){
goto ExitLoop;
}
ParameterBase = (PUCHAR)&ProcessId;
//__asm{
//lea eax,
//mov ParameterBase,eax
//}
NeedAllocCount = 0;
//计算需要申请内存的个数
for (i=5;i<5+ParametersCount*4;i+=4){
NeedAlloc=(BOOL)GetParameterValue(ParameterBase,i);
if (NeedAlloc){
NeedAllocCount++;
}
}
if (NeedAllocCount){
//申请存放参数信息的buffer
AllocBuffers = new PVOID;
if (!AllocBuffers){
goto ExitLoop;
}
AllocBufferSize = new ULONG;
if (!AllocBufferSize){
goto ExitLoop;
}
}
NeedAllocCount = 0;
//遍历参数,然后把对应值写入目标进程中
//因为是__stdcall所以第一个参数是在最后,最后的参数在最前面
for (i=5,Index=ParametersCount;i<5+ParametersCount*4;i+=4,Index--){
NeedAlloc=(BOOL)GetParameterValue(ParameterBase,i); //是否需要申请内存
ParameterValue = GetParameterValue(ParameterBase,i+2); //参数值
ParameterSize = (DWORD)GetParameterValue(ParameterBase,i+3); //参数长度
if (NeedAlloc){
//需要申请内存
MemBase = VirtualAllocEx(hProcess,NULL,ParameterSize,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
if (!MemBase){
goto ExitLoop;
}
//把参数值写入目标进程
if (!WriteProcessMemory(hProcess,MemBase,ParameterValue,ParameterSize,NULL)){
goto ExitLoop;
}
//更改shell code中push后面的值
if (!WriteProcessMemory(hProcess,(RemoteExeBase+(Index-1)*5+1),&MemBase,4,NULL)){
goto ExitLoop;
}
//保存参数信息
AllocBuffers = MemBase;
AllocBufferSize = ParameterSize;
NeedAllocCount ++;
}else{
//更改shell code中push后面的值
if (!WriteProcessMemory(hProcess,(RemoteExeBase+(Index-1)*5+1),&ParameterValue,4,NULL)){
goto ExitLoop;
}
}
}
//构造call eax
if (!WriteProcessMemory(hProcess,(RemoteExeBase+ParametersCount*5+1),&pFunAddress,4,NULL)){
goto ExitLoop;
}
//创建远程线程执行shell code(我们的api函数)
hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)RemoteExeBase, NULL, 0, &dwThreadId);
if (!hThread){
goto ExitLoop;
}
//等待线程执行结束
WaitForSingleObject(hThread, INFINITE);
GetExitCodeThread(hThread, (LPDWORD)&pRetValue); //获取返回值
if (NeedAllocCount){
Index = 0;
for (i=5;i<5+ParametersCount*4;i+=4){
NeedAlloc=(BOOL)GetParameterValue(ParameterBase,i);
NeedRet = (BOOL)GetParameterValue(ParameterBase,i+1);
ParameterValue = GetParameterValue(ParameterBase,i+2);
ParameterSize = (DWORD)GetParameterValue(ParameterBase,i+3);
if (NeedAlloc){
//需要申请内存
if (NeedRet){
//需要返回书局
ReadProcessMemory(hProcess,AllocBuffers,ParameterValue,ParameterSize,NULL);
}
//释放参数申请的内存
VirtualFreeEx(hProcess,AllocBuffers,0,MEM_RELEASE);
Index++;
}
}
}
ExitLoop:
//清理内存和句柄
if (ShellCode){
delete []ShellCode;
}
if (AllocBuffers){
delete []AllocBuffers;
}
if (AllocBufferSize){
delete []AllocBufferSize;
}
if (RemoteExeBase){
VirtualFreeEx(hProcess,RemoteExeBase,0,MEM_RELEASE);
}
if (hProcess){
CloseHandle(hProcess);
}
if (hThread){
CloseHandle(hThread);
}
return pRetValue;
}
页:
[1]