MODBUS.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. package de.tudarmstadt.informatik.hostage.protocol;
  2. import java.util.ArrayList;
  3. import java.util.HashMap;
  4. import java.util.InputMismatchException;
  5. import java.util.List;
  6. import de.tudarmstadt.informatik.hostage.wrapper.Packet;
  7. /**
  8. * Created by Shreyas Srinivasa on 25.05.15.
  9. */
  10. public class MODBUS implements Protocol {
  11. public int getPort() {
  12. return 502;
  13. }
  14. public boolean isClosed() {
  15. return false;
  16. }
  17. public boolean isSecure() {
  18. return false;
  19. }
  20. private StringBuffer command = new StringBuffer();
  21. @Override
  22. public String toString() {
  23. return "MODBUS";
  24. }
  25. public TALK_FIRST whoTalksFirst() {
  26. return TALK_FIRST.CLIENT;
  27. }
  28. //Declarations
  29. HashMap<Integer,Integer> coil = new HashMap<Integer,Integer>();
  30. HashMap<Integer,Integer> register = new HashMap<Integer,Integer>();
  31. HashMap<Integer,Integer> discreteInput = new HashMap<Integer,Integer>();
  32. //Function Request Codes
  33. public static final int READ_COILS = 1;
  34. public static final int READ_INPUT_DISCRETES = 2;
  35. public static final int READ_HOLDING_REGISTERS=3;
  36. public static final int READ_INPUT_REGISTERS = 4;
  37. public static final int WRITE_COIL = 5;
  38. public static final int WRITE_SINGLE_REGISTER = 6;
  39. public static final int MODBUS_SERVICE = 17; //for detection using metasploit module
  40. public static final int MODBUS_DISCOVER=1;
  41. //public static final int WRITE_MULTIPLE_COILS = 15; Not sure of these commands
  42. //public static final int WRITE_MULTIPLE_REGISTERS = 16; Not sure of these commands
  43. //Packet Constants, declaring it for now, depends on usage. Static assignment is not a good idea
  44. int FUNCTION_CODE;
  45. int UNIT_NUMBER;
  46. int DATA_ADDRESS;
  47. int SIZE;
  48. public int sid=1; // Denotes the Unit Number or Slave_ID of the device
  49. public static final int COIL_MAX_DATA_ADDRESS = 128; // Max coil data address
  50. public static final int COIL_START_ADDRESS = 1; // Start address of coil
  51. public static final int DISCRETE_MAX_DATA_ADDRESS = 10032; // Max DISCRETE_INPUT data address
  52. public static final int DISCRETE_START_ADDRESS = 10001; // Start address of DISCRETE_INPUT
  53. public static final int ANALOG_INPUT_MAX_DATA_ADDRESS = 30009; //Max ANALOG_INPUT data address
  54. public static final int ANALOG_INPUT_START_ADDRESS = 30001;//Start address of ANALOG_INPUT
  55. public static final int HOLDING_REGISTERS_MAX_ADDRESS = 40009; // MAX HOLDING_REGISTER data_address
  56. public static final int HOLDING_REGISTERS_START_ADDRESS = 40001; // Start address of the HOLDING_REGISTER
  57. @Override
  58. public List<Packet> processMessage(Packet requestPacket) {
  59. List<Packet> responsePackets = new ArrayList<Packet>();
  60. byte[] request = null;
  61. if (requestPacket != null) {
  62. request = requestPacket.getBytes();
  63. getRequestType(request);
  64. responsePackets=processRequest(request,getRequestType(request));
  65. System.out.println(responsePackets);
  66. }
  67. return responsePackets;
  68. }
  69. private List<Packet> processRequest(byte[] request,int requestType) {
  70. List<Packet> responsePackets = new ArrayList<Packet>();
  71. switch (requestType){
  72. case MODBUS_SERVICE:
  73. // responsePackets.add(new Packet(request,getDeviceInfo()));
  74. responsePackets.add(new Packet(getDeviceInfo()+"\r\n","EE:FF:66:88:GH:JI:DJ"));
  75. System.out.println(responsePackets);
  76. break;
  77. case READ_INPUT_REGISTERS:
  78. sid=(request[6]);
  79. int registerAddress = (request[9]);
  80. if(sid==1){
  81. //Exception packet
  82. }
  83. else if(sid==2 && registerAddress >= ANALOG_INPUT_START_ADDRESS && registerAddress<=ANALOG_INPUT_MAX_DATA_ADDRESS) {
  84. request[9] = (byte) readRegister(registerAddress);
  85. responsePackets.add(new Packet(request, getDeviceInfo()));
  86. }
  87. else if(sid==2 && registerAddress < ANALOG_INPUT_START_ADDRESS || registerAddress > ANALOG_INPUT_MAX_DATA_ADDRESS ){
  88. //Exception packet
  89. }
  90. break;
  91. case READ_HOLDING_REGISTERS:
  92. sid=request[6];
  93. int holdingRegisterAddress=request[9];
  94. if (sid==1){
  95. //exception packet
  96. }
  97. else if (sid==2 && holdingRegisterAddress >=HOLDING_REGISTERS_START_ADDRESS && holdingRegisterAddress <= HOLDING_REGISTERS_MAX_ADDRESS){
  98. request[9] = (byte) readRegister(holdingRegisterAddress);
  99. responsePackets.add(new Packet(request, getDeviceInfo()));
  100. }
  101. else if(sid==2 && holdingRegisterAddress < HOLDING_REGISTERS_START_ADDRESS || holdingRegisterAddress > HOLDING_REGISTERS_MAX_ADDRESS ){
  102. //Exception packet
  103. }
  104. case READ_COILS:
  105. sid= (request[6]);
  106. int address = (request[9]);
  107. if(sid==1&&address<COIL_MAX_DATA_ADDRESS && address>=COIL_START_ADDRESS){
  108. request[5]=4;
  109. request[9]=(byte)readCoil(address);
  110. responsePackets.add(new Packet(request,getDeviceInfo()));
  111. }
  112. //Imitating Siemens Simatic S7-200 Architecture
  113. else if(sid==1 && address<COIL_START_ADDRESS || address>COIL_MAX_DATA_ADDRESS){
  114. request[7]=(byte)129;
  115. request[8]=(byte)2;
  116. request[9]=0;
  117. request[10]=0;
  118. request[11]=0;
  119. responsePackets.add(new Packet(request,getDeviceInfo()));
  120. }
  121. else if(sid==2){
  122. //Exception packet
  123. }
  124. break;
  125. case READ_INPUT_DISCRETES:
  126. sid =request[6];
  127. int inputAddress = (request[9]);
  128. if(sid==1&& inputAddress>DISCRETE_MAX_DATA_ADDRESS || inputAddress<DISCRETE_START_ADDRESS){
  129. request[7]=(byte)129;
  130. request[8]=(byte)2;
  131. request[9]=0;
  132. request[10]=0;
  133. request[11]=0;
  134. responsePackets.add(new Packet(request,getDeviceInfo()));
  135. }
  136. else if(sid==1&&inputAddress<DISCRETE_MAX_DATA_ADDRESS && inputAddress>=DISCRETE_START_ADDRESS){
  137. request[5]=4;
  138. request[9]=(byte)readDiscrete(inputAddress);
  139. responsePackets.add(new Packet(request,getDeviceInfo()));
  140. }
  141. else if(sid==2){
  142. //Exception packet
  143. }
  144. break;
  145. case WRITE_COIL:
  146. sid=request[6];
  147. int coilAddress = (request[9]);
  148. int coilData = (request[10]);
  149. if(sid==2){
  150. //Exception packet
  151. }
  152. else if(sid==1 && coilAddress>COIL_MAX_DATA_ADDRESS){
  153. //exception packet
  154. }
  155. else if(sid==1 && coilAddress<=COIL_MAX_DATA_ADDRESS && coilAddress>=COIL_START_ADDRESS) {
  156. writeCoil(coilAddress, coilData);
  157. responsePackets.add(new Packet(request, getDeviceInfo()));
  158. }
  159. break;
  160. case WRITE_SINGLE_REGISTER:
  161. sid = request[6];
  162. int regAddress=(request[9]);
  163. int regData=(request[10]);
  164. if (sid==1){
  165. //exception
  166. }
  167. else if(sid==2 && regAddress >= ANALOG_INPUT_START_ADDRESS && regAddress<=ANALOG_INPUT_MAX_DATA_ADDRESS) {
  168. writeSingleRegister(regAddress,regData);
  169. responsePackets.add(new Packet(request,getDeviceInfo()));
  170. }
  171. else if(sid==2 && regAddress < ANALOG_INPUT_START_ADDRESS || regAddress > ANALOG_INPUT_MAX_DATA_ADDRESS ){
  172. //Exception packet
  173. }
  174. else if (sid==2 && regAddress >=HOLDING_REGISTERS_START_ADDRESS && regAddress <= HOLDING_REGISTERS_MAX_ADDRESS){
  175. writeSingleRegister(regAddress,regData);
  176. responsePackets.add(new Packet(request,getDeviceInfo()));
  177. }
  178. else if(sid==2 && regAddress < HOLDING_REGISTERS_START_ADDRESS || regAddress > HOLDING_REGISTERS_MAX_ADDRESS ) {
  179. //Exception Packet
  180. }
  181. break;
  182. default:
  183. break;
  184. }
  185. return responsePackets;
  186. }
  187. //Read Coil function
  188. public int readCoil(int address) {
  189. address+=1;//has an offset 1
  190. if (coil.containsKey(address)) {
  191. int val = (Integer) coil.get(address);
  192. return val;
  193. } else {
  194. coil.put(address, rand());
  195. //System.out.println(coil);
  196. int val = (Integer) coil.get(address);
  197. System.out.println("Address:" + String.valueOf(address) + "Data:" + String.valueOf(val));
  198. return val;
  199. }
  200. }
  201. //Random input of 0 & 1 for coils
  202. private int rand() {
  203. int num =(Math.random()<0.5)?0:1;
  204. return num;
  205. }
  206. //Device Information
  207. private String DeviceInfo = getDeviceInfo();
  208. private String getDeviceInfo() {
  209. DeviceInfo = "5369656d656e732053494d415449432053372d323030"; // Hex value for Simatic S7 200
  210. return DeviceInfo;
  211. }
  212. private int readRegister(int registerAddress) {
  213. // registerAddress+=30001; //Offset of 30001 Check the packet in wireshark and decide to put offset
  214. if (register.containsKey(registerAddress)) {
  215. int val = (Integer) register.get(registerAddress);
  216. return val;
  217. } else {
  218. register.put(registerAddress, randvalue());
  219. int val = (Integer) register.get(registerAddress);
  220. System.out.println("Address:" + String.valueOf(registerAddress) + "Data:" + String.valueOf(val));
  221. return val;
  222. }
  223. }
  224. private int randvalue(){
  225. int num =(Math.random()<0.5)?0:255; //Max Hex value that can be stored in 10 bit Binary is 255
  226. return num;
  227. }
  228. private int writeSingleRegister(int regAddress, int regData){
  229. //regData+=30001;
  230. register.put(regAddress, regData);
  231. int val = (Integer)register.get(regAddress);
  232. return val;
  233. }
  234. private int writeCoil(int coilAddress, int coilData) {
  235. coilAddress+=1;//offset 1
  236. coil.put(coilAddress,coilData);
  237. int val=(Integer)coil.get(coilAddress);
  238. return val;
  239. }
  240. //Read Coil function
  241. public int readDiscrete(int address) {
  242. address+=1;//offset 1
  243. if (discreteInput.containsKey(address)) {
  244. int val = (Integer) discreteInput.get(address);
  245. return val;
  246. } else {
  247. discreteInput.put(address, rand());
  248. //System.out.println(coil);
  249. int val = (Integer) discreteInput.get(address);
  250. System.out.println("Address:" + String.valueOf(address) + "Data:" + String.valueOf(val));
  251. return val;
  252. }
  253. }
  254. /* gets the type of request made from the master */
  255. private int getRequestType(byte[] request) {
  256. int requestType=request[7];
  257. if (requestType == 17) {
  258. requestType = MODBUS_SERVICE;
  259. } else if (requestType == 5) {
  260. requestType = WRITE_COIL;
  261. } else if (requestType == 1) {
  262. requestType = READ_COILS;
  263. } else if (requestType == 6) {
  264. requestType = WRITE_SINGLE_REGISTER;
  265. } else if (requestType == 4) {
  266. requestType = READ_INPUT_REGISTERS;
  267. }
  268. else if (requestType==2){
  269. requestType = READ_INPUT_DISCRETES;
  270. }
  271. else if (requestType==3){
  272. requestType = READ_HOLDING_REGISTERS;
  273. }
  274. System.out.println(requestType);
  275. return requestType;
  276. }
  277. }