-
-
未解决 [求助][讨论][求助]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, ®s->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, ®s->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(®s, 0, sizeof(struct mips_regswithpc));
ptrace_attach(target);
ptrace_getregs(target, &oldregs);
memcpy(®s, &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, ®s);
//备份
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(®s, 0, sizeof(struct mips_regswithpc));
ptrace_getregs(target, ®s);
//获取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大端序
赞赏
赞赏
雪币:
留言: