近几天在看机器狗时看到机器狗使用的这个技术.
逆向了一下那功能,但有几个问题不太清楚的,烦请大大们指教下.
留个blog地址,做下广告:http://blog.163.com/takile
以下为代码(代码写得不好,有兴趣的看看吧.):
#include <stdio.h>
#include <windows.h>
typedef long NTSTATUS;
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
#define NT_SUCCESS(status) ((NTSTATUS)(status) >= 0)
typedef struct _SYSTEM_MODULE_INFORMATION
{
ULONG Reserved[2];
PVOID Base;
ULONG Size;
ULONG Flags;
USHORT Index;
USHORT Unknown;
USHORT LoadCount;
USHORT ModuleNameOffset;
CHAR ImageName[256];
}SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
typedef struct _MemoryChunk
{
PVOID pPhysicalAddress;
PVOID pUnknown;
PVOID pBuffer;
DWORD dwBufferSize;
}MemoryChunk;
typedef enum _SYSTEM_INFORMATION_CLASS
{
SystemBasicInformation,
SystemProcessorInformation,
SystemPerformanceInformation,
SystemTimeOfDayInformation,
SystemNotImplemented1,
SystemProcessesAndThreadsInformation,
SystemCallCounts,
SystemConfigurationInformation,
SystemProcessorTimes,
SystemGlobalFlag,
SystemNotImplemented2,
SystemModuleInformation,
SystemLockInformation,
SystemNotImplemented3,
SystemNotImplemented4,
SystemNotImplemented5,
SystemHandleInformation,
SystemObjectInformation,
SystemPagefileInformation,
SystemInstructionEmulationCounts,
SystemInvalidInfoClass1,
SystemCacheInformation,
SystemPoolTagInformation,
SystemProcessorStatistics,
SystemDpcInformation,
SystemNotImplemented6,
SystemLoadImage,
SystemUnloadImage,
SystemTimeAdjustment,
SystemNotImplemented7,
SystemNotImplemented8,
SystemNotImplemented9,
SystemCrashDumpInformation,
SystemExceptionInformation,
SystemCrashDumpStateInformation,
SystemKernelDebuggerInformation,
SystemContextSwitchInformation,
SystemRegistryQuotaInformation,
SystemLoadAndCallImage,
SystemPrioritySeparation,
SystemNotImplemented10,
SystemNotImplemented11,
SystemInvalidInfoClass2,
SystemInvalidInfoClass3,
SystemTimeZoneInformation,
SystemLookasideInformation,
SystemSetTimeSlipEvent,
SystemCreateSession,
SystemDeleteSession,
SystemInvalidInfoClass4,
SystemRangeStartInformation,
SystemVerifierInformation,
SystemAddVerifier,
SystemSessionProcessesInformation
} SYSTEM_INFORMATION_CLASS;
typedef enum _DEBUG_CONTROL_CODE{
DebugGetTraceInformation = 1,
DebugSetInternalBreakpoint = 2,
DebugSetSpeicalCall = 3,
DebugClearSpeicalCalls = 4,
DebugQuerySpecialCalls = 5,
DebugDbgBreakPoint = 6,
//获取KdVersionBlock
DebugSysGetVersion = 7,
/*
从内核空间拷贝到用户空间,或者从用户空间拷贝到用户空间
但不能从用户空间拷贝到内核空间
*/
DebugCopyMemoryChunks_0 = 8,
/*
从用户空间拷贝到内核空间,或者从用户空间拷贝到用户空间
但不能从内核空间拷贝到用户空间
*/
DebugCopyMemoryChunks_1 = 9,
/*
从物理地址拷贝到用户空间,不能写至内核空间
*/
DebugCopyPhyMemory_0 = 10,
/*
从用户空间拷贝到物理地址,不能读取内核空间
*/
DebugCopyPhyMemory_1 = 11,
//读写处理器相关控制块
DebugSysReadControlSpace = 12,
DebugSysWriteControlSpace = 13,
//读写端口
DebugSysReadIoSpace = 14,
DebugSysWriteIoSpace = 15,
//分别调用 RDMSD@4 和 WRMSR@12
DebugSysReadMsr = 16,
DebugSysWriteMsr = 17,
//读写总线数据
DebugSysReadBusData = 18,
DebugSysWriteBusData = 19,
DebugSysCheckLowMemory = 20,
//分别调用 _KdEnableDebugger@0 和 _KdDisableDebugger@0
DebugSysEnableDebugger = 21,
DebugSysDisableDebugger = 22,
//获取和设置一些调试相关的变量
DebugSysGetAutoEnableOnEvent = 23,
DebugSysSetAutoEnableOnEvent = 24,
DebugSysGetPitchDebugger = 25,
DebugSysSetDbgPrintBufferSize = 26,
DebugSysGetIgnoreUmExceptions = 27,
DebugSysSetIgnoreUmExceptions = 28
}DEBUG_CONTROL_CODE;
NTSTATUS WINAPI ZwQuerySystemInformation(
ULONG SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
NTSTATUS NTAPI ZwSystemDebugControl(
IN DEBUG_CONTROL_CODE ControlCode,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
OUT PULONG ReturnLength
);
typedef NTSTATUS (__stdcall *ZWQUERYSYSTEMINFORMATION)(
ULONG SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
typedef NTSTATUS (__stdcall *ZWSYSTEMDEBUGCONTROL)(
IN DEBUG_CONTROL_CODE ControlCode,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
OUT PULONG ReturnLength
);
NTSTATUS
PsSetLoadImageNotifyRoutine(
IN PVOID NotifyRoutine
);
void CurrentProcess_AdjustTokenPrivileges()
{
BOOL bRet = FALSE;
HANDLE hTokenHandle = NULL;
TOKEN_PRIVILEGES tp;
LUID luid;
bRet = ::OpenProcessToken((HANDLE)::GetCurrentProcess(), 0xF01FF, &hTokenHandle);
if ( FALSE == bRet )
{
printf("OpenProcessToken error: %u\n", ::GetLastError());
goto FunReturn;
}
if ( 0 == ::LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid) )
{
printf("LookupPrivilegeValue error: %u\n", ::GetLastError());
goto FunReturn;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if ( 0 == ::AdjustTokenPrivileges(hTokenHandle, 0, &tp, sizeof(TOKEN_PRIVILEGES), 0, 0) )
{
printf("AdjustTokenPrivileges error: %u\n", ::GetLastError());
goto FunReturn;
}
FunReturn:
if ( NULL != hTokenHandle )
{
CloseHandle(hTokenHandle);
hTokenHandle = NULL;
}
} ZWQUERYSYSTEMINFORMATION pZwQuerySystemInformation = NULL;
ZWSYSTEMDEBUGCONTROL pZwSystemDebugControl = NULL;
int main(int argc, char * argv[])
{
DWORD dwRet = 0;
HMODULE hNtDll_Module = NULL, hNtOs_Module = NULL;
BYTE *pBuf = NULL, *pImageName = NULL, *pImageNameOffset = NULL;
DWORD dwReturnLength = 0, dwIndex = 0, dwToRead = 0;
PSYSTEM_MODULE_INFORMATION pSysModuleInfo = NULL;
ULONG uModuleCount = 0;
USHORT uModuleNameOffset = 0;
PVOID pPsSetLoadImageNotifyRoutine = NULL;
PVOID pRealPsSetLoadImageNotifyRoutine = NULL;
PVOID pPsImageNotifyEnabled = 0;
char szImageName[MAX_PATH] = {0};
MemoryChunk structMemory;
BYTE *pInstruction = NULL, *pOriInstruction = NULL;
CurrentProcess_AdjustTokenPrivileges();
hNtDll_Module = ::GetModuleHandle("ntdll.dll");
if ( NULL == hNtDll_Module )
{
printf("GetmoduleHandle Error = %u\n", ::GetLastError());
goto FunReturn;
}
pZwQuerySystemInformation = (ZWQUERYSYSTEMINFORMATION)::GetProcAddress(hNtDll_Module, "ZwQuerySystemInformation");
pZwSystemDebugControl = (ZWSYSTEMDEBUGCONTROL)::GetProcAddress(hNtDll_Module, "ZwSystemDebugControl");
if ( NULL == pZwSystemDebugControl || NULL == pZwQuerySystemInformation )
{
printf("pZwSystemDebugControl or pZwQuerySystemInformation is NULL.\n");
goto FunReturn;
}
dwRet = pZwQuerySystemInformation(SystemModuleInformation, pBuf, 0, &dwReturnLength);
if ( STATUS_SUCCESS != dwRet )
{
if ( STATUS_INFO_LENGTH_MISMATCH != dwRet )
{
printf("ZwQuerySystemInformation Error = %u\n", ::GetLastError());
goto FunReturn;
}
else
pBuf = new BYTE[dwReturnLength];
}
if ( NULL == pBuf )
{
printf("pBuf == NULL.\n");
goto FunReturn;
}
dwRet = pZwQuerySystemInformation(SystemModuleInformation, pBuf, dwReturnLength, 0);
if ( STATUS_SUCCESS != dwRet )
{
printf("ZwQuerySystemInformation Error = %u\n", ::GetLastError());
goto FunReturn;
}
uModuleCount = *((PULONG)pBuf);
pSysModuleInfo = (PSYSTEM_MODULE_INFORMATION)(PUCHAR)((PUCHAR)pBuf + sizeof(ULONG));
uModuleNameOffset = (USHORT)(PSYSTEM_MODULE_INFORMATION)pSysModuleInfo->ModuleNameOffset;
pImageName = (BYTE *)(PSYSTEM_MODULE_INFORMATION)pSysModuleInfo->ImageName;
pImageNameOffset = pImageName + uModuleNameOffset;
hNtOs_Module = ::LoadLibraryEx((char *)pImageNameOffset, 0, DONT_RESOLVE_DLL_REFERENCES);
if ( NULL == hNtOs_Module )
{
printf("LoadLibraryEx Error = %u\n", ::GetLastError());
goto FunReturn;
}
pPsSetLoadImageNotifyRoutine = ::GetProcAddress(hNtOs_Module, "PsSetLoadImageNotifyRoutine");
if ( NULL == pPsSetLoadImageNotifyRoutine )
{
printf("GetProcAddress(PsSetLoadImageNotifyRoutine) Error = %u\n", ::GetLastError());
goto FunReturn;
}
pRealPsSetLoadImageNotifyRoutine = (BYTE *)((BYTE *)pPsSetLoadImageNotifyRoutine - (BYTE *)hNtOs_Module);
pRealPsSetLoadImageNotifyRoutine = (BYTE *)((BYTE *)(PSYSTEM_MODULE_INFORMATION)pSysModuleInfo->Base + (DWORD)pRealPsSetLoadImageNotifyRoutine);
dwReturnLength = 0;
pOriInstruction = new BYTE[128];
if ( NULL == pOriInstruction )
{
printf("pInstruction == NULL.\n");
goto FunReturn;
}
__asm
{
and pRealPsSetLoadImageNotifyRoutine, 7FFFFFFFh
}
structMemory.pPhysicalAddress = pRealPsSetLoadImageNotifyRoutine;
structMemory.pUnknown = NULL;
structMemory.pBuffer = pOriInstruction;
structMemory.dwBufferSize = 128;
dwRet = pZwSystemDebugControl(DebugCopyPhyMemory_0, &structMemory, sizeof(MemoryChunk), 0, 0, &dwReturnLength);
if ( STATUS_SUCCESS != dwRet )
{
printf("ZwSystemDebugControl Error = %u\n", ::GetLastError());
goto FunReturn;
}
pInstruction = pOriInstruction;
for ( dwIndex = 0; dwIndex < 128; dwIndex++ )
{
if ( *pInstruction == 0xC6 && *(pInstruction + 1) == 0x05 )
{
pPsImageNotifyEnabled = 0;
pInstruction += 2;
pPsImageNotifyEnabled = (PVOID)*(PDWORD)pInstruction;
break;
}
pInstruction++;
}
if ( (DWORD)pPsImageNotifyEnabled < 0x80000000 )
{
printf("pPsImageNotifyEnabled < 0x80000000.\n");
goto FunReturn;
}
__asm
{
and pPsImageNotifyEnabled, 7FFFFFFFh
}
structMemory.pPhysicalAddress = pPsImageNotifyEnabled;
structMemory.pUnknown = NULL;
structMemory.pBuffer = &dwToRead;
structMemory.dwBufferSize = 4;
dwReturnLength = 0;
dwRet = pZwSystemDebugControl(DebugCopyPhyMemory_0, &structMemory, sizeof(MemoryChunk), 0, 0, &dwReturnLength);
if ( STATUS_SUCCESS != dwRet )
{
printf("ZwSystemDebugControl Error = %u\n", ::GetLastError());
goto FunReturn;
}
printf("---.\n");
if ( dwToRead == 1 )
{
dwToRead = 0;
structMemory.pPhysicalAddress = pPsImageNotifyEnabled;
structMemory.pUnknown = NULL;
structMemory.pBuffer = &dwToRead;
structMemory.dwBufferSize = 4;
dwReturnLength = 0;
dwRet = pZwSystemDebugControl(DebugCopyPhyMemory_1, &structMemory, sizeof(MemoryChunk), 0, 0, &dwReturnLength);
if ( STATUS_SUCCESS == dwRet )
printf("Ok.\n");
}
FunReturn:
if ( NULL != hNtDll_Module )
{
FreeLibrary(hNtDll_Module);
hNtDll_Module = NULL;
}
if ( NULL != hNtOs_Module )
{
FreeLibrary(hNtOs_Module);
hNtOs_Module = NULL;
}
if ( NULL != pBuf )
{
delete[] pBuf;
pBuf = NULL;
}
if ( NULL != pOriInstruction )
{
delete[] pOriInstruction;
pOriInstruction = NULL;
pInstruction = NULL;
}
pImageNameOffset = NULL;
pImageName = NULL;
system("pause");
return 0;
} 问题一:把PsSetLoadImageNotifyRoutine的内核地址高位置0是什么意思阿?有什么详细的文档解释一下吗?
问题二:通过搜索指令找到PsImageNotifyEnabled并把其设0,具体有什么作用阿?把杀软的实时监控功能废掉吗?
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)