Skip to content

Commit

Permalink
minor bug fixes and improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
DarthTon committed Sep 25, 2014
1 parent d976c5b commit d38b573
Show file tree
Hide file tree
Showing 14 changed files with 307 additions and 38 deletions.
1 change: 1 addition & 0 deletions src/BlackBone/BlackBone.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@
<ClInclude Include="ManualMap\Native\NtLoader.h" />
<ClInclude Include="Misc\DynImport.h" />
<ClInclude Include="Misc\NameResolve.h" />
<ClInclude Include="Misc\Thunk.hpp" />
<ClInclude Include="Misc\Trace.hpp" />
<ClInclude Include="Misc\Utils.h" />
<ClInclude Include="Patterns\PatternSearch.h" />
Expand Down
3 changes: 3 additions & 0 deletions src/BlackBone/BlackBone.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -468,5 +468,8 @@
<ClInclude Include="PE\PEImage.h">
<Filter>PE</Filter>
</ClInclude>
<ClInclude Include="Misc\Thunk.hpp">
<Filter>Misc</Filter>
</ClInclude>
</ItemGroup>
</Project>
3 changes: 3 additions & 0 deletions src/BlackBone/DriverControl/DriverControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,7 @@ NTSTATUS DriverControl::ProtectMem( DWORD pid, ptr_t base, ptr_t size, DWORD pro
/// <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="wait">Wait for injection</param>
/// <returns>Status code</returns>
NTSTATUS DriverControl::InjectDll(
Expand All @@ -485,6 +486,7 @@ NTSTATUS DriverControl::InjectDll(
InjectType itype,
uint32_t initRVA /*= 0*/,
const std::wstring& initArg /*= L""*/,
bool unlink /*= false*/,
bool wait /*= true*/
)
{
Expand All @@ -500,6 +502,7 @@ NTSTATUS DriverControl::InjectDll(
data.pid = pid;
data.initRVA = initRVA;
data.wait = wait;
data.unlink = unlink;
data.type = itype;

if (!DeviceIoControl( _hDriver, IOCTL_BLACKBONE_INJECT_DLL, &data, sizeof( data ), nullptr, 0, &bytes, NULL ))
Expand Down
2 changes: 2 additions & 0 deletions src/BlackBone/DriverControl/DriverControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ class DriverControl
/// <param name="itype">Injection type</param>
/// <param name="initRVA">Init routine RVA</param>
/// <param name="initArg">Init routine argument</param>
/// <param name="unlink">Unlonk module after injection</param>
/// <param name="wait">Wait for injection</param>
/// <returns>Status code</returns>
BLACKBONE_API NTSTATUS InjectDll(
Expand All @@ -191,6 +192,7 @@ class DriverControl
InjectType itype,
uint32_t initRVA = 0,
const std::wstring& initArg = L"",
bool unlink = false,
bool wait = true
);

Expand Down
97 changes: 97 additions & 0 deletions src/BlackBone/Misc/Thunk.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#include "../Config.h"
#include <stdint.h>
#include <winnt.h>

// Thunk code
#pragma pack(push, 1)
struct ThunkData
{
#ifndef USE64
/*
mov eax, pInstance
mov fs:[0x14], eax
mov eax, pMethod
jmp eax
*/
uint8_t mov1 = 0xB8;
void* pInst = nullptr;
uint16_t fs1 = '\x64\xA3';
uint8_t fs2 = FIELD_OFFSET( NT_TIB, ArbitraryUserPointer );
uint8_t fs3 = 0;
uint16_t fs4 = 0;
uint8_t mov2 = 0xB8;
void* pFn = nullptr;
uint16_t jmp1 = '\xFF\xE0';
#else
/*
mov rax, pInstance
mov gs:[0x28], rax
mov rax, pMethod
jmp rax
*/
uint16_t mov1 = '\x48\xB8';
void* pInst = nullptr;
uint32_t fs1 = '\x65\x48\x89\x04';
uint8_t fs2 = 0x25;
uint8_t fs3 = FIELD_OFFSET( NT_TIB, ArbitraryUserPointer );
uint8_t fs4 = 0;
uint16_t fs5 = 0;
uint16_t mov2 = '\x48\xB8';
void* pFn = nullptr;
uint16_t jmp1 = '\xFF\xE0';
#endif

void setup( void* pInstance, void* pMethod )
{
pInst = pInstance;
pFn = pMethod;
}
};
#pragma pack(pop)


template<typename fn, typename C>
class Win32Thunk;

template<typename R, typename... Args, typename C>
class Win32Thunk < R( __stdcall* )(Args...), C >
{
public:
typedef R( C::*TypeMember )(Args...);
typedef R( __stdcall* TypeFree )(Args...);

public:
Win32Thunk( TypeMember pfn, C* pInstance )
: _pMethod( pfn )
, _pInstance( pInstance )
{
DWORD dwOld = 0;
VirtualProtect( &_thunk, sizeof( _thunk ), PAGE_EXECUTE_READWRITE, &dwOld );
_thunk.setup( this, &Win32Thunk::WrapHandler );
}

/// <summary>
/// Redirect call
/// </summary>
/// <param name="...args">Arguments</param>
/// <returns>Call result</returns>
static R __stdcall WrapHandler( Args... args )
{
auto _this = reinterpret_cast<Win32Thunk*>(((PNT_TIB)NtCurrentTeb())->ArbitraryUserPointer);
return (_this->_pInstance->*_this->_pMethod)(args...);
}

/// <summary>
/// Get thunk
/// </summary>
/// <returns></returns>
TypeFree GetThunk()
{
return reinterpret_cast<TypeFree>(&_thunk);
}

private:
TypeMember _pMethod = nullptr; // Member function to call
C* _pInstance = nullptr; // Bound instance
ThunkData _thunk; // Thunk code
};
23 changes: 18 additions & 5 deletions src/BlackBone/Process/Process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,7 @@ NTSTATUS Process::CreateAndAttach(
{
// Create new thread to make sure LdrInitializeProcess gets called
if (forceInit)
{
auto pProc = _modules.GetExport( _modules.GetModule( L"ntdll.dll", Sections ), "NtYieldExecution" ).procAddress;
if (pProc)
_remote.ExecDirect( pProc, 0 );
}
EnsureInit();
}
else
ResumeThread( pi.hThread );
Expand Down Expand Up @@ -143,6 +139,19 @@ NTSTATUS Process::Detach()
return STATUS_SUCCESS;
}

/// <summary>
/// Ensure LdrInitializeProcess gets called
/// </summary>
/// <returns>Status code</returns>
NTSTATUS Process::EnsureInit()
{
auto pProc = _modules.GetExport( _modules.GetModule( L"ntdll.dll", blackbone::Sections ), "NtYieldExecution" ).procAddress;
if (pProc)
return _remote.ExecDirect( pProc, 0 );

return STATUS_NOT_FOUND;
}


/// <summary>
/// Checks if process still exists
Expand Down Expand Up @@ -322,8 +331,12 @@ NTSTATUS Process::EnumByNameOrPID(
break;
}

// Sort results
std::sort( found.begin(), found.end() );

VirtualFree( buffer, 0, MEM_RELEASE );
return status;
}


}
11 changes: 11 additions & 0 deletions src/BlackBone/Process/Process.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ struct ProcessInfo
uint32_t pid = 0;
std::wstring imageName;
std::vector<ThreadInfo> threads;

bool operator < (const ProcessInfo& other)
{
return this->pid < other.pid;
}
};


Expand Down Expand Up @@ -86,6 +91,12 @@ class Process
/// <returns>Status code</returns>
BLACKBONE_API NTSTATUS Detach();

/// <summary>
/// Ensure LdrInitializeProcess gets called
/// </summary>
/// <returns>Status code</returns>
BLACKBONE_API NTSTATUS EnsureInit();

/// <summary>
/// Get process ID
/// </summary>
Expand Down
35 changes: 16 additions & 19 deletions src/BlackBone/Process/RPC/RemoteExec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,9 +269,8 @@ DWORD RemoteExec::ExecDirect( ptr_t pCode, ptr_t arg )
/// <returns>Status</returns>
NTSTATUS RemoteExec::CreateRPCEnvironment( bool bThread /*= true*/, bool bEvent /*= true*/ )
{
NTSTATUS dwResult = STATUS_SUCCESS;
DWORD thdID = GetTickCount(); // randomize thread id
bool status = true;
NTSTATUS status = STATUS_SUCCESS;

//
// Allocate environment codecave
Expand All @@ -298,15 +297,14 @@ NTSTATUS RemoteExec::CreateRPCEnvironment( bool bThread /*= true*/, bool bEvent
}
else
{
status = false;
LastNtStatus( STATUS_NOT_SUPPORTED );
status = LastNtStatus( STATUS_NOT_SUPPORTED );
}
}

if ((bThread && thdID == 0) || !status)
dwResult = LastNtStatus();
if (bThread && thdID == 0)
status = LastNtStatus();

return dwResult;
return status;
}

/// <summary>
Expand Down Expand Up @@ -381,9 +379,11 @@ DWORD RemoteExec::CreateWorkerThread()
/// Create event to synchronize APC procedures
/// </summary>
/// <param name="threadID">The thread identifier.</param>
/// <returns>true on success</returns>
bool RemoteExec::CreateAPCEvent( DWORD threadID )
/// <returns>Status code</returns>
NTSTATUS RemoteExec::CreateAPCEvent( DWORD threadID )
{
NTSTATUS status = STATUS_SUCCESS;

if(_hWaitEvent == NULL)
{
AsmJitHelper a;
Expand Down Expand Up @@ -415,7 +415,7 @@ bool RemoteExec::CreateAPCEvent( DWORD threadID )
return false;

a.GenCall( static_cast<size_t>(pCreateEvent), {
_userData.ptr<size_t>( ) + EVENT_OFFSET, EVENT_ALL_ACCESS,
_userData.ptr<size_t>() + EVENT_OFFSET, EVENT_ALL_ACCESS,
_userData.ptr<size_t>() + ARGS_OFFSET, 0, FALSE } );

// Save status
Expand All @@ -424,30 +424,27 @@ bool RemoteExec::CreateAPCEvent( DWORD threadID )

a->ret();

NTSTATUS status = _userData.Write( ARGS_OFFSET, obAttr );
status = _userData.Write( ARGS_OFFSET, obAttr );
status |= _userData.Write( ARGS_OFFSET + sizeof(obAttr), ustr );
status |= _userData.Write( ARGS_OFFSET + sizeof(obAttr) + sizeof(ustr), len, pEventName );

if (status != STATUS_SUCCESS)
return false;
if (!NT_SUCCESS( status ))
return LastNtStatus( status );

ExecInNewThread( a->make(), a->getCodeSize(), dwResult );

status = _userData.Read<NTSTATUS>( ERR_OFFSET, -1 );
if (status != STATUS_SUCCESS)
return false;
if (!NT_SUCCESS( status ))
return LastNtStatus( status );

ustr.Buffer = pEventName;
obAttr.ObjectName = &ustr;

// Open created event
status = GET_IMPORT( NtOpenEvent )( &_hWaitEvent, SYNCHRONIZE | EVENT_MODIFY_STATE, &obAttr );

if (status != STATUS_SUCCESS)
return false;
}

return true;
return status;
}

/// <summary>
Expand Down
4 changes: 2 additions & 2 deletions src/BlackBone/Process/RPC/RemoteExec.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ class RemoteExec
/// Create event to synchronize APC procedures
/// </summary>
/// <param name="threadID">The thread identifier.</param>
/// <returns>true on success</returns>
bool CreateAPCEvent( DWORD threadID );
/// <returns>Status code</returns>
NTSTATUS CreateAPCEvent( DWORD threadID );

/// <summary>
/// Copy executable code into remote codecave for future execution
Expand Down
1 change: 1 addition & 0 deletions src/BlackBoneDrv/BlackBoneDef.h
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ typedef struct _INJECT_DLL
ULONG initRVA; // Init routine RVA, if 0 - no init routine
ULONG pid; // Target process ID
BOOLEAN wait; // Wait on injection thread
BOOLEAN unlink; // Unlink module after injection
InjectType type; // Type of injection
} INJECT_DLL, *PINJECT_DLL;

Expand Down
7 changes: 7 additions & 0 deletions src/BlackBoneDrv/Inject.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,13 @@ NTSTATUS BBInjectDll( IN PINJECT_DLL pData )
status = STATUS_INVALID_PARAMETER;
}

// Unlink module
if (pData->unlink && NT_SUCCESS( status ))
{
PVOID modBase = *(PVOID*)((PUCHAR)pUserBuf + MOD_OFFSET);
BBUnlinkFromLoader( pProcess, modBase, isWow64 );
}

ZwFreeVirtualMemory( ZwCurrentProcess(), &pUserBuf, &size, MEM_RELEASE );
}

Expand Down
Loading

0 comments on commit d38b573

Please sign in to comment.