simplify thread safety code

This commit is contained in:
Akash Mozumdar 2018-06-12 17:31:24 -04:00
parent 30f95423f1
commit 32bcee8f50
5 changed files with 27 additions and 168 deletions

View File

@ -43,7 +43,7 @@ target_compile_options(vnrhost PRIVATE
target_link_libraries(vnrhost target_link_libraries(vnrhost
#ithsys #ithsys
profile profile
${WDK_HOME}/lib/wxp/i386/ntdll.lib #${WDK_HOME}/lib/wxp/i386/ntdll.lib
) )
target_compile_definitions(vnrhost target_compile_definitions(vnrhost

View File

@ -25,7 +25,7 @@
namespace { // unnamed namespace { // unnamed
//enum { MAX_ENTRY = 0x40 }; //enum { MAX_ENTRY = 0x40 };
#define HM_LOCK win_mutex_lock<HookManager::mutex_type> d_locker(hmcs) // Synchronized scope for accessing private data #define HM_LOCK CriticalSectionLocker d_locker(hmcs) // Synchronized scope for accessing private data
} // unnamed namespace } // unnamed namespace
@ -59,14 +59,14 @@ DWORD GetHookName(LPSTR str, DWORD pid, DWORD hook_addr, DWORD max)
ProcessRecord *pr = ::man->GetProcessRecord(pid); ProcessRecord *pr = ::man->GetProcessRecord(pid);
if (!pr) if (!pr)
return 0; return 0;
NtWaitForSingleObject(pr->hookman_mutex, 0, 0); WaitForSingleObject(pr->hookman_mutex, 0);
const Hook *hks = (const Hook *)pr->hookman_map; const Hook *hks = (const Hook *)pr->hookman_map;
for (int i = 0; i < MAX_HOOK; i++) for (int i = 0; i < MAX_HOOK; i++)
if (hks[i].Address() == hook_addr) { if (hks[i].Address() == hook_addr) {
len = hks[i].NameLength(); len = hks[i].NameLength();
if (len >= max) if (len >= max)
len = max; len = max;
NtReadVirtualMemory(pr->process_handle, hks[i].Name(), str, len, &len); ReadProcessMemory(pr->process_handle, hks[i].Name(), str, len, &len);
if (str[len - 1] == 0) if (str[len - 1] == 0)
len--; len--;
else else
@ -74,18 +74,11 @@ DWORD GetHookName(LPSTR str, DWORD pid, DWORD hook_addr, DWORD max)
break; break;
} }
NtReleaseMutant(pr->hookman_mutex, 0); ReleaseMutex(pr->hookman_mutex);
//::man->UnlockProcessHookman(pid); //::man->UnlockProcessHookman(pid);
return len; return len;
} }
// Artikash 5/31/2018: required for unordered_map to work with struct key
bool operator==(const ThreadParameter& one, const ThreadParameter& two)
{
return one.pid == two.pid && one.hook == two.hook && one.retn == two.retn && one.spl == two.spl;
}
#define NAMED_PIPE_DISCONNECT 1
//Class member of HookManger //Class member of HookManger
HookManager::HookManager() : HookManager::HookManager() :
// jichi 9/21/2013: Zero memory // jichi 9/21/2013: Zero memory
@ -105,11 +98,14 @@ HookManager::HookManager() :
TextThread* consoleTextThread = threadTable[{0, -1UL, -1UL, -1UL}] = new TextThread({ 0, -1UL, -1UL, -1UL }, new_thread_number++); TextThread* consoleTextThread = threadTable[{0, -1UL, -1UL, -1UL}] = new TextThread({ 0, -1UL, -1UL, -1UL }, new_thread_number++);
consoleTextThread->Status() |= USING_UNICODE; consoleTextThread->Status() |= USING_UNICODE;
SetCurrent(consoleTextThread); SetCurrent(consoleTextThread);
InitializeCriticalSection(&hmcs);
} }
HookManager::~HookManager() HookManager::~HookManager()
{ {
// Artikash 5/31/2018: This is called when the program terminates, so Windows should automatically free all these resources.....right? // Artikash 5/31/2018: This is called when the program terminates, so Windows should automatically free all these resources.....right?
//LeaveCriticalSection(&hmcs);
//LARGE_INTEGER timeout={-1000*1000,-1}; //LARGE_INTEGER timeout={-1000*1000,-1};
//IthBreak(); //IthBreak();
//NtWaitForSingleObject(destroy_event, 0, 0); //NtWaitForSingleObject(destroy_event, 0, 0);
@ -364,88 +360,6 @@ HANDLE HookManager::GetHostPipeByPID(DWORD pid)
MK_BASIC_TYPE(DWORD) MK_BASIC_TYPE(DWORD)
MK_BASIC_TYPE(LPVOID) MK_BASIC_TYPE(LPVOID)
//DWORD Hash(LPCWSTR module, int length)
//{
// bool flag = (length==-1);
// DWORD hash = 0;
// for (;*module && (flag || length--); module++)
// hash = ((hash>>7)|(hash<<25)) + *module;
// return hash;
//}
//void AddLink(WORD from, WORD to) { ::man->AddLink(from, to); }
// jichi 9/27/2013: Unparse to hook parameters /H code
void GetCode(const HookParam &hp, LPWSTR buffer, DWORD pid)
{
WCHAR c;
LPWSTR ptr = buffer;
// jichi 12/7/2014: disabled
//if (hp.type&PRINT_DWORD)
// c = L'H';
if (hp.type&USING_UNICODE) {
if (hp.type&USING_STRING)
c = L'Q';
else if (hp.type&STRING_LAST_CHAR)
c = L'L';
else
c = L'W';
} else {
if (hp.type&USING_STRING)
c = L'S';
else if (hp.type&BIG_ENDIAN)
c = L'A';
else if (hp.type&STRING_LAST_CHAR)
c = L'E';
else
c = L'B';
}
ptr += swprintf(ptr, L"/H%c",c);
if (hp.type & NO_CONTEXT)
*ptr++ = L'N';
if (hp.offset>>31)
ptr += swprintf(ptr, L"-%X",-(hp.offset+4));
else
ptr += swprintf(ptr, L"%X",hp.offset);
if (hp.type & DATA_INDIRECT) {
if (hp.index>>31)
ptr += swprintf(ptr, L"*-%X",-hp.index);
else
ptr += swprintf(ptr,L"*%X",hp.index);
}
if (hp.type & USING_SPLIT) {
if (hp.split >> 31)
ptr += swprintf(ptr, L":-%X", -(4 + hp.split));
else
ptr += swprintf(ptr, L":%X", hp.split);
}
if (hp.type & SPLIT_INDIRECT) {
if (hp.split_index >> 31)
ptr += swprintf(ptr, L"*-%X", -hp.split_index);
else
ptr += swprintf(ptr, L"*%X", hp.split_index);
}
if (hp.module) {
if (pid) {
WCHAR path[MAX_PATH];
MEMORY_BASIC_INFORMATION info;
ProcessRecord* pr = ::man->GetProcessRecord(pid);
if (pr) {
HANDLE hProc = pr->process_handle;
if (NT_SUCCESS(NtQueryVirtualMemory(hProc,(PVOID)hp.address, MemorySectionName, path, MAX_PATH*2, 0)) &&
NT_SUCCESS(NtQueryVirtualMemory(hProc,(PVOID)hp.address, MemoryBasicInformation, &info, sizeof(info), 0)))
ptr += swprintf(ptr, L"@%X:%s", hp.address - (DWORD)info. AllocationBase, wcsrchr(path,L'\\') + 1);
}
} else {
ptr += swprintf(ptr, L"@%X!%X", hp.address, hp.module);
if (hp.function)
ptr += swprintf(ptr, L"!%X", hp.function);
}
}
else
ptr += swprintf(ptr, L"@%X", hp.address);
}
void AddHooksToProfile(Profile& pf, const ProcessRecord& pr); void AddHooksToProfile(Profile& pf, const ProcessRecord& pr);
DWORD AddThreadToProfile(Profile& pf, const ProcessRecord& pr, TextThread* thread); DWORD AddThreadToProfile(Profile& pf, const ProcessRecord& pr, TextThread* thread);
void MakeHookRelative(const ProcessRecord& pr, HookParam& hp); void MakeHookRelative(const ProcessRecord& pr, HookParam& hp);

View File

@ -95,8 +95,7 @@ private:
std::unordered_map<ThreadParameter, TextThread*, ThreadParameterHasher> threadTable; std::unordered_map<ThreadParameter, TextThread*, ThreadParameterHasher> threadTable;
std::unordered_map<DWORD, ProcessRecord*> processRecordsByIds; std::unordered_map<DWORD, ProcessRecord*> processRecordsByIds;
typedef win_mutex<CRITICAL_SECTION> mutex_type; CRITICAL_SECTION hmcs;
mutex_type hmcs;
TextThread *current; TextThread *current;
ConsoleCallback console; // jichi 12/25/2013: add console output callback ConsoleCallback console; // jichi 12/25/2013: add console output callback

View File

@ -19,7 +19,13 @@ struct ThreadParameter {
DWORD pid; // jichi: 5/11/2014: The process ID DWORD pid; // jichi: 5/11/2014: The process ID
DWORD hook; // Artikash 6/6/2018: The start address of the hook DWORD hook; // Artikash 6/6/2018: The start address of the hook
DWORD retn; // jichi 5/11/2014: The return address of the hook DWORD retn; // jichi 5/11/2014: The return address of the hook
DWORD spl; // jichi 5/11/2014: the processed split value of the hook parameter DWORD spl; // jichi 5/11/2014: the processed split value of the hook paramete
// Artikash 5/31/2018: required for unordered_map to work with struct key
friend bool operator==(const ThreadParameter& one, const ThreadParameter& two)
{
return one.pid == two.pid && one.hook == two.hook && one.retn == two.retn && one.spl == two.spl;
}
}; };
#define CURRENT_SELECT 0x1000 #define CURRENT_SELECT 0x1000

View File

@ -8,77 +8,6 @@
# pragma warning(disable:4800) // C4800: forcing value to bool # pragma warning(disable:4800) // C4800: forcing value to bool
#endif // _MSC_VER #endif // _MSC_VER
// Mutex lock
// The interface of this class is consistent with the mutex class
template <typename _Mutex>
class win_mutex_lock
{
typedef win_mutex_lock<_Mutex> _Self;
win_mutex_lock(const _Self&);
_Self &operator=(const _Self&);
_Mutex &_M_mutex;
bool _M_locked;
public:
typedef _Mutex mutex_type;
typedef typename _Mutex::native_handle_type native_handle_type;
explicit win_mutex_lock(mutex_type &mutex)
: _M_mutex(mutex), _M_locked(false) { lock(); }
~win_mutex_lock() { if (_M_locked) _M_mutex.unlock(); }
mutex_type &mutex() { return _M_mutex; }
//bool isLock() const { return _M_locked; }
native_handle_type native_handle() { return _M_mutex.native_handle(); }
void unlock() { _M_mutex.unlock(); _M_locked = false; }
void lock() { _M_mutex.lock(); _M_locked = true; }
bool try_lock() { return _M_locked = _M_mutex.try_lock(); }
};
// Mutex
template <typename _Mutex, size_t _Irql = 0>
class win_mutex
{
typedef win_mutex<_Mutex> _Self;
typedef _Mutex __native_type;
enum { __minimal_irql = _Irql };
__native_type _M_mutex;
win_mutex(const _Self&);
_Self &operator=(const _Self&);
private:
win_mutex() {}
typedef __native_type *native_handle_type;
native_handle_type native_handle() { return &_M_mutex; }
static size_t minimal_irql() { return __minimal_irql; }
void unlock() {}
void lock() {}
bool try_lock() {}
};
template <>
class IHFSERVICE win_mutex<CRITICAL_SECTION>
{
typedef win_mutex<CRITICAL_SECTION> _Self;
typedef CRITICAL_SECTION __native_type;
enum { __minimal_irql = 0 };
win_mutex(const _Self&);
_Self &operator=(const _Self&);
__native_type _M_mutex;
public:
typedef __native_type *native_handle_type;
native_handle_type native_handle() { return &_M_mutex; }
static size_t minimal_irql() { return __minimal_irql; }
win_mutex() { ::InitializeCriticalSection(&_M_mutex); }
~win_mutex() { ::DeleteCriticalSection(&_M_mutex); }
void lock() { ::EnterCriticalSection(&_M_mutex); }
void unlock() { ::LeaveCriticalSection(&_M_mutex); }
bool try_lock() { return ::TryEnterCriticalSection(&_M_mutex); }
};
class MutexLocker class MutexLocker
{ {
HANDLE m; HANDLE m;
@ -90,4 +19,15 @@ template <>
~MutexLocker() { if (m != INVALID_HANDLE_VALUE && m != nullptr) ReleaseMutex(m); } ~MutexLocker() { if (m != INVALID_HANDLE_VALUE && m != nullptr) ReleaseMutex(m); }
}; };
class CriticalSectionLocker
{
CRITICAL_SECTION cs;
public:
explicit CriticalSectionLocker(CRITICAL_SECTION cs) : cs(cs)
{
EnterCriticalSection(&cs);
}
~CriticalSectionLocker() { LeaveCriticalSection(&cs); }
};
// EOF // EOF