├── README.md ├── baleful ├── pintool.py ├── reverse400 └── wyvern /README.md: -------------------------------------------------------------------------------- 1 | # Pintool 2 | 3 | This tool can be useful for solving some reversing challenges in CTFs events. Implements the technique described here: 4 | 5 | - http://shell-storm.org/blog/A-binary-analysis-count-me-if-you-can/ 6 | 7 | 8 | ### Configuration 9 | You must configure your pin PATH inside of script 10 | 11 | ```sh 12 | PIN = "./pin-2.13-62732-gcc.4.4.7-linux/pin" 13 | INSCOUNT32 = "./pin-2.13-62732-gcc.4.4.7-linux/inscount0.so" 14 | INSCOUNT64 = "./pin-2.13-62732-gcc.4.4.7-linux/source/tools/ManualExamples/obj-intel64/inscount0.so" 15 | ``` 16 | 17 | ### Help 18 | 19 | 20 | 21 | ```sh 22 | $python pintool.py 23 | usage: pintool.py [-h] [-e] [-l LEN] [-c NUMBER] [-b CHARACTER] [-a ARCH] 24 | [-i INITPASS] [-s SIMBOL] [-d EXPRESSION] 25 | Filename 26 | 27 | positional arguments: 28 | Filename Program for playing with Pin Tool 29 | 30 | optional arguments: 31 | -h, --help show this help message and exit 32 | -e Study the password length, for example -e -l 40, with 40 33 | characters 34 | -l LEN Length of password (Default: 10 ) 35 | -c NUMBER Charset definition for brute force (1-Lowercase, 2-Uppecase, 36 | 3-Numbers, 4-Hexadecimal, 5-Punctuation, 6-All) 37 | -b CHARACTER Add characters for the charset, example -b _- 38 | -a ARCH Program architecture 32 or 64 bits, -a 32 or -a 64 39 | -i INITPASS Inicial password characters, example -i CTF{ 40 | -s SIMBOL Simbol for complete all password (Default: _ ) 41 | -d EXPRESSION Difference between instructions that are successful or not 42 | (Default: != 0, example -d '== -12', -d '=> 900', -d '<= 17' 43 | or -d '!= 32') 44 | ``` 45 | 46 | 47 | ### Examples 48 | **Baleful - picoCTF 2014** 49 | ```sh 50 | $python pintool.py -l 30 -c 1,2,3 -b _{} -s - baleful 51 | p----------------------------- = 763799 difference -12 instructions 52 | pa---------------------------- = 763787 difference -12 instructions 53 | pac--------------------------- = 763775 difference -12 instructions 54 | pack-------------------------- = 763763 difference -12 instructions 55 | packe------------------------- = 763751 difference -12 instructions 56 | packer------------------------ = 763739 difference -12 instructions 57 | packers----------------------- = 763727 difference -12 instructions 58 | packers_---------------------- = 763715 difference -12 instructions 59 | packers_a--------------------- = 763703 difference -12 instructions 60 | packers_an-------------------- = 763691 difference -12 instructions 61 | packers_and------------------- = 763679 difference -12 instructions 62 | packers_and_------------------ = 763667 difference -12 instructions 63 | packers_and_v----------------- = 763655 difference -12 instructions 64 | packers_and_vm---------------- = 763643 difference -12 instructions 65 | packers_and_vms--------------- = 763631 difference -12 instructions 66 | packers_and_vms_-------------- = 763619 difference -12 instructions 67 | packers_and_vms_a------------- = 763607 difference -12 instructions 68 | packers_and_vms_an------------ = 763595 difference -12 instructions 69 | packers_and_vms_and----------- = 763583 difference -12 instructions 70 | packers_and_vms_and_---------- = 763571 difference -12 instructions 71 | packers_and_vms_and_x--------- = 763559 difference -12 instructions 72 | packers_and_vms_and_xo-------- = 763547 difference -12 instructions 73 | packers_and_vms_and_xor------- = 763535 difference -12 instructions 74 | packers_and_vms_and_xors------ = 763523 difference -12 instructions 75 | packers_and_vms_and_xors_----- = 763511 difference -12 instructions 76 | packers_and_vms_and_xors_o---- = 763499 difference -12 instructions 77 | packers_and_vms_and_xors_oh--- = 763487 difference -12 instructions 78 | packers_and_vms_and_xors_oh_-- = 763475 difference -12 instructions 79 | packers_and_vms_and_xors_oh_m- = 763463 difference -12 instructions 80 | packers_and_vms_and_xors_oh_my = 763463 difference -12 instructions 81 | packers_and_vms_and_xors_oh_my 82 | ``` 83 | 84 | **Reverse 400 - Hack You 2014** 85 | 86 | ```sh 87 | $python pintool.py -l 37 -c 4 -i CTF{ -b }_ -s - -d '=> 651' reverse400 88 | CTF{c________________________________ = 1057174 difference 1300 instructions 89 | CTF{c9_______________________________ = 1058474 difference 1300 instructions 90 | CTF{c9f______________________________ = 1059774 difference 1300 instructions 91 | CTF{c9fd_____________________________ = 1061074 difference 1300 instructions 92 | CTF{c9fd9____________________________ = 1062374 difference 1300 instructions 93 | CTF{c9fd99___________________________ = 1063674 difference 1300 instructions 94 | CTF{c9fd99d__________________________ = 1064974 difference 1300 instructions 95 | CTF{c9fd99de_________________________ = 1066274 difference 1300 instructions 96 | CTF{c9fd99de8________________________ = 1067574 difference 1300 instructions 97 | CTF{c9fd99de8e_______________________ = 1068874 difference 1300 instructions 98 | CTF{c9fd99de8eb______________________ = 1070174 difference 1300 instructions 99 | CTF{c9fd99de8eb0_____________________ = 1071474 difference 1300 instructions 100 | CTF{c9fd99de8eb08____________________ = 1072774 difference 1300 instructions 101 | CTF{c9fd99de8eb082___________________ = 1074074 difference 1300 instructions 102 | CTF{c9fd99de8eb082c__________________ = 1075374 difference 1300 instructions 103 | CTF{c9fd99de8eb082c6_________________ = 1076674 difference 1300 instructions 104 | CTF{c9fd99de8eb082c66________________ = 1077974 difference 1300 instructions 105 | CTF{c9fd99de8eb082c66c_______________ = 1079274 difference 1300 instructions 106 | CTF{c9fd99de8eb082c66c4______________ = 1080574 difference 1300 instructions 107 | CTF{c9fd99de8eb082c66c4c_____________ = 1081874 difference 1300 instructions 108 | CTF{c9fd99de8eb082c66c4ce____________ = 1083174 difference 1300 instructions 109 | CTF{c9fd99de8eb082c66c4ce4___________ = 1084474 difference 1300 instructions 110 | CTF{c9fd99de8eb082c66c4ce40__________ = 1085774 difference 1300 instructions 111 | CTF{c9fd99de8eb082c66c4ce403_________ = 1087074 difference 1300 instructions 112 | CTF{c9fd99de8eb082c66c4ce4039________ = 1088374 difference 1300 instructions 113 | CTF{c9fd99de8eb082c66c4ce4039f19c____ = 1093574 difference 1300 instructions 114 | CTF{c9fd99de8eb082c66c4ce4039f19c4___ = 1094874 difference 1300 instructions 115 | CTF{c9fd99de8eb082c66c4ce4039f19c4f__ = 1096174 difference 1300 instructions 116 | CTF{c9fd99de8eb082c66c4ce4039f19c4fc_ = 1097474 difference 1300 instructions 117 | CTF{c9fd99de8eb082c66c4ce4039f19c4fc} = 1098391 difference 917 instructions 118 | CTF{c9fd99de8eb082c66c4ce4039f19c4fc} 119 | ``` 120 | 121 | **wyvern 500 - CSAW CTF 2015** 122 | 123 | ```sh 124 | $python pintool.py -c 1,2,3 -b _ -s - -a 64 -l 28 wyvern 125 | d--------------------------- = 1505212 difference 10332 instructions 126 | dr-------------------------- = 1515830 difference 10618 instructions 127 | dr4------------------------- = 1521965 difference 6135 instructions 128 | dr4g------------------------ = 1533160 difference 11195 instructions 129 | dr4g0----------------------- = 1539867 difference 6707 instructions 130 | dr4g0n---------------------- = 1546952 difference 7085 instructions 131 | dr4g0n_--------------------- = 1554227 difference 7275 instructions 132 | dr4g0n_o-------------------- = 1566566 difference 12339 instructions 133 | dr4g0n_or------------------- = 1574413 difference 7847 instructions 134 | dr4g0n_or_------------------ = 1582638 difference 8225 instructions 135 | dr4g0n_or_p----------------- = 1591053 difference 8415 instructions 136 | dr4g0n_or_p4---------------- = 1599752 difference 8699 instructions 137 | dr4g0n_or_p4t--------------- = 1608735 difference 8983 instructions 138 | dr4g0n_or_p4tr-------------- = 1618098 difference 9363 instructions 139 | dr4g0n_or_p4tri------------- = 1627651 difference 9553 instructions 140 | dr4g0n_or_p4tric------------ = 1642776 difference 15125 instructions 141 | dr4g0n_or_p4tric1----------- = 1652899 difference 10123 instructions 142 | dr4g0n_or_p4tric1a---------- = 1663001 difference 10102 instructions 143 | dr4g0n_or_p4tric1an--------- = 1673709 difference 10708 instructions 144 | dr4g0n_or_p4tric1an_-------- = 1684701 difference 10992 instructions 145 | dr4g0n_or_p4tric1an_i------- = 1695977 difference 11276 instructions 146 | dr4g0n_or_p4tric1an_it------ = 1707626 difference 11649 instructions 147 | dr4g0n_or_p4tric1an_it5----- = 1719474 difference 11848 instructions 148 | dr4g0n_or_p4tric1an_it5_---- = 1731606 difference 12132 instructions 149 | dr4g0n_or_p4tric1an_it5_L--- = 1744022 difference 12416 instructions 150 | dr4g0n_or_p4tric1an_it5_LL-- = 1756811 difference 12789 instructions 151 | dr4g0n_or_p4tric1an_it5_LLV- = 1769799 difference 12988 instructions 152 | dr4g0n_or_p4tric1an_it5_LLVM = 1785242 difference 15443 instructions 153 | dr4g0n_or_p4tric1an_it5_LLVM 154 | ``` 155 | 156 | License 157 | ---- 158 | 159 | MIT 160 | 161 | ## Contact 162 | For bugs please email me. 163 | -------------------------------------------------------------------------------- /baleful: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wagiro/pintool/d538a79a185fb82ff2eb80360497274bf4a567ee/baleful -------------------------------------------------------------------------------- /pintool.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env/python 2 | #coding: utf8 3 | # 4 | #prog_name= 'pintool.py' 5 | #prog_version = '0.3' 6 | #prog_release = '20151028' 7 | #prog_author = 'Eduardo Garcia Melia' 8 | #prog_author_mail = 'wagiro@gmail.com' 9 | 10 | 11 | import sys 12 | import string as s 13 | import subprocess 14 | import argparse 15 | import re 16 | 17 | 18 | #configure by the user 19 | PIN = "./pin-3.11-97998-g7ecce2dac-gcc-linux/pin" 20 | INSCOUNT32 = "./pin-3.11-97998-g7ecce2dac-gcc-linux/source/tools/ManualExamples/obj-ia32/inscount0.so" 21 | INSCOUNT64 = "./pin-3.11-97998-g7ecce2dac-gcc-linux/source/tools/ManualExamples/obj-intel64/inscount0.so" 22 | 23 | 24 | def start(): 25 | 26 | parser = argparse.ArgumentParser(prog='pintool.py') 27 | parser.add_argument('-e', dest='study', action='store_true', default=False, help='Study the password length, for example -e -l 40, with 40 characters') 28 | parser.add_argument('-l', dest='len', type=str, nargs=1, default='10', help='Length of password (Default: 10 )') 29 | parser.add_argument('-c', dest='number', type=str, default=1, help="Charset definition for brute force\n (1-Lowercase,\n2-Uppecase,\n3-Numbers,\n4-Hexadecimal,\n5-Punctuation,\n6-All)") 30 | parser.add_argument('-b', dest='character', type=str, nargs=1, default='', help='Add characters for the charset, example -b _-') 31 | parser.add_argument('-a', dest='arch', type=str, nargs=1, default='32', help='Program architecture 32 or 64 bits, -b 32 or -b 64 ') 32 | parser.add_argument('-i', dest='initpass', type=str, nargs=1, default='', help='Inicial password characters, example -i CTF{') 33 | parser.add_argument('-s', dest='simbol', type=str, nargs=1, default='_', help='Simbol for complete all password (Default: _ )') 34 | parser.add_argument('-d', dest='expression', type=str, nargs=1, default='!= 0', help="Difference between instructions that are successful or not (Default: != 0, example -d '== -12', -d '=> 900', -d '<= 17' or -d '!= 32')") 35 | parser.add_argument('-r', dest='reverse', action='store_true', default=False, help='Reverse order. Bruteforce from the last character') 36 | parser.add_argument('Filename',help='Program for playing with Pin Tool') 37 | 38 | 39 | if len(sys.argv) < 2: 40 | parser.print_help() 41 | sys.exit() 42 | 43 | args = parser.parse_args() 44 | 45 | return args 46 | 47 | 48 | def getCharset(num,addchar): 49 | char = "" 50 | charset = { '1': s.ascii_lowercase, 51 | '2': s.ascii_uppercase, 52 | '3': s.digits, 53 | '4': s.hexdigits, 54 | '5': s.punctuation, 55 | '6': s.printable} 56 | 57 | 58 | if num is 1: 59 | return charset['1'] 60 | else: 61 | num = num.split(',') 62 | 63 | for i in num: 64 | if 1 <= int(i) <= 6: 65 | i= '%s' % i 66 | char += charset[i] 67 | else: 68 | print "Number %s out of range." % (i) 69 | 70 | return char+''.join(addchar) 71 | 72 | 73 | def pin(passwd): 74 | try: 75 | command = "echo " + passwd + " | " + PIN + " -t " + INSCOUNT + " -- ./"+ args.Filename + " ; cat inscount.out" 76 | output = subprocess.check_output(command,shell=True,stderr=subprocess.PIPE) 77 | except: 78 | print "Unexpected error:", sys.exc_info()[0] 79 | raise 80 | 81 | output = re.findall(r"Count ([\w.-]+)", output) 82 | 83 | return int(''.join(output)) 84 | 85 | 86 | def lengthdetect(passlen): 87 | inicialdifference = 0 88 | for i in range(1,passlen+1): 89 | password = "_"*i 90 | inscount = pin(password) 91 | 92 | if inicialdifference == 0: 93 | inicialdifference = inscount 94 | 95 | print "%s = with %d characters difference %d instructions" %(password, i, inscount-inicialdifference) 96 | 97 | def addchar(initpass, char): 98 | 99 | if args.reverse: 100 | initpass = char + initpass 101 | else: 102 | initpass += char 103 | 104 | return initpass 105 | 106 | 107 | 108 | def solve(initpass,passlen,symbfill,charset,expression): 109 | 110 | 111 | initlen = len(initpass) 112 | 113 | for i in range(initlen,passlen): 114 | 115 | 116 | if args.reverse: 117 | tempassword = symbfill*(passlen-i) + initpass 118 | else: 119 | tempassword = initpass + symbfill*(passlen-i) 120 | 121 | inicialdifference = 0 122 | 123 | if args.reverse: 124 | i = passlen - i 125 | 126 | for char in charset: 127 | 128 | if args.reverse: 129 | password = tempassword[:i-1] + '\\'+char + tempassword[i:] 130 | else: 131 | password = tempassword[:i] + '\\'+char + tempassword[i+1:] 132 | 133 | inscount = pin(password) 134 | 135 | newpass = password.replace("\\","", 1) 136 | 137 | if inicialdifference == 0: 138 | inicialdifference = inscount 139 | 140 | difference = inscount-inicialdifference 141 | 142 | print "%s = %d difference %d instructions" %(newpass, inscount, difference) 143 | 144 | sys.stdout.write("\033[F") 145 | 146 | if "!=" in expression: 147 | if difference != int(number): 148 | print "%s = %d difference %d instructions" %(newpass, inscount, difference) 149 | initpass = addchar(initpass, char) 150 | break 151 | elif "==" in expression: 152 | if difference == int(number): 153 | print "%s = %d difference %d instructions" %(newpass, inscount, difference) 154 | initpass = addchar(initpass, char) 155 | break 156 | elif "<=" in expression: 157 | if difference <= int(number): 158 | print "%s = %d difference %d instructions" %(newpass, inscount, difference) 159 | initpass = addchar(initpass, char) 160 | break 161 | elif "=>" in expression: 162 | if difference >= int(number): 163 | print "%s = %d difference %d instructions" %(newpass, inscount, difference) 164 | initpass = addchar(initpass, char) 165 | break 166 | else: 167 | print "Unknown value for -d option" 168 | sys.exit() 169 | 170 | if char == charset[-1]: 171 | print "\n\nPassword not found, try to change charset...\n" 172 | sys.exit() 173 | 174 | 175 | return password.replace("\\","",1) 176 | 177 | 178 | if __name__ == '__main__': 179 | 180 | args = start() 181 | 182 | initpass = ''.join(args.initpass) 183 | passlen = int(''.join(args.len)) 184 | symbfill = ''.join(args.simbol) 185 | charset = symbfill+getCharset(args.number,args.character) 186 | arch = ''.join(args.arch) 187 | expression = ''.join(args.expression).rstrip() 188 | number = expression.split()[1] 189 | study = args.study 190 | 191 | 192 | if len(initpass) >= passlen: 193 | print "The length of init password must be less than password length." 194 | sys.exit() 195 | 196 | 197 | if passlen > 64: 198 | print "The password must be less than 64 characters." 199 | sys.exit() 200 | 201 | 202 | if len(symbfill) > 1: 203 | print "Only one symbol is allowed." 204 | sys.exit() 205 | 206 | 207 | if arch == "32": 208 | INSCOUNT = INSCOUNT32 209 | elif arch == "64": 210 | INSCOUNT = INSCOUNT64 211 | else: 212 | print "Unknown architecture" 213 | sys.exit() 214 | 215 | 216 | if study is True: 217 | lengthdetect(passlen) 218 | sys.exit() 219 | 220 | 221 | password = solve(initpass,passlen,symbfill,charset,expression) 222 | 223 | print "Password: ", password 224 | -------------------------------------------------------------------------------- /reverse400: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wagiro/pintool/d538a79a185fb82ff2eb80360497274bf4a567ee/reverse400 -------------------------------------------------------------------------------- /wyvern: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wagiro/pintool/d538a79a185fb82ff2eb80360497274bf4a567ee/wyvern --------------------------------------------------------------------------------