mirror of https://github.com/upx/upx.git
filter 0x51 (ARM call trick, big-endian at compress time)
This commit is contained in:
parent
fa702b48e3
commit
fd2b9a6e21
|
@ -21,7 +21,8 @@ ifeq ($(firstword $(CXX)),g++)
|
|||
USE_GNUC ?= 1
|
||||
endif
|
||||
ifeq ($(USE_GNUC),1)
|
||||
CXXFLAGS += -O2 -MMD
|
||||
#CXXFLAGS += -O2 -MMD
|
||||
CXXFLAGS += -g -MMD
|
||||
CXXFLAGS += -Wall -W -Wcast-align -Wcast-qual -Wpointer-arith -Wwrite-strings -Werror
|
||||
endif
|
||||
CPPFLAGS += $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES)
|
||||
|
|
|
@ -404,21 +404,38 @@ static int s_ct32_e8e9_bswap_be(Filter *f)
|
|||
return 0;
|
||||
|
||||
|
||||
#define ARMCT_COND (((b[3] & 0x0f) == 0x0b))
|
||||
#define ARMCT_COND_le (((b[3] & 0x0f) == 0x0b))
|
||||
|
||||
static int f_ct24arm_le(Filter *f)
|
||||
{
|
||||
CT24ARM(f, ARMCT_COND, a / 4 + f->addvalue, get_le24, set_le24)
|
||||
CT24ARM(f, ARMCT_COND_le, a / 4 + f->addvalue, get_le24, set_le24)
|
||||
}
|
||||
|
||||
static int u_ct24arm_le(Filter *f)
|
||||
{
|
||||
CT24ARM(f, ARMCT_COND, 0 - a / 4 - f->addvalue, get_le24, set_le24)
|
||||
CT24ARM(f, ARMCT_COND_le, 0 - a / 4 - f->addvalue, get_le24, set_le24)
|
||||
}
|
||||
|
||||
static int s_ct24arm_le(Filter *f)
|
||||
{
|
||||
CT24ARM(f, ARMCT_COND, a + f->addvalue, get_le24, set_dummy)
|
||||
CT24ARM(f, ARMCT_COND_le, a + f->addvalue, get_le24, set_dummy)
|
||||
}
|
||||
|
||||
#define ARMCT_COND_be (((b[0] & 0x0f) == 0x0b))
|
||||
|
||||
static int f_ct24arm_be(Filter *f)
|
||||
{
|
||||
CT24ARM(f, ARMCT_COND_be, a / 4 + f->addvalue, get_be24, set_be24)
|
||||
}
|
||||
|
||||
static int u_ct24arm_be(Filter *f)
|
||||
{
|
||||
CT24ARM(f, ARMCT_COND_be, 0 - a / 4 - f->addvalue, get_be24, set_be24)
|
||||
}
|
||||
|
||||
static int s_ct24arm_be(Filter *f)
|
||||
{
|
||||
CT24ARM(f, ARMCT_COND_be, a + f->addvalue, get_be24, set_dummy)
|
||||
}
|
||||
|
||||
#undef CT24ARM
|
||||
|
|
|
@ -226,6 +226,7 @@ const FilterImp::FilterEntry FilterImp::filters[] = {
|
|||
|
||||
// 24-bit calltrick for arm
|
||||
{ 0x50, 8, 0x01ffffff, f_ct24arm_le, u_ct24arm_le, s_ct24arm_le },
|
||||
{ 0x51, 8, 0x01ffffff, f_ct24arm_be, u_ct24arm_be, s_ct24arm_be },
|
||||
|
||||
// 32-bit cto calltrick with jmp and jcc(swap 0x0f/0x8Y) and relative renumbering
|
||||
{ 0x80, 8, 0x00ffffff, f_ctojr32_e8e9_bswap_le, u_ctojr32_e8e9_bswap_le, s_ctojr32_e8e9_bswap_le },
|
||||
|
|
146
src/p_lx_elf.cpp
146
src/p_lx_elf.cpp
|
@ -625,53 +625,16 @@ ehdr_lebe(Elf_LE32_Ehdr *const ehdr_le, Elf_BE32_Ehdr const *const ehdr_be)
|
|||
ehdr_le->e_shstrndx = ehdr_be->e_shstrndx;
|
||||
}
|
||||
|
||||
int
|
||||
PackLinuxElf32::ARM_buildLoader(const Filter *ft, void (*fix_ehdr)(void *, void const *))
|
||||
{
|
||||
unsigned const sz_loader = sizeof(linux_elf32arm_loader);
|
||||
unsigned const sz_fold = sizeof(linux_elf32arm_fold);
|
||||
|
||||
if (this->ei_data
|
||||
== ((Elf32_Ehdr const *)linux_elf32arm_fold)->e_ident[Elf32_Ehdr::EI_DATA] ) {
|
||||
return buildLinuxLoader(linux_elf32arm_loader, sz_loader,
|
||||
linux_elf32arm_fold, sz_fold, ft );
|
||||
}
|
||||
else {
|
||||
// linux_elf32arm_loader[] is all instructions, except for two strings
|
||||
// at the end: the copyright message, and the SELinux message.
|
||||
// The copyright message begins and ends with '\n', and the SELinux
|
||||
// message ends with '\n'. So copy back to the third '\n' from the end,
|
||||
// and apply brev() only before that point.
|
||||
MemBuffer brev_loader(sz_loader);
|
||||
MemBuffer brev_fold (sz_fold);
|
||||
int nl = 0;
|
||||
int j;
|
||||
for (j= sz_loader; --j>=0; ) {
|
||||
unsigned char const c = linux_elf32arm_loader[j];
|
||||
brev_loader[j] = c;
|
||||
if ('\n'==c) {
|
||||
if (3==++nl) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
brev(brev_loader, linux_elf32arm_loader, j);
|
||||
brev(brev_fold, linux_elf32arm_fold, sz_fold);
|
||||
fix_ehdr(brev_fold.getVoidPtr(), (void const *)linux_elf32arm_fold);
|
||||
return buildLinuxLoader(brev_loader, sz_loader, brev_fold, sz_fold, ft);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
PackLinuxElf32armBe::buildLoader(Filter const *ft)
|
||||
{
|
||||
return ARM_buildLoader(ft, (void (*)(void*, const void*))ehdr_bele);
|
||||
return ARM_buildLoader(ft, true);
|
||||
}
|
||||
|
||||
int
|
||||
PackLinuxElf32armLe::buildLoader(Filter const *ft)
|
||||
{
|
||||
return ARM_buildLoader(ft, (void (*)(void*, const void*))ehdr_lebe);
|
||||
return ARM_buildLoader(ft, false);
|
||||
}
|
||||
|
||||
static const
|
||||
|
@ -1024,18 +987,20 @@ void PackLinuxElf32x86::pack1(OutputFile *fo, Filter &ft)
|
|||
generateElfHdr(fo, linux_i386elf_fold, getbrk(phdri, ehdri.e_phnum) );
|
||||
}
|
||||
|
||||
void PackLinuxElf32::ARM_pack1(OutputFile *fo, void (*fix_ehdr)(void *, void const *))
|
||||
void PackLinuxElf32::ARM_pack1(OutputFile *fo, bool const isBE)
|
||||
{
|
||||
Elf32_Ehdr const *const fold = (Elf32_Ehdr const *)&linux_elf32arm_fold;
|
||||
cprElfHdr3 h3;
|
||||
// We need Elf32_Ehdr and Elf32_Phdr with the correct byte gender.
|
||||
// We need Elf32_Ehdr and Elf32_Phdr with byte gender of target.
|
||||
// The stub may have been compiled differently.
|
||||
if (this->ei_data==fold->e_ident[Elf32_Ehdr::EI_DATA]) {
|
||||
memcpy(&h3, (void const *)linux_elf32arm_fold,
|
||||
sizeof(Elf32_Ehdr) + 2*sizeof(Elf32_Phdr) );
|
||||
}
|
||||
else {
|
||||
fix_ehdr((void *)&h3.ehdr, (void const *)linux_elf32arm_fold);
|
||||
(isBE ? (void (*)(void *, void const *))ehdr_bele
|
||||
: (void (*)(void *, void const *))ehdr_lebe)
|
||||
((void *)&h3.ehdr, (void const *)linux_elf32arm_fold);
|
||||
brev((unsigned char *)&h3.phdr[0],
|
||||
sizeof(Elf32_Ehdr) + (unsigned char const *)&linux_elf32arm_fold,
|
||||
3*sizeof(Elf32_Phdr) );
|
||||
|
@ -1046,13 +1011,13 @@ void PackLinuxElf32::ARM_pack1(OutputFile *fo, void (*fix_ehdr)(void *, void con
|
|||
void PackLinuxElf32armLe::pack1(OutputFile *fo, Filter &ft)
|
||||
{
|
||||
super::pack1(fo, ft);
|
||||
ARM_pack1(fo, (void (*)(void *, void const *))ehdr_lebe);
|
||||
ARM_pack1(fo, false);
|
||||
}
|
||||
|
||||
void PackLinuxElf32armBe::pack1(OutputFile *fo, Filter &ft) // FIXME
|
||||
{
|
||||
super::pack1(fo, ft);
|
||||
ARM_pack1(fo, (void (*)(void *, void const *))ehdr_bele);
|
||||
ARM_pack1(fo, true);
|
||||
}
|
||||
|
||||
void PackLinuxElf32ppc::pack1(OutputFile *fo, Filter &ft)
|
||||
|
@ -1371,6 +1336,85 @@ void PackLinuxElf64amd::pack3(OutputFile *fo, Filter &ft)
|
|||
#include "bele.h"
|
||||
using namespace NBELE;
|
||||
|
||||
// Filter 0x50, 0x51 assume HostPolicy::isLE
|
||||
static const int *
|
||||
ARM_getFilters(bool const isBE)
|
||||
{
|
||||
static const int f50[] = { 0x50, -1 };
|
||||
static const int f51[] = { 0x51, -1 };
|
||||
if (HostPolicy::isBE ^ isBE)
|
||||
return f51;
|
||||
return f50;
|
||||
}
|
||||
|
||||
const int *
|
||||
PackLinuxElf32armBe::getFilters() const
|
||||
{
|
||||
return ARM_getFilters(true);
|
||||
}
|
||||
|
||||
const int *
|
||||
PackLinuxElf32armLe::getFilters() const
|
||||
{
|
||||
return ARM_getFilters(false);
|
||||
}
|
||||
|
||||
int
|
||||
PackLinuxElf32::ARM_buildLoader(const Filter *ft, bool const isBE)
|
||||
{
|
||||
unsigned const sz_loader = sizeof(linux_elf32arm_loader);
|
||||
unsigned const sz_fold = sizeof(linux_elf32arm_fold);
|
||||
|
||||
// Was ARM code assembled for same endianness as the target?
|
||||
bool const asm_brev = (this->ei_data
|
||||
!= ((Elf32_Ehdr const *)linux_elf32arm_fold)->e_ident[Elf32_Ehdr::EI_DATA] );
|
||||
|
||||
MemBuffer tmp_fold(sz_fold);
|
||||
memcpy(tmp_fold, linux_elf32arm_fold, sz_fold);
|
||||
|
||||
// 0xe3530050 is "cmp fid,#0x50" with fid .req r3
|
||||
if (HostPolicy::isBE ^ isBE) { // change filter 0x50 to filter 0x51
|
||||
if (HostPolicy::isBE ^ isBE ^ asm_brev) { // find 0xe3530050 big-endian
|
||||
checkPatch(NULL,0,0,0); // reset
|
||||
patch_be32(tmp_fold, sz_fold, "\xe3\x53\x00\x50", 0xe3530051);
|
||||
checkPatch(NULL,0,0,0); // reset
|
||||
}
|
||||
else { // find 0xe3530050 little-endian
|
||||
checkPatch(NULL,0,0,0); // reset
|
||||
patch_le32(tmp_fold, sz_fold, "\x50\x00\x53\xe3", 0xe3530051);
|
||||
checkPatch(NULL,0,0,0); // reset
|
||||
}
|
||||
}
|
||||
if (!asm_brev) { // was assembled to match target
|
||||
return buildLinuxLoader(linux_elf32arm_loader, sz_loader,
|
||||
tmp_fold, sz_fold, ft );
|
||||
}
|
||||
else { // was assembled brev() from target
|
||||
// linux_elf32arm_loader[] is all instructions, except for two strings
|
||||
// at the end: the copyright message, and the SELinux message.
|
||||
// The copyright message begins and ends with '\n', and the SELinux
|
||||
// message ends with '\n'. So copy back to the third '\n' from the end,
|
||||
// and apply brev() only before that point.
|
||||
MemBuffer brev_loader(sz_loader);
|
||||
int nl = 0;
|
||||
int j;
|
||||
for (j= sz_loader; --j>=0; ) {
|
||||
unsigned char const c = linux_elf32arm_loader[j];
|
||||
brev_loader[j] = c;
|
||||
if ('\n'==c) {
|
||||
if (3==++nl) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
brev(brev_loader, linux_elf32arm_loader, j);
|
||||
(isBE ? (void (*)(void *, void const *))ehdr_bele
|
||||
: (void (*)(void *, void const *))ehdr_lebe)
|
||||
(tmp_fold.getVoidPtr(), (void const *)linux_elf32arm_fold);
|
||||
return buildLinuxLoader(brev_loader, sz_loader, tmp_fold, sz_fold, ft);
|
||||
}
|
||||
}
|
||||
|
||||
void PackLinuxElf32::ARM_pack3(OutputFile *fo, Filter &ft, bool isBE)
|
||||
{
|
||||
unsigned const hlen = sz_elf_hdrs + sizeof(l_info) + sizeof(p_info);
|
||||
|
@ -1803,20 +1847,6 @@ PackLinuxElf32armBe::~PackLinuxElf32armBe()
|
|||
{
|
||||
}
|
||||
|
||||
const int *
|
||||
PackLinuxElf32armLe::getFilters() const
|
||||
{
|
||||
static const int filters[] = { 0x50, -1 };
|
||||
return filters;
|
||||
}
|
||||
|
||||
const int *
|
||||
PackLinuxElf32armBe::getFilters() const
|
||||
{
|
||||
static const int filters[] = { 0x50, -1 };
|
||||
return filters;
|
||||
}
|
||||
|
||||
unsigned
|
||||
PackLinuxElf32::elf_get_offset_from_address(unsigned const addr) const
|
||||
{
|
||||
|
|
|
@ -85,10 +85,9 @@ protected:
|
|||
|
||||
// These ARM routines are essentially common to big/little endian,
|
||||
// but the class hierarchy splits after this class.
|
||||
virtual int ARM_buildLoader(Filter const *ft,
|
||||
void (*fix_ehdr)(void *, void const *) );
|
||||
virtual void ARM_pack3(OutputFile *, Filter &, bool);
|
||||
virtual void ARM_pack1(OutputFile *, void (*)(void *, void const *));
|
||||
virtual int ARM_buildLoader(Filter const *ft, bool isBE);
|
||||
virtual void ARM_pack3(OutputFile *, Filter &, bool isBE);
|
||||
virtual void ARM_pack1(OutputFile *, bool isBE);
|
||||
|
||||
virtual void pack1(OutputFile *, Filter &); // generate executable header
|
||||
virtual void pack2(OutputFile *, Filter &); // append compressed data
|
||||
|
|
Loading…
Reference in New Issue