hardsploit_gui 2.3 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +22 -22
  3. data/Rakefile +1 -1
  4. data/bin/hardsploit_gui +3 -3
  5. data/lib/Firmwares/FPGA/I2C/I2C_INTERACT/HARDSPLOIT_FIRMWARE_FPGA_I2C_INTERACT.rpd +0 -0
  6. data/lib/Firmwares/FPGA/PARALLEL/NO_MUX_PARALLEL_MEMORY/HARDSPLOIT_FIRMWARE_FPGA_NO_MUX_PARALLEL_MEMORY.rpd +0 -0
  7. data/lib/Firmwares/FPGA/SPI/SPI_INTERACT/HARDSPLOIT_FIRMWARE_FPGA_SPI_INTERACT.rpd +0 -0
  8. data/lib/Firmwares/FPGA/SPI/SPI_SNIFFER/HARDSPLOIT_FIRMWARE_FPGA_SPI_SNIFFER.rpd +0 -0
  9. data/lib/Firmwares/FPGA/SWD/SWD_INTERACT/HARDSPLOIT_FIRMWARE_FPGA_SWD_INTERACT.rpd +0 -0
  10. data/lib/Firmwares/FPGA/UART/UART_INTERACT/HARDSPLOIT_FIRMWARE_FPGA_UART_INTERACT.rpd +0 -0
  11. data/lib/Firmwares/FPGA/VersionFPGA.rb +5 -5
  12. data/lib/Firmwares/UC/VersionUC.rb +12 -12
  13. data/lib/HardsploitAPI/Core/HardsploitAPI.rb +210 -210
  14. data/lib/HardsploitAPI/Core/HardsploitAPI_CONSTANT.rb +150 -150
  15. data/lib/HardsploitAPI/Core/HardsploitAPI_ERROR.rb +109 -109
  16. data/lib/HardsploitAPI/Core/HardsploitAPI_FIRMWARE.rb +305 -305
  17. data/lib/HardsploitAPI/Core/HardsploitAPI_PROGRESS.rb +28 -28
  18. data/lib/HardsploitAPI/Core/HardsploitAPI_USB_COMMUNICATION.rb +166 -166
  19. data/lib/HardsploitAPI/Modules/I2C/HardsploitAPI_I2C.rb +356 -356
  20. data/lib/HardsploitAPI/Modules/NO_MUX_PARALLEL_MEMORY/HardsploitAPI_NO_MUX_PARALLEL_MEMORY.rb +206 -206
  21. data/lib/HardsploitAPI/Modules/NRF24L01/HardsploitAPI_NRF24L01.rb +306 -306
  22. data/lib/HardsploitAPI/Modules/SPI/HardsploitAPI_SPI.rb +340 -340
  23. data/lib/HardsploitAPI/Modules/SPI_SNIFFER/HardsploitAPI_SPI_SNIFFER.rb +83 -83
  24. data/lib/HardsploitAPI/Modules/SWD/HardsploitAPI_SWD.rb +367 -367
  25. data/lib/HardsploitAPI/Modules/SWD/HardsploitAPI_SWD_DEBUG.rb +89 -89
  26. data/lib/HardsploitAPI/Modules/SWD/HardsploitAPI_SWD_MEM_AP.rb +61 -61
  27. data/lib/HardsploitAPI/Modules/SWD/HardsploitAPI_SWD_STM32.rb +121 -121
  28. data/lib/HardsploitAPI/Modules/TEST/HardsploitAPI_TEST_INTERACT.rb +98 -98
  29. data/lib/HardsploitAPI/Modules/UART/HardsploitAPI_UART.rb +196 -196
  30. data/lib/Hardsploit_gui.rb +96 -96
  31. data/lib/LICENSE.txt +674 -674
  32. data/lib/README.md +22 -22
  33. data/lib/TRADEMARK +2 -2
  34. data/lib/class/Chip_editor.rb +304 -304
  35. data/lib/class/Chip_management.rb +496 -496
  36. data/lib/class/Command_editor.rb +216 -216
  37. data/lib/class/Command_table.rb +233 -233
  38. data/lib/class/Console.rb +26 -26
  39. data/lib/class/ErrorMsg.rb +312 -312
  40. data/lib/class/Export.rb +140 -140
  41. data/lib/class/Export_manager.rb +124 -124
  42. data/lib/class/Firmware.rb +70 -70
  43. data/lib/class/Generic_commands.rb +260 -260
  44. data/lib/class/{i2c → I2C}/I2c_command.rb +51 -51
  45. data/lib/class/{i2c → I2C}/I2c_export.rb +95 -95
  46. data/lib/class/{i2c → I2C}/I2c_import.rb +117 -117
  47. data/lib/class/{i2c → I2C}/I2c_scanner.rb +114 -114
  48. data/lib/class/{i2c → I2C}/I2c_settings.rb +148 -148
  49. data/lib/class/Import.rb +193 -193
  50. data/lib/class/{parallel → PARALLEL}/Parallel_export.rb +118 -118
  51. data/lib/class/{parallel → PARALLEL}/Parallel_import.rb +113 -113
  52. data/lib/class/{parallel → PARALLEL}/Parallel_settings.rb +81 -81
  53. data/lib/class/Progress_bar.rb +32 -32
  54. data/lib/class/{spi → SPI}/Spi_export.rb +108 -108
  55. data/lib/class/{spi → SPI}/Spi_import.rb +159 -159
  56. data/lib/class/{spi → SPI}/Spi_settings.rb +108 -108
  57. data/lib/class/{spi → SPI}/Spi_sniffer.rb +101 -101
  58. data/lib/class/Signal_mapper.rb +120 -120
  59. data/lib/class/Wire_helper.rb +230 -230
  60. data/lib/class/swd/Swd.rb +125 -125
  61. data/lib/class/swd/Swd_scanner.rb +121 -121
  62. data/lib/class/swd/Swd_settings.rb +76 -76
  63. data/lib/class/uart/Uart_baudrate.rb +62 -62
  64. data/lib/class/uart/Uart_console.rb +115 -115
  65. data/lib/class/uart/Uart_settings.rb +102 -102
  66. data/lib/db/associations.rb +138 -138
  67. data/lib/db/database.rb +4 -4
  68. data/lib/db/development.sqlite3 +0 -0
  69. data/lib/db/migrate/004_create_manufacturers.rb +13 -13
  70. data/lib/db/migrate/005_create_packages.rb +13 -13
  71. data/lib/db/migrate/006_create_chip_types.rb +11 -11
  72. data/lib/db/migrate/007_create_buses.rb +11 -11
  73. data/lib/db/migrate/008_create_signals.rb +14 -14
  74. data/lib/db/migrate/009_create_chips.rb +25 -25
  75. data/lib/db/migrate/010_create_commands.rb +21 -21
  76. data/lib/db/migrate/011_create_bytes.rb +19 -19
  77. data/lib/db/migrate/012_create_i2c_settings.rb +21 -21
  78. data/lib/db/migrate/013_create_spi_settings.rb +26 -26
  79. data/lib/db/migrate/014_create_parallel_settings.rb +21 -21
  80. data/lib/db/migrate/015_create_pins.rb +19 -19
  81. data/lib/db/migrate/016_create_uses.rb +17 -17
  82. data/lib/db/migrate/017_create_swd_settings.rb +19 -19
  83. data/lib/db/migrate/018_create_uart_settings.rb +22 -22
  84. data/lib/db/schema.rb +157 -157
  85. data/lib/db/seeds.rb +161 -161
  86. data/lib/gui/gui_chip_editor.rb +349 -349
  87. data/lib/gui/gui_chip_management.rb +377 -377
  88. data/lib/gui/gui_command_editor.rb +219 -219
  89. data/lib/gui/gui_export.rb +132 -132
  90. data/lib/gui/gui_export_manager.rb +93 -93
  91. data/lib/gui/gui_generic_commands.rb +202 -202
  92. data/lib/gui/gui_generic_export.rb +164 -164
  93. data/lib/gui/gui_generic_import.rb +142 -142
  94. data/lib/gui/gui_i2c_command.rb +116 -116
  95. data/lib/gui/gui_i2c_settings.rb +230 -230
  96. data/lib/gui/gui_import.rb +131 -131
  97. data/lib/gui/gui_parallel_settings.rb +195 -195
  98. data/lib/gui/gui_progress_bar.rb +85 -85
  99. data/lib/gui/gui_signal_mapper.rb +121 -121
  100. data/lib/gui/gui_signal_scanner.rb +146 -146
  101. data/lib/gui/gui_spi_import.rb +126 -126
  102. data/lib/gui/gui_spi_settings.rb +313 -313
  103. data/lib/gui/gui_spi_sniffer.rb +112 -112
  104. data/lib/gui/gui_swd_settings.rb +166 -166
  105. data/lib/gui/gui_uart_baudrate.rb +114 -114
  106. data/lib/gui/gui_uart_console.rb +164 -164
  107. data/lib/gui/gui_uart_settings.rb +243 -243
  108. data/lib/gui/gui_wire_helper.rb +99 -99
  109. data/lib/gui_designer/gui_chip_editor.ui +549 -549
  110. data/lib/gui_designer/gui_chip_management.ui +886 -886
  111. data/lib/gui_designer/gui_command_editor.ui +350 -350
  112. data/lib/gui_designer/gui_export.ui +171 -171
  113. data/lib/gui_designer/gui_export_manager.ui +115 -115
  114. data/lib/gui_designer/gui_generic_commands.ui +342 -342
  115. data/lib/gui_designer/gui_generic_export.ui +202 -202
  116. data/lib/gui_designer/gui_generic_import.ui +165 -165
  117. data/lib/gui_designer/gui_i2c_command.ui +148 -148
  118. data/lib/gui_designer/gui_i2c_settings.ui +292 -292
  119. data/lib/gui_designer/gui_import.ui +168 -168
  120. data/lib/gui_designer/gui_parallel_settings.ui +247 -247
  121. data/lib/gui_designer/gui_progress_bar.ui +86 -86
  122. data/lib/gui_designer/gui_signal_mapper.ui +179 -179
  123. data/lib/gui_designer/gui_signal_scanner.ui +261 -261
  124. data/lib/gui_designer/gui_spi_settings.ui +446 -446
  125. data/lib/gui_designer/gui_spi_sniffer.ui +156 -156
  126. data/lib/gui_designer/gui_swd_settings.ui +189 -189
  127. data/lib/gui_designer/gui_uart_baudrate.ui +161 -161
  128. data/lib/gui_designer/gui_uart_console.ui +284 -284
  129. data/lib/gui_designer/gui_uart_settings.ui +280 -280
  130. data/lib/gui_designer/gui_wire_helper.ui +117 -117
  131. data/lib/images/search.png +0 -0
  132. data/lib/logs/error.log +0 -63
  133. data/lib/models/bus.rb +19 -19
  134. data/lib/models/byte.rb +29 -29
  135. data/lib/models/chip.rb +41 -41
  136. data/lib/models/chip_type.rb +14 -14
  137. data/lib/models/command.rb +20 -20
  138. data/lib/models/i2c_setting.rb +41 -41
  139. data/lib/models/manufacturer.rb +14 -14
  140. data/lib/models/package.rb +26 -26
  141. data/lib/models/parallel_setting.rb +37 -37
  142. data/lib/models/pin.rb +14 -14
  143. data/lib/models/signall.rb +20 -20
  144. data/lib/models/spi_setting.rb +67 -67
  145. data/lib/models/swd_setting.rb +25 -25
  146. data/lib/models/uart_setting.rb +52 -52
  147. data/lib/models/use.rb +6 -6
  148. data/lib/startHardsploit.rb +10 -10
  149. metadata +14 -14
@@ -1,340 +1,340 @@
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
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