如何解决Nasm:在 bmp 文件中隐藏 messagem
我在汇编中制作了这个程序,它应该从终端接收一个文件 txt(msg 在哪里),一个文件 bmp 和文件 bmp 应该具有的名称(文件等于原始文件,但带有隐藏的 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.",NULL
errMsgRead db "Error reading from the file.",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,img_url ; file name string
mov rsi,0 ; check for success
jl errorOnopen
mov qword [imgDesc],rax
;open file new image
openNewImg:
mov rax,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,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,qword [imgDesc]
syscall
mov rax,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,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,rbx ; addr of characters
mov rdi,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,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
我是这样运行的:
$ nasm -F dwarf -f elf64 hiddeMsg.asm
$ ld -o HideMsg hiddeMsg.o
$ ./HiddeMsg msg.txt img.bmp img_mod.bmp
并且我期望“生成”一个名称为 img_mod.bmp 的图像等于原始图像(又名 img.bmp)但隐藏 msg.txt 中的 msg...但是当我编译并运行它时显示任何错误但也不做任何事情,我不知道为什么?
文件 msg 有文本:«one text message»
原图: img.bmp
解决方法
您的程序再次提前终止,因为第一次检查没有正确比较 argc。
当您的程序启动时 (HiddeMsg msg.txt img.bmp img_mod.bmp
),堆栈包含以下内容:
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
检查参数的数量:
mov rbp,rsp
mov rax,[rbp] ; argc
cmp rax,4
jne fim
其他参数是指向文件名的指针。将这些指针转换为它们的十进制表示形式并没有用,就像您的程序调用 converte 所做的那样。只需将指针存储在本地以备后用:
mov rax,[rbp+8*2] ; argv[1]
mov [msg_url],rax
mov rax,[rbp+8*3] ; argv[2]
mov [img_url],[rbp+8*4] ; argv[3]
mov [new_img],rax
打开消息文件变成
mov rsi,O_RDONLY
mov rdi,[msg_url]
mov rax,SYS_open
syscall
test rax,rax
js errorOnOpen
mov [msgDesc],rax
您在从消息文件和位图文件读取的部分中进行了混搭,出于某种原因,您将读取的这两个内容都以零结尾。
您将消息的零放在与用于位图的相同偏移量处!此操作将破坏位图的 1 个字节!
继续阅读并归零,以便使用正确的 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
不要像这样终止 64 位程序。使用正确的SYS_exit syscall
:
fim:
xor edi,edi
mov eax,SYS_exit
syscall
有这么多错误你最好不要过分强调escrever的内容。首先练习打开和关闭文件,并从消息文件中打印消息。更简单的事情。只有在效果良好时才继续前进......
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。