Last active
June 18, 2020 20:58
-
-
Save CarlTBarnes/c88a85373873f6ff54b79071e1a67d80 to your computer and use it in GitHub Desktop.
Debug Viewer Detection
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
!From https://clarionhub.com/t/how-to-detect-if-an-outputdebugstring-viewer-is-running/241 | |
!I have not tested this code | |
PROGRAM | |
!INCLUDE('Windows.inc'),ONCE | |
MAP | |
OutputDebugStringNotReady(),BOOL !0=Ready, Non-Zero indicates Not Ready | |
MODULE('Standard Windows APIs') | |
OpenEvent(DWORD InDesiredAccess, BOOL InInheritHandle, | | |
*CSTRING InName),LONG,RAW,PASCAL,DLL(1),NAME('OpenEventA') | |
GetLastError(),LONG,PASCAL,DLL(1) | |
CloseHandle(LONG InObject),BOOL,PASCAL,DLL(1) | |
END | |
END | |
CODE | |
MESSAGE('An OutputDebugString View is ['& | | |
CHOOSE( OutputDebugStringNotReady()=0, 'Running', 'NOT Running') &']') | |
!========================================================== | |
OutputDebugStringNotReady PROCEDURE()!,LONG | |
!Ported from VB6 Code written by *Carl Barnes* | |
!PSS: OutputDebugString is expensive requiring a switch to kernel mode to access event, mutex and MMF. See | |
! http://www.unixwiz.net/techtips/outputdebugstring.html | |
hObject LONG,AUTO | |
SYNCHRONIZE LONG(100000h) ! 10 0000 | |
szEventName CSTRING('DBWIN_BUFFER_READY') !case sensitive | |
RetError LONG,AUTO | |
CODE | |
hObject = OpenEvent(SYNCHRONIZE, FALSE, szEventName) | |
IF hObject <> 0 THEN !Open worked, Event exists | |
CloseHandle(hObject) | |
RetError = 0 !We are ready | |
ELSE | |
RetError = GetLastError() | |
! probably 2 = File Not Found, | |
! i.e. the Event name does not exist because there is no debugger | |
IF RetError = 0 | |
RetError = -1 ! no handle and no error, then say -1 | |
END | |
END | |
RETURN RetError | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// From http://www.unixwiz.net/techtips/outputdebugstring.html | |
/* | |
* pseudocode for OutputDebugString | |
* | |
* from KERNEL32.DLL ver 5.0.2195.6794 | |
* | |
* Reverse engineered by Steve Friedl (steve@unixwiz.net) | |
*/ | |
void OutputDebugStringA(LPTSTR *lpString) | |
{ | |
DBWIN_buffer *pDBBuffer = 0; | |
HANDLE hFileMap = 0; | |
HANDLE hBufferEvent = 0; | |
HANDLE hDataEvent = 0; | |
// if we can't make or acquire the mutex, we're done | |
if ( hDbwinMutex == 0 ) | |
hDbwinMutex = setup_mutex(); | |
if ( hDbwinMutex == 0) return; | |
(void) WaitForSingleObject(hDbwinMutex, INFINITE); | |
hFileMap = OpenFileMapping(FILE_MAP_WRITE, FALSE, "DBWIN_BUFFER"); | |
pDBBuffer = (DBWIN_buffer *) MapViewOfFile( | |
hFileMap, | |
FILE_MAP_READ|FILE_MAP_WRITE, | |
0, // file offset high | |
0, // file offset low | |
0 ); // # of bytes to map (entire file) | |
hBufferEvent = OpenEvent( SYNCHRONIZE, FALSE, "DBWIN_BUFFER_READY"); | |
hDataEvent = OpenEvent( EVENT_MODIFY_STATE, FALSE, "DBWIN_DATA_READY"); | |
const char *p = lpString; | |
int len = strlen(lpString); | |
while ( len > 0 ) | |
{ | |
if ( WaitForSingleObject(hBufferEvent, 10*1000) != WAIT_OBJECT_0 ) | |
{ | |
/* ERROR: give up */ | |
break; | |
} | |
// populate the shared memory segment. The string | |
// is limited to 4k or so. | |
pBuffer->dwProcessId = GetCurrentProcessId(); | |
int n = min(len, sizeof(pBuffer->data)-1); | |
memcpy(pBuffer->data, p, n); | |
pBuffer->data[n] = '\0'; | |
len -= n; | |
p += n; | |
SetEvent(hDataEvent); | |
} | |
// cleanup after ourselves | |
CloseHandle(hBufferEvent); | |
CloseHandle(hDataEvent); | |
UnmapViewOfFile(pDBBuffer); | |
CloseHandle(hFileMap); | |
} | |
HANDLE setup_mutex(void) | |
{ | |
SID_IDENTIFIER_AUTHORITY SIAWindowsNT = SECURITY_NT_AUTHORITY; | |
SID_IDENTIFIER_AUTHORITY SIAWorld = SECURITY_WORLD_SID_AUTHORITY; | |
SID *pSidSYSTEM = 0, // | |
*pSidAdmins = 0, | |
*pSidEveryone = 0; | |
AllocateAndInitializeSid(&SIAWindowsNT, | |
1, SECURITY_LOCAL_SYSTEM_RID, | |
0, 0, 0, 0, 0, 0, 0, | |
&pSidSYSTEM); | |
AllocateAndInitializeSid(&SIAWindowsNT, | |
2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, | |
0, 0, 0, 0, 0, 0, | |
&pSidAdmins); | |
AllocateAndInitializeSid(&SIAWorld, | |
1, SECURITY_WORLD_RID, | |
0, 0, 0, 0, 0, 0, 0, | |
&pSidEveryone); | |
const DWORD dwACLSize = GetLengthSid(pSidSYSTEM) | |
+ GetLengthSig(pSidAdmins) | |
+ GetLengthSig(pSidEveryone) | |
+ 32; | |
ACL *pACL = GlobalAlloc( 0, dwACLSize ); | |
InitializeAcl(pACL, dwACLsize, ACL_REVISION ); | |
AddAccessAllowedAce(pACL, | |
ACL_REVISION, | |
SYNCHRONIZE | READ_CONTROL | MUTEX_QUERY_STATE, | |
pSidEveryone); | |
AddAccessAllowedAce(pACL, | |
ACL_REVISION, | |
MUTEX_ALL_ACCESS, | |
pSidSYSTEM); | |
AddAccessAllowedAce(pACL, | |
ACL_REVISION, | |
MUTEX_ALL_ACCESS, | |
pSidAdmins); | |
SECURITY_DESCRIPTOR sd; | |
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); | |
SetSecurityDescriptorDacl(&sd, TRUE, pACL, FALSE); | |
SECURITY_ATTRIBUTES sa; | |
ZeroMemory(&sa, sizeof sa); | |
sa.bInheritHandle = FALSE; | |
sa.nLength = sizeof sa; | |
sa.lpSecurityDescriptor = &sd; | |
HANDLE hMutex = CreateMutex(&sa, FALSE, "DBWinMutex"); | |
FreeSid(pSidAdmins); | |
FreeSid(pSidSYSTEM); | |
FreeSid(pSidEveryone); | |
GlobalFree(pACL); | |
return hMutex; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment