A heap-based buffer overflow was discovered in upx, during the variable 'bucket' points to an inaccessible address. The issue is being triggered in the function PackLinuxElf32::invert_pt_dynamic at p_lx_elf.cpp:1688.
ASAN reports:
==110358==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61600000fed9 at pc 0x00000045acc8 bp 0x7ffd88c9b020 sp 0x7ffd88c9b010
READ of size 4 at 0x61600000fed9 thread T0
#0 0x45acc7 in PackLinuxElf32::invert_pt_dynamic(N_Elf::Dyn<N_Elf::ElfITypes<LE16, LE32, LE32, LE32, LE32> > const*) /home/test/Desktop/EVAULATION/upx/src/p_lx_elf.cpp:1688#1 0x463ba5 in PackLinuxElf32::invert_pt_dynamic(N_Elf::Dyn<N_Elf::ElfITypes<LE16, LE32, LE32, LE32, LE32> > const*) /home/test/Desktop/EVAULATION/upx/src/p_lx_elf.cpp:1583#2 0x463ba5 in PackLinuxElf32::PackLinuxElf32help1(InputFile*) /home/test/Desktop/EVAULATION/upx/src/p_lx_elf.cpp:305#3 0x464e96 in PackLinuxElf32Le::PackLinuxElf32Le(InputFile*) /home/test/Desktop/EVAULATION/upx/src/p_lx_elf.h:395#4 0x464e96 in PackLinuxElf32x86::PackLinuxElf32x86(InputFile*) /home/test/Desktop/EVAULATION/upx/src/p_lx_elf.cpp:4800#5 0x464e96 in PackBSDElf32x86::PackBSDElf32x86(InputFile*) /home/test/Desktop/EVAULATION/upx/src/p_lx_elf.cpp:4817#6 0x464e96 in PackFreeBSDElf32x86::PackFreeBSDElf32x86(InputFile*) /home/test/Desktop/EVAULATION/upx/src/p_lx_elf.cpp:4828#7 0x4f337a in PackMaster::visitAllPackers(Packer* (*)(Packer*, void*), InputFile*, options_t const*, void*) /home/test/Desktop/EVAULATION/upx/src/packmast.cpp:190#8 0x4f50f9 in PackMaster::getUnpacker(InputFile*) /home/test/Desktop/EVAULATION/upx/src/packmast.cpp:248#9 0x4f521f in PackMaster::unpack(OutputFile*) /home/test/Desktop/EVAULATION/upx/src/packmast.cpp:266#10 0x52a1e6 in do_one_file(char const*, char*) /home/test/Desktop/EVAULATION/upx/src/work.cpp:160#11 0x52a69e in do_files(int, int, char**) /home/test/Desktop/EVAULATION/upx/src/work.cpp:271#12 0x403ace in main /home/test/Desktop/EVAULATION/upx/src/main.cpp:1538#13 0x7ff33c8dc82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)#14 0x404828 in _start (/home/test/Desktop/EVAULATION/upx/src/upx.out+0x404828)
0x61600000fed9 is located 1 bytes to the right of 600-byte region [0x61600000fc80,0x61600000fed8)
allocated by thread T0 here:
#0 0x7ff33d4d0602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)#1 0x42732a in MemBuffer::alloc(unsigned long long) /home/test/Desktop/EVAULATION/upx/src/mem.cpp:194
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/test/Desktop/EVAULATION/upx/src/p_lx_elf.cpp:1688 PackLinuxElf32::invert_pt_dynamic(N_Elf::Dyn<N_Elf::ElfITypes<LE16, LE32, LE32, LE32, LE32>> const*)
Shadow bytes around the buggy address:
0x0c2c7fff9f80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2c7fff9f90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2c7fff9fa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2c7fff9fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2c7fff9fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c2c7fff9fd0: 00 00 00 00 00 00 00 00 00 00 00[fa]fa fa fa fa
0x0c2c7fff9fe0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2c7fff9ff0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2c7fffa000: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2c7fffa010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2c7fffa020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Heap right redzone: fb
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
==110358==ABORTING
Verified "problem not present" in official release upx-4.0.2 of Jan.30, 2023:
$ valgrind $UPX402 -df $PoC -o /dev/null
==26280== Memcheck, a memory error detector
==26280== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==26280== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==26280== Command: /home2/upx/upx-4.0.2-amd64_linux/upx -df hbo_PackLinuxElf32invert_pt_dynamic -o /dev/null
==26280==
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2023
UPX 4.0.2 Markus Oberhumer, Laszlo Molnar & John Reiser Jan 30th 2023
File size Ratio Format Name
-------------------- ------ ----------- -----------
upx: hbo_PackLinuxElf32invert_pt_dynamic: NotPackedException: not packed by UPX
$
$ grep UPX *
## empty output: independent verification of "not packed by UPX"
$ echo $?
1 ## no matches
$
What's the problem (or question)?
A heap-based buffer overflow was discovered in upx, during the variable 'bucket' points to an inaccessible address. The issue is being triggered in the function PackLinuxElf32::invert_pt_dynamic at p_lx_elf.cpp:1688.
ASAN reports:
==110358==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61600000fed9 at pc 0x00000045acc8 bp 0x7ffd88c9b020 sp 0x7ffd88c9b010 READ of size 4 at 0x61600000fed9 thread T0 #0 0x45acc7 in PackLinuxElf32::invert_pt_dynamic(N_Elf::Dyn<N_Elf::ElfITypes<LE16, LE32, LE32, LE32, LE32> > const*) /home/test/Desktop/EVAULATION/upx/src/p_lx_elf.cpp:1688 #1 0x463ba5 in PackLinuxElf32::invert_pt_dynamic(N_Elf::Dyn<N_Elf::ElfITypes<LE16, LE32, LE32, LE32, LE32> > const*) /home/test/Desktop/EVAULATION/upx/src/p_lx_elf.cpp:1583 #2 0x463ba5 in PackLinuxElf32::PackLinuxElf32help1(InputFile*) /home/test/Desktop/EVAULATION/upx/src/p_lx_elf.cpp:305 #3 0x464e96 in PackLinuxElf32Le::PackLinuxElf32Le(InputFile*) /home/test/Desktop/EVAULATION/upx/src/p_lx_elf.h:395 #4 0x464e96 in PackLinuxElf32x86::PackLinuxElf32x86(InputFile*) /home/test/Desktop/EVAULATION/upx/src/p_lx_elf.cpp:4800 #5 0x464e96 in PackBSDElf32x86::PackBSDElf32x86(InputFile*) /home/test/Desktop/EVAULATION/upx/src/p_lx_elf.cpp:4817 #6 0x464e96 in PackFreeBSDElf32x86::PackFreeBSDElf32x86(InputFile*) /home/test/Desktop/EVAULATION/upx/src/p_lx_elf.cpp:4828 #7 0x4f337a in PackMaster::visitAllPackers(Packer* (*)(Packer*, void*), InputFile*, options_t const*, void*) /home/test/Desktop/EVAULATION/upx/src/packmast.cpp:190 #8 0x4f50f9 in PackMaster::getUnpacker(InputFile*) /home/test/Desktop/EVAULATION/upx/src/packmast.cpp:248 #9 0x4f521f in PackMaster::unpack(OutputFile*) /home/test/Desktop/EVAULATION/upx/src/packmast.cpp:266 #10 0x52a1e6 in do_one_file(char const*, char*) /home/test/Desktop/EVAULATION/upx/src/work.cpp:160 #11 0x52a69e in do_files(int, int, char**) /home/test/Desktop/EVAULATION/upx/src/work.cpp:271 #12 0x403ace in main /home/test/Desktop/EVAULATION/upx/src/main.cpp:1538 #13 0x7ff33c8dc82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) #14 0x404828 in _start (/home/test/Desktop/EVAULATION/upx/src/upx.out+0x404828) 0x61600000fed9 is located 1 bytes to the right of 600-byte region [0x61600000fc80,0x61600000fed8) allocated by thread T0 here: #0 0x7ff33d4d0602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602) #1 0x42732a in MemBuffer::alloc(unsigned long long) /home/test/Desktop/EVAULATION/upx/src/mem.cpp:194 SUMMARY: AddressSanitizer: heap-buffer-overflow /home/test/Desktop/EVAULATION/upx/src/p_lx_elf.cpp:1688 PackLinuxElf32::invert_pt_dynamic(N_Elf::Dyn<N_Elf::ElfITypes<LE16, LE32, LE32, LE32, LE32> > const*) Shadow bytes around the buggy address: 0x0c2c7fff9f80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c2c7fff9f90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c2c7fff9fa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c2c7fff9fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c2c7fff9fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x0c2c7fff9fd0: 00 00 00 00 00 00 00 00 00 00 00[fa]fa fa fa fa 0x0c2c7fff9fe0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c2c7fff9ff0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c2c7fffa000: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c2c7fffa010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c2c7fffa020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Heap right redzone: fb Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack partial redzone: f4 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe ==110358==ABORTINGThen analysis the reasons for segv by debugging:
The instruction to crash is, corresponds to the bucket [j] in the source code
mov r9d, DWORD PTR [rax+rsi*4+0x1c]The value of register rax and rsi are:
The DWORD PTR pointer to 0xa1fffd, where the 0xa20000 is a invalid address.
What should have happened?
Decompress a crafted/suspicious file.
Do you have an idea for a solution?
A boundary check is needed for loop variable 'j' because the size allocated for variable 'buckets' is limited.
How can we reproduce the issue?
upx.out -df $PoC -o /dev/nullPoc can be found here.
Please tell us details about your environment.
upx --version):Ubuntu 16.04 64-bit
Intel(R) Core(TM) i5-6200U CPU @ 2.30GHz with 8GB
same as Host
same as Host
The text was updated successfully, but these errors were encountered: