MySQL.java 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. package de.tudarmstadt.informatik.hostage.protocol;
  2. import java.nio.ByteBuffer;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. import de.tudarmstadt.informatik.hostage.wrapper.ByteArray;
  6. public class MySQL implements Protocol<ByteArray>{
  7. private enum STATE {
  8. NONE, CONNECTED, LOGIN_INFO, CLOSED
  9. }
  10. private STATE state = STATE.NONE;
  11. private byte[] request;
  12. @Override
  13. public List<ByteArray> processMessage(ByteArray request) {
  14. List<ByteArray> response = new ArrayList<ByteArray>();
  15. if(request != null) {
  16. this.request = request.get();
  17. }
  18. switch(state) {
  19. case NONE:
  20. response.add(new ByteArray(greeting()));
  21. state = STATE.CONNECTED;
  22. break;
  23. case CONNECTED:
  24. response.add(new ByteArray(responseOK()));
  25. state = STATE.LOGIN_INFO;
  26. break;
  27. case LOGIN_INFO:
  28. if(this.request[4] == 0x01) {
  29. state = STATE.CLOSED;
  30. } else if(this.request[4] == 0x03) {
  31. response.add(new ByteArray(responseOK()));
  32. } else {
  33. response.add(new ByteArray(responseError()));
  34. }
  35. break;
  36. default:
  37. state = STATE.CLOSED;
  38. break;
  39. }
  40. return response;
  41. }
  42. @Override
  43. public TALK_FIRST whoTalksFirst() {
  44. return TALK_FIRST.SERVER;
  45. }
  46. @Override
  47. public String toString(){
  48. return "MySQL";
  49. }
  50. @Override
  51. public int getPort() {
  52. return 3306;
  53. }
  54. @Override
  55. public boolean isClosed() {
  56. return state == STATE.CLOSED;
  57. }
  58. private byte[] wrapPckt(byte[] pckt) {
  59. byte[] buff = ByteBuffer.allocate(4).putInt(pckt.length).array();
  60. byte[] pcktLength = {buff[3], buff[2], buff[1]};
  61. byte[] pcktNumber = new byte[1];
  62. if(request != null) pcktNumber[0] = (byte) (request[3] + 1);
  63. else pcktNumber[0] = 0x00;
  64. byte[] response = concat(pcktLength, pcktNumber, pckt);
  65. return response;
  66. }
  67. private byte[] greeting() {
  68. byte[] protocol = {0x0a};
  69. String version = "5.5.31-0+wheezy1";
  70. byte[] versionFin = {0x00};
  71. byte[] thread = {0x2a, 0x00, 0x00, 0x00};
  72. byte[] salt = {0x44, 0x64, 0x49, 0x7e, 0x60, 0x48, 0x25, 0x7e, 0x00};
  73. byte[] capabilities = {(byte) 0xff, (byte) 0xf7};
  74. byte[] language = {0x08};
  75. byte[] status = {0x02, 0x00};
  76. byte[] unused = {0x0f, (byte) 0x80, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  77. byte[] salt2 = {0x6c, 0x26, 0x71, 0x2c, 0x25, 0x72, 0x31, 0x3d, 0x7d, 0x21, 0x26, 0x3b, 0x00};
  78. String payload = "mysql_native_password";
  79. byte[] fin = {0x00};
  80. byte[] response = concat(protocol, version.getBytes(),versionFin, thread, salt, capabilities, language, status, unused, salt2, payload.getBytes(), fin);
  81. return wrapPckt(response);
  82. }
  83. private byte[] responseOK() {
  84. byte[] affectedRows = {0x00, 0x00, 0x00};
  85. byte[] status = {0x02, 0x00};
  86. byte[] warnings = {0x00, 0x00};
  87. byte[] response = concat(affectedRows, status, warnings);
  88. return wrapPckt(response);
  89. }
  90. private byte[] response() {
  91. // 4 packets to respond
  92. byte[] pckt0 = {0x01, 0x00, 0x00, 0x01, 0x01};
  93. byte[] pckt1 = {0x27, 0x00, 0x00, 0x02, 0x03, 0x64, 0x65, 0x66, 0x00,
  94. 0x00, 0x00, 0x11, 0x40, 0x40, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6d, 0x6d,
  95. 0x65, 0x6e, 0x74, 0x00, 0x0c, 0x21, 0x00, 0x18, 0x00, 0x00, 0x00, (byte) 0xfd, 0x00, 0x00, 0x1f, 0x00, 0x00};
  96. byte[] pckt2 = {0x05, 0x00, 0x00, 0x03, (byte) 0xfe, 0x00, 0x00, 0x02, 0x00};
  97. byte[] pckt3 = {0x09, 0x00, 0x00, 0x04, 0x08, 0x28, 0x44, 0x65, 0x62, 0x69, 0x61, 0x6e, 0x29};
  98. byte[] pckt4 = {0x05, 0x00, 0x00, 0x05, (byte) 0xfe, 0x00, 0x00, 0x02, 0x00};
  99. byte[] response = concat(pckt0, pckt1, pckt2, pckt3, pckt4);
  100. return response; //no wrapPckt() needed, because packets already have length and number
  101. }
  102. private byte[] responseError() {
  103. byte[] fill1 = {(byte) 0xff};
  104. byte[] code = {0x17, 0x04};
  105. byte[] fill2 = {0x23};
  106. String state = "08S01";
  107. String msg = "Unknown command";
  108. byte[] response = concat(fill1, code, fill2, state.getBytes(), msg.getBytes());
  109. return wrapPckt(response);
  110. }
  111. private byte[] concat(byte[]...bytes) {
  112. int newSize = 0;
  113. for(byte[] b: bytes) newSize += b.length; //get total new size
  114. byte[] dst = new byte[newSize]; //create new array with new size
  115. int currentPos = 0;
  116. int newPos;
  117. for(byte[] b:bytes) { //for each elem b out of bytes
  118. newPos = b.length; //get b.length and new position
  119. System.arraycopy(b, 0, dst, currentPos, newPos); //copy b in dst from currentPos to newPos
  120. currentPos += newPos; //increase currentPos to newPos + currentPos
  121. }
  122. return dst;
  123. }
  124. @Override
  125. public boolean isSecure() {
  126. return false;
  127. }
  128. @Override
  129. public Class<ByteArray> getType() {
  130. return ByteArray.class;
  131. }
  132. }