home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
drdobbs
/
1990
/
10
/
schulman.asc
< prev
next >
Wrap
Text File
|
1990-08-16
|
17KB
|
520 lines
_OPENING OS/2'S BACKDOOR_
by Andrew Schulman
[LISTING ONE]
; DEVHLP.ASM
; to produce DEVHLP.SYS ("OS/2 Device Driver in a Can")
; Andrew Schulman, 32 Andrew St., Cambridge MA 02139
; with revisions by Art Rothstein, Morgan Labs, San Francisco, CA
; DEF file:
; LIBRARY DEVHLP
; DESCRIPTION 'DEVHLP.SYS (c) Andrew Schulman 1990'
; PROTMODE
; masm devhlp; && link devhlp,devhlp.sys,,,devhlp.def
; put in OS/2 config.sys:
; device=devhlp.sys
; access with DosOpen ("DEVHLPXX"), DosDevIOCTL (category 128, func 60h)
.286p
; the only specific DevHlp that DEVHLP.SYS knows about
VerifyAccess equ 27h
ioctlpkt struc
db 13 dup (?) ; header
cat db ? ; category
fun db ? ; function
param dd ? ; param area
dataptr dd ? ; data area
ioctlpkt ends
regs struc
regs_ax dw ?
regs_bx dw ?
regs_cx dw ?
regs_dx dw ?
regs_si dw ?
regs_di dw ?
regs_ds dw ?
regs_es dw ?
regs_flags dw ?
regs ends
regs_size equ size regs
dgroup group _DATA
_DATA segment word public 'DATA'
header dd -1
dw 8880h
dw Strat
dw 0
db 'DEVHLPXX'
db 8 dup (0)
DevHlp dd 0
dispch dw Init ; 0 -- Init
dw 12 dup (Error) ; 1..12 -- not supported
dw DevOp ; 13 -- DevOpen
dw DevOp ; 14 -- DevClose
dw Error ; 15 -- not supported
dw GenIOCtl ; 16 -- DevIOCtl
dw 10 dup (Error) ; 17..26 -- not supported
enddata dw 0
_DATA ends
_TEXT segment word public 'CODE'
assume cs:_TEXT, ds:DGROUP, es:NOTHING
Strat proc far
mov di, es:[bx+2]
and di, 0ffh
cmp di, 26 ; max # of commands
jle Strat1
call Error
jmp short Strat2
Strat1: add di, di
call word ptr [di+dispch]
Strat2: mov word ptr es:[bx+3], ax ; set request header status
ret
Strat endp
; used by DevOpen and DevClose
DevOp proc near
mov ax, 0100h
ret
DevOp endp
GenIOCtl proc near
push es
push bx
cmp es:[bx].cat, 128
jne bad
cmp es:[bx].fun, 60h
jne bad
call Do_DevHlp
jc bad
mov ax, 0100h ; no error
jmp short done
bad: mov ax, 8101h ; error
done: pop bx
pop es
ret
GenIOCtl endp
Do_DevHlp proc near
; verify user's access:
; VerifyAccess will shut down user's app in the event of error
mov ax, word ptr es:[bx+17] ; selector of parameter block
mov di, word ptr es:[bx+15] ; offset
mov cx, regs_size ; length to be read
mov dx, VerifyAccess ; read
call DevHlp
jnc ok1
ret
ok1: mov ax, word ptr es:[bx+21] ; selector of data buffer
mov di, word ptr es:[bx+19] ; offset
mov cx, regs_size ; length to be written
mov dx, (1 SHL 8) + VerifyAccess ; read/write
call DevHlp
jnc ok2
ret
ok2: push ds ; see if we should verify ds
lds di, es:[bx].param
mov ax, [di].regs_ds
pop ds
test ax, ax ; need to verify?
je nods ; skip if no
xor di, di ; verify seg:0 for read, 1 byte
mov cx, 1 ; length
mov dx, VerifyAccess ; read=0
call DevHlp
jc fini ; if carry flag set
nods: push ds ; see if we should verify es
lds di, es:[bx].param
mov ax, [di].regs_es
pop ds
test ax, ax ; need to verify?
je noes ; skip if no
xor di, di ; verify seg:0 for read, 1 byte
mov cx, 1 ; length
mov dx, VerifyAccess ; read=0
call DevHlp
jc fini ; if carry flag set
noes: push ds ; going to be bashed!
push es
push bx
; save DevHlp address on stack so we can change ds
push word ptr DevHlp+2
push word ptr DevHlp
; get the parameters for DevHlp from regs
lds di, es:[bx].param
mov ax, [di].regs_ax
mov bx, [di].regs_bx
mov cx, [di].regs_cx
mov dx, [di].regs_dx
mov si, [di].regs_si
mov es, [di].regs_es
push [di].regs_ds
mov di, [di].regs_di
pop ds
; here it is, the whole point of this exercise!
mov bp, sp
call dword ptr [bp]
pop bp ; pull DevHlp address off stack
pop bp ; without changing carry flag
jc fini
; save ES:BX to put in out-regs: destroys DX
mov bp, es
mov dx, bx
; get back old DS, ES:BX
pop bx
pop es
pop ds
; save FLAGS, SI, DS on stack
pushf
push si
push ds
; set up regs to return to the app
lds si, es:[bx].dataptr
mov [si].regs_ax, ax
pop [si].regs_ds
pop [si].regs_si
pop [si].regs_flags
mov [si].regs_cx, cx
mov [si].regs_bx, dx
mov [si].regs_es, bp
mov [si].regs_di, di
clc
fini: ret
Do_DevHlp endp
Error proc near
mov ax, 8103h
ret
Error endp
Init proc near
mov ax, es:[bx+14]
mov word ptr DevHlp, ax
mov ax, es:[bx+16]
mov word ptr DevHlp+2, ax
mov word ptr es:[bx+14], offset _TEXT:Init ; end of code
mov word ptr es:[bx+16], offset DGROUP:enddata
mov ax, 0100h
ret
Init endp
_TEXT ends
end
[LISTING TWO]
/* DRVRLIST.C
list the device drivers in OS/2
Art Rothstein, 1990
we assume the first driver in the chain is NUL and is in the global data
segment, and that the second driver (CON) is the same segment.
cl -AL drvrlist.c (four-byte data pointers required for memchr)
*/
#define INCL_DOSDEVICES
#include <os2.h>
#include <process.h>
#include <stdio.h>
#include <string.h>
#include "devhlp.h"
USHORT devhlp ;
SEL MakeSel( SEL selValue)
{
extern USHORT devhlp ;
REGS regs ;
USHORT ret ;
regs.dx = DevHlp_VirtToPhys ; // function requested
regs.ds = selValue ; // selector
regs.es = 0 ; // avoid trap
regs.si = 0 ; // offset
ret = DosDevIOCtl( ®s, ®s, 0x60, 128, devhlp) ;
if ( ret != 0 || regs.flags.carry != 0)
return 0 ;
// physical address in ax:bx
regs.cx = 0 ; // limit 65,535
regs.dx = MAKEUSHORT( DevHlp_PhysToUVirt, UVirt_ReadWrite);
regs.es = 0 ; // avoid trap
ret = DosDevIOCtl( ®s, ®s, 0x60, 128, devhlp) ;
if ( ret != 0 || regs.flags.carry != 0) // if error
return 0 ;
return regs.es ; // return the selector
}
BOOL ReleaseSel( SEL selValue)
{
extern USHORT devhlp ;
REGS regs ;
USHORT ret ;
regs.ax = selValue ; // selector to free
regs.dx = MAKEUSHORT( DevHlp_PhysToUVirt, UVirt_Release);
regs.ds = 0 ; // safety
regs.es = 0 ;
ret = DosDevIOCtl( ®s, ®s, 0x60, 128, devhlp) ;
if ( ret != 0 || regs.flags.carry != 0) // if error
return FALSE ;
return TRUE ; // successful return
}
void main( void)
{
USHORT usOffsetDriver
, usBytesLeft; // in search for NUL device
PCH pchGlobal ; // pointer to system global data
static CHAR szDriverName[] = "DEVHLPXX" // device helper driver
, szNullDriver[] = "NUL "; // first driver in system
typedef struct _DDHEADER { // device driver header
struct _DDHEADER * pddNext ; // chain to next driver
USHORT fsAttribute ; // driver attributes
USHORT usStrategyEntryOffset ;
USHORT usIDCEntryOffset ; // inter device communication
CHAR chName[ 8] ; // name for character devices
USHORT usIDCEntrySegmentProt ;
USHORT usIDCDataSegmentProt ;
USHORT usIDCEntrySegmentReal ;
USHORT usIDCDataSegmentReal ;
} DDHEADER ;
typedef DDHEADER * PDDHEADER ;
PDDHEADER pddCurrent // current DCB
, pddNext; // next DCB
SEL selDriver ; // selector of DCB
// open the DEVHLP device
if ((devhlp = open(szDriverName, 0)) == -1) {
puts( "Can't find DEVHLP.SYS") ;
exit( 1) ;
}
// locate the first driver
selDriver = 0x50 ; // global data segment
usOffsetDriver = 0 ;
usBytesLeft = 32000 ; // should be large enough
pchGlobal = MAKEP( MakeSel( selDriver), usOffsetDriver) ;
do {
PCH pchMatch ;
pchMatch = memchr( pchGlobal + 1, 'N', usBytesLeft); //look for first char
if ( pchMatch == NULL) { // if no match
ReleaseSel( SELECTOROF( pchGlobal)) ; // release the selector
puts( "NUL driver not found") ; // and give up
exit( 1) ;
} // if no match
// partial match
usBytesLeft -= pchMatch - pchGlobal ; // reduce residual count
pchGlobal = pchMatch ; // point to start of match
} while ( memcmp( pchGlobal // break out if name matches
, szNullDriver // exactly
, sizeof szNullDriver - 1) != 0);
// run the chain
printf( " Address Name\n") ; // column headings
for ( usOffsetDriver = OFFSETOF( pchGlobal) - 0x0a // back up to DCB start
, pddCurrent = ( PDDHEADER) ( pchGlobal - 0x0a)
, selDriver = SELECTOROF( pddCurrent->pddNext) // selector of next DCB
; ; ) {
printf( "%4X:%04X ", selDriver, usOffsetDriver);
if ( ( pddCurrent->fsAttribute & 0x8000) == 0) // if block driver
printf( "Block device, %d logical units\n"
, pddCurrent->chName[ 0]); // number of units
else // if character driver
printf( "%-8.8s\n", pddCurrent->chName);
selDriver = SELECTOROF( pddCurrent->pddNext) ; // point to next DCB
usOffsetDriver = OFFSETOF( pddCurrent->pddNext) ;
if ( usOffsetDriver == 0xffff) // if end of chain
break ; // we are done
pddNext = MAKEP( MakeSel( selDriver), usOffsetDriver) ;
ReleaseSel( SELECTOROF( pddCurrent)) ; // free previous DCB
pddCurrent = pddNext ; // age the pointer
} // loop once for each device driver
// release the last selector
ReleaseSel( SELECTOROF( pddCurrent)) ;
exit( 0) ;
}
[LISTING THREE]
/* DEVHLP.H -- for use with DosDevIOCtl and DEVHLP.SYS */
#define DevHlp_SchedClockAddr 0x00
#define DevHlp_DevDone 0x01
#define DevHlp_Yield 0x02
#define DevHlp_TCYield 0x03
#define DevHlp_Block 0x04
#define DevHlp_Run 0x05
#define DevHlp_SemRequest 0x06
#define DevHlp_SemClear 0x07
#define DevHlp_SemHandle 0x08
#define DevHlp_PushReqPacket 0x09
#define DevHlp_PullReqPacket 0x0A
#define DevHlp_PullParticular 0x0B
#define DevHlp_SortReqPacket 0x0C
#define DevHlp_AllocReqPacket 0x0D
#define DevHlp_FreeReqPacket 0x0E
#define DevHlp_QueueInit 0x0F
#define DevHlp_QueueFlush 0x10
#define DevHlp_QueueWrite 0x11
#define DevHlp_QueueRead 0x12
#define DevHlp_Lock 0x13
#define DevHlp_Unlock 0x14
#define DevHlp_PhysToVirt 0x15
#define DevHlp_VirtToPhys 0x16
#define DevHlp_PhysToUVirt 0x17
#define DevHlp_AllocPhys 0x18
#define DevHlp_FreePhys 0x19
#define DevHlp_SetROMVector 0x1A
#define DevHlp_SetIRQ 0x1B
#define DevHlp_UnSetIRQ 0x1C
#define DevHlp_SetTimer 0x1D
#define DevHlp_ResetTimer 0x1E
#define DevHlp_MonitorCreate 0x1F
#define DevHlp_Register 0x20
#define DevHlp_DeRegister 0x21
#define DevHlp_MonWrite 0x22
#define DevHlp_MonFlush 0x23
#define DevHlp_GetDosVar 0x24
#define DevHlp_SendEvent 0x25
#define DevHlp_ROMCritSection 0x26
#define DevHlp_VerifyAccess 0x27
#define DevHlp_SysTrace 0x28
#define DevHlp_AttachDD 0x2A
#define DevHlp_AllocGDTSelector 0x2D
#define DevHlp_PhysToGDTSelector 0x2E
#define DevHlp_RealToProt 0x2F
#define DevHlp_ProtToReal 0x30
#define DevHlp_EOI 0x31
#define DevHlp_UnPhysToVirt 0x32
#define DevHlp_TickCount 0x33
#define DevHlp_GetLIDEntry 0x34
#define DevHlp_FreeLIDEntry 0x35
#define DevHlp_ABIOSCall 0x36
#define DevHlp_ABIOSCommonEntry 0x37
#define DevHlp_RegisterStackUsage 0x38
#define UVirt_Exec 0
#define UVirt_ReadWrite 1
#define UVirt_Release 2
#pragma pack(1)
typedef struct {
unsigned int carry : 1;
unsigned int : 1;
unsigned int parity : 1;
unsigned int : 1;
unsigned int aux : 1;
unsigned int : 1;
unsigned int zero : 1;
unsigned int sign : 1;
unsigned int trap : 1;
unsigned int int_en : 1;
unsigned int direction : 1;
unsigned int overflow : 1;
unsigned int iopl : 2;
unsigned int nest_task : 1;
unsigned int : 1;
} FLAGS;
typedef struct {
USHORT ax,bx,cx,dx,si,di,ds,es;
FLAGS flags;
} REGS;
[Figure 1║ Invoking the PhysToUVirt DevHlp]
MOV AX, address_high ; top of 32-bit physical absolute address
MOV BX, address_low ; bottom of 32-bit physical absolute address
MOV CX, length ; count of bytes to map (0=64k)
MOV DH, request_type ; 0=code, 1=data, 2=cancel
MOV DL, DevHlp_PhysToUVirt ; 17h
CALL DWORD PTR [DevHlp]
JNC ok ; carry set=error, clear=ok
; AX contains error code
ok: ; ES:BX contains virtual address
[Figure 2║ Parameters for calling DosDevIOCtl()]
USHORT DosDevIOCtl(pvData, pvParms, usFunction, usCategory, hDevice)
PVOID pvData; /* far pointer to data packet <- driver */
PVOID pvParms; /* far pointer to parameter packet -> driver */
USHORT usFunction; /* two-byte device function */
USHORT usCategory; /* two-byte device category */
HFILE hDevice; /* two-byte device handle */
[Figure 3║ The DEVHLP parameter/data packet]
typedef struct {
USHORT ax, bx, cx, dx, si, di, ds, es, flags;
} REGS;
[Figure 4║ PhysToUVirt() in C]
#define DevHlp_PhysToUVirt 0x17
typedef enum {
UVirt_Exec=0, UVirt_ReadWrite, UVirt_Release
} UVIRT_TYPE;
// turn physical address into virtual address
void far *PhysToUVirt(ULONG addr, USHORT size, UVIRT_TYPE type)
{
REGS r;
USHORT sel, ret=1;
HFILE devhlp;
r.ax = HIUSHORT(addr);
r.bx = LOUSHORT(addr);
r.cx = size;
r.si = r.di = r.ds = r.es = 0; // not used
r.dx = MAKEUSHORT(DevHlp_PhysToUVirt, type);
if ((devhlp = open("DEVHLPXX", 0)) != -1)
{
ret = DosDevIOCtl(&r, &r, 0x60, 128, devhlp);
close(devhlp);
}
// if DosDevIOCtl failed OR if DevHlp set carry flag...
if (ret || (r.flags & 1))
return NULL;
else
return MAKEP(r.es, r.bx);
}