POC: --- BZh (Yes, just three bytes). --- `bd` is uninitialized and passed to `free`, which is potentially exploitable. Stack trace: --- [----------------------------------registers-----------------------------------] RAX: 0x0 RBX: 0x0 RCX: 0x7ffff753b154 (<__GI___libc_write+20>: cmp rax,0xfffffffffffff000) RDX: 0x19 RSI: 0x7fffffffded0 --> 0x5555555f39f6 (<bb_error_msg+326>: mov rax,QWORD PTR [rsp+0x10]) RDI: 0x7fffffffded0 --> 0x5555555f39f6 (<bb_error_msg+326>: mov rax,QWORD PTR [rsp+0x10]) RBP: 0xfffffffd RSP: 0x7fffffffe050 --> 0x0 RIP: 0x5555559a208d (<unpack_bz2_stream+1025>: mov rdi,QWORD PTR [r12+0x40]) R8 : 0x0 R9 : 0x7fffffffded0 --> 0x5555555f39f6 (<bb_error_msg+326>: mov rax,QWORD PTR [rsp+0x10]) R10: 0x0 R11: 0x246 R12: 0x400000004 R13: 0x7fffffffe1e0 --> 0x2 R14: 0x7fffffffe4f0 --> 0x0 R15: 0x0 EFLAGS: 0x10206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x5555559a207c <unpack_bz2_stream+1008>: mov rdx,QWORD PTR [rsp] 0x5555559a2080 <unpack_bz2_stream+1012>: lea rsp,[rsp+0x98] 0x5555559a2088 <unpack_bz2_stream+1020>: mov r12,QWORD PTR [rsp+0x8] => 0x5555559a208d <unpack_bz2_stream+1025>: mov rdi,QWORD PTR [r12+0x40] 0x5555559a2092 <unpack_bz2_stream+1030>: call 0x555555562ac0 <free@plt> 0x5555559a2097 <unpack_bz2_stream+1035>: mov rdi,r12 0x5555559a209a <unpack_bz2_stream+1038>: call 0x555555562ac0 <free@plt> 0x5555559a209f <unpack_bz2_stream+1043>: mov rdi,QWORD PTR [rsp+0x10] [------------------------------------stack-------------------------------------] 0000| 0x7fffffffe050 --> 0x0 0008| 0x7fffffffe058 --> 0x400000004 0016| 0x7fffffffe060 --> 0x555555d7e260 --> 0x0 0024| 0x7fffffffe068 --> 0x0 0032| 0x7fffffffe070 --> 0x7fffffffe1e0 --> 0x2 0040| 0x7fffffffe078 --> 0x7fffffffe090 --> 0x0 0048| 0x7fffffffe080 --> 0x555555d7e262 --> 0x0 0056| 0x7fffffffe088 --> 0x0 [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x00005555559a208d in dealloc_bunzip (bd=0x400000004) at archival/libarchive/decompress_bunzip2.c:764 764 free(bd->dbuf); gdb-peda$ bt #0 0x00005555559a208d in dealloc_bunzip (bd=0x400000004) at archival/libarchive/decompress_bunzip2.c:764 #1 unpack_bz2_stream (xstate=xstate@entry=0x7fffffffe1e0) at archival/libarchive/decompress_bunzip2.c:844 #2 0x000055555594065e in bbunpack (argv=0x7fffffffe4f0, unpacker=0x5555559a1c8c <unpack_bz2_stream>, make_new_name=0x55555593f964 <make_new_name_generic>, expected_ext=0x555555b7045b "bz2") at archival/bbunzip.c:126 #3 0x00005555555eda72 in run_applet_no_and_exit (applet_no=0x15, name=<optimized out>, argv=<optimized out>) at libbb/appletlib.c:997 #4 0x00005555555ee839 in run_applet_and_exit (name=0x7fffffffe75b "bunzip2", argv=0x7fffffffe4e0) at libbb/appletlib.c:1015 #5 0x00005555555eeef2 in busybox_main (argv=0x7fffffffe4e0) at libbb/appletlib.c:958 #6 run_applet_and_exit (name=0x7fffffffe74f "busyboxfull", argv=<optimized out>) at libbb/appletlib.c:1008 #7 0x00005555555ef75c in main (argc=argc@entry=0x3, argv=argv@entry=0x7fffffffe4d8) at libbb/appletlib.c:1123 #8 0x00007ffff744cb97 in __libc_start_main (main=0x5555555ef63c <main>, argc=0x3, argv=0x7fffffffe4d8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe4c8) at ../csu/libc-start.c:310 #9 0x0000555555562b4a in _start () ---
The cmdline is `~/busybox/busybox bunzip2 -f < poc`
Can't reproduce: unpack_bz2_stream() { bunzip_data *bd; ... while (1) { /* "Process one BZ... stream" loop */ jmp_buf jmpbuf; /* Setup for I/O error handling via longjmp */ i = setjmp(jmpbuf); if (i == 0) i = start_bunzip(&jmpbuf, &bd, xstate->src_fd, outbuf + 2, len); static int FAST_FUNC start_bunzip( void *jmpbuf, bunzip_data **bdp, int in_fd, const void *inbuf, int len) { bunzip_data *bd; ... /* Allocate bunzip_data. Most fields initialize to zero. */ bd = *bdp = xzalloc(i); bd->jmpbuf = jmpbuf; ... /* Ensure that file starts with "BZh['1'-'9']." */ i = get_bits(bd, 16); The above get_bits() will longjmp(*bd->jmpbuf) on short read. At which point bd is initialized properly, and free(bd) will not bomb out.