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