Nasm:在 bmp 文件中隐藏 messagem

Posted

技术标签:

【中文标题】Nasm:在 bmp 文件中隐藏 messagem【英文标题】:Nasm: Hide messagem in bmp file 【发布时间】:2021-01-17 22:46:04 【问题描述】:

我在汇编中制作了这个程序,它应该从终端接收一个文件 txt(味精在哪里),一个文件 bmp 和文件 bmp 应该具有的名称(文件等于原始文件,但带有隐藏的味精) !

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

我是这样运行的:

$ 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 包含以下文本:«一条短信»

原图: img.bmp

【问题讨论】:

strace ./HiddeMsg msg.txt img.bmp img_mod.bmp 或在 GDB 等调试器和单步调试器下运行时,您会看到什么?好像你 haven't done any debugging (或者没有告诉我们你发现了什么,就 SO 而言这是等价的)。此外,就minimal reproducible example而言,此代码远非最小。 @PeterCordes 我不知道如何调试 nasm 项目...从来没有在课堂上学习/完成它,据我了解,我认为老师说调试一个程序有点不同使用来自不...的程序的命令行... 在 GDB 中,starti msg.txt img.bmp img_mod.bmp 使用 args 运行它,在 _start 的第一条指令之前停止。学习使用调试器将更容易弄清楚其他所有内容,非常值得您花时间。 (并且浪费其他人的时间来询问您没有使用调试器调试过的代码,strace,甚至是调试打印函数调用。我强烈建议使用调试器,因为调试打印调用很难编写汇编) 【参考方案1】:

您的程序再次提前终止,因为第一次检查没有正确比较 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], rax

mov rax, [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 的内容过分坚持。首先练习打开和关闭文件,并从消息文件中打印消息。更简单的事情。只有在效果良好时才能继续...

【讨论】:

以上是关于Nasm:在 bmp 文件中隐藏 messagem的主要内容,如果未能解决你的问题,请参考以下文章

直接在x86硬件上显示图片(无os)

我的训练数据集中的隐藏文件使 tensorflow 返回“未知的图像文件格式。需要 JPEG、PNG、GIF、BMP 之一。”

在 JPG 图像中隐藏消息

用C或C++怎样提取出bmp图像的像素点信息值?用LSB算法做信息隐藏,位图是24位的。

NASM 和 GDB 符号:“在符号文件中找不到任何代码段。”

拓展名为bmp的图片无法显示