Exemplo n.º 1
0
def R1Q0(questionCounter):
    Qs = [
        "What is the IMAGE_DOS_HEADER.e_magic in ASCII?",
        "What is the numeric value of the IMAGE_DOS_HEADER.e_magic?"
    ]

    #Print the question
    q = random.randint(0, len(Qs) - 1)

    print Qs[q]
    answer = raw_input("Answer: ")

    if q == 0:
        CheckAnswerString(answer, "MZ")
    else:
        CheckAnswerNum(answer, 0x5A4D)
def R6Q0(questionCounter):
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR6
    Qs = [
        "What is the value of IMAGE_EXPORT_DIRECTORY.Base?",
        "What value should be subtracted from an ordinal to get its index into the AddressOfFunctions array?",
        "What is the value of IMAGE_EXPORT_DIRECTORY.NumberOfFunctions?",
        "How many functions does this binary export?",
        "What is the value of IMAGE_EXPORT_DIRECTORY.NumberOfNames?",
        "How many functions does this binary export by name?",
        "How many functions does this binary export by ordinal?",
        "Is NumberOfNames == NumberOfFunctions? (Y or N)",
        "What is the value of IMAGE_EXPORT_DIRECTORY.AddressOfFunctions?",
        "What is the RVA to the Export Address Table (EAT)?",
        "What is the VA to the Export Address Table (EAT)?",
        "What is the value of IMAGE_EXPORT_DIRECTORY.AddressOfNames?",
        "What is the RVA of the Export Names Table (ENT)?",
        "What is the VA of the Export Names Table (ENT)?",
        "What is the value of IMAGE_EXPORT_DIRECTORY.AddressOfNameOrdinals?",
        "What is the value of IMAGE_EXPORT_DIRECTORY.TimeDateStamp?",
        "According to the exports information, what year was this binary compiled?",
        "Does the exports' TimeDateStamp match the File Header TimeDateStamp? (Y or N)",
        "Is the exports' TimeDateStamp what's checked against when the loader is checking if bound imports still have correct VAs? (Y or N)",
        "Is the File Header's TimeDateStamp what's checked against when the loader is checking if bound imports still have correct VAs? (Y or N)",
        "Which of the following points at the Export Address Table (EAT): AddressOfFunctions, AddressOfNames, or AddressOfNameOrdinals?",
        "Which of the following points at the Export Names Table (ENT): AddressOfFunctions, AddressOfNames, or AddressOfNameOrdinals?",
    ]
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR6

    x = random.randint(2, 3)
    #  if x == 0:
    #    pe = pefile.PE('../template32-bound.exe')
    #    suffix = ".exe"
    #  elif x == 1:
    #    pe = pefile.PE('../template64-bound.exe')
    #    suffix = ".exe"
    if x == 2:
        pe = pefile.PE('../template32-bound.dll')
        suffix = ".dll"
    else:
        pe = pefile.PE('../template64-bound.dll')
        suffix = ".dll"

    #TODO: want to be able to randomize entries/size of delay load IAT

    #FIXME: what's the more graceful way of doing this?
    error = 1
    while error:
        try:
            #write out the (actually un)modified file
            outFileName = "Round6Q" + str(questionCounter) + suffix
            pe.write(outFileName)
            error = 0
        except IOError:
            questionCounter += 1

    #Print the question
    q = random.randint(0, len(Qs) - 1)
    print "For binary R6Bins/%s..." % outFileName
    print Qs[q]
    answer = raw_input("Answer: ")

    if q == 0 or q == 1:
        CheckAnswerNum(answer, pe.DIRECTORY_ENTRY_EXPORT.struct.Base)
    elif q == 2 or q == 3:
        CheckAnswerNum(answer,
                       pe.DIRECTORY_ENTRY_EXPORT.struct.NumberOfFunctions)
    elif q == 4 or q == 5:
        CheckAnswerNum(answer, pe.DIRECTORY_ENTRY_EXPORT.struct.NumberOfNames)
    elif q == 6:
        CheckAnswerNum(
            answer, pe.DIRECTORY_ENTRY_EXPORT.struct.NumberOfFunctions -
            pe.DIRECTORY_ENTRY_EXPORT.struct.NumberOfNames)
    elif q == 7:
        if pe.DIRECTORY_ENTRY_EXPORT.struct.NumberOfFunctions == pe.DIRECTORY_ENTRY_EXPORT.struct.NumberOfNames:
            CheckAnswerString(answer, "Y")
        else:
            CheckAnswerString(answer, "N")
    elif q == 8 or q == 9:
        CheckAnswerNum(answer,
                       pe.DIRECTORY_ENTRY_EXPORT.struct.AddressOfFunctions)
    elif q == 10:
        CheckAnswerNum(
            answer, pe.OPTIONAL_HEADER.ImageBase +
            pe.DIRECTORY_ENTRY_EXPORT.struct.AddressOfFunctions)
    elif q == 11 or q == 12:
        CheckAnswerNum(answer, pe.DIRECTORY_ENTRY_EXPORT.struct.AddressOfNames)
    elif q == 13:
        CheckAnswerNum(
            answer, pe.OPTIONAL_HEADER.ImageBase +
            pe.DIRECTORY_ENTRY_EXPORT.struct.AddressOfNames)
    elif q == 14:
        CheckAnswerNum(answer,
                       pe.DIRECTORY_ENTRY_EXPORT.struct.AddressOfNameOrdinals)
    elif q == 15:
        CheckAnswerNum(answer, pe.DIRECTORY_ENTRY_EXPORT.struct.TimeDateStamp)
    elif q == 16:
        exportYear = 1970 + int(
            pe.DIRECTORY_ENTRY_EXPORT.struct.TimeDateStamp / 31556926)
        CheckAnswerNum(answer, exportYear)
    elif q == 17:
        #50% chance to randomize file header timedatestamp
        if random.randint(0, 1):
            pe.FILE_HEADER.TimeDateStamp = random.randint(0, 4294967296)
        if pe.DIRECTORY_ENTRY_EXPORT.struct.TimeDateStamp == pe.FILE_HEADER.TimeDateStamp:
            CheckAnswerString(answer, "Y")
        else:
            CheckAnswerString(answer, "N")
    elif q == 18:
        CheckAnswerString(answer, "Y")
    elif q == 19:
        CheckAnswerString(answer, "N")
    elif q == 20:
        CheckAnswerString(answer, "AddressOfFunctions")
    elif q == 21:
        CheckAnswerString(answer, "AddressOfNames")
def R7Q0(questionCounter):
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR7
    Qs = [
        "According to the debugging information, what year was this file compiled?",
        "Does the debug information TimeDateStamp match the File Header TimeDateStamp?",
        "What is the RVA that would point at this file's path the the debugging information (.pdb file)?",
        "What is the full filename, including path, where this file's debugging information (.pdb file) was originally placed at compile time?",
        "What is the file offset that points at the .pdb file path?",
        "What is the RVA of the debug information?",
        "What is the VA of the debug information?",
        "What is the file offset to the debug information?"
    ]
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR7

    x = random.randint(0, 3)
    if x == 0:
        pe = pefile.PE('../template32-bound.dll')
        suffix = ".dll"
    elif x == 1:
        pe = pefile.PE('../template32-bound.exe')
        suffix = ".exe"
    if x == 2:
        pe = pefile.PE('../template64-bound.exe')
        suffix = ".exe"
    else:
        pe = pefile.PE('../template64-bound.dll')
        suffix = ".dll"

    outFileName = "Round7Q" + str(questionCounter) + suffix

    if random.randint(0, 1):
        pe.DIRECTORY_ENTRY_DEBUG[0].struct.TimeDateStamp = random.randint(
            0, 4294967296)
        if random.randint(0, 1):
            pe.FILE_HEADER.TimeDateStamp = pe.DIRECTORY_ENTRY_DEBUG[
                0].struct.TimeDateStamp

    #FIXME: what's the more graceful way of doing this?
    error = 1
    while error:
        try:
            outFileName = "Round7Q" + str(questionCounter) + suffix
            #TODO: randomize some more of these elements
            pe.write(outFileName)
            error = 0
        except IOError:
            questionCounter += 1

    q = random.randint(0, len(Qs) - 1)
    print "For binary R7Bins/%s..." % outFileName
    print Qs[q]

    answer = raw_input("Answer: ")

    if q == 0:
        debugYear = 1970 + int(
            pe.DIRECTORY_ENTRY_DEBUG[0].struct.TimeDateStamp / 31556926)
        CheckAnswerNum(answer, debugYear)
    elif q == 1:
        if pe.DIRECTORY_ENTRY_DEBUG[
                0].struct.TimeDateStamp == pe.FILE_HEADER.TimeDateStamp:
            CheckAnswerString(answer, "Y")
        else:
            CheckAnswerString(answer, "N")
    elif q == 2:
        #The 0x18 offset comes from the fact that all my template binaries currently are
        #using CV_INFO_PDB70 for the debug information
        #TODO: want to show both CV_INFO_PDB70 and CV_INFO_PDB20 types (in the original
        #class all the files were CV_INFO_PDB20 type)
        CheckAnswerNum(
            answer, pe.DIRECTORY_ENTRY_DEBUG[0].struct.AddressOfRawData + 0x18)
    elif q == 3:
        CheckAnswerString(
            answer,
            pe.get_string_at_rva(
                pe.DIRECTORY_ENTRY_DEBUG[0].struct.AddressOfRawData + 0x18))
    elif q == 4:
        CheckAnswerNum(
            answer,
            pe.get_offset_from_rva(
                pe.DIRECTORY_ENTRY_DEBUG[0].struct.AddressOfRawData + 0x18))
    elif q == 5:
        CheckAnswerNum(answer,
                       pe.OPTIONAL_HEADER.DATA_DIRECTORY[6].VirtualAddress)
    elif q == 6:
        CheckAnswerNum(
            answer, pe.OPTIONAL_HEADER.ImageBase +
            pe.OPTIONAL_HEADER.DATA_DIRECTORY[6].VirtualAddress)
    elif q == 7:
        CheckAnswerNum(
            answer,
            pe.get_offset_from_rva(
                pe.OPTIONAL_HEADER.DATA_DIRECTORY[0].VirtualAddress))
def R7Q1(questionCounter):
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR7
    Qs = [
        "How many relocations are there from RVA %x to %x?",
        "Is 0x%x a relocation location? (Y or N)",
        "What is the RVA of the relocation information?",
        "What is the VA of the relocation information?",
        "What is the file offset to the relocation information?",
        "What section is the relocation information in?"
    ]
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR7

    x = random.randint(0, 3)
    if x == 0:
        pe = pefile.PE('../template32-bound.dll')
        suffix = ".dll"
    elif x == 1:
        pe = pefile.PE('../template32-bound.exe')
        suffix = ".exe"
    if x == 2:
        pe = pefile.PE('../template64-bound.exe')
        suffix = ".exe"
    else:
        pe = pefile.PE('../template64-bound.dll')
        suffix = ".dll"

    #FIXME: what's the more graceful way of doing this?
    error = 1
    while error:
        try:
            outFileName = "Round7Q" + str(questionCounter) + suffix
            #TODO: randomize some more of these elements
            pe.write(outFileName)
            error = 0
        except IOError:
            questionCounter += 1

    q = random.randint(0, len(Qs) - 1)
    print "For binary R7Bins/%s..." % outFileName
    relocEntry = pe.DIRECTORY_ENTRY_BASERELOC[random.randint(
        0,
        len(pe.DIRECTORY_ENTRY_BASERELOC) - 1)]
    if q == 0:
        #pick a random page to ask about
        interpolatedQuestion = Qs[q] % (relocEntry.struct.VirtualAddress,
                                        relocEntry.struct.VirtualAddress +
                                        0x1000)
    elif q == 1:
        #pick a random relocation to ask about
        relocEntry2 = relocEntry.entries[random.randint(
            0,
            len(relocEntry.entries) - 1)]
        relocRVA = relocEntry2.rva
        if random.randint(0, 1):
            realReloc = 1
        else:
            realReloc = 0
            relocRVA += 1

        interpolatedQuestion = Qs[q] % relocRVA
    else:
        interpolatedQuestion = Qs[q]
    print interpolatedQuestion
    answer = raw_input("Answer: ")

    if q == 0:
        CheckAnswerNum(answer, len(relocEntry.entries))
    elif q == 1:
        if realReloc:
            CheckAnswerString(answer, "Y")
        else:
            CheckAnswerString(answer, "N")
    elif q == 2:
        CheckAnswerNum(answer,
                       pe.OPTIONAL_HEADER.DATA_DIRECTORY[5].VirtualAddress)
    elif q == 3:
        CheckAnswerNum(
            answer, pe.OPTIONAL_HEADER.ImageBase +
            pe.OPTIONAL_HEADER.DATA_DIRECTORY[5].VirtualAddress)
    elif q == 4:
        CheckAnswerNum(
            answer,
            pe.get_offset_from_rva(
                pe.OPTIONAL_HEADER.DATA_DIRECTORY[5].VirtualAddress))
    elif q == 5:
        CheckAnswerString(
            answer,
            pe.get_section_by_rva(
                pe.OPTIONAL_HEADER.DATA_DIRECTORY[5].VirtualAddress).Name)
Exemplo n.º 5
0
def R5Q3(questionCounter):
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR5
    Qs = [
        "Is this binary using \"normal\" or \"bound\" imports?",
        "How many IMAGE_BOUND_FORWARDER_REF structures are in the bound import directory table?"
    ]
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR5

    totalBoundRefs = 0

    q = random.randint(0, len(Qs) - 1)

    if q == 0:
        x = random.randint(0, 7)
    else:
        x = random.randint(0, 3)
    if x == 0:
        pe = pefile.PE('../template32-bound.exe')
        suffix = ".exe"
    elif x == 1:
        pe = pefile.PE('../template64-bound.exe')
        suffix = ".exe"
    elif x == 2:
        pe = pefile.PE('../template32-bound.dll')
        suffix = ".dll"
    elif x == 3:
        pe = pefile.PE('../template64-bound.dll')
        suffix = ".dll"
    elif x == 4:
        pe = pefile.PE('../template32.exe')
        suffix = ".exe"
    elif x == 5:
        pe = pefile.PE('../template64.exe')
        suffix = ".exe"
    elif x == 6:
        pe = pefile.PE('../template32.dll')
        suffix = ".dll"
    else:
        pe = pefile.PE('../template64.dll')
        suffix = ".dll"
    if x <= 3:
        importType = "bound"
        for entry in pe.DIRECTORY_ENTRY_BOUND_IMPORT:
            totalBoundRefs += len(entry.entries)
    else:
        importType = "normal"

    #TODO: want to be able to randomize entries/size of delay load IAT

    #FIXME: what's the more graceful way of doing this?
    error = 1
    while error:
        try:
            #write out the (actually un)modified file
            outFileName = "Round5Q" + str(questionCounter) + suffix
            pe.write(outFileName)
            error = 0
        except IOError:
            questionCounter += 1

    #Print the question
    print "For binary R5Bins/%s..." % outFileName
    print Qs[q]
    answer = raw_input("Answer: ")

    if q == 0:
        CheckAnswerString(answer, importType)
    elif q == 1:
        CheckAnswerNum(answer, totalBoundRefs)
Exemplo n.º 6
0
def R4Q1(questionCounter):
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR4
    Qs = [
        "How many DLLs does this binary import from?",
        "How many entries are there in the import directory table?",
        "Does this binary directly import functions from %s? (Y or N)"
    ]
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR4

    #These names should all be things that none of the template binaries actually import from
    randomDLLNames = [
        "ADVAPI32.dll", "GDI32.dll", "SHELL32.dll", "NTDLL.dll",
        "COMCTL32.dll", "MSI.dll", "OLE32.dll", "MSVCRT.dll", "SETUPAPI.dll",
        "CRYPT32.dll", "SECUR32.dll", "IMAGEHLP.dll"
    ]

    x = random.randint(0, 3)
    if x == 0:
        pe = pefile.PE('../template32.exe')
        suffix = ".exe"
    elif x == 1:
        pe = pefile.PE('../template64.exe')
        suffix = ".exe"
    elif x == 2:
        pe = pefile.PE('../template32.dll')
        suffix = ".dll"
    else:
        pe = pefile.PE('../template64.dll')
        suffix = ".dll"

    #TODO: eventually I want to be able to add new IAT information

    #FIXME: what's the more graceful way of doing this?
    error = 1
    while error:
        try:
            #write out the (actually un)modified file
            outFileName = "Round4Q" + str(questionCounter) + suffix
            pe.write(filename=outFileName)
            error = 0
        except IOError:
            questionCounter += 1

    #Print the question
    q = random.randint(0, len(Qs) - 1)
    print "For binary R4Bins/%s..." % outFileName
    interpolatedQuestion = Qs[q]
    if q == 2:
        if random.randint(0, 1):
            #In this case we will ask about a fake DLL
            dllName = randomDLLNames[random.randint(0,
                                                    len(randomDLLNames) - 1)]
            importsNamedDll = "N"
        else:
            #In this case we will ask about a real DLL
            dllName = pe.DIRECTORY_ENTRY_IMPORT[random.randint(
                0,
                len(pe.DIRECTORY_ENTRY_IMPORT) - 1)].dll
            importsNamedDll = "Y"
        interpolatedQuestion = Qs[q] % dllName
    print interpolatedQuestion
    answer = raw_input("Answer: ")

    if q == 0 or q == 1:
        CheckAnswerNum(answer, len(pe.DIRECTORY_ENTRY_IMPORT))
    elif q == 2:
        CheckAnswerString(answer, importsNamedDll)
Exemplo n.º 7
0
def R4Q3(questionCounter):
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR4
    Qs = [
        "How many functions does this import from %s?",
        "At what RVA do the IAT entries from %s start?",
        "At what VA do the IAT entries from %s start?",
        "At what RVA do the INT entries from %s start?",
        "At what VA do the INT entries from %s start?",
        "Does this import function %s!%s? (Y or N)"
    ]
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR4

    #These names should all be things that none of the template binaries actually import from the DLLs they do import from
    nonImportedFunctionNames = ["foo"]

    x = random.randint(0, 3)
    if x == 0:
        pe = pefile.PE('../template32.exe')
        suffix = ".exe"
    elif x == 1:
        pe = pefile.PE('../template64.exe')
        suffix = ".exe"
    elif x == 2:
        pe = pefile.PE('../template32.dll')
        suffix = ".dll"
    else:
        pe = pefile.PE('../template64.dll')
        suffix = ".dll"

    #TODO: eventually I want to be able to move around the IAT
    #For now it will always be in the same section, but with a randomized name
    RandomizeSectionNames(pe)
    #FIXME: what's the more graceful way of doing this?
    error = 1
    while error:
        try:
            #write out the modified file
            outFileName = "Round4Q" + str(questionCounter) + suffix
            pe.write(filename=outFileName)
            pe = pefile.PE(outFileName)
            error = 0
        except IOError:
            questionCounter += 1

    #pick the question
    q = random.randint(0, len(Qs) - 1)

    #select random existing DLL being imported from
    entry = pe.DIRECTORY_ENTRY_IMPORT[random.randint(
        0,
        len(pe.DIRECTORY_ENTRY_IMPORT) - 1)]
    if q < 5:
        #This is the simpler question, we just need the name
        interpolatedQuestion = Qs[q] % entry.dll
    else:
        #here we need to choose whether we will
        if random.randint(0, 1):
            realImport = "Y"
            importName = entry.imports[random.randint(0,
                                                      len(entry.imports) -
                                                      1)].name
        else:
            realImport = "N"
            importedFunctions = []
            for imp in entry.imports:
                importedFunctions.append(imp.name)
            nonImportedFunctionNames = GetExportsByName(entry.dll)
            #Now get only the functions that are NOT imported
            nonImportedFunctionNames = list(
                set(nonImportedFunctionNames).difference(
                    set(importedFunctions)))
            importName = nonImportedFunctionNames[random.randint(
                0,
                len(nonImportedFunctionNames) - 1)]
        interpolatedQuestion = Qs[q] % (entry.dll, importName)
    print "For binary R4Bins/%s..." % outFileName
    print interpolatedQuestion
    answer = raw_input("Answer: ")

    if q == 0:
        CheckAnswerNum(answer, len(entry.imports))
    elif q == 1:
        CheckAnswerNum(answer, entry.struct.FirstThunk)
    elif q == 2:
        CheckAnswerNum(answer,
                       pe.OPTIONAL_HEADER.ImageBase + entry.struct.FirstThunk)
    elif q == 3:
        CheckAnswerNum(answer, entry.struct.OriginalFirstThunk)
    elif q == 4:
        CheckAnswerNum(
            answer,
            pe.OPTIONAL_HEADER.ImageBase + entry.struct.OriginalFirstThunk)
    elif q == 5:
        CheckAnswerString(answer, realImport)
Exemplo n.º 8
0
def R4Q2(questionCounter):
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR4
    Qs = [
        "What section is the import directory table in?",
        "In what section can the IAT be found?",
        "What section is the import address table in?"
    ]
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR4

    x = random.randint(0, 3)
    if x == 0:
        pe = pefile.PE('../template32.exe')
        suffix = ".exe"
    elif x == 1:
        pe = pefile.PE('../template64.exe')
        suffix = ".exe"
    elif x == 2:
        pe = pefile.PE('../template32.dll')
        suffix = ".dll"
    else:
        pe = pefile.PE('../template64.dll')
        suffix = ".dll"

    #TODO: eventually I want to be able to move around the IAT
    #For now it will always be in the same section, but with a randomized name
    RandomizeSectionNames(pe)

    #FIXME: what's the more graceful way of doing this?
    error = 1
    while error:
        try:
            #write out the modified file
            outFileName = "Round4Q" + str(questionCounter) + suffix
            pe.write(filename=outFileName)
            pe = pefile.PE(outFileName)
            error = 0
        except IOError:
            questionCounter += 1

    #Print the question
    q = random.randint(0, len(Qs) - 1)
    print "For binary R4Bins/%s..." % outFileName
    print Qs[q]
    answer = raw_input("Answer: ")

    #TODO: update this to use pe.get_section_by_rva?

    if q == 0:
        for section in pe.sections:
            if (section.VirtualAddress <=
                    pe.OPTIONAL_HEADER.DATA_DIRECTORY[1].VirtualAddress
                    and (section.VirtualAddress + section.Misc_VirtualSize) >
                    pe.OPTIONAL_HEADER.DATA_DIRECTORY[1].VirtualAddress):
                #V's solution to the string comparison issue ;)
                tmp = ['\x00'] * 8
                tmp[:len(answer)] = list(answer.lower())
                mungedAnswer = ''.join(tmp)
                CheckAnswerString(mungedAnswer, section.Name)
    elif q == 1 or q == 2:
        for section in pe.sections:
            if (section.VirtualAddress <=
                    pe.OPTIONAL_HEADER.DATA_DIRECTORY[12].VirtualAddress
                    and (section.VirtualAddress + section.Misc_VirtualSize) >
                    pe.OPTIONAL_HEADER.DATA_DIRECTORY[1].VirtualAddress):
                tmp = ['\x00'] * 8
                tmp[:len(answer)] = list(answer.lower())
                mungedAnswer = ''.join(tmp)
                CheckAnswerString(mungedAnswer, section.Name)
Exemplo n.º 9
0
def R3Q1(questionCounter):
  #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR3
  Qs = ["What is the value for this section's Characteristics?",
        "How many flags are set in the Characteristics?",
        "Does this section have the IMAGE_SCN_CTN_CODE characteristic set? (Y or N)",
        "Does this section contain code? (Y or N)",
        "Does this section have the IMAGE_SCN_CNT_INITIALIZED_DATA characteristic set? (Y or N)",
        "Does this section contain initialized data? (Y or N)",
        "Does this section have the IMAGE_SCN_CNT_UNINITIALIZED_DATA characteristic set? (Y or N)",
        "Does this section contain uninitialized data? (Y or N)",
        "Does this section have the IMAGE_SCN_MEM_NOT_CACHED characteristic set? (Y or N)",
        "Should this section not be cached? (Y or N)",
        "Does this section have the IMAGE_SCN_MEM_NOT_PAGED characteristic set? (Y or N)",
        "Should this section not be paged out to disk? (Y or N)",
        "Does this section have the IMAGE_SCN_MEM_DISCARDABLE characteristic set? (Y or N)",
        "Is this section discardable? (Y or N)",
        "Can this section be removed from memory when the loader is done with it? (Y or N)",
        "Does this section have the IMAGE_SCN_MEM_SHARED characteristic set? (Y or N)",
        "Can this section be shared between processes? (Y or N)",
        "Does this section have the IMAGE_SCN_MEM_EXECUTE characteristic set? (Y or N)",
        "Is this section executable? (Y or N)",
        "Does this section have the IMAGE_SCN_MEM_WRITE characteristic set? (Y or N)",
        "Is this section writable? (Y or N)"]
#        "Does this section have the IMAGE_SCN_MEM_READ characteristic set? (Y or N)",
  #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR3

  x = random.randint(0,3)
  if x == 0:
    pe = pefile.PE('../template32.exe')
    suffix = ".exe"
  elif x == 1:
    pe = pefile.PE('../template64.exe')
    suffix = ".exe"
  elif x == 2:
    pe = pefile.PE('../template32.dll')
    suffix = ".dll"
  else:
    pe = pefile.PE('../template64.dll')
    suffix = ".dll"

  #pick a random section
  randSectIndex = random.randint(0,len(pe.sections)-1)

  numFlagsSet = 0
  if random.randint(0,1) == 1:
    pe.sections[randSectIndex].Characteristics |= 0x00000020
    IMAGE_SCN_CTN_CODE = "Y"
    numFlagsSet += 1
  else:
    IMAGE_SCN_CTN_CODE = "N"
  if random.randint(0,1) == 1:
    pe.sections[randSectIndex].Characteristics |= 0x00000040
    IMAGE_SCN_CNT_INITIALIZED_DATA = "Y"
    numFlagsSet += 1
  else:
    pe.sections[randSectIndex].Characteristics &= ~0x00000040
    IMAGE_SCN_CNT_INITIALIZED_DATA = "N"
  if random.randint(0,1) == 1:
    pe.sections[randSectIndex].Characteristics |= 0x00000080
    IMAGE_SCN_CNT_UNINITIALIZED_DATA = "Y"
    numFlagsSet += 1
  else:
    pe.sections[randSectIndex].Characteristics &= ~0x00000080
    IMAGE_SCN_CNT_UNINITIALIZED_DATA = "N"
    
  if random.randint(0,1) == 1:
    pe.sections[randSectIndex].Characteristics |= 0x02000000
    IMAGE_SCN_MEM_DISCARDABLE = "Y"
    numFlagsSet += 1
  else:
    pe.sections[randSectIndex].Characteristics &= ~0x02000000
    IMAGE_SCN_MEM_DISCARDABLE = "N"
    
  if random.randint(0,1) == 1:
    pe.sections[randSectIndex].Characteristics |= 0x04000000
    IMAGE_SCN_MEM_NOT_CACHED = "Y"
    numFlagsSet += 1
  else:
    pe.sections[randSectIndex].Characteristics &= ~0x04000000
    IMAGE_SCN_MEM_NOT_CACHED = "N"

  if random.randint(0,1) == 1:
    pe.sections[randSectIndex].Characteristics |= 0x08000000
    IMAGE_SCN_MEM_NOT_PAGED = "Y"
    numFlagsSet += 1
  else:
    pe.sections[randSectIndex].Characteristics &= ~0x08000000
    IMAGE_SCN_MEM_NOT_PAGED = "N"

  if random.randint(0,1) == 1:
    pe.sections[randSectIndex].Characteristics |= 0x10000000
    IMAGE_SCN_MEM_SHARED = "Y"
    numFlagsSet += 1
  else:
    pe.sections[randSectIndex].Characteristics &= ~0x10000000
    IMAGE_SCN_MEM_SHARED = "N"

  if random.randint(0,1) == 1:
    pe.sections[randSectIndex].Characteristics |= 0x20000000
    IMAGE_SCN_MEM_EXECUTE = "Y"
    numFlagsSet += 1
  else:
    pe.sections[randSectIndex].Characteristics &= ~0x20000000
    IMAGE_SCN_MEM_EXECUTE = "N"

  if random.randint(0,1) == 1:
    pe.sections[randSectIndex].Characteristics |= 0x80000000
    IMAGE_SCN_MEM_WRITE = "Y"
    numFlagsSet += 1
  else:
    pe.sections[randSectIndex].Characteristics &= ~0x80000000
    IMAGE_SCN_MEM_WRITE = "N"

  #FIXME: what's the more graceful way of doing this?
  error = 1
  while error:
    try:
      #write out the modified file
      outFileName = "Round3Q" + str(questionCounter) + suffix
      pe.write(filename=outFileName)
      error = 0
    except IOError:
      questionCounter+=1
  
 
  #Print the question
  q = random.randint(0,len(Qs)-1)
  print "For binary R3Bins/%s..." % outFileName
  print "For section '%s'..." % pe.sections[randSectIndex].Name
  print Qs[q]
  answer = raw_input("Answer: ")

  if q == 0:
    CheckAnswerNum(answer,pe.sections[randSectIndex].Characteristics)
  elif q == 1:
    CheckAnswerNum(answer,numFlagsSet)
  elif q == 2 or q == 3:
    CheckAnswerString(answer,IMAGE_SCN_CTN_CODE)
  elif q == 4 or q == 5:
    CheckAnswerString(answer,IMAGE_SCN_CNT_INITIALIZED_DATA)
  elif q == 6 or q == 7:
    CheckAnswerString(answer,IMAGE_SCN_CNT_UNINITIALIZED_DATA)
  elif q == 8 or q == 9:
    CheckAnswerString(answer,IMAGE_SCN_MEM_NOT_CACHED)
  elif q == 10 or q == 11:
    CheckAnswerString(answer,IMAGE_SCN_MEM_NOT_PAGED)
  elif q == 12 or q == 13 or q == 14:
    CheckAnswerString(answer,IMAGE_SCN_MEM_DISCARDABLE)
  elif q == 15 or q == 16:
    CheckAnswerString(answer,IMAGE_SCN_MEM_SHARED)
  elif q == 17 or q == 18:
    CheckAnswerString(answer,IMAGE_SCN_MEM_EXECUTE)
  elif q == 19 or q == 20:
    CheckAnswerString(answer,IMAGE_SCN_MEM_WRITE)
Exemplo n.º 10
0
def R3Q3(questionCounter):
  #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR3
  Qs = ["Is the Optional Header SizeOfImage value correct? (Y or N)",
  "Does the IMAGE_OPTIONAL_HEADER.SizeOfImage match the expected value based on the number and size of sections? (Y or N)"]
  #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR3

  #Just reusing the capability from R1Q4
  randomSectionNames = [".xeno", "xeno", ".kovah", "kovah", 
                        ".boring", ".section", ".names", ".are", ".the",
                        ".new", ".normal", ".when", ".you're",
                        ".just", ".trying", ".to", 
                        ".move", ".forward", ":P", ":D", ":O",
                         "<-siht", "<-si", "<-ton", "<-a", "<-epip"]

  x = random.randint(0,3)
  if x == 0:
    pe = pefile.PE('../template32.exe')
    suffix = ".exe"
  elif x == 1:
    pe = pefile.PE('../template64.exe')
    suffix = ".exe"
  elif x == 2:
    pe = pefile.PE('../template32.dll')
    suffix = ".dll"
  else:
    pe = pefile.PE('../template64.dll')
    suffix = ".dll"

  #Created new function to insert random sections and write the file out
  numExtraSections = random.randint(1,5)
  totalNumSections = pe.FILE_HEADER.NumberOfSections + numExtraSections 
  #Since we haven't actually modified pe.FILE_HEADER.NumberOfSections in the binary yet
  #this function will know whether to add new sections based on whether the first param
  #is greater than the existing header or not
  updateSizeOfImage = random.randint(0,1)

  #FIXME: what's the more graceful way of doing this?
  error = 1
  while error:
    try:
      #write out the modified file
      outFileName = "Round3Q" + str(questionCounter) + suffix
      pe.x_modifySectionsAndWrite(totalNumSections, randomSectionNames, updateSizeOfImage, outFileName)
      #Reopen the file otherwise the pe.sections[] calculations below won't be accurate
      pe = pefile.PE(outFileName)
      error = 0
    except IOError:
      questionCounter+=1


  #Print the question
  q = random.randint(0,len(Qs)-1)
  print "For binary R3Bins/%s..." % outFileName
  print Qs[q]
  answer = raw_input("Answer: ")

  if q == 0 or q == 1:
    if updateSizeOfImage:
      CheckAnswerString(answer,"Y")
    else:
      CheckAnswerString(answer,"N")
      print "Bonus question: What should the value of SizeOfImage be?"
      answer = raw_input("Answer: ")
      CheckAnswerNum(answer, pe.sections[-1].Misc_VirtualSize + pe.sections[-1].VirtualAddress)
Exemplo n.º 11
0
def R3Q2(questionCounter):
  #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR3
  Qs = ["What is the section name that typically contains the program's main code?",
        "What is the section name that typically contains the program's writable global data?",
        "What is the section name that typically contains the program's read-only global data?",
        "What is the section name that typically contains the program's relocation data?",
        "What is the section name that typically contains the program's resources?",
        "Although it is commonly merged into other sections, what is a possible name for the section containing global data which is uninitialized, and therefore does not need to be stored on disk?",
        "Although it is commonly merged into other sections, what is a possible name for the section containing import data?",
        "Although it is commonly merged into other sections, what is a possible name for the section containing export data?",
        "What is the commonly used prefix for sections that can be paged to disk?",
        "What is the section name that typically contains 64 bit programs' exception handling data structures?",
        "Can a section's SizeOfRawData be larger than its VirtualSize? (Y or N)",
        "Can a section's VirtualSize be larger than its SizeOfRawData? (Y or N)"]
  #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR3

  #Print the question
  q = random.randint(0,len(Qs)-1)
  print Qs[q]
  answer = raw_input("Answer: ")
  
  if q == 0:
    CheckAnswerString(answer,".text")
  elif q == 1:
    CheckAnswerString(answer,".data")
  elif q == 2:
    CheckAnswerString(answer,".rdata")
  elif q == 3:
    CheckAnswerString(answer,".reloc")
  elif q == 4:
    CheckAnswerString(answer,".rsrc")
  elif q == 5:
    CheckAnswerString(answer,".bss")
  elif q == 6:
    CheckAnswerString(answer,".idata")
  elif q == 7:
    CheckAnswerString(answer,".edata")
  elif q == 8:
    CheckAnswerString(answer,"PAGE")
  elif q == 9:
    CheckAnswerString(answer,".pdata")
  elif q == 10 or q == 11:
    CheckAnswerString(answer, "Y")
    print "I want to ask you 'When will this be the case?', but I wouldn't be able to parse your reply :) So just make sure you know!"
def R2Q5(questionCounter):
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR2
    Qs = [
        "What is the value of IMAGE_OPTIONAL_HEADER.DLLCharacteristics?",
        "Is IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE set? (Y or N)",
        "Does this binary support ASLR? (Y or N)",
        "Is IMAGE_DLL_CHARACTERISTICS_NX_COMPAT set? (Y or N)",
        "Does this binary support hardware DEP? (Y or N)",
        "Does this binary support non-executable data? (Y or N)",
        "Is IMAGE_DLL_CHARACTERISTICS_NO_SEH set? (Y or N)",
        "Does this binary have the flag set for no support for SEH? (Y or N)",
        "Is IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE set? (Y or N)",
        "Does this binary support multiple users in terminal server (i.e. RDP) environments? (Y or N)",
        "How many flags are set in the IMAGE_OPTIONAL_HEADER.DLLCharacteristics?"
    ]
    #  "Is IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY set? (Y or N)",
    #  "Does this binary require checking its digital signature? (Y or N)",
    #  "Is IMAGE_DLLCHARACTERISTICS_NO_ISOLATION set? (Y or N)",
    #  "Is IMAGE_DLLCHARACTERISTICS_NO_BIND set? (Y or N)",
    #  "Is IMAGE_DLLCHARACTERISTICS_WDM_DRIVER set? (Y or N)",
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR2

    x = random.randint(0, 3)
    if x == 0:
        pe = pefile.PE('../template32.exe')
        suffix = ".exe"
    elif x == 1:
        pe = pefile.PE('../template64.exe')
        suffix = ".exe"
    elif x == 2:
        pe = pefile.PE('../template32.dll')
        suffix = ".dll"
    else:
        pe = pefile.PE('../template64.dll')
        suffix = ".dll"

    numFlagsSet = 0
    if random.randint(0, 1) == 1:
        #Found out the hard way just doing something like
        #"pe.OPTIONAL_HEADER.IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = True"
        #doesn't effect the file for these characteristics
        pe.OPTIONAL_HEADER.DllCharacteristics |= 0x40
        #    print "IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE"
        aslrCompat = "Y"
        numFlagsSet += 1
    else:
        pe.OPTIONAL_HEADER.DllCharacteristics &= ~0x40
        aslrCompat = "N"
    if random.randint(0, 1) == 1:
        pe.OPTIONAL_HEADER.DllCharacteristics |= 0x100
        #    print "IMAGE_DLL_CHARACTERISTICS_NX_COMPAT"
        numFlagsSet += 1
        nxCompat = "Y"
    else:
        pe.OPTIONAL_HEADER.DllCharacteristics &= ~0x100
        nxCompat = "N"
    if random.randint(0, 1) == 1:
        pe.OPTIONAL_HEADER.DllCharacteristics |= 0x400
        #    print "IMAGE_DLL_CHARACTERISTICS_NO_SEH"
        numFlagsSet += 1
        noSEH = "Y"
    else:
        pe.OPTIONAL_HEADER.DllCharacteristics &= ~0x400
        noSEH = "N"
    if random.randint(0, 1) == 1:
        pe.OPTIONAL_HEADER.DllCharacteristics |= 0x8000
        #    print "IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE"
        numFlagsSet += 1
        termSrv = "Y"
    else:
        pe.OPTIONAL_HEADER.DllCharacteristics &= ~0x8000
        termSrv = "N"

    #FIXME: what's the more graceful way of doing this?
    error = 1
    while error:
        try:
            #write out the modified file
            outFileName = "Round2Q" + str(questionCounter) + suffix
            pe.write(filename=outFileName)
            error = 0
        except IOError:
            questionCounter += 1

    #Print the question
    q = random.randint(0, len(Qs) - 1)
    #  print "characteristics = %x" % pe.OPTIONAL_HEADER.DllCharacteristics
    #  print "numFlagsSet = %u" % numFlagsSet
    print "For binary R2Bins/%s..." % outFileName
    print Qs[q]
    answer = raw_input("Answer: ")

    if q == 0:
        CheckAnswerNum(answer, pe.OPTIONAL_HEADER.DllCharacteristics)
    elif q == 1 or q == 2:
        CheckAnswerString(answer, aslrCompat)
    elif q == 3 or q == 4 or q == 5:
        CheckAnswerString(answer, nxCompat)
    elif q == 6 or q == 7:
        CheckAnswerString(answer, noSEH)
    elif q == 8 or q == 9:
        CheckAnswerString(answer, termSrv)
    elif q == 10:
        CheckAnswerNum(answer, numFlagsSet)
def R2Q0(questionCounter):
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR2
    Qs = [
        "What is the IMAGE_OPTIONAL_HEADER.Magic value?",
        "What value of the optional header 'Magic' field indicates a 32 bit (PE32) binary?",
        "According to the IMAGE_OPTIONAL_HEADER.Magic, is this a 32 bit (PE32) binary? (Y or N)",
        "What value of the optional header 'Magic' field indicates a 64 bit (PE32+) binary?",
        "According to the IMAGE_OPTIONAL_HEADER.Magic, is this a 64 bit (PE32+) binary? (Y or N)"
    ]
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR2

    #For simplicity, rather than trying to go through the rigamarole of
    #changing the optional header, we just randomly pick whether we open
    #a 32 or 64 bit template
    x = random.randint(0, 1)
    if x:
        if random.randint(0, 1):
            pe = pefile.PE('../template32.exe')
            suffix = ".exe"
        else:
            pe = pefile.PE('../template32.dll')
            suffix = ".dll"
        is32 = "Y"
        is64 = "N"
    else:
        if random.randint(0, 1):
            pe = pefile.PE('../template64.exe')
            suffix = ".exe"
        else:
            pe = pefile.PE('../template64.dll')
            suffix = ".dll"
        is32 = "N"
        is64 = "Y"

    #FIXME: what's the more graceful way of doing this?
    error = 1
    while error:
        try:
            #write out the (actually un)modified file
            outFileName = "Round2Q" + str(questionCounter) + suffix
            pe.write(filename=outFileName)
            error = 0
        except IOError:
            questionCounter += 1

    #Print the question
    q = random.randint(0, len(Qs) - 1)
    print "For binary R2Bins/%s..." % outFileName
    print Qs[q]
    answer = raw_input("Answer: ")

    if q == 0:
        CheckAnswerNum(answer, pe.OPTIONAL_HEADER.Magic)
    elif q == 1:
        CheckAnswerNum(answer, 0x010B)
    elif q == 2:
        CheckAnswerString(answer, is32)
    elif q == 3:
        CheckAnswerNum(answer, 0x020B)
    elif q == 4:
        CheckAnswerString(answer, is64)
Exemplo n.º 14
0
def R1Q5(questionCounter):
    Qs = [
        "Is the IMAGE_FILE_EXECUTABLE_IMAGE file header characteristic set? (Y or N)",
        "Is this file a regular executable (.exe)? (Y or N)",
        "Is the IMAGE_FILE_DLL file header characteristic set? (Y or N)",
        "Is this file a dynamic-link library (.dll)? (Y or N)",
        "Is the IMAGE_FILE_LARGE_ADDRESS_AWARE file header characteristic set? (Y or N)",
        "Does this file support being loaded at an address > 2GB? (Y or N)",
        "Is the IMAGE_FILE_32BIT_MACHINE file header characteristic set? (Y or N)",
        "What is the IMAGE_FILE_HEADER.Characteristics field? ",
        "How many characteristics are set in this file's file header?"
    ]  #,
    #        "According to the file header, is this a 32 or 64 bit binary? (32 or 64)"#Not a good question because it can be set on 64 bit executables just fine
    #        "Is this file a .exe/.sys or .dll? (enter exe, sys, or dll)",#lazy, don't want to deal with the response
    #        "Is this file an executable or dynamic library? (enter \"executable\" or \"library\")"]#lazy, don't want to deal with the response

    #I am not generating any questions about other characteristics, because the
    #point is not to make it a trivia game, but to reinforce information that I
    #think is useful:

    #pick the random question
    q = random.randint(0, len(Qs) - 1)

    currentTime = int(time())
    #For simplicity, rather than trying to go through the rigamarole of
    #changing the optional header, we just randomly pick whether we open
    #a 32 or 64 bit template
    x = random.randint(0, 3)
    if x == 0:
        pe = pefile.PE('../template32.exe')
        binBits = 32
        binTypeStr = "PE"
        isDll = "N"
    elif x == 1:
        pe = pefile.PE('../template64.exe')
        binBits = 64
        binTypeStr = "PE+"
        isDll = "N"
    elif x == 2:
        pe = pefile.PE('../template32.dll')
        binBits = 32
        binTypeStr = "PE"
        isDll = "Y"
    else:
        pe = pefile.PE('../template64.dll')
        binBits = 64
        binTypeStr = "PE+"
        isDll = "Y"

    numFlagsSet = 1
    if isDll == "Y":
        numFlagsSet += 1
    #decide whether to twiddle the bits
    #Found out the hard way just doing something like
    #"pe.FILE_HEADER.IMAGE_FILE_LARGE_ADDRESS_AWARE = True"
    #doesn't effect the file for these characteristics
    if random.randint(0, 1) == 1:
        pe.FILE_HEADER.Characteristics |= 0x20
        isLargeAware = "Y"
        numFlagsSet += 1
    else:
        pe.FILE_HEADER.Characteristics &= ~0x20
        isLargeAware = "N"
    if random.randint(0, 1) == 1:
        pe.FILE_HEADER.Characteristics |= 0x100
        is32Characteristics = "Y"
        numFlagsSet += 1
    else:
        pe.FILE_HEADER.Characteristics &= ~0x100
        is32Characteristics = "N"

    #FIXME: what's the more graceful way of doing this?
    error = 1
    while error:
        try:
            #write out the modified file
            outFileName = "Round1Q" + str(questionCounter) + ".txt"
            pe.write(filename=outFileName)
            error = 0
        except IOError:
            questionCounter += 1

    #Print the question
    print "For binary R1Bins/%s..." % outFileName
    print Qs[q]
    answer = raw_input("Answer: ")

    if q == 0 or q == 1:
        CheckAnswerString(answer, "Y")
    elif q == 2 or q == 3:
        CheckAnswerString(answer, isDll)
    elif q == 4 or q == 5:
        CheckAnswerString(answer, isLargeAware)
    elif q == 6:
        CheckAnswerString(answer, is32Characteristics)
    elif q == 7:
        CheckAnswerNum(answer, pe.FILE_HEADER.Characteristics)
    elif q == 8:
        CheckAnswerNum(answer, numFlagsSet)
Exemplo n.º 15
0
def R1Q4(questionCounter):
    Qs = [
        "How many sections does this binary have?",
        "What is the IMAGE_FILE_HEADER.NumberOfSections field?",
        "Does this binary have %u sections? (Y or N)"
    ]

    #to point out that section names don't have to start with a .
    #and to have easter eggs for the student who becomes the reader :P
    randomSectionNames = [
        ".xeno", "xeno", ".kovah", "kovah", ".foo", ".bar", ".baz", "foobar",
        "foofus", "UPX0", "UPX1", ".UPX2", "SCREEEE!", "HAHAHA", "FOOLISH",
        "MORTAL", "YOU_HAVE", "STEPPED", "INTO_THE", "DEN_OF", "THE...",
        "BASALISK", "<-eht", "<-taehc", "<-edoc", "<-si", "<-x"
    ]

    #pick the random question
    q = random.randint(0, len(Qs) - 1)
    correctNumSections = random.randint(0, 1)
    #print "correctNumSections = %u" % correctNumSections

    x = random.randint(0, 3)
    if x == 0:
        pe = pefile.PE('../template32.exe')
        suffix = ".exe"
    elif x == 1:
        pe = pefile.PE('../template64.exe')
        suffix = ".exe"
    elif x == 2:
        pe = pefile.PE('../template32.dll')
        suffix = ".dll"
    else:
        pe = pefile.PE('../template64.dll')
        suffix = ".dll"

    #Created new function to insert random sections and write the file out
    numExtraSections = random.randint(1, 5)
    #print "numExtraSections = %u" % numExtraSections
    existingNumSections = pe.FILE_HEADER.NumberOfSections
    totalNumSections = existingNumSections + numExtraSections
    #If it picks 5 there is then a 25% chance you will get rickrolled by the
    #section names! (5% chance overall) Easter Egg! :D

    #FIXME: what's the more graceful way of doing this?
    error = 1
    while error:
        try:
            outFileName = "Round1Q" + str(questionCounter) + ".exe"
            #Since we haven't actually modified pe.FILE_HEADER.NumberOfSections in the binary yet
            #this function will know whether to add new sections based on whether the first param
            #is greater than the existing header or not
            pe.x_modifySectionsAndWrite(totalNumSections, randomSectionNames,
                                        1, outFileName)
            pe = pefile.PE(outFileName)
            error = 0
        except IOError:
            questionCounter += 1

    #Print the question
    print "For binary R1Bins/%s..." % outFileName
    if q == 2:
        if correctNumSections:
            interpolatedQuestion = Qs[q] % totalNumSections
            correctStr = "Y"
        else:
            interpolatedQuestion = Qs[q] % (totalNumSections +
                                            random.randint(1, 2))
            correctStr = "N"
    else:
        interpolatedQuestion = Qs[q]

    #ask question
    print interpolatedQuestion
    answer = raw_input("Answer: ")

    if q == 0 or q == 1:
        CheckAnswerNum(answer, pe.FILE_HEADER.NumberOfSections)
    elif q == 2:
        CheckAnswerString(answer, correctStr)
Exemplo n.º 16
0
def R1Q3(questionCounter):
    Qs = [
        "Is this a 32 bit or 64 bit binary? (enter 32 or 64)",
        "Is this a PE32 or PE32+ binary? (enter PE32 or PE32+)",
        "What is the IMAGE_FILE_HEADER.Machine field?",
        "What IMAGE_FILE_HEADER.Machine value indicates a 64 bit binary?",
        "What IMAGE_FILE_HEADER.Machine value indicates a 32 bit binary?"
    ]

    #pick the random question
    q = random.randint(0, len(Qs) - 1)

    #For simplicity, rather than trying to go through the rigamarole of
    #changing the optional header, we just randomly pick whether we open
    #a 32 or 64 bit template
    x = random.randint(0, 1)
    if x:
        if random.randint(0, 1):
            pe = pefile.PE('../template32.exe')
            suffix = ".exe"
        else:
            pe = pefile.PE('../template32.dll')
            suffix = ".dll"
        binType = 32
        binTypeStr = "PE32"
    else:
        if random.randint(0, 1):
            pe = pefile.PE('../template64.exe')
            suffix = ".exe"
        else:
            pe = pefile.PE('../template64.dll')
            suffix = ".dll"
        binType = 64
        binTypeStr = "PE32+"
    #print "selected %s binary" % binTypeStr

    #In the future we might want to make modifications to the template binary in every case
    #but for now I don't think it significantly improves the learning, and it's just extra work ;)

    #FIXME: what's the more graceful way of doing this?
    error = 1
    while error:
        try:
            #write out the (actually un)modified file
            outFileName = "Round1Q" + str(questionCounter) + ".exe"
            pe.write(filename=outFileName)
            error = 0
        except IOError:
            questionCounter += 1

    #Print the question
    print "For binary R1Bins/%s..." % outFileName
    print Qs[q]
    answer = raw_input("Answer: ")

    if q == 0:
        CheckAnswerNum(answer, binType)
    elif q == 1:
        CheckAnswerString(answer, binTypeStr)
    elif q == 2:
        if binType == 32:
            CheckAnswerNum(answer, 0x014C)
        else:
            CheckAnswerNum(answer, 0x8664)
    elif q == 3:
        CheckAnswerNum(answer, 0x8664)
    elif q == 4:
        CheckAnswerNum(answer, 0x014C)