patternMinor
File shredder in x86 NASM Assembly
Viewed 0 times
filex86assemblyshreddernasm
Problem
This is a file shredder utility that runs on Linux. It writes random bytes over the file contents, repeating this 48 times and calling
```
; Description : A file shredder, it reads a dword from urandom then replaces
; the file contents with it, this process is repeated 48 times
; using a different random dword on each pass. It calls fsync
; after each pass is complete to ensure that the changes are
; reflected in the disk.
;
; Build using these commands:
; nasm -f elf shredder.asm
; ld -o shredit shredder.o -m elf_i386 -s
section .data
UsagePrefix: db 'Usage: '
USAGEPREFIXLEN: equ $-UsagePrefix
UsageSuffix: db ' file_name',0ah
USAGESUFFIXLEN: equ $-UsageSuffix
UrandomPath: db '/dev/urandom',0
ErrorMsg: db 'There was an error, file NOT shredded',0ah
ERRORMSGLEN: equ $-ErrorMsg
PASSES: equ 48 ; how many passes
section .bss
UrandomFd: resd 1
Size: resd 1
RandomBuffer: resd 128
RANDOMBUFFERSIZE: equ $-RandomBuffer ; changing this breaks the code that
; calculates the number of passes
section .text
global _start
; in : eax
; what in : null-terminated string
; out : eax
; what out : length
; trashes : nothing
; description : very simple function to find the null terminator ('\0'), it uses
; the naive algorithm and avoids repne scasb because this is ~15%
; faster than repne scasb on my machine...
GetLength:
push ecx ; save caller's registers
push esi ;
mov esi,eax ; iterate using esi then sub later
xor ecx,ecx ; we are looking for the null byte
jmp .skip ; it might be the first byte
.loop:
inc esi ; count this iteration
.skip:
cmp byte [esi],cl ; check if this is the byte
jne .loop ; repeat until found
sub eax,esi ; calculate the le
sys_fsync after each pass to make sure data goes to disk.```
; Description : A file shredder, it reads a dword from urandom then replaces
; the file contents with it, this process is repeated 48 times
; using a different random dword on each pass. It calls fsync
; after each pass is complete to ensure that the changes are
; reflected in the disk.
;
; Build using these commands:
; nasm -f elf shredder.asm
; ld -o shredit shredder.o -m elf_i386 -s
section .data
UsagePrefix: db 'Usage: '
USAGEPREFIXLEN: equ $-UsagePrefix
UsageSuffix: db ' file_name',0ah
USAGESUFFIXLEN: equ $-UsageSuffix
UrandomPath: db '/dev/urandom',0
ErrorMsg: db 'There was an error, file NOT shredded',0ah
ERRORMSGLEN: equ $-ErrorMsg
PASSES: equ 48 ; how many passes
section .bss
UrandomFd: resd 1
Size: resd 1
RandomBuffer: resd 128
RANDOMBUFFERSIZE: equ $-RandomBuffer ; changing this breaks the code that
; calculates the number of passes
section .text
global _start
; in : eax
; what in : null-terminated string
; out : eax
; what out : length
; trashes : nothing
; description : very simple function to find the null terminator ('\0'), it uses
; the naive algorithm and avoids repne scasb because this is ~15%
; faster than repne scasb on my machine...
GetLength:
push ecx ; save caller's registers
push esi ;
mov esi,eax ; iterate using esi then sub later
xor ecx,ecx ; we are looking for the null byte
jmp .skip ; it might be the first byte
.loop:
inc esi ; count this iteration
.skip:
cmp byte [esi],cl ; check if this is the byte
jne .loop ; repeat until found
sub eax,esi ; calculate the le
Solution
Well, since no one else has responded, I'll turn my comments into an answer. I'm reluctant to do that as I haven't actually tried the changes I am proposing. But they do represent a review, so they allow the question to be resolved.
Hope this is helpful.
- Can the 'rewind file' code be moved down after .wholeloop? Seems like that might allow you to remove the (now redundant) sys_lseek after checking ebp.
- Have you experimented with fsync? On large files, do you get better perf with 1 call at the end, or one after each write?
- From a more utilitarian point of view, is writing random data the best way to shred a file? Seems like writing all 1s followed by all 0s might be more effective. Maybe even 01010101 followed by 10101010. I'm sure I've read articles on this that google could turn up.
- It looks like handleRemaining can also be combined with 'Overwrite with random'. If you keep the real size in edi, then
mov edx, edi; and edx, 0xffh(like you do in handleRemaining) always gets you the right size to write. Andsub edi, edxafter thejl Errorkeeps the correct remaining size in edi. You are done when edi hits zero.
Hope this is helpful.
Context
StackExchange Code Review Q#136130, answer score: 2
Revisions (0)
No revisions yet.