天马阁

 找回密码
 立即注册
                                        →→→→→→→→→→→→ 1点击查看所有VIP教程目录长列表(总教程数269个) 2办理VIP详情进入 ←←←←←←←←←←←←
1 x64CE与x64dbg入门基础教程 7课 已完结 2 x64汇编语言基础教程 16课 已完结 3 x64辅助入门基础教程 9课 已完结 4 C++x64内存辅助实战技术教程 149课 已完结
5 C++x64内存检测与过检测技术教程 10课 已完结 6 C+x64二叉树分析遍历与LUA自动登陆教程 19课已完结 7 C++BT功能原理与x64实战教程 29课 已完结 8 C+FPS框透视与自瞄x64实现原理及防护思路 30课完结
64驱?封? 9 64反驱? 10 64位V? 11 绝? 12 ???课?
13 64透 ? 14 64U ? 15 64Q ? 16 64功 ?
17 64U ? 18 64模 ? 19 64多 ? 20 64网 ?
21 64注 ? 22 64火 ? 23 64棋 ? 24 64自二链L?
25 64破 ? VIP会员办理QQ: 89986068   
【请先加好友,然后到好友列表双击联系客服办理,不然可能无法接受到信息。】
27 加入2000人交流群637034024 3 28 免责声明?
查看: 4736|回复: 0

VC++远程调用与禁用Ctrl+Alt+Delete热键

[复制链接]

12

主题

0

回帖

14

积分

编程入门

Rank: 1

天马币
24
发表于 2024-3-1 13:58:35 | 显示全部楼层 |阅读模式
   场景一:有某一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,[ebp+8]
//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[NeedAllocCount];
if (!AllocBuffers){
goto ExitLoop;
}
AllocBufferSize = new ULONG[NeedAllocCount];
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[NeedAllocCount] = MemBase;
AllocBufferSize[NeedAllocCount] = 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[Index],ParameterValue,ParameterSize,NULL);
}
//释放参数申请的内存
VirtualFreeEx(hProcess,AllocBuffers[Index],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;
}

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

天马阁|C/C++辅助教程|安卓逆向安全| 论坛导航|免责申明|Archiver||网站地图
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表天马阁立场!
任何人不得以任何方式翻录、盗版或出售本站视频,一经发现我们将追究其相关责任!
我们一直在努力成为最好的编程论坛!
Copyright© 2010-2021 All Right Reserved.
快速回复 返回顶部 返回列表