Beispiel #1
0
def R5Q0(questionCounter):
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR5
    Qs = [
        "What is the value of IMAGE_OPTIONAL_HEADER.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].RVA?",
        "What is the RVA that points at the bound import directory table?",
        "What is the value of IMAGE_OPTIONAL_HEADER.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size?",
        "What is the size of the bound import directory table?",
        "What is the value of IMAGE_OPTIONAL_HEADER.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].RVA?",
        "What is the RVA that points directly at the delay-load Import Address Table (IAT)?",
        "What is the value of IMAGE_OPTIONAL_HEADER.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].Size?",
        "What is the total size of the delay-load Import Address Table (IAT)?"
    ]
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR5

    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"
    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 = "Round5Q" + 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 R5Bins/%s..." % outFileName
    print Qs[q]
    answer = raw_input("Answer: ")

    if q == 0 or q == 1:
        CheckAnswerNum(answer,
                       pe.OPTIONAL_HEADER.DATA_DIRECTORY[11].VirtualAddress)
    elif q == 2 or q == 3:
        CheckAnswerNum(answer, pe.OPTIONAL_HEADER.DATA_DIRECTORY[11].Size)
    elif q == 4 or q == 5:
        CheckAnswerNum(answer,
                       pe.OPTIONAL_HEADER.DATA_DIRECTORY[13].VirtualAddress)
    elif q == 6 or q == 7:
        CheckAnswerNum(answer, pe.OPTIONAL_HEADER.DATA_DIRECTORY[13].Size)
Beispiel #2
0
def R1Q1(questionCounter):
    Qs = [
        "How far into the binary is the IMAGE_NT_HEADERS structure?",
        "How far into the binary is the structure with the 'PE' signature?",
        "What is the IMAGE_DOS_HEADER.e_lfanew?",
        "What is the offset from the end of the IMAGE_DOS_HEADER to the IMAGE_NT_HEADERS?"
    ]

    #Open the binary and manipulate IMAGE_DOS_HEADER.e_lfanew
    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"

    #pe.write(filename=outFileName)
    #Made a new function in pefile which also writes the file
    #Create a random sized (but less than 0x200) byte list
    bytelist = ['\x41'] * 4 * random.randint(0, 128)
    #Insert the byte string wherever the DOS_HEADER.e_lfanew currently says it is
    #FIXME: what's the more graceful way of doing this?
    error = 1
    while error:
        try:
            outFileName = "Round1Q" + str(questionCounter) + suffix
            pe.x_randomize_NT_HEADER_location(bytelist, pe.DOS_HEADER.e_lfanew,
                                              outFileName)
            pe = pefile.PE(outFileName)
            error = 0
        except IOError:
            questionCounter += 1

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

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

    #Check the answer
    if q == 3:
        #When it's question [3] we're actually looking for a difference from the end
        #of the DOS header not just from the beginning of the file
        CheckAnswerNum(answer, (pe.DOS_HEADER.e_lfanew -
                                list(pe.DOS_HEADER.__pack__()).__len__()))
    else:
        CheckAnswerNum(answer, pe.DOS_HEADER.e_lfanew)
def R2Q4(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.FileAlignment?",
        "What is the alignment needed to align section data *in the file*?",
        "What is the value of IMAGE_OPTIONAL_HEADER.SectionAlignment?",
        "What is the alignment needed to align section information *in memory*?",
    ]
    #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"

    #TODO: randomize this a bit (just want to get the basics of the question for now)

    #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)
    #  if q == 0 or q == 1:
    #    print "answer = %x" % pe.OPTIONAL_HEADER.FileAlignment
    #  if q == 2 or q == 3:
    #    print "answer = %x" % pe.OPTIONAL_HEADER.SectionAlignment
    print "For binary R2Bins/%s..." % outFileName
    print Qs[q]
    answer = raw_input("Answer: ")

    if q == 0 or q == 1:
        CheckAnswerNum(answer, pe.OPTIONAL_HEADER.FileAlignment)
    if q == 2 or q == 3:
        CheckAnswerNum(answer, pe.OPTIONAL_HEADER.SectionAlignment)
def R2Q1(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.AddressOfEntryPoint?",
        "What is the RVA of the first code which executes in this binary?",
        "What is the VA of the first code which executes in this binary?"
    ]
    #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"

    #TODO: randomize this a bit (just want to get the basics of the question for now)

    #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 or q == 1:
        CheckAnswerNum(answer, pe.OPTIONAL_HEADER.AddressOfEntryPoint)
    elif q == 2:
        CheckAnswerNum(
            answer, pe.OPTIONAL_HEADER.AddressOfEntryPoint +
            pe.OPTIONAL_HEADER.ImageBase)
def R2Q3(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.SizeOfImage?",
        "What is the total amount of memory this binary will reserve in memory?"
    ]
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR2

    #Just reusing the capability from R1Q4
    randomSectionNames = [
        ".xeno", "xeno", ".kovah", "kovah", ".foo", ".bar", ".baz", "foobar",
        "foofus", "ONCE", "A_JOLLY", "SWAGMAN", "CAMPED", "BY_A", "BILABONG",
        "UNDER", "THE", "SHADE", "OF_A", "COOLIBAH", "TREE...", "AND_THEN",
        "A", "BASALISK", "GOT_HIM!"
        "<-eht", "<-taehc", "<-edoc", "<-si", "<-s"
    ]

    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
    #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
            #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
    q = random.randint(0, len(Qs) - 1)
    #  print "answer = %x" % pe.OPTIONAL_HEADER.SizeOfImage
    print "For binary R2Bins/%s..." % outFileName
    print Qs[q]
    answer = raw_input("Answer: ")

    if q == 0 or q == 1:
        CheckAnswerNum(answer, pe.OPTIONAL_HEADER.SizeOfImage)
Beispiel #6
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 R2Q2(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.ImageBase?",
        "What is the preferred VA this binary would like to be loaded into memory at?"
    ]
    #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"

    newBase = 0x10000 * random.randint(0, 0x1000)
    pe.relocate_image(newBase)
    pe.OPTIONAL_HEADER.ImageBase = newBase

    #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 "answer = %x" % pe.OPTIONAL_HEADER.ImageBase
    print "For binary R2Bins/%s..." % outFileName
    print Qs[q]
    answer = raw_input("Answer: ")

    if q == 0 or q == 1:
        CheckAnswerNum(answer, newBase)
Beispiel #8
0
def R5Q2(questionCounter):
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR5
    Qs = [
        "How many ImgDelayDescr structures are in the delayed import directory table (excluding the null entry)?",
        "How many DLLs are referenced by the delay import directory table?",
        "What is the RVA of the delayed IAT for %s?",
        "What is the VA of the delayed IAT for %s?",
        "What is the RVA of the delayed INT for %s?",
        "What is the VA of the delayed INT for %s?"
    ]
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR5

    possibleDLLNames = [
        "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,
        1)  #FIXME: change back to 0,3 when 64 bit delay load stuff is working
    if x == 0:
        pe = pefile.PE('../template32-bound.exe')
        suffix = ".exe"
    elif x == 1:
        pe = pefile.PE('../template32-bound.dll')
        suffix = ".dll"
    elif x == 2:
        pe = pefile.PE('../template64-bound.exe')
        suffix = ".exe"
    else:
        pe = pefile.PE('../template64-bound.dll')
        suffix = ".dll"

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

    numDelayLoadEntries = random.randint(1, 4)
    i = 0
    randomDllList = []
    randomFunctionsList = []
    while i < numDelayLoadEntries:
        #meh, don't care if we get duplicates for now
        randomDllList.append(possibleDLLNames[random.randint(
            0,
            len(possibleDLLNames) - 1)])
        randomFunctionsList += [[]]
        randomFunctionsList[i] += GetExportsByName(randomDllList[i])
        i += 1

    #FIXME: what's the more graceful way of doing this?
    error = 1
    while error:
        try:
            #This will create a new section, ".dload", with a bunch of fake entries for delay load imports
            pe.x_CreateDelayLoadEntries(randomDllList, randomFunctionsList,
                                        outFileName)
            #reopen so we can pick a random delay load entry
            pe = pefile.PE(outFileName)
            error = 0
        except IOError:
            questionCounter += 1

    #select random existing DLL being imported from
    entry = pe.DIRECTORY_ENTRY_DELAY_IMPORT[random.randint(
        0,
        len(pe.DIRECTORY_ENTRY_DELAY_IMPORT) - 1)]

    #Print the question
    q = random.randint(0, len(Qs) - 1)
    if q <= 1:
        interpolatedQuestion = Qs[q]
    else:
        interpolatedQuestion = Qs[q] % entry.dll

    print "For binary R5Bins/%s..." % outFileName
    print interpolatedQuestion
    answer = raw_input("Answer: ")

    if q == 0 or q == 1:
        CheckAnswerNum(answer, len(pe.DIRECTORY_ENTRY_DELAY_IMPORT))
    if q == 2:
        CheckAnswerNum(answer, entry.struct.pIAT)
    if q == 3:
        CheckAnswerNum(answer,
                       pe.OPTIONAL_HEADER.ImageBase + entry.struct.pIAT)
    if q == 4:
        CheckAnswerNum(answer, entry.struct.pINT)
    if q == 5:
        CheckAnswerNum(answer,
                       pe.OPTIONAL_HEADER.ImageBase + entry.struct.pINT)
Beispiel #9
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)
Beispiel #10
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)
Beispiel #11
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)
Beispiel #12
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)
Beispiel #13
0
def R1Q2(questionCounter):
    Qs = [
        "What year was this binary compiled according to the file header TimeDateStamp?",
        "What is the IMAGE_FILE_HEADER's TimeDateStamp?",
        "How many years old is this binary? (round down)"
    ]

    #Open the binary and manipulate FILE_HEADER.TimeDateStamp
    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 the random question
    q = random.randint(0, len(Qs) - 1)

    currentTime = int(time())
    #If we happen to get the [2]nd question, we need a binary
    #that's older than the current year
    if q == 2:
        pe.FILE_HEADER.TimeDateStamp = random.randint(0, currentTime)
    #otherwise it can just be from whenever
    else:
        pe.FILE_HEADER.TimeDateStamp = random.randint(0, 4294967296)

    #print "selected random TimeDateStamp = %u" % pe.FILE_HEADER.TimeDateStamp

    #31556926 seconds per year as far as epoc time is concerned
    #so divide by that many to get the year
    binaryYear = 1970 + int(pe.FILE_HEADER.TimeDateStamp / 31556926)
    #print binaryYear
    currentYear = 1970 + int(currentTime / 31556926)

    #write out the modified file
    #FIXME: what's the more graceful way of doing this?
    error = 1
    while error:
        try:
            outFileName = "Round1Q" + str(questionCounter) + suffix
            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, binaryYear)
    elif q == 1:
        CheckAnswerNum(answer, pe.FILE_HEADER.TimeDateStamp)
    elif q == 2:
        CheckAnswerNum(answer, int(currentYear - binaryYear))
def R6Q1(questionCounter):
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR6
    Qs = ["What is the RVA of %s", "What is the ordinal of %s"]
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR6

    #Randomly chosen function names which will point at faux funcs
    funcs = [
        "FunkyTown", "Func-yTown", "Karate", "Jujitsu", "TaeKwonDo",
        "DorKwonDo", "Judo", "Kickboxing", "DeleteHD", "PwnSauce",
        "JumpTheShark", "WakeUpNeo", "TheMatrixHasYou", "FollowTheWhiteRabbit",
        "KnockKnock", "Pro-rate", "Intimidate", "Inculcate", "Obviate",
        "Instantiate", "Devastate", "Infiltrate", "Obliviate", "Annihilate",
        "Eradicate", "KILLKILLKILL", "CheepSaram", "HousePersonLOL",
        "WonSoongEe", "EeShimNiDa", "Naaaay", "ChaDongCha", "NengJangGo",
        "PeeHenGee", "Add", "Sub", "Mul", "Div", "Mod", "AND", "OR", "XOR",
        "NOR", "NAND", "MakeMountainFromMolehill", "LookGiftHorseInTheMouth",
        "BurnCandleAtBothEnds", "SqeezeCharmin",
        "CountChickensBeforeTheyreHatched", "PlayWithFood",
        "CryOverSpilledMilk", "VoteWolverine", "VoteLobo", "BeginPhase2",
        "OpenThePortal", "GetAngry", "GetEven", "GetOdd", "GetShorty",
        "GetBusy", "GetGone"
    ]

    x = random.randint(0, 0)
    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 = "Round6Q" + str(questionCounter) + suffix
            pe.x_CreateExports(5, funcs, outFileName)
            pe = pefile.PE(outFileName)
            error = 0
        except IOError:
            questionCounter += 1

    #pick a random export to ask questions about
    randomOrdinal = random.randint(0,
                                   len(pe.DIRECTORY_ENTRY_EXPORT.symbols) - 1)
    randomExport = pe.DIRECTORY_ENTRY_EXPORT.symbols[randomOrdinal]

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

    answer = raw_input("Answer: ")

    if q == 0:
        CheckAnswerNum(answer, randomExport.address)
    elif q == 1:
        CheckAnswerNum(answer, randomOrdinal)
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))
Beispiel #16
0
def R5Q1(questionCounter):
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR5
    Qs = [
        "How many IMAGE_BOUND_IMPORT_DESCRIPTOR structures are in the bound import directory table (excluding the null entry)?",
        "How many DLLs are referenced by the bound import directory table?",
        "What is the value of IMAGE_BOUND_IMPORT_DESCRIPTOR.OffsetModuleName for %s?",
        "How far is it from the start of the bound import directory table to the string for %s?",
        "What is the value of IMAGE_BOUND_IMPORT_DESCRIPTOR.TimeDateStamp for %s?",
        "For the %s that bound imports were bound against, what year was it compiled?"
    ]
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR5

    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"
    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 = "Round5Q" + str(questionCounter) + suffix
            pe.write(outFileName)
            error = 0
        except IOError:
            questionCounter += 1

    #pick a random bound import entry
    entry = pe.DIRECTORY_ENTRY_BOUND_IMPORT[random.randint(
        0,
        len(pe.DIRECTORY_ENTRY_BOUND_IMPORT) - 1)]
    #Print the question
    q = random.randint(0, len(Qs) - 1)
    if q <= 1:
        interpolatedQuestion = Qs[q]
    else:
        interpolatedQuestion = Qs[q] % entry.name

    print "For binary R5Bins/%s..." % outFileName
    print interpolatedQuestion
    answer = raw_input("Answer: ")

    if q == 0 or q == 1:
        CheckAnswerNum(answer, len(pe.DIRECTORY_ENTRY_BOUND_IMPORT))
    elif q == 2 or q == 3:
        CheckAnswerNum(answer, entry.struct.OffsetModuleName)
    elif q == 4:
        CheckAnswerNum(answer, entry.struct.TimeDateStamp)
    elif q == 5:
        binaryYear = 1970 + int(entry.struct.TimeDateStamp / 31556926)
        CheckAnswerNum(answer, binaryYear)
Beispiel #17
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)
Beispiel #18
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)
Beispiel #19
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)
Beispiel #20
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)
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)
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)
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)
Beispiel #24
0
def R8Q0(questionCounter):
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR8
    Qs = [
        "What is the RVA of the TLS directory?",
        "What is the VA of the TLS directory?",
        "What is the file offset to the TLS directory?",
        "What is the RVA of the TLS callbacks array?",
        "What is the VA of the TLS callbacks array?",
        "What is the file offset to the TLS callbacks array?",
        "How many TLS callbacks does this binary contain?",
        "What is the RVA of callback index %u?",
        "What is the VA of callback index %u?"
    ]
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR8

    #TODO: currently I just made one template file that has 5 functions that can possibly be called
    #and the code will just add or subtract pointers in the callback table to these functions
    x = random.randint(0, 0)
    if x == 0:
        pe = pefile.PE('../template32-tls.exe')
        suffix = ".exe"


#  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"

    numTlsEntries = random.randint(1, 5)
    #TODO: randomly and independently pick numTlsEntries entries from the binary's exports
    randomCallbackAddressesList = [0x401000] * numTlsEntries
    randomCallbackAddressesList += [
        0
    ]  #easier to just add the null terminator here
    #FIXME: what's the more graceful way of doing this?
    error = 1
    while error:
        try:
            outFileName = "Round8Q" + str(questionCounter) + suffix
            pe.x_CreateTLS(randomCallbackAddressesList, outFileName)
            error = 0
        except IOError:
            questionCounter += 1

    pe = pefile.PE(outFileName)

    q = random.randint(0, len(Qs) - 1)
    print "For binary R8Bins/%s..." % outFileName
    if q >= 7:
        randIndex = random.randint(0, numTlsEntries - 1)
        interpolatedQuestion = Qs[q] % randIndex
    else:
        interpolatedQuestion = Qs[q]
    print interpolatedQuestion
    answer = raw_input("Answer: ")

    if q == 0:
        CheckAnswerNum(answer,
                       pe.OPTIONAL_HEADER.DATA_DIRECTORY[9].VirtualAddress)
    elif q == 1:
        CheckAnswerNum(
            answer, pe.OPTIONAL_HEADER.ImageBase +
            pe.OPTIONAL_HEADER.DATA_DIRECTORY[9].VirtualAddress)
    elif q == 2:
        CheckAnswerNum(answer, pe.DIRECTORY_ENTRY_TLS.struct.get_file_offset())
    elif q == 3:
        CheckAnswerNum(
            answer, pe.DIRECTORY_ENTRY_TLS.struct.AddressOfCallBacks -
            pe.OPTIONAL_HEADER.ImageBase)
    elif q == 4:
        CheckAnswerNum(answer,
                       pe.DIRECTORY_ENTRY_TLS.struct.AddressOfCallBacks)
    elif q == 5:
        CheckAnswerNum(
            answer,
            pe.get_offset_from_rva(
                pe.DIRECTORY_ENTRY_TLS.struct.AddressOfCallBacks -
                pe.OPTIONAL_HEADER.ImageBase))
    elif q == 6:
        CheckAnswerNum(answer, numTlsEntries)
    elif q == 7:
        callbackArray = pe.DIRECTORY_ENTRY_TLS.struct.AddressOfCallBacks - pe.OPTIONAL_HEADER.ImageBase
        CheckAnswerNum(
            answer,
            pe.get_dword_at_rva(callbackArray + randIndex * 4) -
            pe.OPTIONAL_HEADER.ImageBase)
    elif q == 8:
        callbackArray = DIRECTORY_ENTRY_TLS.struct.AddressOfCallBacks - pe.OPTIONAL_HEADER.ImageBase
        CheckAnswerNum(answer,
                       pe.get_dword_at_rva(callbackArray + randIndex * 4))
Beispiel #25
0
def R3Q0(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 of IMAGE_SECTION_HEADER.VirtualAddress?",
        "What is the RVA this section will be loaded at?",
        "What is the VA this section will be loaded at?",
        "What is the value of IMAGE_SECTION_HEADER.Misc.VirtualSize?",
        "How much virtual memory will this section occupy?",
        "What is the RVA of the first byte of memory after this section?",
        "What is the VA of the first byte of memory after this section?",
        "What is the value of IMAGE_SECTION_HEADER.PointerToRawData?",
        "How far into the file on disk is the data for this section?",
        "What is the file offset for this section's data?",
        "What is the value of IMAGE_SECTION_HEADER.SizeOfRawData?",
        "How much space does this section's data occupy on disk?",
        "What is the file offset for the first byte of data after this section?"]
  #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"

  RandomizeSectionNames(pe)
  
  #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
  
  #pick a random section
  randSectIndex = random.randint(0,len(pe.sections)-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 or q == 1:
    CheckAnswerNum(answer, pe.sections[randSectIndex].VirtualAddress)
  if q == 2:
    CheckAnswerNum(answer, pe.OPTIONAL_HEADER.ImageBase + pe.sections[randSectIndex].VirtualAddress)
  if q == 3 or q == 4:
    CheckAnswerNum(answer, pe.sections[randSectIndex].Misc_VirtualSize)
  if q == 5:
    CheckAnswerNum(answer, (pe.sections[randSectIndex].VirtualAddress + pe.sections[randSectIndex].Misc_VirtualSize))
  if q == 6:
    CheckAnswerNum(answer, (pe.OPTIONAL_HEADER.ImageBase + pe.sections[randSectIndex].VirtualAddress + pe.sections[randSectIndex].Misc_VirtualSize))
  if q == 7 or q == 8 or q == 9:
    CheckAnswerNum(answer, pe.sections[randSectIndex].PointerToRawData)
  if q == 10 or q == 11:
    CheckAnswerNum(answer, pe.sections[randSectIndex].SizeOfRawData)
  if q == 12:
    CheckAnswerNum(answer, (pe.sections[randSectIndex].PointerToRawData + pe.sections[randSectIndex].SizeOfRawData))    
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")
Beispiel #27
0
def R10Q0(questionCounter):
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR8
    Qs = [
        "What is the RVA of the load configuration directory?",
        "What is the VA of the load configuration directory?",
        "What is the file offset to the load configuration directory?",
        "What is the RVA of the security cookie used for buffer overflow protection?",
        "What is the RVA of the stack cookie (canary) added when the /GS compile option is used?",
        "What is the VA of the security cookie used for buffer overflow protection?",
        "What is the VA of the stack cookie (canary) added when the /GS compile option is used?",
        "What is the RVA of the structured exception handler table?",
        "What is the RVA of the table used when /SAFESEH linker option is used?",
        "What is the VA of the security cookie used for buffer overflow protection?",
        "What is the VA of the table used when /SAFESEH linker option is used?",
        "How many SEH handlers are available in this binary?"
    ]
    #NOTE: if you update the number of questions in this function, you need to update the boundaries in StartR8

    #TODO: currently I just made one template file that has 5 functions that can possibly be called
    #and the code will just add or subtract pointers in the callback table to these functions
    x = random.randint(0, 1)
    if x == 0:
        pe = pefile.PE('../template32.exe')
        suffix = ".exe"
    elif x == 1:
        pe = pefile.PE('../template32.dll')
        suffix = ".dll"

    #Add some misc randomizations
    #TODO: make these actually consistent with the binaries
    pe.DIRECTORY_ENTRY_LOAD_CONFIG.struct.SecurityCookie += random.randint(
        0, 10) * 0x1000
    pe.DIRECTORY_ENTRY_LOAD_CONFIG.struct.SEHandlerTable += random.randint(
        0, 10) * 0x100
    pe.DIRECTORY_ENTRY_LOAD_CONFIG.struct.SEHandlerCount = random.randint(
        0, 10)

    #FIXME: what's the more graceful way of doing this?
    error = 1
    while error:
        try:
            outFileName = "Round10Q" + 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 R10Bins/%s..." % outFileName
    print Qs[q]
    answer = raw_input("Answer: ")

    if q == 0:
        CheckAnswerNum(answer,
                       pe.OPTIONAL_HEADER.DATA_DIRECTORY[10].VirtualAddress)
    elif q == 1:
        CheckAnswerNum(
            answer, pe.OPTIONAL_HEADER.ImageBase +
            pe.OPTIONAL_HEADER.DATA_DIRECTORY[10].VirtualAddress)
    elif q == 2:
        CheckAnswerNum(answer,
                       pe.DIRECTORY_ENTRY_LOAD_CONFIG.struct.get_file_offset())
    elif q == 3 or q == 4:
        CheckAnswerNum(
            answer, pe.DIRECTORY_ENTRY_LOAD_CONFIG.struct.SecurityCookie -
            pe.OPTIONAL_HEADER.ImageBase)
    elif q == 5 or q == 6:
        CheckAnswerNum(answer,
                       pe.DIRECTORY_ENTRY_LOAD_CONFIG.struct.SecurityCookie)
    elif q == 7 or q == 8:
        CheckAnswerNum(
            answer, pe.DIRECTORY_ENTRY_LOAD_CONFIG.struct.SEHandlerTable -
            pe.OPTIONAL_HEADER.ImageBase)
    elif q == 9 or q == 10:
        CheckAnswerNum(answer,
                       pe.DIRECTORY_ENTRY_LOAD_CONFIG.struct.SEHandlerTable)
    elif q == 11:
        CheckAnswerNum(answer,
                       pe.DIRECTORY_ENTRY_LOAD_CONFIG.struct.SEHandlerCount)