SHOW:
|
|
- or go back to the newest paste.
| 1 | import urllib2 | |
| 2 | from cookielib import CookieJar | |
| 3 | from Crypto.Cipher import AES | |
| 4 | import argparse | |
| 5 | ||
| 6 | cj = CookieJar() | |
| 7 | agentACM = 'AppleCoreMedia/1.0.0.11D201 (iPhone; U; CPU OS 7_1_2 like Mac OS X; en_us)' | |
| 8 | openerACM = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) | |
| 9 | openerACM.addheaders = [('User-agent', agentACM)]
| |
| 10 | ||
| 11 | def getUrl(url): | |
| 12 | response = openerACM.open(url) | |
| 13 | return response.read() | |
| 14 | ||
| 15 | def downloadM3U8(outFile,srcUrl=None,srcFile=None,baseUrl=None,key=None): | |
| 16 | if srcUrl: | |
| 17 | m3u8_data = getUrl(srcUrl) | |
| 18 | m3u8name = srcUrl.split('?')[0].split('/')[-1]
| |
| 19 | parameters = srcUrl.split('?')[1]
| |
| 20 | baseUrl = srcUrl.split('?')[0][:-1*len(m3u8name)]
| |
| 21 | if srcFile: | |
| 22 | m3u8_data = open(srcFile, 'rb').read() | |
| 23 | decrypter = None | |
| 24 | fileObj = open(outFile, 'wb') | |
| 25 | for line in m3u8_data.split('\n'):
| |
| 26 | if line.startswith('#EXT-X-KEY'):
| |
| 27 | if 'METHOD=AES-128' in line: | |
| 28 | if 'URI=' in line: | |
| 29 | if key: | |
| 30 | keyValue = key | |
| 31 | else: | |
| 32 | keyUrl = line.split('URI="')[1].split('"')[0]
| |
| 33 | keyValue = getUrl(keyUrl) | |
| 34 | if 'IV=' in line: | |
| 35 | iv = line.split('IV=0x')[1].decode('hex')
| |
| 36 | else: | |
| 37 | iv = '00000000000000000000000000000000'.decode('hex')
| |
| 38 | - | print 'KEY : %X' % keyValue |
| 38 | + | print 'KEY : %s' % keyValue.encode('hex')
|
| 39 | - | print 'IV : %X' % iv |
| 39 | + | print 'IV : %s' % iv.encode('hex')
|
| 40 | decrypter = AES.new(keyValue, AES.MODE_CBC, iv) | |
| 41 | if not line.startswith('#'):
| |
| 42 | print line.split('?')[0].split('/')[-1]
| |
| 43 | if baseUrl: | |
| 44 | if not (line.startswith('http://') or line.startswith('https://')):
| |
| 45 | line = baseUrl+line | |
| 46 | data = getUrl(line) | |
| 47 | if decrypter: | |
| 48 | data = decrypter.decrypt(data) | |
| 49 | fileObj.write(data) | |
| 50 | fileObj.close() | |
| 51 | ||
| 52 | if __name__=="__main__": | |
| 53 | parser = argparse.ArgumentParser(description='Download-Decrypt M3U8') | |
| 54 | parser.add_argument('-i', dest='input', help='Input M3U8 Url or File', metavar='URL-FILE', required=True)
| |
| 55 | parser.add_argument('-o', dest='outFile', help='Output TS File', metavar='FILE', required=True)
| |
| 56 | parser.add_argument('-baseurl', dest='baseUrl', help='Base Url for input m3u8', metavar='URL')
| |
| 57 | ||
| 58 | parser.add_argument('-key', dest='keyFile', help='Key File', metavar='FILE')
| |
| 59 | parser.add_argument('-keyhex', dest='keyHex', help='Key in Hex', metavar='KEXHEX')
| |
| 60 | ||
| 61 | args = parser.parse_args() | |
| 62 | ||
| 63 | if args.keyFile: key = open(args.keyFile, "rb").read() | |
| 64 | elif args.keyHex: key = args.keyHex.decode('hex')
| |
| 65 | else: key = None | |
| 66 | ||
| 67 | if args.input.startswith('http://') or args.input.startswith('https://'):
| |
| 68 | downloadM3U8(args.outFile,srcUrl=args.input,baseUrl=args.baseUrl,key=key) | |
| 69 | else: | |
| 70 | downloadM3U8(args.outFile,srcFile=args.input,baseUrl=args.baseUrl,key=key) |