├── Examples ├── swdProgrammer.rb ├── testI2C.rb ├── testNRF24L01.rb ├── testParralel.rb ├── testSPI.rb ├── testSPISniffer.rb ├── testSWD.rb ├── testUARTBufferOverflow.rb ├── testUARTConsole.rb └── testUARTFuzzer.rb ├── Firmwares ├── FPGA │ ├── I2C │ │ └── I2C_INTERACT │ │ │ └── HARDSPLOIT_FIRMWARE_FPGA_I2C_INTERACT.rpd │ ├── PARALLEL │ │ └── NO_MUX_PARALLEL_MEMORY │ │ │ └── HARDSPLOIT_FIRMWARE_FPGA_NO_MUX_PARALLEL_MEMORY.rpd │ ├── SPI │ │ ├── SPI_INTERACT │ │ │ └── HARDSPLOIT_FIRMWARE_FPGA_SPI_INTERACT.rpd │ │ └── SPI_SNIFFER │ │ │ └── HARDSPLOIT_FIRMWARE_FPGA_SPI_SNIFFER.rpd │ ├── SWD │ │ └── SWD_INTERACT │ │ │ └── HARDSPLOIT_FIRMWARE_FPGA_SWD_INTERACT.rpd │ ├── TEST │ │ └── TEST_INTERACT │ │ │ └── HARDSPLOIT_FIRMWARE_FPGA_TEST_INTERACT.rpd │ ├── UART │ │ └── UART_INTERACT │ │ │ └── HARDSPLOIT_FIRMWARE_FPGA_UART_INTERACT.rpd │ └── VersionFPGA.rb └── UC │ ├── HARDSPLOIT_FIRMWARE_UC.bin │ └── VersionUC.rb ├── HardsploitAPI ├── Core │ ├── HardsploitAPI.rb │ ├── HardsploitAPI_CONSTANT.rb │ ├── HardsploitAPI_ERROR.rb │ ├── HardsploitAPI_FIRMWARE.rb │ ├── HardsploitAPI_PROGRESS.rb │ └── HardsploitAPI_USB_COMMUNICATION.rb └── Modules │ ├── I2C │ └── HardsploitAPI_I2C.rb │ ├── NO_MUX_PARALLEL_MEMORY │ └── HardsploitAPI_NO_MUX_PARALLEL_MEMORY.rb │ ├── NRF24L01 │ └── HardsploitAPI_NRF24L01.rb │ ├── SPI │ └── HardsploitAPI_SPI.rb │ ├── SPI_SNIFFER │ └── HardsploitAPI_SPI_SNIFFER.rb │ ├── SWD │ ├── HardsploitAPI_SWD.rb │ ├── HardsploitAPI_SWD_DEBUG.rb │ ├── HardsploitAPI_SWD_MEM_AP.rb │ └── HardsploitAPI_SWD_STM32.rb │ ├── TEST │ └── HardsploitAPI_TEST_INTERACT.rb │ └── UART │ └── HardsploitAPI_UART.rb ├── LICENSE.txt ├── README.md └── TRADEMARK /Examples/swdProgrammer.rb: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | 9 | require 'io/console' 10 | require_relative '../HardsploitAPI/Core/HardsploitAPI' 11 | require_relative '../HardsploitAPI/Modules/SWD/HardsploitAPI_SWD' 12 | 13 | def callbackInfo(receiveData) 14 | #print receiveData + "\n" 15 | end 16 | 17 | def callbackData(receiveData) 18 | if receiveData != nil then 19 | puts "received #{receiveData.size}" 20 | p receiveData 21 | else 22 | puts "ISSUE BECAUSE DATA IS NIL" 23 | end 24 | end 25 | 26 | def callbackSpeedOfTransfert(receiveData) 27 | #puts "Speed : #{receiveData}" 28 | end 29 | 30 | def callbackProgress(percent:,startTime:,endTime:) 31 | print "\r\e[#{31}mUpload of FPGA firmware in progress : #{percent}%\e[0m" 32 | #puts "Progress : #{percent}% Start@ #{startTime} Stop@ #{endTime}" 33 | #puts "Elasped time #{(endTime-startTime).round(4)} sec" 34 | end 35 | 36 | #puts "Number of hardsploit detected :#{HardsploitAPI.getNumberOfBoardAvailable}" 37 | 38 | HardsploitAPI.callbackInfo = method(:callbackInfo) 39 | HardsploitAPI.callbackData = method(:callbackData) 40 | HardsploitAPI.callbackSpeedOfTransfert = method(:callbackSpeedOfTransfert) 41 | HardsploitAPI.callbackProgress = method(:callbackProgress) 42 | HardsploitAPI.id = 0 # id of hardsploit 0 for the first one, 1 for the second etc 43 | 44 | HardsploitAPI.instance.getAllVersions 45 | 46 | if ARGV[1] != "nofirmware" then 47 | HardsploitAPI.instance.loadFirmware("SWD") 48 | end 49 | 50 | begin 51 | swd = HardsploitAPI_SWD.new( 52 | memory_start_address: "0x08000000", 53 | memory_size_address: "0x1FFFF7E0", 54 | cpu_id_address: "0xE000ED00", 55 | device_id_address: "0x1FFFF7E8" 56 | ) 57 | 58 | #TO OBTAIN ID CODE 59 | code = swd.obtainCodes 60 | puts "DP.IDCODE: #{code[:DebugPortId].to_s(16)} " 61 | puts "AP.IDCODE: #{code[:AccessPortId].to_s(16)} " 62 | 63 | if ARGV[0] == nil 64 | puts "Write firmware command but path of file not founded" 65 | else 66 | # ERASE FLASH !!!!!!!!!! AND WRITE THE CONTENT OF THE FILE ON THE FLASH 67 | puts "Begin of write" 68 | swd.writeFlash(ARGV[0]) 69 | puts "Write finished" 70 | end 71 | 72 | rescue HardsploitAPI::ERROR::HARDSPLOIT_NOT_FOUND 73 | puts "Hardsploit not found" 74 | rescue HardsploitAPI::ERROR::USB_ERROR 75 | puts "USB ERRROR" 76 | end 77 | -------------------------------------------------------------------------------- /Examples/testI2C.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | require 'io/console' 9 | require_relative '../HardsploitAPI/Core/HardsploitAPI' 10 | require_relative '../HardsploitAPI/Modules/I2C/HardsploitAPI_I2C' 11 | 12 | def callbackInfo(receiveData) 13 | #print receiveData + "\n" 14 | end 15 | 16 | def callbackData(receiveData) 17 | if receiveData != nil then 18 | puts "received #{receiveData.size}" 19 | p receiveData 20 | else 21 | puts "ISSUE BECAUSE DATA IS NIL" 22 | end 23 | end 24 | 25 | def callbackSpeedOfTransfert(receiveData) 26 | #puts "Speed : #{receiveData}" 27 | end 28 | 29 | def callbackProgress(percent:,startTime:,endTime:) 30 | print "\r\e[#{31}mUpload of FPGA firmware in progress : #{percent}%\e[0m" 31 | #puts "Progress : #{percent}% Start@ #{startTime} Stop@ #{endTime}" 32 | #puts "Elasped time #{(endTime-startTime).round(4)} sec" 33 | end 34 | 35 | #puts "Number of hardsploit detected :#{HardsploitAPI.getNumberOfBoardAvailable}" 36 | 37 | HardsploitAPI.callbackInfo = method(:callbackInfo) 38 | HardsploitAPI.callbackData = method(:callbackData) 39 | HardsploitAPI.callbackSpeedOfTransfert = method(:callbackSpeedOfTransfert) 40 | HardsploitAPI.callbackProgress = method(:callbackProgress) 41 | HardsploitAPI.id = 0 # id of hardsploit 0 for the first one, 1 for the second etc 42 | 43 | HardsploitAPI.instance.getAllVersions 44 | 45 | if ARGV[0] != "nofirmware" then 46 | HardsploitAPI.instance.loadFirmware("I2C") 47 | end 48 | 49 | def i2cCustomScan 50 | begin 51 | #Create an instance of I2C 52 | i2c = HardsploitAPI_I2C.new(speed:HardsploitAPI::I2C::KHZ_100) 53 | 54 | #Change the speed 55 | i2c.speed = HardsploitAPI::I2C::KHZ_100 56 | 57 | #scan I2C 58 | puts "I2C SCAN :" 59 | scan_result = i2c.i2c_Scan 60 | #check parity of array index to know if a Read or Write address 61 | # Index 0 is write address because is is even 62 | # Index 1 is read address because it is odd 63 | 64 | # Index 160 (0xA0) is write address because is is even 65 | # Index 161 (0xA1) is read address because is is odd 66 | 67 | #If value is 0 slave address is not available 68 | #If valude is 1 slave address is available 69 | 70 | for i in (0..scan_result.size-1) do 71 | if scan_result[i] == 1 then 72 | puts " #{(i).to_s(16)} #{scan_result[i]}" 73 | end 74 | end 75 | 76 | rescue HardsploitAPI::ERROR::HARDSPLOIT_NOT_FOUND 77 | puts "Hardsploit not found" 78 | rescue HardsploitAPI::ERROR::USB_ERROR 79 | puts "USB ERRROR" 80 | end 81 | end 82 | 83 | def i2cCustomInteract 84 | begin 85 | #Create an instance of I2C 86 | i2c = HardsploitAPI_I2C.new(speed:HardsploitAPI::I2C::KHZ_100) 87 | 88 | testpack = Array.new 89 | 90 | #interact I2C 91 | # write with even address 92 | # read with odd address 93 | 94 | #Write 4 bytes at 0x00 0x00 95 | # testpack.push HardAPI.lowByte(4) #Count Low Byte 96 | # testpack.push HardAPI.highByte(4) #Count High Byte 97 | # testpack.push 0xA0 98 | # testpack.push 41 #First data byte 99 | # testpack.push 42 #Second data byte 100 | # testpack.push 43 101 | # testpack.push 44 102 | 103 | 104 | #Write pointer of I2C memorie at 0x00 0x00 105 | # testpack.push HardsploitAPI.lowByte(word:2) #Count Low Byte 106 | # testpack.push HardsploitAPI.highByte(word:2) #Count High Byte 107 | # testpack.push 0xA0 108 | # testpack.push 0x00 109 | # testpack.push 0x00 110 | 111 | testpack.push HardsploitAPI.lowByte(word:2) #Count Low Byte 112 | testpack.push HardsploitAPI.highByte(word:2) #Count High Byte 113 | testpack.push 0xA0 114 | testpack.push 0x00 115 | testpack.push 0x00 116 | 117 | testpack.push HardsploitAPI.lowByte(word:4) #Count Low Byte 118 | testpack.push HardsploitAPI.highByte(word:4) #Count High Byte 119 | testpack.push 0xA1 120 | 121 | 122 | 123 | 124 | begin 125 | #result contient les ACK NACK ou les data si dispo cf wiki 126 | # https://github.com/OPALESECURITY/hardsploit-api/wiki#i2c-interact 127 | result = i2c.i2c_Interact(payload:testpack) 128 | p result 129 | rescue HardsploitAPI::ERROR::USB_ERROR 130 | puts "Error during USB communication, please retry" 131 | end 132 | 133 | rescue HardsploitAPI::ERROR::HARDSPLOIT_NOT_FOUND 134 | puts "Hardsploit not found" 135 | end 136 | end 137 | 138 | while true 139 | char = STDIN.getch 140 | puts char 141 | if char == "\u0003" 142 | puts "Finished" 143 | exit 144 | 145 | elsif char == "z" then 146 | crossvalue = Array.new 147 | #Default wiring 148 | for i in 0..63 149 | crossvalue.push i 150 | end 151 | 152 | #swap 2 first signal 153 | crossvalue[0] = 8 154 | crossvalue[1] = 9 155 | 156 | crossvalue[8] = 0 157 | crossvalue[9] = 1 158 | 159 | HardsploitAPI.instance.setCrossWiring(value:crossvalue) 160 | 161 | puts "cross SWAP" 162 | 163 | elsif char == "e" then 164 | crossvalue = Array.new 165 | #Default wiring 166 | for i in 0..63 167 | crossvalue.push i 168 | end 169 | HardsploitAPI.instance.setCrossWiring(value:crossvalue) 170 | puts "cross Normal" 171 | 172 | elsif char == "w" then 173 | HardsploitAPI.instance.setStatutLed(led:HardsploitAPI::USB_COMMAND::GREEN_LED,state:true); 174 | elsif char == "x" then 175 | HardsploitAPI.instance.setStatutLed(led:HardsploitAPI::USB_COMMAND::GREEN_LED,state:false); 176 | elsif char == "i" then 177 | i2cCustomInteract 178 | elsif char == "s" then 179 | i2cCustomScan 180 | elsif char == "p" then 181 | print "Upload Firmware check : #{HardsploitAPI.instance.uploadFirmware(pathFirmware:File.expand_path(File.dirname(__FILE__)) + "/../../HARDSPLOIT-VHDL/Firmware/FPGA/I2C/I2C_INTERACT/HARDSPLOIT_FIRMWARE_FPGA_I2C_INTERACT.rpd",checkFirmware:false)}\n" 182 | end 183 | end 184 | -------------------------------------------------------------------------------- /Examples/testNRF24L01.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | require 'io/console' 9 | require_relative '../HardsploitAPI/Core/HardsploitAPI' 10 | require_relative '../HardsploitAPI/Modules/NRF24L01/HardsploitAPI_NRF24L01' 11 | 12 | def callbackInfo(receiveData) 13 | #print receiveData + "\n" 14 | end 15 | 16 | def callbackData(receiveData) 17 | if receiveData != nil then 18 | puts "received #{receiveData.size}" 19 | p receiveData 20 | else 21 | puts "ISSUE BECAUSE DATA IS NIL" 22 | end 23 | end 24 | 25 | def callbackSpeedOfTransfert(receiveData) 26 | #puts "Speed : #{receiveData}" 27 | end 28 | 29 | def callbackProgress(percent:,startTime:,endTime:) 30 | print "\r\e[#{31}mUpload of FPGA firmware in progress : #{percent}%\e[0m" 31 | #puts "Progress : #{percent}% Start@ #{startTime} Stop@ #{endTime}" 32 | #puts "Elasped time #{(endTime-startTime).round(4)} sec" 33 | end 34 | 35 | puts "Number of hardsploit detected :#{HardsploitAPI.getNumberOfBoardAvailable}" 36 | HardsploitAPI.callbackInfo = method(:callbackInfo) 37 | HardsploitAPI.callbackData = method(:callbackData) 38 | HardsploitAPI.callbackSpeedOfTransfert = method(:callbackSpeedOfTransfert) 39 | HardsploitAPI.callbackProgress = method(:callbackProgress) 40 | HardsploitAPI.id = 0 41 | 42 | HardsploitAPI.instance.getAllVersions 43 | 44 | if ARGV[0] != "nofirmware" then 45 | HardsploitAPI.instance.loadFirmware("SPI") 46 | end 47 | 48 | # HARDSPLOIT NRF24L01 49 | # SPI_CLK (pin A0) ===> SCK 50 | # SPI_CS (pin A1) ===> CSN 51 | # SPI_MOSI (pin A2) ===> MOSI 52 | # SPI_MISO (pin A3) ===> MISO 53 | # SPI_PULSE (pin A4) ===> CE 54 | 55 | begin 56 | @nrf = HardsploitAPI_NRF24L01.new 57 | if @nrf.reset then 58 | #You need to change your channel and you address 59 | @nrf.initDrone(channel:98,address:[0x66, 0x88, 0x68, 0x68, 0x68]) 60 | else 61 | raise "NRF24L01 not found" 62 | end 63 | 64 | rescue HardsploitAPI::ERROR::HARDSPLOIT_NOT_FOUND 65 | puts "Hardsploit not found" 66 | rescue HardsploitAPI::ERROR::USB_ERROR 67 | puts "USB ERRROR" 68 | end 69 | 70 | puts "NRF24L01+" 71 | puts "Press p to program hardsploit" 72 | puts "Press r to received" 73 | puts "Press t to transmit" 74 | puts "Press s to sniff all channel" 75 | 76 | while true 77 | char = STDIN.getch 78 | puts char 79 | if char == "\u0003" 80 | puts "Finished" 81 | exit 82 | elsif char == "t" then 83 | datat = [0xFF,0xFF] 84 | @nrf.Send(datat) 85 | puts "Send data" 86 | p datat 87 | elsif char == "r" then 88 | puts "Listen :" 89 | while 1 90 | data = @nrf.Read 91 | if data.size > 0 then 92 | p data 93 | end 94 | end 95 | elsif char == "s" then 96 | puts "Sniffing in progress :" 97 | for i in 90..110 98 | @nrf.NRF24L01_FlushTx() 99 | @nrf.NRF24L01_FlushRx() 100 | @nrf.changeChannel(channel:i) 101 | timeoutValue = 1 # timeout in seconds 102 | 103 | #read during 1 second to verify if something is available 104 | timeBegin = Time.now 105 | while(1) 106 | if(Time.now - timeBegin) > timeoutValue then 107 | puts "Nothing to read on channel #{i} after #{timeoutValue} second" 108 | break 109 | end 110 | data = @nrf.Read 111 | if data.size > 0 then 112 | puts "Something is available on channel #{i}, you need to read this channel now" 113 | p data 114 | break 115 | end 116 | end 117 | end 118 | 119 | elsif char == "p" then 120 | HardsploitAPI.instance.loadFirmware("SPI") 121 | end 122 | end 123 | -------------------------------------------------------------------------------- /Examples/testParralel.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | require 'io/console' 9 | require_relative '../HardsploitAPI/Core/HardsploitAPI' 10 | require_relative '../HardsploitAPI/Modules/NO_MUX_PARALLEL_MEMORY/HardsploitAPI_NO_MUX_PARALLEL_MEMORY' 11 | 12 | def callbackInfo(receiveData) 13 | #print receiveData + "\n" 14 | end 15 | 16 | def callbackData(receiveData) 17 | if receiveData != nil then 18 | puts "received #{receiveData.size}" 19 | p receiveData 20 | else 21 | puts "ISSUE BECAUSE DATA IS NIL" 22 | end 23 | end 24 | 25 | def callbackSpeedOfTransfert(receiveData) 26 | #puts "Speed : #{receiveData}" 27 | end 28 | def callbackProgress(percent:,startTime:,endTime:) 29 | print "\r\e[#{31}mUpload of FPGA firmware in progress : #{percent}%\e[0m" 30 | #puts "Progress : #{percent}% Start@ #{startTime} Stop@ #{endTime}" 31 | #puts "Elasped time #{(endTime-startTime).round(4)} sec" 32 | end 33 | 34 | #puts "Number of hardsploit detected :#{HardsploitAPI.getNumberOfBoardAvailable}" 35 | 36 | HardsploitAPI.callbackInfo = method(:callbackInfo) 37 | HardsploitAPI.callbackData = method(:callbackData) 38 | HardsploitAPI.callbackSpeedOfTransfert = method(:callbackSpeedOfTransfert) 39 | HardsploitAPI.callbackProgress = method(:callbackProgress) 40 | HardsploitAPI.id = 0 # id of hardsploit 0 for the first one, 1 for the second etc 41 | 42 | HardsploitAPI.instance.getAllVersions 43 | 44 | if ARGV[0] != "nofirmware" then 45 | HardsploitAPI.instance.loadFirmware("PARALLEL") 46 | end 47 | 48 | @para = HardsploitAPI_PARALLEL.new 49 | 50 | while true 51 | char = STDIN.getch 52 | puts char 53 | if char == "\u0003" 54 | puts "Finished" 55 | exit 56 | 57 | #Dump parallele 8 bits at 100ns for latency 58 | elsif char == "a" then 59 | time = Time.new 60 | #dump_size =65536 #ROM 61 | dump_size =65536 #RAM 62 | 63 | 64 | @para.read_Memory_WithoutMultiplexing(path:"file.bin",addressStart:0,addressStop:dump_size-1,bits8_or_bits16_DataSize:true,latency:1600 ) # true = 8 bits 1600ns latency 65 | time = Time.new - time 66 | puts "DUMP #{((dump_size/time)).round(2)}Bytes/s #{(dump_size)}Bytes in #{time.round(4)} s" 67 | 68 | #Dump parallele 16 bits at 100ns for latency 69 | elsif char == "z" then 70 | time = Time.new 71 | dump_size = 5 72 | @para.read_Memory_WithoutMultiplexing(path:"file.bin",addressStart:0,addressStop:dump_size-1,bits8_or_bits16_DataSize:false,latency:1600) #false = 16 bits 1600ns latency 73 | time = Time.new - time 74 | puts "DUMP #{((2*(dump_size)/(1024*time))).round(2)}KBytes/s #{(2*dump_size)}Bytes in #{time.round(4)} s" 75 | 76 | elsif char == "w" then 77 | HardsploitAPI.instance.setStatutLed(led:HardsploitAPI::USB_COMMAND::GREEN_LED,state:true); 78 | elsif char == "x" then 79 | HardsploitAPI.instance.setStatutLed(led:HardsploitAPI::USB_COMMAND::GREEN_LED,state:false); 80 | 81 | elsif char == "p" then 82 | HardsploitAPI.instance.loadFirmware("PARALLEL") 83 | end 84 | end 85 | -------------------------------------------------------------------------------- /Examples/testSPI.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | require 'io/console' 9 | require_relative '../HardsploitAPI/Core/HardsploitAPI' 10 | require_relative '../HardsploitAPI/Modules/SPI/HardsploitAPI_SPI' 11 | 12 | def callbackInfo(receiveData) 13 | #print receiveData + "\n" 14 | end 15 | 16 | def callbackData(receiveData) 17 | if receiveData != nil then 18 | puts "received #{receiveData.size}" 19 | p receiveData 20 | else 21 | puts "ISSUE BECAUSE DATA IS NIL" 22 | end 23 | end 24 | 25 | def callbackSpeedOfTransfert(receiveData) 26 | #puts "Speed : #{receiveData}" 27 | end 28 | def callbackProgress(percent:,startTime:,endTime:) 29 | puts "Progress : #{percent}% Start@ #{startTime} Stop@ #{endTime}" 30 | puts "Elasped time #{(endTime-startTime).round(4)} sec" 31 | end 32 | 33 | #puts "Number of hardsploit detected :#{HardsploitAPI.getNumberOfBoardAvailable}" 34 | 35 | HardsploitAPI.callbackInfo = method(:callbackInfo) 36 | HardsploitAPI.callbackData = method(:callbackData) 37 | HardsploitAPI.callbackSpeedOfTransfert = method(:callbackSpeedOfTransfert) 38 | HardsploitAPI.callbackProgress = method(:callbackProgress) 39 | HardsploitAPI.id = 0 # id of hardsploit 0 for the first one, 1 for the second etc 40 | 41 | HardsploitAPI.instance.getAllVersions 42 | 43 | if ARGV[0] != "nofirmware" then 44 | HardsploitAPI.instance.loadFirmware("SPI") 45 | end 46 | 47 | @spi = HardsploitAPI_SPI.new(speed:60,mode:0) 48 | #The current API version 49 | #p HardsploitAPI::VERSION::API 50 | 51 | def spiCustomCommand 52 | #Speed Range 1-255 SPI clock = 150Mhz / (2*speed) tested from 3 to 255 (25Mhz to about 0.3Khz) 53 | 54 | testpack = Array.new 55 | for i in (0..10) do 56 | testpack.push i 57 | end 58 | result = @spi.spi_Interact(payload:testpack) 59 | p result 60 | end 61 | 62 | while true 63 | char = STDIN.getch 64 | puts char 65 | if char == "\u0003" 66 | puts "Finished" 67 | exit 68 | 69 | elsif char == "z" then 70 | crossvalue = Array.new 71 | #Default wiring 72 | for i in 0..63 73 | crossvalue.push i 74 | end 75 | 76 | #swap 2 first signal 77 | crossvalue[0] = 1 78 | crossvalue[1] = 0 79 | crossvalue[2] = 2 80 | crossvalue[3] = 3 81 | 82 | crossvalue[60] = 60 83 | crossvalue[61] = 61 84 | crossvalue[62] = 62 85 | crossvalue[63] = 63 86 | 87 | HardsploitAPI.setCrossWiring(value:crossvalue) 88 | 89 | puts "cross SWAP" 90 | 91 | elsif char == "e" then 92 | crossvalue = Array.new 93 | #Default wiring 94 | for i in 0..63 95 | crossvalue.push i 96 | end 97 | 98 | #swap 2 first signal 99 | 100 | HardsploitAPI.setCrossWiring(value:crossvalue) 101 | puts "cross Normal" 102 | elsif char == "w" then 103 | HardsploitAPI.instance.setStatutLed(led:HardsploitAPI::USB_COMMAND::GREEN_LED,state:true); 104 | @spi.pulse=1 105 | elsif char == "x" then 106 | HardsploitAPI.instance.setStatutLed(led:HardsploitAPI::USB_COMMAND::GREEN_LED,state:false); 107 | @spi.pulse=0 108 | elsif char == "i" then 109 | spiCustomCommand 110 | elsif char == "p" then 111 | HardsploitAPI.instance.loadFirmware("SPI") 112 | end 113 | end 114 | -------------------------------------------------------------------------------- /Examples/testSPISniffer.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | require 'io/console' 9 | require_relative '../HardsploitAPI/Core/HardsploitAPI' 10 | require_relative '../HardsploitAPI/Modules/SPI_SNIFFER/HardsploitAPI_SPI_SNIFFER' 11 | 12 | def callbackInfo(receiveData) 13 | #print receiveData + "\n" 14 | end 15 | 16 | def callbackData(receiveData) 17 | if receiveData != nil then 18 | puts "received #{receiveData.size}" 19 | p receiveData 20 | else 21 | puts "ISSUE BECAUSE DATA IS NIL" 22 | end 23 | end 24 | 25 | def callbackSpeedOfTransfert(receiveData) 26 | #puts "Speed : #{receiveData}" 27 | end 28 | 29 | def callbackProgress(percent:,startTime:,endTime:) 30 | print "\r\e[#{31}mUpload of FPGA firmware in progress : #{percent}%\e[0m" 31 | #puts "Progress : #{percent}% Start@ #{startTime} Stop@ #{endTime}" 32 | #puts "Elasped time #{(endTime-startTime).round(4)} sec" 33 | end 34 | 35 | #puts "Number of hardsploit detected :#{HardsploitAPI.getNumberOfBoardAvailable}" 36 | 37 | HardsploitAPI.callbackInfo = method(:callbackInfo) 38 | HardsploitAPI.callbackData = method(:callbackData) 39 | HardsploitAPI.callbackSpeedOfTransfert = method(:callbackSpeedOfTransfert) 40 | HardsploitAPI.callbackProgress = method(:callbackProgress) 41 | HardsploitAPI.id = 0 # id of hardsploit 0 for the first one, 1 for the second etc 42 | 43 | HardsploitAPI.instance.getAllVersions 44 | 45 | if ARGV[0] != "nofirmware" then 46 | HardsploitAPI.instance.loadFirmware("SPI_SNIFFER") 47 | end 48 | 49 | @spi = HardsploitAPI_SPI_SNIFFER.new(mode:0,sniff:HardsploitAPI::SPISniffer::MOSI) # MISO MOSI MISO_MOSI 50 | 51 | sleep(0.5) 52 | def spiCustomCommand 53 | i = '.' 54 | while 1 55 | i == "." ? i = ".." : i = "." #just to have a toggle in console to keep alive the console 56 | begin 57 | result = @spi.spi_receive_available_data 58 | 59 | #if half a simple array, if fullduplex first item -> an array of MISO and second array -> an array of MOSI 60 | case @spi.sniff 61 | when HardsploitAPI::SPISniffer::MISO 62 | puts "MISO : #{result}" 63 | when HardsploitAPI::SPISniffer::MOSI 64 | puts "MOSI : #{result}" 65 | else 66 | puts "MOSI : #{result[0]}" 67 | puts "MISO : #{result[1]}" 68 | end 69 | 70 | rescue HardsploitAPI::ERROR::HARDSPLOIT_NOT_FOUND 71 | puts "Hardsploit not found" 72 | rescue HardsploitAPI::ERROR::USB_ERROR 73 | puts i 74 | #Ignore time out because we read in continous 75 | end 76 | end 77 | end 78 | 79 | while true 80 | char = STDIN.getch 81 | puts char 82 | if char == "\u0003" 83 | puts "Finished" 84 | exit 85 | 86 | elsif char == "i" then 87 | spiCustomCommand 88 | elsif char == "p" then 89 | HardsploitAPI.instance.loadFirmware("SPI") 90 | end 91 | end 92 | -------------------------------------------------------------------------------- /Examples/testSWD.rb: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | require 'io/console' 9 | require_relative '../HardsploitAPI/Core/HardsploitAPI' 10 | require_relative '../HardsploitAPI/Modules/SWD/HardsploitAPI_SWD' 11 | 12 | def callbackInfo(receiveData) 13 | #print receiveData + "\n" 14 | end 15 | 16 | def callbackData(receiveData) 17 | if receiveData != nil then 18 | puts "received #{receiveData.size}" 19 | p receiveData 20 | else 21 | puts "ISSUE BECAUSE DATA IS NIL" 22 | end 23 | end 24 | 25 | def callbackSpeedOfTransfert(receiveData) 26 | #puts "Speed : #{receiveData}" 27 | end 28 | def callbackProgress(percent:,startTime:,endTime:) 29 | print "\r\e[#{31}mUpload of FPGA firmware in progress : #{percent}%\e[0m" 30 | #puts "Progress : #{percent}% Start@ #{startTime} Stop@ #{endTime}" 31 | #puts "Elasped time #{(endTime-startTime).round(4)} sec" 32 | end 33 | puts "Number of hardsploit detected :#{HardsploitAPI.getNumberOfBoardAvailable}" 34 | HardsploitAPI.callbackInfo = method(:callbackInfo) 35 | HardsploitAPI.callbackData = method(:callbackData) 36 | HardsploitAPI.callbackSpeedOfTransfert = method(:callbackSpeedOfTransfert) 37 | HardsploitAPI.callbackProgress = method(:callbackProgress) 38 | HardsploitAPI.id = 0 # id of hardsploit 0 for the first one, 1 for the second etc 39 | 40 | HardsploitAPI.instance.getAllVersions 41 | 42 | if ARGV[0] != "nofirmware" then 43 | HardsploitAPI.instance.loadFirmware("SWD") 44 | end 45 | 46 | #The current API version 47 | #p HardsploitAPI::VERSION::API 48 | def swdCustomRead 49 | begin 50 | swd = HardsploitAPI_SWD.new( 51 | memory_start_address: "0x08000000", 52 | memory_size_address: "0x1FFFF7E0", 53 | cpu_id_address: "0xE000ED00", 54 | device_id_address: "0x1FFFF7E8" 55 | ) 56 | #TO OBTAIN ID CODE 57 | code = swd.obtainCodes 58 | puts "DP.IDCODE: #{code[:DebugPortId].to_s(16)} " 59 | #puts "AP.IDCODE: #{code[:AccessPortId].to_s(16)} " 60 | #puts "CPU ID : #{code[:CpuId].to_s(16)} " 61 | # puts "DEVICE ID : #{code[:DeviceId].to_s(16)}" 62 | rescue 63 | puts "MCU NOT FOUND" 64 | #puts "Read ARM Register" 65 | #swd.readRegs 66 | 67 | #puts "stop" 68 | #swd.stop 69 | 70 | #TO DUMP FLASH 71 | #swd.dumpFlash('dumdp.bin') 72 | #swd.erase 73 | # ERASE FLASH !!!!!!!!!! AND WRITE THE CONTENT OF THE FILE ON THE FLASH 74 | #swd.writeFlash('dumdp2.bin') 75 | 76 | rescue HardsploitAPI::ERROR::HARDSPLOIT_NOT_FOUND 77 | puts "Hardsploit not found" 78 | rescue HardsploitAPI::ERROR::USB_ERROR 79 | puts "USB ERRROR" 80 | end 81 | end 82 | def swdCustomWrite 83 | begin 84 | 85 | swd = HardsploitAPI_SWD.new( 86 | memory_start_address: "0x08000000", 87 | memory_size_address: "0x1FFFF7E0", 88 | cpu_id_address: "0xE000ED00", 89 | device_id_address: "0x1FFFF7E8" 90 | ) 91 | #TO OBTAIN ID CODE 92 | code = swd.obtainCodes 93 | puts "DP.IDCODE: #{code[:DebugPortId].to_s(16)} " 94 | puts "AP.IDCODE: #{code[:AccessPortId].to_s(16)} " 95 | puts "CPU ID : #{code[:CpuId].to_s(16)} " 96 | 97 | #TO DUMP FLASH 98 | #swd.dumpFlash('dumdp.bin') 99 | #swd.erase 100 | # ERASE FLASH !!!!!!!!!! AND WRITE THE CONTENT OF THE FILE ON THE FLASH 101 | swd.writeFlash('dumdp2.bin') 102 | #unhalt 103 | #swd.stop 104 | 105 | rescue HardsploitAPI::ERROR::HARDSPLOIT_NOT_FOUND 106 | puts "Hardsploit not found" 107 | rescue HardsploitAPI::ERROR::USB_ERROR 108 | puts "USB ERRROR" 109 | end 110 | end 111 | 112 | while true 113 | char = STDIN.getch 114 | puts char 115 | if char == "\u0003" 116 | puts "Finished" 117 | exit 118 | 119 | elsif char == "z" then 120 | crossvalue = Array.new 121 | #Default wiring 122 | for i in 0..63 123 | crossvalue.push i 124 | end 125 | crossvalue[1] = HardsploitAPI.getSignalId(signal:"SWD_CLK") 126 | crossvalue[2] = HardsploitAPI.getSignalId(signal:"SWD_IO") 127 | 128 | crossvalue[0] = 2 129 | 130 | p crossvalue 131 | HardsploitAPI.instance.setCrossWiring(value:crossvalue) 132 | 133 | puts "cross SWAP" 134 | HardsploitAPI.instance.signalHelpingWiring(signal:"SWD_CLK") 135 | elsif char == "e" then 136 | crossvalue = Array.new 137 | #Default wiring 138 | for i in 0..63 139 | crossvalue.push i 140 | end 141 | 142 | crossvalue[0] = 2 143 | crossvalue[1] = HardsploitAPI.getSignalId(signal:"SWD_IO") 144 | crossvalue[2] = HardsploitAPI.getSignalId(signal:"SWD_CLK") 145 | 146 | p crossvalue 147 | HardsploitAPI.instance.setCrossWiring(value:crossvalue) 148 | puts "cross Normal" 149 | 150 | HardsploitAPI.instance.signalHelpingWiring(signal:"SWD_CLK") 151 | # TEST POUR LE BUG DE CROSS WIRING PRESS M 152 | elsif char == 'm' 153 | # 0 = CLK 154 | # 1 = IO 155 | swd = HardsploitAPI_SWD.new( 156 | memory_start_address: "0x08000000", 157 | memory_size_address: "0x1FFFF7E0", 158 | cpu_id_address: "0xE000ED00", 159 | device_id_address: "0x1FFFF7E8" 160 | ) 161 | base_crossvalue = Array.new 162 | for i in 0..63 163 | base_crossvalue.push i 164 | end 165 | crossvalue = Array.new(base_crossvalue) 166 | crossvalue[0] = 2 167 | crossvalue[1] = 3 168 | crossvalue[2] = 1 169 | crossvalue[3] = 0 170 | HardsploitAPI.instance.setCrossWiring(value:crossvalue) 171 | result = swd.obtainCodes 172 | #for i in 0..63 173 | # crossvalue = Array.new(base_crossvalue) 174 | # crossvalue[i] = 0 175 | # crossvalue[0] = i 176 | # crossvalue[i.next] = 1 177 | # crossvalue[1] = i.next 178 | # p crossvalue 179 | # HardsploitAPI.instance.setCrossWiring(value:crossvalue) 180 | # result = swd.obtainCodes 181 | # p result unless result.nil? 182 | # char = 'r' 183 | # p "Branchement suivant" 184 | # while char != 'n' 185 | # char = STDIN.getch 186 | # p "Next" 187 | # end 188 | #end 189 | elsif char == "i" then 190 | crossvalue = Array.new 191 | #Default wiring 192 | for i in 0..63 193 | crossvalue.push i 194 | end 195 | #HardsploitAPI.instance.stopFPGA 196 | #sleep(1) 197 | #HardsploitAPI.instance.startFPGA 198 | #sleep(1) 199 | HardsploitAPI.instance.setCrossWiring(value:crossvalue) 200 | 201 | swd.find(numberOfConnectedPinFromA0:2) 202 | elsif char == "w" then 203 | HardsploitAPI.instance.setStatutLed(led:HardsploitAPI::USB_COMMAND::GREEN_LED,state:true); 204 | elsif char == "x" then 205 | HardsploitAPI.instance.setStatutLed(led:HardsploitAPI::USB_COMMAND::GREEN_LED,state:false); 206 | elsif char == "f" then 207 | swdCustomRead 208 | elsif char == "g" then 209 | swdCustomWrite 210 | 211 | elsif char == "1" then 212 | puts "Read @ 0x20000000 " 213 | p swd.read_mem32(0x20000000,3) 214 | #p swd.read_mem8(0x20000000,4) 215 | 216 | elsif char == "2" then 217 | puts "Write @ 0x20000000 " 218 | swd.write_mem32(0x20000000,[11,11,11,11,11,11,11,11,11,11,11,11]) 219 | swd.write_mem8(0x20000000,[1,2,3,4,5,6,7,8,9,10,14,12]) 220 | 221 | elsif char == "p" then 222 | HardsploitAPI.instance.loadFirmware("SWD") 223 | end 224 | end 225 | -------------------------------------------------------------------------------- /Examples/testUARTBufferOverflow.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | require 'io/console' 9 | require_relative '../HardsploitAPI/Core/HardsploitAPI' 10 | require_relative '../HardsploitAPI/Modules/UART/HardsploitAPI_UART' 11 | 12 | def callbackInfo(receiveData) 13 | #print receiveData + "\n" 14 | end 15 | 16 | def callbackData(receiveData) 17 | if receiveData != nil then 18 | puts "received #{receiveData.size}" 19 | p receiveData 20 | end 21 | end 22 | 23 | def callbackSpeedOfTransfert(receiveData) 24 | #puts "Speed : #{receiveData}" 25 | end 26 | def callbackProgress(percent:,startTime:,endTime:) 27 | print "\r\e[#{31}mUpload of FPGA firmware in progress : #{percent}%\e[0m" 28 | #puts "Progress : #{percent}% Start@ #{startTime} Stop@ #{endTime}" 29 | #puts "Elasped time #{(endTime-startTime).round(4)} sec" 30 | end 31 | 32 | #puts "Number of hardsploit detected :#{HardsploitAPI.getNumberOfBoardAvailable}" 33 | 34 | HardsploitAPI.callbackInfo = method(:callbackInfo) 35 | HardsploitAPI.callbackData = method(:callbackData) 36 | HardsploitAPI.callbackSpeedOfTransfert = method(:callbackSpeedOfTransfert) 37 | HardsploitAPI.callbackProgress = method(:callbackProgress) 38 | HardsploitAPI.id = 0 # id of hardsploit 0 for the first one, 1 for the second etc 39 | 40 | HardsploitAPI.instance.getAllVersions 41 | 42 | if ARGV[0] != "nofirmware" then 43 | HardsploitAPI.instance.loadFirmware("UART") 44 | end 45 | @uart = HardsploitAPI_UART.new(baud_rate:57600, word_width:8,use_parity_bit:0,parity_type:0,nb_stop_bits:1,idle_line_level:1) 46 | puts "Effective baudrate #{@uart.baud_rate}" 47 | 48 | Thread.new{uartCustomRead()} 49 | puts "Reading :" 50 | 51 | def uartCustomSend 52 | begin 53 | #Send 32 bytes 54 | payload = Array.new 55 | for i in 0..35 56 | payload.push 0x40 57 | end 58 | #Address OpenDoor 59 | payload.push 0xFD 60 | payload.push 0x29 61 | 62 | payload.push 13 #Carriage return 63 | @uart.write(payload:payload) 64 | puts payload.pack("C*") 65 | rescue HardsploitAPI::ERROR::HARDSPLOIT_NOT_FOUND 66 | puts "Hardsploit not found" 67 | rescue HardsploitAPI::ERROR::USB_ERROR 68 | puts "USB ERRROR" 69 | end 70 | end 71 | 72 | def uartCustomRead 73 | while 1 74 | begin 75 | tab = @uart.sendAndReceived 76 | print tab.pack('c*') 77 | rescue HardsploitAPI::ERROR::HARDSPLOIT_NOT_FOUND 78 | puts "Hardsploit not found" 79 | rescue HardsploitAPI::ERROR::USB_ERROR 80 | puts "USB ERRROR" 81 | end 82 | sleep(0.2) 83 | end 84 | end 85 | 86 | while true 87 | char = STDIN.getch 88 | puts char 89 | if char == "\u0003" 90 | puts "Finished" 91 | exit 92 | 93 | elsif char == "e" then 94 | puts "enableMeasureBaudRate" 95 | @uart.enableMeasureBaudRate 96 | 97 | elsif char == "d" then 98 | puts "disableMeasureBaudRate" 99 | @uart.disableMeasureBaudRate 100 | 101 | elsif char == "b" then 102 | p @uart.measureBaudRate 103 | elsif char == "s" then 104 | puts "uartCustomSend" 105 | uartCustomSend 106 | elsif char == "r" then 107 | #Thread.new{uartCustomRead()} 108 | uartCustomRead() 109 | elsif char == "p" then 110 | print "Upload Firmware check : #{HardsploitAPI.instance.uploadFirmware(pathFirmware:File.expand_path(File.dirname(__FILE__)) + "/../../HARDSPLOIT-VHDL/Firmware/FPGA/UART/UART_INTERACT/HARDSPLOIT_FIRMWARE_FPGA_UART_INTERACT.rpd",checkFirmware:false)}\n" 111 | @uart.setSettings 112 | end 113 | end 114 | -------------------------------------------------------------------------------- /Examples/testUARTConsole.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | require 'io/console' 9 | require_relative '../HardsploitAPI/Core/HardsploitAPI' 10 | require_relative '../HardsploitAPI/Modules/UART/HardsploitAPI_UART' 11 | 12 | def callbackInfo(receiveData) 13 | #print receiveData + "\n" 14 | end 15 | 16 | def callbackData(receiveData) 17 | if receiveData != nil then 18 | puts "received #{receiveData.size}" 19 | p receiveData 20 | end 21 | end 22 | 23 | def callbackSpeedOfTransfert(receiveData) 24 | #puts "Speed : #{receiveData}" 25 | end 26 | def callbackProgress(percent:,startTime:,endTime:) 27 | print "\r\e[#{31}mUpload of FPGA firmware in progress : #{percent}%\e[0m" 28 | #puts "Progress : #{percent}% Start@ #{startTime} Stop@ #{endTime}" 29 | #puts "Elasped time #{(endTime-startTime).round(4)} sec" 30 | end 31 | 32 | #puts "Number of hardsploit detected :#{HardsploitAPI.getNumberOfBoardAvailable}" 33 | 34 | HardsploitAPI.callbackInfo = method(:callbackInfo) 35 | HardsploitAPI.callbackData = method(:callbackData) 36 | HardsploitAPI.callbackSpeedOfTransfert = method(:callbackSpeedOfTransfert) 37 | HardsploitAPI.callbackProgress = method(:callbackProgress) 38 | HardsploitAPI.id = 0 # id of hardsploit 0 for the first one, 1 for the second etc 39 | 40 | HardsploitAPI.instance.getAllVersions 41 | 42 | if ARGV[0] != "nofirmware" then 43 | HardsploitAPI.instance.loadFirmware("UART") 44 | end 45 | 46 | @uart = HardsploitAPI_UART.new(baud_rate:57600, word_width:8,use_parity_bit:0,parity_type:0,nb_stop_bits:2,idle_line_level:1) 47 | puts "\nEffective baudrate #{@uart.baud_rate} \n" 48 | Thread.new{uartCustomRead()} 49 | puts "Start reading :\n\n" 50 | 51 | def uartCustomRead 52 | while 1 53 | begin 54 | tab = @uart.sendAndReceived 55 | print tab.pack('c*') 56 | rescue HardsploitAPI::ERROR::HARDSPLOIT_NOT_FOUND 57 | puts "Hardsploit not found" 58 | rescue HardsploitAPI::ERROR::USB_ERROR 59 | puts "USB ERRROR" 60 | end 61 | sleep(0.1) 62 | end 63 | end 64 | 65 | while true 66 | char = STDIN.getch 67 | if char == "\u0003" 68 | puts "Finished" 69 | exit 70 | else 71 | @uart.write(payload:[char.ord]) 72 | print char 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /Examples/testUARTFuzzer.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | require 'io/console' 9 | require_relative '../HardsploitAPI/Core/HardsploitAPI' 10 | require_relative '../HardsploitAPI/Modules/UART/HardsploitAPI_UART' 11 | 12 | def callbackInfo(receiveData) 13 | #print receiveData + "\n" 14 | end 15 | 16 | def callbackData(receiveData) 17 | if receiveData != nil then 18 | puts "received #{receiveData.size}" 19 | p receiveData 20 | end 21 | end 22 | 23 | def callbackSpeedOfTransfert(receiveData) 24 | #puts "Speed : #{receiveData}" 25 | end 26 | def callbackProgress(percent:,startTime:,endTime:) 27 | print "\r\e[#{31}mUpload of FPGA firmware in progress : #{percent}%\e[0m" 28 | #puts "Progress : #{percent}% Start@ #{startTime} Stop@ #{endTime}" 29 | #puts "Elasped time #{(endTime-startTime).round(4)} sec" 30 | end 31 | 32 | #puts "Number of hardsploit detected :#{HardsploitAPI.getNumberOfBoardAvailable}" 33 | 34 | HardsploitAPI.callbackInfo = method(:callbackInfo) 35 | HardsploitAPI.callbackData = method(:callbackData) 36 | HardsploitAPI.callbackSpeedOfTransfert = method(:callbackSpeedOfTransfert) 37 | HardsploitAPI.callbackProgress = method(:callbackProgress) 38 | HardsploitAPI.id = 0 # id of hardsploit 0 for the first one, 1 for the second etc 39 | 40 | HardsploitAPI.instance.getAllVersions 41 | 42 | if ARGV[0] != "nofirmware" then 43 | HardsploitAPI.instance.loadFirmware("UART") 44 | end 45 | @uart = HardsploitAPI_UART.new(baud_rate:57600, word_width:8,use_parity_bit:0,parity_type:0,nb_stop_bits:1,idle_line_level:1) 46 | puts "Effective baudrate #{@uart.baud_rate}" 47 | 48 | Thread.new{uartCustomRead()} 49 | puts "Reading :" 50 | 51 | def uartCustomSend 52 | begin 53 | payload = Array.new 54 | for i in 0..23 55 | payload.push 0x40 56 | end 57 | payload.push 13 #Carriage return 58 | 59 | @uart.write(payload:payload) 60 | puts payload.pack("C*") 61 | rescue HardsploitAPI::ERROR::HARDSPLOIT_NOT_FOUND 62 | puts "Hardsploit not found" 63 | rescue HardsploitAPI::ERROR::USB_ERROR 64 | puts "USB ERRROR" 65 | end 66 | end 67 | 68 | def uartCustomRead 69 | while 1 70 | begin 71 | tab = @uart.sendAndReceived 72 | print tab.pack('c*') 73 | rescue HardsploitAPI::ERROR::HARDSPLOIT_NOT_FOUND 74 | puts "Hardsploit not found" 75 | rescue HardsploitAPI::ERROR::USB_ERROR 76 | puts "USB ERRROR" 77 | end 78 | sleep(0.2) 79 | end 80 | end 81 | 82 | while true 83 | char = STDIN.getch 84 | puts char 85 | if char == "\u0003" 86 | puts "Finished" 87 | exit 88 | 89 | elsif char == "e" then 90 | puts "enableMeasureBaudRate" 91 | @uart.enableMeasureBaudRate 92 | 93 | elsif char == "d" then 94 | puts "disableMeasureBaudRate" 95 | @uart.disableMeasureBaudRate 96 | 97 | elsif char == "b" then 98 | p @uart.measureBaudRate 99 | elsif char == "s" then 100 | puts "uartCustomSend" 101 | uartCustomSend 102 | elsif char == "r" then 103 | #Thread.new{uartCustomRead()} 104 | uartCustomRead() 105 | elsif char == "p" then 106 | HardsploitAPI.instance.loadFirmware("UART") 107 | @uart.setSettings 108 | end 109 | end 110 | -------------------------------------------------------------------------------- /Firmwares/FPGA/I2C/I2C_INTERACT/HARDSPLOIT_FIRMWARE_FPGA_I2C_INTERACT.rpd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serma-safety-security/hardsploit-api-ruby/e01441fcd60436b7af7cf883e86407462b249448/Firmwares/FPGA/I2C/I2C_INTERACT/HARDSPLOIT_FIRMWARE_FPGA_I2C_INTERACT.rpd -------------------------------------------------------------------------------- /Firmwares/FPGA/PARALLEL/NO_MUX_PARALLEL_MEMORY/HARDSPLOIT_FIRMWARE_FPGA_NO_MUX_PARALLEL_MEMORY.rpd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serma-safety-security/hardsploit-api-ruby/e01441fcd60436b7af7cf883e86407462b249448/Firmwares/FPGA/PARALLEL/NO_MUX_PARALLEL_MEMORY/HARDSPLOIT_FIRMWARE_FPGA_NO_MUX_PARALLEL_MEMORY.rpd -------------------------------------------------------------------------------- /Firmwares/FPGA/SPI/SPI_INTERACT/HARDSPLOIT_FIRMWARE_FPGA_SPI_INTERACT.rpd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serma-safety-security/hardsploit-api-ruby/e01441fcd60436b7af7cf883e86407462b249448/Firmwares/FPGA/SPI/SPI_INTERACT/HARDSPLOIT_FIRMWARE_FPGA_SPI_INTERACT.rpd -------------------------------------------------------------------------------- /Firmwares/FPGA/SPI/SPI_SNIFFER/HARDSPLOIT_FIRMWARE_FPGA_SPI_SNIFFER.rpd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serma-safety-security/hardsploit-api-ruby/e01441fcd60436b7af7cf883e86407462b249448/Firmwares/FPGA/SPI/SPI_SNIFFER/HARDSPLOIT_FIRMWARE_FPGA_SPI_SNIFFER.rpd -------------------------------------------------------------------------------- /Firmwares/FPGA/SWD/SWD_INTERACT/HARDSPLOIT_FIRMWARE_FPGA_SWD_INTERACT.rpd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serma-safety-security/hardsploit-api-ruby/e01441fcd60436b7af7cf883e86407462b249448/Firmwares/FPGA/SWD/SWD_INTERACT/HARDSPLOIT_FIRMWARE_FPGA_SWD_INTERACT.rpd -------------------------------------------------------------------------------- /Firmwares/FPGA/TEST/TEST_INTERACT/HARDSPLOIT_FIRMWARE_FPGA_TEST_INTERACT.rpd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serma-safety-security/hardsploit-api-ruby/e01441fcd60436b7af7cf883e86407462b249448/Firmwares/FPGA/TEST/TEST_INTERACT/HARDSPLOIT_FIRMWARE_FPGA_TEST_INTERACT.rpd -------------------------------------------------------------------------------- /Firmwares/FPGA/UART/UART_INTERACT/HARDSPLOIT_FIRMWARE_FPGA_UART_INTERACT.rpd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serma-safety-security/hardsploit-api-ruby/e01441fcd60436b7af7cf883e86407462b249448/Firmwares/FPGA/UART/UART_INTERACT/HARDSPLOIT_FIRMWARE_FPGA_UART_INTERACT.rpd -------------------------------------------------------------------------------- /Firmwares/FPGA/VersionFPGA.rb: -------------------------------------------------------------------------------- 1 | class VersionFPGA 2 | module VERSION_FPGA 3 | FPGA = "V1.2.0" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /Firmwares/UC/HARDSPLOIT_FIRMWARE_UC.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serma-safety-security/hardsploit-api-ruby/e01441fcd60436b7af7cf883e86407462b249448/Firmwares/UC/HARDSPLOIT_FIRMWARE_UC.bin -------------------------------------------------------------------------------- /Firmwares/UC/VersionUC.rb: -------------------------------------------------------------------------------- 1 | #=================================================== 2 | # Hardsploit UC - By Opale Security 3 | # www.opale-security.com || www.hardsploit.io 4 | # License: GNU General Public License v3 5 | # License URI: http://www.gnu.org/licenses/gpl.txt 6 | #=================================================== 7 | 8 | class VersionUC 9 | module VERSION_UC 10 | UC = "V1.0.3" 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /HardsploitAPI/Core/HardsploitAPI.rb: -------------------------------------------------------------------------------- 1 | require 'singleton' 2 | require 'libusb' 3 | require 'thread' 4 | require_relative 'HardsploitAPI_CONSTANT' 5 | require_relative 'HardsploitAPI_USB_COMMUNICATION' 6 | require_relative 'HardsploitAPI_FIRMWARE' 7 | require_relative 'HardsploitAPI_ERROR' 8 | require_relative '../../Firmwares/FPGA/VersionFPGA' 9 | require_relative '../../Firmwares/UC/VersionUC' 10 | class String 11 | def black; "\e[30m#{self}\e[0m" end 12 | def red; "\e[31m#{self}\e[0m" end 13 | def green; "\e[32m#{self}\e[0m" end 14 | def brown; "\e[33m#{self}\e[0m" end 15 | def blue; "\e[34m#{self}\e[0m" end 16 | def magenta; "\e[35m#{self}\e[0m" end 17 | def cyan; "\e[36m#{self}\e[0m" end 18 | def gray; "\e[37m#{self}\e[0m" end 19 | 20 | def bg_black; "\e[40m#{self}\e[0m" end 21 | def bg_red; "\e[41m#{self}\e[0m" end 22 | def bg_green; "\e[42m#{self}\e[0m" end 23 | def bg_brown; "\e[43m#{self}\e[0m" end 24 | def bg_blue; "\e[44m#{self}\e[0m" end 25 | def bg_magenta; "\e[45m#{self}\e[0m" end 26 | def bg_cyan; "\e[46m#{self}\e[0m" end 27 | def bg_gray; "\e[47m#{self}\e[0m" end 28 | 29 | def bold; "\e[1m#{self}\e[22m" end 30 | def italic; "\e[3m#{self}\e[23m" end 31 | def underline; "\e[4m#{self}\e[24m" end 32 | def blink; "\e[5m#{self}\e[25m" end 33 | def reverse_color; "\e[7m#{self}\e[27m" end 34 | end 35 | 36 | class HardsploitAPI 37 | include Singleton 38 | include USB_COMMAND 39 | include USB 40 | include VERSION 41 | include ERROR 42 | 43 | @@callbackData = nil 44 | @@callbackInfo = nil 45 | @@callbackProgress = nil 46 | @@callbackSpeedOfTransfert = nil 47 | @@id = 0 48 | @@crossWiringValue = Array.new 49 | 50 | def self.callbackData= fn 51 | @@callbackData = fn 52 | end 53 | def self.callbackInfo= fn 54 | @@callbackInfo = fn 55 | end 56 | def self.callbackProgress= fn 57 | @@callbackProgress = fn 58 | end 59 | def self.callbackSpeedOfTransfert= fn 60 | @@callbackSpeedOfTransfert = fn 61 | end 62 | 63 | def self.crossWiringValue 64 | return @@crossWiringValue 65 | end 66 | 67 | def self.id=id 68 | if (id < 0) then 69 | raise ERROR::HARDSPLOIT_NOT_FOUND 70 | else 71 | @@id = id 72 | end 73 | end 74 | 75 | def initialize 76 | if @@callbackData == nil or @@callbackInfo == nil or @@callbackProgress == nil or @@callbackSpeedOfTransfert == nil then 77 | raise "Error you need to specify callbackData callbackInfo callbackProgress callbackSpeedOfTransfert first" 78 | else 79 | #Default wiring 80 | for i in 0..63 81 | @@crossWiringValue.push i 82 | end 83 | self.connect 84 | puts "Hardsploit is connected".green.bold 85 | end 86 | end 87 | 88 | # Set the leds of uC returning nothing 89 | # * +led+:: USB_COMMAND::GREEN_LED or USB_COMMAND::RED_LED 90 | # * +state+:: callback to return +data for dump function+ 91 | def setStatutLed(led:,state:) 92 | packet_send = Array.new 93 | packet_send.push 0 #size set before send automatic 94 | packet_send.push 0 #size set before send automatic 95 | packet_send.push HardsploitAPI.lowByte(word:led) 96 | packet_send.push HardsploitAPI.highByte(word:led) 97 | packet_send.push (state ? 1 : 0) 98 | return sendPacket(packet_send) 99 | end 100 | 101 | 102 | # Set custom value to wiring led 103 | # * +value+:: 64 bits (8x8 Bytes) values to represent led (PortH PortG PortF PortE PortD PortC PortB PortA) 104 | def setWiringLeds(value:) 105 | # parametters = HardsploitAPI.checkParametters(["value"],args) 106 | # val = parametters[:value] 107 | 108 | packet = Array.new 109 | packet.push 0 #low byte of lenght of trame refresh automaticly before send by usb 110 | packet.push 0 #high byte of lenght of trame refresh automaticly before send by usb 111 | packet.push HardsploitAPI.lowByte(word:USB_COMMAND::FPGA_COMMAND) 112 | packet.push HardsploitAPI.highByte(word:USB_COMMAND::FPGA_COMMAND) 113 | 114 | packet.push 0x23 #Command SPI write wiring led 115 | 116 | packet.push HardsploitAPI.reverseBit((value & 0x00000000000000FF) >> 0) 117 | packet.push HardsploitAPI.reverseBit((value & 0x000000000000FF00) >> 8 ) 118 | packet.push HardsploitAPI.reverseBit((value & 0x0000000000FF0000) >> 16 ) 119 | packet.push HardsploitAPI.reverseBit((value & 0x00000000FF000000) >> 24 ) 120 | packet.push HardsploitAPI.reverseBit((value & 0x000000FF00000000) >> 32 ) 121 | packet.push HardsploitAPI.reverseBit((value & 0x0000FF0000000000) >> 40 ) 122 | packet.push HardsploitAPI.reverseBit((value & 0x00FF000000000000) >> 48 ) 123 | packet.push HardsploitAPI.reverseBit((value & 0xFF00000000000000) >> 56 ) 124 | 125 | return HardsploitAPI.instance.sendPacket(packet) 126 | end 127 | 128 | # Obtaint the version number of the board 129 | def getVersionNumber 130 | packet = Array.new 131 | packet.push 0 #low byte of lenght of trame refresh automaticly before send by usb 132 | packet.push 0 #high byte of lenght of trame refresh automaticly before send by usb 133 | packet.push HardsploitAPI.lowByte(word:USB_COMMAND::GET_VERSION_NUMBER) 134 | packet.push HardsploitAPI.highByte(word:USB_COMMAND::GET_VERSION_NUMBER) 135 | 136 | #remove header 137 | version_number = self.sendAndReceiveDATA(packet,1000).drop(4) 138 | if version_number.size < 20 then #if size more thant 20 char error when reading version number 139 | return version_number.pack('U*') 140 | else 141 | return "BAD VERSION NUMBER" 142 | end 143 | end 144 | 145 | def getAllVersions 146 | puts "API : #{VERSION::API}".blue.bold 147 | puts "Board : #{getVersionNumber}".blue.bold 148 | puts "FPGA : #{VersionFPGA::VERSION_FPGA::FPGA}".blue.bold 149 | puts "Microcontroller : #{VersionUC::VERSION_UC::UC}".blue.bold 150 | end 151 | 152 | def self.reverseBit(byte) 153 | return byte.to_s(2).rjust(8, "0").reverse.to_i(2) 154 | end 155 | 156 | # Set cross wiring 157 | # * +value+:: 64*8 bits to represent wiring 158 | def setCrossWiring(value:) 159 | if not value.size == 64 then 160 | raise HardsploitAPI::ERROR::API_CROSS_WIRING 161 | end 162 | 163 | packet = Array.new 164 | packet.push 0 #low byte of lenght of trame refresh automaticly before send by usb 165 | packet.push 0 #high byte of lenght of trame refresh automaticly before send by usb 166 | packet.push HardsploitAPI.lowByte(word:USB_COMMAND::FPGA_COMMAND) 167 | packet.push HardsploitAPI.highByte(word:USB_COMMAND::FPGA_COMMAND) 168 | 169 | packet.push 0x75 #Cross wiring command 170 | packet.push *value 171 | @@crossWiringValue = value 172 | return self.sendPacket(packet) 173 | end 174 | 175 | def self.allPosibility(numberOfConnectedPinFromA0:,numberOfSignalsForBus:) 176 | if numberOfConnectedPinFromA0 < numberOfSignalsForBus then 177 | raise HardsploitAPI::ERROR::API_SCANNER_WRONG_PIN_NUMBER 178 | end 179 | a = Array.new 180 | for i in 0..numberOfConnectedPinFromA0-1 181 | a.push i 182 | end 183 | return a.permutation.to_a 184 | end 185 | 186 | def self.prepare_packet 187 | packet = [] 188 | packet.push 0 #low byte of lenght of trame refresh automaticly before send by usb 189 | packet.push 0 #high byte of lenght of trame refresh automaticly before send by usb 190 | packet.push HardsploitAPI.lowByte(word:HardsploitAPI::USB_COMMAND::FPGA_COMMAND) 191 | packet.push HardsploitAPI.highByte(word:HardsploitAPI::USB_COMMAND::FPGA_COMMAND) 192 | packet.push 0x50 #Command RAW COMMUNICATION TO FPGA FIFO 193 | return packet 194 | end 195 | 196 | #call back 197 | def consoleProgress(percent:,startTime:,endTime:) 198 | @@callbackProgress.call(percent:percent,startTime:startTime,endTime:endTime) 199 | end 200 | def consoleData(value) 201 | @@callbackData.call(value) 202 | end 203 | def consoleSpeed(value) 204 | @@callbackSpeedOfTransfert.call(value) 205 | end 206 | def consoleInfo(value) 207 | @@callbackInfo.call(value) 208 | end 209 | 210 | end 211 | -------------------------------------------------------------------------------- /HardsploitAPI/Core/HardsploitAPI_CONSTANT.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | 9 | class HardsploitAPI 10 | public 11 | 12 | # Obtain signal Id 13 | # Params: 14 | # +signal+:: Name of signal you want obtain ud 15 | def self.getSignalId(signal:) 16 | wires = Hash.new 17 | 18 | #Parallel module 19 | wires["A0"] = 0 20 | wires["A1"] = 1 21 | wires["A2"] = 2 22 | wires["A3"] = 3 23 | wires["A4"] = 4 24 | wires["A5"] = 5 25 | wires["A6"] = 6 26 | wires["A7"] = 7 27 | wires["A8"] = 8 28 | wires["A9"] = 9 29 | wires["A10"] = 10 30 | wires["A11"] = 11 31 | wires["A12"] = 12 32 | wires["A13"] = 13 33 | wires["A14"] = 14 34 | wires["A15"] = 15 35 | wires["A16"] = 16 36 | wires["A17"] = 17 37 | wires["A18"] = 18 38 | wires["A19"] = 19 39 | wires["A20"] = 20 40 | wires["A21"] = 21 41 | wires["A22"] = 22 42 | wires["A23"] = 23 43 | wires["A24"] = 24 44 | wires["A25"] = 25 45 | wires["A26"] = 26 46 | wires["A27"] = 27 47 | wires["A28"] = 28 48 | wires["A29"] = 29 49 | wires["A30"] = 30 50 | wires["A31"] = 31 51 | 52 | wires["D0"] = 32 53 | wires["D1"] = 33 54 | wires["D2"] = 34 55 | wires["D3"] = 35 56 | wires["D4"] = 36 57 | wires["D5"] = 37 58 | wires["D6"] = 38 59 | wires["D7"] = 39 60 | wires["D8"] = 40 61 | wires["D9"] = 41 62 | wires["D10"] = 42 63 | wires["D11"] = 43 64 | wires["D12"] = 44 65 | wires["D13"] = 45 66 | wires["D14"] = 46 67 | wires["D15"] = 47 68 | 69 | wires["RST"] = 48 70 | wires["CE"] = 49 71 | wires["OE"] = 50 72 | wires["WE"] = 51 73 | wires["PARA_CLK"] = 52 74 | wires["WP"] = 53 75 | wires["ADV"] = 54 76 | 77 | #SPI module 78 | wires["SPI_CLK"] = 0 79 | wires["CS"] = 1 80 | wires["MOSI"] = 2 81 | wires["MISO"] = 3 82 | wires["PULSE"] = 4 83 | 84 | #I2C module 85 | wires["I2C_CLK"] = 0 86 | wires["SDA"] = 1 87 | 88 | #UART module 89 | wires["TX"] = 0 90 | wires["RX"] = 1 91 | 92 | #SWD module 93 | wires["SWD_CLK"] = 0 94 | wires["SWD_IO"] = 1 95 | 96 | return wires[signal] 97 | end 98 | 99 | # Power on the led for each signal specified 100 | # Params: 101 | # +signal+:: Name of signal you want visual help (set the led) 102 | def signalHelpingWiring(signal:) 103 | begin 104 | HardsploitAPI.instance.setWiringLeds(value:2**HardsploitAPI.crossWiringValue.index(HardsploitAPI.getSignalId(signal:signal))) 105 | rescue 106 | raise 'UNKNOWN SIGNAL' 107 | end 108 | end 109 | 110 | module USB_COMMAND 111 | GREEN_LED = 0 112 | RED_LED = 1 113 | LOOPBACK = 2 114 | ERASE_FIRMWARE = 3 115 | WRITE_PAGE_FIRMWARE = 4 116 | READ_PAGE_FIRMWARE = 5 117 | READ_ID_FLASH = 6 118 | START_FPGA = 7 119 | STOP_FPGA = 8 120 | FPGA_COMMAND = 9 121 | FPGA_DATA = 10 122 | STOP_FPGA_DATA = 11 123 | START_FPGA_DATA = 12 124 | GET_SERIAL_NUMBER = 13 125 | GET_VERSION_NUMBER = 14 126 | VCP_ERROR = 0xFFFF 127 | end 128 | 129 | module I2C 130 | KHZ_100 = 0 131 | KHZ_400 = 1 132 | KHZ_1000 = 2 133 | KHZ_40 = 3 134 | end 135 | 136 | module SPISniffer 137 | MOSI = 1 138 | MISO = 2 139 | MISO_MOSI = 3 140 | end 141 | 142 | module USB 143 | OUT_ENDPOINT = 0X02 144 | IN_ENDPOINT = 0X81 145 | USB_TRAME_SIZE = 8192 146 | end 147 | module VERSION 148 | API = "2.0.0" 149 | end 150 | end 151 | -------------------------------------------------------------------------------- /HardsploitAPI/Core/HardsploitAPI_ERROR.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | 9 | class HardsploitAPI 10 | module ERROR 11 | class Standard < StandardError; end 12 | 13 | class HARDSPLOIT_NOT_FOUND < Standard 14 | def initialize(msg="HARDSPLOIT NOT FOUND") 15 | super(msg) 16 | end 17 | end 18 | class API_CROSS_WIRING < Standard 19 | def initialize(msg="The crossWiring array must be a 64 items array") 20 | super(msg) 21 | end 22 | end 23 | class API_SCANNER_WRONG_PIN_NUMBER < Standard 24 | def initialize(msg="You need to connect more thant pins needed by the module 2 for swd, 2 for I2C etc") 25 | super(msg) 26 | end 27 | end 28 | class FileIssue < Standard 29 | def initialize(msg="Issue with file") 30 | super(msg) 31 | end 32 | end 33 | 34 | class I2CWrongSpeed < Standard 35 | def initialize(msg="Uknown speed, speed must be KHZ_100 = 0, KHZ_400 = 1,KHZ_1000 = 2") 36 | super(msg) 37 | end 38 | end 39 | class SPIWrongPulse < Standard 40 | def initialize(msg="Wrong, Pulse must be 0 or 1") 41 | super(msg) 42 | end 43 | end 44 | class SPIWrongSpeed < Standard 45 | def initialize(msg="Speed must be between 3 and 255") 46 | super(msg) 47 | end 48 | end 49 | class SPIWrongMode < Standard 50 | def initialize(msg="Mode must be between 0 and 3") 51 | super(msg) 52 | end 53 | end 54 | 55 | class SPIWrongPayloadSize < Standard 56 | def initialize(msg="Size of the data need to be less than 4000") 57 | super(msg) 58 | end 59 | end 60 | 61 | class WrongStartAddress < Standard 62 | def initialize(msg="Start address can't be negative and not more than size max - 1") 63 | super(msg) 64 | end 65 | end 66 | 67 | class SpiError < Standard 68 | def initialize(msg="Error during SPI processing") 69 | super(msg) 70 | end 71 | end 72 | 73 | class USB_PACKET_IS_TOO_LARGE < Standard 74 | def initialize(msg="USB_PACKET_IS_TOO_LARGE") 75 | super(msg) 76 | end 77 | end 78 | 79 | class USB_ERROR < Standard 80 | def initialize(msg="USB ERROR") 81 | super(msg) 82 | end 83 | end 84 | 85 | class SWD_ERROR < Standard 86 | def initialize(msg="SWD ERROR, WAIT, FAUL, ACK or something like that") 87 | super(msg) 88 | end 89 | end 90 | 91 | class UART_WrongSettings < Standard 92 | def initialize(msg="Wrong UART settings") 93 | super(msg) 94 | end 95 | end 96 | 97 | class UART_WrongTxPayloadSize < Standard 98 | def initialize(msg="Wrong TX payload size") 99 | super(msg) 100 | end 101 | end 102 | 103 | class UART_WrongPayloadSize < Standard 104 | def initialize(msg="Size of the data need to be less than 4000") 105 | super(msg) 106 | end 107 | end 108 | end 109 | end 110 | -------------------------------------------------------------------------------- /HardsploitAPI/Core/HardsploitAPI_FIRMWARE.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | 9 | class HardsploitAPI 10 | public 11 | def loadFirmware(firmware) 12 | base_path = File.expand_path(File.dirname(__FILE__)) + '/../../Firmwares/FPGA/' 13 | case firmware 14 | when 'I2C' 15 | firmware_path = base_path + 'I2C/I2C_INTERACT/HARDSPLOIT_FIRMWARE_FPGA_I2C_INTERACT.rpd' 16 | HardsploitAPI.instance.uploadFirmware(pathFirmware: firmware_path, checkFirmware: false) 17 | when 'SPI' 18 | firmware_path = base_path + 'SPI/SPI_INTERACT/HARDSPLOIT_FIRMWARE_FPGA_SPI_INTERACT.rpd' 19 | HardsploitAPI.instance.uploadFirmware(pathFirmware: firmware_path, checkFirmware: false) 20 | when 'SPI_SNIFFER' 21 | firmware_path = base_path + 'SPI/SPI_SNIFFER/HARDSPLOIT_FIRMWARE_FPGA_SPI_SNIFFER.rpd' 22 | HardsploitAPI.instance.uploadFirmware(pathFirmware: firmware_path, checkFirmware: false) 23 | when 'PARALLEL' 24 | firmware_path = base_path + 'PARALLEL/NO_MUX_PARALLEL_MEMORY/HARDSPLOIT_FIRMWARE_FPGA_NO_MUX_PARALLEL_MEMORY.rpd' 25 | HardsploitAPI.instance.uploadFirmware(pathFirmware: firmware_path, checkFirmware: false) 26 | when 'SWD' 27 | firmware_path = base_path + 'SWD/SWD_INTERACT/HARDSPLOIT_FIRMWARE_FPGA_SWD_INTERACT.rpd' 28 | HardsploitAPI.instance.uploadFirmware(pathFirmware: firmware_path, checkFirmware: false) 29 | when 'UART' 30 | firmware_path = base_path + 'UART/UART_INTERACT/HARDSPLOIT_FIRMWARE_FPGA_UART_INTERACT.rpd' 31 | HardsploitAPI.instance.uploadFirmware(pathFirmware: firmware_path, checkFirmware: false) 32 | when 'uC' 33 | system("dfu-util -D 0483:df11 -a 0 -s 0x08000000 -R --download #{File.expand_path(File.dirname(__FILE__))}'/../Firmwares/UC/HARDSPLOIT_FIRMWARE_UC.bin'") 34 | end 35 | end 36 | 37 | # Wait to receive data 38 | # * +pathFirmware+:: path of rpd file (vhdl) 39 | # * +checkFirmware+:: boolean if check is needed (recommended false, in case issue true to check) 40 | # Return true if firmware write == firmware read (slow because read the firmware for check) 41 | def uploadFirmware(pathFirmware:,checkFirmware:) 42 | stopFPGA 43 | eraseFirmware 44 | firmwarewrite = self.writeFirmware(pathFirmware)#return array of bytes write 45 | if checkFirmware == true then 46 | firmwareRead = self.readFirmware(firmwarewrite.length) #return array of bytes read 47 | startFPGA 48 | sleep(1) 49 | return (firmwarewrite == firmwareRead) 50 | else 51 | startFPGA 52 | sleep(1) 53 | return true 54 | end 55 | end 56 | 57 | def startFPGA 58 | packet = Array.new 59 | packet.push HardsploitAPI.lowByte(word:4) 60 | packet.push HardsploitAPI.highByte(word:4) 61 | packet.push HardsploitAPI.lowByte(word:USB_COMMAND::START_FPGA) 62 | packet.push HardsploitAPI.highByte(word:USB_COMMAND::START_FPGA) 63 | self.sendPacket(packet) 64 | end 65 | def stopFPGA 66 | packet = Array.new 67 | packet.push HardsploitAPI.lowByte(word:4) 68 | packet.push HardsploitAPI.highByte(word:4) 69 | packet.push HardsploitAPI.lowByte(word:USB_COMMAND::STOP_FPGA) 70 | packet.push HardsploitAPI.highByte(word:USB_COMMAND::STOP_FPGA) 71 | self.sendPacket(packet) 72 | end 73 | 74 | 75 | protected 76 | def eraseFirmware 77 | usbPacket = Array.new 78 | usbPacket.push HardsploitAPI.lowByte(word:4) #length of trame 79 | usbPacket.push HardsploitAPI.highByte(word:4) 80 | usbPacket.push HardsploitAPI.lowByte(word:USB_COMMAND::ERASE_FIRMWARE) 81 | usbPacket.push HardsploitAPI.highByte(word:USB_COMMAND::ERASE_FIRMWARE) 82 | 83 | consoleInfo "Start to erase Firmware\n" 84 | t1 = Time.now 85 | 86 | #Timeout very high to detect the end of erasing 87 | received_data = sendAndReceiveDATA(usbPacket,15000) 88 | 89 | t2 = Time.now 90 | delta = t2 - t1 91 | consoleSpeed "Firmware erased in #{delta.round(4)} sec\n\n" 92 | 93 | end 94 | 95 | #Just path of file and wait. is a blocking function until firmware has been uploaded 96 | def writeFirmware (file_path) 97 | t1 = Time.now 98 | consoleInfo "Upload firmware in progress\n" 99 | 100 | usbPacket= Array.new 101 | file = File.read(file_path,:encoding => 'iso-8859-1').unpack('C*') #string to array byte 102 | puts "Date of last modification of the firmware #{File.mtime(file_path)}" 103 | 104 | consoleInfo "FIRMARE Write #{file.size} bytes\n" 105 | 106 | nbFullPage = file.size/256 107 | nbLastByte = file.size%256 108 | 109 | nbFullPacket = nbFullPage/31 110 | nbLastPagePacket = nbFullPage%31 111 | nbSuppressBytesAtLast = 256-nbLastByte 112 | #complete last page with the last alone byte ( without full page) 113 | if nbLastByte > 0 then 114 | for i in 0.. (nbSuppressBytesAtLast-1) 115 | file.push 0xFF 116 | end 117 | nbFullPage = nbFullPage+1 118 | nbLastByte = 0 119 | 120 | #recalculating packet after complete half page to a full page 121 | nbFullPacket = nbFullPage/31 122 | nbLastPagePacket = nbFullPage%31 123 | else 124 | nbSuppressBytesAtLast = 0 125 | end 126 | 127 | consoleInfo "REAL Write #{file.size} bytes\n" 128 | 129 | #Now only full page but maybe a half packet 130 | #Prepare the full packet (31 pages of 256 byte each) 131 | for ipacket in 0..nbFullPacket-1 132 | usbPacket= Array.new 133 | usbPacket.push 0 #lenght of trame modify by sendUSBPacket 134 | usbPacket.push 0 135 | usbPacket.push HardsploitAPI.lowByte(word:USB_COMMAND::WRITE_PAGE_FIRMWARE) 136 | usbPacket.push HardsploitAPI.highByte(word:USB_COMMAND::WRITE_PAGE_FIRMWARE) 137 | usbPacket.push HardsploitAPI.lowByte(word:(ipacket)*31) # low byte Nb of the first page 138 | usbPacket.push HardsploitAPI.highByte(word:(ipacket)*31) # high byte Nb of the first page 139 | usbPacket.push 31 #Nb of pages sent 140 | 141 | start = (ipacket)*31*256 142 | stop = (ipacket+1)*31*256 -1 #array start at index = 0 143 | 144 | for iFile in start..stop 145 | usbPacket.push HardsploitAPI.reverseBit(file[iFile]) 146 | end 147 | 148 | percent = ipacket *100 / (nbFullPacket-1) 149 | begin 150 | sendPacket(usbPacket) 151 | consoleSpeed "UPLOAD AT : #{ipacket} / #{(nbFullPacket-1)} (#{percent}) %\n" 152 | HardsploitAPI.instance.consoleProgress( 153 | percent: percent, 154 | startTime:t1, 155 | endTime: Time.new 156 | ) 157 | rescue 158 | raise USB_ERROR 159 | end 160 | end 161 | 162 | #Prepare the last packet with the rest of data 163 | if nbLastPagePacket >0 then 164 | usbPacket= Array.new 165 | usbPacket.push 0 #lenght of trame modify by sendUSBPacket 166 | usbPacket.push 0 167 | usbPacket.push HardsploitAPI.lowByte(word:USB_COMMAND::WRITE_PAGE_FIRMWARE) 168 | usbPacket.push HardsploitAPI.highByte(word:USB_COMMAND::WRITE_PAGE_FIRMWARE) 169 | 170 | if nbFullPacket == 0 then 171 | usbPacket.push HardsploitAPI.lowByte(word:(nbFullPacket)*31) # low byte Nb of the first page 172 | usbPacket.push HardsploitAPI.highByte(word:(nbFullPacket)*31) # high byte Nb of the first page 173 | else 174 | usbPacket.push HardsploitAPI.lowByte(word:(nbFullPacket)*31 + 1 ) # low byte Nb of the first page 175 | usbPacket.push HardsploitAPI.highByte(word:(nbFullPacket)*31+ 1 ) # high byte Nb of the first page 176 | end 177 | 178 | usbPacket.push nbLastPagePacket # nb of page < 31 179 | 180 | start = (nbFullPacket)*31*256 181 | stop = (nbFullPacket)*31*256 + nbLastPagePacket*256 -1 182 | 183 | for iFile in start..stop 184 | #inverted LSB MSB 185 | usbPacket.push HardsploitAPI.reverseBit(file[iFile]) 186 | end 187 | begin 188 | sendPacket(usbPacket) 189 | consoleSpeed "UPLOAD AT : 100 %\n" 190 | HardsploitAPI.instance.consoleProgress( 191 | percent: 100, 192 | startTime:t1, 193 | endTime: Time.new 194 | ) 195 | rescue 196 | raise ERROR::USB_ERROR 197 | end 198 | end 199 | 200 | t2 = Time.now 201 | delta = t2 - t1 202 | consoleSpeed "FIRMWARE WAS WRITTEN in #{delta.round(4)} sec\n" 203 | file.pop(nbSuppressBytesAtLast) 204 | return file 205 | end 206 | 207 | #Read firmware 208 | def readFirmware(size) 209 | consoleSpeed "START READ FIRMWARE \n" 210 | readFirmware = Array.new 211 | t1 = Time.now 212 | 213 | nbFullPage = size/256 214 | nbLastByte = size%256 215 | 216 | 217 | nbFullPacket = nbFullPage/31 218 | nbLastPagePacket = nbFullPage%31 219 | 220 | if nbLastByte > 0 then 221 | nbSuppressBytesAtLast = 256-nbLastByte 222 | 223 | nbFullPage = nbFullPage+1 224 | nbLastByte = 0 225 | 226 | nbFullPacket = nbFullPage/31 227 | nbLastPagePacket = nbFullPage%31 228 | else 229 | nbSuppressBytesAtLast = 0 230 | 231 | end 232 | 233 | for ipacket in 0..nbFullPacket-1 234 | usbPacket= Array.new 235 | usbPacket.push 7 236 | usbPacket.push 0 237 | usbPacket.push HardsploitAPI.lowByte(word:USB_COMMAND::READ_PAGE_FIRMWARE) 238 | usbPacket.push HardsploitAPI.highByte(word:USB_COMMAND::READ_PAGE_FIRMWARE) 239 | usbPacket.push HardsploitAPI.lowByte(word:(ipacket)*31) # low byte Nb of the first page 240 | usbPacket.push HardsploitAPI.highByte(word:(ipacket)*31) # high byte Nb of the first page 241 | usbPacket.push 31 # nb of page max 31 per packet 242 | 243 | received_data = sendAndReceiveDATA(usbPacket,3000) 244 | #remove header 245 | received_data = received_data.drop(7) 246 | 247 | #reverse byte 248 | received_data = received_data.collect {|x| HardsploitAPI.reverseBit(x) } 249 | readFirmware.push *received_data 250 | if nbFullPacket == 1 then 251 | consoleSpeed "READ AT : 1 / 2 50 %\n" 252 | HardsploitAPI.instance.consoleProgress( 253 | percent: 50, 254 | startTime:t1, 255 | endTime: Time.new 256 | ) 257 | else 258 | percent = ipacket *100 / (nbFullPacket-1) 259 | consoleSpeed "READ AT : #{ipacket} / #{(nbFullPacket-1)} (#{percent} %) \n" 260 | HardsploitAPI.instance.consoleProgress( 261 | percent: percent, 262 | startTime:t1, 263 | endTime: Time.new 264 | ) 265 | end 266 | end 267 | 268 | #Prepare the last packet with the rest of data 269 | if nbLastPagePacket >0 then 270 | usbPacket= Array.new 271 | usbPacket.push 7 272 | usbPacket.push 0 273 | usbPacket.push HardsploitAPI.lowByte(word:USB_COMMAND::READ_PAGE_FIRMWARE) 274 | usbPacket.push HardsploitAPI.highByte(word:USB_COMMAND::READ_PAGE_FIRMWARE) 275 | 276 | #Increase nb of page to add the last byte 277 | if nbFullPacket == 0 then 278 | usbPacket.push HardsploitAPI.lowByte(word:(nbFullPacket)*31) # low byte Nb of the first page 279 | usbPacket.push HardsploitAPI.highByte(word:(nbFullPacket)*31) # high byte Nb of the first page 280 | else 281 | usbPacket.push HardsploitAPI.lowByte(word:(nbFullPacket)*31 + 1 ) # low byte Nb of the first page 282 | usbPacket.push HardsploitAPI.highByte(word:(nbFullPacket)*31+ 1 ) # high byte Nb of the first page 283 | end 284 | 285 | usbPacket.push nbLastPagePacket 286 | 287 | received_data = sendAndReceiveDATA(usbPacket,15000) 288 | #remove header 289 | received_data = received_data.drop(7) 290 | #reverse byte 291 | received_data = received_data.collect {|x| HardsploitAPI.reverseBit(x) } 292 | readFirmware.push *received_data 293 | 294 | consoleSpeed "READ AT 100%\n" 295 | end 296 | 297 | #remove a fake byte at last of reading just for transmiting 298 | readFirmware.pop(nbSuppressBytesAtLast) 299 | 300 | t2 = Time.now 301 | delta = t2 - t1 302 | consoleSpeed "READ FIRMWARE FINISH in #{delta.round(4)} sec\n" 303 | return readFirmware 304 | end 305 | end 306 | -------------------------------------------------------------------------------- /HardsploitAPI/Core/HardsploitAPI_PROGRESS.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | 9 | class HardsploitAPI 10 | class HardsploitProgress 11 | def initialize(percent,timeElasped) 12 | @Percent = percent 13 | @TimeElasped = timeElasped 14 | end 15 | def getPercent 16 | return @Percent 17 | end 18 | def setPercent(percent) 19 | @Percent = percent 20 | end 21 | def getTimeElasped 22 | return @TimeElasped 23 | end 24 | def setTimeElasped(timeElasped) 25 | @TimeElasped = timeElasped 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /HardsploitAPI/Core/HardsploitAPI_USB_COMMUNICATION.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | 9 | require "benchmark" 10 | class HardsploitAPI 11 | public 12 | 13 | # Obtain the number of hardsploit connected to PC 14 | # Return number 15 | def self.getNumberOfBoardAvailable 16 | return LIBUSB::Context.new.devices(:idVendor => 0x0483, :idProduct => 0xFFFF).size 17 | end 18 | 19 | # Connect board and get an instance to work with 20 | # Return USB_STATE 21 | def connect 22 | @usb = LIBUSB::Context.new 23 | @devices = @usb.devices(:idVendor => 0x0483, :idProduct => 0xFFFF) 24 | 25 | if @devices.size == 0 then 26 | @device = nil 27 | @dev = nil 28 | raise ERROR::HARDSPLOIT_NOT_FOUND 29 | else 30 | if @@id >= @devices.size then 31 | raise ERROR::HARDSPLOIT_NOT_FOUND 32 | else 33 | begin 34 | if @dev == nil then 35 | @dev = @devices[@@id].open 36 | if RUBY_PLATFORM=~/linux/i && @dev.kernel_driver_active?(0) 37 | @dev.detach_kernel_driver(0) 38 | end 39 | @dev.claim_interface(0) 40 | end 41 | self.startFPGA 42 | sleep(0.1) 43 | self.setStatutLed(led:USB_COMMAND::GREEN_LED,state:true); 44 | rescue 45 | raise ERROR::USB_ERROR 46 | end 47 | end 48 | end 49 | end 50 | 51 | def reconncet 52 | @usb = LIBUSB::Context.new 53 | @devices = @usb.devices(:idVendor => 0x0483, :idProduct => 0xFFFF) 54 | if @devices.size == 0 then 55 | @device = nil 56 | @dev = nil 57 | raise ERROR::HARDSPLOIT_NOT_FOUND 58 | else 59 | begin 60 | @dev = @devices[@@id].open 61 | if RUBY_PLATFORM=~/linux/i && @dev.kernel_driver_active?(0) 62 | @dev.detach_kernel_driver(0) 63 | end 64 | @dev.claim_interface(0) 65 | self.startFPGA 66 | sleep(0.1) 67 | self.setStatutLed(led:USB_COMMAND::GREEN_LED,state:true); 68 | 69 | rescue 70 | raise ERROR::USB_ERROR 71 | end 72 | end 73 | end 74 | 75 | # Obtain low byte of a word 76 | # * +word+:: 16 bit word 77 | # Return low byte of the word 78 | def self.lowByte(word:) 79 | return word & 0xFF 80 | end 81 | 82 | # Obtain high byte of a word 83 | # * +word+:: 16 bit word 84 | # Return high byte of the word 85 | def self.highByte(word:) 86 | return (word & 0xFF00) >> 8 87 | end 88 | 89 | # Obtain high byte of a word 90 | # * +lByte+:: low byte 91 | # * +hByte+:: high byte 92 | # Return 16 bits integer concatenate with low and high bytes 93 | def self.BytesToInt(lByte:,hByte:) 94 | return (lByte + (hByte<<8)) 95 | end 96 | 97 | 98 | # Send data and wait to receive response 99 | # * +packet_send+:: array of byte 100 | # * +timeout+:: timeout to read response (ms) 101 | # Return USB_STATE or array with response (improve soon with exception) 102 | def sendAndReceiveDATA(packet_send,timeout) 103 | time = Time.new 104 | begin 105 | sendPacket(packet_send) 106 | received_data = @dev.bulk_transfer(:endpoint=>IN_ENDPOINT, :dataIn=>USB::USB_TRAME_SIZE, :timeout=>timeout) 107 | consoleSpeed "RECEIVE #{((received_data.bytes.to_a.size/(Time.new-time))).round(2)}Bytes/s #{(received_data.bytes.to_a.size)}Bytes in #{(Time.new-time).round(4)} s" 108 | return received_data.bytes.to_a 109 | rescue LIBUSB::ERROR_NO_DEVICE 110 | raise ERROR::HARDSPLOIT_NOT_FOUND 111 | rescue 112 | raise ERROR::USB_ERROR 113 | end 114 | end 115 | 116 | # Wait to receive data 117 | # * +timeout+:: timeout to read response (ms) 118 | # Return USB_STATE or array with response (improve soon with exception) 119 | def receiveDATA(timeout) 120 | begin 121 | received_data = @dev.bulk_transfer(:endpoint=>IN_ENDPOINT, :dataIn=>USB::USB_TRAME_SIZE, :timeout=>timeout) 122 | return received_data 123 | rescue LIBUSB::ERROR_NO_DEVICE 124 | raise ERROR::USB_ERROR 125 | rescue LIBUSB::ERROR_NO_DEVICE 126 | raise ERROR::HARDSPLOIT_NOT_FOUND 127 | end 128 | end 129 | 130 | # Send USB packet 131 | # * +packet+:: array with bytes 132 | # Return number of byte sent 133 | def sendPacket(packet_send) 134 | 135 | begin 136 | if packet_send.size <= 8191 then 137 | 138 | packet_send[0] = HardsploitAPI.lowByte(word:packet_send.size) 139 | packet_send[1] = HardsploitAPI.highByte(word:packet_send.size) 140 | 141 | #if a multiple of packet size add a value to explicit the end of trame 142 | if packet_send.size % 64 ==0 then 143 | packet_send.push 0 144 | end 145 | 146 | number_of_data_send = 0 147 | time = Benchmark.realtime do 148 | number_of_data_send = @dev.bulk_transfer(:endpoint=>OUT_ENDPOINT, :dataOut=>packet_send.pack('c*'),:timeout=>3000) 149 | end 150 | consoleSpeed "SEND #{((number_of_data_send/time)).round(2)}Bytes/s SEND #{(number_of_data_send)}Bytes in #{time.round(4)} s" 151 | if number_of_data_send == packet_send.size then 152 | return number_of_data_send 153 | else 154 | raise ERROR::USB_ERROR 155 | end 156 | else 157 | raise ERROR::USB_ERROR 158 | end 159 | rescue LIBUSB::ERROR_NO_DEVICE 160 | #TRY TO RECONNECT maybe error due to disconnecting and reconnecting board 161 | reconncet 162 | rescue 163 | raise ERROR::USB_ERROR 164 | end 165 | end 166 | end 167 | -------------------------------------------------------------------------------- /HardsploitAPI/Modules/I2C/HardsploitAPI_I2C.rb: -------------------------------------------------------------------------------- 1 | #=================================================== 2 | # Hardsploit API - By Opale Security 3 | # www.opale-security.com || www.hardsploit.io 4 | # License: GNU General Public License v3 5 | # License URI: http://www.gnu.org/licenses/gpl.txt 6 | #=================================================== 7 | require_relative '../../Core/HardsploitAPI' 8 | class HardsploitAPI_I2C 9 | 10 | public 11 | 12 | #attr_accessor :speed 13 | #attr_reader :device_version 14 | 15 | # * +speed+:: I2C::KHZ_40 , I2C::KHZ_100 , I2C::KHZ_400 , I2C::KHZ_1000 16 | def initialize(speed:) 17 | #to be sure the singleton was initialize 18 | HardsploitAPI.instance.connect 19 | self.speed=speed 20 | end 21 | 22 | def speed 23 | return @speed 24 | end 25 | 26 | def speed=(speed) 27 | unless [HardsploitAPI::I2C::KHZ_40, HardsploitAPI::I2C::KHZ_100, HardsploitAPI::I2C::KHZ_400,HardsploitAPI::I2C::KHZ_1000].include?(speed) then 28 | raise HardsploitAPI::ERROR::I2CWrongSpeed 29 | end 30 | @speed = speed 31 | end 32 | 33 | # Interact with I2C bus 34 | # * +payload+:: payload to send 35 | def i2c_Interact(payload:) 36 | if (payload.size > 4000) then 37 | raise TypeError, 'Size of the data need to be less than 4000' 38 | end 39 | 40 | packet = Array.new 41 | packet.push 0 #low byte of lenght of trame refresh automaticly before send by usb 42 | packet.push 0 #high byte of lenght of trame refresh automaticly before send by usb 43 | packet.push HardsploitAPI.lowByte(word:HardsploitAPI::USB_COMMAND::FPGA_COMMAND) 44 | packet.push HardsploitAPI.highByte(word:HardsploitAPI::USB_COMMAND::FPGA_COMMAND) 45 | 46 | packet.push 0x50 #Command RAW COMMUNICATION TO FPGA FIFO 47 | 48 | packet.push @speed #Add speed 49 | packet.concat payload #Add data 50 | 51 | #remove header (4 bytes 2 for size 2 for type of command) 52 | return HardsploitAPI.instance.sendAndReceiveDATA(packet,2000).drop(4) 53 | end 54 | 55 | # Start I2C scan to find addresses 56 | # * +speed+:: I2C::KHZ_100 , I2C::KHZ_400 , I2C::KHZ_1000 57 | # * Return An array 256 value for each addresse if 0 not present if 1 present 58 | def i2c_Scan 59 | if (@speed < 0) and (@speed >3) then 60 | I2CWrongSpeed 61 | end 62 | 63 | array_i2c_scan = Array.new 64 | result_scan = Array.new 65 | return_scan = Array.new 66 | 67 | #we want scan just read address it is a partial scan (fastest) 68 | for i in (1..255).step(2) do 69 | array_i2c_scan.push HardsploitAPI.lowByte(word:1) #Count Low Byte 70 | array_i2c_scan.push HardsploitAPI.highByte(word:1) #Count High Byte 71 | array_i2c_scan.push i 72 | end 73 | 74 | result_scan = i2c_Interact(payload:array_i2c_scan) 75 | if result_scan.size != 256 then 76 | result_scan.clear 77 | end 78 | 79 | for i in (0..result_scan.size-1).step(2) do 80 | #Check if ACK_ERROR 81 | if result_scan[i] == 1 then 82 | return_scan.push 1 #For write 83 | return_scan.push 1 #For read 84 | else 85 | return_scan.push 0 #For write 86 | return_scan.push 0 #For read 87 | end 88 | end 89 | return return_scan 90 | end 91 | 92 | # Interact with I2C bus 93 | # * +speed+:: I2C::KHZ_100 , I2C::KHZ_400 , I2C::KHZ_1000 94 | # * +i2cBaseAddress+:: I2C base address / Write address (8bits) 95 | # * +startAddress+:: Start address (included) 96 | # * +stopAddress+:: Stop address (included) 97 | # * +sizeMax+:: Size max of memory (important to calculate automaticly the number of byte to set address) 98 | def i2c_Generic_Dump (i2cBaseAddress:,startAddress:,stopAddress:,sizeMax:) 99 | if ((startAddress < 0) or (startAddress > sizeMax-1)) then 100 | raise TypeError, "Start address can't be negative and not more than size max - 1" 101 | end 102 | 103 | if ((stopAddress < 0) or (stopAddress > (sizeMax-1))) then 104 | raise TypeError, "Stop address can't be negative and not more than size max-1 because start at 0" 105 | end 106 | 107 | if (stopAddress <= startAddress) then 108 | raise TypeError, "Stop address need to be greater than start address" 109 | end 110 | 111 | numberOfByteAddress = (((Math.log(sizeMax-1,2)).floor + 1) / 8.0).ceil 112 | if numberOfByteAddress > 4 then 113 | raise TypeError, "Size max must be less than 2^32 about 4Gb" 114 | end 115 | 116 | if numberOfByteAddress <= 0 then 117 | raise TypeError, "There is an issue with calculating of number of byte needed" 118 | end 119 | startTime = Time.now 120 | packet_size = 2000 - numberOfByteAddress - 1 121 | number_complet_packet = ( (stopAddress-startAddress+1) / packet_size).floor 122 | size_last_packet = (stopAddress-startAddress+1) % packet_size 123 | 124 | #SEND the first complete trame 125 | for i in 0..number_complet_packet - 1 do 126 | packet = generate_i2c_read_command( 127 | i2cBaseAddress: i2cBaseAddress, 128 | numberOfByteAddress: numberOfByteAddress + startAddress, 129 | startAddress: i * packet_size, 130 | size: packet_size 131 | ) 132 | #Remove header, result of read command and numberOfByte Address too 133 | HardsploitAPI.instance.consoleData ( process_dump_i2c_result( i2c_Interact( payload: packet ))) 134 | HardsploitAPI.instance.consoleProgress( 135 | percent: 100 * ( i + 1 ) / ( number_complet_packet + ( size_last_packet.zero? ? 0 : 1 )), 136 | startTime: startTime, 137 | endTime: Time.new 138 | ) 139 | end 140 | 141 | if(size_last_packet > 0 ) then 142 | packet = generate_i2c_read_command( 143 | i2cBaseAddress: i2cBaseAddress, 144 | numberOfByteAddress: numberOfByteAddress, 145 | startAddress: number_complet_packet * packet_size + startAddress, 146 | size: size_last_packet 147 | ) 148 | #Remove header, result of read command and numberOfByte Address too 149 | HardsploitAPI.instance.consoleData( process_dump_i2c_result( i2c_Interact( payload:packet ))) 150 | HardsploitAPI.instance.consoleProgress( 151 | percent: 100, 152 | startTime: startTime, 153 | endTime: Time.new 154 | ) 155 | end 156 | 157 | delta = Time.now - startTime 158 | HardsploitAPI.instance.consoleSpeed "Write in #{delta.round(4)} sec" 159 | end 160 | 161 | #For the moment only with EEPROM (not need to erase or activate write) 162 | def i2c_Generic_Import (i2cBaseAddress:,startAddress:,pageSize:,memorySize:,dataFile:,writePageLatency:) 163 | startTime = Time.now 164 | begin 165 | file = File.open(dataFile, 'rb') 166 | sizeFile = file.size 167 | rescue Exception => e 168 | raise Error::FileIssue, e.message 169 | end 170 | 171 | if ((startAddress < 0) or (startAddress > memorySize - 1)) then 172 | raise Error::WrongStartAddress 173 | end 174 | 175 | if ((pageSize <= 0) and (pageSize > 1024)) then 176 | raise TypeError, "pageSize need to be greater than 0 and less than 1024" 177 | end 178 | 179 | numberOfByteAddress = (((Math.log(memorySize - 1, 2)).floor + 1) / 8.0).ceil 180 | if numberOfByteAddress > 4 then 181 | raise TypeError, "Size max must be less than 2^32 about 4Gb" 182 | end 183 | 184 | if numberOfByteAddress <= 0 then 185 | raise TypeError, "There is an issue with calculating of number of byte needed" 186 | end 187 | 188 | packet_size = pageSize 189 | number_complet_packet = (sizeFile / packet_size).floor 190 | size_last_packet = sizeFile % packet_size 191 | 192 | #SEND the first complete trame 193 | for i in 0..number_complet_packet-1 do 194 | packet = generate_i2c_write_command( 195 | i2cBaseAddress: i2cBaseAddress, 196 | numberOfByteAddress: numberOfByteAddress, 197 | startAddress: i * packet_size, 198 | data: file.read( packet_size ).unpack( "C*" ) 199 | ) 200 | 201 | #Remove header, result of read command and numberOfByte Address too 202 | process_import_i2c_result( i2c_Interact( payload: packet )) 203 | 204 | HardsploitAPI.instance.consoleProgress( 205 | percent: 100 * ( i + 1 ) / ( number_complet_packet + ( size_last_packet.zero? ? 0 : 1 )), 206 | startTime: startTime, 207 | endTime: Time.new 208 | ) 209 | #if too many error when write increase because we need to wait to write a full page 210 | sleep(writePageLatency) 211 | end 212 | 213 | if(size_last_packet > 0 ) then 214 | packet = generate_i2c_write_command( 215 | i2cBaseAddress: i2cBaseAddress, 216 | numberOfByteAddress: numberOfByteAddress, 217 | startAddress: number_complet_packet * packet_size + startAddress, 218 | data: file.read( size_last_packet ).unpack( "C*" ) 219 | ) 220 | 221 | #Remove header, result of read command and numberOfByte Address too 222 | process_import_i2c_result ( i2c_Interact(payload: packet) ) 223 | HardsploitAPI.instance.consoleProgress( 224 | percent: 100, 225 | startTime: startTime, 226 | endTime: Time.new 227 | ) 228 | end 229 | 230 | delta = Time.now - startTime 231 | HardsploitAPI.instance.consoleSpeed "Write in #{delta.round(4)} sec" 232 | end 233 | 234 | def find(numberOfConnectedPinFromA0:) 235 | posibility = HardsploitAPI.allPosibility( 236 | numberOfConnectedPinFromA0: numberOfConnectedPinFromA0, 237 | numberOfSignalsForBus: 2 238 | ) 239 | compare_tab = Array.new(256, 1) 240 | for item in posibility 241 | currentWiring = 0 242 | for value in item 243 | currentWiring += 2 ** value 244 | end 245 | HardsploitAPI.instance.setWiringLeds(value: currentWiring) 246 | for i in 0..(63 - item.size) 247 | item.push i + numberOfConnectedPinFromA0 248 | end 249 | HardsploitAPI.instance.setCrossWiring(value: item) 250 | begin 251 | tab = i2c_Scan 252 | return item if tab.include?(1) and tab != compare_tab 253 | rescue Exception => msg 254 | puts msg 255 | end 256 | end 257 | end 258 | 259 | private 260 | 261 | def process_import_i2c_result (packet) 262 | result = Array.new 263 | for i in (0..packet.size - 1).step(2) do 264 | case packet[i] 265 | when 0 #Write ACK 266 | #Do nothing,don't save write ack 267 | else 268 | raise TypeError, "Error in I2C transaction (NACK), write failed " 269 | end 270 | end 271 | return result 272 | end 273 | 274 | def process_dump_i2c_result (packet) 275 | result = Array.new 276 | for i in (0..packet.size - 1).step(2) do 277 | case packet[i] 278 | when 1 #Read ACK 279 | #Save read data 280 | result.push packet[i + 1] 281 | when 0 #Write ACK 282 | #Do nothing,don't save write ack 283 | else 284 | raise TypeError, "Error in I2C transaction, I2C export seems to be wrong" 285 | end 286 | end 287 | return result 288 | end 289 | 290 | def generate_i2c_write_command (i2cBaseAddress:, numberOfByteAddress:, startAddress:, data:) 291 | packet = Array.new 292 | #Push write command 293 | packet.push HardsploitAPI.lowByte(word:numberOfByteAddress+data.size) #size of write command 294 | packet.push HardsploitAPI.highByte(word:numberOfByteAddress+data.size) #size of write command 295 | 296 | packet.push i2cBaseAddress #push Write address 297 | 298 | case numberOfByteAddress 299 | when 1 300 | packet.push ((startAddress & 0x000000FF) >> 0) #AddStart0 301 | when 2 302 | packet.push ((startAddress & 0x0000FF00) >> 8 ) #AddStart1 303 | packet.push ((startAddress & 0x000000FF) >> 0) #AddStart 304 | when 3 305 | packet.push ((startAddress & 0x00FF0000) >> 16 ) #AddStart2 306 | packet.push ((startAddress & 0x0000FF00) >> 8 ) #AddStart1 307 | packet.push ((startAddress & 0x000000FF) >> 0) #AddStart0 308 | when 4 309 | packet.push ((startAddress & 0xFF000000) >> 24 ) #AddStart3 310 | packet.push ((startAddress & 0x00FF0000) >> 16 ) #AddStart2 311 | packet.push ((startAddress & 0x0000FF00) >> 8 ) #AddStart1 312 | packet.push ((startAddress & 0x000000FF) >> 0) #AddStart0 313 | else 314 | raise TypeError, "Issue in generate_i2c_write_command function when parse number of byte address" 315 | end 316 | 317 | #Push data to write 318 | packet.push *data 319 | return packet 320 | end 321 | 322 | def generate_i2c_read_command (i2cBaseAddress:, numberOfByteAddress:, startAddress:, size:) 323 | packet = Array.new 324 | #Push write command for start address 325 | packet.push HardsploitAPI.lowByte(word: numberOfByteAddress) #size of write command 326 | packet.push HardsploitAPI.highByte(word: numberOfByteAddress) #size of write command 327 | 328 | packet.push i2cBaseAddress #push Write address 329 | 330 | case numberOfByteAddress 331 | when 1 332 | packet.push ((startAddress & 0x000000FF) >> 0) #AddStart0 333 | when 2 334 | packet.push ((startAddress & 0x0000FF00) >> 8 ) #AddStart1 335 | packet.push ((startAddress & 0x000000FF) >> 0) #AddStart 336 | when 3 337 | packet.push ((startAddress & 0x00FF0000) >> 16 ) #AddStart2 338 | packet.push ((startAddress & 0x0000FF00) >> 8 ) #AddStart1 339 | packet.push ((startAddress & 0x000000FF) >> 0) #AddStart0 340 | when 4 341 | packet.push ((startAddress & 0xFF000000) >> 24 ) #AddStart3 342 | packet.push ((startAddress & 0x00FF0000) >> 16 ) #AddStart2 343 | packet.push ((startAddress & 0x0000FF00) >> 8 ) #AddStart1 344 | packet.push ((startAddress & 0x000000FF) >> 0) #AddStart0 345 | else 346 | raise TypeError, "Issue in generate_spi_read_command function when parse number of byte address" 347 | end 348 | 349 | #Push read command to read size data 350 | packet.push HardsploitAPI.lowByte(word:size) #size of read command 351 | packet.push HardsploitAPI.highByte(word:size) #size of read command 352 | packet.push i2cBaseAddress+1 #push read address 353 | 354 | return packet 355 | end 356 | end 357 | -------------------------------------------------------------------------------- /HardsploitAPI/Modules/NO_MUX_PARALLEL_MEMORY/HardsploitAPI_NO_MUX_PARALLEL_MEMORY.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | 9 | class HardsploitAPI_PARALLEL 10 | public 11 | def initialize 12 | #to be sure the singleton was initialize 13 | HardsploitAPI.instance.connect 14 | end 15 | 16 | def readManufactuerCodeMemory 17 | write_command_Memory_WithoutMultiplexing(0x00000000,0x90) #ReadDeviceIdentifierCommand 18 | return readByteFromMemory(1) #Read from 1 to 1 = read 1 byte at 1 19 | end 20 | 21 | def readDeviceIdMemory 22 | write_command_Memory_WithoutMultiplexing(0x00000000,0x90) #ReadDeviceIdentifierCommand 23 | return readByteFromMemory(0)#Read 0 24 | end 25 | 26 | def writeByteToMemory(address,value) 27 | #Write data in word mode and read Five status register 28 | write_command_Memory_WithoutMultiplexing(address,0x0040) 29 | write_command_Memory_WithoutMultiplexing(address,value) 30 | return readByteFromMemory(0) 31 | end 32 | 33 | def readMode 34 | #go in read mode 35 | write_command_Memory_WithoutMultiplexing(0x000000,0x00FF) 36 | end 37 | 38 | def eraseBlockMemory(blockAddress) 39 | #Read Five Word 40 | write_command_Memory_WithoutMultiplexing(blockAddress,0x0020) #Block erase command 41 | statut = write_command_Memory_WithoutMultiplexing(blockAddress,0x00D0) #Confirm Block erase command 42 | 43 | timeout = 10 44 | # while (statut != 128 ) && (timeout >= 0) 45 | # 46 | # puts "#{statut} #{timeout}" 47 | # statut = readByteFromMemory(0) #read statut register 48 | # sleep(100) 49 | # if timeout == 0 then 50 | # return statut 51 | # else 52 | # timeout = timeout-1 53 | # end 54 | # end 55 | for ty in 0..4 56 | puts readByteFromMemory(0) 57 | end 58 | 59 | puts "Return timeout" 60 | return statut 61 | end 62 | 63 | def clearStatusRegisterOfMemory 64 | #Clear Statut register 65 | write_command_Memory_WithoutMultiplexing(0x000000,0x50) 66 | end 67 | 68 | def unlockBlock (blockAddress) 69 | write_command_Memory_WithoutMultiplexing(blockAddress,0x0060) #Lock Block Command 70 | write_command_Memory_WithoutMultiplexing(blockAddress,0x00D0) #UnLock Command 71 | return readByteFromMemory(0x000000) #read statut register 72 | end 73 | 74 | def write_command_Memory_WithoutMultiplexing(address,data) 75 | packet = HardsploitAPI.prepare_packet 76 | packet.push 0 #16 bits 77 | packet.push (1500/6.66).floor #latency at 1500ns 78 | 79 | packet.push ((address & 0xFF000000) >> 24 ) #AddStart3 80 | packet.push ((address & 0x00FF0000) >> 16 ) #AddStart2 81 | packet.push ((address & 0x0000FF00) >> 8 ) #AddStart1 82 | packet.push ((address & 0x000000FF) >> 0) #AddStart0 83 | packet.push 0x20 #Memory write command 84 | packet.push ((data & 0xFF00) >> 8 ) #Data HIGHT BYTE 85 | packet.push ((data & 0xFF) >> 0) #Data LOW BYTE 86 | 87 | 88 | result = HardsploitAPI.instance.sendAndReceiveDATA(packet,1000) 89 | if result == USB_STATE::TIMEOUT_RECEIVE then 90 | raise "TIMEOUT" 91 | elsif result[4] == (data & 0xFF) 92 | 93 | return readByteFromMemory(0) 94 | else 95 | raise "ERROR BAD RESPONSE" 96 | end 97 | end 98 | 99 | def readByteFromMemory(address) 100 | packet = Array.new 101 | packet.push 0 #low byte of lenght of trame refresh automaticly before send by usb 102 | packet.push 0 #high byte of lenght of trame refresh automaticly before send by usb 103 | packet.push HardsploitAPI.lowByte(HardsploitAPI::USB_COMMAND::FPGA_COMMAND) 104 | packet.push HardsploitAPI.highByte(HardsploitAPI::USB_COMMAND::FPGA_COMMAND) 105 | 106 | packet.push 0x50 #Command RAW COMMUNICATION TO FPGA FIFO 107 | 108 | 109 | #16 bits 110 | packet.push 0 111 | packet.push (1500/6.66).floor 112 | 113 | 114 | packet.push ((address & 0xFF000000) >> 24 ) #AddStart3 115 | packet.push ((address & 0x00FF0000) >> 16 ) #AddStart2 116 | packet.push ((address & 0x0000FF00) >> 8 ) #AddStart1 117 | packet.push ((address & 0x000000FF) >> 0) #AddStart0 118 | 119 | packet.push 0x10 #Memory read command 120 | packet.push ((address & 0xFF000000) >> 24 ) #AddStart3 121 | packet.push ((address & 0x00FF0000) >> 16 ) #AddStop2 122 | packet.push ((address & 0x0000FF00) >> 8 ) #AddStop1 123 | packet.push ((address & 0x000000FF) >> 0) #AddStop0 124 | 125 | result = sendAndReceiveDATA(packet,1000) 126 | 127 | if result == USB_STATE::TIMEOUT_RECEIVE then 128 | return "TIMEOUT" 129 | else 130 | if result.size == 6 then 131 | return HardsploitAPI.BytesToInt(result[4] , result[5]) 132 | else 133 | raise "BAD RESPONSE" 134 | end 135 | end 136 | end 137 | 138 | 139 | 140 | 141 | 142 | # Read parallele memory in asynchronous mode (blocking function) but callBack data is used to receive packet 143 | # * +addressStart+:: 32 bits address 144 | # * +addressStop+:: 32 bits address 145 | # * +bits8_or_bits16_DataSize+:: 0 for 8 bits operation & 1 for 16 bits operation 146 | # * +latency+:: latency in ns range 7ns to 1600ns=1,6ms 147 | # Return USB_STATE End with TIMEOUT_RECEIVE but need to check if received the right number of bytes to ensure all is correct 148 | def read_Memory_WithoutMultiplexing(path:,addressStart: , addressStop:, bits8_or_bits16_DataSize:, latency:) 149 | numberOfByteReaded = 0 150 | packet = HardsploitAPI.prepare_packet 151 | 152 | #Chek if 8bits or 16 bits 153 | if bits8_or_bits16_DataSize == true then 154 | packet.push 1 155 | else 156 | packet.push 0 157 | end 158 | 159 | #Check latency value 160 | if ((latency >= 7) and (latency <= 1600)) then 161 | packet.push (latency/6.66).floor 162 | else 163 | raise TypeError, 'Latency value must be from 7 to 1695' 164 | end 165 | 166 | #Check address 167 | if (addressStop <= addressStart ) then 168 | raise TypeError, 'Stop address is less than start address' 169 | end 170 | 171 | packet.push ((addressStart & 0xFF000000) >> 24 ) #AddStart3 172 | packet.push ((addressStart & 0x00FF0000) >> 16 ) #AddStart2 173 | packet.push ((addressStart & 0x0000FF00) >> 8 ) #AddStart1 174 | packet.push ((addressStart & 0x000000FF) >> 0) #AddStart0 175 | 176 | packet.push 0x10 #Memory read command 177 | packet.push ((addressStop & 0xFF000000) >> 24 ) #AddStart3 178 | packet.push ((addressStop & 0x00FF0000) >> 16 ) #AddStop2 179 | packet.push ((addressStop & 0x0000FF00) >> 8 ) #AddStop1 180 | packet.push ((addressStop & 0x000000FF) >> 0) #AddStop0 181 | 182 | HardsploitAPI.instance.sendPacket(packet) 183 | 184 | if bits8_or_bits16_DataSize then 185 | sizeCalculated = (addressStop-addressStart+1) 186 | else 187 | sizeCalculated = (addressStop-addressStart+1)*2 188 | end 189 | file = File.open(path,"wb") 190 | numberOfByteReaded = 0 191 | while true 192 | tmp= HardsploitAPI.instance.receiveDATA(2000) 193 | #remove header (4 bytes 2 for size 2 for type of command) 194 | tmp = tmp.bytes.drop(4) 195 | file.write tmp.pack('C*') 196 | 197 | numberOfByteReaded = numberOfByteReaded + tmp.size 198 | HardsploitAPI.instance.consoleInfo "Receive #{numberOfByteReaded} of #{sizeCalculated}" 199 | if numberOfByteReaded >= sizeCalculated then 200 | file.close 201 | #Exit because we received all data 202 | return 203 | end 204 | end 205 | end 206 | end 207 | -------------------------------------------------------------------------------- /HardsploitAPI/Modules/NRF24L01/HardsploitAPI_NRF24L01.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | 9 | require_relative '../../Core/HardsploitAPI' 10 | require_relative '../../Modules/SPI/HardsploitAPI_SPI' 11 | class HardsploitAPI_NRF24L01 12 | public 13 | # Instruction Mnemonics 14 | R_REGISTER = 0x00 15 | W_REGISTER = 0x20 16 | REGISTER_MASK = 0x1F 17 | ACTIVATE = 0x50 18 | R_RX_PL_WID = 0x60 19 | R_RX_PAYLOAD = 0x61 20 | W_TX_PAYLOAD = 0xA0 21 | W_ACK_PAYLOAD = 0xA8 22 | FLUSH_TX = 0xE1 23 | FLUSH_RX = 0xE2 24 | REUSE_TX_PL = 0xE3 25 | NOP = 0xFF 26 | 27 | #Register map 28 | NRF24L01_00_CONFIG = 0x00 29 | NRF24L01_01_EN_AA = 0x01 30 | NRF24L01_02_EN_RXADDR = 0x02 31 | NRF24L01_03_SETUP_AW = 0x03 32 | NRF24L01_04_SETUP_RETR = 0x04 33 | NRF24L01_05_RF_CH = 0x05 34 | NRF24L01_06_RF_SETUP = 0x06 35 | NRF24L01_07_STATUS = 0x07 36 | NRF24L01_08_OBSERVE_TX = 0x08 37 | NRF24L01_09_CD = 0x09 38 | NRF24L01_0A_RX_ADDR_P0 = 0x0A 39 | NRF24L01_0B_RX_ADDR_P1 = 0x0B 40 | NRF24L01_0C_RX_ADDR_P2 = 0x0C 41 | NRF24L01_0D_RX_ADDR_P3 = 0x0D 42 | NRF24L01_0E_RX_ADDR_P4 = 0x0E 43 | NRF24L01_0F_RX_ADDR_P5 = 0x0F 44 | NRF24L01_10_TX_ADDR = 0x10 45 | NRF24L01_11_RX_PW_P0 = 0x11 46 | NRF24L01_12_RX_PW_P1 = 0x12 47 | NRF24L01_13_RX_PW_P2 = 0x13 48 | NRF24L01_14_RX_PW_P3 = 0x14 49 | NRF24L01_15_RX_PW_P4 = 0x15 50 | NRF24L01_16_RX_PW_P5 = 0x16 51 | NRF24L01_17_FIFO_STATUS = 0x17 52 | NRF24L01_1C_DYNPD = 0x1C 53 | NRF24L01_1D_FEATURE = 0x1D 54 | 55 | # Bit mnemonics 56 | NRF24L01_00_MASK_RX_DR = 6 57 | NRF24L01_00_MASK_TX_DS = 5 58 | NRF24L01_00_MASK_MAX_RT = 4 59 | NRF24L01_00_EN_CRC = 3 60 | NRF24L01_00_CRCO = 2 61 | NRF24L01_00_PWR_UP = 1 62 | NRF24L01_00_PRIM_RX = 0 63 | NRF24L01_07_RX_DR = 6 64 | NRF24L01_07_TX_DS = 5 65 | NRF24L01_07_MAX_RT = 4 66 | 67 | # Bitrates 68 | NRF24L01_BR_1M = 0 69 | NRF24L01_BR_2M = 1 70 | NRF24L01_BR_250K = 2 71 | NRF24L01_BR_RSVD = 3 72 | 73 | TXRX_OFF = 0 74 | TX_EN = 1 75 | RX_EN = 2 76 | 77 | def BV(x) 78 | return (1 << x) 79 | end 80 | 81 | def sendAndReceiveSPI(packet) 82 | begin 83 | return @spi.spi_Interact(payload:packet) 84 | rescue HardsploitAPI::ERROR::HARDSPLOIT_NOT_FOUND 85 | puts "Hardsploit not found" 86 | rescue HardsploitAPI::ERROR::USB_ERROR 87 | puts "USB ERROR" 88 | end 89 | end 90 | 91 | def initialize() 92 | #Speed Range 1-255 SPI clock = 150Mhz / (2*speed) tested from 3 to 255 (25Mhz to about 0.3Khz) 93 | @spi = HardsploitAPI_SPI.new(speed:8,mode:0) # 150/(2*8) = 9.3Mhz 94 | @rf_setup = 0x0F 95 | @tout =0 96 | end 97 | 98 | def initDrone(channel:,address:) 99 | config = BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PRIM_RX) 100 | NRF24L01_WriteReg(NRF24L01_00_CONFIG, config); 101 | NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x0f); # Auto Acknoledgement 102 | NRF24L01_Activate(0x73); #Allow write feature reg 103 | NRF24L01_WriteReg( NRF24L01_1D_FEATURE,0x06); #enableDynamicPayloads 104 | NRF24L01_WriteReg( NRF24L01_1C_DYNPD,0x3f); #enableDynamicPayloads 105 | NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); # Enable data pipe 0 106 | NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); # 5-byte RX/TX address 107 | #NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0xFF); # 4ms retransmit t/o, 15 tries 108 | NRF24L01_WriteReg(NRF24L01_05_RF_CH, channel); # Channel - bind 109 | setBitrate(NRF24L01_BR_250K) 110 | setPower(3) #Max power 111 | NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); # Clear data ready, data 112 | NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, 16); 113 | NRF24L01_WriteReg(NRF24L01_17_FIFO_STATUS, 0x00); 114 | NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0,address); 115 | NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, address); 116 | 117 | initialize(); 118 | 119 | config |= BV(NRF24L01_00_PWR_UP); 120 | NRF24L01_WriteReg(NRF24L01_00_CONFIG, config); 121 | 122 | valid_packets = missed_packets = bad_packets = 0; 123 | 124 | NRF24L01_SetTxRxMode(TXRX_OFF); 125 | NRF24L01_SetTxRxMode(RX_EN); 126 | # puts "EN_AA" 127 | # p NRF24L01_ReadReg(NRF24L01_01_EN_AA) 128 | # puts "EN_RXADDR" 129 | # p NRF24L01_ReadReg(NRF24L01_02_EN_RXADDR) 130 | # puts "SETUP_AW" 131 | # p NRF24L01_ReadReg(NRF24L01_03_SETUP_AW) 132 | # puts "RF_CH" 133 | # p NRF24L01_ReadReg(NRF24L01_05_RF_CH) 134 | # puts "RX_PW_P0" 135 | # p NRF24L01_ReadRegisterMulti(NRF24L01_0A_RX_ADDR_P0,5) 136 | # puts "TX_PW_P0" 137 | # p NRF24L01_ReadRegisterMulti(NRF24L01_10_TX_ADDR,5) 138 | # puts "RX_ADDR_P0" 139 | # p NRF24L01_ReadReg(NRF24L01_0A_RX_ADDR_P0) 140 | # puts "TX_ADDR" 141 | # p NRF24L01_ReadReg(NRF24L01_10_TX_ADDR) 142 | # puts "config" 143 | # p config 144 | end 145 | 146 | def NRF24L01_WriteReg(reg, data) 147 | result = sendAndReceiveSPI([ (W_REGISTER | (REGISTER_MASK & reg)),data ]) 148 | return result[1] 149 | end 150 | 151 | def NRF24L01_WriteRegisterMulti(reg, payload) 152 | tmppayload = Array.new 153 | tmppayload.push (W_REGISTER | (REGISTER_MASK & reg)) 154 | tmppayload.push *payload 155 | result = sendAndReceiveSPI(tmppayload) 156 | return result[0] 157 | end 158 | 159 | def NRF24L01_WritePayload(payload) 160 | tmpWpayload = Array.new 161 | tmpWpayload.push (W_TX_PAYLOAD) 162 | tmpWpayload.push *payload 163 | result = sendAndReceiveSPI(tmpWpayload) 164 | return result[0] 165 | end 166 | 167 | def NRF24L01_ReadReg(reg) 168 | result = sendAndReceiveSPI([R_REGISTER | (REGISTER_MASK & reg) ,0xFF ]) 169 | return result[1] 170 | end 171 | 172 | def readPayloadSize 173 | result = sendAndReceiveSPI([R_RX_PL_WID ,0xFF ]) 174 | return result[1] 175 | end 176 | 177 | def NRF24L01_ReadRegisterMulti(reg,length) 178 | tab = Array.new 179 | tab.push (R_REGISTER | (REGISTER_MASK & reg)) 180 | tab.push *Array.new(length, 0xFF) 181 | return sendAndReceiveSPI(tab).drop(1) #remove the first byte 182 | end 183 | 184 | def readPayload(length) 185 | tab = Array.new 186 | tab.push R_RX_PAYLOAD 187 | tab.push *Array.new(length, 0xFF) 188 | return sendAndReceiveSPI(tab).drop(1) #remove the first byte 189 | end 190 | 191 | def readAvailableData 192 | return readPayload(readPayloadSize) 193 | end 194 | 195 | def Strobe(state) 196 | result = sendAndReceiveSPI([state]) 197 | return result[0]; 198 | end 199 | 200 | def NRF24L01_FlushTx() 201 | return Strobe(FLUSH_TX); 202 | end 203 | 204 | def NRF24L01_FlushRx() 205 | return Strobe(FLUSH_RX); 206 | end 207 | 208 | def NRF24L01_Activate(code) 209 | result = sendAndReceiveSPI([ACTIVATE ,code]) 210 | return result[0]; 211 | end 212 | 213 | def dataAvailable() 214 | result = sendAndReceiveSPI([R_REGISTER ,HardsploitAPI_NRF24L01::NRF24L01_07_STATUS]) 215 | if ((result[0] & BV(HardsploitAPI_NRF24L01::NRF24L01_07_RX_DR))>>6)==1 216 | return true 217 | else 218 | return false 219 | end 220 | end 221 | 222 | def changeChannel(channel:) 223 | NRF24L01_WriteReg(NRF24L01_05_RF_CH, channel) 224 | end 225 | 226 | def setBitrate(bitrate) 227 | #Note that bitrate 250kbps (and bit RF_DR_LOW) is valid only 228 | #for nRF24L01+. There is no way to programmatically tell it from 229 | #older version, nRF24L01, but the older is practically phased out 230 | #by Nordic, so we assume that we deal with with modern version. 231 | 232 | # Bit 0 goes to RF_DR_HIGH, bit 1 - to RF_DR_LOW 233 | @rf_setup = (@rf_setup & 0xD7) | ((bitrate & 0x02) << 4) | ((bitrate & 0x01) << 3); 234 | return NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, @rf_setup); 235 | end 236 | 237 | # Power setting is 0..3 for nRF24L01 238 | def setPower(nrf_power) 239 | if (nrf_power < 0) or (nrf_power > 3) then 240 | raise "NRF setPower, wrong must be between 0 and 3" 241 | end 242 | @rf_setup = (@rf_setup & 0xF9) | ((nrf_power & 0x03) << 1) 243 | return NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, @rf_setup) 244 | end 245 | 246 | def CE_lo 247 | @spi.pulse = 0 248 | end 249 | 250 | def CE_hi 251 | @spi.pulse = 1 252 | end 253 | 254 | def NRF24L01_SetTxRxMode(mode) 255 | if(mode == TX_EN) then 256 | CE_lo() 257 | #sleep(0.5) 258 | NRF24L01_WriteReg(NRF24L01_07_STATUS, (1 << NRF24L01_07_RX_DR) | (1 << NRF24L01_07_TX_DS) | (1 << NRF24L01_07_MAX_RT)) #reset the flag(s) 259 | NRF24L01_WriteReg(NRF24L01_00_CONFIG, (1 << NRF24L01_00_EN_CRC)| (1 << NRF24L01_00_CRCO) | (1 << NRF24L01_00_PWR_UP)) #switch to TX mode 260 | #sleep(0.5) 261 | CE_hi() 262 | elsif (mode == RX_EN) then 263 | CE_lo() 264 | # sleep(0.5) 265 | NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70) # reset the flag(s) 266 | NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0F) # switch to RX mode 267 | NRF24L01_WriteReg(NRF24L01_07_STATUS, (1 << NRF24L01_07_RX_DR) | (1 << NRF24L01_07_TX_DS) | (1 << NRF24L01_07_MAX_RT)) #reset the flag(s) 268 | NRF24L01_WriteReg(NRF24L01_00_CONFIG, (1 << NRF24L01_00_EN_CRC)| (1 << NRF24L01_00_CRCO) | (1 << NRF24L01_00_PWR_UP) | (1 << NRF24L01_00_PRIM_RX)) #switch to RX mode 269 | # sleep(0.5) 270 | CE_hi() 271 | else 272 | NRF24L01_WriteReg(NRF24L01_00_CONFIG, (1 << NRF24L01_00_EN_CRC)) #PowerDown 273 | CE_lo() 274 | end 275 | end 276 | 277 | def reset() 278 | NRF24L01_SetTxRxMode(TXRX_OFF) 279 | NRF24L01_FlushTx() 280 | NRF24L01_FlushRx() 281 | return true 282 | end 283 | 284 | def Read() 285 | tabdataread = Array.new 286 | if dataAvailable() 287 | NRF24L01_WriteReg(0x07,BV(HardsploitAPI_NRF24L01::NRF24L01_07_RX_DR)) 288 | tabdataread.push *readPayload(16) 289 | return tabdataread 290 | else 291 | return tabdataread 292 | end 293 | end 294 | 295 | def Send(dataSend) 296 | NRF24L01_SetTxRxMode(TXRX_OFF) 297 | NRF24L01_FlushTx() 298 | NRF24L01_WritePayload(dataSend) 299 | NRF24L01_SetTxRxMode(TX_EN) 300 | sleep(0.1) 301 | NRF24L01_SetTxRxMode(TXRX_OFF) 302 | NRF24L01_FlushTx() 303 | NRF24L01_FlushRx() 304 | NRF24L01_SetTxRxMode(RX_EN); 305 | end 306 | end 307 | -------------------------------------------------------------------------------- /HardsploitAPI/Modules/SPI/HardsploitAPI_SPI.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | 9 | require_relative '../../Core/HardsploitAPI' 10 | class HardsploitAPI_SPI 11 | public 12 | 13 | def initialize(speed:,mode:) 14 | #to be sure the singleton was initialize 15 | HardsploitAPI.instance.connect 16 | self.speed=speed 17 | self.mode=mode 18 | @pulse = 0 19 | end 20 | 21 | def pulse 22 | return @pulse 23 | end 24 | 25 | def pulse=(pulse) 26 | if (pulse == 0) or (pulse == 1) then 27 | @pulse = pulse 28 | spi_SetSettings #Send an Empty array to validate the value of pulse 29 | else 30 | raise HardsploitAPI::ERROR::SPIWrongPulse 31 | end 32 | end 33 | 34 | def speed 35 | return @speed 36 | end 37 | 38 | def speed=(speed) 39 | if (speed <=2) or (speed >256) then 40 | raise HardsploitAPI::ERROR::SPIWrongSpeed 41 | else 42 | @speed = speed 43 | end 44 | end 45 | 46 | def mode 47 | return @mode 48 | end 49 | 50 | def mode=(mode) 51 | if ( mode < 0 ) or ( mode > 3 ) then 52 | raise HardsploitAPI::ERROR::SPIWrongMode 53 | else 54 | @mode = mode 55 | end 56 | end 57 | 58 | def spi_SetSettings() 59 | packet = Array.new 60 | packet.push 0 #low byte of lenght of trame refresh automaticly before send by usb 61 | packet.push 0 #high byte of lenght of trame refresh automaticly before send by usb 62 | packet.push HardsploitAPI.lowByte(word:HardsploitAPI::USB_COMMAND::FPGA_COMMAND) 63 | packet.push HardsploitAPI.highByte(word:HardsploitAPI::USB_COMMAND::FPGA_COMMAND) 64 | 65 | packet.push 0x50 #Command RAW COMMUNICATION TO FPGA FIFO 66 | 67 | packet.push (( @pulse & 1 ) << 2 ) || ( @mode & 3 ) #Add mode and the value of pin pulse 68 | packet.push @speed #Add speed 69 | begin 70 | HardsploitAPI.instance.sendPacket packet 71 | rescue 72 | raise HardsploitAPI::ERROR::USB_ERROR 73 | end 74 | end 75 | 76 | # SPI interact 77 | # * +payload+:: Byte array want to send 78 | # * Return SPI data received 79 | def spi_Interact(payload:) 80 | if ( payload.size > 4000 ) then 81 | raise SPIWrongPayloadSize 82 | end 83 | 84 | packet = Array.new 85 | packet.push 0 #low byte of lenght of trame refresh automaticly before send by usb 86 | packet.push 0 #high byte of lenght of trame refresh automaticly before send by usb 87 | packet.push HardsploitAPI.lowByte(word:HardsploitAPI::USB_COMMAND::FPGA_COMMAND) 88 | packet.push HardsploitAPI.highByte(word:HardsploitAPI::USB_COMMAND::FPGA_COMMAND) 89 | 90 | packet.push 0x50 #Command RAW COMMUNICATION TO FPGA FIFO 91 | packet.push (( @pulse & 1 ) << 2 ) || ( @mode & 3 ) #Add mode and the value of pin pulse 92 | packet.push @speed #Add speed 93 | packet.concat payload #Add data 94 | #puts "Payload : #{payload}" 95 | 96 | #remove header (4 bytes 2 for size 2 for type of command) 97 | return HardsploitAPI.instance.sendAndReceiveDATA(packet, 1000).drop(4) 98 | end 99 | 100 | 101 | # Spi generic Import 102 | # * +writeSpiCommand+:: The write command most of the time 0x02 103 | # * +startAddress+:: Start address (included) 104 | # * +pageSize+:: Size of page 105 | # * +memorySize+:: Size max of memory in byte (important, to calculate automatically the number of byte to set address) 106 | # * +saveFile+:: File contain data 107 | # * +writePageLatency+:: Time to wait after each pages written 108 | # * +enableWriteSpiCommand+:: Enable write commad most of the time 0x06 109 | # * +clearSpiCommand+:: Bulk erase command most of the time 0x60 chip eraseTime 110 | # * +clearChipTime+:: Time to erase entire the memory (bulk erase) in case of flash memory, 240 seconds for a 512Mb spansion memory and 13 seconds for a 16Mb Micron memory, see the datasheet 111 | # * +isFLASH+:: True if it is a Flash memory (add clear content) 112 | def spi_Generic_Import (startAddress:,pageSize:,memorySize:,dataFile:,writeSpiCommand:,writePageLatency:,enableWriteSpiCommand:,clearSpiCommand:,clearChipTime:,isFLASH:) 113 | #Start time 114 | startTime = Time.now 115 | 116 | file = File.open(dataFile, 'rb') 117 | sizeFile = file.size 118 | 119 | if (( startAddress < 0 ) or ( startAddress > memorySize - 1 )) then 120 | raise Error::WrongStartAddress 121 | end 122 | 123 | if (( pageSize <= 0 ) and ( pageSize > 2048 )) then 124 | raise TypeError, "pageSize need to be greater than 0 and less than 2048" 125 | end 126 | 127 | numberOfByteAddress = ((( Math.log( memorySize - 1, 2 )).floor + 1 ) / 8.0 ).ceil 128 | if numberOfByteAddress > 4 then 129 | raise TypeError, "Size max must be less than 2^32 about 4Gb" 130 | end 131 | 132 | if numberOfByteAddress <= 0 then 133 | raise TypeError, "There is an issue with calculating of number of byte needed" 134 | end 135 | 136 | #if flash memory we need to erase it before and wait enought 137 | #time (erase cycle time in datasheet) or polling status register 138 | if isFLASH then 139 | spi_Interact(payload: [clearSpiCommand]) 140 | sleep(clearChipTime) 141 | end 142 | 143 | startTime = Time.now 144 | packet_size = pageSize 145 | number_complet_packet = (sizeFile / packet_size).floor 146 | size_last_packet = sizeFile % packet_size 147 | 148 | #SEND the first complete trame 149 | for i in 0..number_complet_packet - 1 do 150 | #Enable write latch 151 | spi_Interact(payload: [enableWriteSpiCommand]) 152 | packet = generate_spi_write_command( 153 | numberOfByteAddress: numberOfByteAddress, 154 | writeSpiCommand: writeSpiCommand, 155 | startAddress: i * packet_size + startAddress, 156 | data: file.read(packet_size).unpack("C*") 157 | ) 158 | 159 | temp = spi_Interact( payload: packet ) 160 | #Remove header, result of read command and numberOfByte Address too 161 | unless packet.size == temp.size then 162 | raise HardsploitAPI::SpiError 163 | end 164 | 165 | HardsploitAPI.instance.consoleProgress( 166 | percent: 100 * ( i + 1 ) / ( number_complet_packet + ( size_last_packet.zero? ? 0 : 1 ) ), 167 | startTime:startTime, 168 | endTime: Time.new 169 | ) 170 | #if too many error when write increase because we need to wait to write a full page 171 | sleep(writePageLatency) 172 | end 173 | 174 | if( size_last_packet > 0 )then 175 | #Enable write latch 176 | spi_Interact( payload: [enableWriteSpiCommand] ) 177 | packet = generate_spi_write_command( 178 | numberOfByteAddress: numberOfByteAddress, 179 | writeSpiCommand: writeSpiCommand, 180 | startAddress: number_complet_packet * packet_size + startAddress, 181 | data: file.read(size_last_packet).unpack("C*") 182 | ) 183 | temp = spi_Interact( payload: packet ) 184 | #Remove header, result of write command and numberOfByte Address too 185 | unless packet.size == temp.size then 186 | raise HardsploitAPI::SpiError 187 | end 188 | 189 | #Send 100% in case of last packet 190 | HardsploitAPI.instance.consoleProgress( 191 | percent: 100, 192 | startTime: startTime, 193 | endTime: Time.now 194 | ) 195 | end 196 | delta = Time.now - startTime 197 | HardsploitAPI.instance.consoleSpeed "Write in #{delta.round(4)} sec" 198 | end 199 | 200 | 201 | # Spi generic dump 202 | # * +readSpiCommand+:: The read command 203 | # * +startAddress+:: Start address (included) 204 | # * +stopAddress+:: Stop address (included) 205 | # * +sizeMax+:: Size max of memory (important to calculate automaticly the number of byte to set address) 206 | def spi_Generic_Dump (readSpiCommand:,startAddress:,stopAddress:,sizeMax:) 207 | if (( startAddress < 0 ) or ( startAddress > sizeMax - 1 )) then 208 | raise TypeError, "Start address can't be negative and not more than size max - 1" 209 | end 210 | 211 | if (( stopAddress < 0 ) or ( stopAddress > ( sizeMax - 1 ))) then 212 | raise TypeError, "Stop address can't be negative and not more than size max-1 because start at 0" 213 | end 214 | 215 | if ( stopAddress < startAddress ) then 216 | raise TypeError, "Stop address need to be greater than start address" 217 | end 218 | 219 | numberOfByteAddress = ((( Math.log( sizeMax - 1, 2 )).floor + 1) / 8.0 ).ceil 220 | if numberOfByteAddress > 4 then 221 | raise TypeError, "Size max must be less than 2^32 about 4Gb" 222 | end 223 | 224 | if numberOfByteAddress <= 0 then 225 | raise TypeError, "There is an issue with calculating of number of byte needed" 226 | end 227 | 228 | #Start time 229 | startTime = Time.now 230 | packet_size = 4000 - numberOfByteAddress - 1 231 | number_complet_packet = (( stopAddress - startAddress + 1 ) / packet_size ).floor 232 | size_last_packet = ( stopAddress - startAddress + 1 ) % packet_size 233 | 234 | #SEND the first complete trame 235 | for i in 0..number_complet_packet - 1 do 236 | packet = generate_spi_read_command( 237 | numberOfByteAddress: numberOfByteAddress, 238 | readSpiCommand: readSpiCommand, 239 | startAddress: i * packet_size + startAddress, 240 | size: packet_size 241 | ) 242 | begin 243 | temp = spi_Interact( payload: packet ) 244 | rescue 245 | raise HardsploitAPI::ERROR::USB_ERROR 246 | end 247 | #Remove header, result of read command and numberOfByte Address too 248 | #puts "receive real size #{temp.size}" 249 | HardsploitAPI.instance.consoleData temp.drop( numberOfByteAddress + 1 ) 250 | HardsploitAPI.instance.consoleProgress( 251 | percent: 100 * ( i + 1 ) / ( number_complet_packet + ( size_last_packet.zero? ? 0 : 1 )), 252 | startTime: startTime, 253 | endTime: Time.new 254 | ) 255 | end 256 | 257 | if( size_last_packet > 0 ) then 258 | packet = generate_spi_read_command( 259 | numberOfByteAddress: numberOfByteAddress, 260 | readSpiCommand: readSpiCommand, 261 | startAddress: number_complet_packet * packet_size + startAddress, 262 | size: size_last_packet 263 | ) 264 | temp = spi_Interact( payload: packet ) 265 | #Remove header, result of read command and numberOfByte Address too 266 | HardsploitAPI.instance.consoleData temp.drop( numberOfByteAddress + 1 ) 267 | begin 268 | HardsploitAPI.instance.consoleProgress( 269 | percent: 100, 270 | startTime: startTime, 271 | endTime: Time.now 272 | ) 273 | rescue 274 | raise HardsploitAPI::ERROR::USB_ERROR 275 | end 276 | end 277 | delta = Time.now - startTime 278 | HardsploitAPI.instance.consoleSpeed "Write in #{delta.round(4)} sec" 279 | end 280 | 281 | protected 282 | def generate_spi_read_command (numberOfByteAddress:,readSpiCommand:,startAddress:,size:) 283 | packet = Array.new 284 | packet.push readSpiCommand 285 | case numberOfByteAddress 286 | when 1 287 | packet.push ((startAddress & 0x000000FF) >> 0) #AddStart0 288 | when 2 289 | packet.push ((startAddress & 0x0000FF00) >> 8 ) #AddStart1 290 | packet.push ((startAddress & 0x000000FF) >> 0) #AddStart0 291 | when 3 292 | packet.push ((startAddress & 0x00FF0000) >> 16 ) #AddStart2 293 | packet.push ((startAddress & 0x0000FF00) >> 8 ) #AddStart1 294 | packet.push ((startAddress & 0x000000FF) >> 0) #AddStart0 295 | when 4 296 | packet.push ((startAddress & 0xFF000000) >> 24 ) #AddStart3 297 | packet.push ((startAddress & 0x00FF0000) >> 16 ) #AddStart2 298 | packet.push ((startAddress & 0x0000FF00) >> 8 ) #AddStart1 299 | packet.push ((startAddress & 0x000000FF) >> 0) #AddStart0 300 | else 301 | raise TypeError, "Issue in generate_spi_read_command function when parse number of byte address" 302 | end 303 | 304 | #put N dummy byte to read size data 305 | packet.push *Array.new(size, 0) 306 | if packet.size > 4000 then 307 | raise TypeError, "Too many byte to send in spi mode not more than 4000 is needed" 308 | end 309 | return packet 310 | end 311 | 312 | def generate_spi_write_command (numberOfByteAddress:,writeSpiCommand:,startAddress:,data:) 313 | packet = Array.new 314 | packet.push writeSpiCommand 315 | case numberOfByteAddress 316 | when 1 317 | packet.push (( startAddress & 0x000000FF) >> 0 ) #AddStart0 318 | when 2 319 | packet.push (( startAddress & 0x0000FF00) >> 8 ) #AddStart1 320 | packet.push (( startAddress & 0x000000FF) >> 0 ) #AddStart0 321 | when 3 322 | packet.push (( startAddress & 0x00FF0000) >> 16 ) #AddStart2 323 | packet.push (( startAddress & 0x0000FF00) >> 8 ) #AddStart1 324 | packet.push (( startAddress & 0x000000FF) >> 0 ) #AddStart0 325 | when 4 326 | packet.push (( startAddress & 0xFF000000) >> 24 ) #AddStart3 327 | packet.push (( startAddress & 0x00FF0000) >> 16 ) #AddStart2 328 | packet.push (( startAddress & 0x0000FF00) >> 8 ) #AddStart1 329 | packet.push (( startAddress & 0x000000FF) >> 0 ) #AddStart0 330 | else 331 | raise TypeError, "Issue in generate_spi_write_command function when parse number of byte address" 332 | end 333 | #Push data to write 334 | packet.push *data 335 | if packet.size > 4000 then 336 | raise TypeError, "Too many byte to send in spi mode not more than 4000 is needed" 337 | end 338 | return packet 339 | end 340 | end 341 | -------------------------------------------------------------------------------- /HardsploitAPI/Modules/SPI_SNIFFER/HardsploitAPI_SPI_SNIFFER.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | 9 | require_relative '../../Core/HardsploitAPI' 10 | class HardsploitAPI_SPI_SNIFFER 11 | public 12 | 13 | def initialize(mode:,sniff:) 14 | #to be sure the singleton was initialize 15 | HardsploitAPI.instance.connect 16 | self.mode=mode 17 | self.sniff=sniff 18 | spi_SetSettings 19 | end 20 | 21 | def mode 22 | return @mode 23 | end 24 | def sniff 25 | return @sniff 26 | end 27 | def mode=(mode) 28 | if ( mode < 0 ) or ( mode > 3 ) then 29 | raise HardsploitAPI::ERROR::SPIWrongMode 30 | else 31 | @mode = mode 32 | end 33 | end 34 | def sniff=(sniff) 35 | case sniff 36 | when HardsploitAPI::SPISniffer::MISO; @sniff = sniff 37 | when HardsploitAPI::SPISniffer::MOSI; @sniff = sniff 38 | when HardsploitAPI::SPISniffer::MISO_MOSI; @sniff = sniff 39 | else 40 | raise HardsploitAPI::ERROR::SPIWrongMode 41 | end 42 | end 43 | def spi_SetSettings 44 | packet = HardsploitAPI.prepare_packet 45 | packet.push 0x10 #Command change mode 46 | packet.push @mode + (@sniff<<6) #Add mode 47 | begin 48 | HardsploitAPI.instance.sendPacket packet 49 | rescue 50 | raise HardsploitAPI::ERROR::USB_ERROR 51 | end 52 | end 53 | 54 | def odds_and_evens(tab, return_odds) 55 | tab.select.with_index{|_, i| return_odds ? i.odd? : i.even?} 56 | end 57 | # spi_receive_available_data 58 | # * Return data received 59 | def spi_receive_available_data 60 | packet = Array.new 61 | packet.push 0 #low byte of lenght of trame refresh automaticly before send by usb 62 | packet.push 0 #high byte of lenght of trame refresh automaticly before send by usb 63 | packet.push HardsploitAPI.lowByte(word:HardsploitAPI::USB_COMMAND::FPGA_COMMAND) 64 | packet.push HardsploitAPI.highByte(word:HardsploitAPI::USB_COMMAND::FPGA_COMMAND) 65 | 66 | packet.push 0x50 #Command RAW COMMUNICATION TO FPGA FIFO 67 | packet.push 0x20 #Command receive available data 68 | 69 | #remove header (4 bytes 2 for size 2 for type of command) 70 | result = HardsploitAPI.instance.sendAndReceiveDATA(packet, 200).drop(4) 71 | 72 | #if half a simple array, if fullduplex first item -> an array of MISO and second array -> an array of MOSI 73 | case @sniff 74 | when HardsploitAPI::SPISniffer::MISO,HardsploitAPI::SPISniffer::MOSI 75 | return result 76 | else 77 | myresult = Array.new 78 | myresult.push odds_and_evens(result,true) 79 | myresult.push odds_and_evens(result,false) 80 | return myresult 81 | end 82 | end 83 | end 84 | -------------------------------------------------------------------------------- /HardsploitAPI/Modules/SWD/HardsploitAPI_SWD.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | require_relative 'HardsploitAPI_SWD_DEBUG' 9 | require_relative 'HardsploitAPI_SWD_STM32' 10 | require_relative '../../Core/HardsploitAPI' 11 | 12 | class HardsploitAPI_SWD 13 | #attr_accessor :debugPort 14 | #attr_accessor :stm32 15 | DCRDR = 0xE000EDF8 # address of Debug Core Register Data Register 16 | DCRSR = 0xE000EDF4 # address of Debug Core Register Selector Register 17 | 18 | def initialize(memory_start_address:, memory_size_address:, cpu_id_address:, device_id_address:) 19 | HardsploitAPI.instance.connect 20 | @memory_start_address = memory_start_address.hex 21 | @memory_size_address = memory_size_address.hex 22 | @cpu_id_address = cpu_id_address.hex 23 | @device_id_address = device_id_address.hex 24 | end 25 | 26 | def readRegs 27 | #halt the target before read register 28 | stop 29 | 30 | @stm32.ahb.csw(1,2) 31 | 32 | p read_mem8(0x1FFFF7E0,2) 33 | #p @stm32.ahb.readWord(@memory_size_address).to_s(16) 34 | for i in 0..36 35 | #Write DCRSR address into TAR register 36 | #Write core register index Rn into DRW register. 37 | write_mem32( DCRSR,[i,0,0,0]) 38 | #@stm32.ahb.writeWord( DCRSR,i) 39 | 40 | #Write DCRDR address into TAR register. 41 | #Read core register value from DRW register. 42 | #value = @stm32.ahb.readWord( DCRDR) 43 | result = read_mem32(DCRDR,1) 44 | value = result[0] + (result[1] << 8) + (result[2] << 16) + (result[3] << 24) 45 | puts "R#{i} #{value.to_s(16)}" 46 | end 47 | end 48 | 49 | def stop 50 | # halt the processor core 51 | write_mem32(0xE000EDF0,[0x03,0x00,0x5F,0xA0]) 52 | end 53 | 54 | def start 55 | # start the processor core 56 | write_mem32(0xE000EDF0,[0x00,0x00,0x5F,0xA0]) 57 | end 58 | def obtainCodes 59 | @debugPort = SWD_DEBUG_PORT.new(self) 60 | @stm32 = SWD_STM32.new(@debugPort) 61 | # Cortex M4 0x410FC241 62 | # Cortex M3 0x411FC231 63 | resetSWD 64 | # code = { 65 | # :DebugPortId => @debugPort.idcode, 66 | # :AccessPortId => @stm32.ahb.idcode, 67 | # :CpuId => @stm32.ahb.readWord(@cpu_id_address), 68 | # :DeviceId => @stm32.ahb.readWord(@device_id_address) 69 | # } 70 | 71 | code = { 72 | :DebugPortId => @debugPort.idcode, 73 | :AccessPortId => @stm32.ahb.idcode, 74 | :CpuId => @stm32.ahb.readWord(@cpu_id_address) 75 | } 76 | return code 77 | end 78 | 79 | def find(numberOfConnectedPinFromA0:) 80 | posibility = HardsploitAPI.allPosibility( 81 | numberOfConnectedPinFromA0: numberOfConnectedPinFromA0, 82 | numberOfSignalsForBus: 2 83 | ) 84 | for item in posibility 85 | currentWiring = 0 86 | for value in item 87 | currentWiring += 2 ** value 88 | end 89 | HardsploitAPI.instance.setWiringLeds(value: currentWiring) 90 | for i in 0..(63 - item.size) 91 | item.push i + numberOfConnectedPinFromA0 92 | end 93 | HardsploitAPI.instance.setCrossWiring(value: item) 94 | begin 95 | code = obtainCodes 96 | return item 97 | rescue Exception => msg 98 | puts msg 99 | end 100 | end 101 | end 102 | 103 | def writeFlash(path) 104 | obtainCodes 105 | dataWrite = IO.binread(path) 106 | dataWrite = dataWrite.unpack("C*") 107 | HardsploitAPI.instance.consoleInfo "Halting Processor" 108 | @stm32.halt 109 | HardsploitAPI.instance.consoleInfo "Erasing Flash" 110 | @stm32.flashUnlock 111 | @stm32.flashErase 112 | HardsploitAPI.instance.consoleInfo "Programming Flash" 113 | @stm32.flashProgram 114 | time = Time.new 115 | @stm32.flashWrite(@memory_start_address, dataWrite) 116 | time = Time.new - time 117 | HardsploitAPI.instance.consoleSpeed "Write #{((dataWrite.size/time)).round(2)}Bytes/s #{(dataWrite.size)}Bytes in #{time.round(4)} s" 118 | @stm32.flashProgramEnd 119 | HardsploitAPI.instance.consoleInfo "Resetting" 120 | @stm32.sysReset 121 | HardsploitAPI.instance.consoleInfo "Start" 122 | @stm32.unhalt 123 | end 124 | 125 | def eraseFlash 126 | obtainCodes 127 | HardsploitAPI.instance.consoleInfo 'Erase' 128 | @stm32.flashErase 129 | end 130 | 131 | def dumpFlash(path) 132 | obtainCodes 133 | @stm32.halt 134 | flash_size = (@stm32.ahb.readWord(@memory_size_address) & 0xFFFF) 135 | HardsploitAPI.instance.consoleInfo "Flash size : #{(flash_size)} KB" 136 | HardsploitAPI.instance.consoleInfo "Dump flash" 137 | time = Time.new 138 | data = @stm32.flashRead(@memory_start_address, (flash_size * 1024)) 139 | time = Time.new - time 140 | HardsploitAPI.instance.consoleSpeed "DUMP #{((data.size/time)).round(2)}Bytes/s #{(data.size)}Bytes in #{time.round(4)} s" 141 | IO.binwrite(path, data.pack('C*')) 142 | HardsploitAPI.instance.consoleInfo "Finish dump" 143 | end 144 | def read_mem8(address,size) 145 | packet = HardsploitAPI.prepare_packet 146 | packet.push 0xAA #Read mode 147 | packet.push HardsploitAPI.lowByte(word: size) 148 | packet.push HardsploitAPI.highByte(word: size) 149 | packet.push ((address & 0xFF) >> 0) 150 | packet.push ((address & 0xFF00) >> 8 ) 151 | packet.push ((address & 0xFF0000) >> 16 ) 152 | packet.push ((address & 0xFF000000) >> 24 ) 153 | 154 | # --[2:0] Size 155 | # --Size of access field: 156 | # --b000 = 8 bits 157 | # --b001 = 16 bits 158 | # --b010 = 32 bits 159 | # --b011-111 are reserved. 160 | # --Reset value: b000 161 | # 162 | # --[5:4] AddrInc 163 | # --0b00 = auto increment off. 164 | # --0b01 = increment single. Single transfer from corresponding byte lane. 165 | # --0b10 = increment packed.[b] 166 | # --0b11 = reserved. No transfer. 167 | # --Size of address increment is defined by the Size field [2:0]. 168 | # --Reset value: 0b00. 169 | packet.push 0b00010000 # single 8 bits auto increment 170 | result = HardsploitAPI.instance.sendAndReceiveDATA(packet, 1000) 171 | raise HardsploitAPI::ERROR::SWD_ERROR,"Error during reading timeout or ACK issue" unless result.class == Array 172 | #raise HardsploitAPI::ERROR::SWD_ERROR,"We need to receive #{size } and we received #{result.size-4}" unless (result.size-4) == size # Receive all data 173 | return result.drop(4) 174 | end 175 | def read_mem32(address,size) 176 | packet = HardsploitAPI.prepare_packet 177 | packet.push 0xAA #Read mode 178 | packet.push HardsploitAPI.lowByte(word: size) 179 | packet.push HardsploitAPI.highByte(word: size) 180 | packet.push ((address & 0xFF) >> 0) 181 | packet.push ((address & 0xFF00) >> 8 ) 182 | packet.push ((address & 0xFF0000) >> 16 ) 183 | packet.push ((address & 0xFF000000) >> 24 ) 184 | 185 | # --[2:0] Size 186 | # --Size of access field: 187 | # --b000 = 8 bits 188 | # --b001 = 16 bits 189 | # --b010 = 32 bits 190 | # --b011-111 are reserved. 191 | # --Reset value: b000 192 | # 193 | # --[5:4] AddrInc 194 | # --0b00 = auto increment off. 195 | # --0b01 = increment single. Single transfer from corresponding byte lane. 196 | # --0b10 = increment packed.[b] 197 | # --0b11 = reserved. No transfer. 198 | # --Size of address increment is defined by the Size field [2:0]. 199 | # --Reset value: 0b00. 200 | packet.push 0b00010010 # single 32 bits auto increment 201 | 202 | result = HardsploitAPI.instance.sendAndReceiveDATA(packet, 1000) 203 | raise HardsploitAPI::ERROR::SWD_ERROR,"Error during reading timeout or ACK issue" unless result.class == Array 204 | raise HardsploitAPI::ERROR::SWD_ERROR,"We need to receive #{size +4 } and we received #{result.size}" unless (result.size-4)/4 == size # Receive all data 205 | return result.drop(4) 206 | end 207 | def write_mem32(address,data) 208 | raise "Too many data (> 2000)" if data.size > 2000 209 | packet = HardsploitAPI.prepare_packet 210 | packet.push 0xBB #Write ap 211 | packet.push ((address & 0xFF) >> 0) 212 | packet.push ((address & 0xFF00) >> 8 ) 213 | packet.push ((address & 0xFF0000) >> 16 ) 214 | packet.push ((address & 0xFF000000) >> 24 ) 215 | 216 | # --[2:0] Size 217 | # --Size of access field: 218 | # --b000 = 8 bits 219 | # --b001 = 16 bits 220 | # --b010 = 32 bits 221 | # --b011-111 are reserved. 222 | # --Reset value: b000 223 | # 224 | # --[5:4] AddrInc 225 | # --0b00 = auto increment off. 226 | # --0b01 = increment single. Single transfer from corresponding byte lane. 227 | # --0b10 = increment packed.[b] 228 | # --0b11 = reserved. No transfer. 229 | # --Size of address increment is defined by the Size field [2:0]. 230 | # --Reset value: 0b00. 231 | packet.push 0b00010010 # single 32 bits auto increment neeed to write in flash 232 | 233 | packet.push *data 234 | result = HardsploitAPI.instance.sendAndReceiveDATA(packet, 1000) 235 | raise HardsploitAPI::ERROR::SWD_ERROR,"Error during writing, timeout" unless result.class == Array 236 | raise HardsploitAPI::ERROR::SWD_ERROR,"Error during writing" unless result.size == 5 237 | return true if result[4] == 1 238 | raise HardsploitAPI::ERROR::SWD_ERROR,"WAIT response" if result[4] == 2 239 | raise HardsploitAPI::ERROR::SWD_ERROR,"FAULT response" if result[4] == 4 240 | raise HardsploitAPI::ERROR::SWD_ERROR,"WRITE ERROR #{result[4]}" 241 | end 242 | 243 | def write_mem8(address,data) 244 | raise "Too many data (> 2000)" if data.size > 2000 245 | packet = HardsploitAPI.prepare_packet 246 | packet.push 0xBB #Write ap 247 | packet.push ((address & 0xFF) >> 0) 248 | packet.push ((address & 0xFF00) >> 8 ) 249 | packet.push ((address & 0xFF0000) >> 16 ) 250 | packet.push ((address & 0xFF000000) >> 24 ) 251 | 252 | # --[2:0] Size 253 | # --Size of access field: 254 | # --b000 = 8 bits 255 | # --b001 = 16 bits 256 | # --b010 = 32 bits 257 | # --b011-111 are reserved. 258 | # --Reset value: b000 259 | # 260 | # --[5:4] AddrInc 261 | # --0b00 = auto increment off. 262 | # --0b01 = increment single. Single transfer from corresponding byte lane. 263 | # --0b10 = increment packed.[b] 264 | # --0b11 = reserved. No transfer. 265 | # --Size of address increment is defined by the Size field [2:0]. 266 | # --Reset value: 0b00. 267 | packet.push 0b00010000 # single 8 bits auto increment neeed to write in flash 268 | packet.push *data 269 | 270 | packet.push 0 #Dummy need to be improve in VHDL 271 | 272 | result = HardsploitAPI.instance.sendAndReceiveDATA(packet, 1000) 273 | raise HardsploitAPI::ERROR::SWD_ERROR,"Error during writing, timeout" unless result.class == Array 274 | raise HardsploitAPI::ERROR::SWD_ERROR,"Error during writing" unless result.size == 5 275 | return true if result[4] == 1 276 | raise HardsploitAPI::ERROR::SWD_ERROR,"WAIT response" if result[4] == 2 277 | raise HardsploitAPI::ERROR::SWD_ERROR,"FAULT response" if result[4] == 4 278 | raise HardsploitAPI::ERROR::SWD_ERROR,"WRITE ERROR #{result[4]}" 279 | end 280 | 281 | def write_mem16Packed(address,data) 282 | raise "Too many data (> 2000)" if data.size > 2000 283 | packet = HardsploitAPI.prepare_packet 284 | packet.push 0xBB #Write ap 285 | packet.push ((address & 0xFF) >> 0) 286 | packet.push ((address & 0xFF00) >> 8 ) 287 | packet.push ((address & 0xFF0000) >> 16 ) 288 | packet.push ((address & 0xFF000000) >> 24 ) 289 | 290 | # --[2:0] Size 291 | # --Size of access field: 292 | # --b000 = 8 bits 293 | # --b001 = 16 bits 294 | # --b010 = 32 bits 295 | # --b011-111 are reserved. 296 | # --Reset value: b000 297 | # 298 | # --[5:4] AddrInc 299 | # --0b00 = auto increment off. 300 | # --0b01 = increment single. Single transfer from corresponding byte lane. 301 | # --0b10 = increment packed.[b] 302 | # --0b11 = reserved. No transfer. 303 | # --Size of address increment is defined by the Size field [2:0]. 304 | # --Reset value: 0b00. 305 | packet.push 0b00100001 # packet 16 bits auto increment neeed to write in flash 306 | 307 | packet.push *data 308 | result = HardsploitAPI.instance.sendAndReceiveDATA(packet, 1000) 309 | raise HardsploitAPI::ERROR::SWD_ERROR,"Error during writing, timeout" unless result.class == Array 310 | raise HardsploitAPI::ERROR::SWD_ERROR,"Error during writing" unless result.size == 5 311 | return true if result[4] == 1 312 | raise HardsploitAPI::ERROR::SWD_ERROR,"WAIT response" if result[4] == 2 313 | raise HardsploitAPI::ERROR::SWD_ERROR,"FAULT response" if result[4] == 4 314 | raise HardsploitAPI::ERROR::SWD_ERROR,"WRITE ERROR #{result[4]}" 315 | end 316 | 317 | def writeSWD(ap, register, data) 318 | packet = HardsploitAPI.prepare_packet 319 | packet.push 0x10 #Write mode 320 | packet.push (calcOpcode(ap, register, false)) #Send Request 321 | packet.push ((data & 0xFF) >> 0) 322 | packet.push ((data & 0xFF00) >> 8 ) 323 | packet.push ((data & 0xFF0000) >> 16 ) 324 | packet.push ((data & 0xFF000000) >> 24 ) 325 | result = HardsploitAPI.instance.sendAndReceiveDATA(packet, 1000) 326 | raise HardsploitAPI::ERROR::SWD_ERROR,"Error during writing, timeout" unless result.class == Array 327 | raise HardsploitAPI::ERROR::SWD_ERROR, "Error during writing" unless result.size == 5 328 | return true if result[4] == 1 329 | raise HardsploitAPI::ERROR::SWD_ERROR,"WAIT response" if result[4] == 2 330 | raise HardsploitAPI::ERROR::SWD_ERROR,"FAULT response" if result[4] == 4 331 | raise HardsploitAPI::ERROR::SWD_ERROR,"WRITE ERROR #{result[4]}" 332 | end 333 | 334 | def readSWD(ap, register) 335 | packet = HardsploitAPI.prepare_packet 336 | packet.push 0x11 #Read mode 337 | packet.push(calcOpcode(ap,register, true)) #Send Request 338 | result = HardsploitAPI.instance.sendAndReceiveDATA(packet, 1000) 339 | raise HardsploitAPI::ERROR::SWD_ERROR,"Error during reading timeout" unless result.class == Array 340 | raise HardsploitAPI::ERROR::SWD_ERROR,"Read error ACK : #{result[4]}" if result.size == 5 # Receive ACK 341 | return (result[7] << 24) + (result[6] << 16) + (result[5] << 8 ) + result[4] if result.size == 8 # Receive read + 4bytes for header 342 | raise HardsploitAPI::ERROR::SWD_ERROR,"Error during reading" 343 | end 344 | 345 | #Return array with 1 byte for ACK 346 | #Return 32bits integer for data read here is Core ID 347 | #Raise if error 348 | def resetSWD 349 | packet = HardsploitAPI.prepare_packet 350 | packet.push 0x00 #Reset mode 351 | result = HardsploitAPI.instance.sendAndReceiveDATA(packet, 1000) 352 | raise HardsploitAPI::ERROR::SWD_ERROR,"Error during reading ICCODE timeout" unless result.class == Array 353 | return (result[7] << 24) + (result[6] << 16) + (result[5] << 8 ) + result[4] if result.size == 8 354 | raise HardsploitAPI::ERROR::SWD_ERROR,"Reset error ACK #{result[4]}" if result.size == 5 #reveice ACK 355 | raise HardsploitAPI::ERROR::SWD_ERROR,"Error during reading ICCODE result != 4" 356 | end 357 | 358 | def calcOpcode (ap, register, read) 359 | opcode = 0x00 360 | (ap ? opcode |= 0x40 : opcode |= 0x00) 361 | (read ? opcode |= 0x20 : opcode |= 0x00) 362 | opcode = opcode | ((register & 0x01) << 4) | ((register & 0x02) << 2) #Addr AP DP bit 2..3 363 | opcode = opcode | (((opcode & 0x78).to_s(2).count('1').odd? ? 1 : 0) << 2) #0x78 mask to take only read ap and register to process parity bit 364 | opcode = opcode | 0x81 #Start and Park Bit 365 | return opcode 366 | end 367 | end 368 | -------------------------------------------------------------------------------- /HardsploitAPI/Modules/SWD/HardsploitAPI_SWD_DEBUG.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | class SWD_DEBUG_PORT 9 | 10 | def initialize(swdAPI) 11 | @swdAPI = swdAPI 12 | sleep(0.5) 13 | @swdAPI.resetSWD 14 | 15 | @curAP = -1 16 | @curBank = -1 17 | abort(1,1,1,1,1) 18 | select(0,0) 19 | 20 | # power shit up 21 | HardsploitAPI.instance.consoleInfo "Power shit up" 22 | 23 | @swdAPI.writeSWD(FALSE, 1, 0x54000000) 24 | if (status() >> 24) != 0xF4 then 25 | raise "error powering up system" 26 | exit(0) 27 | else 28 | HardsploitAPI.instance.consoleInfo "POWERING UP SYTEM OK" 29 | end 30 | end 31 | 32 | def getAPI 33 | return @swdAPI 34 | end 35 | 36 | def idcode 37 | return @swdAPI.readSWD(FALSE, 0) 38 | end 39 | 40 | def abort (orunerr, wdataerr, stickyerr, stickycmp, dap) 41 | value = 0x00000000 42 | (orunerr ? value |= 0x10 : value |= 0x00) 43 | (wdataerr ? value |= 0x08 : value |= 0x00) 44 | (stickyerr ? value |= 0x04 : value |= 0x00) 45 | (stickycmp ? value |= 0x02 : value |= 0x00) 46 | (dap ? value |= 0x01 : value |= 0x00) 47 | @swdAPI.writeSWD(FALSE, 0, value) 48 | end 49 | 50 | def status 51 | val= @swdAPI.readSWD(FALSE,1) 52 | return val 53 | end 54 | 55 | def control (trnCount = 0, trnMode = 0, maskLane = 0, orunDetect = 0) 56 | value = 0x54000000 57 | value = value | ((trnCount & 0xFFF) << 12) 58 | value = value | ((maskLane & 0x00F) << 8) 59 | value = value | ((trnMode & 0x003) << 2) 60 | (orunDetect ? value |= 0x01 : value |= 0x00) 61 | @swdAPI.writeSWD(False, 1, value) 62 | end 63 | 64 | def select (apsel, apbank) 65 | if apsel != @curAP or apbank != @curBank then 66 | @curAP = apsel 67 | @curBank = apbank 68 | value = 0 | ((apsel & 0xFF) << 24) | ((apbank & 0x0F) << 4) 69 | @swdAPI.writeSWD(FALSE, 2, value) 70 | end 71 | end 72 | 73 | def readRB 74 | return @swdAPI.readSWD(FALSE, 3) 75 | end 76 | def readAP ( apsel, address) 77 | adrBank = (address >> 4) & 0xF 78 | adrReg = (address >> 2) & 0x3 79 | select(apsel, adrBank) 80 | return @swdAPI.readSWD(TRUE, adrReg) 81 | end 82 | 83 | def writeAP (apsel, address, data) 84 | adrBank = (address >> 4) & 0xF 85 | adrReg = (address >> 2) & 0x3 86 | select(apsel, adrBank) 87 | @swdAPI.writeSWD(TRUE, adrReg, data) 88 | end 89 | end 90 | -------------------------------------------------------------------------------- /HardsploitAPI/Modules/SWD/HardsploitAPI_SWD_MEM_AP.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | 9 | class SWD_MEM_AP 10 | 11 | def initialize( dp, apsel) 12 | @dp = dp 13 | @apsel = apsel 14 | csw(1,2) # 32-bit auto-incrementing addressing 15 | end 16 | 17 | def csw ( addrInc, size) 18 | @dp.readAP(@apsel, 0x00) 19 | val = @dp.readRB() & 0xFFFFFF00 20 | @dp.writeAP(@apsel, 0x00, val + (addrInc << 4) + size) 21 | end 22 | 23 | def idcode 24 | @dp.readAP(@apsel, 0xFC) 25 | id = @dp.readRB() 26 | @dp.select(0,0) 27 | return id 28 | end 29 | 30 | def readWord (addr) 31 | @dp.writeAP(@apsel, 0x04, addr) 32 | @dp.readAP(@apsel, 0x0C) 33 | return @dp.readRB() 34 | end 35 | 36 | def writeWord (addr, data) 37 | @dp.writeAP(@apsel, 0x04, addr) 38 | @dp.writeAP(@apsel, 0x0C, data) 39 | return @dp.readRB() 40 | end 41 | 42 | def readBlock ( address, size)#1K boundaries and return 4K of data word alignement 43 | if size < 1 then 44 | raise "readBlock error : count must be >= 1" 45 | end 46 | if size > 1024 then 47 | raise "readBlock error : size must be <= 1024 " 48 | end 49 | return @dp.getAPI.read_mem32(address,size) 50 | end 51 | 52 | def writeBlock (address,data) #1K boundaries 53 | if data.length < 1 then 54 | raise "readBlock error : count must be >= 1" 55 | end 56 | if data.length > 1024 then 57 | raise "readBlock error : size must be <= 1024 " 58 | end 59 | @dp.getAPI.write_mem16Packed(address,data) 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /HardsploitAPI/Modules/SWD/HardsploitAPI_SWD_STM32.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | 9 | require_relative 'HardsploitAPI_SWD_MEM_AP' 10 | 11 | class SWD_STM32 12 | attr_accessor :ahb 13 | 14 | def initialize(debugPort) 15 | @ahb = SWD_MEM_AP.new(debugPort, 0) 16 | @debugPort = debugPort 17 | end 18 | 19 | def halt 20 | # halt the processor core 21 | @ahb.writeWord(0xE000EDF0, 0xA05F0003) 22 | end 23 | def unhalt 24 | # unhalt the processor core 25 | @ahb.writeWord(0xE000EDF0, 0xA05F0000) 26 | end 27 | def sysReset 28 | # restart the processor and peripherals 29 | @ahb.writeWord(0xE000ED0C, 0x05FA0004) 30 | end 31 | 32 | def flashRead(address,size) 33 | data = Array.new 34 | # Read a word of 32bits (4 Bytes in same time) 35 | size = size / 4 36 | #Chunk to 1k block for SWD 37 | # ARM_debug_interface_v5 Automatic address increment is only guaranteed to operate on the bottom 10-bits of the 38 | # address held in the TAR. Auto address incrementing of bit [10] and beyond is 39 | # IMPLEMENTATION DEFINED. This means that auto address incrementing at a 1KB boundary 40 | # is IMPLEMENTATION DEFINED 41 | 42 | #But for hardsploit max 8192 so chuck to 1k due to swd limitation 43 | 44 | packet_size = 1024 45 | number_complet_packet = (size / packet_size).floor 46 | size_last_packet = size % packet_size 47 | startTime = Time.now 48 | #number_complet_packet 49 | for i in 0..number_complet_packet - 1 do 50 | data.push(*self.ahb.readBlock(i * 4 * packet_size + address, packet_size)) 51 | #puts "Read #{packet_size} KB : #{i}" 52 | HardsploitAPI.instance.consoleProgress( 53 | percent: 100 * (i + 1) / (number_complet_packet + (size_last_packet.zero? ? 0 : 1)), 54 | startTime: startTime, 55 | endTime: Time.new 56 | ) 57 | end 58 | #Last partial packet 59 | if size_last_packet > 0 then 60 | data.push(*self.ahb.readBlock(number_complet_packet*4*packet_size+address,size_last_packet)) 61 | #puts "Read last packet : #{size_last_packet} packet of 4 bytes" 62 | HardsploitAPI.instance.consoleProgress( 63 | percent: 100, 64 | startTime: startTime, 65 | endTime: Time.new 66 | ) 67 | end 68 | return data 69 | end 70 | 71 | def flashWrite(address,data) 72 | #Chunk to 1k block for SWD 73 | packet_size = 1024 #1024 74 | number_complet_packet = (data.size/packet_size).floor 75 | size_last_packet = data.size % packet_size 76 | startTime = Time.now 77 | #ahb.csw(2, 1) # 16-bit packed incrementing addressing 78 | #number_complet_packet 79 | for i in 0..number_complet_packet-1 do 80 | self.ahb.writeBlock(address+i*packet_size,data[i*packet_size..i*packet_size-1+packet_size]) 81 | #puts "Write #{packet_size} KB : #{i}" 82 | HardsploitAPI.instance.consoleProgress( 83 | percent: 100 * (i + 1) / (number_complet_packet + (size_last_packet.zero? ? 0 : 1)), 84 | startTime: startTime, 85 | endTime:Time.new 86 | ) 87 | end 88 | #Last partial packet 89 | if size_last_packet > 0 then 90 | self.ahb.writeBlock(address+number_complet_packet*packet_size,data[number_complet_packet*packet_size..number_complet_packet*packet_size+size_last_packet]) 91 | #puts "Write last packet : #{size_last_packet} packet" 92 | HardsploitAPI.instance.consoleProgress(percent:100,startTime:startTime,endTime:Time.new) 93 | end 94 | ahb.csw(1, 2) # set to default 32-bit incrementing addressing 95 | end 96 | 97 | def flashUnlock 98 | # unlock main flash 99 | @ahb.writeWord(0x40022004, 0x45670123) 100 | @ahb.writeWord(0x40022004, 0xCDEF89AB) 101 | end 102 | def flashErase 103 | HardsploitAPI.instance.consoleInfo "Flash unlock" 104 | flashUnlock 105 | # start the mass erase 106 | @ahb.writeWord(0x40022010, 0x00000204) 107 | @ahb.writeWord(0x40022010, 0x00000244) 108 | # check the BSY flag 109 | while (@ahb.readWord(0x4002200C) & 1) == 1 110 | HardsploitAPI.instance.consoleInfo "waiting for erase completion..." 111 | end 112 | @ahb.writeWord(0x40022010, 0x00000200) 113 | HardsploitAPI.instance.consoleInfo "Finish unlock flash" 114 | end 115 | def flashProgram 116 | @ahb.writeWord(0x40022010, 0x00000201) 117 | end 118 | def flashProgramEnd 119 | @ahb.writeWord(0x40022010, 0x00000200) 120 | end 121 | end 122 | -------------------------------------------------------------------------------- /HardsploitAPI/Modules/TEST/HardsploitAPI_TEST_INTERACT.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | 9 | class HardsploitAPI_TEST 10 | public 11 | # Write value of 64 IO for testing purpose 12 | # * +value+:: 64bits to write on all ports 13 | # return [Integer] Return the value sent (lookback) (64bits) 14 | 15 | def test_InteractWrite(*args) 16 | parametters = HardsploitAPI.checkParametters(["value"],args) 17 | val = parametters[:value] 18 | 19 | packet = Array.new 20 | packet.push 0 #low byte of lenght of trame refresh automaticly before send by usb 21 | packet.push 0 #high byte of lenght of trame refresh automaticly before send by usb 22 | packet.push HardsploitAPI.lowByte(USB_COMMAND::FPGA_COMMAND) 23 | packet.push HardsploitAPI.highByte(USB_COMMAND::FPGA_COMMAND) 24 | 25 | #Command RAW COMMUNICATION TO FPGA FIFO 26 | packet.push 0x50 27 | 28 | #Write mode 29 | packet.push 0xEF 30 | 31 | packet.push ((val & 0x00000000000000FF) >> 0) 32 | packet.push ((val & 0x000000000000FF00) >> 8 ) 33 | packet.push ((val & 0x0000000000FF0000) >> 16 ) 34 | packet.push ((val & 0x00000000FF000000) >> 24 ) 35 | packet.push ((val & 0x000000FF00000000) >> 32 ) 36 | packet.push ((val & 0x0000FF0000000000) >> 40 ) 37 | packet.push ((val & 0x00FF000000000000) >> 48 ) 38 | packet.push ((val & 0xFF00000000000000) >> 56 ) 39 | 40 | sendPacket packet 41 | 42 | tmp= receiveDATA(1000) 43 | case tmp 44 | when HardsploitAPI::USB_STATE::BUSY 45 | return USB_STATE::BUSY 46 | when HardsploitAPI::USB_STATE::TIMEOUT_RECEIVE 47 | return USB_STATE::TIMEOUT_RECEIVE 48 | else 49 | #remove header (4 bytes 2 for size 2 for type of command) 50 | tmp = tmp.bytes.drop(4) 51 | 52 | return 0 | (tmp[0] << 0) | (tmp[1] << 8) | (tmp[2] << 16) | (tmp[3] << 24) | (tmp[4] << 32) | (tmp[5] << 40) | (tmp[6] << 48) | (tmp[7] << 56) 53 | end 54 | end 55 | 56 | # Read value of 64 IO for testing purpose 57 | # 58 | # return [Integer] 64bits 59 | 60 | def test_InteractRead 61 | packet = Array.new 62 | packet.push 0 #low byte of lenght of trame refresh automaticly before send by usb 63 | packet.push 0 #high byte of lenght of trame refresh automaticly before send by usb 64 | packet.push HardsploitAPI.lowByte(USB_COMMAND::FPGA_COMMAND) 65 | packet.push HardsploitAPI.highByte(USB_COMMAND::FPGA_COMMAND) 66 | 67 | ##packet.push 0x50 #Command RAW COMMUNICATION TO FPGA FIFO 68 | packet.push 0x50 69 | 70 | #Read mode 71 | packet.push 0xCD 72 | 73 | packet.push 0xA1 74 | packet.push 0xA2 75 | packet.push 0xA3 76 | packet.push 0xA4 77 | packet.push 0xA5 78 | packet.push 0xA6 79 | packet.push 0xA7 80 | packet.push 0xA8 81 | 82 | 83 | sendPacket packet 84 | 85 | tmp= receiveDATA(1000) 86 | case tmp 87 | when HardsploitAPI::USB_STATE::BUSY 88 | return USB_STATE::BUSY 89 | when HardsploitAPI::USB_STATE::TIMEOUT_RECEIVE 90 | puts "TIMEOUT" 91 | # raise "test_InteractRead Timeout" 92 | else 93 | #remove header (4 bytes 2 for size 2 for type of command) 94 | tmp = tmp.bytes.drop(4) 95 | return 0 | (tmp[0] << 0) | (tmp[1] << 8) | (tmp[2] << 16) | (tmp[3] << 24) | (tmp[4] << 32) | (tmp[5] << 40) | (tmp[6] << 48) | (tmp[7] << 56) 96 | end 97 | end 98 | end 99 | -------------------------------------------------------------------------------- /HardsploitAPI/Modules/UART/HardsploitAPI_UART.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | #=================================================== 3 | # Hardsploit API - By Opale Security 4 | # www.opale-security.com || www.hardsploit.io 5 | # License: GNU General Public License v3 6 | # License URI: http://www.gnu.org/licenses/gpl.txt 7 | #=================================================== 8 | 9 | require_relative '../../Core/HardsploitAPI' 10 | class HardsploitAPI_UART 11 | public 12 | def initialize(baud_rate:,word_width:,use_parity_bit:,parity_type:,nb_stop_bits:,idle_line_level:) 13 | #to be sure the singleton was initialize 14 | HardsploitAPI.instance 15 | self.baud_rate = baud_rate 16 | self.word_width = word_width 17 | self.use_parity_bit = use_parity_bit 18 | self.parity_type = parity_type 19 | self.nb_stop_bits = nb_stop_bits 20 | self.idle_line_level = idle_line_level 21 | setSettings 22 | 23 | @payload_TX = Array.new 24 | end 25 | 26 | def baud_rate 27 | return 150000000 / @baud_rate 28 | end 29 | 30 | def baud_rate=(baud_rate) 31 | if (baud_rate >= 2400) and (baud_rate <= 1036800) then 32 | @baud_rate = 150000000 / baud_rate 33 | else 34 | raise HardsploitAPI::ERROR::UART_WrongSettings 35 | end 36 | end 37 | 38 | def word_width 39 | return @word_width 40 | end 41 | 42 | def word_width=(word_width) 43 | if (word_width >= 5) and (word_width <= 8) then 44 | @word_width = word_width 45 | else 46 | raise HardsploitAPI::ERROR::UART_WrongSettings 47 | end 48 | end 49 | 50 | def use_parity_bit 51 | return @use_parity_bit 52 | end 53 | 54 | def use_parity_bit=(use_parity_bit) 55 | if (use_parity_bit >= 0) and (use_parity_bit <= 1) then 56 | @use_parity_bit = use_parity_bit 57 | else 58 | raise HardsploitAPI::ERROR::UART_WrongSettings 59 | end 60 | end 61 | 62 | def parity_type 63 | return @parity_type 64 | end 65 | 66 | def parity_type=(parity_type) 67 | if (parity_type >= 0) and (parity_type <= 1) then 68 | @parity_type = parity_type 69 | else 70 | raise HardsploitAPI::ERROR::UART_WrongSettings 71 | end 72 | end 73 | 74 | def nb_stop_bits 75 | return @nb_stop_bits 76 | end 77 | 78 | def nb_stop_bits=(nb_stop_bits) 79 | if (nb_stop_bits >= 1) and (nb_stop_bits <= 2) then 80 | @nb_stop_bits = nb_stop_bits 81 | else 82 | raise HardsploitAPI::ERROR::UART_WrongSettings 83 | end 84 | end 85 | 86 | def idle_line_level 87 | return @idle_line_level 88 | end 89 | 90 | def idle_line_level=(idle_line_level) 91 | if (idle_line_level >= 0) and (idle_line_level <= 1) then 92 | @idle_line_level = idle_line_level 93 | else 94 | raise HardsploitAPI::ERROR::UART_WrongSettings 95 | end 96 | end 97 | 98 | # write 99 | # * +payload+:: Byte array want to send 100 | # * Return nothing 101 | def write(payload:) 102 | if ( (@payload_TX.size + payload.size) > 4000) then 103 | raise HardsploitAPI::ERROR::UART_WrongTxPayloadSize 104 | end 105 | @payload_TX.concat payload #Add data 106 | end 107 | 108 | # sendAndReceived ( send and receive) 109 | # First write data if needed and refresh (data are sent and reveived data if needed) and you obtain available data 110 | # * Return nothing 111 | def sendAndReceived 112 | packet = HardsploitAPI.prepare_packet 113 | packet.push 0x20 #Send command 114 | packet.concat @payload_TX 115 | 116 | begin 117 | tmp = HardsploitAPI.instance.sendAndReceiveDATA(packet,1000) 118 | rescue 119 | raise HardsploitAPI::ERROR::USB_ERROR 120 | end 121 | 122 | @payload_TX.clear 123 | #remove header (4 bytes 2 for size 2 for type of command 1 dummy byte) 124 | return tmp.drop(5) 125 | end 126 | 127 | # enableMeasureBaudRate 128 | # 129 | # * 130 | def enableMeasureBaudRate 131 | packet = HardsploitAPI.prepare_packet 132 | packet.push 0x41 # command 133 | begin 134 | tmp = HardsploitAPI.instance.sendAndReceiveDATA(packet,1000) 135 | rescue 136 | raise HardsploitAPI::ERROR::USB_ERROR 137 | end 138 | end 139 | 140 | # disableMeasureBaudRate 141 | # 142 | # * 143 | def disableMeasureBaudRate 144 | packet = HardsploitAPI.prepare_packet 145 | packet.push 0x40 # command 146 | begin 147 | tmp = HardsploitAPI.instance.sendAndReceiveDATA(packet,1000) 148 | rescue 149 | raise HardsploitAPI::ERROR::USB_ERROR 150 | end 151 | end 152 | 153 | # measureBaudRate 154 | # 155 | # * Return 32 bits period 156 | def measureBaudRate 157 | packet = HardsploitAPI.prepare_packet 158 | packet.push 0x30 # command 159 | 160 | begin 161 | tmp = HardsploitAPI.instance.sendAndReceiveDATA(packet,1000) 162 | rescue 163 | raise HardsploitAPI::ERROR::USB_ERROR 164 | end 165 | #remove header (4 bytes 2 for size 2 for type of command) 166 | tmp = tmp.drop(4) 167 | period = tmp[0] + (tmp[1] << 8 ) + (tmp[2] << 16 ) + (tmp[3] << 24 ) 168 | period = period * 33.33*(10**-9) #s 169 | if period > 0 then 170 | return (1 / period).to_i 171 | else 172 | return 0 173 | end 174 | end 175 | 176 | # settings 177 | # * Return nothing 178 | def setSettings 179 | packet = HardsploitAPI.prepare_packet 180 | packet.push 0x00 #Settings command 181 | packet.push ((@parity_type & 0b1) << 7) || ((@use_parity_bit & 0b1) << 6) || ((@nb_stop_bits & 0b11) << 4) || (@word_width & 0b1111) 182 | packet.push @idle_line_level & 1 183 | packet.push HardsploitAPI.lowByte(word: @baud_rate) 184 | packet.push HardsploitAPI.highByte(word: @baud_rate) 185 | 186 | begin 187 | HardsploitAPI.instance.sendPacket packet 188 | sleep(1) 189 | # tmp= HardsploitAPI.instance.receiveDATA(1000) 190 | #remove header (4 bytes 2 for size 2 for type of command) 191 | # return tmp.bytes.drop(4) 192 | rescue 193 | raise HardsploitAPI::ERROR::USB_ERROR 194 | end 195 | end 196 | end 197 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hardsploit 2 | 3 | The essential security auditing tool for Internet of Things devices you'll need in your toolbox 4 | 5 | ### [GO TO HARDSPLOIT](http://www.hardsploit.io) 6 | 7 | TO LEARN ABOUT IT 8 | 9 | ### [GO TO SHOP](https://www.shop-hardsploit.com) 10 | TO BUY 11 | 12 | ### [GO TO WIKI](https://github.com/OPALESECURITY/hardsploit-api/wiki) 13 | 14 | TO UNDERSTAND HOW USE IT 15 | 16 | ### [GO TO FORUM](http://forum.hardsploit.io) 17 | 18 | FOR SUPPORT / HELP 19 | 20 | ### [GO TO BUG TRACKER](https://github.com/OPALESECURITY/hardsploit-api/issues) 21 | 22 | FOR BUGS OR IMPROVEMENTS 23 | -------------------------------------------------------------------------------- /TRADEMARK: -------------------------------------------------------------------------------- 1 | "Hardsploit" is a trademark of OPALE SECURITY. Permission to use the trademark 2 | with attribution to OPALE SECURITY is denied to all licensees of Hardsploit for 3 | the purpose of naming or describing copies or derived works. --------------------------------------------------------------------------------