vmlinux/386 check for __ksymtab; fix unpack
This commit is contained in:
+55
-30
@@ -46,12 +46,13 @@ static const
|
|||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
PackVmlinuxI386::PackVmlinuxI386(InputFile *f) :
|
PackVmlinuxI386::PackVmlinuxI386(InputFile *f) :
|
||||||
super(f), n_ptload(0), phdri(NULL), shdri(NULL)
|
super(f), n_ptload(0), phdri(NULL), shdri(NULL), shstrtab(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PackVmlinuxI386::~PackVmlinuxI386()
|
PackVmlinuxI386::~PackVmlinuxI386()
|
||||||
{
|
{
|
||||||
|
delete [] shstrtab;
|
||||||
delete [] phdri;
|
delete [] phdri;
|
||||||
delete [] shdri;
|
delete [] shdri;
|
||||||
}
|
}
|
||||||
@@ -81,6 +82,34 @@ int PackVmlinuxI386::getStrategy(Filter &/*ft*/)
|
|||||||
return (opt->no_filter ? -3 : ((opt->filter > 0) ? -2 : 2));
|
return (opt->no_filter ? -3 : ((opt->filter > 0) ? -2 : 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Elf_LE32_Shdr const *
|
||||||
|
PackVmlinuxI386::getElfSections()
|
||||||
|
{
|
||||||
|
Elf_LE32_Shdr const *p, *shstrsec=0;
|
||||||
|
shdri = new Elf_LE32_Shdr[(unsigned) ehdri.e_shnum];
|
||||||
|
fi->seek(ehdri.e_shoff, SEEK_SET);
|
||||||
|
fi->readx(shdri, ehdri.e_shnum * sizeof(*shdri));
|
||||||
|
int j;
|
||||||
|
for (p = shdri, j= ehdri.e_shnum; --j>=0; ++p) {
|
||||||
|
if (Elf32_Shdr::SHT_STRTAB==p->sh_type
|
||||||
|
&& (p->sh_size + p->sh_offset) <= (unsigned) file_size
|
||||||
|
&& (10+ p->sh_name) <= p->sh_size // 1+ strlen(".shstrtab")
|
||||||
|
) {
|
||||||
|
delete [] shstrtab;
|
||||||
|
shstrtab = new char[1+ p->sh_size];
|
||||||
|
fi->seek(p->sh_offset, SEEK_SET);
|
||||||
|
fi->readx(shstrtab, p->sh_size);
|
||||||
|
shstrtab[p->sh_size] = '\0';
|
||||||
|
if (0==strcmp(".shstrtab", shstrtab + p->sh_name)) {
|
||||||
|
shstrsec = p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return shstrsec;
|
||||||
|
}
|
||||||
|
|
||||||
static int __acc_cdecl_qsort
|
static int __acc_cdecl_qsort
|
||||||
compare_Phdr(void const *aa, void const *bb)
|
compare_Phdr(void const *aa, void const *bb)
|
||||||
{
|
{
|
||||||
@@ -143,6 +172,22 @@ bool PackVmlinuxI386::canPack()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A Linux kernel must have a __ksymtab section. [??]
|
||||||
|
Elf_LE32_Shdr const *p, *const shstrsec = getElfSections();
|
||||||
|
if (0==shstrsec) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int j;
|
||||||
|
for (p = shdri, j= ehdri.e_shnum; --j>=0; ++p) {
|
||||||
|
if (Elf32_Shdr::SHT_PROGBITS==p->sh_type
|
||||||
|
&& 0==strcmp("__ksymtab", p->sh_name + shstrtab)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
phdri = new Elf_LE32_Phdr[(unsigned) ehdri.e_phnum];
|
phdri = new Elf_LE32_Phdr[(unsigned) ehdri.e_phnum];
|
||||||
fi->seek(ehdri.e_phoff, SEEK_SET);
|
fi->seek(ehdri.e_phoff, SEEK_SET);
|
||||||
fi->readx(phdri, ehdri.e_phnum * sizeof(*phdri));
|
fi->readx(phdri, ehdri.e_phnum * sizeof(*phdri));
|
||||||
@@ -220,6 +265,8 @@ static bool defineFilterSymbols(Linker *linker, const Filter *ft)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const
|
||||||
|
#include "stub/i386-linux.kernel.head-vmlinux.h"
|
||||||
|
|
||||||
void PackVmlinuxI386::pack(OutputFile *fo)
|
void PackVmlinuxI386::pack(OutputFile *fo)
|
||||||
{
|
{
|
||||||
@@ -284,13 +331,9 @@ void PackVmlinuxI386::pack(OutputFile *fo)
|
|||||||
shdro[1].sh_type = Elf32_Shdr::SHT_PROGBITS;
|
shdro[1].sh_type = Elf32_Shdr::SHT_PROGBITS;
|
||||||
shdro[1].sh_flags = Elf32_Shdr::SHF_ALLOC | Elf32_Shdr::SHF_EXECINSTR;
|
shdro[1].sh_flags = Elf32_Shdr::SHF_ALLOC | Elf32_Shdr::SHF_EXECINSTR;
|
||||||
shdro[1].sh_offset = fo_off;
|
shdro[1].sh_offset = fo_off;
|
||||||
shdro[1].sh_size = 1+ 4+ ph.c_len + lsize;
|
shdro[1].sh_size = sizeof(head_stack) + ph.c_len + lsize;
|
||||||
shdro[1].sh_addralign = 1;
|
shdro[1].sh_addralign = 1;
|
||||||
|
|
||||||
{
|
|
||||||
static const
|
|
||||||
#include "stub/i386-linux.kernel.head-vmlinux.h"
|
|
||||||
|
|
||||||
// ENTRY_POINT
|
// ENTRY_POINT
|
||||||
fo->write(&head_stack[0], sizeof(head_stack)-2*(1+ 4) +1);
|
fo->write(&head_stack[0], sizeof(head_stack)-2*(1+ 4) +1);
|
||||||
tmp_le32 = ehdri.e_entry; fo->write(&tmp_le32, 4);
|
tmp_le32 = ehdri.e_entry; fo->write(&tmp_le32, 4);
|
||||||
@@ -303,7 +346,6 @@ void PackVmlinuxI386::pack(OutputFile *fo)
|
|||||||
|
|
||||||
fo->write(obuf, ph.c_len); fo_off += ph.c_len;
|
fo->write(obuf, ph.c_len); fo_off += ph.c_len;
|
||||||
fo->write(loader, lsize); fo_off += lsize;
|
fo->write(loader, lsize); fo_off += lsize;
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
printf("%-13s: compressed : %8u bytes\n", getName(), ph.c_len);
|
printf("%-13s: compressed : %8u bytes\n", getName(), ph.c_len);
|
||||||
@@ -416,35 +458,18 @@ int PackVmlinuxI386::canUnpack()
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// find the .shstrtab section
|
// find the .shstrtab section
|
||||||
char shstrtab[40];
|
Elf_LE32_Shdr const *const shstrsec = getElfSections();
|
||||||
Elf_LE32_Shdr *p, *p_shstrtab=0;
|
if (0==shstrsec) {
|
||||||
shdri = new Elf_LE32_Shdr[(unsigned) ehdri.e_shnum];
|
|
||||||
fi->seek(ehdri.e_shoff, SEEK_SET);
|
|
||||||
fi->readx(shdri, ehdri.e_shnum * sizeof(*shdri));
|
|
||||||
int j;
|
|
||||||
for (p = shdri, j= ehdri.e_shnum; --j>=0; ++p) {
|
|
||||||
if (Elf32_Shdr::SHT_STRTAB==p->sh_type
|
|
||||||
&& p->sh_size <= sizeof(shstrtab)
|
|
||||||
&& (p->sh_size + p->sh_offset) <= (unsigned) file_size
|
|
||||||
&& (10+ p->sh_name) <= p->sh_size // 1+ strlen(".shstrtab")
|
|
||||||
) {
|
|
||||||
fi->seek(p->sh_offset, SEEK_SET);
|
|
||||||
fi->readx(shstrtab, p->sh_size);
|
|
||||||
if (0==strcmp(".shstrtab", shstrtab + p->sh_name)) {
|
|
||||||
p_shstrtab = p;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (0==p_shstrtab) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for .text .note .note and sane (.sh_size + .sh_offset)
|
// check for .text .note .note and sane (.sh_size + .sh_offset)
|
||||||
p_note0 = p_note1 = p_text = 0;
|
p_note0 = p_note1 = p_text = 0;
|
||||||
|
int j;
|
||||||
|
Elf_LE32_Shdr *p;
|
||||||
for (p= shdri, j= ehdri.e_shnum; --j>=0; ++p) {
|
for (p= shdri, j= ehdri.e_shnum; --j>=0; ++p) {
|
||||||
if ((unsigned)file_size < (p->sh_size + p->sh_offset)
|
if ((unsigned)file_size < (p->sh_size + p->sh_offset)
|
||||||
|| p_shstrtab->sh_size < (5+ p->sh_name) ) {
|
|| shstrsec->sh_size < (5+ p->sh_name) ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (0==strcmp(".text", shstrtab + p->sh_name)) {
|
if (0==strcmp(".text", shstrtab + p->sh_name)) {
|
||||||
@@ -491,7 +516,7 @@ void PackVmlinuxI386::unpack(OutputFile *fo)
|
|||||||
ibuf.dealloc();
|
ibuf.dealloc();
|
||||||
|
|
||||||
ph = ph_tmp;
|
ph = ph_tmp;
|
||||||
fi->seek(p_text->sh_offset, SEEK_SET);
|
fi->seek(p_text->sh_offset + sizeof(head_stack) -5, SEEK_SET);
|
||||||
fi->readx(&buf[0], 5);
|
fi->readx(&buf[0], 5);
|
||||||
if (0xE8!=buf[0] || get_le32(&buf[1]) != ph.c_len)
|
if (0xE8!=buf[0] || get_le32(&buf[1]) != ph.c_len)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ public:
|
|||||||
virtual int canUnpack();
|
virtual int canUnpack();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual Elf_LE32_Shdr const *getElfSections();
|
||||||
virtual int buildLoader(const Filter *ft);
|
virtual int buildLoader(const Filter *ft);
|
||||||
virtual Linker* newLinker() const;
|
virtual Linker* newLinker() const;
|
||||||
// virtual const upx_byte *getLoader() const;
|
// virtual const upx_byte *getLoader() const;
|
||||||
@@ -64,6 +65,7 @@ protected:
|
|||||||
unsigned sz_ptload;
|
unsigned sz_ptload;
|
||||||
Elf_LE32_Phdr *phdri; // from input file
|
Elf_LE32_Phdr *phdri; // from input file
|
||||||
Elf_LE32_Shdr *shdri; // from input file
|
Elf_LE32_Shdr *shdri; // from input file
|
||||||
|
char *shstrtab; // from input file
|
||||||
Elf_LE32_Shdr *p_text;
|
Elf_LE32_Shdr *p_text;
|
||||||
Elf_LE32_Shdr *p_note0;
|
Elf_LE32_Shdr *p_note0;
|
||||||
Elf_LE32_Shdr *p_note1;
|
Elf_LE32_Shdr *p_note1;
|
||||||
|
|||||||
Reference in New Issue
Block a user