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