1
0
mirror of https://github.com/upx/upx synced 2025-09-28 19:06:07 +08:00

Detect too-short Mach_command, also be careful in recovery

fuzzing from leon.weiss AT @ruhr-uni-bochum.de
https://github.com/upx/upx/issues/875
https://github.com/upx/upx/issues/874
	modified:   p_mach.cpp
This commit is contained in:
John Reiser 2025-01-31 11:34:48 -08:00 committed by Markus F.X.J. Oberhumer
parent 7b06ba0b78
commit a49d023bd0

View File

@ -1678,6 +1678,12 @@ tribool PackMachBase<T>::canUnpack()
Mach_command const *ptr = (Mach_command const *)rawmseg; Mach_command const *ptr = (Mach_command const *)rawmseg;
for (unsigned j= 0; j < ncmds; for (unsigned j= 0; j < ncmds;
ptr = (Mach_command const *)(ptr->cmdsize + (char const *)ptr), ++j) { ptr = (Mach_command const *)(ptr->cmdsize + (char const *)ptr), ++j) {
if (headway < (int)sizeof(Mach_command)) {
char buf[200]; snprintf(buf, sizeof(buf),
"bad Mach_command[%u]{@0x%zx,+0x%x}",
j, (sizeof(mhdri) + ((char const *)ptr - (char const *)rawmseg)), headway);
throwCantPack(buf);
}
unsigned const cmd = ptr->cmd; unsigned const cmd = ptr->cmd;
unsigned const cmdsize = ptr->cmdsize; unsigned const cmdsize = ptr->cmdsize;
if (is_bad_linker_command(cmd, cmdsize, headway, lc_seg, sizeof(Addr))) { if (is_bad_linker_command(cmd, cmdsize, headway, lc_seg, sizeof(Addr))) {
@ -1769,7 +1775,8 @@ tribool PackMachBase<T>::canUnpack()
fi->seek(offLINK - bufsize, SEEK_SET); fi->seek(offLINK - bufsize, SEEK_SET);
} }
MemBuffer buf(bufsize); MemBuffer buf(bufsize);
MemBuffer buf3(bufsize); MemBuffer buf3(upx::max(bufsize, 0x1008u));
buf3.clear();
fi->readx(buf, bufsize); fi->readx(buf, bufsize);
// Do not overwrite buf[]; For scratch space, then use buf3 instead. // Do not overwrite buf[]; For scratch space, then use buf3 instead.
@ -1882,9 +1889,13 @@ tribool PackMachBase<T>::canUnpack()
unsigned const *p; unsigned const *p;
for (p = (unsigned const *)&buf3[0x1000]; p > lo; ) if (*--p) { for (p = (unsigned const *)&buf3[0x1000]; p > lo; ) if (*--p) {
overlay_offset = *(TE32 const *)p; overlay_offset = *(TE32 const *)p;
if ((unsigned)file_size < (overlay_offset + sizeof(PackHeader) + sizeof(overlay_offset)))
throwCantUnpack("file corrupted");
if ((off_t)overlay_offset < offLINK) { if ((off_t)overlay_offset < offLINK) {
overlay_offset = ((char const *)p - (char const *)lo) + overlay_offset = ((char const *)p - (char const *)lo) +
(offLINK - 0x1000) - overlay_offset + sizeof(l_info); (offLINK - 0x1000) - overlay_offset + sizeof(l_info);
if ((unsigned)file_size < (overlay_offset + sizeof(PackHeader) + sizeof(overlay_offset)))
throwCantUnpack("file corrupted");
fi->seek(overlay_offset, SEEK_SET); fi->seek(overlay_offset, SEEK_SET);
fi->readx(buf3, bufsize); fi->readx(buf3, bufsize);
if (b_ptr->sz_unc < 0x4000 if (b_ptr->sz_unc < 0x4000
@ -1985,6 +1996,12 @@ tribool PackMachBase<T>::canPack()
unsigned char const *ptr = (unsigned char const *)rawmseg; unsigned char const *ptr = (unsigned char const *)rawmseg;
for (unsigned j= 0; j < ncmds; ++j) { for (unsigned j= 0; j < ncmds; ++j) {
Mach_segment_command const *segptr = (Mach_segment_command const *)ptr; Mach_segment_command const *segptr = (Mach_segment_command const *)ptr;
if (headway < sizeof(Mach_command)) {
char buf[200]; snprintf(buf, sizeof(buf),
"bad Mach_command[%u]{@0x%zx,+0x%x}",
j, (sizeof(mhdri) + ((char const *)segptr - (char const *)rawmseg)), headway);
throwCantPack(buf);
}
unsigned const cmd = segptr->cmd &~ LC_REQ_DYLD; unsigned const cmd = segptr->cmd &~ LC_REQ_DYLD;
unsigned const cmdsize = segptr->cmdsize; unsigned const cmdsize = segptr->cmdsize;
if (is_bad_linker_command(cmd, cmdsize, headway, lc_seg, sizeof(Addr))) { if (is_bad_linker_command(cmd, cmdsize, headway, lc_seg, sizeof(Addr))) {