SafeDisc debugger detection

Laurent Pinchart laurent.pinchart at skynet.be
Sat Apr 6 18:22:46 CST 2002


Hi,

This patches implements the debugger detection code needed by SafeDisc copy 
protected applications. It can be split into several parts:

	* win32/device.c, win32/secdrv.c, include/secdrv.h:
	Implementation of the SafeDisc secdrv.sys NT driver.

	* memory/emulate.c:
	Preliminary implementation of the SharedUserData shared memory page, located
	at 0x7ffe0000.

	* dlls/ntdll/nt.c:
	Fixed NtQueryInformationProcess to return correct information and error code
	for ProcessDebugPort when no debugger is attached.

	* dlls/ntdll/signal_i386.c:
	Modified do_sigsegv to allow INSTR_EmulateInstruction to modify the exception
	code.

	* include/miscemu.h, memory/instr.c:
	Modified INSTR_EmulateInstruction so that int 0x01 emulation raises an
	EXCEPTION_ACCESS_VIOLATION instead of EXCEPTION_PRIV_INSTRUCTION.

	* scheduler/process.c:
	Reserves the SharedUserData page (PAGE_NOACCESS at 0x7ffe0000) at process
	initialization.

Please note that SafeDisc protected programs won't crash anymore, but still 
won't run. You'll get a nice dialog box asking you to insert the CD in the 
cdrom drive :-) I'll start working on that tomorrow.

Feedback is welcome. I've tested this patch with a game protected by SafeDisc 
1.3.0. It might not work for newer versions.

Laurent Pinchart


-------------- next part --------------
--- /dev/null	Thu Jan  1 01:00:00 1970
+++ memory/emulate.c	Fri Apr  5 00:41:44 2002
@@ -0,0 +1,53 @@
+/*
+ * Emulation of privileged memory
+ *
+ * Copyright 2002 Laurent Pinchart
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "windef.h"
+#include "wingdi.h"
+#include "wine/winuser16.h"
+#include "module.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(virtual);
+
+#ifdef __i386__
+
+/***********************************************************************
+ *           MEMORY_SharedUserData
+ *
+ * Handles exceptions for the SharedUserData access.
+ */
+BOOL MEMORY_SharedUserData( LPVOID arg, LPCVOID addr )
+{
+    DWORD dwProtection;
+    BOOL ret;
+
+    TRACE( "MEMORY_SharedUserData\n" );
+
+    ret = VirtualProtect( (LPVOID)0x7ffe0000, 0x10000, PAGE_READWRITE, &dwProtection );
+    if ( ret )
+    {
+	*(LPDWORD)0x7ffe0000 = 0x12345678;
+	ret = VirtualProtect( (LPVOID)0x7ffe0000, 0x10000, PAGE_READONLY, &dwProtection );
+    }
+
+    return ret;
+}
+
+#endif  /* __i386__ */
-------------- next part --------------
A non-text attachment was scrubbed...
Name: safedisc.patch
Type: text/x-c
Size: 9191 bytes
Desc: not available
Url : http://www.winehq.org/pipermail/wine-patches/attachments/20020407/a14269be/safedisc.bin
-------------- next part --------------
--- /dev/null	Thu Jan  1 01:00:00 1970
+++ win32/secdrv.c	Sun Apr  7 00:08:34 2002
@@ -0,0 +1,189 @@
+/*
+ * SafeDisc copy protection driver
+ *
+ * Copyright 2002 Laurent Pinchart
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "winerror.h"
+#include "file.h"
+#include "winioctl.h"
+#include "winnt.h"
+#include "secdrv.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(vxd);
+
+static BOOL SECDRV_GetDRInfo( LPVOID lpvInBuffer, DWORD cbInBuffer,
+			      LPVOID lpvOutBuffer, LPDWORD lpCbOutBuffer );
+static BOOL SECDRV_GetIdtInfo( LPVOID lpvInBuffer, DWORD cbInBuffer,
+			       LPVOID lpvOutBuffer, LPDWORD lpCbOutBuffer );
+static BOOL SECDRV_Setup( LPVOID lpvInBuffer, DWORD cbInBuffer,
+			  LPVOID lpvOutBuffer, LPDWORD lpCbOutBuffer );
+static VOID SECDRV_BuildVerificationData( LPVOID lpBuffer );
+
+static unsigned int contextDr1 = 0x00000000;
+static unsigned int contextDr7 = 0x00000400;
+
+BOOL SECDRV_DeviceIo_SafeDisc( LPVOID lpvInBuffer, DWORD cbInBuffer,
+			       LPVOID lpvOutBuffer, DWORD cbOutBuffer )
+{
+	PSECDRV_IOC_IN_BUFFER pInBuffer   = (PSECDRV_IOC_IN_BUFFER)lpvInBuffer;
+	PSECDRV_IOC_OUT_BUFFER pOutBuffer = (PSECDRV_IOC_OUT_BUFFER)lpvOutBuffer;
+	BOOL retv;
+
+	if ( ! pInBuffer || ! pOutBuffer )
+		return FALSE;
+
+	if ( cbInBuffer != 0x514 || cbOutBuffer != 0x610 )
+		return FALSE;
+
+	retv = FALSE;
+
+	switch( pInBuffer->dwCommand ) {
+	case SECDRV_CMD_INFO_DR:
+		retv = SECDRV_GetDRInfo( pInBuffer->bUserData, pInBuffer->cbUserData,
+					 pOutBuffer->bUserData, &pOutBuffer->cbUserData );
+		break;
+	case SECDRV_CMD_INFO_IDT:
+		retv = SECDRV_GetIdtInfo( pInBuffer->bUserData, pInBuffer->cbUserData,
+					  pOutBuffer->bUserData, &pOutBuffer->cbUserData );
+		break;
+	case SECDRV_CMD_SETUP:
+		retv = SECDRV_Setup( pInBuffer->bUserData, pInBuffer->cbUserData,
+				     pOutBuffer->bUserData, &pOutBuffer->cbUserData );
+		break;
+	default:
+		FIXME( "unsupported command\n" );
+		break;
+	}
+
+	if ( retv )
+	{
+	    pOutBuffer->dwVersionMajor = 1;
+	    pOutBuffer->dwVersionMinor = 3;
+	    pOutBuffer->dwVersionPatch = 0;
+	    SECDRV_BuildVerificationData( pOutBuffer->bVerificationData );
+	}
+
+	return retv;
+}
+
+static VOID SECDRV_BuildVerificationData( LPVOID lpBuffer )
+{
+	DWORD dwRandom = 0xf367ac7f;
+	LPDWORD lpDwBuffer = (LPDWORD)lpBuffer;
+	int i;
+
+	/* lpDwBuffer[0] should be initialized with KeTickCount.LowPart.
+	 * If done, KeTickCount.LowPart should also be accessible from user
+	 * space by a read operation at address 0x7ffe0000.
+	 */
+	lpDwBuffer[0] = 0x12345678;
+
+	for ( i = 3; i != 0; --i )
+	{
+		dwRandom = 0x361962e9 - dwRandom * 0x0d5acb1b;
+		lpDwBuffer[i]  = dwRandom;
+		lpDwBuffer[0] ^= dwRandom;
+	}
+}
+
+static BOOL SECDRV_GetDRInfo( LPVOID lpvInBuffer, DWORD cbInBuffer,
+			      LPVOID lpvOutBuffer, LPDWORD lpCbOutBuffer )
+{
+	unsigned int dwDebugRegister;
+
+//	FIXME( "SECDRV_GetDRInfo not supported yet\n" );
+
+	if ( cbInBuffer != 0 )
+	{
+		FIXME( "cbInBuffer != 0\n" );
+		return FALSE;
+	}
+
+	if ( contextDr1 == 0xbd331200 )
+	{
+		/* I don't understand why. It's not even a valid DR7 value */
+		dwDebugRegister = 0x3871dd10;
+	}
+	else
+	{
+		dwDebugRegister = contextDr7;
+	}
+
+	*(LPDWORD)lpvOutBuffer = dwDebugRegister & 0x00000500;
+	*lpCbOutBuffer = 4;
+
+	return TRUE;
+}
+			      
+static BOOL SECDRV_GetIdtInfo( LPVOID lpvInBuffer, DWORD cbInBuffer,
+			       LPVOID lpvOutBuffer, LPDWORD lpCbOutBuffer )
+{
+	struct _IDTR {
+		WORD limit;
+		DWORD base;
+	} idtr;
+
+	ULONGLONG *idt;
+	DWORD dwOffset;
+
+	if ( cbInBuffer != 0 )
+		return FALSE;
+
+	asm( "sidtl %0" : "=m"(idtr) );
+	idt = (ULONGLONG*)idtr.base;
+
+//	dwOffset = ( idt[3] & 0x0000ffff ) - ( idt[1] & 0x0000ffff );
+	dwOffset = 0;
+
+	if ( dwOffset > 0x100 )
+	{
+		*(LPDWORD)lpvOutBuffer = 0x2c8;
+	}
+	else
+	{
+		*(LPDWORD)lpvOutBuffer = dwOffset;
+		contextDr1 = 0xbd331200;
+	}
+
+	*lpCbOutBuffer = 4;
+
+	return TRUE;
+}
+
+static BOOL SECDRV_Setup( LPVOID lpvInBuffer, DWORD cbInBuffer,
+			  LPVOID lpvOutBuffer, LPDWORD lpCbOutBuffer )
+{
+	if ( cbInBuffer != 0 )
+		return FALSE;
+
+	*(LPDWORD)lpvOutBuffer = 0x5278d11b;
+	*lpCbOutBuffer = 4;
+
+	return TRUE;
+}
-------------- next part --------------
--- /dev/null	Thu Jan  1 01:00:00 1970
+++ include/secdrv.h	Sat Apr  6 23:32:54 2002
@@ -0,0 +1,58 @@
+/*
+ * SafeDisc copy protection driver
+ *
+ * Copyright 2002 Laurent Pinchart
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __WINE_SECDRV_H
+#define __WINE_SECDRV_H
+
+#include "windef.h"
+
+typedef struct _SECDRV_IOC_IN_BUFFER
+{
+    DWORD dwVersionMajor;
+    DWORD dwVersionMinor;
+    DWORD dwVersionPatch;
+
+    DWORD dwCommand;
+    BYTE bVerificationData[0x400];
+
+    DWORD cbUserData;
+    BYTE  bUserData[0x100];
+} SECDRV_IOC_IN_BUFFER, *PSECDRV_IOC_IN_BUFFER;
+
+typedef struct _SECDRV_IOC_OUT_BUFFER
+{
+    DWORD dwVersionMajor;
+    DWORD dwVersionMinor;
+    DWORD dwVersionPatch;
+
+    BYTE  bVerificationData[0x400];
+
+    DWORD cbUserData;
+    BYTE  bUserData[0x200];
+} SECDRV_IOC_OUT_BUFFER, *PSECDRV_IOC_OUT_BUFFER;
+
+#define SECDRV_CMD_INFO_DR		(0x0000003c)
+#define SECDRV_CMD_INFO_IDT		(0x0000003d)
+#define SECDRV_CMD_SETUP		(0x0000003e)
+
+extern BOOL SECDRV_DeviceIo_SafeDisc( LPVOID lpvInBuffer, DWORD cbInBuffer,
+                                      LPVOID lpvOutBuffer, DWORD cbOutBuffer );
+
+#endif /* __WINE_SECDRV_H */


More information about the wine-patches mailing list