使用c语言进行纯代码注入编写)

该文介绍了如何使用C语言进行代码注入,首先确定注入进程的上下文,然后编写代码替换共享库函数地址。通过展示64位环境下的示例代码,文中详细说明了如何构造机械码数组,以及如何将代码注入到目标进程中执行,包括分配内存、写入机器码和创建远程线程等步骤。这种方法属于一种基础的代码注入方式,更高级的方法可能涉及查找内核DLL的方法地址以实现更通用的注入。
摘要由CSDN通过智能技术生成

使用c语言进行纯代码注入编写

步骤

1.确定注入进程的上下文,因为要生成机械码,例如x64的机械码,只能注入到64为程序。
2.使用c编写代码。替换掉里面的共享库函数地址。

演示

写一个简单的代码,我是用的是64为环境

#include <windows.h>

int main() {
    char text[] = "Hello, World!";  //字符串需要这样声明,保证存储在栈中
    char caption[] = "Message Box Example";
    int ret = MessageBox(NULL, text, caption, MB_OK);
    return 0;
}

反汇编效果如下
在这里插入图片描述
现在修改内容
将call main 全部填空,将 mov cs:_imp_MessageBoxA ,的操作数改成特殊值1122334455667788h,以便替换地址
修改后图片
在这里插入图片描述
将这个方法转为c byte型数组保存下来

unsigned char main[126] = {
    0x55, 0x48, 0x89, 0xE5, 0x48, 0x83, 0xEC, 0x50, 0x90, 0x90, 0x90, 0x90, 0x90, 0x48, 0xB8, 0x48, 
    0x65, 0x6C, 0x6C, 0x6F, 0x2C, 0x20, 0x57, 0x48, 0x89, 0x45, 0xEE, 0xC7, 0x45, 0xF6, 0x6F, 0x72, 
    0x6C, 0x64, 0x66, 0xC7, 0x45, 0xFA, 0x21, 0x00, 0x48, 0xB8, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 
    0x65, 0x20, 0x48, 0xBA, 0x42, 0x6F, 0x78, 0x20, 0x45, 0x78, 0x61, 0x6D, 0x48, 0x89, 0x45, 0xD0, 
    0x48, 0x89, 0x55, 0xD8, 0xC7, 0x45, 0xE0, 0x70, 0x6C, 0x65, 0x00, 0x48, 0x8D, 0x55, 0xD0, 0x48, 
    0x8D, 0x45, 0xEE, 0x41, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x49, 0x89, 0xD0, 0x48, 0x89, 0xC2, 0xB9, 
    0x00, 0x00, 0x00, 0x00, 0x48, 0xB8, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0xFF, 0xD0, 
    0x89, 0x45, 0xFC, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x48, 0x83, 0xC4, 0x50, 0x5D, 0xC3
};

源码

使用下面代码进行注入会弹出对话框

#include <windows.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
int main() {
     unsigned char strcode[126] = {
            0x55, 0x48, 0x89, 0xE5, 0x48, 0x83, 0xEC, 0x50, 0x90, 0x90, 0x90, 0x90, 0x90, 0x48, 0xB8, 0x48,
            0x65, 0x6C, 0x6C, 0x6F, 0x2C, 0x20, 0x57, 0x48, 0x89, 0x45, 0xEE, 0xC7, 0x45, 0xF6, 0x6F, 0x72,
            0x6C, 0x64, 0x66, 0xC7, 0x45, 0xFA, 0x21, 0x00, 0x48, 0xB8, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67,
            0x65, 0x20, 0x48, 0xBA, 0x42, 0x6F, 0x78, 0x20, 0x45, 0x78, 0x61, 0x6D, 0x48, 0x89, 0x45, 0xD0,
            0x48, 0x89, 0x55, 0xD8, 0xC7, 0x45, 0xE0, 0x70, 0x6C, 0x65, 0x00, 0x48, 0x8D, 0x55, 0xD0, 0x48,
            0x8D, 0x45, 0xEE, 0x41, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x49, 0x89, 0xD0, 0x48, 0x89, 0xC2, 0xB9,
            0x00, 0x00, 0x00, 0x00, 0x48, 0xB8, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0xFF, 0xD0,
            0x89, 0x45, 0xFC, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x48, 0x83, 0xC4, 0x50, 0x5D, 0xC3
    };
//此处是要替换的值
    unsigned char address[16] = {0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11};
    int addressFindFlag=0;
    int injectCodeIndex=0;
    int indexAddress=0;//记录要替换的地址的最后一位的索引
    char addressIndexstrx[3];
    char injectCodeIndexstrx[3];
    for (int i = 0; i < sizeof(strcode); ++i) {

        sprintf(injectCodeIndexstrx,"%02x",strcode[i]);
        sprintf(addressIndexstrx,"%02x",address[injectCodeIndex]);
        if(strcmp(addressIndexstrx,injectCodeIndexstrx)==0){
            addressFindFlag+=1;
            injectCodeIndex+=1;
            if(addressFindFlag>7){
                indexAddress=i;
                printf("find:::%d\n",i);
            }
        }else{
            addressFindFlag=0;
            injectCodeIndex=0;
        }
    }
    //自身加载一次共享库,防止获取不到MessageBoxA地址
    LoadLibraryA("user32.dll");
    HMODULE user32 = GetModuleHandle("user32.dll");
    FARPROC messagebox = GetProcAddress(user32, "MessageBoxA");

    char str1[17];
    sprintf(str1,"%p",messagebox);
    printf("%s\n",str1);
    printf("point:%d",strlen(str1));


    unsigned char addressd[16] = {0};
    for (int i = 0; i < 8; i++) {
        addressd[i] = *((unsigned char*)&messagebox + i);
    }
    for (int i = 0; i < sizeof(addressd)/2; ++i) {
        strcode[indexAddress-sizeof(addressd)/2+i+1]=addressd[i];
    }
    for (int i = 0; i < sizeof(strcode); i++) {
        printf("sssss%d, ",i);
    printf("sssss%x\n, ", strcode[i]);
    }
    printf("Address of MessageBoxA:%d\n",sizeof(addressd));

    // 获取目标进程句柄
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 2588);
    if (hProcess == NULL) {
        printf("打开目标进程失败\n");
        return 1;
    }

    // 在目标进程中分配内存空间
    LPVOID lpBaseAddress = VirtualAllocEx(hProcess, NULL, sizeof(strcode), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (lpBaseAddress == NULL) {
        printf("在目标进程中分配内存失败\n");
        CloseHandle(hProcess);
        return 1;
    }

    // 将机器码写入目标进程中分配的内存空间
    if (!WriteProcessMemory(hProcess, lpBaseAddress, strcode, sizeof(strcode), NULL)) {
        printf("写入机器码失败\n");
        VirtualFreeEx(hProcess, lpBaseAddress, sizeof(strcode), MEM_RELEASE);
        CloseHandle(hProcess);
        return 1;
    }

    // 在目标进程中创建一个线程,执行写入的机器码
    HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpBaseAddress, NULL, 0, NULL);
    if (hThread == NULL) {
        printf("创建远程线程失败\n");
        VirtualFreeEx(hProcess, lpBaseAddress, sizeof(strcode), MEM_RELEASE);
        CloseHandle(hProcess);
        return 1;
    }

    // 等待线程执行完毕,并释放相关资源
    WaitForSingleObject(hThread, INFINITE);
    VirtualFreeEx(hProcess, lpBaseAddress, sizeof(strcode), MEM_RELEASE);
    CloseHandle(hThread);
    CloseHandle(hProcess);
//    MessageBox(NULL, "2", "2", MB_OK);
    char * aa[50];
    gets(aa);
    return 0;

}

在这里插入图片描述

这种方式只是一种比较一般的代码注入方式,更有效的是可以使用汇编取到pcb 进程控制块找到kenral.dll找到方法地址,通过这些块可以做到通用的注入代码生成,免杀等。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值