Reputation: 11
I made this program in assembly that should receive from the terminal one file txt (where's the msg is), one file bmp and the name of that the file bmp should have (file equal to the original but with the hidden msg)!
section .data
; -----
; Define standard constants.
LF equ 10 ; line feed
NULL equ 0 ; end of string
TRUE equ 1
FALSE equ 0
EXIT_SUCCESS equ 0 ; success code
STDIN equ 0 ; standard input
STDOUT equ 1 ; standard output
STDERR equ 2 ; standard error
SYS_write equ 1; write
SYS_read equ 0 ; read
SYS_open equ 2 ; file open
SYS_close equ 3 ; file close
SYS_exit equ 60 ; terminate
SYS_creat equ 85 ; file open/create
SYS_time equ 201 ; get time
O_CREAT equ 0x40
O_TRUNC equ 0x200
O_APPEND equ 0x400
O_RDONLY equ 000000q ; read only
O_WRONLY equ 000001q ; write only
S_IRUSR equ 00400q
S_IWUSR equ 00200q
S_IXUSR equ 00100q
; -----
; Variables/constants for main.
MSGBUFF_SIZE equ 256
IMGBUFF_SIZE equ 24000
NEWBUFF_SIZE equ 24000
newLine db LF, NULL
db LF, LF, NULL
msgDesc dq 1
imgDesc dq 1
newDesc dq 1
errMsgOpen db "Error opening the file.", LF, NULL
errMsgRead db "Error reading from the file.", LF, NULL
img_url db '-----------------',0
msg_url db '-----------------',0
new_img db '-----------------',0
nullstr db '(null)',0
;offset db 1
;size db 1
; -------------------------------------------------------
section .bss
readMsgBuffer: resb MSGBUFF_SIZE
readImgBuffer: resb IMGBUFF_SIZE
readNewBuffer: resb NEWBUFF_SIZE
offset resq 1
size resq 1
; -------------------------------------------------------
section .text
global _start
_start:
mov rbp, rsp
mov rax, [rbp+8] ; argc
cmp rax, 4
jne fim
;read args
mov rax, [rbp+8*3] ;argv[1]
mov rdi, msg_url ;
call converte
mov rax, [rbp+8*4] ;argv[2]
mov rdi, img_url ;
call converte
mov rax, [rbp+8*5] ;argv[3]
mov rdi, new_img ;
call converte
;open file msg
openMsg:
mov rax, SYS_open ; file open
mov rdi, msg_url ; file name string
mov rsi, O_RDONLY ; read only access
syscall ; call the kernel
cmp rax, 0 ; check for success
jl errorOnOpen
mov qword [msgDesc], rax
;open file img
openImg:
mov rax, SYS_open ; file open
mov rdi, img_url ; file name string
mov rsi, O_RDONLY ; read only access
syscall ; call the kernel
cmp rax, 0 ; check for success
jl errorOnOpen
mov qword [imgDesc], rax
;open file new image
openNewImg:
mov rax, SYS_open ; file open
mov rdi, new_img ; file name string
mov rsi, O_APPEND ; append
syscall ; call the kernel
cmp rax, 0 ; check for success
jl errorOnOpen
mov qword [newDesc], rax
;read msg
mov rax, SYS_read
mov rdi, qword [msgDesc]
mov rsi, readMsgBuffer
mov rdx, MSGBUFF_SIZE
syscall
cmp rax, 0
jl errorOnRead
;read img
mov rax, SYS_read
mov rdi, qword [imgDesc]
mov rsi, readImgBuffer
mov rdx, IMGBUFF_SIZE
syscall
cmp rax, 0
jl errorOnRead
mov rsi, readImgBuffer
mov byte [rsi+rax], NULL
mov rdi, readImgBuffer
mov rsi, readMsgBuffer
mov byte [rsi+rax], NULL
mov r8, readMsgBuffer
call escrever
;close files
mov rax, SYS_close
mov rdi, qword [msgDesc]
syscall
mov rax, SYS_close
mov rdi, qword [imgDesc]
syscall
mov rax, SYS_close
mov rdi, qword [newDesc]
syscall
fim:
mov rsp, rbp
pop rbp
mov rax, 1
xor rbx, rbx
int 0x80
ret
errorOnOpen:
mov rdi, errMsgOpen
call printString
jmp fim
errorOnRead:
mov rdi, errMsgRead
call printString
jmp fim
escrever:
push rbp
mov rbp, rsp
push rbx
; first 10 bytes
mov rax, SYS_write ; code for write()
mov rsi, rdi ; addr of characters
mov rdi, newDesc ; file descriptor
mov rdx, 10
syscall ; system call
mov rbx, readImgBuffer
mov rdx, 0
add rbx, 10
;eax = offset
offsetBit:
cmp rdx, 4
je loop
mov r9b, byte[rbx]
add rax, r9
mov rcx, 10
mul rcx
inc rdx
jmp offsetBit
mov r9, rax
mov rax, SYS_write ; code for write()
mov rsi, rbx ; addr of characters
mov rdi, newDesc ; file descriptor
mov rdx, r9
syscall ; system call
mov r12, 0 ;count byte pixel, to jump the 4ºbit
mov r13, 0 ;size file
mov rdi, readImgBuffer ;have position of content
loop:
cmp byte [r8], NULL ;not done
je done
inc r13 ;count one byte
mov rdx, 0 ;count bit character msg
caracter:
mov sil, byte[r8] ;read one byte of the pixel
cmp rdx, 8 ;end of last bit
je loop
cmp r12, 4 ;4º byte pixel
jne continue
mov r12, 0 ;reset byte pixel
continue:
mov al, byte[rdi] ;have byte of pixel
mov cl, 10
shr al, 1
mul cl
shl sil, 1
adc al, 0
mov byte[rdi], al ;modify last bit
inc rdx ;change bit of character
inc r8 ;change byte of pixel
jmp caracter
done:
mov rdi, readImgBuffer
add rdi, r9 ; offset position
mov rax, SYS_write ; code for write()
mov rsi, rdi ; addr of characters
mov rdi, newDesc ; file descriptor newImage
mov rdx, r13
syscall
pop rbx
pop rbp
ret
global printString
printString:
push rbp
mov rbp, rsp
push rbx
; Count characters in string.
mov rbx, rdi
mov rdx, 0
strCountLoop:
cmp byte [rbx], NULL
je strCountDone
inc rdx
inc rbx
jmp strCountLoop
strCountDone:
cmp rdx, 0
je prtDone
; Call OS to output string.
mov rax, SYS_write ; code for write()
mov rsi, rdi ; addr of characters
mov rdi, STDOUT ; file descriptor
; count set above
syscall ; system call
; String printed, return to calling routine.
prtDone:
pop rbx
pop rbp
ret
converte:
push rbx
push rcx
push rdx
mov rbx, 10
xor rcx, rcx
.J1:
xor rdx, rdx
div rbx
push dx
add cl, 1
or eax, eax
jnz .J1
mov rbx, rcx
.J2:
pop ax
or al, 00110000b ; to ASCII
mov [rdi], al ; Store AL to [EDI] (EDI is a pointer to a buffer)
add rdi, 1 ; = inc edi
loop .J2 ; until there are no digits left
mov byte [rdi], 0 ; ASCIIZ terminator (0)
mov rax, rbx ; Restore Count of digits
pop rdx
pop rcx
pop rbx
ret
I run it like:
$ nasm -F dwarf -f elf64 hiddeMsg.asm
$ ld -o HideMsg hiddeMsg.o
$ ./HiddeMsg msg.txt img.bmp img_mod.bmp
and I was expecting to "generate" one image with name img_mod.bmp equal to the original (aka img.bmp) but with the msg in msg.txt hidden... But as I compile and run it doesn't show any errors but also don't do anything and I don't have any idea why?
the file msg has the text: «one text message»
the original image: img.bmp
Upvotes: 1
Views: 156
Reputation: 39191
Your program once more terminates prematurely because the very first check does not compare the argc correctly.
When your program starts (HiddeMsg msg.txt img.bmp img_mod.bmp
), the stack contains the following:
at RSP+32 argv3 pointer to 'img_mod.bmp'
at RSP+24 argv2 pointer to 'img.bmp'
at RSP+16 argv1 pointer to 'msg.txt'
at RSP+8 argv0 pointer to the program name
at RSP argc 4
Check the number of arguments:
mov rbp, rsp
mov rax, [rbp] ; argc
cmp rax, 4
jne fim
The other arguments are pointers to the file names. It's not useful to convert these pointers to their decimal representation like your program is doing with calling converte. Just store the pointers locally for later use:
mov rax, [rbp+8*2] ; argv[1]
mov [msg_url], rax
mov rax, [rbp+8*3] ; argv[2]
mov [img_url], rax
mov rax, [rbp+8*4] ; argv[3]
mov [new_img], rax
Opening the message file becomes
mov rsi, O_RDONLY
mov rdi, [msg_url]
mov rax, SYS_open
syscall
test rax, rax
js errorOnOpen
mov [msgDesc], rax
You have a mash-up in the part that reads from the message file and the bitmap file, where, for some reason, you zero-terminate both these contents that were read.
You are putting the zero for the message at the same offset as you used for the bitmap! This action will destroy 1 byte of the bitmap!
Keep reading and zeroing together so you use the correct RAX
:
mov edx, MSGBUFF_SIZE
mov rsi, readMsgBuffer
mov rdi, [msgDesc]
mov rax, SYS_read
syscall ; -> RAX
test rax, rax
js errorOnRead
mov rsi, readMsgBuffer
mov byte [rsi+rax], NULL
fim: mov rsp, rbp pop rbp mov rax, 1 xor rbx, rbx int 0x80 ret
Don't terminate your 64-bit program like this. Use the correct SYS_exit syscall
:
fim:
xor edi, edi
mov eax, SYS_exit
syscall
With this many errors you should better not insist too much on the contents of escrever. First exercise opening and closing files, and printing the message from the message file. Simpler things. Only move on once this works good...
Upvotes: 1