├── modules ├── README.md ├── disassembly │ ├── asmdump.py │ └── diasm.py ├── fileoperation │ ├── filesizedump.py │ └── rename.py ├── hexdump │ └── hexdump.py ├── main.py ├── metamorfik_proeject.py └── opcodeOperation │ └── asmToOpcodeSequence.py └── samples └── penkor.dll /modules/README.md: -------------------------------------------------------------------------------- 1 | # malwareStaticFeatureExtractionFramework 2 | 3 | Static feature extraction framework for executable file. In malware analysis we need get all possible information for executable files. I this project we use some useful libraries achive tehese. We get and produce features for executable file and store into database. 4 | 5 | ### Libraries 6 | we use below libraries in this project. 7 | 8 | For disassembly operation; 9 | * Distorm3 10 | * Capstone 11 | 12 | For PE header informations; 13 | Coming... 14 | 15 | For database operations; 16 | 17 | ### Feature Set 18 | 19 | Coming... 20 | -------------------------------------------------------------------------------- /modules/disassembly/asmdump.py: -------------------------------------------------------------------------------- 1 | from __future__ import division # to float division 2 | import distorm3 # distorm disassembler library 3 | from capstone import * # capstone disassembler library 4 | import os 5 | from operator import itemgetter # to sort dictionary 6 | import collections # to comparasion 7 | 8 | 9 | def clear(folderPath, fileExtension): 10 | ''' 11 | Delete files with specific extension in given folder 12 | 13 | ''' 14 | for root, dirs, files in os.walk(folderPath): 15 | for file in files: 16 | if not file.endswith(fileExtension) : 17 | print os.path.join(root, file)+" is removed" 18 | os.remove(os.path.join(root, file)) 19 | #Disassemble(os.path.join(root, file),"32bit",False,True) 20 | 21 | def countStatisticResult(opcodeDictionary, filename): 22 | opcodeSum = sum(opcodeDictionary.values()) 23 | #print "- Total Instruction Num : "+str(opcodeSum) 24 | outfile = open("totalInstruction.txt", 'a') 25 | outfile.write(filename+" "+str(opcodeSum)+"\n") 26 | 27 | sortedOpcodeList = sorted(opcodeDictionary.items(), key=itemgetter(1),reverse=True) 28 | #print sortedOpcodeList 29 | 30 | opcodePercentList = [] 31 | 32 | for opcode, count in sortedOpcodeList: 33 | 34 | percent = float("{0:.2f}".format((100*count)/opcodeSum)) 35 | opcodePercentList.append(opcode+" "+str(count)+" "+str(percent)) 36 | 37 | outfile = open(filename+".opcode2", 'w') 38 | outfile.write('\n'.join('%s' % x for x in opcodePercentList)) 39 | 40 | 41 | def distormDisassemble(filename,code, bits, countStatisticsResult= False): 42 | # start function variables 43 | distormOpcodeDict = dict() # key = opcode, value = count 44 | distormFilename = filename+".opcode" 45 | distormOpcodeList = [] 46 | 47 | # Output file for opcodes 48 | distormFile = open(distormFilename, 'w') 49 | #distormFile.write(filename+";") 50 | 51 | # define distorm arguments 52 | offset = 0 53 | length = None 54 | 55 | if bits == '16bit': 56 | mode = distorm3.Decode16Bits 57 | elif bits == '32bit': 58 | mode = distorm3.Decode32Bits 59 | else: 60 | mode = distorm3.Decode64Bits 61 | 62 | # Decoded instruction 63 | iterable = distorm3.DecodeGenerator(offset, code, mode) 64 | 65 | for (offset, size, instruction, hexdump) in iterable: 66 | # print("%.8x: %-32s %s" % (offset, hexdump, instruction)) 67 | 68 | opcode = instruction.split(" ")[0].lower() # get opcode 69 | 70 | distormOpcodeList.append(opcode) # add opcode to List 71 | distormFile.write(opcode+",") # write opcode to file 72 | 73 | if countStatisticsResult : # count opcode value for statistics results 74 | # count opcode number 75 | if opcode in distormOpcodeDict: 76 | distormOpcodeDict[opcode] += 1 77 | else: 78 | distormOpcodeDict[opcode] = 1 79 | 80 | if countStatisticsResult : # count opcode statistics results and write them file 81 | countStatisticResult(distormOpcodeDict, filename) 82 | 83 | print filename+" is disassembled." 84 | return distormOpcodeList 85 | 86 | 87 | def capstoneDisassemble(filename,code,bits,countStatisticsResult= False): 88 | # start function variables 89 | capstoneOpcodeDict = dict() # key = opcode, value = count 90 | capstoneFilename = filename+".capstone" 91 | capstoneOpcodeList = [] 92 | 93 | # Output file for opcodes 94 | capstoneFile = open(capstoneFilename, 'w') 95 | #capstoneFile.write(filename+";") 96 | if bits == '16bit': 97 | mode = CS_MODE_16 98 | elif bits == '32bit': 99 | mode = CS_MODE_32 100 | else: 101 | mode = CS_MODE_64 102 | 103 | #generateOpCodeFromHex(code) 104 | md = Cs(CS_ARCH_X86, mode) 105 | for (address, size, mnemonic, op_str) in md.disasm_lite(code, 0x1000): 106 | 107 | opcode = str(mnemonic) 108 | 109 | capstoneOpcodeList.append(opcode) 110 | #print"%s" %(i.mnemonic) #print"0x%x:\t%s\t\t%s" %(i.address, i.mnemonic, i.op_str) 111 | capstoneFile.write(opcode+",") 112 | 113 | if countStatisticsResult : 114 | # count opcode number 115 | if opcode in capstoneOpcodeDict: 116 | capstoneOpcodeDict[opcode] += 1 117 | else: 118 | capstoneOpcodeDict[opcode] = 1 119 | 120 | if countStatisticsResult: 121 | countStatisticResult(capstoneOpcodeDict, filename) 122 | 123 | print filename+" is disassembled." 124 | return capstoneOpcodeList 125 | 126 | 127 | def Disassemble(filename, bits='32bit',capstone=True, distorm=True,compare=False): 128 | """Disassemble binary code with distorm3 and capstone. 129 | 130 | @param filename : executable file 131 | @param bits : file bits ; 16bit, 32bit or 64bit decoding 132 | @param capstone : capstone disassebly is used or not 133 | @param distorm : capstone disassebly is used or not 134 | @param compare : comparasion of distorm and capstone 135 | 136 | @returns: tuple of (offset, instruction, hex bytes) 137 | """ 138 | 139 | # start function variables 140 | (file, ext) = os.path.splitext(filename) 141 | 142 | code = "" 143 | # Read the code from the file 144 | try: 145 | code = open(filename, 'rb').read() 146 | except Exception as err: 147 | print str(err) 148 | 149 | 150 | if distorm : 151 | distormOpcodeList = distormDisassemble(file,code, bits) 152 | 153 | if capstone : 154 | capstoneOpcodeList = capstoneDisassemble(file,code,bits) 155 | 156 | if compare : 157 | # compare two list 158 | 159 | compare = lambda x, y: collections.Counter(x) == collections.Counter(y) 160 | print compare(capstoneOpcodeList, distormOpcodeList) 161 | print set(capstoneOpcodeList) == set (distormOpcodeList) 162 | 163 | def DisassembleFolder(directory): 164 | """"Disassemble all file under directory which given as parameter 165 | 166 | """ 167 | 168 | for root, dirs, files in os.walk(directory): 169 | for file in files: 170 | Disassemble(os.path.join(root, file),"32bit",False,True) 171 | 172 | # Running .... 173 | # Disassembly function test ###################################################################################################### 174 | DisassembleFolder('/home/mint/workspace/malwareDetection/dataSet/OPCODE/') 175 | #clear('/home/mint/workspace/malwareDetection/dataSet/OPCODE/malware/NGVCK2/','.opcode') 176 | ######################################################################### 177 | -------------------------------------------------------------------------------- /modules/disassembly/diasm.py: -------------------------------------------------------------------------------- 1 | from __future__ import division # to float division 2 | import distorm3 # distorm disassembler library 3 | import os, sys 4 | from operator import itemgetter # to sort dictionary 5 | import collections # to comparasion 6 | 7 | 8 | def distormDisassemble(filename,code, bits, countStatisticsResult= False): 9 | # start function variables 10 | distormOpcodeDict = dict() # key = opcode, value = count 11 | distormFilename = filename+".asm" 12 | distormOpcodeList = [] 13 | 14 | # Output file for opcodes 15 | distormFile = open(distormFilename, 'w') 16 | #distormFile.write(filename+";") 17 | 18 | # define distorm arguments 19 | offset = 0 20 | length = None 21 | 22 | if bits == '16bit': 23 | mode = distorm3.Decode16Bits 24 | elif bits == '32bit': 25 | mode = distorm3.Decode32Bits 26 | else: 27 | mode = distorm3.Decode64Bits 28 | 29 | # Decoded instruction 30 | iterable = distorm3.DecodeGenerator(offset, code, mode) 31 | 32 | for (offset, size, instruction, hexdump) in iterable: 33 | print("%.8x: %-32s %s" % (offset, hexdump, instruction)) 34 | 35 | distormFile.write(instruction+"\n") # write opcode to file 36 | 37 | 38 | print (filename+" is disassembled.") 39 | return distormOpcodeList 40 | 41 | ''' 42 | # Disassemble given files 43 | # 44 | # filename : file path 45 | # bits : file bit (16, 32 0r 64). 32 bit default value this parameter 46 | # 47 | # return : no return value. Write disassembled result into a file which has extension .opcode 48 | ''' 49 | def Disassemble(filename, bits='32bit'): 50 | 51 | 52 | # start function variables 53 | (file, ext) = os.path.splitext(filename) 54 | 55 | code = "" 56 | # Read the code from the file 57 | try: 58 | code = open(filename, 'rb').read() 59 | except Exception as err: 60 | print (str(err)) 61 | 62 | distormOpcodeList = distormDisassemble(file,code, bits) 63 | 64 | def DisassembleFolder(directory): 65 | """"Disassemble all file under directory which given as parameter 66 | """ 67 | 68 | for root, dirs, files in os.walk(directory): 69 | for file in files: 70 | Disassemble(os.path.join(root, file)) 71 | 72 | if __name__ == '__main__': 73 | 74 | parser = argparse.ArgumentParser(description="Disassemble files") 75 | parser.add_argument("-d", "--directory", default = '', help="Directory path") 76 | 77 | args = parser.parse_args() 78 | 79 | if args.directory : 80 | directory = args.directory 81 | DisassembleFolder(directory) 82 | else : 83 | filename = sys.argv[1] 84 | Disassemble(filename) 85 | 86 | -------------------------------------------------------------------------------- /modules/fileoperation/filesizedump.py: -------------------------------------------------------------------------------- 1 | 2 | import os, os 3 | 4 | def getFileSizes(directory,outputFileName): 5 | outfile = open(outputFileName+".txt", 'w') 6 | for root, dirs, files in os.walk(directory): 7 | for file in files: 8 | filename = root+"\\"+file 9 | outfile.write(filename+" "+str(os.path.getsize(filename))+"\n") 10 | print "All file size computed." 11 | 12 | # Getting bening and malware file sizes ############################################## 13 | #getFileSizes('C:\\Users\\asus\\Desktop\\MetamorfikBackup\\win7_8_mixBeningFiles\\',"biningfilesSizes") 14 | #getFileSizes('C:\\Users\\asus\\Desktop\\win7_8_mixBeningFiles\\',"biningfilesSizes") 15 | ###################################################################################### -------------------------------------------------------------------------------- /modules/fileoperation/rename.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on 24 Kas 2015 3 | 4 | @author: mint 5 | ''' 6 | 7 | import os 8 | 9 | def change_file_ext(cur_dir, old_ext, new_ext, sub_dirs=False): 10 | ''' 11 | https://gomputor.wordpress.com/2008/09/29/change-the-extension-of-multiple-files-in-a-chosen-directory-with-python/ 12 | @param cur_dir the directory which include the file 13 | @param old_ext 14 | @param new_ext 15 | @param sub_dir 16 | ''' 17 | if sub_dirs: 18 | for root, dirs, files in os.walk(cur_dir): 19 | for filename in files: 20 | file_ext = os.path.splitext(filename)[1] 21 | if old_ext == file_ext: 22 | oldname = os.path.join(root, filename) 23 | newname = oldname.replace(old_ext, new_ext) 24 | os.rename(oldname, newname) 25 | else: 26 | files = os.listdir(cur_dir) 27 | for filename in files: 28 | file_ext = os.path.splitext(filename)[1] 29 | if old_ext == file_ext: 30 | newfile = filename.replace(old_ext, new_ext) 31 | os.rename(filename, newfile) 32 | 33 | # change all .txt files to .html only in this directory 34 | #change_file_ext('/home/user/my_files', '.txt', '.html') 35 | # change all .txt files to .html also in sub-directories 36 | #change_file_ext('/home/user/my_files', '.txt', '.html', True) 37 | 38 | ''' 39 | Rename mail output files 40 | ''' 41 | def renameFile(folderPath): 42 | for filename in os.listdir(folderPath): 43 | newFileName = filename[:-9]+".mail" 44 | #print filename+" is renamed as "+newFileName 45 | os.rename(folderPath+filename, folderPath+newFileName) 46 | print filename+" is renamed as "+newFileName 47 | 48 | renameFile("/home/mint/workspace/malwareDetection/dataSet/MAIL/malware/NGVCK2/") 49 | 50 | 51 | -------------------------------------------------------------------------------- /modules/hexdump/hexdump.py: -------------------------------------------------------------------------------- 1 | import binascii # to convert binary to hex 2 | import os, sys 3 | 4 | def hexdump(filename): 5 | 6 | # start function variables 7 | (file, ext) = os.path.splitext(filename) 8 | outputFileName = file+".hexcode" 9 | 10 | # Read the code from the file 11 | try: 12 | code = open(filename, 'rb').read() 13 | hexcode = binascii.hexlify(code) 14 | except Exception as err: 15 | print str(err) 16 | 17 | outfile = open(outputFileName, 'w') 18 | outfile.write(hexcode) 19 | print outputFileName+" hex code dumped." 20 | return hexcode 21 | 22 | def hexdumpFolder(directory,extensionList): 23 | for root, dirs, files in os.walk(directory): 24 | for file in files: 25 | (filename, ext) = os.path.splitext(file) 26 | if ext in extensionList: 27 | filename = root+"\\"+file 28 | hexcode = hexdump(filename) 29 | 30 | # Test ... 31 | #hexdump('C:\\Users\\asus\\Desktop\\test\\all_viruses_exe\\type1_2_3_4_5_6_9\\ngvck_type1_1000.EXE') 32 | #hexdumpFolder('C:\\Users\\asus\\Desktop\\test\\all_viruses_exe\\type1_2_3_4_5_6_9\\',[".exe",".EXE",".dll",".DLL",".com",".COM"]) 33 | 34 | # Running ... 35 | #hexdumpFolder('C:\\Users\\asus\\Desktop\\win7_8_mixBeningFiles\\',[".exe",".EXE",".dll",".DLL",".com",".COM"]) 36 | # hexdumpFolder('C:\\Users\\asus\\Desktop\\MetamorfikBackup\\all_ngvck_viruses_exe\\',[".exe",".EXE",".dll",".DLL",".com",".COM"]) 37 | hexdumpFolder('C:\\Users\\asus\\Desktop\\workspace\\G2\\',[".exe",".EXE",".dll",".DLL",".com",".COM"]) 38 | -------------------------------------------------------------------------------- /modules/main.py: -------------------------------------------------------------------------------- 1 | import os 2 | import tfidf 3 | 4 | def tf_idf(directory,ext): 5 | table = tfidf.tfidf() 6 | for root, dirs, files in os.walk(directory): 7 | for file in files: 8 | if file.endswith(ext): 9 | filename = root+file 10 | try: 11 | print file 12 | content = open(filename, 'rb').read() 13 | opcodeList = content.split(",") 14 | table.addDocument(file, opcodeList) 15 | except Exception as err: 16 | print str(err) 17 | print table.similarities (["nop"]) 18 | #Running ... 19 | #table = tfidf.tfidf() 20 | #table.addDocument("foo", ["alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel"]) 21 | #table.addDocument("bar", ["alpha", "bravo", "charlie", "india", "juliet", "kilo"]) 22 | #table.addDocument("baz", ["kilo", "lima", "mike", "november"]) 23 | 24 | #print table.similarities (["alpha", "bravo", "charlie"]) # => [['foo', 0.6875], ['bar', 0.75], ['baz', 0.0]] 25 | 26 | tf_idf('C:\\Users\\asus\\Desktop\\workspace\\test\\all_viruses_exe\\type1_2_3_4_5_6_9\\',".distorm") -------------------------------------------------------------------------------- /modules/metamorfik_proeject.py: -------------------------------------------------------------------------------- 1 | from __future__ import division # to float division 2 | 3 | import distorm3 4 | from capstone import * 5 | import os, sys 6 | from operator import itemgetter # to sort dictionary 7 | import collections # to comparasion 8 | import binascii # to convert binary to hex 9 | 10 | 11 | def mergeDisassembleResult(directory,resultFileName): 12 | """ Finding most used opcodes 13 | """ 14 | 15 | outfile = open(resultFileName+".opcodeSequences", 'w') 16 | 17 | for root, dirs, files in os.walk(directory): 18 | for file in files: 19 | 20 | if file.endswith(".distorm"): 21 | 22 | filename = root+"\\"+file 23 | # Read the code from the file 24 | try: 25 | print file 26 | opcodeSequence = open(filename, 'rb').read() 27 | outfile.write(opcodeSequence) 28 | except Exception as err: 29 | print str(err) 30 | 31 | def findCommonUsedOpcodes(directory,resultFileName): 32 | """Finding and merging all opcode sequence in a file 33 | """ 34 | 35 | opcodeDict = dict() 36 | opcodeCountDict = dict() 37 | opcodePercentDict = dict() 38 | 39 | 40 | for root, dirs, files in os.walk(directory): 41 | for file in files: 42 | 43 | if file.endswith(".distorm2"): 44 | 45 | filename = root+"\\"+file 46 | # Read the code from the file 47 | try: 48 | print file 49 | # Open this file. 50 | f = open(filename, "r") 51 | 52 | # Loop over each line in the file. 53 | for line in f.readlines(): 54 | 55 | # Strip the line to remove whitespace. 56 | line = line.strip() 57 | 58 | # Split the line. 59 | opcode, count, percent = line.split(" ") 60 | 61 | #count opcode usage number 62 | if opcode in opcodeDict: 63 | opcodeDict[opcode] += 1 64 | else: 65 | opcodeDict[opcode] = 1 66 | 67 | #count opcode count number 68 | if opcode in opcodeCountDict : 69 | countSum = int(opcodeCountDict[opcode])+int(count) 70 | opcodeCountDict[opcode] = countSum 71 | 72 | else: 73 | opcodeCountDict[opcode] = count 74 | 75 | #count opcode percent number 76 | if opcode in opcodePercentDict: 77 | percentSum = float(opcodePercentDict[opcode])+float(percent) 78 | opcodePercentDict[opcode] = percentSum 79 | else: 80 | opcodePercentDict[opcode] = percent 81 | 82 | except Exception as err: 83 | print str(err) 84 | 85 | sortedOpcodeList = sorted(opcodeDict.items(), key=itemgetter(1),reverse=True) 86 | sortedOpcodeCountList = sorted(opcodeCountDict.items(), key=itemgetter(1),reverse=True) 87 | sortedOpcodePercentList = sorted(opcodePercentDict.items(), key=itemgetter(1),reverse=True) 88 | 89 | outfile = open(resultFileName+".commonOpcodes", 'w') 90 | outfile.write('\n'.join('%s %s' % x for x in sortedOpcodeList)) 91 | 92 | outfile = open(resultFileName+".commonOpcodesCount", 'w') 93 | outfile.write('\n'.join('%s %s' % x for x in sortedOpcodeCountList)) 94 | 95 | outfile = open(resultFileName+".commonOpcodesPercent", 'w') 96 | outfile.write('\n'.join('%s %s' % x for x in sortedOpcodePercentList)) 97 | print sortedOpcodeList 98 | print sortedOpcodeCountList 99 | print sortedOpcodePercentList 100 | 101 | 102 | 103 | #mergeDisassembleResult('C:\\Users\\asus\\Desktop\\all_ngvck_viruses_exe\\all_viruses_exe\\type2_3_4_5_6_9\\',"type2_3_4_5_6_9") 104 | 105 | # Finding opcodes usage count and percent within all virus and malware ########################################################## 106 | #findCommonUsedOpcodes('C:\\Users\\asus\\Desktop\\all_ngvck_viruses_exe\\all_viruses_exe\\',"bening_all_opcodes") 107 | #findCommonUsedOpcodes('C:\\Users\\asus\\Desktop\\win7_8_mixBeningFiles\\',"bening_all_opcodes") 108 | #findCommonUsedOpcodes('C:\\Users\\asus\\Desktop\\test\\',"test") 109 | #findCommonUsedOpcodes('C:\\Users\\asus\\Desktop\\MetamorfikBackup\\all_ngvck_viruses_exe\\all_viruses_exe\\',"virus") 110 | #findCommonUsedOpcodes('C:\\Users\\asus\\Desktop\\win7_8_mixBeningFiles\\',"bening_all_opcodes") 111 | ################################################################################################################################## 112 | #findCommonUsedOpcodes('C:\\Users\\asus\\Desktop\\win7_8_mixBeningFiles\\',"win7_8_mixBeningFiles") 113 | #findCommonUsedOpcodes('C:\\Users\\asus\\Desktop\\pureWin7_8_mixBeningFiles\\',"pureWin7_8_mixBeningFiles") 114 | findCommonUsedOpcodes('C:\\Users\\asus\\Desktop\\pureWin7BeningFiles\\',"pureWin7BeningFiles") 115 | #findCommonUsedOpcodes('C:\\Users\\asus\\Desktop\\pureWin8BeningFiles\\',"pureWin8BeningFiles") 116 | 117 | 118 | -------------------------------------------------------------------------------- /modules/opcodeOperation/asmToOpcodeSequence.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | def asmToOpcode(filename,opcodeList): 4 | 5 | # start function variables 6 | (file, ext) = os.path.splitext(filename) 7 | outputFileName = file+".opcode" 8 | outfile = open(outputFileName, 'w') 9 | 10 | # Read the code from the file 11 | try: 12 | content = open(filename,"r").read() 13 | parsdContent = content.split("\n") 14 | 15 | for item in parsdContent: 16 | item = ' '.join(item.split()) 17 | opcContent = item.split(" ") 18 | # print opcContent 19 | for opcode in opcodeList: 20 | if opcode in opcContent : 21 | if not ((opcode in ["in","and","or"]) and (("file" in opcContent) or ("File" in opcContent) or ("size" in opcContent) or ("Section" in opcContent))): 22 | outfile.write(opcode+",") 23 | #print opcContent 24 | break 25 | 26 | 27 | except Exception as err: 28 | print str(err) 29 | 30 | print outputFileName+" opcode list dumped." 31 | 32 | 33 | def asmToOpcodeFolder(directory,extensionList): 34 | 35 | opcodes = [] 36 | opcodeList = open("opcodelist.txt", 'rb').readlines() 37 | 38 | for i in range(len(opcodeList)): 39 | opcodes.append(opcodeList[i].strip('\n')) 40 | 41 | 42 | for root, dirs, files in os.walk(directory): 43 | for file in files: 44 | (filename, ext) = os.path.splitext(file) 45 | if ext in extensionList: 46 | filename = root+"\\"+file 47 | asmToOpcode(filename,opcodes) 48 | 49 | def uniqueOpcodes(folderPath, extensionList): 50 | outputFileName = folderPath+"unique.opcode" 51 | outfile = open(outputFileName, 'w') 52 | opcodeList = [] 53 | 54 | for root, dirs, files in os.walk(folderPath): 55 | for file in files: 56 | (filename, ext) = os.path.splitext(file) 57 | if ext in extensionList: 58 | filename = root+"\\"+file 59 | content = open(filename,"r").read() 60 | oplist = content.split(",") 61 | 62 | for opcode in oplist: 63 | if (opcode not in opcodeList) and (opcode not in " "): 64 | opcodeList.append(opcode) 65 | outfile.write(opcode+",") 66 | 67 | 68 | #asmToOpcodeFolder('C:\\Users\\asus\\Desktop\\workspace\\ASM\\',[".asm",".ASM"]) 69 | uniqueOpcodes('C:\\Users\\asus\\Desktop\\workspace\\ASM\\',[".opcode"]) -------------------------------------------------------------------------------- /samples/penkor.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncarkaci/StaticFeatureExtractionFrameworkForMalwareAnalysis/6d8104165a774ad0c90770de8d0c494d1b4bf87e/samples/penkor.dll --------------------------------------------------------------------------------