Newer
Older
GoStats / GoStats.php
root on 1 Oct 2019 16 KB typo
  1. #!/usr/bin/php
  2. <?php
  3. error_reporting(0);
  4.  
  5. /***
  6. * Configuration Settings - CHANGE THESE
  7. */
  8. $url = ""; // URL of GoPhish listner e.g. http://www.site.com:8080
  9. $key = ""; // GoPhish API key
  10. $pwd = "/opt/pwdlyser/"; // /directory/containing/pwdlyser
  11. $geoip = false; // use freegeoip.net on IP addresses? set to false to disable this.
  12. $formUsername = "username"; // username name of landing page form input box
  13. $formPassword = "password"; // password name of landing page form input box
  14.  
  15.  
  16. /***
  17. * Main program - Don't edit below
  18. */
  19. echo "╔═╗┌─┐╔═╗┌┬┐┌─┐┌┬┐┌─┐\n║ ╦│ │╚═╗ │ ├─┤ │ └─┐ v1.0\n╚═╝└─┘╚═╝ ┴ ┴ ┴ ┴ └─┘\n";
  20.  
  21. foreach (glob("Classes/*.php") as $filename)
  22. include $filename;
  23.  
  24. $definitions = new \Clapp\CommandLineArgumentDefinition(
  25. array(
  26. "help|h" => "Shows help message",
  27. "list|l" => "List campaigns and their ID's",
  28. "campaign|c=i" => "Get campaign by id",
  29. "dump|d=s" => "Dump user:pass list to </path/to/file.txt>",
  30. "training|t=s" => "Dump list of users requiring training </path/to/file.txt>",
  31. "all|a" => "All of the below options",
  32. "ips|i" => "Top 10 IP's",
  33. "useragent|u" => "Top 10 user agents",
  34. "attempts|m" => "Top 10 attempts to log in",
  35. "active|o" => "Active times",
  36. "rolling|r" => "Activities per half hour",
  37. "speed|e" => "Clickthrough speed",
  38. "stats|s" => "Victim statistics",
  39. "pass|p" => "Password analysis with pwdlyser",
  40. )
  41. );
  42.  
  43. $filter = new \Clapp\CommandArgumentFilter($definitions, $argv);
  44.  
  45. if ($filter->getParam('h') === true || $argc < 2) {
  46. fwrite(STDERR, $definitions->getUsage());
  47. exit(0);
  48. }
  49.  
  50. /* Get list of campaigns */
  51. if ($filter->getParam("list") !== false) {
  52. echo "[+] Getting data from server\n";
  53. $curl = new curl();
  54. $curl->url = "$url/api/campaigns/?api_key=$key";
  55. $list = $curl->curlQuery();
  56.  
  57. if(isset($list->message) && $list->message == "Invalid API Key"){
  58. echo "[!] Invalid API key\n";
  59. exit(0);
  60. }else{
  61. echo "[id] -campaign name-\n";
  62. foreach($list as $id)
  63. echo "[".$id['id']."] ".$id['name']."\n";
  64. }
  65. exit(0);
  66. }
  67.  
  68. /* Get campaign data */
  69. $campid = $filter->getParam('c');
  70. if ($campid == null || !is_numeric($campid)) {
  71. echo "[!] Campaign ID not set\nn";
  72. exit(0);
  73. }else{
  74. echo "[+] Getting data from server\n";
  75. $curl = new curl();
  76. $curl->url = "$url/api/campaigns/$campid?api_key=$key";
  77. $list = $curl->curlQuery();
  78. if(isset($list->message) && $list->message == "Invalid API Key"){
  79. echo "[!] Invalid API key\n";
  80. exit(0);
  81. }else{
  82. /* all data got correctly time to do stuff! */
  83. echo "[$campid] ".$list['name']."\n";
  84. echo "\n--- Notable times ---\n";
  85.  
  86. if(isset($list['launch_date']) && $list['launch_date'] <> ""){
  87. $time = date('d-m-Y H:i', $datetime = strtotime(substr($list['launch_date'], 0, 10) . ' ' . substr($list['launch_date'], 11, 8 )));
  88. echo "Campaign launched: $time\n";
  89. }
  90.  
  91. foreach($list['timeline'] as $record){
  92. if($record['message'] == "Email Sent"){
  93. $time = date('d-m-Y H:i', $datetime = strtotime(substr($record['time'], 0, 10) . ' ' . substr($record['time'], 11, 8 )));
  94. echo "First email sent: $time\n";
  95. break;
  96. }
  97. }
  98. foreach($list['timeline'] as $record){
  99. if($record['message'] == "Email Sent"){
  100. $time = date('d-m-Y H:i', $datetime = strtotime(substr($record['time'], 0, 10) . ' ' . substr($record['time'], 11, 8 )));
  101. }
  102. }
  103. echo "Last email sent: $time\n";
  104. foreach($list['timeline'] as $record){
  105. if($record['message'] == "Clicked Link"){
  106. $time = date('d-m-Y H:i', $datetime = strtotime(substr($record['time'], 0, 10) . ' ' . substr($record['time'], 11, 8 )));
  107. echo "First email opened: $time\n";
  108. break;
  109. }
  110. }
  111. foreach($list['timeline'] as $record){
  112. if($record['message'] == "Clicked Link"){
  113. $time = date('d-m-Y H:i', $datetime = strtotime(substr($record['time'], 0, 10) . ' ' . substr($record['time'], 11, 8 )));
  114. echo "First page view: $time\n";
  115. break;
  116. }
  117. }
  118. foreach($list['timeline'] as $record){
  119. if($record['message'] == "Submitted Data"){
  120. $time = date('d-m-Y H:i', $datetime = strtotime(substr($record['time'], 0, 10) . ' ' . substr($record['time'], 11, 8 )));
  121. echo "First credentials submitted: $time\n";
  122. break;
  123. }
  124. }
  125. if(isset($list['completed_date']) && $list['completed_date'] <> ""){
  126. $time = date('d-m-Y H:i', $datetime = strtotime(substr($list['completed_date'], 0, 10) . ' ' . substr($list['completed_date'], 11, 8 )));
  127. echo "Campaign finished: $time\n";
  128. }
  129. }
  130. }
  131.  
  132. /* Top 10 IP's */
  133. if ($filter->getParam("ips") !== false || $filter->getParam("all") !== false) {
  134. $ips = array();
  135. foreach($list['timeline'] as $item){
  136. if($item['details'] <> ""){
  137. $details = json_decode($item['details'], true);
  138. if($details['browser']['address'] !== "unknown")
  139. $ips[] = (string)$details['browser']['address'];
  140. }
  141. }
  142. $ips = array_count_values($ips);
  143. arsort($ips);
  144. $ips = array_slice($ips,0,10,true);
  145. echo "\n--- Top 10 IP's ---\n";
  146. foreach($ips as $ip=>$no){
  147. $geoip_details = "";
  148. if($geoip == true){
  149. $geojson = file_get_contents("http://freegeoip.net/json/$ip");
  150. $geodetails = json_decode($geojson, true);
  151. $geoip_details = "- ".$geodetails['country_name'].", ".$geodetails['city'];
  152. }
  153. echo "[$no] $ip $geoip_details\n";
  154. }
  155. }
  156.  
  157. /* Top 10 user agent's */
  158. if ($filter->getParam("useragent") !== false || $filter->getParam("all") !== false) {
  159. $agents = array();
  160. foreach($list['timeline'] as $item){
  161. if($item['details'] <> "" && $item['message'] == "Clicked Link"){ // only people who visited site, not email user agent
  162. $details = json_decode($item['details'], true);
  163. if($details['browser']['user-agent'] !== "unknown" && $details['browser']['user-agent'] !== "")
  164. $agents[] = (string)$details['browser']['user-agent'];
  165. }
  166. }
  167. $agents = array_count_values($agents);
  168. arsort($agents);
  169. $agents = array_slice($agents,0,10,true);
  170. echo "\n--- Top 10 User Agents ---\n";
  171. foreach($agents as $ua=>$no){
  172. echo "[$no] $ua\n";
  173. }
  174. }
  175.  
  176. /* Top 10 attempts to log in */
  177. if($filter->getParam("attempts") !== false || $filter->getParam("all") !== false) {
  178. $userids = array();
  179. foreach($list['results'] as $item){
  180. $userids[$item['id']] = $item['email'];
  181. }
  182. $attemptrids = array();
  183. foreach($list['timeline'] as $item){
  184. if($item['details'] <> ""){
  185. $details = json_decode($item['details'], true);
  186. if(isset($details['payload'][$formPassword][0]) && $details['payload'][$formPassword][0] <> ""){
  187. $attemptrids[$details['payload']['rid'][0]] += 1;
  188. }
  189. }
  190. }
  191. arsort($attemptrids);
  192. $attemptrids = array_slice($attemptrids,0,10,true);
  193. echo "\n--- Top 10 Login Attempts ---\n";
  194. foreach($attemptrids as $id=>$amount){
  195. //$newemail= preg_replace('/(?:^|.@).\K|.\.[^@]*$(*SKIP)(*F)|.(?=.*?\.)/', '*', $userids[$id]);
  196. //echo "[$amount] $newemail\n";
  197. echo "[$amount] $userids[$id]\n";
  198. }
  199. }
  200.  
  201. /* Active times */
  202. if($filter->getParam("active") !== false || $filter->getParam("all") !== false) {
  203. $active_count = array();
  204. $active_percent = array();
  205. $total = 0;
  206. echo "\n--- Active times (hour, actions & percent) ---\n";
  207. foreach($list['timeline'] as $item){
  208. if($item['message'] != "Campaign Created" && $item['message'] != "Email Sent" ){
  209. $hour = (int)substr($item['time'], 11, 2);
  210. $active_count[$hour]++;
  211. $total++;
  212. }
  213.  
  214. }
  215. foreach($active_count as $id => $count) // populate percentages
  216. $active_percent[$id] = ($count / $total) * 100;
  217.  
  218. for($i = 0; $i <= 12; $i++){
  219. $iDsp = str_pad($i, 2, " ", STR_PAD_LEFT);
  220. $j = $i+12;
  221. $user1 = str_pad($active_count[$i], 4, " ", STR_PAD_LEFT);
  222. $user2 = str_pad($active_count[$j], 4, " ", STR_PAD_LEFT);
  223. $percent1 = number_format($active_percent[$i], 2, '.', '');
  224. $percent1 = str_pad($percent1, 5, " ", STR_PAD_LEFT);
  225. $percent2 = number_format($active_percent[$j], 2, '.', '');
  226. $percent2 = str_pad($percent2, 5, " ", STR_PAD_LEFT);
  227. echo "$iDsp - $user1 = $percent1% | $j - $user2 = $percent2% \n";
  228. }
  229. }
  230.  
  231. /* Rolling times */
  232. if($filter->getParam("rolling") !== false || $filter->getParam("all") !== false) {
  233. $active_count = array();
  234. $active_percent = array();
  235. $total = 0;
  236. echo "\n--- Rolling times (clicked link or submitted data) ---\n";
  237. foreach($list['timeline'] as $item){
  238. if($item['message'] == "Clicked Link" || $item['message'] == "Submitted Data" ){
  239. $month = (int)substr($item['time'], 5, 2);
  240. $day = (int)substr($item['time'], 8, 2);
  241. $hour = (int)substr($item['time'], 11, 2);
  242. $min = (int)substr($item['time'], 14, 2);
  243. $min = ($min < 30 ? "00" : 30);
  244. $hour2 = $hour;
  245. $min2 = $min;
  246. if($min == 30){$hour2++; $min2 = "00";}else{$min2 = 30;}
  247. $active_count[$month."/".$day." ".$hour.":".$min." - ".$hour2.":".$min2]++;
  248. $total++;
  249. }
  250.  
  251. }
  252. foreach($active_count as $id => $count)
  253. echo "$id = $count\n";
  254. }
  255.  
  256. /* Clickthrough speed */
  257. if ($filter->getParam("speed") !== false || $filter->getParam("all") !== false) {
  258. $speed_opened = array();
  259. $speed_visited = array();
  260. $speed_offset = array();
  261. echo "\n--- Clickthrough Speed ---\n";
  262. foreach($list['timeline'] as $item){
  263. if($item['message'] == "Email Opened"){
  264. $details = json_decode($item['details'], true);
  265. $check_rid = $details['payload']['rid'][0];
  266.  
  267. $current_time = strtotime(substr($item['time'], 0, 10) . ' ' . substr($item['time'], 11, 8 ));
  268. $existing_time = strtotime(substr($speed_opened[$check_rid], 0, 10) . ' ' . substr($speed_opened[$check_rid], 11, 8 ));
  269.  
  270. if(!isset($speed_opened[$check_rid]) || $existing_time > $current_time)
  271. $speed_opened[$check_rid] = $item['time'];
  272. }
  273. if($item['message'] == "Clicked Link"){
  274. $details = json_decode($item['details'], true);
  275. $check_rid = $details['payload']['rid'][0];
  276. if(!isset($speed_visited[$check_rid]))
  277. $speed_visited[$check_rid] = $item['time'];
  278. }
  279. }
  280. foreach($speed_opened as $id=>$val){ // remove all the ones that didn't visit site
  281. if(!isset($speed_visited[$id]))
  282. unset($speed_opened[$id]);
  283. }
  284. foreach($speed_visited as $id=>$val){ // remove all the ones that didn't load email tracking image
  285. if(!isset($speed_opened[$id]))
  286. unset($speed_visited[$id]);
  287. }
  288. foreach($speed_opened as $id=>$val){ //calculate speed between reading email and clicking link
  289. $date_opened = substr($val, 0, 10);
  290. $time_opened = substr($val, 11, 8 );
  291. $time_opened_stamp = strtotime($date_opened." ".$time_opened);
  292.  
  293. $date_visited = substr($speed_visited[$id], 0, 10);
  294. $time_visited = substr($speed_visited[$id], 11, 8 );
  295. $time_visited_stamp = strtotime($date_visited." ".$time_visited);
  296.  
  297. $diff = $time_visited_stamp - $time_opened_stamp;
  298. if($diff > 0)
  299. $speed_offset[$id] = $diff;
  300. }
  301.  
  302. unset($speed_opened); // check me out doing memory management and cleaning up! :D
  303. unset($speed_visited);
  304.  
  305. $quickest = min($speed_offset);
  306. echo "Quickest click: $quickest sec\n";
  307. $longest = max($speed_offset);
  308. $longest = floor(($longest / 60) % 60);
  309. echo "Longest click: $longest min\n";
  310. $sec_5 = array_reduce($speed_offset, function ($a, $b){
  311. return ($b <= 5) ? ++$a : $a; });
  312. echo "Users clicked < 5 sec: $sec_5 \n";
  313. $sec_30 = array_reduce($speed_offset, function ($a, $b){
  314. return ($b <= 30) ? ++$a : $a; });
  315. echo "Users clicked < 30 sec: $sec_30 \n";
  316. $sec_60 = array_reduce($speed_offset, function ($a, $b){
  317. return ($b <= 60) ? ++$a : $a; });
  318. echo "Users clicked < 1 min: $sec_60 \n";
  319. }
  320.  
  321. /* Victim statistics */
  322. if ($filter->getParam("stats") !== false || $filter->getParam("all") !== false) {
  323. $status = array();
  324. foreach($list['results'] as $item){
  325. if($item['status'] <> ""){
  326. $status[] = $item['status'];
  327. }
  328. }
  329. echo "\n--- Victim Statistics ---\n";
  330. $statusall = count($status);
  331. $counts = array_count_values($status);
  332. echo "Targets: ".$statusall."\n";
  333. $openedpercent = ($counts['Email Opened'] / $statusall) * 100;
  334. echo "Email opened: ".$counts['Email Opened']." (".round($openedpercent, 2)."%)\n";
  335. $linkpercent = ($counts['Clicked Link'] / $statusall) * 100;
  336. echo "Visited link: ".$counts['Clicked Link']." (".round($linkpercent, 2)."%)\n";
  337. $subpercent = ($counts['Submitted Data'] / $statusall) * 100;
  338. echo "Submitted data: ".$counts['Submitted Data']." (".round($subpercent, 2)."%)\n";
  339. foreach($list['timeline'] as $item){
  340. if($item['details'] <> ""){
  341. $details = json_decode($item['details'], true);
  342. if($details['payload'][$formPassword][0] <> "")
  343. $totalLoginAttempts++;
  344. }
  345. }
  346. echo "Total login attempts: $totalLoginAttempts\n";
  347. }
  348.  
  349. /* Pwdlyzer */
  350. if ($filter->getParam("pass") !== false || $filter->getParam("all") !== false) {
  351. $username = array();
  352. $password = array();
  353. echo "\n--- Password Statistics ---\n";
  354. foreach($list['timeline'] as $item){
  355. if($item['details'] <> ""){
  356. $details = json_decode($item['details'], true);
  357. if($details['payload'][$formPassword][0] <> ""){
  358. $username[] = $details['payload'][$formUsername][0];
  359. $password[] = $details['payload'][$formPassword][0];
  360. }
  361. }
  362. }
  363. $tmpfname = tempnam("/tmp", "GoStats-");
  364. $pwdfname = tempnam("/tmp", "GoStats-");
  365. $handle = fopen($tmpfname, "w");
  366. foreach($username as $id=>$user){
  367. fwrite($handle, "$user:".$password[$id]."\n");
  368. }
  369. fclose($handle);
  370. echo "[+] Launching pwdlyzer\n";
  371. exec("cd $pwd && ./pwdlyser.py -p $tmpfname --all > $pwdfname");
  372. unlink($tmpfname);
  373. echo "[+] pwdlyzer results at: $pwdfname\n";
  374. }
  375.  
  376. /* dump username:password list to file */
  377. $dumpfile = $filter->getParam('dump');
  378. if(file_exists($dumpfile)){
  379. echo "[!] File already exists ($dumpfile)\n";
  380. exit(0);
  381. }
  382. if(!file_exists($dumpfile) && isset($dumpfile)){
  383. $username = array();
  384. $password = array();
  385. echo "\n--- Dumping username:password to file ---\n";
  386. foreach($list['timeline'] as $item){
  387. if($item['details'] <> ""){
  388. $details = json_decode($item['details'], true);
  389. if($details['payload'][$formPassword][0] <> ""){
  390. $username[] = $details['payload'][$formUsername][0];
  391. $password[] = $details['payload'][$formPassword][0];
  392. }
  393. }
  394. }
  395. $handle = fopen($dumpfile, "w");
  396. foreach($username as $id=>$user){
  397. fwrite($handle, "$user:".$password[$id]."\n");
  398. }
  399. fclose($handle);
  400. echo "[+] File created: $dumpfile\n";
  401. }
  402.  
  403. /* dump list of users requiring training */
  404. $dumpfile2 = $filter->getParam('training');
  405. if(file_exists($dumpfile2)){
  406. echo "[!] File already exists ($dumpfile)\n";
  407. exit(0);
  408. }
  409. if(!file_exists($dumpfile2) && isset($dumpfile2)){
  410. $tusername = array();
  411. $temail = array();
  412. $tstatus = array();
  413. echo "\n--- Dumping list of users requiring training ---\n";
  414. foreach($list['results'] as $item){
  415. if($item['status'] == "Submitted Data" || $item['status'] == "Clicked Link"){
  416. $tusername[] = $item['first_name']." ".$item['last_name'];
  417. $temail[] = $item['email'];
  418. $tstatus[] = $item['status'];
  419. }
  420. }
  421. $handle = fopen($dumpfile2, "w");
  422. foreach($tusername as $id=>$user){
  423. fwrite($handle, "$user, ".$temail[$id].", ".$tstatus[$id]."\n");
  424. }
  425. fclose($handle);
  426. echo "[+] File created: $dumpfile2\n";
  427. }
  428.  
  429. ?>
Buy Me A Coffee