Skip to content

Instantly share code, notes, and snippets.

@CarlTBarnes
Last active June 18, 2020 20:58
Show Gist options
  • Save CarlTBarnes/c88a85373873f6ff54b79071e1a67d80 to your computer and use it in GitHub Desktop.
Save CarlTBarnes/c88a85373873f6ff54b79071e1a67d80 to your computer and use it in GitHub Desktop.
Debug Viewer Detection
!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
// 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