mirror of
https://github.com/donnaskiez/ac.git
synced 2024-11-21 22:24:08 +01:00
some MAJOR changes LOL
This commit is contained in:
parent
2861eed804
commit
977905ee77
11 changed files with 345 additions and 20 deletions
|
@ -3,16 +3,29 @@
|
|||
#include <string>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "../user/um/threadpool.h"
|
||||
#include "../user/um/ummanager.h"
|
||||
|
||||
void TestFunction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if ( argc == 1 )
|
||||
//if ( argc == 1 )
|
||||
//{
|
||||
// LOG_INFO( "No target process passed, terminating" );
|
||||
// return ERROR;
|
||||
//}
|
||||
|
||||
usermode::Manager manager( "notepad.exe" );
|
||||
manager.ValidateProcessThreads();
|
||||
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
LOG_INFO( "No target process passed, terminating" );
|
||||
return ERROR;
|
||||
|
||||
}
|
||||
|
||||
UserMode::Manager um_manager( argv[1]);
|
||||
|
||||
}
|
26
user/um/imports.cpp
Normal file
26
user/um/imports.cpp
Normal file
|
@ -0,0 +1,26 @@
|
|||
#include "imports.h"
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
usermode::Imports::Imports()
|
||||
{
|
||||
NtQueryInformationThread = nullptr;
|
||||
|
||||
this->ImportMap[ "NtQueryInformationThread" ] = NtQueryInformationThread;
|
||||
|
||||
std::map<std::string, void*>::iterator it;
|
||||
for ( it = this->ImportMap.begin(); it != this->ImportMap.end(); it++ )
|
||||
{
|
||||
HMODULE module_handle = GetModuleHandle( L"ntdll.dll" );
|
||||
if ( !module_handle )
|
||||
{
|
||||
LOG_ERROR( "GetModuleHandle failed with status code 0x%x", GetLastError() );
|
||||
return;
|
||||
}
|
||||
it->second = GetProcAddress( module_handle, it->first.c_str());
|
||||
if ( !it->second )
|
||||
{
|
||||
LOG_ERROR( "GetProcAddress failed with status code 0x%x", GetLastError() );
|
||||
}
|
||||
}
|
||||
}
|
22
user/um/imports.h
Normal file
22
user/um/imports.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#ifndef IMPORTS_H
|
||||
#define IMPORTS_H
|
||||
|
||||
#include <winternl.h>
|
||||
#include <Windows.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
typedef NTSTATUS( WINAPI* pNtQueryInformationThread )( HANDLE, LONG, PVOID, ULONG, PULONG );
|
||||
|
||||
namespace usermode
|
||||
{
|
||||
class Imports
|
||||
{
|
||||
public:
|
||||
std::map<std::string, void*> ImportMap;
|
||||
void* NtQueryInformationThread;
|
||||
Imports();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,10 +1,101 @@
|
|||
#include "process.h"
|
||||
|
||||
#include "../common.h"
|
||||
#include "../um/imports.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
HANDLE usermode::process::GetHandleToProcessGivenName( std::string ProcessName )
|
||||
#define ThreadQuerySetWin32StartAddress 9
|
||||
|
||||
usermode::Process::Process( int ThreadCount, std::string ProcessName )
|
||||
{
|
||||
this->process_name = ProcessName;
|
||||
this->thread_pool = std::make_unique<ThreadPool>( ThreadCount );
|
||||
this->process_handle = GetHandleToProcessGivenName( ProcessName );
|
||||
this->function_imports = std::make_unique<Imports>();
|
||||
|
||||
if ( this->process_handle == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
this->thread_pool->Stop();
|
||||
throw std::invalid_argument("Failed to initiate process class handle with error");
|
||||
}
|
||||
}
|
||||
|
||||
usermode::Process::~Process()
|
||||
{
|
||||
/* Wait for our jobs to be finished, then safely stop our pool */
|
||||
while ( true )
|
||||
{
|
||||
if ( this->thread_pool->Busy() == FALSE ) { this->thread_pool->Stop(); }
|
||||
}
|
||||
}
|
||||
|
||||
void usermode::Process::ValidateProcessThreads()
|
||||
{
|
||||
std::vector<UINT64> threads = GetProcessThreadsStartAddresses();
|
||||
}
|
||||
|
||||
std::vector<UINT64> usermode::Process::GetProcessThreadsStartAddresses()
|
||||
{
|
||||
HANDLE thread_snapshot_handle = INVALID_HANDLE_VALUE;
|
||||
THREADENTRY32 thread_entry;
|
||||
NTSTATUS status;
|
||||
HANDLE thread_handle;
|
||||
UINT64 start_address;
|
||||
std::vector<UINT64> start_addresses;
|
||||
|
||||
pNtQueryInformationThread NtQueryInfo = ( pNtQueryInformationThread )this->function_imports->ImportMap["NtQueryInformationThread"];
|
||||
|
||||
thread_snapshot_handle = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
|
||||
|
||||
if ( thread_snapshot_handle == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
LOG_ERROR( "thread snapshot handle invalid with error 0x%x", GetLastError() );
|
||||
return {};
|
||||
}
|
||||
|
||||
thread_entry.dwSize = sizeof( THREADENTRY32 );
|
||||
|
||||
if ( !Thread32First( thread_snapshot_handle, &thread_entry ))
|
||||
{
|
||||
LOG_ERROR( "Thread32First failed with status 0x%x", GetLastError() );
|
||||
CloseHandle( thread_snapshot_handle );
|
||||
return {};
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if ( thread_entry.th32OwnerProcessID != process_id )
|
||||
continue;
|
||||
|
||||
thread_handle = OpenThread( THREAD_ALL_ACCESS, FALSE, thread_entry.th32ThreadID );
|
||||
|
||||
if ( thread_handle == INVALID_HANDLE_VALUE )
|
||||
continue;
|
||||
|
||||
status = NtQueryInfo(
|
||||
thread_handle,
|
||||
( THREADINFOCLASS )ThreadQuerySetWin32StartAddress,
|
||||
&start_address,
|
||||
sizeof( UINT64 ),
|
||||
NULL
|
||||
);
|
||||
|
||||
if ( !NT_SUCCESS( status ) )
|
||||
{
|
||||
LOG_ERROR( "NtQueryInfo failed with status code 0x%lx", status );
|
||||
continue;
|
||||
}
|
||||
|
||||
start_addresses.push_back( start_address );
|
||||
|
||||
} while ( Thread32Next( thread_snapshot_handle, &thread_entry ) );
|
||||
|
||||
return start_addresses;
|
||||
}
|
||||
|
||||
|
||||
HANDLE usermode::Process::GetHandleToProcessGivenName( std::string ProcessName )
|
||||
{
|
||||
std::wstring wide_process_name;
|
||||
std::wstring target_process_name;
|
||||
|
@ -32,17 +123,18 @@ HANDLE usermode::process::GetHandleToProcessGivenName( std::string ProcessName )
|
|||
|
||||
do
|
||||
{
|
||||
process_handle = OpenProcess(
|
||||
process_handle = OpenProcess(
|
||||
PROCESS_ALL_ACCESS,
|
||||
FALSE,
|
||||
process_entry.th32ProcessID
|
||||
FALSE,
|
||||
process_entry.th32ProcessID
|
||||
);
|
||||
|
||||
/*
|
||||
* this will generally fail due to a process being an elevated process and denying
|
||||
* us access so we dont really care if OpenProcess fails in most cases
|
||||
*/
|
||||
if ( process_handle == NULL )
|
||||
{
|
||||
LOG_ERROR( "OpenProcess failed with error 0x%x", GetLastError() );
|
||||
continue;
|
||||
}
|
||||
|
||||
target_process_name = std::wstring( process_entry.szExeFile );
|
||||
|
||||
|
@ -50,6 +142,7 @@ HANDLE usermode::process::GetHandleToProcessGivenName( std::string ProcessName )
|
|||
{
|
||||
LOG_INFO( "Found target process" );
|
||||
CloseHandle( process_snapshot_handle );
|
||||
this->process_id = process_entry.th32ProcessID;
|
||||
return process_handle;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,34 @@
|
|||
#ifndef PROCESS_H
|
||||
#define PROCESS_H
|
||||
|
||||
#include <Windows.h>
|
||||
#include <windows.h>
|
||||
#include <winternl.h>
|
||||
#include <TlHelp32.h>
|
||||
#include <string>
|
||||
|
||||
#include "../um/threadpool.h"
|
||||
#include "../um/imports.h"
|
||||
|
||||
namespace usermode
|
||||
{
|
||||
namespace process
|
||||
class Process
|
||||
{
|
||||
HANDLE process_handle;
|
||||
DWORD process_id;
|
||||
std::string process_name;
|
||||
std::mutex mutex;
|
||||
std::unique_ptr<Imports> function_imports;
|
||||
|
||||
HANDLE GetHandleToProcessGivenName( std::string ProcessName );
|
||||
}
|
||||
std::vector<UINT64> GetProcessThreadsStartAddresses();
|
||||
public:
|
||||
std::unique_ptr<ThreadPool> thread_pool;
|
||||
|
||||
Process( int ThreadCount, std::string ProcessName );
|
||||
~Process();
|
||||
|
||||
void ValidateProcessThreads();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
86
user/um/threadpool.cpp
Normal file
86
user/um/threadpool.cpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
#include "threadpool.h"
|
||||
|
||||
/*
|
||||
* This is the idle loop each thread will be running until a job is ready
|
||||
* for execution
|
||||
*/
|
||||
void usermode::ThreadPool::ThreadLoop()
|
||||
{
|
||||
while ( true )
|
||||
{
|
||||
std::function<void()> job;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock( this->queue_mutex );
|
||||
|
||||
/*
|
||||
* This is equivalent to :
|
||||
*
|
||||
* while (!this->jobs.empty() || should_terminate)
|
||||
* mutex_condition.wait(lock);
|
||||
*
|
||||
* we are essentially waiting for a job to be queued up or the terminate flag to be set.
|
||||
* Another piece of useful information is that the predicate is checked under the lock
|
||||
* as the precondition for .wait() is that the calling thread owns the lock.
|
||||
*
|
||||
* Now, when .wait() is run, the lock is unlocked the the executing thread is blocked and
|
||||
* is added to a list of threads current waiting on the predicate. In our case whether
|
||||
* there are new jobs available for the terminate flag is set. Once the condition variables
|
||||
* are true i.e there are new jobs or we are terminating, the lock is reacquired by the thread
|
||||
* and the thread is unblocked.
|
||||
*/
|
||||
mutex_condition.wait( lock, [ this ] { return !this->jobs.empty() || this->should_terminate; } );
|
||||
|
||||
if ( this->should_terminate )
|
||||
return;
|
||||
|
||||
/* get the first job in the queue*/
|
||||
job = jobs.front();
|
||||
jobs.pop();
|
||||
}
|
||||
/* run the job */
|
||||
job();
|
||||
}
|
||||
}
|
||||
|
||||
usermode::ThreadPool::ThreadPool(int ThreadCount)
|
||||
{
|
||||
this->thread_count = ThreadCount;
|
||||
this->should_terminate = false;
|
||||
|
||||
/* Initiate our threads and store them in our threads vector */
|
||||
for ( int i = 0; i < this->thread_count; i++ )
|
||||
{
|
||||
this->threads.emplace_back( std::thread( &ThreadPool::ThreadLoop, this ) );
|
||||
}
|
||||
}
|
||||
|
||||
void usermode::ThreadPool::QueueJob( const std::function<void()>& job )
|
||||
{
|
||||
/* push a job into our job queue safely by holding our queue lock */
|
||||
std::unique_lock<std::mutex> lock( this->queue_mutex );
|
||||
this->jobs.push( job );
|
||||
lock.unlock();
|
||||
mutex_condition.notify_one();
|
||||
}
|
||||
|
||||
void usermode::ThreadPool::Stop()
|
||||
{
|
||||
/* safely set our termination flag to true */
|
||||
std::unique_lock<std::mutex> lock( this->queue_mutex );
|
||||
should_terminate = true;
|
||||
lock.unlock();
|
||||
/* unlock all threads waiting on our condition */
|
||||
mutex_condition.notify_all();
|
||||
/* join the threads and clear our threads vector */
|
||||
for ( std::thread& thread : threads ) { thread.join(); }
|
||||
threads.clear();
|
||||
}
|
||||
|
||||
bool usermode::ThreadPool::Busy()
|
||||
{
|
||||
/* allows us to wait for when the job queue is empty allowing us to safely call the destructor */
|
||||
std::unique_lock<std::mutex> lock( this->queue_mutex );
|
||||
bool pool_busy = !jobs.empty();
|
||||
this->queue_mutex.unlock();
|
||||
return pool_busy;
|
||||
}
|
31
user/um/threadpool.h
Normal file
31
user/um/threadpool.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#ifndef THREADPOOL_H
|
||||
#define THREADPOOL_H
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <functional>
|
||||
|
||||
namespace usermode
|
||||
{
|
||||
class ThreadPool
|
||||
{
|
||||
int thread_count;
|
||||
bool should_terminate;
|
||||
std::mutex queue_mutex;
|
||||
std::condition_variable mutex_condition;
|
||||
std::vector<std::thread> threads;
|
||||
std::queue<std::function<void()>> jobs;
|
||||
|
||||
void ThreadLoop();
|
||||
|
||||
public:
|
||||
|
||||
ThreadPool( int ThreadCount );
|
||||
void QueueJob(const std::function<void()>& job);
|
||||
void Stop();
|
||||
bool Busy();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -2,11 +2,22 @@
|
|||
|
||||
#include "../common.h"
|
||||
#include "process.h"
|
||||
#include "../um/imports.h"
|
||||
|
||||
#include <TlHelp32.h>
|
||||
|
||||
UserMode::Manager::Manager( std::string ProcessName )
|
||||
usermode::Manager::Manager( std::string ProcessName )
|
||||
{
|
||||
this->process_name = ProcessName;
|
||||
this->process_handle = GetHandleToProcessGivenName( ProcessName );
|
||||
this->process = std::make_unique<Process>( 4, ProcessName );
|
||||
}
|
||||
|
||||
usermode::Manager::~Manager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void usermode::Manager::ValidateProcessThreads()
|
||||
{
|
||||
this->process->thread_pool->QueueJob( [ this ]() {this->process->ValidateProcessThreads(); } );
|
||||
}
|
||||
|
|
|
@ -2,17 +2,26 @@
|
|||
#define UMMANAGER_H
|
||||
|
||||
#include <string>
|
||||
#include <winternl.h>
|
||||
#include <Windows.h>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
namespace UserMode
|
||||
#include "process.h"
|
||||
|
||||
namespace usermode
|
||||
{
|
||||
class Manager
|
||||
{
|
||||
std::string process_name;
|
||||
HANDLE process_handle;
|
||||
std::unique_ptr<Process> process;
|
||||
|
||||
public:
|
||||
Manager( std::string ProcessName );
|
||||
~Manager();
|
||||
|
||||
void ValidateProcessThreads();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -129,13 +129,17 @@
|
|||
<ItemGroup>
|
||||
<ClCompile Include="km\kprotection.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="um\imports.cpp" />
|
||||
<ClCompile Include="um\process.cpp" />
|
||||
<ClCompile Include="um\threadpool.cpp" />
|
||||
<ClCompile Include="um\ummanager.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="common.h" />
|
||||
<ClInclude Include="km\kprotection.h" />
|
||||
<ClInclude Include="um\imports.h" />
|
||||
<ClInclude Include="um\process.h" />
|
||||
<ClInclude Include="um\threadpool.h" />
|
||||
<ClInclude Include="um\ummanager.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
|
|
@ -27,6 +27,12 @@
|
|||
<ClCompile Include="um\process.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="um\threadpool.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="um\imports.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="common.h">
|
||||
|
@ -41,5 +47,11 @@
|
|||
<ClInclude Include="um\process.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="um\threadpool.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="um\imports.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
Reference in a new issue