;Copyright (c) 1998,1999 by Anarchriz. All rights reserved. ; You may use parts of the code or the whole code if you credit me for it. ; There lies some hard work in it. One of the reasons I released it. ;Last modified: 09/01/99 .model tiny .stack 100h poly equ 0edb88320h ;reflected 0x04c11db7h STEPSIZE equ 1024 .data ;Messages beginMsg db 'Patcher 0.9 - Copyright (c) 1998,1999 by Anarchriz.',10,13,'$' helpMsg db ' Help:',10,13 db ' usage: patch [offset] [file1] [file2]',10,13 db ' offset - the offset where to patch',10,13 db ' file1 - the file to patch',10,13 db ' file2 - the file to use while patching',10,13 db ' when called with no parameters this help is displayed.',10,13,'$' invalidOffsetMsg db 'ERROR: the offset is no number or to long',10,13,'$' needFilesMsg db 'ERROR: I need the filenames',10,13,'$' errorHelpMsg db '> For help run the program with no parameters.',10,13,'$' closeErrorMsg db 'ERROR: Error on closing ???',10,13,'$' file1notfoundMsg db 'ERROR: file1 not found',10,13,'$' file2notfoundMsg db 'ERROR: file2 not found',10,13,'$' file1OpenErrorMsg db 'ERROR: Error on opening file1',10,13,'$' file2OpenErrorMsg db 'ERROR: Error on opening file2',10,13,'$' file1ReadErrorMsg db 'ERROR: Error while reading file1',10,13,'$' file2ReadErrorMsg db 'ERROR: Error while reading file2',10,13,'$' filesizeErrorMsg db 'ERROR: Overflow in combination of filesizes and offset',10,13,'$' moveFileErrorMsg db 'ERROR: Error while moving filepointer',10,13,'$' writeFileErrorMSg db 'ERROR: Error while writing to file1',10,13,'$' ;Variables parameterLen db (?) parameterPos dw 81h filehandle1 dw (0) filehandle2 dw (0) implantOffset dd (?) crc32 dd 0ffffffffh filesize1 dd (?) filesize2 dd (?) bufferOffset dw (?) basecrc dd (?) originalEndCrc dd (?) newEndCrc dd (?) indexValues dd (?) xorSequence db 8 dup (0) parameterBuffer db 128 dup (?) crctable dd 256 dup (?) readbuffer db STEPSIZE dup (?) dta db 128 dup (?) .code .386 start: mov ax, @data mov ds, ax call InitTable mov ah, 1ah mov dx, offset dta int 21h ;set dta address mov dx, offset beginMsg call PrintMsg ;lees offset parameter uit mov al,[es:80h] ;TO-DO : Check (if to big) mov [parameterLen],al call GetNextParameter cmp ax, 0ffffh je printHelp call ExtractOffset ;extract 32 bit offset cmp eax, 0ffffffffh je invalidOffset mov [implantOffset],eax call GetNextParameter ;get first filename cmp ax, 0ffffh je noMoreParameters mov dx, offset parameterbuffer call FindFile cmp ax, 0ffffh je file1notfound ;file1 not found mov eax, dword ptr[dta+1ah] mov [filesize1], eax mov dx, offset parameterbuffer call OpenFile cmp ax, 0ffffh je file1OpenError ;error on opening file 1 mov [filehandle1], ax call GetNextParameter ;get second filename cmp ax, 0ffffh je noMoreParameters mov dx, offset parameterbuffer call FindFile cmp ax, 0ffffh je file2notfound ;file2 not found mov eax, dword ptr[dta+1ah] mov [filesize2], eax mov dx, offset parameterbuffer call OpenFile cmp ax, 0ffffh je file2OpenError ;error on opening file 2 mov [filehandle2], ax ;check if parameter info is right mov eax, [filesize2] add eax, 4 ;correction for 4 xtra 'special' bytes mov ecx, [implantOffset] add eax, ecx jc filesizeError cmp eax, [filesize1] ja filesizeError xor eax, eax xor bx, bx mov si, offset filehandle1 mov dx, offset readbuffer ;ecx=offset cmp ecx, 0 je noNeedForCompute call ComputeCRC32 cmp ax, 0ffffh je readErrorCRC noNeedForCompute: push dword ptr[crc32] pop dword ptr[basecrc] mov eax, [implantOffset] mov si, offset filehandle1 ;si is nog wel goed eigenlijk call MoveFile ;set file pointer back to implant offset cmp eax, 0ffffffffh je moveFileErrorMain mov ecx, [filesize2] add ecx, 4 ;correction for 4 xtra 'special' bytes mov si, offset filehandle1 ;si is nog wel goed eigenlijk ;dx still pointer to readbuffer call ComputeCRC32 ;**************** move file cmp ax, 0ffffh je readErrorCRC push dword ptr[crc32] pop dword ptr[originalEndCrc] push dword ptr[basecrc] pop dword ptr[crc32] mov ecx, [filesize2] mov si, offset filehandle2 ;dx still points to readbuffer call ComputeCRC32 ;first time I read in file2 cmp ax, 0ffffh je readErrorCRC push dword ptr[crc32] pop dword ptr[newEndCrc] ;*** And now the most important part: The Reverse Algorithm *** call ComputeReverse mov eax, [implantOffset] mov si, offset filehandle1 call MoveFile cmp eax, 0ffffffffh je moveFileErrorMain xor eax, eax mov si, offset filehandle2 call MoveFile cmp eax, 0ffffffffh je moveFileErrorMain mov dx, offset readbuffer bigWriteLoop: mov si, offset filehandle2 call ReadFile cmp ax,0ffffh je readFileError mov si, offset filehandle1 ;ax is bytes to write call WriteFile cmp ax, 0ffffh je writeFileError cmp ax, STEPSIZE je bigWriteLoop mov dx, offset xorSequence mov ax, 4 call WriteFile cmp ax, 0ffffh je writeFileError closeFiles: mov si, offset filehandle1 call CloseFile cmp ax, 0ffffh je closeError mov si, offset filehandle2 call CloseFile cmp ax, 0ffffh je closeError exit: mov ax, 4c00h int 21h printHelp: mov dx, offset helpMsg call PrintMsg jmp exit invalidOffset: mov dx, offset invalidOffsetMsg call PrintMsg jmp errorExit noMoreParameters: mov dx, offset needFilesMsg call PrintMsg jmp closeFiles file1notfound: mov dx, offset file1notfoundMsg call PrintMsg jmp closeFiles file2notfound: mov dx, offset file2notfoundMsg call PrintMsg jmp closeFiles file1OpenError: mov dx, offset file1OpenErrorMsg call PrintMsg jmp closeFiles file2OpenError: mov dx, offset file2OpenErrorMsg call PrintMsg jmp closeFIles filesizeError: mov dx, offset filesizeErrorMsg call PrintMsg jmp closeFiles readErrorCrc: mov dx, offset file1ReadErrorMsg call PrintMsg jmp closeFiles readFileError: mov dx, offset file2ReadErrorMsg call PrintMsg jmp closeFiles moveFileErrorMain: mov dx, offset moveFileErrorMsg call PrintMsg jmp closeFiles writeFileError: mov dx, offset writeFileErrorMsg call PrintMsg jmp closeFiles closeError: mov dx, offset closeErrorMsg call PrintMsg jmp exit errorExit: mov dx, offset errorHelpMsg call PrintMsg jmp exit ;******************************** ;*** Compute Reverse *** ;******************************** ;Parameters: global originalEndCrc ; global newEndCrc ;Returns: in d[xorSequence+0] is the transformation message sequence ComputeReverse proc push eax push bx push di mov di, 4 computeReverseLoop: mov al, byte ptr[originalEndCrc+di-1] xor al, byte ptr[xorSequence+di+3] call GetTableEntry xor dword ptr[xorSequence+di], eax mov byte ptr[indexValues+di-1], bl dec di jnz computeReverseLoop mov eax, dword ptr[newEndCrc] xor dword ptr[xorSequence], eax mov eax, dword ptr[indexValues] xor dword ptr[xorSequence], eax pop di pop bx pop eax ComputeReverse endp ;******************************** ;* Extract 32bit Offset * ;******************************** ;ax=length para ;return eax=0ffffffffh if toLong or noNumber ; else eax=para ExtractOffset proc push edx push bx push cx cmp ax, 8 ja toLong mov bx, ax xor edx, edx xor cx, cx ExtractOffsetLus: xor eax, eax dec bx mov al, [parameterBuffer+bx] cmp al, 30h jb noNumber cmp al, 39h ja checkABCDEF and al, 00001111b jmp readyForAdd checkABCDEF: and al, 11011111b cmp al, 41h jb noNumber cmp al, 46h ja noNumber sub al, 37h readyForAdd: shl eax, cl or edx, eax add cl, 4 or bx, bx jnz ExtractOffsetLus mov eax, edx ExtractOffset_return: pop cx pop bx pop edx ret toLong: noNumber: mov eax, 0ffffffffh jmp ExtractOffset_return ExtractOffset endp ;******************************** ;* Get next parameter * ;******************************** ;return: ax=0ffffh=no parameter found; else ax=length para GetNextParameter proc push cx push di push si push ds push es cld xor cx, cx mov cl, [parameterLen] mov al, 20h mov di, [parameterPos] repe scasb ;skip spaties jcxz no_parameter dec di inc cx mov si, di repne scasb ;zoek naar spatie jcxz no_correction dec di inc cx no_correction: mov [parameterLen], cl mov [parameterPos], di sub di, si ;verschil tussen indices= lengte para mov cx, di mov di, offset parameterBuffer mov ax, ds ;/* push es pop ds push ax pop es ; xchg ds,es */ mov ax, cx ;maak kopietje van lengte para rep movsb ;copy from ds:si(psp) to es:di(buffer) mov byte ptr[es:di],0 GetNextParameter_return: pop es pop ds pop si pop di pop cx ret no_parameter: mov ax, 0ffffh jmp GetNextParameter_return GetNextParameter endp ;*** Get Table Entry *** ;Parameters: al first byte of Entry to search ;Returns: eax Entry ; bx entry number GetTableEntry proc mov bx, offset crctable-1 getTableEntry_loop: add bx, 4 ;points to crctable+k*4-1 (k:1..) cmp [bx], al jne getTableEntry_loop sub bx, 3 mov eax, [bx] sub bx, offset crctable shr bx, 2 ret GetTableEntry endp ;***************************** ;* Init Crc-Table * ;***************************** InitTable proc push eax push ebx push cx xor ebx, ebx InitTableLus: xor eax, eax mov al, bl ;generate entry mov cl, 0 entrylus: test eax, 1 jz no_topbit shr eax, 1 xor eax, poly jmp entrygoon no_topbit: shr eax, 1 entrygoon: inc cl test cl, 8 jz entrylus mov dword ptr[ebx*4 + crctable], eax inc bx test bx, 256 jz InitTableLus pop cx pop ebx pop eax ret InitTable endp ;*** Compute part of CRC-32 *** ;ds:dx=pointer buffer waarvan crc32 berekent wordt ;ax=aantal bytes die moet worden berekent ComputePartCRC32 proc push eax push ebx push cx push si mov cx, ax mov si, dx mov eax, crc32 computeLus: xor ebx, ebx xor al, [si] mov bl, al shr eax, 8 xor eax, dword ptr[4*ebx+crctable] inc si loop computeLus mov [crc32], eax ;mov [bufferOffset], si pop si pop cx pop ebx pop eax ret ComputePartCRC32 endp ;*** Compute CRC-32 *** ;Parameters: ds:dx pointer readbuffer (STEPSIZE big) ; ds:si pointer filehandle ; ecx number of bytes to read ;Returns: ax=ffffh on error ; ax=0 on no error ComputeCRC32 proc ;****** must implement pointer mover before readfile in main ****** readmore: call ReadFile cmp ax, 0ffffh je computeCRC_readerror ;ax holds read bytes cmp ecx, STEPSIZE jae computecrc ; cmp ax, 0 ; jne beginOfBuffer ; mov dx, [bufferOffset] ; beginOfBuffer: mov eax, ecx computecrc: call ComputePartCRC32 sub ecx, eax cmp ecx, 0 ja readmore jb computeCRC_readerror ;unexpected EOF xor eax, eax ;everything is right ret computeCRC_readerror: mov ax, 0ffffh ret ComputeCRC32 endp ;************************** ;*** File routines *** ;************************** ;eax=offset ; ds:si=pointer filehandle ;return eax=0ffffffffh on error MoveFile proc push cx push dx mov dx, ax shr eax, 16 mov cx, ax mov ax, 4200h mov bx, [si] int 21h jc moveFileError moveFileReturn: pop dx pop cx ret moveFileError: mov eax, 0ffffffffh jmp moveFileReturn MoveFile endp ;ds:dx=pointer filename ;return: ax<0ffffh=handle.;ax=true=open error. OpenFile proc mov ax, 3d02h int 21h jc open_error ret open_error: mov ax, 0ffffh ret OpenFile endp ;ds:dx=pointer readbuffer ; ds:si=pointer filehandle ;return ax=ax=read bytes;ax=0ffffh=read error. ReadFile proc push bx push cx mov ah, 3fh mov bx, [si] mov cx, STEPSIZE int 21h jc read_error ReadFile_return: pop cx pop bx ret read_error: mov ax, 0ffffh jmp ReadFile_return ReadFile endp ;ds:dx=pointer (write)readbuffer ; ds:si=pointer filehandle ; ax=bytes to write ;return ax=written bytes;ax=0ffffh=write error. WriteFile proc push bx push cx mov cx, ax mov ah, 40h mov bx, [si] int 21h jc write_error WriteFile_return: pop cx pop bx ret write_error: mov ax, 0ffffh jmp WriteFile_return WriteFile endp ;ds:si=pointer filehandle CloseFile proc push bx mov ah, 3eh mov bx, [si] cmp bx, 0 je doNotClose int 21h jc close_error mov word ptr[si], 0 doNotClose: xor ax,ax CloseFile_return: pop bx ret close_error: mov ax, 0ffffh jmp CloseFile_return CloseFile endp ;ds:dx=point file spec ;return: ax=ffffh -> file not found els,e ax=n/a FindFile proc push cx xor cx, cx mov ah, 4eh int 21h jc not_found FindFile_return: pop cx ret not_found: mov ax, 0ffffh jmp FindFile_return FindFile endp PrintMsg proc push ax mov ah,9 int 21h pop ax ret PrintMsg endp end start