Advertisement
Guest User

Untitled

a guest
Dec 10th, 2018
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.19 KB | None | 0 0
  1. #include <iostream>
  2. #include <string>
  3. #include <fstream>
  4. #include <sstream>
  5. #include <map>
  6.  
  7. #define uc unsigned char
  8.  
  9.  
  10. using namespace std;
  11.  
  12. namespace Utils {
  13.  
  14. /**
  15. * Функция читает 6 байт из файла и возвращает строку с MAC адресом
  16. * @param file - файл
  17. * @return строка с MAC адресом
  18. */
  19. std::string readMAC(std::fstream &file) {
  20. char MAC[6];
  21. file.read(MAC, 6);
  22.  
  23. std::ostringstream ss;
  24. for (int i = 0; i < 6; ++i) {
  25. if (i != 0) ss << ':';
  26. ss.width(2); //< Два символа для каждого байта
  27. ss.fill('0'); //< Дополняем нулем, если не хватает нужного количества символов
  28. ss << std::hex << (MAC[i] & 0xFF);
  29. }
  30.  
  31. // TODO: FIX IT! Пустой MAC
  32. if (ss.str() == "00:00:00:00:00:00") return Utils::readMAC(file);
  33. else return (ss.str());
  34. }
  35.  
  36. /**
  37. * Функция читает 2 байта из файла и определяет тип кадра
  38. * 0x0800 - IPv4, 0x8060 - ARP
  39. * @param file - файл
  40. * @return строка - тип
  41. */
  42. std::tuple<std::string, std::string, int> getFrameType(std::fstream &file) {
  43. char bytes[2];
  44. file.read(bytes, 2);
  45.  
  46. int packetSize = (unsigned char)bytes[0] << 8 | (unsigned char)bytes[1] << 0;
  47.  
  48. std::string protocol;
  49. if (bytes[0] == 8 && bytes[1] == 0) protocol = "IPv4";
  50. else if (bytes[0] == 8 && bytes[1] == 6) protocol = "ARP";
  51. else protocol = "Unknown";
  52.  
  53. std::string frameType;
  54. if (packetSize <= 0x05DC) {
  55. file.read(bytes, 2); // Cчитываем дополнительно два байта
  56. file.seekg(-2, std::ios_base::cur);
  57. if ((uc)bytes[0] == 0xFF && (uc)bytes[1] == 0xFF) frameType = "Raw 802.3";
  58. else if ((uc)bytes[0] == 0xAA && (uc)bytes[1] == 0xAA) frameType = "Ethernet SNAP";
  59. else frameType = "802.3/LLC";
  60. }
  61. else frameType = "Ethernet DIX";
  62.  
  63. return std::make_tuple(frameType, protocol, packetSize);
  64. }
  65.  
  66. std::string readIP(std::fstream &file) {
  67. char ip[4];
  68. file.read(ip, 4);
  69.  
  70. std::ostringstream ss;
  71. for (int i = 0; i < 4; ++i) {
  72. if (i != 0) ss << '.';
  73. ss << std::dec << (ip[i] & 0xFF);
  74. }
  75.  
  76. return ss.str();
  77. }
  78.  
  79. /**
  80. * Функция читает два байта и возвращает число
  81. * @param file - файл
  82. * @return целове число
  83. */
  84. int readShort(std::fstream &file) {
  85. char bytes[2];
  86. file.read(bytes, 2);
  87.  
  88. // return (unsigned char)bytes[1] << 0 | (unsigned char)bytes[0] << 8;
  89. return (unsigned char)bytes[0] << 8 | (unsigned char)bytes[1] << 0;
  90. }
  91.  
  92. /**
  93. * Функция читает байт и определяет по нему тип пакета
  94. * 0x01 - ICMP, 0x06 - TCP, 0x17 - UDP
  95. * @return строка - тип пакета
  96. */
  97. std::string getPacketType(std::fstream &file) {
  98. char byte;
  99. file.read(&byte, 1);
  100.  
  101. switch (byte) {
  102. case 0x01: return std::string("ICMP");
  103. case 0x06: return std::string("TCP");
  104. case 0x11: return std::string("UDP");
  105. default: return std::string("Unknown");
  106. }
  107. }
  108.  
  109. void printMap(std::map<std::string, int> &map) {
  110. for (auto &elem : map) {
  111. std::cout << elem.first << ": " << elem.second << std::endl;
  112. }
  113. }
  114.  
  115. }
  116.  
  117. namespace Packets {
  118.  
  119. /**
  120. * Функция парсит IPv4 пакет и выводит его данные
  121. * @link https://en.wikipedia.org/wiki/IPv4#Header
  122. * @param file - файл
  123. */
  124. void IPv4(std::fstream &file) {
  125. file.ignore(2); // Пропускаем 2 байта (Version, IHL, DSCP, ECN)
  126.  
  127. int packetSize = Utils::readShort(file); // 2 байта - Размер IPv4 пакета
  128. cout << "IPv4 packet size: " << packetSize << endl;
  129.  
  130. file.ignore(5); // Пропускаем 5 байт (Identification, Flags, Fragment Offset, TTL)
  131.  
  132. cout << "Packet type: " << Utils::getPacketType(file) << endl; // 1 байт - Протокол
  133.  
  134. file.ignore(2); // Пропускаем 2 байта (Header Checksum)
  135.  
  136. cout << "Source IP4 : " << Utils::readIP(file) << endl; // 4 байта
  137. cout << "Destination IP4: " << Utils::readIP(file) << endl; // 4 байта
  138.  
  139. file.ignore(packetSize - 20); // Пропускаем данные пакета (размер пакета - 20 байт на Header)
  140. }
  141.  
  142. /**
  143. * Размер ARP пакета меньше 46 байт
  144. * Но т.к. минимальное значение пакета должно быть 46 байт
  145. * То пропускаем 46 байт!
  146. */
  147. void ARP(std::fstream &file) {
  148. file.ignore(46);
  149. }
  150.  
  151. }
  152.  
  153. using namespace std;
  154.  
  155. int main() {
  156. string filePath = "F:/files/ethers07.bin";
  157. std::fstream file(filePath, std::ios::in | std::ios::binary);
  158.  
  159. // Счетчики
  160. std::map<std::string, int> frames;
  161. std::map<std::string, int> protocols;
  162.  
  163. int frameNumber = 1;
  164. while (file.good() && !file.eof()) {
  165. // cout << "File pointer:" << file.tellg() << endl;
  166. cout << "Frame number: " << frameNumber++ << endl;
  167. // Читаем два MAC адреса из файла
  168. cout << "Destination MAC: " << Utils::readMAC(file) << endl;
  169. cout << "Source MAC: " << Utils::readMAC(file) << endl;
  170.  
  171. string frameType;
  172. string protocol;
  173. int packetSize;
  174. tie(frameType, protocol, packetSize) = Utils::getFrameType(file);
  175.  
  176. if (frames.count(frameType) == 0) frames.insert({ frameType, 1 });
  177. else frames.at(frameType)++;
  178.  
  179. if (protocols.count(protocol) == 0) protocols.insert({ protocol, 1 });
  180. else protocols.at(protocol)++;
  181.  
  182.  
  183. cout << "Frame type: " << frameType << endl;
  184.  
  185. if (protocol == "IPv4") {
  186. Packets::IPv4(file);
  187. }
  188. else if (protocol == "ARP") {
  189. Packets::ARP(file);
  190. }
  191. else if (protocol == "Unknown") {
  192. cout << "Packet size: " << packetSize << endl;
  193. file.seekg(packetSize, std::ios_base::cur);
  194. }
  195. // TODO: Legacy code: eof ставится только после попытки чтения
  196. file.ignore(1);
  197. if (file.eof()) {
  198. cout << endl << "Frame types:" << endl;
  199. Utils::printMap(frames);
  200. cout << endl << "Protocol:" << endl;
  201. Utils::printMap(protocols);
  202. system("pause");
  203. return 0;
  204. }
  205. file.seekg(-1, std::ios_base::cur);
  206.  
  207. cout << endl << endl;
  208. }
  209. return 0;
  210. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement