首页
社区
课程
招聘
未解决 [求助][讨论][求助]Mips64 注入so失败求助 10雪币
发表于: 2025-8-22 17:48 382

未解决 [求助][讨论][求助]Mips64 注入so失败求助 10雪币

2025-8-22 17:48
382
#include <stdio.h>
#include <stdlib.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/regdef.h>
#include <dirent.h>
#include <string.h>
#include <unistd.h>
#include <dlfcn.h>
#include <time.h>
/* 0 - 31 are integer registers, 32 - 63 are fp registers.  */
#define FPR_BASE        32
#define PC              64
#define CAUSE           65
#define BADVADDR        66
#define MMHI            67
#define MMLO            68
#define FPC_CSR         69
#define FPC_EIR         70
#define DSP_BASE        71              /* 3 more hi / lo register pairs */
#define DSP_CONTROL     77
#define ACX             78

/*
 * This struct defines the registers as used by PTRACE_{GET,SET}REGS. The
 * format is the same for both 32- and 64-bit processes. Registers for 32-bit
 * processes are sign extended.
 */
struct pt_regs {
    unsigned long long regs[32];
    unsigned long long lo;
    unsigned long long hi;
    unsigned long long cp0_epc;
    unsigned long long cp0_badvaddr;
    unsigned long long cp0_status;
    unsigned long long cp0_cause;
} __attribute__ ((aligned (8)));

#define MIPS_v0 general_regs.regs[2]
#define MIPS_v1 general_regs.regs[3]
#define MIPS_a0 general_regs.regs[4]
#define MIPS_a1 general_regs.regs[5]
#define MIPS_a2 general_regs.regs[6]
#define MIPS_a3 general_regs.regs[7]
#define MIPS_sp general_regs.regs[29]
#define MIPS_ra general_regs.regs[31]
#define MIPS_pc pc
#define MIPS_t9 general_regs.regs[25]

struct mips_regswithpc
{
    struct pt_regs general_regs;
    long long pc;
}__attribute__ ((aligned (8)));



long getlibcaddr(pid_t pid) {
    FILE *fp;
    char filename[30];
    char line[850];
    long addr;
    char perms[5];
    char* modulePath;
    void* handle = dlopen("/lib32/libc.so.6", RTLD_LAZY);
    if (!handle) {
        fprintf(stderr, "dlopen failed: %s\n", dlerror());
        exit(1);
    }
    sprintf(filename, "/proc/%d/maps", pid);
    fp = fopen(filename, "r");
    if (fp == NULL) {
        fprintf(stderr, "Failed to open %s\n", filename);
        dlclose(handle);
        exit(1);
    }
    while (fgets(line, 850, fp) != NULL) {
        if (sscanf(line, "%lx-%*lx %*s %*s %*s %*d", &addr) == 1) {
            if (strstr(line, "libc-") != NULL) {
                fclose(fp);
                dlclose(handle);
                return addr;
            }
        }
    }
    fclose(fp);
    dlclose(handle);
    return -1;
}

long getFunctionAddress(char* funcName)
{
    void* self = dlopen("/lib32/libc.so.6", RTLD_LAZY);
    void* funcAddr = dlsym(self, funcName);
    return (long)funcAddr;
}

int checkloaded(pid_t pid, char* libname)
{
    FILE *fp;
    char filename[30];
    char line[850];
    long addr;
    char perms[5];
    char* modulePath;
    sprintf(filename, "/proc/%d/maps", pid);
    fp = fopen(filename, "r");
    if(fp == NULL)
        exit(1);
    while(fgets(line, 850, fp) != NULL)
    {
        sscanf(line, "%lx-%*lx %*s %*s %*s %*d", &addr);
        if(strstr(line, libname) != NULL)
        {
            fclose(fp);
            return 1;
        }
    }
    fclose(fp);
    return 0;
}

void usage(char* name)
{
    printf("usage: %s [-p pid] [library-to-inject]\n", name);
}

void print_mips_regswithpc(struct mips_regswithpc *regs) {
    if (!regs) {
        printf("regs is NULL\n");
        return;
    }

    printf("General Registers:\n");
    for (int i = 0; i < 32; i++) {
        printf("regs[%d] = %llx\n", i, regs->general_regs.regs[i]);
    }

    printf("Special Registers:\n");
    printf("lo = %llx\n", regs->general_regs.lo);
    printf("hi = %llx\n", regs->general_regs.hi);
    printf("cp0_epc = %llx\n", regs->general_regs.cp0_epc);
    printf("cp0_badvaddr = %llx\n", regs->general_regs.cp0_badvaddr);
    printf("cp0_status = %llx\n", regs->general_regs.cp0_status);
    printf("cp0_cause = %llx\n", regs->general_regs.cp0_cause);

    printf("Program Counter (pc) = %llx\n", regs->pc);
}
void ptrace_attach(pid_t target);
void ptrace_detach(pid_t target);
int  ptrace_getregs(pid_t target, struct mips_regswithpc* regs);
void ptrace_cont(pid_t target);
int  ptrace_setregs(pid_t target, struct mips_regswithpc* regs);
siginfo_t ptrace_getsiginfo(pid_t target);
void ptrace_read(int pid, unsigned long addr, void *vptr, int len);
void ptrace_write(int pid, unsigned long addr, void *vptr, int len);
void checktargetsig(int pid);
void restoreStateAndDetach(pid_t target, unsigned long addr, void* backup, int datasize, struct mips_regswithpc oldregs);

void ptrace_attach(pid_t target)
{
    int waitpidstatus;

    if(ptrace(PTRACE_ATTACH, target, NULL, NULL) == -1)
    {
        fprintf(stderr, "ptrace(PTRACE_ATTACH) failed\n");
        exit(1);
    }

    if(waitpid(target, &waitpidstatus, WUNTRACED) != target)
    {
        fprintf(stderr, "waitpid(%d) failed\n", target);
        exit(1);
    }
}

void ptrace_detach(pid_t target)
{
    if(ptrace(PTRACE_DETACH, target, NULL, NULL) == -1)
    {
        fprintf(stderr, "ptrace(PTRACE_DETACH) failed\n");
        exit(1);
    }
}

int ptrace_getregs(pid_t pid, struct mips_regswithpc *regs){
    if(ptrace(PTRACE_GETREGS, pid, NULL, &regs->general_regs) < 0)
    {
        perror("ptrace_getregs: Can not get register values");
        return -1;
    }
    regs->MIPS_pc = ptrace(PT_READ_U, pid, (void*)PC, 0);
    if(regs->MIPS_pc < 0)
    {
        perror("ptrace_getregs: Can not get PC values");
        return -1;
    }
    print_mips_regswithpc(regs);
    return 0;
}


void ptrace_cont(pid_t target)
{
    struct timespec* sleeptime = malloc(sizeof(struct timespec));
    sleeptime->tv_sec = 0;
    sleeptime->tv_nsec = 5000000;
    if(ptrace(PTRACE_CONT, target, NULL, NULL) == -1)
    {
        fprintf(stderr, "ptrace(PTRACE_CONT) failed\n");
        exit(1);
    }
    nanosleep(sleeptime, NULL);
    checktargetsig(target);
}

int ptrace_setregs(pid_t pid, struct mips_regswithpc *regs) {
    if (ptrace(PTRACE_SETREGS, pid, NULL, &regs->general_regs) < 0) {
        perror("ptrace_setregs: Can not set register values");
        return -1;
    }

    if (ptrace(PT_WRITE_U, pid, (void*)PC, regs->pc) < 0) {
        perror("ptrace_setregs: Can not set PC values");
        return -1;
    }

    print_mips_regswithpc(regs);
    return 0;
}

siginfo_t ptrace_getsiginfo(pid_t target)
{
    siginfo_t targetsig;
    if(ptrace(PTRACE_GETSIGINFO, target, NULL, &targetsig) == -1)
    {
        fprintf(stderr, "ptrace(PTRACE_GETSIGINFO) failed\n");
        exit(1);
    }
    return targetsig;
}

void ptrace_read(int pid, unsigned long addr, void *vptr, int len)
{
    int bytesRead = 0;
    int i = 0;
    long word = 0;
    long *ptr = (long *) vptr;
    while (bytesRead < len)
    {
        word = ptrace(PTRACE_PEEKTEXT, pid, addr + bytesRead, NULL);
        if(word == -1)
        {
            fprintf(stderr, "ptrace(PTRACE_PEEKTEXT) failed\n");
            exit(1);
        }
        bytesRead += sizeof(word);
        ptr[i++] = word;
    }
}

void ptrace_write(int pid, unsigned long addr, void *vptr, int len)
{
    int byteCount = 0;
    long word = 0;
    while (byteCount < len)
    {
        memcpy(&word, vptr + byteCount, sizeof(word));
        word = ptrace(PTRACE_POKETEXT, pid, addr + byteCount, word);
        if(word == -1)
        {
            fprintf(stderr, "ptrace(PTRACE_POKETEXT) failed\n");
            exit(1);
        }
        byteCount += sizeof(word);
    }
}

void checktargetsig(int pid)
{
    siginfo_t targetsig = ptrace_getsiginfo(pid);
    if(targetsig.si_signo != SIGTRAP)
    {
        fprintf(stderr, "instead of expected SIGTRAP, target stopped with signal %d: %s\n", targetsig.si_signo, strsignal(targetsig.si_signo));
        fprintf(stderr, "sending process %d a SIGSTOP signal for debugging purposes\n", pid);
        ptrace(PTRACE_CONT, pid, NULL, SIGSTOP);
        exit(1);
    }
}

void restoreStateAndDetach(pid_t target, unsigned long addr, void* backup, int datasize, struct mips_regswithpc oldregs)
{
    ptrace_write(target, addr, backup, datasize);
    ptrace_setregs(target, &oldregs);
    ptrace_detach(target);
}




void injectSharedLibrary() {
    asm volatile (
        /*
            regs.regs[16] = targetMallocAddr;//s0
            regs.regs[17] = targetFreeAddr;//s1
            regs.regs[18] = targetDlopenAddr;//s2
            regs.regs[19] = libPathLength;//s3
        */
        "nop \n"
        "break 0 \n"           // 测试暂停
        // // malloc(len)
        // "move $a0, $s3 \n"     // $a0=长度
        // "move $t9, $s0 \n"     // $a0=长度
        // "jalr $t9 \n"          // 调用malloc
        // "nop \n"
        // "move $s4, $v0 \n"     
        // "break 0 \n"           // 暂停
        // // dlopen调用
        // "move $a0,$s4 \n"       
        // "li $a1, 1 \n"       
        // "move $t9, $s2 \n"     
        // "jalr $t9 \n"
        // "nop \n"
        // "break 0 \n"           // 暂停检查返回值

        // // free调用
        // "move $a0,$s4 \n" 
        // "move $t9, $s1 \n" 
        // "jalr $t9 \n"
        // "nop \n"

        // "break 0 \n"
    );
}
void injectSharedLibrary_end()
{
}



int main(int argc, char** argv)
{
    //处理参数
    if(argc < 4)
    {
        usage(argv[0]);
        return 1;
    }

    char* command = argv[1];
    char* commandArg = argv[2];
    char* libname = argv[3];
    char* libPath = realpath(libname, NULL);

    char* processName = NULL;
    pid_t target = 0;

    if(!libPath)
    {
        fprintf(stderr, "can't find file \"%s\"\n", libname);
        return 1;
    }

    if(!strcmp(command, "-p"))
    {
        target = atoi(commandArg);
        printf("targeting process with pid %d\n", target);
    }
    else
    {
        usage(argv[0]);
        return 1;
    }
    int libPathLength = strlen(libPath) + 1;
    int mypid = getpid();
    long mylibcaddr = getlibcaddr(mypid);
    printf("mylibcaddr:%x\r\n",mylibcaddr);
    long mallocAddr = getFunctionAddress("malloc");
    long freeAddr = getFunctionAddress("free");
    long dlopenAddr = getFunctionAddress("__libc_dlopen_mode");
    printf("mallocAddr:%x freeAddr:%x dlopenAddr:%x\r\n",mallocAddr,freeAddr,dlopenAddr);
    //get libc&func offset
    long mallocOffset = mallocAddr - mylibcaddr;
    long freeOffset = freeAddr - mylibcaddr;
    long dlopenOffset = dlopenAddr - mylibcaddr;
    printf("mallocOffset:%x freeOffset:%x dlopenOffset:%x\r\n",mallocOffset,freeOffset,dlopenOffset);
    //get target func address
    long targetLibcAddr = getlibcaddr(target);
    printf("targetLibcAddr:%x\r\n",targetLibcAddr);
    long targetMallocAddr = targetLibcAddr + mallocOffset;
    long targetFreeAddr = targetLibcAddr + freeOffset;
    long targetDlopenAddr = targetLibcAddr + dlopenOffset;
    printf("targetMallocAddr:%x targetFreeAddr:%x targetDlopenAddr:%x\r\n",targetMallocAddr,targetFreeAddr,targetDlopenAddr);

    //get regs
    struct mips_regswithpc oldregs, regs;
    memset(&oldregs, 0, sizeof(struct mips_regswithpc));
    memset(&regs, 0, sizeof(struct mips_regswithpc));
    ptrace_attach(target);
    ptrace_getregs(target, &oldregs);
    memcpy(&regs, &oldregs, sizeof(struct mips_regswithpc));
    //get inject address
    unsigned long remote_mem_rwx = regs.general_regs.cp0_epc;
    //regs.general_regs.cp0_epc = remote_mem_rwx+4;
    printf("regs.general_regs.cp0_epc %x\r\n",regs.general_regs.cp0_epc);
    printf("regs.pc %x\r\n",regs.pc);
    //regs.general_regs.regs[16] = targetMallocAddr;//s0
    //regs.general_regs.regs[17] = targetFreeAddr;//s1
    //regs.general_regs.regs[18] = targetDlopenAddr;//s2
    //regs.general_regs.regs[19] = libPathLength;//s3
    //ptrace_setregs(target, &regs);
    //备份
    size_t injectSharedLibrary_size = (intptr_t) injectSharedLibrary_end - (intptr_t)injectSharedLibrary;
    char* backup = malloc(injectSharedLibrary_size * sizeof(char));
    ptrace_read(target, remote_mem_rwx, backup, injectSharedLibrary_size);
    //写入目标进程
    char* newcode = malloc((injectSharedLibrary_size-12) * sizeof(char));
    memset(newcode, 0, (injectSharedLibrary_size-12) * sizeof(char));
    memcpy(newcode, (char*)injectSharedLibrary+12, injectSharedLibrary_size-12);
    ptrace_write(target, remote_mem_rwx, newcode, injectSharedLibrary_size-12);
    printf("hello\r\n");
    ptrace_cont(target);
    //目标程序执行完malloc返回到这里
    struct mips_regswithpc malloc_regs;
    memset(&malloc_regs, 0, sizeof(struct mips_regswithpc));
    ptrace_getregs(target, &malloc_regs);
    unsigned long targetBuf = malloc_regs.general_regs.regs[2];
    printf("targetBuf %llx\r\n",targetBuf);
    if(targetBuf == 0)
    {
        fprintf(stderr, "malloc() failed to allocate memory\n");
        restoreStateAndDetach(target, remote_mem_rwx, backup, injectSharedLibrary_size, oldregs);
        free(backup);
        free(newcode);
        return 1;
    }
    //将路径写入malloc出来的内存中
    ptrace_write(target, targetBuf, libPath, libPathLength);
    printf("test\n");
    ptrace_cont(target);
    printf("dlopen success\r\n");
    //目标函数执行完dlopen返回到这里
    memset(&regs, 0, sizeof(struct mips_regswithpc));
    ptrace_getregs(target, &regs);
    //获取dlopen函数返回值
    unsigned long remote_libso_addr = regs.general_regs.regs[2];
    printf("[inject]: get remote %s at =%x\n",libname,remote_libso_addr);
    if(remote_libso_addr == 0)
    {
        fprintf(stderr, "__libc_dlopen_mode() failed to load %s\n", libname); //查看有没有加载成功
        restoreStateAndDetach(target, remote_mem_rwx, backup, injectSharedLibrary_size, oldregs);
        free(backup);
        free(newcode);
        return 1;
    }
    //检查是否加载成功
    if(checkloaded(target, libname))
    {
        printf("[inject]: \"%s\" successfully injected\n", libname);
    }
    else
    {
        fprintf(stderr, "could not inject \"%s\"\n", libname);
    }

    ptrace_cont(target); //执行到最后的int3
    restoreStateAndDetach(target, remote_mem_rwx, backup, injectSharedLibrary_size, oldregs);
    free(backup);
    free(newcode);

    return 0;
}

注释了修改寄存器的操作,仅写入nop和break 0到目标进程的epc处,并从epc处开始执行,目标程序报段错误

Target process started. My PID is 6828

dlopen succeeded (for linking purpose).

Target running... 6828

Target running... 6828

Target running... 6828

Target running... 6828

Target running... 6828

Segmentation fault

下面是获取到的寄存器值

General Registers:
regs[0] = 204
regs[1] = 10008ce1
regs[2] = 204
regs[3] = 1003c100
regs[4] = 0
regs[5] = 0
regs[6] = 7fb8ecb0
regs[7] = 1
regs[8] = 100381a0
regs[9] = 20
regs[10] = ffffffffffffffff
regs[11] = 85603
regs[12] = 2acf2310
regs[13] = 2aab4998
regs[14] = 0
regs[15] = 2acf0ef0
regs[16] = 16
regs[17] = 0
regs[18] = 0
regs[19] = 1002ffc0
regs[20] = 0
regs[21] = 0
regs[22] = 1
regs[23] = 0
regs[24] = 20
regs[25] = 1000af90
regs[26] = 7fb8ecb0
regs[27] = 0
regs[28] = 100381a0
regs[29] = 7fb8ec10
regs[30] = 7fb8ece0
regs[31] = 10006dc0
Special Registers:
lo = 2
hi = 3
cp0_epc = 1000affc
cp0_badvaddr = 2ab7f0f0
cp0_status = 8cf3
cp0_cause = 800020
Program Counter (pc) = 0

不知道为什么获取到的寄存器,zero寄存器值不是0


我的设备是Linux version 2.6.21.7-Cavium-Octeon,mips64大端序


传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回