本文整理汇总了C++中LastNtStatus函数的典型用法代码示例。如果您正苦于以下问题:C++ LastNtStatus函数的具体用法?C++ LastNtStatus怎么用?C++ LastNtStatus使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了LastNtStatus函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: LastNtStatus
NTSTATUS ProcessMemory::Read(ptr_t dwAddress, size_t dwSize, PVOID pResult, bool handleHoles /*= false*/) {
DWORD64 dwRead = 0;
if(dwAddress == 0)
return LastNtStatus(STATUS_INVALID_ADDRESS);
LastNtStatus(STATUS_SUCCESS);
// Simple read
if(!handleHoles) {
return _core.GetNative()->ReadProcessMemoryT(dwAddress, pResult, dwSize, &dwRead);
}
// Read all committed memory regions
else {
MEMORY_BASIC_INFORMATION64 mbi = {0};
for(ptr_t memptr = dwAddress; memptr < dwAddress + dwSize; memptr = mbi.BaseAddress + mbi.RegionSize) {
if(_core.GetNative()->VirtualQueryExT(memptr, &mbi) != STATUS_SUCCESS)
continue;
// Filter empty regions
if(mbi.State != MEM_COMMIT || mbi.Protect == PAGE_NOACCESS)
continue;
uint64_t region_ptr = memptr - dwAddress;
if(_core.GetNative()->ReadProcessMemoryT(mbi.BaseAddress,
reinterpret_cast<uint8_t*>(pResult) + region_ptr,
static_cast<size_t>(mbi.RegionSize),
&dwRead) != STATUS_SUCCESS) {
return LastNtStatus();
}
}
}
return STATUS_SUCCESS;
}
示例2: Native
//.........这里部分代码省略.........
/// Read virtual memory
/// </summary>
/// <param name="lpBaseAddress">Memory address</param>
/// <param name="lpBuffer">Output buffer</param>
/// <param name="nSize">Number of bytes to read</param>
/// <param name="lpBytes">Mumber of bytes read</param>
/// <returns>Status code</returns>
NTSTATUS NativeWow64::ReadProcessMemoryT( ptr_t lpBaseAddress, LPVOID lpBuffer, size_t nSize, DWORD64 *lpBytes /*= nullptr */ )
{
DWORD64 junk = 0;
if (lpBytes == nullptr)
lpBytes = &junk;
return GET_IMPORT( NtWow64ReadVirtualMemory64 )( _hProcess, lpBaseAddress, lpBuffer, nSize, lpBytes );
}
/// <summary>
/// Write virtual memory
/// </summary>
/// <param name="lpBaseAddress">Memory address</param>
/// <param name="lpBuffer">Buffer to write</param>
/// <param name="nSize">Number of bytes to read</param>
/// <param name="lpBytes">Mumber of bytes read</param>
/// <returns>Status code</returns>
NTSTATUS NativeWow64::WriteProcessMemoryT( ptr_t lpBaseAddress, LPCVOID lpBuffer, size_t nSize, DWORD64 *lpBytes /*= nullptr */ )
{
DWORD64 junk = 0;
if (lpBytes == nullptr)
lpBytes = &junk;
return GET_IMPORT( NtWow64WriteVirtualMemory64 )( _hProcess, lpBaseAddress, (LPVOID)lpBuffer, nSize, lpBytes );
}
/// <summary>
/// Call NtQueryInformationProcess for underlying process
/// </summary>
/// <param name="infoClass">Information class</param>
/// <param name="lpBuffer">Output buffer</param>
/// <param name="bufSize">Buffer size</param>
/// <returns>Status code</returns>
NTSTATUS NativeWow64::QueryProcessInfoT( PROCESSINFOCLASS infoClass, LPVOID lpBuffer, uint32_t bufSize )
{
ULONG length = 0;
return GET_IMPORT( NtWow64QueryInformationProcess64 )(_hProcess, infoClass, lpBuffer, bufSize, &length);
}
/// <summary>
/// Call NtSetInformationProcess for underlying process
/// </summary>
/// <param name="infoClass">Information class</param>
/// <param name="lpBuffer">Input buffer</param>
/// <param name="bufSize">Buffer size</param>
/// <returns>Status code</returns>
NTSTATUS NativeWow64::SetProcessInfoT( PROCESSINFOCLASS infoClass, LPVOID lpBuffer, uint32_t bufSize )
{
static ptr_t ntspi = _local.GetProcAddress64( _local.getNTDLL64(), "NtSetInformationProcess" );
if (ntspi == 0)
return STATUS_ORDINAL_NOT_FOUND;
return static_cast<NTSTATUS>(_local.X64Call( ntspi, _hProcess, infoClass, lpBuffer, bufSize ));
}
/// <summary>
/// Creates new thread in the remote process
/// </summary>
/// <param name="hThread">Created thread handle</param>
/// <param name="entry">Thread entry point</param>
/// <param name="arg">Thread argument</param>
/// <param name="flags">Creation flags</param>
/// <returns>Status code</returns>*/
NTSTATUS NativeWow64::CreateRemoteThreadT( HANDLE& hThread, ptr_t entry, ptr_t arg, CreateThreadFlags flags, DWORD access )
{
// Try to use default routine if possible
/*if(_wowBarrier.targetWow64 == true)
{
return Native::CreateRemoteThreadT( hThread, entry, arg, flags, access );
}
else*/
{
LastNtStatus( STATUS_SUCCESS );
static DWORD64 NtCreateThreadEx = _local.GetProcAddress64( _local.getNTDLL64(), "NtCreateThreadEx" );
if (NtCreateThreadEx == 0)
return LastNtStatus( STATUS_ORDINAL_NOT_FOUND );
// hThread can't be used directly because x64Call will zero stack space near variable
DWORD64 hThd2 = NULL;
NTSTATUS status = static_cast<NTSTATUS>(_local.X64Call(
NtCreateThreadEx, &hThd2, access, NULL,
_hProcess, entry, arg, flags,
0, 0x1000, 0x100000, NULL
));
hThread = reinterpret_cast<HANDLE>(hThd2);
return status;
}
}
示例3: LastNtStatus
/// <summary>
/// Creates new thread in the remote process
/// </summary>
/// <param name="hThread">Created thread handle</param>
/// <param name="entry">Thread entry point</param>
/// <param name="arg">Thread argument</param>
/// <param name="flags">Creation flags</param>
/// <param name="access">Access override</param>
/// <returns>Status code</returns>
NTSTATUS Native::CreateRemoteThreadT( HANDLE& hThread, ptr_t entry, ptr_t arg, CreateThreadFlags flags, DWORD access /*= THREAD_ALL_ACCESS*/ )
{
LastNtStatus( STATUS_SUCCESS );
NTSTATUS status = 0;
auto pCreateThread = GET_IMPORT( NtCreateThreadEx );
if (pCreateThread)
{
status = pCreateThread(
&hThread, access, NULL,
_hProcess, reinterpret_cast<PTHREAD_START_ROUTINE>(entry),
reinterpret_cast<LPVOID>(arg), static_cast<DWORD>(flags),
0, 0x1000, 0x100000, NULL
);
if (!NT_SUCCESS( status ))
hThread = NULL;
}
else
{
DWORD win32Flags = 0;
if (flags & CreateSuspended)
win32Flags = CREATE_SUSPENDED;
hThread = CreateRemoteThread(
_hProcess, NULL, 0, reinterpret_cast<PTHREAD_START_ROUTINE>(entry),
reinterpret_cast<LPVOID>(arg), win32Flags, NULL
);
status = LastNtStatus();
}
return status;
}
示例4: sizeof
/// <summary>
/// Grant current process arbitrary privilege
/// </summary>
/// <param name="name">Privilege name</param>
/// <returns>Status</returns>
NTSTATUS Process::GrantPriviledge( const std::basic_string<TCHAR>& name )
{
TOKEN_PRIVILEGES Priv, PrivOld;
DWORD cbPriv = sizeof(PrivOld);
HANDLE hToken;
if (!OpenThreadToken( GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, FALSE, &hToken ))
{
if (GetLastError() != ERROR_NO_TOKEN)
return LastNtStatus();
if (!OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken ))
return LastNtStatus();
}
Priv.PrivilegeCount = 1;
Priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
LookupPrivilegeValue( NULL, name.c_str(), &Priv.Privileges[0].Luid );
if (!AdjustTokenPrivileges( hToken, FALSE, &Priv, sizeof(Priv), &PrivOld, &cbPriv ))
{
CloseHandle( hToken );
return LastNtStatus();
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
CloseHandle( hToken );
return LastNtStatus();
}
return STATUS_SUCCESS;
}
示例5: LastNtStatus
/// <summary>
/// Fix relocations if image wasn't loaded at base address
/// </summary>
/// <param name="pImage">image data</param>
/// <returns>true on success</returns>
bool MMap::RelocateImage( ImageContext* pImage )
{
// Reloc delta
size_t Delta = pImage->imgMem.ptr<size_t>() - static_cast<size_t>(pImage->PEImage.imageBase());
// No need to relocate
if (Delta == 0)
{
LastNtStatus( STATUS_SUCCESS );
return true;
}
pe::RelocData* fixrec = reinterpret_cast<pe::RelocData*>(pImage->PEImage.DirectoryAddress( IMAGE_DIRECTORY_ENTRY_BASERELOC ));
if (fixrec == nullptr)
{
// TODO: return proper error code
LastNtStatus( STATUS_IMAGE_NOT_AT_BASE );
return false;
}
while (fixrec->BlockSize)
{
DWORD count = (fixrec->BlockSize - 8) >> 1; // records count
for (DWORD i = 0; i < count; ++i)
{
WORD fixtype = (fixrec->Item[i].Type); // fixup type
WORD fixoffset = (fixrec->Item[i].Offset) % 4096; // offset in 4K block
// no fixup required
if (fixtype == IMAGE_REL_BASED_ABSOLUTE)
continue;
// add delta
if (fixtype == IMAGE_REL_BASED_HIGHLOW || fixtype == IMAGE_REL_BASED_DIR64)
{
size_t fixRVA = static_cast<ULONG>(fixoffset) + fixrec->PageRVA;
size_t val = *reinterpret_cast<size_t*>(
reinterpret_cast<size_t>(pImage->FileImage.base()) + fixoffset + fixrec->PageRVA)
+ Delta;
// Apply relocation
if (pImage->imgMem.Write( fixRVA, val ) != STATUS_SUCCESS)
return false;
}
else
{
// TODO: support for all remaining relocations
LastNtStatus( STATUS_INVALID_IMAGE_FORMAT );
return false;
}
}
// next reloc entry
fixrec = reinterpret_cast<pe::RelocData*>(reinterpret_cast<size_t>(fixrec) + fixrec->BlockSize);
}
return true;
}
示例6: BLACBONE_TRACE
bool MMap::RelocateImage(ImageContext* pImage) {
BLACBONE_TRACE(L"ManualMap: Relocating image '%ls'", pImage->FilePath.c_str());
// Reloc delta
size_t Delta = pImage->imgMem.Ptr<size_t>() - static_cast<size_t>(pImage->peImage.ImageBase());
// No need to relocate
if(Delta == 0) {
BLACBONE_TRACE(L"ManualMap: No need for relocation");
LastNtStatus(STATUS_SUCCESS);
return true;
}
auto start = pImage->peImage.DirectoryAddress(IMAGE_DIRECTORY_ENTRY_BASERELOC);
auto end = start + pImage->peImage.DirectorySize(IMAGE_DIRECTORY_ENTRY_BASERELOC);
RelocData* fixrec = reinterpret_cast<RelocData*>(start);
if(fixrec == nullptr) {
// TODO: return proper error code
BLACBONE_TRACE(L"ManualMap: Can't relocate image, no relocation data");
LastNtStatus(STATUS_IMAGE_NOT_AT_BASE);
return false;
}
while((size_t)fixrec < end && fixrec->BlockSize) {
DWORD count = (fixrec->BlockSize - 8) >> 1; // records count
for(DWORD i = 0; i < count; ++i) {
WORD fixtype = (fixrec->Item[i].Type); // fixup type
WORD fixoffset = (fixrec->Item[i].Offset) % 4096; // offset in 4K block
// no fixup required
if(fixtype == IMAGE_REL_BASED_ABSOLUTE)
continue;
// add delta
if(fixtype == IMAGE_REL_BASED_HIGHLOW || fixtype == IMAGE_REL_BASED_DIR64) {
size_t fixRVA = fixoffset + fixrec->PageRVA;
size_t val = *reinterpret_cast<size_t*>(pImage->peImage.ResolveRVAToVA(fixoffset + fixrec->PageRVA)) + Delta;
auto status = STATUS_SUCCESS;
if(pImage->flags & HideVAD)
status = Driver().WriteMem(_process.Id(), pImage->imgMem.Ptr() + fixRVA, sizeof(val), &val);
else
status = pImage->imgMem.Write(fixRVA, val);
// Apply relocation
if(!NT_SUCCESS(status)) {
BLACBONE_TRACE(L"ManualMap: Failed to apply relocation at offset 0x%x. Status = 0x%x", fixRVA, status);
return false;
}
} else {
// TODO: support for all remaining relocations
BLACBONE_TRACE(L"ManualMap: Abnormal relocation type %d. Aborting", fixtype);
LastNtStatus(STATUS_INVALID_IMAGE_FORMAT);
return false;
}
}
// next reloc entry
fixrec = reinterpret_cast<RelocData*>(reinterpret_cast<size_t>(fixrec) + fixrec->BlockSize);
}
return true;
}
示例7: CopyCode
/// <summary>
/// Create new thread and execute code in it. Wait until execution ends
/// </summary>
/// <param name="pCode">Code to execute</param>
/// <param name="size">Code size</param>
/// <param name="callResult">Code return value</param>
/// <returns>Status</returns>
NTSTATUS RemoteExec::ExecInNewThread( PVOID pCode, size_t size, uint64_t& callResult )
{
AsmJitHelper a;
NTSTATUS dwResult = STATUS_SUCCESS;
// Write code
dwResult = CopyCode( pCode, size );
if (dwResult != STATUS_SUCCESS)
return dwResult;
bool switchMode = (_proc.core().native()->GetWow64Barrier().type == wow_64_32);
auto pExitThread = _mods.GetExport( _mods.GetModule(
L"ntdll.dll", LdrList, switchMode ? mt_mod64 : mt_default ),
"NtTerminateThread" ).procAddress;
if (pExitThread == 0)
return LastNtStatus( STATUS_NOT_FOUND );
a.GenPrologue( switchMode );
// Prepare thread to run in x64 mode
if(switchMode)
{
// Allocate new x64 activation stack
auto createActStack = _mods.GetExport( _mods.GetModule( L"ntdll.dll", LdrList, mt_mod64 ),
"RtlAllocateActivationContextStack" ).procAddress;
if (createActStack)
{
a.GenCall( static_cast<size_t>(createActStack), { _userData.ptr<size_t>() + 0x3100 } );
a->mov( a->zax, _userData.ptr<size_t>( ) + 0x3100 );
a->mov( a->zax, a->intptr_ptr( a->zax ) );
a.SetTebPtr();
a->mov( a->intptr_ptr( a->zdx, 0x2C8 ), a->zax );
}
}
a.GenCall( _userCode.ptr<size_t>(), { } );
a.ExitThreadWithStatus( (size_t)pExitThread, _userData.ptr<size_t>() + INTRET_OFFSET );
// Execute code in newly created thread
if (_userCode.Write( size, a->getCodeSize(), a->make() ) == STATUS_SUCCESS)
{
auto thread = _threads.CreateNew( _userCode.ptr<ptr_t>() + size, _userData.ptr<ptr_t>()/*, HideFromDebug*/ );
dwResult = thread.Join();
callResult = _userData.Read<uint64_t>( INTRET_OFFSET, 0 );
}
else
dwResult = LastNtStatus();
return dwResult;
}
示例8: LastNtStatus
/// <summary>
/// Set WOW64 thread context
/// </summary>
/// <param name="hThread">Thread handle.</param>
/// <param name="ctx">Thread context</param>
/// <returns>Status code</returns>
NTSTATUS NativeWow64::SetThreadContextT( HANDLE hThread, _CONTEXT32& ctx )
{
// Target process is x64. 32bit CONTEXT is not available.
if (_wowBarrier.targetWow64 == false)
{
return STATUS_NOT_SUPPORTED;
}
else
{
LastNtStatus( STATUS_SUCCESS );
SetThreadContext( hThread, reinterpret_cast<const CONTEXT*>(&ctx) );
return LastNtStatus();
}
}
示例9: LastNtStatus
/// <summary>
/// Copy executable code into remote codecave for future execution
/// </summary>
/// <param name="pCode">Code to copy</param>
/// <param name="size">Code size</param>
/// <returns>Status</returns>
NTSTATUS RemoteExec::CopyCode( PVOID pCode, size_t size )
{
if (!_userCode.valid())
_userCode = _memory.Allocate( size );
// Reallocate for larger code
if (size > _userCode.size())
if ((_userCode.Realloc(size)) == 0)
return LastNtStatus();
if (_userCode.Write( 0, size, pCode ) != STATUS_SUCCESS)
return LastNtStatus();
return STATUS_SUCCESS;
}
示例10: Unload
/// <summary>
/// Reload driver
/// </summary>
/// <param name="path">Path to the driver file</param>
/// <returns>Status code</returns>
NTSTATUS DriverControl::Reload( std::wstring path /*= L"" */ )
{
NTSTATUS status = STATUS_SUCCESS;
Unload();
// Use default path
if (path.empty())
{
const wchar_t* filename = nullptr;
if (IsWindows10OrGreater())
filename = L"BlackBoneDrv10.sys";
else if (IsWindows8Point1OrGreater())
filename = L"BlackBoneDrv81.sys";
else if (IsWindows8OrGreater())
filename = L"BlackBoneDrv8.sys";
else if (IsWindows7OrGreater())
filename = L"BlackBoneDrv7.sys";
else
filename = L"BlackBoneDrv.sys";
path = Utils::GetExeDirectory() + L"\\" + filename;
}
status = _loadStatus = LoadDriver( DRIVER_SVC_NAME, path );
if (!NT_SUCCESS( status ))
{
BLACBONE_TRACE( L"Failed to load driver %ls. Status 0x%X", path.c_str(), status );
return LastNtStatus( status );
}
_hDriver = CreateFileW(
BLACKBONE_DEVICE_FILE,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL
);
if (_hDriver == INVALID_HANDLE_VALUE)
{
status = LastNtStatus();
BLACBONE_TRACE( L"Failed to open driver handle. Status 0x%X", status );
return status;
}
return status;
}
示例11: CreateWorkerThread
/// <summary>
/// Create environment for future remote procedure calls
///
/// _userData layout (x86/x64):
/// --------------------------------------------------------------------------------------------------------------------------
/// | Internal return value | Return value | Last Status code | Event handle | Space for copied arguments and strings |
/// -------------------------------------------------------------------------------------------------------------------------
/// | 8/8 bytes | 8/8 bytes | 8/8 bytes | 16/16 bytes | |
/// --------------------------------------------------------------------------------------------------------------------------
/// </summary>
/// <param name="noThread">Create only codecave and sync event, without thread</param>
/// <returns>Status</returns>
NTSTATUS RemoteExec::CreateRPCEnvironment( bool noThread /*= false*/ )
{
NTSTATUS dwResult = STATUS_SUCCESS;
DWORD thdID = 0;
bool status = true;
//
// Allocate environment codecave
//
if (!_workerCode.valid())
_workerCode = _memory.Allocate( 0x1000 );
if (!_userData.valid())
_userData = _memory.Allocate( 0x4000, PAGE_READWRITE );
if (!_userCode.valid())
_userCode = _memory.Allocate( 0x1000 );
// Create RPC thread and sync event
if (noThread == false)
{
thdID = CreateWorkerThread();
if (thdID)
status = CreateAPCEvent( thdID );
}
if (thdID == 0 || status == false)
dwResult = LastNtStatus();
return dwResult;
}
示例12: LastNtStatus
/// <summary>
/// Maps single memory region into current process
/// </summary>
/// <param name="pid">Target PID</param>
/// <param name="base">Region base address</param>
/// <param name="size">Region size</param>
/// <param name="result">Mapped region info</param>
/// <returns>Status code</returns>
NTSTATUS DriverControl::MapMemoryRegion( DWORD pid, ptr_t base, uint32_t size, MapMemoryRegionResult& result )
{
MAP_MEMORY_REGION data = { 0 };
MAP_MEMORY_REGION_RESULT mapResult = { 0 };
DWORD bytes = 0;
// Not loaded
if (_hDriver == INVALID_HANDLE_VALUE)
return STATUS_DEVICE_DOES_NOT_EXIST;
data.pid = pid;
data.base = base;
data.size = size;
if (DeviceIoControl( _hDriver, IOCTL_BLACKBONE_MAP_REGION, &data, sizeof( data ), &mapResult, sizeof( mapResult ), &bytes, NULL ))
{
result.newPtr = mapResult.newPtr;
result.originalPtr = mapResult.originalPtr;
result.removedPtr = mapResult.removedPtr;
result.removedSize = mapResult.removedSize;
result.size = mapResult.size;
return STATUS_SUCCESS;
}
return LastNtStatus();
}
示例13: sizeof
/// <summary>
/// Free virtual memory
/// </summary>
/// <param name="pid">Tarhet PID</param>
/// <param name="base">Desired base. If 0 address is chosed by the system</param>
/// <param name="size">Region size</param>
/// <param name="type">Free type - MEM_RELEASE/MEM_DECOMMIT</param>
/// <returns>Status code</returns>
NTSTATUS DriverControl::FreeMem( DWORD pid, ptr_t base, ptr_t size, DWORD type )
{
DWORD bytes = 0;
ALLOCATE_FREE_MEMORY freeMem = { 0 };
ALLOCATE_FREE_MEMORY_RESULT result = { 0 };
freeMem.pid = pid;
freeMem.base = base;
freeMem.size = size;
freeMem.type = type;
freeMem.allocate = FALSE;
freeMem.physical = FALSE;
// Not loaded
if (_hDriver == INVALID_HANDLE_VALUE)
return STATUS_DEVICE_DOES_NOT_EXIST;
if (!DeviceIoControl(
_hDriver, IOCTL_BLACKBONE_ALLOCATE_FREE_MEMORY,
&freeMem, sizeof( freeMem ),
&result, sizeof( result ), &bytes, NULL
))
{
return LastNtStatus();
}
return STATUS_SUCCESS;
}
示例14: LastNtStatus
/// <summary>
/// Reallocate existing block for new size
/// </summary>
/// <param name="size">New block size</param>
/// <param name="desired">Desired base address of new block</param>
/// <param name="protection">Memory protection</param>
/// <returns>New block address</returns>
ptr_t MemBlock::Realloc( size_t size, ptr_t desired /*= 0*/, DWORD protection /*= PAGE_EXECUTE_READWRITE*/ )
{
ptr_t desired64 = desired;
_memory->core().native()->VirualAllocExT( desired64, size, MEM_COMMIT, protection );
if (!desired64)
{
desired64 = 0;
_memory->core( ).native( )->VirualAllocExT( desired64, size, MEM_COMMIT, protection );
if (desired64)
LastNtStatus( STATUS_IMAGE_NOT_AT_BASE );
}
// Replace current instance
if (desired64)
{
Free();
_ptr = desired64;
_size = size;
_protection = protection;
}
return desired64;
}
示例15: wcscpy_s
/// <summary>
/// Inject DLL into arbitrary process
/// </summary>
/// <param name="pid">Target PID</param>
/// <param name="path">Full qualified dll path</param>
/// <param name="itype">Injection type</param>
/// <param name="initRVA">Init routine RVA</param>
/// <param name="initArg">Init routine argument</param>
/// <param name="unlink">Unlink module after injection</param>
/// <param name="erasePE">Erase PE headers after injection</param>
/// <param name="wait">Wait for injection</param>
/// <returns>Status code</returns>
NTSTATUS DriverControl::InjectDll(
DWORD pid,
const std::wstring& path,
InjectType itype,
uint32_t initRVA /*= 0*/,
const std::wstring& initArg /*= L""*/,
bool unlink /*= false*/,
bool erasePE /*= false*/,
bool wait /*= true*/
)
{
DWORD bytes = 0;
INJECT_DLL data = { IT_Thread };
// Not loaded
if (_hDriver == INVALID_HANDLE_VALUE)
return STATUS_DEVICE_DOES_NOT_EXIST;
wcscpy_s( data.FullDllPath, path.c_str() );
wcscpy_s( data.initArg, initArg.c_str() );
data.type = itype;
data.pid = pid;
data.initRVA = initRVA;
data.wait = wait;
data.unlink = unlink;
data.erasePE = erasePE;
if (!DeviceIoControl( _hDriver, IOCTL_BLACKBONE_INJECT_DLL, &data, sizeof( data ), nullptr, 0, &bytes, NULL ))
return LastNtStatus();
return STATUS_SUCCESS;
}