Exemplo n.º 1
0
//得到文件系统回调链表头地址
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;
	}
}
Exemplo n.º 2
0
/*
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++;
	 }
}
Exemplo n.º 3
0
	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);
	}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
/// <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);
}