Hello,
just tried to get some more information where this stack smashing happens.

The stack canary gets at least overwritten here:

165                             memmove(detect + n + 1, detect + n,
166                                     (j - n) * sizeof(int));

The variable detect has a size of 12.
The parameter to memove is the second element,
therefore the size parameter to memove should be <= 8.

But actually the size parameter to memove is 12,
therefore memove writes beyond the variable detect.

Attached file shows some debugging attempts.

Kind regards,
Bernhard

# 2023-07-11 bookworm/stable amd64 qemu VM

apt update
apt dist-upgrade

apt install systemd-coredump gdb rr valgrind outguess outguess-dbgsym
apt build-dep outguess



mkdir /home/benutzer/source/outguess/orig -p
cd    /home/benutzer/source/outguess/orig
apt source outguess





benutzer@debian:~$ wget -q 
https://upload.wikimedia.org/wikipedia/commons/3/3f/JPEG_example_flower.jpg
benutzer@debian:~$ echo msg1 > msg1.txt
benutzer@debian:~$ echo msg2 > msg2.txt
benutzer@debian:~$ outguess -k "key1" -d msg1.txt -E -K "key2" -D msg2.txt -p 
100 JPEG_example_flower.jpg JPEG_example_flower.steg.jpg
Initialize encoding/decoding tables
Reading JPEG_example_flower.jpg....
JPEG compression quality set to 100
Extracting usable bits:   70325 bits
Correctable message size: 17434 bits, 24.79%
Encoded 'msg1.txt': 40 bits, 5 bytes
Finding best embedding...
    0:    33(45.8%)[82.5%], bias    28(0.85), saved:    -1, total:  0.05%
    1:    28(38.9%)[70.0%], bias    25(0.89), saved:    -1, total:  0.04%
    6:    30(42.3%)[75.0%], bias    19(0.63), saved:    -1, total:  0.04%
   11:    28(38.9%)[70.0%], bias    13(0.46), saved:    -1, total:  0.04%
11, 41: Embedding data: 40 in 70325
Bits embedded: 72, changed: 28(38.9%)[70.0%], bias: 13, tot: 68673, skip: 68601
Encoded 'msg2.txt' with ECC: 96 bits, 12 bytes
Finding best embedding...
*** stack smashing detected ***: terminated
Abgebrochen (Speicherabzug geschrieben)


cd /home/benutzer/source/outguess/orig/outguess-0.4

coredumpctl list
TIME                          PID  UID  GID SIG     COREFILE EXE                
 SIZE
Tue 2023-07-11 10:00:02 CEST 1136 1000 1000 SIGABRT present  /usr/bin/outguess 
412.4K

coredumpctl gdb --debugger-argument=-q 1136

(gdb) bt
#0  __pthread_kill_implementation (threadid=<optimized out>, 
signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
#1  0x00007f83ca05bd2f in __pthread_kill_internal (signo=6, threadid=<optimized 
out>) at ./nptl/pthread_kill.c:78
#2  0x00007f83ca00cef2 in __GI_raise (sig=sig@entry=6) at 
../sysdeps/posix/raise.c:26
#3  0x00007f83c9ff7472 in __GI_abort () at ./stdlib/abort.c:79
#4  0x00007f83ca0502d0 in __libc_message (action=action@entry=do_abort, 
fmt=fmt@entry=0x7f83ca16a210 "*** %s ***: terminated\n") at 
../sysdeps/posix/libc_fatal.c:155
#5  0x00007f83ca0e8e82 in __GI___fortify_fail (msg=msg@entry=0x7f83ca16a1f8 
"stack smashing detected") at ./debug/fortify_fail.c:26
#6  0x00007f83ca0e8e60 in __stack_chk_fail () at ./debug/stack_chk_fail.c:24
#7  0x00005627c3781422 in steg_adjust_errors 
(bitmap=bitmap@entry=0x7ffda38f0c30, flags=flags@entry=8) at 
./src/outguess.c:187
#8  0x00005627c37814ba in steg_embedchunk (bitmap=bitmap@entry=0x7ffda38f0c30, 
iter=iter@entry=0x7ffda38f0670, data=0, bits=1, bits@entry=8, 
embed=embed@entry=8) at ./src/outguess.c:206
#9  0x00005627c3781aa8 in steg_embed (bitmap=bitmap@entry=0x7ffda38f0c30, 
iter=iter@entry=0x7ffda38f0670, as=as@entry=0x7ffda38f0560, 
data=data@entry=0x5627c4d96b30 "BU\026\330E\315>ۆL\260\246\203\177", 
datalen=datalen@entry=12, seed=seed@entry=0, embed=8) at ./src/outguess.c:285
#10 0x00005627c3781e44 in steg_find (bitmap=bitmap@entry=0x7ffda38f0c30, 
iter=iter@entry=0x7ffda38f0a30, as=as@entry=0x7ffda38f0810, siter=<optimized 
out>, siterstart=<optimized out>, data=data@entry=0x5627c4d96b30 
"BU\026\330E\315>ۆL\260\246\203\177", datalen=12, flags=8) at 
./src/outguess.c:444
#11 0x00005627c3782a04 in do_embed (bitmap=bitmap@entry=0x7ffda38f0c30, 
filename=filename@entry=0x7ffda38f16ec "msg2.txt", key=key@entry=0x7ffda38f0fe0 
"key2", klen=<optimized out>, cfg=cfg@entry=0x7ffda38f0c24, 
result=result@entry=0x7ffda38f0c08) at ./src/outguess.c:719
#12 0x00005627c3780d12 in main (argc=<optimized out>, argv=0x7ffda38f1488) at 
./src/outguess.c:1025

(gdb) up
#7  0x00005627c3781422 in steg_adjust_errors 
(bitmap=bitmap@entry=0x7ffda38f0c30, flags=flags@entry=8) at 
./src/outguess.c:187
187     }

(gdb) list 138, 188
138     void
139     steg_adjust_errors(bitmap *bitmap, int flags)
140     {
141             int i, j, n, many, flag;
142             int priority[ERRORBITS], detect[ERRORBITS];
143
144             many = ERRORBITS - steg_errors;
145             for (j = 0; j < many && j < steg_err_cnt; j++) {
146                     priority[j] = steg_err_buf[j];
147                     detect[j] = bitmap->detect[priority[j]];
148             }
149
150             /* Very simple sort */
151             do {
152                     for (flag = 0, i = 0; i < j - 1; i++)
153                             if (detect[i] < detect[i + 1]) {
154                                     SWAP(detect[i], detect[i+1]);
155                                     SWAP(priority[i], priority[i+1]);
156                                     flag = 1;
157                             }
158             } while (flag);
159
160             for (i = j; i < steg_err_cnt; i++) {
161                     for (n = 0; n < j; n++)
162                             if (detect[n] < bitmap->detect[steg_err_buf[i]])
163                                     break;
164                     if (n < j - 1) {
165                             memmove(detect + n + 1, detect + n,
166                                     (j - n) * sizeof(int));
167                             memmove(priority + n + 1, priority + n,
168                                     (j - n) * sizeof(int));
169                     }
170                     if (n < j) {
171                             priority[n] = steg_err_buf[i];
172                             detect[n] = bitmap->detect[steg_err_buf[i]];
173                     }
174             }
175
176             for (i = 0; i < j; i++) {
177                     if (flags & STEG_EMBED) {
178                             WRITE_BIT(bitmap->locked, i, 0);
179                             if (TEST_BIT(bitmap->bitmap, priority[i]))
180                                     WRITE_BIT(bitmap->bitmap, i, 0);
181                             else
182                                     WRITE_BIT(bitmap->bitmap, i, 1);
183                     }
184                     steg_mis--;
185                     steg_mod -= detect[i];
186             }
187     }
188








benutzer@debian:~$ valgrind outguess -k "key1" -d msg1.txt -E -K "key2" -D 
msg2.txt -p 100 JPEG_example_flower.jpg JPEG_example_flower.steg.jpg
==5915== Memcheck, a memory error detector
==5915== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==5915== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==5915== Command: outguess -k key1 -d msg1.txt -E -K key2 -D msg2.txt -p 100 
JPEG_example_flower.jpg JPEG_example_flower.steg.jpg
==5915== 
Initialize encoding/decoding tables
Reading JPEG_example_flower.jpg....
JPEG compression quality set to 100
Extracting usable bits:   70325 bits
Correctable message size: 17434 bits, 24.79%
Encoded 'msg1.txt': 40 bits, 5 bytes
Finding best embedding...
    0:    33(45.8%)[82.5%], bias    28(0.85), saved:    -1, total:  0.05%
    1:    28(38.9%)[70.0%], bias    25(0.89), saved:    -1, total:  0.04%
    6:    30(42.3%)[75.0%], bias    19(0.63), saved:    -1, total:  0.04%
   11:    28(38.9%)[70.0%], bias    13(0.46), saved:    -1, total:  0.04%
11, 41: Embedding data: 40 in 70325
Bits embedded: 72, changed: 28(38.9%)[70.0%], bias: 13, tot: 68673, skip: 68601
Encoded 'msg2.txt' with ECC: 96 bits, 12 bytes
Finding best embedding...
*** stack smashing detected ***: terminated
==5915== 
==5915== Process terminating with default action of signal 6 (SIGABRT)
==5915==    at 0x49BECCC: __pthread_kill_implementation (pthread_kill.c:44)
==5915==    by 0x496FEF1: raise (raise.c:26)
==5915==    by 0x495A471: abort (abort.c:79)
==5915==    by 0x49B32CF: __libc_message (libc_fatal.c:155)
==5915==    by 0x4A4BE81: __fortify_fail (fortify_fail.c:26)
==5915==    by 0x4A4BE5F: __stack_chk_fail (stack_chk_fail.c:24)
==5915==    by 0x10B421: steg_adjust_errors (outguess.c:187)
==5915==    by 0x10B4B9: steg_embedchunk (outguess.c:206)
==5915==    by 0x10BAA7: steg_embed (outguess.c:285)
==5915==    by 0x10BE43: steg_find (outguess.c:444)
==5915==    by 0x10CA03: do_embed (outguess.c:719)
==5915==    by 0x10AD11: main (outguess.c:1025)
==5915== 
==5915== HEAP SUMMARY:
==5915==     in use at exit: 891,416 bytes in 15 blocks
==5915==   total heap usage: 411 allocs, 396 frees, 3,261,833 bytes allocated
==5915== 
==5915== LEAK SUMMARY:
==5915==    definitely lost: 2,048 bytes in 3 blocks
==5915==    indirectly lost: 0 bytes in 0 blocks
==5915==      possibly lost: 0 bytes in 0 blocks
==5915==    still reachable: 889,368 bytes in 12 blocks
==5915==         suppressed: 0 bytes in 0 blocks
==5915== Rerun with --leak-check=full to see details of leaked memory
==5915== 
==5915== For lists of detected and suppressed errors, rerun with: -s
==5915== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Abgebrochen (Speicherabzug geschrieben)








benutzer@debian:~$ rr record outguess -k "key1" -d msg1.txt -E -K "key2" -D 
msg2.txt -p 100 JPEG_example_flower.jpg JPEG_example_flower.steg.jpg
rr: Saving execution to trace directory 
`/home/benutzer/.local/share/rr/outguess-0'.
Initialize encoding/decoding tables
Reading JPEG_example_flower.jpg....
JPEG compression quality set to 100
Extracting usable bits:   70325 bits
Correctable message size: 17434 bits, 24.79%
Encoded 'msg1.txt': 40 bits, 5 bytes
Finding best embedding...
    0:    33(45.8%)[82.5%], bias    28(0.85), saved:    -1, total:  0.05%
    1:    28(38.9%)[70.0%], bias    25(0.89), saved:    -1, total:  0.04%
    6:    30(42.3%)[75.0%], bias    19(0.63), saved:    -1, total:  0.04%
   11:    28(38.9%)[70.0%], bias    13(0.46), saved:    -1, total:  0.04%
11, 41: Embedding data: 40 in 70325
Bits embedded: 72, changed: 28(38.9%)[70.0%], bias: 13, tot: 68673, skip: 68601
Encoded 'msg2.txt' with ECC: 96 bits, 12 bytes
Finding best embedding...
*** stack smashing detected ***: terminated
Abgebrochen



cd /home/benutzer/source/outguess/orig/outguess-0.4
rr replay --debugger-option=-q outguess-0
set width 0
set pagination off
cont
b steg_adjust_errors
reverse-cont
reverse-cont
display/i $pc

(rr) stepi
0x000055771c8b112d      140     {
1: x/i $pc
=> 0x55771c8b112d <steg_adjust_errors+45>:      mov    %rax,0x58(%rsp)
(rr) x/1xg $rsp + 0x58
0x7ffc6a268be8: 0x00007fc5aac7289a
(rr) stepi
0x000055771c8b1132      140     {
1: x/i $pc
=> 0x55771c8b1132 <steg_adjust_errors+50>:      xor    %eax,%eax
(rr) x/1xg $rsp + 0x58
0x7ffc6a268be8: 0x3462b133551b0000
(rr) watch *0x7ffc6a268be8
Hardware watchpoint 2: *0x7ffc6a268be8
(rr) cont
Continuing.

Hardware watchpoint 2: *0x7ffc6a268be8

Old value = 1427832832
New value = 0
__memcpy_avx_unaligned_erms () at 
../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:376
376     ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S: Datei oder 
Verzeichnis nicht gefunden.
1: x/i $pc
=> 0x7fc5aad2c610 <__memcpy_avx_unaligned_erms+144>:    ret
(rr) bt
#0  __memcpy_avx_unaligned_erms () at 
../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:376
#1  0x000055771c8b1301 in memmove (__len=12, __src=<optimized out>, 
__dest=0x7ffc6a268be0) at 
/usr/include/x86_64-linux-gnu/bits/string_fortified.h:36
#2  steg_adjust_errors (bitmap=bitmap@entry=0x7ffc6a269470, 
flags=flags@entry=8) at ./src/outguess.c:165
#3  0x000055771c8b14ba in steg_embedchunk (bitmap=bitmap@entry=0x7ffc6a269470, 
iter=iter@entry=0x7ffc6a268eb0, data=0, bits=1, bits@entry=8, 
embed=embed@entry=8) at ./src/outguess.c:206
#4  0x000055771c8b1aa8 in steg_embed (bitmap=bitmap@entry=0x7ffc6a269470, 
iter=iter@entry=0x7ffc6a268eb0, as=as@entry=0x7ffc6a268da0, 
data=data@entry=0x55771e27fb30 "BU\026\330E\315>ۆL\260\246\305\177", 
datalen=datalen@entry=12, seed=seed@entry=0, embed=8) at ./src/outguess.c:285
#5  0x000055771c8b1e44 in steg_find (bitmap=bitmap@entry=0x7ffc6a269470, 
iter=iter@entry=0x7ffc6a269270, as=as@entry=0x7ffc6a269050, siter=<optimized 
out>, siterstart=<optimized out>, data=data@entry=0x55771e27fb30 
"BU\026\330E\315>ۆL\260\246\305\177", datalen=12, flags=8) at 
./src/outguess.c:444
#6  0x000055771c8b2a04 in do_embed (bitmap=bitmap@entry=0x7ffc6a269470, 
filename=filename@entry=0x7ffc6a26b5cd "msg2.txt", key=key@entry=0x7ffc6a269820 
"key2", klen=<optimized out>, cfg=cfg@entry=0x7ffc6a269464, 
result=result@entry=0x7ffc6a269448) at ./src/outguess.c:719
#7  0x000055771c8b0d12 in main (argc=<optimized out>, argv=0x7ffc6a269cc8) at 
./src/outguess.c:1025

(rr) up
#1  0x000055771c8b1301 in memmove (__len=12, __src=<optimized out>, 
__dest=0x7ffc6a268be0) at 
/usr/include/x86_64-linux-gnu/bits/string_fortified.h:36
warning: Source file is more recent than executable.
36        return __builtin___memmove_chk (__dest, __src, __len,
(rr) up
#2  steg_adjust_errors (bitmap=bitmap@entry=0x7ffc6a269470, 
flags=flags@entry=8) at ./src/outguess.c:165
165                             memmove(detect + n + 1, detect + n,
(rr) print detect
$1 = {0, 0, 0}
(rr) print &detect[0]
$2 = (int *) 0x7ffc6a268bdc
(rr) print &detect[1]
$3 = (int *) 0x7ffc6a268be0
(rr) print n
$4 = <optimized out>
(rr) print sizeof(detect)
$5 = 12

164                     if (n < j - 1) {
165                             memmove(detect + n + 1, detect + n,
166                                     (j - n) * sizeof(int));
167                             memmove(priority + n + 1, priority + n,
168                                     (j - n) * sizeof(int));
169                     }







cd /home/benutzer/source/outguess
cp -a orig try1
cd try1/outguess-0.4
DEB_BUILD_OPTIONS="noopt nostrip" dpkg-buildpackage -b

dpkg --purge outguess-dbgsym
dpkg -i /home/benutzer/source/outguess/try1/*.deb

rr record outguess -k "key1" -d msg1.txt -E -K "key2" -D msg2.txt -p 100 
JPEG_example_flower.jpg JPEG_example_flower.steg.jpg
rr: Saving execution to trace directory 
`/home/benutzer/.local/share/rr/outguess-1'.

cd /home/benutzer/source/outguess/try1/outguess-0.4
rr replay --debugger-option=-q outguess-1
set width 0
set pagination off
display/i $pc
cont
b steg_adjust_errors
reverse-cont
reverse-cont

Continuing.

Breakpoint 1, steg_adjust_errors (bitmap=0x7ffd2c2330d0, flags=8) at 
./src/outguess.c:140
140     {
1: x/i $pc
=> 0x55d1ce5a1518 <steg_adjust_errors+15>:      mov    %fs:0x28,%rax
(rr) stepi
0x000055d1ce5a1521      140     {
1: x/i $pc
=> 0x55d1ce5a1521 <steg_adjust_errors+24>:      mov    %rax,-0x8(%rbp)
(rr) x/1xg $rbp - 0x8
0x7ffd2c232818: 0x00007ffd2c232ad0
(rr) stepi
0x000055d1ce5a1525      140     {
1: x/i $pc
=> 0x55d1ce5a1525 <steg_adjust_errors+28>:      xor    %eax,%eax
(rr) x/1xg $rbp - 0x8
0x7ffd2c232818: 0x82be3b60206e5f00

(rr) watch *0x7ffd2c232818
Hardware watchpoint 2: *0x7ffd2c232818
(rr) cont
Continuing.

Hardware watchpoint 2: *0x7ffd2c232818

Old value = 544104192
New value = 0
__memcpy_avx_unaligned_erms () at 
../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:376
376     ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S: Datei oder 
Verzeichnis nicht gefunden.
1: x/i $pc
=> 0x7fcef07c4610 <__memcpy_avx_unaligned_erms+144>:    ret
(rr) bt
#0  __memcpy_avx_unaligned_erms () at 
../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:376
#1  0x000055d1ce5a16fc in steg_adjust_errors (bitmap=0x7ffd2c2330d0, flags=8) 
at ./src/outguess.c:165
#2  0x000055d1ce5a19cb in steg_embedchunk (bitmap=0x7ffd2c2330d0, 
iter=0x7ffd2c232ad0, data=0, bits=1, embed=8) at ./src/outguess.c:206
#3  0x000055d1ce5a1dc9 in steg_embed (bitmap=0x7ffd2c2330d0, 
iter=0x7ffd2c232ad0, as=0x7ffd2c2329c0, data=0x55d1ced53b30 
"BU\026\330E\315>ۆL\260\246\316\177", datalen=12, seed=0, embed=8) at 
./src/outguess.c:285
#4  0x000055d1ce5a24d6 in steg_find (bitmap=0x7ffd2c2330d0, 
iter=0x7ffd2c232e90, as=0x7ffd2c232c70, siter=256, siterstart=0, 
data=0x55d1ced53b30 "BU\026\330E\315>ۆL\260\246\316\177", datalen=12, flags=8) 
at ./src/outguess.c:444
#5  0x000055d1ce5a3323 in do_embed (bitmap=0x7ffd2c2330d0, 
filename=0x7ffd2c2355cd "msg2.txt", key=0x7ffd2c233480 "key2", klen=4, 
cfg=0x7ffd2c2330c4, result=0x7ffd2c2330ac) at ./src/outguess.c:719
#6  0x000055d1ce5a4089 in main (argc=2, argv=0x7ffd2c2338f8) at 
./src/outguess.c:1025
(rr) up
#1  0x000055d1ce5a16fc in steg_adjust_errors (bitmap=0x7ffd2c2330d0, flags=8) 
at ./src/outguess.c:165
165                             memmove(detect + n + 1, detect + n,
(rr) list
160             for (i = j; i < steg_err_cnt; i++) {
161                     for (n = 0; n < j; n++)
162                             if (detect[n] < bitmap->detect[steg_err_buf[i]])
163                                     break;
164                     if (n < j - 1) {
165                             memmove(detect + n + 1, detect + n,
166                                     (j - n) * sizeof(int));
167                             memmove(priority + n + 1, priority + n,
168                                     (j - n) * sizeof(int));
169                     }
(rr) print sizeof detect
$1 = 12
(rr) print detect
$2 = {0, 0, 0}
(rr) print &detect[0]
$3 = (int *) 0x7ffd2c23280c
(rr) print &detect[1]
$4 = (int *) 0x7ffd2c232810
(rr) print &detect[2]
$5 = (int *) 0x7ffd2c232814
(rr) print n
$6 = 0
(rr) print j
$7 = 3
(rr) print (j - n) * sizeof(int)
$8 = 12

Reply via email to