最近才刚刚上班,老大给了一个wmi的事件订阅的样本给我,叫我尝试拦截一下wmi的参数。
拿到任务首先去收一下有没有前人的代码可以借鉴(抄袭)的,看到有关于附加wmi的设备驱动的,好的,抄下来看看。具体实现是附加到WMIDataDevice设备上面,对IRP_MJ_SYSTEM_CONTROL进行过滤,然后就是什么都没有发生,之后看了一下微软给的wmi的驱动编程,由于网上没有现成的代码,本人技术拉跨,凭借拙略的英语阅读能力知道了要先注册下面这个函数,不然不给用IoWMIRegistrationControl,勉强按照要求做好,耶!居然真的能接收到消息,好的使用powershell随便试试几句指令,结果是什么都接收不到。
最后老大又给了一个usb设备驱动的源码给我,让我看看(抄)。
虽然能勉强的跑起来但是资料比较少,本人技术又菜,所以结果虽然能接收到消息,但是当我用powershell执行命令,debugview上面是一动不动。
之后又死皮赖脸的缠着老大(尝试从老大这里得到有用的突破口)。
老大说你可以尝试在r3获取消息,仔细去研究一下微软给的c++调用wmi的代码(样本虽然的脚本,但是调用的函数都是一样的),看能不能hook一下虚函数。好的!sir于是有的下面的代码
#include <windows.h>
#include <rpcndr.h>
#include <stdio.h>
#include <comdef.h>
#include <Wbemidl.h>
#include "detours.h"
#pragma comment(lib, "detours.lib")
#pragma comment(lib, "wbemuuid.lib")
typedef HRESULT (STDMETHODCALLTYPE * PExecMethod)(//STDMETHODCALLTYPE
const BSTR strObjectPath,
const BSTR strMethodName,
long lFlags,
IWbemContext *pCtx,
IWbemClassObject *pInParams,
IWbemClassObject **ppOutParams,
IWbemCallResult **ppCallResult
);
PExecMethod hookexe;
HRESULT STDMETHODCALLTYPE h_ExecMethod(const BSTR strObjectPath,const BSTR strMethodName,long lFlags,IWbemContext *pCtx,IWbemClassObject *pInParams, IWbemClassObject **ppOutParams, IWbemCallResult **ppCallResult){
MessageBoxA(0, 0, 0, 0);
return hookexe(strObjectPath, strMethodName, lFlags, pCtx, pInParams, ppOutParams, ppCallResult);
}
void Hook(int flag) {
if(flag){
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
// this will hook the function
DetourAttach(&(LPVOID &)hookexe, &h_ExecMethod);
DetourTransactionCommit();
}
else {
// unhook
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
// this will hook the function
DetourDetach(&(LPVOID &)hookexe, &h_ExecMethod);
DetourTransactionCommit();
}
}
void Hook_func() {
ULONG32 hook_addr;
HRESULT hres;
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
hres = CoInitializeSecurity(
NULL,
-1, // COM negotiates service
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
);
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&pLoc);
IWbemServices *pSvc = NULL;
hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc);
hook_addr = (ULONG32)pSvc;
hook_addr = *(ULONG32 *)hook_addr;//mov edx. [eax]
hook_addr = *(ULONG32 *)(hook_addr + 0x60);//mov eax ,[edx+0x60]
//得到当前的执行函数
hookexe = (PExecMethod)hook_addr;
pLoc->Release();
pSvc->Release();
CoUninitialize();
}
void TestFun() {
HRESULT hres;
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
hres = CoInitializeSecurity(
NULL,
-1, // COM negotiates service
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
);
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *)&pLoc);
wchar_t NameSpacewmi[] = { 'R','O','O','T','\\','D','E','F','A','U','L','T','\0' };
IWbemServices *pSvc = NULL;
hres = pLoc->ConnectServer(
NameSpacewmi,
NULL,
NULL,
0,
NULL,
0,
0,
&pSvc
);
hres = CoSetProxyBlanket(
pSvc, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL, // client identity
EOAC_NONE // proxy capabilities
);
// set up to call the Win32_Process::Create method
unsigned char calname[23] = {
0x53, 0x65, 0x74, 0x45, 0x78, 0x70, 0x61, 0x6E,
0x64, 0x65, 0x64, 0x53, 0x74, 0x72, 0x69, 0x6E,
0x67, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x00
};
unsigned char funName[11] = {
0x53, 0x74, 0x64, 0x52, 0x65, 0x67, 0x50, 0x72,
0x6F, 0x76, 0x00
};
BSTR MethodName = _bstr_t((char *)calname);
BSTR ClassName = _bstr_t((char *)funName);
IWbemClassObject* pClass = NULL;
hres = pSvc->GetObject(ClassName, 0, NULL, &pClass, NULL);
IWbemClassObject* pInParamsDefinition = NULL;
hres = pClass->GetMethod(MethodName, 0,
&pInParamsDefinition, NULL);
IWbemClassObject* pClassInstance = NULL;
hres = pInParamsDefinition->SpawnInstance(0, &pClassInstance);
VARIANT varCommand;
varCommand.vt = VT_I4;
varCommand.iVal = 0x80000001;//HKEY_CURRENT_USER
varCommand.lVal = 0x80000001;
wchar_t hDefName[] = { 'h','D','e','f','K','e','y','\0' };//hDefKey
hres = pClassInstance->Put(hDefName, 0, &varCommand, 0);
VariantClear(&varCommand);
unsigned char regDir[70] = {
0x53, 0x6F, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
0x5C, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F,
0x66, 0x74, 0x5C, 0x57, 0x69, 0x6E, 0x64, 0x6F,
0x77, 0x73, 0x5C, 0x43, 0x75, 0x72, 0x72, 0x65,
0x6E, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F,
0x6E, 0x5C, 0x45, 0x78, 0x70, 0x6C, 0x6F, 0x72,
0x65, 0x72, 0x5C, 0x55, 0x73, 0x65, 0x72, 0x20,
0x53, 0x68, 0x65, 0x6C, 0x6C, 0x20, 0x46, 0x6F,
0x6C, 0x64, 0x65, 0x72, 0x73 ,0x00
};
VARIANT varCommand2;
varCommand2.vt = VT_BSTR;
varCommand2.bstrVal = _bstr_t((char *)regDir);
wchar_t sbName[] = { 's','S','u','b','K','e','y','N','a','m','e','\0' };//sSubKeyName
hres = pClassInstance->Put((LPCWSTR)sbName, 0, &varCommand2, 0);
VariantClear(&varCommand2);
unsigned char key[8] = {
0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70 ,0x00
};
VARIANT varCommand4;
varCommand4.vt = VT_BSTR;
varCommand4.bstrVal = _bstr_t((char *)key);
wchar_t svaName[] = { 's','V','a','l','u','e','N','a','m','e','\0' };//sValueName
hres = pClassInstance->Put(svaName, 0, &varCommand4, 0);
VariantClear(&varCommand4);
unsigned char value[13] = {
0x63, 0x3A, 0x5C, 0x42, 0x6F, 0x6F, 0x74, 0x57,
0x6F, 0x77, 0x36, 0x34, 0x00
};
VARIANT varCommand3;
varCommand3.vt = VT_BSTR;
varCommand3.bstrVal = _bstr_t((char *)value);
wchar_t svalueName[] = { 's','V','a','l','u','e','\0' };//sValueName
hres = pClassInstance->Put(L"sValue", 0, &varCommand3, 0);
VariantClear(&varCommand3);
// Execute Method
IWbemClassObject* pOutParams = NULL;
ClassName = _bstr_t((char *)funName);
hres = pSvc->ExecMethod(ClassName, MethodName, 0, NULL, pClassInstance, &pOutParams, NULL);
// Clean up
//--------------------------
VariantClear(&varCommand);
SysFreeString(ClassName);
SysFreeString(MethodName);
pClass->Release();
pClassInstance->Release();
pInParamsDefinition->Release();
//pOutParams->Release();
pLoc->Release();
pSvc->Release();
CoUninitialize();
}
int main() {
Hook_func();
//这里hook一下
Hook(1);
TestFun();
Hook(0);
return 0;
}
说一下这个代码,首先是自己去拿到链接对象,然后当该进程的其他线程去再次尝试去创建对象的时候的分配的还是它,然后就能干一些比较猥琐的事情,hook它的虚函数。这里的测试函数是我之前写的一个用wmi修改注册表的代码,上面有一些立即数,主要是不会被扫出字符串。
这里要说的是这个代码是有问题的,问题会发生在第三方库detours
这里我是真的不知道为什么,当时没想到去0x78eaae10看看,实际上问题就是出现在那,当时没有办法怎么办,发动秘籍,在吗?老大你帮我看一看,然后老大看了 一下问题找到了。
具体问题就是CoUninitialize函数,当这个函数执行之后会出现下面的情况。
???我就关闭一个对象你把我的模块都给我卸载了,这样合适吗?
解决方案。
1、不适用这个函数,模块就不会被卸载(但是初始化安全的哪个地方可能过不去,但是不影响,我管你成功不成功)
2、hook卸载模块的函数
3、如果写成dll不会出现这个问题就算关闭,模块也不会被卸掉(如果要拿参数就从这里入手,代码就不贴了,上面的改改就能用)
4、放弃