Line | Count | Source |
1 | | /* p_lx_sh.cpp -- |
2 | | |
3 | | This file is part of the UPX executable compressor. |
4 | | |
5 | | Copyright (C) Markus Franz Xaver Johannes Oberhumer |
6 | | Copyright (C) Laszlo Molnar |
7 | | Copyright (C) John F. Reiser |
8 | | All Rights Reserved. |
9 | | |
10 | | UPX and the UCL library are free software; you can redistribute them |
11 | | and/or modify them under the terms of the GNU General Public License as |
12 | | published by the Free Software Foundation; either version 2 of |
13 | | the License, or (at your option) any later version. |
14 | | |
15 | | This program is distributed in the hope that it will be useful, |
16 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | | GNU General Public License for more details. |
19 | | |
20 | | You should have received a copy of the GNU General Public License |
21 | | along with this program; see the file COPYING. |
22 | | If not, write to the Free Software Foundation, Inc., |
23 | | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
24 | | |
25 | | Markus F.X.J. Oberhumer Laszlo Molnar |
26 | | <markus@oberhumer.com> <ezerotven+github@gmail.com> |
27 | | |
28 | | John F. Reiser |
29 | | <jreiser@users.sourceforge.net> |
30 | | */ |
31 | | |
32 | | |
33 | | #include "conf.h" |
34 | | |
35 | | #include "file.h" |
36 | | #include "filter.h" |
37 | | #include "packer.h" |
38 | | #include "p_elf.h" |
39 | | #include "p_unix.h" |
40 | | #include "p_lx_exc.h" |
41 | | #include "p_lx_sh.h" |
42 | | |
43 | | #define PT_LOAD Elf_LE32_Phdr::PT_LOAD |
44 | | |
45 | | |
46 | | /************************************************************************* |
47 | | // |
48 | | **************************************************************************/ |
49 | | |
50 | | static const CLANG_FORMAT_DUMMY_STATEMENT |
51 | | #include "stub/i386-linux.elf.shell-entry.h" |
52 | | static const CLANG_FORMAT_DUMMY_STATEMENT |
53 | | #include "stub/i386-linux.elf.shell-fold.h" |
54 | | |
55 | | |
56 | | PackLinuxI386sh::PackLinuxI386sh(InputFile *f) : |
57 | 11.5k | super(f), o_shname(0), l_shname(0) |
58 | 11.5k | { |
59 | 11.5k | } |
60 | | |
61 | | PackLinuxI386sh::~PackLinuxI386sh() |
62 | 11.5k | { |
63 | 11.5k | } |
64 | | |
65 | | void |
66 | | PackLinuxI386sh::buildLoader(Filter const *ft) |
67 | 0 | { |
68 | 0 | unsigned const sz_fold = sizeof(stub_i386_linux_elf_shell_fold); |
69 | 0 | MemBuffer buf(sz_fold); |
70 | 0 | memcpy(buf, stub_i386_linux_elf_shell_fold, sz_fold); |
71 | |
|
72 | 0 | checkPatch(nullptr, 0, 0, 0); // reset |
73 | 0 | patch_le32(buf,sz_fold,"UPX3",l_shname); |
74 | 0 | patch_le32(buf,sz_fold,"UPX2",o_shname); |
75 | | |
76 | | // get fresh filter |
77 | 0 | Filter fold_ft = *ft; |
78 | 0 | fold_ft.init(ft->id, ft->addvalue); |
79 | 0 | int preferred_ctos[2] = { ft->cto, -1 }; |
80 | 0 | fold_ft.preferred_ctos = preferred_ctos; |
81 | | |
82 | | // filter |
83 | 0 | optimizeFilter(&fold_ft, buf, sz_fold); |
84 | 0 | unsigned fold_hdrlen = sizeof(l_info) + sizeof(Elf32_Ehdr) + |
85 | 0 | sizeof(Elf32_Phdr) * get_te16(&((Elf32_Ehdr const *)(void *)buf)->e_phnum); |
86 | 0 | if (0 == get_le32(buf + fold_hdrlen)) { |
87 | | // inconsistent SIZEOF_HEADERS in *.lds (ld, binutils) |
88 | 0 | fold_hdrlen = upx::umax(0x80u, fold_hdrlen); |
89 | 0 | } |
90 | 0 | bool success = fold_ft.filter(buf + fold_hdrlen, sz_fold - fold_hdrlen); |
91 | 0 | UNUSED(success); |
92 | |
|
93 | 0 | buildLinuxLoader( |
94 | 0 | stub_i386_linux_elf_shell_entry, sizeof(stub_i386_linux_elf_shell_entry), |
95 | 0 | buf, sz_fold, ft ); |
96 | 0 | } |
97 | | |
98 | 0 | void PackLinuxI386sh::patchLoader() { } |
99 | | |
100 | | |
101 | | bool PackLinuxI386sh::getShellName(char *buf) |
102 | 0 | { |
103 | 0 | exetype = -1; |
104 | 0 | l_shname = (int) strcspn(buf, " \t\n\v\f\r"); |
105 | 0 | buf[l_shname] = 0; |
106 | 0 | static char const *const shname[] = { // known shells that accept "-c" arg |
107 | 0 | "ash", "bash", "bsh", "csh", "ksh", "pdksh", "sh", "tcsh", "zsh", |
108 | 0 | "python", "python2", "python3", |
109 | 0 | nullptr |
110 | 0 | }; |
111 | 0 | const char *bname = strrchr(buf, '/'); |
112 | 0 | if (bname == nullptr) |
113 | 0 | return false; |
114 | 0 | for (int j = 0; nullptr != shname[j]; ++j) { |
115 | 0 | if (0 == strcmp(shname[j], bname + 1)) { |
116 | 0 | bool const s = bool(super::canPack()); |
117 | 0 | if (s) { |
118 | 0 | opt->o_unix.blocksize = blocksize = file_size; |
119 | 0 | } |
120 | 0 | unsigned size = fi->st_size(); |
121 | 0 | if (size > (125<<10)) { // 128KB but allow 3KB for environment |
122 | 0 | printWarn(fi->getName(), "Likely E2BIG for size=%u", size); |
123 | 0 | return false; |
124 | 0 | } |
125 | 0 | return s; |
126 | 0 | } |
127 | 0 | } |
128 | 0 | return false; |
129 | 0 | } |
130 | | |
131 | | |
132 | | tribool PackLinuxI386sh::canPack() |
133 | 0 | { |
134 | 0 | #if defined(__linux__) //{ |
135 | | // only compress i386sh scripts when running under Linux |
136 | 0 | char buf[512]; |
137 | |
|
138 | 0 | fi->readx(buf, sizeof(buf)); |
139 | 0 | fi->seek(0, SEEK_SET); |
140 | 0 | buf[sizeof(buf) - 1] = 0; |
141 | 0 | if (!memcmp(buf, "#!/", 3)) { // #!/bin/sh |
142 | 0 | o_shname = 2; |
143 | 0 | return getShellName(&buf[o_shname]); |
144 | 0 | } |
145 | 0 | else if (!memcmp(buf, "#! /", 4)) { // #! /bin/sh |
146 | 0 | o_shname = 3; |
147 | 0 | return getShellName(&buf[o_shname]); |
148 | 0 | } |
149 | 0 | #endif //} |
150 | 0 | return false; |
151 | 0 | } |
152 | | |
153 | | |
154 | | void |
155 | | PackLinuxI386sh::pack1(OutputFile *fo, Filter &) |
156 | 0 | { |
157 | 0 | generateElfHdr(fo, stub_i386_linux_elf_shell_fold, 0x08048000); |
158 | 0 | } |
159 | | |
160 | | off_t |
161 | | PackLinuxI386sh::pack3(OutputFile *fo, Filter &ft) |
162 | 0 | { |
163 | 0 | return elfout.phdr[0].p_filesz = super::pack3(fo,ft); |
164 | 0 | } |
165 | | |
166 | | /* vim:set ts=4 sw=4 et: */ |