Skip to content

Commit

Permalink
Merge fc02489 into 2230e1d
Browse files Browse the repository at this point in the history
  • Loading branch information
dimkr authored Feb 7, 2020
2 parents 2230e1d + fc02489 commit 875d025
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 54 deletions.
6 changes: 6 additions & 0 deletions ci/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ meson configure build-$1 -Ddir_prefix=$here
ninja -C build-$1
test -n "`strace -qqe mkdir ./build-$1/test_putser 2>&1 | grep $here`"

# make sure binwalk fails to identify the payload format
test `binwalk -M ./build-$1/test_putser | grep 0x | wc -l` -eq 1

# make sure there are no compression-related strings
test -z "`strings -a ./build-$1/test_putser | grep -i -e lz -e xz -e deflate -e miniz -e zlib -e zstandard -e zstd -e huff -e rle -e copy -e license`"

# make sure there are no file descriptor leaks
valgrind -q --leak-check=full --error-exitcode=1 --malloc-fill=1 --free-fill=1 --track-fds=yes ./build-$1/test_putser

Expand Down
46 changes: 29 additions & 17 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -65,40 +65,52 @@ compression_sources = []
compression_cflags = ['-DPAPAW_XZ', '-Wno-unused-function']
compression_includes = [include_directories('xz-embedded/userspace'), include_directories('xz-embedded/linux/include/linux')]
cfg.set('COMPRESSION_CMD', '"xz", "-c", "--check=none", "--lzma2=preset=9e,dict=512KiB"')
cfg.set('OBFUSCATION', 'obfuscated = b"\\0\\0\\0\\x08\\0" + compressed[5:-2] + b"\\0\\0"')
cfg.set('DEOBFUSCATION', 'deobfuscated = b"\\3757zXZ" + obfuscated[5:-2] + b"YZ"')
cfg.set('DECOMPRESSION_CMD', '"xz", "-d"')

compression = get_option('compression')
if compression == 'lzma'
compression_cflags = ['-DPAPAW_LZMA']
compression_includes = []
cfg.set('COMPRESSION_CMD', '"xz", "-c", "--format=lzma", "--lzma1=preset=9e,dict=512KiB"')
cfg.set('OBFUSCATION', 'compressed[:5] + b"\\x08" + compressed[5:]')
cfg.set('DEOBFUSCATION', 'deobfuscated = obfuscated[:5] + obfuscated[6:]')
elif compression == 'zstd'
compression_cflags = ['-DPAPAW_ZSTD']
compression_includes = []
compression_sources += [
custom_target('zstddeclib',
input: 'zstd/contrib/single_file_decoder/zstddeclib-in.c',
output: 'zstddeclib.h',
command: [
join_paths(meson.current_source_dir(), 'zstd/contrib/single_file_decoder/combine.sh'),
'-r',
join_paths(meson.current_source_dir(), 'zstd/lib'),
'-r',
join_paths(meson.current_source_dir(), 'zstd/lib/common'),
'-r',
join_paths(meson.current_source_dir(), 'zstd/lib/decompress'),
'-o',
'@OUTPUT@',
'@INPUT@'
])
custom_target('zstddeclib_obfuscated',
input: custom_target('zstddeclib',
input: 'zstd/contrib/single_file_decoder/zstddeclib-in.c',
output: 'zstddeclib.h',
command: [
join_paths(meson.current_source_dir(), 'zstd/contrib/single_file_decoder/combine.sh'),
'-r',
join_paths(meson.current_source_dir(), 'zstd/lib'),
'-r',
join_paths(meson.current_source_dir(), 'zstd/lib/common'),
'-r',
join_paths(meson.current_source_dir(), 'zstd/lib/decompress'),
'-o',
'@OUTPUT@',
'@INPUT@'
]),
output: 'zstddeclib_obfuscated.h',
command: ['sed', 's/0xFD2FB528/0x00000008/', '@INPUT@'],
capture: true)
]
cfg.set('COMPRESSION_CMD', '"zstd", "-q", "-c", "-19", "--no-check"')
cfg.set('OBFUSCATION', 'obfuscated = b"\\x08\\0\\0\\x00" + compressed[4:]')
cfg.set('DEOBFUSCATION', 'deobfuscated = b"\\x28\\xb5\\x2f\\xfd" + obfuscated[4:]')
cfg.set('DECOMPRESSION_CMD', '"zstd", "-d"')
elif compression == 'deflate'
compression_cflags = ['-DPAPAW_DEFLATE']
compression_includes = []
cfg.set('COMPRESSION_CMD', '"python3", "-c", "import sys, zlib; sys.stdout.buffer.write(zlib.compress(open(sys.argv[1], \'rb\').read(), 9))"')
cfg.set('DECOMPRESSION_CMD', '"python3", "-c", "import sys, zlib; sys.stdout.buffer.write(zlib.decompress(sys.stdin.buffer.read()))"')
cfg.set('COMPRESSION_CMD', '"python3", "-c", "import sys, zlib; o = zlib.compressobj(9, zlib.DEFLATED, -15, 9, zlib.Z_DEFAULT_STRATEGY); sys.stdout.buffer.write(o.compress(open(sys.argv[1], \'rb\').read())); sys.stdout.buffer.write(o.flush())"')
cfg.set('OBFUSCATION', 'compressed')
cfg.set('DEOBFUSCATION', 'deobfuscated = obfuscated')
cfg.set('DECOMPRESSION_CMD', '"python3", "-c", "import sys, zlib; sys.stdout.buffer.write(zlib.decompress(sys.stdin.buffer.read(), -15))"')
endif

papaw = executable('papaw',
Expand Down
66 changes: 33 additions & 33 deletions papaw.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,32 +43,33 @@
# include <sys/ptrace.h>
#endif

#ifdef PAPAW_XZ
# define MINIZ_NO_ZLIB_APIS
#endif

#if defined(PAPAW_XZ) || defined(PAPAW_DEFLATE)
#ifdef PAPAW_DEFLATE
# define MINIZ_NO_ARCHIVE_APIS

# include "miniz/miniz_common.h"
static void *xalloc(size_t);
static void xfree(void *);
# include "miniz/miniz_common.h"
# undef MZ_MALLOC
# undef MZ_FREE
# define MZ_MALLOC xalloc
# undef MZ_FREE
# define MZ_FREE xfree
# undef MZ_ASSERT
# define MZ_ASSERT(x) do {} while (0)

# ifdef PAPAW_DEFLATE
# include "miniz/miniz_tinfl.c"
# endif

# include "miniz/miniz_tinfl.c"
# include "miniz/miniz.c"
#endif

#ifdef PAPAW_XZ
#elif defined(PAPAW_XZ)
# define XZ_EXTERN static

# include "xz-embedded/linux/lib/xz/xz_stream.h"
# undef HEADER_MAGIC
# define HEADER_MAGIC "\0\0\0\x08\0"
# undef FOOTER_MAGIC
# define FOOTER_MAGIC "\0\0"

# include "xz-embedded/userspace/xz_config.h"
static void *xalloc(size_t);
static void xfree(void *);
# undef kmalloc
# define kmalloc(size, flags) xalloc(size)
# undef kfree
Expand All @@ -78,9 +79,13 @@ static void xfree(void *);
# undef vfree
# define vfree xfree

# include "xz-embedded/linux/lib/xz/xz_crc32.c"
# include "xz-embedded/linux/lib/xz/xz_dec_lzma2.c"
# include "xz-embedded/linux/lib/xz/xz_dec_stream.c"
#elif defined(PAPAW_LZMA)
# include "lzma/C/LzmaDec.h"
# undef LZMA_PROPS_SIZE
# define LZMA_PROPS_SIZE 6
# include "lzma/C/LzmaDec.c"
# define LZMA_HEADER_SIZE LZMA_PROPS_SIZE + 8
#elif defined(PAPAW_ZSTD)
Expand All @@ -90,16 +95,7 @@ static void xfree(void *);
# define ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT
# define HUF_FORCE_DECOMPRESS_X1
# define MEM_FORCE_MEMORY_ACCESS 0
# include "zstddeclib.h"
#endif

#ifdef PAPAW_XZ

static uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc)
{
return (uint32_t)mz_crc32((mz_ulong)crc, buf, size);
}

# include "zstddeclib_obfuscated.h"
#endif

#if defined(PAPAW_LZMA) || defined(PAPAW_XZ) || defined(PAPAW_DEFLATE)
Expand Down Expand Up @@ -151,7 +147,7 @@ static bool extract(const int out,
const uint32_t olen)
{
#ifdef PAPAW_XZ
struct xz_buf xzbuf;
struct xz_buf xzbuf = {0};
struct xz_dec *xz;
#elif defined(PAPAW_LZMA)
SizeT inlen = clen - LZMA_HEADER_SIZE, outlen = olen;
Expand All @@ -161,8 +157,8 @@ static bool extract(const int out,
#elif defined(PAPAW_ZSTD)
unsigned char *p;
#elif defined(PAPAW_DEFLATE)
mz_stream strm = {0};
unsigned char *p;
mz_ulong outlen;
#endif
void *map;

Expand Down Expand Up @@ -190,9 +186,7 @@ static bool extract(const int out,
return false;

xzbuf.in = data;
xzbuf.in_pos = 0;
xzbuf.in_size = clen;
xzbuf.out_pos = 0;
xzbuf.out_size = olen;

xz = xz_dec_init(XZ_SINGLE, 0);
Expand All @@ -201,6 +195,8 @@ static bool extract(const int out,
return false;
}

xz_crc32_init();

if ((xz_dec_run(xz, &xzbuf) != XZ_STREAM_END) || (xzbuf.out_size != olen)) {
xz_dec_end(xz);
munmap(xzbuf.out, (size_t)olen);
Expand Down Expand Up @@ -254,15 +250,19 @@ static bool extract(const int out,
return true;
#elif defined(PAPAW_DEFLATE)
decompress:
if (mz_inflateInit2(&strm, -15) != MZ_OK)
return false;

p = mmap(NULL, (size_t)olen, PROT_WRITE, MAP_SHARED, out, 0);
if (p == MAP_FAILED)
return false;

outlen = (mz_ulong)olen;
if (mz_uncompress(p,
&outlen,
data,
(mz_ulong)clen) != MZ_OK) {
strm.next_in = data;
strm.avail_in = clen;
strm.next_out = p;
strm.avail_out = olen;

if (mz_inflate(&strm, MZ_FINISH) != MZ_STREAM_END) {
munmap(p, (size_t)olen);
return false;
}
Expand Down
10 changes: 7 additions & 3 deletions papawify.in
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,16 @@ cmd = [@COMPRESSION_CMD@]
if args.uncompressed:
cmd = ["cat"]

data = subprocess.check_output(cmd + [args.input])
compressed = subprocess.check_output(cmd + [args.input])
if args.uncompressed:
obfuscated = compressed
else:
obfuscated = @OBFUSCATION@

with open(args.stub, "rb") as infp, open(args.output, "wb") as outfp:
outfp.write(infp.read())
outfp.write(data)
outfp.write(obfuscated)
outfp.write(struct.pack(">L", os.path.getsize(args.input)))
outfp.write(struct.pack(">L", len(data)))
outfp.write(struct.pack(">L", len(obfuscated)))

os.chmod(args.output, 0o755)
4 changes: 3 additions & 1 deletion unpapawify.in
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ with open(sys.argv[1], "rb") as infp:
xz = subprocess.Popen([@DECOMPRESSION_CMD@],
stdin=subprocess.PIPE,
stdout=open(sys.argv[2], "wb"))
xz.stdin.write(data[-(size + 8):-8])
obfuscated = data[-(size + 8):-8]
@DEOBFUSCATION@
xz.stdin.write(deobfuscated)
xz.stdin.close()
xz.wait()

0 comments on commit 875d025

Please sign in to comment.