diff --git a/src/compress.cpp b/src/compress.cpp index c6260523..13d4d245 100644 --- a/src/compress.cpp +++ b/src/compress.cpp @@ -106,7 +106,7 @@ int upx_compress ( const upx_bytep src, unsigned src_len, cresult->c_len = 0; #endif - if (method < 0) { + if (0) { } #if defined(WITH_LZMA) else if (M_IS_LZMA(method)) @@ -152,7 +152,7 @@ int upx_decompress ( const upx_bytep src, unsigned src_len, if (cresult && cresult->method == 0) cresult = NULL; - if (method < 0) { + if (0) { } #if defined(WITH_LZMA) else if (M_IS_LZMA(method)) @@ -165,6 +165,10 @@ int upx_decompress ( const upx_bytep src, unsigned src_len, #if defined(WITH_UCL) else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method)) r = upx_ucl_decompress(src, src_len, dst, dst_len, method, cresult); +#endif +#if defined(WITH_ZLIB) + else if (M_IS_DEFLATE(method)) + r = upx_zlib_decompress(src, src_len, dst, dst_len, method, cresult); #endif else { throwInternalError("unknown decompression method"); @@ -193,7 +197,7 @@ int upx_test_overlap ( const upx_bytep buf, unsigned src_off, unsigned overlap_overhead = src_off + src_len - *dst_len; assert((int)overlap_overhead > 0); - if (method < 0) { + if (0) { } #if defined(WITH_LZMA) else if (M_IS_LZMA(method)) diff --git a/src/linker.cpp b/src/linker.cpp index 80713f93..e5b6766e 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -130,18 +130,52 @@ ElfLinker::~ElfLinker() free(relocations); } -void ElfLinker::init(const void *pdata, int plen) +void ElfLinker::init(const void *pdata_v, int plen) { - upx_byte *i = new upx_byte[plen + 1]; - memcpy(i, pdata, plen); - input = i; - inputlen = plen; - input[plen] = 0; + const upx_byte *pdata = (const upx_byte *) pdata_v; + // decompress + if (plen >= 16 && memcmp(pdata, "UPX#", 4) == 0) + { + int method = -1; + unsigned u_len, c_len; + if (pdata[4] == M_DEFLATE) + { + method = M_DEFLATE; + u_len = get_le16(pdata + 5); + c_len = get_le16(pdata + 7); + pdata += 9; + assert(9 + c_len == (unsigned) plen); + } + else if (pdata[4] == 0 && pdata[5] == M_DEFLATE) + { + method = M_DEFLATE; + u_len = get_le32(pdata + 6); + c_len = get_le32(pdata + 10); + pdata += 14; + assert(14 + c_len == (unsigned) plen); + } + else + throwBadLoader(); + assert((unsigned) plen < u_len); + inputlen = u_len; + input = new upx_byte[inputlen + 1]; + unsigned new_len = u_len; + int r = upx_decompress(pdata, c_len, input, &new_len, method, NULL); + if (r != 0 || new_len != u_len) + throwBadLoader(); + } + else + { + inputlen = plen; + input = new upx_byte[inputlen + 1]; + memcpy(input, pdata, inputlen); + } + input[inputlen] = 0; // NUL terminate - output = new upx_byte[plen]; + output = new upx_byte[inputlen]; outputlen = 0; - int pos = find(input, plen, "Sections:", 9); + int pos = find(input, inputlen, "Sections:", 9); assert(pos != -1); char *psections = (char *) input + pos;