//得到文件系统回调链表头地址 VOID GetListHeadAddr() { PUCHAR Addr; PUCHAR x,i; UNICODE_STRING IoRegisterFsRegistrationChangeString={0}; PVOID EnumParameter; WIN_VER_DETAIL WinVer; ULONG ulIoRegisterFsRegistrationChangeMountAware; RtlInitUnicodeString(&IoRegisterFsRegistrationChangeString, L"IoRegisterFsRegistrationChange"); Addr=MmGetSystemRoutineAddress(&IoRegisterFsRegistrationChangeString); IopFsNotifyChangeQueueHead = NULL; WinVer = GetWindowsVersion(); switch(WinVer) { case WINDOWS_VERSION_2K3_SP1_SP2: case WINDOWS_VERSION_XP: case WINDOWS_VERSION_7_7000: // Addr=*(ULONG*)((BYTE*)Addr+25); // IopFsNotifyChangeQueueHead=Addr; for (i=(ULONG)Addr;i < i+SizeOfProc(Addr);i++) { if (*i == 0xbe) { IopFsNotifyChangeQueueHead = *(PULONG)(i+1); if (MmIsAddressValidEx(IopFsNotifyChangeQueueHead)) { return; } } } break; case WINDOWS_VERSION_7_7600_UP: for (i=(ULONG)Addr;i < i+SizeOfProc(Addr);i++) { if (*i == 0xe8) { ulIoRegisterFsRegistrationChangeMountAware = *(PULONG)(i+1)+(ULONG)(i+5); if (MmIsAddressValidEx(ulIoRegisterFsRegistrationChangeMountAware)) { if (DebugOn) KdPrint(("ulIoRegisterFsRegistrationChangeMountAware:%08x\r\n",ulIoRegisterFsRegistrationChangeMountAware)); for (x=(ULONG)ulIoRegisterFsRegistrationChangeMountAware;x < x+SizeOfProc(ulIoRegisterFsRegistrationChangeMountAware);x++) { if (*x == 0xbf) { if (DebugOn) KdPrint(("x:%08x\r\n",x)); IopFsNotifyChangeQueueHead = *(PULONG)(x+1); if (MmIsAddressValidEx(IopFsNotifyChangeQueueHead)) { return; } break; } } } break; } } break; } }
/* NTKERNELAPI BOOLEAN KeRegisterBugCheckCallback ( __out PKBUGCHECK_CALLBACK_RECORD CallbackRecord, __in PKBUGCHECK_CALLBACK_ROUTINE CallbackRoutine, __in PVOID Buffer, __in ULONG Length, __in PUCHAR Component ) typedef struct _KBUGCHECK_CALLBACK_RECORD { LIST_ENTRY Entry; PKBUGCHECK_CALLBACK_ROUTINE CallbackRoutine; PVOID Buffer; ULONG Length; PUCHAR Component; ULONG_PTR Checksum; UCHAR State; } KBUGCHECK_CALLBACK_RECORD, *PKBUGCHECK_CALLBACK_RECORD; LIST_ENTRY KeBugCheckCallbackListHead; LIST_ENTRY KeBugCheckReasonCallbackListHead; */ void GetBugCheckCallBack(PSYSTEM_NOTIFY SystemNotify) { //UCHAR* Base=(UCHAR*)KeRegisterBugCheckCallback; PUCHAR Base=(UCHAR*)GetFunctionAddr(L"KeRegisterBugCheckCallback"); PUCHAR i=0; PKBUGCHECK_CALLBACK_RECORD pBugCheckRecordPack; PLIST_ENTRY pListEntry; PLIST_ENTRY pListNext; ULONG Address; Address=0; if (DebugOn) KdPrint(("Base:%08x",Base)); for(i=Base;i<i+SizeOfProc(Base);i++) { if (DebugOn) KdPrint(("i:%08x",i)); if(*i==0xc6 && *(i+1)==0x40 && *(i+2)==0x1c && *(i+3)==0x01) { Address=*(ULONG*)(i+6); if (DebugOn) KdPrint(("Base:%08x Address:%08x\r\n",Base,Address)); break; } } if (!MmIsAddressValidEx(Address)){ return; } BugCheckNum = SystemNotify->ulCount; pBugCheckRecordPack=Address; pListEntry=&(pBugCheckRecordPack->Entry); pListNext=pListEntry->Flink; { pBugCheckRecordPack=pListNext; if (DebugOn) DbgPrint("回调入口:%X 类型:BugCheckCallBack 包地址:%X\n",pBugCheckRecordPack->CallbackRoutine,pBugCheckRecordPack); memset(SystemNotify->NotifyInfo[BugCheckNum].lpwzObject,0, sizeof(SystemNotify->NotifyInfo[BugCheckNum].lpwzObject)); swprintf(SystemNotify->NotifyInfo[BugCheckNum].lpwzObject, L"KBUGCHECK_CALLBACK_RECORD:0x%08X",pBugCheckRecordPack); SystemNotify->NotifyInfo[BugCheckNum].ulObject = pBugCheckRecordPack; SystemNotify->NotifyInfo[BugCheckNum].ulNotifyBase = (ULONG)(pBugCheckRecordPack->CallbackRoutine); memset(SystemNotify->NotifyInfo[BugCheckNum].lpwzType,0,sizeof(SystemNotify->NotifyInfo[BugCheckNum].lpwzType)); wcscat(SystemNotify->NotifyInfo[BugCheckNum].lpwzType,L"BugCheckCallBack"); memset(SystemNotify->NotifyInfo[BugCheckNum].lpszModule,0,sizeof(SystemNotify->NotifyInfo[BugCheckNum].lpszModule)); if (!IsAddressInSystem( pBugCheckRecordPack->CallbackRoutine, &ulModuleBase, &ulModuleSize, SystemNotify->NotifyInfo[BugCheckNum].lpszModule)) { strcat(SystemNotify->NotifyInfo[BugCheckNum].lpszModule,"Unknown"); } BugCheckNum++; SystemNotify->ulCount++; } while(pListNext->Flink!=pListEntry) { pListNext=pListNext->Flink; pBugCheckRecordPack=pListNext; if (DebugOn) DbgPrint("回调入口:%X 类型:BugCheckCallBack 包地址:%X\n",pBugCheckRecordPack->CallbackRoutine,pBugCheckRecordPack); memset(SystemNotify->NotifyInfo[BugCheckNum].lpwzObject,0, sizeof(SystemNotify->NotifyInfo[BugCheckNum].lpwzObject)); swprintf(SystemNotify->NotifyInfo[BugCheckNum].lpwzObject, L"KBUGCHECK_CALLBACK_RECORD:0x%08X",pBugCheckRecordPack); SystemNotify->NotifyInfo[BugCheckNum].ulObject = pBugCheckRecordPack; SystemNotify->NotifyInfo[BugCheckNum].ulNotifyBase = (ULONG)(pBugCheckRecordPack->CallbackRoutine); memset(SystemNotify->NotifyInfo[BugCheckNum].lpwzType,0,sizeof(SystemNotify->NotifyInfo[BugCheckNum].lpwzType)); wcscat(SystemNotify->NotifyInfo[BugCheckNum].lpwzType,L"BugCheckCallBack"); memset(SystemNotify->NotifyInfo[BugCheckNum].lpszModule,0,sizeof(SystemNotify->NotifyInfo[BugCheckNum].lpszModule)); if (!IsAddressInSystem( pBugCheckRecordPack->CallbackRoutine, &ulModuleBase, &ulModuleSize, SystemNotify->NotifyInfo[BugCheckNum].lpszModule)) { strcat(SystemNotify->NotifyInfo[BugCheckNum].lpszModule,"Unknown"); } BugCheckNum++; SystemNotify->ulCount++; } }
NTSTATUS MExcept::CreateVEH(size_t pTargetBase, size_t imageSize, eModType mt, bool partial) { AsmJitHelper a; uint64_t result = 0; auto& mods = _proc.Modules(); #ifdef USE64 // Add module to module table if(!_pModTable.Valid()) { _pModTable = _proc.Memory().Allocate(0x1000); _pModTable.Release(); if(!_pModTable.Valid()) return LastNtStatus(); } ModuleTable table; _pModTable.Read(0, table); // Add new entry to the table table.entry[table.count].base = pTargetBase; table.entry[table.count].size = imageSize; table.count++; _pModTable.Write(0, table); // No handler required if(partial) return STATUS_SUCCESS; // VEH codecave _pVEHCode = _proc.Memory().Allocate(0x2000); _pVEHCode.Release(); if(!_pVEHCode.Valid()) return LastNtStatus(); BLACBONE_TRACE("ManualMap: Vectored hander: 0x%p\n", _pVEHCode.Ptr()); asmjit::Label lExit = a->newLabel(); asmjit::Label lLoop1 = a->newLabel(); asmjit::Label skip1 = a->newLabel(); asmjit::Label found1 = a->newLabel(); // // Assembly code for VectoredHandler64 // 0x10 - EXCEPTION_RECORD.ExceptionAddress // 0x20 - EXCEPTION_RECORD.ExceptionInformation[0] // 0x30 - EXCEPTION_RECORD.ExceptionInformation[2] // 0x38 - EXCEPTION_RECORD.ExceptionInformation[3] // a->mov(asmjit::host::rax, asmjit::host::qword_ptr(asmjit::host::rcx)); a->cmp(asmjit::host::dword_ptr(asmjit::host::rax), EH_EXCEPTION_NUMBER); // Exception code a->jne(lExit); a->cmp(asmjit::host::qword_ptr(asmjit::host::rax, 0x20), EH_PURE_MAGIC_NUMBER1); // Sub code a->jne(lExit); a->cmp(asmjit::host::qword_ptr(asmjit::host::rax, 0x38), 0); // Image base a->jne(lExit); a->mov(asmjit::host::r9, _pModTable.Ptr()); a->mov(asmjit::host::rdx, asmjit::host::qword_ptr(asmjit::host::r9)); // Record count a->add(asmjit::host::r9, sizeof(table.count)); a->xor_(asmjit::host::r10, asmjit::host::r10); a->bind(lLoop1); a->mov(asmjit::host::r8, asmjit::host::qword_ptr(asmjit::host::rax, 0x30)); a->mov(asmjit::host::r11, asmjit::host::qword_ptr(asmjit::host::r9)); a->cmp(asmjit::host::r8, asmjit::host::r11); a->jl(skip1); a->add(asmjit::host::r11, asmjit::host::qword_ptr(asmjit::host::r9, sizeof(table.entry[0].base))); // Size a->cmp(asmjit::host::r8, asmjit::host::r11); a->jg(skip1); a->jmp(found1); a->bind(skip1); a->add(asmjit::host::r9, sizeof(ExceptionModule)); a->add(asmjit::host::r10, 1); a->cmp(asmjit::host::r10, asmjit::host::rdx); a->jne(lLoop1); a->jmp(lExit); a->bind(found1); a->mov(asmjit::host::qword_ptr(asmjit::host::rax, 0x20), EH_MAGIC_NUMBER1); a->mov(asmjit::host::rcx, asmjit::host::qword_ptr(asmjit::host::rcx)); a->mov(asmjit::host::rdx, asmjit::host::qword_ptr(asmjit::host::r9)); a->mov(asmjit::host::qword_ptr(asmjit::host::rax, 0x38), asmjit::host::rdx); a->bind(lExit); a->xor_(asmjit::host::rax, asmjit::host::rax); a->ret(); a->db(0xCC); a->db(0xCC); a->db(0xCC); if(_pVEHCode.Write(0, a->getCodeSize(), a->make()) != STATUS_SUCCESS) { _pVEHCode.Free(); return LastNtStatus(); } #else UNREFERENCED_PARAMETER(pTargetBase); UNREFERENCED_PARAMETER(imageSize); // No handler required if(partial) return STATUS_SUCCESS; // VEH codecave _pVEHCode = _proc.Memory().Allocate(0x2000); _pVEHCode.Release(); if(!_pVEHCode.Valid()) return LastNtStatus(); // Resolve compiler incremental table address, if any void *pFunc = ResolveJmp(&VectoredHandler); size_t fnSize = static_cast<size_t>(SizeOfProc(pFunc)); size_t dataOfs = 0, code_ofs = 0, code_ofs2 = 0;; // Find and replace magic values for(uint8_t *pData = reinterpret_cast<uint8_t*>(pFunc); pData < reinterpret_cast<uint8_t*>(pFunc) + fnSize - 4; pData++) { // LdrpInvertedFunctionTable if(*(size_t*)pData == 0xDEADDA7A) { dataOfs = pData - reinterpret_cast<uint8_t*>(pFunc); continue; } // DecodeSystemPointer address if(*(size_t*)pData == 0xDEADC0DE) { code_ofs = pData - reinterpret_cast<uint8_t*>(pFunc); break; } // LdrProtectMrdata address if(*(size_t*)pData == 0xDEADC0D2) { code_ofs2 = pData - reinterpret_cast<uint8_t*>(pFunc); continue; } } auto pDecode = mods.GetExport(mods.GetModule(L"ntdll.dll", Sections, mt), "RtlDecodeSystemPointer").procAddress; // Write handler data into target process if(!NT_SUCCESS(_pVEHCode.Write(0, fnSize, pFunc)) || !NT_SUCCESS(_pVEHCode.Write(dataOfs, _proc.NativeLdr().LdrpInvertedFunctionTable())) || !NT_SUCCESS(_pVEHCode.Write(code_ofs, static_cast<size_t>(pDecode))) || !NT_SUCCESS(_pVEHCode.Write(code_ofs2, _proc.NativeLdr().LdrProtectMrdata()))) { _pVEHCode.Free(); return LastNtStatus(); } #endif // AddVectoredExceptionHandler(0, pHandler); auto pAddHandler = mods.GetExport(mods.GetModule(L"ntdll.dll", Sections, mt), "RtlAddVectoredExceptionHandler").procAddress; if(pAddHandler == 0) return STATUS_NOT_FOUND; a->reset(); a.GenPrologue(); a.GenCall(static_cast<size_t>(pAddHandler), {0, _pVEHCode.Ptr<size_t>()}); _proc.Remote().AddReturnWithEvent(a, mt); a.GenEpilogue(); _proc.Remote().ExecInWorkerThread(a->make(), a->getCodeSize(), result); _hVEH = static_cast<size_t>(result); return (_hVEH == 0 ? STATUS_NOT_FOUND : STATUS_SUCCESS); }
void GetCreateProcessNotify(PSYSTEM_NOTIFY SystemNotify) { PEX_FAST_REF Ref; //UCHAR* Base=(UCHAR*)PsSetCreateProcessNotifyRoutine; PUCHAR Base; PUCHAR i=0,x=0; ULONG Address=0; PEX_CALLBACK_ROUTINE_BLOCK Point; WIN_VER_DETAIL WinVer; PUCHAR ulPspSetCreateProcessNotifyRoutine; Base=(UCHAR*)GetFunctionAddr(L"PsSetCreateProcessNotifyRoutine"); if (DebugOn) KdPrint(("Base:%08x\r\n",Base)); if (!MmIsAddressValidEx(Base)) { return ; } WinVer = GetWindowsVersion(); switch(WinVer) { case WINDOWS_VERSION_2K3_SP1_SP2: case WINDOWS_VERSION_XP: /* 805d0c27 56 push esi 805d0c28 57 push edi 805d0c29 7464 je nt!PsSetCreateProcessNotifyRoutine+0x73 (805d0c8f) 805d0c2b bf404a5680 mov edi,offset nt!PspCreateProcessNotifyRoutine (80564a40) 指令bf 40 4a 56 80即包含地址80564a40 805d0c30 57 push edi */ for(i=Base;i<i+SizeOfProc(Base);i++) { if (DebugOn) KdPrint(("[%08x]Base:%08x\r\n",i,Base)); if(*i == 0xbf) { Address=*(ULONG*)(i+1); if (DebugOn) KdPrint(("[%08x]Base:%08x %08x\r\n",i,Base,Address)); //DbgPrint("进程创建回调函数数组地址:%d\n",Address); //数组是EX_FAST_REF类型 break; } } break; case WINDOWS_VERSION_7_7000: case WINDOWS_VERSION_7_7600_UP: /* 83f9c821 33db xor ebx,ebx 83f9c823 c7450ca0a9f483 mov dword ptr [ebp+0Ch],offset nt!PspCreateProcessNotifyRoutine (83f4a9a0) 83f9c82a ff750c push dword ptr [ebp+0Ch] */ for(i=Base;i<i+SizeOfProc(Base);i++) { if(*i == 0xe8) { ulPspSetCreateProcessNotifyRoutine=*(ULONG*)(i+1)+(i+5); if (DebugOn) KdPrint(("[%08x]ulPspSetCreateProcessNotifyRoutine:%08x\r\n",i,ulPspSetCreateProcessNotifyRoutine)); if (MmIsAddressValidEx(ulPspSetCreateProcessNotifyRoutine)) { for(x=ulPspSetCreateProcessNotifyRoutine;x<x+SizeOfProc(ulPspSetCreateProcessNotifyRoutine);x++) { if (DebugOn) KdPrint(("[%08x]Base:%08x\r\n",x,Base)); if (*x == 0xc7) { //DbgPrint("进程创建回调函数数组地址:%d\n",Address); //数组是EX_FAST_REF类型 Address=*(ULONG*)(x+3); if (DebugOn) KdPrint(("[%08x]Base:%08x %08x\r\n",x,ulPspSetCreateProcessNotifyRoutine,Address)); break; } } } break; } } break; } //KdPrint(("没有找到进程创建回调函数数组\n")); if (!MmIsAddressValidEx(Address)){ return ; } Ref=(PEX_FAST_REF)(Address); CreateProcessNum = SystemNotify->ulCount; for(i=0;i<8;i++) { Point=(PEX_CALLBACK_ROUTINE_BLOCK)((Ref->Value>>3)<<3);//得到存有函数地址的结构 if(MmIsAddressValidEx((PVOID)Point)) { if (DebugOn) DbgPrint("回调入口:%X 类型:CreateProcess\n",(ULONG)(Point->Function)); memset(SystemNotify->NotifyInfo[CreateProcessNum].lpwzObject,0, sizeof(SystemNotify->NotifyInfo[CreateProcessNum].lpwzObject)); swprintf(SystemNotify->NotifyInfo[CreateProcessNum].lpwzObject, L"EX_CALLBACK_ROUTINE_BLOCK:0x%08X",Point); SystemNotify->NotifyInfo[CreateProcessNum].ulNotifyBase = (ULONG)(Point->Function); memset(SystemNotify->NotifyInfo[CreateProcessNum].lpwzType,0,sizeof(SystemNotify->NotifyInfo[CreateProcessNum].lpwzType)); wcscat(SystemNotify->NotifyInfo[CreateProcessNum].lpwzType,L"CreateProcess"); memset(SystemNotify->NotifyInfo[CreateProcessNum].lpszModule,0,sizeof(SystemNotify->NotifyInfo[CreateProcessNum].lpszModule)); if (!IsAddressInSystem( Point->Function, &ulModuleBase, &ulModuleSize, SystemNotify->NotifyInfo[CreateProcessNum].lpszModule)) { strcat(SystemNotify->NotifyInfo[CreateProcessNum].lpszModule,"Unknown"); } CreateProcessNum++; SystemNotify->ulCount++; } Ref++; } return; }
/// <summary> /// Inject VEH wrapper into process /// Used to enable execution of SEH handlers out of image /// </summary> /// <param name="pTargetBase">Target image base address</param> /// <param name="imageSize">Size of the image</param> /// <returns>Error code</returns> NTSTATUS MExcept::CreateVEH( size_t pTargetBase, size_t imageSize ) { AsmJitHelper ea; uint64_t result = 0; // VEH codecave _pVEHCode = _proc.memory().Allocate( 0x2000 ); _pVEHCode.Release(); if (!_pVEHCode.valid()) return LastNtStatus(); #ifdef USE64 asmjit::Label lExit = ea->newLabel(); // // Assembly code for VectoredHandler64 // 0x10 - EXCEPTION_RECORD.ExceptionAddress // 0x20 - EXCEPTION_RECORD.ExceptionInformation[0] // 0x30 - EXCEPTION_RECORD.ExceptionInformation[2] // 0x38 - EXCEPTION_RECORD.ExceptionInformation[3] // ea->mov( asmjit::host::rax, qword_ptr( asmjit::host::rcx ) ); ea->cmp( asmjit::host::dword_ptr( asmjit::host::rax ), EH_EXCEPTION_NUMBER ); ea->jne( lExit ); ea->mov( asmjit::host::rdx, pTargetBase ); ea->mov( asmjit::host::r8, asmjit::host::qword_ptr( asmjit::host::rax, 0x30 ) ); ea->cmp( asmjit::host::r8, asmjit::host::rdx );; ea->jl( lExit ); ea->add( asmjit::host::rdx, imageSize ); ea->cmp( asmjit::host::r8, asmjit::host::rdx );; ea->jg( lExit ); ea->cmp( asmjit::host::qword_ptr( asmjit::host::rax, 0x20 ), EH_PURE_MAGIC_NUMBER1 );; ea->jne( lExit ); ea->cmp( asmjit::host::qword_ptr( asmjit::host::rax, 0x38 ), 0 ); ea->jne( lExit ); ea->mov( asmjit::host::qword_ptr( asmjit::host::rax, 0x20 ), EH_MAGIC_NUMBER1 ); ea->mov( asmjit::host::rcx, qword_ptr( asmjit::host::rcx ) ); ea->mov( asmjit::host::rdx, pTargetBase ); ea->mov( asmjit::host::qword_ptr( asmjit::host::rax, 0x38 ), asmjit::host::rdx ); ea->bind( lExit ); ea->xor_( asmjit::host::rax, asmjit::host::rax ); ea->ret(); ea->emit( 0xCC ); ea->emit( 0xCC ); ea->emit( 0xCC ); if (_pVEHCode.Write( 0, ea->getCodeSize(), ea->make() ) != STATUS_SUCCESS) { _pVEHCode.Free(); return LastNtStatus(); } #else UNREFERENCED_PARAMETER( pTargetBase ); UNREFERENCED_PARAMETER( imageSize ); // Resolve compiler incremental table address if any void *pFunc = ResolveJmp( &VectoredHandler ); size_t fnSize = static_cast<size_t>(SizeOfProc( pFunc )); size_t dataOfs = 0, code_ofs = 0; // Find and replace magic values for (uint8_t *pData = reinterpret_cast<uint8_t*>(pFunc); pData < reinterpret_cast<uint8_t*>(pFunc) + fnSize - 4; pData++) { // LdrpInvertedFunctionTable if(*(size_t*)pData == 0xDEADDA7A) { dataOfs = pData - reinterpret_cast<uint8_t*>(pFunc); continue; } // DecodeSystemPointer address if(*(size_t*)pData == 0xDEADC0DE) { code_ofs = pData - reinterpret_cast<uint8_t*>(pFunc); break; } } // Write handler data into target process if (_pVEHCode.Write( 0, fnSize, pFunc ) != STATUS_SUCCESS || _pVEHCode.Write( dataOfs, _proc.nativeLdr().LdrpInvertedFunctionTable() ) != STATUS_SUCCESS || _pVEHCode.Write( code_ofs, &DecodeSystemPointer ) != STATUS_SUCCESS) { _pVEHCode.Free(); return LastNtStatus(); } #endif ea.GenPrologue(); // AddVectoredExceptionHandler(0, pHandler); ea.GenCall( reinterpret_cast<void*>(&AddVectoredExceptionHandler), { 0, _pVEHCode.ptr<size_t>() } ); _proc.remote().AddReturnWithEvent( ea ); ea.GenEpilogue(); _proc.remote().ExecInWorkerThread( ea->make(), ea->getCodeSize(), result ); _hVEH = static_cast<size_t>(result); return (result == 0 ? STATUS_NOT_FOUND : STATUS_SUCCESS); }