flat assembler
Message board for the users of flat assembler.

Index > DOS > File shredder

Author
Thread Post new topic Reply to topic
Fixit



Joined: 22 Nov 2012
Posts: 161
Fixit
This used to work under XP, but doesn't now. It prompts for a filename, but then it won't accept any input.

Can someone help me ?

Thanks

Code:
; SHRED.ASM Ver 1i B/W version
;
; Tasm code
; ***** FILE is NOT recoverable !!!! ****
;
; Supports Long Filenames
; Works in Win XP in a DOS box, with short or long filenames
;
; Shreds a 331 Meg file in 80 secs on an AMD K-6 475 MHz
;
; Overwrite a file with zero bytes, truncates it to zero bytes,
; set file time and date to 12:59:58 pm 1/1/80,
; renames it and then deletes it.
; Single files only. (For Safety)
;
; Use SHORT (8.3) FILENAME when file is a LFN
; Ex. C:\PROGRA~1\VERYLO~1.ASM
;
; Works across drives, handles periods in the path names
;
; Help from Stealth, Raymond, Bitrake, Rudy Weiser, Frank Kotler,
; Fauzan Mirza, Robert Redelmeier, QvasiModo, and others
.MODEL SMALL
.386
.stack 200h

.data? ; can contain ONLY un-initialized data, keeps executable small

random db 64000 dup(?)
file_name db 128 dup(?) ; DOS maximum path length
storage db 150 dup(?)

.data

handle dw ?
file_size dd ?
name_size dw ?


; Direct video writes, shows right after Version number !!
;
prompt db 13,10,13,10,9,'File Shredder Ver. 1h' ,13,10
db 13,10,9, Copyright 1996 - 2012',13,10
db 13,10,9,'IF YOU USE THIS PROGRAM, OVERWRITTEN FILES',13,10
db 13,10,9,'WILL BE GONE FOR GOOD. THIS PROGRAM CAUSES',13,10
db 13,10,9,'PERMANENT DATA LOSS. YOU HAVE BEEN WARNED!!',13,10
db 13,10,9,'Use SHORT (8.3) FILENAME when file is a LFN.',13,10
db 13,10,9,'Use full path when not in current DIR/DRIVE',13,10
db 13,10,9,'Usage: C:\PROGRA~1\FILENAME.ASM',13,10,13,10
db 13,10,9,'File name to SHRED --> $'

not_there db 13,10,13,10,13,9,'File not present.',13,10,'$'
emsg2 db 13,10,13,10,'Error moving file pointer.',13,10,'$'
emsg3 db 13,10,13,10,'Error writing to file.',13,10,'$'
done_msg db 13,10,13,10,'File has been shredded.',13,10,'$'
eraser_name db 'àáâãäåæç.',0

.code

start:
mov ah,15 ; clear the screen
int 10h
mov ah,0
int 10h

mov ax,@data
mov ds,ax
mov es,ax ; need for LFN functions
mov bx,00h ; write zeros into memory

zero_out: ; Set memory to zero
mov [random + bx],00h
inc bx
cmp bx,64000
jnz zero_out

mov dx, offset prompt
mov ah,9
int 21h

mov file_name,128 ; max characters in input
mov dx,offset file_name; get filename
mov ah,0ah ; 
;mov al,128 ; max length of string
int 21h
mov cl,[file_name + 1] ; how many bytes read in
add cl,2 ; find position after last character
mov ch,00
mov si,cx ; move count to index register
mov [name_size],cx ; save size
mov file_name[si],00 ; make into ASCII string

; Change any read-only attribute

change:
lea dx,file_name + 2
mov ax,4301h
mov bl,01h ; set attributes
;Bitfields for file attributes: (CX register)
;Bit(s) Description (Table 01420)
; 7 shareable (Novell NetWare)
; 7 pending deleted files (Novell DOS, OpenDOS)
; 6 unused
; 5 archive
; 4 directory
; 3 volume label
; execute-only (Novell NetWare)
; 2 system
; 1 hidden
; 0 read-only

mov cx,00000000b ; remove read-only attribute
int 21h

;INT 21 - Windows95 - LONG FILENAME - CREATE OR OPEN FILE
; AX = 716Ch
; BX = access mode and sharing flags (see #01782,also AX=6C00h);
; CX = attributes
; DX = action (see #01781)
; DS:SI -> ASCIZ filename

open_it:

mov ax,716Ch ; create file
xor cx,cx ; file attributes

; file access modes (bits) BX register
; 000 read-only
; 001 write-only
; 010 read-write
; 100 read-only, do not modify file's last-access time

; Bitfields for Windows95 long-name open action: DX Register
; Bit(s) Description (Table 01781)
; 0 open file (fail if file does not exist)
; 1 truncate file if it already exists (fail if file does not exist)
; 4 create new file if file does not already exist (fail if exists)
; Note: the only valid combinations of multiple flags are bits 4&0 and 4&1


mov bx,00000001b ; access mode - write only
mov dx,00000001b ; open file
lea si,file_name + 2 ; sets the file name
int 21h
mov [handle],ax ; Save file handle
jnc short get_size ; No errors, go on
no_file:
mov dx,offset not_there; Get error message
jmp error ; and go display/exit
get_size:
mov ax,4202h ; Set file pointer
mov bx,[handle] ; for this file
xor cx,cx ; relative to end of file
xor dx,dx ; offset 0 bytes
int 21h
jnc save_size
err2:
mov dx,offset emsg2 ; Get error message
jmp error ; and go display/exit

save_size:
mov word ptr [file_size],ax ; Save low word of file size
mov word ptr [file_size + 2],dx ; Save high word

mov ax,4200h ; Move file pointer
mov bx,[handle] ; for this file
xor cx,cx ; relative to beginning of file
xor dx,dx ; offset 0 bytes
int 21h
jc err2 ; Errors: go handle

next_bunch:
mov cx,64000 ; Assume 64,000 bytes or more
; left to do

sub word ptr [file_size],cx ; Is there ? - subtract it
sbb word ptr [file_size + 2],0 ; from saved file size

jae wipe ; There were 64,000 bytes or
; more left

mov cx,word ptr [file_size] ; Get number of bytes left
add cx,64000 ; back CX (undo subtraction)

wipe:
mov ah,40h ; Write file
mov bx,[handle] ; Handle
lea dx,random ; Write the random bytes
int 21h
jnc check_size ; No errors, go on

err3:
mov dx,offset emsg3 ; Get appropriate error message
jmp error ; and go display/exit

check_size:
cmp ax,cx
jnz err3
cmp ax,64000 ; Full 64,000 bytes written,
je next_bunch ; yes, go check for more
jmp SHORT $+2 ; short delay cuz sometimes
; file isn't renamed
;
mov bx,[handle] ; close file
mov ah,3eh
int 21h

trunc:

; Truncate file to zero bytes

mov ah,3ch ; truncate file to zero bytes
mov cx,0
mov dx,offset file_name + 2
int 21h

mov bx,[handle] ; close file
mov ah,3eh
int 21h

; Store the path

scan:
lea si,[file_name + 2]
xor cx,cx
mov di,si
mov cx,[name_size]

mov al,'\'
add di,cx
std ; scan from right to left
dec di
repne scasb
jnz short no_path ; No slash is present
add cx,1 ;

no_path:
mov di,offset storage
cld ; change directions and scan
rep movsb ; from left to right
mov al,00
stosb ; make path ASCIZ

; Add on eraser_name to end of storage

add_eraser:

mov cx,[name_size]
mov si,cx
lea di,storage
mov al,00 ; stops at the byte after the "00"
repnz scasb
dec di ; backup one

xor cx,cx
mov si,offset eraser_name
mov cx,9 ; # of characters
rep movsb

; Rename and delete file (LFN)

rename:
mov dx,offset file_name + 2 ; old file name
mov di,offset storage
mov ax,7156h ; LFN support
int 21h

; Change file date and time

mov ax,716Ch ; open file
xor cx,cx ; file attributes

; file access modes (bits) FOR BX Register
; 000 read-only
; 001 write-only
; 010 read-write
; 100 read-only, do not modify file's last-access time
; set bit 14 - commit file after every write operation

mov bx,00000000000000010b ; access mode (R/W)

mov dx,1 ; open file
lea si,storage ; sets the file name
int 21h
mov bx,ax ; save file handle
push bx

mov ax,5701h ; change file date
; BITS 5-10 are minutes, 11-15 are hours
mov cx,677dh ; 12:59:58 pm 110011101111101b
;
; BITS 0-4 are day, 5-8 are month, 9-15 (year - 1980)
mov dx,021h ; 1/1/80 0000000000100001b
int 21h

pop bx

;INT 21 U - DOS 4.0+ - COMMIT FILE
; AH = 6Ah
; BX = file handle

mov ah,6ah ; make sure this file is written to disk
int 21h

mov ah,3eh ; close file
int 21h

; INT 21 - Windows95 - LONG FILENAME - DELETE FILE
; AX = 7141h
; DS:DX -> ASCIZ long name of file to delete

mov dx,offset storage ; delete file
mov ax,7141h
xor si,si
int 21h
; idea from Fauzan Mirza
xor ax,ax ; Zero out file_name
mov di,offset storage + 2
mov cx,150
repnz stosb

finito:
mov ah,9
mov dx,offset done_msg
int 21h
mov ax,4c00h ; Set errorlevel to 0
int 21h
error:
mov ah,9
int 21h
mov ax,4c01h ; Set errorlevel to 1
int 21h

end start    


edit by revolution: added code tags
Post 22 Nov 2012, 20:53
View user's profile Send private message Reply with quote
Picnic



Joined: 05 May 2007
Posts: 1288
Location: Paradise Falls
Picnic
hi, i did a few quick changes and compile in fasm, at first glance it looks to work on my xp.

Code:
; SHRED.ASM Ver 1i B/W version 
; 
; Tasm code 
; ***** FILE is NOT recoverable !!!! **** 
; 
; Supports Long Filenames 
; Works in Win XP in a DOS box, with short or long filenames 
; 
; Shreds a 331 Meg file in 80 secs on an AMD K-6 475 MHz 
; 
; Overwrite a file with zero bytes, truncates it to zero bytes, 
; set file time and date to 12:59:58 pm 1/1/80, 
; renames it and then deletes it. 
; Single files only. (For Safety) 
; 
; Use SHORT (8.3) FILENAME when file is a LFN 
; Ex. C:\PROGRA~1\VERYLO~1.ASM 
; 
; Works across drives, handles periods in the path names 
; 
; Help from Stealth, Raymond, Bitrake, Rudy Weiser, Frank Kotler, 
; Fauzan Mirza, Robert Redelmeier, QvasiModo, and others 

offset equ
ptr equ

format MZ
stack 200h 
entry main:start

segment main

start:
mov ah,15 ; clear the screen
int 10h
mov ah,0
int 10h

mov ax,dataseg
mov ds,ax
mov es,ax ; need for LFN functions
mov bx,00h ; write zeros into memory

zero_out: ; Set memory to zero
mov [random + bx],00h
inc bx
cmp bx,64000
jnz zero_out

mov dx, offset prompt
mov ah,9
int 21h

mov byte [file_name],128 ; max characters in input
mov dx,offset file_name; get filename
mov ah,0ah ;
;mov al,128 ; max length of string
int 21h
mov cl,[file_name + 1] ; how many bytes read in
add cl,2 ; find position after last character
mov ch,00
mov si,cx ; move count to index register
mov [name_size],cx ; save size
mov [file_name+si],00 ; make into ASCII string

; Change any read-only attribute

change:
mov dx,file_name + 2
mov ax,4301h
mov bl,01h ; set attributes
;Bitfields for file attributes: (CX register)
;Bit(s) Description (Table 01420)
; 7 shareable (Novell NetWare)
; 7 pending deleted files (Novell DOS, OpenDOS)
; 6 unused
; 5 archive
; 4 directory
; 3 volume label
; execute-only (Novell NetWare)
; 2 system
; 1 hidden
; 0 read-only

mov cx,00000000b ; remove read-only attribute
int 21h

;INT 21 - Windows95 - LONG FILENAME - CREATE OR OPEN FILE
; AX = 716Ch
; BX = access mode and sharing flags (see #01782,also AX=6C00h);
; CX = attributes
; DX = action (see #01781)
; DS:SI -> ASCIZ filename

open_it:

mov ax,716Ch ; create file
xor cx,cx ; file attributes

; file access modes (bits) BX register
; 000 read-only
; 001 write-only
; 010 read-write
; 100 read-only, do not modify file's last-access time

; Bitfields for Windows95 long-name open action: DX Register
; Bit(s) Description (Table 01781)
; 0 open file (fail if file does not exist)
; 1 truncate file if it already exists (fail if file does not exist)
; 4 create new file if file does not already exist (fail if exists)
; Note: the only valid combinations of multiple flags are bits 4&0 and 4&1


mov bx,00000001b ; access mode - write only
mov dx,00000001b ; open file
mov si,file_name + 2 ; sets the file name
int 21h
mov [handle],ax ; Save file handle
jnc short get_size ; No errors, go on
no_file:
mov dx,offset not_there; Get error message
jmp error ; and go display/exit
get_size:
mov ax,4202h ; Set file pointer
mov bx,[handle] ; for this file
xor cx,cx ; relative to end of file
xor dx,dx ; offset 0 bytes
int 21h
jnc save_size
err2:
mov dx,offset emsg2 ; Get error message
jmp error ; and go display/exit

save_size:
mov word ptr [file_size],ax ; Save low word of file size
mov word ptr [file_size + 2],dx ; Save high word

mov ax,4200h ; Move file pointer
mov bx,[handle] ; for this file
xor cx,cx ; relative to beginning of file
xor dx,dx ; offset 0 bytes
int 21h
jc err2 ; Errors: go handle

next_bunch:
mov cx,64000 ; Assume 64,000 bytes or more
; left to do

sub word ptr [file_size],cx ; Is there ? - subtract it
sbb word ptr [file_size + 2],0 ; from saved file size

jae wipe ; There were 64,000 bytes or
; more left

mov cx,word ptr [file_size] ; Get number of bytes left
add cx,64000 ; back CX (undo subtraction)

wipe:
mov ah,40h ; Write file
mov bx,[handle] ; Handle
mov dx,random ; Write the random bytes
int 21h
jnc check_size ; No errors, go on

err3:
mov dx,offset emsg3 ; Get appropriate error message
jmp error ; and go display/exit

check_size:
cmp ax,cx
jnz err3
cmp ax,64000 ; Full 64,000 bytes written,
je next_bunch ; yes, go check for more
jmp SHORT $+2 ; short delay cuz sometimes
; file isn't renamed
;
mov bx,[handle] ; close file
mov ah,3eh
int 21h

trunc:

; Truncate file to zero bytes

mov ah,3ch ; truncate file to zero bytes
mov cx,0
mov dx,offset file_name + 2
int 21h

mov bx,[handle] ; close file
mov ah,3eh
int 21h

; Store the path

scan:
mov si,file_name + 2
xor cx,cx
mov di,si
mov cx,[name_size]

mov al,'\'
add di,cx
std ; scan from right to left
dec di
repne scasb
jnz short no_path ; No slash is present
add cx,1 ;

no_path:
mov di,offset storage
cld ; change directions and scan
rep movsb ; from left to right
mov al,00
stosb ; make path ASCIZ

; Add on eraser_name to end of storage

add_eraser:

mov cx,[name_size]
mov si,cx
mov di,storage
mov al,00 ; stops at the byte after the "00"
repnz scasb
dec di ; backup one

xor cx,cx
mov si,offset eraser_name
mov cx,9 ; # of characters
rep movsb

; Rename and delete file (LFN)

rename:
mov dx,offset file_name + 2 ; old file name
mov di,offset storage
mov ax,7156h ; LFN support
int 21h

; Change file date and time

mov ax,716Ch ; open file
xor cx,cx ; file attributes

; file access modes (bits) FOR BX Register
; 000 read-only
; 001 write-only
; 010 read-write
; 100 read-only, do not modify file's last-access time
; set bit 14 - commit file after every write operation

mov bx,00000000000000010b ; access mode (R/W)

mov dx,1 ; open file
mov si,storage ; sets the file name
int 21h
mov bx,ax ; save file handle
push bx

mov ax,5701h ; change file date
; BITS 5-10 are minutes, 11-15 are hours
mov cx,677dh ; 12:59:58 pm 110011101111101b
;
; BITS 0-4 are day, 5-8 are month, 9-15 (year - 1980)
mov dx,021h ; 1/1/80 0000000000100001b
int 21h

pop bx

;INT 21 U - DOS 4.0+ - COMMIT FILE
; AH = 6Ah
; BX = file handle

mov ah,6ah ; make sure this file is written to disk
int 21h

mov ah,3eh ; close file
int 21h

; INT 21 - Windows95 - LONG FILENAME - DELETE FILE
; AX = 7141h
; DS:DX -> ASCIZ long name of file to delete

mov dx,offset storage ; delete file
mov ax,7141h
xor si,si
int 21h
; idea from Fauzan Mirza
xor ax,ax ; Zero out file_name
mov di,offset storage + 2
mov cx,150
repnz stosb

finito:
mov ah,9
mov dx,offset done_msg
int 21h
mov ax,4c00h ; Set errorlevel to 0
int 21h
error:
mov ah,9
int 21h
mov ax,4c01h ; Set errorlevel to 1
int 21h


segment dataseg

; Direct video writes, shows right after Version number !!
;
prompt db 13,10,13,10,9,'File Shredder Ver. 1h' ,13,10
db 13,10,9, Copyright 1996 - 2012',13,10
db 13,10,9,'IF YOU USE THIS PROGRAM, OVERWRITTEN FILES',13,10
db 13,10,9,'WILL BE GONE FOR GOOD. THIS PROGRAM CAUSES',13,10
db 13,10,9,'PERMANENT DATA LOSS. YOU HAVE BEEN WARNED!!',13,10
db 13,10,9,'Use SHORT (8.3) FILENAME when file is a LFN.',13,10
db 13,10,9,'Use full path when not in current DIR/DRIVE',13,10
db 13,10,9,'Usage: C:\PROGRA~1\FILENAME.ASM',13,10,13,10
db 13,10,9,'File name to SHRED --> $'

not_there db 13,10,13,10,13,9,'File not present.',13,10,'$'
emsg2 db 13,10,13,10,'Error moving file pointer.',13,10,'$'
emsg3 db 13,10,13,10,'Error writing to file.',13,10,'$'
done_msg db 13,10,13,10,'File has been shredded.',13,10,'$'
eraser_name db 'àáâãäåæç.',0

handle dw ?
file_size dd ?
name_size dw ?

random db 64000 dup(?)
file_name db 128 dup(?) ; DOS maximum path length
storage db 150 dup(?)
    


Here are the changes:

- made data and code segment
- remove offset and ptr directive
- replace all lea with mov
- update line: mov file_name[si],00 ; make into ASCII string
- update line: mov file_name,128 ; max characters in input
Post 22 Nov 2012, 21:36
View user's profile Send private message Reply with quote
ACP



Joined: 23 Sep 2006
Posts: 204
ACP
Unless you overwrite sectors allocated to hold your file you are not erasing file content completely - even than you can't be sure everything got erased since allocated sectors could change before the erasing operation. Secondly you should repeat write operation couple of times and always flush the disk cache. Finally using DOS interface under Windows XP or newer to erase a file is a very bad idea due to critical differences in handling of memory and filesystems. Just take a peek at CreateFile() Win32 function for example.
Post 24 Nov 2012, 21:50
View user's profile Send private message Reply with quote
Fixit



Joined: 22 Nov 2012
Posts: 161
Fixit
ACP wrote:
Unless you overwrite sectors allocated to hold your file you are not erasing file content completely - even than you can't be sure everything got erased since allocated sectors could change before the erasing operation. Secondly you should repeat write operation couple of times and always flush the disk cache. Finally using DOS interface under Windows XP or newer to erase a file is a very bad idea due to critical differences in handling of memory and filesystems. Just take a peek at CreateFile() Win32 function for example.


I will look into it.

I have used file restore programs and they can't even find any file that has been erased.

Would you like me to send you the executable so you can try it ?

Andy
Post 24 Nov 2012, 23:07
View user's profile Send private message Reply with quote
rugxulo



Joined: 09 Aug 2005
Posts: 2341
Location: Usono (aka, USA)
rugxulo
IIRC, DOS delete only changes the first letter of the file name itself to 0xE5. Until further allocation and use of disk space is done, the file data is still there and can be recovered by "undelete" or similar.
Post 25 Nov 2012, 02:00
View user's profile Send private message Visit poster's website Reply with quote
ACP



Joined: 23 Sep 2006
Posts: 204
ACP
rugxulo wrote:
IIRC, DOS delete only changes the first letter of the file name itself to 0xE5. Until further allocation and use of disk space is done, the file data is still there and can be recovered by "undelete" or similar.


Exactly. In my post I've been referring to forensic class disk imaging software that analyze whole disk image - not just filesystem entries. Removing files completely from digital media is more tricky than one might think and is tightly connected with underlying filesystem, media hardware. Relaying on operating system file handling API is not the right direction in this case.

Get some good book on filesystem internals and forensic analysis to better understand the topic. However you code will work well if used for only deleting file content partially. In most cases this is more than enough for most users. For complete and safe removal you still need to do a lot more coding. At this stage at least add a loop to write random data over and over (why not add switch for controlling loop count).
Post 25 Nov 2012, 11:28
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1901
DOS386
Quote:

zero_out: ; Set memory to zero
mov [random + bx],00h
inc bx
cmp bx,64000
jnz zero_out


This looks unfinished ... is the result really random ??? Confused

Quote:
at first glance it looks to work on my xp


Write caches are your enemy when erasing. Overwriting the file data (even multiple times) only makes sense if in every pass all data is really being transfered to the lowest level (HD head) and written to the disk. Another problem is remapping of sectors. HD's and even more non-mechanical devices may remap sectors between writing sensitive data and writing wipe data. The sensitive data is impossible to find or delete using file I/O, but it is still recoverable using forensic technologies.

Solution: burn down or melt the device at at least 911F Very Happy .
Post 16 Dec 2012, 07:44
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.