嘿:)我目前正在开发一个x86 / x64 Linux的memoryhacking-library。 我奋斗的一点是实现某种远程系统调用的执行。
这是我的代码,当我试图执行一个有效的系统调用时,只是崩溃了另一个进程。
(在代码中使用的所有函数都是ptrace的包装器)你可以在这里find完整的代码: http : //code.google.com/p/ethonmem/source/browse/
long Debugger::executeSyscall( unsigned long code, std::vector<unsigned long> const& args) const { // Backup registers. Registers buRegs = getRegisters(buRegs); FpuRegisters buFregs = getFpuRegisters(buFregs); // Get register set to modify. Registers regs = buRegs; #if __WORDSIZE == 32 // EAX stores the syscall code. regs.eax = code; // If less than 7 args exist, they are stored in registers. size_t argCount = args.size(); if(argCount < 7) { while(argCount) { switch(argCount) { case 1: regs.ebx = args[0]; break; case 2: regs.ecx = args[1]; break; case 3: regs.edx = args[2]; break; case 4: regs.esi = args[3]; break; case 5: regs.edi = args[4]; break; case 6: regs.ebp = args[5]; break; } --argCount; } } // Otherwise we have to use memory. else { // Get stack space. regs.esp -= argCount * sizeof(unsigned long); // Write arguments to stack. for(size_t i = 0; i < argCount; ++i) writeWord(regs.esp + i * sizeof(unsigned long), args[i]); // EBX stores the address. regs.ebx = regs.esp; } // Write INT 0x80-instruction to current instruction pointer position. unsigned long const oldInstruction = readWord(regs.eip); uint8_t newInstruction[sizeof(long)] = { 0xCD, 0x80, 0xCC, 0xCC }; writeWord(regs.eip, *reinterpret_cast<unsigned long*>(&newInstruction[0])); #elif __WORDSIZE == 64 // RAX stores the syscall code. regs.rax = code; // If less than 7 args exist, they are stored in registers. size_t argCount = args.size(); if(argCount < 7) { while(argCount) { switch(argCount) { case 1: regs.rdi = args[0]; break; case 2: regs.rsi = args[1]; break; case 3: regs.rdx = args[2]; break; case 4: regs.r10 = args[3]; // Or RCX ??? break; case 5: regs.r8 = args[4]; break; case 6: regs.r9 = args[5]; break; } --argCount; } } // Otherwise this fails. else { BOOST_THROW_EXCEPTION(EthonError() << ErrorString("More than 6 arguments passed to a 64bit syscall")); } // Write SYSCALL-instruction to current instruction pointer position. unsigned long const oldInstruction = readWord(regs.rip); uint8_t newInstruction[sizeof(long)] = { 0x0F, 0x05, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC }; writeWord(regs.rip, *reinterpret_cast<unsigned long*>(&newInstruction[0])); #endif // Apply new registers. setRegisters(regs); // Step to begin of syscall. stepSyscall(); // Step to end of syscall. stepSyscall(); // Fetch return value and restore patched word getRegisters(regs); long returnValue; #if __WORDSIZE == 32 returnValue = regs.eax; writeWord(regs.eip, oldInstruction); #elif __WORDSIZE == 64 returnValue = regs.rax; writeWord(regs.rip, oldInstruction); #endif // Restore registers. setRegisters(buRegs); setFpuRegisters(buFregs); return returnValue; }
有人能够检测到我的错误吗? 谢谢:)问候,弗洛里安
你知道当系统调用发生时,%rip是否已经增加到下一条指令? 通常在e8或e9(call / jmp)之后,也可能在0f05系统调用之后,%rip指向调用后的地址,而不是直接指向地址。 使用%rip – 2可能会修复它。
只是一个疯狂的猜测,你确定任何内存地址作为syscall参数传递有效吗?