MySQL.java 4.8 KB

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