Index: tools/ipoddfu/ipoddfu.py |
— | — | @@ -0,0 +1,33 @@ |
| 2 | +#!/usr/bin/env python
|
| 3 | +#
|
| 4 | +#
|
| 5 | +# Copyright 2010 TheSeven
|
| 6 | +#
|
| 7 | +#
|
| 8 | +# This file is part of TheSeven's iPod tools.
|
| 9 | +#
|
| 10 | +# TheSeven's iBugger is free software: you can redistribute it and/or
|
| 11 | +# modify it under the terms of the GNU General Public License as
|
| 12 | +# published by the Free Software Foundation, either version 2 of the
|
| 13 | +# License, or (at your option) any later version.
|
| 14 | +#
|
| 15 | +# TheSeven's iBugger is distributed in the hope that it will be useful,
|
| 16 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 17 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 18 | +# See the GNU General Public License for more details.
|
| 19 | +#
|
| 20 | +# You should have received a copy of the GNU General Public License along
|
| 21 | +# with TheSeven's iPod tools. If not, see <http://www.gnu.org/licenses/>.
|
| 22 | +#
|
| 23 | +#
|
| 24 | +
|
| 25 | +
|
| 26 | +import sys
|
| 27 | +import libipoddfu
|
| 28 | +
|
| 29 | +if len(sys.argv) != 2:
|
| 30 | + print "Syntax: ipoddfu.py <file>"
|
| 31 | + exit(2)
|
| 32 | +
|
| 33 | +dev = libipoddfu.ipoddfu()
|
| 34 | +dev.uploadfile(sys.argv[1])
|
Index: tools/ipoddfu/libipoddfu.py |
— | — | @@ -0,0 +1,148 @@ |
| 2 | +#!/usr/bin/env python
|
| 3 | +#
|
| 4 | +#
|
| 5 | +# Copyright 2010 TheSeven
|
| 6 | +#
|
| 7 | +#
|
| 8 | +# This file is part of TheSeven's iPod tools.
|
| 9 | +#
|
| 10 | +# TheSeven's iBugger is free software: you can redistribute it and/or
|
| 11 | +# modify it under the terms of the GNU General Public License as
|
| 12 | +# published by the Free Software Foundation, either version 2 of the
|
| 13 | +# License, or (at your option) any later version.
|
| 14 | +#
|
| 15 | +# TheSeven's iBugger is distributed in the hope that it will be useful,
|
| 16 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 17 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 18 | +# See the GNU General Public License for more details.
|
| 19 | +#
|
| 20 | +# You should have received a copy of the GNU General Public License along
|
| 21 | +# with TheSeven's iPod tools. If not, see <http://www.gnu.org/licenses/>.
|
| 22 | +#
|
| 23 | +#
|
| 24 | +
|
| 25 | +
|
| 26 | +import sys
|
| 27 | +import struct
|
| 28 | +import usb.core
|
| 29 | +
|
| 30 | +
|
| 31 | +class ipoddfu:
|
| 32 | + def __init__(self, generation = 0, type = 0):
|
| 33 | + self.dev = usb.core.find(idVendor=0x05ac, idProduct=0x1220)
|
| 34 | + if self.dev and generation in [0, 2] and type in [0, 1]:
|
| 35 | + self.dev.set_configuration(1)
|
| 36 | + self.generation = 2;
|
| 37 | + self.type = 1;
|
| 38 | + print("Connected to S5L8701 Bootrom DFU mode, USB version %s" % self.dev.bcdDevice)
|
| 39 | + return
|
| 40 | + self.dev = usb.core.find(idVendor=0x05ac, idProduct=0x1240)
|
| 41 | + if self.dev and generation in [0, 2] and type in [0, 2]:
|
| 42 | + self.dev.set_configuration(1)
|
| 43 | + self.generation = 2;
|
| 44 | + self.type = 2;
|
| 45 | + print("Connected to iPod Nano 2G NOR DFU mode, USB version %s" % self.dev.bcdDevice)
|
| 46 | + return
|
| 47 | + self.dev = usb.core.find(idVendor=0x05ac, idProduct=0x1223)
|
| 48 | + if self.dev and generation in [0, 3] and type in [0, 1]:
|
| 49 | + self.dev.set_configuration(1)
|
| 50 | + self.generation = 3;
|
| 51 | + self.type = 1;
|
| 52 | + print("Connected to S5L8702 Bootrom DFU mode, USB version %s" % self.dev.bcdDevice)
|
| 53 | + return
|
| 54 | + self.dev = usb.core.find(idVendor=0x05ac, idProduct=0x1242)
|
| 55 | + if self.dev and generation in [0, 3] and type in [0, 1]:
|
| 56 | + self.dev.set_configuration(1)
|
| 57 | + self.generation = 3;
|
| 58 | + self.type = 2;
|
| 59 | + print("Connected to iPod Nano 3G WTF mode, USB version %s" % self.dev.bcdDevice)
|
| 60 | + return
|
| 61 | + self.dev = usb.core.find(idVendor=0x05ac, idProduct=0x1225)
|
| 62 | + if self.dev and generation in [0, 4] and type in [0, 1]:
|
| 63 | + self.dev.set_configuration(1)
|
| 64 | + self.generation = 4;
|
| 65 | + self.type = 1;
|
| 66 | + print("Connected to S5L8720 Bootrom DFU mode, USB version %s" % self.dev.bcdDevice)
|
| 67 | + return
|
| 68 | + self.dev = usb.core.find(idVendor=0x05ac, idProduct=0x1243)
|
| 69 | + if self.dev and generation in [0, 4] and type in [0, 1]:
|
| 70 | + self.dev.set_configuration(1)
|
| 71 | + self.generation = 4;
|
| 72 | + self.type = 2;
|
| 73 | + print("Connected to iPod Nano 4G WTF mode, USB version %s" % self.dev.bcdDevice)
|
| 74 | + return
|
| 75 | +
|
| 76 | + raise Exception("Could not find specified DFU device (generation = %d, type = %d)" % (generation, type))
|
| 77 | +
|
| 78 | + @staticmethod
|
| 79 | + def crc32(data):
|
| 80 | + crc_table = []
|
| 81 | + for i in range(256):
|
| 82 | + t = i;
|
| 83 | + for j in range(8):
|
| 84 | + if t & 1:
|
| 85 | + t = (t >> 1) ^ 0xedb88320
|
| 86 | + else:
|
| 87 | + t = t >> 1
|
| 88 | + crc_table.append(t)
|
| 89 | +
|
| 90 | + crc = 0xffffffff
|
| 91 | + for i in range(len(data)):
|
| 92 | + crc = (crc >> 8) ^ crc_table[(crc ^ struct.unpack("B", data[i])[0]) & 0xff];
|
| 93 | +
|
| 94 | + return crc
|
| 95 | +
|
| 96 | +
|
| 97 | + def getcpu(self):
|
| 98 | + result = self.handle.controlMsg(0xa1, 0xff, 0x3f, 2, 0, 100)
|
| 99 | + return struct.pack("%dB" % len(result), *result)
|
| 100 | +
|
| 101 | +
|
| 102 | + def upload(self, data, exploit = 0):
|
| 103 | + if exploit == 1 and self.generation == 2 and self.type == 1:
|
| 104 | + data = f.read().ljust(0x200f0, "\0") \
|
| 105 | + + "\xb8\x48\x02\x22\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" \
|
| 106 | + + "\0\0\0\x22\0\0\0\x22\0\0\0\x22\0\0\0\x22" \
|
| 107 | + + "\0\0\0\x22\0\0\0\x22\0\0\0\x22\0\0\0\x22" \
|
| 108 | + + "\0\0\0\x22\0\0\0\x22\0\0\0\x22\0\0\0\x22" \
|
| 109 | + + "\0\0\0\x22\0\0\0\x22\0\0\0\x22\0\0\0\x22" \
|
| 110 | + + "\0\0\0\x22\0\0\0\x22\0\0\0\x22\0\0\0\x22" \
|
| 111 | + + "\0\0\0\x22\0\0\0\x22\0\0\0\x22\0\0\0\x22" \
|
| 112 | + + "\0\0\0\x22\0\0\0\x22\0\0\0\x22\0\0\0\x22" \
|
| 113 | + + "\0\0\0\x22\0\0\0\x22\0\0\0\x22\0\0\0\x22"
|
| 114 | +
|
| 115 | + data = data + struct.pack("<I", self.crc32(data))
|
| 116 | +
|
| 117 | + sys.stdout.write("Upload: .")
|
| 118 | + sys.stdout.flush()
|
| 119 | + for index in range((len(data) + 2047) // 2048):
|
| 120 | + self.dev.ctrl_transfer(0x21, 1, index, 0, data[2048 * index : 2048 * (index + 1)], 100)
|
| 121 | + result = (0, 0, 0, 0, 0, 0)
|
| 122 | + while result[4] != 0x05:
|
| 123 | + result = self.dev.ctrl_transfer(0xa1, 3, 0, 0, 6, 100)
|
| 124 | + sys.stdout.write(".")
|
| 125 | + sys.stdout.flush()
|
| 126 | +
|
| 127 | + self.dev.ctrl_transfer(0x21, 1, index, 0, "", 100)
|
| 128 | + result = (0, 0, 0, 0, 0, 0)
|
| 129 | + index = 0
|
| 130 | + try:
|
| 131 | + while result[4] != 0x02 and index < 1000:
|
| 132 | + result = self.dev.ctrl_transfer(0xa1, 3, 0, 0, 6, 100)
|
| 133 | + index = index + 1
|
| 134 | + except:
|
| 135 | + pass
|
| 136 | +
|
| 137 | + if (exploit == 0 and (index == 1000 or result[4] == 0x02)) or \
|
| 138 | + (exploit == 1 and (index == 1000 or result[4] != 0x04)):
|
| 139 | + print(" failed: %X / %X" % (result[4], result[0]))
|
| 140 | + raise Exception("DFU upload failed! (%X / %X)" % (result[4], result[0]))
|
| 141 | + else:
|
| 142 | + print(" done")
|
| 143 | +
|
| 144 | +
|
| 145 | + def uploadfile(self, file, exploit = 0):
|
| 146 | + f = open(file, "rb")
|
| 147 | + data = f.read()
|
| 148 | + f.close()
|
| 149 | + self.upload(data, exploit)
|