4

几天前,我通过修补单个调用指令编写了一个简单的钩子/绕道。它可以在 Ubuntu 12.xyz(32 位)上运行,现在我更新到 Linux Mint 17.1(32 位)并且出现分段错误。

我有两个项目

  • 调用名为 goodGuy 的函数的目标项目
  • 由 dlopen() 加载的库项目,它覆盖目标应用程序中调用指令的偏移量

在覆盖调用指令偏移之前,我通过以下方式修改了页面的保护:

mprotect(pageOf(address),pagesize,PROT_WRITE|PROT_EXEC|PROT_READ)

这工作正常(返回 0)。

当我调试我的程序时,它在尝试写入调用地址时崩溃:

memcpy((void*)(address + 1),(void*)&callOffset,4);

看起来我不允许覆盖指令,但为什么呢?

我禁用了 ALSR 并-z execstack -fno-stack-protector在 g++ 中使用了标志。

你知道如何让我的应用程序写指令吗?

谢谢你,亚历克斯

编辑

对不起各位,代码如下:

目标应用:

#include <dlfcn.h>
#include <stdio.h>
#include <stdio.h>
#include <iostream>

void goodGuy();
//full lib path !
char libPath[] = "INSER_YOUR_PATH_HERE/lib.so";

int main(){
  dlopen(libPath,RTLD_NOW);
  goodGuy();
  return 0;
}

void goodGuy(){
    printf("good guy :)\n");
}

和共享库代码:

#include <stdio.h>
#include <cstring>
#include <stdint.h>
#include <sys/mman.h>
#include <unistd.h>

void badGuy();

int pagesize = sysconf(_SC_PAGESIZE);

void *pageOf(void* p){
    return (void*)((unsigned int)p & ~(pagesize - 1));
}

extern "C" void __attribute__ ((constructor)) DllLoad(void){
    uint32_t addressOfCall = 0x0804862a; //Address where goodGuy is called in target app
    uint32_t addressOfNextInstruction = addressOfCall + 5;
    uint32_t callOffset = (uint32_t)badGuy - addressOfNextInstruction;

    mprotect(pageOf((void*)(addressOfCall + 1)),pagesize, PROT_WRITE|PROT_EXEC|PROT_READ);
    memcpy((void*)(addressOfCall + 1),(void*)&callOffset,4);
}

void badGuy(){
  printf("bad guy :(\n");
}

要找出addressOfCall,用gdb打开目标应用程序gdb target并显示主函数,disas main看看+29

gdb$ disas main
Dump of assembler code for function main()
   0x0804860d <+0>: push   ebp
   0x0804860e <+1>: mov    ebp,esp
   0x08048610 <+3>: and    esp,0xfffffff0
   0x08048613 <+6>: sub    esp,0x10
   0x08048616 <+9>: mov    DWORD PTR [esp+0x4],0x2
   0x0804861e <+17>:    mov    DWORD PTR [esp],0x804a060
   0x08048625 <+24>:    call   0x80484f0 <dlopen@plt>
    ___________
   |0x0804862a| <+29>:  call   0x8048636 <goodGuy()>
   |__________|
   0x0804862f <+34>:    mov    eax,0x0
   0x08048634 <+39>:    leave  
   0x08048635 <+40>:    ret    
4

0 回答 0