├── 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.
--------------------------------------------------------------------------------